Reputation-gated egress for Tor

Reputation-gated egress for Tor

TLDR: a working Tor onion service that gates egress on a proof of membership instead of an identity, a response to the fate sharing problem, and the open problem underneath it: pricing the burn of a shared IP when anonymity forbids attribution, a problem that reduces to a spent set no single party may own. Code at dmarzzz/reputation-gated-onion-egress.

In 2016 Cloudflare, the company whose machines stand between a large fraction of the web and anyone wishing to read it, published its accusation of Tor, titled “The Trouble with Tor”: 94 percent of what arrives from the Tor network is malicious. On that claim it put CAPTCHAs and challenges in front of Tor traffic by default, for every customer at once. The Tor Project answered in kind, “The Trouble with CloudFlare”, and posed a modest empirical question, by what method was this 94 percent counted. A decade later it has no answer, and many still report getting blocked when going through Tor. In particular, those in the private agentic community report that while using SearXNG, a metasearch engine with built-in Tor support, they still get blocked. The academic literature has a name for this condition, fate sharing: everyone behind a shared address inherits the penalty that any one of them earned.

In this post we show a simple reproduction of an agent being blocked when using SearXNG over Tor. We then present the design and implementation of a candidate solution: a reputation-gated onion service that admits requests on a zk proof of membership, rate-limited with a rate-limiting nullifier (RLN). The open problem underneath is pricing the burn of the shared IP when anonymity forbids attributing it to any member, which reduces to a spent set no single party is trusted to keep.

Tor exit IPs are a public blocklist

Blocking Tor exit nodes programmatically is easy, because Tor publishes the full list of exit IPs itself: the firewall and CDN vendors ingest it as a live feed that updates as exits rotate, so banning all of Tor is a checkbox. The folklore is easy to check directly. I fetched the same real pages over a Tor exit, a home IP, and a datacenter IP, same client and same request rate, and recorded the HTTP status each site returned, so the only variable was the address I arrived from. The Tor-arm method and scripts are in the repo. At the request level, over the same 36 sites, the home IP was blocked 8.3 percent of the time, the datacenter IP 16.7 percent, and Tor 17.1 percent. Each non-Tor lane is one address on one day, so the datacenter number may partly be a DigitalOcean blocklist artifact. The experiment also separates two layers that can both block: the destination you are trying to reach, and the search engine you use to find it. The search engine sits a layer earlier, so Google can block you before you even know your destination. For a small sample size, 36 web destinations and 6,024 search queries over about 50 Tor exits, the web-destination result is mostly bimodal, with a thin middle tier between 4 and 27 percent. The sites that wall Tor at 90 to 100 percent are mostly fronted by commercial anti-bot vendors, Cloudflare, Akamai, or DataDome, and the rest block almost none. The search-engine arm is messier, its 24 engines spread from fully open to Google’s 83 percent.

tor exit blocking distribution

nike, indeed, and g2 wall off 100 percent of tor traffic and google blocks 83; amazon, reddit, and the independent engines block none. a single “percent of tor blocked” number is just the mix of the two.

Our methodology has one blind spot: a Tor exit is a single address carrying many users at once, and we cannot isolate whether someone else was hitting the same destination from the same exit during our run. An observed block could therefore be rate limiting of a busy address rather than a judgment of the address itself, and the status code tells the two apart. Call an IP’s reputation the subjective score a destination keeps for an address, built from everything that address has been seen doing before. A 429 says the address is sending too many requests right now and should slow down. A 403, a CAPTCHA, or a JS challenge says its reputation is bad enough to refuse it outright, no matter how slowly it asks. The ambiguity weighs hardest on the search arm, where SearXNG sends every query to every engine, so each engine sees the exit’s whole query stream even though our own footprint was held to five jittered queries per exit. Classified by status code, search-engine blocks are roughly two-thirds reputation and one-third rate limit, against about 98 percent reputation for web destinations.

block by kind

every block, classified by kind and split by arm: reputation (403, captcha, js challenge) against rate limit (429). the sites an egress actually has to reach block almost purely on reputation.

The literature defines this problem of sharing an IP’s reputation as the fate sharing problem. Khattak and coauthors named it in 2016: “Some blocks specifically target Tor, while others result from fate-sharing when abuse-based automated blockers trigger due to misbehaving Web sessions sharing the same exit node.” Unfortunately, at this point it may not even matter whether you actually share fate with malicious traffic over an exit node, since many operators block the traffic automatically through their CDNs. The point is proven further by Singh and coauthors, who found that even conservative exit policies do not keep exit relays off the blacklists. The fate sharing problem may have created an irreversible sealed fate problem for Tor. The rest of this post outlines a mechanism that shrinks fate sharing from the whole Tor network to a membership set you can price, and shows what it still cannot attribute.

Gating on membership, not identity

Today the cost of sybiling a Tor exit is close to zero: identities are free and requests are free, so one abuser, or one abuser wearing a thousand fresh identities, can poison a shared IP at no cost to themselves. There are a few ways to attach a cost:

For this proof of concept we take the first path. The goal is narrow: a live egress that plugs into the Tor network, reachable by routing through Tor, and passes traffic to the clearnet only for requests carrying a zero-knowledge proof of membership in a set, rate-limited per member with RLN. To get there we deliberately put off a pile of protocol design decisions. The membership set is hard coded rather than maintained by onchain staking, so admission stays an explicit trust root. There is no payment layer, though one would slot in as an extra per-request check exactly where the rate limit sits today. We wanted a working system first, and the harder design questions it raises are the subject of the last section. Below we describe the two components of the design, then the results of deploying it.

An onion service instead of an exit node

Modifying a Tor exit node to accept something like a zk proof is not possible within the Tor protocol as deployed, for two reasons:

  1. The Tor protocol has no slot for a credential at the exit. A stream opens with a cell carrying only an address and a port, and an exit’s only admission control is its exit policy, an accept or reject list of addresses and ports, so there is nowhere to demand a proof from the anonymous circuit that is asking.
  2. An exit only works if it is public. Clients pick exits from the published consensus, so the moment a clean IP becomes an exit it joins the very blocklist we are trying to escape.

Tor offers another, lesser known kind of node for almost this exact reason: the onion service.

exit node vs onion service

network flow diagram of a Tor exit relay versus a Tor onion service reaching the same clearnet destination.

An onion service has no exit at all. Where a normal circuit is three hops ending at an exit relay that talks to the destination in the clear, an onion service is named by a public key, and the .onion address is that key. The client builds a three-hop circuit to a rendezvous relay, the service builds its own three-hop circuit to the same relay, and the rendezvous splices them together. That makes six hops in total, with no single relay seeing both ends and neither side ever learning the other’s IP. It is two parties meeting at a neutral spot that neither one picked. And because the service is a key rather than an address, it never appears in the directory consensus the way exits do, so there is no published IP to put on a blocklist.

The gateway is a v3 onion service running on a box with a single clean IP. A member connects to the onion address over Tor, the gateway forwards the traffic to the clearnet from its own IP, and the destination sees one ordinary address that appears on no Tor list. The tunnel carries one TLS connection to port 443, end to end; the gateway learns the host and port, never the content. That IP stays clean for exactly as long as the members behind it keep it clean, which is what the gate, a zk membership proof described in the next subsection, is for.

A membership proof, rate-limited with RLN

The gate has to do two things that sound contradictory: decide whether a request comes from an allowed member, and hold each member to a rate budget, all without learning which member it is talking to. The first half can be solved with a Semaphore group; ring signatures or a bespoke credential scheme could express the same membership claim, but Semaphore ships the proof and the nullifier we need in one audited, widely deployed package. The set of allowed users is a Merkle tree whose leaves are identity commitments; each member holds a secret, and their leaf is a hash of it. To pass the gate, a client proves in zero knowledge that it knows the secret behind some leaf of the tree, without revealing which leaf. Every valid proof looks identical from the gateway’s side, so the anonymity set is the whole tree.

The second half comes from one extra public output of the same proof. Alongside the membership claim, the circuit exposes a nullifier, a hash of (secret, scope), and we set the scope to the current epoch number. Two properties fall out of the hash:

  1. Within an epoch a member can only ever produce one nullifier, so the gateway can count requests per nullifier and keep each member inside a budget without knowing who anyone is.
  2. Across epochs the nullifier changes to a fresh value that cannot be linked to the old one, so the pseudonym expires as the epoch rolls over.

Together the two halves resolve the contradiction the gate opened with: it admits only members and meters each one, without ever learning which member it is serving. This is the RLN idea, or exactly its counting half: the Shamir-share slashing that completes RLN activates once there is a stake to slash.

The wire protocol

With the proof defined, let’s look at how it travels. The client and gateway speak a small protocol of their own, no HTTP and no headers, where the proof is the entire identity layer. Every request opens with a single line of JSON we call the envelope:

{
  "v": 1,
  "target": "www.google.com:443",
  "proof": {
    "merkleTreeDepth": 3,           // size parameter of the tree, same for every member
    "merkleTreeRoot": "18939…",     // commitment to the whole set, same for every member
    "message": "1",
    "scope": "20638",               // the current epoch number
    "nullifier": "13974…",          // hash(secret, epoch): this member's pseudonym for the epoch
    "points": ["632…", "497…", "…"] // the zk proof itself, ~0.9 KB
  }
}

Nothing in the envelope narrows down who sent it. The root and the depth describe the set, not the member (depth 3 caps the set at 2^3 = 8 members, a PoC toy; the Discussion treats depth as a privacy parameter); every member’s envelope carries the same values, and the root is simply what the gateway compares against its own copy. The one member-specific field is the nullifier, and it is a pseudonym that expires with the epoch.

The whole exchange is three moves on one connection, the same shape as HTTP CONNECT: a short preamble before TLS begins, so TLS stays end to end, and the preamble is never visible on the network because it rides inside the Tor encryption.

the gateway handshake

sequence diagram of the gateway handshake between the client, gateway, and destination.

To admit a request, the gateway runs five checks in order:

  1. the proof verifies as a zero-knowledge proof
  2. its root equals the root the gateway loaded at boot, so the proof speaks for our set and not one the client invented
  3. its scope is the current epoch, with one epoch of clock skew allowed
  4. the target parses as host:443, the TLS-only policy that keeps the gateway a metadata-only tunnel
  5. the nullifier is still under its budget for the epoch, and the counter increments

All five must pass; anything else gets an error verdict and a dropped connection, so the gate fails closed by default. The cost is lopsided on purpose. Generating a proof is the expensive step, but the client does it about once per epoch and caches the result, so every request in that epoch reuses one proof. The gateway pays only the verification, which is the cheap side of the asymmetry and is all that sits in the hot path.

There are a few improvements to this protocol we would need to make to take it to production, but for the PoC they are not needed. These are:

Deployment and results

We deployed the full open-source system on a single DigitalOcean server. It runs as two processes, which is just how a Tor onion service works, not a design choice of ours: a Tor daemon that publishes the onion service and handles the rendezvous routing, and the gateway itself, a small Node process that listens on localhost and does the proof checks. Tor maps the onion address onto that local port, and the gateway binds nothing public, so the box is reachable only through Tor. The onion name is registered nowhere. On first start the Tor daemon generates a v3 keypair and writes the .onion address, which is that public key encoded as text, to a file that persists across restarts. There is no DNS and no certificate authority, and nothing to enumerate, because the address exists only as long as we hold the key.

To use it, a member runs a small client that starts its own Tor and a local proxy, then sends ordinary traffic through it. Through that proxy we hit a whatismyip service, api.ipify.org, and it reported back the gateway’s DigitalOcean address, not the client’s. The world sees the clean egress IP, never the member behind it. A thousand-request load test to Google then returned 1000 of 1000 with none blocked, which makes sense: this is a presumably fresh IP with no bad history, though DigitalOcean could have recycled it from a prior tenant, so for now the destination sees an ordinary address and lets it through.

Since the onion route doubles the hops, three from the client to the rendezvous and three from the gateway, so every request crosses six relays there and back instead of three, it is worth understanding how much worse the latency gets. People already report trouble browsing the regular internet over plain three-hop Tor, and this path is longer. We timed the same thousand requests to Google, and the median was 1.69 seconds against a 0.15 second direct baseline, with a p99 near 8 seconds from ordinary Tor circuit variance, and a one-hour soak that forced a fresh circuit on every request still held 99.90 percent success across 3903 requests. The gate itself is not the bottleneck: verifying a proof takes a median of 32.5 milliseconds on the gateway regardless of set size, a serialized ceiling of roughly 27 to 31 checks per second per core, and each proof is about 0.9 kilobytes on the wire.

latency of the gated path

latency of the 1000-request load test to google, warm (reused circuit) versus cold (fresh rendezvous each request). the six-hop path’s 1.69 second warm median is about four times the 0.43 second median we measured for a plain three-hop tor fetch (of a lightweight control page, not google), and about eleven times the 0.15 second direct baseline.

Discussion

The PoC proved out our two core concerns: live Tor network integration and latency. For Tor integration, the only path we found was to go with an onion service, and we are able to hit the egress by going through a rendezvous point in the live Tor network. The additional hops from this approach are three on the way there and three on the way back over the typical query-then-return path through a Tor exit node.

Naturally, the next question after these results is: what modifications to this design do we need to make to deploy it to production? From a vibes level, we want something that roughly feels like Tor, latency and anonymity wise, but has a much lower block rate, ideally even zero outside of standard rate limits. Made precise, that vibe comes down to four properties, each stated against the adversary it actually holds against.

You could name others, operator privacy, a fail-closed admission gate, data-minimization at the gateway, latency within a constant of Tor, but these four are the essentials this protocol stands or falls on. The first two are the anonymity Tor already gives; the last two are the reputation story it does not.

The design space

Ultimately the privacy in terms of requester unlinkability of a Tor-based protocol is proportional to the anonymity set size, which is roughly equivalent to the number of nodes passing around traffic. If the set is size 1 and the adversary controls it, they can correlate requests trivially. If the size is thousands, well then an adversary needs to control a much larger amount to correlate. In particular the most effective attack involves controlling entry and exit points to the network (Johnson et al., Users Get Routed, CCS 2013).

Therefore, different choices in topology and payment have different impacts on the anonymity set. Anything which relies on a committee for agreeing on shared resource consumption or for payment de facto decreases the anonymity set by some amount for some period of time. Ultimately the desired privacy level, as well as the shape of the traffic expected to go through it, should dictate the answer to these questions. For instance, Tor is much better for async GET requests than streaming Netflix over websocket. Our PoC was one node and no payment: a single gateway in front of a hard-coded membership, enough to prove the gate works and to measure the path. One gateway is one IP, one burn away from dead, and an anonymity set of one on the gateway side, so production cannot stay that small. From here the design space branches two ways.

  1. Topology: what is the target anonymity set size, aka the target number of gateways serving requests.
  2. Payment: what does a member pay and where is it counted, from a refundable stake that buys a base allowance, to a fee per request, to both, and whether that budget is metered at each gateway or once across the whole fleet.

So what’s the actual problem? An onion service is represented as a public key, and this public key is used to rendezvous with a specific gateway. The protocol or the users must coordinate some way of rotating the gateways they are sending requests through in order to maximize their privacy. The introduction of coordination across multiple gateways creates challenges for payments and resource allocation, and therefore more attack vectors for sybils, or more latency and complexity in the protocol. These two axes, topology and payment, are the design space.

Topology

A gateway here is one onion key in front of one clean IP, so the topology question is how many onion keys a member can rendezvous with and whose membership set stands behind each one, with the anonymity set growing as you read down. Each shape has a live precedent: Privacy Pass runs the single-verifier corner in production, Tor’s own bridge distribution is a federation of distributors each rationing their own pool (Lox adds anonymous trust levels to exactly that shape), and WAKU-RLN-RELAY runs a flat fleet of relays enforcing one shared RLN membership.

Of the three shapes, the flat fleet is the only one where adding an operator grows the crowd instead of splitting it, which is why the next version stays there. The cost is that a member’s budget now has to be counted across operators who do not trust each other, and that is the payment question.

Payment

Payment is about what admission actually consumes, and on a flat fleet the accounting gets strictly heavier as you read down. The problem is older than it looks: untraceable e-cash was catching anonymous double-spenders in 1988, and Compact E-Cash and periodic n-times anonymous authentication refined that into the same per-epoch anonymous budget that RLN enforces today. What is new here is the venue: the counter has to survive N mutually distrusting gateways rather than one bank.

What the fleet still needs is the spent set no single party may own, and the adjacent literature says it is buildable: spending from your own budget needs less than consensus, FastPay built real payments on exactly that observation, and Nym already ships double-spend protection for anonymous credentials across its gateways. The next version starts there: a fee counted once across a small fleet of three gateways over one deposit-contract set, with the burn priced per member rather than per request.

Addendum: zk payment channels

The payment section above treats the distributed spent set as the price of the flat fleet. There is a design that refuses to pay it: a zk payment channel per member-gateway pair. The ZK API Usage Credits construction is fundamentally such a channel bound to one recipient, and the shape has a name in the literature: it is BOLT, the anonymous payment channel Green and Miers built for exactly this asymmetry, with RLN’s slash standing in for BOLT’s revocation tokens and watchtowers. Open a channel with each gateway and every gateway keeps its own channel state; nothing crosses between operators, because nothing is shared.

How it would work

A channel is an escrowed deposit plus a state counter. To pay, the member proves in zero knowledge that it holds the current signed state with balance remaining, the gateway blindly signs the decremented state, and the payment proof rides the same envelope the membership proof rides today. The gateway learns that some member with an open channel paid, and cannot link the spend to the previous one. Double-spending an old state is punished rather than prevented: replaying a spent index leaks the member’s secret through the same Shamir-line algebra RLN already uses, and the deposit becomes slashable by anyone. Egress pricing is flat, so the refund machinery that dominates the LLM version of this construction, where costs vary by 100x, can be deleted whole.

The channels would be opened in batch at enrollment, all of them at once, funded through something shielded, because the funding edge is where the anonymity dies otherwise. A member who opens channels lazily on first use leaks its gateway affinities in the timing, and one who funds from a bare wallet links its whole gateway set through exchange KYC trails. BOLT’s paper says this plainly: the guarantees hold only if channels are funded with anonymized capital.

What it costs

We swept the literature behind this fork, BOLT and zkChannels, the TumbleBit-to-Accio payment-hub line, Chaumian ecash from Chaum through Fedimint and the IETF credit-token drafts, the channel capital-efficiency work, and the formal-verification record, and the channel path carries three costs for this fleet.

The sweep also returned something better than a verdict: a simplification. With refunds deleted and every ticket priced flat, the credits construction collapses into the stack this post already runs. Prove membership, prove one counter inequality, spend index times price stays inside the deposit, and emit one more nullifier. The spent set that checks that nullifier needs no consensus, because RLN prices its inconsistency: a double-spend across two gateways is caught when they reconcile, the secret falls out of the algebra, and the deposit is slashed, so the async window is bounded by the deposit rather than trusted away. Fedimint runs this shape today with a BFT spent list; Nym runs it with deferred reconciliation across its gateways. For a fleet whose requests cost the same and whose adversary is the operator, the distributed spent set turns out to be the cheap path, and channels remain the right tool where they were invented: one counterparty, variable costs, no fleet to gossip. The open problems that actually gate the next version are narrower and better than before: the bound relating gossip lag to the maximum extractable double-spend, the self-slash race where a member burns its own deposit before the gateway sweeps earned balance, and the deposit-edge KYC leak.

References

  1. The Tor Project. https://www.torproject.org/
  2. dmarz, reputation-gated-onion-egress. https://github.com/dmarzzz/reputation-gated-onion-egress
  3. Prince, The Trouble with Tor, Cloudflare blog, 2016. https://blog.cloudflare.com/the-trouble-with-tor/
  4. Perry, The Trouble with CloudFlare, Tor Project blog, 2016. https://blog.torproject.org/trouble-cloudflare/
  5. SearXNG metasearch engine. https://github.com/searxng/searxng
  6. Khattak, Fifield, Afroz, Javed, Sundaresan, McCoy, Paxson, Murdoch, Do You See What I See? Differential Treatment of Anonymous Users, NDSS 2016. https://www.ndss-symposium.org/wp-content/uploads/2017/09/do-you-see-what-i-see-differential-treatment-anonymous-users.pdf
  7. Rate-Limiting Nullifier (RLN) docs. https://rate-limiting-nullifier.github.io/rln-docs
  8. The Tor Project, Bulk Tor Exit List. https://check.torproject.org/torbulkexitlist
  9. Palo Alto Networks, Built-in External Dynamic Lists (Tor exit IP addresses). https://docs.paloaltonetworks.com/network-security/security-policy/administration/objects/external-dynamic-lists/built-in-edls
  10. dmarz, Tor exit-blocking benchmark: method and classifier. https://github.com/dmarzzz/reputation-gated-onion-egress/blob/main/docs/exit-blocking-benchmark.md
  11. Singh, Nithyanand, Afroz, Pearce, Tschantz, Gill, Paxson, Characterizing the Nature and Dynamics of Tor Exit Blocking, USENIX Security 2017. https://www.usenix.org/conference/usenixsecurity17/technical-sessions/presentation/singh
  12. The Tor Project, Tor protocol specification: opening streams. https://spec.torproject.org/tor-spec/opening-streams.html
  13. The Tor Project, Tor manual (exit policy). https://2019.www.torproject.org/docs/tor-manual.html.en
  14. The Tor Project, Why is the list of Tor exit relays public? https://support.torproject.org/about-tor/alt-design/hide-list-of-exits/
  15. Semaphore. https://semaphore.pse.dev
  16. dmarz, reputation-gated-onion-egress: tor/torrc. https://github.com/dmarzzz/reputation-gated-onion-egress/blob/main/tor/torrc
  17. dmarz, reputation-gated-onion-egress: gateway/gateway.mjs. https://github.com/dmarzzz/reputation-gated-onion-egress/blob/main/gateway/gateway.mjs
  18. dmarz, reputation-gated-onion-egress: scripts/run-client.sh. https://github.com/dmarzzz/reputation-gated-onion-egress/blob/main/scripts/run-client.sh
  19. ipify, a public IP address API. https://api.ipify.org
  20. Johnson, Wacek, Jansen, Sherr, Syverson, Users Get Routed: Traffic Correlation on Tor by Realistic Adversaries, CCS 2013. https://dl.acm.org/doi/10.1145/2508859.2516651
  21. Davidson, Goldberg, Sullivan, Tankersley, Valsorda, Privacy Pass: Bypassing Internet Challenges Anonymously, PoPETs 2018. https://petsymposium.org/popets/2018/popets-2018-0026.php
  22. Tulloch, Goldberg, Lox: Protecting the Social Graph in Bridge Distribution, PoPETs 2023. https://petsymposium.org/popets/2023/popets-2023-0029.php
  23. Taheri-Boshrooyeh, Thoren, Whitehat, et al., WAKU-RLN-RELAY: Privacy-Preserving Peer-to-Peer Economic Spam Protection, arXiv 2022. https://arxiv.org/abs/2207.00117
  24. Crapis, Buterin, ZK API Usage Credits: LLMs and Beyond, ethresear.ch. https://ethresear.ch/t/zk-api-usage-credits-llms-and-beyond/24104
  25. Chaum, Fiat, Naor, Untraceable Electronic Cash, CRYPTO 1988. https://link.springer.com/chapter/10.1007/0-387-34799-2_25
  26. Camenisch, Hohenberger, Lysyanskaya, Compact E-Cash, EUROCRYPT 2005. https://eprint.iacr.org/2005/060
  27. Camenisch, Hohenberger, Kohlweiss, Lysyanskaya, Meyerovich, How to Win the Clone Wars: Efficient Periodic n-Times Anonymous Authentication, CCS 2006. https://eprint.iacr.org/2006/454
  28. Tsang, Au, Kapadia, Smith, BLAC: Blacklistable Anonymous Credentials, ACM TISSEC 2010. https://homes.luddy.indiana.edu/kapadia/papers/blac-tissec-preprint.pdf
  29. Guerraoui, Kuznetsov, Monti, Pavlovic, Seredinschi, The Consensus Number of a Cryptocurrency, PODC 2019. https://arxiv.org/abs/1906.05574
  30. Baudet, Danezis, Sonnino, FastPay: High-Performance Byzantine Fault Tolerant Settlement, AFT 2020. https://dl.acm.org/doi/abs/10.1145/3419614.3423249
  31. Nym, zk-nym double-spend protection. https://nym.com/docs/network/cryptography/zk-nym/double-spend-prot
  32. Green, Miers, Bolt: Anonymous Payment Channels for Decentralized Currencies, CCS 2017. https://acmccs.github.io/papers/p473-greenA.pdf
  33. Guasoni, Huberman, Shikhelman, Lightning Network Economics: Channels, Management Science 70(6), 2024. https://pubsonline.informs.org/doi/10.1287/mnsc.2022.01664
  34. Heilman, AlShenibr, Baldimtsi, Scafuro, Goldberg, TumbleBit: An Untrusted Bitcoin-Compatible Anonymous Payment Hub, NDSS 2017. https://www.ndss-symposium.org/wp-content/uploads/2017/09/ndss201701-3HeilmanPaper.pdf
  35. Fedimint, federated Chaumian mint. https://github.com/fedimint/fedimint

Further reading

  1. Semaphore v4 (LeanIMT dynamic groups). https://github.com/semaphore-protocol/semaphore
  2. Maleki, Sainz, Legarda, Santos-Grueiro, Scarcity Is Not Enough: Structural Limits of Linear Sybil Cost Under Parallelizable Resources, arXiv 2026 (preprint). https://arxiv.org/abs/2605.29651
  3. Balegas, Duarte, Ferreira, Rodrigues, Preguica, Najafzadeh, Shapiro, Extending Eventually Consistent Cloud Databases for Enforcing Numeric Invariants, SRDS 2015. https://arxiv.org/pdf/1503.09052
  4. Anonymous Credit Tokens, draft-schlesinger-cfrg-act. https://datatracker.ietf.org/doc/draft-schlesinger-cfrg-act
  5. The Tor Project, Proof of Work for onion service introduction (proposal 327). https://spec.torproject.org/proposals/327-pow-over-intro.html
  6. Laurie, Clayton, Proof-of-Work Proves Not to Work, WEIS 2004. https://www.cl.cam.ac.uk/~rnc1/proofwork.pdf
  7. Tsang, Kapadia, Cornelius, Smith, Nymble: Blocking Misbehaving Users in Anonymizing Networks, IEEE TDSC 2011. https://homes.luddy.indiana.edu/kapadia/papers/nymble-tdsc.pdf
  8. Douceur, The Sybil Attack, IPTPS 2002. https://www.freehaven.net/anonbib/cache/sybil.pdf
  9. barryWhiteHat, Semaphore RLN, rate limiting nullifier for spam prevention in anonymous p2p setting, ethresear.ch 2019. https://ethresear.ch/t/semaphore-rln-rate-limiting-nullifier-for-spam-prevention-in-anonymous-p2p-setting/5009
  10. Decentralised Cloudflare using RLN and rich user identities, ethresear.ch. https://ethresear.ch/t/decentralised-cloudflare-using-rln-and-rich-user-identities/10774
  11. The Tor Project, Rendezvous Single Onion Services (proposal 260). https://spec.torproject.org/proposals/260-rend-single-onion.html
  12. IETF RFC 9576, The Privacy Pass Architecture. https://datatracker.ietf.org/doc/rfc9576/
  13. Apple, iCloud Private Relay Overview, 2021. https://www.apple.com/privacy/docs/iCloud_Private_Relay_Overview_Dec2021.PDF
  14. The Tor Project, Res tokens: anonymous credentials for onion service DoS resilience (proposal 331). https://spec.torproject.org/proposals/331-res-tokens-for-anti-dos.html
  15. DigitalOcean, Reserved IPs pricing. https://docs.digitalocean.com/products/networking/reserved-ips/details/pricing/
  16. Oxylabs, ISP proxy pricing. https://oxylabs.io/pricing/isp-proxies
  17. AIMultiple, Proxy server pricing comparison. https://aimultiple.com/proxy-pricing