Commit ba2be81f authored by Nick Mathewson's avatar Nick Mathewson 🥔
Browse files

Merge remote-tracking branch 'teor/feature17840-v11-merged-v2'

parents cae59b91 c213f277
Loading
Loading
Loading
Loading

changes/feature17840

0 → 100644
+9 −0
Original line number Diff line number Diff line
  o Minor feature (IPv6):
    - Add ClientUseIPv4, which is set to 1 by default. If set to 0, tor
      avoids using IPv4 for client OR and directory connections.
    - Add ClientPreferIPv6DirPort, which is set to 0 by default. If set
      to 1, tor prefers IPv6 directory addresses.
    - Try harder to fulfil IP version restrictions ClientUseIPv4 0 and
      ClientUseIPv6 0; and the preferences ClientPreferIPv6ORPort and
      ClientPreferIPv6DirPort.
      Closes ticket 17840; patch by "teor".
+29 −8
Original line number Diff line number Diff line
@@ -390,6 +390,7 @@ GENERAL OPTIONS
    authorities.
    By default, the directory authorities are also FallbackDirs. Specifying a
    FallbackDir replaces Tor's default hard-coded FallbackDirs (if any).
    (See the **DirAuthority** entry for an explanation of each flag.)

[[UseDefaultFallbackDirs]] **UseDefaultFallbackDirs** **0**|**1**::
    Use Tor's default hard-coded FallbackDirs (if any). (When a
@@ -413,6 +414,10 @@ GENERAL OPTIONS
    if an "ipv6=__address__:__orport__" flag is present, then the directory
    authority is listening for IPv6 connections on the indicated IPv6 address
    and OR Port. +
 +
    Tor will contact the authority at __address__:__port__ (the DirPort) to
    download directory documents. If an IPv6 address is supplied, Tor will
    also download directory documents at the IPv6 address on the DirPort. +
 +
    If no **DirAuthority** line is given, Tor will use the default directory
    authorities. NOTE: this option is intended for setting up a private Tor
@@ -1506,17 +1511,33 @@ The following options are useful only for clients (that is, if
    If no defaults are available there, these options default to 20, .80,
    .60, and 100, respectively.

[[ClientUseIPv4]] **ClientUseIPv4** **0**|**1**::
    If this option is set to 0, Tor will avoid connecting to directory servers
    and entry nodes over IPv4. Note that clients with an IPv4
    address in a **Bridge**, proxy, or pluggable transport line will try
    connecting over IPv4 even if **ClientUseIPv4** is set to 0. (Default: 1)

[[ClientUseIPv6]] **ClientUseIPv6** **0**|**1**::
    If this option is set to 1, Tor might connect to entry nodes over
    IPv6. Note that clients configured with an IPv6 address in a
    **Bridge** line will try connecting over IPv6 even if
    **ClientUseIPv6** is set to 0. (Default: 0)
    If this option is set to 1, Tor might connect to directory servers or
    entry nodes over IPv6. Note that clients configured with an IPv6 address
    in a **Bridge**, proxy, or pluggable transport line will try connecting
    over IPv6 even if **ClientUseIPv6** is set to 0. (Default: 0)

[[ClientPreferIPv6DirPort]] **ClientPreferIPv6DirPort** **0**|**1**|**auto**::
    If this option is set to 1, Tor prefers a directory port with an IPv6
    address over one with IPv4, for direct connections, if a given directory
    server has both. (Tor also prefers an IPv6 DirPort if IPv4Client is set to
    0.) If this option is set to auto, clients prefer IPv4. Other things may
    influence the choice. This option breaks a tie to the favor of IPv6.
    (Default: auto)

[[ClientPreferIPv6ORPort]] **ClientPreferIPv6ORPort** **0**|**1**::
[[ClientPreferIPv6ORPort]] **ClientPreferIPv6ORPort** **0**|**1**|**auto**::
    If this option is set to 1, Tor prefers an OR port with an IPv6
    address over one with IPv4 if a given entry node has both. Other
    things may influence the choice. This option breaks a tie to the
    favor of IPv6. (Default: 0)
    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)

[[PathsNeededToBuildCircuits]] **PathsNeededToBuildCircuits** __NUM__::
    Tor clients don't build circuits for user traffic until they know
+53 −0
Original line number Diff line number Diff line
@@ -910,6 +910,59 @@ tor_addr_is_loopback(const tor_addr_t *addr)
  }
}

/* Is addr valid?
 * Checks that addr is non-NULL and not tor_addr_is_null().
 * If for_listening is true, IPv4 addr 0.0.0.0 is allowed.
 * It means "bind to all addresses on the local machine". */
int
tor_addr_is_valid(const tor_addr_t *addr, int for_listening)
{
  /* NULL addresses are invalid regardless of for_listening */
  if (addr == NULL) {
    return 0;
  }

  /* Only allow IPv4 0.0.0.0 for_listening. */
  if (for_listening && addr->family == AF_INET
      && tor_addr_to_ipv4h(addr) == 0) {
    return 1;
  }

  /* Otherwise, the address is valid if it's not tor_addr_is_null() */
  return !tor_addr_is_null(addr);
}

/* Is the network-order IPv4 address v4n_addr valid?
 * Checks that addr is not zero.
 * Except if for_listening is true, where IPv4 addr 0.0.0.0 is allowed. */
int
tor_addr_is_valid_ipv4n(uint32_t v4n_addr, int for_listening)
{
  /* Any IPv4 address is valid with for_listening. */
  if (for_listening) {
    return 1;
  }

  /* Otherwise, zero addresses are invalid. */
  return v4n_addr != 0;
}

/* Is port valid?
 * Checks that port is not 0.
 * Except if for_listening is true, where port 0 is allowed.
 * It means "OS chooses a port". */
int
tor_port_is_valid(uint16_t port, int for_listening)
{
  /* Any port value is valid with for_listening. */
  if (for_listening) {
    return 1;
  }

  /* Otherwise, zero ports are invalid. */
  return port != 0;
}

/** Set <b>dest</b> to equal the IPv4 address in <b>v4addr</b> (given in
 * network order). */
void
+21 −0
Original line number Diff line number Diff line
@@ -267,6 +267,27 @@ void tor_addr_from_in6(tor_addr_t *dest, const struct in6_addr *in6);
int tor_addr_is_null(const tor_addr_t *addr);
int tor_addr_is_loopback(const tor_addr_t *addr);

int tor_addr_is_valid(const tor_addr_t *addr, int for_listening);
int tor_addr_is_valid_ipv4n(uint32_t v4n_addr, int for_listening);
#define tor_addr_is_valid_ipv4h(v4h_addr, for_listening) \
        tor_addr_is_valid_ipv4n(htonl(v4h_addr), (for_listening))
int tor_port_is_valid(uint16_t port, int for_listening);
/* Are addr and port both valid? */
#define tor_addr_port_is_valid(addr, port, for_listening) \
        (tor_addr_is_valid((addr), (for_listening)) &&    \
         tor_port_is_valid((port), (for_listening)))
/* Are ap->addr and ap->port both valid? */
#define tor_addr_port_is_valid_ap(ap, for_listening) \
        tor_addr_port_is_valid(&(ap)->addr, (ap)->port, (for_listening))
/* Are the network-order v4addr and port both valid? */
#define tor_addr_port_is_valid_ipv4n(v4n_addr, port, for_listening) \
        (tor_addr_is_valid_ipv4n((v4n_addr), (for_listening)) &&    \
         tor_port_is_valid((port), (for_listening)))
/* Are the host-order v4addr and port both valid? */
#define tor_addr_port_is_valid_ipv4h(v4h_addr, port, for_listening) \
        (tor_addr_is_valid_ipv4h((v4h_addr), (for_listening)) &&    \
         tor_port_is_valid((port), (for_listening)))

int tor_addr_port_split(int severity, const char *addrport,
                        char **address_out, uint16_t *port_out);

+27 −21
Original line number Diff line number Diff line
@@ -1778,7 +1778,7 @@ pick_tor2web_rendezvous_node(router_crn_flags_t flags,
  router_add_running_nodes_to_smartlist(all_live_nodes,
                                        allow_invalid,
                                        0, 0, 0,
                                        need_desc);
                                        need_desc, 0);

  /* Filter all_live_nodes to only add live *and* whitelisted RPs to
   * the list whitelisted_live_rps. */
@@ -2144,7 +2144,9 @@ choose_good_entry_server(uint8_t purpose, cpath_build_state_t *state)
  const node_t *choice;
  smartlist_t *excluded;
  const or_options_t *options = get_options();
  router_crn_flags_t flags = CRN_NEED_GUARD|CRN_NEED_DESC;
  /* If possible, choose an entry server with a preferred address,
   * otherwise, choose one with an allowed address */
  router_crn_flags_t flags = CRN_NEED_GUARD|CRN_NEED_DESC|CRN_PREF_ADDR;
  const node_t *node;

  if (state && options->UseEntryGuards &&
@@ -2161,14 +2163,6 @@ choose_good_entry_server(uint8_t purpose, cpath_build_state_t *state)
     * family. */
    nodelist_add_node_and_family(excluded, node);
  }
  if (firewall_is_fascist_or()) {
    /* Exclude all ORs that we can't reach through our firewall */
    smartlist_t *nodes = nodelist_get_list();
    SMARTLIST_FOREACH(nodes, const node_t *, node, {
      if (!fascist_firewall_allows_node(node))
        smartlist_add(excluded, (void*)node);
    });
  }
  /* and exclude current entry guards and their families,
   * unless we're in a test network, and excluding guards
   * would exclude all nodes (i.e. we're in an incredibly small tor network,
@@ -2247,9 +2241,11 @@ onion_extend_cpath(origin_circuit_t *circ)
    if (r) {
      /* If we're a client, use the preferred address rather than the
         primary address, for potentially connecting to an IPv6 OR
         port. */
      info = extend_info_from_node(r, server_mode(get_options()) == 0);
      tor_assert(info);
         port. Servers always want the primary (IPv4) address. */
      int client = (server_mode(get_options()) == 0);
      info = extend_info_from_node(r, client);
      /* Clients can fail to find an allowed address */
      tor_assert(info || client);
    }
  } else {
    const node_t *r =
@@ -2324,33 +2320,43 @@ extend_info_new(const char *nickname, const char *digest,
 * <b>for_direct_connect</b> is true, in which case the preferred
 * address is used instead. May return NULL if there is not enough
 * info about <b>node</b> to extend to it--for example, if there is no
 * routerinfo_t or microdesc_t.
 * routerinfo_t or microdesc_t, or if for_direct_connect is true and none of
 * the node's addresses are allowed by tor's firewall and IP version config.
 **/
extend_info_t *
extend_info_from_node(const node_t *node, int for_direct_connect)
{
  tor_addr_port_t ap;
  int valid_addr = 0;

  if (node->ri == NULL && (node->rs == NULL || node->md == NULL))
    return NULL;

  /* Choose a preferred address first, but fall back to an allowed address.
   * choose_address returns 1 on success, but get_prim_orport returns 0. */
  if (for_direct_connect)
    node_get_pref_orport(node, &ap);
    valid_addr = fascist_firewall_choose_address_node(node,
                                                      FIREWALL_OR_CONNECTION,
                                                      0, &ap);
  else
    node_get_prim_orport(node, &ap);
    valid_addr = !node_get_prim_orport(node, &ap);

  if (valid_addr)
    log_debug(LD_CIRC, "using %s for %s",
              fmt_addrport(&ap.addr, ap.port),
              node->ri ? node->ri->nickname : node->rs->nickname);
  else
    log_warn(LD_CIRC, "Could not choose valid address for %s",
              node->ri ? node->ri->nickname : node->rs->nickname);

  if (node->ri)
  if (valid_addr && node->ri)
    return extend_info_new(node->ri->nickname,
                             node->identity,
                             node->ri->onion_pkey,
                             node->ri->onion_curve25519_pkey,
                             &ap.addr,
                             ap.port);
  else if (node->rs && node->md)
  else if (valid_addr && node->rs && node->md)
    return extend_info_new(node->rs->nickname,
                             node->identity,
                             node->md->onion_pkey,
Loading