ExitPolicy accept6/reject6 produces IPv6 wildcard addresses only

In previous versions of Tor, ExitPolicy accept6/reject6 * produced
policy entries for IPv4 and IPv6 wildcard addresses.

To reduce operator confusion, change accept6/reject6 * to only produce
an IPv6 wildcard address.

Resolves bug #16069.

Patch on 2eb7eafc9d and a96c0affcb (25 Oct 2012),
released in 0.2.4.7-alpha.
This commit is contained in:
teor (Tim Wilson-Brown) 2015-09-14 11:46:58 +10:00
parent 36ad8d8fdc
commit d3358a0a05
8 changed files with 126 additions and 30 deletions

View File

@ -1,4 +1,6 @@
o Minor bug fixes (torrc exit policies): o Minor bug fixes (torrc exit policies):
- accept6/reject6 * lines only produce IPv6 wildcard addresses,
previously they would produce both IPv4 and IPv6 wildcard addresses.
- When parsing torrc ExitPolicies, we now warn if: - When parsing torrc ExitPolicies, we now warn if:
* an IPv4 address is used on an accept6 or reject6 line. The line is * an IPv4 address is used on an accept6 or reject6 line. The line is
ignored, but the rest of the policy items in the list are used. ignored, but the rest of the policy items in the list are used.
@ -13,6 +15,6 @@
* when expanding an accept/reject * line to include both IPv4 and IPv6 * when expanding an accept/reject * line to include both IPv4 and IPv6
wildcard addresses. wildcard addresses.
- In each instance, usage advice is provided to avoid the message. - In each instance, usage advice is provided to avoid the message.
Partial fix for ticket 16069. Patch by "teor". Resolves ticket 16069. Patch by "teor".
Patch on 2eb7eafc9d78 and a96c0affcb4c (25 Oct 2012), Patch on 2eb7eafc9d78 and a96c0affcb4c (25 Oct 2012),
released in 0.2.4.7-alpha. released in 0.2.4.7-alpha.

View File

@ -1537,12 +1537,26 @@ is non-zero):
"\*". + "\*". +
+ +
For example, "accept 18.7.22.69:\*,reject 18.0.0.0/8:\*,accept \*:\*" would For example, "accept 18.7.22.69:\*,reject 18.0.0.0/8:\*,accept \*:\*" would
reject any traffic destined for MIT except for web.mit.edu, and accept reject any IPv4 traffic destined for MIT except for web.mit.edu, and accept
anything else. + any other IPv4 or IPv6 traffic. +
+ +
To specify all internal and link-local networks (including 0.0.0.0/8, Tor also allows IPv6 exit policy entries. For instance, "reject6 [FC00::]/7:*"
169.254.0.0/16, 127.0.0.0/8, 192.168.0.0/16, 10.0.0.0/8, and rejects all destinations that share 7 most significant bit prefix with
172.16.0.0/12), you can use the "private" alias instead of an address. address FC00::. Respectively, "accept6 [C000::]/3:*" accepts all destinations
that share 3 most significant bit prefix with address C000::. +
+
accept6 and reject6 only produce IPv6 exit policy entries. Using an IPv4
address with accept6 or reject6 is ignored and generates a warning.
accept/reject allows either IPv4 or IPv6 addresses. Use *4 as an IPv4
wildcard address, and *6 as an IPv6 wildcard address. accept/reject *
expands to matching IPv4 and IPv6 wildcard address rules. +
+
To specify all IPv4 and IPv6 internal and link-local networks (including
0.0.0.0/8, 169.254.0.0/16, 127.0.0.0/8, 192.168.0.0/16, 10.0.0.0/8,
172.16.0.0/12, [::]/8, [FC00::]/7, [FE80::]/10, [FEC0::]/10, [FF00::]/8,
and [::]/127), you can use the "private" alias instead of an address.
("private" always produces rules for IPv4 and IPv6 addresses, even when
used with accept6/reject6.)
These addresses are rejected by default (at the beginning of your exit These addresses are rejected by default (at the beginning of your exit
policy), along with your public IP address, unless you set the policy), along with your public IP address, unless you set the
ExitPolicyRejectPrivate config option to 0. For example, once you've done ExitPolicyRejectPrivate config option to 0. For example, once you've done
@ -1551,11 +1565,6 @@ is non-zero):
may also allow connections to your own computer that are addressed to its 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 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. +
+
Tor also allow IPv6 exit policy entries. For instance, "reject6 [FC00::]/7:*"
rejects all destinations that share 7 most significant bit prefix with
address FC00::. Respectively, "accept6 [C000::]/3:*" accepts all destinations
that share 3 most significant bit prefix with address C000::. +
+ +
This directive can be specified multiple times so you don't have to put it This directive can be specified multiple times so you don't have to put it
all on one line. + all on one line. +
@ -1577,6 +1586,9 @@ is non-zero):
reject *:6881-6999 reject *:6881-6999
accept *:* accept *:*
Since the default exit policy uses accept/reject *, it applies to both
IPv4 and IPv6 addresses.
[[ExitPolicyRejectPrivate]] **ExitPolicyRejectPrivate** **0**|**1**:: [[ExitPolicyRejectPrivate]] **ExitPolicyRejectPrivate** **0**|**1**::
Reject all private (local) networks, along with your own public IP address, Reject all private (local) networks, along with your own public IP address,
at the beginning of your exit policy. See above entry on ExitPolicy. at the beginning of your exit policy. See above entry on ExitPolicy.

View File

@ -620,13 +620,20 @@ tor_addr_to_PTR_name(char *out, size_t outlen,
* yield an IPv4 wildcard. * yield an IPv4 wildcard.
* *
* If 'flags & TAPMP_EXTENDED_STAR' is true, then the wildcard address '*' * If 'flags & TAPMP_EXTENDED_STAR' is true, then the wildcard address '*'
* yields an AF_UNSPEC wildcard address, and the following change is made * yields an AF_UNSPEC wildcard address, which expands to corresponding
* wildcard IPv4 and IPv6 rules, and the following change is made
* in the grammar above: * in the grammar above:
* Address ::= IPv4Address / "[" IPv6Address "]" / "*" / "*4" / "*6" * Address ::= IPv4Address / "[" IPv6Address "]" / "*" / "*4" / "*6"
* with the new "*4" and "*6" productions creating a wildcard to match * with the new "*4" and "*6" productions creating a wildcard to match
* IPv4 or IPv6 addresses. * IPv4 or IPv6 addresses.
* *
*/ * If 'flags & TAPMP_EXTENDED_STAR' and 'flags & TAPMP_STAR_IPV4_ONLY' are
* both true, then the wildcard address '*' yields an IPv4 wildcard.
*
* If 'flags & TAPMP_EXTENDED_STAR' and 'flags & TAPMP_STAR_IPV6_ONLY' are
* both true, then the wildcard address '*' yields an IPv6 wildcard.
*
* TAPMP_STAR_IPV4_ONLY and TAPMP_STAR_IPV6_ONLY are mutually exclusive. */
int int
tor_addr_parse_mask_ports(const char *s, tor_addr_parse_mask_ports(const char *s,
unsigned flags, unsigned flags,
@ -643,6 +650,10 @@ tor_addr_parse_mask_ports(const char *s,
tor_assert(s); tor_assert(s);
tor_assert(addr_out); tor_assert(addr_out);
/* We can either only want an IPv4 address or only want an IPv6 address,
* but we can't only want IPv4 & IPv6 at the same time. */
tor_assert(!((flags & TAPMP_STAR_IPV4_ONLY)
&& (flags & TAPMP_STAR_IPV6_ONLY)));
/** Longest possible length for an address, mask, and port-range combination. /** Longest possible length for an address, mask, and port-range combination.
* Includes IP, [], /mask, :, ports */ * Includes IP, [], /mask, :, ports */
@ -688,12 +699,21 @@ tor_addr_parse_mask_ports(const char *s,
if (!strcmp(address, "*")) { if (!strcmp(address, "*")) {
if (flags & TAPMP_EXTENDED_STAR) { if (flags & TAPMP_EXTENDED_STAR) {
family = AF_UNSPEC; if (flags & TAPMP_STAR_IPV4_ONLY) {
tor_addr_make_unspec(addr_out); family = AF_INET;
log_info(LD_GENERAL, tor_addr_from_ipv4h(addr_out, 0);
"'%s' expands into rules which apply to all IPv4 and IPv6 " } else if (flags & TAPMP_STAR_IPV6_ONLY) {
"addresses. (Use accept/reject *4:* for IPv4 or " static char nil_bytes[16] = { [0]=0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 };
"accept[6]/reject[6] *6:* for IPv6.)", s); family = AF_INET6;
tor_addr_from_ipv6_bytes(addr_out, nil_bytes);
} else {
family = AF_UNSPEC;
tor_addr_make_unspec(addr_out);
log_info(LD_GENERAL,
"'%s' expands into rules which apply to all IPv4 and IPv6 "
"addresses. (Use accept/reject *4:* for IPv4 or "
"accept[6]/reject[6] *6:* for IPv6.)", s);
}
} else { } else {
family = AF_INET; family = AF_INET;
tor_addr_from_ipv4h(addr_out, 0); tor_addr_from_ipv4h(addr_out, 0);

View File

@ -227,10 +227,19 @@ int tor_addr_parse_PTR_name(tor_addr_t *result, const char *address,
int tor_addr_port_lookup(const char *s, tor_addr_t *addr_out, int tor_addr_port_lookup(const char *s, tor_addr_t *addr_out,
uint16_t *port_out); uint16_t *port_out);
/* Does the address * yield an AF_UNSPEC wildcard address (1) and do we
/* Does the address * yield an AF_UNSPEC wildcard address (1),
* which expands to corresponding wildcard IPv4 and IPv6 rules, and do we
* allow *4 and *6 for IPv4 and IPv6 wildcards, respectively; * allow *4 and *6 for IPv4 and IPv6 wildcards, respectively;
* or does the address * yield IPv4 wildcard address (0). */ * or does the address * yield IPv4 wildcard address (0). */
#define TAPMP_EXTENDED_STAR 1 #define TAPMP_EXTENDED_STAR 1
/* Does the address * yield an IPv4 wildcard address rule (1);
* or does it yield wildcard IPv4 and IPv6 rules (0) */
#define TAPMP_STAR_IPV4_ONLY (1 << 1)
/* Does the address * yield an IPv6 wildcard address rule (1);
* or does it yield wildcard IPv4 and IPv6 rules (0) */
#define TAPMP_STAR_IPV6_ONLY (1 << 2)
/* TAPMP_STAR_IPV4_ONLY and TAPMP_STAR_IPV6_ONLY are mutually exclusive. */
int tor_addr_parse_mask_ports(const char *s, unsigned flags, int tor_addr_parse_mask_ports(const char *s, unsigned flags,
tor_addr_t *addr_out, maskbits_t *mask_out, tor_addr_t *addr_out, maskbits_t *mask_out,
uint16_t *port_min_out, uint16_t *port_max_out); uint16_t *port_min_out, uint16_t *port_max_out);

View File

@ -1,5 +1,5 @@
## Configuration file for a typical Tor user ## Configuration file for a typical Tor user
## Last updated 2 September 2014 for Tor 0.2.6.1-alpha. ## Last updated 11 September 2015 for Tor 0.2.7.3-alpha.
## (may or may not work for much older or much newer versions of Tor.) ## (may or may not work for much older or much newer versions of Tor.)
## ##
## Lines that begin with "## " try to explain what's going on. Lines ## Lines that begin with "## " try to explain what's going on. Lines
@ -24,6 +24,7 @@
## can access your SocksPort may be able to learn about the connections ## can access your SocksPort may be able to learn about the connections
## you make. ## you make.
#SocksPolicy accept 192.168.0.0/16 #SocksPolicy accept 192.168.0.0/16
#SocksPolicy accept6 FC00::/7
#SocksPolicy reject * #SocksPolicy reject *
## Logs go to stdout at level "notice" unless redirected by something ## Logs go to stdout at level "notice" unless redirected by something
@ -174,8 +175,10 @@
## networks, including to your public IP address. See the man page entry ## networks, including to your public IP address. See the man page entry
## for ExitPolicyRejectPrivate if you want to allow "exit enclaving". ## for ExitPolicyRejectPrivate if you want to allow "exit enclaving".
## ##
#ExitPolicy accept *:6660-6667,reject *:* # allow irc ports but no more #ExitPolicy accept *:6660-6667,reject *:* # allow irc ports on IPv4 and IPv6 but no more
#ExitPolicy accept *:119 # accept nntp as well as default exit policy #ExitPolicy accept *:119 # accept nntp ports on IPv4 and IPv6 as well as default exit policy
#ExitPolicy accept *4:119 # accept nntp ports on IPv4 only as well as default exit policy
#ExitPolicy accept6 *6:119 # accept nntp ports on IPv6 only as well as default exit policy
#ExitPolicy reject *:* # no exits allowed #ExitPolicy reject *:* # no exits allowed
## Bridge relays (or "bridges") are Tor relays that aren't listed in the ## Bridge relays (or "bridges") are Tor relays that aren't listed in the

View File

@ -1,5 +1,5 @@
## Configuration file for a typical Tor user ## Configuration file for a typical Tor user
## Last updated 2 September 2014 for Tor 0.2.6.1-alpha. ## Last updated 11 September 2015 for Tor 0.2.7.3-alpha.
## (may or may not work for much older or much newer versions of Tor.) ## (may or may not work for much older or much newer versions of Tor.)
## ##
## Lines that begin with "## " try to explain what's going on. Lines ## Lines that begin with "## " try to explain what's going on. Lines
@ -24,6 +24,7 @@
## can access your SocksPort may be able to learn about the connections ## can access your SocksPort may be able to learn about the connections
## you make. ## you make.
#SocksPolicy accept 192.168.0.0/16 #SocksPolicy accept 192.168.0.0/16
#SocksPolicy accept6 FC00::/7
#SocksPolicy reject * #SocksPolicy reject *
## Logs go to stdout at level "notice" unless redirected by something ## Logs go to stdout at level "notice" unless redirected by something
@ -174,8 +175,10 @@
## networks, including to your public IP address. See the man page entry ## networks, including to your public IP address. See the man page entry
## for ExitPolicyRejectPrivate if you want to allow "exit enclaving". ## for ExitPolicyRejectPrivate if you want to allow "exit enclaving".
## ##
#ExitPolicy accept *:6660-6667,reject *:* # allow irc ports but no more #ExitPolicy accept *:6660-6667,reject *:* # allow irc ports on IPv4 and IPv6 but no more
#ExitPolicy accept *:119 # accept nntp as well as default exit policy #ExitPolicy accept *:119 # accept nntp ports on IPv4 and IPv6 as well as default exit policy
#ExitPolicy accept *4:119 # accept nntp ports on IPv4 only as well as default exit policy
#ExitPolicy accept6 *6:119 # accept nntp ports on IPv6 only as well as default exit policy
#ExitPolicy reject *:* # no exits allowed #ExitPolicy reject *:* # no exits allowed
## Bridge relays (or "bridges") are Tor relays that aren't listed in the ## Bridge relays (or "bridges") are Tor relays that aren't listed in the

View File

@ -3820,6 +3820,12 @@ router_parse_addr_policy(directory_token_t *tok, unsigned fmt_flags)
else else
newe.policy_type = ADDR_POLICY_ACCEPT; newe.policy_type = ADDR_POLICY_ACCEPT;
/* accept6/reject6 * produces an IPv6 wildcard address only.
* (accept/reject * produces rules for IPv4 and IPv6 wildcard addresses.) */
if (tok->tp == K_ACCEPT6 || tok->tp == K_REJECT6) {
fmt_flags |= TAPMP_STAR_IPV6_ONLY;
}
if (tor_addr_parse_mask_ports(arg, fmt_flags, &newe.addr, &newe.maskbits, if (tor_addr_parse_mask_ports(arg, fmt_flags, &newe.addr, &newe.maskbits,
&newe.prt_min, &newe.prt_max) < 0) { &newe.prt_min, &newe.prt_max) < 0) {
log_warn(LD_DIR,"Couldn't parse line %s. Dropping", escaped(arg)); log_warn(LD_DIR,"Couldn't parse line %s. Dropping", escaped(arg));
@ -3829,9 +3835,12 @@ router_parse_addr_policy(directory_token_t *tok, unsigned fmt_flags)
return addr_policy_get_canonical_entry(&newe); return addr_policy_get_canonical_entry(&newe);
} }
/** Parse an exit policy line of the format "accept/reject private:...". /** Parse an exit policy line of the format "accept[6]/reject[6] private:...".
* This didn't exist until Tor 0.1.1.15, so nobody should generate it in * This didn't exist until Tor 0.1.1.15, so nobody should generate it in
* router descriptors until earlier versions are obsolete. * router descriptors until earlier versions are obsolete.
*
* accept/reject and accept6/reject6 private all produce rules for both
* IPv4 and IPv6 addresses.
*/ */
static addr_policy_t * static addr_policy_t *
router_parse_addr_policy_private(directory_token_t *tok) router_parse_addr_policy_private(directory_token_t *tok)

View File

@ -77,7 +77,8 @@ test_policies_general(void *arg)
int i; int i;
smartlist_t *policy = NULL, *policy2 = NULL, *policy3 = NULL, smartlist_t *policy = NULL, *policy2 = NULL, *policy3 = NULL,
*policy4 = NULL, *policy5 = NULL, *policy6 = NULL, *policy4 = NULL, *policy5 = NULL, *policy6 = NULL,
*policy7 = NULL; *policy7 = NULL, *policy8 = NULL, *policy9 = NULL,
*policy10 = NULL, *policy11 = NULL;
addr_policy_t *p; addr_policy_t *p;
tor_addr_t tar; tor_addr_t tar;
config_line_t line; config_line_t line;
@ -192,6 +193,30 @@ test_policies_general(void *arg)
tt_assert(p != NULL); tt_assert(p != NULL);
smartlist_add(policy7, p); smartlist_add(policy7, p);
tt_int_op(0, OP_EQ, policies_parse_exit_policy(NULL, &policy8,
EXIT_POLICY_IPV6_ENABLED |
EXIT_POLICY_REJECT_PRIVATE |
EXIT_POLICY_ADD_DEFAULT, 0));
tt_assert(policy8);
tt_int_op(0, OP_EQ, policies_parse_exit_policy(NULL, &policy9,
EXIT_POLICY_REJECT_PRIVATE |
EXIT_POLICY_ADD_DEFAULT, 0));
tt_assert(policy9);
/* accept6 * and reject6 * produce IPv6 wildcards only */
policy10 = smartlist_new();
p = router_parse_addr_policy_item_from_string("accept6 *:*",-1);
tt_assert(p != NULL);
smartlist_add(policy10, p);
policy11 = smartlist_new();
p = router_parse_addr_policy_item_from_string("reject6 *:*",-1);
tt_assert(p != NULL);
smartlist_add(policy11, p);
tt_assert(!exit_policy_is_general_exit(policy)); tt_assert(!exit_policy_is_general_exit(policy));
tt_assert(exit_policy_is_general_exit(policy2)); tt_assert(exit_policy_is_general_exit(policy2));
tt_assert(!exit_policy_is_general_exit(NULL)); tt_assert(!exit_policy_is_general_exit(NULL));
@ -200,6 +225,10 @@ test_policies_general(void *arg)
tt_assert(!exit_policy_is_general_exit(policy5)); tt_assert(!exit_policy_is_general_exit(policy5));
tt_assert(!exit_policy_is_general_exit(policy6)); tt_assert(!exit_policy_is_general_exit(policy6));
tt_assert(!exit_policy_is_general_exit(policy7)); tt_assert(!exit_policy_is_general_exit(policy7));
tt_assert(exit_policy_is_general_exit(policy8));
tt_assert(exit_policy_is_general_exit(policy9));
tt_assert(!exit_policy_is_general_exit(policy10));
tt_assert(!exit_policy_is_general_exit(policy11));
tt_assert(cmp_addr_policies(policy, policy2)); tt_assert(cmp_addr_policies(policy, policy2));
tt_assert(cmp_addr_policies(policy, NULL)); tt_assert(cmp_addr_policies(policy, NULL));
@ -208,7 +237,12 @@ test_policies_general(void *arg)
tt_assert(!policy_is_reject_star(policy2, AF_INET)); tt_assert(!policy_is_reject_star(policy2, AF_INET));
tt_assert(policy_is_reject_star(policy, AF_INET)); tt_assert(policy_is_reject_star(policy, AF_INET));
tt_assert(policy_is_reject_star(policy10, AF_INET));
tt_assert(!policy_is_reject_star(policy10, AF_INET6));
tt_assert(policy_is_reject_star(policy11, AF_INET));
tt_assert(policy_is_reject_star(policy11, AF_INET6));
tt_assert(policy_is_reject_star(NULL, AF_INET)); tt_assert(policy_is_reject_star(NULL, AF_INET));
tt_assert(policy_is_reject_star(NULL, AF_INET6));
addr_policy_list_free(policy); addr_policy_list_free(policy);
policy = NULL; policy = NULL;
@ -219,13 +253,13 @@ test_policies_general(void *arg)
line.value = (char*)"accept *:80,reject private:*,reject *:*"; line.value = (char*)"accept *:80,reject private:*,reject *:*";
line.next = NULL; line.next = NULL;
tt_int_op(0, OP_EQ, policies_parse_exit_policy(&line,&policy, tt_int_op(0, OP_EQ, policies_parse_exit_policy(&line,&policy,
EXIT_POLICY_IPV6_ENABLED | ~EXIT_POLICY_IPV6_ENABLED |
EXIT_POLICY_ADD_DEFAULT,0)); EXIT_POLICY_ADD_DEFAULT,0));
tt_assert(policy); tt_assert(policy);
//test_streq(policy->string, "accept *:80"); //test_streq(policy->string, "accept *:80");
//test_streq(policy->next->string, "reject *:*"); //test_streq(policy->next->string, "reject *:*");
tt_int_op(smartlist_len(policy),OP_EQ, 4); tt_int_op(smartlist_len(policy),OP_EQ, 9);
/* test policy summaries */ /* test policy summaries */
/* check if we properly ignore private IP addresses */ /* check if we properly ignore private IP addresses */
@ -427,6 +461,10 @@ test_policies_general(void *arg)
addr_policy_list_free(policy5); addr_policy_list_free(policy5);
addr_policy_list_free(policy6); addr_policy_list_free(policy6);
addr_policy_list_free(policy7); addr_policy_list_free(policy7);
addr_policy_list_free(policy8);
addr_policy_list_free(policy9);
addr_policy_list_free(policy10);
addr_policy_list_free(policy11);
tor_free(policy_str); tor_free(policy_str);
if (sm) { if (sm) {
SMARTLIST_FOREACH(sm, char *, s, tor_free(s)); SMARTLIST_FOREACH(sm, char *, s, tor_free(s));