/* 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; }