summaryrefslogtreecommitdiff
path: root/src/feature
diff options
context:
space:
mode:
authorDavid Goulet <dgoulet@torproject.org>2021-01-27 21:49:56 -0500
committerDavid Goulet <dgoulet@torproject.org>2021-01-29 14:28:51 -0500
commit8dda7bfdb84a5e4b3b422592f811a465e37bb155 (patch)
treef9fec43b5038ff7922917faeb12e2d56c57e6a61 /src/feature
parent0ec507171dcdeccc52c7e26deb164b99fe5c73fa (diff)
downloadtor-8dda7bfdb84a5e4b3b422592f811a465e37bb155.tar.gz
tor-8dda7bfdb84a5e4b3b422592f811a465e37bb155.zip
relay: Add bloomfiter of relay address + {OR|Dir}Port
In order to deny re-entry in the network, we now keep a bloomfilter of relay ORPort + address and authorities ORPort + address and DirPort + address combinations. So when an Exit stream is handled, we deny anything connecting back into the network on the ORPorts for relays and on the ORPort+DirPort for the authorities. Related to #2667 Signed-off-by: David Goulet <dgoulet@torproject.org>
Diffstat (limited to 'src/feature')
-rw-r--r--src/feature/nodelist/dirlist.c9
-rw-r--r--src/feature/nodelist/nodelist.c64
-rw-r--r--src/feature/nodelist/nodelist.h5
3 files changed, 63 insertions, 15 deletions
diff --git a/src/feature/nodelist/dirlist.c b/src/feature/nodelist/dirlist.c
index 576a6a2e49..423c4106e2 100644
--- a/src/feature/nodelist/dirlist.c
+++ b/src/feature/nodelist/dirlist.c
@@ -58,10 +58,13 @@ add_trusted_dir_to_nodelist_addr_set(const dir_server_t *dir)
tor_assert(dir);
tor_assert(dir->is_authority);
- /* Add IPv4 and then IPv6 if applicable. */
- nodelist_add_addr_to_address_set(&dir->ipv4_addr);
+ /* Add IPv4 and then IPv6 if applicable. For authorities, we add the ORPort
+ * and DirPort so re-entry into the network back to them is not possible. */
+ nodelist_add_addr_to_address_set(&dir->ipv4_addr, dir->ipv4_orport,
+ dir->ipv4_dirport);
if (!tor_addr_is_null(&dir->ipv6_addr)) {
- nodelist_add_addr_to_address_set(&dir->ipv6_addr);
+ /* IPv6 DirPort is not a thing yet for authorities. */
+ nodelist_add_addr_to_address_set(&dir->ipv6_addr, dir->ipv6_orport, 0);
}
}
diff --git a/src/feature/nodelist/nodelist.c b/src/feature/nodelist/nodelist.c
index cfa8b69f81..0c9bdb3c0e 100644
--- a/src/feature/nodelist/nodelist.c
+++ b/src/feature/nodelist/nodelist.c
@@ -135,6 +135,10 @@ typedef struct nodelist_t {
/* Set of addresses that belong to nodes we believe in. */
address_set_t *node_addrs;
+ /* Set of addresses + port that belong to nodes we know and that we don't
+ * allow network re-entry towards them. */
+ addr_port_set_t *reentry_set;
+
/* The valid-after time of the last live consensus that initialized the
* nodelist. We use this to detect outdated nodelists that need to be
* rebuilt using a newer consensus. */
@@ -447,40 +451,58 @@ node_addrs_changed(node_t *node)
static void
node_add_to_address_set(const node_t *node)
{
- if (!the_nodelist || !the_nodelist->node_addrs)
+ if (!the_nodelist ||
+ !the_nodelist->node_addrs || !the_nodelist->reentry_set)
return;
- /* These various address sources can be redundant, but it's likely faster
- * to add them all than to compare them all for equality. */
+ /* These various address sources can be redundant, but it's likely faster to
+ * add them all than to compare them all for equality.
+ *
+ * For relays, we only add the ORPort in the addr+port set since we want to
+ * allow re-entry into the network to the DirPort so the self reachability
+ * test succeeds and thus the 0 value for the DirPort. */
if (node->rs) {
if (!tor_addr_is_null(&node->rs->ipv4_addr))
- nodelist_add_addr_to_address_set(&node->rs->ipv4_addr);
+ nodelist_add_addr_to_address_set(&node->rs->ipv4_addr,
+ node->rs->ipv4_orport, 0);
if (!tor_addr_is_null(&node->rs->ipv6_addr))
- nodelist_add_addr_to_address_set(&node->rs->ipv6_addr);
+ nodelist_add_addr_to_address_set(&node->rs->ipv6_addr,
+ node->rs->ipv6_orport, 0);
}
if (node->ri) {
if (!tor_addr_is_null(&node->ri->ipv4_addr))
- nodelist_add_addr_to_address_set(&node->ri->ipv4_addr);
+ nodelist_add_addr_to_address_set(&node->ri->ipv4_addr,
+ node->ri->ipv4_orport, 0);
if (!tor_addr_is_null(&node->ri->ipv6_addr))
- nodelist_add_addr_to_address_set(&node->ri->ipv6_addr);
+ nodelist_add_addr_to_address_set(&node->ri->ipv6_addr,
+ node->ri->ipv6_orport, 0);
}
if (node->md) {
if (!tor_addr_is_null(&node->md->ipv6_addr))
- nodelist_add_addr_to_address_set(&node->md->ipv6_addr);
+ nodelist_add_addr_to_address_set(&node->md->ipv6_addr,
+ node->md->ipv6_orport, 0);
}
}
/** Add the given address into the nodelist address set. */
void
-nodelist_add_addr_to_address_set(const tor_addr_t *addr)
+nodelist_add_addr_to_address_set(const tor_addr_t *addr,
+ uint16_t or_port, uint16_t dir_port)
{
if (BUG(!addr) || tor_addr_is_null(addr) ||
(!tor_addr_is_v4(addr) && !tor_addr_is_v6(addr)) ||
- !the_nodelist || !the_nodelist->node_addrs) {
+ !the_nodelist || !the_nodelist->node_addrs ||
+ !the_nodelist->reentry_set) {
return;
}
address_set_add(the_nodelist->node_addrs, addr);
+ if (or_port != 0) {
+ addr_port_set_add(the_nodelist->reentry_set, addr, or_port);
+ }
+ if (dir_port != 0) {
+ addr_port_set_add(the_nodelist->reentry_set, addr, dir_port);
+ }
}
/** Return true if <b>addr</b> is the address of some node in the nodelist.
@@ -497,6 +519,21 @@ nodelist_probably_contains_address(const tor_addr_t *addr)
return address_set_probably_contains(the_nodelist->node_addrs, addr);
}
+/** Return true if <b>addr</b> is the address of some node in the nodelist and
+ * corresponds also to the given port. If not, probably return false. */
+bool
+nodelist_reentry_probably_contains(const tor_addr_t *addr, uint16_t port)
+{
+ if (BUG(!addr) || BUG(!port))
+ return false;
+
+ if (!the_nodelist || !the_nodelist->reentry_set)
+ return false;
+
+ return addr_port_set_probably_contains(the_nodelist->reentry_set,
+ addr, port);
+}
+
/** Add <b>ri</b> to an appropriate node in the nodelist. If we replace an
* old routerinfo, and <b>ri_old_out</b> is not NULL, set *<b>ri_old_out</b>
* to the previous routerinfo.
@@ -628,10 +665,13 @@ nodelist_set_consensus(const networkstatus_t *ns)
* v6). Then we add the number of configured trusted authorities we have. */
int estimated_addresses = smartlist_len(ns->routerstatus_list) *
get_estimated_address_per_node();
- estimated_addresses += (get_n_authorities(V3_DIRINFO & BRIDGE_DIRINFO) *
+ estimated_addresses += (get_n_authorities(V3_DIRINFO | BRIDGE_DIRINFO) *
get_estimated_address_per_node());
address_set_free(the_nodelist->node_addrs);
+ addr_port_set_free(the_nodelist->reentry_set);
the_nodelist->node_addrs = address_set_new(estimated_addresses);
+ /* Times two here is for both the ORPort and DirPort. */
+ the_nodelist->reentry_set = addr_port_set_new(estimated_addresses * 2);
SMARTLIST_FOREACH_BEGIN(ns->routerstatus_list, routerstatus_t *, rs) {
node_t *node = node_get_or_create(rs->identity_digest);
@@ -858,6 +898,8 @@ nodelist_free_all(void)
address_set_free(the_nodelist->node_addrs);
the_nodelist->node_addrs = NULL;
+ addr_port_set_free(the_nodelist->reentry_set);
+ the_nodelist->reentry_set = NULL;
tor_free(the_nodelist);
}
diff --git a/src/feature/nodelist/nodelist.h b/src/feature/nodelist/nodelist.h
index b762fb339c..ada0a640a1 100644
--- a/src/feature/nodelist/nodelist.h
+++ b/src/feature/nodelist/nodelist.h
@@ -35,7 +35,10 @@ node_t *nodelist_add_microdesc(microdesc_t *md);
void nodelist_set_consensus(const networkstatus_t *ns);
void nodelist_ensure_freshness(const networkstatus_t *ns);
int nodelist_probably_contains_address(const tor_addr_t *addr);
-void nodelist_add_addr_to_address_set(const tor_addr_t *addr);
+bool nodelist_reentry_probably_contains(const tor_addr_t *addr,
+ uint16_t port);
+void nodelist_add_addr_to_address_set(const tor_addr_t *addr,
+ uint16_t or_port, uint16_t dir_port);
void nodelist_remove_microdesc(const char *identity_digest, microdesc_t *md);
void nodelist_remove_routerinfo(routerinfo_t *ri);