relay: Use testing circuit instead of dummy descriptor fetch

Tor now can learn its address from a NETINFO cell coming from an authority.
Thus, instead from launching a dummy descriptor fetch to learn the address
from the directory response (unauthenticated), we simply now launch a one-hop
testing circuit.

Related to #40071

Signed-off-by: David Goulet <dgoulet@torproject.org>
This commit is contained in:
David Goulet 2020-09-18 11:50:12 -04:00 committed by Nick Mathewson
parent 46ccde66a9
commit 4b98140733
2 changed files with 46 additions and 27 deletions

View File

@ -114,7 +114,9 @@
#define CIRCUIT_PURPOSE_S_HSDIR_POST 20 #define CIRCUIT_PURPOSE_S_HSDIR_POST 20
#define CIRCUIT_PURPOSE_S_HS_MAX_ 20 #define CIRCUIT_PURPOSE_S_HS_MAX_ 20
/** A testing circuit; not meant to be used for actual traffic. */ /** A testing circuit; not meant to be used for actual traffic. It is used for
* bandwidth measurement, reachability test and address discovery from an
* authority using the NETINFO cell. */
#define CIRCUIT_PURPOSE_TESTING 21 #define CIRCUIT_PURPOSE_TESTING 21
/** A controller made this circuit and Tor should not use it. */ /** A controller made this circuit and Tor should not use it. */
#define CIRCUIT_PURPOSE_CONTROLLER 22 #define CIRCUIT_PURPOSE_CONTROLLER 22

View File

@ -65,6 +65,9 @@
#include "app/config/config.h" #include "app/config/config.h"
#include "core/mainloop/connection.h" #include "core/mainloop/connection.h"
#include "core/mainloop/mainloop.h" #include "core/mainloop/mainloop.h"
#include "core/or/circuitlist.h"
#include "core/or/circuituse.h"
#include "core/or/extendinfo.h"
#include "core/or/policies.h" #include "core/or/policies.h"
#include "feature/client/bridges.h" #include "feature/client/bridges.h"
#include "feature/control/control_events.h" #include "feature/control/control_events.h"
@ -137,7 +140,7 @@ static int signed_desc_digest_is_recognized(signed_descriptor_t *desc);
static const char *signed_descriptor_get_body_impl( static const char *signed_descriptor_get_body_impl(
const signed_descriptor_t *desc, const signed_descriptor_t *desc,
int with_annotations); int with_annotations);
static void launch_dummy_descriptor_download_as_needed(time_t now, static void launch_dummy_circuit_as_needed(time_t now,
const or_options_t *options); const or_options_t *options);
/****************************************************************************/ /****************************************************************************/
@ -2306,7 +2309,7 @@ update_all_descriptor_downloads(time_t now)
return; return;
update_router_descriptor_downloads(now); update_router_descriptor_downloads(now);
update_microdesc_downloads(now); update_microdesc_downloads(now);
launch_dummy_descriptor_download_as_needed(now, get_options()); launch_dummy_circuit_as_needed(now, get_options());
} }
/** Clear all our timeouts for fetching v3 directory stuff, and then /** Clear all our timeouts for fetching v3 directory stuff, and then
@ -2760,23 +2763,20 @@ update_consensus_router_descriptor_downloads(time_t now, int is_vote,
smartlist_free(no_longer_old); smartlist_free(no_longer_old);
} }
/** How often should we launch a server/authority request to be sure of getting /** How often should we launch a circuit to an authority to be sure of getting
* a guess for our IP? */ * a guess for our IP? */
/*XXXX+ this info should come from netinfo cells or something, or we should
* do this only when we aren't seeing incoming data. see bug 652. */
#define DUMMY_DOWNLOAD_INTERVAL (20*60) #define DUMMY_DOWNLOAD_INTERVAL (20*60)
/** As needed, launch a dummy router descriptor fetch to see if our /** As needed, launch a dummy router descriptor fetch to see if our
* address has changed. */ * address has changed. */
static void static void
launch_dummy_descriptor_download_as_needed(time_t now, launch_dummy_circuit_as_needed(time_t now, const or_options_t *options)
const or_options_t *options)
{ {
static time_t last_dummy_download = 0; static time_t last_dummy_circuit = 0;
bool have_addr; bool have_addr;
tor_addr_t addr_out; tor_addr_t addr_out;
/* This dummy fetch only matter for relays. */ /* This dummy circuit only matter for relays. */
if (!server_mode(options)) { if (!server_mode(options)) {
return; return;
} }
@ -2784,27 +2784,44 @@ launch_dummy_descriptor_download_as_needed(time_t now,
/* Lookup the address cache to learn if we have a good usable address. We /* Lookup the address cache to learn if we have a good usable address. We
* still force relays to have an IPv4 so that alone is enough to learn if we * still force relays to have an IPv4 so that alone is enough to learn if we
* need a lookup. In case we don't have one, we might want to attempt a * need a lookup. In case we don't have one, we might want to attempt a
* dummy fetch to learn our address as a suggestion from an authority. */ * dummy circuit to learn our address as a suggestion from an authority. */
have_addr = relay_find_addr_to_publish(options, AF_INET, have_addr = relay_find_addr_to_publish(options, AF_INET,
RELAY_FIND_ADDR_CACHE_ONLY, RELAY_FIND_ADDR_CACHE_ONLY,
&addr_out); &addr_out);
/* XXXX+ we could be smarter here; see notes on bug 652. */ /* If we're a relay or bridge for which we were unable to discover our
/* If we're a server that doesn't have an address, we rely on directory * public address, we rely on learning our address from a directory
* fetches to learn when our address changes. So if we haven't tried to get * authority from the NETINFO cell. */
* any routerdescs in a long time, try a dummy fetch now. */ if (!have_addr && last_dummy_circuit + DUMMY_DOWNLOAD_INTERVAL < now) {
if (!have_addr && last_dummy_circuit = now;
last_descriptor_download_attempted + DUMMY_DOWNLOAD_INTERVAL < now &&
last_dummy_download + DUMMY_DOWNLOAD_INTERVAL < now) { const routerstatus_t *rs = router_pick_trusteddirserver(V3_DIRINFO, 0);
last_dummy_download = now; if (BUG(!rs)) {
/* XX/teor - do we want an authority here, because they are less likely /* We should really always have trusted directories configured at this
* to give us the wrong address? (See #17782) * stage. They are loaded early either from default list or the one
* I'm leaving the previous behaviour intact, because I don't like * given in the configuration file. */
* the idea of some relays contacting an authority every 20 minutes. */ return;
directory_get_from_dirserver(DIR_PURPOSE_FETCH_SERVERDESC, }
ROUTER_PURPOSE_GENERAL, "authority.z", const node_t *node = node_get_by_id(rs->identity_digest);
PDS_RETRY_IF_NO_SERVERS, if (BUG(!node)) {
DL_WANT_ANY_DIRSERVER); /* If there is a routerstatus_t, there is a node_t thus this should
* never fail. */
return;
}
extend_info_t *ei = extend_info_from_node(node, 1);
if (BUG(!ei)) {
return;
}
log_debug(LD_GENERAL, "Attempting dummy testing circuit to an authority "
"in order to learn our address.");
/* Launch a one-hop testing circuit to a trusted authority so we can learn
* our address through the NETINFO cell. */
circuit_launch_by_extend_info(CIRCUIT_PURPOSE_TESTING, ei,
CIRCLAUNCH_IS_INTERNAL |
CIRCLAUNCH_ONEHOP_TUNNEL);
extend_info_free(ei);
} }
} }