1 /* Copyright (c) 2018, The Tor Project, Inc. */
2 /* See LICENSE for licensing information */
5 #define TOR_CHANNEL_INTERNAL_
6 #define CIRCUITLIST_PRIVATE
8 #include "core/or/or.h"
9 #include "core/or/dos.h"
10 #include "core/or/circuitlist.h"
11 #include "lib/crypt_ops/crypto_rand.h"
12 #include "feature/stats/geoip_stats.h"
13 #include "core/or/channel.h"
14 #include "feature/nodelist/microdesc.h"
15 #include "feature/nodelist/networkstatus.h"
16 #include "feature/nodelist/nodelist.h"
17 #include "feature/nodelist/routerlist.h"
19 #include "feature/nodelist/networkstatus_st.h"
20 #include "core/or/or_connection_st.h"
21 #include "feature/nodelist/routerstatus_st.h"
23 #include "test/test.h"
24 #include "test/log_test_helpers.h"
26 static networkstatus_t
*dummy_ns
= NULL
;
27 static networkstatus_t
*
28 mock_networkstatus_get_latest_consensus(void)
33 static networkstatus_t
*
34 mock_networkstatus_get_latest_consensus_by_flavor(consensus_flavor_t f
)
36 tor_assert(f
== FLAV_MICRODESC
);
40 /* Number of address a single node_t can have. Default to the production
41 * value. This is to control the size of the bloom filter. */
42 static int addr_per_node
= 2;
44 mock_get_estimated_address_per_node(void)
50 mock_enable_dos_protection(const networkstatus_t
*ns
)
56 /** Test that the connection tracker of the DoS subsystem will block clients
57 * who try to establish too many connections */
59 test_dos_conn_creation(void *arg
)
63 MOCK(get_param_cc_enabled
, mock_enable_dos_protection
);
64 MOCK(get_param_conn_enabled
, mock_enable_dos_protection
);
66 /* Initialize test data */
67 or_connection_t or_conn
;
68 time_t now
= 1281533250; /* 2010-08-11 13:27:30 UTC */
69 tt_int_op(AF_INET
,OP_EQ
, tor_addr_parse(&or_conn
.real_addr
,
71 tor_addr_t
*addr
= &or_conn
.real_addr
;
73 /* Get DoS subsystem limits */
75 uint32_t max_concurrent_conns
= get_param_conn_max_concurrent_count(NULL
);
77 /* Introduce new client */
78 geoip_note_client_seen(GEOIP_CLIENT_CONNECT
, addr
, NULL
, now
);
79 { /* Register many conns from this client but not enough to get it blocked */
81 for (i
= 0; i
< max_concurrent_conns
; i
++) {
82 dos_new_client_conn(&or_conn
);
86 /* Check that new conns are still permitted */
87 tt_int_op(DOS_CONN_DEFENSE_NONE
, OP_EQ
,
88 dos_conn_addr_get_defense_type(addr
));
90 /* Register another conn and check that new conns are not allowed anymore */
91 dos_new_client_conn(&or_conn
);
92 tt_int_op(DOS_CONN_DEFENSE_CLOSE
, OP_EQ
,
93 dos_conn_addr_get_defense_type(addr
));
95 /* Close a client conn and see that a new conn will be permitted again */
96 dos_close_client_conn(&or_conn
);
97 tt_int_op(DOS_CONN_DEFENSE_NONE
, OP_EQ
,
98 dos_conn_addr_get_defense_type(addr
));
100 /* Register another conn and see that defense measures get reactivated */
101 dos_new_client_conn(&or_conn
);
102 tt_int_op(DOS_CONN_DEFENSE_CLOSE
, OP_EQ
,
103 dos_conn_addr_get_defense_type(addr
));
109 /** Helper mock: Place a fake IP addr for this channel in <b>addr_out</b> */
111 mock_channel_get_addr_if_possible(channel_t
*chan
, tor_addr_t
*addr_out
)
114 tt_int_op(AF_INET
,OP_EQ
, tor_addr_parse(addr_out
, "18.0.0.1"));
121 /** Test that the circuit tracker of the DoS subsystem will block clients who
122 * try to establish too many circuits. */
124 test_dos_circuit_creation(void *arg
)
129 MOCK(get_param_cc_enabled
, mock_enable_dos_protection
);
130 MOCK(get_param_conn_enabled
, mock_enable_dos_protection
);
131 MOCK(channel_get_addr_if_possible
,
132 mock_channel_get_addr_if_possible
);
134 /* Initialize channels/conns/circs that will be used */
135 channel_t
*chan
= tor_malloc_zero(sizeof(channel_t
));
139 /* Initialize test data */
140 or_connection_t or_conn
;
141 time_t now
= 1281533250; /* 2010-08-11 13:27:30 UTC */
142 tt_int_op(AF_INET
,OP_EQ
, tor_addr_parse(&or_conn
.real_addr
,
144 tor_addr_t
*addr
= &or_conn
.real_addr
;
146 /* Get DoS subsystem limits */
148 uint32_t max_circuit_count
= get_param_cc_circuit_burst(NULL
);
149 uint32_t min_conc_conns_for_cc
=
150 get_param_cc_min_concurrent_connection(NULL
);
152 /* Introduce new client and establish enough connections to activate the
153 * circuit counting subsystem */
154 geoip_note_client_seen(GEOIP_CLIENT_CONNECT
, addr
, NULL
, now
);
155 for (i
= 0; i
< min_conc_conns_for_cc
; i
++) {
156 dos_new_client_conn(&or_conn
);
159 /* Register new circuits for this client and conn, but not enough to get
161 for (i
=0; i
< max_circuit_count
-1; i
++) {
162 dos_cc_new_create_cell(chan
);
164 /* see that we didn't get detected for dosing */
165 tt_int_op(DOS_CC_DEFENSE_NONE
, OP_EQ
, dos_cc_get_defense_type(chan
));
167 /* Register another CREATE cell that will push us over the limit. Check that
168 * the cell gets refused. */
169 dos_cc_new_create_cell(chan
);
170 tt_int_op(DOS_CC_DEFENSE_REFUSE_CELL
, OP_EQ
, dos_cc_get_defense_type(chan
));
172 /* TODO: Wait a few seconds before sending the cell, and check that the
173 buckets got refilled properly. */
174 /* TODO: Actually send a Tor cell (instead of calling the DoS function) and
175 * check that it will get refused */
182 /** Test that the DoS subsystem properly refills the circuit token buckets. */
184 test_dos_bucket_refill(void *arg
)
188 /* For this test, this variable is set to the current circ count of the token
190 uint32_t current_circ_count
;
192 MOCK(get_param_cc_enabled
, mock_enable_dos_protection
);
193 MOCK(get_param_conn_enabled
, mock_enable_dos_protection
);
194 MOCK(channel_get_addr_if_possible
,
195 mock_channel_get_addr_if_possible
);
197 time_t now
= 1281533250; /* 2010-08-11 13:27:30 UTC */
198 update_approx_time(now
);
200 /* Initialize channels/conns/circs that will be used */
201 channel_t
*chan
= tor_malloc_zero(sizeof(channel_t
));
204 or_connection_t or_conn
;
205 tt_int_op(AF_INET
,OP_EQ
, tor_addr_parse(&or_conn
.real_addr
,
207 tor_addr_t
*addr
= &or_conn
.real_addr
;
209 /* Initialize DoS subsystem and get relevant limits */
211 uint32_t max_circuit_count
= get_param_cc_circuit_burst(NULL
);
212 uint64_t circ_rate
= get_circuit_rate_per_second();
213 /* Check that the circuit rate is a positive number and smaller than the max
215 tt_u64_op(circ_rate
, OP_GT
, 1);
216 tt_u64_op(circ_rate
, OP_LT
, max_circuit_count
);
218 /* Register this client */
219 geoip_note_client_seen(GEOIP_CLIENT_CONNECT
, addr
, NULL
, now
);
220 dos_new_client_conn(&or_conn
);
222 /* Fetch this client from the geoip cache and get its DoS structs */
223 clientmap_entry_t
*entry
= geoip_lookup_client(addr
, NULL
,
224 GEOIP_CLIENT_CONNECT
);
226 dos_client_stats_t
* dos_stats
= &entry
->dos_stats
;
227 /* Check that the circuit bucket is still uninitialized */
228 tt_uint_op(dos_stats
->cc_stats
.circuit_bucket
, OP_EQ
, 0);
230 /* Send a create cell: then check that the circ token bucket got initialized
231 * and one circ was subtracted. */
232 dos_cc_new_create_cell(chan
);
233 current_circ_count
= max_circuit_count
- 1;
234 tt_uint_op(dos_stats
->cc_stats
.circuit_bucket
, OP_EQ
, current_circ_count
);
236 /* Now send 29 more CREATEs and ensure that the bucket is missing 30
238 for (i
=0; i
< 29; i
++) {
239 dos_cc_new_create_cell(chan
);
240 current_circ_count
--;
242 tt_uint_op(dos_stats
->cc_stats
.circuit_bucket
, OP_EQ
, current_circ_count
);
244 /* OK! Progress time forward one sec, refill the bucket and check that the
245 * refill happened correctly. */
247 update_approx_time(now
);
248 cc_stats_refill_bucket(&dos_stats
->cc_stats
, addr
);
250 current_circ_count
+= circ_rate
;
251 tt_uint_op(dos_stats
->cc_stats
.circuit_bucket
, OP_EQ
, current_circ_count
);
253 /* Now send as many CREATE cells as needed to deplete our token bucket
255 for (; current_circ_count
!= 0; current_circ_count
--) {
256 dos_cc_new_create_cell(chan
);
258 tt_uint_op(current_circ_count
, OP_EQ
, 0);
259 tt_uint_op(dos_stats
->cc_stats
.circuit_bucket
, OP_EQ
, current_circ_count
);
261 /* Now progress time a week forward, and check that the token bucket does not
262 * have more than max_circs allowance, even tho we let it simmer for so
264 now
+= 604800; /* a week */
265 update_approx_time(now
);
266 cc_stats_refill_bucket(&dos_stats
->cc_stats
, addr
);
267 current_circ_count
+= max_circuit_count
;
268 tt_uint_op(dos_stats
->cc_stats
.circuit_bucket
, OP_EQ
, current_circ_count
);
270 /* Now send as many CREATE cells as needed to deplete our token bucket
272 for (; current_circ_count
!= 0; current_circ_count
--) {
273 dos_cc_new_create_cell(chan
);
275 tt_uint_op(current_circ_count
, OP_EQ
, 0);
276 tt_uint_op(dos_stats
->cc_stats
.circuit_bucket
, OP_EQ
, current_circ_count
);
278 /* Now use a very large time, and check that the token bucket does not have
279 * more than max_circs allowance, even tho we let it simmer for so long. */
280 now
= INT32_MAX
; /* 2038? */
281 update_approx_time(now
);
282 cc_stats_refill_bucket(&dos_stats
->cc_stats
, addr
);
283 current_circ_count
+= max_circuit_count
;
284 tt_uint_op(dos_stats
->cc_stats
.circuit_bucket
, OP_EQ
, current_circ_count
);
286 /* Now send as many CREATE cells as needed to deplete our token bucket
288 for (; current_circ_count
!= 0; current_circ_count
--) {
289 dos_cc_new_create_cell(chan
);
291 tt_uint_op(current_circ_count
, OP_EQ
, 0);
292 tt_uint_op(dos_stats
->cc_stats
.circuit_bucket
, OP_EQ
, current_circ_count
);
294 /* Now use a very small time, and check that the token bucket has exactly
295 * the max_circs allowance, because backward clock jumps are rare. */
296 now
= INT32_MIN
; /* 19?? */
297 update_approx_time(now
);
298 cc_stats_refill_bucket(&dos_stats
->cc_stats
, addr
);
299 current_circ_count
+= max_circuit_count
;
300 tt_uint_op(dos_stats
->cc_stats
.circuit_bucket
, OP_EQ
, current_circ_count
);
302 /* Now send as many CREATE cells as needed to deplete our token bucket
304 for (; current_circ_count
!= 0; current_circ_count
--) {
305 dos_cc_new_create_cell(chan
);
307 tt_uint_op(current_circ_count
, OP_EQ
, 0);
308 tt_uint_op(dos_stats
->cc_stats
.circuit_bucket
, OP_EQ
, current_circ_count
);
310 /* Progress time forward one sec again, refill the bucket and check that the
311 * refill happened correctly. */
313 update_approx_time(now
);
314 cc_stats_refill_bucket(&dos_stats
->cc_stats
, addr
);
316 current_circ_count
+= circ_rate
;
317 tt_uint_op(dos_stats
->cc_stats
.circuit_bucket
, OP_EQ
, current_circ_count
);
319 /* Now send as many CREATE cells as needed to deplete our token bucket
321 for (; current_circ_count
!= 0; current_circ_count
--) {
322 dos_cc_new_create_cell(chan
);
324 tt_uint_op(current_circ_count
, OP_EQ
, 0);
325 tt_uint_op(dos_stats
->cc_stats
.circuit_bucket
, OP_EQ
, current_circ_count
);
327 /* Now use a very large time (again), and check that the token bucket does
328 * not have more than max_circs allowance, even tho we let it simmer for so
330 now
= INT32_MAX
; /* 2038? */
331 update_approx_time(now
);
332 cc_stats_refill_bucket(&dos_stats
->cc_stats
, addr
);
333 current_circ_count
+= max_circuit_count
;
334 tt_uint_op(dos_stats
->cc_stats
.circuit_bucket
, OP_EQ
, current_circ_count
);
336 /* Now send as many CREATE cells as needed to deplete our token bucket
338 for (; current_circ_count
!= 0; current_circ_count
--) {
339 dos_cc_new_create_cell(chan
);
341 tt_uint_op(current_circ_count
, OP_EQ
, 0);
342 tt_uint_op(dos_stats
->cc_stats
.circuit_bucket
, OP_EQ
, current_circ_count
);
344 /* This code resets the time to zero with 32-bit time_t, which triggers the
345 * code that initialises the bucket. */
346 #if SIZEOF_TIME_T == 8
347 /* Now use a very very small time, and check that the token bucket has
348 * exactly the max_circs allowance, because backward clock jumps are rare.
350 now
= (time_t)INT64_MIN
; /* ???? */
351 update_approx_time(now
);
352 cc_stats_refill_bucket(&dos_stats
->cc_stats
, addr
);
353 current_circ_count
+= max_circuit_count
;
354 tt_uint_op(dos_stats
->cc_stats
.circuit_bucket
, OP_EQ
, current_circ_count
);
356 /* Now send as many CREATE cells as needed to deplete our token bucket
358 for (; current_circ_count
!= 0; current_circ_count
--) {
359 dos_cc_new_create_cell(chan
);
361 tt_uint_op(current_circ_count
, OP_EQ
, 0);
362 tt_uint_op(dos_stats
->cc_stats
.circuit_bucket
, OP_EQ
, current_circ_count
);
364 /* Progress time forward one sec again, refill the bucket and check that the
365 * refill happened correctly. */
367 update_approx_time(now
);
368 cc_stats_refill_bucket(&dos_stats
->cc_stats
, addr
);
370 current_circ_count
+= circ_rate
;
371 tt_uint_op(dos_stats
->cc_stats
.circuit_bucket
, OP_EQ
, current_circ_count
);
373 /* Now send as many CREATE cells as needed to deplete our token bucket
375 for (; current_circ_count
!= 0; current_circ_count
--) {
376 dos_cc_new_create_cell(chan
);
378 tt_uint_op(current_circ_count
, OP_EQ
, 0);
379 tt_uint_op(dos_stats
->cc_stats
.circuit_bucket
, OP_EQ
, current_circ_count
);
381 /* Now use a very very small time, and check that the token bucket has
382 * exactly the max_circs allowance, because backward clock jumps are rare.
384 now
= (time_t)INT64_MIN
; /* ???? */
385 update_approx_time(now
);
386 cc_stats_refill_bucket(&dos_stats
->cc_stats
, addr
);
387 current_circ_count
+= max_circuit_count
;
388 tt_uint_op(dos_stats
->cc_stats
.circuit_bucket
, OP_EQ
, current_circ_count
);
390 /* Now send as many CREATE cells as needed to deplete our token bucket
392 for (; current_circ_count
!= 0; current_circ_count
--) {
393 dos_cc_new_create_cell(chan
);
395 tt_uint_op(current_circ_count
, OP_EQ
, 0);
396 tt_uint_op(dos_stats
->cc_stats
.circuit_bucket
, OP_EQ
, current_circ_count
);
398 /* Now use a very very large time, and check that the token bucket does not
399 * have more than max_circs allowance, even tho we let it simmer for so
401 now
= (time_t)INT64_MAX
; /* ???? */
402 update_approx_time(now
);
403 cc_stats_refill_bucket(&dos_stats
->cc_stats
, addr
);
404 current_circ_count
+= max_circuit_count
;
405 tt_uint_op(dos_stats
->cc_stats
.circuit_bucket
, OP_EQ
, current_circ_count
);
407 /* Now send as many CREATE cells as needed to deplete our token bucket
409 for (; current_circ_count
!= 0; current_circ_count
--) {
410 dos_cc_new_create_cell(chan
);
412 tt_uint_op(current_circ_count
, OP_EQ
, 0);
413 tt_uint_op(dos_stats
->cc_stats
.circuit_bucket
, OP_EQ
, current_circ_count
);
421 /* Test if we avoid counting a known relay. */
423 test_known_relay(void *arg
)
425 clientmap_entry_t
*entry
= NULL
;
426 routerstatus_t
*rs
= NULL
; microdesc_t
*md
= NULL
; routerinfo_t
*ri
= NULL
;
430 MOCK(networkstatus_get_latest_consensus
,
431 mock_networkstatus_get_latest_consensus
);
432 MOCK(networkstatus_get_latest_consensus_by_flavor
,
433 mock_networkstatus_get_latest_consensus_by_flavor
);
434 MOCK(get_estimated_address_per_node
,
435 mock_get_estimated_address_per_node
);
436 MOCK(get_param_cc_enabled
, mock_enable_dos_protection
);
440 dummy_ns
= tor_malloc_zero(sizeof(*dummy_ns
));
441 dummy_ns
->flavor
= FLAV_MICRODESC
;
442 dummy_ns
->routerstatus_list
= smartlist_new();
444 /* Setup an OR conn so we can pass it to the DoS subsystem. */
445 or_connection_t or_conn
;
446 tor_addr_parse(&or_conn
.real_addr
, "42.42.42.42");
448 rs
= tor_malloc_zero(sizeof(*rs
));
449 rs
->addr
= tor_addr_to_ipv4h(&or_conn
.real_addr
);
450 crypto_rand(rs
->identity_digest
, sizeof(rs
->identity_digest
));
451 smartlist_add(dummy_ns
->routerstatus_list
, rs
);
453 /* This will make the nodelist bloom filter very large
454 * (the_nodelist->node_addrs) so we will fail the contain test rarely. */
455 addr_per_node
= 1024;
456 nodelist_set_consensus(dummy_ns
);
458 /* We have now a node in our list so we'll make sure we don't count it as a
459 * client connection. */
460 geoip_note_client_seen(GEOIP_CLIENT_CONNECT
, &or_conn
.real_addr
, NULL
, 0);
461 /* Suppose we have 5 connections in rapid succession, the counter should
462 * always be 0 because we should ignore this. */
463 dos_new_client_conn(&or_conn
);
464 dos_new_client_conn(&or_conn
);
465 dos_new_client_conn(&or_conn
);
466 dos_new_client_conn(&or_conn
);
467 dos_new_client_conn(&or_conn
);
468 entry
= geoip_lookup_client(&or_conn
.real_addr
, NULL
, GEOIP_CLIENT_CONNECT
);
470 /* We should have a count of 0. */
471 tt_uint_op(entry
->dos_stats
.concurrent_count
, OP_EQ
, 0);
473 /* To make sure that his is working properly, make a unknown client
474 * connection and see if we do get it. */
475 tor_addr_parse(&or_conn
.real_addr
, "42.42.42.43");
476 geoip_note_client_seen(GEOIP_CLIENT_CONNECT
, &or_conn
.real_addr
, NULL
, 0);
477 dos_new_client_conn(&or_conn
);
478 dos_new_client_conn(&or_conn
);
479 entry
= geoip_lookup_client(&or_conn
.real_addr
, NULL
, GEOIP_CLIENT_CONNECT
);
481 /* We should have a count of 2. */
482 tt_uint_op(entry
->dos_stats
.concurrent_count
, OP_EQ
, 2);
485 routerstatus_free(rs
); routerinfo_free(ri
); microdesc_free(md
);
486 smartlist_clear(dummy_ns
->routerstatus_list
);
487 networkstatus_vote_free(dummy_ns
);
489 UNMOCK(networkstatus_get_latest_consensus
);
490 UNMOCK(networkstatus_get_latest_consensus_by_flavor
);
491 UNMOCK(get_estimated_address_per_node
);
492 UNMOCK(get_param_cc_enabled
);
495 struct testcase_t dos_tests
[] = {
496 { "conn_creation", test_dos_conn_creation
, TT_FORK
, NULL
, NULL
},
497 { "circuit_creation", test_dos_circuit_creation
, TT_FORK
, NULL
, NULL
},
498 { "bucket_refill", test_dos_bucket_refill
, TT_FORK
, NULL
, NULL
},
499 { "known_relay" , test_known_relay
, TT_FORK
,