summaryrefslogtreecommitdiff
path: root/src/feature/hs/hs_dos.c
diff options
context:
space:
mode:
authorDavid Goulet <dgoulet@torproject.org>2019-05-29 14:05:16 -0400
committerDavid Goulet <dgoulet@torproject.org>2019-08-06 07:58:14 -0400
commit9f738be8937d675929b43a149d706160641a089d (patch)
tree8a54a82b32bea028f6693f97e359899d3bd43aec /src/feature/hs/hs_dos.c
parent4ee65a6f877e841739f037ad27d2d588ce4e0c51 (diff)
downloadtor-9f738be8937d675929b43a149d706160641a089d.tar.gz
tor-9f738be8937d675929b43a149d706160641a089d.zip
hs: Limit the amount of relayed INTRODUCE2
This commit add the hs_dos.{c|h} file that has the purpose of having the anti-DoS code for onion services. At this commit, it only has one which is a function that decides if an INTRODUCE2 can be sent on the given introduction service circuit (S<->IP) using a simple token bucket. The rate per second is 25 and allowed burst to 200. Basic defenses on #15516. Signed-off-by: David Goulet <dgoulet@torproject.org>
Diffstat (limited to 'src/feature/hs/hs_dos.c')
-rw-r--r--src/feature/hs/hs_dos.c60
1 files changed, 60 insertions, 0 deletions
diff --git a/src/feature/hs/hs_dos.c b/src/feature/hs/hs_dos.c
new file mode 100644
index 0000000000..ad9d044f48
--- /dev/null
+++ b/src/feature/hs/hs_dos.c
@@ -0,0 +1,60 @@
+/* Copyright (c) 2019, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file hs_dos.c
+ * \brief Implement denial of service mitigation for the onion service
+ * subsystem.
+ *
+ * This module defenses:
+ *
+ * - Introduction Rate Limiting: If enabled by the consensus, an introduction
+ * point will rate limit client introduction towards the service (INTRODUCE2
+ * cells). It uses a token bucket model with a rate and burst per second.
+ *
+ * Proposal 305 will expand this module by allowing an operator to define
+ * these values into the ESTABLISH_INTRO cell. Not yet implemented.
+ **/
+
+#define HS_DOS_PRIVATE
+
+#include "core/or/circuitlist.h"
+
+#include "hs_dos.h"
+
+/*
+ * Public API.
+ */
+
+/* Return true iff an INTRODUCE2 cell can be sent on the given service
+ * introduction circuit. */
+bool
+hs_dos_can_send_intro2(or_circuit_t *s_intro_circ)
+{
+ tor_assert(s_intro_circ);
+
+ /* Should not happen but if so, scream loudly. */
+ if (BUG(TO_CIRCUIT(s_intro_circ)->purpose != CIRCUIT_PURPOSE_INTRO_POINT)) {
+ return false;
+ }
+
+ /* This is called just after we got a valid and parsed INTRODUCE1 cell. The
+ * service has been found and we have its introduction circuit.
+ *
+ * First, the INTRODUCE2 bucket will be refilled (if any). Then, decremented
+ * because we are about to send or not the cell we just got. Finally,
+ * evaluate if we can send it based on our token bucket state. */
+
+ /* Refill INTRODUCE2 bucket. */
+ token_bucket_ctr_refill(&s_intro_circ->introduce2_bucket,
+ (uint32_t) approx_time());
+
+ /* Decrement the bucket for this valid INTRODUCE1 cell we just got. Don't
+ * underflow else we end up with a too big of a bucket. */
+ if (token_bucket_ctr_get(&s_intro_circ->introduce2_bucket) > 0) {
+ token_bucket_ctr_dec(&s_intro_circ->introduce2_bucket, 1);
+ }
+
+ /* Finally, we can send a new INTRODUCE2 if there are still tokens. */
+ return token_bucket_ctr_get(&s_intro_circ->introduce2_bucket) > 0;
+}