9

I was under the impression that WebRTC goes to great lengths to achieve P2P connectivity despite NATs. [1][2] That's why I was surprised to learn that WebRTC fails to connect peers in some situations where a P2P connection is easy to achieve. I would like to understand why this happens, and if there is anything I can do to improve the situation.


Why do I claim that P2P is easy to achieve in some of these situations? I claim this because I have set up an experiment with 2 devices on different networks:

  • Device F is connected to the internet behind Full-cone NAT
  • Device S is connected to the internet behind Symmetric NAT

I can easily achieve a P2P connection between these devices in the following manner:

  1. Device F binds a connection to a random (unpredictable) port and sends a UDP packet through that port to anywhere on the internet. Because F is behind Full-cone NAT, this packet has "hole-punched" the port open, allowing any external addresses to now send packets through that port. In my case the port that I opened locally appears to be the same as the external port. (If the external port was different from the local port, we could use something like STUN to figure out the external port.)

  2. Device S binds a connection to a random (unpredictable) port and sends a UDP packet through that port to the external IP and port of Device F. This packet can be delivered, because the port was hole-punched open in step 1. After this packet, Device S has hole-punched through its own port, allowing packets from Device F to be sent back through it. Device F will know where to send the packets, because the packet that S sent contains the external IP and port. Because Device S has Symmetric NAT, the hole-punching didn't open the port for all traffic, only for traffic from Device F (the external IP and port of Device F).

I used Python to verify that I am able to open a P2P connection between these devices and send messages in both directions, as described above. I don't understand why WebRTC is unable to achieve a P2P connection like this.


Why do I claim that WebRTC fails to connect in some of these situations where a connection should be easy? I claim this because I tried to achieve a WebRTC P2P connection with 3 different code examples. All of the examples worked when devices were in the same local network, but didn't work when the devices were in different networks (the setup described above). None of the libraries I tried provided any useful debugging information to figure out what went wrong, and chrome://webrtc-internals didn't provide any useful information either. I also tried in Firefox to verify that this issue is not implementation-specific.

To be specific, I tried the following code examples:

  1. simple-peer, a WebRTC library. I tried the first example code in the README.

  2. PeerJS, another WebRTC library. I tried the demo page they have set up.

  3. A code snippet from a Stackoverflow answer. [3]

In all 3 experiments I also tried to switch which device initiates the connection and which device receives it.

Since this issue isn't specific to WebRTC implementation, and it isn't specific to any particular WebRTC JavaScript library, I'm beginning to suspect that the spec for WebRTC is broken in some fundamental way, preventing WebRTC from achieving P2P connections in situations where they would be easy to achieve. Am I missing something here?

[1] https://webrtc.org/getting-started/turn-server states: "For most WebRTC applications to function a server is required for relaying the traffic between peers, since a direct socket is often not possible between the clients". This gives the impression that WebRTC should be able to achieve a P2P connection in a scenario where it is easy to achieve.

[2] https://webrtcforthecurious.com/docs/03-connecting/ states: "WebRTC will gather all the information it can and will go to great lengths to achieve bi-directional communication between two WebRTC Agents." This also gives the impression that WebRTC should be able to achieve a P2P connection in a scenario where it is easy to achieve.

[3] WebRTC datachannel with manual signaling, example please?

Atte Juvonen
  • 4,922
  • 7
  • 46
  • 89
  • You didn't show a whole lot of code. Did you specify a STUN server in your WebRTC configuration? How are you exchanging the offer message between endpoints? Did you get wireshark traces and logs from both sides to see what candidates were getting generated? Without any of this, we can only speculate. – selbie Jan 08 '22 at 19:10
  • Have you tried making device S the offeror/initiator and device F the answerer/receiver? In your testing which device called `RTCPeerConnection.createOffer()` and which device called `createAnswer()`? Have you tried switching roles? I've added better console status logging to the SO Example. Once you paste the offer in second tab don't put answer immediately in first tab, wait, second tab connection attempts time out. Then you put answer in first tab, then first tab attempts connection and both connect. Let us know what is the behavior in your setup, with switched roles between device F and S – the Hutt Jan 12 '22 at 14:09
  • it is already a long post to read, and you are adding more details in the comments. please edit your post for these extras so people can see what else have you got. and check if you have redundant information, and make sections through the use of horizontal split lines and header. – Yılmaz Durmaz Jan 19 '22 at 08:07

0 Answers0