Tor  0.4.7.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"
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"
24 
25 #include "core/or/dos.h"
26 #include "core/or/dos_sys.h"
27 
28 #include "core/or/dos_options_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 MOCK_IMPL(STATIC unsigned int,
85 get_param_cc_enabled, (const networkstatus_t *ns))
86 {
87  if (dos_get_options()->DoSCircuitCreationEnabled != -1) {
88  return dos_get_options()->DoSCircuitCreationEnabled;
89  }
90 
91  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 get_param_cc_min_concurrent_connection(const networkstatus_t *ns)
99 {
100  if (dos_get_options()->DoSCircuitCreationMinConnections) {
101  return dos_get_options()->DoSCircuitCreationMinConnections;
102  }
103  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 get_param_cc_circuit_rate(const networkstatus_t *ns)
112 {
113  /* This is in seconds. */
114  if (dos_get_options()->DoSCircuitCreationRate) {
115  return dos_get_options()->DoSCircuitCreationRate;
116  }
117  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 get_param_cc_circuit_burst(const networkstatus_t *ns)
126 {
127  if (dos_get_options()->DoSCircuitCreationBurst) {
128  return dos_get_options()->DoSCircuitCreationBurst;
129  }
130  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 get_param_cc_defense_type(const networkstatus_t *ns)
138 {
139  if (dos_get_options()->DoSCircuitCreationDefenseType) {
140  return dos_get_options()->DoSCircuitCreationDefenseType;
141  }
142  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 get_param_cc_defense_time_period(const networkstatus_t *ns)
151 {
152  /* Time in seconds. */
153  if (dos_get_options()->DoSCircuitCreationDefenseTimePeriod) {
154  return dos_get_options()->DoSCircuitCreationDefenseTimePeriod;
155  }
156  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 MOCK_IMPL(STATIC unsigned int,
164 get_param_conn_enabled, (const networkstatus_t *ns))
165 {
166  if (dos_get_options()->DoSConnectionEnabled != -1) {
167  return dos_get_options()->DoSConnectionEnabled;
168  }
169  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 get_param_conn_max_concurrent_count(const networkstatus_t *ns)
177 {
178  if (dos_get_options()->DoSConnectionMaxConcurrentCount) {
179  return dos_get_options()->DoSConnectionMaxConcurrentCount;
180  }
181  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 get_param_conn_defense_type(const networkstatus_t *ns)
189 {
190  if (dos_get_options()->DoSConnectionDefenseType) {
191  return dos_get_options()->DoSConnectionDefenseType;
192  }
193  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 get_param_conn_connect_rate(const networkstatus_t *ns)
202 {
203  if (dos_get_options()->DoSConnectionConnectRate) {
204  return dos_get_options()->DoSConnectionConnectRate;
205  }
206  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 get_param_conn_connect_burst(const networkstatus_t *ns)
215 {
216  if (dos_get_options()->DoSConnectionConnectBurst) {
217  return dos_get_options()->DoSConnectionConnectBurst;
218  }
219  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 get_param_conn_connect_defense_time_period(const networkstatus_t *ns)
228 {
229  /* Time in seconds. */
230  if (dos_get_options()->DoSConnectionConnectDefenseTimePeriod) {
231  return dos_get_options()->DoSConnectionConnectDefenseTimePeriod;
232  }
233  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 set_dos_parameters(const networkstatus_t *ns)
244 {
245  /* Get the default consensus param values. */
246  dos_cc_enabled = get_param_cc_enabled(ns);
247  dos_cc_min_concurrent_conn = get_param_cc_min_concurrent_connection(ns);
248  dos_cc_circuit_rate = get_param_cc_circuit_rate(ns);
249  dos_cc_circuit_burst = get_param_cc_circuit_burst(ns);
250  dos_cc_defense_time_period = get_param_cc_defense_time_period(ns);
251  dos_cc_defense_type = get_param_cc_defense_type(ns);
252 
253  /* Connection detection. */
254  dos_conn_enabled = get_param_conn_enabled(ns);
255  dos_conn_max_concurrent_count = get_param_conn_max_concurrent_count(ns);
256  dos_conn_defense_type = get_param_conn_defense_type(ns);
257  dos_conn_connect_rate = get_param_conn_connect_rate(ns);
258  dos_conn_connect_burst = get_param_conn_connect_burst(ns);
259  dos_conn_connect_defense_time_period =
260  get_param_conn_connect_defense_time_period(ns);
261 }
262 
263 /* Free everything for the circuit creation DoS mitigation subsystem. */
264 static void
265 cc_free_all(void)
266 {
267  /* If everything is freed, the circuit creation subsystem is not enabled. */
268  dos_cc_enabled = 0;
269 }
270 
271 /* Called when the consensus has changed. Do appropriate actions for the
272  * circuit creation subsystem. */
273 static void
274 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  if (dos_cc_enabled && !get_param_cc_enabled(ns)) {
279  cc_free_all();
280  }
281 }
282 
283 /** Return the number of circuits we allow per second under the current
284  * configuration. */
285 STATIC uint64_t
286 get_circuit_rate_per_second(void)
287 {
288  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 cc_stats_refill_bucket(cc_client_stats_t *stats, const tor_addr_t *addr)
296 {
297  uint32_t new_circuit_bucket_count;
298  uint64_t num_token, elapsed_time_last_refill = 0, circuit_rate = 0;
299  time_t now;
300  int64_t last_refill_ts;
301 
302  tor_assert(stats);
303  tor_assert(addr);
304 
305  now = approx_time();
306  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  if ((int64_t)now == last_refill_ts) {
313  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  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  if (last_refill_ts == 0) {
326  num_token = dos_cc_circuit_burst;
327  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  if ((int64_t)now < last_refill_ts) {
339  /* Use the maximum allowed value of token. */
340  num_token = dos_cc_circuit_burst;
341  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  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  if (elapsed_time_last_refill > UINT32_MAX) {
352  num_token = dos_cc_circuit_burst;
353  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  num_token = elapsed_time_last_refill * circuit_rate;
360 
361  end:
362  /* If the sum would overflow, use the maximum allowed value. */
363  if (num_token > UINT32_MAX - stats->circuit_bucket) {
364  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  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  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  tor_assert_nonfatal(new_circuit_bucket_count >= stats->circuit_bucket ||
379  new_circuit_bucket_count == dos_cc_circuit_burst);
380 
381  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  stats->circuit_bucket = new_circuit_bucket_count;
388  stats->last_circ_bucket_refill_ts = now;
389 
390  done:
391  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 cc_has_exhausted_circuits(const dos_client_stats_t *stats)
399 {
400  tor_assert(stats);
401  return stats->cc_stats.circuit_bucket == 0 &&
402  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 cc_mark_client(cc_client_stats_t *stats)
409 {
410  tor_assert(stats);
411  /* We add a random offset of a maximum of half the defense time so it is
412  * less predictable. */
413  stats->marked_until_ts =
414  approx_time() + dos_cc_defense_time_period +
415  crypto_rand_int_range(1, dos_cc_defense_time_period / 2);
416 }
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 cc_channel_addr_is_marked(channel_t *chan)
423 {
424  time_t now;
425  tor_addr_t addr;
426  clientmap_entry_t *entry;
427  cc_client_stats_t *stats = NULL;
428 
429  if (chan == NULL) {
430  goto end;
431  }
432  /* Must be a client connection else we ignore. */
433  if (!channel_is_client(chan)) {
434  goto end;
435  }
436  /* Without an IP address, nothing can work. */
437  if (!channel_get_addr_if_possible(chan, &addr)) {
438  goto end;
439  }
440 
441  /* We are only interested in client connection from the geoip cache. */
442  entry = geoip_lookup_client(&addr, NULL, GEOIP_CLIENT_CONNECT);
443  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  goto end;
448  }
449  now = approx_time();
450  stats = &entry->dos_stats.cc_stats;
451 
452  end:
453  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 conn_mark_client(conn_client_stats_t *stats)
462 {
463  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  stats->marked_until_ts =
468  approx_time() + dos_conn_connect_defense_time_period +
469  crypto_rand_int_range(1, dos_conn_connect_defense_time_period / 2);
470 }
471 
472 /* Free everything for the connection DoS mitigation subsystem. */
473 static void
474 conn_free_all(void)
475 {
476  dos_conn_enabled = 0;
477 }
478 
479 /* Called when the consensus has changed. Do appropriate actions for the
480  * connection mitigation subsystem. */
481 static void
482 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  if (dos_conn_enabled && !get_param_conn_enabled(ns)) {
487  conn_free_all();
488  }
489 }
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 conn_update_on_connect(conn_client_stats_t *stats, const tor_addr_t *addr)
499 {
500  tor_assert(stats);
501  tor_assert(addr);
502 
503  /* Update concurrent count for this new connect. */
504  stats->concurrent_count++;
505 
506  /* Refill connect connection count. */
507  token_bucket_ctr_refill(&stats->connect_count, (uint32_t) approx_time());
508 
509  /* Decrement counter for this new connection. */
510  if (token_bucket_ctr_get(&stats->connect_count) > 0) {
511  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  if (token_bucket_ctr_get(&stats->connect_count) == 0 &&
518  stats->marked_until_ts == 0) {
519  conn_mark_client(stats);
520  }
521 
522  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 }
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 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  if (BUG(stats->concurrent_count == 0)) {
539  return;
540  }
541 
542  stats->concurrent_count--;
543  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 dos_is_enabled(void)
554 {
555  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 dos_cc_new_create_cell(channel_t *chan)
563 {
564  tor_addr_t addr;
565  clientmap_entry_t *entry;
566 
567  tor_assert(chan);
568 
569  /* Skip everything if not enabled. */
570  if (!dos_cc_enabled) {
571  goto end;
572  }
573 
574  /* Must be a client connection else we ignore. */
575  if (!channel_is_client(chan)) {
576  goto end;
577  }
578  /* Without an IP address, nothing can work. */
579  if (!channel_get_addr_if_possible(chan, &addr)) {
580  goto end;
581  }
582 
583  /* We are only interested in client connection from the geoip cache. */
584  entry = geoip_lookup_client(&addr, NULL, GEOIP_CLIENT_CONNECT);
585  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  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  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  if (entry->dos_stats.cc_stats.circuit_bucket > 0) {
604  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  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  if (entry->dos_stats.cc_stats.marked_until_ts == 0) {
614  log_debug(LD_DOS, "Detected circuit creation DoS by address: %s",
615  fmt_addr(&addr));
616  cc_num_marked_addrs++;
617  }
618  cc_mark_client(&entry->dos_stats.cc_stats);
619  }
620 
621  end:
622  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 dos_cc_get_defense_type(channel_t *chan)
630 {
631  tor_assert(chan);
632 
633  /* Skip everything if not enabled. */
634  if (!dos_cc_enabled) {
635  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  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  cc_num_rejected_cells++;
644  return dos_cc_defense_type;
645  }
646 
647  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 dos_conn_addr_get_defense_type(const tor_addr_t *addr)
657 {
658  clientmap_entry_t *entry;
659 
660  tor_assert(addr);
661 
662  /* Skip everything if not enabled. */
663  if (!dos_conn_enabled) {
664  goto end;
665  }
666 
667  /* We are only interested in client connection from the geoip cache. */
668  entry = geoip_lookup_client(addr, NULL, GEOIP_CLIENT_CONNECT);
669  if (entry == NULL) {
670  goto end;
671  }
672 
673  /* Is this address marked as making too many client connections? */
674  if (entry->dos_stats.conn_stats.marked_until_ts >= approx_time()) {
675  conn_num_addr_connect_rejected++;
676  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  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  if (entry->dos_stats.conn_stats.concurrent_count >
686  dos_conn_max_concurrent_count) {
687  conn_num_addr_rejected++;
688  return dos_conn_defense_type;
689  }
690 
691  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 dos_geoip_entry_about_to_free(const clientmap_entry_t *geoip_ent)
706 {
707  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  if (geoip_ent->dos_stats.conn_stats.concurrent_count == 0) {
712  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. */
719  if (conn->type == CONN_TYPE_OR) {
720  or_connection_t *or_conn = TO_OR_CONN(conn);
721  if (!tor_addr_compare(&geoip_ent->addr, &TO_CONN(or_conn)->addr,
722  CMP_EXACT)) {
723  or_conn->tracked_for_dos_mitigation = 0;
724  }
725  }
726  } SMARTLIST_FOREACH_END(conn);
727 
728  end:
729  return;
730 }
731 
732 /** A new geoip client entry has been allocated, initialize its DoS object. */
733 void
734 dos_geoip_entry_init(clientmap_entry_t *geoip_ent)
735 {
736  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  token_bucket_ctr_init(&geoip_ent->dos_stats.conn_stats.connect_count,
744  dos_conn_connect_rate, dos_conn_connect_burst,
745  (uint32_t) approx_time());
746 }
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 dos_note_refuse_single_hop_client(void)
752 {
753  num_single_hop_client_refused++;
754 }
755 
756 /* Return true iff single hop client connection (ESTABLISH_RENDEZVOUS) should
757  * be refused. */
758 int
759 dos_should_refuse_single_hop_client(void)
760 {
761  /* If we aren't a public relay, this shouldn't apply to anything. */
763  return 0;
764  }
765 
766  if (dos_get_options()->DoSRefuseSingleHopClientRendezvous != -1) {
767  return dos_get_options()->DoSRefuseSingleHopClientRendezvous;
768  }
769 
770  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 dos_log_heartbeat(void)
778 {
779  smartlist_t *elems = smartlist_new();
780 
781  /* Stats number coming from relay.c append_cell_to_circuit_queue(). */
783  "%" PRIu64 " circuits killed with too many cells",
785 
786  if (dos_cc_enabled) {
788  "%" PRIu64 " circuits rejected, "
789  "%" PRIu32 " marked addresses",
790  cc_num_rejected_cells, cc_num_marked_addrs);
791  } else {
792  smartlist_add_asprintf(elems, "[DoSCircuitCreationEnabled disabled]");
793  }
794 
795  if (dos_conn_enabled) {
797  "%" PRIu64 " same address concurrent "
798  "connections rejected", conn_num_addr_rejected);
800  "%" PRIu64 " connections rejected",
801  conn_num_addr_connect_rejected);
802  } else {
803  smartlist_add_asprintf(elems, "[DoSConnectionEnabled disabled]");
804  }
805 
806  if (dos_should_refuse_single_hop_client()) {
808  "%" PRIu64 " single hop clients refused",
809  num_single_hop_client_refused);
810  } else {
812  "[DoSRefuseSingleHopClientRendezvous disabled]");
813  }
814 
815  /* HS DoS stats. */
817  "%" PRIu64 " INTRODUCE2 rejected",
819 
820  char *msg = smartlist_join_strings(elems, ", ", 0, NULL);
821 
822  log_notice(LD_HEARTBEAT,
823  "Heartbeat: DoS mitigation since startup: %s.", msg);
824 
825  tor_free(msg);
826  SMARTLIST_FOREACH(elems, char *, e, tor_free(e));
827  smartlist_free(elems);
828 }
829 
830 /* Called when a new client connection has been established on the given
831  * address. */
832 void
833 dos_new_client_conn(or_connection_t *or_conn, const char *transport_name)
834 {
835  clientmap_entry_t *entry;
836 
837  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  if (!dos_is_enabled()) {
842  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  if (nodelist_probably_contains_address(&TO_CONN(or_conn)->addr)) {
850  goto end;
851  }
852 
853  /* We are only interested in client connection from the geoip cache. */
854  entry = geoip_lookup_client(&TO_CONN(or_conn)->addr, transport_name,
856  if (BUG(entry == NULL)) {
857  /* Should never happen because we note down the address in the geoip
858  * cache before this is called. */
859  goto end;
860  }
861 
862  /* Update stats from this new connect. */
863  conn_update_on_connect(&entry->dos_stats.conn_stats,
864  &TO_CONN(or_conn)->addr);
865 
866  or_conn->tracked_for_dos_mitigation = 1;
867 
868  end:
869  return;
870 }
871 
872 /* Called when a client connection for the given IP address has been closed. */
873 void
874 dos_close_client_conn(const or_connection_t *or_conn)
875 {
876  clientmap_entry_t *entry;
877 
878  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  if (!or_conn->tracked_for_dos_mitigation) {
884  goto end;
885  }
886 
887  /* We are only interested in client connection from the geoip cache. */
888  entry = geoip_lookup_client(&TO_CONN(or_conn)->addr, NULL,
890  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  goto end;
894  }
895 
896  /* Update stats from this new close. */
897  conn_update_on_close(&entry->dos_stats.conn_stats, &TO_CONN(or_conn)->addr);
898 
899  end:
900  return;
901 }
902 
903 /* Called when the consensus has changed. We might have new consensus
904  * parameters to look at. */
905 void
906 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. */
913  return;
914  }
915 
916  cc_consensus_has_changed(ns);
917  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  set_dos_parameters(ns);
922 }
923 
924 /* Return true iff the DoS mitigation subsystem is enabled. */
925 int
926 dos_enabled(void)
927 {
928  return dos_is_enabled();
929 }
930 
931 /* Free everything from the Denial of Service subsystem. */
932 void
933 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  cc_free_all();
938 
939  /* Free the connection mitigation subsystem. It is safe to do this even if
940  * it wasn't initialized. */
941  conn_free_all();
942 }
943 
944 /* Initialize the Denial of Service subsystem. */
945 void
946 dos_init(void)
947 {
948  /* To initialize, we only need to get the parameters. */
949  set_dos_parameters(NULL);
950 }
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:2893
int channel_get_addr_if_possible(const channel_t *chan, tor_addr_t *addr_out)
Definition: channel.c:2835
Header file for channel.c.
const or_options_t * get_options(void)
Definition: config.c:919
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:218
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:451
Header file for mainloop.c.
#define tor_free(p)
Definition: malloc.h:52
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.
int nodelist_probably_contains_address(const tor_addr_t *addr)
Definition: nodelist.c:548
Header file for nodelist.c.
Master header file for Tor-specific functionality.
#define TO_CONN(c)
Definition: or.h:616
OR connection structure.
uint64_t stats_n_circ_max_cell_reached
Definition: relay.c:135
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
AUTOBOOL DoSConnectionEnabled
Definition: dos_options.inc:12
INT DoSCircuitCreationDefenseType
Definition: dos_options.inc:30
POSINT DoSCircuitCreationMinConnections
Definition: dos_options.inc:19
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:57
POSINT DoSConnectionMaxConcurrentCount
Definition: dos_options.inc:38
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)
Definition: token_bucket.c:265
void token_bucket_ctr_refill(token_bucket_ctr_t *bucket, uint32_t now_ts)
Definition: token_bucket.c:294
#define tor_assert(expr)
Definition: util_bug.h:102