RSS Amplifier

Maverick Journals · Mar 2, 2026

How I handle malicious traffic on Hidden Services

0
Sign in to vote or save

Maverick · Maverick Journals

During the alpha release of my custom WAF, I realized a few things about handling malicious traffic. When I first built it, I was too confident and directly killed Tor circuits. But if you kill a circuit, Tor can automatically rotate and switch to a new one. Back then I only relied on circuit IDs or I2P destinations. I started with manual parsing, which was quite dangerous, and eventually moved to proxy_header. For now it only supports Tor. I’ll implement I2P later once I fully understand how to apply it properly. (Edit: I2P is actually already safe from this by design)

Why did I do this at Layer 4 (TCP)? Because it’s much safer than doing it at Layer 7 (HTTP). Identity is taken directly from injected connection metadata, which is outside the user’s control. Meanwhile, identity at the HTTP layer is very vulnerable to manual spoofing or header smuggling, where attackers fake identity or reputation.

Let’s go back to my old method of closing circuits. In hidden service traffic, where we don’t know the visitor’s identity, it’s hard to tell which traffic is clean and which is malicious. Cookies? Some visitors don’t like them. So circuit IDs and destination headers are the best option. But when I closed a bad circuit, I ended up losing the identity of that malicious traffic. At first I added session cookies as a second layer of defense. But again, I didn’t want privacy-focused visitors to lose access just because they reject cookies. Everything should work without them, regardless of the situation. Even though “under attack” mode still requires cookies for verification, I don’t think it’s an issue in this context. So instead of closing the circuit, I just recorded it. I integrated this with stem-rs for circuit observation. If an attacker rotates circuits using stem, then I defend using the same method too. Fair enough.

So what do I do with a malicious circuit? I drop the connection directly at Layer 4. It’s cheaper than handling it at Layer 7. When a circuit dies, my observer sends a signal to papaya to remove it. I know manual parsing like this can be risky, so I fuzzed it heavily. I’ve been using this project since mid-December, quietly running it on allium before finally using it on my blog in January during the alpha release. Since I use it across all my hidden services, I get to see what’s wrong and what needs fixing. Besides fuzzing and tooling, I also tested certain endpoints using intruder to trigger violations or even just do flooding. I’m satisfied with the results.

Here is how I do it in Burp Suite:

  1. I use the Intruder to trigger violations.

    WAF Block
    WAF Block

  2. Request is blocked because flooding is detected.

    Permanent Block
    Permanent Block

  3. For continuous requests, karma will rise and the connection will be dropped at L4.

    L4 Block
    L4 Block

For benchmarking, I’m also quite happy. I benchmarked it with criterion, and stress tests average around 8.5k RPS for circuit parsing, backend requests, and triggering WAF blocks, mocking one connection per circuit with connection close. Results may vary depending on the device. In this case, the bottleneck is Tor itself, so anything beyond that is basically overkill.

Other changes include trimming dependencies, adding some docs, CI/CD, and releasing v0.1.0 of gaunter. Yes, named after the Witcher character because I like the franchise lol. There’s also a mirror on Codeberg in case anyone wants to open issues or pull requests there. On Tor, I use cgit for mirroring too. But the main repo stays on Forgejo because I can create unlimited packages and run my own registry. The container images are available both on my Forgejo and on Docker Hub, so you can pull from whichever you prefer.

Since this project is my daily driver, I’ll keep maintaining it as long as I still remember that I run multiple services on the darknet. I just hope I can stay consistent with what I’m doing now.

Read the original on mrmave.work

Comments

Nothing yet. Say the first thing.

    Sign in to join the conversation.