Announcing the Vanguards Add-On for Onion Services

by asn | July 20, 2018

An Intro to Onion Service Security

Earlier this year, the Tor Project released its first stable Tor and Tor Browser releases with the new v3 onion service protocol. The protocol features many improvements, including longer and more secure onion addresses, service enumeration resistance, improved authentication, and upgraded cryptography.

However, while this new protocol closes off some attacks (particularly enumeration and related targeted DoS attacks), it does not solve any attacks that could lead to service deanonymization.

We believe that the most serious threat that v3 onion services currently face is guard discovery. A guard discovery attack enables an adversary to determine the guard node(s) that are in use by a Tor client and/or Tor onion service. Once the guard node is known, traffic analysis attacks that can deanonymize an onion service (or onion service user) become easier.

The most basic form of this attack is to make many connections to a Tor onion service, in order to force it to create circuits until one of the adversary's nodes is chosen for the middle hop next to the guard. That is possible because middle hops for rendezvous circuits are picked from the set of all relays:

A traffic analysis side channel can be used to confirm that the malicious node is in fact part of the rendezvous circuit, leading to the discovery of that onion service's guard node. From that point, the guard node can be compromised, coerced, or surveilled to determine the actual IP address of the onion service or client.

The Vanguards Control Port Add-On

Fixing the guard discovery problem in Tor itself is an immense project -- primarily because it involves many trade-offs between performance and scalability versus path security, which makes it very hard to pick good defaults for every onion service.

Because of this, we have created an add-on that can be used in conjunction with a Tor onion service server or a Tor client that accesses Tor onion services.

The add-on uses our Control Port Protocol and the corresponding Stem Library to defend against these attacks. The hope is that it will we will be able to study the performance and functionality of this feature and gather feedback before we deploy these changes in Tor for all onion services and clients.

Vanguards, Bandguards, and a Rendguard, oh my!

Our add-on has three components:


The core functionality is provided by the Vanguards component which implements the Mesh Vanguards (Proposal 292). This ensures that all onion service circuits are restricted to a set of second and third layer guards, which have randomized rotation times as defined in that proposal. Basically, now all the hops of onion service circuits are pinned to specific nodes instead of sampling random ones from the whole network every time.

This change to fixed nodes for the second and third layer guards is designed to force the adversary to have to run many more nodes, and to execute both an active sybil attack, as well as a node compromise attack. In particular, the addition of second layer guard nodes means that the adversary goes from being able to discover your guard in minutes by running just one middle node, to requiring them to sustain the attack for weeks or even months, even if they run 5% of the network.

The analysis behind our choice for the number of guards at each layer, and for rotation duration parameters is available on GitHub. Here is how our current vanguard 2-3-8 topology looks like:

Furthermore, to better protect the identity of these new pinned guard nodes the circuit lengths have been altered for rendezous point circuits, hidden service directory circuits, and introduction point circuits. You can see them here (where L1 is the first layer guard, L2 is second layer guard, L3 is third layer guard, M is random middle): 


Additionally, the Bandguards component of the add-on also checks for evidence of bandwidth side channel attacks, which may be used by the adversary to aid/amplify traffic analysis attacks.

When these attacks are detected, the circuit is (optionally) closed.

Note that the Bandguards component also closes any circuit older than 24 hours (the `circ_max_age_hours` setting), and has an option (off-by-default) to close circuits that transmit more than a certain number of megabytes (the `circ_max_megabytes` option).

If your service requires large file uploads, or very long-lived circuits, set these options to 0 in your vanguards.conf.


Finally, the Rendguards component of the add-on performs analysis on the prevalence of rendezvous points on the onion service side. The rendezvous point is chosen by the client when it connects to an onion service, and some attacks rely on the use of a malicious rendezvous point to aid in traffic analysis.

This component tracks the frequency of rendezvous point use, and when it finds overuse, it optionally closes circuits from that rendezvous point and emits a log message.

Each of these components is configurable. Please see the README for more information.

Requirements, Installation, Usage, and Caveats

The Vanguards add-on is primarily for high-risk onion service operators at this point. In order for the Bandguards side channel detection features to be enabled, Tor or above is required, but the script will run with Tor 0.3.3.x+. Earlier Tors do not have sufficient Control Port support for the script, however.

Additionally, while they have been thoroughly tested by us, the parameters for the various detection mechanisms of the Bandguards and Rendgaurd components are still experimental and may need fine tuning for your service or scenario, especially if it differs from our testing environment.

If you notice log messages or alarms from these components, it does not necessarily mean that you are under attack. If you can, please report frequent log messages to the GitHub issue tracker.

Thank you and let us know if you have any questions or concerns! :)


Please note that the comment area below has been archived.

July 20, 2018


So you traded the chance of randomly selecting an adversarial middle node over time (along with those caveats of having to own a large stake in the network, and shaping node awareness) for the chance of selecting an adversarial node the first time. If you get lucky the first time (short rotation adversarial, or long rotation non adversarial ): great. If you get unlucky the first time (long rotation time adversarial, short rotation non-adversarial): you're still SOL, possibly more so.

That's correct. It is also the same trade-off we made when first deploying Guard nodes very early in Tor's history.

For onion services, the key thing that makes this worthwhile is that the adversary gets to force you to create as many circuits as they like, by continuously connecting to you. So if you are actually under attack, it is strictly better to use restricted second and third layer guards that rotate slower than your circuit creation.

For onion clients, it is a bit more fuzzy since it is harder to get them to build lots of circuits. But, if the adversary only controls a small percentage of the network, you're still more likely to get lucky than be SOL right away, as you say.

July 20, 2018

In reply to mikeperry


Not exactly the same tradeoff. Guards obtain their status flag by relaying massive amounts of data compared to relay-only. To have made a single poor choice of guard is not immediately a failure of the network goal since guards which do not serve their purpose lose the status. It may be easy for a adversarial to perform some analysis, but a surveilled guard is not as vulnerable.

So here you have a trade off explicitly for onion services to mitigate the number of connections being abused to identify ips of possible interest. I'd admit it would be a hard choice except that onion services that want to stay anonymous should be trying to blend in with other clients in the first place. They could do this by choosing guards that service many requests but that won't stop the issue of paramount concern; as you mentioned.

Why doesn't the guard recognize that *any* deviance in number of concurrent connections from possible client behavior *is* a threat. It doesn't matter if it's a client or onion service. Could not the guard throttle concurrent connections and total bandwidth to a "client" as a defensive measure? It sounds like a sacrifice but the services that count on it probably don't want to stand out. mtc.

Deploying a defense at the guard node against dos/circuit churn attacks against services isn't really feasible because the guard node can't tell if the service is actually under attack or just suddenly popular.

I thought about adding configurable rate limits on the total number of circuits before sounding some sort of alarm in this vanguards addon, but even that is iffy. Even a quiet service can suddenly get a lot of unexpected attention if it goes viral.

Plus, any sort of limits like this are inherently DoS vectors to take down a service.

July 23, 2018

In reply to mikeperry


I'm talking about those situations (suddenly popular==measurably bad), so the extra attention you describe is undoubtedly an attack vector against the onion service in active exploitation (or client doing something reckless). (and in the case of the service is having to be mitigated at the client when it's too late) The design proposed benefits adversarial nodes the most as they stand to gain from the status-quo the current design offers. Suppose you can say with some certainty the guards chosen are non-adversarial. Then adversarial nodes stand to benefit from these non-adversarial becoming more associated/connected, more nodes to target, and a way to shift network topology to an adversarial benefit.

Now suppose worse case for an onion service trying as I describe to not stand out. By enforcing the behavior at the guard, these "clients" all look relatively similar, and deprives the successful adversary of benefit. Those who are expected to be targeting these onion services can only succeed if they also simultaneously own multiple guards (perhaps being used to scale).

It would slow down the service, but if the operator sees that warning, continues for whatever reason, then they likely need the service for support. I would be recreating the onion address. So slower is okay, clear warnings okay too. The adversary also needs to experience the churn, and by deflecting at the guard no benefit is gained from surveilling a single non-adversarial guard.

I do see what you mean about the proposed design helping those onion services where suddenly popular==no problem. For some (I'd think many/most) this behavior is undesirable.

Look I dunno (non-gendered) dude.. Nodes like "being connected and stuff" is kinda vague (maybe you mean fingerprinting? search the comments of this post for that thread). As is how to have the entire network enforce an appropriate set of heuristics on how onion services get used at the guard node...

I'm a little on the yolo side myself but I still deal in science over here. To me, the tradeoffs are clear. If you do not use this addon, the adversary can find your guard in a hot minute (which is much shorter than a wall-clock minute ;), and can use a whole treasure chest of unfixed-in-core-tor attacks to confirm this, observe the guard, and then find your IP address. If you do use this addon, you are making use of the best ways we know of to slow down these attacks. Just a little bit before they go into core-tor.

But maybe you know how to yolo with the wingnut opsec better than I do. That's why it is an addon! Best of luck!

July 25, 2018

In reply to mikeperry


translation: it's ok for situationally adversarial nodes to exploit this design, ignoring the undesirable, to say disclose location of a network peer acting contrary to sponsor interests (oh, I don't know like to politics of copyright enforcement), versus situationally being non-adversarial when the peer *is* acting in alignment with sponsor interest (like, oh, I don't know supporting insurgency against perceived anti-competitive political structure, ie. supporting regime change)

You do realize that what you just said sounds like: a) I tried something like that to prevent abuse and failed, and b) you're clearly in opposition to situationally adversarial nodes, which by transitivity means c) you would support such a node when acting in the interest of aligned political powers and simultaneously when acting exclusively in network interest.

Not sure what to make of the rest of your comment, but all I really wanted to know was if research besides your failed attempt has been made. And whether a ticket to seriously investigate the matter exists.

But hey, if your response: The USA is great!, is actually what you meant, all the power to you. Otherwise sorry for misunderstanding.

July 23, 2018

In reply to mikeperry


besides what I said before a client side script can verify expected guard behavior so that adversarial guards are detectable.

July 20, 2018


Yay finally Mike Perry does some research!! We love you Mike you're always making us proud when supporting Tor! Keep it up, proud of ya

July 20, 2018


I am hosting V3 onions already and this news terrifies me. Should I delete private_key and generate new V3 onions for my services each month or what?

Tor is not secure at all if 3rd party can know my hosting IP address.

This addon is designed to make it as hard as possible for someone to determine the IP address of an onion service. Success of an attack depends on the adversary's ability to run large portions of the Tor network in addition to being able to compromise honest nodes.

July 21, 2018

In reply to mikeperry


Hi mike, I just don't understand why this is a firefox add-on.
Many people are using Chrome over Tor(according to my access.log) and they can't use your addon because they proxy Chrome traffic over Tor's SOCKSport.

Simple question: Why not implement it to Tor core?

It's not a firefox add-on, it's a Tor core add-on written in Python and uses the control port.

It is not directly implemented in Tor core because it would have been much harder to do it if we had to write it in C and integrate it with all the other modules of Tor core (like the guard subsystem). Hence we are working around that by deploying it as an add-on that uses the control port.

For maintenance purpose, please consider adding it to your dist.tpo so I can
install it by "apt install vanguard" easily.

To reduce attack surface, my website server is running without any unnecessary things such as 'git'. It'll be nice if this tool is simpler & easy to use.

apt install vanguard
vanguard --configure (will open config file with nano)
service vanguard start (will start as daemon)
service vanguard stop (will kill the daemon)

July 20, 2018


just use 4-hop onions as default, and don't worry about the middle node reading the guard node... ... 3 cents

No, unfortunately as soon as a malicious middle node is chosen next to your guard node on one of the (many) circuits that the adversary creates, a specially timed stream of data can be used to determine that it is in fact present in the circuit and next to your guard, regardless of the number of hops in your path. See the README for more details:

And see for the latest research paper on this type of attack.

This is why this addon restricts the number of nodes that can be in the second and third hop, and puts hard limits on the data that can be sent down a Tor circuit that is dropped by the client (and also optionally limits the total amount of data sent on a Tor circuit).

Your choice. Travis runs the unit test suite on both Python 2.7 and 3.5 on every commit. The local tox script will also run the tests with pypy, if it is installed (Travis is a nightmare to get to work with pypy). There is 99% code coverage (the missing 1% is actually a couple lines of glue that check for python2 vs 3, so they are actually alternately covered in the python2 and python3 tests).

July 21, 2018


As a V3 website owner, should I start using bridge to connect to the network?
Currently I'm directly connecting to the Tor.

Me ----> tor-network[Tor1 - Tor2 - Tor3]

But you're saying Tor1(guard) can be found, so:

Me ---> Tor Bridge ---> network[Tor1 - Tor2 - Tor3]

Will this decrease deanonymization? If so, which bridge should I use? meek/obfs4/suggestion please...

Without the vanguards addon, these same attacks will work to find the bridge your onion service is using. So using a bridge by itself is not a defense. However, using a bridge with this addon will provide some additional benefit. Namely, if the bridge is not well-known, it can help obscure the fact that your onion service server is connecting to the Tor network, because the traffic from your onion service into the Tor network will be obfuscated. If meek still works, it is probably the best option, but I think meek no longer works well because the major cloud providers started blocking it --… -- so obfs4 or basket may be the best choice. I would use two bridges.

I have not tested using the addon with bridges though. If you run into problems, please file them at (or comment here).

A related option is running a relay on your onion service machine to try to blend your traffic in with other relay traffic. However, this setup has downsides. In particular, it requires some hacky configuration to prevent other side channel leaks: Additionally, downtime of that relay will be strongly correlated with your onion service downtime, which over time can leak the fact that they are on the same machine. So this is also a difficult trade-off at the moment.

July 21, 2018

In reply to mikeperry


Thank you for your reply. I will definitely try this once these are solved:

1. install/update via APT
2. Wiki document (easy to understand)
3. ExcludeNodes support (I'm using "EN default,{us}")

Hope some geeks help on these tasks...

This is a great priority list. Here's one based on it, which I intend to follow in this order. People are helping with debian packages already! yay.

1. install/update via APT
2. Test bridge support, fix any bugs, and write up setup in README.
3. Separate README into setup+install instructions and a separate TECHNICAL_DETAILS doc.
4. ExcludeNodes support (esp country and netmask rules, eg - "EN default,{us},")

July 21, 2018


Are there any implications for using Vanguards with the HiddenServiceSingleHopMode setting enabled? Maybe irrelevant but unsure if there's any collision here in terms of Onion Service discovery (or, e.g, if HiddenServiceSingleHopMode renders the benefit of Vanguards obsolete for the server side?)

Onion services with HiddenServiceSingleHopMode enabled do not use entry guards because they don't benefit from them (since they are not anonymous), hence there is no point for guard discovery attack or deanonymization attacks there.

July 21, 2018


Hi everyone from Russia !!
I am reading this , and dont understand anything ]]
Because i'm just starting explore this , and just can to start tor or i2p on my device .
But i know , what this is most inportant in our life .
Thank you , see you .
Bye .

July 22, 2018


Wouldn't this be more dangerous now since it would make the network fingerprint stand out and since you didn't add the necessary padding (yet) to make the network fingerprint look about the same across the board?

Thanks for your work Mike and George

There are two ways that this addon will alter your network fingerprint.

The first is observable by a local observer watching your connections into the Tor network. They would now see you're using your two entry guards slightly differently than how stock Tor uses its two guards today. We're working on making all existing stock Tor clients use two guards in a more balanced way (which is possible with a consensus parameter change), but it takes a lot of effort to convince the whole herd of cats that this should be done sooner rather than later. The hard part is that the counter argument against making all clients use two guards in a balanced way is "Whaaaaa?? I thought Tor was using ONE GUARD. WE SHOULD FIX THAT." Except making stock Tor actually use one guard is even harder, and opens up more low-resource attacks, too.

While this fingerprinting vector could be eliminated by setting the vanguards configuration option num_layer1_guards to 1 instead of its current default of 2, it turns out that telling Tor to use only one guard as an onion service opens up a very noisy side channel + confirmation attack that can be detected by this same local observer (because it is possible for them to force a "single entry guard" onion service to use a second guard at specific times).

The second way your network fingerprint differs when you use this addon is that your guard nodes will see that your Tor client is only connecting to a restricted set of middle hops instead of the whole network (unless you also use that same Tor client to also connect to the external Internet). At this time, there are a lot of other traffic analysis vectors that can be used to fingerprint a hidden service if you control the guard node, though.

In both cases, I personally feel that the benefit from protecting against guard discovery outweighs the additional fingerprinting risk from these two vectors. And in the long term, we can mitigate/obscure them, too.

July 22, 2018


1. How can we know that our onion service is compromized(attacker know Guard node)?
2. Doesn't this mean we should rotate .onion domain daily|monthly|yearly?
3. If 3 is true, why not make a torDNS system?

xyz.tor --resove---> xyzonionnamenow.onion

July 23, 2018


That's good to have current stable tor in Debian torproject's repository, but why other widely used projects like stem and nyx are not in this repo? Without stem (or with outdated stem) I cannot test many tools (including this vanguards tool).

July 23, 2018


I am so happy to see the "Rendguards" component here. Thank you so much for taking it into consideration. While I honestly think all here is great work, just using Rendguards feature set to 2.0 as it is the default value currently in vanguards.conf is a huge win. I know for sure from a tipper that this malicious rendezvous relay overuse attack was used to discover the Guard of a V2 onion service, and after that the guard in question was just watched at its ISP level, with no clue or track to the guard operator.

It's true that an attacker can overuse honest relays by deliberately choosing them as rendezvous points, but this depends on the popularity of the onion service as well. Basically, the more popular an onion service is (and more honest non attacking clients connecting to it) the harder is to fool it with such false positives. As an attacker uses this method to ban more and more relays as being used for rendezvous point position, the total number of established rendezvous circuits will grow and more effort will be required to ban new relays. At least this becomes a very noisy attack, very visible to the onion service operator.

I am not sure why this parameter is set at this value: rend_use_scale_at_count = 1000
Wouldn't a bigger number do much better here? Like 100000 or even 500000? Is it that expensive to keep track of this number of rend circuits and apply the filter over them?

This is a great question s7r. There is a TODO question in the source about this. The statistical test we should really be doing should be based on "Statistical Confidence Intervals", and also factor in a bunch of variables about our assumptions about how fast we want to react to new nodes, etc.

However, the intuition is that the larger the scale_at variable, the slower the script can react to new nodes suddenly entering the network with the purposes of attacking a node. So setting this as low as possible while still not triggering false positives seems like the right move, at least until we have better models on this attack.

July 30, 2018


Hi all, i'm running a v3 onion service and Vanguard. All ok in tor and vanguard logs but TorBrowser says: Unable to connect.

How much time should I wait to stablish new circuits with Vanguard?

August 03, 2018


This tool is totally useless when I can't install it in python2.7 (install, pyQT installed)
I actually don't know how to install it, your guide is too poor for a newbie.
Can anyone help me please?
Windows 7


August 13, 2018


Does anyone know how to get this addon to work with Tor Browser that is sandboxed? I have gotten it to work with the regular tor browser. Also can this be used on Tor Browser and Tor network running at same time? Or I guess it could be done using a different control port and running two instances of vanguard?

August 31, 2018


You can try to simulate some fake-host in random places to reduce the capacity of the detectors to reach some real-host using IoT devices... That forces to the detectors to deploy more attacks over fake random host/places.Just an idea.

October 15, 2018


> Also can this be used on Tor Browser and Tor network running at same time?
You mean plain standalone tor install, running possibly as daemon, and Tor Browser? And both as clients only.
If so, than some kind of onionbalance for clients should be deployed, reasons just as in:
Synchronize layer2+layer3 guards when using OnionBalance · Issue #12 · mikeperry-tor/vanguards · GitHub
I.e. two tors: double exposure of guards used.
I'm nterested if this can be achieved, and how. Obviously not the same, but similar way to OnionBalance...

October 18, 2018


mike, I'd file an issue with your vanguards on github, but M$ won't allow anonymous registration, so I'll attempt to post about it here.
This is the command to start vanguards from source:
./vanguards/src/ --loglevel NOTICE --logfile log.vanguards
and pretty similarly with another instance for another Tor.
Importantly, I get DEBUG lines out. Such as:
If that isn't a bug, but intended behavior, maybe I don't connect something here...

October 30, 2018


Same for me, I cannot register an anonymous account on github for opening an issue.
It is a serious problem for a project like Tor.

I cannot run run vanguard

  1. ./src/ --control_port 9099<br />
  2. NOTICE[Wed Oct 31 01:49:43 2018]: Creating new vanguard state file at: vanguards.state<br />
  3. NOTICE[Wed Oct 31 01:49:43 2018]: Vanguards 0.2.3.dev0 connected to Tor (git-5da0e95e4871a0a1) using stem 1.4.1<br />
  4. Traceback (most recent call last):<br />
  5. File "./src/", line 8, in <module><br />
  6. vanguards.main.main()<br />
  7. File "/root/vanguards/src/vanguards/", line 23, in main<br />
  8. run_main()<br />
  9. File "/root/vanguards/src/vanguards/", line 62, in run_main<br />
  10. ret = control_loop(state)<br />
  11. File "/root/vanguards/src/vanguards/", line 99, in control_loop<br />
  12. state.new_consensus_event(controller, None)<br />
  13. File "/root/vanguards/src/vanguards/", line 206, in new_consensus_event<br />
  14. exclude_nodes = ExcludeNodes(controller)<br />
  15. File "/root/vanguards/src/vanguards/", line 60, in __init__<br />
  16. self._parse_line(controller.get_conf("ExcludeNodes"))<br />
  17. File "/root/vanguards/src/vanguards/", line 75, in _parse_line<br />
  18. if p[0] == "$":<br />
  19. IndexError: string index out of range<br />

November 17, 2018


NOTE: the page appears to be broken, trying to post with 8.5a4, my Noscript is at restrictions disabled for this site; the previous poster too appears to have issues. Do not blame me if this comes out poorly, it's the preview doesn't work)

I believe in this project (mildly, not claiming much competence). To me it looks much more prospective, and very much at hand in comparison to the alternatives mentioned in the FAQ chapter:
Alternate designs that we don't do (yet):
(where at this time, Vanguards has no mention there at all).

It would be great to learn whether Tor team is closer to a consensus on deploying Vanguards in Tor itself. Or if it is going for some of the alternatives mentioned in the link... Those certainly do look very far from doable any time soon (and Vanguards works... as we are speaking, in many HS and many clients --although not yet massively, not enough numbers for the disadvantages of running Vanguards addon to be fully compensated, I'd think...)...

But the Tor team may be able to tell us more

May 02, 2019


Are packages still on the TODO list? It's been months and (as far as I'm aware) there are still no packages.