Meaning of TURN Server's transport option

1,268 views
Skip to first unread message

Thanasis Polychronakis

unread,
Aug 7, 2015, 5:08:09 AM8/7/15
to discuss-webrtc
Hello there,

I am trying to understand what significance the transport option has in a TURN based ICE Candidate gathering.

I am talking about when defining the turn server endpoints on PeerConnection initialization:

turn:<IP_ADDR>?transport=tcp


I understand that TURN servers will not return TCP ICE Candidates for WebRTC as WebRTC simply does not support it... (however it does support p2p TCP WebRTC connections, correct?)

So what is the meaning of defining a transport query parameter in the TURN Server's url? How does it affect the ICE Candidates gathering operation?


Thomas Bruun

unread,
Aug 7, 2015, 6:16:25 AM8/7/15
to discuss...@googlegroups.com
This section of the TURN RFC does a pretty good job of explaining it:
https://tools.ietf.org/html/rfc5766#section-2.1
> --
>
> ---
> You received this message because you are subscribed to the Google Groups
> "discuss-webrtc" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to discuss-webrt...@googlegroups.com.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/discuss-webrtc/0b1ed748-87a5-441b-aebd-3781e6002ba3%40googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.



--
Thomas Bruun
Developer, appear.in

Thanasis Polychronakis

unread,
Aug 7, 2015, 6:45:31 AM8/7/15
to discuss-webrtc
Thank you Thomas!

So I understand the literal meaning of the transport option for a TURN request, now i need to understand how significant it is for WebRTC.

I am trying to understand if determining TURN TCP connectivity has any meaning via the means of a WebRTC capable browser. I am reading the Testrtc code published by google that is available at: https://test.webrtc.org/

I know that an ICE Candidate of type srflx (STUN) with protocol TCP and an internet IP means that the client has inbound TCP connectivity.

But analyzing how the testrtc code works I am still baffled on they way it uses a TURN server with transport type of TCP. The tests begin by fetching TURN server credentials using the url: https://computeengineondemand.appspot.com/turn?username=1234&key=5678, if you open that url you will get back a JSON with the TURN servers from google, a couple using UDP as the transport and the same couple using TCP.

Then tcp connectivity is inferred from this part of the code: https://github.com/webrtc/testrtc/blob/master/src/js/conntest.js#L25-L34 that looks for TCP candidates generated from the TURN server (as explained by the comment above).

So why is this technique being employed and what can it tell us for the connectivity state of the client?

There are two ultimate questions I need to answer:

1. How can we be sure that the client can perform outbound TCP connections? (Isn't turn initial handshake being done by tcp anyway? so any relay candidate of any type means de facto that the client can perform an outbound TCP connection, at least on  TURN's port 3478).

2. Does using a TURN url with a transport of TCP give us any useful information as to the client's connectivity abilities? If not why do we need it in WebRTC and what is testrtc trying to accomplish?

Thanks

Christoffer Jansson

unread,
Aug 7, 2015, 8:34:22 AM8/7/15
to discuss...@googlegroups.com
On Fri, Aug 7, 2015 at 12:45 PM Thanasis Polychronakis <than...@gmail.com> wrote:
Thank you Thomas!

So I understand the literal meaning of the transport option for a TURN request, now i need to understand how significant it is for WebRTC.

I am trying to understand if determining TURN TCP connectivity has any meaning via the means of a WebRTC capable browser. I am reading the Testrtc code published by google that is available at: https://test.webrtc.org/

I know that an ICE Candidate of type srflx (STUN) with protocol TCP and an internet IP means that the client has inbound TCP connectivity.

But analyzing how the testrtc code works I am still baffled on they way it uses a TURN server with transport type of TCP. The tests begin by fetching TURN server credentials using the url: https://computeengineondemand.appspot.com/turn?username=1234&key=5678, if you open that url you will get back a JSON with the TURN servers from google, a couple using UDP as the transport and the same couple using TCP.

Then tcp connectivity is inferred from this part of the code: https://github.com/webrtc/testrtc/blob/master/src/js/conntest.js#L25-L34 that looks for TCP candidates generated from the TURN server (as explained by the comment above).

So why is this technique being employed and what can it tell us for the connectivity state of the client?

There are two ultimate questions I need to answer:

1. How can we be sure that the client can perform outbound TCP connections? (Isn't turn initial handshake being done by tcp anyway? so any relay candidate of any type means de facto that the client can perform an outbound TCP connection, at least on  TURN's port 3478).

You are correct in that the TURN https://tools.ietf.org/html/rfc6062 server requires the request being made over TCP regardless of requesting transport=udp/tcp.

2. Does using a TURN url with a transport of TCP give us any useful information as to the client's connectivity abilities? If not why do we need it in WebRTC and what is testrtc trying to accomplish?
This makes sure that the TURN server allocates TCP candidates (https://tools.ietf.org/html/rfc6062#section-5.1), then the client generates RELAY TCP candidates if successful, if we cannot gather any RELAY TCP candidates we know it's not a viable option (trusting that the TURN server will provide TCP candidates if possible, i.e. the issue is most likely on the clients network).

When testing in general, it's good practice to be explicit/specific, otherwise it's hard to set pass/failure criteria (unless you are doing fuzzing/exploratory testing). 
In this case we test for RELAY TCP candidates hence why we specially request the TURN server to allocate them.

Also you got to remember that some ports might be blocked, do not just think of the protocol by itself as a sole factor here. 

Another thing to note is that there is no guarantee for a successful connection, it's a best effort approach, the same goes for these tests.

Hopefully that answers your questions somewhat.

/Chris

Alexandre GOUAILLARD

unread,
Aug 7, 2015, 9:44:34 AM8/7/15
to discuss...@googlegroups.com
But analyzing how the testrtc code works I am still baffled on they way it uses a TURN server with transport type of TCP. The tests begin by fetching TURN server credentials using the url: https://computeengineondemand.appspot.com/turn?username=1234&key=5678, if you open that url you will get back a JSON with the TURN servers from google, a couple using UDP as the transport and the same couple using TCP.


the CEOD code is just here to load balance the turn server cluster. It will give you back a turn server (IP:port) and credentials. It is up to the application to decide if it is going to use tcp or udp to connect to TURN. then, depending if the prefix is turn or turns you will end up with the four possible cases:
turn + udp => udp
turn + tcp => tcp 
turns + tcp => tls
turns + udp => dtls (spec in progress)

 
Then tcp connectivity is inferred from this part of the code: https://github.com/webrtc/testrtc/blob/master/src/js/conntest.js#L25-L34 that looks for TCP candidates generated from the TURN server (as explained by the comment above).


the candidates are not generated by the turn server. the candidate are generated by the browser locally, but only if the turn server answered to lower level connection primitives. You do not have access to this step at the JS level, you can only infer it by the existence of a relay candidate, which is exactly what the code does:
- ask the ice gathering to try to generate a relay candidate with transport = tcp and the provided turn server
=> if the turn server exists (suppose it is, google provides it)
=> if the credential are ok (again, suppose it is)
=> if there is a local port that let tcp through
=> if the turn server is configured to receive TCP on the corresponding port (suppose it is)
THEN
a relay candidate is create during the gathering.

By getting a relay candidate (or not) knowing all the other steps, you infer if you have any tcp port open.

 Rince and repeat for udp, tls dtls, just like the code does.

 
You are correct in that the TURN https://tools.ietf.org/html/rfc6062 server requires the request being made over TCP regardless of requesting transport=udp/tcp.

Webrtc does not support TCP connection *outbound from TURN*. whatever protocol you use to connect to the turn server form the client, it will only relay over UDP thereafter.


peer A <----[udp, tcp, tls, dtls] ---->  TURN <------udp------> ..... (can be peer B directly, or another turn server and peer B)


For more options, visit https://groups.google.com/d/optout.



--
Alex. Gouaillard, PhD, PhD, MBA
------------------------------------------------------------------------------------
CTO - Temasys Communications, S'pore / Mountain View
President - CoSMo Software, Cambridge, MA
------------------------------------------------------------------------------------

Thanasis Polychronakis

unread,
Aug 7, 2015, 9:45:30 AM8/7/15
to discuss-webrtc
Hi Christopher!

Some followup questions:

When testing in general, it's good practice to be explicit/specific, otherwise it's hard to set pass/failure criteria (unless you are doing fuzzing/exploratory testing). 
In this case we test for RELAY TCP candidates hence why we specially request the TURN server to allocate them.

My app is actually trying to do fuzzy / exploratory testing, much like testrtc does, you can view a test result in this url that I snapped right now: https://www.netscan.co/r/JVyR7

The problem is that a TURN server, with transport set to TCP will never produce any RELAY TCP Candidates. I guess this means that the client (the browser) is not capable of performing a connection through the TURN server via TCP thus will not display those candidates (as they are not valid).

Is this correct?  

Christoffer Jansson

unread,
Aug 7, 2015, 9:55:05 AM8/7/15
to discuss...@googlegroups.com
On Fri, Aug 7, 2015 at 3:45 PM Thanasis Polychronakis <than...@gmail.com> wrote:
Hi Christopher!

Some followup questions:

When testing in general, it's good practice to be explicit/specific, otherwise it's hard to set pass/failure criteria (unless you are doing fuzzing/exploratory testing). 
In this case we test for RELAY TCP candidates hence why we specially request the TURN server to allocate them.

My app is actually trying to do fuzzy / exploratory testing, much like testrtc does, you can view a test result in this url that I snapped right now: https://www.netscan.co/r/JVyR7

The problem is that a TURN server, with transport set to TCP will never produce any RELAY TCP Candidates. I guess this means that the client (the browser) is not capable of performing a connection through the TURN server via TCP thus will not display those candidates (as they are not valid).

Is this correct?  
See Alexandre GOUAILLARD's answer, he's a lot better at explaining these things as you can see ;)

/Chris

Christoffer Jansson

unread,
Aug 7, 2015, 9:56:10 AM8/7/15
to discuss...@googlegroups.com
On Fri, Aug 7, 2015 at 3:44 PM Alexandre GOUAILLARD <agoua...@gmail.com> wrote:
But analyzing how the testrtc code works I am still baffled on they way it uses a TURN server with transport type of TCP. The tests begin by fetching TURN server credentials using the url: https://computeengineondemand.appspot.com/turn?username=1234&key=5678, if you open that url you will get back a JSON with the TURN servers from google, a couple using UDP as the transport and the same couple using TCP.


the CEOD code is just here to load balance the turn server cluster. It will give you back a turn server (IP:port) and credentials. It is up to the application to decide if it is going to use tcp or udp to connect to TURN. then, depending if the prefix is turn or turns you will end up with the four possible cases:
turn + udp => udp
turn + tcp => tcp 
turns + tcp => tls
turns + udp => dtls (spec in progress)

 
Then tcp connectivity is inferred from this part of the code: https://github.com/webrtc/testrtc/blob/master/src/js/conntest.js#L25-L34 that looks for TCP candidates generated from the TURN server (as explained by the comment above).


the candidates are not generated by the turn server. the candidate are generated by the browser locally, but only if the turn server answered to lower level connection primitives. You do not have access to this step at the JS level, you can only infer it by the existence of a relay candidate, which is exactly what the code does:
- ask the ice gathering to try to generate a relay candidate with transport = tcp and the provided turn server
=> if the turn server exists (suppose it is, google provides it)
=> if the credential are ok (again, suppose it is)
=> if there is a local port that let tcp through
=> if the turn server is configured to receive TCP on the corresponding port (suppose it is)
THEN
a relay candidate is create during the gathering.

By getting a relay candidate (or not) knowing all the other steps, you infer if you have any tcp port open.

 Rince and repeat for udp, tls dtls, just like the code does.

 
You are correct in that the TURN https://tools.ietf.org/html/rfc6062 server requires the request being made over TCP regardless of requesting transport=udp/tcp.

Webrtc does not support TCP connection *outbound from TURN*. whatever protocol you use to connect to the turn server form the client, it will only relay over UDP thereafter.
Right, sorry for not being clear on that part, I was referring to the Peer A to TURN connection as you illustrate below not the other end (e.g. Peer B etc). 

Alexandre GOUAILLARD

unread,
Aug 7, 2015, 10:08:18 AM8/7/15
to discuss...@googlegroups.com
thanks chris.

I bumped into that stone long time ago and learned from the best:
- justin uberti pointed me to the difference between inbound and outbound connection to a turn server (super confusing at first since it kinda read "turn tcp" for both, right? )
- warren McDonald made a very clear email on the mailing list long time ago (2 years-ish) with the matrix of configurations for the turn urls. Not only that but he had tested them all with both firefox and chrome, at a time I did not even understand the difference.... I was humbled.

Happy I could help.

alex.


For more options, visit https://groups.google.com/d/optout.

Thanasis Polychronakis

unread,
Aug 7, 2015, 12:28:57 PM8/7/15
to discuss-webrtc
Thank you Alex and Chris, 

so to summarize:

in our case we only have a single peer (A) as we try to determine their connectivity state for www.netscan.co.

As long as this peer:

  1. Does not accept inbound TCP or UDP connections (no srflx candidates)
  2. Is not able to produce any TURN UDP candidates thus can not connect with the TURN server
  3. And we reliably determine that outbound TCP is not possible (via custom XHR probes on high random ports with the turn or other server)
Then is it safe to assume that this client will not be able to perform any WebRTC connection under any scenario?

Alexandre GOUAILLARD

unread,
Aug 7, 2015, 12:45:25 PM8/7/15
to discuss...@googlegroups.com
you still need to test the secure variants of connection through TURN (TLS / DTLS), at least TLS over 443.

I would also test connection with HTTP proxy, but I think you should have that covered since it is transparent to the JS app.


For more options, visit https://groups.google.com/d/optout.



--
Reply all
Reply to author
Forward
0 new messages