commit 1bfc91a029839f36e04c8204d1bccaa04a5c2afd Author: David Goulet dgoulet@torproject.org Date: Thu Jan 25 16:20:52 2018 -0500
dos: Apply defense for circuit creation DoS
If the client address was detected as malicious, apply a defense which is at this commit to return a DESTROY cell.
Signed-off-by: David Goulet dgoulet@torproject.org --- src/or/command.c | 7 ++++++ src/or/dos.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/or/dos.h | 1 + 3 files changed, 73 insertions(+)
diff --git a/src/or/command.c b/src/or/command.c index d2df55a4b..0d2808e23 100644 --- a/src/or/command.c +++ b/src/or/command.c @@ -290,6 +290,13 @@ command_process_create_cell(cell_t *cell, channel_t *chan) return; }
+ /* Check if we should apply a defense for this channel. */ + if (dos_cc_get_defense_type(chan) == DOS_CC_DEFENSE_REFUSE_CELL) { + channel_send_destroy(cell->circ_id, chan, + END_CIRC_REASON_RESOURCELIMIT); + return; + } + if (!server_mode(options) || (!public_server_mode(options) && channel_is_outgoing(chan))) { log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, diff --git a/src/or/dos.c b/src/or/dos.c index b83ea6029..8c00a2f31 100644 --- a/src/or/dos.c +++ b/src/or/dos.c @@ -36,6 +36,7 @@ static dos_cc_defense_type_t dos_cc_defense_type; static int32_t dos_cc_defense_time_period;
/* Keep some stats for the heartbeat so we can report out. */ +static uint64_t cc_num_rejected_cells; static uint32_t cc_num_marked_addrs;
/* @@ -323,6 +324,44 @@ cc_mark_client(cc_client_stats_t *stats) crypto_rand_int_range(1, dos_cc_defense_time_period / 2); }
+/* Return true iff the given channel address is marked as malicious. This is + * called a lot and part of the fast path of handling cells. It has to remain + * as fast as we can. */ +static int +cc_channel_addr_is_marked(channel_t *chan) +{ + time_t now; + tor_addr_t addr; + clientmap_entry_t *entry; + cc_client_stats_t *stats = NULL; + + if (chan == NULL) { + goto end; + } + /* Must be a client connection else we ignore. */ + if (!channel_is_client(chan)) { + goto end; + } + /* Without an IP address, nothing can work. */ + if (!channel_get_addr_if_possible(chan, &addr)) { + goto end; + } + + /* We are only interested in client connection from the geoip cache. */ + entry = geoip_lookup_client(&addr, NULL, GEOIP_CLIENT_CONNECT); + if (entry == NULL) { + /* We can have a connection creating circuits but not tracked by the geoip + * cache. Once this DoS subsystem is enabled, we can end up here with no + * entry for the channel. */ + goto end; + } + now = approx_time(); + stats = &entry->dos_stats.cc_stats; + + end: + return stats && stats->marked_until_ts >= now; +} + /* Concurrent connection private API. */
/* Free everything for the connection DoS mitigation subsystem. */ @@ -421,6 +460,32 @@ dos_cc_new_create_cell(channel_t *chan) return; }
+/* Return the defense type that should be used for this circuit. + * + * This is part of the fast path and called a lot. */ +dos_cc_defense_type_t +dos_cc_get_defense_type(channel_t *chan) +{ + tor_assert(chan); + + /* Skip everything if not enabled. */ + if (!dos_cc_enabled) { + goto end; + } + + /* On an OR circuit, we'll check if the previous channel is a marked client + * connection detected by our DoS circuit creation mitigation subsystem. */ + if (cc_channel_addr_is_marked(chan)) { + /* We've just assess that this circuit should trigger a defense for the + * cell it just seen. Note it down. */ + cc_num_rejected_cells++; + return dos_cc_defense_type; + } + + end: + return DOS_CC_DEFENSE_NONE; +} + /* Concurrent connection detection public API. */
/* General API */ diff --git a/src/or/dos.h b/src/or/dos.h index bb8d7d1a7..fa86295cf 100644 --- a/src/or/dos.h +++ b/src/or/dos.h @@ -81,6 +81,7 @@ typedef enum dos_cc_defense_type_t { } dos_cc_defense_type_t;
void dos_cc_new_create_cell(channel_t *channel); +dos_cc_defense_type_t dos_cc_get_defense_type(channel_t *chan);
/* * Concurrent connection DoS mitigation interface.
tor-commits@lists.torproject.org