mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2025-02-24 06:48:05 +01:00
Use fascist firewall and ClientUseIPv4 for bridge clients
Bridge clients ignore ClientUseIPv6, acting as if it is always 1. This preserves existing behaviour. Make ClientPreferIPv6OR/DirPort auto by default: * Bridge clients prefer IPv6 by default. * Other clients prefer IPv4 by default. This preserves existing behaviour.
This commit is contained in:
parent
4528f89316
commit
3b8216f215
12 changed files with 402 additions and 384 deletions
|
@ -1500,19 +1500,21 @@ The following options are useful only for clients (that is, if
|
|||
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**::
|
||||
[[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.) Other things may influence the choice. This option breaks a tie to the
|
||||
favor of IPv6. (Default: 0)
|
||||
0.) If this option is set to auto, Tor bridge clients prefer IPv6, and
|
||||
other 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. (Tor also
|
||||
prefers an IPv6 ORPort if IPv4Client is set to 0.) Other things may
|
||||
influence the choice. This option breaks a tie to the favor of IPv6.
|
||||
(Default: 0)
|
||||
prefers an IPv6 ORPort if IPv4Client is set to 0.) If this option is set
|
||||
to auto, Tor bridge clients prefer IPv6, 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
|
||||
|
|
|
@ -190,8 +190,8 @@ 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(ClientPreferIPv6DirPort, BOOL, "0"),
|
||||
V(ClientPreferIPv6ORPort, AUTOBOOL, "auto"),
|
||||
V(ClientPreferIPv6DirPort, AUTOBOOL, "auto"),
|
||||
V(ClientRejectInternalAddresses, BOOL, "1"),
|
||||
V(ClientTransportPlugin, LINELIST, NULL),
|
||||
V(ClientUseIPv6, BOOL, "0"),
|
||||
|
@ -3073,9 +3073,8 @@ options_validate(or_options_t *old_options, or_options_t *options,
|
|||
}
|
||||
}
|
||||
|
||||
/* Terminate Reachable*Addresses with reject *, but check if it has an
|
||||
* IPv6 entry on the way through */
|
||||
int reachable_knows_ipv6 = 0;
|
||||
/* Terminate Reachable*Addresses with reject *
|
||||
*/
|
||||
for (i=0; i<3; i++) {
|
||||
config_line_t **linep =
|
||||
(i==0) ? &options->ReachableAddresses :
|
||||
|
@ -3085,20 +3084,6 @@ options_validate(or_options_t *old_options, or_options_t *options,
|
|||
continue;
|
||||
/* We need to end with a reject *:*, not an implicit accept *:* */
|
||||
for (;;) {
|
||||
/* Check if the policy has an IPv6 entry, or uses IPv4-specific
|
||||
* policies (and therefore we assume it's aware of IPv6). */
|
||||
if (!strcmpstart((*linep)->value, "accept6") ||
|
||||
!strcmpstart((*linep)->value, "reject6") ||
|
||||
!strstr((*linep)->value, "*6") ||
|
||||
strchr((*linep)->value, '[') ||
|
||||
!strcmpstart((*linep)->value, "accept4") ||
|
||||
!strcmpstart((*linep)->value, "reject4") ||
|
||||
!strstr((*linep)->value, "*4"))
|
||||
reachable_knows_ipv6 = 1;
|
||||
/* already has a reject all */
|
||||
if (!strcmp((*linep)->value, "reject *:*") ||
|
||||
!strcmp((*linep)->value, "reject *"))
|
||||
break;
|
||||
linep = &((*linep)->next);
|
||||
if (!*linep) {
|
||||
*linep = tor_malloc_zero(sizeof(config_line_t));
|
||||
|
@ -3112,18 +3097,6 @@ options_validate(or_options_t *old_options, or_options_t *options,
|
|||
}
|
||||
}
|
||||
|
||||
if (options->ClientUseIPv6 &&
|
||||
(options->ReachableAddresses ||
|
||||
options->ReachableORAddresses ||
|
||||
options->ReachableDirAddresses) &&
|
||||
!reachable_knows_ipv6)
|
||||
log_warn(LD_CONFIG, "You have set ClientUseIPv6 1 and at least one of "
|
||||
"ReachableAddresses, ReachableORAddresses, or "
|
||||
"ReachableDirAddresses, but without any IPv6-specific rules. "
|
||||
"Tor won't connect to any IPv6 addresses, unless a rule accepts "
|
||||
"them. (Use 'accept6 *:*' or 'reject6 *:*' as the last rule to "
|
||||
"disable this warning.)");
|
||||
|
||||
if ((options->ReachableAddresses ||
|
||||
options->ReachableORAddresses ||
|
||||
options->ReachableDirAddresses ||
|
||||
|
@ -3135,18 +3108,20 @@ options_validate(or_options_t *old_options, or_options_t *options,
|
|||
|
||||
/* We check if Reachable*Addresses blocks all addresses in
|
||||
* parse_reachable_addresses(). */
|
||||
if (options->ClientUseIPv4 == 0 && options->ClientUseIPv6 == 0)
|
||||
if (options->ClientUseIPv4 == 0 && !fascist_firewall_use_ipv6(options))
|
||||
REJECT("Tor cannot connect to the Internet if ClientUseIPv4 is 0 and "
|
||||
"ClientUseIPv6 is 0. Please set at least one of these options "
|
||||
"to 1.");
|
||||
"to 1, or configure bridges.");
|
||||
|
||||
if (options->ClientUseIPv6 == 0 && options->ClientPreferIPv6ORPort == 1)
|
||||
if (!fascist_firewall_use_ipv6(options)
|
||||
&& options->ClientPreferIPv6ORPort == 1)
|
||||
log_warn(LD_CONFIG, "ClientPreferIPv6ORPort 1 is ignored unless "
|
||||
"ClientUseIPv6 is also 1.");
|
||||
"ClientUseIPv6 is also 1, or bridges are configured.");
|
||||
|
||||
if (options->ClientUseIPv6 == 0 && options->ClientPreferIPv6DirPort == 1)
|
||||
if (!fascist_firewall_use_ipv6(options)
|
||||
&& options->ClientPreferIPv6DirPort == 1)
|
||||
log_warn(LD_CONFIG, "ClientPreferIPv6DirPort 1 is ignored unless "
|
||||
"ClientUseIPv6 is also 1.");
|
||||
"ClientUseIPv6 is also 1, or bridges are configured.");
|
||||
|
||||
if (options->UseBridges &&
|
||||
server_mode(options))
|
||||
|
|
|
@ -1722,7 +1722,7 @@ connection_connect_sockaddr,(connection_t *conn,
|
|||
return inprogress ? 0 : 1;
|
||||
}
|
||||
|
||||
/* Log a message if connection violates ClientUseIPv4 0 or ClientUseIPv6 0.
|
||||
/* Log a message if connection attempt is made when IPv4 or IPv6 is disabled.
|
||||
* Log a less severe message if we couldn't conform to ClientPreferIPv6ORPort
|
||||
* or ClientPreferIPv6ORPort. */
|
||||
static void
|
||||
|
@ -1730,9 +1730,9 @@ connection_connect_log_client_use_ip_version(const connection_t *conn)
|
|||
{
|
||||
const or_options_t *options = get_options();
|
||||
|
||||
/* Only non-bridge clients care about ClientUseIPv4/6, bail out early on
|
||||
* servers and bridge clients */
|
||||
if (options->UseBridges || server_mode(options) || !conn
|
||||
/* Only clients care about ClientUseIPv4/6, bail out early on servers, and
|
||||
* on connections we don't care about */
|
||||
if (server_mode(options) || !conn
|
||||
|| conn->type == CONN_TYPE_EXIT) {
|
||||
return;
|
||||
}
|
||||
|
@ -1742,11 +1742,11 @@ connection_connect_log_client_use_ip_version(const connection_t *conn)
|
|||
return;
|
||||
}
|
||||
|
||||
const int must_ipv4 = (options->ClientUseIPv6 == 0);
|
||||
const int must_ipv4 = !fascist_firewall_use_ipv6(options);
|
||||
const int must_ipv6 = (options->ClientUseIPv4 == 0);
|
||||
const int pref_ipv6 = (conn->type == CONN_TYPE_OR
|
||||
? nodelist_prefer_ipv6_orport(options)
|
||||
: nodelist_prefer_ipv6_dirport(options));
|
||||
? fascist_firewall_prefer_ipv6_orport(options)
|
||||
: fascist_firewall_prefer_ipv6_dirport(options));
|
||||
tor_addr_t real_addr;
|
||||
tor_addr_make_null(&real_addr, AF_UNSPEC);
|
||||
|
||||
|
@ -1773,12 +1773,14 @@ connection_connect_log_client_use_ip_version(const connection_t *conn)
|
|||
if ((!pref_ipv6 && tor_addr_family(&real_addr) == AF_INET6)
|
||||
|| (pref_ipv6 && tor_addr_family(&real_addr) == AF_INET)) {
|
||||
log_info(LD_NET, "Connection to %s doesn't satisfy ClientPreferIPv6%sPort "
|
||||
"%d, with ClientUseIPv4 %d and ClientUseIPv6 %d.",
|
||||
"%d, with ClientUseIPv4 %d, and fascist_firewall_use_ipv6 %d "
|
||||
"(ClientUseIPv6 %d and UseBridges %d).",
|
||||
fmt_addr(&real_addr),
|
||||
conn->type == CONN_TYPE_OR ? "OR" : "Dir",
|
||||
conn->type == CONN_TYPE_OR ? options->ClientPreferIPv6ORPort
|
||||
: options->ClientPreferIPv6DirPort,
|
||||
options->ClientUseIPv4, options->ClientUseIPv4);
|
||||
options->ClientUseIPv4, fascist_firewall_use_ipv6(options),
|
||||
options->ClientUseIPv6, options->UseBridges);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -730,7 +730,8 @@ directory_initiate_command_routerstatus_rend(const routerstatus_t *status,
|
|||
* directory server, we have selected a server that has at least one address
|
||||
* allowed by ClientUseIPv4/6 and Reachable{"",OR,Dir}Addresses. This
|
||||
* selection uses the preference in ClientPreferIPv6{OR,Dir}Port, if
|
||||
* possible. (If UseBridges is set, clients ignore all these settings.)
|
||||
* possible. (If UseBridges is set, clients always use IPv6, and prefer it
|
||||
* by default.)
|
||||
*
|
||||
* Now choose an address that we can use to connect to the directory server.
|
||||
*/
|
||||
|
@ -1070,6 +1071,15 @@ directory_initiate_command_rend(const tor_addr_port_t *or_addr_port,
|
|||
log_debug(LD_DIR, "anonymized %d, use_begindir %d.",
|
||||
anonymized_connection, use_begindir);
|
||||
|
||||
if (!dir_port && !use_begindir) {
|
||||
char ipaddr[TOR_ADDR_BUF_LEN];
|
||||
tor_addr_to_str(ipaddr, &addr, TOR_ADDR_BUF_LEN, 0);
|
||||
log_warn(LD_BUG, "Cannot use directory server without dirport or "
|
||||
"begindir! Address: %s, DirPort: %d, Connection Port: %d",
|
||||
escaped_safe_str_client(ipaddr), dir_port, port);
|
||||
return;
|
||||
}
|
||||
|
||||
log_debug(LD_DIR, "Initiating %s", dir_conn_purpose_to_string(dir_purpose));
|
||||
|
||||
#ifndef NON_ANONYMOUS_MODE_ENABLED
|
||||
|
|
|
@ -214,76 +214,6 @@ nodelist_add_microdesc(microdesc_t *md)
|
|||
return node;
|
||||
}
|
||||
|
||||
/** Do we prefer to connect to IPv6, ignoring ClientPreferIPv6ORPort and
|
||||
* ClientPreferIPv6DirPort?
|
||||
* If we're unsure, return -1, otherwise, return 1 for IPv6 and 0 for IPv4.
|
||||
*/
|
||||
static int
|
||||
nodelist_prefer_ipv6(const or_options_t *options)
|
||||
{
|
||||
/*
|
||||
Cheap implementation of config options ClientUseIPv4 & ClientUseIPv6 --
|
||||
If we're a server, use IPv4.
|
||||
If we're a client running with bridges, use IPv6.
|
||||
Otherwise, use IPv6 if we can and it's preferred, or if IPv4 is disabled.
|
||||
See #4455 and #17840 for more on this subject.
|
||||
*/
|
||||
|
||||
/* Servers prefer IPv4 */
|
||||
if (server_mode(options)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Bridge clients prefer IPv6 */
|
||||
if (options->UseBridges) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!options->ClientUseIPv4) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/** Do we prefer to connect to IPv6 ORPorts?
|
||||
*/
|
||||
int
|
||||
nodelist_prefer_ipv6_orport(const or_options_t *options)
|
||||
{
|
||||
int pref_ipv6 = nodelist_prefer_ipv6(options);
|
||||
|
||||
if (pref_ipv6 >= 0) {
|
||||
return pref_ipv6;
|
||||
}
|
||||
|
||||
/* We prefer IPv6 ORPorts if the option is set */
|
||||
if (options->ClientUseIPv6 && options->ClientPreferIPv6ORPort) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Do we prefer to connect to IPv6 DirPorts?
|
||||
*/
|
||||
int
|
||||
nodelist_prefer_ipv6_dirport(const or_options_t *options)
|
||||
{
|
||||
int pref_ipv6 = nodelist_prefer_ipv6(options);
|
||||
|
||||
if (pref_ipv6 >= 0) {
|
||||
return pref_ipv6;
|
||||
}
|
||||
|
||||
/* We prefer IPv6 DirPorts if the option is set */
|
||||
if (options->ClientUseIPv6 && options->ClientPreferIPv6DirPort) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Tell the nodelist that the current usable consensus is <b>ns</b>.
|
||||
* This makes the nodelist change all of the routerstatus entries for
|
||||
* the nodes, drop nodes that no longer have enough info to get used,
|
||||
|
@ -330,7 +260,7 @@ 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 (nodelist_prefer_ipv6_orport(options) &&
|
||||
if (fascist_firewall_prefer_ipv6_orport(options) &&
|
||||
(tor_addr_is_null(&rs->ipv6_addr) == 0 ||
|
||||
(node->md && tor_addr_is_null(&node->md->ipv6_addr) == 0)))
|
||||
node->ipv6_preferred = 1;
|
||||
|
@ -916,9 +846,13 @@ node_get_addr(const node_t *node, tor_addr_t *addr_out)
|
|||
uint32_t
|
||||
node_get_prim_addr_ipv4h(const node_t *node)
|
||||
{
|
||||
if (node->ri) {
|
||||
/* Don't check the ORPort or DirPort, as this function isn't port-specific,
|
||||
* and the node might have a valid IPv4 address, yet have a zero
|
||||
* ORPort or DirPort.
|
||||
*/
|
||||
if (node->ri && tor_addr_is_valid_ipv4h(node->ri->addr, 0)) {
|
||||
return node->ri->addr;
|
||||
} else if (node->rs) {
|
||||
} else if (node->rs && tor_addr_is_valid_ipv4h(node->rs->addr, 0)) {
|
||||
return node->rs->addr;
|
||||
}
|
||||
return 0;
|
||||
|
@ -994,20 +928,44 @@ node_get_declared_family(const node_t *node)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/* Does this node have a valid IPv6 address? */
|
||||
static int
|
||||
/* Does this node have a valid IPv6 address?
|
||||
* Prefer node_has_ipv6_orport() or node_has_ipv6_dirport() for
|
||||
* checking specific ports. */
|
||||
int
|
||||
node_has_ipv6_addr(const node_t *node)
|
||||
{
|
||||
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);
|
||||
/* Don't check the ORPort or DirPort, as this function isn't port-specific,
|
||||
* and the node might have a valid IPv6 address, yet have a zero
|
||||
* ORPort or DirPort.
|
||||
*/
|
||||
if (node->ri && tor_addr_is_valid(&node->ri->ipv6_addr, 0))
|
||||
return 1;
|
||||
if (node->rs && tor_addr_is_valid(&node->rs->ipv6_addr, 0))
|
||||
return 1;
|
||||
if (node->md && tor_addr_is_valid(&node->md->ipv6_addr, 0))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Does this node have a valid IPv6 ORPort? */
|
||||
int
|
||||
node_has_ipv6_orport(const node_t *node)
|
||||
{
|
||||
tor_addr_port_t ipv6_orport;
|
||||
node_get_pref_ipv6_orport(node, &ipv6_orport);
|
||||
return tor_addr_port_is_valid_ap(&ipv6_orport, 0);
|
||||
}
|
||||
|
||||
/* Does this node have a valid IPv6 DirPort? */
|
||||
int
|
||||
node_has_ipv6_dirport(const node_t *node)
|
||||
{
|
||||
tor_addr_port_t ipv6_dirport;
|
||||
node_get_pref_ipv6_dirport(node, &ipv6_dirport);
|
||||
return tor_addr_port_is_valid_ap(&ipv6_dirport, 0);
|
||||
}
|
||||
|
||||
/** Return 1 if we prefer the IPv6 address and OR TCP port of
|
||||
* <b>node</b>, else 0.
|
||||
*
|
||||
|
@ -1028,20 +986,18 @@ node_ipv6_or_preferred(const node_t *node)
|
|||
tor_addr_port_t ipv4_addr;
|
||||
node_assert_ok(node);
|
||||
|
||||
if (!options->ClientUseIPv6) {
|
||||
if (!fascist_firewall_use_ipv6(options)) {
|
||||
return 0;
|
||||
} else if (node->ipv6_preferred || node_get_prim_orport(node, &ipv4_addr)
|
||||
|| nodelist_prefer_ipv6_orport(get_options())) {
|
||||
return node_has_ipv6_addr(node);
|
||||
|| fascist_firewall_prefer_ipv6_orport(get_options())) {
|
||||
return node_has_ipv6_orport(node);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define RETURN_IPV4_AP(r, port_field, ap_out) \
|
||||
STMT_BEGIN \
|
||||
if (r) { \
|
||||
if ((r)->addr == 0 || (r)->port_field == 0) \
|
||||
return -1; \
|
||||
if (r && tor_addr_port_is_valid_ipv4h((r)->addr, (r)->port_field, 0)) { \
|
||||
tor_addr_from_ipv4h(&(ap_out)->addr, (r)->addr); \
|
||||
(ap_out)->port = (r)->port_field; \
|
||||
return 0; \
|
||||
|
@ -1091,16 +1047,16 @@ node_get_pref_ipv6_orport(const node_t *node, tor_addr_port_t *ap_out)
|
|||
* fascist_firewall_* functions. Also check if the address or port are valid,
|
||||
* and try another alternative if they are not. */
|
||||
|
||||
if (node->ri && node->ri->ipv6_orport
|
||||
&& !tor_addr_is_null(&node->ri->ipv6_addr)) {
|
||||
if (node->ri && tor_addr_port_is_valid(&node->ri->ipv6_addr,
|
||||
node->ri->ipv6_orport, 0)) {
|
||||
tor_addr_copy(&ap_out->addr, &node->ri->ipv6_addr);
|
||||
ap_out->port = node->ri->ipv6_orport;
|
||||
} else if (node->rs && node->rs->ipv6_orport
|
||||
&& !tor_addr_is_null(&node->rs->ipv6_addr)) {
|
||||
} else if (node->rs && tor_addr_port_is_valid(&node->rs->ipv6_addr,
|
||||
node->rs->ipv6_orport, 0)) {
|
||||
tor_addr_copy(&ap_out->addr, &node->rs->ipv6_addr);
|
||||
ap_out->port = node->rs->ipv6_orport;
|
||||
} else if (node->md && node->md->ipv6_orport
|
||||
&& !tor_addr_is_null(&node->md->ipv6_addr)) {
|
||||
} else if (node->md && tor_addr_port_is_valid(&node->md->ipv6_addr,
|
||||
node->md->ipv6_orport, 0)) {
|
||||
tor_addr_copy(&ap_out->addr, &node->md->ipv6_addr);
|
||||
ap_out->port = node->md->ipv6_orport;
|
||||
} else {
|
||||
|
@ -1129,11 +1085,11 @@ node_ipv6_dir_preferred(const node_t *node)
|
|||
tor_addr_port_t ipv4_addr;
|
||||
node_assert_ok(node);
|
||||
|
||||
if (!options->ClientUseIPv6) {
|
||||
if (!fascist_firewall_use_ipv6(options)) {
|
||||
return 0;
|
||||
} else if (node->ipv6_preferred || node_get_prim_dirport(node, &ipv4_addr)
|
||||
|| nodelist_prefer_ipv6_dirport(get_options())) {
|
||||
return node_has_ipv6_addr(node);
|
||||
|| fascist_firewall_prefer_ipv6_dirport(get_options())) {
|
||||
return node_has_ipv6_dirport(node);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -1183,12 +1139,12 @@ node_get_pref_ipv6_dirport(const node_t *node, tor_addr_port_t *ap_out)
|
|||
* they are not. Note that microdescriptors have no dir_port. */
|
||||
|
||||
/* Assume IPv4 and IPv6 dirports are the same */
|
||||
if (node->ri && node->ri->dir_port
|
||||
&& !tor_addr_is_null(&node->ri->ipv6_addr)) {
|
||||
if (node->ri && tor_addr_port_is_valid(&node->ri->ipv6_addr,
|
||||
node->ri->dir_port, 0)) {
|
||||
tor_addr_copy(&ap_out->addr, &node->ri->ipv6_addr);
|
||||
ap_out->port = node->ri->dir_port;
|
||||
} else if (node->rs && node->rs->dir_port
|
||||
&& !tor_addr_is_null(&node->rs->ipv6_addr)) {
|
||||
} else if (node->rs && tor_addr_port_is_valid(&node->rs->ipv6_addr,
|
||||
node->rs->dir_port, 0)) {
|
||||
tor_addr_copy(&ap_out->addr, &node->rs->ipv6_addr);
|
||||
ap_out->port = node->rs->dir_port;
|
||||
} else {
|
||||
|
|
|
@ -21,8 +21,6 @@ MOCK_DECL(const node_t *, node_get_by_id, (const char *identity_digest));
|
|||
const node_t *node_get_by_hex_id(const char *identity_digest);
|
||||
node_t *nodelist_set_routerinfo(routerinfo_t *ri, routerinfo_t **ri_old_out);
|
||||
node_t *nodelist_add_microdesc(microdesc_t *md);
|
||||
int nodelist_prefer_ipv6_orport(const or_options_t *options);
|
||||
int nodelist_prefer_ipv6_dirport(const or_options_t *options);
|
||||
void nodelist_set_consensus(networkstatus_t *ns);
|
||||
|
||||
void nodelist_remove_microdesc(const char *identity_digest, microdesc_t *md);
|
||||
|
@ -58,6 +56,9 @@ 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_has_ipv6_addr(const node_t *node);
|
||||
int node_has_ipv6_orport(const node_t *node);
|
||||
int node_has_ipv6_dirport(const node_t *node);
|
||||
/* Deprecated - use node_ipv6_or_preferred or node_ipv6_dir_preferred */
|
||||
#define node_ipv6_preferred(node) node_ipv6_or_preferred(node)
|
||||
int node_ipv6_or_preferred(const node_t *node);
|
||||
|
|
10
src/or/or.h
10
src/or/or.h
|
@ -4066,14 +4066,18 @@ typedef struct {
|
|||
* connecting over IPv4. We enforce this for OR and Dir connections. */
|
||||
int ClientUseIPv4;
|
||||
/** If true, clients may connect over IPv6. If false, they will avoid
|
||||
* connecting over IPv4. We enforce this for OR and Dir connections. */
|
||||
* connecting over IPv4. We enforce this for OR and Dir connections.
|
||||
* Use fascist_firewall_use_ipv6() instead of accessing this value
|
||||
* directly. */
|
||||
int ClientUseIPv6;
|
||||
/** If true, prefer an IPv6 OR port over an IPv4 one for entry node
|
||||
* connections. Use nodelist_prefer_ipv6_orport() instead of accessing
|
||||
* connections. If auto, bridge clients prefer IPv6, and other clients
|
||||
* prefer IPv4. Use fascist_firewall_prefer_ipv6_orport() instead of accessing
|
||||
* this value directly. */
|
||||
int ClientPreferIPv6ORPort;
|
||||
/** If true, prefer an IPv6 directory port over an IPv4 one for direct
|
||||
* directory connections. Use nodelist_prefer_ipv6_dirport() instead of
|
||||
* directory connections. If auto, bridge clients prefer IPv6, and other
|
||||
* clients prefer IPv4. Use fascist_firewall_prefer_ipv6_dirport() instead of
|
||||
* accessing this value directly. */
|
||||
int ClientPreferIPv6DirPort;
|
||||
|
||||
|
|
|
@ -272,8 +272,8 @@ parse_reachable_addresses(void)
|
|||
ret = -1;
|
||||
}
|
||||
|
||||
/* XX/teor - we ignore ReachableAddresses for bridge clients and relays */
|
||||
if (!options->UseBridges || server_mode(options)) {
|
||||
/* We ignore ReachableAddresses for relays */
|
||||
if (!server_mode(options)) {
|
||||
if ((reachable_or_addr_policy
|
||||
&& policy_is_reject_star(reachable_or_addr_policy, AF_UNSPEC))
|
||||
|| (reachable_dir_addr_policy
|
||||
|
@ -282,12 +282,45 @@ parse_reachable_addresses(void)
|
|||
"ReachableAddresses, ReachableORAddresses, or "
|
||||
"ReachableDirAddresses reject all addresses. Please accept "
|
||||
"some addresses in these options.");
|
||||
} else if (options->ClientUseIPv4 == 1
|
||||
&& ((reachable_or_addr_policy
|
||||
&& policy_is_reject_star(reachable_or_addr_policy, AF_INET))
|
||||
|| (reachable_dir_addr_policy
|
||||
&& policy_is_reject_star(reachable_dir_addr_policy, AF_INET)))) {
|
||||
log_warn(LD_CONFIG, "You have set ClientUseIPv4 1, but "
|
||||
"ReachableAddresses, ReachableORAddresses, or "
|
||||
"ReachableDirAddresses reject all IPv4 addresses. "
|
||||
"Tor will not connect using IPv4.");
|
||||
} else if (fascist_firewall_use_ipv6(options)
|
||||
&& ((reachable_or_addr_policy
|
||||
&& policy_is_reject_star(reachable_or_addr_policy, AF_INET6))
|
||||
|| (reachable_dir_addr_policy
|
||||
&& policy_is_reject_star(reachable_dir_addr_policy, AF_INET6)))) {
|
||||
log_warn(LD_CONFIG, "You have configured tor to use IPv6 "
|
||||
"(ClientUseIPv6 1 or UseBridges 1), but "
|
||||
"ReachableAddresses, ReachableORAddresses, or "
|
||||
"ReachableDirAddresses reject all IPv6 addresses. "
|
||||
"Tor will not connect using IPv6.");
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** Return true iff the firewall options, including ClientUseIPv4 0 and
|
||||
* ClientUseIPv6 0, might block any address:port combination.
|
||||
*/
|
||||
int
|
||||
firewall_is_fascist_or(void)
|
||||
{
|
||||
const or_options_t *options = get_options();
|
||||
/* Assume every non-bridge relay has an IPv4 address.
|
||||
* Clients which use bridges may only know the IPv6 address of their
|
||||
* bridge. */
|
||||
return (reachable_or_addr_policy != NULL || options->ClientUseIPv4 == 0
|
||||
|| (options->ClientUseIPv6 == 0 && options->UseBridges == 1));
|
||||
}
|
||||
|
||||
/** Return true iff <b>policy</b> (possibly NULL) will allow a
|
||||
* connection to <b>addr</b>:<b>port</b>.
|
||||
*/
|
||||
|
@ -326,14 +359,14 @@ addr_policy_permits_address(uint32_t addr, uint16_t port,
|
|||
/** Return true iff we think our firewall will let us make a connection to
|
||||
* addr:port.
|
||||
*
|
||||
* If UseBridges is set, or we are configured as a server, ignore the
|
||||
* following address family preferences.
|
||||
* If we are configured as a server, ignore any address family preference and
|
||||
* just use IPv4.
|
||||
* Otherwise:
|
||||
* - return false for all IPv4 addresses:
|
||||
* - if ClientUseIPv4 is 0, or
|
||||
* if pref_only and pref_ipv6 are both true;
|
||||
* - return false for all IPv6 addresses:
|
||||
* - if ClientUseIPv6 is 0, or
|
||||
* - if fascist_firewall_use_ipv6() is 0, or
|
||||
* - if pref_only is true and pref_ipv6 is false.
|
||||
*
|
||||
* Return false if addr is NULL or tor_addr_is_null(), or if port is 0. */
|
||||
|
@ -349,13 +382,14 @@ fascist_firewall_allows_address(const tor_addr_t *addr,
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (!options->UseBridges && !server_mode(options)) {
|
||||
if (!server_mode(options)) {
|
||||
if (tor_addr_family(addr) == AF_INET &&
|
||||
(!options->ClientUseIPv4 || (pref_only && pref_ipv6)))
|
||||
return 0;
|
||||
|
||||
/* Bridges can always use IPv6 */
|
||||
if (tor_addr_family(addr) == AF_INET6 &&
|
||||
(!options->ClientUseIPv6 || (pref_only && !pref_ipv6)))
|
||||
(!fascist_firewall_use_ipv6(options) || (pref_only && !pref_ipv6)))
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -363,6 +397,87 @@ fascist_firewall_allows_address(const tor_addr_t *addr,
|
|||
firewall_policy);
|
||||
}
|
||||
|
||||
/** Is this client configured to use IPv6?
|
||||
* Clients use IPv6 if ClientUseIPv6 is 1, or UseBridges is 1.
|
||||
*/
|
||||
int fascist_firewall_use_ipv6(const or_options_t *options)
|
||||
{
|
||||
return (options->ClientUseIPv6 == 1 || options->UseBridges == 1);
|
||||
}
|
||||
|
||||
/** Do we prefer to connect to IPv6, ignoring ClientPreferIPv6ORPort and
|
||||
* ClientPreferIPv6DirPort?
|
||||
* If we're unsure, return -1, otherwise, return 1 for IPv6 and 0 for IPv4.
|
||||
*/
|
||||
static int
|
||||
fascist_firewall_prefer_ipv6_impl(const or_options_t *options)
|
||||
{
|
||||
/*
|
||||
Cheap implementation of config options ClientUseIPv4 & ClientUseIPv6 --
|
||||
If we're a server or IPv6 is disabled, use IPv4.
|
||||
If IPv4 is disabled, use IPv6.
|
||||
*/
|
||||
|
||||
if (server_mode(options) || !fascist_firewall_use_ipv6(options)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!options->ClientUseIPv4) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/** Do we prefer to connect to IPv6 ORPorts?
|
||||
*/
|
||||
int
|
||||
fascist_firewall_prefer_ipv6_orport(const or_options_t *options)
|
||||
{
|
||||
int pref_ipv6 = fascist_firewall_prefer_ipv6_impl(options);
|
||||
|
||||
if (pref_ipv6 >= 0) {
|
||||
return pref_ipv6;
|
||||
}
|
||||
|
||||
/* We can use both IPv4 and IPv6 - which do we prefer? */
|
||||
if (options->ClientPreferIPv6ORPort == 1) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* For bridge clients, ClientPreferIPv6ORPort auto means "prefer IPv6". */
|
||||
if (options->UseBridges && options->ClientPreferIPv6ORPort != 0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Do we prefer to connect to IPv6 DirPorts?
|
||||
*/
|
||||
int
|
||||
fascist_firewall_prefer_ipv6_dirport(const or_options_t *options)
|
||||
{
|
||||
int pref_ipv6 = fascist_firewall_prefer_ipv6_impl(options);
|
||||
|
||||
if (pref_ipv6 >= 0) {
|
||||
return pref_ipv6;
|
||||
}
|
||||
|
||||
/* We can use both IPv4 and IPv6 - which do we prefer? */
|
||||
if (options->ClientPreferIPv6DirPort == 1) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* For bridge clients, ClientPreferIPv6ORPort auto means "prefer IPv6".
|
||||
* XX/teor - do bridge clients ever use a DirPort? */
|
||||
if (options->UseBridges && options->ClientPreferIPv6DirPort != 0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Return true iff we think our firewall will let us make a connection to
|
||||
* addr:port. Uses ReachableORAddresses or ReachableDirAddresses based on
|
||||
* fw_connection.
|
||||
|
@ -380,12 +495,12 @@ fascist_firewall_allows_address_addr(const tor_addr_t *addr, uint16_t port,
|
|||
return fascist_firewall_allows_address(addr, port,
|
||||
reachable_or_addr_policy,
|
||||
pref_only,
|
||||
nodelist_prefer_ipv6_orport(options));
|
||||
fascist_firewall_prefer_ipv6_orport(options));
|
||||
} else if (fw_connection == FIREWALL_DIR_CONNECTION) {
|
||||
return fascist_firewall_allows_address(addr, port,
|
||||
reachable_dir_addr_policy,
|
||||
pref_only,
|
||||
nodelist_prefer_ipv6_dirport(options));
|
||||
fascist_firewall_prefer_ipv6_dirport(options));
|
||||
} else {
|
||||
log_warn(LD_BUG, "Bad firewall_connection_t value %d.",
|
||||
fw_connection);
|
||||
|
@ -478,30 +593,6 @@ fascist_firewall_allows_ri_impl(const routerinfo_t *ri,
|
|||
ri->dir_port, fw_connection, pref_only);
|
||||
}
|
||||
|
||||
/** Return true iff we think our firewall will let us make a connection to
|
||||
* <b>ri</b> on either its IPv4 or IPv6 address. Uses
|
||||
* or_port/ipv6_orport/ReachableORAddresses or dir_port/ReachableDirAddresses
|
||||
* based on IPv4/IPv6 and <b>fw_connection</b>.
|
||||
* If pref_only, return false if addr is not in the client's preferred address
|
||||
* family.
|
||||
* Consults the corresponding node if the addresses in ri are not permitted. */
|
||||
int
|
||||
fascist_firewall_allows_ri(const routerinfo_t *ri,
|
||||
firewall_connection_t fw_connection, int pref_only)
|
||||
{
|
||||
if (!ri) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Assume IPv4 and IPv6 DirPorts are the same */
|
||||
if (fascist_firewall_allows_ri_impl(ri, fw_connection, pref_only)) {
|
||||
return 1;
|
||||
} else {
|
||||
const node_t *node = node_get_by_id(ri->cache_info.identity_digest);
|
||||
return fascist_firewall_allows_node(node, fw_connection, pref_only);
|
||||
}
|
||||
}
|
||||
|
||||
/** Like fascist_firewall_allows_rs, but doesn't consult the node. */
|
||||
static int
|
||||
fascist_firewall_allows_rs_impl(const routerstatus_t *rs,
|
||||
|
@ -562,40 +653,6 @@ fascist_firewall_allows_md_impl(const microdesc_t *md,
|
|||
fw_connection, pref_only);
|
||||
}
|
||||
|
||||
/** Return true iff we think our firewall will let us make a connection to
|
||||
* <b>md</b> on its IPv6 address. (The IPv4 address is in the routerstatus and
|
||||
* the routerinfo.) Uses ipv6_orport/ReachableORAddresses or
|
||||
* dir_port/ReachableDirAddresses based on <b>fw_connection</b>.
|
||||
* If pref_only, return false if addr is not in the client's preferred address
|
||||
* family.
|
||||
* Consults the corresponding node if the address in md is not permitted. */
|
||||
int
|
||||
fascist_firewall_allows_md(const microdesc_t *md,
|
||||
firewall_connection_t fw_connection,
|
||||
int pref_only)
|
||||
{
|
||||
if (!md) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (fascist_firewall_allows_md_impl(md, fw_connection, pref_only)) {
|
||||
return 1;
|
||||
} else {
|
||||
networkstatus_t *ns;
|
||||
ns = networkstatus_get_latest_consensus_by_flavor(FLAV_MICRODESC);
|
||||
if (!ns) {
|
||||
return 0;
|
||||
}
|
||||
const routerstatus_t *rs;
|
||||
rs = router_get_consensus_status_by_descriptor_digest(ns, md->digest);
|
||||
if (!rs) {
|
||||
return 0;
|
||||
}
|
||||
const node_t *node = node_get_by_id(rs->identity_digest);
|
||||
return fascist_firewall_allows_node(node, fw_connection, pref_only);
|
||||
}
|
||||
}
|
||||
|
||||
/** Return true iff we think our firewall will let us make a connection to
|
||||
* <b>node</b>:
|
||||
* - if <b>preferred</b> is true, on its preferred address,
|
||||
|
@ -816,44 +873,6 @@ fascist_firewall_choose_address_ipv4h(uint32_t ipv4h_addr,
|
|||
} \
|
||||
STMT_END
|
||||
|
||||
/** Copy an address and port from <b>ri</b> into <b>ap</b> that we think our
|
||||
* firewall will let us connect to. Uses ipv4h_addr/ipv6_addr and
|
||||
* ipv4_orport/ipv6_orport/ReachableORAddresses or
|
||||
* ipv4_dirport/ipv6_dirport/ReachableDirAddresses based on IPv4/IPv6 and
|
||||
* <b>fw_connection</b>.
|
||||
* If pref_only, only choose preferred addresses. In either case, choose
|
||||
* a preferred address before an address that's not preferred.
|
||||
* If neither address is chosen, return 0, else return 1.
|
||||
* Consults the corresponding node if the addresses in ri are not valid. */
|
||||
int
|
||||
fascist_firewall_choose_address_ri(const routerinfo_t *ri,
|
||||
firewall_connection_t fw_connection,
|
||||
int pref_only, tor_addr_port_t* ap)
|
||||
{
|
||||
if (!ri) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
tor_assert(ap);
|
||||
|
||||
/* Don't do the lookup if the IPv6 address/port in ri is OK.
|
||||
* If it's OK, assume the dir_port is also OK. */
|
||||
tor_addr_port_t ipv6_or_ap;
|
||||
IPV6_OR_LOOKUP(ri, ri->cache_info.identity_digest, ipv6_or_ap);
|
||||
|
||||
/* Assume IPv4 and IPv6 DirPorts are the same.
|
||||
* Assume the IPv6 OR and Dir addresses are the same. */
|
||||
return fascist_firewall_choose_address_ipv4h(ri->addr,
|
||||
ri->or_port,
|
||||
ri->dir_port,
|
||||
&ipv6_or_ap.addr,
|
||||
ipv6_or_ap.port,
|
||||
ri->dir_port,
|
||||
fw_connection,
|
||||
pref_only,
|
||||
ap);
|
||||
}
|
||||
|
||||
/** Copy an address and port from <b>rs</b> into <b>ap</b> that we think our
|
||||
* firewall will let us connect to. Uses ipv4h_addr/ipv6_addr and
|
||||
* ipv4_orport/ipv6_orport/ReachableORAddresses or
|
||||
|
@ -892,73 +911,6 @@ fascist_firewall_choose_address_rs(const routerstatus_t *rs,
|
|||
ap);
|
||||
}
|
||||
|
||||
/* Copy the IPv6 address and ORPort from <b>md</b> into <b>ap</b> if we think
|
||||
* our firewall will let us connect to it. Uses ReachableORAddresses.
|
||||
* If pref_only, only copy if it's a preferred address.
|
||||
* If <b>fw_connection</b> is FIREWALL_DIR_CONNECTION, don't copy the address.
|
||||
* If the address isn't copied, return 0, else return 1. */
|
||||
static int
|
||||
fascist_firewall_choose_address_md_impl(const microdesc_t *md,
|
||||
firewall_connection_t fw_connection,
|
||||
int pref_only, tor_addr_port_t* ap)
|
||||
{
|
||||
if (!md) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Can't check dirport, it doesn't have one */
|
||||
if (fw_connection == FIREWALL_DIR_CONNECTION) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
tor_assert(ap);
|
||||
|
||||
if (fascist_firewall_allows_md(md, fw_connection, pref_only)) {
|
||||
tor_addr_copy(&ap->addr, &md->ipv6_addr);
|
||||
ap->port = md->ipv6_orport;
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/** Lookup the node for md, and call fascist_firewall_choose_address_node on
|
||||
* it. If any step in this process fails, fall back to calling
|
||||
* fascist_firewall_choose_address_md_impl. */
|
||||
int
|
||||
fascist_firewall_choose_address_md(const microdesc_t *md,
|
||||
firewall_connection_t fw_connection,
|
||||
int pref_only, tor_addr_port_t* ap)
|
||||
{
|
||||
if (!md) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
tor_assert(ap);
|
||||
|
||||
/* If we can't get the node, */
|
||||
networkstatus_t *ns;
|
||||
ns = networkstatus_get_latest_consensus_by_flavor(FLAV_MICRODESC);
|
||||
if (!ns) {
|
||||
return fascist_firewall_choose_address_md_impl(md, fw_connection,
|
||||
pref_only, ap);
|
||||
}
|
||||
const routerstatus_t *rs;
|
||||
rs = router_get_consensus_status_by_descriptor_digest(ns, md->digest);
|
||||
if (!rs) {
|
||||
return fascist_firewall_choose_address_md_impl(md, fw_connection,
|
||||
pref_only, ap);
|
||||
}
|
||||
const node_t *node = node_get_by_id(rs->identity_digest);
|
||||
if (node) {
|
||||
return fascist_firewall_choose_address_node(node, fw_connection,
|
||||
pref_only, ap);
|
||||
} else {
|
||||
return fascist_firewall_choose_address_md_impl(md, fw_connection,
|
||||
pref_only, ap);
|
||||
}
|
||||
}
|
||||
|
||||
/** Copy an address and port from <b>node</b> into <b>ap</b> that we think our
|
||||
* firewall will let us connect to. Uses ipv4h_addr/ipv6_addr and
|
||||
* ipv4_orport/ipv6_orport/ReachableORAddresses or
|
||||
|
|
|
@ -29,6 +29,11 @@ typedef enum firewall_connection_t {
|
|||
|
||||
typedef int exit_policy_parser_cfg_t;
|
||||
|
||||
int firewall_is_fascist_or(void);
|
||||
int fascist_firewall_use_ipv6(const or_options_t *options);
|
||||
int fascist_firewall_prefer_ipv6_orport(const or_options_t *options);
|
||||
int fascist_firewall_prefer_ipv6_dirport(const or_options_t *options);
|
||||
|
||||
int fascist_firewall_allows_address_addr(const tor_addr_t *addr, uint16_t port,
|
||||
firewall_connection_t fw_connection,
|
||||
int pref_only);
|
||||
|
@ -39,15 +44,9 @@ int fascist_firewall_allows_address_ipv4h(uint32_t ipv4h_or_addr,
|
|||
uint16_t ipv4_or_port,
|
||||
firewall_connection_t fw_connection,
|
||||
int pref_only);
|
||||
int fascist_firewall_allows_ri(const routerinfo_t *ri,
|
||||
firewall_connection_t fw_connection,
|
||||
int pref_only);
|
||||
int fascist_firewall_allows_rs(const routerstatus_t *rs,
|
||||
firewall_connection_t fw_connection,
|
||||
int pref_only);
|
||||
int fascist_firewall_allows_md(const microdesc_t *md,
|
||||
firewall_connection_t fw_connection,
|
||||
int pref_only);
|
||||
int fascist_firewall_allows_node(const node_t *node,
|
||||
firewall_connection_t fw_connection,
|
||||
int pref_only);
|
||||
|
@ -61,15 +60,9 @@ const tor_addr_port_t * fascist_firewall_choose_address(
|
|||
int want_a,
|
||||
firewall_connection_t fw_connection,
|
||||
int pref_only);
|
||||
int fascist_firewall_choose_address_ri(const routerinfo_t *ri,
|
||||
firewall_connection_t fw_connection,
|
||||
int pref_only, tor_addr_port_t* ap);
|
||||
int fascist_firewall_choose_address_rs(const routerstatus_t *rs,
|
||||
firewall_connection_t fw_connection,
|
||||
int pref_only, tor_addr_port_t* ap);
|
||||
int fascist_firewall_choose_address_md(const microdesc_t *md,
|
||||
firewall_connection_t fw_connection,
|
||||
int pref_only, tor_addr_port_t* ap);
|
||||
int fascist_firewall_choose_address_node(const node_t *node,
|
||||
firewall_connection_t fw_connection,
|
||||
int pref_only, tor_addr_port_t* ap);
|
||||
|
|
|
@ -1594,8 +1594,8 @@ router_picked_poor_directory_log(const routerstatus_t *rs)
|
|||
#define RETRY_ALTERNATE_IP_VERSION(retry_label) \
|
||||
STMT_BEGIN \
|
||||
if (result == NULL && try_ip_pref && options->ClientUseIPv4 \
|
||||
&& options->ClientUseIPv6 && !server_mode(options) && n_not_preferred \
|
||||
&& !n_busy) { \
|
||||
&& fascist_firewall_use_ipv6(options) && !server_mode(options) \
|
||||
&& n_not_preferred && !n_busy) { \
|
||||
n_excluded = 0; \
|
||||
n_busy = 0; \
|
||||
try_ip_pref = 0; \
|
||||
|
@ -1976,7 +1976,7 @@ router_add_running_nodes_to_smartlist(smartlist_t *sl, int allow_invalid,
|
|||
continue;
|
||||
if (node_is_unreliable(node, need_uptime, need_capacity, need_guard))
|
||||
continue;
|
||||
/* Choose a node with a preferred OR address */
|
||||
/* Choose a node with an OR address that matches the firewall rules */
|
||||
if (!fascist_firewall_allows_node(node, FIREWALL_OR_CONNECTION, pref_addr))
|
||||
continue;
|
||||
|
||||
|
@ -2443,7 +2443,7 @@ node_sl_choose_by_bandwidth(const smartlist_t *sl,
|
|||
* If <b>CRN_PREF_ADDR</b> is set in flags, we only consider nodes that
|
||||
* have an address that is preferred by the ClientPreferIPv6ORPort setting
|
||||
* (regardless of this flag, we exclude nodes that aren't allowed by the
|
||||
* firewall, including ClientUseIPv4 0 and ClientUseIPv6 0).
|
||||
* firewall, including ClientUseIPv4 0 and fascist_firewall_use_ipv6() == 0).
|
||||
*/
|
||||
const node_t *
|
||||
router_choose_random_node(smartlist_t *excludedsmartlist,
|
||||
|
|
|
@ -107,6 +107,11 @@ test_choose_random_entry_no_guards(void *arg)
|
|||
chosen_entry = choose_random_entry(NULL);
|
||||
tt_assert(chosen_entry);
|
||||
|
||||
/* And with the preference on auto */
|
||||
mocked_options.ClientPreferIPv6ORPort = -1;
|
||||
chosen_entry = choose_random_entry(NULL);
|
||||
tt_assert(chosen_entry);
|
||||
|
||||
/* Check that we don't get a guard if it doesn't pass mandatory address
|
||||
* settings */
|
||||
memset(&mocked_options, 0, sizeof(mocked_options));
|
||||
|
@ -128,6 +133,21 @@ test_choose_random_entry_no_guards(void *arg)
|
|||
chosen_entry = choose_random_entry(NULL);
|
||||
tt_assert(chosen_entry);
|
||||
|
||||
/* Check that we get a guard if it passes preferred address settings when
|
||||
* they're auto */
|
||||
memset(&mocked_options, 0, sizeof(mocked_options));
|
||||
mocked_options.ClientUseIPv4 = 1;
|
||||
mocked_options.ClientPreferIPv6ORPort = -1;
|
||||
|
||||
chosen_entry = choose_random_entry(NULL);
|
||||
tt_assert(chosen_entry);
|
||||
|
||||
/* And with IPv6 active */
|
||||
mocked_options.ClientUseIPv6 = 1;
|
||||
|
||||
chosen_entry = choose_random_entry(NULL);
|
||||
tt_assert(chosen_entry);
|
||||
|
||||
done:
|
||||
memset(&mocked_options, 0, sizeof(mocked_options));
|
||||
UNMOCK(get_options);
|
||||
|
@ -166,6 +186,11 @@ test_choose_random_entry_one_possible_guard(void *arg)
|
|||
chosen_entry = choose_random_entry(NULL);
|
||||
tt_ptr_op(chosen_entry, OP_EQ, the_guard);
|
||||
|
||||
/* And with the preference on auto */
|
||||
mocked_options.ClientPreferIPv6ORPort = -1;
|
||||
chosen_entry = choose_random_entry(NULL);
|
||||
tt_ptr_op(chosen_entry, OP_EQ, the_guard);
|
||||
|
||||
/* Check that we don't get a guard if it doesn't pass mandatory address
|
||||
* settings */
|
||||
memset(&mocked_options, 0, sizeof(mocked_options));
|
||||
|
@ -190,6 +215,21 @@ test_choose_random_entry_one_possible_guard(void *arg)
|
|||
* time, so we can't be sure we get the guard */
|
||||
tt_assert(chosen_entry);
|
||||
|
||||
/* Check that we get the guard if it passes preferred address settings when
|
||||
* they're auto */
|
||||
memset(&mocked_options, 0, sizeof(mocked_options));
|
||||
mocked_options.ClientUseIPv4 = 1;
|
||||
mocked_options.ClientPreferIPv6ORPort = -1;
|
||||
|
||||
chosen_entry = choose_random_entry(NULL);
|
||||
tt_ptr_op(chosen_entry, OP_EQ, the_guard);
|
||||
|
||||
/* and with IPv6 active */
|
||||
mocked_options.ClientUseIPv6 = 1;
|
||||
|
||||
chosen_entry = choose_random_entry(NULL);
|
||||
tt_ptr_op(chosen_entry, OP_EQ, the_guard);
|
||||
|
||||
done:
|
||||
memset(&mocked_options, 0, sizeof(mocked_options));
|
||||
UNMOCK(get_options);
|
||||
|
@ -722,8 +762,9 @@ test_node_preferred_orport(void *arg)
|
|||
|
||||
/* Setup options */
|
||||
memset(&mocked_options, 0, sizeof(mocked_options));
|
||||
/* We don't test ClientPreferIPv6ORPort here, because it's only used in
|
||||
* nodelist_set_consensus to setup each node_t. */
|
||||
/* We don't test ClientPreferIPv6ORPort here, because it's used in
|
||||
* nodelist_set_consensus to setup node.ipv6_preferred, which we set
|
||||
* directly. */
|
||||
MOCK(get_options, mock_get_options);
|
||||
|
||||
/* Setup IP addresses */
|
||||
|
|
|
@ -1235,10 +1235,42 @@ test_policies_fascist_firewall_allows_address(void *arg)
|
|||
|
||||
/* Test the function's address matching with UseBridges on */
|
||||
memset(&mock_options, 0, sizeof(or_options_t));
|
||||
mock_options.ClientUseIPv4 = 0;
|
||||
mock_options.ClientUseIPv6 = 0;
|
||||
mock_options.ClientUseIPv4 = 1;
|
||||
mock_options.ClientUseIPv6 = 1;
|
||||
mock_options.UseBridges = 1;
|
||||
|
||||
tt_assert(fascist_firewall_allows_address(&ipv4_addr, port, policy, 0, 0)
|
||||
== 1);
|
||||
tt_assert(fascist_firewall_allows_address(&ipv6_addr, port, policy, 0, 0)
|
||||
== 1);
|
||||
tt_assert(fascist_firewall_allows_address(&r_ipv4_addr, port, policy, 0, 0)
|
||||
== 0);
|
||||
tt_assert(fascist_firewall_allows_address(&r_ipv6_addr, port, policy, 0, 0)
|
||||
== 0);
|
||||
|
||||
/* Preferring IPv4 */
|
||||
tt_assert(fascist_firewall_allows_address(&ipv4_addr, port, policy, 1, 0)
|
||||
== 1);
|
||||
tt_assert(fascist_firewall_allows_address(&ipv6_addr, port, policy, 1, 0)
|
||||
== 0);
|
||||
tt_assert(fascist_firewall_allows_address(&r_ipv4_addr, port, policy, 1, 0)
|
||||
== 0);
|
||||
tt_assert(fascist_firewall_allows_address(&r_ipv6_addr, port, policy, 1, 0)
|
||||
== 0);
|
||||
|
||||
/* Preferring IPv6 */
|
||||
tt_assert(fascist_firewall_allows_address(&ipv4_addr, port, policy, 1, 1)
|
||||
== 0);
|
||||
tt_assert(fascist_firewall_allows_address(&ipv6_addr, port, policy, 1, 1)
|
||||
== 1);
|
||||
tt_assert(fascist_firewall_allows_address(&r_ipv4_addr, port, policy, 1, 1)
|
||||
== 0);
|
||||
tt_assert(fascist_firewall_allows_address(&r_ipv6_addr, port, policy, 1, 1)
|
||||
== 0);
|
||||
|
||||
/* bridge clients always use IPv6, regardless of ClientUseIPv6 */
|
||||
mock_options.ClientUseIPv4 = 1;
|
||||
mock_options.ClientUseIPv6 = 0;
|
||||
tt_assert(fascist_firewall_allows_address(&ipv4_addr, port, policy, 0, 0)
|
||||
== 1);
|
||||
tt_assert(fascist_firewall_allows_address(&ipv6_addr, port, policy, 0, 0)
|
||||
|
@ -1389,6 +1421,22 @@ test_policies_fascist_firewall_choose_address(void *arg)
|
|||
FIREWALL_DIR_CONNECTION, 1)
|
||||
== &ipv4_dir_ap);
|
||||
|
||||
/* Auto (Preferring IPv4) */
|
||||
mock_options.ClientPreferIPv6ORPort = -1;
|
||||
mock_options.ClientPreferIPv6DirPort = -1;
|
||||
tt_assert(fascist_firewall_choose_address(&ipv4_or_ap, &ipv6_or_ap, 0,
|
||||
FIREWALL_OR_CONNECTION, 0)
|
||||
== &ipv4_or_ap);
|
||||
tt_assert(fascist_firewall_choose_address(&ipv4_or_ap, &ipv6_or_ap, 0,
|
||||
FIREWALL_OR_CONNECTION, 1)
|
||||
== &ipv4_or_ap);
|
||||
tt_assert(fascist_firewall_choose_address(&ipv4_dir_ap, &ipv6_dir_ap, 0,
|
||||
FIREWALL_DIR_CONNECTION, 0)
|
||||
== &ipv4_dir_ap);
|
||||
tt_assert(fascist_firewall_choose_address(&ipv4_dir_ap, &ipv6_dir_ap, 0,
|
||||
FIREWALL_DIR_CONNECTION, 1)
|
||||
== &ipv4_dir_ap);
|
||||
|
||||
/* Preferring IPv6 */
|
||||
mock_options.ClientPreferIPv6ORPort = 1;
|
||||
mock_options.ClientPreferIPv6DirPort = 1;
|
||||
|
@ -1440,41 +1488,75 @@ test_policies_fascist_firewall_choose_address(void *arg)
|
|||
/* Choose an address with UseBridges on */
|
||||
memset(&mock_options, 0, sizeof(or_options_t));
|
||||
mock_options.UseBridges = 1;
|
||||
mock_options.ClientUseIPv4 = 1;
|
||||
mock_options.ClientUseIPv6 = 1;
|
||||
|
||||
for (mock_options.ClientUseIPv4 = 0; mock_options.ClientUseIPv4 <= 1;
|
||||
mock_options.ClientUseIPv4++) {
|
||||
for (mock_options.ClientUseIPv6 = 0; mock_options.ClientUseIPv6 <= 1;
|
||||
mock_options.ClientUseIPv6++) {
|
||||
for (mock_options.ClientPreferIPv6ORPort = 0;
|
||||
mock_options.ClientPreferIPv6ORPort <= 1;
|
||||
mock_options.ClientPreferIPv6ORPort++) {
|
||||
for (mock_options.ClientPreferIPv6DirPort = 0;
|
||||
mock_options.ClientPreferIPv6DirPort <= 1;
|
||||
mock_options.ClientPreferIPv6DirPort++) {
|
||||
/* This (ab)uses the actual enum values */
|
||||
tt_assert(FIREWALL_OR_CONNECTION < FIREWALL_DIR_CONNECTION);
|
||||
for (firewall_connection_t fw_connection = FIREWALL_OR_CONNECTION;
|
||||
fw_connection <= FIREWALL_DIR_CONNECTION; fw_connection++) {
|
||||
for (int pref_only = 0; pref_only <= 1; pref_only++) {
|
||||
|
||||
/* Ignoring all other settings, want_a should choose the address
|
||||
* for bridge clients */
|
||||
tt_assert(fascist_firewall_choose_address(&ipv4_or_ap,
|
||||
&ipv6_or_ap, 1,
|
||||
fw_connection,
|
||||
pref_only)
|
||||
/* Preferring IPv4 */
|
||||
mock_options.ClientPreferIPv6ORPort = 0;
|
||||
mock_options.ClientPreferIPv6DirPort = 0;
|
||||
tt_assert(fascist_firewall_choose_address(&ipv4_or_ap, &ipv6_or_ap, 0,
|
||||
FIREWALL_OR_CONNECTION, 0)
|
||||
== &ipv4_or_ap);
|
||||
tt_assert(fascist_firewall_choose_address(&ipv4_or_ap,
|
||||
&ipv6_or_ap, 0,
|
||||
fw_connection,
|
||||
pref_only)
|
||||
tt_assert(fascist_firewall_choose_address(&ipv4_or_ap, &ipv6_or_ap, 0,
|
||||
FIREWALL_OR_CONNECTION, 1)
|
||||
== &ipv4_or_ap);
|
||||
tt_assert(fascist_firewall_choose_address(&ipv4_dir_ap, &ipv6_dir_ap, 0,
|
||||
FIREWALL_DIR_CONNECTION, 0)
|
||||
== &ipv4_dir_ap);
|
||||
tt_assert(fascist_firewall_choose_address(&ipv4_dir_ap, &ipv6_dir_ap, 0,
|
||||
FIREWALL_DIR_CONNECTION, 1)
|
||||
== &ipv4_dir_ap);
|
||||
|
||||
/* Auto (Preferring IPv6 for bridge clients) */
|
||||
mock_options.ClientPreferIPv6ORPort = -1;
|
||||
mock_options.ClientPreferIPv6DirPort = -1;
|
||||
tt_assert(fascist_firewall_choose_address(&ipv4_or_ap, &ipv6_or_ap, 0,
|
||||
FIREWALL_OR_CONNECTION, 0)
|
||||
== &ipv6_or_ap);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
tt_assert(fascist_firewall_choose_address(&ipv4_or_ap, &ipv6_or_ap, 0,
|
||||
FIREWALL_OR_CONNECTION, 1)
|
||||
== &ipv6_or_ap);
|
||||
tt_assert(fascist_firewall_choose_address(&ipv4_dir_ap, &ipv6_dir_ap, 0,
|
||||
FIREWALL_DIR_CONNECTION, 0)
|
||||
== &ipv6_dir_ap);
|
||||
tt_assert(fascist_firewall_choose_address(&ipv4_dir_ap, &ipv6_dir_ap, 0,
|
||||
FIREWALL_DIR_CONNECTION, 1)
|
||||
== &ipv6_dir_ap);
|
||||
|
||||
/* Preferring IPv6 */
|
||||
mock_options.ClientPreferIPv6ORPort = 1;
|
||||
mock_options.ClientPreferIPv6DirPort = 1;
|
||||
tt_assert(fascist_firewall_choose_address(&ipv4_or_ap, &ipv6_or_ap, 0,
|
||||
FIREWALL_OR_CONNECTION, 0)
|
||||
== &ipv6_or_ap);
|
||||
tt_assert(fascist_firewall_choose_address(&ipv4_or_ap, &ipv6_or_ap, 0,
|
||||
FIREWALL_OR_CONNECTION, 1)
|
||||
== &ipv6_or_ap);
|
||||
tt_assert(fascist_firewall_choose_address(&ipv4_dir_ap, &ipv6_dir_ap, 0,
|
||||
FIREWALL_DIR_CONNECTION, 0)
|
||||
== &ipv6_dir_ap);
|
||||
tt_assert(fascist_firewall_choose_address(&ipv4_dir_ap, &ipv6_dir_ap, 0,
|
||||
FIREWALL_DIR_CONNECTION, 1)
|
||||
== &ipv6_dir_ap);
|
||||
|
||||
|
||||
/* In the default configuration (Auto / IPv6 off), bridge clients should
|
||||
* still use and prefer IPv6 regardless of ClientUseIPv6. */
|
||||
mock_options.ClientUseIPv6 = 0;
|
||||
mock_options.ClientPreferIPv6ORPort = -1;
|
||||
mock_options.ClientPreferIPv6DirPort = -1;
|
||||
tt_assert(fascist_firewall_choose_address(&ipv4_or_ap, &ipv6_or_ap, 0,
|
||||
FIREWALL_OR_CONNECTION, 0)
|
||||
== &ipv6_or_ap);
|
||||
tt_assert(fascist_firewall_choose_address(&ipv4_or_ap, &ipv6_or_ap, 0,
|
||||
FIREWALL_OR_CONNECTION, 1)
|
||||
== &ipv6_or_ap);
|
||||
tt_assert(fascist_firewall_choose_address(&ipv4_dir_ap, &ipv6_dir_ap, 0,
|
||||
FIREWALL_DIR_CONNECTION, 0)
|
||||
== &ipv6_dir_ap);
|
||||
tt_assert(fascist_firewall_choose_address(&ipv4_dir_ap, &ipv6_dir_ap, 0,
|
||||
FIREWALL_DIR_CONNECTION, 1)
|
||||
== &ipv6_dir_ap);
|
||||
|
||||
/* Choose an address with IPv4 on */
|
||||
memset(&mock_options, 0, sizeof(or_options_t));
|
||||
|
|
Loading…
Add table
Reference in a new issue