Alternative to coturn: TURNs TLS not working


is there an alternative to coturn as stun/turn server? With coturn turns TLS seems not to work. In various projects like nextcloud talk, matrix and also here you can find countless posts that turns via tcp does not work. So the turn traffic runs unencrypted via udp if no E2E is possible.


From what I have seen on this forum, there are people struggling to make it work, and there are who succeed. So turn tls must be working even if its not obvious to do it.

uh ? what that could mean ? If there is no turn traffic should either

  • use DTLS on port 10000, so be encrypted
  • not work at all for clients behind ‘corporate’ firewalls.
    I don’t see any way for the ‘unencrypted’ scenario. Do you have links backing up your claim ?

Me too struggling to get COTURN running, especially with letsencrypt… Falling back to jetty of JVB2 to get things going …

Some links to this eternal problem, with which many are struggling!topic/turn-server-project-rfc5766-turn-server/PeolsBQLcJg!msg/turn-server-project-rfc5766-turn-server/-jFdNKSdebE/rNKN9ElUBeoJ!topic/turn-server-project-rfc5766-turn-server/-bfZCuTae0g

I was thinking of using nginx as reverse proxy in front of coturn to handle TLS/tcp even I have public IP coturn running on. Some links:

@cosmo83 did you try to set the letsencrypt cross signing cert (lets-encrypt-x3-cross-signed file downloadable from letsencrypt) in ca-file= of coturn config. I’ve tried with two different CAs so far, Digicert und Telesec (German Telekom).


@gpatel-fr: don’t understand. I thought, if TURNs on tcp is not working and udp is used instead for turn, the traffic is unencrypted on transport in conferences > 2 people (not talking about e2e content in 1:1 conferences). This is my jitsi/prosody config:

turncredentials = {
{ type = “stun”, host = “”, port = “443” },
{ type = “turn”, host = “”, port = “443”, transport = “udp” },
{ type = “turns”, host = “”, port = “443”, transport = “tcp” }

From my understand if not port 443/tcp is used, the transport is unencrypted.


this is not an accurate statement by itself, transport encryption is mostly done with TLS on internet, but TLS works in other cases than HTTPS on port 443, such as DTLS, protocol used on the port 10000 by Jitsi.

@gpatel-fr Okay, generally this is correct, but in this case (coturn) the traffic on 443/udp is not encrypted and turns on 443/tcp fails.

if the trafic is not encrypted it’s the fault of the sender.
If I remember correctly the recent coturn problems are coming from a missing certificate in the coturn server configuration. Check the forum.

@gpatel-fr Yes, I set a cert in my coturn config.

I checked port 443 of my coturn with “./” and the results are fine. cert and key are in pem format. The cert file contains the full chain. A check with “openssl s_client -connect” looks good too.

It is completely incomprehensible to me why a TLS connection can’t be established. I have tested two different CAs, “DigiCert Global Root G2” and “T-TeleSec GlobalRoot Class 2”, and if I use these certificate files e.g. in nginx, it works fine.

It would be interesting to hear from someone who can really establish a TURNs/tcp connection with coturn, tell us which CA they use and post their coturn config file here.



@gpatel-fr : a question of understanding: independent of coturn. If in Jitsi the traffic from the peer runs over a videobridge (per 10000/UDP), then the transport route itself is not encrypted, right? But does the audio/video content run in plain text between peer and videobridge or is the content protected? If that would be the case, it would not make any big difference with an intermediate turn server, because it only passes the traffic through. And then it would also (almost) not matter if the coturn accepts the content via 443/TCP+TLS or only via 443/UDP.

if by transport route you mean who is talking to who, this is never hidden to the routers between the nodes talking to each others :slight_smile:

yes, the video content is protectes by TLS as well as the signals between the server and the clients, the chat, etc… An observer on the network can gather who is sending more video or more sound, but that’s about it witout breaking TLS encryption (not so easy)


Who talks to whom (IPs) is independent of whether the transport route is TLS encrypted. That is clear.

Okay, and if the video traffic from a peer runs through a coturn server, is the video content itself encrypted, even if the connection to the coturn server is not 443/tcp+tls, but only 443/tcp or 443/udp? That’s the point I don’t understand?


Are my meetings encrypted? Is encryption end-to-end?

This is something we get asked a lot, so let’s dive into the details:

Jitsi meetings can operate in 2 ways: peer-to-peer (P2P) or via the Jitsi Videobridge (JVB). This is transparent to the user. P2P mode is only used for 1-to-1 meetings. In this case, audio and video are encrypted using DTLS-SRTP all the way from the sender to the receiver, even if they traverse network components like TURN servers.

In the case of multiparty meetings all audio and video traffic is still encrypted on the network (again, using DTLS-SRTP). Packets are decrypted while traversing Jitsi Videobridge; however they are never stored to any persistent storage and only live in memory while being routed to other participants in the meeting.

it’s not 443/tcp or 443/udp. There is one and only one listener on port 443 in default Jitsi configuration, it’s the nginx one. In fact it would be quite impossible to have 2 listeners. The nginx listener do a pre-handling you can see here:

stream {
upstream web {
upstream turn {
# since 1.13.10
map $ssl_preread_alpn_protocols $upstream {
~\bh2\b web;
~\bhttp/1. web;
default turn;

server {
    listen 443;
    listen [::]:443;

    # since 1.11.5
    ssl_preread on;
    proxy_pass $upstream;

    # Increase buffer to serve video
    proxy_buffer_size 10m;


Like it’s named, it’s the ALPN protocol. In short, the server pre-reads the TLS packet to find it’s type, and if it’s a packet for a web server, it transfers it to the web server, else it transfers it to the Turn server. At this level the TLS connexion is not yet done. So you see that there is no difference between the packets received for the web server and the turn server, they are both TLS packets.
As of the UDP packets retransmitted to the videobridge by the turn server, I admin that I have not fired a tcpdump to see what they are, but I have looked at videobridge and not seen any trace of coturn setup, so the videobridge config seems to completely unchanged. As by default videobrige listen for DTLS (encrypted) packets, it receive from the turn server what it expects normally: DTLS packets.

You are talking about the jitsi nginx. I’m still on coturn ports and encryption.

yes it’s a jitsi forum. And you can’t understand how coturn is working if you don’t look at nginx config.

Here are very good information about TLS DTLS and coturn:

Jitsi uses WebRTC and WebRTC traffic is (per the standards) always encrypted using DTLS-SRTP between the WebRTC endpoints. In a normal Jitsi conference the endpoints are either two clients (p2p) or each client and the videobridge (more than two participiants) and the media transferred is encrypted on the application layer (WebRTC DTLS-SRTP).
The TLS/DTLS part you are asking about (if I understand you correctly) is an additional encryption on the transport layer. Consequently, unless something really bad happened, the media is still encrypted between the actual endpoints even if its relayed through a TURN server that happens to terminate the transport layer encryption (because inside the transport protocol, the application layer itself is encrypted).

Disclaimer: I did not check the source code nor did I perform a network monitoring to confirm the above. So please correct me if I got something wrong here.

1 Like

@plokta very good explanation, TLS on the transport layer is overkill, I understand.

To come back to my initial question: nevertheless, out of pure technical interest, it would be interesting to know why 443/TCP-TLS does not work with coturn and why so many have a problem with it. Maybe someone else has an idea.

In general it should work :wink:
I can only speculate but I believe one common problem is that people fail to configure the correct and complete certificate chain for coturn when coturn is fronted by nginx using ALPN multiplexing. ALPN is a TLS handshake extension that is evaluated by nginx before sending back the ServerHello of the TLS handshake. nginx will just pass everything through to coturn if ALPN does not indicate http traffic, so nginx does not complete the TLS handshake in these cases. Therefore, coturn needs to be correctly configured to terminate TLS traffic even if it sits behind nginx.

1 Like