Merge branch 'assume_reachable_revamp'

This commit is contained in:
Nick Mathewson 2020-06-26 08:34:56 -04:00
commit dbc2b75009
20 changed files with 123 additions and 50 deletions

3
changes/ticket33224 Normal file
View File

@ -0,0 +1,3 @@
o Minor features (relay, IPv6):
- Add an AssumeReachableIPv6 option to disable self-checking IPv6
reachability. Closes part of ticket 33224.

5
changes/ticket34064 Normal file
View File

@ -0,0 +1,5 @@
o Minor features (relay, ipv6):
- Add new "assume-reachable" and "assume-reachable-ipv6" parameters
to be used in an emergency to tell relays that they should publish
even if they cannot complete their ORPort self-checks.
Closes ticket 34064 and part of 33224.

View File

@ -2145,7 +2145,12 @@ is non-zero):
don't do self-reachability testing; just upload your server descriptor don't do self-reachability testing; just upload your server descriptor
immediately. If **AuthoritativeDirectory** is also set, this option immediately. If **AuthoritativeDirectory** is also set, this option
instructs the dirserver to bypass remote reachability testing too and list instructs the dirserver to bypass remote reachability testing too and list
all connected servers as running. all connected servers as running. (Default: 0)
[[AssumeReachableIPv6]] **AssumeReachableIPv6** **0**|**1**|**auto**::
Like **AssumeReachable**, but affects only the relay's own IPv6 ORPort.
If this value is set to "auto", then Tor will look at **AssumeReachable**
instead. (Default: auto)
[[BridgeRelay]] **BridgeRelay** **0**|**1**:: [[BridgeRelay]] **BridgeRelay** **0**|**1**::
Sets the relay to act as a "bridge" with respect to relaying connections Sets the relay to act as a "bridge" with respect to relaying connections

View File

@ -323,6 +323,7 @@ static const config_var_t option_vars_[] = {
V(AlternateDirAuthority, LINELIST, NULL), V(AlternateDirAuthority, LINELIST, NULL),
OBSOLETE("AlternateHSAuthority"), OBSOLETE("AlternateHSAuthority"),
V(AssumeReachable, BOOL, "0"), V(AssumeReachable, BOOL, "0"),
V(AssumeReachableIPv6, AUTOBOOL, "auto"),
OBSOLETE("AuthDirBadDir"), OBSOLETE("AuthDirBadDir"),
OBSOLETE("AuthDirBadDirCCs"), OBSOLETE("AuthDirBadDirCCs"),
V(AuthDirBadExit, LINELIST, NULL), V(AuthDirBadExit, LINELIST, NULL),
@ -3225,6 +3226,10 @@ options_validate_cb(const void *old_options_, void *options_, char **msg)
REJECT("TokenBucketRefillInterval must be between 1 and 1000 inclusive."); REJECT("TokenBucketRefillInterval must be between 1 and 1000 inclusive.");
} }
if (options->AssumeReachable && options->AssumeReachableIPv6 == 0) {
REJECT("Cannot set AssumeReachable 1 and AssumeReachableIPv6 0.");
}
if (options->ExcludeExitNodes || options->ExcludeNodes) { if (options->ExcludeExitNodes || options->ExcludeNodes) {
options->ExcludeExitNodesUnion_ = routerset_new(); options->ExcludeExitNodesUnion_ = routerset_new();
routerset_union(options->ExcludeExitNodesUnion_,options->ExcludeExitNodes); routerset_union(options->ExcludeExitNodesUnion_,options->ExcludeExitNodes);

View File

@ -195,7 +195,14 @@ struct or_options_t {
unsigned int HTTPTunnelPort_set : 1; unsigned int HTTPTunnelPort_set : 1;
/**@}*/ /**@}*/
int AssumeReachable; /**< Whether to publish our descriptor regardless. */ /** Whether to publish our descriptor regardless of all our self-tests
*/
int AssumeReachable;
/** Whether to publish our descriptor regardless of IPv6 self-tests.
*
* This is an autobool; when set to AUTO, it uses AssumeReachable.
**/
int AssumeReachableIPv6;
int AuthoritativeDir; /**< Boolean: is this an authoritative directory? */ int AuthoritativeDir; /**< Boolean: is this an authoritative directory? */
int V3AuthoritativeDir; /**< Boolean: is this an authoritative directory int V3AuthoritativeDir; /**< Boolean: is this an authoritative directory
* for version 3 directories? */ * for version 3 directories? */

View File

@ -90,7 +90,7 @@ static int consensus_nf_pad_single_onion;
* for every single connection, every second. * for every single connection, every second.
*/ */
void void
channelpadding_new_consensus_params(networkstatus_t *ns) channelpadding_new_consensus_params(const networkstatus_t *ns)
{ {
#define DFLT_NETFLOW_INACTIVE_KEEPALIVE_LOW 1500 #define DFLT_NETFLOW_INACTIVE_KEEPALIVE_LOW 1500
#define DFLT_NETFLOW_INACTIVE_KEEPALIVE_HIGH 9500 #define DFLT_NETFLOW_INACTIVE_KEEPALIVE_HIGH 9500

View File

@ -37,7 +37,6 @@ int channelpadding_send_enable_command(channel_t *chan, uint16_t low_timeout,
int channelpadding_get_circuits_available_timeout(void); int channelpadding_get_circuits_available_timeout(void);
unsigned int channelpadding_get_channel_idle_timeout(const channel_t *, int); unsigned int channelpadding_get_channel_idle_timeout(const channel_t *, int);
void channelpadding_new_consensus_params(networkstatus_t *ns); void channelpadding_new_consensus_params(const networkstatus_t *ns);
#endif /* !defined(TOR_CHANNELPADDING_H) */ #endif /* !defined(TOR_CHANNELPADDING_H) */

View File

@ -1055,7 +1055,7 @@ circuit_build_no_more_hops(origin_circuit_t *circ)
control_event_client_status(LOG_NOTICE, "CIRCUIT_ESTABLISHED"); control_event_client_status(LOG_NOTICE, "CIRCUIT_ESTABLISHED");
clear_broken_connection_map(1); clear_broken_connection_map(1);
if (server_mode(options) && if (server_mode(options) &&
!router_should_skip_orport_reachability_check(options)) { !router_all_orports_seem_reachable(options)) {
inform_testing_reachability(); inform_testing_reachability();
router_do_reachability_checks(1, 1); router_do_reachability_checks(1, 1);
} }

View File

@ -399,7 +399,7 @@ circuit_build_times_initial_timeout(void)
* and learn a new timeout. * and learn a new timeout.
*/ */
static int32_t static int32_t
circuit_build_times_recent_circuit_count(networkstatus_t *ns) circuit_build_times_recent_circuit_count(const networkstatus_t *ns)
{ {
int32_t num; int32_t num;
num = networkstatus_get_param(ns, "cbtrecentcount", num = networkstatus_get_param(ns, "cbtrecentcount",
@ -425,7 +425,7 @@ circuit_build_times_recent_circuit_count(networkstatus_t *ns)
*/ */
void void
circuit_build_times_new_consensus_params(circuit_build_times_t *cbt, circuit_build_times_new_consensus_params(circuit_build_times_t *cbt,
networkstatus_t *ns) const networkstatus_t *ns)
{ {
int32_t num; int32_t num;

View File

@ -43,7 +43,7 @@ int circuit_build_times_needs_circuits_now(const circuit_build_times_t *cbt);
void circuit_build_times_init(circuit_build_times_t *cbt); void circuit_build_times_init(circuit_build_times_t *cbt);
void circuit_build_times_free_timeouts(circuit_build_times_t *cbt); void circuit_build_times_free_timeouts(circuit_build_times_t *cbt);
void circuit_build_times_new_consensus_params(circuit_build_times_t *cbt, void circuit_build_times_new_consensus_params(circuit_build_times_t *cbt,
networkstatus_t *ns); const networkstatus_t *ns);
double circuit_build_times_timeout_rate(const circuit_build_times_t *cbt); double circuit_build_times_timeout_rate(const circuit_build_times_t *cbt);
double circuit_build_times_close_rate(const circuit_build_times_t *cbt); double circuit_build_times_close_rate(const circuit_build_times_t *cbt);

View File

@ -1642,7 +1642,7 @@ static void
circuit_testing_opened(origin_circuit_t *circ) circuit_testing_opened(origin_circuit_t *circ)
{ {
if (have_performed_bandwidth_test || if (have_performed_bandwidth_test ||
!router_should_skip_orport_reachability_check(get_options())) { !router_all_orports_seem_reachable(get_options())) {
/* either we've already done everything we want with testing circuits, /* either we've already done everything we want with testing circuits,
* or this testing circuit became open due to a fluke, e.g. we picked * or this testing circuit became open due to a fluke, e.g. we picked
* a last hop where we already had the connection open due to an * a last hop where we already had the connection open due to an
@ -1661,7 +1661,7 @@ circuit_testing_failed(origin_circuit_t *circ, int at_last_hop)
{ {
const or_options_t *options = get_options(); const or_options_t *options = get_options();
if (server_mode(options) && if (server_mode(options) &&
router_should_skip_orport_reachability_check(options)) router_all_orports_seem_reachable(options))
return; return;
log_info(LD_GENERAL, log_info(LD_GENERAL,

View File

@ -1279,7 +1279,7 @@ getinfo_helper_events(control_connection_t *control_conn,
? "1" : "0"); ? "1" : "0");
} else if (!strcmp(question, "status/reachability-succeeded/or")) { } else if (!strcmp(question, "status/reachability-succeeded/or")) {
*answer = tor_strdup( *answer = tor_strdup(
router_should_skip_orport_reachability_check(options) ? router_all_orports_seem_reachable(options) ?
"1" : "0"); "1" : "0");
} else if (!strcmp(question, "status/reachability-succeeded/dir")) { } else if (!strcmp(question, "status/reachability-succeeded/dir")) {
*answer = tor_strdup( *answer = tor_strdup(
@ -1288,7 +1288,7 @@ getinfo_helper_events(control_connection_t *control_conn,
} else if (!strcmp(question, "status/reachability-succeeded")) { } else if (!strcmp(question, "status/reachability-succeeded")) {
tor_asprintf( tor_asprintf(
answer, "OR=%d DIR=%d", answer, "OR=%d DIR=%d",
router_should_skip_orport_reachability_check(options) ? 1 : 0, router_all_orports_seem_reachable(options) ? 1 : 0,
router_dirport_seems_reachable(options) ? 1 : 0); router_dirport_seems_reachable(options) ? 1 : 0);
} else if (!strcmp(question, "status/bootstrap-phase")) { } else if (!strcmp(question, "status/bootstrap-phase")) {
*answer = control_event_boot_last_msg(); *answer = control_event_boot_last_msg();

View File

@ -1670,7 +1670,35 @@ notify_before_networkstatus_changes(const networkstatus_t *old_c,
static void static void
notify_after_networkstatus_changes(void) notify_after_networkstatus_changes(void)
{ {
const networkstatus_t *c = networkstatus_get_latest_consensus();
const or_options_t *options = get_options();
const time_t now = approx_time();
scheduler_notify_networkstatus_changed(); scheduler_notify_networkstatus_changed();
/* The "current" consensus has just been set and it is a usable flavor so
* the first thing we need to do is recalculate the voting schedule static
* object so we can use the timings in there needed by some subsystems
* such as hidden service and shared random. */
dirauth_sched_recalculate_timing(options, now);
reschedule_dirvote(options);
nodelist_set_consensus(c);
update_consensus_networkstatus_fetch_time(now);
/* Change the cell EWMA settings */
cmux_ewma_set_options(options, c);
/* XXXX this call might be unnecessary here: can changing the
* current consensus really alter our view of any OR's rate limits? */
connection_or_update_token_buckets(get_connection_array(), options);
circuit_build_times_new_consensus_params(
get_circuit_build_times_mutable(), c);
channelpadding_new_consensus_params(c);
circpad_new_consensus_params(c);
router_new_consensus_params(c);
} }
/** Copy all the ancillary information (like router download status and so on) /** Copy all the ancillary information (like router download status and so on)
@ -2115,29 +2143,6 @@ networkstatus_set_current_consensus(const char *consensus,
/* Notify that we just changed the consensus so the current global value /* Notify that we just changed the consensus so the current global value
* can be looked at. */ * can be looked at. */
notify_after_networkstatus_changes(); notify_after_networkstatus_changes();
/* The "current" consensus has just been set and it is a usable flavor so
* the first thing we need to do is recalculate the voting schedule static
* object so we can use the timings in there needed by some subsystems
* such as hidden service and shared random. */
dirauth_sched_recalculate_timing(options, now);
reschedule_dirvote(options);
nodelist_set_consensus(c);
update_consensus_networkstatus_fetch_time(now);
/* Change the cell EWMA settings */
cmux_ewma_set_options(options, c);
/* XXXX this call might be unnecessary here: can changing the
* current consensus really alter our view of any OR's rate limits? */
connection_or_update_token_buckets(get_connection_array(), options);
circuit_build_times_new_consensus_params(
get_circuit_build_times_mutable(), c);
channelpadding_new_consensus_params(c);
circpad_new_consensus_params(c);
} }
/* Reset the failure count only if this consensus is actually valid. */ /* Reset the failure count only if this consensus is actually valid. */

View File

@ -621,7 +621,7 @@ get_estimated_address_per_node, (void))
* and grab microdescriptors into nodes as appropriate. * and grab microdescriptors into nodes as appropriate.
*/ */
void void
nodelist_set_consensus(networkstatus_t *ns) nodelist_set_consensus(const networkstatus_t *ns)
{ {
const or_options_t *options = get_options(); const or_options_t *options = get_options();
int authdir = authdir_mode_v3(options); int authdir = authdir_mode_v3(options);
@ -952,7 +952,7 @@ nodelist_assert_ok(void)
/** Ensure that the nodelist has been created with the most recent consensus. /** Ensure that the nodelist has been created with the most recent consensus.
* If that's not the case, make it so. */ * If that's not the case, make it so. */
void void
nodelist_ensure_freshness(networkstatus_t *ns) nodelist_ensure_freshness(const networkstatus_t *ns)
{ {
tor_assert(ns); tor_assert(ns);

View File

@ -32,8 +32,8 @@ const node_t *node_get_by_hex_id(const char *identity_digest,
unsigned flags); unsigned flags);
node_t *nodelist_set_routerinfo(routerinfo_t *ri, routerinfo_t **ri_old_out); node_t *nodelist_set_routerinfo(routerinfo_t *ri, routerinfo_t **ri_old_out);
node_t *nodelist_add_microdesc(microdesc_t *md); node_t *nodelist_add_microdesc(microdesc_t *md);
void nodelist_set_consensus(networkstatus_t *ns); void nodelist_set_consensus(const networkstatus_t *ns);
void nodelist_ensure_freshness(networkstatus_t *ns); void nodelist_ensure_freshness(const networkstatus_t *ns);
int nodelist_probably_contains_address(const tor_addr_t *addr); int nodelist_probably_contains_address(const tor_addr_t *addr);
void nodelist_add_addr4_to_address_set(const uint32_t addr); void nodelist_add_addr4_to_address_set(const uint32_t addr);
void nodelist_add_addr6_to_address_set(const tor_addr_t *addr); void nodelist_add_addr6_to_address_set(const tor_addr_t *addr);

View File

@ -1349,6 +1349,17 @@ should_refuse_unknown_exits(const or_options_t *options)
} }
} }
/**
* If true, then we will publish our descriptor even if our own IPv4 ORPort
* seems to be unreachable.
**/
static bool publish_even_when_ipv4_orport_unreachable = false;
/**
* If true, then we will publish our descriptor even if our own IPv6 ORPort
* seems to be unreachable.
**/
static bool publish_even_when_ipv6_orport_unreachable = false;
/** Decide if we're a publishable server. We are a publishable server if: /** Decide if we're a publishable server. We are a publishable server if:
* - We don't have the ClientOnly option set * - We don't have the ClientOnly option set
* and * and
@ -1377,8 +1388,18 @@ decide_if_publishable_server(void)
return 1; return 1;
if (!router_get_advertised_or_port(options)) if (!router_get_advertised_or_port(options))
return 0; return 0;
if (!router_should_skip_orport_reachability_check(options)) if (!router_orport_seems_reachable(options, AF_INET)) {
return 0; // We have an ipv4 orport, and it doesn't seem reachable.
if (!publish_even_when_ipv4_orport_unreachable) {
return 0;
}
}
if (!router_orport_seems_reachable(options, AF_INET6)) {
// We have an ipv6 orport, and it doesn't seem reachable.
if (!publish_even_when_ipv6_orport_unreachable) {
return 0;
}
}
if (router_have_consensus_path() == CONSENSUS_PATH_INTERNAL) { if (router_have_consensus_path() == CONSENSUS_PATH_INTERNAL) {
/* All set: there are no exits in the consensus (maybe this is a tiny /* All set: there are no exits in the consensus (maybe this is a tiny
* test network), so we can't check our DirPort reachability. */ * test network), so we can't check our DirPort reachability. */
@ -2402,6 +2423,24 @@ router_rebuild_descriptor(int force)
return 0; return 0;
} }
/** Called when we have a new set of consensus parameters. */
void
router_new_consensus_params(const networkstatus_t *ns)
{
const int32_t DEFAULT_ASSUME_REACHABLE = 0;
const int32_t DEFAULT_ASSUME_REACHABLE_IPV6 = 0;
int ar, ar6;
ar = networkstatus_get_param(ns,
"assume-reachable",
DEFAULT_ASSUME_REACHABLE, 0, 1);
ar6 = networkstatus_get_param(ns,
"assume-reachable-ipv6",
DEFAULT_ASSUME_REACHABLE_IPV6, 0, 1);
publish_even_when_ipv4_orport_unreachable = ar;
publish_even_when_ipv6_orport_unreachable = ar || ar6;
}
/** If our router descriptor ever goes this long without being regenerated /** If our router descriptor ever goes this long without being regenerated
* because something changed, we force an immediate regenerate-and-upload. */ * because something changed, we force an immediate regenerate-and-upload. */
#define FORCE_REGENERATE_DESCRIPTOR_INTERVAL (18*60*60) #define FORCE_REGENERATE_DESCRIPTOR_INTERVAL (18*60*60)

View File

@ -81,6 +81,7 @@ int router_should_advertise_dirport(const or_options_t *options,
void consider_publishable_server(int force); void consider_publishable_server(int force);
int should_refuse_unknown_exits(const or_options_t *options); int should_refuse_unknown_exits(const or_options_t *options);
void router_new_consensus_params(const networkstatus_t *);
void router_upload_dir_desc_to_dirservers(int force); void router_upload_dir_desc_to_dirservers(int force);
void mark_my_descriptor_dirty_if_too_old(time_t now); void mark_my_descriptor_dirty_if_too_old(time_t now);
void mark_my_descriptor_dirty(const char *reason); void mark_my_descriptor_dirty(const char *reason);

View File

@ -86,9 +86,8 @@ router_reachability_checks_disabled(const or_options_t *options)
* orport checks. * orport checks.
*/ */
int int
router_orport_seems_reachable( router_orport_seems_reachable(const or_options_t *options,
const or_options_t *options, int family)
int family)
{ {
tor_assert_nonfatal(family == AF_INET || family == AF_INET6 || family == 0); tor_assert_nonfatal(family == AF_INET || family == AF_INET6 || family == 0);
int reach_checks_disabled = router_reachability_checks_disabled(options); int reach_checks_disabled = router_reachability_checks_disabled(options);
@ -96,6 +95,11 @@ router_orport_seems_reachable(
return true; return true;
} }
// Note that we do a == 1 here, not just a boolean check. This value
// is also an autobool, so CFG_AUTO does not mean that we should
// assume IPv6 ports are reachable.
const bool ipv6_assume_reachable = (options->AssumeReachableIPv6 == 1);
// Which reachability flags should we look at? // Which reachability flags should we look at?
const bool checking_ipv4 = (family == AF_INET || family == 0); const bool checking_ipv4 = (family == AF_INET || family == 0);
const bool checking_ipv6 = (family == AF_INET6 || family == 0); const bool checking_ipv6 = (family == AF_INET6 || family == 0);
@ -105,7 +109,7 @@ router_orport_seems_reachable(
return false; return false;
} }
} }
if (checking_ipv6) { if (checking_ipv6 && !ipv6_assume_reachable) {
if (have_orport_for_family(AF_INET6) && !can_reach_or_port_ipv6) { if (have_orport_for_family(AF_INET6) && !can_reach_or_port_ipv6) {
return false; return false;
} }
@ -409,7 +413,7 @@ ready_to_publish(const or_options_t *options)
{ {
return options->PublishServerDescriptor_ != NO_DIRINFO && return options->PublishServerDescriptor_ != NO_DIRINFO &&
router_dirport_seems_reachable(options) && router_dirport_seems_reachable(options) &&
router_should_skip_orport_reachability_check(options); router_all_orports_seem_reachable(options);
} }
/** Annotate that we found our ORPort reachable with a given address /** Annotate that we found our ORPort reachable with a given address

View File

@ -15,7 +15,7 @@
#ifdef HAVE_MODULE_RELAY #ifdef HAVE_MODULE_RELAY
struct or_options_t; struct or_options_t;
#define router_should_skip_orport_reachability_check(opts) \ #define router_all_orports_seem_reachable(opts) \
router_orport_seems_reachable((opts),0) router_orport_seems_reachable((opts),0)
int router_orport_seems_reachable( int router_orport_seems_reachable(
const struct or_options_t *options, const struct or_options_t *options,
@ -34,7 +34,7 @@ void router_reset_reachability(void);
#else /* !defined(HAVE_MODULE_RELAY) */ #else /* !defined(HAVE_MODULE_RELAY) */
#define router_should_skip_orport_reachability_check(opts) \ #define router_all_orports_seem_reachable(opts) \
((void)(opts), 0) ((void)(opts), 0)
#define router_orport_seems_reachable(opts, fam) \ #define router_orport_seems_reachable(opts, fam) \
((void)(opts), (void)(fam), 0) ((void)(opts), (void)(fam), 0)

View File

@ -270,7 +270,7 @@ rep_hist_circbuilding_dormant(time_t now)
/* see if we'll still need to build testing circuits */ /* see if we'll still need to build testing circuits */
if (server_mode(options) && if (server_mode(options) &&
(!router_should_skip_orport_reachability_check(options) || (!router_all_orports_seem_reachable(options) ||
!circuit_enough_testing_circs())) !circuit_enough_testing_circs()))
return 0; return 0;
if (!router_dirport_seems_reachable(options)) if (!router_dirport_seems_reachable(options))