summaryrefslogtreecommitdiff
path: root/src/or/dos.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/or/dos.c')
-rw-r--r--src/or/dos.c289
1 files changed, 289 insertions, 0 deletions
diff --git a/src/or/dos.c b/src/or/dos.c
new file mode 100644
index 0000000000..4b5983d16d
--- /dev/null
+++ b/src/or/dos.c
@@ -0,0 +1,289 @@
+/* Copyright (c) 2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/*
+ * \file dos.c
+ * \brief Implement Denial of Service mitigation subsystem.
+ */
+
+#define DOS_PRIVATE
+
+#include "or.h"
+#include "channel.h"
+#include "config.h"
+#include "geoip.h"
+#include "main.h"
+#include "networkstatus.h"
+
+#include "dos.h"
+
+/*
+ * Circuit creation denial of service mitigation.
+ *
+ * Namespace used for this mitigation framework is "dos_cc_" where "cc" is for
+ * Circuit Creation.
+ */
+
+/* Is the circuit creation DoS mitigation enabled? */
+static unsigned int dos_cc_enabled = 0;
+
+/* Consensus parameters. They can be changed when a new consensus arrives.
+ * They are initialized with the hardcoded default values. */
+static uint32_t dos_cc_min_concurrent_conn;
+static uint32_t dos_cc_circuit_rate_tenths;
+static uint32_t dos_cc_circuit_burst;
+static dos_cc_defense_type_t dos_cc_defense_type;
+static int32_t dos_cc_defense_time_period;
+
+/*
+ * Concurrent connection denial of service mitigation.
+ *
+ * Namespace used for this mitigation framework is "dos_conn_".
+ */
+
+/* Is the connection DoS mitigation enabled? */
+static unsigned int dos_conn_enabled = 0;
+
+/* Consensus parameters. They can be changed when a new consensus arrives.
+ * They are initialized with the hardcoded default values. */
+static uint32_t dos_conn_max_concurrent_count;
+static dos_conn_defense_type_t dos_conn_defense_type;
+
+/*
+ * General interface of the denial of service mitigation subsystem.
+ */
+
+/* Return true iff the circuit creation mitigation is enabled. We look at the
+ * consensus for this else a default value is returned. */
+MOCK_IMPL(STATIC unsigned int,
+get_param_cc_enabled, (const networkstatus_t *ns))
+{
+ if (get_options()->DoSCircuitCreationEnabled != -1) {
+ return get_options()->DoSCircuitCreationEnabled;
+ }
+
+ return !!networkstatus_get_param(ns, "DoSCircuitCreationEnabled",
+ DOS_CC_ENABLED_DEFAULT, 0, 1);
+}
+
+/* Return the parameter for the minimum concurrent connection at which we'll
+ * start counting circuit for a specific client address. */
+STATIC uint32_t
+get_param_cc_min_concurrent_connection(const networkstatus_t *ns)
+{
+ if (get_options()->DoSCircuitCreationMinConnections) {
+ return get_options()->DoSCircuitCreationMinConnections;
+ }
+ return networkstatus_get_param(ns, "DoSCircuitCreationMinConnections",
+ DOS_CC_MIN_CONCURRENT_CONN_DEFAULT,
+ 1, INT32_MAX);
+}
+
+/* Return the parameter for the time rate that is how many circuits over this
+ * time span. */
+static uint32_t
+get_param_cc_circuit_rate_tenths(const networkstatus_t *ns)
+{
+ /* This is in seconds. */
+ if (get_options()->DoSCircuitCreationRateTenths) {
+ return get_options()->DoSCircuitCreationRateTenths;
+ }
+ return networkstatus_get_param(ns, "DoSCircuitCreationRateTenths",
+ DOS_CC_CIRCUIT_RATE_TENTHS_DEFAULT,
+ 1, INT32_MAX);
+}
+
+/* Return the parameter for the maximum circuit count for the circuit time
+ * rate. */
+STATIC uint32_t
+get_param_cc_circuit_burst(const networkstatus_t *ns)
+{
+ if (get_options()->DoSCircuitCreationBurst) {
+ return get_options()->DoSCircuitCreationBurst;
+ }
+ return networkstatus_get_param(ns, "DoSCircuitCreationBurst",
+ DOS_CC_CIRCUIT_BURST_DEFAULT,
+ 1, INT32_MAX);
+}
+
+/* Return the consensus parameter of the circuit creation defense type. */
+static uint32_t
+get_param_cc_defense_type(const networkstatus_t *ns)
+{
+ if (get_options()->DoSCircuitCreationDefenseType) {
+ return get_options()->DoSCircuitCreationDefenseType;
+ }
+ return networkstatus_get_param(ns, "DoSCircuitCreationDefenseType",
+ DOS_CC_DEFENSE_TYPE_DEFAULT,
+ DOS_CC_DEFENSE_NONE, DOS_CC_DEFENSE_MAX);
+}
+
+/* Return the consensus parameter of the defense time period which is how much
+ * time should we defend against a malicious client address. */
+static int32_t
+get_param_cc_defense_time_period(const networkstatus_t *ns)
+{
+ /* Time in seconds. */
+ if (get_options()->DoSCircuitCreationDefenseTimePeriod) {
+ return get_options()->DoSCircuitCreationDefenseTimePeriod;
+ }
+ return networkstatus_get_param(ns, "DoSCircuitCreationDefenseTimePeriod",
+ DOS_CC_DEFENSE_TIME_PERIOD_DEFAULT,
+ 0, INT32_MAX);
+}
+
+/* Return true iff connection mitigation is enabled. We look at the consensus
+ * for this else a default value is returned. */
+MOCK_IMPL(STATIC unsigned int,
+get_param_conn_enabled, (const networkstatus_t *ns))
+{
+ if (get_options()->DoSConnectionEnabled != -1) {
+ return get_options()->DoSConnectionEnabled;
+ }
+ return !!networkstatus_get_param(ns, "DoSConnectionEnabled",
+ DOS_CONN_ENABLED_DEFAULT, 0, 1);
+}
+
+/* Return the consensus parameter for the maximum concurrent connection
+ * allowed. */
+STATIC uint32_t
+get_param_conn_max_concurrent_count(const networkstatus_t *ns)
+{
+ if (get_options()->DoSConnectionMaxConcurrentCount) {
+ return get_options()->DoSConnectionMaxConcurrentCount;
+ }
+ return networkstatus_get_param(ns, "DoSConnectionMaxConcurrentCount",
+ DOS_CONN_MAX_CONCURRENT_COUNT_DEFAULT,
+ 1, INT32_MAX);
+}
+
+/* Return the consensus parameter of the connection defense type. */
+static uint32_t
+get_param_conn_defense_type(const networkstatus_t *ns)
+{
+ if (get_options()->DoSConnectionDefenseType) {
+ return get_options()->DoSConnectionDefenseType;
+ }
+ return networkstatus_get_param(ns, "DoSConnectionDefenseType",
+ DOS_CONN_DEFENSE_TYPE_DEFAULT,
+ DOS_CONN_DEFENSE_NONE, DOS_CONN_DEFENSE_MAX);
+}
+
+/* Set circuit creation parameters located in the consensus or their default
+ * if none are present. Called at initialization or when the consensus
+ * changes. */
+static void
+set_dos_parameters(const networkstatus_t *ns)
+{
+ /* Get the default consensus param values. */
+ dos_cc_enabled = get_param_cc_enabled(ns);
+ dos_cc_min_concurrent_conn = get_param_cc_min_concurrent_connection(ns);
+ dos_cc_circuit_rate_tenths = get_param_cc_circuit_rate_tenths(ns);
+ dos_cc_circuit_burst = get_param_cc_circuit_burst(ns);
+ dos_cc_defense_time_period = get_param_cc_defense_time_period(ns);
+ dos_cc_defense_type = get_param_cc_defense_type(ns);
+
+ /* Connection detection. */
+ dos_conn_enabled = get_param_conn_enabled(ns);
+ dos_conn_max_concurrent_count = get_param_conn_max_concurrent_count(ns);
+ dos_conn_defense_type = get_param_conn_defense_type(ns);
+}
+
+/* Free everything for the circuit creation DoS mitigation subsystem. */
+static void
+cc_free_all(void)
+{
+ /* If everything is freed, the circuit creation subsystem is not enabled. */
+ dos_cc_enabled = 0;
+}
+
+/* Called when the consensus has changed. Do appropriate actions for the
+ * circuit creation subsystem. */
+static void
+cc_consensus_has_changed(const networkstatus_t *ns)
+{
+ /* Looking at the consensus, is the circuit creation subsystem enabled? If
+ * not and it was enabled before, clean it up. */
+ if (dos_cc_enabled && !get_param_cc_enabled(ns)) {
+ cc_free_all();
+ }
+}
+
+/* Concurrent connection private API. */
+
+/* Free everything for the connection DoS mitigation subsystem. */
+static void
+conn_free_all(void)
+{
+ dos_conn_enabled = 0;
+}
+
+/* Called when the consensus has changed. Do appropriate actions for the
+ * connection mitigation subsystem. */
+static void
+conn_consensus_has_changed(const networkstatus_t *ns)
+{
+ /* Looking at the consensus, is the connection mitigation subsystem enabled?
+ * If not and it was enabled before, clean it up. */
+ if (dos_conn_enabled && !get_param_conn_enabled(ns)) {
+ conn_free_all();
+ }
+}
+
+/* General private API */
+
+/* Return true iff we have at least one DoS detection enabled. This is used to
+ * decide if we need to allocate any kind of high level DoS object. */
+static inline int
+dos_is_enabled(void)
+{
+ return (dos_cc_enabled || dos_conn_enabled);
+}
+
+/* Circuit creation public API. */
+
+/* Concurrent connection detection public API. */
+
+/* General API */
+
+/* Called when the consensus has changed. We might have new consensus
+ * parameters to look at. */
+void
+dos_consensus_has_changed(const networkstatus_t *ns)
+{
+ cc_consensus_has_changed(ns);
+ conn_consensus_has_changed(ns);
+
+ /* We were already enabled or we just became enabled but either way, set the
+ * consensus parameters for all subsystems. */
+ set_dos_parameters(ns);
+}
+
+/* Return true iff the DoS mitigation subsystem is enabled. */
+int
+dos_enabled(void)
+{
+ return dos_is_enabled();
+}
+
+/* Free everything from the Denial of Service subsystem. */
+void
+dos_free_all(void)
+{
+ /* Free the circuit creation mitigation subsystem. It is safe to do this
+ * even if it wasn't initialized. */
+ cc_free_all();
+
+ /* Free the connection mitigation subsystem. It is safe to do this even if
+ * it wasn't initialized. */
+ conn_free_all();
+}
+
+/* Initialize the Denial of Service subsystem. */
+void
+dos_init(void)
+{
+ /* To initialize, we only need to get the parameters. */
+ set_dos_parameters(NULL);
+}
+