Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add Tor support: onion listeners #8

Open
warner opened this issue Dec 8, 2015 · 9 comments
Open

add Tor support: onion listeners #8

warner opened this issue Dec 8, 2015 · 9 comments

Comments

@warner
Copy link
Collaborator

warner commented Dec 8, 2015

My plan here is to add a --tor flag, which will:

  • use Tor for all connections to the Rendezvous Server (txtorcon will be asked to create a new Tor instance)
  • for Transit, ask txtorcon to create an ephemeral Hidden Service, and use tor:XYZ.onion:PORT as the "direct hint", instead of scanning and revealing local IP addresses
  • continue to advertise the Relay Server as the "relay hints"
  • use Tor to connect to the Relay Server, if a direct connection doesn't succeed

If both sides are using --tor, they should be able to connect with the HS "direct hints". But if only one side is using Tor, the other won't be able to use the HS, so they must fall back to the relay.

@warner
Copy link
Collaborator Author

warner commented Dec 8, 2015

Incidentally, this might require changing the CLI scripts from blocking-style calls to Twisted-style calls, because it sounds like getting Requests to use SOCKS is not a solved problem. See https://github.com/kennethreitz/requests/pull/478 for background.

At this point we have decent unit tests, so I don't think this would hurt the stability of the blocking API.

@warner
Copy link
Collaborator Author

warner commented Mar 28, 2016

I've landed preliminary support for this in e04e840. Use wormhole --tor send and wormhole --tor receive. This does not yet listen on an onion server: it just makes tor-based connections to the other side's hints (so if both sides use Tor, or if one uses Tor and the other is behind NAT, then it will go through the relay).

@whatisgravity
Copy link

I was going to recommend this, would take out the necessary rendezvous.

@warner
Copy link
Collaborator Author

warner commented May 31, 2016

BTW, with the recent (large) implementation/protocol changes I landed for 0.8.0, I might have broken our existing preliminary Tor support (I haven't had time to test it, and the unit tests don't cover it). If so, I'm sorry, and rest assured it it will return soon.

@meejah
Copy link
Member

meejah commented Jun 3, 2016

I have tested it, and Tor support works.

@warner
Copy link
Collaborator Author

warner commented Jun 5, 2016

awesome, thanks!

@whatisgravity
Copy link

So the next step would be creating the hidden services in a manner similar to onionshare or is that out of scope for this project?

@warner
Copy link
Collaborator Author

warner commented Jul 3, 2016

Yup, creating hidden services is the next step.

Just before the big 0.8.0 release, I added several messages with which the two sides can advertise their connectivity options to each other. There's an abilities-v1 message which lists the kinds of outbound connections that the message-sender can make, so the first half is for Tor-capable clients to include a {type: "tor-v1"} element inthe abilities-v1 array (see wormhole.transit.Common.get_connection_abilities).

The second half is for the other side to notice both 1: "oh, hey, they can connect to Tor" and 2: "Oh, hey, I can start an onion-service", and then actually start the onion service. Once the service is running and we know the .onion address, we send it in a hints-v1 message (search for get_connection_hints()). On receipt, the node seeing the hints-v1 message should initiate connections to all the hints it contains, one of which will be {type: "tor-v1", hostname: "XYZ.onion", port: 1234}.

One trick with onion services is that they take a fairly long time to spin up, so you don't want to bother doing if the other side won't be able to use it, or if there's a better pathway to use (e.g. if the sender is behind Tor, but the receiver has a public IP address, then the sender should just use Tor and an exit node to reach the receiver). Also, there's no point in having both sender and receiver spin up a hidden service: one is sufficient.

In most cases the sender is started before the receiver (the only exception being where you and I meet offline, agree on a code, then both go home and type it in). So there's a big chunk of idle time (after the sender starts, before the receiver finishes typing in the code) during which we could spin up the hidden service and not increase our overall latency. But we don't know if the receiver will be able to connect to it until after they startup and we get their first few messages.

So I'm thinking that maybe we should have a wormhole send argument that basically means "spin up the hidden service right away, just in case they end up being able to use it" (maybe this could be the same argument that says "only ever speak through Tor, because I want to protect my IP address"). Without this argument, we'll wait until the receiver tells us that they can speak Tor before we spin it up (and maybe we also look at the other connection hints, and exhaust all the more direct possibilities, before spinning up the HS).

(OTOH, I'm assuming that starting an HS imposes some load on the tor network, so it's polite to avoid doing it unless necessary.. maybe it's not that big of a deal, and we can just start one up every time we use --tor).

@warner
Copy link
Collaborator Author

warner commented Jul 27, 2016

reminder to myself: meejah says the best API in txtorcon-0.15.0 for this is probably:

TCPHiddenServiceEndpoint.system_tor(
  reactor, 
  UNIXEndpoint(reactor, "/var/run/tor/control"),
  public_port=RELAY_PORT,
  hidden_service_dir="/tmp/foo",
)

Also, assuming that a side which doesn't use --tor isn't capable of using tor hints, we've got nine cases to deal with:

(Receiver Abilities)
(Sender Abilities) rx=public-IP rx=private-IP rx=tor
tx=public-IP direct direct direct (torified)
tx=private-IP direct relay relay (torified)
tx=tor direct (torified) relay (torified) HS

If the non---tor side is able to use Tor (but we only spin up the HS if we're restricting ourselves to --tor), it looks like:

(Receiver Abilities)
(Sender Abilities) rx=public-IP (+tor) rx=private-IP (+tor) rx=tor
tx=public-IP (+tor) direct direct direct (torified)
tx=private-IP (+tor) direct relay HS
tx=tor direct (torified) HS HS

If we decided to aggressively spin up the hidden service any time we can, even if we have no idea if the other side can use it, we could flip that middle private+private case to HS. But that doesn't feel like a win.. I suspect the number of times that will be helpful is fairly small.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants