From acf7ea77d8d76830924a14145afbcf3c95a06b0e Mon Sep 17 00:00:00 2001 From: David Goulet Date: Thu, 25 Jan 2018 16:28:54 -0500 Subject: [PATCH] dos: Add the connection DoS mitigation subsystem Defend against an address that has reached the concurrent connection count threshold. Signed-off-by: David Goulet --- src/or/connection.c | 8 ++++++++ src/or/dos.c | 34 ++++++++++++++++++++++++++++++++++ src/or/dos.h | 2 ++ 3 files changed, 44 insertions(+) diff --git a/src/or/connection.c b/src/or/connection.c index 15f489c6b4..791fd95c27 100644 --- a/src/or/connection.c +++ b/src/or/connection.c @@ -1600,6 +1600,14 @@ connection_handle_listener_read(connection_t *conn, int new_type) return 0; } } + if (new_type == CONN_TYPE_OR) { + /* Assess with the connection DoS mitigation subsystem if this address + * can open a new connection. */ + if (dos_conn_addr_get_defense_type(&addr) == DOS_CONN_DEFENSE_CLOSE) { + tor_close_socket(news); + return 0; + } + } newconn = connection_new(new_type, conn->socket_family); newconn->s = news; diff --git a/src/or/dos.c b/src/or/dos.c index 8c00a2f310..7e3a2ab7f9 100644 --- a/src/or/dos.c +++ b/src/or/dos.c @@ -53,6 +53,9 @@ static unsigned int dos_conn_enabled = 0; static uint32_t dos_conn_max_concurrent_count; static dos_conn_defense_type_t dos_conn_defense_type; +/* Keep some stats for the heartbeat so we can report out. */ +static uint64_t conn_num_addr_rejected; + /* * General interface of the denial of service mitigation subsystem. */ @@ -488,6 +491,37 @@ dos_cc_get_defense_type(channel_t *chan) /* Concurrent connection detection public API. */ +/* Return true iff the given address is permitted to open another connection. + * A defense value is returned for the caller to take appropriate actions. */ +dos_conn_defense_type_t +dos_conn_addr_get_defense_type(const tor_addr_t *addr) +{ + clientmap_entry_t *entry; + + tor_assert(addr); + + /* Skip everything if not enabled. */ + if (!dos_conn_enabled) { + 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) { + goto end; + } + + /* Need to be above the maximum concurrent connection count to trigger a + * defense. */ + if (entry->dos_stats.concurrent_count > dos_conn_max_concurrent_count) { + conn_num_addr_rejected++; + return dos_conn_defense_type; + } + + end: + return DOS_CONN_DEFENSE_NONE; +} + /* General API */ /* Called when a new client connection has been established on the given diff --git a/src/or/dos.h b/src/or/dos.h index fa86295cf6..cc7749836f 100644 --- a/src/or/dos.h +++ b/src/or/dos.h @@ -107,6 +107,8 @@ typedef enum dos_conn_defense_type_t { DOS_CONN_DEFENSE_MAX = 2, } dos_conn_defense_type_t; +dos_conn_defense_type_t dos_conn_addr_get_defense_type(const tor_addr_t *addr); + #ifdef DOS_PRIVATE STATIC uint32_t get_param_conn_max_concurrent_count(