Skip to content

Commit

Permalink
Merge ed80453 into 5f96968
Browse files Browse the repository at this point in the history
  • Loading branch information
nmathewson committed Jul 17, 2020
2 parents 5f96968 + ed80453 commit ccca5f6
Show file tree
Hide file tree
Showing 14 changed files with 128 additions and 119 deletions.
7 changes: 7 additions & 0 deletions changes/ticket33898
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
o Minor features (relay address tracking):
- We store relay addresses for OR connections in a more logical way.
Previously we would sometimes overwrite the actual address of a
connection with a "canonical address", and then store the "real
address" elsewhere to remember it. We now track the "canonical address"
elsewhere for the cases where we need it, and leave the connection's
address alone. Closes ticket 33898.
32 changes: 10 additions & 22 deletions src/core/mainloop/connection.c
Original file line number Diff line number Diff line change
Expand Up @@ -434,14 +434,6 @@ connection_describe_peer_internal(const connection_t *conn,
} else if (conn->type == CONN_TYPE_OR) {
/* For OR connections, we have a lot to do. */
const or_connection_t *or_conn = CONST_TO_OR_CONN(conn);
/* we report 'real_addr' as the address we're talking with, if it's set.
*
* TODO: Eventually we should have 'addr' always mean the address on the
* internet, and have a separate 'canonical_addr' field.
*/
if (!tor_addr_is_null(&or_conn->real_addr)) {
addr = &or_conn->real_addr;
}
/* We report the IDs we're talking to... */
if (fast_digest_is_zero(or_conn->identity_digest)) {
// This could be a client, so scrub it. No identity to report.
Expand All @@ -453,13 +445,17 @@ connection_describe_peer_internal(const connection_t *conn,
tor_snprintf(extra_buf, sizeof(extra_buf),
" ID=%s", id_buf);
}
if (! tor_addr_eq(addr, &conn->addr) && !scrub) {
if (! scrub && (! tor_addr_eq(addr, &or_conn->canonical_orport.addr) ||
conn->port != or_conn->canonical_orport.port)) {
/* We report canonical address, if it's different */
char canonical_addr_buf[TOR_ADDR_BUF_LEN];
if (tor_addr_to_str(canonical_addr_buf, &conn->addr,
if (tor_addr_to_str(canonical_addr_buf, &or_conn->canonical_orport.addr,
sizeof(canonical_addr_buf), 1)) {
strlcat(extra_buf, " canonical_addr=", sizeof(extra_buf));
strlcat(extra_buf, canonical_addr_buf, sizeof(extra_buf));
tor_snprintf(extra_buf+strlen(extra_buf),
sizeof(extra_buf)-strlen(extra_buf),
" canonical_addr=%s:%"PRIu16,
canonical_addr_buf,
or_conn->canonical_orport.port);
}
}
} else if (conn->type == CONN_TYPE_EXIT) {
Expand Down Expand Up @@ -570,6 +566,7 @@ or_connection_new(int type, int socket_family)
tor_assert(type == CONN_TYPE_OR || type == CONN_TYPE_EXT_OR);
connection_init(now, TO_CONN(or_conn), type, socket_family);

tor_addr_make_unspec(&or_conn->canonical_orport.addr);
connection_or_set_canonical(or_conn, 0);

if (type == CONN_TYPE_EXT_OR)
Expand Down Expand Up @@ -2252,16 +2249,7 @@ connection_connect_log_client_use_ip_version(const connection_t *conn)
? fascist_firewall_prefer_ipv6_orport(options)
: fascist_firewall_prefer_ipv6_dirport(options));
tor_addr_t real_addr;
tor_addr_make_null(&real_addr, AF_UNSPEC);

/* OR conns keep the original address in real_addr, as addr gets overwritten
* with the descriptor address */
if (conn->type == CONN_TYPE_OR) {
const or_connection_t *or_conn = CONST_TO_OR_CONN(conn);
tor_addr_copy(&real_addr, &or_conn->real_addr);
} else if (conn->type == CONN_TYPE_DIR) {
tor_addr_copy(&real_addr, &conn->addr);
}
tor_addr_copy(&real_addr, &conn->addr);

/* Check if we broke a mandatory address family restriction */
if ((must_ipv4 && tor_addr_family(&real_addr) == AF_INET6)
Expand Down
3 changes: 3 additions & 0 deletions src/core/or/channel.c
Original file line number Diff line number Diff line change
Expand Up @@ -3255,6 +3255,9 @@ channel_when_last_xmit(channel_t *chan)
*
* This function calls the lower layer and asks if this channel matches a
* given extend_info_t.
*
* NOTE that this function only checks for an address/port match, and should
* be used only when no identity is available.
*/
int
channel_matches_extend_info(channel_t *chan, extend_info_t *extend_info)
Expand Down
33 changes: 20 additions & 13 deletions src/core/or/channeltls.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -673,6 +667,9 @@ channel_tls_is_canonical_method(channel_t *chan, int req)
*
* This implements the matches_extend_info method for channel_tls_t; the upper
* layer wants to know if this channel matches an extend_info_t.
*
* NOTE that this function only checks for an address/port match, and should
* be used only when no identify is available.
*/
static int
channel_tls_matches_extend_info_method(channel_t *chan,
Expand All @@ -692,6 +689,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);
Expand Down Expand Up @@ -722,8 +729,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
Expand All @@ -734,7 +741,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);
}

/**
Expand Down Expand Up @@ -1883,7 +1890,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;
}
Expand Down Expand Up @@ -1921,7 +1928,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) {
Expand Down
67 changes: 27 additions & 40 deletions src/core/or/connection_or.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand All @@ -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;

Expand Down Expand Up @@ -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);
}

/*
Expand Down Expand Up @@ -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 "
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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. "
Expand All @@ -1824,17 +1807,18 @@ 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 "
"chain; ignoring.");
} 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();
}
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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);
Expand Down
9 changes: 2 additions & 7 deletions src/core/or/connection_st.h
Original file line number Diff line number Diff line change
Expand Up @@ -137,15 +137,11 @@ struct connection_t {
* any more!
*
* The misuses of this field include:
* * Setting it to the canonical address of a relay on an OR connection.
* * Setting it on linked connections, possibly.
* * Updating it based on the Forwarded-For header-- Forwarded-For is
* set by a proxy, but not a local trusted troxy.
* set by a proxy, but not a local trusted proxy.
**/
tor_addr_t addr; /**< IP that socket "s" is directly connected to;
* may be the IP address for a proxy or pluggable transport,
* see "address" for the address of the final destination.
*/
tor_addr_t addr;
uint16_t port; /**< If non-zero, port that socket "s" is directly connected
* to; may be the port for a proxy or pluggable transport,
* see "address" for the port at the final destination. */
Expand All @@ -165,7 +161,6 @@ struct connection_t {
*
* * An address we're trying to resolve (as an exit).
* * A unix address we're trying to bind to (as a listener).
* * A canonical address for an OR connection.
**/
char *address;
/** Another connection that's connected to this one in lieu of a socket. */
Expand Down
Loading

0 comments on commit ccca5f6

Please sign in to comment.