As a public and anonymous network, Tor is open to many types of denial-of-service attempts. It's necessary to constantly develop a variety of defenses that mitigate specific types of attacks.
These mitigations are expected to improve network availability, but DoS mitigation is also important for limiting the avenues an attacker could use to perform active attacks on anonymity. For example, the ability to kill targeted Tor instances can be used to facilitate traffic analysis. See the "Sniper Attack" paper by Jansen, Tschorsch, Johnson, and Scheuermann.
The attack and defense environment changes over time. Expect that this document is an attempt to describe the current state of things, but that it may not be complete.
In practice there are always overlaps between these resource types. Connecting to an onion service, for example, puts some strain on every resource type here.
Memory exhaustion is both one of the most serious denial-of-service avenues and the subject of the most fully developed defense mechanisms so far. We track overall memory use and free the most disposable objects first when usage is over threshold.
The available CPU time on a router can be exhausted, assuming the implementation is not capable of processing network input at line rate in all circumstances. This is especially problematic in the single-threaded C implementation. Certain expensive operations like circuit extension handshakes are deferred to a thread pool, but time on the main thread is still a precious resource.
We currently don't directly monitor and respond to CPU usage. Instead C Tor relies on limits for protocol resources, like circuits extensions and onion service introductions, that are associated with this CPU load.
Relay operators can place hard limits on total bandwidth using the
RelayBandwidth options. These options can help relay operators avoid bandwidth peaks on their network, however they aren't designed as denial of service prevention mechanisms.
Beyond just shaving off harmful bandwidth peaks it's important that normal service is not disrupted too much, and especially not disrupted in a targetable way. To approximate this goal we rely on flow control and fair dequeueing of relayed cells.
All channels to some extent are a limited resource, but we focus specifically on preventing floods of incoming TLS connections.
Excessive incoming TLS connections consume memory as well as limited network and operating system resources. Excessive incoming connections typically signal a low-effort denial of service attack.
The C Tor implementation establishes limits on both the number of concurrent connections per IP address and the rate of new connections, using the
DoSConnection family of configuration options and their corresponding consensus parameters.
Excessive circuit creation can impact the entire path of that circuit, so it's important to reject these attacks any time they can be identified. Ideally we reject them as early as possible, before they have fully built the circuit.
Because of Tor's anonymity, most affected nodes experience the circuit flood as coming from every direction. The guard position, however, has a chance to notice specific peers that are creating too many circuits.
The C Tor implementation limits the acceptable rate of circuit creation per client IP address using the
DoSCircuit configuration options and their corresponding consensus parameters.
Flooding an onion service with introduction attempts causes significant network load. In addition to the CPU, memory, and bandwidth load experienced by the introduction point and the service, all involved relays experience a circuit creation flood.
We have two types of onion service DoS mitigations currently. Both are optional, enabled as needed by individual onion servce operators.
Introduction attempts can be rate-limited by each introduction point, at the request of the service.
This defense is configured by an operator using the
HiddenServiceEnableIntroDos configuration options. Services use the introduction DoS extension to communicate these settings to each introduction point.
A short non-interactive computational puzzle can be solved with each connection attempt. Requests provided by the client will be entered into a queue prioritized by their puzzle solution's effort score. Requests are processed by the service at a limited rate, which can be adjusted to a value within the server's capabilities.
Based on the queue behavior, servers will continuously provide an updated effort suggestion. Queue backlogs cause the effort to rise, and an idle server will cause the effort to decay. If the queue is never overfull the effort decays to zero, asking clients not to include a proof-of-work solution at all.
We may support multiple cryptographic algorithms for this puzzle in the future, but currently we support one type. It's called
v1 in our protocol, and it's based on the Equi-X algorithm developed for this purpose. See the document on Proof of Work for onion service introduction.
This defense is configured by an operator using the
HiddenServicePoW configuration options. Additionally, it requires both the client and the onion service to be compiled with the
pow module (and
--enable-gpl mode) available. Despite this non-default build setting, proof of work is available through common packagers like the Tor Browser and Debian.