]> git.ipfire.org Git - thirdparty/tor.git/commitdiff
add configuration and network parameters for stream dos mitigation
authortrinity-1686a <trinity@deuxfleurs.fr>
Sat, 9 Sep 2023 10:28:33 +0000 (12:28 +0200)
committerDavid Goulet <dgoulet@torproject.org>
Wed, 18 Oct 2023 17:06:04 +0000 (13:06 -0400)
src/core/or/dos.c
src/core/or/dos.h
src/core/or/dos_options.inc

index ccdb30dbee9609a29514ef5054c3519c30f76aa1..a47738c9066e8be25805b206a7c5a837a7d146d3 100644 (file)
@@ -78,6 +78,24 @@ static uint64_t conn_num_addr_connect_rejected;
  * circ_max_cell_queue_size_out limit before being marked. */
 static uint32_t dos_num_circ_max_outq;
 
+/*
+ * Stream denial of service mitigation.
+ *
+ * Namespace used for this mitigation framework is "dos_stream_".
+ */
+
+/* Is the connection DoS mitigation enabled? */
+static unsigned int dos_stream_enabled = 0;
+
+/* Consensus parameters. They can be changed when a new consensus arrives.
+ * They are initialized with the hardcoded default values. */
+static dos_stream_defense_type_t dos_stream_defense_type;
+static uint32_t dos_stream_rate = DOS_STREAM_RATE_DEFAULT;
+static uint32_t dos_stream_burst = DOS_STREAM_BURST_DEFAULT;
+
+/* Keep some stats for the heartbeat so we can report out. */
+static uint64_t stream_num_rejected;
+
 /*
  * General interface of the denial of service mitigation subsystem.
  */
@@ -258,6 +276,58 @@ get_param_conn_connect_defense_time_period(const networkstatus_t *ns)
                                  INT32_MAX);
 }
 
+/* Return true iff the stream creation mitigation is enabled. We look at the
+ * consensus for this else a default value is returned. */
+MOCK_IMPL(STATIC unsigned int,
+get_param_stream_enabled, (const networkstatus_t *ns))
+{
+  if (dos_get_options()->DoSStreamCreationEnabled != -1) {
+    return dos_get_options()->DoSStreamCreationEnabled;
+  }
+
+  return !!networkstatus_get_param(ns, "DoSStreamCreationEnabled",
+                                   DOS_STREAM_ENABLED_DEFAULT, 0, 1);
+}
+
+/* Return the parameter for the time rate that is how many stream per circuit
+ * over this time span. */
+static uint32_t
+get_param_stream_rate(const networkstatus_t *ns)
+{
+  /* This is in seconds. */
+  if (dos_get_options()->DoSStreamCreationRate) {
+    return dos_get_options()->DoSStreamCreationRate;
+  }
+  return networkstatus_get_param(ns, "DoSStreamCreationRate",
+                                 DOS_STREAM_RATE_DEFAULT,
+                                 1, INT32_MAX);
+}
+
+/* Return the parameter for the maximum circuit count for the circuit time
+ * rate. */
+static uint32_t
+get_param_stream_burst(const networkstatus_t *ns)
+{
+  if (dos_get_options()->DoSStreamCreationBurst) {
+    return dos_get_options()->DoSStreamCreationBurst;
+  }
+  return networkstatus_get_param(ns, "DoSStreamCreationBurst",
+                                 DOS_STREAM_BURST_DEFAULT,
+                                 1, INT32_MAX);
+}
+
+/* Return the consensus parameter of the circuit creation defense type. */
+static uint32_t
+get_param_stream_defense_type(const networkstatus_t *ns)
+{
+  if (dos_get_options()->DoSStreamCreationDefenseType) {
+    return dos_get_options()->DoSStreamCreationDefenseType;
+  }
+  return networkstatus_get_param(ns, "DoSStreamCreationDefenseType",
+                                 DOS_STREAM_DEFENSE_TYPE_DEFAULT,
+                                 DOS_STREAM_DEFENSE_NONE, DOS_STREAM_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. */
@@ -283,6 +353,12 @@ set_dos_parameters(const networkstatus_t *ns)
 
   /* Circuit. */
   dos_num_circ_max_outq = get_param_dos_num_circ_max_outq(ns);
+
+  /* Stream. */
+  dos_stream_enabled = get_param_stream_enabled(ns);
+  dos_stream_defense_type = get_param_stream_rate(ns);
+  dos_stream_rate = get_param_stream_burst(ns);
+  dos_stream_burst = get_param_stream_defense_type(ns);
 }
 
 /* Free everything for the circuit creation DoS mitigation subsystem. */
@@ -945,6 +1021,14 @@ dos_log_heartbeat(void)
                            "[DoSRefuseSingleHopClientRendezvous disabled]");
   }
 
+  if (dos_stream_enabled) {
+    smartlist_add_asprintf(elems,
+                           "%" PRIu64 " stream rejected",
+                           stream_num_rejected);
+  } else {
+    smartlist_add_asprintf(elems, "[DoSStreamCreationEnabled disabled]");
+  }
+
   /* HS DoS stats. */
   smartlist_add_asprintf(elems,
                          "%" PRIu64 " INTRODUCE2 rejected",
index 4a2227f132783ca0b4f293328c6a4dda64b10d73..8b36fe14155b9b0cd9292ad59b5d94f635575451 100644 (file)
@@ -159,6 +159,33 @@ typedef enum dos_conn_defense_type_t {
 
 dos_conn_defense_type_t dos_conn_addr_get_defense_type(const tor_addr_t *addr);
 
+/*
+ * Stream creation DoS mitigation subsystem interface.
+ */
+
+/* DoSStreamCreationEnabled default. Disabled by deault. */
+#define DOS_STREAM_ENABLED_DEFAULT 0
+/* DoSStreamCreationDefenseType maps to the dos_stream_defense_type_t enum */
+#define DOS_STREAM_DEFENSE_TYPE_DEFAULT DOS_STREAM_DEFENSE_REFUSE_STREAM
+/* DosStreamCreationRate is 100 per seconds. */
+#define DOS_STREAM_RATE_DEFAULT 100
+/* DosStreamCreationBurst default. */
+#define DOS_STREAM_BURST_DEFAULT 300
+
+/* Type of defense that we can use for the stream creation DoS mitigation. */
+typedef enum dos_stream_defense_type_t {
+  /* No defense used. */
+  DOS_STREAM_DEFENSE_NONE           = 1,
+  /* Reject the stream */
+  DOS_STREAM_DEFENSE_REFUSE_STREAM  = 2,
+  /* Close the circuit */
+  DOS_STREAM_DEFENSE_CLOSE_CIRCUIT  = 3,
+
+  /* Maimum value that can be used. Useful for the boundaries of the
+   * consensus parameter. */
+  DOS_STREAM_DEFENSE_MAX            = 3,
+} dos_stream_defense_type_t;
+
 #ifdef DOS_PRIVATE
 
 STATIC uint32_t get_param_conn_max_concurrent_count(
@@ -176,6 +203,8 @@ MOCK_DECL(STATIC unsigned int, get_param_cc_enabled,
           (const networkstatus_t *ns));
 MOCK_DECL(STATIC unsigned int, get_param_conn_enabled,
           (const networkstatus_t *ns));
+MOCK_DECL(STATIC unsigned int, get_param_stream_enabled,
+          (const networkstatus_t *ns));
 
 #endif /* defined(DOS_PRIVATE) */
 
index 9baa7a35b861306432b4cd7ba541528a43489511..4d15c33f3d3b10fa8120e356c463a8fbc756c04b 100644 (file)
@@ -50,6 +50,19 @@ CONF_VAR(DoSConnectionConnectBurst, POSINT, 0, "0")
 /** Allowed rate of client connection allowed per address. */
 CONF_VAR(DoSConnectionConnectRate, POSINT, 0, "0")
 
+/** Autobool: Is the stream creation DoS mitigation subsystem enabled? */
+CONF_VAR(DoSStreamCreationEnabled, AUTOBOOL, 0, "auto")
+
+/** Stream rate used to refill the token bucket. */
+CONF_VAR(DoSStreamCreationRate, POSINT, 0, "0")
+
+/** Maximum allowed burst of stream. */
+CONF_VAR(DoSStreamCreationBurst, POSINT, 0, "0")
+
+/** When an circuit is detected as malicious, what defense should be used
+ * against it. See the dos_stream_defense_type_t enum. */
+CONF_VAR(DoSStreamCreationDefenseType, INT, 0, "0")
+
 /** For how much time (in seconds) the connection connect rate defense is
 * applicable for a malicious address. A random time delta is added to the
 * defense time of an address which will be between 1 second and half of this