diff options
author | Nick Mathewson <nickm@torproject.org> | 2020-11-17 07:58:37 -0500 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2020-11-17 07:58:37 -0500 |
commit | b13f32ee97e9a10e578c6f01775a1e2449b28693 (patch) | |
tree | d3759bd891c0b209f3baf926b14f3ea76dc9a66d /src/feature/relay | |
parent | 41bea71adc0d92b745cbedd454556cbdb52a4046 (diff) | |
parent | 9aaac94cc3d2b4768bbac1e40396b74373f7bc5a (diff) | |
download | tor-b13f32ee97e9a10e578c6f01775a1e2449b28693.tar.gz tor-b13f32ee97e9a10e578c6f01775a1e2449b28693.zip |
Merge branch 'ticket40071_045_01_squashed' into master
Diffstat (limited to 'src/feature/relay')
-rw-r--r-- | src/feature/relay/relay_find_addr.c | 68 | ||||
-rw-r--r-- | src/feature/relay/relay_find_addr.h | 2 | ||||
-rw-r--r-- | src/feature/relay/router.c | 21 |
3 files changed, 88 insertions, 3 deletions
diff --git a/src/feature/relay/relay_find_addr.c b/src/feature/relay/relay_find_addr.c index 43b958d563..9c2c8b281c 100644 --- a/src/feature/relay/relay_find_addr.c +++ b/src/feature/relay/relay_find_addr.c @@ -12,10 +12,16 @@ #include "app/config/resolve_addr.h" #include "core/mainloop/mainloop.h" +#include "core/or/circuitlist.h" +#include "core/or/circuituse.h" +#include "core/or/extendinfo.h" #include "feature/control/control_events.h" #include "feature/dircommon/dir_connection_st.h" #include "feature/nodelist/dirlist.h" +#include "feature/nodelist/node_select.h" +#include "feature/nodelist/nodelist.h" +#include "feature/nodelist/routerstatus_st.h" #include "feature/relay/relay_find_addr.h" #include "feature/relay/router.h" #include "feature/relay/routermode.h" @@ -151,3 +157,65 @@ relay_has_address_set(int family) return relay_find_addr_to_publish(get_options(), family, RELAY_FIND_ADDR_CACHE_ONLY, &addr); } + +/** How often should we launch a circuit to an authority to be sure of getting + * a guess for our IP? */ +#define DUMMY_DOWNLOAD_INTERVAL (20*60) + +void +relay_addr_learn_from_dirauth(void) +{ + static time_t last_dummy_circuit = 0; + const or_options_t *options = get_options(); + time_t now = time(NULL); + bool have_addr; + tor_addr_t addr_out; + + /* This dummy circuit only matter for relays. */ + if (BUG(!server_mode(options))) { + return; + } + + /* 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 + * need a lookup. In case we don't have one, we might want to attempt a + * dummy circuit to learn our address as a suggestion from an authority. */ + have_addr = relay_find_addr_to_publish(options, AF_INET, + RELAY_FIND_ADDR_CACHE_ONLY, + &addr_out); + + /* If we're a relay or bridge for which we were unable to discover our + * public address, we rely on learning our address from a directory + * authority from the NETINFO cell. */ + if (!have_addr && last_dummy_circuit + DUMMY_DOWNLOAD_INTERVAL < now) { + last_dummy_circuit = now; + + const routerstatus_t *rs = router_pick_trusteddirserver(V3_DIRINFO, 0); + if (BUG(!rs)) { + /* We should really always have trusted directories configured at this + * stage. They are loaded early either from default list or the one + * given in the configuration file. */ + return; + } + const node_t *node = node_get_by_id(rs->identity_digest); + if (BUG(!node)) { + /* 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); + } +} diff --git a/src/feature/relay/relay_find_addr.h b/src/feature/relay/relay_find_addr.h index 3d30946b05..34890cd34e 100644 --- a/src/feature/relay/relay_find_addr.h +++ b/src/feature/relay/relay_find_addr.h @@ -24,6 +24,8 @@ MOCK_DECL(bool, relay_find_addr_to_publish, bool relay_has_address_set(int family); +void relay_addr_learn_from_dirauth(void); + #ifdef RELAY_FIND_ADDR_PRIVATE #endif /* RELAY_FIND_ADDR_PRIVATE */ diff --git a/src/feature/relay/router.c b/src/feature/relay/router.c index 29103ed6c6..3aa9561f4f 100644 --- a/src/feature/relay/router.c +++ b/src/feature/relay/router.c @@ -2071,7 +2071,9 @@ router_build_fresh_unsigned_routerinfo,(routerinfo_t **ri_out)) /* Tor requires a relay to have an IPv4 so bail if we can't find it. */ if (!have_v4) { - log_warn(LD_CONFIG, "Don't know my address while generating descriptor"); + log_info(LD_CONFIG, "Don't know my address while generating descriptor. " + "Launching circuit to authority to learn it."); + relay_addr_learn_from_dirauth(); result = TOR_ROUTERINFO_ERROR_NO_EXT_ADDR; goto err; } @@ -2679,8 +2681,21 @@ check_descriptor_ipaddress_changed(time_t now) /* Ignore returned value because we want to notice not only an address * change but also if an address is lost (current == UNSPEC). */ - find_my_address(get_options(), family, LOG_INFO, ¤t, &method, - &hostname); + bool found = find_my_address(get_options(), family, LOG_INFO, ¤t, + &method, &hostname); + if (!found) { + /* Address was possibly not found because it is simply not configured or + * discoverable. Fallback to our cache, which includes any suggestion + * sent by a trusted directory server. */ + found = relay_find_addr_to_publish(get_options(), family, + RELAY_FIND_ADDR_CACHE_ONLY, + ¤t); + } + + /* The "current" address might be UNSPEC meaning it was not discovered nor + * found in our current cache. If we had an address before and we have + * none now, we consider this an IP change since it appears the relay lost + * its address. */ if (!tor_addr_eq(previous, ¤t)) { char *source; |