relay: Publish IPv4 descriptor on guessed IPv6 reachability failure

On an IPv6 reachability failure test, if the address was configured, don't
publish the descriptor and log warn. If the address was auto discovered, still
publish the descriptor.

Closes #33247.

Signed-off-by: David Goulet <dgoulet@torproject.org>
This commit is contained in:
David Goulet 2020-07-24 09:11:16 -04:00
parent fda0fa02bf
commit ad9806b539
4 changed files with 66 additions and 10 deletions

View File

@ -12,6 +12,8 @@
#include "orconfig.h"
#include "core/or/or.h"
#include "app/config/resolve_addr.h"
#include "core/mainloop/periodic.h"
#include "core/mainloop/cpuworker.h" // XXXX use a pubsub event.
#include "core/mainloop/mainloop.h"
@ -218,14 +220,31 @@ reachability_warnings_callback(time_t now, const or_options_t *options)
tor_asprintf(&where6, "[%s]:%d", address6, me->ipv6_orport);
const char *opt_and = (!v4_ok && !v6_ok) ? "and" : "";
log_warn(LD_CONFIG,
"Your server has not managed to confirm reachability for "
"its ORPort(s) at %s%s%s. Relays do not publish descriptors "
"until their ORPort and DirPort are reachable. Please check "
"your firewalls, ports, address, /etc/hosts file, etc.",
where4?where4:"",
opt_and,
where6?where6:"");
/* IPv4 reachability test worked but not the IPv6. We will _not_
* publish the descriptor if our IPv6 was configured. We will if it
* was auto discovered. */
if (v4_ok && !v6_ok && !resolved_addr_is_configured(AF_INET6)) {
static ratelim_t rlim = RATELIM_INIT(3600);
log_fn_ratelim(&rlim, LOG_NOTICE, LD_CONFIG,
"Auto-discovered IPv6 address %s has not been found "
"reachable. However, IPv4 address is reachable. "
"Publishing server descriptor without IPv6 address.",
where6 ? where6 : "");
/* Indicate we want to publish even if reachability test failed. */
mark_my_descriptor_if_omit_ipv6_changes("IPv4 is reachable. "
"IPv6 is not but was "
"auto-discovered", true);
} else {
log_warn(LD_CONFIG,
"Your server has not managed to confirm reachability for "
"its ORPort(s) at %s%s%s. Relays do not publish "
"descriptors until their ORPort and DirPort are "
"reachable. Please check your firewalls, ports, address, "
"/etc/hosts file, etc.",
where4?where4:"",
opt_and,
where6?where6:"");
}
tor_free(where4);
tor_free(where6);
if (!v4_ok) {

View File

@ -2442,6 +2442,34 @@ router_new_consensus_params(const networkstatus_t *ns)
publish_even_when_ipv6_orport_unreachable = ar || ar6;
}
/** Indicate if the IPv6 address should be omitted from the descriptor when
* publishing it. This can happen if the IPv4 is reachable but the
* auto-discovered IPv6 is not. We still publish the descriptor.
*
* Only relays should look at this and only for their descriptor.
*
* XXX: The real harder fix is to never put in the routerinfo_t a non
* reachable address and instead use the last resolved address cache to do
* reachability test or anything that has to do with what address tor thinks
* it has. */
static bool omit_ipv6_on_publish = false;
/** Mark our descriptor out of data iff the IPv6 omit status flag is flipped
* it changes from its previous value.
*
* This is used when our IPv6 port is found reachable or not. */
void
mark_my_descriptor_if_omit_ipv6_changes(const char *reason, bool omit_ipv6)
{
bool previous = omit_ipv6_on_publish;
omit_ipv6_on_publish = omit_ipv6;
/* Only mark it dirty if the IPv6 omit flag was flipped. */
if (previous != omit_ipv6) {
mark_my_descriptor_dirty(reason);
}
}
/** 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)
@ -2847,7 +2875,7 @@ router_dump_router_to_string(routerinfo_t *router,
}
}
if (router->ipv6_orport &&
if (!omit_ipv6_on_publish && router->ipv6_orport &&
tor_addr_family(&router->ipv6_addr) == AF_INET6) {
char addr[TOR_ADDR_BUF_LEN];
const char *a;

View File

@ -84,6 +84,8 @@ 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);
void mark_my_descriptor_if_omit_ipv6_changes(const char *reason,
bool omit_ipv6);
void check_descriptor_bandwidth_changed(time_t now);
void check_descriptor_ipaddress_changed(time_t now);
int router_has_bandwidth_to_be_dirserver(const or_options_t *options);

View File

@ -398,6 +398,7 @@ router_orport_found_reachable(int family)
{
const routerinfo_t *me = router_get_my_routerinfo();
const or_options_t *options = get_options();
const char *reachable_reason = "ORPort found reachable";
bool *can_reach_ptr;
if (family == AF_INET) {
can_reach_ptr = &can_reach_or_port_ipv4;
@ -422,7 +423,13 @@ router_orport_found_reachable(int family)
ready_to_publish(options) ?
" Publishing server descriptor." : "");
mark_my_descriptor_dirty("ORPort found reachable");
/* Make sure our descriptor is marked to publish the IPv6 if it is now
* reachable. This can change at runtime. */
if (family == AF_INET6) {
mark_my_descriptor_if_omit_ipv6_changes(reachable_reason, false);
} else {
mark_my_descriptor_dirty(reachable_reason);
}
/* This is a significant enough change to upload immediately,
* at least in a test network */
if (options->TestingTorNetwork == 1) {