From 93ac6ec4d3d19aaff7fed2ea97b0a30528da3767 Mon Sep 17 00:00:00 2001 From: Roger Dingledine Date: Wed, 27 Jan 2021 23:48:57 -0500 Subject: [PATCH] exit: Deny re-entry into the network Exit relays now reject exit attempts to known relay addresses + ORPort and also to authorities on the ORPort and DirPort. Closes #2667 Signed-off-by: David Goulet --- changes/ticket2667 | 4 ++++ src/core/or/connection_edge.c | 25 +++++++++++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 changes/ticket2667 diff --git a/changes/ticket2667 b/changes/ticket2667 new file mode 100644 index 0000000000..cc42286ef9 --- /dev/null +++ b/changes/ticket2667 @@ -0,0 +1,4 @@ + o Major feature (exit): + - Re-entry into the network is now denied at the Exit level to all relays' + ORPort and authorities' ORPort+DirPort. This is to help mitigate a series + of attacks. See ticket for more information. Closes ticket 2667. diff --git a/src/core/or/connection_edge.c b/src/core/or/connection_edge.c index 67a772be08..f9a9bbdb73 100644 --- a/src/core/or/connection_edge.c +++ b/src/core/or/connection_edge.c @@ -4035,6 +4035,31 @@ connection_exit_connect(edge_connection_t *edge_conn) return; } + /* Next, check for attempts to connect back into the Tor network. We don't + * want to allow these for the same reason we don't want to allow + * infinite-length circuits (see "A Practical Congestion Attack on Tor Using + * Long Paths", Usenix Security 2009). See also ticket 2667. + * + * The TORPROTOCOL reason is used instead of EXITPOLICY so client do NOT + * attempt to retry connecting onto another circuit that will also fail + * bringing considerable more load on the network if so. + * + * Since the address+port set here is a bloomfilter, in very rare cases, the + * check will create a false positive meaning that the destination could + * actually be legit and thus being denied exit. However, sending back a + * reason that makes the client retry results in much worst consequences in + * case of an attack so this is a small price to pay. */ + if (!connection_edge_is_rendezvous_stream(edge_conn) && + nodelist_reentry_probably_contains(&conn->addr, conn->port)) { + log_info(LD_EXIT, "%s:%d tried to connect back to a known relay address. " + "Closing.", escaped_safe_str_client(conn->address), + conn->port); + connection_edge_end(edge_conn, END_STREAM_REASON_TORPROTOCOL); + circuit_detach_stream(circuit_get_by_edge_conn(edge_conn), edge_conn); + connection_free(conn); + return; + } + #ifdef HAVE_SYS_UN_H if (conn->socket_family != AF_UNIX) { #else