mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2025-02-28 16:58:18 +01:00
61 lines
2 KiB
C
61 lines
2 KiB
C
|
/* 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;
|
||
|
}
|