diff options
author | Nick Mathewson <nickm@torproject.org> | 2020-07-16 14:36:54 -0400 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2020-07-17 11:42:49 -0400 |
commit | 7b3bd45cfe400deb2420afa0018c642402cc4f94 (patch) | |
tree | 8b3b46311ff19d3f62c177773d58660adb365f73 /src/core/or | |
parent | 44da9206701a2b157474f94ccf64996dce192924 (diff) | |
download | tor-7b3bd45cfe400deb2420afa0018c642402cc4f94.tar.gz tor-7b3bd45cfe400deb2420afa0018c642402cc4f94.zip |
or_connection_t: replace real_addr with canonical_orport.
Instead of replacing connection_t.{addr,port} with a canonical
orport, and tracking the truth in real_addr, we now leave
connection_t.addr alone, and put the canonical address in
canonical_orport.
Closes #40042
Closes #33898
Diffstat (limited to 'src/core/or')
-rw-r--r-- | src/core/or/channeltls.c | 30 | ||||
-rw-r--r-- | src/core/or/connection_or.c | 67 | ||||
-rw-r--r-- | src/core/or/dos.c | 12 | ||||
-rw-r--r-- | src/core/or/or_connection_st.h | 17 |
4 files changed, 59 insertions, 67 deletions
diff --git a/src/core/or/channeltls.c b/src/core/or/channeltls.c index 90049a7e5c..7ec977be3c 100644 --- a/src/core/or/channeltls.c +++ b/src/core/or/channeltls.c @@ -548,14 +548,8 @@ channel_tls_get_remote_addr_method(const channel_t *chan, return 0; } - if (! tor_addr_is_null(&tlschan->conn->real_addr)) { - /* They want the real address, and real_addr is set. */ - tor_addr_copy(addr_out, &(tlschan->conn->real_addr)); - } else { - /* We'll have to give them the nominal address, which hopefully has - * not been overwritten yet. */ - tor_addr_copy(addr_out, &TO_CONN(tlschan->conn)->addr); - } + /* They want the real address, so give it to them. */ + tor_addr_copy(addr_out, &TO_CONN(tlschan->conn)->addr); return 1; } @@ -692,6 +686,16 @@ channel_tls_matches_extend_info_method(channel_t *chan, return 0; } + const tor_addr_port_t *orport = &tlschan->conn->canonical_orport; + // If the canonical address is set, then we'll allow matches based on that. + if (! tor_addr_is_unspec(&orport->addr)) { + if (extend_info_has_orport(extend_info, &orport->addr, orport->port)) { + return 1; + } + } + + // We also want to match if the true address and port are listed in the + // extend info. return extend_info_has_orport(extend_info, &TO_CONN(tlschan->conn)->addr, TO_CONN(tlschan->conn)->port); @@ -722,8 +726,8 @@ channel_tls_matches_target_method(channel_t *chan, return 0; } - /* real_addr is the address this connection came from. - * base_.addr is updated by connection_or_init_conn_from_address() + /* addr is the address this connection came from. + * canonical_orport is updated by connection_or_init_conn_from_address() * to be the address in the descriptor. It may be tempting to * allow either address to be allowed, but if we did so, it would * enable someone who steals a relay's keys to covertly impersonate/MITM it @@ -734,7 +738,7 @@ channel_tls_matches_target_method(channel_t *chan, * An adversary who has stolen a relay's keys could also post a fake relay * descriptor, but that attack is easier to detect. */ - return tor_addr_eq(&(tlschan->conn->real_addr), target); + return tor_addr_eq(&TO_CONN(tlschan->conn)->addr, target); } /** @@ -1883,7 +1887,7 @@ channel_tls_process_netinfo_cell(cell_t *cell, channel_tls_t *chan) * might be doing something funny, but nobody else is doing a MITM * on the relay's TCP. */ - if (tor_addr_eq(&addr, &(chan->conn->real_addr))) { + if (tor_addr_eq(&addr, &TO_CONN(chan->conn)->addr)) { connection_or_set_canonical(chan->conn, 1); break; } @@ -1921,7 +1925,7 @@ channel_tls_process_netinfo_cell(cell_t *cell, channel_tls_t *chan) * we were unable to resolve it previously. The endpoint address is passed * in order to make sure to never consider an address that is the same as * our endpoint. */ - relay_address_new_suggestion(&my_apparent_addr, &chan->conn->real_addr, + relay_address_new_suggestion(&my_apparent_addr, &TO_CONN(chan->conn)->addr, identity_digest); if (! chan->conn->handshake_state->sent_netinfo) { diff --git a/src/core/or/connection_or.c b/src/core/or/connection_or.c index 91dcbe695b..0795521be0 100644 --- a/src/core/or/connection_or.c +++ b/src/core/or/connection_or.c @@ -893,7 +893,9 @@ connection_or_init_conn_from_address(or_connection_t *conn, conn->base_.port = port; tor_addr_copy(&conn->base_.addr, addr); - tor_addr_copy(&conn->real_addr, addr); + if (! conn->base_.address) { + conn->base_.address = tor_strdup(fmt_addr(addr)); + } connection_or_check_canonicity(conn, started_here); } @@ -905,9 +907,10 @@ connection_or_init_conn_from_address(or_connection_t *conn, static void connection_or_check_canonicity(or_connection_t *conn, int started_here) { + (void) started_here; + const char *id_digest = conn->identity_digest; const ed25519_public_key_t *ed_id = NULL; - const tor_addr_t *addr = &conn->real_addr; if (conn->chan) ed_id = & TLS_CHAN_TO_BASE(conn->chan)->ed25519_identity; @@ -936,34 +939,17 @@ connection_or_check_canonicity(or_connection_t *conn, int started_here) } else { node_ap = &node_ipv6_ap; } - if (!started_here) { - /* Override the addr/port, so our log messages will make sense. - * This is dangerous, since if we ever try looking up a conn by - * its actual addr/port, we won't remember. Careful! */ - /* XXXX arma: this is stupid, and it's the reason we need real_addr - * to track is_canonical properly. What requires it? */ - /* XXXX <arma> i believe the reason we did this, originally, is because - * we wanted to log what OR a connection was to, and if we logged the - * right IP address and port 56244, that wouldn't be as helpful. now we - * log the "right" port too, so we know if it's moria1 or moria2. - */ - /* See #33898 for a ticket that resolves this technical debt. */ - tor_addr_copy(&conn->base_.addr, &node_ap->addr); - conn->base_.port = node_ap->port; - } + /* Remember the canonical addr/port so our log messages will make + sense. */ + tor_addr_port_copy(&conn->canonical_orport, node_ap); tor_free(conn->nickname); conn->nickname = tor_strdup(node_get_nickname(r)); - tor_free(conn->base_.address); - conn->base_.address = tor_addr_to_str_dup(&node_ap->addr); } else { tor_free(conn->nickname); conn->nickname = tor_malloc(HEX_DIGEST_LEN+2); conn->nickname[0] = '$'; base16_encode(conn->nickname+1, HEX_DIGEST_LEN+1, conn->identity_digest, DIGEST_LEN); - - tor_free(conn->base_.address); - conn->base_.address = tor_addr_to_str_dup(addr); } /* @@ -1144,8 +1130,8 @@ connection_or_group_set_badness_(smartlist_t *group, int force) (int)(now - or_conn->base_.timestamp_created), best->base_.s, (int)(now - best->base_.timestamp_created)); connection_or_mark_bad_for_new_circs(or_conn); - } else if (!tor_addr_compare(&or_conn->real_addr, - &best->real_addr, CMP_EXACT)) { + } else if (tor_addr_eq(&TO_CONN(or_conn)->addr, + &TO_CONN(best)->addr)) { log_info(LD_OR, "Marking %s unsuitable for new circuits: " "(fd "TOR_SOCKET_T_FORMAT", %d secs old). We have a better " @@ -1275,7 +1261,7 @@ static or_connect_failure_entry_t * or_connect_failure_new(const or_connection_t *or_conn) { or_connect_failure_entry_t *ocf = tor_malloc_zero(sizeof(*ocf)); - or_connect_failure_init(or_conn->identity_digest, &or_conn->real_addr, + or_connect_failure_init(or_conn->identity_digest, &TO_CONN(or_conn)->addr, TO_CONN(or_conn)->port, ocf); return ocf; } @@ -1653,8 +1639,8 @@ connection_tls_start_handshake,(or_connection_t *conn, int receiving)) log_warn(LD_BUG,"tor_tls_new failed. Closing."); return -1; } - tor_tls_set_logged_address(conn->tls, // XXX client and relay? - escaped_safe_str(conn->base_.address)); + tor_tls_set_logged_address(conn->tls, + connection_describe_peer(TO_CONN(conn))); connection_start_reading(TO_CONN(conn)); log_debug(LD_HANDSHAKE,"starting TLS handshake on fd "TOR_SOCKET_T_FORMAT, @@ -1801,18 +1787,15 @@ connection_or_check_valid_tls_handshake(or_connection_t *conn, crypto_pk_t *identity_rcvd=NULL; const or_options_t *options = get_options(); int severity = server_mode(options) ? LOG_PROTOCOL_WARN : LOG_WARN; - const char *safe_address = - started_here ? conn->base_.address : - safe_str_client(conn->base_.address); const char *conn_type = started_here ? "outgoing" : "incoming"; int has_cert = 0; check_no_tls_errors(); has_cert = tor_tls_peer_has_cert(conn->tls); if (started_here && !has_cert) { - log_info(LD_HANDSHAKE,"Tried connecting to router at %s:%d, but it didn't " + log_info(LD_HANDSHAKE,"Tried connecting to router at %s, but it didn't " "send a cert! Closing.", - safe_address, conn->base_.port); + connection_describe_peer(TO_CONN(conn))); return -1; } else if (!has_cert) { log_debug(LD_HANDSHAKE,"Got incoming connection with no certificate. " @@ -1824,9 +1807,9 @@ connection_or_check_valid_tls_handshake(or_connection_t *conn, int v = tor_tls_verify(started_here?severity:LOG_INFO, conn->tls, &identity_rcvd); if (started_here && v<0) { - log_fn(severity,LD_HANDSHAKE,"Tried connecting to router at %s:%d: It" + log_fn(severity,LD_HANDSHAKE,"Tried connecting to router at %s: It" " has a cert but it's invalid. Closing.", - safe_address, conn->base_.port); + connection_describe_peer(TO_CONN(conn))); return -1; } else if (v<0) { log_info(LD_HANDSHAKE,"Incoming connection gave us an invalid cert " @@ -1834,7 +1817,8 @@ connection_or_check_valid_tls_handshake(or_connection_t *conn, } else { log_debug(LD_HANDSHAKE, "The certificate seems to be valid on %s connection " - "with %s:%d", conn_type, safe_address, conn->base_.port); + "with %s", conn_type, + connection_describe_peer(TO_CONN(conn))); } check_no_tls_errors(); } @@ -2027,9 +2011,14 @@ connection_or_client_learned_peer_id(or_connection_t *conn, /* If we learned an identity for this connection, then we might have * just discovered it to be canonical. */ connection_or_check_canonicity(conn, conn->handshake_state->started_here); + if (conn->tls) + tor_tls_set_logged_address(conn->tls, + connection_describe_peer(TO_CONN(conn))); } if (authdir_mode_tests_reachability(options)) { + // We don't want to use canonical_orport here -- we want the address + // that we really used. dirserv_orconn_tls_done(&conn->base_.addr, conn->base_.port, (const char*)rsa_peer_id, ed_peer_id); } @@ -2507,11 +2496,9 @@ connection_or_send_netinfo,(or_connection_t *conn)) netinfo_cell_set_timestamp(netinfo_cell, (uint32_t)now); /* Their address. */ - const tor_addr_t *remote_tor_addr = - !tor_addr_is_null(&conn->real_addr) ? &conn->real_addr : &conn->base_.addr; - /* We use &conn->real_addr below, unless it hasn't yet been set. If it - * hasn't yet been set, we know that base_.addr hasn't been tampered with - * yet either. */ + const tor_addr_t *remote_tor_addr = &TO_CONN(conn)->addr; + /* We can safely use TO_CONN(conn)->addr here, since we no longer replace + * it with a canonical address. */ netinfo_addr_t *their_addr = netinfo_addr_from_tor_addr(remote_tor_addr); netinfo_cell_set_other_addr(netinfo_cell, their_addr); diff --git a/src/core/or/dos.c b/src/core/or/dos.c index 5f99280030..41bf303ffe 100644 --- a/src/core/or/dos.c +++ b/src/core/or/dos.c @@ -584,7 +584,7 @@ dos_geoip_entry_about_to_free(const clientmap_entry_t *geoip_ent) SMARTLIST_FOREACH_BEGIN(get_connection_array(), connection_t *, conn) { if (conn->type == CONN_TYPE_OR) { or_connection_t *or_conn = TO_OR_CONN(conn); - if (!tor_addr_compare(&geoip_ent->addr, &or_conn->real_addr, + if (!tor_addr_compare(&geoip_ent->addr, &TO_CONN(or_conn)->addr, CMP_EXACT)) { or_conn->tracked_for_dos_mitigation = 0; } @@ -696,12 +696,12 @@ dos_new_client_conn(or_connection_t *or_conn, const char *transport_name) * reason to do so is because network reentry is possible where a client * connection comes from an Exit node. Even when we'll fix reentry, this is * a robust defense to keep in place. */ - if (nodelist_probably_contains_address(&or_conn->real_addr)) { + if (nodelist_probably_contains_address(&TO_CONN(or_conn)->addr)) { goto end; } /* We are only interested in client connection from the geoip cache. */ - entry = geoip_lookup_client(&or_conn->real_addr, transport_name, + entry = geoip_lookup_client(&TO_CONN(or_conn)->addr, transport_name, GEOIP_CLIENT_CONNECT); if (BUG(entry == NULL)) { /* Should never happen because we note down the address in the geoip @@ -712,7 +712,7 @@ dos_new_client_conn(or_connection_t *or_conn, const char *transport_name) entry->dos_stats.concurrent_count++; or_conn->tracked_for_dos_mitigation = 1; log_debug(LD_DOS, "Client address %s has now %u concurrent connections.", - fmt_addr(&or_conn->real_addr), + fmt_addr(&TO_CONN(or_conn)->addr), entry->dos_stats.concurrent_count); end: @@ -735,7 +735,7 @@ dos_close_client_conn(const or_connection_t *or_conn) } /* We are only interested in client connection from the geoip cache. */ - entry = geoip_lookup_client(&or_conn->real_addr, NULL, + entry = geoip_lookup_client(&TO_CONN(or_conn)->addr, NULL, GEOIP_CLIENT_CONNECT); if (entry == NULL) { /* This can happen because we can close a connection before the channel @@ -753,7 +753,7 @@ dos_close_client_conn(const or_connection_t *or_conn) entry->dos_stats.concurrent_count--; log_debug(LD_DOS, "Client address %s has lost a connection. Concurrent " "connections are now at %u", - fmt_addr(&or_conn->real_addr), + fmt_addr(&TO_CONN(or_conn)->addr), entry->dos_stats.concurrent_count); end: diff --git a/src/core/or/or_connection_st.h b/src/core/or/or_connection_st.h index 2507f90803..8e012a6b85 100644 --- a/src/core/or/or_connection_st.h +++ b/src/core/or/or_connection_st.h @@ -50,17 +50,18 @@ struct or_connection_t { channel_tls_t *chan; /** - * The actual address (as modified by any proxies) that this connection - * came from or went to. (See connection_t.addr for caveats.) + * The "canonical" address and port for this relay's ORPort, if this is + * a known relay. * - * TECHNICAL DEBT: + * An ORPort is "canonical" in this sense only if it is the same ORPort + * that is listed for this identity in the consensus we have. * - * This field shouldn't really exist. We need it because our code - * overwrites conenction_t.addr with the "canonical address" of the OR we - * are talking to, taken from the descriptor of the authenticated OR. - * That's a bad choice. + * This field may be set on outbound connections for _any_ relay, and on + * inbound connections after authentication. If we don't know the relay's + * identity, or if we don't have the relay's identity in our consensus, we + * leave this address as UNSPEC. **/ - tor_addr_t real_addr; + tor_addr_port_t canonical_orport; /** Should this connection be used for extending circuits to the server * matching the <b>identity_digest</b> field? Set to true if we're pretty |