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@torproject.org>
This commit is contained in:
David Goulet 2020-07-14 11:26:40 -04:00
parent 9f61a6bdc3
commit 502f3f5afe

View file

@ -1822,54 +1822,55 @@ router_get_descriptor_gen_reason(void)
* ORPort or DirPort. * ORPort or DirPort.
* listener_type is either CONN_TYPE_OR_LISTENER or CONN_TYPE_DIR_LISTENER. */ * listener_type is either CONN_TYPE_OR_LISTENER or CONN_TYPE_DIR_LISTENER. */
static void 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 listener_type)
{ {
int family, port_cfg;
tor_assert(addr);
tor_assert(listener_type == CONN_TYPE_OR_LISTENER || tor_assert(listener_type == CONN_TYPE_OR_LISTENER ||
listener_type == CONN_TYPE_DIR_LISTENER); listener_type == CONN_TYPE_DIR_LISTENER);
/* The first advertised Port may be the magic constant CFG_AUTO_PORT. family = tor_addr_family(addr);
*/ /* 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, port_cfg = get_first_advertised_port_by_type_af(listener_type, family);
AF_INET); if (port_cfg != 0 &&
if (port_v4_cfg != 0 && !port_exists_by_type_addr_port(listener_type, addr, port_cfg, 1)) {
!port_exists_by_type_addr32h_port(listener_type, const tor_addr_t *port_addr =
ipv4h_desc_addr, port_v4_cfg, 1)) { get_first_advertised_addr_by_type_af(listener_type, family);
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, /* If we're building a descriptor with no advertised address,
* something is terribly wrong. */ * something is terribly wrong. */
tor_assert(port_addr); tor_assert(port_addr);
tor_addr_t desc_addr;
char port_addr_str[TOR_ADDR_BUF_LEN]; char port_addr_str[TOR_ADDR_BUF_LEN];
char desc_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(port_addr_str, port_addr, TOR_ADDR_BUF_LEN, 0);
tor_addr_to_str(desc_addr_str, 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 ? const char *listener_str = (listener_type == CONN_TYPE_OR_LISTENER ?
"OR" : "Dir"); "OR" : "Dir");
log_warn(LD_CONFIG, "The IPv4 %sPort address %s does not match the " 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 " "descriptor address %s. If you have a static public IPv4 "
"address, use 'Address <IPv4>' and 'OutboundBindAddress " "address, use 'Address <%s>' and 'OutboundBindAddress "
"<IPv4>'. If you are behind a NAT, use two %sPort lines: " "<%s>'. If you are behind a NAT, use two %sPort lines: "
"'%sPort <PublicPort> NoListen' and '%sPort <InternalPort> " "'%sPort <PublicPort> NoListen' and '%sPort <InternalPort> "
"NoAdvertise'.", "NoAdvertise'.",
listener_str, port_addr_str, desc_addr_str, listener_str, af_str, listener_str, port_addr_str, desc_addr_str, af_str,
listener_str, listener_str); af_str, listener_str, listener_str, listener_str);
} }
} }
/* Tor relays only have one IPv4 address in the descriptor, which is derived /** Tor relays only have one IPv4 or/and one IPv6 address in the descriptor,
* from the Address torrc option, or guessed using various methods in * which is derived from the Address torrc option, or guessed using various
* router_pick_published_address(). * methods in relay_find_addr_to_publish().
* Warn the operator if there is no ORPort on the descriptor address *
* ipv4h_desc_addr. * 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. * Warn the operator if there is no DirPort on the descriptor address.
*
* This catches a few common config errors: * This catches a few common config errors:
* - operators who expect ORPorts and DirPorts to be advertised on the * - operators who expect ORPorts and DirPorts to be advertised on the
* ports' listen addresses, rather than the torrc Address (or guessed * 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; * addresses;
* - discrepancies between guessed addresses and configured listen * - discrepancies between guessed addresses and configured listen
* addresses (when the Address option isn't set). * addresses (when the Address option isn't set).
*
* If a listener is listening on all IPv4 addresses, it is assumed that it * 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. * is listening on the configured Address, and no messages are logged.
*
* If an operators has specified NoAdvertise ORPorts in a NAT setting, * If an operators has specified NoAdvertise ORPorts in a NAT setting,
* no messages are logged, unless they have specified other advertised * no messages are logged, unless they have specified other advertised
* addresses. * addresses.
*
* The message tells operators to configure an ORPort and DirPort that match * 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 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); CONN_TYPE_OR_LISTENER);
router_check_descriptor_address_port_consistency(ipv4h_desc_addr, router_check_descriptor_address_port_consistency(addr,
CONN_TYPE_DIR_LISTENER); CONN_TYPE_DIR_LISTENER);
} }
@ -2033,7 +2036,7 @@ MOCK_IMPL(STATIC int,
router_build_fresh_unsigned_routerinfo,(routerinfo_t **ri_out)) router_build_fresh_unsigned_routerinfo,(routerinfo_t **ri_out))
{ {
routerinfo_t *ri = NULL; routerinfo_t *ri = NULL;
uint32_t addr; tor_addr_t ipv4_addr, ipv6_addr;
char platform[256]; char platform[256];
int hibernating = we_are_hibernating(); int hibernating = we_are_hibernating();
const or_options_t *options = get_options(); const or_options_t *options = get_options();
@ -2044,22 +2047,37 @@ router_build_fresh_unsigned_routerinfo,(routerinfo_t **ri_out))
goto err; 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"); log_warn(LD_CONFIG, "Don't know my address while generating descriptor");
result = TOR_ROUTERINFO_ERROR_NO_EXT_ADDR; result = TOR_ROUTERINFO_ERROR_NO_EXT_ADDR;
goto err; goto err;
} }
/* Log a message if the address in the descriptor doesn't match the ORPort /* Log a message if the address in the descriptor doesn't match the ORPort
* and DirPort addresses configured by the operator. */ * 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 = tor_malloc_zero(sizeof(routerinfo_t));
ri->cache_info.routerlist_index = -1; ri->cache_info.routerlist_index = -1;
ri->nickname = tor_strdup(options->Nickname); 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); 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 = ri->supports_tunnelled_dir_requests =
directory_permits_begindir_requests(options); directory_permits_begindir_requests(options);
ri->cache_info.published_on = time(NULL); 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, tor_memdup(&get_current_curve25519_keypair()->pubkey,
sizeof(curve25519_public_key_t)); 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()); ri->identity_pkey = crypto_pk_dup_key(get_server_identity_key());
if (BUG(crypto_pk_get_digest(ri->identity_pkey, if (BUG(crypto_pk_get_digest(ri->identity_pkey,
ri->cache_info.identity_digest) < 0)) { ri->cache_info.identity_digest) < 0)) {