commit 45113b648b413989ca82d2c3be6afae1699cae43 Author: David Goulet dgoulet@torproject.org Date: Tue Jan 26 12:11:10 2021 -0500
test: Add DoS connection rate unit test
Related to #40253
Signed-off-by: David Goulet dgoulet@torproject.org --- src/core/or/dos.c | 2 +- src/core/or/dos.h | 1 + src/test/test_dos.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+), 1 deletion(-)
diff --git a/src/core/or/dos.c b/src/core/or/dos.c index 0169a631c2..ba4e5442d6 100644 --- a/src/core/or/dos.c +++ b/src/core/or/dos.c @@ -210,7 +210,7 @@ get_param_conn_connect_rate(const networkstatus_t *ns)
/* Return the connection connect burst parameters either from the * configuration file or, if not found, consensus parameter. */ -static uint32_t +STATIC uint32_t get_param_conn_connect_burst(const networkstatus_t *ns) { if (dos_get_options()->DoSConnectionConnectBurst) { diff --git a/src/core/or/dos.h b/src/core/or/dos.h index cadabdb2c9..3153a1fc5f 100644 --- a/src/core/or/dos.h +++ b/src/core/or/dos.h @@ -155,6 +155,7 @@ STATIC uint32_t get_param_conn_max_concurrent_count( STATIC uint32_t get_param_cc_circuit_burst(const networkstatus_t *ns); STATIC uint32_t get_param_cc_min_concurrent_connection( const networkstatus_t *ns); +STATIC uint32_t get_param_conn_connect_burst(const networkstatus_t *ns);
STATIC uint64_t get_circuit_rate_per_second(void); STATIC void cc_stats_refill_bucket(cc_client_stats_t *stats, diff --git a/src/test/test_dos.c b/src/test/test_dos.c index cbebecb030..d9ddaec108 100644 --- a/src/test/test_dos.c +++ b/src/test/test_dos.c @@ -79,6 +79,9 @@ test_dos_conn_creation(void *arg) { /* Register many conns from this client but not enough to get it blocked */ unsigned int i; for (i = 0; i < max_concurrent_conns; i++) { + /* Don't trigger the connect() rate limitation so advance the clock 1 + * second for each connection. */ + update_approx_time(++now); dos_new_client_conn(&or_conn, NULL); } } @@ -496,11 +499,69 @@ test_known_relay(void *arg) UNMOCK(get_param_cc_enabled); }
+/** Test that the connection tracker of the DoS subsystem will block clients + * who try to establish too many connections */ +static void +test_dos_conn_rate(void *arg) +{ + (void) arg; + + MOCK(get_param_cc_enabled, mock_enable_dos_protection); + MOCK(get_param_conn_enabled, mock_enable_dos_protection); + + /* Initialize test data */ + or_connection_t or_conn; + time_t now = 1281533250; /* 2010-08-11 13:27:30 UTC */ + tt_int_op(AF_INET,OP_EQ, tor_addr_parse(&TO_CONN(&or_conn)->addr, + "18.0.0.1")); + tor_addr_t *addr = &TO_CONN(&or_conn)->addr; + update_approx_time(now); + + /* Get DoS subsystem limits */ + dos_init(); + uint32_t burst_conn = get_param_conn_connect_burst(NULL); + + /* Introduce new client */ + geoip_note_client_seen(GEOIP_CLIENT_CONNECT, addr, NULL, now); + { /* Register many conns from this client but not enough to get it blocked */ + unsigned int i; + for (i = 0; i < burst_conn - 1; i++) { + dos_new_client_conn(&or_conn, NULL); + } + } + + /* Check that new conns are still permitted */ + tt_int_op(DOS_CONN_DEFENSE_NONE, OP_EQ, + dos_conn_addr_get_defense_type(addr)); + + /* Register another conn and check that new conns are not allowed anymore. + * We should have reached our burst. */ + dos_new_client_conn(&or_conn, NULL); + tt_int_op(DOS_CONN_DEFENSE_CLOSE, OP_EQ, + dos_conn_addr_get_defense_type(addr)); + + /* Advance the time 12 hours. It should still be blocked. */ + update_approx_time(now + (12 * 60 * 60)); + tt_int_op(DOS_CONN_DEFENSE_CLOSE, OP_EQ, + dos_conn_addr_get_defense_type(addr)); + + /* Advance the time 24 hours plus 13 hours. It should be unblocked. + * Remember, we had a random value between 24 hours and rand(24/2) thus + * adding 13 hours is safe. */ + update_approx_time(now + (37 * 60 * 60)); + tt_int_op(DOS_CONN_DEFENSE_NONE, OP_EQ, + dos_conn_addr_get_defense_type(addr)); + + done: + dos_free_all(); +} + struct testcase_t dos_tests[] = { { "conn_creation", test_dos_conn_creation, TT_FORK, NULL, NULL }, { "circuit_creation", test_dos_circuit_creation, TT_FORK, NULL, NULL }, { "bucket_refill", test_dos_bucket_refill, TT_FORK, NULL, NULL }, { "known_relay" , test_known_relay, TT_FORK, NULL, NULL }, + { "conn_rate", test_dos_conn_rate, TT_FORK, NULL, NULL }, END_OF_TESTCASES };
tor-commits@lists.torproject.org