sipsorcery
sipsorcery copied to clipboard
WebRTC TURN over TCP needs adjust
Clients firewalls are outright configured to block UDP or not route UDP. This presents a problem to establish WebRTC sessions to our SipSorcery .NET backend, even when we provide a TURN server to proxy the traffic between peers. In this implementation, the browser is peer to the backend stack, the corresponding peer (on a static IP address)
While the client can establish a TCP connection to COTURN (our TURN server), it seems SipSorcery does not offer TCP options. It is not clear if this line L287 is a bug since "udp" is hard coded under the tcp condition:
https://github.com/sipsorcery-org/sipsorcery/blob/23441de26e75e83d117b0e94abfd8ab15cd0e159/src/net/ICE/RTCIceCandidate.cs#L287
There is a TCP ICE channel albeit with a very confusing base class. I have personally never used or tested that implementation.
In the original implementation no TCP option was implemented for RTP as I was somewhat skeptical that it would work well enough to be useful. As soon as there's packet loss or congestion TCP is going to be a big handicap for real-time media. I do get the point about corporate firewalls blocking UDP and I guess with WebRTC now taking over from VoIP an occassionally glitchy stream is better than no stream.
WebRTC is indeed taking a learing role in the conversational AI implementations, since its ability to carry data and voice provides a cross-browser channel whilst avoiding WebSockets, often outright blocked in corporate networks.
We see tcp in the robust solutions like Google Meet, when udp failsover:
Engineers best to decide on their implementation. Quality difference in 1:1 streams should be minimally different (passing over same routes).
We shall do trails of PR https://github.com/sipsorcery-org/sipsorcery/pull/1295 in our preprod.
Really love your work. Will contribute additional PRs, wherever we can help too.
@sipsorcery I saw that the PR https://github.com/sipsorcery-org/sipsorcery/pull/1295 is now merged, to align RTC candidate to use TCP. Can we release an updated Nuget with the changes?
@bryanlimktscv (or anyone else) would you be able to confirm whether that PR allows ICE over TCP to now work?
It is not clear if this fix solves it, because the interim solution has been JavaScript client to use tcp to TURN server, while backend .net stack uses UDP. this solved the client accessing through their firewall.
on revision, its not clear if it should return tcp and must be checked against RFC spec, as we often see tcp connects receive udp proposal:
using TURN server: Coturn-4.6.3 'Gorst'
If forced to use TCP Allocation by using REQUESTED-TRANSPORT: TCP, it fails relay and connectivity.
There might be something we're missing, haven't looked at the RFC again.
tcpdump on the TURN server
I tried the webrtc samples in Firefox and Chromium (Edge). While the connection with the TURN server is TCP, it still uses UDP encapsulated inside the TURN-TCP (?)
At this point, I don't know if WebRTC behavior is on the same level or not.
JSONs from Firefox
-
Both forces relay-only
-
RTCPeer A is configured with
?transport=tcp -
RTCPeer B is without
-
RTCPeer A
{
"sdp": "v=0
o=mozilla...THIS_IS_SDPARTA-99.0 7142885487407455343 0 IN IP4 0.0.0.0
s=-
t=0 0
a=fingerprint:sha-256 DA:EC:9D:9A:A5:33:F4:D2:CE:BD:73:AA:51:1E:6C:78:A9:34:72:E1:2E:15:0D:6A:4E:88:F6:41:F8:F9:73:D7
a=group:BUNDLE 0
a=ice-options:trickle
a=msid-semantic:WMS *
m=application 9 UDP/DTLS/SCTP webrtc-datachannel
c=IN IP4 0.0.0.0
a=sendrecv
a=ice-pwd:02a076d6870cb9741652b6245eccb1b3
a=ice-ufrag:2c898136
a=mid:0
a=setup:actpass
a=sctp-port:5000
a=max-message-size:1073741823
",
"type": "offer"
}
- RTCPeer B
Got remote answer
{
"sdp": "v=0
o=mozilla...THIS_IS_SDPARTA-99.0 4923176688973568470 0 IN IP4 0.0.0.0
s=-
t=0 0
a=fingerprint:sha-256 0A:1D:61:E3:73:2A:D0:F2:66:2C:99:6E:04:47:9D:38:5F:4E:B0:FF:5C:5C:FE:A8:72:3F:29:F0:A0:59:57:28
a=group:BUNDLE 0
a=ice-options:trickle
a=msid-semantic:WMS *
m=application 9 UDP/DTLS/SCTP webrtc-datachannel
c=IN IP4 0.0.0.0
a=sendrecv
a=ice-pwd:a6be97f6e91d00732782cc14bc20df64
a=ice-ufrag:87b98be5
a=mid:0
a=setup:active
a=sctp-port:5000
a=max-message-size:1073741823
",
"type": "answer"
}
- RTCPeer A
RTCIceCandidate
{
"address": "10.10.10.1",
"candidate": "candidate:0 1 UDP 8331263 10.10.10.1 55715 typ relay raddr 10.10.10.1 rport 55715",
"component": "rtp",
"foundation": "0",
"port": 55715,
"priority": 8331263,
"protocol": "udp",
"sdpMid": "0",
"sdpMLineIndex": 0,
"type": "relay"
}
- RTCPeer B
RTCIceCandidate
{
"address": "10.10.10.1",
"candidate": "candidate:0 1 UDP 8331263 10.10.10.1 52511 typ relay raddr 10.10.10.1 rport 52511",
"component": "rtp",
"foundation": "0",
"port": 52511,
"priority": 8331263,
"protocol": "udp",
"sdpMid": "0",
"sdpMLineIndex": 0,
"type": "relay"
}
i setup a coturn instance on my network, added no-udp to the config file and forced TCP with the ice server configuration and set iceTransportPolicy to relay and i've been unable to break it, seems to be working fine.