LCOV - code coverage report
Current view: top level - feature/relay - selftest.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 0 133 0.0 %
Date: 2021-11-24 03:28:48 Functions: 0 13 0.0 %

          Line data    Source code
       1             : /* Copyright (c) 2001 Matej Pfajfar.
       2             :  * Copyright (c) 2001-2004, Roger Dingledine.
       3             :  * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
       4             :  * Copyright (c) 2007-2021, The Tor Project, Inc. */
       5             : /* See LICENSE for licensing information */
       6             : 
       7             : /**
       8             :  * \file selftest.c
       9             :  * \brief Relay self-testing
      10             :  *
      11             :  * Relays need to make sure that their own ports are reachable, and estimate
      12             :  * their own bandwidth, before publishing.
      13             :  */
      14             : 
      15             : #include "core/or/or.h"
      16             : 
      17             : #include "app/config/config.h"
      18             : 
      19             : #include "core/mainloop/connection.h"
      20             : #include "core/mainloop/mainloop.h"
      21             : #include "core/mainloop/netstatus.h"
      22             : 
      23             : #include "core/or/circuitbuild.h"
      24             : #include "core/or/circuitlist.h"
      25             : #include "core/or/circuituse.h"
      26             : #include "core/or/crypt_path_st.h"
      27             : #include "core/or/extendinfo.h"
      28             : #include "core/or/extend_info_st.h"
      29             : #include "core/or/origin_circuit_st.h"
      30             : #include "core/or/relay.h"
      31             : 
      32             : #include "feature/control/control_events.h"
      33             : 
      34             : #include "feature/dirauth/authmode.h"
      35             : 
      36             : #include "feature/dirclient/dirclient.h"
      37             : #include "feature/dircommon/directory.h"
      38             : 
      39             : #include "feature/nodelist/authority_cert_st.h"
      40             : #include "feature/nodelist/routerinfo.h"
      41             : #include "feature/nodelist/routerinfo_st.h"
      42             : #include "feature/nodelist/routerlist.h" // but...
      43             : #include "feature/nodelist/routerset.h"
      44             : #include "feature/nodelist/torcert.h"
      45             : 
      46             : #include "feature/relay/relay_periodic.h"
      47             : #include "feature/relay/router.h"
      48             : #include "feature/relay/selftest.h"
      49             : 
      50             : static bool have_orport_for_family(int family);
      51             : static void inform_testing_reachability(const tor_addr_t *addr,
      52             :                                         uint16_t port);
      53             : 
      54             : /** Whether we can reach our IPv4 ORPort from the outside. */
      55             : static bool can_reach_or_port_ipv4 = false;
      56             : /** Whether we can reach our IPv6 ORPort from the outside. */
      57             : static bool can_reach_or_port_ipv6 = false;
      58             : 
      59             : /** Has informed_testing_reachable logged a message about testing our IPv4
      60             :  * ORPort? */
      61             : static bool have_informed_testing_or_port_ipv4 = false;
      62             : /** Has informed_testing_reachable logged a message about testing our IPv6
      63             :  * ORPort? */
      64             : static bool have_informed_testing_or_port_ipv6 = false;
      65             : 
      66             : /** Forget what we have learned about our reachability status. */
      67             : void
      68           0 : router_reset_reachability(void)
      69             : {
      70           0 :   can_reach_or_port_ipv4 = can_reach_or_port_ipv6 = false;
      71           0 :   have_informed_testing_or_port_ipv4 =
      72           0 :     have_informed_testing_or_port_ipv6 = false;
      73           0 : }
      74             : 
      75             : /** Return 1 if we won't do reachability checks, because:
      76             :  *   - AssumeReachable is set, or
      77             :  *   - the network is disabled.
      78             :  * Otherwise, return 0.
      79             :  */
      80             : static int
      81           0 : router_reachability_checks_disabled(const or_options_t *options)
      82             : {
      83           0 :   return options->AssumeReachable ||
      84           0 :          net_is_disabled();
      85             : }
      86             : 
      87             : /** Return 0 if we need to do an ORPort reachability check, because:
      88             :  *   - no reachability check has been done yet, or
      89             :  *   - we've initiated reachability checks, but none have succeeded.
      90             :  *  Return 1 if we don't need to do an ORPort reachability check, because:
      91             :  *   - we've seen a successful reachability check, or
      92             :  *   - AssumeReachable is set, or
      93             :  *   - the network is disabled.
      94             : 
      95             :  * If `family'`is AF_INET or AF_INET6, return true only when we should skip
      96             :  * the given family's orport check (Because it's been checked, or because we
      97             :  * aren't checking it.)  If `family` is 0, return true if we can skip _all_
      98             :  * orport checks.
      99             :  */
     100             : int
     101           0 : router_orport_seems_reachable(const or_options_t *options,
     102             :                               int family)
     103             : {
     104           0 :   tor_assert_nonfatal(family == AF_INET || family == AF_INET6 || family == 0);
     105           0 :   int reach_checks_disabled = router_reachability_checks_disabled(options);
     106           0 :   if (reach_checks_disabled) {
     107             :     return true;
     108             :   }
     109             : 
     110             :   // Note that we do a == 1 here, not just a boolean check.  This value
     111             :   // is also an autobool, so CFG_AUTO does not mean that we should
     112             :   // assume IPv6 ports are reachable.
     113           0 :   const bool ipv6_assume_reachable = (options->AssumeReachableIPv6 == 1);
     114             : 
     115             :   // Which reachability flags should we look at?
     116           0 :   const bool checking_ipv4 = (family == AF_INET || family == 0);
     117           0 :   const bool checking_ipv6 = (family == AF_INET6 || family == 0);
     118             : 
     119           0 :   if (checking_ipv4) {
     120           0 :     if (have_orport_for_family(AF_INET) && !can_reach_or_port_ipv4) {
     121             :       return false;
     122             :     }
     123             :   }
     124           0 :   if (checking_ipv6 && !ipv6_assume_reachable) {
     125           0 :     if (have_orport_for_family(AF_INET6) && !can_reach_or_port_ipv6) {
     126           0 :       return false;
     127             :     }
     128             :   }
     129             : 
     130             :   return true;
     131             : }
     132             : 
     133             : /** Relay DirPorts are no longer used (though authorities are). In either case,
     134             :  * reachability self test is done anymore, since network re-entry towards an
     135             :  * authority DirPort is not allowed. Thus, consider it always reachable. */
     136             : int
     137           0 : router_dirport_seems_reachable(const or_options_t *options)
     138             : {
     139           0 :   (void) options;
     140           0 :   return 1;
     141             : }
     142             : 
     143             : /** See if we currently believe our ORPort to be unreachable. If so, return 1
     144             :  * else return 0. */
     145             : static int
     146           0 : router_should_check_reachability(void)
     147             : {
     148           0 :   const routerinfo_t *me = router_get_my_routerinfo();
     149           0 :   const or_options_t *options = get_options();
     150             : 
     151           0 :   if (!me)
     152             :     return 0;
     153             : 
     154             :   /* Doesn't check our IPv6 address, see #34065. */
     155           0 :   if (routerset_contains_router(options->ExcludeNodes, me, -1) &&
     156           0 :       options->StrictNodes) {
     157             :     /* If we've excluded ourself, and StrictNodes is set, we can't test
     158             :      * ourself. */
     159             : #define SELF_EXCLUDED_WARN_INTERVAL 3600
     160           0 :     static ratelim_t warning_limit=RATELIM_INIT(SELF_EXCLUDED_WARN_INTERVAL);
     161           0 :     log_fn_ratelim(&warning_limit, LOG_WARN, LD_CIRC,
     162             :                    "Can't perform self-tests for this relay: we have "
     163             :                    "listed ourself in ExcludeNodes, and StrictNodes is set. "
     164             :                    "We cannot learn whether we are usable, and will not "
     165             :                    "be able to advertise ourself.");
     166           0 :     return 0;
     167             :   }
     168             :   return 1;
     169             : }
     170             : 
     171             : /**
     172             :  * Return true if we have configured an ORPort for the given family that
     173             :  * we would like to advertise.
     174             :  *
     175             :  * Like other self-testing functions, this function looks at our most
     176             :  * recently built descriptor.
     177             :  **/
     178             : static bool
     179           0 : have_orport_for_family(int family)
     180             : {
     181           0 :   const routerinfo_t *me = router_get_my_routerinfo();
     182             : 
     183           0 :   if (!me)
     184             :     return false;
     185             : 
     186           0 :   tor_addr_port_t ap;
     187           0 :   if (router_get_orport(me, &ap, family) < 0) {
     188           0 :     return false;
     189             :   }
     190             :   return true;
     191             : }
     192             : 
     193             : /** Allocate and return a new extend_info_t that can be used to build
     194             :  * a circuit to or through the router <b>r</b>, using an address from
     195             :  * <b>family</b> (if available).
     196             :  *
     197             :  * Clients don't have routerinfos, so this function should only be called on a
     198             :  * server.
     199             :  *
     200             :  * If the requested address is not available, returns NULL. */
     201             : static extend_info_t *
     202           0 : extend_info_from_router(const routerinfo_t *r, int family)
     203             : {
     204           0 :   crypto_pk_t *rsa_pubkey;
     205           0 :   extend_info_t *info;
     206           0 :   tor_addr_port_t ap;
     207             : 
     208           0 :   if (BUG(!r)) {
     209           0 :     return NULL;
     210             :   }
     211             : 
     212             :   /* Relays always assume that the first hop is reachable. They ignore
     213             :    * ReachableAddresses. */
     214           0 :   tor_assert_nonfatal(router_or_conn_should_skip_reachable_address_check(
     215             :                                                            get_options(), 0));
     216             : 
     217           0 :   const ed25519_public_key_t *ed_id_key;
     218           0 :   if (r->cache_info.signing_key_cert)
     219           0 :     ed_id_key = &r->cache_info.signing_key_cert->signing_key;
     220             :   else
     221             :     ed_id_key = NULL;
     222             : 
     223           0 :   if (router_get_orport(r, &ap, family) < 0) {
     224             :     /* We don't have an ORPort for the requested family. */
     225             :     return NULL;
     226             :   }
     227           0 :   rsa_pubkey = router_get_rsa_onion_pkey(r->onion_pkey, r->onion_pkey_len);
     228           0 :   info = extend_info_new(r->nickname, r->cache_info.identity_digest,
     229             :                          ed_id_key,
     230           0 :                          rsa_pubkey, r->onion_curve25519_pkey,
     231           0 :                          &ap.addr, ap.port);
     232           0 :   crypto_pk_free(rsa_pubkey);
     233           0 :   return info;
     234             : }
     235             : 
     236             : /** Launch a self-testing circuit to one of our ORPorts, using an address from
     237             :  * <b>family</b> (if available). The circuit can be used to test reachability
     238             :  * or bandwidth. <b>me</b> is our own routerinfo.
     239             :  *
     240             :  * Logs an info-level status message. If <b>orport_reachable</b> is false,
     241             :  * call it a reachability circuit. Otherwise, call it a bandwidth circuit.
     242             :  *
     243             :  * See router_do_reachability_checks() for details. */
     244             : static void
     245           0 : router_do_orport_reachability_checks(const routerinfo_t *me,
     246             :                                      int family,
     247             :                                      int orport_reachable)
     248             : {
     249           0 :   extend_info_t *ei = extend_info_from_router(me, family);
     250           0 :   int ipv6_flags = (family == AF_INET6 ? CIRCLAUNCH_IS_IPV6_SELFTEST : 0);
     251             : 
     252             :   /* If we're trying to test IPv6, but we don't have an IPv6 ORPort, ei will
     253             :    * be NULL. */
     254           0 :   if (ei) {
     255           0 :     const char *family_name = fmt_af_family(family);
     256           0 :     const tor_addr_port_t *ap = extend_info_get_orport(ei, family);
     257           0 :     log_info(LD_CIRC, "Testing %s of my %s ORPort: %s.",
     258             :              !orport_reachable ? "reachability" : "bandwidth",
     259             :              family_name, fmt_addrport_ap(ap));
     260             : 
     261           0 :     if (!orport_reachable) {
     262             :       /* Only log if we are actually doing a reachability test to learn if our
     263             :        * ORPort is reachable. Else, this prints a log notice if we are simply
     264             :        * opening a bandwidth testing circuit even though we are reachable. */
     265           0 :       inform_testing_reachability(&ap->addr, ap->port);
     266             :     }
     267             : 
     268           0 :     circuit_launch_by_extend_info(CIRCUIT_PURPOSE_TESTING, ei,
     269             :                                   CIRCLAUNCH_NEED_CAPACITY|
     270             :                                   CIRCLAUNCH_IS_INTERNAL|
     271             :                                   ipv6_flags);
     272           0 :     extend_info_free(ei);
     273             :   }
     274           0 : }
     275             : 
     276             : /** Some time has passed, or we just got new directory information. See if we
     277             :  * currently believe our ORPort to be unreachable. If so, launch a new test
     278             :  * for it.
     279             :  *
     280             :  * For ORPort, we simply try making a circuit that ends at ourselves.  Success
     281             :  * is noticed in onionskin_answer().
     282             :  */
     283             : void
     284           0 : router_do_reachability_checks(void)
     285             : {
     286           0 :   const routerinfo_t *me = router_get_my_routerinfo();
     287           0 :   const or_options_t *options = get_options();
     288           0 :   int orport_reachable_v4 =
     289           0 :     router_orport_seems_reachable(options, AF_INET);
     290           0 :   int orport_reachable_v6 =
     291           0 :     router_orport_seems_reachable(options, AF_INET6);
     292             : 
     293           0 :   if (router_should_check_reachability()) {
     294           0 :     bool need_testing = !circuit_enough_testing_circs();
     295             :     /* At the moment, tor relays believe that they are reachable when they
     296             :      * receive any create cell on an inbound connection, if the address
     297             :      * family is correct.
     298             :      */
     299           0 :     if (!orport_reachable_v4 || need_testing) {
     300           0 :       router_do_orport_reachability_checks(me, AF_INET, orport_reachable_v4);
     301             :     }
     302           0 :     if (!orport_reachable_v6 || need_testing) {
     303           0 :       router_do_orport_reachability_checks(me, AF_INET6, orport_reachable_v6);
     304             :     }
     305             :   }
     306           0 : }
     307             : 
     308             : /** Log a message informing the user that we are testing a port for
     309             :  * reachability, if we have not already logged such a message.
     310             :  *
     311             :  * Calls to router_reset_reachability() will reset our view of whether we have
     312             :  * logged this message for a given port. */
     313             : static void
     314           0 : inform_testing_reachability(const tor_addr_t *addr, uint16_t port)
     315             : {
     316           0 :   if (!router_get_my_routerinfo())
     317           0 :     return;
     318             : 
     319           0 :   bool *have_informed_ptr;
     320           0 :   if (tor_addr_family(addr) == AF_INET) {
     321             :     have_informed_ptr = &have_informed_testing_or_port_ipv4;
     322             :   } else {
     323           0 :     have_informed_ptr = &have_informed_testing_or_port_ipv6;
     324             :   }
     325             : 
     326           0 :   if (*have_informed_ptr) {
     327             :     /* We already told the user that we're testing this port; no need to
     328             :      * do it again. */
     329             :     return;
     330             :   }
     331             : 
     332           0 :   char addr_buf[TOR_ADDRPORT_BUF_LEN];
     333           0 :   strlcpy(addr_buf, fmt_addrport(addr, port), sizeof(addr_buf));
     334             : 
     335           0 :   const char *afname = fmt_af_family(tor_addr_family(addr));
     336             : 
     337           0 :   control_event_server_status(LOG_NOTICE,
     338             :                               "CHECKING_REACHABILITY ORADDRESS=%s",
     339             :                               addr_buf);
     340             : 
     341           0 :   log_notice(LD_OR, "Now checking whether %s ORPort %s is reachable... "
     342             :              "(this may take up to %d minutes -- look for log "
     343             :              "messages indicating success)",
     344             :              afname, addr_buf,
     345             :              TIMEOUT_UNTIL_UNREACHABILITY_COMPLAINT/60);
     346             : 
     347           0 :   *have_informed_ptr = true;
     348             : }
     349             : 
     350             : /**
     351             :  * Return true if this module knows of no reason why we shouldn't publish
     352             :  * a server descriptor.
     353             :  **/
     354             : static bool
     355           0 : ready_to_publish(const or_options_t *options)
     356             : {
     357           0 :   return options->PublishServerDescriptor_ != NO_DIRINFO &&
     358           0 :          router_all_orports_seem_reachable(options);
     359             : }
     360             : 
     361             : /** Annotate that we found our ORPort reachable with a given address
     362             :  * family. */
     363             : void
     364           0 : router_orport_found_reachable(int family)
     365             : {
     366           0 :   const routerinfo_t *me = router_get_my_routerinfo();
     367           0 :   const or_options_t *options = get_options();
     368           0 :   const char *reachable_reason = "ORPort found reachable";
     369           0 :   bool *can_reach_ptr;
     370           0 :   if (family == AF_INET) {
     371             :     can_reach_ptr = &can_reach_or_port_ipv4;
     372           0 :   } else if (family == AF_INET6) {
     373             :     can_reach_ptr = &can_reach_or_port_ipv6;
     374             :   } else {
     375           0 :     tor_assert_nonfatal_unreached();
     376           0 :     return;
     377             :   }
     378           0 :   if (!*can_reach_ptr && me) {
     379           0 :     tor_addr_port_t ap;
     380           0 :     if (router_get_orport(me, &ap, family) < 0) {
     381           0 :       return;
     382             :     }
     383           0 :     char *address = tor_strdup(fmt_addrport_ap(&ap));
     384             : 
     385           0 :     *can_reach_ptr = true;
     386             : 
     387           0 :     log_notice(LD_OR,"Self-testing indicates your ORPort %s is reachable from "
     388             :                "the outside. Excellent.%s",
     389             :                address,
     390             :                ready_to_publish(options) ?
     391             :                " Publishing server descriptor." : "");
     392             : 
     393             :     /* Make sure our descriptor is marked to publish the IPv6 if it is now
     394             :      * reachable. This can change at runtime. */
     395           0 :     if (family == AF_INET6) {
     396           0 :       mark_my_descriptor_if_omit_ipv6_changes(reachable_reason, false);
     397             :     } else {
     398           0 :       mark_my_descriptor_dirty(reachable_reason);
     399             :     }
     400             :     /* This is a significant enough change to upload immediately,
     401             :      * at least in a test network */
     402           0 :     if (options->TestingTorNetwork == 1) {
     403           0 :       reschedule_descriptor_update_check();
     404             :     }
     405           0 :     control_event_server_status(LOG_NOTICE,
     406             :                                 "REACHABILITY_SUCCEEDED ORADDRESS=%s",
     407             :                                 address);
     408           0 :     tor_free(address);
     409             :   }
     410             : }
     411             : 
     412             : /** We have enough testing circuits open. Send a bunch of "drop"
     413             :  * cells down each of them, to exercise our bandwidth.
     414             :  *
     415             :  * May use IPv4 and IPv6 testing circuits (if available). */
     416             : void
     417           0 : router_perform_bandwidth_test(int num_circs, time_t now)
     418             : {
     419           0 :   int num_cells = (int)(get_options()->BandwidthRate * 10 /
     420             :                         CELL_MAX_NETWORK_SIZE);
     421           0 :   int max_cells = num_cells < CIRCWINDOW_START ?
     422             :                     num_cells : CIRCWINDOW_START;
     423           0 :   int cells_per_circuit = max_cells / num_circs;
     424           0 :   origin_circuit_t *circ = NULL;
     425             : 
     426           0 :   log_notice(LD_OR,"Performing bandwidth self-test...done.");
     427           0 :   while ((circ = circuit_get_next_by_purpose(circ,
     428             :                                              CIRCUIT_PURPOSE_TESTING))) {
     429             :     /* dump cells_per_circuit drop cells onto this circ */
     430           0 :     int i = cells_per_circuit;
     431           0 :     if (circ->base_.state != CIRCUIT_STATE_OPEN)
     432           0 :       continue;
     433           0 :     circ->base_.timestamp_dirty = now;
     434           0 :     while (i-- > 0) {
     435           0 :       if (relay_send_command_from_edge(0, TO_CIRCUIT(circ),
     436             :                                        RELAY_COMMAND_DROP,
     437             :                                        NULL, 0, circ->cpath->prev)<0) {
     438             :         return; /* stop if error */
     439             :       }
     440             :     }
     441             :   }
     442             : }

Generated by: LCOV version 1.14