Media transfer in webrtc with TURN relay - webrtc

Suppose A want to communicate with B
By sending Allocate request to turn server T1 , A get the relay address and port as R1:r1
Similarly, B sending Allocate request to turn server T2, B get the relay address and port as R2:r2
Now A want to send media to B, then A send media to R1:r1, with R2:r2 as the destination address, when turn server receives the media at R2:r2, it forward to B. is the media transfer in webrtc, forwarded in this way or not?
If A don't know the B's relayed transport address, then How can A reaches B?

Yes this is exactly how it works if you use TURN relay.
If A and B want to connect with each other, they must know each others server reflexive or relay address. This applies if A and B are in separate networks. Server reflexive address is NATs public address which is gathered through STUN server. If they don't know any of these two addresses then they can't connect with each other.
If A doesn't know B's relayed transport address then they can connect through server reflexive address.
Even knowing only server reflexive address of each other won't guarantee connection establishment. If one of A or B is behind symmetric NAT and other is behind Symmetric/PRC NAT then A and B must know the turn relay address of each other to guarantee connection establishment.

Related

WebRTC: do we need a TURN server if one peer is always using Full Cone Or Address Restricted (but not Port Restricted) NAT?

I have been reading a bit about WebRTC, and I'm not getting why we need a Turn Server if only 1 peer is using Symmetric NAT, and the other is using neither Symmetric nor Port Restricted NAT, so let’s say A is using Full Cone NAT, B is using Symmetric NAT:
STUN SERVER will send the correct IP address of B to A, and the correct IP + Port address of A to B.
A tries to connect to B (now A will be able to accept messages from B since it’s in the Dest Address Column).
B tries to connect to A, which will allow requests from A going to B (ofc A needs to update the port to the one received from B instead of the Sdp).
am I missing something, or is this correct (and implemented), or is this too complicated to be implemented?
And if this is correct, then theoretically, if I’m peer A and I'm using Full Cone NAT, any peer B can connect to me (as long as I send the connection request first), without needing a TURN server.
Thanks
If the symmetric NAT environment only changes the port, you would be correct with regarding connectivity to Full Cone NAT. The hole punching step would work.
But many enterprise and mobile environments have complex routing schemes and crazy network environments that are different from a legacy home network router. These environments aren't just a little router box that hooks up to a cable modem. It's a complex array of routers and load balancers using a bank of IP addresses. And each outbound connection might get an IP address different from a previous connection. So it's technically "symmetric NAT".
And so after a node within this environment obtains an external IP/port pair from a STUN server, subsequent sends to a peer address might change both both the port and the IP address as well.
As such, the NATs see completely different IP addresses than expected when the UDP packets arrive during the hole punching step. Hence, a relay address (TURN) is needed here.
This question is a little easier if you think in terms of Mapping/Filtering. The other NAT terms don't do a good job of describing how things actually work. My answer comes from RFC 4787 and WebRTC for the Curious: Connecting
Mapping is when your NAT allocates a IP/Port for an outbound packet. A remote peer can the send traffic to this mapping. Filtering are the rules around who can use these mappings.
Filtering and Mappings can then be address dependent and independent. If a mapping is address dependent it means a new mapping is created for each time you contact a new IP/Port. If a mapping is address independent it means it is re-used no matter where you send traffic. These same rules apply to filtering.
If one peer is address + filtering independent I don't believe a TURN server would provide a benefit.
If you want TCP connectivity deploying a TURN server is a good idea. Some WebRTC servers support TCP, but I don't believe any browsers generate passive TCP candidates.

Is a single TURN server sufficient for two devices behind restricted NAT configurations?

Let's assume two devices are behind symmetric NATs.
Device_1 ONLY gathers HOST and REFLEXIVE candidates. It sends them to Device_2 in an SDP OFFER.
Device_2 gathers HOST, REFLEXIVE and RELAY candidates. It sends them to Device_1 in an SDP ANSWER.
During ICE connectivity checks, Device_2 will install a permission into its TURN server. This will be the REFLEXIVE candidate of Device_1.
At some point, a STUN indication will be sent from Device_1 (reflexive) to Device_2 (relay). If Device_2 has created a permission for reflexive address of Device_1, the UDP packet should hit the TURN server, get wrapped in a STUN message, and then arrive at Device_2. This connectivity check should pass, and therefore bidirectional traffic should flow.
Is this understanding correct?
RESTRICTED_NAT RESTRICTED_NAT
| |
Device_1 <----> | <--UDP--> [Device_2_TURN] <--SEND--> | <----> Device_2
Peer | | Client
Host Host
Reflexive Reflexive
Relay
I asked a similar question a while ago Will ICE negotiations between peers behind two symmetric NAT's result in requiring two TURN servers?, but now im having doubts that two TURN servers are required for two peers behind symmetric NATs. The reason being, the permission that is created on the TURN server only includes an IP address.
https://datatracker.ietf.org/doc/html/rfc5766#section-9.1
When forming a CreatePermission request, the client MUST include at
least one XOR-PEER-ADDRESS attribute, and MAY include more than one
such attribute. The IP address portion of each XOR-PEER-ADDRESS
attribute contains the IP address for which a permission should be
installed or refreshed. The port portion of each XOR-PEER-ADDRESS
attribute will be ignored and can be any arbitrary value. The
various XOR-PEER-ADDRESS attributes can appear in any order.
That means that as long as the same server reflexive IP sends a UDP message to the relayed transport address, it should go through. Meaning, only one TURN server should be used.
Yes Philipp is right, it depends on the implementation details.
But the other criteria you did not specify is your list of assumptions is if the NAT's in front of Device_1 and Device_2 does let UDP pass through or not.
The most evil/problematic scenario is if Device_1 and Device_2 can't use UDP to connect to the Internet. In that case they both will have to use TCP to connect to each of their TURN relays. Since most (?) TURN servers today only hand our UDP candidates in this scenario Device_1 uses TCP to connect Device_1_TURN. The same applies to Device_2. But since both hand out UDP candidates now TURN server needs to connect to TURN server.
Device_1 <--TCP--> Device_1_TURN <--UDP--> Device_2_TURN <--TCP--> Device_2
In this case you can't get away with just one TURN relay, since Device_1 can't connect via UDP to the UDP based relay candidates of Device_2.
You could reduce this scenario to one TURN server again if the TURN server and Device_2 both implement support for TURN TCP candidates. And then Device_1 needs to have support for ICE TCP and connect via TCP to the TURN server:
Device_1 <--TCP--> Device_2_TURN <--TCP--> Device_2
This depends on how well the turn server software that you use has implemented the RFC. You'll need to check it.
The port is part of the xor-peer-address that gets sent to the TURN server so the natural assumption would be that any lookups happen against the full address.
But in the case of the other side being behind a symmetric NAT the port (and sometimes the IP but that is rare) used will be different. Which is likely the reason for the specific requirement in the RFC.

Why WebRTC uses a candidate pair and not one IP + Port pair for bidirectional communication

I've been investigating the "internals" of WebRTC and have made significant progress so far. My javascript client app works flawlessly, I've setup STUN, TURN(s) and my peers are able to connect even when both are located in symmetric NAT environments.
When I was reading the IETF draft on ICE and NAT traversal, I assumed that non-relay connections are possible, when at least one of the peers is located in a non-symmetric NAT environment, where UDP hole punching is possible on the routing gateway.
While building a WebRTC-based file transfer service, I realized I need to detect in code, if the transfer is relayed. I started investigating the connection and transport properties and it turned out that the transfer is still defined with candidate pair, and not a single connection of a given type.
So on receiver's side, I have:
Local candidate type: srflx
Remote candidate type: relay
which I probably should consider as "when a receiver is being sent data" - a bound port on NAT is used (srflx), but when the receiver is sending data to the sender (remote endpoint) - it is relayed.
Is this a correct "reading" of a pair configuration? But what's more important, given that there is an srflx candidate in a selected pair, why is it still a pair, and not one bidirectional connection socket?
WebRTC is primarily UDP. Keep that in mind with regards to "connections".
So on receiver's side, I have:
Local candidate type: srflx
Remote candidate type: relay
What this means is that all communication is going through the TURN server address allocated by the remote peer. And their TURN server is forwarding to your srflx address - which is your public IP address (and port mapping) as obtained via STUN/TURN.
So if you are trying to detect if you using a relay, check both the local and remote.
They are called "candidate pairs", because ultimately the WebRTC/P2P connection is going to established with one address from your end and one address from the other end. Each candidate address on your side is attempting to ping an address on the remote side. Eventually both sides converge on a single "candidate pair" as the final route.
Does this help?

How to check if webrtc peers communicated in p2p mode or relay mode

Say:
A and B in the same Lan,
A and B in different Lan.
but connect by webrtc logic, how can I check if it's really communicated by p2p or by relay server (turn server)? I can see multiple icecandidate exchanged each other but not sure which one is used actually!
For case 1) I think A and B should use local Lan connection to talk to each other but How can I confirm it's!
For case 2) it maybe use p2p connection or use relay server for media relay, how can I know what's the actual connection being used?
call the peerconnection.getStats() API once the ICE connection is up (i.e. on iceconnectionstatechange to connected or completed).
Then iterate the statistics to find the currently active connection, find the pointers to the local and remote candidate and look at their candidateType field.
The sample at https://webrtc.github.io/samples/src/content/peerconnection/constraints/ shows most of this but doesn't show the candidateType, only the ip and port.
Maybe below method is not good answer but it should work:
If A and B in the same lan, after connection finished, disconnect internet connection but keep Lan with A and B, if A and B can communicate successfully, then it must be communicated by Lan since internet disconnected already.
If A and B in different lan, just remove the turn server to connect A and B, if A and B can be connected and communicated successfully, then A and B should be not use relay server p2p communicate. otherwise if using turn server can communicate and without turn server can not, then it must be using turn server in relay mode. (i think it's a fake p2p since a relay server is in the middle of communication).

How to send packets to a client under Symmetric NAT

I am trying to send UDP Packets to a public server from a client in symmetric nat. i am able to send packets to the server However i want the server to send packets to the client under symmetric cone nat. How do i solve this? Please help me.
Make the server send packets to the client's external IP+Port which the server detects on the arrival of first packet from client.
Basically, the router allows any outgoing UDP traffic from the devices connected to it and blocks all incoming UDP traffic. But it maintains a table of source and destination IP+port whenever a UDP packet is sent out. It allows replies from devices external to the router, provided the router must have an entry of external device IP+port.
So, you just need to use this mapping in the table now.
Just make your server detect the client's external IP+port from the packet it receives from the client and then let the server send back packets to the client on that external IP+port.
This will punch a hole in the router's firewall i.e., the router firewall will now allow the incoming UDP packets as it already contains an entry in it's table. This process is called HOLE PUNCHING.
You can understand all this NAT traversal process in the various RFC's published.