Chrome WebRTC DataChannels: ICE-TCP server reflexive candidates missing even with STUN
Asked Answered
D

1

5

I'm building (yet another) manual signalling WebRTC chat via DataChannels (CoffeeScript, sorry JS guys). It works fine in local connections, but not over the internet behind a NAT (unfortunately I couldn't try NATless yet).

I don't want to maintain a TURN server, but I'm fine if only one peer must be publicly-reachable from the internet for the setup to work. Since I'm the only one with a reachable machine, we need me to host a TCP connection. In Firefox there are no TCP candidates reported so I guess ICE-TCP is not yet supported.

On Chrome, looking at the SDP offers/answers, the STUN servers correctly identified both peer's public IPs and added each server reflexive UDP candidate (see line 10 below) but there is no TCP server reflexive candidate, so the connection never succeeds. There is also a TCP candidate included (see line 9 below) but it's just a host candidate.

Here's a sample SDP offer (my public IP is 88.88.88.88):

01. v=0
02. o=- 7452583715680269460 2 IN IP4 127.0.0.1
03. s=-
04. t=0 0
05. a=msid-semantic: WMS
06. m=application 50816 DTLS/SCTP 5000
07. c=IN IP4 88.88.88.88
08. a=candidate:864190085 1 udp 2122194687 10.10.10.4 50816 typ host generation 0
09. a=candidate:2097250933 1 tcp 1518214911 10.10.10.4 0 typ host generation 0
10. a=candidate:3500406889 1 udp 1685987071 88.88.88.88 50816 typ srflx raddr 10.10.10.4 rport 50816 generation 0
11. a=ice-ufrag:2066nM5kqwFDQMBT
12. a=ice-pwd:thO7oP0H+H1VBHFNfT8SLFiI
13. a=ice-options:google-ice
14. a=fingerprint:sha-256 72:87:BF:AD:03:9C:09:A7:58:0C:3A:DF:.....:B7
15. a=setup:actpass
16. a=mid:data
17. a=sctpmap:5000 webrtc-datachannel 1024

I'm sure the internet can reach my machine via NAT and port forwarding is fine (my machine is the default host to NAT-forward to).

  • Why is there no TCP server-reflexive candidate reported in my offers/answers?
  • Does Chrome lack server-reflexive ICE-TCP candidate discovery?
  • Is it possible to manually add a server reflexive candidate given the public IP reported by the STUN server?
Darcidarcia answered 2/5, 2014 at 18:35 Comment(0)
U
5

First, STUN can support TCP over a NAT in accordance with the new RFC and with the proposed updates for said RFC for DTLS. All this said, Chrome should still support SCTP over TCP and Firefox still does not according to bug 891551.

I also highly doubt that MEDIA will ever support a TCP connection and suspect that only SCTP will be supported for any TCP connection(relayed or not).

[Note: For history sake, I am keeping the rest of my answer intact but a good comment made by @adamfisk, showed me some errata.]


Original answer

STUN CANNOT work with TCP over a NAT.

Its RFC says as much in the application statement. Stun is only designed to work with UDP. This is why SCTP needs to be on built on UDP so that you can go around NATs. (Only Chrome gives the internal option of TCP).

You will have to set up port forwarding on one of the NATs if you want TCP traffic to go through it but STUN will not help you.

Sorry for the bad news :(

EDIT: This is simply a limitation of STUN, not of SCTP(so chrome could do nothing about it if they wanted to). FireFox does NOT support SCTP over TCP anyways. I am not 100% on TURN. The RFC seems to say that TCP is support only in the communication between the client and the server, not the actual relay. Check this out, Chrome may work with TCP through a TURN server from what T. R. Missner states at the bottom of the thread.

You MAY have to have port forwarding set up on both sides if you want to use TCP with an RTCDataConnection.

Unread answered 2/5, 2014 at 19:32 Comment(11)
So then both peers need a port-forwarded NAT? Too bad, I thought TCP could be used to circumvent the issue behind the scenes with the classic approach where the port-forwarded host acts as a TCP server so the other peer can connect to him. Seems weird it's not one of the options STUN provides!Darcidarcia
Also: why is ICE-TCP implemented then? Is this a case of DataChannels being mandatory SCTP? And why are the dummy local TCP connections shown? I feel like I'm really missing something here.Darcidarcia
@DuckTyped, I edited my answer, It would seem that TURN MAY be your only option other than Port forwarding.Unread
Yup, STUN does not address TCP, either incoming or outgoing. Too bad, since a single TCP server should suffice. Of course ICE still works, but without external-IP candidates and STUN not providing TCP support it's pretty much useless.Darcidarcia
According to tools.ietf.org/html/draft-ietf-mmusic-ice-tcp-16#section-5 the TCP candidates I'm getting are host candidates (5.1). 5.4 seems redundant when already using UDP, but why are Server Reflexive Candidates (5.2) not working? I guess 5.3 is not even implemented in Chrome (though my NAT has UPnP enabled), but 5.2 looks exactly like what I need, TCP candidates with public-IP-discovery. There is an interesting note at the bottom of section 5.2: A widely used protocol for obtaining server reflexive candidates is STUN.Darcidarcia
@Darcidarcia Yes, ICE could possibly support TCP but since you are only working with STUN servers, you can only get external UDP candidates. Chrome's ICE negotiation is limited by the servers that you provide. The main issue is probably the server you are utilizing and since they just seem to be public servers, they very well may not be that complex and support everything.Unread
According to bugzilla.mozilla.org/show_bug.cgi?id=891551, the stunprotocol.org server is ICE-TCP enabled. As I understand the ICE-TCP draft, server reflexive discovery can use STUN to learn about its external IP address even if STUN returns only UDP candidates. I think the culprit here is Chrome, which just does not implement the srflx discovery even if the STUN server returns an appropriate srflx candidate. Thanks for your time, I'll leave this answer unaccepted for a couple days in case anyone can help.Darcidarcia
First, you're referencing an old STUN RFC. The current one is: tools.ietf.org/html/rfc5389 There you'll see that STUN certainly does support TCP, and it's used for ICE-TCP. ICE-TCP itself will only work in a smaller percentage of cases than UDP, however, so is much less reliable. That's likely why it's not implemented in WebRTC, and it may never be.Missal
@adamfisk, thanks for the update :). I updated the answer to indicate that STUN could support TCP but honestly, only SCTP will be supported and right now only by Chrome(there is a bug for Firefox currently on fixing that).Unread
@BenjaminTrent agreed. I don't necessarily think ICE-TCP is clearly useful in many scenarios, but it does exist =). STUN is like HTTP and many other protocols, however, in that it doesn't specify the transport. So saying that STUN doesn't support TCP is incorrect.Missal
So, again, you're referencing an obsolete RFC. STUN really plays a small part in ICE, which does the heavy lifting, and STUN over TCP or over UDP will always will with any NAT because NATs never block outgoing traffic in general. Saying STUN doesn't work with a NAT is like saying HTTP doesn't work with a NAT. The thing that might not work with specific NAT combinations is ICE. ICE is what actually traverses the NAT while STUN is an extremely simple protocol that the NAT doesn't affect.Missal

© 2022 - 2024 — McMap. All rights reserved.