26#include "core/or/dos.h"
40static unsigned int dos_cc_enabled = 0;
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;
51static uint64_t cc_num_rejected_cells;
52static uint32_t cc_num_marked_addrs;
53static uint32_t cc_num_marked_addrs_max_queue;
62static unsigned int dos_conn_enabled = 0;
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;
74static uint64_t conn_num_addr_rejected;
75static uint64_t conn_num_addr_connect_rejected;
79static uint32_t dos_num_circ_max_outq;
88static unsigned int dos_stream_enabled = 0;
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;
97static uint64_t stream_num_rejected;
104static uint64_t num_single_hop_client_refused;
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
117 DOS_NUM_CIRC_MAX_OUTQ_DEFAULT,
118 DOS_NUM_CIRC_MAX_OUTQ_MIN,
119 DOS_NUM_CIRC_MAX_OUTQ_MAX);
127 if (dos_get_options()->DoSCircuitCreationEnabled != -1) {
132 DOS_CC_ENABLED_DEFAULT, 0, 1);
140 if (dos_get_options()->DoSCircuitCreationMinConnections) {
144 DOS_CC_MIN_CONCURRENT_CONN_DEFAULT,
154 if (dos_get_options()->DoSCircuitCreationRate) {
158 DOS_CC_CIRCUIT_RATE_DEFAULT,
167 if (dos_get_options()->DoSCircuitCreationBurst) {
171 DOS_CC_CIRCUIT_BURST_DEFAULT,
179 if (dos_get_options()->DoSCircuitCreationDefenseType) {
183 DOS_CC_DEFENSE_TYPE_DEFAULT,
184 DOS_CC_DEFENSE_NONE, DOS_CC_DEFENSE_MAX);
193 if (dos_get_options()->DoSCircuitCreationDefenseTimePeriod) {
197 DOS_CC_DEFENSE_TIME_PERIOD_DEFAULT,
206 if (dos_get_options()->DoSConnectionEnabled != -1) {
210 DOS_CONN_ENABLED_DEFAULT, 0, 1);
218 if (dos_get_options()->DoSConnectionMaxConcurrentCount) {
222 DOS_CONN_MAX_CONCURRENT_COUNT_DEFAULT,
230 if (dos_get_options()->DoSConnectionDefenseType) {
234 DOS_CONN_DEFENSE_TYPE_DEFAULT,
235 DOS_CONN_DEFENSE_NONE, DOS_CONN_DEFENSE_MAX);
243 if (dos_get_options()->DoSConnectionConnectRate) {
247 DOS_CONN_CONNECT_RATE_DEFAULT,
256 if (dos_get_options()->DoSConnectionConnectBurst) {
260 DOS_CONN_CONNECT_BURST_DEFAULT,
270 if (dos_get_options()->DoSConnectionConnectDefenseTimePeriod) {
274 DOS_CONN_CONNECT_DEFENSE_TIME_PERIOD_DEFAULT,
275 DOS_CONN_CONNECT_DEFENSE_TIME_PERIOD_MIN,
284 if (dos_get_options()->DoSStreamCreationEnabled != -1) {
289 DOS_STREAM_ENABLED_DEFAULT, 0, 1);
298 if (dos_get_options()->DoSStreamCreationRate) {
302 DOS_STREAM_RATE_DEFAULT,
311 if (dos_get_options()->DoSStreamCreationBurst) {
315 DOS_STREAM_BURST_DEFAULT,
323 if (dos_get_options()->DoSStreamCreationDefenseType) {
327 DOS_STREAM_DEFENSE_TYPE_DEFAULT,
328 DOS_STREAM_DEFENSE_NONE,
329 DOS_STREAM_DEFENSE_MAX);
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);
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);
356 dos_num_circ_max_outq = get_param_dos_num_circ_max_outq(ns);
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);
380 if (dos_cc_enabled && !get_param_cc_enabled(ns)) {
388get_circuit_rate_per_second(
void)
390 return dos_cc_circuit_rate;
399 uint32_t new_circuit_bucket_count;
400 uint64_t num_token, elapsed_time_last_refill = 0, circuit_rate = 0;
402 int64_t last_refill_ts;
408 last_refill_ts = (int64_t)stats->last_circ_bucket_refill_ts;
414 if ((int64_t)now == last_refill_ts) {
421 circuit_rate = get_circuit_rate_per_second();
427 if (last_refill_ts == 0) {
428 num_token = dos_cc_circuit_burst;
440 if ((int64_t)now < last_refill_ts) {
442 num_token = dos_cc_circuit_burst;
449 elapsed_time_last_refill = (uint64_t)now - last_refill_ts;
453 if (elapsed_time_last_refill > UINT32_MAX) {
454 num_token = dos_cc_circuit_burst;
461 num_token = elapsed_time_last_refill * circuit_rate;
465 if (num_token > UINT32_MAX - stats->circuit_bucket) {
466 new_circuit_bucket_count = dos_cc_circuit_burst;
470 new_circuit_bucket_count = MIN(stats->circuit_bucket + (uint32_t)num_token,
471 dos_cc_circuit_burst);
476 tor_assert_nonfatal(new_circuit_bucket_count <= dos_cc_circuit_burst);
480 tor_assert_nonfatal(new_circuit_bucket_count >= stats->circuit_bucket ||
481 new_circuit_bucket_count == dos_cc_circuit_burst);
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);
489 stats->circuit_bucket = new_circuit_bucket_count;
490 stats->last_circ_bucket_refill_ts = now;
503 return stats->cc_stats.circuit_bucket == 0 &&
504 stats->conn_stats.concurrent_count >= dos_cc_min_concurrent_conn;
515 stats->marked_until_ts =
524cc_channel_addr_is_marked(
channel_t *chan)
552 stats = &entry->dos_stats.cc_stats;
555 return stats && stats->marked_until_ts >= now;
569 stats->marked_until_ts =
570 approx_time() + dos_conn_connect_defense_time_period +
578 dos_conn_enabled = 0;
588 if (dos_conn_enabled && !get_param_conn_enabled(ns)) {
606 stats->concurrent_count++;
610 (uint32_t) monotime_coarse_absolute_sec());
613 if (token_bucket_ctr_get(&stats->connect_count) > 0) {
614 token_bucket_ctr_dec(&stats->connect_count, 1);
620 if (token_bucket_ctr_get(&stats->connect_count) == 0 &&
621 stats->marked_until_ts == 0) {
622 conn_mark_client(stats);
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));
641 if (BUG(stats->concurrent_count == 0)) {
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);
658 return (dos_cc_enabled || dos_conn_enabled);
665dos_get_num_cc_rejected(
void)
667 return cc_num_rejected_cells;
672dos_get_num_cc_marked_addr(
void)
674 return cc_num_marked_addrs;
679dos_get_num_cc_marked_addr_maxq(
void)
681 return cc_num_marked_addrs_max_queue;
686dos_get_num_conn_addr_rejected(
void)
688 return conn_num_addr_rejected;
693dos_get_num_conn_addr_connect_rejected(
void)
695 return conn_num_addr_connect_rejected;
700dos_get_num_single_hop_refused(
void)
702 return num_single_hop_client_refused;
715 if (!dos_cc_enabled) {
744 cc_stats_refill_bucket(&entry->dos_stats.cc_stats, &addr);
748 if (entry->dos_stats.cc_stats.circuit_bucket > 0) {
749 entry->dos_stats.cc_stats.circuit_bucket--;
754 if (cc_has_exhausted_circuits(&entry->dos_stats)) {
758 if (entry->dos_stats.cc_stats.marked_until_ts == 0) {
759 log_debug(
LD_DOS,
"Detected circuit creation DoS by address: %s",
761 cc_num_marked_addrs++;
763 cc_mark_client(&entry->dos_stats.cc_stats);
779 if (!dos_cc_enabled) {
785 if (cc_channel_addr_is_marked(chan)) {
788 cc_num_rejected_cells++;
789 return dos_cc_defense_type;
793 return DOS_CC_DEFENSE_NONE;
800dos_conn_defense_type_t
801dos_conn_addr_get_defense_type(
const tor_addr_t *addr)
808 if (!dos_conn_enabled) {
819 if (entry->dos_stats.conn_stats.marked_until_ts >=
approx_time()) {
820 conn_num_addr_connect_rejected++;
821 return dos_conn_defense_type;
826 entry->dos_stats.conn_stats.marked_until_ts = 0;
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;
837 return DOS_CONN_DEFENSE_NONE;
844dos_get_num_stream_rejected(
void)
846 return stream_num_rejected;
853dos_stream_defense_type_t
856 if (!dos_stream_enabled || circ == NULL)
857 return DOS_STREAM_DEFENSE_NONE;
860 (uint32_t) monotime_coarse_absolute_sec());
864 return DOS_STREAM_DEFENSE_NONE;
869 ++stream_num_rejected;
870 return dos_stream_defense_type;
879 (uint32_t) monotime_coarse_absolute_sec());
898 if (geoip_ent->dos_stats.conn_stats.concurrent_count == 0) {
913 } SMARTLIST_FOREACH_END(conn);
931 dos_conn_connect_rate, dos_conn_connect_burst,
932 (uint32_t) monotime_coarse_absolute_sec());
938dos_note_circ_max_outq(
const channel_t *chan)
946 if (!dos_cc_enabled) {
966 if (entry->dos_stats.cc_stats.marked_until_ts >=
approx_time()) {
971 if (dos_num_circ_max_outq == 0) {
980 dos_num_circ_max_outq) {
983 if (entry->dos_stats.cc_stats.marked_until_ts == 0) {
984 cc_num_marked_addrs_max_queue++;
986 log_info(
LD_DOS,
"Detected outbound max circuit queue from addr: %s",
988 cc_mark_client(&entry->dos_stats.cc_stats);
1001dos_note_refuse_single_hop_client(
void)
1003 num_single_hop_client_refused++;
1009dos_should_refuse_single_hop_client(
void)
1016 if (dos_get_options()->DoSRefuseSingleHopClientRendezvous != -1) {
1021 "DoSRefuseSingleHopClientRendezvous",
1027dos_log_heartbeat(
void)
1033 "%" PRIu64
" circuits killed with too many cells",
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);
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);
1058 if (dos_should_refuse_single_hop_client()) {
1060 "%" PRIu64
" single hop clients refused",
1061 num_single_hop_client_refused);
1064 "[DoSRefuseSingleHopClientRendezvous disabled]");
1067 if (dos_stream_enabled) {
1069 "%" PRIu64
" stream rejected",
1070 stream_num_rejected);
1077 "%" PRIu64
" INTRODUCE2 rejected",
1083 "Heartbeat: DoS mitigation since startup: %s.", msg);
1087 smartlist_free(elems);
1093dos_new_client_conn(
or_connection_t *or_conn,
const char *transport_name)
1102 if (!dos_is_enabled()) {
1107 entry = geoip_lookup_client(&
TO_CONN(or_conn)->addr, transport_name,
1109 if (BUG(entry == NULL)) {
1116 conn_update_on_connect(&entry->dos_stats.conn_stats,
1141 entry = geoip_lookup_client(&
TO_CONN(or_conn)->addr, NULL,
1143 if (entry == NULL) {
1150 conn_update_on_close(&entry->dos_stats.conn_stats, &
TO_CONN(or_conn)->addr);
1169 cc_consensus_has_changed(ns);
1170 conn_consensus_has_changed(ns);
1174 set_dos_parameters(ns);
1181 return dos_is_enabled();
1202 set_dos_parameters(NULL);
int tor_addr_compare(const tor_addr_t *addr1, const tor_addr_t *addr2, tor_addr_comparison_t how)
int channel_is_client(const channel_t *chan)
int channel_get_addr_if_possible(const channel_t *chan, tor_addr_t *addr_out)
Header file for channel.c.
Functions and types for monotonic times.
const or_options_t * get_options(void)
Header file for config.c.
Header file for connection.c.
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.
uint64_t hs_dos_get_intro2_rejected_count(void)
Header file containing denial of service defenses for the HS subsystem for all versions.
smartlist_t * get_connection_array(void)
Header file for mainloop.c.
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.
uint64_t stats_n_circ_max_cell_reached
int public_server_mode(const or_options_t *options)
Header file for routermode.c.
void smartlist_add_asprintf(struct smartlist_t *sl, const char *pattern,...)
char * smartlist_join_strings(smartlist_t *sl, const char *join, int terminate, size_t *len_out)
smartlist_t * smartlist_new(void)
#define SMARTLIST_FOREACH_BEGIN(sl, type, var)
#define SMARTLIST_FOREACH(sl, type, var, cmd)
uint32_t num_circ_max_cell_queue_size
AUTOBOOL DoSConnectionEnabled
POSINT DoSStreamCreationRate
INT DoSCircuitCreationDefenseType
POSINT DoSCircuitCreationMinConnections
POSINT DoSStreamCreationBurst
INT DoSStreamCreationDefenseType
POSINT DoSCircuitCreationBurst
POSINT DoSConnectionConnectBurst
POSINT DoSConnectionConnectRate
POSINT DoSCircuitCreationRate
INT DoSConnectionDefenseType
AUTOBOOL DoSCircuitCreationEnabled
INTERVAL DoSCircuitCreationDefenseTimePeriod
AUTOBOOL DoSRefuseSingleHopClientRendezvous
INTERVAL DoSConnectionConnectDefenseTimePeriod
POSINT DoSConnectionMaxConcurrentCount
AUTOBOOL DoSStreamCreationEnabled
token_bucket_ctr_t stream_limiter
unsigned int tracked_for_dos_mitigation
#define MOCK_IMPL(rv, funcname, arglist)
void token_bucket_ctr_init(token_bucket_ctr_t *bucket, uint32_t rate, uint32_t burst, uint32_t now_ts_sec)
void token_bucket_ctr_refill(token_bucket_ctr_t *bucket, uint32_t now_ts_sec)