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.
* 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);
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);
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);
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");
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 "
"address, use 'Address <IPv4>' and 'OutboundBindAddress "
"<IPv4>'. If you are behind a NAT, use two %sPort lines: "
"address, use 'Address <%s>' and 'OutboundBindAddress "
"<%s>'. 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);
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 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.
/** 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)) {