mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2025-02-25 15:10:48 +01:00
When IPv6 addresses have not been downloaded, use hard-coded address info
The microdesc consensus does not contain any IPv6 addresses.
When a client has a microdesc consensus but no microdescriptor, make it
use the hard-coded IPv6 address for the node (if available).
(Hard-coded addresses can come from authorities, fallback directories,
or configured bridges.)
If there is no hard-coded address, log a BUG message, and fail the
connection attempt. (All existing code checks for a hard-coded address
before choosing a node address.)
Fixes 20996, fix on b167e82
from 19608 in 0.2.8.5-alpha.
This commit is contained in:
parent
5227ff4aad
commit
0417dae580
3 changed files with 59 additions and 8 deletions
|
@ -1126,6 +1126,9 @@ node_get_prim_orport(const node_t *node, tor_addr_port_t *ap_out)
|
||||||
node_assert_ok(node);
|
node_assert_ok(node);
|
||||||
tor_assert(ap_out);
|
tor_assert(ap_out);
|
||||||
|
|
||||||
|
/* Check ri first, because rewrite_node_address_for_bridge() updates
|
||||||
|
* node->ri with the configured bridge address. */
|
||||||
|
|
||||||
RETURN_IPV4_AP(node->ri, or_port, ap_out);
|
RETURN_IPV4_AP(node->ri, or_port, ap_out);
|
||||||
RETURN_IPV4_AP(node->rs, or_port, ap_out);
|
RETURN_IPV4_AP(node->rs, or_port, ap_out);
|
||||||
/* Microdescriptors only have an IPv6 address */
|
/* Microdescriptors only have an IPv6 address */
|
||||||
|
@ -1156,9 +1159,11 @@ node_get_pref_ipv6_orport(const node_t *node, tor_addr_port_t *ap_out)
|
||||||
node_assert_ok(node);
|
node_assert_ok(node);
|
||||||
tor_assert(ap_out);
|
tor_assert(ap_out);
|
||||||
|
|
||||||
/* Prefer routerstatus over microdesc for consistency with the
|
/* Check ri first, because rewrite_node_address_for_bridge() updates
|
||||||
* fascist_firewall_* functions. Also check if the address or port are valid,
|
* node->ri with the configured bridge address.
|
||||||
* and try another alternative if they are not. */
|
* Prefer rs over md for consistency with the fascist_firewall_* functions.
|
||||||
|
* Check if the address or port are valid, and try another alternative
|
||||||
|
* if they are not. */
|
||||||
|
|
||||||
if (node->ri && tor_addr_port_is_valid(&node->ri->ipv6_addr,
|
if (node->ri && tor_addr_port_is_valid(&node->ri->ipv6_addr,
|
||||||
node->ri->ipv6_orport, 0)) {
|
node->ri->ipv6_orport, 0)) {
|
||||||
|
@ -1218,6 +1223,9 @@ node_get_prim_dirport(const node_t *node, tor_addr_port_t *ap_out)
|
||||||
node_assert_ok(node);
|
node_assert_ok(node);
|
||||||
tor_assert(ap_out);
|
tor_assert(ap_out);
|
||||||
|
|
||||||
|
/* Check ri first, because rewrite_node_address_for_bridge() updates
|
||||||
|
* node->ri with the configured bridge address. */
|
||||||
|
|
||||||
RETURN_IPV4_AP(node->ri, dir_port, ap_out);
|
RETURN_IPV4_AP(node->ri, dir_port, ap_out);
|
||||||
RETURN_IPV4_AP(node->rs, dir_port, ap_out);
|
RETURN_IPV4_AP(node->rs, dir_port, ap_out);
|
||||||
/* Microdescriptors only have an IPv6 address */
|
/* Microdescriptors only have an IPv6 address */
|
||||||
|
@ -1250,8 +1258,11 @@ node_get_pref_ipv6_dirport(const node_t *node, tor_addr_port_t *ap_out)
|
||||||
node_assert_ok(node);
|
node_assert_ok(node);
|
||||||
tor_assert(ap_out);
|
tor_assert(ap_out);
|
||||||
|
|
||||||
/* Check if the address or port are valid, and try another alternative if
|
/* Check ri first, because rewrite_node_address_for_bridge() updates
|
||||||
* they are not. Note that microdescriptors have no dir_port. */
|
* node->ri with the configured bridge address.
|
||||||
|
* Prefer rs over md for consistency with the fascist_firewall_* functions.
|
||||||
|
* Check if the address or port are valid, and try another alternative
|
||||||
|
* if they are not. */
|
||||||
|
|
||||||
/* Assume IPv4 and IPv6 dirports are the same */
|
/* Assume IPv4 and IPv6 dirports are the same */
|
||||||
if (node->ri && tor_addr_port_is_valid(&node->ri->ipv6_addr,
|
if (node->ri && tor_addr_port_is_valid(&node->ri->ipv6_addr,
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include "or.h"
|
#include "or.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "dirserv.h"
|
#include "dirserv.h"
|
||||||
|
#include "microdesc.h"
|
||||||
#include "networkstatus.h"
|
#include "networkstatus.h"
|
||||||
#include "nodelist.h"
|
#include "nodelist.h"
|
||||||
#include "policies.h"
|
#include "policies.h"
|
||||||
|
@ -893,6 +894,33 @@ fascist_firewall_choose_address_ipv4h(uint32_t ipv4h_addr,
|
||||||
pref_ipv6, ap);
|
pref_ipv6, ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* The microdescriptor consensus has no IPv6 addresses in rs: they are in
|
||||||
|
* the microdescriptors. This means we can't rely on the node's IPv6 address
|
||||||
|
* until its microdescriptor is available (when using microdescs).
|
||||||
|
* But for bridges, rewrite_node_address_for_bridge() updates node->ri with
|
||||||
|
* the configured address, so we can trust bridge addresses.
|
||||||
|
* (Bridges could gain an IPv6 address if their microdescriptor arrives, but
|
||||||
|
* this will never be their preferred address: that is in the config.)
|
||||||
|
* Returns true if the node needs a microdescriptor for its IPv6 address, and
|
||||||
|
* false if the addresses in the node are already up-to-date.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
node_awaiting_ipv6(const or_options_t* options, const node_t *node)
|
||||||
|
{
|
||||||
|
tor_assert(node);
|
||||||
|
|
||||||
|
/* There's no point waiting for an IPv6 address if we'd never use it */
|
||||||
|
if (!fascist_firewall_use_ipv6(options)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We are waiting if we_use_microdescriptors_for_circuits() and we have no
|
||||||
|
* md. Bridges have a ri based on their config. They would never use the
|
||||||
|
* address from their md, so there's no need to wait for it. */
|
||||||
|
return (!node->md && we_use_microdescriptors_for_circuits(options) &&
|
||||||
|
!node->ri);
|
||||||
|
}
|
||||||
|
|
||||||
/** Like fascist_firewall_choose_address_base(), but takes <b>rs</b>.
|
/** Like fascist_firewall_choose_address_base(), but takes <b>rs</b>.
|
||||||
* Consults the corresponding node, then falls back to rs if node is NULL.
|
* Consults the corresponding node, then falls back to rs if node is NULL.
|
||||||
* This should only happen when there's no valid consensus, and rs doesn't
|
* This should only happen when there's no valid consensus, and rs doesn't
|
||||||
|
@ -909,15 +937,15 @@ fascist_firewall_choose_address_rs(const routerstatus_t *rs,
|
||||||
|
|
||||||
tor_assert(ap);
|
tor_assert(ap);
|
||||||
|
|
||||||
|
const or_options_t *options = get_options();
|
||||||
const node_t *node = node_get_by_id(rs->identity_digest);
|
const node_t *node = node_get_by_id(rs->identity_digest);
|
||||||
|
|
||||||
if (node) {
|
if (node && !node_awaiting_ipv6(options, node)) {
|
||||||
return fascist_firewall_choose_address_node(node, fw_connection, pref_only,
|
return fascist_firewall_choose_address_node(node, fw_connection, pref_only,
|
||||||
ap);
|
ap);
|
||||||
} else {
|
} else {
|
||||||
/* There's no node-specific IPv6 preference, so use the generic IPv6
|
/* There's no node-specific IPv6 preference, so use the generic IPv6
|
||||||
* preference instead. */
|
* preference instead. */
|
||||||
const or_options_t *options = get_options();
|
|
||||||
int pref_ipv6 = (fw_connection == FIREWALL_OR_CONNECTION
|
int pref_ipv6 = (fw_connection == FIREWALL_OR_CONNECTION
|
||||||
? fascist_firewall_prefer_ipv6_orport(options)
|
? fascist_firewall_prefer_ipv6_orport(options)
|
||||||
: fascist_firewall_prefer_ipv6_dirport(options));
|
: fascist_firewall_prefer_ipv6_dirport(options));
|
||||||
|
@ -951,6 +979,18 @@ fascist_firewall_choose_address_node(const node_t *node,
|
||||||
|
|
||||||
node_assert_ok(node);
|
node_assert_ok(node);
|
||||||
|
|
||||||
|
/* Calling fascist_firewall_choose_address_node() when the node is missing
|
||||||
|
* IPv6 information breaks IPv6-only clients.
|
||||||
|
* If the node is a hard-coded fallback directory or authority, call
|
||||||
|
* fascist_firewall_choose_address_rs() on the fake (hard-coded) routerstatus
|
||||||
|
* for the node.
|
||||||
|
* If it is not hard-coded, check that the node has a microdescriptor, full
|
||||||
|
* descriptor (routerinfo), or is one of our configured bridges before
|
||||||
|
* calling this function. */
|
||||||
|
if (BUG(node_awaiting_ipv6(get_options(), node))) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
const int pref_ipv6_node = (fw_connection == FIREWALL_OR_CONNECTION
|
const int pref_ipv6_node = (fw_connection == FIREWALL_OR_CONNECTION
|
||||||
? node_ipv6_or_preferred(node)
|
? node_ipv6_or_preferred(node)
|
||||||
: node_ipv6_dir_preferred(node));
|
: node_ipv6_dir_preferred(node));
|
||||||
|
|
|
@ -948,7 +948,7 @@ authority_certs_fetch_resource_impl(const char *resource,
|
||||||
|
|
||||||
/* If we've just downloaded a consensus from a bridge, re-use that
|
/* If we've just downloaded a consensus from a bridge, re-use that
|
||||||
* bridge */
|
* bridge */
|
||||||
if (options->UseBridges && node && !get_via_tor) {
|
if (options->UseBridges && node && node->ri && !get_via_tor) {
|
||||||
/* clients always make OR connections to bridges */
|
/* clients always make OR connections to bridges */
|
||||||
tor_addr_port_t or_ap;
|
tor_addr_port_t or_ap;
|
||||||
/* we are willing to use a non-preferred address if we need to */
|
/* we are willing to use a non-preferred address if we need to */
|
||||||
|
|
Loading…
Add table
Reference in a new issue