mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-10 21:23:58 +01:00
Merge branch 'bug5535_only_rebased'
This commit is contained in:
commit
d7a646edcf
5
changes/bug5535
Normal file
5
changes/bug5535
Normal file
@ -0,0 +1,5 @@
|
||||
o Major features:
|
||||
- If configured with ClientUseIPv6, clients may connect to entry
|
||||
nodes over IPv6. Another new config option, ClientPreferIPv6ORPort,
|
||||
can be set to make this even more likely to happen.
|
||||
Implements ticket 5535.
|
@ -1171,6 +1171,18 @@ The following options are useful only for clients (that is, if
|
||||
If no defaults are available there, these options default to 20, .70,
|
||||
0.0, 200, and 4 respectively.
|
||||
|
||||
**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** option will try connecting over IPv6 if even if
|
||||
**ClientUseIPv6** is set to 0. (Default: 0)
|
||||
|
||||
**ClientPreferIPv6ORPort** **0**|**1**::
|
||||
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)
|
||||
|
||||
|
||||
SERVER OPTIONS
|
||||
--------------
|
||||
|
@ -3792,12 +3792,10 @@ onion_extend_cpath(origin_circuit_t *circ)
|
||||
} else if (cur_len == 0) { /* picking first node */
|
||||
const node_t *r = choose_good_entry_server(purpose, state);
|
||||
if (r) {
|
||||
/* If we're extending to a bridge, use the preferred address
|
||||
rather than the primary, for potentially extending to an IPv6
|
||||
bridge. */
|
||||
int use_pref_addr = (r->ri != NULL &&
|
||||
r->ri->purpose == ROUTER_PURPOSE_BRIDGE);
|
||||
info = extend_info_from_node(r, use_pref_addr);
|
||||
/* 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);
|
||||
}
|
||||
} else {
|
||||
@ -3865,34 +3863,43 @@ extend_info_alloc(const char *nickname, const char *digest,
|
||||
|
||||
/** Allocate and return a new extend_info that can be used to build a
|
||||
* circuit to or through the node <b>node</b>. Use the primary address
|
||||
* of the node unless <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.
|
||||
* of the node (i.e. its IPv4 address) unless
|
||||
* <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.
|
||||
**/
|
||||
extend_info_t *
|
||||
extend_info_from_node(const node_t *node, int for_direct_connect)
|
||||
{
|
||||
if (node->ri) {
|
||||
const routerinfo_t *r = node->ri;
|
||||
tor_addr_port_t ap;
|
||||
if (for_direct_connect)
|
||||
node_get_pref_orport(node, &ap);
|
||||
else
|
||||
node_get_prim_orport(node, &ap);
|
||||
return extend_info_alloc(r->nickname, r->cache_info.identity_digest,
|
||||
r->onion_pkey, &ap.addr, ap.port);
|
||||
} else if (node->rs && node->md) {
|
||||
tor_addr_t addr;
|
||||
tor_addr_from_ipv4h(&addr, node->rs->addr);
|
||||
tor_addr_port_t ap;
|
||||
|
||||
if (node->ri == NULL && (node->rs == NULL || node->md == NULL))
|
||||
return NULL;
|
||||
|
||||
if (for_direct_connect)
|
||||
node_get_pref_orport(node, &ap);
|
||||
else
|
||||
node_get_prim_orport(node, &ap);
|
||||
|
||||
log_debug(LD_CIRC, "using %s:%d for %s",
|
||||
fmt_and_decorate_addr(&ap.addr), ap.port,
|
||||
node->ri ? node->ri->nickname : node->rs->nickname);
|
||||
|
||||
if (node->ri)
|
||||
return extend_info_alloc(node->ri->nickname,
|
||||
node->identity,
|
||||
node->ri->onion_pkey,
|
||||
&ap.addr,
|
||||
ap.port);
|
||||
else if (node->rs && node->md)
|
||||
return extend_info_alloc(node->rs->nickname,
|
||||
node->identity,
|
||||
node->md->onion_pkey,
|
||||
&addr,
|
||||
node->rs->or_port);
|
||||
} else {
|
||||
&ap.addr,
|
||||
ap.port);
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/** Release storage held by an extend_info_t struct. */
|
||||
@ -5607,10 +5614,15 @@ rewrite_node_address_for_bridge(const bridge_info_t *bridge, node_t *node)
|
||||
}
|
||||
}
|
||||
|
||||
/* Indicate that we prefer connecting to this bridge over the
|
||||
protocol that the bridge address indicates. Last bridge
|
||||
descriptor handled wins. */
|
||||
node->ipv6_preferred = tor_addr_family(&bridge->addr) == AF_INET6;
|
||||
/* Mark bridge as preferably connected to over IPv6 if its IPv6
|
||||
address is in a Bridge line and ClientPreferIPv6ORPort is
|
||||
set. Unless both is true, a potential IPv6 OR port of this
|
||||
bridge won't get selected.
|
||||
|
||||
XXX ipv6_preferred is never reset (#6757) */
|
||||
if (get_options()->ClientPreferIPv6ORPort == 1 &&
|
||||
tor_addr_family(&bridge->addr) == AF_INET6)
|
||||
node->ipv6_preferred = 1;
|
||||
|
||||
/* XXXipv6 we lack support for falling back to another address for
|
||||
the same relay, warn the user */
|
||||
|
@ -225,8 +225,10 @@ static config_var_t _option_vars[] = {
|
||||
V(CircuitPriorityHalflife, DOUBLE, "-100.0"), /*negative:'Use default'*/
|
||||
V(ClientDNSRejectInternalAddresses, BOOL,"1"),
|
||||
V(ClientOnly, BOOL, "0"),
|
||||
V(ClientPreferIPv6ORPort, BOOL, "0"),
|
||||
V(ClientRejectInternalAddresses, BOOL, "1"),
|
||||
V(ClientTransportPlugin, LINELIST, NULL),
|
||||
V(ClientUseIPv6, BOOL, "0"),
|
||||
V(ConsensusParams, STRING, NULL),
|
||||
V(ConnLimit, UINT, "1000"),
|
||||
V(ConnDirectionStatistics, BOOL, "0"),
|
||||
|
@ -206,6 +206,7 @@ nodelist_set_consensus(networkstatus_t *ns)
|
||||
{
|
||||
const or_options_t *options = get_options();
|
||||
int authdir = authdir_mode_v2(options) || authdir_mode_v3(options);
|
||||
int client = !server_mode(options);
|
||||
|
||||
init_nodelist();
|
||||
if (ns->flavor == FLAV_MICRODESC)
|
||||
@ -242,6 +243,11 @@ nodelist_set_consensus(networkstatus_t *ns)
|
||||
node->is_bad_directory = rs->is_bad_directory;
|
||||
node->is_bad_exit = rs->is_bad_exit;
|
||||
node->is_hs_dir = rs->is_hs_dir;
|
||||
node->ipv6_preferred = 0;
|
||||
if (client && options->ClientPreferIPv6ORPort == 1 &&
|
||||
(tor_addr_is_null(&rs->ipv6_addr) == 0 ||
|
||||
(node->md && tor_addr_is_null(&node->md->ipv6_addr) == 0)))
|
||||
node->ipv6_preferred = 1;
|
||||
}
|
||||
|
||||
} SMARTLIST_FOREACH_END(rs);
|
||||
@ -815,31 +821,44 @@ node_get_declared_family(const node_t *node)
|
||||
int
|
||||
node_ipv6_preferred(const node_t *node)
|
||||
{
|
||||
tor_addr_port_t ipv4_addr;
|
||||
node_assert_ok(node);
|
||||
if (node->ri)
|
||||
return (!tor_addr_is_null(&node->ri->ipv6_addr)
|
||||
&& (node->ipv6_preferred || node->ri->addr == 0));
|
||||
if (node->rs)
|
||||
return (!tor_addr_is_null(&node->rs->ipv6_addr)
|
||||
&& (node->ipv6_preferred || node->rs->addr == 0));
|
||||
|
||||
if (node->ipv6_preferred || node_get_prim_orport(node, &ipv4_addr)) {
|
||||
if (node->ri)
|
||||
return !tor_addr_is_null(&node->ri->ipv6_addr);
|
||||
if (node->md)
|
||||
return !tor_addr_is_null(&node->md->ipv6_addr);
|
||||
if (node->rs)
|
||||
return !tor_addr_is_null(&node->rs->ipv6_addr);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Copy the primary (IPv4) OR port (IP address and TCP port) for
|
||||
* <b>node</b> into *<b>ap_out</b>. */
|
||||
void
|
||||
* <b>node</b> into *<b>ap_out</b>. Return 0 if a valid address and
|
||||
* port was copied, else return non-zero.*/
|
||||
int
|
||||
node_get_prim_orport(const node_t *node, tor_addr_port_t *ap_out)
|
||||
{
|
||||
node_assert_ok(node);
|
||||
tor_assert(ap_out);
|
||||
|
||||
if (node->ri) {
|
||||
if (node->ri->addr == 0 || node->ri->or_port == 0)
|
||||
return -1;
|
||||
tor_addr_from_ipv4h(&ap_out->addr, node->ri->addr);
|
||||
ap_out->port = node->ri->or_port;
|
||||
} else if (node->rs) {
|
||||
return 0;
|
||||
}
|
||||
if (node->rs) {
|
||||
if (node->rs->addr == 0 || node->rs->or_port == 0)
|
||||
return -1;
|
||||
tor_addr_from_ipv4h(&ap_out->addr, node->rs->addr);
|
||||
ap_out->port = node->rs->or_port;
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/** Copy the preferred OR port (IP address and TCP port) for
|
||||
@ -849,7 +868,13 @@ node_get_pref_orport(const node_t *node, tor_addr_port_t *ap_out)
|
||||
{
|
||||
tor_assert(ap_out);
|
||||
|
||||
if (node_ipv6_preferred(node))
|
||||
/* Cheap implementation of config option ClientUseIPv6 -- simply
|
||||
don't prefer IPv6 when ClientUseIPv6 is not set. (See #4455 for
|
||||
more on this subject.) Note that this filter is too strict since
|
||||
we're hindering not only clients! Erring on the safe side
|
||||
shouldn't be a problem though. XXX move this check to where
|
||||
outgoing connections are made? -LN */
|
||||
if (get_options()->ClientUseIPv6 == 1 && node_ipv6_preferred(node))
|
||||
node_get_pref_ipv6_orport(node, ap_out);
|
||||
else
|
||||
node_get_prim_orport(node, ap_out);
|
||||
@ -863,9 +888,17 @@ node_get_pref_ipv6_orport(const node_t *node, tor_addr_port_t *ap_out)
|
||||
node_assert_ok(node);
|
||||
tor_assert(ap_out);
|
||||
|
||||
/* We prefer the microdesc over a potential routerstatus here. They
|
||||
are not being synchronised atm so there might be a chance that
|
||||
they differ at some point, f.ex. when flipping
|
||||
UseMicrodescriptors? -LN */
|
||||
|
||||
if (node->ri) {
|
||||
tor_addr_copy(&ap_out->addr, &node->ri->ipv6_addr);
|
||||
ap_out->port = node->ri->ipv6_orport;
|
||||
} else if (node->md) {
|
||||
tor_addr_copy(&ap_out->addr, &node->md->ipv6_addr);
|
||||
ap_out->port = node->md->ipv6_orport;
|
||||
} else if (node->rs) {
|
||||
tor_addr_copy(&ap_out->addr, &node->rs->ipv6_addr);
|
||||
ap_out->port = node->rs->ipv6_orport;
|
||||
|
@ -42,18 +42,18 @@ int node_get_purpose(const node_t *node);
|
||||
int node_is_me(const node_t *node);
|
||||
int node_exit_policy_rejects_all(const node_t *node);
|
||||
smartlist_t *node_get_all_orports(const node_t *node);
|
||||
void node_get_prim_orport(const node_t *node, tor_addr_port_t *ap_out);
|
||||
void node_get_pref_orport(const node_t *node, tor_addr_port_t *ap_out);
|
||||
void node_get_pref_ipv6_orport(const node_t *node, tor_addr_port_t *ap_out);
|
||||
uint32_t node_get_prim_addr_ipv4h(const node_t *node);
|
||||
int node_allows_single_hop_exits(const node_t *node);
|
||||
const char *node_get_nickname(const node_t *node);
|
||||
const char *node_get_platform(const node_t *node);
|
||||
uint32_t node_get_prim_addr_ipv4h(const node_t *node);
|
||||
void node_get_address_string(const node_t *node, char *cp, size_t len);
|
||||
long node_get_declared_uptime(const node_t *node);
|
||||
time_t node_get_published_on(const node_t *node);
|
||||
const smartlist_t *node_get_declared_family(const node_t *node);
|
||||
int node_ipv6_preferred(const node_t *node);
|
||||
int node_get_prim_orport(const node_t *node, tor_addr_port_t *ap_out);
|
||||
void node_get_pref_orport(const node_t *node, tor_addr_port_t *ap_out);
|
||||
void node_get_pref_ipv6_orport(const node_t *node, tor_addr_port_t *ap_out);
|
||||
|
||||
smartlist_t *nodelist_get_list(void);
|
||||
|
||||
|
11
src/or/or.h
11
src/or/or.h
@ -1960,6 +1960,10 @@ typedef struct microdesc_t {
|
||||
|
||||
/** As routerinfo_t.onion_pkey */
|
||||
crypto_pk_t *onion_pkey;
|
||||
/** As routerinfo_t.ipv6_add */
|
||||
tor_addr_t ipv6_addr;
|
||||
/** As routerinfo_t.ipv6_orport */
|
||||
uint16_t ipv6_orport;
|
||||
/** As routerinfo_t.family */
|
||||
smartlist_t *family;
|
||||
/** Exit policy summary */
|
||||
@ -3487,6 +3491,13 @@ typedef struct {
|
||||
* over randomly chosen exits. */
|
||||
int ClientRejectInternalAddresses;
|
||||
|
||||
/** If true, clients may connect over IPv6. XXX we don't really
|
||||
enforce this -- clients _may_ set up outgoing IPv6 connections
|
||||
even when this option is not set. */
|
||||
int ClientUseIPv6;
|
||||
/** If true, prefer an IPv6 OR port over an IPv4 one. */
|
||||
int ClientPreferIPv6ORPort;
|
||||
|
||||
/** The length of time that we think a consensus should be fresh. */
|
||||
int V3AuthVotingInterval;
|
||||
/** The length of time we think it will take to distribute votes. */
|
||||
|
@ -524,6 +524,7 @@ static token_rule_t networkstatus_detached_signature_token_table[] = {
|
||||
/** List of tokens recognized in microdescriptors */
|
||||
static token_rule_t microdesc_token_table[] = {
|
||||
T1_START("onion-key", K_ONION_KEY, NO_ARGS, NEED_KEY_1024),
|
||||
T0N("a", K_A, GE(1), NO_OBJ ),
|
||||
T01("family", K_FAMILY, ARGS, NO_OBJ ),
|
||||
T01("p", K_P, CONCAT_ARGS, NO_OBJ ),
|
||||
A01("@last-listed", A_LAST_LISTED, CONCAT_ARGS, NO_OBJ ),
|
||||
@ -4454,6 +4455,14 @@ microdescs_parse_from_string(const char *s, const char *eos,
|
||||
md->onion_pkey = tok->key;
|
||||
tok->key = NULL;
|
||||
|
||||
{
|
||||
smartlist_t *a_lines = find_all_by_keyword(tokens, K_A);
|
||||
if (a_lines) {
|
||||
find_single_ipv6_orport(a_lines, &md->ipv6_addr, &md->ipv6_orport);
|
||||
smartlist_free(a_lines);
|
||||
}
|
||||
}
|
||||
|
||||
if ((tok = find_opt_by_keyword(tokens, K_FAMILY))) {
|
||||
int i;
|
||||
md->family = smartlist_new();
|
||||
|
Loading…
Reference in New Issue
Block a user