Line data Source code
1 : /* Copyright (c) 2018-2021, The Tor Project, Inc. */
2 : /* See LICENSE for licensing information */
3 :
4 : #define DOS_PRIVATE
5 : #define CHANNEL_OBJECT_PRIVATE
6 : #define CIRCUITLIST_PRIVATE
7 :
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"
18 :
19 : #include "feature/nodelist/networkstatus_st.h"
20 : #include "core/or/or_connection_st.h"
21 : #include "feature/nodelist/routerstatus_st.h"
22 :
23 : #include "test/test.h"
24 : #include "test/log_test_helpers.h"
25 :
26 : static networkstatus_t *dummy_ns = NULL;
27 : static networkstatus_t *
28 12 : mock_networkstatus_get_latest_consensus(void)
29 : {
30 12 : return dummy_ns;
31 : }
32 :
33 : static networkstatus_t *
34 1 : mock_networkstatus_get_latest_consensus_by_flavor(consensus_flavor_t f)
35 : {
36 1 : tor_assert(f == FLAV_MICRODESC);
37 1 : return dummy_ns;
38 : }
39 :
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;
43 : static int
44 2 : mock_get_estimated_address_per_node(void)
45 : {
46 2 : return addr_per_node;
47 : }
48 :
49 : static unsigned int
50 9 : mock_enable_dos_protection(const networkstatus_t *ns)
51 : {
52 9 : (void) ns;
53 9 : return 1;
54 : }
55 :
56 : /** Test that the connection tracker of the DoS subsystem will block clients
57 : * who try to establish too many connections */
58 : static void
59 1 : test_dos_conn_creation(void *arg)
60 : {
61 1 : (void) arg;
62 :
63 1 : MOCK(get_param_cc_enabled, mock_enable_dos_protection);
64 1 : MOCK(get_param_conn_enabled, mock_enable_dos_protection);
65 :
66 : /* Initialize test data */
67 1 : or_connection_t or_conn;
68 1 : time_t now = 1281533250; /* 2010-08-11 13:27:30 UTC */
69 1 : tt_int_op(AF_INET,OP_EQ, tor_addr_parse(&TO_CONN(&or_conn)->addr,
70 : "18.0.0.1"));
71 1 : tor_addr_t *addr = &TO_CONN(&or_conn)->addr;
72 :
73 : /* Get DoS subsystem limits */
74 1 : dos_init();
75 1 : uint32_t max_concurrent_conns = get_param_conn_max_concurrent_count(NULL);
76 :
77 : /* Introduce new client */
78 1 : geoip_note_client_seen(GEOIP_CLIENT_CONNECT, addr, NULL, now);
79 : { /* Register many conns from this client but not enough to get it blocked */
80 1 : unsigned int i;
81 102 : for (i = 0; i < max_concurrent_conns; i++) {
82 : /* Don't trigger the connect() rate limitation so advance the clock 1
83 : * second for each connection. */
84 100 : update_approx_time(++now);
85 100 : dos_new_client_conn(&or_conn, NULL);
86 : }
87 : }
88 :
89 : /* Check that new conns are still permitted */
90 1 : tt_int_op(DOS_CONN_DEFENSE_NONE, OP_EQ,
91 : dos_conn_addr_get_defense_type(addr));
92 :
93 : /* Register another conn and check that new conns are not allowed anymore */
94 1 : dos_new_client_conn(&or_conn, NULL);
95 1 : tt_int_op(DOS_CONN_DEFENSE_CLOSE, OP_EQ,
96 : dos_conn_addr_get_defense_type(addr));
97 :
98 : /* Close a client conn and see that a new conn will be permitted again */
99 1 : dos_close_client_conn(&or_conn);
100 1 : tt_int_op(DOS_CONN_DEFENSE_NONE, OP_EQ,
101 : dos_conn_addr_get_defense_type(addr));
102 :
103 : /* Register another conn and see that defense measures get reactivated */
104 1 : dos_new_client_conn(&or_conn, NULL);
105 1 : tt_int_op(DOS_CONN_DEFENSE_CLOSE, OP_EQ,
106 : dos_conn_addr_get_defense_type(addr));
107 :
108 1 : done:
109 1 : dos_free_all();
110 1 : }
111 :
112 : /** Helper mock: Place a fake IP addr for this channel in <b>addr_out</b> */
113 : static int
114 821 : mock_channel_get_addr_if_possible(const channel_t *chan, tor_addr_t *addr_out)
115 : {
116 821 : (void)chan;
117 821 : tt_int_op(AF_INET,OP_EQ, tor_addr_parse(addr_out, "18.0.0.1"));
118 : return 1;
119 :
120 0 : done:
121 0 : return 0;
122 : }
123 :
124 : /** Test that the circuit tracker of the DoS subsystem will block clients who
125 : * try to establish too many circuits. */
126 : static void
127 1 : test_dos_circuit_creation(void *arg)
128 : {
129 1 : (void) arg;
130 1 : unsigned int i;
131 :
132 1 : MOCK(get_param_cc_enabled, mock_enable_dos_protection);
133 1 : MOCK(get_param_conn_enabled, mock_enable_dos_protection);
134 1 : MOCK(channel_get_addr_if_possible,
135 : mock_channel_get_addr_if_possible);
136 :
137 : /* Initialize channels/conns/circs that will be used */
138 1 : channel_t *chan = tor_malloc_zero(sizeof(channel_t));
139 1 : channel_init(chan);
140 1 : chan->is_client = 1;
141 :
142 : /* Initialize test data */
143 1 : or_connection_t or_conn;
144 1 : time_t now = 1281533250; /* 2010-08-11 13:27:30 UTC */
145 1 : tt_int_op(AF_INET,OP_EQ, tor_addr_parse(&TO_CONN(&or_conn)->addr,
146 : "18.0.0.1"));
147 1 : tor_addr_t *addr = &TO_CONN(&or_conn)->addr;
148 :
149 : /* Get DoS subsystem limits */
150 1 : dos_init();
151 1 : uint32_t max_circuit_count = get_param_cc_circuit_burst(NULL);
152 1 : uint32_t min_conc_conns_for_cc =
153 1 : get_param_cc_min_concurrent_connection(NULL);
154 :
155 : /* Introduce new client and establish enough connections to activate the
156 : * circuit counting subsystem */
157 1 : geoip_note_client_seen(GEOIP_CLIENT_CONNECT, addr, NULL, now);
158 5 : for (i = 0; i < min_conc_conns_for_cc ; i++) {
159 3 : dos_new_client_conn(&or_conn, NULL);
160 : }
161 :
162 : /* Register new circuits for this client and conn, but not enough to get
163 : * detected as dos */
164 90 : for (i=0; i < max_circuit_count-1; i++) {
165 89 : dos_cc_new_create_cell(chan);
166 : }
167 : /* see that we didn't get detected for dosing */
168 1 : tt_int_op(DOS_CC_DEFENSE_NONE, OP_EQ, dos_cc_get_defense_type(chan));
169 :
170 : /* Register another CREATE cell that will push us over the limit. Check that
171 : * the cell gets refused. */
172 1 : dos_cc_new_create_cell(chan);
173 1 : tt_int_op(DOS_CC_DEFENSE_REFUSE_CELL, OP_EQ, dos_cc_get_defense_type(chan));
174 :
175 : /* TODO: Wait a few seconds before sending the cell, and check that the
176 : buckets got refilled properly. */
177 : /* TODO: Actually send a Tor cell (instead of calling the DoS function) and
178 : * check that it will get refused */
179 :
180 1 : done:
181 1 : tor_free(chan);
182 1 : dos_free_all();
183 1 : }
184 :
185 : /** Test that the DoS subsystem properly refills the circuit token buckets. */
186 : static void
187 1 : test_dos_bucket_refill(void *arg)
188 : {
189 1 : (void) arg;
190 1 : int i;
191 : /* For this test, this variable is set to the current circ count of the token
192 : * bucket. */
193 1 : uint32_t current_circ_count;
194 :
195 1 : MOCK(get_param_cc_enabled, mock_enable_dos_protection);
196 1 : MOCK(get_param_conn_enabled, mock_enable_dos_protection);
197 1 : MOCK(channel_get_addr_if_possible,
198 : mock_channel_get_addr_if_possible);
199 :
200 1 : time_t now = 1281533250; /* 2010-08-11 13:27:30 UTC */
201 1 : update_approx_time(now);
202 :
203 : /* Initialize channels/conns/circs that will be used */
204 1 : channel_t *chan = tor_malloc_zero(sizeof(channel_t));
205 1 : channel_init(chan);
206 1 : chan->is_client = 1;
207 1 : or_connection_t or_conn;
208 1 : tt_int_op(AF_INET,OP_EQ, tor_addr_parse(&TO_CONN(&or_conn)->addr,
209 : "18.0.0.1"));
210 1 : tor_addr_t *addr = &TO_CONN(&or_conn)->addr;
211 :
212 : /* Initialize DoS subsystem and get relevant limits */
213 1 : dos_init();
214 1 : uint32_t max_circuit_count = get_param_cc_circuit_burst(NULL);
215 1 : uint64_t circ_rate = get_circuit_rate_per_second();
216 : /* Check that the circuit rate is a positive number and smaller than the max
217 : * circuit count */
218 1 : tt_u64_op(circ_rate, OP_GT, 1);
219 1 : tt_u64_op(circ_rate, OP_LT, max_circuit_count);
220 :
221 : /* Register this client */
222 1 : geoip_note_client_seen(GEOIP_CLIENT_CONNECT, addr, NULL, now);
223 1 : dos_new_client_conn(&or_conn, NULL);
224 :
225 : /* Fetch this client from the geoip cache and get its DoS structs */
226 1 : clientmap_entry_t *entry = geoip_lookup_client(addr, NULL,
227 : GEOIP_CLIENT_CONNECT);
228 1 : tt_assert(entry);
229 1 : dos_client_stats_t* dos_stats = &entry->dos_stats;
230 : /* Check that the circuit bucket is still uninitialized */
231 1 : tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, 0);
232 :
233 : /* Send a create cell: then check that the circ token bucket got initialized
234 : * and one circ was subtracted. */
235 1 : dos_cc_new_create_cell(chan);
236 1 : current_circ_count = max_circuit_count - 1;
237 1 : tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
238 :
239 : /* Now send 29 more CREATEs and ensure that the bucket is missing 30
240 : * tokens */
241 30 : for (i=0; i < 29; i++) {
242 29 : dos_cc_new_create_cell(chan);
243 29 : current_circ_count--;
244 : }
245 1 : tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
246 :
247 : /* OK! Progress time forward one sec, refill the bucket and check that the
248 : * refill happened correctly. */
249 1 : now += 1;
250 1 : update_approx_time(now);
251 1 : cc_stats_refill_bucket(&dos_stats->cc_stats, addr);
252 : /* check refill */
253 1 : current_circ_count += circ_rate;
254 1 : tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
255 :
256 : /* Now send as many CREATE cells as needed to deplete our token bucket
257 : * completely */
258 64 : for (; current_circ_count != 0; current_circ_count--) {
259 63 : dos_cc_new_create_cell(chan);
260 : }
261 1 : tt_uint_op(current_circ_count, OP_EQ, 0);
262 1 : tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
263 :
264 : /* Now progress time a week forward, and check that the token bucket does not
265 : * have more than max_circs allowance, even tho we let it simmer for so
266 : * long. */
267 1 : now += 604800; /* a week */
268 1 : update_approx_time(now);
269 1 : cc_stats_refill_bucket(&dos_stats->cc_stats, addr);
270 1 : current_circ_count += max_circuit_count;
271 1 : tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
272 :
273 : /* Now send as many CREATE cells as needed to deplete our token bucket
274 : * completely */
275 91 : for (; current_circ_count != 0; current_circ_count--) {
276 90 : dos_cc_new_create_cell(chan);
277 : }
278 1 : tt_uint_op(current_circ_count, OP_EQ, 0);
279 1 : tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
280 :
281 : /* Now use a very large time, and check that the token bucket does not have
282 : * more than max_circs allowance, even tho we let it simmer for so long. */
283 1 : now = INT32_MAX; /* 2038? */
284 1 : update_approx_time(now);
285 1 : cc_stats_refill_bucket(&dos_stats->cc_stats, addr);
286 1 : current_circ_count += max_circuit_count;
287 1 : tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
288 :
289 : /* Now send as many CREATE cells as needed to deplete our token bucket
290 : * completely */
291 91 : for (; current_circ_count != 0; current_circ_count--) {
292 90 : dos_cc_new_create_cell(chan);
293 : }
294 1 : tt_uint_op(current_circ_count, OP_EQ, 0);
295 1 : tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
296 :
297 : /* Now use a very small time, and check that the token bucket has exactly
298 : * the max_circs allowance, because backward clock jumps are rare. */
299 1 : now = INT32_MIN; /* 19?? */
300 1 : update_approx_time(now);
301 1 : cc_stats_refill_bucket(&dos_stats->cc_stats, addr);
302 1 : current_circ_count += max_circuit_count;
303 1 : tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
304 :
305 : /* Now send as many CREATE cells as needed to deplete our token bucket
306 : * completely */
307 91 : for (; current_circ_count != 0; current_circ_count--) {
308 90 : dos_cc_new_create_cell(chan);
309 : }
310 1 : tt_uint_op(current_circ_count, OP_EQ, 0);
311 1 : tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
312 :
313 : /* Progress time forward one sec again, refill the bucket and check that the
314 : * refill happened correctly. */
315 1 : now += 1;
316 1 : update_approx_time(now);
317 1 : cc_stats_refill_bucket(&dos_stats->cc_stats, addr);
318 : /* check refill */
319 1 : current_circ_count += circ_rate;
320 1 : tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
321 :
322 : /* Now send as many CREATE cells as needed to deplete our token bucket
323 : * completely */
324 4 : for (; current_circ_count != 0; current_circ_count--) {
325 3 : dos_cc_new_create_cell(chan);
326 : }
327 1 : tt_uint_op(current_circ_count, OP_EQ, 0);
328 1 : tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
329 :
330 : /* Now use a very large time (again), and check that the token bucket does
331 : * not have more than max_circs allowance, even tho we let it simmer for so
332 : * long. */
333 1 : now = INT32_MAX; /* 2038? */
334 1 : update_approx_time(now);
335 1 : cc_stats_refill_bucket(&dos_stats->cc_stats, addr);
336 1 : current_circ_count += max_circuit_count;
337 1 : tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
338 :
339 : /* Now send as many CREATE cells as needed to deplete our token bucket
340 : * completely */
341 91 : for (; current_circ_count != 0; current_circ_count--) {
342 90 : dos_cc_new_create_cell(chan);
343 : }
344 1 : tt_uint_op(current_circ_count, OP_EQ, 0);
345 1 : tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
346 :
347 : /* This code resets the time to zero with 32-bit time_t, which triggers the
348 : * code that initialises the bucket. */
349 : #if SIZEOF_TIME_T == 8
350 : /* Now use a very very small time, and check that the token bucket has
351 : * exactly the max_circs allowance, because backward clock jumps are rare.
352 : */
353 1 : now = (time_t)INT64_MIN; /* ???? */
354 1 : update_approx_time(now);
355 1 : cc_stats_refill_bucket(&dos_stats->cc_stats, addr);
356 1 : current_circ_count += max_circuit_count;
357 1 : tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
358 :
359 : /* Now send as many CREATE cells as needed to deplete our token bucket
360 : * completely */
361 91 : for (; current_circ_count != 0; current_circ_count--) {
362 90 : dos_cc_new_create_cell(chan);
363 : }
364 1 : tt_uint_op(current_circ_count, OP_EQ, 0);
365 1 : tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
366 :
367 : /* Progress time forward one sec again, refill the bucket and check that the
368 : * refill happened correctly. */
369 1 : now += 1;
370 1 : update_approx_time(now);
371 1 : cc_stats_refill_bucket(&dos_stats->cc_stats, addr);
372 : /* check refill */
373 1 : current_circ_count += circ_rate;
374 1 : tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
375 :
376 : /* Now send as many CREATE cells as needed to deplete our token bucket
377 : * completely */
378 4 : for (; current_circ_count != 0; current_circ_count--) {
379 3 : dos_cc_new_create_cell(chan);
380 : }
381 1 : tt_uint_op(current_circ_count, OP_EQ, 0);
382 1 : tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
383 :
384 : /* Now use a very very small time, and check that the token bucket has
385 : * exactly the max_circs allowance, because backward clock jumps are rare.
386 : */
387 1 : now = (time_t)INT64_MIN; /* ???? */
388 1 : update_approx_time(now);
389 1 : cc_stats_refill_bucket(&dos_stats->cc_stats, addr);
390 1 : current_circ_count += max_circuit_count;
391 1 : tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
392 :
393 : /* Now send as many CREATE cells as needed to deplete our token bucket
394 : * completely */
395 91 : for (; current_circ_count != 0; current_circ_count--) {
396 90 : dos_cc_new_create_cell(chan);
397 : }
398 1 : tt_uint_op(current_circ_count, OP_EQ, 0);
399 1 : tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
400 :
401 : /* Now use a very very large time, and check that the token bucket does not
402 : * have more than max_circs allowance, even tho we let it simmer for so
403 : * long. */
404 1 : now = (time_t)INT64_MAX; /* ???? */
405 1 : update_approx_time(now);
406 1 : cc_stats_refill_bucket(&dos_stats->cc_stats, addr);
407 1 : current_circ_count += max_circuit_count;
408 1 : tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
409 :
410 : /* Now send as many CREATE cells as needed to deplete our token bucket
411 : * completely */
412 91 : for (; current_circ_count != 0; current_circ_count--) {
413 90 : dos_cc_new_create_cell(chan);
414 : }
415 1 : tt_uint_op(current_circ_count, OP_EQ, 0);
416 1 : tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
417 : #endif /* SIZEOF_TIME_T == 8 */
418 :
419 1 : done:
420 1 : tor_free(chan);
421 1 : dos_free_all();
422 1 : }
423 :
424 : /* Test if we avoid counting a known relay. */
425 : static void
426 1 : test_known_relay(void *arg)
427 : {
428 1 : clientmap_entry_t *entry = NULL;
429 1 : routerstatus_t *rs = NULL; microdesc_t *md = NULL; routerinfo_t *ri = NULL;
430 :
431 1 : (void) arg;
432 :
433 1 : MOCK(networkstatus_get_latest_consensus,
434 : mock_networkstatus_get_latest_consensus);
435 1 : MOCK(networkstatus_get_latest_consensus_by_flavor,
436 : mock_networkstatus_get_latest_consensus_by_flavor);
437 1 : MOCK(get_estimated_address_per_node,
438 : mock_get_estimated_address_per_node);
439 1 : MOCK(get_param_cc_enabled, mock_enable_dos_protection);
440 :
441 1 : dos_init();
442 :
443 1 : dummy_ns = tor_malloc_zero(sizeof(*dummy_ns));
444 1 : dummy_ns->flavor = FLAV_MICRODESC;
445 1 : dummy_ns->routerstatus_list = smartlist_new();
446 :
447 : /* Setup an OR conn so we can pass it to the DoS subsystem. */
448 1 : or_connection_t or_conn;
449 1 : tor_addr_parse(&TO_CONN(&or_conn)->addr, "42.42.42.42");
450 :
451 1 : rs = tor_malloc_zero(sizeof(*rs));
452 1 : tor_addr_copy(&rs->ipv4_addr, &TO_CONN(&or_conn)->addr);
453 1 : crypto_rand(rs->identity_digest, sizeof(rs->identity_digest));
454 1 : smartlist_add(dummy_ns->routerstatus_list, rs);
455 :
456 : /* This will make the nodelist bloom filter very large
457 : * (the_nodelist->node_addrs) so we will fail the contain test rarely. */
458 1 : addr_per_node = 1024;
459 1 : nodelist_set_consensus(dummy_ns);
460 :
461 : /* We have now a node in our list so we'll make sure we don't count it as a
462 : * client connection. */
463 1 : geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &TO_CONN(&or_conn)->addr,
464 : NULL, 0);
465 : /* Suppose we have 5 connections in rapid succession, the counter should
466 : * always be 0 because we should ignore this. */
467 1 : dos_new_client_conn(&or_conn, NULL);
468 1 : dos_new_client_conn(&or_conn, NULL);
469 1 : dos_new_client_conn(&or_conn, NULL);
470 1 : dos_new_client_conn(&or_conn, NULL);
471 1 : dos_new_client_conn(&or_conn, NULL);
472 1 : entry = geoip_lookup_client(&TO_CONN(&or_conn)->addr, NULL,
473 : GEOIP_CLIENT_CONNECT);
474 1 : tt_assert(entry);
475 : /* We should have a count of 0. */
476 1 : tt_uint_op(entry->dos_stats.conn_stats.concurrent_count, OP_EQ, 0);
477 :
478 : /* To make sure that his is working properly, make a unknown client
479 : * connection and see if we do get it. */
480 1 : tor_addr_parse(&TO_CONN(&or_conn)->addr, "42.42.42.43");
481 1 : geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &TO_CONN(&or_conn)->addr,
482 : NULL, 0);
483 1 : dos_new_client_conn(&or_conn, NULL);
484 1 : dos_new_client_conn(&or_conn, NULL);
485 1 : entry = geoip_lookup_client(&TO_CONN(&or_conn)->addr, NULL,
486 : GEOIP_CLIENT_CONNECT);
487 1 : tt_assert(entry);
488 : /* We should have a count of 2. */
489 1 : tt_uint_op(entry->dos_stats.conn_stats.concurrent_count, OP_EQ, 2);
490 :
491 1 : done:
492 1 : routerstatus_free(rs); routerinfo_free(ri); microdesc_free(md);
493 1 : smartlist_clear(dummy_ns->routerstatus_list);
494 1 : networkstatus_vote_free(dummy_ns);
495 1 : dos_free_all();
496 1 : UNMOCK(networkstatus_get_latest_consensus);
497 1 : UNMOCK(networkstatus_get_latest_consensus_by_flavor);
498 1 : UNMOCK(get_estimated_address_per_node);
499 1 : UNMOCK(get_param_cc_enabled);
500 1 : }
501 :
502 : /** Test that the connection tracker of the DoS subsystem will block clients
503 : * who try to establish too many connections */
504 : static void
505 1 : test_dos_conn_rate(void *arg)
506 : {
507 1 : (void) arg;
508 :
509 1 : MOCK(get_param_cc_enabled, mock_enable_dos_protection);
510 1 : MOCK(get_param_conn_enabled, mock_enable_dos_protection);
511 :
512 : /* Initialize test data */
513 1 : or_connection_t or_conn;
514 1 : time_t now = 1281533250; /* 2010-08-11 13:27:30 UTC */
515 1 : tt_int_op(AF_INET,OP_EQ, tor_addr_parse(&TO_CONN(&or_conn)->addr,
516 : "18.0.0.1"));
517 1 : tor_addr_t *addr = &TO_CONN(&or_conn)->addr;
518 1 : update_approx_time(now);
519 :
520 : /* Get DoS subsystem limits */
521 1 : dos_init();
522 1 : uint32_t burst_conn = get_param_conn_connect_burst(NULL);
523 :
524 : /* Introduce new client */
525 1 : geoip_note_client_seen(GEOIP_CLIENT_CONNECT, addr, NULL, now);
526 : { /* Register many conns from this client but not enough to get it blocked */
527 1 : unsigned int i;
528 41 : for (i = 0; i < burst_conn - 1; i++) {
529 39 : dos_new_client_conn(&or_conn, NULL);
530 : }
531 : }
532 :
533 : /* Check that new conns are still permitted */
534 1 : tt_int_op(DOS_CONN_DEFENSE_NONE, OP_EQ,
535 : dos_conn_addr_get_defense_type(addr));
536 :
537 : /* Register another conn and check that new conns are not allowed anymore.
538 : * We should have reached our burst. */
539 1 : dos_new_client_conn(&or_conn, NULL);
540 1 : tt_int_op(DOS_CONN_DEFENSE_CLOSE, OP_EQ,
541 : dos_conn_addr_get_defense_type(addr));
542 :
543 : /* Advance the time 12 hours. It should still be blocked. */
544 1 : update_approx_time(now + (12 * 60 * 60));
545 1 : tt_int_op(DOS_CONN_DEFENSE_CLOSE, OP_EQ,
546 : dos_conn_addr_get_defense_type(addr));
547 :
548 : /* Advance the time 24 hours plus 13 hours. It should be unblocked.
549 : * Remember, we had a random value between 24 hours and rand(24/2) thus
550 : * adding 13 hours is safe. */
551 1 : update_approx_time(now + (37 * 60 * 60));
552 1 : tt_int_op(DOS_CONN_DEFENSE_NONE, OP_EQ,
553 : dos_conn_addr_get_defense_type(addr));
554 :
555 1 : done:
556 1 : dos_free_all();
557 1 : }
558 :
559 : struct testcase_t dos_tests[] = {
560 : { "conn_creation", test_dos_conn_creation, TT_FORK, NULL, NULL },
561 : { "circuit_creation", test_dos_circuit_creation, TT_FORK, NULL, NULL },
562 : { "bucket_refill", test_dos_bucket_refill, TT_FORK, NULL, NULL },
563 : { "known_relay" , test_known_relay, TT_FORK,
564 : NULL, NULL },
565 : { "conn_rate", test_dos_conn_rate, TT_FORK, NULL, NULL },
566 : END_OF_TESTCASES
567 : };
|