Skip to content
This repository has been archived by the owner on Nov 22, 2022. It is now read-only.

Other signaling strategies #14

Open
backkem opened this issue Feb 15, 2019 · 19 comments
Open

Other signaling strategies #14

backkem opened this issue Feb 15, 2019 · 19 comments
Labels

Comments

@backkem
Copy link
Contributor

backkem commented Feb 15, 2019

go-libp2p-webrtc-direct contains the first step towards WebRTC support in go-ipfs: a port of js-libp2p-webrtc-direct which is the simplest WebRTC transport on the JS side. The drawback of *-libp2p-webrtc-direct is that the signaling is done over HTTP. This requires a direct connection between the peers and therefore can't make use of WebRTC's NAT traversal capabilities.

This ticket aims to explore other signaling strategies. For example, strategies that would also work when both peers are behind a NAT. I think it would be preferable to explore strategies that work across libp2p implementations.

'Centralized' signaling

Signaling over connected peers

@rob-deutsch

This comment has been minimized.

@cretz

This comment has been minimized.

@backkem

This comment has been minimized.

@cretz
Copy link

cretz commented Feb 15, 2019

Ah, ok. So to clarify, you need decentralized signaling on both the JS and Go. Part of my experiment was to find something that solved the same. There is a current bug preventing go-ipfs from talking to js-ipfs, but in general IPFS pubsub is the only solution I have found in this space. The only other thing I have considered is building a Go version of gun. Otherwise, there are other DHTs (e.g. bittorrent mainline) mutably available from Go, but the JS side can't write to them.

Also, in general I'd like to see a signaling abstraction project that provided a common API and a collection of signaling backends (not specific to decentralized or anything) that a dev could leverage. I personally moved to centralized a system like https://www.websocket.in/ after realizing there are no easy decentralized ones (I don't want a 600+k js-ipfs blob if I can avoid it and it was struggling to communicate w/ go-ipfs at the time of my experiment).

EDIT: I should add I have had recent success using https://github.com/amark/gun for signaling. I'm not sure it applies to a libp2p project though, it's more of an alternative than complementary.

@rob-deutsch
Copy link

rob-deutsch commented Feb 22, 2019

So I've been um'ing and ah'ing over this for the last week, and I have some thoughts to throw into the pile. And a suggested way forward...

I want to start by noting that the ultimate problem here can be framed as: PeerA and PeerB exist but can only run web browsers. PeerA wants to create a WebRTC connection with PeerB. We need some way of getting a message to PeerB. This is the ultimate desire, even though we call it "signalling".

Any solution here only makes sense if people will actually use it. Key attributes would be:

  • Better than centralised signalling
  • Reliable
  • Easily implementable by anyone and everyone. That is, even if it's not decentralised, there's umpteen free services to be used with no hassle.

So let's simplify this discussion be removing a few options:

  • daviddias/webrtc-explorer is not capable of fulfilling this role (yet). From the README.md; 'Currently signalling is performed through a central server. The signalling throught the Chord routing is under development.'
  • DHT doesn't appear - to my uninformed eyes - to offer much in the way of solutions. Correct me if I'm wrong?

Of the remaining options, they can be split into two buckets as follows:

Decentralised

Semi-decentralised

Decentralised

Unfortunately, I think we have to disregard decentralised signalling for now.

IPFS is an awesome decentralised network, and @cretz has done awesome work, but is pubsub ready for primetime? Is it possible to code? Is it sufficiently reliable? I'm unconvinced.

Tor is an interesting option. It allows us to pass messages between two peers. But will Tor allow to web browsers to pass messages between each other? It would need to have HTTP/WebSocket entry points.

Are there other options here?

Semi-decentralised

I am warming up to this idea. The two options above are more similar than we give them credit for, but they ultimately fail on two aspects:

  1. There are no public reliable servers because they are prone to abuse. I don't have a strong desire to operate what's essentially a free data proxy.
  2. libp2p/js-libp2p-webrtc-star is more than just a signalling server, it does peer discover as well. I would say that this is nice, but unnecessary.

Potential solution

I think the easiest way to phrase this is to do something like libp2p/js-libp2p-webrtc-star with a few important differences that make it far more desirable to operate free and open signalling servers:

  1. Standardised SDP. Currently libp2p/js-libp2p-webrtc-star can be abused as a proxy by putting arbitrary data into SDP offers/answers. If we have a standard SDP and peers only submit their ICE candidates then this severely limits the potential for abuse. The signalling server itself can develop the SDP offer/answer with no arbitrary data.
  2. No peer discovery feature.
  3. Describe it as simply a "front" for a WebRTC connection. A libp2p peer simply chooses and registers itself with a service, and then announces to the world essentially something along the lines of "if you want to to talk to me, send your SDP offer to this other peer"

@cretz
Copy link

cretz commented Feb 22, 2019

Tor is an interesting option. It allows us to pass messages between two peers. But will Tor allow to web browsers to pass messages between each other? It would need to have HTTP/WebSocket entry points.

If you're in the Tor browser, there are some opportunities, but not much more than a regular browser. I have a PoC that might interest you though it's outdated and there needs to be an app side somewhere: https://github.com/cretz/tor-dht-poc

@rob-deutsch
Copy link

Wow @cretz, is there anything you haven't done?!

The thing is that we would want Tor to be access for a regular browser.

@backkem
Copy link
Contributor Author

backkem commented Mar 4, 2019

@rob-deutsch I agree with your thoughts above. It would be interesting to create a super strict, minimal version of SDP. Some thoughts:

  • I think we should probably add limits to variadic parts of SDP. E.g. for these data oriented use-case you could limit to only a single data channel media section.
  • I'm debating if protocol buffers could offer an advantage over JSON for the data format. It's fast & strict but it would add an extra dependency on the the browser side.
  • I'm also interested in re-writing pions/signaler to be an extendable signaling server where you can plug in your own signaling mechanism, transport protocol and middleware (e.g. for monitoring). Maybe this effort could live in that repo.

@cchudant
Copy link

Could the dialMe protocol (libp2p/specs#64) be used to achieve browser-to-browser p2p?

Here is how that would work:

  • Peer A wants to dial Peer B
  • Peer A uses p2p-circuit in order to dial Peer B
    At this point Peer A and Peer B are connected over a relay
  • Peer A sends its ICE using the dialMe protocol (using a multiaddr with its ICE) to Peer B over the relay
  • Peer B initiates the WebRTC connection to Peer A and direct connection is achieved

The dialMe protocol was introduced to handle the case where a peer is behind an impenetrable NAT, and since we need some way to exchange the ICEs between browsers, I think it makes sense to use it here.

@backkem
Copy link
Contributor Author

backkem commented Apr 24, 2019

@SkyBeastMC It seems the dialMe protocol currently only allows for exchanging a peer id and multi addresses:

message DialMe {
  message Peer {
    required bytes id = 1;    // peer id
    repeated string addrs = 2; // a multiaddr to dial the the peer over
  }
   optional Peer peer = 1;

In order to exchange ICE info we need:

  • A way to send the SDP offer as part of the DialMe message. This can be done by either:
    • Extending the message to include some arbitrary data.
    • Formulate a way to represent a SDP offer/answer as a MultiAddr.
  • A way for the peer to send a reply to the (specific) DialMe request containing the SDP answer.

@cchudant
Copy link

Oh, I forgot Peer A needed Peer B's SDP answer as well.
Should we create another protocol for exchanging SDPs then?

@backkem
Copy link
Contributor Author

backkem commented Apr 24, 2019

Maybe we can add it to the spec discussion.

@guysv
Copy link

guysv commented Nov 4, 2019

@rob-deutsch I'm not sure that it's possible to standardize the SDP dialog. There will always be user-controlled bits in the SDP, hence the signaling server could always be abused into transferring arbitrary data. It might be less obvious, which is not much, but it will also have higher bandwidth overhead, which will might deter attackers.

Anyway, in my opinion, a metered-per-peer signaling service should solve this exploit in a more elegant way.

Also, what about forwarding messages in exchange for POW? 👀

@backkem
Copy link
Contributor Author

backkem commented May 17, 2020

The go-webrtc-aside-transport implements signaling over another transport.

@ForestJohnson
Copy link

I'm super interested in using this software (https://github.com/libp2p/go-libp2p-webrtc-direct, https://github.com/Jorropo/go-webrtc-aside-transport). For my use case, I want to establish a connection between two servers that are both potentially behind NAT. For me, routing application traffic through a relay circuit defeats the purpose. However, in my use case it's reasonable to assume that a semi-trusted relay circuit exists for the purposes of exchanging Session Description Protocol (SDP).

I also want to establish a connection between a browser and one of those servers, but that's less important to me initially.

I know it won't work If neither of them can get a public listening port (for example, via upnp), and/or one of them has an inscrutable NAT/firewall. But I'm hoping I can get it to work for the majority of users who are on reasonable "home" networks, for example, not dorm WiFi, not LTE hotspot, and not restrictive corporate firewall.

@aarshkshah1992
Copy link

aarshkshah1992 commented Feb 4, 2021

We have a spec for a direct connection upgrade over Relay:
libp2p/specs#173

which has been implemented at:
libp2p/go-libp2p#711.

We are also currently exploring the idea of "limited Relays" which meter the bandwidth and time you can use them for (should be just about enough for co-ordinating a hole punch/signalling).

Would be great to use something similar for the signalling so we don't rely on direct HTTP connections.

@backkem
Copy link
Contributor Author

backkem commented Feb 4, 2021

@aarshkshah1992 Are there plans to 'abstract' the signaling? AKA have the signaling path be injected into transports that require it. That would allow protocols that need signaling to be developed separately from all potential signaling paths. In the case of this repo it would mean we only need go-libp2p-webrtc instead of all the different flavors there are today.

@aarshkshah1992
Copy link

@backkem None for now but will very much keep this in mind when we get to working on decentralised signalling for WebRTC.

@o01eg
Copy link

o01eg commented Sep 23, 2021

I think it also possible to connect browser node to non-browser node with public IP without any signaling by generating answer SDP. It only requires TLS fingerprint which could be part of address.

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

No branches or pull requests

8 participants