[tor-commits] [tor/master] relay: Publish IPv4/IPv6 from resolved address cache

nickm at torproject.org nickm at torproject.org
Mon Jul 20 20:50:41 UTC 2020


commit 502f3f5afe84d7b5ad02f8fc2262232bbd9beb13
Author: David Goulet <dgoulet at torproject.org>
Date:   Tue Jul 14 11:26:40 2020 -0400

    relay: Publish IPv4/IPv6 from resolved address cache
    
    When a relay builds a new descriptor, use the new relay_find_addr_to_publish()
    interface to find the address to publish per family.
    
    This commit also make the check for address consistency to also work for a
    configured IPv6 for which before it was IPv4 only.
    
    Related to #40025
    
    Signed-off-by: David Goulet <dgoulet at torproject.org>
---
 src/feature/relay/router.c | 131 ++++++++++++++++++++++++---------------------
 1 file changed, 71 insertions(+), 60 deletions(-)

diff --git a/src/feature/relay/router.c b/src/feature/relay/router.c
index 4f4ba8559b..cebc44b1f5 100644
--- a/src/feature/relay/router.c
+++ b/src/feature/relay/router.c
@@ -1822,54 +1822,55 @@ router_get_descriptor_gen_reason(void)
  * ORPort or DirPort.
  * listener_type is either CONN_TYPE_OR_LISTENER or CONN_TYPE_DIR_LISTENER. */
 static void
-router_check_descriptor_address_port_consistency(uint32_t ipv4h_desc_addr,
+router_check_descriptor_address_port_consistency(const tor_addr_t *addr,
                                                  int listener_type)
 {
+  int family, port_cfg;
+
+  tor_assert(addr);
   tor_assert(listener_type == CONN_TYPE_OR_LISTENER ||
              listener_type == CONN_TYPE_DIR_LISTENER);
 
-  /* The first advertised Port may be the magic constant CFG_AUTO_PORT.
-   */
-  int port_v4_cfg = get_first_advertised_port_by_type_af(listener_type,
-                                                         AF_INET);
-  if (port_v4_cfg != 0 &&
-      !port_exists_by_type_addr32h_port(listener_type,
-                                        ipv4h_desc_addr, port_v4_cfg, 1)) {
-        const tor_addr_t *port_addr = get_first_advertised_addr_by_type_af(
-                                                                listener_type,
-                                                                AF_INET);
-        /* If we're building a descriptor with no advertised address,
-         * something is terribly wrong. */
-        tor_assert(port_addr);
-
-        tor_addr_t desc_addr;
-        char port_addr_str[TOR_ADDR_BUF_LEN];
-        char desc_addr_str[TOR_ADDR_BUF_LEN];
-
-        tor_addr_to_str(port_addr_str, port_addr, TOR_ADDR_BUF_LEN, 0);
-
-        tor_addr_from_ipv4h(&desc_addr, ipv4h_desc_addr);
-        tor_addr_to_str(desc_addr_str, &desc_addr, TOR_ADDR_BUF_LEN, 0);
-
-        const char *listener_str = (listener_type == CONN_TYPE_OR_LISTENER ?
-                                    "OR" : "Dir");
-        log_warn(LD_CONFIG, "The IPv4 %sPort address %s does not match the "
-                 "descriptor address %s. If you have a static public IPv4 "
-                 "address, use 'Address <IPv4>' and 'OutboundBindAddress "
-                 "<IPv4>'. If you are behind a NAT, use two %sPort lines: "
-                 "'%sPort <PublicPort> NoListen' and '%sPort <InternalPort> "
-                 "NoAdvertise'.",
-                 listener_str, port_addr_str, desc_addr_str, listener_str,
-                 listener_str, listener_str);
-      }
-}
-
-/* Tor relays only have one IPv4 address in the descriptor, which is derived
- * from the Address torrc option, or guessed using various methods in
- * router_pick_published_address().
- * Warn the operator if there is no ORPort on the descriptor address
- * ipv4h_desc_addr.
+  family = tor_addr_family(addr);
+  /* The first advertised Port may be the magic constant CFG_AUTO_PORT. */
+  port_cfg = get_first_advertised_port_by_type_af(listener_type, family);
+  if (port_cfg != 0 &&
+      !port_exists_by_type_addr_port(listener_type, addr, port_cfg, 1)) {
+    const tor_addr_t *port_addr =
+      get_first_advertised_addr_by_type_af(listener_type, family);
+    /* If we're building a descriptor with no advertised address,
+     * something is terribly wrong. */
+    tor_assert(port_addr);
+
+    char port_addr_str[TOR_ADDR_BUF_LEN];
+    char desc_addr_str[TOR_ADDR_BUF_LEN];
+
+    tor_addr_to_str(port_addr_str, port_addr, TOR_ADDR_BUF_LEN, 0);
+    tor_addr_to_str(desc_addr_str, addr, TOR_ADDR_BUF_LEN, 0);
+
+    const char *listener_str = (listener_type == CONN_TYPE_OR_LISTENER ?
+                                "OR" : "Dir");
+    const char *af_str = fmt_af_family(family);
+    log_warn(LD_CONFIG, "The %s %sPort address %s does not match the "
+             "descriptor address %s. If you have a static public IPv4 "
+             "address, use 'Address <%s>' and 'OutboundBindAddress "
+             "<%s>'. If you are behind a NAT, use two %sPort lines: "
+             "'%sPort <PublicPort> NoListen' and '%sPort <InternalPort> "
+             "NoAdvertise'.",
+             af_str, listener_str, port_addr_str, desc_addr_str, af_str,
+             af_str, listener_str, listener_str, listener_str);
+  }
+}
+
+/** Tor relays only have one IPv4 or/and one IPv6 address in the descriptor,
+ * which is derived from the Address torrc option, or guessed using various
+ * methods in relay_find_addr_to_publish().
+ *
+ * Warn the operator if there is no ORPort associated with the given address
+ * in addr.
+ *
  * Warn the operator if there is no DirPort on the descriptor address.
+ *
  * This catches a few common config errors:
  *  - operators who expect ORPorts and DirPorts to be advertised on the
  *    ports' listen addresses, rather than the torrc Address (or guessed
@@ -1878,20 +1879,22 @@ router_check_descriptor_address_port_consistency(uint32_t ipv4h_desc_addr,
  *    addresses;
  *  - discrepancies between guessed addresses and configured listen
  *    addresses (when the Address option isn't set).
+ *
  * If a listener is listening on all IPv4 addresses, it is assumed that it
  * is listening on the configured Address, and no messages are logged.
+ *
  * If an operators has specified NoAdvertise ORPorts in a NAT setting,
  * no messages are logged, unless they have specified other advertised
  * addresses.
+ *
  * The message tells operators to configure an ORPort and DirPort that match
- * the Address (using NoListen if needed).
- */
+ * the Address (using NoListen if needed). */
 static void
-router_check_descriptor_address_consistency(uint32_t ipv4h_desc_addr)
+router_check_descriptor_address_consistency(const tor_addr_t *addr)
 {
-  router_check_descriptor_address_port_consistency(ipv4h_desc_addr,
+  router_check_descriptor_address_port_consistency(addr,
                                                    CONN_TYPE_OR_LISTENER);
-  router_check_descriptor_address_port_consistency(ipv4h_desc_addr,
+  router_check_descriptor_address_port_consistency(addr,
                                                    CONN_TYPE_DIR_LISTENER);
 }
 
@@ -2033,7 +2036,7 @@ MOCK_IMPL(STATIC int,
 router_build_fresh_unsigned_routerinfo,(routerinfo_t **ri_out))
 {
   routerinfo_t *ri = NULL;
-  uint32_t addr;
+  tor_addr_t ipv4_addr, ipv6_addr;
   char platform[256];
   int hibernating = we_are_hibernating();
   const or_options_t *options = get_options();
@@ -2044,22 +2047,37 @@ router_build_fresh_unsigned_routerinfo,(routerinfo_t **ri_out))
     goto err;
   }
 
-  if (router_pick_published_address(options, &addr, 0) < 0) {
+  /* Find our resolved address both IPv4 and IPv6. In case the address is not
+   * found, the object is set to an UNSPEC address. */
+  bool have_v4 = relay_find_addr_to_publish(options, AF_INET, 0, &ipv4_addr);
+  bool have_v6 = relay_find_addr_to_publish(options, AF_INET6, 0, &ipv6_addr);
+
+  /* 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");
     result = TOR_ROUTERINFO_ERROR_NO_EXT_ADDR;
     goto err;
   }
-
   /* Log a message if the address in the descriptor doesn't match the ORPort
    * and DirPort addresses configured by the operator. */
-  router_check_descriptor_address_consistency(addr);
+  router_check_descriptor_address_consistency(&ipv4_addr);
+  router_check_descriptor_address_consistency(&ipv6_addr);
 
   ri = tor_malloc_zero(sizeof(routerinfo_t));
   ri->cache_info.routerlist_index = -1;
   ri->nickname = tor_strdup(options->Nickname);
-  tor_addr_from_ipv4h(&ri->ipv4_addr, addr);
-  ri->ipv4_orport = router_get_advertised_or_port(options);
+
+  /* IPv4. */
+  tor_addr_copy(&ri->ipv4_addr, &ipv4_addr);
+  ri->ipv4_orport = router_get_advertised_or_port_by_af(options, AF_INET);
   ri->ipv4_dirport = router_get_advertised_dir_port(options, 0);
+
+  /* IPv6. */
+  if (have_v6) {
+    tor_addr_copy(&ri->ipv6_addr, &ipv6_addr);
+    ri->ipv6_orport = router_get_advertised_or_port_by_af(options, AF_INET6);
+  }
+
   ri->supports_tunnelled_dir_requests =
     directory_permits_begindir_requests(options);
   ri->cache_info.published_on = time(NULL);
@@ -2071,13 +2089,6 @@ router_build_fresh_unsigned_routerinfo,(routerinfo_t **ri_out))
     tor_memdup(&get_current_curve25519_keypair()->pubkey,
                sizeof(curve25519_public_key_t));
 
-  /* For now, at most one IPv6 or-address is being advertised. */
-  tor_addr_port_t ipv6_orport;
-  router_get_advertised_ipv6_or_ap(options, &ipv6_orport);
-  /* If there is no valid IPv6 ORPort, the address and port are null. */
-  tor_addr_copy(&ri->ipv6_addr, &ipv6_orport.addr);
-  ri->ipv6_orport = ipv6_orport.port;
-
   ri->identity_pkey = crypto_pk_dup_key(get_server_identity_key());
   if (BUG(crypto_pk_get_digest(ri->identity_pkey,
                            ri->cache_info.identity_digest) < 0)) {





More information about the tor-commits mailing list