LCOV - code coverage report
Current view: top level - feature/relay - relay_find_addr.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 29 55 52.7 %
Date: 2021-11-24 03:28:48 Functions: 2 3 66.7 %

          Line data    Source code
       1             : /* Copyright (c) 2001-2021, The Tor Project, Inc. */
       2             : /* See LICENSE for licensing information */
       3             : 
       4             : /**
       5             :  * \file relay_find_addr.c
       6             :  * \brief Implement mechanism for a relay to find its address.
       7             :  **/
       8             : 
       9             : #include "core/or/or.h"
      10             : 
      11             : #include "app/config/config.h"
      12             : #include "app/config/resolve_addr.h"
      13             : 
      14             : #include "core/mainloop/mainloop.h"
      15             : #include "core/or/circuitlist.h"
      16             : #include "core/or/circuituse.h"
      17             : #include "core/or/extendinfo.h"
      18             : 
      19             : #include "feature/control/control_events.h"
      20             : #include "feature/dircommon/dir_connection_st.h"
      21             : #include "feature/nodelist/dirlist.h"
      22             : #include "feature/nodelist/node_select.h"
      23             : #include "feature/nodelist/nodelist.h"
      24             : #include "feature/nodelist/routerstatus_st.h"
      25             : #include "feature/relay/relay_find_addr.h"
      26             : #include "feature/relay/router.h"
      27             : #include "feature/relay/routermode.h"
      28             : 
      29             : /** Consider the address suggestion suggested_addr as a possible one to use as
      30             :  * our address.
      31             :  *
      32             :  * This is called when a valid NETINFO cell is received containing a candidate
      33             :  * for our address or when a directory sends us back the X-Your-Address-Is
      34             :  * header.
      35             :  *
      36             :  * The suggested address is ignored if it does NOT come from a trusted source.
      37             :  * At the moment, we only look a trusted directory authorities.
      38             :  *
      39             :  * The suggested address is ignored if it is internal or it is the same as the
      40             :  * given peer_addr which is the address from the endpoint that sent the
      41             :  * NETINFO cell.
      42             :  *
      43             :  * The identity_digest is NULL if this is an address suggested by a directory
      44             :  * since this is a plaintext connection.
      45             :  *
      46             :  * The suggested address is set in our suggested address cache if everything
      47             :  * passes. */
      48             : void
      49           8 : relay_address_new_suggestion(const tor_addr_t *suggested_addr,
      50             :                              const tor_addr_t *peer_addr,
      51             :                              const char *identity_digest)
      52             : {
      53           8 :   const or_options_t *options = get_options();
      54             : 
      55           8 :   tor_assert(suggested_addr);
      56           8 :   tor_assert(peer_addr);
      57             : 
      58             :   /* Non server should just ignore this suggestion. Clients don't need to
      59             :    * learn their address let alone cache it. */
      60           8 :   if (!server_mode(options)) {
      61             :     return;
      62             :   }
      63             : 
      64             :   /* Is the peer a trusted source? Ignore anything coming from non trusted
      65             :    * source. In this case, we only look at trusted directory authorities. */
      66           8 :   if (!router_addr_is_trusted_dir(peer_addr) ||
      67           6 :       (identity_digest && !router_digest_is_trusted_dir(identity_digest))) {
      68           2 :     return;
      69             :   }
      70             : 
      71             :   /* Ignore a suggestion that is an internal address or the same as the one
      72             :    * the peer address. */
      73           6 :   if (tor_addr_is_internal(suggested_addr, 0)) {
      74             :     /* Do not believe anyone who says our address is internal. */
      75             :     return;
      76             :   }
      77           4 :   if (tor_addr_eq(suggested_addr, peer_addr)) {
      78             :     /* Do not believe anyone who says our address is their address. */
      79           2 :     log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
      80             :            "A relay endpoint %s is telling us that their address is ours.",
      81             :            fmt_addr(peer_addr));
      82           2 :     return;
      83             :   }
      84             : 
      85             :   /* Save the suggestion in our cache. */
      86           2 :   resolved_addr_set_suggested(suggested_addr);
      87             : }
      88             : 
      89             : /** Find our address to be published in our descriptor. Three places are
      90             :  * looked at:
      91             :  *
      92             :  *    1. Resolved cache. Populated by find_my_address() during the relay
      93             :  *       periodic event that attempts to learn if our address has changed.
      94             :  *
      95             :  *    2. If flags is set with RELAY_FIND_ADDR_CACHE_ONLY, only the resolved
      96             :  *       and suggested cache are looked at. No address discovery will be done.
      97             :  *
      98             :  *    3. Finally, if all fails, use the suggested address cache which is
      99             :  *       populated by the NETINFO cell content or HTTP header from a
     100             :  *       directory.
     101             :  *
     102             :  * The AddressDisableIPv6 is checked here for IPv6 address discovery and if
     103             :  * set, false is returned and addr_out is UNSPEC.
     104             :  *
     105             :  * Before doing any discovery, the configuration is checked for an ORPort of
     106             :  * the given family. If none can be found, false is returned and addr_out is
     107             :  * UNSPEC.
     108             :  *
     109             :  * Return true on success and addr_out contains the address to use for the
     110             :  * given family. On failure to find the address, false is returned and
     111             :  * addr_out is set to an AF_UNSPEC address. */
     112           6 : MOCK_IMPL(bool,
     113             : relay_find_addr_to_publish, (const or_options_t *options, int family,
     114             :                              int flags, tor_addr_t *addr_out))
     115             : {
     116           6 :   tor_assert(options);
     117           6 :   tor_assert(addr_out);
     118             : 
     119           6 :   tor_addr_make_unspec(addr_out);
     120             : 
     121             :   /* If an IPv6 is requested, check if IPv6 address discovery is disabled on
     122             :    * this instance. If so, we return a failure. It is done here so we don't
     123             :    * query the suggested cache that might be populated with an IPv6. */
     124           6 :   if (family == AF_INET6 && options->AddressDisableIPv6) {
     125             :     return false;
     126             :   }
     127             : 
     128             :   /* There is no point on attempting an address discovery to publish if we
     129             :    * don't have an ORPort for this family. */
     130           6 :   if (!routerconf_find_or_port(options, family)) {
     131             :     return false;
     132             :   }
     133             : 
     134             :   /* First, check our resolved address cache. It should contain the address
     135             :    * we've discovered from the periodic relay event. */
     136           6 :   resolved_addr_get_last(family, addr_out);
     137           6 :   if (!tor_addr_is_null(addr_out)) {
     138           2 :     goto found;
     139             :   }
     140             : 
     141             :   /* Second, attempt to find our address. The following can do a DNS resolve
     142             :    * thus only do it when the no cache only flag is flipped. */
     143           4 :   if (!(flags & RELAY_FIND_ADDR_CACHE_ONLY)) {
     144           0 :     if (find_my_address(options, family, LOG_INFO, addr_out, NULL, NULL)) {
     145           0 :       goto found;
     146             :     }
     147             :   }
     148             : 
     149             :   /* Third, consider address from our suggestion cache. */
     150           4 :   resolved_addr_get_suggested(family, addr_out);
     151           4 :   if (!tor_addr_is_null(addr_out)) {
     152           2 :     goto found;
     153             :   }
     154             : 
     155             :   /* No publishable address was found even though we have an ORPort thus
     156             :    * print a notice log so operator can notice. We'll do that every hour so
     157             :    * it is not too spammy but enough so operators address the issue. */
     158           2 :   static ratelim_t rlim = RATELIM_INIT(3600);
     159           2 :   log_fn_ratelim(&rlim, LOG_NOTICE, LD_CONFIG,
     160             :                  "Unable to find %s address for ORPort %u. "
     161             :                  "You might want to specify %sOnly to it or set an "
     162             :                  "explicit address or set Address.",
     163             :                  fmt_af_family(family),
     164             :                  routerconf_find_or_port(options, family),
     165             :                  (family == AF_INET) ? fmt_af_family(AF_INET6) :
     166             :                                        fmt_af_family(AF_INET));
     167             : 
     168             :   /* Not found. */
     169           2 :   return false;
     170             : 
     171             :  found:
     172             :   return true;
     173             : }
     174             : 
     175             : /** How often should we launch a circuit to an authority to be sure of getting
     176             :  * a guess for our IP? */
     177             : #define DUMMY_DOWNLOAD_INTERVAL (20*60)
     178             : 
     179             : void
     180           0 : relay_addr_learn_from_dirauth(void)
     181             : {
     182           0 :   static time_t last_dummy_circuit = 0;
     183           0 :   const or_options_t *options = get_options();
     184           0 :   time_t now = time(NULL);
     185           0 :   bool have_addr;
     186           0 :   tor_addr_t addr_out;
     187             : 
     188             :   /* This dummy circuit only matter for relays. */
     189           0 :   if (BUG(!server_mode(options))) {
     190           0 :     return;
     191             :   }
     192             : 
     193             :   /* Lookup the address cache to learn if we have a good usable address. We
     194             :    * still force relays to have an IPv4 so that alone is enough to learn if we
     195             :    * need a lookup. In case we don't have one, we might want to attempt a
     196             :    * dummy circuit to learn our address as a suggestion from an authority. */
     197           0 :   have_addr = relay_find_addr_to_publish(options, AF_INET,
     198             :                                          RELAY_FIND_ADDR_CACHE_ONLY,
     199             :                                          &addr_out);
     200             : 
     201             :   /* If we're a relay or bridge for which we were unable to discover our
     202             :    * public address, we rely on learning our address from a directory
     203             :    * authority from the NETINFO cell. */
     204           0 :   if (!have_addr && last_dummy_circuit + DUMMY_DOWNLOAD_INTERVAL < now) {
     205           0 :     last_dummy_circuit = now;
     206             : 
     207           0 :     const routerstatus_t *rs = router_pick_trusteddirserver(V3_DIRINFO, 0);
     208           0 :     if (BUG(!rs)) {
     209             :       /* We should really always have trusted directories configured at this
     210             :        * stage. They are loaded early either from default list or the one
     211             :        * given in the configuration file. */
     212           0 :       return;
     213             :     }
     214           0 :     const node_t *node = node_get_by_id(rs->identity_digest);
     215           0 :     if (!node) {
     216             :       /* This can happen if we are still in the early starting stage where no
     217             :        * descriptors we actually fetched and thus we have the routerstatus_t
     218             :        * for the authority but not its descriptor which is needed to build a
     219             :        * circuit and thus learn our address. */
     220           0 :       log_info(LD_GENERAL, "Can't build a circuit to an authority. Unable to "
     221             :                            "learn for now our address from them.");
     222           0 :       return;
     223             :     }
     224           0 :     extend_info_t *ei = extend_info_from_node(node, 1);
     225           0 :     if (BUG(!ei)) {
     226           0 :       return;
     227             :     }
     228             : 
     229           0 :     log_debug(LD_GENERAL, "Attempting dummy testing circuit to an authority "
     230             :                           "in order to learn our address.");
     231             : 
     232             :     /* Launch a one-hop testing circuit to a trusted authority so we can learn
     233             :      * our address through the NETINFO cell. */
     234           0 :     circuit_launch_by_extend_info(CIRCUIT_PURPOSE_TESTING, ei,
     235             :                                   CIRCLAUNCH_IS_INTERNAL |
     236             :                                   CIRCLAUNCH_ONEHOP_TUNNEL);
     237           0 :     extend_info_free(ei);
     238             :   }
     239             : }

Generated by: LCOV version 1.14