aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2020-06-26 08:34:56 -0400
committerNick Mathewson <nickm@torproject.org>2020-06-26 08:34:56 -0400
commitdbc2b75009a781f2664b871a6033d47b04946299 (patch)
tree0f9e01d158bb54534233dd2e0792175a057592df
parent40922629fe92a947ef3d84e71826a5030884cf08 (diff)
parentcb25f5772441e6caed4ae8b84300f32de078fe62 (diff)
downloadtor-dbc2b75009a781f2664b871a6033d47b04946299.tar.gz
tor-dbc2b75009a781f2664b871a6033d47b04946299.zip
Merge branch 'assume_reachable_revamp'
-rw-r--r--changes/ticket332243
-rw-r--r--changes/ticket340645
-rw-r--r--doc/tor.1.txt7
-rw-r--r--src/app/config/config.c5
-rw-r--r--src/app/config/or_options_st.h9
-rw-r--r--src/core/or/channelpadding.c2
-rw-r--r--src/core/or/channelpadding.h3
-rw-r--r--src/core/or/circuitbuild.c2
-rw-r--r--src/core/or/circuitstats.c4
-rw-r--r--src/core/or/circuitstats.h2
-rw-r--r--src/core/or/circuituse.c4
-rw-r--r--src/feature/control/control_getinfo.c4
-rw-r--r--src/feature/nodelist/networkstatus.c51
-rw-r--r--src/feature/nodelist/nodelist.c4
-rw-r--r--src/feature/nodelist/nodelist.h4
-rw-r--r--src/feature/relay/router.c43
-rw-r--r--src/feature/relay/router.h1
-rw-r--r--src/feature/relay/selftest.c14
-rw-r--r--src/feature/relay/selftest.h4
-rw-r--r--src/feature/stats/predict_ports.c2
20 files changed, 123 insertions, 50 deletions
diff --git a/changes/ticket33224 b/changes/ticket33224
new file mode 100644
index 0000000000..3fdab7dc53
--- /dev/null
+++ b/changes/ticket33224
@@ -0,0 +1,3 @@
+ o Minor features (relay, IPv6):
+ - Add an AssumeReachableIPv6 option to disable self-checking IPv6
+ reachability. Closes part of ticket 33224.
diff --git a/changes/ticket34064 b/changes/ticket34064
new file mode 100644
index 0000000000..13ed70c8f6
--- /dev/null
+++ b/changes/ticket34064
@@ -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.
diff --git a/doc/tor.1.txt b/doc/tor.1.txt
index a7b3a67879..327925b020 100644
--- a/doc/tor.1.txt
+++ b/doc/tor.1.txt
@@ -2145,7 +2145,12 @@ is non-zero):
don't do self-reachability testing; just upload your server descriptor
immediately. If **AuthoritativeDirectory** is also set, this option
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**::
Sets the relay to act as a "bridge" with respect to relaying connections
diff --git a/src/app/config/config.c b/src/app/config/config.c
index 0048c96f49..9d852e5408 100644
--- a/src/app/config/config.c
+++ b/src/app/config/config.c
@@ -323,6 +323,7 @@ static const config_var_t option_vars_[] = {
V(AlternateDirAuthority, LINELIST, NULL),
OBSOLETE("AlternateHSAuthority"),
V(AssumeReachable, BOOL, "0"),
+ V(AssumeReachableIPv6, AUTOBOOL, "auto"),
OBSOLETE("AuthDirBadDir"),
OBSOLETE("AuthDirBadDirCCs"),
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.");
}
+ if (options->AssumeReachable && options->AssumeReachableIPv6 == 0) {
+ REJECT("Cannot set AssumeReachable 1 and AssumeReachableIPv6 0.");
+ }
+
if (options->ExcludeExitNodes || options->ExcludeNodes) {
options->ExcludeExitNodesUnion_ = routerset_new();
routerset_union(options->ExcludeExitNodesUnion_,options->ExcludeExitNodes);
diff --git a/src/app/config/or_options_st.h b/src/app/config/or_options_st.h
index 2f375f5d9b..07126cc6ce 100644
--- a/src/app/config/or_options_st.h
+++ b/src/app/config/or_options_st.h
@@ -195,7 +195,14 @@ struct or_options_t {
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 V3AuthoritativeDir; /**< Boolean: is this an authoritative directory
* for version 3 directories? */
diff --git a/src/core/or/channelpadding.c b/src/core/or/channelpadding.c
index be2ce78a17..c754a58c42 100644
--- a/src/core/or/channelpadding.c
+++ b/src/core/or/channelpadding.c
@@ -90,7 +90,7 @@ static int consensus_nf_pad_single_onion;
* for every single connection, every second.
*/
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_HIGH 9500
diff --git a/src/core/or/channelpadding.h b/src/core/or/channelpadding.h
index d1c7192ffd..9246988cdc 100644
--- a/src/core/or/channelpadding.h
+++ b/src/core/or/channelpadding.h
@@ -37,7 +37,6 @@ int channelpadding_send_enable_command(channel_t *chan, uint16_t low_timeout,
int channelpadding_get_circuits_available_timeout(void);
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) */
-
diff --git a/src/core/or/circuitbuild.c b/src/core/or/circuitbuild.c
index be8ec6f3cb..652d85b1c1 100644
--- a/src/core/or/circuitbuild.c
+++ b/src/core/or/circuitbuild.c
@@ -1055,7 +1055,7 @@ circuit_build_no_more_hops(origin_circuit_t *circ)
control_event_client_status(LOG_NOTICE, "CIRCUIT_ESTABLISHED");
clear_broken_connection_map(1);
if (server_mode(options) &&
- !router_should_skip_orport_reachability_check(options)) {
+ !router_all_orports_seem_reachable(options)) {
inform_testing_reachability();
router_do_reachability_checks(1, 1);
}
diff --git a/src/core/or/circuitstats.c b/src/core/or/circuitstats.c
index 6a9d84df99..bc6c263798 100644
--- a/src/core/or/circuitstats.c
+++ b/src/core/or/circuitstats.c
@@ -399,7 +399,7 @@ circuit_build_times_initial_timeout(void)
* and learn a new timeout.
*/
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;
num = networkstatus_get_param(ns, "cbtrecentcount",
@@ -425,7 +425,7 @@ circuit_build_times_recent_circuit_count(networkstatus_t *ns)
*/
void
circuit_build_times_new_consensus_params(circuit_build_times_t *cbt,
- networkstatus_t *ns)
+ const networkstatus_t *ns)
{
int32_t num;
diff --git a/src/core/or/circuitstats.h b/src/core/or/circuitstats.h
index 317eeac202..930e0a9ba3 100644
--- a/src/core/or/circuitstats.h
+++ b/src/core/or/circuitstats.h
@@ -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_free_timeouts(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_close_rate(const circuit_build_times_t *cbt);
diff --git a/src/core/or/circuituse.c b/src/core/or/circuituse.c
index 7358817531..f4cd4ced43 100644
--- a/src/core/or/circuituse.c
+++ b/src/core/or/circuituse.c
@@ -1642,7 +1642,7 @@ static void
circuit_testing_opened(origin_circuit_t *circ)
{
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,
* 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
@@ -1661,7 +1661,7 @@ circuit_testing_failed(origin_circuit_t *circ, int at_last_hop)
{
const or_options_t *options = get_options();
if (server_mode(options) &&
- router_should_skip_orport_reachability_check(options))
+ router_all_orports_seem_reachable(options))
return;
log_info(LD_GENERAL,
diff --git a/src/feature/control/control_getinfo.c b/src/feature/control/control_getinfo.c
index 8d6c314b43..47e0224a90 100644
--- a/src/feature/control/control_getinfo.c
+++ b/src/feature/control/control_getinfo.c
@@ -1279,7 +1279,7 @@ getinfo_helper_events(control_connection_t *control_conn,
? "1" : "0");
} else if (!strcmp(question, "status/reachability-succeeded/or")) {
*answer = tor_strdup(
- router_should_skip_orport_reachability_check(options) ?
+ router_all_orports_seem_reachable(options) ?
"1" : "0");
} else if (!strcmp(question, "status/reachability-succeeded/dir")) {
*answer = tor_strdup(
@@ -1288,7 +1288,7 @@ getinfo_helper_events(control_connection_t *control_conn,
} else if (!strcmp(question, "status/reachability-succeeded")) {
tor_asprintf(
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);
} else if (!strcmp(question, "status/bootstrap-phase")) {
*answer = control_event_boot_last_msg();
diff --git a/src/feature/nodelist/networkstatus.c b/src/feature/nodelist/networkstatus.c
index e07d58c91c..f63d598ef7 100644
--- a/src/feature/nodelist/networkstatus.c
+++ b/src/feature/nodelist/networkstatus.c
@@ -1670,7 +1670,35 @@ notify_before_networkstatus_changes(const networkstatus_t *old_c,
static 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();
+
+ /* 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)
@@ -2115,29 +2143,6 @@ networkstatus_set_current_consensus(const char *consensus,
/* Notify that we just changed the consensus so the current global value
* can be looked at. */
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. */
diff --git a/src/feature/nodelist/nodelist.c b/src/feature/nodelist/nodelist.c
index 6b2c0d2016..dd6c65661a 100644
--- a/src/feature/nodelist/nodelist.c
+++ b/src/feature/nodelist/nodelist.c
@@ -621,7 +621,7 @@ get_estimated_address_per_node, (void))
* and grab microdescriptors into nodes as appropriate.
*/
void
-nodelist_set_consensus(networkstatus_t *ns)
+nodelist_set_consensus(const networkstatus_t *ns)
{
const or_options_t *options = get_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.
* If that's not the case, make it so. */
void
-nodelist_ensure_freshness(networkstatus_t *ns)
+nodelist_ensure_freshness(const networkstatus_t *ns)
{
tor_assert(ns);
diff --git a/src/feature/nodelist/nodelist.h b/src/feature/nodelist/nodelist.h
index 4ba699d69d..826d1b957a 100644
--- a/src/feature/nodelist/nodelist.h
+++ b/src/feature/nodelist/nodelist.h
@@ -32,8 +32,8 @@ const node_t *node_get_by_hex_id(const char *identity_digest,
unsigned flags);
node_t *nodelist_set_routerinfo(routerinfo_t *ri, routerinfo_t **ri_old_out);
node_t *nodelist_add_microdesc(microdesc_t *md);
-void nodelist_set_consensus(networkstatus_t *ns);
-void nodelist_ensure_freshness(networkstatus_t *ns);
+void nodelist_set_consensus(const networkstatus_t *ns);
+void nodelist_ensure_freshness(const networkstatus_t *ns);
int nodelist_probably_contains_address(const tor_addr_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);
diff --git a/src/feature/relay/router.c b/src/feature/relay/router.c
index dfe9c9a823..5e00e4cb32 100644
--- a/src/feature/relay/router.c
+++ b/src/feature/relay/router.c
@@ -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:
* - We don't have the ClientOnly option set
* and
@@ -1377,8 +1388,18 @@ decide_if_publishable_server(void)
return 1;
if (!router_get_advertised_or_port(options))
return 0;
- if (!router_should_skip_orport_reachability_check(options))
- return 0;
+ if (!router_orport_seems_reachable(options, AF_INET)) {
+ // 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) {
/* All set: there are no exits in the consensus (maybe this is a tiny
* test network), so we can't check our DirPort reachability. */
@@ -2402,6 +2423,24 @@ router_rebuild_descriptor(int force)
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
* because something changed, we force an immediate regenerate-and-upload. */
#define FORCE_REGENERATE_DESCRIPTOR_INTERVAL (18*60*60)
diff --git a/src/feature/relay/router.h b/src/feature/relay/router.h
index b7d99a1016..fab109be7c 100644
--- a/src/feature/relay/router.h
+++ b/src/feature/relay/router.h
@@ -81,6 +81,7 @@ int router_should_advertise_dirport(const or_options_t *options,
void consider_publishable_server(int force);
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 mark_my_descriptor_dirty_if_too_old(time_t now);
void mark_my_descriptor_dirty(const char *reason);
diff --git a/src/feature/relay/selftest.c b/src/feature/relay/selftest.c
index 589e9a303f..5602ac1d47 100644
--- a/src/feature/relay/selftest.c
+++ b/src/feature/relay/selftest.c
@@ -86,9 +86,8 @@ router_reachability_checks_disabled(const or_options_t *options)
* orport checks.
*/
int
-router_orport_seems_reachable(
- const or_options_t *options,
- int family)
+router_orport_seems_reachable(const or_options_t *options,
+ int family)
{
tor_assert_nonfatal(family == AF_INET || family == AF_INET6 || family == 0);
int reach_checks_disabled = router_reachability_checks_disabled(options);
@@ -96,6 +95,11 @@ router_orport_seems_reachable(
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?
const bool checking_ipv4 = (family == AF_INET || family == 0);
const bool checking_ipv6 = (family == AF_INET6 || family == 0);
@@ -105,7 +109,7 @@ router_orport_seems_reachable(
return false;
}
}
- if (checking_ipv6) {
+ if (checking_ipv6 && !ipv6_assume_reachable) {
if (have_orport_for_family(AF_INET6) && !can_reach_or_port_ipv6) {
return false;
}
@@ -409,7 +413,7 @@ ready_to_publish(const or_options_t *options)
{
return options->PublishServerDescriptor_ != NO_DIRINFO &&
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
diff --git a/src/feature/relay/selftest.h b/src/feature/relay/selftest.h
index 9b7005db39..911d8bdc3f 100644
--- a/src/feature/relay/selftest.h
+++ b/src/feature/relay/selftest.h
@@ -15,7 +15,7 @@
#ifdef HAVE_MODULE_RELAY
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)
int router_orport_seems_reachable(
const struct or_options_t *options,
@@ -34,7 +34,7 @@ void router_reset_reachability(void);
#else /* !defined(HAVE_MODULE_RELAY) */
-#define router_should_skip_orport_reachability_check(opts) \
+#define router_all_orports_seem_reachable(opts) \
((void)(opts), 0)
#define router_orport_seems_reachable(opts, fam) \
((void)(opts), (void)(fam), 0)
diff --git a/src/feature/stats/predict_ports.c b/src/feature/stats/predict_ports.c
index 37f7f4c583..57463952e7 100644
--- a/src/feature/stats/predict_ports.c
+++ b/src/feature/stats/predict_ports.c
@@ -270,7 +270,7 @@ rep_hist_circbuilding_dormant(time_t now)
/* see if we'll still need to build testing circuits */
if (server_mode(options) &&
- (!router_should_skip_orport_reachability_check(options) ||
+ (!router_all_orports_seem_reachable(options) ||
!circuit_enough_testing_circs()))
return 0;
if (!router_dirport_seems_reachable(options))