Virgil from tor2web is interested in implementing a feature of tor2web mode that will allow Tor to specify a specific node as the rendezvous point of an HS circuit.
The idea here is that if tor2web specifies itself as the RP, the latency of RP establishment during HS circuit building will decrease. (I don't know if this is true or whether the speedup will be measurable, but it's worth trying).
My idea for implementing this feature is to introduce a torrc option (temp name Tor2webRendezvousPoints) that acts similar to ExitNodes etc., and forces Tor to select one of the specified RPs as the RP of all HS circuits.
I'm calling this a tor2web feature since I don't see much use for non-tor2web clients.
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information
Child items ...
Show closed items
Linked items 0
Link issues together to show that they're related.
Learn more.
I did a bit of work on this. Virgil, some questions:
a)
Tor has an optimization when building circuits, where if there
already is an unused circuit lying around, it cannibalizes it and
uses that instead. This can also happen in HS circuits, and in that
case the exit node of the cannibalized circuit becomes the RP of
the HS circuit.
It's unclear what Tor2Web wants to do with regards to this. I have
currently disabled the canibalization completely, so that all HS
circuits use the provided RP node.
Another approach would be to always prefer canibalizing circuits if
we can find any, with the reasoning that circuit establishment is
the most costly procedure of the HS circuit (not sure if it's
true). Of course in this case, you won't be the RP anymore, so you
will have more latency after circuit establishment.
You can imagine optimizations here, where Tor keeps creating many
circuits to our RP, so that those get canibalized later. I don't
think I have time to properly implement this approach, and I'm not
sure if it can get merged upstream.
FWIW, I'm not sure how frequent canibalization will be in a use
case like Tor2Web. I will look a bit into this.
b)
What should happen if the white-listed RP is not available in the
network?
Normally this should not happen in your use case (since you run the
RP), so I'm thinking of just refusing to establish any RP
circuits. However, since this is tailored for tor2web, would you
prefer it if Tor picked a random other node when the whitelisted RP
is not available?
(a) I support the simplicity of "always use the designated RP" instead of cannibalizing circuits. Multi-layered funny exceptions confuse my meager brain.
(b) I support sending an error to the logfile (high severity) and then going with a random node as the RP.
My idea for implementing this feature is to introduce a torrc option (temp name Tor2webRendezvousPoints) that acts similar to ExitNodes etc., and forces Tor to select one of the specified RPs as the RP of all HS circuits.
Is there a reason to make this a specific feature of Tor2web mode? Why not just call it "RendezvousPoints" which works just like ExitNodes ? Then if a user wants to set herself as the sole entry in RendezvousPoints that her liability.
I also wrote some unittests and man page documentation.
I also attached some use intructions at tor2web_rp_instructions.txt.
Hope it works for you. Let me know if it doesn't.
BTW, while working on this ticket, I found a weird HS bug (#13151 (moved)). Till the bug is fixed in tor, it's likely that your setup is not going to work if you don't apply Roger's client-side patch to your tor2web tor. You can find Roger's patch at comment:4:ticket:13151.
(a) I support the simplicity of "always use the designated RP" instead of cannibalizing circuits. Multi-layered funny exceptions confuse my meager brain.
Done.
(b) I support sending an error to the logfile (high severity) and then going with a random node as the RP.
Done.
Is there a reason to make this a specific feature of Tor2web mode? Why not just call it "Tor2webRendezvousPoints" which works just like ExitNodes ? Then if a user wants to set herself as the sole entry in RendezvousPoints that her liability.
I think I prefer it this way since the feature can actually harm client anonymity, and I don't see an actual reason for non-tor2web clients to do this. Furthermore, the behavior of "always use the designated RP, but if it's down just pick a random node as RP" is not secure, and it's likely not what normal users expect. If we later decide to make this feature available to non-tor2web clients it's quite easy to do.
Make Tor2web to be released with the default version of Tor, by adding some difficult extra layer like commandline arguments --yes-i-know-that-i-am-taking-risks-by-running-tor2web-mode
OR
Make Tor Project to release a Tor2web-enabled version of Tor as part of it's release cycle
That would be very important to enable easier installation/deployment of Tor2web software having Tor software as it's core dependency.
Because currently a Tor2web node is yet not a Relay itself, if it must became, we shall adjust the way it create the default configuration file and have some specific default setting while acting as a Relay too.
Why disable cannibalization when we're using this feature? I'm not sure what the benefit is supposed to be, and I don't see it explained above.
I'd be more comfortable if the code here were mostly #if'd out when we aren't building with tor2web mode. (e.g, if the pick_tor2web_rendezvous node didn't exist for most builds.)
Should we safe_str_client() our choice of rendezvous point?
Other than that, does it look okay to me. Does it work?
If I wanted to allow canibalization, I would either have to extend to a 4th hop (the wanted RP) or only accept canibalization when the last hop is the wanted RP. So I decided to not tinker with that part of the code, and disable canibalization for RP circuits completely.
BTW, note that cannibalization is only disabled for client RP circuits (purpose == CIRCUIT_PURPOSE_C_ESTABLISH_REND) if Tor2webRendezvousPoints is enabled.
Is there a better behavior?
I'd be more comfortable if the code here were mostly #if'd out when we aren't building with tor2web mode. (e.g, if the pick_tor2web_rendezvous node didn't exist for most builds.)
Me too. But I'm calling these functions from the unittests. Should I #if out the unittests too?
Unfortunately, I just checked and the test binary does not work when Tor2web-mode is enabled...
$ ./src/test/testSep 22 21:22:55.408 [err] This copy of Tor was compiled to run in 'tor2web mode'. It can only be run with the Tor2webMode torrc option enabled.Sep 22 21:22:55.408 [err] set_options(): Bug: Acting on config options left us in a broken state. Dying.
Should we safe_str_client() our choice of rendezvous point?
Done and pushed!
Other than that, does it look okay to me. Does it work?
Is an acceptable test for this simply pinging the top 100 most popular .onion services and getting the median response time with and without setting Tor2webRendezvousPoints to the second Tor instance?
I just want to verify that I'm performing the appropriate test.
Is an acceptable test for this simply pinging the top 100 most popular .onion services and getting the median response time with and without setting Tor2webRendezvousPoints to the second Tor instance?
I just want to verify that I'm performing the appropriate test.
Yes, this is as ready as it will ever be.
Your test seems appropriate, but I would suggest to look at what karsten has been doing over at #1944 (closed).
He is using torperf which is more robust, and he also has a Tor patch for cleaning the rendezvous caches of Tor that impact performance.
We can take another look at the patch; no payment is necessary. (If it's ready, we should merge it for free. If it isn't ready, we really shouldn't merge it.)
Trac: Milestone: Tor: 0.2.7.x-final to Tor: 0.2.6.x-final
I added some extra ifdef guards as discussed above. The trick was to look at defined(ENABLE_TOR2WEB_MODE) || defined(TOR_UNIT_TESTS) . Then I merged to master and fixed up some conflicts. Review of merge commit would be appreciated. (caf28519d9a4f7f0a5fa36a0cd94fe9c0ee292dc)
Trac: Status: needs_review to closed Resolution: N/Ato implemented
Hrm. But it doesn't have to be that way. In fact, I think #9685 (moved) was about opening an ORPort on the tor2web client, and setting the rendezvous point to that ip:port:fingerprint, even though it is not a known relay. Should that idea get rescued somewhere in a ticket? It seems a shame to build something different and then close #9685 (moved) as a duplicate.
For code cleanliness, I think you don't want to check #if defined(ENABLE_TOR2WEB_MODE) in circuitbuild.c, but instead rely on the value of options->Tor2webMode, which is enforced in options_act(). That's what we do elsewhere in the code, e.g. connection_ap_handshake_rewrite_and_attach().
I actually got snookered thinking that grepping for ENABLE_TOR2WEB_MODE was the way to find all the changes that are affected by tor2web mode, because that's how this change was enabled.
I think that the right fix is not to remove the #ifdefs, but to add more #ifdefs. Tor2web code should not be compiled for average users; otherwise is begging for trouble.
I think that the right fix is not to remove the #ifdefs, but to add more #ifdefs. Tor2web code should not be compiled for average users; otherwise is begging for trouble.
I could get behind that. Consistency is what I want.
I would really love if Tor would build a Tor version with Tor2web enabled, sitting in it's own repository, but being build explicitly for Tor2web uses. It would over-simplify the Tor2web setup process.
If i open a ticket about it, any chance to get a Tor release explicitly build for Tor2web mode?
Hrm. But it doesn't have to be that way. In fact, I think #9685 (moved) was about opening an ORPort on the tor2web client, and setting the rendezvous point to that ip:port:fingerprint, even though it is not a known relay. Should that idea get rescued somewhere in a ticket? It seems a shame to build something different and then close #9685 (moved) as a duplicate.
Yeah that would be an alternative approach yes. I reopened #9685 (moved).