Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Tor Trac #27490]: When ClientPreferIPv6ORPort is set to auto, and a relay is being chosen for a directory or orport connection, prefer IPv4 or IPv6 at random #317

Closed
wants to merge 18 commits into from

Conversation

Labels
None yet
Projects
None yet
3 participants
@neelchauhan
Copy link
Contributor

@neelchauhan neelchauhan commented Sep 11, 2018

For the ticket here.

Copy link
Contributor

@teor2345 teor2345 left a comment

There is one design problem with this patch:

ClientPreferIPv6ORPort already has an "auto" setting, which means "bridge clients use the configured bridge IP address, other clients use IPv4". The auto setting is the default. (I didn't realise when I wrote down the steps.)

This patch tells all clients to use IPv4 50% of the time, and IPv6 50% of the time. We can't make 50% of clients use IPv6 by default, until most relays have IPv6. Otherwise, we would overload the IPv6 Guards. Right now, about 25% of Guard consensus weight has IPv6:
https://metrics.torproject.org/advbw-ipv6.html

Please add another option for this feature. You can call it ClientAutoIPv6ORPort if you want.

I also added a ticket to set the IPv6 probability based on the number of Guards or Bridges with IPv6:
https://trac.torproject.org/projects/tor/ticket/27647

Otherwise, this is a good patch, but some documentation and tests need to be updated.

In the future, we also want to remove ClientPreferIPv6DirPort, and decide between IPv4 and IPv6 just before connecting. But this patch helps us get better IPv6 support.

Please fix the policy/fascist_firewall_choose_address unit test:
https://travis-ci.org/torproject/tor/jobs/427442291#L6076

Please update the ClientPreferIPv6ORPort documentation in the struct:

/** If true, prefer an IPv6 OR port over an IPv4 one for entry node

And man page:

tor/doc/tor.1.txt

Line 1731 in 8815960

[[ClientPreferIPv6ORPort]] **ClientPreferIPv6ORPort** **0**|**1**|**auto**::

Tor logs an info-level message when a non-preferred address family is used:

/* Check if we couldn't satisfy an address family preference */

When ClientPreferIPv6ORPort is auto and fascist_firewall_use_ipv6() is true, we should log the address family Tor actually used. When ClientPreferIPv6ORPort is not auto, we should keep the existing logs.

fascist_firewall_prefer_ipv6_orport() and node_ipv6_or_preferred() used to return the same value every time. Please update the comments in every function that calls fascist_firewall_prefer_ipv6_orport() and node_ipv6_or_preferred() to say that they can return a random value:

If ClientPreferIPv6ORPort is auto, and the bridge has IPv4 and IPv6 addresses, assign it a random preference:

node->ipv6_preferred = (fascist_firewall_prefer_ipv6_orport(options) &&

If ClientPreferIPv6ORPort is auto, and the node has IPv4 and IPv6 addresses, assign it a random preference:

if (fascist_firewall_prefer_ipv6_orport(options) &&

If ClientPreferIPv6ORPort is auto, and the node has IPv4 and IPv6 addresses, returns a random preference:

fascist_firewall_prefer_ipv6_orport(const or_options_t *options)

If ClientPreferIPv6ORPort is auto, and the routerstatus has IPv4 and IPv6 addresses, choose one of those addresses at random:

int pref_ipv6 = (fw_connection == FIREWALL_OR_CONNECTION

If ClientPreferIPv6ORPort is auto, and the node has IPv4 and IPv6 addresses, prefer one of those addresses at random:

/** Like fascist_firewall_allows_base(), but takes node, and looks up pref_ipv6

If ClientPreferIPv6ORPort is auto, and the node has IPv4 and IPv6 addresses, choose one of those addresses at random:

/** Copy the preferred OR port (IP address and TCP port) for

@@ -0,0 +1,6 @@
o Minor features (ipv6):
- If ClientPreferIPv6ORPort is set to auto and a relay is being chosen
for a Directory or ORPort connection, we choose IPv4 or IPv6 at random.
Copy link
Contributor

@teor2345 teor2345 Sep 12, 2018

This line of the changes file is confusing: clients only make ORPort connections. (They tunnel directory connections over the ORPort.)

I suggest just saying: "for an ORPort connection"

Copy link
Contributor

@teor2345 teor2345 Sep 12, 2018

Also, we still choose whatever address is in the bridge line, see:

if (options->ClientPreferIPv6ORPort == -1) {
/* Mark which address to use based on which bridge_t we got. */
node->ipv6_preferred = (tor_addr_family(&bridge->addr) == AF_INET6 &&
!tor_addr_is_null(&node->rs->ipv6_addr));
} else {
/* Mark which address to use based on user preference */
node->ipv6_preferred = (fascist_firewall_prefer_ipv6_orport(options) &&
!tor_addr_is_null(&node->rs->ipv6_addr));
}

I suggest saying: "we choose IPv4 or IPv6 at random, except for bridges, which use the address in the Bridge line."

/* Choose whether we prefer IPv4 or IPv6 by randomly choosing an address
* family. Return 0 for IPv4, and 1 for IPv6. */
static int
fascist_firewall_choose_preferred_addr(void)
Copy link
Contributor

@teor2345 teor2345 Sep 12, 2018

This function name is confusing: the other fascist_firewall_choose_* functions choose between two addresses. This function chooses between two address families at random.

I suggest: "fascist_firewall_rand_preferred_addr"

@teor2345
Copy link
Contributor

@teor2345 teor2345 commented Sep 12, 2018

I think that this patch will break existing configs when:

  • there are a small number of Bridges (or EntryNodes),
  • they are all marked as IPv4-preferred when they are loaded, and
  • the device running tor only has IPv6.

We can fix this bug in a few different ways:

  • make sure we always fall back to non-preferred addresses if all preferred addresses fail:
    • we will find these bugs when we test
  • reset the preferred flags on all nodes if all preferred addresses failL
    • I think we should remove the flag instead
  • stop setting the IPv6 preferred flag on nodes:

@coveralls
Copy link

@coveralls coveralls commented Sep 12, 2018

Coverage Status

Coverage increased (+0.04%) to 61.865% when pulling a956184 on neelchauhan:b27490 into aebc98d on torproject:master.

@@ -666,6 +666,9 @@ struct or_options_t {
* accessing this value directly. */
int ClientPreferIPv6DirPort;

/** If true, automatically choose between IPv4 and IPv6. */
Copy link
Contributor

@teor2345 teor2345 Sep 21, 2018

We choose between IPv4 and IPv6 at random, so let's document that.

@@ -329,6 +329,7 @@ static config_var_t option_vars_[] = {
V(ClientOnly, BOOL, "0"),
V(ClientPreferIPv6ORPort, AUTOBOOL, "auto"),
V(ClientPreferIPv6DirPort, AUTOBOOL, "auto"),
V(ClientAutoIPv6ORPort, BOOL, "0"),
Copy link
Contributor

@teor2345 teor2345 Sep 21, 2018

Each new option needs an entry in the tor man page. Edit doc/tor.1.txt

Copy link
Contributor

@teor2345 teor2345 left a comment

I am confused by these commits. I will suggest a way forward in the trac ticket.

@@ -458,8 +458,9 @@ fascist_firewall_use_ipv6(const or_options_t *options)
* IPv4, or they prefer it.
* ClientPreferIPv6DirPort is deprecated, but check it anyway. */
return (options->ClientUseIPv6 == 1 || options->ClientUseIPv4 == 0 ||
options->ClientPreferIPv6ORPort ||
options->ClientPreferIPv6DirPort == 1 || options->UseBridges == 1);
options->ClientPreferIPv6ORPort == -1 ||
Copy link
Contributor

@teor2345 teor2345 Sep 21, 2018

IPv6 is also used when ClientPreferIPv6ORPort is 1, so this line should not be changed.

} else if (options->ClientPreferIPv6ORPort == -1) {
return fascist_firewall_choose_preferred_addr();
} else if (options->ClientAutoIPv6ORPort) {
return fascist_firewall_rand_preferred_addr();
Copy link
Contributor

@teor2345 teor2345 Sep 21, 2018

If ClientAutoIPv6ORPort is 1 and ClientPreferIPv6ORPort is 1, what should happen?

I think we should prefer IPv4 and IPv6 at random, but this code will just prefer IPv6.
To make ClientAutoIPv6ORPort override ClientPreferIPv6ORPort, check it first.

Previously, we preferred to IPv4 if ClientPreferIPv6ORPort is auto
except when an IPv6 bridge was specified. Closes ticket 27490. Patch
by Neel Chauhan.
for an ORPort connection, we prefer IPv4 or IPv6 at random if we have
Copy link
Contributor

@teor2345 teor2345 Sep 21, 2018

ClientPreferIPv6ORPort does not choose at random any more. Only ClientAutoIPv6ORPort chooses at random.

@@ -1733,8 +1733,9 @@ The following options are useful only for clients (that is, if
address over one with IPv4 if a given entry node has both. (Tor also
prefers an IPv6 ORPort if IPv4Client is set to 0.) If this option is set
to auto, Tor bridge clients prefer the configured bridge address, and
other clients prefer IPv4. Other things may influence the choice. This
option breaks a tie to the favor of IPv6. (Default: auto)
other clients choose what they have, or choose randomly if they have
Copy link
Contributor

@teor2345 teor2345 Sep 21, 2018

ClientPreferIPv6ORPort does not choose randomly. ClientAutoIPv6ORPort chooses randomly.

@@ -657,8 +657,8 @@ struct or_options_t {
int ClientUseIPv6;
/** If true, prefer an IPv6 OR port over an IPv4 one for entry node
* connections. If auto, bridge clients prefer IPv6, and other clients
* prefer IPv4. Use node_ipv6_or_preferred() instead of accessing this value
* directly. */
* prefer what they have or choose randomly if they are dual-stack. Use
Copy link
Contributor

@teor2345 teor2345 Sep 21, 2018

ClientPreferIPv6ORPort does not choose randomly. ClientAutoIPv6ORPort chooses randomly.

/* Mark which address to use based on user preference */
/* Mark which address to use based on user preference. Keep in mind
* that fascist_firewall_prefer_ipv6_orport() can infer a random
* preference if both IPv4 and IPv6 are available. */
Copy link
Contributor

@teor2345 teor2345 Sep 21, 2018

fascist_firewall_prefer_ipv6_orport() only returns a random preference if ClientAutoIPv6ORPort is 1

@@ -1529,6 +1529,8 @@ node_has_ipv6_dirport(const node_t *node)
*
* If you don't have a node, consider looking it up.
* If there is no node, use fascist_firewall_prefer_ipv6_orport().
* fascist_firewall_prefer_ipv6_orport() can infer a random
* preference if we have both IPv4 and IPv6.
Copy link
Contributor

@teor2345 teor2345 Sep 21, 2018

fascist_firewall_prefer_ipv6_orport() only returns a random preference if ClientAutoIPv6ORPort is 1

@@ -1539,6 +1541,7 @@ node_ipv6_or_preferred(const node_t *node)

/* XX/teor - node->ipv6_preferred is set from
* fascist_firewall_prefer_ipv6_orport() each time the consensus is loaded.
* and can be random.
Copy link
Contributor

@teor2345 teor2345 Sep 21, 2018

fascist_firewall_prefer_ipv6_orport() only returns a random preference if ClientAutoIPv6ORPort is 1

@@ -752,9 +752,14 @@ rewrite_node_address_for_bridge(const bridge_info_t *bridge, node_t *node)
}

if (options->ClientPreferIPv6ORPort == -1) {
Copy link
Contributor

@teor2345 teor2345 Sep 21, 2018

Do not change how ClientPreferIPv6ORPort works. Instead, add new behaviour when ClientAutoIPv6ORPort is set.

@@ -618,7 +618,10 @@ nodelist_set_consensus(networkstatus_t *ns)
node->is_bad_exit = rs->is_bad_exit;
node->is_hs_dir = rs->is_hs_dir;
node->ipv6_preferred = 0;
if (fascist_firewall_prefer_ipv6_orport(options) &&
if (options->ClientPreferIPv6ORPort == -1 &&
Copy link
Contributor

@teor2345 teor2345 Sep 21, 2018

Do not change how ClientPreferIPv6ORPort works. Instead, add new behaviour when ClientAutoIPv6ORPort is set.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment