]> git.ipfire.org Git - thirdparty/tor.git/commitdiff
Avoid disclosing exit IP addresses in exit policies by default
authorteor (Tim Wilson-Brown) <teor2345@gmail.com>
Fri, 1 Jul 2016 05:37:13 +0000 (15:37 +1000)
committerteor (Tim Wilson-Brown) <teor2345@gmail.com>
Fri, 1 Jul 2016 05:37:13 +0000 (15:37 +1000)
From 0.2.7.2-alpha onwards, Exits would reject all the IP addresses
they knew about in their exit policy. But this may have disclosed
addresses that were otherwise unlisted.

Now, only advertised addresses are rejected by default by
ExitPolicyRejectPrivate. All known addresses are only rejected when
ExitPolicyRejectLocalInterfaces is explicitly set to 1.

changes/bug18456 [new file with mode: 0644]
doc/tor.1.txt
src/or/config.c
src/or/control.c
src/or/main.c
src/or/or.h
src/or/policies.c
src/or/policies.h
src/test/test_policy.c

diff --git a/changes/bug18456 b/changes/bug18456
new file mode 100644 (file)
index 0000000..843c70a
--- /dev/null
@@ -0,0 +1,6 @@
+  o Major bugfixes (exit policies):
+    - Avoid disclosing exit outbound bind addresses, configured port bind
+      addresses, and local interface addresses in relay descriptors by
+      default under ExitPolicyRejectPrivate. Instead, only reject these
+      (otherwise unlisted) addresses if ExitPolicyRejectLocalInterfaces is set.
+      Fixes bug 18456; bugfix on 0.2.7.2-alpha. Patch by teor.
index 64f0da0eebddd0d2d8c2d8f85157caf281e4675c..c22f94e0bd8f158ca9592258c76795c0e24bfdb8 100644 (file)
@@ -1701,15 +1701,16 @@ is non-zero):
     used with accept6/reject6.) +
  +
     Private addresses are rejected by default (at the beginning of your exit
-    policy), along with any configured primary public IPv4 and IPv6 addresses,
-    and any public IPv4 and IPv6 addresses on any interface on the relay.
+    policy), along with any configured primary public IPv4 and IPv6 addresses.
     These private addresses are rejected unless you set the
     ExitPolicyRejectPrivate config option to 0. For example, once you've done
     that, you could allow HTTP to 127.0.0.1 and block all other connections to
     internal networks with "accept 127.0.0.1:80,reject private:\*", though that
     may also allow connections to your own computer that are addressed to its
     public (external) IP address. See RFC 1918 and RFC 3330 for more details
-    about internal and reserved IP address space. +
+    about internal and reserved IP address space. See
+    ExitPolicyRejectLocalInterfaces if you want to block every address on the
+    relay, even those that aren't advertised in the descriptor. +
  +
     This directive can be specified multiple times so you don't have to put it
     all on one line. +
@@ -1739,16 +1740,23 @@ is non-zero):
     IPv4 and IPv6 addresses.
 
 [[ExitPolicyRejectPrivate]] **ExitPolicyRejectPrivate** **0**|**1**::
-    Reject all private (local) networks, along with any configured public
-    IPv4 and IPv6 addresses, at the beginning of your exit policy. (This
-    includes the IPv4 and IPv6 addresses advertised by the relay, any
-    OutboundBindAddress, and the bind addresses of any port options, such as
-    ORPort and DirPort.) This also rejects any public IPv4 and IPv6 addresses
-    on any interface on the relay. (If IPv6Exit is not set, all IPv6 addresses
-    will be rejected anyway.)
+    Reject all private (local) networks, along with the relay's advertised
+    public IPv4 and IPv6 addresses, at the beginning of your exit policy.
     See above entry on ExitPolicy.
     (Default: 1)
 
+[[ExitPolicyRejectLocalInterfaces]] **ExitPolicyRejectLocalInterfaces** **0**|**1**::
+    Reject all IPv4 and IPv6 addresses that the relay knows about, at the
+    beginning of your exit policy. This includes any OutboundBindAddress, the
+    bind addresses of any port options, such as ControlPort or DNSPort, and any
+    public IPv4 and IPv6 addresses on any interface on the relay. (If IPv6Exit
+    is not set, all IPv6 addresses will be rejected anyway.)
+    See above entry on ExitPolicy.
+    This option is off by default, because it lists all public relay IP
+    addresses in the ExitPolicy, even those relay operators might prefer not
+    to disclose.
+    (Default: 0)
+
 [[IPv6Exit]] **IPv6Exit** **0**|**1**::
     If set, and we are an exit node, allow clients to use us for IPv6
     traffic. (Default: 0)
index 45acd39980844b31eccf0d05f8787a5ca7756bf4..5643c8d226b7f9116a9ef0773d6fcf63b4951c68 100644 (file)
@@ -244,6 +244,7 @@ static config_var_t option_vars_[] = {
   V(ExitNodes,                   ROUTERSET, NULL),
   V(ExitPolicy,                  LINELIST, NULL),
   V(ExitPolicyRejectPrivate,     BOOL,     "1"),
+  V(ExitPolicyRejectLocalInterfaces, BOOL, "0"),
   V(ExitPortStatistics,          BOOL,     "0"),
   V(ExtendAllowPrivateAddresses, BOOL,     "0"),
   V(ExitRelay,                   AUTOBOOL, "auto"),
@@ -4320,6 +4321,8 @@ options_transition_affects_descriptor(const or_options_t *old_options,
       old_options->ExitRelay != new_options->ExitRelay ||
       old_options->ExitPolicyRejectPrivate !=
         new_options->ExitPolicyRejectPrivate ||
+      old_options->ExitPolicyRejectLocalInterfaces !=
+        new_options->ExitPolicyRejectLocalInterfaces ||
       old_options->IPv6Exit != new_options->IPv6Exit ||
       !config_lines_eq(old_options->ORPort_lines,
                        new_options->ORPort_lines) ||
index d3613d8d4f53bef9d773601d20e914d64fe9b982..ea7d7b7962d2993a19d699359a536c7ab89d74e7 100644 (file)
@@ -3025,7 +3025,7 @@ static const getinfo_item_t getinfo_items[] = {
        " ExitPolicyRejectPrivate."),
   ITEM("exit-policy/reject-private/relay", policies,
        "The relay-specific rules appended to the configured exit policy by"
-       " ExitPolicyRejectPrivate."),
+       " ExitPolicyRejectPrivate and/or ExitPolicyRejectLocalInterfaces."),
   ITEM("exit-policy/full", policies, "The entire exit policy of onion router"),
   ITEM("exit-policy/ipv4", policies, "IPv4 parts of exit policy"),
   ITEM("exit-policy/ipv6", policies, "IPv6 parts of exit policy"),
index 65a67a992377492553224ab3b210daf5619738ce..2b9b08546c04cc9ea5a7401d4f0333ffaec8a634 100644 (file)
@@ -2220,8 +2220,8 @@ ip_address_changed(int at_interface)
 {
   const or_options_t *options = get_options();
   int server = server_mode(options);
-  int exit_reject_private = (server && options->ExitRelay
-                             && options->ExitPolicyRejectPrivate);
+  int exit_reject_interfaces = (server && options->ExitRelay
+                                && options->ExitPolicyRejectLocalInterfaces);
 
   if (at_interface) {
     if (! server) {
@@ -2239,8 +2239,8 @@ ip_address_changed(int at_interface)
   }
 
   /* Exit relays incorporate interface addresses in their exit policies when
-   * ExitPolicyRejectPrivate is set */
-  if (exit_reject_private || (server && !at_interface)) {
+   * ExitPolicyRejectLocalInterfaces is set */
+  if (exit_reject_interfaces || (server && !at_interface)) {
     mark_my_descriptor_dirty("IP address changed");
   }
 
index a1a0810e4bd2e7ee0dfb8392e0446e828a3c62a7..98f5a006d84e09b1f66c0c723ff4d3fddef30635 100644 (file)
@@ -3573,7 +3573,13 @@ typedef struct {
   /** Bitmask; derived from AllowInvalidNodes. */
   invalid_router_usage_t AllowInvalid_;
   config_line_t *ExitPolicy; /**< Lists of exit policy components. */
-  int ExitPolicyRejectPrivate; /**< Should we not exit to local addresses? */
+  int ExitPolicyRejectPrivate; /**< Should we not exit to reserved private
+                                * addresses, and our own published addresses?
+                                */
+  int ExitPolicyRejectLocalInterfaces; /**< Should we not exit to local
+                                        * interface addresses?
+                                        * Includes OutboundBindAddresses and
+                                        * configured ports. */
   config_line_t *SocksPolicy; /**< Lists of socks policy components */
   config_line_t *DirPolicy; /**< Lists of dir policy components */
   /** Addresses to bind for listening for SOCKS connections. */
index 2703d7edefd0c94ff656693ac3722e7f871996cb..544c6b7dbb82a6f8cc2e593a38971de32cc69333 100644 (file)
@@ -1843,10 +1843,18 @@ policies_log_first_redundant_entry(const smartlist_t *policy)
  *
  * If <b>ipv6_exit</b> is false, prepend "reject *6:*" to the policy.
  *
+ * If <b>configured_addresses</b> contains addresses:
+ *   - prepend entries that reject the addresses in this list. These may be the
+ *     advertised relay addresses and/or the outbound bind addresses,
+ *     depending on the ExitPolicyRejectPrivate and
+ *     ExitPolicyRejectLocalInterfaces settings.
  * If <b>rejectprivate</b> is true:
  *   - prepend "reject private:*" to the policy.
- *   - prepend entries that reject publicly routable addresses on this exit
- *     relay by calling policies_parse_exit_policy_reject_private
+ * If <b>reject_interface_addresses</b> is true:
+ *   - prepend entries that reject publicly routable interface addresses on
+ *     this exit relay by calling policies_parse_exit_policy_reject_private
+ * If <b>reject_configured_port_addresses</b> is true:
+ *   - prepend entries that reject all configured port addresses
  *
  * If cfg doesn't end in an absolute accept or reject and if
  * <b>add_default_policy</b> is true, add the default exit
@@ -1874,13 +1882,16 @@ policies_parse_exit_policy_internal(config_line_t *cfg,
   if (rejectprivate) {
     /* Reject IPv4 and IPv6 reserved private netblocks */
     append_exit_policy_string(dest, "reject private:*");
-    /* Reject IPv4 and IPv6 publicly routable addresses on this exit relay */
-    policies_parse_exit_policy_reject_private(
-                                            dest, ipv6_exit,
+  }
+
+  /* Consider rejecting IPv4 and IPv6 advertised relay addresses, outbound bind
+   * addresses, publicly routable addresses, and configured port addresses
+   * on this exit relay */
+  policies_parse_exit_policy_reject_private(dest, ipv6_exit,
                                             configured_addresses,
                                             reject_interface_addresses,
                                             reject_configured_port_addresses);
-  }
+
   if (parse_addr_policy(cfg, dest, -1))
     return -1;
 
@@ -1908,8 +1919,14 @@ policies_parse_exit_policy_internal(config_line_t *cfg,
  * If <b>EXIT_POLICY_REJECT_PRIVATE</b> bit is set in <b>options</b>:
  *   - prepend an entry that rejects all destinations in all netblocks
  *     reserved for private use.
+ *   - prepend entries that reject the advertised relay addresses in
+ *     configured_addresses
+ * If <b>EXIT_POLICY_REJECT_LOCAL_INTERFACES</b> bit is set in <b>options</b>:
  *   - prepend entries that reject publicly routable addresses on this exit
  *     relay by calling policies_parse_exit_policy_internal
+ *   - prepend entries that reject the outbound bind addresses in
+ *     configured_addresses
+ *   - prepend entries that reject all configured port addresses
  *
  * If <b>EXIT_POLICY_ADD_DEFAULT</b> bit is set in <b>options</b>, append
  * default exit policy entries to <b>result</b> smartlist.
@@ -1922,12 +1939,14 @@ policies_parse_exit_policy(config_line_t *cfg, smartlist_t **dest,
   int ipv6_enabled = (options & EXIT_POLICY_IPV6_ENABLED) ? 1 : 0;
   int reject_private = (options & EXIT_POLICY_REJECT_PRIVATE) ? 1 : 0;
   int add_default = (options & EXIT_POLICY_ADD_DEFAULT) ? 1 : 0;
+  int reject_local_interfaces = (options &
+                                 EXIT_POLICY_REJECT_LOCAL_INTERFACES) ? 1 : 0;
 
   return policies_parse_exit_policy_internal(cfg,dest,ipv6_enabled,
                                              reject_private,
                                              configured_addresses,
-                                             reject_private,
-                                             reject_private,
+                                             reject_local_interfaces,
+                                             reject_local_interfaces,
                                              add_default);
 }
 
@@ -1993,6 +2012,7 @@ policies_copy_outbound_addresses_to_smartlist(smartlist_t *addr_list,
  *    add it to the list of configured addresses.
  *  - if ipv6_local_address is non-NULL, and not the null tor_addr_t, add it
  *    to the list of configured addresses.
+ * If <b>or_options->ExitPolicyRejectLocalInterfaces</b> is true:
  *  - if or_options->OutboundBindAddressIPv4_ is not the null tor_addr_t, add
  *    it to the list of configured addresses.
  *  - if or_options->OutboundBindAddressIPv6_ is not the null tor_addr_t, add
@@ -2036,11 +2056,20 @@ policies_parse_exit_policy_from_options(const or_options_t *or_options,
     parser_cfg |= EXIT_POLICY_ADD_DEFAULT;
   }
 
+  if (or_options->ExitPolicyRejectLocalInterfaces) {
+    parser_cfg |= EXIT_POLICY_REJECT_LOCAL_INTERFACES;
+  }
+
   /* Copy the configured addresses into the tor_addr_t* list */
-  policies_copy_ipv4h_to_smartlist(configured_addresses, local_address);
-  policies_copy_addr_to_smartlist(configured_addresses, ipv6_local_address);
-  policies_copy_outbound_addresses_to_smartlist(configured_addresses,
-                                                or_options);
+  if (or_options->ExitPolicyRejectPrivate) {
+    policies_copy_ipv4h_to_smartlist(configured_addresses, local_address);
+    policies_copy_addr_to_smartlist(configured_addresses, ipv6_local_address);
+  }
+
+  if (or_options->ExitPolicyRejectLocalInterfaces) {
+    policies_copy_outbound_addresses_to_smartlist(configured_addresses,
+                                                  or_options);
+  }
 
   rv = policies_parse_exit_policy(or_options->ExitPolicy, result, parser_cfg,
                                   configured_addresses);
@@ -2820,7 +2849,8 @@ getinfo_helper_policies(control_connection_t *conn,
       return -1;
     }
 
-    if (!options->ExitPolicyRejectPrivate) {
+    if (!options->ExitPolicyRejectPrivate &&
+        !options->ExitPolicyRejectLocalInterfaces) {
       *answer = tor_strdup("");
       return 0;
     }
@@ -2829,16 +2859,22 @@ getinfo_helper_policies(control_connection_t *conn,
     smartlist_t *configured_addresses = smartlist_new();
 
     /* Copy the configured addresses into the tor_addr_t* list */
-    policies_copy_ipv4h_to_smartlist(configured_addresses, me->addr);
-    policies_copy_addr_to_smartlist(configured_addresses, &me->ipv6_addr);
-    policies_copy_outbound_addresses_to_smartlist(configured_addresses,
-                                                  options);
+    if (options->ExitPolicyRejectPrivate) {
+      policies_copy_ipv4h_to_smartlist(configured_addresses, me->addr);
+      policies_copy_addr_to_smartlist(configured_addresses, &me->ipv6_addr);
+    }
+
+    if (options->ExitPolicyRejectLocalInterfaces) {
+      policies_copy_outbound_addresses_to_smartlist(configured_addresses,
+                                                    options);
+    }
 
     policies_parse_exit_policy_reject_private(
-                                            &private_policy_list,
-                                            options->IPv6Exit,
-                                            configured_addresses,
-                                            1, 1);
+                                      &private_policy_list,
+                                      options->IPv6Exit,
+                                      configured_addresses,
+                                      options->ExitPolicyRejectLocalInterfaces,
+                                      options->ExitPolicyRejectLocalInterfaces);
     *answer = policy_dump_to_string(private_policy_list, 1, 1);
 
     addr_policy_list_free(private_policy_list);
index aaa6fa0a4e5a3cab5de93589504d341ba72da28f..e134e686d22b512b813f52b9c75c67e1e4560fe3 100644 (file)
  */
 #define POLICY_BUF_LEN 72
 
-#define EXIT_POLICY_IPV6_ENABLED   (1 << 0)
-#define EXIT_POLICY_REJECT_PRIVATE (1 << 1)
-#define EXIT_POLICY_ADD_DEFAULT    (1 << 2)
+#define EXIT_POLICY_IPV6_ENABLED             (1 << 0)
+#define EXIT_POLICY_REJECT_PRIVATE           (1 << 1)
+#define EXIT_POLICY_ADD_DEFAULT              (1 << 2)
+#define EXIT_POLICY_REJECT_LOCAL_INTERFACES  (1 << 3)
 
 typedef enum firewall_connection_t {
   FIREWALL_OR_CONNECTION      = 0,
index 14182af86b0944e2b4566d6c1e508d5fac6c7292..a972bd5b293f52d8f2529f35c6adc643bff9c74c 100644 (file)
@@ -1082,10 +1082,32 @@ test_policies_getinfo_helper_policies(void *arg)
   append_exit_policy_string(&mock_my_routerinfo.exit_policy, "reject *6:*");
 
   mock_options.IPv6Exit = 1;
-  mock_options.ExitPolicyRejectPrivate = 1;
   tor_addr_from_ipv4h(&mock_options.OutboundBindAddressIPv4_, TEST_IPV4_ADDR);
   tor_addr_parse(&mock_options.OutboundBindAddressIPv6_, TEST_IPV6_ADDR);
 
+  mock_options.ExitPolicyRejectPrivate = 1;
+  mock_options.ExitPolicyRejectLocalInterfaces = 1;
+
+  rv = getinfo_helper_policies(NULL, "exit-policy/reject-private/relay",
+                               &answer, &errmsg);
+  tt_assert(rv == 0);
+  tt_assert(answer != NULL);
+  tt_assert(strlen(answer) > 0);
+  tor_free(answer);
+
+  mock_options.ExitPolicyRejectPrivate = 1;
+  mock_options.ExitPolicyRejectLocalInterfaces = 0;
+
+  rv = getinfo_helper_policies(NULL, "exit-policy/reject-private/relay",
+                               &answer, &errmsg);
+  tt_assert(rv == 0);
+  tt_assert(answer != NULL);
+  tt_assert(strlen(answer) > 0);
+  tor_free(answer);
+
+  mock_options.ExitPolicyRejectPrivate = 0;
+  mock_options.ExitPolicyRejectLocalInterfaces = 1;
+
   rv = getinfo_helper_policies(NULL, "exit-policy/reject-private/relay",
                                &answer, &errmsg);
   tt_assert(rv == 0);
@@ -1093,6 +1115,16 @@ test_policies_getinfo_helper_policies(void *arg)
   tt_assert(strlen(answer) > 0);
   tor_free(answer);
 
+  mock_options.ExitPolicyRejectPrivate = 0;
+  mock_options.ExitPolicyRejectLocalInterfaces = 0;
+
+  rv = getinfo_helper_policies(NULL, "exit-policy/reject-private/relay",
+                               &answer, &errmsg);
+  tt_assert(rv == 0);
+  tt_assert(answer != NULL);
+  tt_assert(strlen(answer) == 0);
+  tor_free(answer);
+
   rv = getinfo_helper_policies(NULL, "exit-policy/ipv4", &answer,
                                &errmsg);
   tt_assert(rv == 0);