ipfs / notes

IPFS Collaborative Notebook for Research
MIT License
400 stars 33 forks source link

Tor onion integration #37

Open david415 opened 8 years ago

david415 commented 8 years ago

chatting with Juan Bennet at c-base, Berlin about Tor onion service integration

here's what we've identified as necessary for proper Tor integration:

  1. adding /onion to go-multiaddr - /onion/<onion-key>/ipfs/<ipfs-key>
  2. adding /onion dialing to go-multiaddr-net
  3. make a build of go-ipfs that:
    • only uses /onion
    • only bootstrap to onion nodes
    • disable mdns service
    • disable NAT service

I know plenty of people who'd be willing to run some Tor onion bootstrap nodes.

(edited by @jbenet for links)

whyrusleeping commented 8 years ago

:+1: this would be pretty cool!

david415 commented 8 years ago

OK I've written the go-multiaddr Tor onion address decoding: https://github.com/jbenet/go-multiaddr/pull/13

leif commented 8 years ago

This sounds like a good plan for location-anonymous tor users to have a persistent identity and announce themselves to peers, but it doesn't cover the use case of anonymously (unlinkably?) accessing data from ipfs.

For that we'll need a mode that doesn't transmit any linkable identifiers (which includes not announcing pieces to the DHT).

david415 commented 8 years ago

@leif, Good point. The only "pieces" we'll be announcing to the DHT is .onion addresses. I suspect it will be very easy for us to create a readonly client mode for non-onion using Tor users to access any IPFS storage server without announcing any identity at all.

david415 commented 8 years ago

Today I wrote a TorDialer and OnionListener; This repo also includes examples programs which can be used as an integration test with your system Tor. However it should soon have more ways to use Tor other than just the control port protocol with the system tor:

https://github.com/david415/oniondialer

Although oniondialer could be improved, we can do this later now that we have the basic interface implementations working. Therefore the next step should be to see how this Dialer and Listener can fit into go-multiaddr ... Probably oniondialer will have to change slightly to get it to fit into go-multiaddr.

david415 commented 8 years ago

I've been looking closely at the source for go-multiaddr and go-multiaddr-net... However I'm not sure if Tor onion service multiaddr string should look like this: /onion/timaq4ygg2iegci7.onion:80 or this /onion/fufu.onion/tcp/80

Whereas the "readonly Tor-ified" multiaddr looks like this: /tor/example.com/tcp/80

or should the /tor/ multiaddr not encapsulate and instead look like this? /tor/example.com:80

What do IPFS developers think of all this?

ghost commented 8 years ago

from chat:

Similar to /dns in https://github.com/jbenet/go-multiaddr/issues/7#issuecomment-125745700

A more explicit, but very bloated option for /tor: /ip4/127.0.0.1/tcp/9050/socks5/dns/example.net/ip4/tcp/80

whyrusleeping commented 8 years ago

maybe: /onion/fufu.onion/tcp4/80 and /tor/example.com/tcp6/80

david415 commented 8 years ago

hi. I chatted with Juan last night on #ipfs and we decided that onion multiaddrs will look like this:

Tor doesn't transport IP or TCP... but is a realiable stream transport. We don't need DNS. Tor clients use a local SOCKS proxy; therefore the remote end does the DNS resolution. I hope I've cleared up the confusion regarding this. If not then I'm afraid this ticket will grow too big with my explainations. Perhaps find me on irc instead of commenting here with queries.

For the Tor exit node case I think it should be represented like so:

So I think this sort of breaks the multiaddr parser model... and so I made my multiaddr/net dev branches do this:

That is the colon separates the embedded onion port number.

whyrusleeping commented 8 years ago

@david415 doing /onion/timaq4ygg2iegci7:80 makes sense to me, all the parameters needed by the onion protocol are in the path element following it. Using the / is strange, as the 80 then doesnt have a label, and its not super clear what its trying to be. @jbenet thoughts?

jbenet commented 8 years ago

we'll already have things like:

/ip4/1.2.3.4/tcp/80/http
/dns/foo.com/A/ip4/tcp/80/http

if we made the restriction that only one component be used, why not then:

/ip4:1.2.3.4/tcp:80/http
/dns:foo.com:A:ip4/tcp:80/http

o/ this is actually harder to impl and does not layer well on a FS approach like 9P or linux proc files, which the former one does

whyrusleeping commented 8 years ago

thats not quite what I was getting at, i'm not saying that we require only one component. I'm saying that we combine the onion address and port into one as they both are given meaning by the /onion path element.

david415 commented 8 years ago

Any suggestions for changes to go-multiaddr-net? Do you not want Tor/Onion related stuff in DialArgs since it is not a thin-waist protocol? See here: https://github.com/jbenet/go-multiaddr-net/blob/master/convert.go#L142-L144

jbenet commented 8 years ago

@david415 right, DialArgs is for net.Dial mostly.

What we should do is:

(i unfort dont have time to work directly on this until after Sep 15. but can CR)

david415 commented 8 years ago

However... later it would be nice to have more granular policy for operating heterogeneous ipfs nodes/gateways/proxies.

david415 commented 8 years ago

I'm looking at go-multiaddr-net and go-ipfs to see how things work... and it makes sense for thin-waist protocols... but this type of thing isn't going to work for the OnionListener use case: https://github.com/ipfs/go-ipfs/blob/master/core/corehttp/corehttp.go#L50-L55

The onion multiaddr isn't enough information to create an onion listener. We need to know the tor process control port in order to create the onion service... then after we auto-create the onion service key material the control port tells us the onion address as well.

Perhaps in this case we need an onion + multiaddr helper function to create a new onion service and it's respective multiaddr? But how to plug it into the normal usage of go-multiaddr-net where the API user expects a multiaddr Listener to be created by only feeding it the multiaddr?

jbenet commented 8 years ago

@david415 maybe the listen onion multiaddr could be different, could include more information, like the proxy:

/ip4/127.0.0.1/tcp/<control-port>/onion/<onion-address>

but it still should be advertised to others as:

/onion/<onion-address>

Perhaps in this case we need an onion + multiaddr helper function to create a new onion service and it's respective multiaddr?

yeah that's definitely doable. harder to make things plug in nicely. the other option is to create a "listener-maker" and mount that onto multiaddr, like:

c := maonion.NewController(NewMultiaddr("/ip4/127.0.0.1/tcp/<control-port>"))
c.NewListener(NewMultiaddr("/onion/<onion-addr>"))

// mount onto a multiaddr-net 
manet.Listen("/onion/<onion-addr>") // doesn't work
manet.AddProtocol("onion", c)
manet.Listen("/onion/<onion-addr>") // now works
// 

but this is kind of "magical" in a way i dont like (i.e. static), probably makes much more sense to rework how multiaddr-net works into something like this:

n := manet.NewNetwork()
n.Add(manet.IP4)
n.Add(manet.IP6)
n.Add(manet.TCP)
n.Add(manet.UDP)
n.Add(onion.Onion)

l, err := n.Listener("/ip4/1.2.3.4/tcp/1234")
c, err := n.Dial("/onion/<onionaddr>") 

// with shortcuts like:
n := manet.NewThinWaistNetwork()
n.Add(onion.Onion)

"network" is a bit odd name, but does give the idea that these networks are stacked and makes more sense why mulriaddrs work the way they do. "transport" is another possible name, but may not capture the full meaning of "network".

jbenet commented 8 years ago

Sorry, let's move multiaddr pluggable-ness discussion to https://github.com/jbenet/go-multiaddr-net/issues/7

jbenet commented 8 years ago

hey @david415 -- @whyrusleeping has made transport changes to go-ipfs libp2p and to https://github.com/jbenet/go-multiaddr-net/ -- chances are we can resume the tor work!

david415 commented 8 years ago

cool! i'll take a look.

jbenet commented 8 years ago

I can put some effort toward this in feb too. On Sat, Jan 2, 2016 at 08:27 David Stainton notifications@github.com wrote:

cool! i'll take a look.

— Reply to this email directly or view it on GitHub https://github.com/ipfs/notes/issues/37#issuecomment-168390975.

kumavis commented 8 years ago

does running an ipfs server as a tor hidden service work by default? I guess there are quite a few dimensions to the intersection of tor and ipfs, and its difficult to tell what works out of the box and what needs development

david415 commented 8 years ago

No. IPFS does not "work by default" as a Tor onion service.

It is not difficult to tell the state of the IPFS + Tor integration because it is utterly non-existent; That's why we have this ticket!

cryptix commented 8 years ago

@david415 :+1:

To reiterate what @leif posted: It might work for dialing an IPFS node from a censored location but you better have a custom ipfs build that doesn't scream your identity to everybody in it's vicinity. I hope we can see different flavors of ipfs nodes before 1.0. A privacy preserving client is much needed otherwise every content you share and spread becomes a tracking cookie. I personally already have that barbed-wire in my head stopping me from using it to share music with my family and that's only a 1st world problem.

kumavis commented 8 years ago

@david415 @cryptix thanks -- I look forward to seeing this ticket progress. If I get some time I will try to pick up some tasks

seanlynch commented 8 years ago

I just posted a $100 bounty expiring in six months. Also paid to get it tweeted from @bountysource to hopefully get it some more attention. If there are blocker issues, let me know and maybe I can post bounties for those as well. https://www.bountysource.com/issues/26255361-tor-onion-integration

TheDeafMute commented 8 years ago

Hi everybody sorry for spammy wadup, but --- Whats the overview of progress atm?

(as a payment for this spammy question, If you all need a(n) alpha/beta tester I am perfectly willing :D)

david415 commented 8 years ago

@seanlynch you wanna pay us $100 for tor integration; ah hahaha. lol.

harlantwood commented 8 years ago

Great work trying to help get this ball rolling @seanlynch.

cpacia commented 8 years ago

One request with this feature we'd like people to be able to run dual stack nodes, reachable via onion and TCP. This way people who run openbazaar stores can opt to service people who are running onion only nodes in addition to regular users.

Kubuxu commented 8 years ago

With dual stack node you can't provide any gaurantees of anonymity, even running ipfs itself in tor only mode will make your tor node identifiable without some major changes.

whyrusleeping commented 8 years ago

@Kubuxu In a lot of cases, thats not necessary. @cpacia just wants to be able to expose his service to peers in the clearnet, and to peers in the tor-net. His node would be identifiable, sure, but it doesnt necessarily compromise the privacy of anyone who would connect to him

cpacia commented 8 years ago

Yeah that's correct. Someone running a dual stack wouldn't necessarily by trying to hide their own IP.

Thinking about it though that might mess up routing if a dual stack node publishes providers on both networks. Those providers wouldn't make it to K nodes on both networks.

seanlynch commented 8 years ago

@david415 I suppose you'd rather I not post a bounty at all? You were already working on it for free. My hope was that others would also contribute. So far an anonymous contributor has added another $15.

At any rate, given that I have been unable to get IPFS to even work reliably on clearnet, I'm not currently comfortable with increasing the bounty. And from reading others' comments, I am not alone in having problems. Once those problems are resolved, assuming I haven't found a better alternative, we can discuss what amount you might consider more palatable.

whyrusleeping commented 8 years ago

I'm working on a websocket ipfs transport and I will be doing a writeup of "how to make ipfs work over X" using websockets as an example. Hopefully me finishing that will make this task a bit easier.

david415 commented 8 years ago

@whyrusleeping @cpacia The other reason to allow clearnet + onion access is so that you can host a node at your house and be able to access it via your LAN when you are at home... and otherwise utilize it's onion service for connectivity. I don't see any conflict here with hiding the location of the service in this case.

spinda commented 7 years ago

Any progress on this?

david415 commented 7 years ago

@whyrusleeping did you write your howto-write-ipfs-pluggable-transports document yet?

@spinda clearly the next step is to write an onion/tor transport plugin for ipfs/go-multiaddr-net.

After that is done the focus should be on how to integrate that tor/onion plugin with the ipfs source...

jbenet commented 7 years ago

We will have a discussion session at the IPFS Q3 workshop on this. Will post the link here later.

jbenet commented 7 years ago

@seanlynch would love to hear more. Mind trying the 0.4.3-dev branch? It's solved a lot of problems people had with 0.4.2

Kubuxu commented 7 years ago

We have just released 0.4.3-rc1 give it a try.

david415 commented 7 years ago

attempting to write a tor onion transport plugin here: https://github.com/david415/ipfs-onion-transport

david415 commented 7 years ago

but is this the wrong way? there's this other api which seems to make more sense -> https://github.com/ipfs/go-libp2p-transport

seanlynch commented 7 years ago

@jbenet @Kubuxu I will try out 0.4.3-rc1 as soon as I can (two small kids). Thanks!

david415 commented 7 years ago

ok i'm going to fix my previous onion transport that i wrote a couple months ago. the problem i was running into previously is that we need the private key material in order to start listening on a given onion service. i will proceed as if the transport has a map from onions to keys... we can store the keys in files on disk or in a database. the constructor for the transport will specify the directory to store them in. fail if key material not found; although this implies some previous admin command to create the onion keys and onion addresses.

cpacia commented 7 years ago

@david415 I'm a little confused about the need for keys. Isn't it just a matter of listening on a given port on localhost and pointing the Tor hidden service configuration to that port to receive incoming traffic?

david415 commented 7 years ago

@cpacia Tor onion services use a 1024 bit RSA key. To create the service you need this private key. The onion address is in fact the truncated hash of the corresponding public key.

david415 commented 7 years ago

I fixed the transport. Here, it needs review: https://github.com/david415/ipfs-onion-transport/blob/master/onion_transport.go

cpacia commented 7 years ago

Oh, ok. For my implementation I was going to use the control port to set up the hidden service which, i believe, just returns the .onion address not the key. I can look and check.

david415 commented 7 years ago

https://gitweb.torproject.org/torspec.git/tree/control-spec.txt#n1433