Line data Source code
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"
13 : #include "core/mainloop/connection.h"
14 : #include "core/mainloop/mainloop.h"
15 : #include "core/or/channel.h"
16 : #include "core/or/connection_or.h"
17 : #include "core/or/relay.h"
18 : #include "feature/hs/hs_dos.h"
19 : #include "feature/nodelist/networkstatus.h"
20 : #include "feature/nodelist/nodelist.h"
21 : #include "feature/relay/routermode.h"
22 : #include "feature/stats/geoip_stats.h"
23 : #include "lib/crypt_ops/crypto_rand.h"
24 :
25 : #include "core/or/dos.h"
26 : #include "core/or/dos_sys.h"
27 :
28 : #include "core/or/dos_options_st.h"
29 : #include "core/or/or_connection_st.h"
30 :
31 : /*
32 : * Circuit creation denial of service mitigation.
33 : *
34 : * Namespace used for this mitigation framework is "dos_cc_" where "cc" is for
35 : * Circuit Creation.
36 : */
37 :
38 : /* Is the circuit creation DoS mitigation enabled? */
39 : static unsigned int dos_cc_enabled = 0;
40 :
41 : /* Consensus parameters. They can be changed when a new consensus arrives.
42 : * They are initialized with the hardcoded default values. */
43 : static uint32_t dos_cc_min_concurrent_conn;
44 : static uint32_t dos_cc_circuit_rate;
45 : static uint32_t dos_cc_circuit_burst;
46 : static dos_cc_defense_type_t dos_cc_defense_type;
47 : static int32_t dos_cc_defense_time_period;
48 :
49 : /* Keep some stats for the heartbeat so we can report out. */
50 : static uint64_t cc_num_rejected_cells;
51 : static uint32_t cc_num_marked_addrs;
52 :
53 : /*
54 : * Concurrent connection denial of service mitigation.
55 : *
56 : * Namespace used for this mitigation framework is "dos_conn_".
57 : */
58 :
59 : /* Is the connection DoS mitigation enabled? */
60 : static unsigned int dos_conn_enabled = 0;
61 :
62 : /* Consensus parameters. They can be changed when a new consensus arrives.
63 : * They are initialized with the hardcoded default values. */
64 : static uint32_t dos_conn_max_concurrent_count;
65 : static dos_conn_defense_type_t dos_conn_defense_type;
66 : static uint32_t dos_conn_connect_rate = DOS_CONN_CONNECT_RATE_DEFAULT;
67 : static uint32_t dos_conn_connect_burst = DOS_CONN_CONNECT_BURST_DEFAULT;
68 : static int32_t dos_conn_connect_defense_time_period =
69 : DOS_CONN_CONNECT_DEFENSE_TIME_PERIOD_DEFAULT;
70 :
71 : /* Keep some stats for the heartbeat so we can report out. */
72 : static uint64_t conn_num_addr_rejected;
73 : static uint64_t conn_num_addr_connect_rejected;
74 :
75 : /*
76 : * General interface of the denial of service mitigation subsystem.
77 : */
78 :
79 : /* Keep stats for the heartbeat. */
80 : static uint64_t num_single_hop_client_refused;
81 :
82 : /* Return true iff the circuit creation mitigation is enabled. We look at the
83 : * consensus for this else a default value is returned. */
84 4 : MOCK_IMPL(STATIC unsigned int,
85 : get_param_cc_enabled, (const networkstatus_t *ns))
86 : {
87 4 : if (dos_get_options()->DoSCircuitCreationEnabled != -1) {
88 0 : return dos_get_options()->DoSCircuitCreationEnabled;
89 : }
90 :
91 4 : return !!networkstatus_get_param(ns, "DoSCircuitCreationEnabled",
92 : DOS_CC_ENABLED_DEFAULT, 0, 1);
93 : }
94 :
95 : /* Return the parameter for the minimum concurrent connection at which we'll
96 : * start counting circuit for a specific client address. */
97 : STATIC uint32_t
98 10 : get_param_cc_min_concurrent_connection(const networkstatus_t *ns)
99 : {
100 10 : if (dos_get_options()->DoSCircuitCreationMinConnections) {
101 0 : return dos_get_options()->DoSCircuitCreationMinConnections;
102 : }
103 10 : return networkstatus_get_param(ns, "DoSCircuitCreationMinConnections",
104 : DOS_CC_MIN_CONCURRENT_CONN_DEFAULT,
105 : 1, INT32_MAX);
106 : }
107 :
108 : /* Return the parameter for the time rate that is how many circuits over this
109 : * time span. */
110 : static uint32_t
111 9 : get_param_cc_circuit_rate(const networkstatus_t *ns)
112 : {
113 : /* This is in seconds. */
114 9 : if (dos_get_options()->DoSCircuitCreationRate) {
115 0 : return dos_get_options()->DoSCircuitCreationRate;
116 : }
117 9 : return networkstatus_get_param(ns, "DoSCircuitCreationRate",
118 : DOS_CC_CIRCUIT_RATE_DEFAULT,
119 : 1, INT32_MAX);
120 : }
121 :
122 : /* Return the parameter for the maximum circuit count for the circuit time
123 : * rate. */
124 : STATIC uint32_t
125 11 : get_param_cc_circuit_burst(const networkstatus_t *ns)
126 : {
127 11 : if (dos_get_options()->DoSCircuitCreationBurst) {
128 0 : return dos_get_options()->DoSCircuitCreationBurst;
129 : }
130 11 : return networkstatus_get_param(ns, "DoSCircuitCreationBurst",
131 : DOS_CC_CIRCUIT_BURST_DEFAULT,
132 : 1, INT32_MAX);
133 : }
134 :
135 : /* Return the consensus parameter of the circuit creation defense type. */
136 : static uint32_t
137 9 : get_param_cc_defense_type(const networkstatus_t *ns)
138 : {
139 9 : if (dos_get_options()->DoSCircuitCreationDefenseType) {
140 0 : return dos_get_options()->DoSCircuitCreationDefenseType;
141 : }
142 9 : return networkstatus_get_param(ns, "DoSCircuitCreationDefenseType",
143 : DOS_CC_DEFENSE_TYPE_DEFAULT,
144 : DOS_CC_DEFENSE_NONE, DOS_CC_DEFENSE_MAX);
145 : }
146 :
147 : /* Return the consensus parameter of the defense time period which is how much
148 : * time should we defend against a malicious client address. */
149 : static int32_t
150 9 : get_param_cc_defense_time_period(const networkstatus_t *ns)
151 : {
152 : /* Time in seconds. */
153 9 : if (dos_get_options()->DoSCircuitCreationDefenseTimePeriod) {
154 0 : return dos_get_options()->DoSCircuitCreationDefenseTimePeriod;
155 : }
156 9 : return networkstatus_get_param(ns, "DoSCircuitCreationDefenseTimePeriod",
157 : DOS_CC_DEFENSE_TIME_PERIOD_DEFAULT,
158 : 0, INT32_MAX);
159 : }
160 :
161 : /* Return true iff connection mitigation is enabled. We look at the consensus
162 : * for this else a default value is returned. */
163 5 : MOCK_IMPL(STATIC unsigned int,
164 : get_param_conn_enabled, (const networkstatus_t *ns))
165 : {
166 5 : if (dos_get_options()->DoSConnectionEnabled != -1) {
167 0 : return dos_get_options()->DoSConnectionEnabled;
168 : }
169 5 : return !!networkstatus_get_param(ns, "DoSConnectionEnabled",
170 : DOS_CONN_ENABLED_DEFAULT, 0, 1);
171 : }
172 :
173 : /* Return the consensus parameter for the maximum concurrent connection
174 : * allowed. */
175 : STATIC uint32_t
176 10 : get_param_conn_max_concurrent_count(const networkstatus_t *ns)
177 : {
178 10 : if (dos_get_options()->DoSConnectionMaxConcurrentCount) {
179 0 : return dos_get_options()->DoSConnectionMaxConcurrentCount;
180 : }
181 10 : return networkstatus_get_param(ns, "DoSConnectionMaxConcurrentCount",
182 : DOS_CONN_MAX_CONCURRENT_COUNT_DEFAULT,
183 : 1, INT32_MAX);
184 : }
185 :
186 : /* Return the consensus parameter of the connection defense type. */
187 : static uint32_t
188 9 : get_param_conn_defense_type(const networkstatus_t *ns)
189 : {
190 9 : if (dos_get_options()->DoSConnectionDefenseType) {
191 0 : return dos_get_options()->DoSConnectionDefenseType;
192 : }
193 9 : return networkstatus_get_param(ns, "DoSConnectionDefenseType",
194 : DOS_CONN_DEFENSE_TYPE_DEFAULT,
195 : DOS_CONN_DEFENSE_NONE, DOS_CONN_DEFENSE_MAX);
196 : }
197 :
198 : /* Return the connection connect rate parameters either from the configuration
199 : * file or, if not found, consensus parameter. */
200 : static uint32_t
201 9 : get_param_conn_connect_rate(const networkstatus_t *ns)
202 : {
203 9 : if (dos_get_options()->DoSConnectionConnectRate) {
204 0 : return dos_get_options()->DoSConnectionConnectRate;
205 : }
206 9 : return networkstatus_get_param(ns, "DoSConnectionConnectRate",
207 : DOS_CONN_CONNECT_RATE_DEFAULT,
208 : 1, INT32_MAX);
209 : }
210 :
211 : /* Return the connection connect burst parameters either from the
212 : * configuration file or, if not found, consensus parameter. */
213 : STATIC uint32_t
214 10 : get_param_conn_connect_burst(const networkstatus_t *ns)
215 : {
216 10 : if (dos_get_options()->DoSConnectionConnectBurst) {
217 0 : return dos_get_options()->DoSConnectionConnectBurst;
218 : }
219 10 : return networkstatus_get_param(ns, "DoSConnectionConnectBurst",
220 : DOS_CONN_CONNECT_BURST_DEFAULT,
221 : 1, INT32_MAX);
222 : }
223 :
224 : /* Return the connection connect defense time period from the configuration
225 : * file or, if not found, the consensus parameter. */
226 : static int32_t
227 9 : get_param_conn_connect_defense_time_period(const networkstatus_t *ns)
228 : {
229 : /* Time in seconds. */
230 9 : if (dos_get_options()->DoSConnectionConnectDefenseTimePeriod) {
231 0 : return dos_get_options()->DoSConnectionConnectDefenseTimePeriod;
232 : }
233 9 : return networkstatus_get_param(ns, "DoSConnectionConnectDefenseTimePeriod",
234 : DOS_CONN_CONNECT_DEFENSE_TIME_PERIOD_DEFAULT,
235 : DOS_CONN_CONNECT_DEFENSE_TIME_PERIOD_MIN,
236 : INT32_MAX);
237 : }
238 :
239 : /* Set circuit creation parameters located in the consensus or their default
240 : * if none are present. Called at initialization or when the consensus
241 : * changes. */
242 : static void
243 9 : set_dos_parameters(const networkstatus_t *ns)
244 : {
245 : /* Get the default consensus param values. */
246 9 : dos_cc_enabled = get_param_cc_enabled(ns);
247 9 : dos_cc_min_concurrent_conn = get_param_cc_min_concurrent_connection(ns);
248 9 : dos_cc_circuit_rate = get_param_cc_circuit_rate(ns);
249 9 : dos_cc_circuit_burst = get_param_cc_circuit_burst(ns);
250 9 : dos_cc_defense_time_period = get_param_cc_defense_time_period(ns);
251 9 : dos_cc_defense_type = get_param_cc_defense_type(ns);
252 :
253 : /* Connection detection. */
254 9 : dos_conn_enabled = get_param_conn_enabled(ns);
255 9 : dos_conn_max_concurrent_count = get_param_conn_max_concurrent_count(ns);
256 9 : dos_conn_defense_type = get_param_conn_defense_type(ns);
257 9 : dos_conn_connect_rate = get_param_conn_connect_rate(ns);
258 9 : dos_conn_connect_burst = get_param_conn_connect_burst(ns);
259 18 : dos_conn_connect_defense_time_period =
260 9 : get_param_conn_connect_defense_time_period(ns);
261 9 : }
262 :
263 : /* Free everything for the circuit creation DoS mitigation subsystem. */
264 : static void
265 240 : cc_free_all(void)
266 : {
267 : /* If everything is freed, the circuit creation subsystem is not enabled. */
268 240 : dos_cc_enabled = 0;
269 240 : }
270 :
271 : /* Called when the consensus has changed. Do appropriate actions for the
272 : * circuit creation subsystem. */
273 : static void
274 0 : cc_consensus_has_changed(const networkstatus_t *ns)
275 : {
276 : /* Looking at the consensus, is the circuit creation subsystem enabled? If
277 : * not and it was enabled before, clean it up. */
278 0 : if (dos_cc_enabled && !get_param_cc_enabled(ns)) {
279 0 : cc_free_all();
280 : }
281 0 : }
282 :
283 : /** Return the number of circuits we allow per second under the current
284 : * configuration. */
285 : STATIC uint64_t
286 13 : get_circuit_rate_per_second(void)
287 : {
288 13 : return dos_cc_circuit_rate;
289 : }
290 :
291 : /* Given the circuit creation client statistics object, refill the circuit
292 : * bucket if needed. This also works if the bucket was never filled in the
293 : * first place. The addr is only used for logging purposes. */
294 : STATIC void
295 829 : cc_stats_refill_bucket(cc_client_stats_t *stats, const tor_addr_t *addr)
296 : {
297 829 : uint32_t new_circuit_bucket_count;
298 829 : uint64_t num_token, elapsed_time_last_refill = 0, circuit_rate = 0;
299 829 : time_t now;
300 829 : int64_t last_refill_ts;
301 :
302 829 : tor_assert(stats);
303 829 : tor_assert(addr);
304 :
305 829 : now = approx_time();
306 829 : last_refill_ts = (int64_t)stats->last_circ_bucket_refill_ts;
307 :
308 : /* If less than a second has elapsed, don't add any tokens.
309 : * Note: If a relay's clock is ever 0, any new clients won't get a refill
310 : * until the next second. But a relay that thinks it is 1970 will never
311 : * validate the public consensus. */
312 829 : if ((int64_t)now == last_refill_ts) {
313 817 : goto done;
314 : }
315 :
316 : /* At this point, we know we might need to add token to the bucket. We'll
317 : * first get the circuit rate that is how many circuit are we allowed to do
318 : * per second. */
319 12 : circuit_rate = get_circuit_rate_per_second();
320 :
321 : /* We've never filled the bucket so fill it with the maximum being the burst
322 : * and we are done.
323 : * Note: If a relay's clock is ever 0, all clients that were last refilled
324 : * in that zero second will get a full refill here. */
325 12 : if (last_refill_ts == 0) {
326 2 : num_token = dos_cc_circuit_burst;
327 2 : goto end;
328 : }
329 :
330 : /* Our clock jumped backward so fill it up to the maximum. Not filling it
331 : * could trigger a detection for a valid client. Also, if the clock jumped
332 : * negative but we didn't notice until the elapsed time became positive
333 : * again, then we potentially spent many seconds not refilling the bucket
334 : * when we should have been refilling it. But the fact that we didn't notice
335 : * until now means that no circuit creation requests came in during that
336 : * time, so the client doesn't end up punished that much from this hopefully
337 : * rare situation.*/
338 10 : if ((int64_t)now < last_refill_ts) {
339 : /* Use the maximum allowed value of token. */
340 3 : num_token = dos_cc_circuit_burst;
341 3 : goto end;
342 : }
343 :
344 : /* How many seconds have elapsed between now and the last refill?
345 : * This subtraction can't underflow, because now >= last_refill_ts.
346 : * And it can't overflow, because INT64_MAX - (-INT64_MIN) == UINT64_MAX. */
347 7 : elapsed_time_last_refill = (uint64_t)now - last_refill_ts;
348 :
349 : /* If the elapsed time is very large, it means our clock jumped forward.
350 : * If the multiplication would overflow, use the maximum allowed value. */
351 7 : if (elapsed_time_last_refill > UINT32_MAX) {
352 1 : num_token = dos_cc_circuit_burst;
353 1 : goto end;
354 : }
355 :
356 : /* Compute how many circuits we are allowed in that time frame which we'll
357 : * add to the bucket. This can't overflow, because both multiplicands
358 : * are less than or equal to UINT32_MAX, and num_token is uint64_t. */
359 6 : num_token = elapsed_time_last_refill * circuit_rate;
360 :
361 12 : end:
362 : /* If the sum would overflow, use the maximum allowed value. */
363 12 : if (num_token > UINT32_MAX - stats->circuit_bucket) {
364 1 : new_circuit_bucket_count = dos_cc_circuit_burst;
365 : } else {
366 : /* We cap the bucket to the burst value else this could overflow uint32_t
367 : * over time. */
368 11 : new_circuit_bucket_count = MIN(stats->circuit_bucket + (uint32_t)num_token,
369 : dos_cc_circuit_burst);
370 : }
371 :
372 : /* This function is not allowed to make the bucket count larger than the
373 : * burst value */
374 12 : tor_assert_nonfatal(new_circuit_bucket_count <= dos_cc_circuit_burst);
375 : /* This function is not allowed to make the bucket count smaller, unless it
376 : * is decreasing it to a newly configured, lower burst value. We allow the
377 : * bucket to stay the same size, in case the circuit rate is zero. */
378 12 : tor_assert_nonfatal(new_circuit_bucket_count >= stats->circuit_bucket ||
379 : new_circuit_bucket_count == dos_cc_circuit_burst);
380 :
381 12 : log_debug(LD_DOS, "DoS address %s has its circuit bucket value: %" PRIu32
382 : ". Filling it to %" PRIu32 ". Circuit rate is %" PRIu64
383 : ". Elapsed time is %" PRIi64,
384 : fmt_addr(addr), stats->circuit_bucket, new_circuit_bucket_count,
385 : circuit_rate, (int64_t)elapsed_time_last_refill);
386 :
387 12 : stats->circuit_bucket = new_circuit_bucket_count;
388 12 : stats->last_circ_bucket_refill_ts = now;
389 :
390 829 : done:
391 829 : return;
392 : }
393 :
394 : /* Return true iff the circuit bucket is down to 0 and the number of
395 : * concurrent connections is greater or equal the minimum threshold set the
396 : * consensus parameter. */
397 : static int
398 819 : cc_has_exhausted_circuits(const dos_client_stats_t *stats)
399 : {
400 819 : tor_assert(stats);
401 819 : return stats->cc_stats.circuit_bucket == 0 &&
402 11 : stats->conn_stats.concurrent_count >= dos_cc_min_concurrent_conn;
403 : }
404 :
405 : /* Mark client address by setting a timestamp in the stats object which tells
406 : * us until when it is marked as positively detected. */
407 : static void
408 1 : cc_mark_client(cc_client_stats_t *stats)
409 : {
410 1 : tor_assert(stats);
411 : /* We add a random offset of a maximum of half the defense time so it is
412 : * less predictable. */
413 2 : stats->marked_until_ts =
414 1 : approx_time() + dos_cc_defense_time_period +
415 1 : crypto_rand_int_range(1, dos_cc_defense_time_period / 2);
416 1 : }
417 :
418 : /* Return true iff the given channel address is marked as malicious. This is
419 : * called a lot and part of the fast path of handling cells. It has to remain
420 : * as fast as we can. */
421 : static int
422 2 : cc_channel_addr_is_marked(channel_t *chan)
423 : {
424 2 : time_t now;
425 2 : tor_addr_t addr;
426 2 : clientmap_entry_t *entry;
427 2 : cc_client_stats_t *stats = NULL;
428 :
429 2 : if (chan == NULL) {
430 0 : goto end;
431 : }
432 : /* Must be a client connection else we ignore. */
433 2 : if (!channel_is_client(chan)) {
434 0 : goto end;
435 : }
436 : /* Without an IP address, nothing can work. */
437 2 : if (!channel_get_addr_if_possible(chan, &addr)) {
438 0 : goto end;
439 : }
440 :
441 : /* We are only interested in client connection from the geoip cache. */
442 2 : entry = geoip_lookup_client(&addr, NULL, GEOIP_CLIENT_CONNECT);
443 2 : if (entry == NULL) {
444 : /* We can have a connection creating circuits but not tracked by the geoip
445 : * cache. Once this DoS subsystem is enabled, we can end up here with no
446 : * entry for the channel. */
447 0 : goto end;
448 : }
449 2 : now = approx_time();
450 2 : stats = &entry->dos_stats.cc_stats;
451 :
452 2 : end:
453 2 : return stats && stats->marked_until_ts >= now;
454 : }
455 :
456 : /* Concurrent connection private API. */
457 :
458 : /* Mark client connection stats by setting a timestamp which tells us until
459 : * when it is marked as positively detected. */
460 : static void
461 1 : conn_mark_client(conn_client_stats_t *stats)
462 : {
463 1 : tor_assert(stats);
464 :
465 : /* We add a random offset of a maximum of half the defense time so it is
466 : * less predictable and thus more difficult to game. */
467 2 : stats->marked_until_ts =
468 1 : approx_time() + dos_conn_connect_defense_time_period +
469 1 : crypto_rand_int_range(1, dos_conn_connect_defense_time_period / 2);
470 1 : }
471 :
472 : /* Free everything for the connection DoS mitigation subsystem. */
473 : static void
474 240 : conn_free_all(void)
475 : {
476 240 : dos_conn_enabled = 0;
477 240 : }
478 :
479 : /* Called when the consensus has changed. Do appropriate actions for the
480 : * connection mitigation subsystem. */
481 : static void
482 0 : conn_consensus_has_changed(const networkstatus_t *ns)
483 : {
484 : /* Looking at the consensus, is the connection mitigation subsystem enabled?
485 : * If not and it was enabled before, clean it up. */
486 0 : if (dos_conn_enabled && !get_param_conn_enabled(ns)) {
487 0 : conn_free_all();
488 : }
489 0 : }
490 :
491 : /** Called when a new client connection has arrived. The following will update
492 : * the client connection statistics.
493 : *
494 : * The addr is used for logging purposes only.
495 : *
496 : * If the connect counter reaches its limit, it is marked. */
497 : static void
498 148 : conn_update_on_connect(conn_client_stats_t *stats, const tor_addr_t *addr)
499 : {
500 148 : tor_assert(stats);
501 148 : tor_assert(addr);
502 :
503 : /* Update concurrent count for this new connect. */
504 148 : stats->concurrent_count++;
505 :
506 : /* Refill connect connection count. */
507 148 : token_bucket_ctr_refill(&stats->connect_count, (uint32_t) approx_time());
508 :
509 : /* Decrement counter for this new connection. */
510 148 : if (token_bucket_ctr_get(&stats->connect_count) > 0) {
511 148 : token_bucket_ctr_dec(&stats->connect_count, 1);
512 : }
513 :
514 : /* Assess connect counter. Mark it if counter is down to 0 and we haven't
515 : * marked it before or it was reset. This is to avoid to re-mark it over and
516 : * over again extending continously the blocked time. */
517 148 : if (token_bucket_ctr_get(&stats->connect_count) == 0 &&
518 1 : stats->marked_until_ts == 0) {
519 1 : conn_mark_client(stats);
520 : }
521 :
522 148 : log_debug(LD_DOS, "Client address %s has now %u concurrent connections. "
523 : "Remaining %" TOR_PRIuSZ "/sec connections are allowed.",
524 : fmt_addr(addr), stats->concurrent_count,
525 : token_bucket_ctr_get(&stats->connect_count));
526 148 : }
527 :
528 : /** Called when a client connection is closed. The following will update
529 : * the client connection statistics.
530 : *
531 : * The addr is used for logging purposes only. */
532 : static void
533 1 : conn_update_on_close(conn_client_stats_t *stats, const tor_addr_t *addr)
534 : {
535 : /* Extra super duper safety. Going below 0 means an underflow which could
536 : * lead to most likely a false positive. In theory, this should never happen
537 : * but lets be extra safe. */
538 1 : if (BUG(stats->concurrent_count == 0)) {
539 0 : return;
540 : }
541 :
542 1 : stats->concurrent_count--;
543 1 : log_debug(LD_DOS, "Client address %s has lost a connection. Concurrent "
544 : "connections are now at %u",
545 : fmt_addr(addr), stats->concurrent_count);
546 : }
547 :
548 : /* General private API */
549 :
550 : /* Return true iff we have at least one DoS detection enabled. This is used to
551 : * decide if we need to allocate any kind of high level DoS object. */
552 : static inline int
553 390 : dos_is_enabled(void)
554 : {
555 390 : return (dos_cc_enabled || dos_conn_enabled);
556 : }
557 :
558 : /* Circuit creation public API. */
559 :
560 : /* Called when a CREATE cell is received from the given channel. */
561 : void
562 819 : dos_cc_new_create_cell(channel_t *chan)
563 : {
564 819 : tor_addr_t addr;
565 819 : clientmap_entry_t *entry;
566 :
567 819 : tor_assert(chan);
568 :
569 : /* Skip everything if not enabled. */
570 819 : if (!dos_cc_enabled) {
571 0 : goto end;
572 : }
573 :
574 : /* Must be a client connection else we ignore. */
575 819 : if (!channel_is_client(chan)) {
576 0 : goto end;
577 : }
578 : /* Without an IP address, nothing can work. */
579 819 : if (!channel_get_addr_if_possible(chan, &addr)) {
580 0 : goto end;
581 : }
582 :
583 : /* We are only interested in client connection from the geoip cache. */
584 819 : entry = geoip_lookup_client(&addr, NULL, GEOIP_CLIENT_CONNECT);
585 819 : if (entry == NULL) {
586 : /* We can have a connection creating circuits but not tracked by the geoip
587 : * cache. Once this DoS subsystem is enabled, we can end up here with no
588 : * entry for the channel. */
589 0 : goto end;
590 : }
591 :
592 : /* General comment. Even though the client can already be marked as
593 : * malicious, we continue to track statistics. If it keeps going above
594 : * threshold while marked, the defense period time will grow longer. There
595 : * is really no point at unmarking a client that keeps DoSing us. */
596 :
597 : /* First of all, we'll try to refill the circuit bucket opportunistically
598 : * before we assess. */
599 819 : cc_stats_refill_bucket(&entry->dos_stats.cc_stats, &addr);
600 :
601 : /* Take a token out of the circuit bucket if we are above 0 so we don't
602 : * underflow the bucket. */
603 819 : if (entry->dos_stats.cc_stats.circuit_bucket > 0) {
604 819 : entry->dos_stats.cc_stats.circuit_bucket--;
605 : }
606 :
607 : /* This is the detection. Assess at every CREATE cell if the client should
608 : * get marked as malicious. This should be kept as fast as possible. */
609 819 : if (cc_has_exhausted_circuits(&entry->dos_stats)) {
610 : /* If this is the first time we mark this entry, log it a info level.
611 : * Under heavy DDoS, logging each time we mark would results in lots and
612 : * lots of logs. */
613 1 : if (entry->dos_stats.cc_stats.marked_until_ts == 0) {
614 1 : log_debug(LD_DOS, "Detected circuit creation DoS by address: %s",
615 : fmt_addr(&addr));
616 1 : cc_num_marked_addrs++;
617 : }
618 1 : cc_mark_client(&entry->dos_stats.cc_stats);
619 : }
620 :
621 818 : end:
622 819 : return;
623 : }
624 :
625 : /* Return the defense type that should be used for this circuit.
626 : *
627 : * This is part of the fast path and called a lot. */
628 : dos_cc_defense_type_t
629 2 : dos_cc_get_defense_type(channel_t *chan)
630 : {
631 2 : tor_assert(chan);
632 :
633 : /* Skip everything if not enabled. */
634 2 : if (!dos_cc_enabled) {
635 0 : goto end;
636 : }
637 :
638 : /* On an OR circuit, we'll check if the previous channel is a marked client
639 : * connection detected by our DoS circuit creation mitigation subsystem. */
640 2 : if (cc_channel_addr_is_marked(chan)) {
641 : /* We've just assess that this circuit should trigger a defense for the
642 : * cell it just seen. Note it down. */
643 1 : cc_num_rejected_cells++;
644 1 : return dos_cc_defense_type;
645 : }
646 :
647 1 : end:
648 : return DOS_CC_DEFENSE_NONE;
649 : }
650 :
651 : /* Concurrent connection detection public API. */
652 :
653 : /* Return true iff the given address is permitted to open another connection.
654 : * A defense value is returned for the caller to take appropriate actions. */
655 : dos_conn_defense_type_t
656 8 : dos_conn_addr_get_defense_type(const tor_addr_t *addr)
657 : {
658 8 : clientmap_entry_t *entry;
659 :
660 8 : tor_assert(addr);
661 :
662 : /* Skip everything if not enabled. */
663 8 : if (!dos_conn_enabled) {
664 0 : goto end;
665 : }
666 :
667 : /* We are only interested in client connection from the geoip cache. */
668 8 : entry = geoip_lookup_client(addr, NULL, GEOIP_CLIENT_CONNECT);
669 8 : if (entry == NULL) {
670 0 : goto end;
671 : }
672 :
673 : /* Is this address marked as making too many client connections? */
674 8 : if (entry->dos_stats.conn_stats.marked_until_ts >= approx_time()) {
675 2 : conn_num_addr_connect_rejected++;
676 2 : return dos_conn_defense_type;
677 : }
678 : /* Reset it to 0 here so that if the marked timestamp has expired that is
679 : * we've gone beyond it, we have to reset it so the detection can mark it
680 : * again in the future. */
681 6 : entry->dos_stats.conn_stats.marked_until_ts = 0;
682 :
683 : /* Need to be above the maximum concurrent connection count to trigger a
684 : * defense. */
685 6 : if (entry->dos_stats.conn_stats.concurrent_count >
686 : dos_conn_max_concurrent_count) {
687 2 : conn_num_addr_rejected++;
688 2 : return dos_conn_defense_type;
689 : }
690 :
691 4 : end:
692 : return DOS_CONN_DEFENSE_NONE;
693 : }
694 :
695 : /* General API */
696 :
697 : /* Take any appropriate actions for the given geoip entry that is about to get
698 : * freed. This is called for every entry that is being freed.
699 : *
700 : * This function will clear out the connection tracked flag if the concurrent
701 : * count of the entry is above 0 so if those connections end up being seen by
702 : * this subsystem, we won't try to decrement the counter for a new geoip entry
703 : * that might have been added after this call for the same address. */
704 : void
705 206 : dos_geoip_entry_about_to_free(const clientmap_entry_t *geoip_ent)
706 : {
707 206 : tor_assert(geoip_ent);
708 :
709 : /* The count is down to 0 meaning no connections right now, we can safely
710 : * clear the geoip entry from the cache. */
711 206 : if (geoip_ent->dos_stats.conn_stats.concurrent_count == 0) {
712 206 : goto end;
713 : }
714 :
715 : /* For each connection matching the geoip entry address, we'll clear the
716 : * tracked flag because the entry is about to get removed from the geoip
717 : * cache. We do not try to decrement if the flag is not set. */
718 0 : SMARTLIST_FOREACH_BEGIN(get_connection_array(), connection_t *, conn) {
719 0 : if (conn->type == CONN_TYPE_OR) {
720 0 : or_connection_t *or_conn = TO_OR_CONN(conn);
721 0 : if (!tor_addr_compare(&geoip_ent->addr, &TO_CONN(or_conn)->addr,
722 : CMP_EXACT)) {
723 0 : or_conn->tracked_for_dos_mitigation = 0;
724 : }
725 : }
726 0 : } SMARTLIST_FOREACH_END(conn);
727 :
728 0 : end:
729 206 : return;
730 : }
731 :
732 : /** A new geoip client entry has been allocated, initialize its DoS object. */
733 : void
734 213 : dos_geoip_entry_init(clientmap_entry_t *geoip_ent)
735 : {
736 213 : tor_assert(geoip_ent);
737 :
738 : /* Initialize the connection count counter with the rate and burst
739 : * parameters taken either from configuration or consensus.
740 : *
741 : * We do this even if the DoS connection detection is not enabled because it
742 : * can be enabled at runtime and these counters need to be valid. */
743 213 : token_bucket_ctr_init(&geoip_ent->dos_stats.conn_stats.connect_count,
744 : dos_conn_connect_rate, dos_conn_connect_burst,
745 213 : (uint32_t) approx_time());
746 213 : }
747 :
748 : /* Note down that we've just refused a single hop client. This increments a
749 : * counter later used for the heartbeat. */
750 : void
751 0 : dos_note_refuse_single_hop_client(void)
752 : {
753 0 : num_single_hop_client_refused++;
754 0 : }
755 :
756 : /* Return true iff single hop client connection (ESTABLISH_RENDEZVOUS) should
757 : * be refused. */
758 : int
759 1 : dos_should_refuse_single_hop_client(void)
760 : {
761 : /* If we aren't a public relay, this shouldn't apply to anything. */
762 1 : if (!public_server_mode(get_options())) {
763 : return 0;
764 : }
765 :
766 1 : if (dos_get_options()->DoSRefuseSingleHopClientRendezvous != -1) {
767 0 : return dos_get_options()->DoSRefuseSingleHopClientRendezvous;
768 : }
769 :
770 1 : return (int) networkstatus_get_param(NULL,
771 : "DoSRefuseSingleHopClientRendezvous",
772 : 0 /* default */, 0, 1);
773 : }
774 :
775 : /* Log a heartbeat message with some statistics. */
776 : void
777 1 : dos_log_heartbeat(void)
778 : {
779 1 : smartlist_t *elems = smartlist_new();
780 :
781 : /* Stats number coming from relay.c append_cell_to_circuit_queue(). */
782 1 : smartlist_add_asprintf(elems,
783 : "%" PRIu64 " circuits killed with too many cells",
784 : stats_n_circ_max_cell_reached);
785 :
786 1 : if (dos_cc_enabled) {
787 0 : smartlist_add_asprintf(elems,
788 : "%" PRIu64 " circuits rejected, "
789 : "%" PRIu32 " marked addresses",
790 : cc_num_rejected_cells, cc_num_marked_addrs);
791 : } else {
792 1 : smartlist_add_asprintf(elems, "[DoSCircuitCreationEnabled disabled]");
793 : }
794 :
795 1 : if (dos_conn_enabled) {
796 0 : smartlist_add_asprintf(elems,
797 : "%" PRIu64 " same address concurrent "
798 : "connections rejected", conn_num_addr_rejected);
799 0 : smartlist_add_asprintf(elems,
800 : "%" PRIu64 " connections rejected",
801 : conn_num_addr_connect_rejected);
802 : } else {
803 1 : smartlist_add_asprintf(elems, "[DoSConnectionEnabled disabled]");
804 : }
805 :
806 1 : if (dos_should_refuse_single_hop_client()) {
807 0 : smartlist_add_asprintf(elems,
808 : "%" PRIu64 " single hop clients refused",
809 : num_single_hop_client_refused);
810 : } else {
811 1 : smartlist_add_asprintf(elems,
812 : "[DoSRefuseSingleHopClientRendezvous disabled]");
813 : }
814 :
815 : /* HS DoS stats. */
816 1 : smartlist_add_asprintf(elems,
817 : "%" PRIu64 " INTRODUCE2 rejected",
818 : hs_dos_get_intro2_rejected_count());
819 :
820 1 : char *msg = smartlist_join_strings(elems, ", ", 0, NULL);
821 :
822 1 : log_notice(LD_HEARTBEAT,
823 : "Heartbeat: DoS mitigation since startup: %s.", msg);
824 :
825 1 : tor_free(msg);
826 6 : SMARTLIST_FOREACH(elems, char *, e, tor_free(e));
827 1 : smartlist_free(elems);
828 1 : }
829 :
830 : /* Called when a new client connection has been established on the given
831 : * address. */
832 : void
833 153 : dos_new_client_conn(or_connection_t *or_conn, const char *transport_name)
834 : {
835 153 : clientmap_entry_t *entry;
836 :
837 153 : tor_assert(or_conn);
838 :
839 : /* Past that point, we know we have at least one DoS detection subsystem
840 : * enabled so we'll start allocating stuff. */
841 153 : if (!dos_is_enabled()) {
842 0 : goto end;
843 : }
844 :
845 : /* We ignore any known address meaning an address of a known relay. The
846 : * reason to do so is because network reentry is possible where a client
847 : * connection comes from an Exit node. Even when we'll fix reentry, this is
848 : * a robust defense to keep in place. */
849 153 : if (nodelist_probably_contains_address(&TO_CONN(or_conn)->addr)) {
850 5 : goto end;
851 : }
852 :
853 : /* We are only interested in client connection from the geoip cache. */
854 148 : entry = geoip_lookup_client(&TO_CONN(or_conn)->addr, transport_name,
855 : GEOIP_CLIENT_CONNECT);
856 148 : if (BUG(entry == NULL)) {
857 : /* Should never happen because we note down the address in the geoip
858 : * cache before this is called. */
859 0 : goto end;
860 : }
861 :
862 : /* Update stats from this new connect. */
863 148 : conn_update_on_connect(&entry->dos_stats.conn_stats,
864 : &TO_CONN(or_conn)->addr);
865 :
866 148 : or_conn->tracked_for_dos_mitigation = 1;
867 :
868 153 : end:
869 153 : return;
870 : }
871 :
872 : /* Called when a client connection for the given IP address has been closed. */
873 : void
874 2 : dos_close_client_conn(const or_connection_t *or_conn)
875 : {
876 2 : clientmap_entry_t *entry;
877 :
878 2 : tor_assert(or_conn);
879 :
880 : /* We have to decrement the count on tracked connection only even if the
881 : * subsystem has been disabled at runtime because it might be re-enabled
882 : * after and we need to keep a synchronized counter at all time. */
883 2 : if (!or_conn->tracked_for_dos_mitigation) {
884 1 : goto end;
885 : }
886 :
887 : /* We are only interested in client connection from the geoip cache. */
888 1 : entry = geoip_lookup_client(&TO_CONN(or_conn)->addr, NULL,
889 : GEOIP_CLIENT_CONNECT);
890 1 : if (entry == NULL) {
891 : /* This can happen because we can close a connection before the channel
892 : * got to be noted down in the geoip cache. */
893 0 : goto end;
894 : }
895 :
896 : /* Update stats from this new close. */
897 1 : conn_update_on_close(&entry->dos_stats.conn_stats, &TO_CONN(or_conn)->addr);
898 :
899 2 : end:
900 2 : return;
901 : }
902 :
903 : /* Called when the consensus has changed. We might have new consensus
904 : * parameters to look at. */
905 : void
906 5 : dos_consensus_has_changed(const networkstatus_t *ns)
907 : {
908 : /* There are two ways to configure this subsystem, one at startup through
909 : * dos_init() which is called when the options are parsed. And this one
910 : * through the consensus. We don't want to enable any DoS mitigation if we
911 : * aren't a public relay. */
912 5 : if (!public_server_mode(get_options())) {
913 : return;
914 : }
915 :
916 0 : cc_consensus_has_changed(ns);
917 0 : conn_consensus_has_changed(ns);
918 :
919 : /* We were already enabled or we just became enabled but either way, set the
920 : * consensus parameters for all subsystems. */
921 0 : set_dos_parameters(ns);
922 : }
923 :
924 : /* Return true iff the DoS mitigation subsystem is enabled. */
925 : int
926 237 : dos_enabled(void)
927 : {
928 237 : return dos_is_enabled();
929 : }
930 :
931 : /* Free everything from the Denial of Service subsystem. */
932 : void
933 240 : dos_free_all(void)
934 : {
935 : /* Free the circuit creation mitigation subsystem. It is safe to do this
936 : * even if it wasn't initialized. */
937 240 : cc_free_all();
938 :
939 : /* Free the connection mitigation subsystem. It is safe to do this even if
940 : * it wasn't initialized. */
941 240 : conn_free_all();
942 240 : }
943 :
944 : /* Initialize the Denial of Service subsystem. */
945 : void
946 9 : dos_init(void)
947 : {
948 : /* To initialize, we only need to get the parameters. */
949 9 : set_dos_parameters(NULL);
950 9 : }
|