Tor 0.4.9.0-alpha-dev
dos.c
1/* Copyright (c) 2018-2021, The Tor Project, Inc. */
2/* See LICENSE for licensing information */
3
4/*
5 * \file dos.c
6 * \brief Implement Denial of Service mitigation subsystem.
7 */
8
9#define DOS_PRIVATE
10
11#include "core/or/or.h"
12#include "app/config/config.h"
15#include "core/or/channel.h"
17#include "core/or/relay.h"
18#include "feature/hs/hs_dos.h"
25
26#include "core/or/dos.h"
27#include "core/or/dos_sys.h"
28
31
32/*
33 * Circuit creation denial of service mitigation.
34 *
35 * Namespace used for this mitigation framework is "dos_cc_" where "cc" is for
36 * Circuit Creation.
37 */
38
39/* Is the circuit creation DoS mitigation enabled? */
40static unsigned int dos_cc_enabled = 0;
41
42/* Consensus parameters. They can be changed when a new consensus arrives.
43 * They are initialized with the hardcoded default values. */
44static uint32_t dos_cc_min_concurrent_conn;
45static uint32_t dos_cc_circuit_rate;
46static uint32_t dos_cc_circuit_burst;
47static dos_cc_defense_type_t dos_cc_defense_type;
48static int32_t dos_cc_defense_time_period;
49
50/* Keep some stats for the heartbeat so we can report out. */
51static uint64_t cc_num_rejected_cells;
52static uint32_t cc_num_marked_addrs;
53static uint32_t cc_num_marked_addrs_max_queue;
54
55/*
56 * Concurrent connection denial of service mitigation.
57 *
58 * Namespace used for this mitigation framework is "dos_conn_".
59 */
60
61/* Is the connection DoS mitigation enabled? */
62static unsigned int dos_conn_enabled = 0;
63
64/* Consensus parameters. They can be changed when a new consensus arrives.
65 * They are initialized with the hardcoded default values. */
66static uint32_t dos_conn_max_concurrent_count;
67static dos_conn_defense_type_t dos_conn_defense_type;
68static uint32_t dos_conn_connect_rate = DOS_CONN_CONNECT_RATE_DEFAULT;
69static uint32_t dos_conn_connect_burst = DOS_CONN_CONNECT_BURST_DEFAULT;
70static int32_t dos_conn_connect_defense_time_period =
71 DOS_CONN_CONNECT_DEFENSE_TIME_PERIOD_DEFAULT;
72
73/* Keep some stats for the heartbeat so we can report out. */
74static uint64_t conn_num_addr_rejected;
75static uint64_t conn_num_addr_connect_rejected;
76
77/** Consensus parameter: How many times a client IP is allowed to hit the
78 * circ_max_cell_queue_size_out limit before being marked. */
79static uint32_t dos_num_circ_max_outq;
80
81/*
82 * Stream denial of service mitigation.
83 *
84 * Namespace used for this mitigation framework is "dos_stream_".
85 */
86
87/* Is the connection DoS mitigation enabled? */
88static unsigned int dos_stream_enabled = 0;
89
90/* Consensus parameters. They can be changed when a new consensus arrives.
91 * They are initialized with the hardcoded default values. */
92static dos_stream_defense_type_t dos_stream_defense_type;
93static uint32_t dos_stream_rate = DOS_STREAM_RATE_DEFAULT;
94static uint32_t dos_stream_burst = DOS_STREAM_BURST_DEFAULT;
95
96/* Keep some stats for the heartbeat so we can report out. */
97static uint64_t stream_num_rejected;
98
99/*
100 * General interface of the denial of service mitigation subsystem.
101 */
102
103/* Keep stats for the heartbeat. */
104static uint64_t num_single_hop_client_refused;
105
106/** Return the consensus parameter for the outbound circ_max_cell_queue_size
107 * limit. */
108static uint32_t
109get_param_dos_num_circ_max_outq(const networkstatus_t *ns)
110{
111#define DOS_NUM_CIRC_MAX_OUTQ_DEFAULT 3
112#define DOS_NUM_CIRC_MAX_OUTQ_MIN 0
113#define DOS_NUM_CIRC_MAX_OUTQ_MAX INT32_MAX
114
115 /* Update the circuit max cell queue size from the consensus. */
116 return networkstatus_get_param(ns, "dos_num_circ_max_outq",
117 DOS_NUM_CIRC_MAX_OUTQ_DEFAULT,
118 DOS_NUM_CIRC_MAX_OUTQ_MIN,
119 DOS_NUM_CIRC_MAX_OUTQ_MAX);
120}
121
122/* Return true iff the circuit creation mitigation is enabled. We look at the
123 * consensus for this else a default value is returned. */
124MOCK_IMPL(STATIC unsigned int,
125get_param_cc_enabled, (const networkstatus_t *ns))
126{
127 if (dos_get_options()->DoSCircuitCreationEnabled != -1) {
128 return dos_get_options()->DoSCircuitCreationEnabled;
129 }
130
131 return !!networkstatus_get_param(ns, "DoSCircuitCreationEnabled",
132 DOS_CC_ENABLED_DEFAULT, 0, 1);
133}
134
135/* Return the parameter for the minimum concurrent connection at which we'll
136 * start counting circuit for a specific client address. */
137STATIC uint32_t
138get_param_cc_min_concurrent_connection(const networkstatus_t *ns)
139{
140 if (dos_get_options()->DoSCircuitCreationMinConnections) {
141 return dos_get_options()->DoSCircuitCreationMinConnections;
142 }
143 return networkstatus_get_param(ns, "DoSCircuitCreationMinConnections",
144 DOS_CC_MIN_CONCURRENT_CONN_DEFAULT,
145 1, INT32_MAX);
146}
147
148/* Return the parameter for the time rate that is how many circuits over this
149 * time span. */
150static uint32_t
151get_param_cc_circuit_rate(const networkstatus_t *ns)
152{
153 /* This is in seconds. */
154 if (dos_get_options()->DoSCircuitCreationRate) {
155 return dos_get_options()->DoSCircuitCreationRate;
156 }
157 return networkstatus_get_param(ns, "DoSCircuitCreationRate",
158 DOS_CC_CIRCUIT_RATE_DEFAULT,
159 1, INT32_MAX);
160}
161
162/* Return the parameter for the maximum circuit count for the circuit time
163 * rate. */
164STATIC uint32_t
165get_param_cc_circuit_burst(const networkstatus_t *ns)
166{
167 if (dos_get_options()->DoSCircuitCreationBurst) {
168 return dos_get_options()->DoSCircuitCreationBurst;
169 }
170 return networkstatus_get_param(ns, "DoSCircuitCreationBurst",
171 DOS_CC_CIRCUIT_BURST_DEFAULT,
172 1, INT32_MAX);
173}
174
175/* Return the consensus parameter of the circuit creation defense type. */
176static uint32_t
177get_param_cc_defense_type(const networkstatus_t *ns)
178{
179 if (dos_get_options()->DoSCircuitCreationDefenseType) {
180 return dos_get_options()->DoSCircuitCreationDefenseType;
181 }
182 return networkstatus_get_param(ns, "DoSCircuitCreationDefenseType",
183 DOS_CC_DEFENSE_TYPE_DEFAULT,
184 DOS_CC_DEFENSE_NONE, DOS_CC_DEFENSE_MAX);
185}
186
187/* Return the consensus parameter of the defense time period which is how much
188 * time should we defend against a malicious client address. */
189static int32_t
190get_param_cc_defense_time_period(const networkstatus_t *ns)
191{
192 /* Time in seconds. */
193 if (dos_get_options()->DoSCircuitCreationDefenseTimePeriod) {
194 return dos_get_options()->DoSCircuitCreationDefenseTimePeriod;
195 }
196 return networkstatus_get_param(ns, "DoSCircuitCreationDefenseTimePeriod",
197 DOS_CC_DEFENSE_TIME_PERIOD_DEFAULT,
198 0, INT32_MAX);
199}
200
201/* Return true iff connection mitigation is enabled. We look at the consensus
202 * for this else a default value is returned. */
203MOCK_IMPL(STATIC unsigned int,
204get_param_conn_enabled, (const networkstatus_t *ns))
205{
206 if (dos_get_options()->DoSConnectionEnabled != -1) {
207 return dos_get_options()->DoSConnectionEnabled;
208 }
209 return !!networkstatus_get_param(ns, "DoSConnectionEnabled",
210 DOS_CONN_ENABLED_DEFAULT, 0, 1);
211}
212
213/* Return the consensus parameter for the maximum concurrent connection
214 * allowed. */
215STATIC uint32_t
216get_param_conn_max_concurrent_count(const networkstatus_t *ns)
217{
218 if (dos_get_options()->DoSConnectionMaxConcurrentCount) {
219 return dos_get_options()->DoSConnectionMaxConcurrentCount;
220 }
221 return networkstatus_get_param(ns, "DoSConnectionMaxConcurrentCount",
222 DOS_CONN_MAX_CONCURRENT_COUNT_DEFAULT,
223 1, INT32_MAX);
224}
225
226/* Return the consensus parameter of the connection defense type. */
227static uint32_t
228get_param_conn_defense_type(const networkstatus_t *ns)
229{
230 if (dos_get_options()->DoSConnectionDefenseType) {
231 return dos_get_options()->DoSConnectionDefenseType;
232 }
233 return networkstatus_get_param(ns, "DoSConnectionDefenseType",
234 DOS_CONN_DEFENSE_TYPE_DEFAULT,
235 DOS_CONN_DEFENSE_NONE, DOS_CONN_DEFENSE_MAX);
236}
237
238/* Return the connection connect rate parameters either from the configuration
239 * file or, if not found, consensus parameter. */
240static uint32_t
241get_param_conn_connect_rate(const networkstatus_t *ns)
242{
243 if (dos_get_options()->DoSConnectionConnectRate) {
244 return dos_get_options()->DoSConnectionConnectRate;
245 }
246 return networkstatus_get_param(ns, "DoSConnectionConnectRate",
247 DOS_CONN_CONNECT_RATE_DEFAULT,
248 1, INT32_MAX);
249}
250
251/* Return the connection connect burst parameters either from the
252 * configuration file or, if not found, consensus parameter. */
253STATIC uint32_t
254get_param_conn_connect_burst(const networkstatus_t *ns)
255{
256 if (dos_get_options()->DoSConnectionConnectBurst) {
257 return dos_get_options()->DoSConnectionConnectBurst;
258 }
259 return networkstatus_get_param(ns, "DoSConnectionConnectBurst",
260 DOS_CONN_CONNECT_BURST_DEFAULT,
261 1, INT32_MAX);
262}
263
264/* Return the connection connect defense time period from the configuration
265 * file or, if not found, the consensus parameter. */
266static int32_t
267get_param_conn_connect_defense_time_period(const networkstatus_t *ns)
268{
269 /* Time in seconds. */
270 if (dos_get_options()->DoSConnectionConnectDefenseTimePeriod) {
271 return dos_get_options()->DoSConnectionConnectDefenseTimePeriod;
272 }
273 return networkstatus_get_param(ns, "DoSConnectionConnectDefenseTimePeriod",
274 DOS_CONN_CONNECT_DEFENSE_TIME_PERIOD_DEFAULT,
275 DOS_CONN_CONNECT_DEFENSE_TIME_PERIOD_MIN,
276 INT32_MAX);
277}
278
279/* Return true iff the stream creation mitigation is enabled. We look at the
280 * consensus for this else a default value is returned. */
281MOCK_IMPL(STATIC unsigned int,
282get_param_stream_enabled, (const networkstatus_t *ns))
283{
284 if (dos_get_options()->DoSStreamCreationEnabled != -1) {
285 return dos_get_options()->DoSStreamCreationEnabled;
286 }
287
288 return !!networkstatus_get_param(ns, "DoSStreamCreationEnabled",
289 DOS_STREAM_ENABLED_DEFAULT, 0, 1);
290}
291
292/* Return the parameter for the time rate that is how many stream per circuit
293 * over this time span. */
294static uint32_t
295get_param_stream_rate(const networkstatus_t *ns)
296{
297 /* This is in seconds. */
298 if (dos_get_options()->DoSStreamCreationRate) {
299 return dos_get_options()->DoSStreamCreationRate;
300 }
301 return networkstatus_get_param(ns, "DoSStreamCreationRate",
302 DOS_STREAM_RATE_DEFAULT,
303 1, INT32_MAX);
304}
305
306/* Return the parameter for the maximum circuit count for the circuit time
307 * rate. */
308static uint32_t
309get_param_stream_burst(const networkstatus_t *ns)
310{
311 if (dos_get_options()->DoSStreamCreationBurst) {
312 return dos_get_options()->DoSStreamCreationBurst;
313 }
314 return networkstatus_get_param(ns, "DoSStreamCreationBurst",
315 DOS_STREAM_BURST_DEFAULT,
316 1, INT32_MAX);
317}
318
319/* Return the consensus parameter of the circuit creation defense type. */
320static uint32_t
321get_param_stream_defense_type(const networkstatus_t *ns)
322{
323 if (dos_get_options()->DoSStreamCreationDefenseType) {
324 return dos_get_options()->DoSStreamCreationDefenseType;
325 }
326 return networkstatus_get_param(ns, "DoSStreamCreationDefenseType",
327 DOS_STREAM_DEFENSE_TYPE_DEFAULT,
328 DOS_STREAM_DEFENSE_NONE,
329 DOS_STREAM_DEFENSE_MAX);
330}
331
332/* Set circuit creation parameters located in the consensus or their default
333 * if none are present. Called at initialization or when the consensus
334 * changes. */
335static void
336set_dos_parameters(const networkstatus_t *ns)
337{
338 /* Get the default consensus param values. */
339 dos_cc_enabled = get_param_cc_enabled(ns);
340 dos_cc_min_concurrent_conn = get_param_cc_min_concurrent_connection(ns);
341 dos_cc_circuit_rate = get_param_cc_circuit_rate(ns);
342 dos_cc_circuit_burst = get_param_cc_circuit_burst(ns);
343 dos_cc_defense_time_period = get_param_cc_defense_time_period(ns);
344 dos_cc_defense_type = get_param_cc_defense_type(ns);
345
346 /* Connection detection. */
347 dos_conn_enabled = get_param_conn_enabled(ns);
348 dos_conn_max_concurrent_count = get_param_conn_max_concurrent_count(ns);
349 dos_conn_defense_type = get_param_conn_defense_type(ns);
350 dos_conn_connect_rate = get_param_conn_connect_rate(ns);
351 dos_conn_connect_burst = get_param_conn_connect_burst(ns);
352 dos_conn_connect_defense_time_period =
353 get_param_conn_connect_defense_time_period(ns);
354
355 /* Circuit. */
356 dos_num_circ_max_outq = get_param_dos_num_circ_max_outq(ns);
357
358 /* Stream. */
359 dos_stream_enabled = get_param_stream_enabled(ns);
360 dos_stream_defense_type = get_param_stream_defense_type(ns);
361 dos_stream_rate = get_param_stream_rate(ns);
362 dos_stream_burst = get_param_stream_burst(ns);
363}
364
365/* Free everything for the circuit creation DoS mitigation subsystem. */
366static void
367cc_free_all(void)
368{
369 /* If everything is freed, the circuit creation subsystem is not enabled. */
370 dos_cc_enabled = 0;
371}
372
373/* Called when the consensus has changed. Do appropriate actions for the
374 * circuit creation subsystem. */
375static void
376cc_consensus_has_changed(const networkstatus_t *ns)
377{
378 /* Looking at the consensus, is the circuit creation subsystem enabled? If
379 * not and it was enabled before, clean it up. */
380 if (dos_cc_enabled && !get_param_cc_enabled(ns)) {
381 cc_free_all();
382 }
383}
384
385/** Return the number of circuits we allow per second under the current
386 * configuration. */
387STATIC uint64_t
388get_circuit_rate_per_second(void)
389{
390 return dos_cc_circuit_rate;
391}
392
393/* Given the circuit creation client statistics object, refill the circuit
394 * bucket if needed. This also works if the bucket was never filled in the
395 * first place. The addr is only used for logging purposes. */
396STATIC void
397cc_stats_refill_bucket(cc_client_stats_t *stats, const tor_addr_t *addr)
398{
399 uint32_t new_circuit_bucket_count;
400 uint64_t num_token, elapsed_time_last_refill = 0, circuit_rate = 0;
401 time_t now;
402 int64_t last_refill_ts;
403
404 tor_assert(stats);
405 tor_assert(addr);
406
407 now = approx_time();
408 last_refill_ts = (int64_t)stats->last_circ_bucket_refill_ts;
409
410 /* If less than a second has elapsed, don't add any tokens.
411 * Note: If a relay's clock is ever 0, any new clients won't get a refill
412 * until the next second. But a relay that thinks it is 1970 will never
413 * validate the public consensus. */
414 if ((int64_t)now == last_refill_ts) {
415 goto done;
416 }
417
418 /* At this point, we know we might need to add token to the bucket. We'll
419 * first get the circuit rate that is how many circuit are we allowed to do
420 * per second. */
421 circuit_rate = get_circuit_rate_per_second();
422
423 /* We've never filled the bucket so fill it with the maximum being the burst
424 * and we are done.
425 * Note: If a relay's clock is ever 0, all clients that were last refilled
426 * in that zero second will get a full refill here. */
427 if (last_refill_ts == 0) {
428 num_token = dos_cc_circuit_burst;
429 goto end;
430 }
431
432 /* Our clock jumped backward so fill it up to the maximum. Not filling it
433 * could trigger a detection for a valid client. Also, if the clock jumped
434 * negative but we didn't notice until the elapsed time became positive
435 * again, then we potentially spent many seconds not refilling the bucket
436 * when we should have been refilling it. But the fact that we didn't notice
437 * until now means that no circuit creation requests came in during that
438 * time, so the client doesn't end up punished that much from this hopefully
439 * rare situation.*/
440 if ((int64_t)now < last_refill_ts) {
441 /* Use the maximum allowed value of token. */
442 num_token = dos_cc_circuit_burst;
443 goto end;
444 }
445
446 /* How many seconds have elapsed between now and the last refill?
447 * This subtraction can't underflow, because now >= last_refill_ts.
448 * And it can't overflow, because INT64_MAX - (-INT64_MIN) == UINT64_MAX. */
449 elapsed_time_last_refill = (uint64_t)now - last_refill_ts;
450
451 /* If the elapsed time is very large, it means our clock jumped forward.
452 * If the multiplication would overflow, use the maximum allowed value. */
453 if (elapsed_time_last_refill > UINT32_MAX) {
454 num_token = dos_cc_circuit_burst;
455 goto end;
456 }
457
458 /* Compute how many circuits we are allowed in that time frame which we'll
459 * add to the bucket. This can't overflow, because both multiplicands
460 * are less than or equal to UINT32_MAX, and num_token is uint64_t. */
461 num_token = elapsed_time_last_refill * circuit_rate;
462
463 end:
464 /* If the sum would overflow, use the maximum allowed value. */
465 if (num_token > UINT32_MAX - stats->circuit_bucket) {
466 new_circuit_bucket_count = dos_cc_circuit_burst;
467 } else {
468 /* We cap the bucket to the burst value else this could overflow uint32_t
469 * over time. */
470 new_circuit_bucket_count = MIN(stats->circuit_bucket + (uint32_t)num_token,
471 dos_cc_circuit_burst);
472 }
473
474 /* This function is not allowed to make the bucket count larger than the
475 * burst value */
476 tor_assert_nonfatal(new_circuit_bucket_count <= dos_cc_circuit_burst);
477 /* This function is not allowed to make the bucket count smaller, unless it
478 * is decreasing it to a newly configured, lower burst value. We allow the
479 * bucket to stay the same size, in case the circuit rate is zero. */
480 tor_assert_nonfatal(new_circuit_bucket_count >= stats->circuit_bucket ||
481 new_circuit_bucket_count == dos_cc_circuit_burst);
482
483 log_debug(LD_DOS, "DoS address %s has its circuit bucket value: %" PRIu32
484 ". Filling it to %" PRIu32 ". Circuit rate is %" PRIu64
485 ". Elapsed time is %" PRIi64,
486 fmt_addr(addr), stats->circuit_bucket, new_circuit_bucket_count,
487 circuit_rate, (int64_t)elapsed_time_last_refill);
488
489 stats->circuit_bucket = new_circuit_bucket_count;
490 stats->last_circ_bucket_refill_ts = now;
491
492 done:
493 return;
494}
495
496/* Return true iff the circuit bucket is down to 0 and the number of
497 * concurrent connections is greater or equal the minimum threshold set the
498 * consensus parameter. */
499static int
500cc_has_exhausted_circuits(const dos_client_stats_t *stats)
501{
502 tor_assert(stats);
503 return stats->cc_stats.circuit_bucket == 0 &&
504 stats->conn_stats.concurrent_count >= dos_cc_min_concurrent_conn;
505}
506
507/* Mark client address by setting a timestamp in the stats object which tells
508 * us until when it is marked as positively detected. */
509static void
510cc_mark_client(cc_client_stats_t *stats)
511{
512 tor_assert(stats);
513 /* We add a random offset of a maximum of half the defense time so it is
514 * less predictable. */
515 stats->marked_until_ts =
516 approx_time() + dos_cc_defense_time_period +
517 crypto_rand_int_range(1, dos_cc_defense_time_period / 2);
518}
519
520/* Return true iff the given channel address is marked as malicious. This is
521 * called a lot and part of the fast path of handling cells. It has to remain
522 * as fast as we can. */
523static int
524cc_channel_addr_is_marked(channel_t *chan)
525{
526 time_t now;
527 tor_addr_t addr;
528 clientmap_entry_t *entry;
529 cc_client_stats_t *stats = NULL;
530
531 if (chan == NULL) {
532 goto end;
533 }
534 /* Must be a client connection else we ignore. */
535 if (!channel_is_client(chan)) {
536 goto end;
537 }
538 /* Without an IP address, nothing can work. */
539 if (!channel_get_addr_if_possible(chan, &addr)) {
540 goto end;
541 }
542
543 /* We are only interested in client connection from the geoip cache. */
544 entry = geoip_lookup_client(&addr, NULL, GEOIP_CLIENT_CONNECT);
545 if (entry == NULL) {
546 /* We can have a connection creating circuits but not tracked by the geoip
547 * cache. Once this DoS subsystem is enabled, we can end up here with no
548 * entry for the channel. */
549 goto end;
550 }
551 now = approx_time();
552 stats = &entry->dos_stats.cc_stats;
553
554 end:
555 return stats && stats->marked_until_ts >= now;
556}
557
558/* Concurrent connection private API. */
559
560/* Mark client connection stats by setting a timestamp which tells us until
561 * when it is marked as positively detected. */
562static void
563conn_mark_client(conn_client_stats_t *stats)
564{
565 tor_assert(stats);
566
567 /* We add a random offset of a maximum of half the defense time so it is
568 * less predictable and thus more difficult to game. */
569 stats->marked_until_ts =
570 approx_time() + dos_conn_connect_defense_time_period +
571 crypto_rand_int_range(1, dos_conn_connect_defense_time_period / 2);
572}
573
574/* Free everything for the connection DoS mitigation subsystem. */
575static void
576conn_free_all(void)
577{
578 dos_conn_enabled = 0;
579}
580
581/* Called when the consensus has changed. Do appropriate actions for the
582 * connection mitigation subsystem. */
583static void
584conn_consensus_has_changed(const networkstatus_t *ns)
585{
586 /* Looking at the consensus, is the connection mitigation subsystem enabled?
587 * If not and it was enabled before, clean it up. */
588 if (dos_conn_enabled && !get_param_conn_enabled(ns)) {
589 conn_free_all();
590 }
591}
592
593/** Called when a new client connection has arrived. The following will update
594 * the client connection statistics.
595 *
596 * The addr is used for logging purposes only.
597 *
598 * If the connect counter reaches its limit, it is marked. */
599static void
600conn_update_on_connect(conn_client_stats_t *stats, const tor_addr_t *addr)
601{
602 tor_assert(stats);
603 tor_assert(addr);
604
605 /* Update concurrent count for this new connect. */
606 stats->concurrent_count++;
607
608 /* Refill connect connection count. */
609 token_bucket_ctr_refill(&stats->connect_count,
610 (uint32_t) monotime_coarse_absolute_sec());
611
612 /* Decrement counter for this new connection. */
613 if (token_bucket_ctr_get(&stats->connect_count) > 0) {
614 token_bucket_ctr_dec(&stats->connect_count, 1);
615 }
616
617 /* Assess connect counter. Mark it if counter is down to 0 and we haven't
618 * marked it before or it was reset. This is to avoid to re-mark it over and
619 * over again extending continuously the blocked time. */
620 if (token_bucket_ctr_get(&stats->connect_count) == 0 &&
621 stats->marked_until_ts == 0) {
622 conn_mark_client(stats);
623 }
624
625 log_debug(LD_DOS, "Client address %s has now %u concurrent connections. "
626 "Remaining %" TOR_PRIuSZ "/sec connections are allowed.",
627 fmt_addr(addr), stats->concurrent_count,
628 token_bucket_ctr_get(&stats->connect_count));
629}
630
631/** Called when a client connection is closed. The following will update
632 * the client connection statistics.
633 *
634 * The addr is used for logging purposes only. */
635static void
636conn_update_on_close(conn_client_stats_t *stats, const tor_addr_t *addr)
637{
638 /* Extra super duper safety. Going below 0 means an underflow which could
639 * lead to most likely a false positive. In theory, this should never happen
640 * but let's be extra safe. */
641 if (BUG(stats->concurrent_count == 0)) {
642 return;
643 }
644
645 stats->concurrent_count--;
646 log_debug(LD_DOS, "Client address %s has lost a connection. Concurrent "
647 "connections are now at %u",
648 fmt_addr(addr), stats->concurrent_count);
649}
650
651/* General private API */
652
653/* Return true iff we have at least one DoS detection enabled. This is used to
654 * decide if we need to allocate any kind of high level DoS object. */
655static inline int
656dos_is_enabled(void)
657{
658 return (dos_cc_enabled || dos_conn_enabled);
659}
660
661/* Circuit creation public API. */
662
663/** Return the number of rejected circuits. */
664uint64_t
665dos_get_num_cc_rejected(void)
666{
667 return cc_num_rejected_cells;
668}
669
670/** Return the number of marked addresses. */
671uint32_t
672dos_get_num_cc_marked_addr(void)
673{
674 return cc_num_marked_addrs;
675}
676
677/** Return the number of marked addresses due to max queue limit reached. */
678uint32_t
679dos_get_num_cc_marked_addr_maxq(void)
680{
681 return cc_num_marked_addrs_max_queue;
682}
683
684/** Return number of concurrent connections rejected. */
685uint64_t
686dos_get_num_conn_addr_rejected(void)
687{
688 return conn_num_addr_rejected;
689}
690
691/** Return the number of connection rejected. */
692uint64_t
693dos_get_num_conn_addr_connect_rejected(void)
694{
695 return conn_num_addr_connect_rejected;
696}
697
698/** Return the number of single hop refused. */
699uint64_t
700dos_get_num_single_hop_refused(void)
701{
702 return num_single_hop_client_refused;
703}
704
705/* Called when a CREATE cell is received from the given channel. */
706void
707dos_cc_new_create_cell(channel_t *chan)
708{
709 tor_addr_t addr;
710 clientmap_entry_t *entry;
711
712 tor_assert(chan);
713
714 /* Skip everything if not enabled. */
715 if (!dos_cc_enabled) {
716 goto end;
717 }
718
719 /* Must be a client connection else we ignore. */
720 if (!channel_is_client(chan)) {
721 goto end;
722 }
723 /* Without an IP address, nothing can work. */
724 if (!channel_get_addr_if_possible(chan, &addr)) {
725 goto end;
726 }
727
728 /* We are only interested in client connection from the geoip cache. */
729 entry = geoip_lookup_client(&addr, NULL, GEOIP_CLIENT_CONNECT);
730 if (entry == NULL) {
731 /* We can have a connection creating circuits but not tracked by the geoip
732 * cache. Once this DoS subsystem is enabled, we can end up here with no
733 * entry for the channel. */
734 goto end;
735 }
736
737 /* General comment. Even though the client can already be marked as
738 * malicious, we continue to track statistics. If it keeps going above
739 * threshold while marked, the defense period time will grow longer. There
740 * is really no point at unmarking a client that keeps DoSing us. */
741
742 /* First of all, we'll try to refill the circuit bucket opportunistically
743 * before we assess. */
744 cc_stats_refill_bucket(&entry->dos_stats.cc_stats, &addr);
745
746 /* Take a token out of the circuit bucket if we are above 0 so we don't
747 * underflow the bucket. */
748 if (entry->dos_stats.cc_stats.circuit_bucket > 0) {
749 entry->dos_stats.cc_stats.circuit_bucket--;
750 }
751
752 /* This is the detection. Assess at every CREATE cell if the client should
753 * get marked as malicious. This should be kept as fast as possible. */
754 if (cc_has_exhausted_circuits(&entry->dos_stats)) {
755 /* If this is the first time we mark this entry, log it.
756 * Under heavy DDoS, logging each time we mark would results in lots and
757 * lots of logs. */
758 if (entry->dos_stats.cc_stats.marked_until_ts == 0) {
759 log_debug(LD_DOS, "Detected circuit creation DoS by address: %s",
760 fmt_addr(&addr));
761 cc_num_marked_addrs++;
762 }
763 cc_mark_client(&entry->dos_stats.cc_stats);
764 }
765
766 end:
767 return;
768}
769
770/* Return the defense type that should be used for this circuit.
771 *
772 * This is part of the fast path and called a lot. */
773dos_cc_defense_type_t
774dos_cc_get_defense_type(channel_t *chan)
775{
776 tor_assert(chan);
777
778 /* Skip everything if not enabled. */
779 if (!dos_cc_enabled) {
780 goto end;
781 }
782
783 /* On an OR circuit, we'll check if the previous channel is a marked client
784 * connection detected by our DoS circuit creation mitigation subsystem. */
785 if (cc_channel_addr_is_marked(chan)) {
786 /* We've just assess that this circuit should trigger a defense for the
787 * cell it just seen. Note it down. */
788 cc_num_rejected_cells++;
789 return dos_cc_defense_type;
790 }
791
792 end:
793 return DOS_CC_DEFENSE_NONE;
794}
795
796/* Concurrent connection detection public API. */
797
798/* Return true iff the given address is permitted to open another connection.
799 * A defense value is returned for the caller to take appropriate actions. */
800dos_conn_defense_type_t
801dos_conn_addr_get_defense_type(const tor_addr_t *addr)
802{
803 clientmap_entry_t *entry;
804
805 tor_assert(addr);
806
807 /* Skip everything if not enabled. */
808 if (!dos_conn_enabled) {
809 goto end;
810 }
811
812 /* We are only interested in client connection from the geoip cache. */
813 entry = geoip_lookup_client(addr, NULL, GEOIP_CLIENT_CONNECT);
814 if (entry == NULL) {
815 goto end;
816 }
817
818 /* Is this address marked as making too many client connections? */
819 if (entry->dos_stats.conn_stats.marked_until_ts >= approx_time()) {
820 conn_num_addr_connect_rejected++;
821 return dos_conn_defense_type;
822 }
823 /* Reset it to 0 here so that if the marked timestamp has expired that is
824 * we've gone beyond it, we have to reset it so the detection can mark it
825 * again in the future. */
826 entry->dos_stats.conn_stats.marked_until_ts = 0;
827
828 /* Need to be above the maximum concurrent connection count to trigger a
829 * defense. */
830 if (entry->dos_stats.conn_stats.concurrent_count >
831 dos_conn_max_concurrent_count) {
832 conn_num_addr_rejected++;
833 return dos_conn_defense_type;
834 }
835
836 end:
837 return DOS_CONN_DEFENSE_NONE;
838}
839
840/* Stream creation public API. */
841
842/** Return the number of rejected stream and resolve. */
843uint64_t
844dos_get_num_stream_rejected(void)
845{
846 return stream_num_rejected;
847}
848
849/* Return the action to take against a BEGIN or RESOLVE cell. Return
850 * DOS_STREAM_DEFENSE_NONE when no action should be taken.
851 * Increment the appropriate counter when the cell was found to go over a
852 * limit. */
853dos_stream_defense_type_t
854dos_stream_new_begin_or_resolve_cell(or_circuit_t *circ)
855{
856 if (!dos_stream_enabled || circ == NULL)
857 return DOS_STREAM_DEFENSE_NONE;
858
860 (uint32_t) monotime_coarse_absolute_sec());
861
862 if (token_bucket_ctr_get(&circ->stream_limiter) > 0) {
863 token_bucket_ctr_dec(&circ->stream_limiter, 1);
864 return DOS_STREAM_DEFENSE_NONE;
865 }
866 /* if defense type is DOS_STREAM_DEFENSE_NONE but DoSStreamEnabled is true,
867 * we count offending cells as rejected, despite them being actually
868 * accepted. */
869 ++stream_num_rejected;
870 return dos_stream_defense_type;
871}
872
873/* Initialize the token bucket for stream rate limit on a circuit. */
874void
875dos_stream_init_circ_tbf(or_circuit_t *circ)
876{
877 token_bucket_ctr_init(&circ->stream_limiter, dos_stream_rate,
878 dos_stream_burst,
879 (uint32_t) monotime_coarse_absolute_sec());
880}
881
882/* General API */
883
884/* Take any appropriate actions for the given geoip entry that is about to get
885 * freed. This is called for every entry that is being freed.
886 *
887 * This function will clear out the connection tracked flag if the concurrent
888 * count of the entry is above 0 so if those connections end up being seen by
889 * this subsystem, we won't try to decrement the counter for a new geoip entry
890 * that might have been added after this call for the same address. */
891void
892dos_geoip_entry_about_to_free(const clientmap_entry_t *geoip_ent)
893{
894 tor_assert(geoip_ent);
895
896 /* The count is down to 0 meaning no connections right now, we can safely
897 * clear the geoip entry from the cache. */
898 if (geoip_ent->dos_stats.conn_stats.concurrent_count == 0) {
899 goto end;
900 }
901
902 /* For each connection matching the geoip entry address, we'll clear the
903 * tracked flag because the entry is about to get removed from the geoip
904 * cache. We do not try to decrement if the flag is not set. */
906 if (conn->type == CONN_TYPE_OR) {
907 or_connection_t *or_conn = TO_OR_CONN(conn);
908 if (!tor_addr_compare(&geoip_ent->addr, &TO_CONN(or_conn)->addr,
909 CMP_EXACT)) {
910 or_conn->tracked_for_dos_mitigation = 0;
911 }
912 }
913 } SMARTLIST_FOREACH_END(conn);
914
915 end:
916 return;
917}
918
919/** A new geoip client entry has been allocated, initialize its DoS object. */
920void
921dos_geoip_entry_init(clientmap_entry_t *geoip_ent)
922{
923 tor_assert(geoip_ent);
924
925 /* Initialize the connection count counter with the rate and burst
926 * parameters taken either from configuration or consensus.
927 *
928 * We do this even if the DoS connection detection is not enabled because it
929 * can be enabled at runtime and these counters need to be valid. */
930 token_bucket_ctr_init(&geoip_ent->dos_stats.conn_stats.connect_count,
931 dos_conn_connect_rate, dos_conn_connect_burst,
932 (uint32_t) monotime_coarse_absolute_sec());
933}
934
935/** Note that the given channel has sent outbound the maximum amount of cell
936 * allowed on the next channel. */
937void
938dos_note_circ_max_outq(const channel_t *chan)
939{
940 tor_addr_t addr;
941 clientmap_entry_t *entry;
942
943 tor_assert(chan);
944
945 /* Skip everything if circuit creation defense is disabled. */
946 if (!dos_cc_enabled) {
947 goto end;
948 }
949
950 /* Must be a client connection else we ignore. */
951 if (!channel_is_client(chan)) {
952 goto end;
953 }
954 /* Without an IP address, nothing can work. */
955 if (!channel_get_addr_if_possible(chan, &addr)) {
956 goto end;
957 }
958
959 /* We are only interested in client connection from the geoip cache. */
960 entry = geoip_lookup_client(&addr, NULL, GEOIP_CLIENT_CONNECT);
961 if (entry == NULL) {
962 goto end;
963 }
964
965 /* Is the client marked? If yes, just ignore. */
966 if (entry->dos_stats.cc_stats.marked_until_ts >= approx_time()) {
967 goto end;
968 }
969
970 /* If max outq parameter is 0, it means disabled, just ignore. */
971 if (dos_num_circ_max_outq == 0) {
972 goto end;
973 }
974
975 entry->dos_stats.num_circ_max_cell_queue_size++;
976
977 /* This is the detection. If we have reached the maximum amount of times a
978 * client IP is allowed to reach this limit, mark client. */
979 if (entry->dos_stats.num_circ_max_cell_queue_size >=
980 dos_num_circ_max_outq) {
981 /* Only account for this marked address if this is the first time we block
982 * it else our counter is inflated with non unique entries. */
983 if (entry->dos_stats.cc_stats.marked_until_ts == 0) {
984 cc_num_marked_addrs_max_queue++;
985 }
986 log_info(LD_DOS, "Detected outbound max circuit queue from addr: %s",
987 fmt_addr(&addr));
988 cc_mark_client(&entry->dos_stats.cc_stats);
989
990 /* Reset after being marked so once unmarked, we start back clean. */
991 entry->dos_stats.num_circ_max_cell_queue_size = 0;
992 }
993
994 end:
995 return;
996}
997
998/* Note down that we've just refused a single hop client. This increments a
999 * counter later used for the heartbeat. */
1000void
1001dos_note_refuse_single_hop_client(void)
1002{
1003 num_single_hop_client_refused++;
1004}
1005
1006/* Return true iff single hop client connection (ESTABLISH_RENDEZVOUS) should
1007 * be refused. */
1008int
1009dos_should_refuse_single_hop_client(void)
1010{
1011 /* If we aren't a public relay, this shouldn't apply to anything. */
1013 return 0;
1014 }
1015
1016 if (dos_get_options()->DoSRefuseSingleHopClientRendezvous != -1) {
1017 return dos_get_options()->DoSRefuseSingleHopClientRendezvous;
1018 }
1019
1020 return (int) networkstatus_get_param(NULL,
1021 "DoSRefuseSingleHopClientRendezvous",
1022 0 /* default */, 0, 1);
1023}
1024
1025/* Log a heartbeat message with some statistics. */
1026void
1027dos_log_heartbeat(void)
1028{
1029 smartlist_t *elems = smartlist_new();
1030
1031 /* Stats number coming from relay.c append_cell_to_circuit_queue(). */
1033 "%" PRIu64 " circuits killed with too many cells",
1035
1036 if (dos_cc_enabled) {
1038 "%" PRIu64 " circuits rejected, "
1039 "%" PRIu32 " marked addresses, "
1040 "%" PRIu32 " marked addresses for max queue",
1041 cc_num_rejected_cells, cc_num_marked_addrs,
1042 cc_num_marked_addrs_max_queue);
1043 } else {
1044 smartlist_add_asprintf(elems, "[DoSCircuitCreationEnabled disabled]");
1045 }
1046
1047 if (dos_conn_enabled) {
1049 "%" PRIu64 " same address concurrent "
1050 "connections rejected", conn_num_addr_rejected);
1052 "%" PRIu64 " connections rejected",
1053 conn_num_addr_connect_rejected);
1054 } else {
1055 smartlist_add_asprintf(elems, "[DoSConnectionEnabled disabled]");
1056 }
1057
1058 if (dos_should_refuse_single_hop_client()) {
1060 "%" PRIu64 " single hop clients refused",
1061 num_single_hop_client_refused);
1062 } else {
1064 "[DoSRefuseSingleHopClientRendezvous disabled]");
1065 }
1066
1067 if (dos_stream_enabled) {
1069 "%" PRIu64 " stream rejected",
1070 stream_num_rejected);
1071 } else {
1072 smartlist_add_asprintf(elems, "[DoSStreamCreationEnabled disabled]");
1073 }
1074
1075 /* HS DoS stats. */
1077 "%" PRIu64 " INTRODUCE2 rejected",
1079
1080 char *msg = smartlist_join_strings(elems, ", ", 0, NULL);
1081
1082 log_notice(LD_HEARTBEAT,
1083 "Heartbeat: DoS mitigation since startup: %s.", msg);
1084
1085 tor_free(msg);
1086 SMARTLIST_FOREACH(elems, char *, e, tor_free(e));
1087 smartlist_free(elems);
1088}
1089
1090/* Called when a new client connection has been established on the given
1091 * address. */
1092void
1093dos_new_client_conn(or_connection_t *or_conn, const char *transport_name)
1094{
1095 clientmap_entry_t *entry;
1096
1097 tor_assert(or_conn);
1098 tor_assert_nonfatal(!or_conn->tracked_for_dos_mitigation);
1099
1100 /* Past that point, we know we have at least one DoS detection subsystem
1101 * enabled so we'll start allocating stuff. */
1102 if (!dos_is_enabled()) {
1103 goto end;
1104 }
1105
1106 /* We are only interested in client connection from the geoip cache. */
1107 entry = geoip_lookup_client(&TO_CONN(or_conn)->addr, transport_name,
1109 if (BUG(entry == NULL)) {
1110 /* Should never happen because we note down the address in the geoip
1111 * cache before this is called. */
1112 goto end;
1113 }
1114
1115 /* Update stats from this new connect. */
1116 conn_update_on_connect(&entry->dos_stats.conn_stats,
1117 &TO_CONN(or_conn)->addr);
1118
1119 or_conn->tracked_for_dos_mitigation = 1;
1120
1121 end:
1122 return;
1123}
1124
1125/* Called when a client connection for the given IP address has been closed. */
1126void
1127dos_close_client_conn(const or_connection_t *or_conn)
1128{
1129 clientmap_entry_t *entry;
1130
1131 tor_assert(or_conn);
1132
1133 /* We have to decrement the count on tracked connection only even if the
1134 * subsystem has been disabled at runtime because it might be re-enabled
1135 * after and we need to keep a synchronized counter at all time. */
1136 if (!or_conn->tracked_for_dos_mitigation) {
1137 goto end;
1138 }
1139
1140 /* We are only interested in client connection from the geoip cache. */
1141 entry = geoip_lookup_client(&TO_CONN(or_conn)->addr, NULL,
1143 if (entry == NULL) {
1144 /* This can happen because we can close a connection before the channel
1145 * got to be noted down in the geoip cache. */
1146 goto end;
1147 }
1148
1149 /* Update stats from this new close. */
1150 conn_update_on_close(&entry->dos_stats.conn_stats, &TO_CONN(or_conn)->addr);
1151
1152 end:
1153 return;
1154}
1155
1156/* Called when the consensus has changed. We might have new consensus
1157 * parameters to look at. */
1158void
1159dos_consensus_has_changed(const networkstatus_t *ns)
1160{
1161 /* There are two ways to configure this subsystem, one at startup through
1162 * dos_init() which is called when the options are parsed. And this one
1163 * through the consensus. We don't want to enable any DoS mitigation if we
1164 * aren't a public relay. */
1166 return;
1167 }
1168
1169 cc_consensus_has_changed(ns);
1170 conn_consensus_has_changed(ns);
1171
1172 /* We were already enabled or we just became enabled but either way, set the
1173 * consensus parameters for all subsystems. */
1174 set_dos_parameters(ns);
1175}
1176
1177/* Return true iff the DoS mitigation subsystem is enabled. */
1178int
1179dos_enabled(void)
1180{
1181 return dos_is_enabled();
1182}
1183
1184/* Free everything from the Denial of Service subsystem. */
1185void
1186dos_free_all(void)
1187{
1188 /* Free the circuit creation mitigation subsystem. It is safe to do this
1189 * even if it wasn't initialized. */
1190 cc_free_all();
1191
1192 /* Free the connection mitigation subsystem. It is safe to do this even if
1193 * it wasn't initialized. */
1194 conn_free_all();
1195}
1196
1197/* Initialize the Denial of Service subsystem. */
1198void
1199dos_init(void)
1200{
1201 /* To initialize, we only need to get the parameters. */
1202 set_dos_parameters(NULL);
1203}
int tor_addr_compare(const tor_addr_t *addr1, const tor_addr_t *addr2, tor_addr_comparison_t how)
Definition: address.c:984
#define fmt_addr(a)
Definition: address.h:239
time_t approx_time(void)
Definition: approx_time.c:32
int channel_is_client(const channel_t *chan)
Definition: channel.c:2918
int channel_get_addr_if_possible(const channel_t *chan, tor_addr_t *addr_out)
Definition: channel.c:2860
Header file for channel.c.
Functions and types for monotonic times.
const or_options_t * get_options(void)
Definition: config.c:944
Header file for config.c.
Header file for connection.c.
#define CONN_TYPE_OR
Definition: connection.h:44
or_connection_t * TO_OR_CONN(connection_t *c)
Header file for connection_or.c.
Common functions for using (pseudo-)random number generators.
int crypto_rand_int_range(unsigned int min, unsigned int max)
Structure dos_options_t to hold options for the DoS subsystem.
Header for core/or/dos_sys.c.
Header file for geoip_stats.c.
@ GEOIP_CLIENT_CONNECT
Definition: geoip_stats.h:24
uint64_t hs_dos_get_intro2_rejected_count(void)
Definition: hs_dos.c:219
Header file containing denial of service defenses for the HS subsystem for all versions.
#define LD_DOS
Definition: log.h:113
#define LD_HEARTBEAT
Definition: log.h:103
smartlist_t * get_connection_array(void)
Definition: mainloop.c:443
Header file for mainloop.c.
#define tor_free(p)
Definition: malloc.h:56
int32_t networkstatus_get_param(const networkstatus_t *ns, const char *param_name, int32_t default_val, int32_t min_val, int32_t max_val)
Header file for networkstatus.c.
Header file for nodelist.c.
Master header file for Tor-specific functionality.
#define TO_CONN(c)
Definition: or.h:612
OR connection structure.
uint64_t stats_n_circ_max_cell_reached
Definition: relay.c:141
Header file for relay.c.
int public_server_mode(const or_options_t *options)
Definition: routermode.c:43
Header file for routermode.c.
void smartlist_add_asprintf(struct smartlist_t *sl, const char *pattern,...)
Definition: smartlist.c:36
char * smartlist_join_strings(smartlist_t *sl, const char *join, int terminate, size_t *len_out)
Definition: smartlist.c:279
smartlist_t * smartlist_new(void)
#define SMARTLIST_FOREACH_BEGIN(sl, type, var)
#define SMARTLIST_FOREACH(sl, type, var, cmd)
Definition: geoip_stats.h:79
uint32_t num_circ_max_cell_queue_size
Definition: dos.h:63
AUTOBOOL DoSConnectionEnabled
Definition: dos_options.inc:12
POSINT DoSStreamCreationRate
Definition: dos_options.inc:57
INT DoSCircuitCreationDefenseType
Definition: dos_options.inc:30
POSINT DoSCircuitCreationMinConnections
Definition: dos_options.inc:19
POSINT DoSStreamCreationBurst
Definition: dos_options.inc:60
INT DoSStreamCreationDefenseType
Definition: dos_options.inc:64
POSINT DoSCircuitCreationBurst
Definition: dos_options.inc:26
POSINT DoSConnectionConnectBurst
Definition: dos_options.inc:48
POSINT DoSConnectionConnectRate
Definition: dos_options.inc:51
POSINT DoSCircuitCreationRate
Definition: dos_options.inc:22
INT DoSConnectionDefenseType
Definition: dos_options.inc:42
AUTOBOOL DoSCircuitCreationEnabled
Definition: dos_options.inc:15
INTERVAL DoSCircuitCreationDefenseTimePeriod
Definition: dos_options.inc:35
AUTOBOOL DoSRefuseSingleHopClientRendezvous
Definition: dos_options.inc:45
INTERVAL DoSConnectionConnectDefenseTimePeriod
Definition: dos_options.inc:70
POSINT DoSConnectionMaxConcurrentCount
Definition: dos_options.inc:38
AUTOBOOL DoSStreamCreationEnabled
Definition: dos_options.inc:54
token_bucket_ctr_t stream_limiter
unsigned int tracked_for_dos_mitigation
#define STATIC
Definition: testsupport.h:32
#define MOCK_IMPL(rv, funcname, arglist)
Definition: testsupport.h:133
void token_bucket_ctr_init(token_bucket_ctr_t *bucket, uint32_t rate, uint32_t burst, uint32_t now_ts_sec)
Definition: token_bucket.c:267
void token_bucket_ctr_refill(token_bucket_ctr_t *bucket, uint32_t now_ts_sec)
Definition: token_bucket.c:296
#define tor_assert(expr)
Definition: util_bug.h:103