Browse Source

Generalize FirewallPorts to FirewallIPs so I can run happily when locked in net 18.

svn:r4737
Nick Mathewson 20 years ago
parent
commit
01d0788950
7 changed files with 88 additions and 9 deletions
  1. 1 1
      doc/TODO
  2. 8 0
      doc/tor.1.in
  3. 2 2
      src/or/circuitbuild.c
  4. 67 1
      src/or/config.c
  5. 2 3
      src/or/directory.c
  6. 5 0
      src/or/or.h
  7. 3 2
      src/or/routerlist.c

+ 1 - 1
doc/TODO

@@ -106,7 +106,7 @@ N . helper nodes (Choose N nodes randomly; if a node dies (goes down for a
     o Document
     . Test, debug
     - On sighup, if usehelpernodes changed to 1, use new circs.
-N - Make a FirewallIPs to correspond to firewallPorts so I can use Tor at
+  o Make a FirewallIPs to correspond to firewallPorts so I can use Tor at
     MIT when my directory is out of date.
   - switch accountingmax to count total in+out, not either in or
     out. it's easy to move in this direction (not risky), but hard to

+ 8 - 0
doc/tor.1.in

@@ -240,6 +240,14 @@ A list of ports that your firewall allows you to connect to.  Only used when
 \fBFascistFirewall\fR is set. (Default: 80, 443)
 .LP
 .TP
+\fBFirewallIPs \fR\fIADDR\fP[\fB/\fP\fIMASK\fP\fB][:\fP\fIPORT\fP]...\fP
+A comma-separated list of IPs that your firewall allows you to connect to.
+Only used when \fBFascistFirewall\fR is set.  The format is as for the
+addresses in ExitPolicy.  For example, 'FirewallIPs 99.0.0.0/8, *:80' means
+that your firewall allows connections to everything inside net 99, and to
+port 80 outside.
+.LP
+.TP
 \fBLongLivedPorts \fR\fIPORTS\fP
 A list of ports for services that tend to have long-running connections
 (e.g. chat and interactive shells). Circuits for streams that use these

+ 2 - 2
src/or/circuitbuild.c

@@ -1427,8 +1427,8 @@ choose_good_entry_server(cpath_build_state_t *state)
 
     for (i=0; i < smartlist_len(rl->routers); i++) {
       r = smartlist_get(rl->routers, i);
-      if (!smartlist_string_num_isin(options->FirewallPorts, r->or_port))
-         smartlist_add(excluded, r);
+      if (!fascist_firewall_allows_address(options,r->addr,r->or_port))
+        smartlist_add(excluded, r);
     }
   }
   choice = router_choose_random_node(options->EntryNodes, options->ExcludeNodes,

+ 67 - 1
src/or/config.c

@@ -122,7 +122,8 @@ static config_var_t _option_vars[] = {
   VAR("ExitNodes",           STRING,   ExitNodes,            NULL),
   VAR("ExitPolicy",          LINELIST, ExitPolicy,           NULL),
   VAR("FascistFirewall",     BOOL,     FascistFirewall,      "0"),
-  VAR("FirewallPorts",       CSV,      FirewallPorts,        "80,443"),
+  VAR("FirewallPorts",       CSV,      FirewallPorts,        ""),
+  VAR("FirewallIPs",         CSV,      FirewallIPs,          NULL),
   VAR("Group",               STRING,   Group,                NULL),
   VAR("HardwareAccel",       BOOL,     HardwareAccel,        "1"),
   VAR("HashedControlPassword",STRING,  HashedControlPassword, NULL),
@@ -1414,6 +1415,8 @@ options_dump(or_options_t *options, int minimal)
   return config_dump(&options_format, options, minimal);
 }
 
+/* Return 0 if every element of sl is string holding a decimal representation
+ * of a port number, or if sl is NULL. Otherwise return -1. */
 static int
 validate_ports_csv(smartlist_t *sl, const char *name)
 {
@@ -1435,6 +1438,58 @@ validate_ports_csv(smartlist_t *sl, const char *name)
   return result;
 }
 
+/* Return 0 if every element of sl is string holding an IP with optional mask
+ * and port, or if sl is NULL. Otherwise return -1. */
+static int
+validate_addr_port_ranges_csv(smartlist_t *sl, const char *name)
+{
+  uint32_t addr, mask;
+  uint16_t port_min, port_max;
+  int result = 0;
+  tor_assert(name);
+
+  if (!sl)
+    return 0;
+
+  SMARTLIST_FOREACH(sl, const char *, cp,
+  {
+    if (parse_addr_and_port_range(cp, &addr, &mask, &port_min, &port_max)<0) {
+      log(LOG_WARN, "IP/port range '%s' invalid in %s", cp, name);
+      result=-1;
+    }
+  });
+  return result;
+}
+
+/** Return true iff we are configured to thing that the local fascist firewall
+ * (if any) will allow a connection to <b>addr</b>:<b>port</b> */
+int
+fascist_firewall_allows_address(or_options_t *options, uint32_t addr,
+                                uint16_t port)
+{
+  uint32_t ipaddr, ipmask;
+  uint16_t portmin, portmax;
+  if (!options->FascistFirewall)
+    return 1;
+
+  if (smartlist_string_num_isin(options->FirewallPorts, port))
+    return 1;
+
+  if (!options->FirewallIPs)
+    return 0;
+
+  SMARTLIST_FOREACH(options->FirewallIPs, const char *, cp,
+    {
+      if (parse_addr_and_port_range(cp, &ipaddr, &ipmask, &portmin, &portmax)<0)
+        continue;
+      if ((addr&ipmask) == (ipaddr&ipmask) &&
+          (portmin <= port) && (port <= portmax))
+        return 1;
+    });
+
+  return 0;
+}
+
 /** Return 0 if every setting in <b>options</b> is reasonable.  Else
  * warn and return -1.  Should have no side effects, except for
  * normalizing the contents of <b>options</b>. */
@@ -1576,6 +1631,17 @@ options_validate(or_options_t *options)
                          "FirewallPorts") < 0)
     result = -1;
 
+  if (validate_addr_port_ranges_csv(options->FirewallIPs,
+                                    "FirewallIPs") < 0)
+    result = -1;
+
+  if (options->FascistFirewall &&
+      !smartlist_len(options->FirewallIPs) &&
+      !smartlist_len(options->FirewallPorts)) {
+    smartlist_add(options->FirewallPorts, tor_strdup("80"));
+    smartlist_add(options->FirewallPorts, tor_strdup("443"));
+  }
+
   if (validate_ports_csv(options->LongLivedPorts,
                          "LongLivedPorts") < 0)
     result = -1;

+ 2 - 3
src/or/directory.c

@@ -137,9 +137,8 @@ directory_post_to_dirservers(uint8_t purpose, const char *payload,
       /* Pay attention to fascistfirewall when we're uploading a
        * router descriptor, but not when uploading a service
        * descriptor -- those use Tor. */
-      if (get_options()->FascistFirewall && purpose == DIR_PURPOSE_UPLOAD_DIR &&
-          !get_options()->HttpProxy) {
-        if (!smartlist_string_num_isin(get_options()->FirewallPorts, ds->dir_port))
+      if (purpose == DIR_PURPOSE_UPLOAD_DIR && !get_options()->HttpProxy) {
+        if (!fascist_firewall_allows_address(get_options(),ds->addr,ds->dir_port))
           continue;
       }
       directory_initiate_command_trusted_dir(ds, purpose, purpose_is_private(purpose),

+ 5 - 0
src/or/or.h

@@ -1094,6 +1094,7 @@ typedef struct {
   int RunAsDaemon; /**< If true, run in the background. (Unix only) */
   int FascistFirewall; /**< Whether to prefer ORs reachable on open ports. */
   smartlist_t *FirewallPorts; /**< Which ports our firewall allows (strings). */
+  smartlist_t *FirewallIPs; /**< Which IPs our firewall allows (strings). */
   /** Application ports that require all nodes in circ to have sufficient uptime. */
   smartlist_t *LongLivedPorts;
   /** Should we try to reuse the same exit node for a given host */
@@ -1375,6 +1376,9 @@ int or_state_save(void);
 
 int config_getinfo_helper(const char *question, char **answer);
 
+int fascist_firewall_allows_address(or_options_t *options, uint32_t addr,
+                                    uint16_t port);
+
 /********************************* connection.c ***************************/
 
 const char *conn_type_to_string(int type);
@@ -1653,6 +1657,7 @@ void hibernate_begin_shutdown(void);
 int we_are_hibernating(void);
 void consider_hibernation(time_t now);
 int accounting_getinfo_helper(const char *question, char **answer);
+void accounting_set_bandwidth_usage_from_state(or_state_t *state);
 
 /********************************* main.c ***************************/
 

+ 3 - 2
src/or/routerlist.c

@@ -187,7 +187,8 @@ router_pick_directory_server_impl(int requireother, int fascistfirewall,
     if (requireother && router_is_me(router))
       continue;
     if (fascistfirewall) {
-      if (!smartlist_string_num_isin(get_options()->FirewallPorts, router->dir_port))
+      if (!fascist_firewall_allows_address(get_options(),router->addr,
+                                           router->dir_port))
         continue;
     }
     /* before 0.0.9rc5-cvs, only trusted dirservers served status info. */
@@ -230,7 +231,7 @@ router_pick_trusteddirserver_impl(int requireother, int fascistfirewall)
           !memcmp(me->identity_digest, d->digest, DIGEST_LEN))
         continue;
       if (fascistfirewall) {
-        if (!smartlist_string_num_isin(get_options()->FirewallPorts, d->dir_port))
+        if (!fascist_firewall_allows_address(get_options(),d->addr,d->dir_port))
           continue;
       }
       smartlist_add(sl, d);