TURN server and Seequre MDaemon /Nextcloud

A TURN server is needed even when our Seequre SFU is used and is publicly accessible..

Seequre SFU uses these ports WebRTC media connections (20000-40000 by default). A client could be behind a restrictive firewall that only allows connections to port 443, so even if the Seequre SFU is publicly accessible the client would need to connect to a TURN server in port 443, and the TURN server will then relay the packets to the 20000-40000 range in the Seequre SFU

For maximum compatibility the TURN server should be configured to listen on port 443. Therefore, when both a TURN server and the Seequre SFU are used each one should run in its own server, or in the same server but each one with its own IP address, as the Seequre SFU will need to bind to port 443 too.

Install and setup coTURN as TURN server#

It is recommended to install the latest coTURN version; at the very minimum coTURN 4.5.0.8 should be used. In previous versions there is a bug that causes the IPv6 UDP sockets created by coTURN not to be freed. Due to this the turn process ends not being able to open new ports and thus not being able to serve new connections. Moreover, when that happens, even if there are no connections a high CPU load will be caused by the turn process. Therefore, if you can not install coTURN 4.5.0.8 or a later version you should restart the turn process periodically to work around that issue.

1. Download and install#
2. Make coturn run as daemon on startup#
  • On Debian and Ubuntu you just need to enable the deployed sysvinit service by adjusting the related environment variable: sudo sed -i '/TURNSERVER_ENABLED/c\TURNSERVER_ENABLED=1' /etc/default/coturn
  • Since Debian Buster and Ubuntu disco the package ships a systemd unit, which does not use /etc/default/coturn but is enabled automatically on install. To check whether a systemd unit is available: ls -l /lib/systemd/system/coturn.service
  • If you installed coTURN manually, you may want to create an sysvinit service or systemd unit, or use another method to run the following during boot: /path/to/turnserver -c /path/to/turnserver.conf -o
  • -o starts the server in daemon mode, -c defines the path to the config file.
  • There is also an official example available at https://github.com/coturn/coturn/blob/master/examples/etc/coturn.service
Running coTURN on privileged ports#

On some GNU/Linux distributions (for example, Ubuntu Focal and later) when coTURN is installed from the official package the coturn service is executed as an unprivileged user like turnserver. Due to this by default coTURN can not use privileged ports, like port 443.

Depending on the system configuration Linux kernel capabilities could be used to overcome this limitation. Capabilities can be associated with executable files using setcap, so you could allow the /usr/bin/turnserver executable to bind sockets to privileged ports with:

setcap cap_net_bind_service=+ep /usr/bin/turnserver

Alternatively, if the system configuration does not allow to set the capability, or if the coturn process needs to access files only readable by root like a SSL certificate for TLS connections, you could configure the coturn service to be executed by root instead of the unprivileged user by executing:

systemctl edit coturn

and then setting the following configuration, which will override the default one:

[Service]
User=root
Group=root
3. Configure turnserver.conf
  • Next you need to adjust the coTURN configuration file to work with Seequre.
  • Choose the listening port (default is 3478) and an authentication secret, where a random hex is recommended openssl rand -hex 32
  • Then uncomment/edit the following settings accordingly:
listening-port=<yourChosenPortNumber>
fingerprint
lt-cred-mech # Only on coTURN below v4.5.0.8!
use-auth-secret
static-auth-secret=<yourChosen/GeneratedSecret>
realm=your.domain.org
total-quota=0
bps-capacity=0
stale-nonce
no-loopback-peers # Only on coTURN below v4.5.1.0!
no-multicast-peers

*When Seequre SFU is used then youre Seequre SFU server is one of the ends; which means the media streams are not end-to-end encrypted between the participants but only between participants and the Seequre SFU server.
When you own your own infrastructure this will not be a problem for most companies.

Also note that even with TURN over TLS a client may not be able to connect with the TURN server if the firewall performs deep packet inspection and drops packets to port 443 that are not really HTTPS packets. This would be a corner case, though, as given that the connection is encrypted in order to inspect the packets that means that the firewall acts as a man-in-the-middle and the connection is not actually encrypted end-to-end. There is nothing that can be done in that case, but it should be rather uncommon.

In order to use TLS connections to the TURN server the TURN server requires a SSL certificate and, therefore, a domain. The path to the certificate file must be set in the cert parameter, and the private key file must be set in the pkey file. Besides that in Seequre Admin settings you must set the TURN server scheme as turns: or turn: and turns:.

Note that, even if TLS provides the maximum compatibility, using a domain can cause problems with Firefox on a very specific scenario: currently Firefox does not perform DNS requests through HTTP tunnels, so even if the WebRTC connection would work through the TURN server the TURN server may not be reachable.

  • The recommended listening port is port 443, even if only turn: but not turns: is used. In some cases firewalls restrict connections only to port 443, but they do not actually check whether the connection is a TLS connection or not. Nevertheless, as mentioned above using both turn: and turns: is recommended for maximum compatibility.
  • The total-quota parameter limits the number of allowed simultaneous connections to the TURN server. Along with max-bps and bps-capacity it can be used to limit the effects of a DoS attack against the TURN server. The value of 0 shown above means unlimited; if a connection limit is desired it should be adjusted depending on your specific setup.

Please note that the number of allowed simultaneous connections limited by total-quota are not only fully established connections, but also the connections being tested during the negotiation phase used to establish the actual connection. During the negotiation phase each peer generates several candidates (an IP address and port) that can be used to establish a connection with that peer. Then the peers try to establish a connection between them with different candidate combinations until a valid one is found. If there is a TURN server then the client will connect to the TURN server too and it will generate additional candidates with the IP address of the TURN server (the so called “relay” candidates). Each of those relay candidates will try to connect to the candidates of the other peer, and each of those connection attempts allocates a slot in the available quota of the TURN server. If there are no more available slots “Allocation Quota Reached” message is written to coTURN logs.

In most cases the candidates that will be generated, and thus the connections to the TURN server during the negotiation phase, can not be known beforehand. When Janus is used the number of candidate combinations is reduced, as the Janus candidates can be known, but the number of relay candidates that will be generated by the client may still be unknown. For example, it seems that browsers generate one relay candidate for each host candidate. Host candidates are those with the IP address known to the client, so typically there will be one for each network device in the system; in the case of Firefox host candidates are also generated for the IP addresses of local bridge network devices.

You should take all that into account if you intend to set a specific value to the total-quota parameter, but for maximum availability an unlimited quota is recommended.

  • If your TURN server is running not behind a NAT, but with direct www connection and static public IP, than you can limit the IPs it listens at and answers with, by setting those as listening-ip and relay-ip. On larger deployments it is recommended to run your TURN server on a dedicated machine that is directly accessible from the internet.
  • The following settings can be used to adjust the logging behaviour. On SBCs with SDcards you may want to adjust this, as by default coTURN logs very verbose. The config file explains everything very well:
no-stdout-log
log-file=...
syslog
simple-log
  • sudo systemctl restart coturn or corresponding restart method
Disabling UDP or TCP protocols#

Unless you have some special need, you should always enable both UDP and TCP protocols in your TURN server, as that provides the maximum compatibility. However, if you must limit the connections from clients to the TURN server through UDP or TCP protocols you can do that by enabling one the following settings, depending on the case:

no-udp
no-tcp

Please note that those settings only limit the protocols from the client to the TURN server. The relayed protocol from the TURN server to the other end (Janus if the High Performance Backend is being used, another client or TURN server if it is not) must be UDP; coTURN provides the setting no-udp-relay to disable the UDP protocol for the relayed connection, but enabling it would cause the TURN server to be unusable in a WebRTC context.

Also keep in mind that disabling the UDP protocol from clients to the TURN server with no-udp in practice disables STUN on that server, as neither Janus nor the clients currently support STUN over TCP.

TURN server and internal networks#

If your TURN server has access to an internal network you should prevent access to the local/internal IPs from the TURN server, except those that are actually needed (like the High Performance Backend if you are using it) by setting the denied-peer-ip and allowed-peer-ip parameters. For example:

allowed-peer-ip={IP_ADDRESS_OF_THE_HIGH_PERFORMANCE_BACKEND}
denied-peer-ip=0.0.0.0-0.255.255.255
denied-peer-ip=10.0.0.0-10.255.255.255
denied-peer-ip=100.64.0.0-100.127.255.255
denied-peer-ip=127.0.0.0-127.255.255.255
denied-peer-ip=169.254.0.0-169.254.255.255
denied-peer-ip=172.16.0.0-172.31.255.255
denied-peer-ip=192.0.0.0-192.0.0.255
denied-peer-ip=192.0.2.0-192.0.2.255
denied-peer-ip=192.88.99.0-192.88.99.255
denied-peer-ip=192.168.0.0-192.168.255.255
denied-peer-ip=198.18.0.0-198.19.255.255
denied-peer-ip=198.51.100.0-198.51.100.255
denied-peer-ip=203.0.113.0-203.0.113.255
denied-peer-ip=240.0.0.0-255.255.255.255

Otherwise a malicious user could access services in that internal network through your TURN server.

Alternatively you could of course prevent access to that internal network from the TURN server by means of a firewall.

4. Configure Seequre to use your TURN server
  • Go to Seequre admin panel > Edit Configs.
    And add your “Turn Settings” and “Stun Settings” STUN server as well:
    • STUN servers: your.domain.org:
    • TURN server: your.domain.org:
    • TURN secret:
    • Protocol: UDP and TCP
  • Do not add http(s):// or turn(s):// protocol prefix here, just enter the bare domain:port
  • Just change the excisting entered data to your own server.
5. Port opening/forwarding
  • The TURN server on <yourChosenPortNumber> needs to be accessible for all Seequre participants, so you need to open it to the web and if your TURN server is running behind a NAT, forward it to the related machine. Also make sure to set the --external-ip option when your TURN server is in a private network.
  • If the SFU is used the TURN server and the SFU must be able to reach each other. If set, the external-ip option defines the IP address of the TURN server that the High Performance Backend will try to connect to. Therefore if both the TURN server and the High Performance Backend are in the same private network they may be able to reach each other using their local IP addresses, and thus it may not be needed to set the external-ip option. Moreover, when both servers are behind a firewall, in some cases (depending on the firewall configuration) setting the external IP can even cause the TURN server and the High Performance Backend to fail to reach each other (for example, if the firewall is not able to “loop” a packet from an internal address to an external one which then should go back to another internal address).
  • Note that in some cases additional addresses can be found during the negotiation of the connection, the so called peer reflexive candidates. Due to this even if the external IP of the TURN server is not reachable by the High Performance Backend the connection may still work, but this should not be relied on.
6. Testing the TURN server

Install coTURN on your client. Please refer above for details. Note that in the case of the client you only need to install it, you do not need to perform any configuration after that.

Run turnutils_uclient -p <port> -W <static-auth-secret> -v -y turn.example.com where – <port> is the port where your TURN server is listening – <static-auth-secret> is the static-auth-secret value configured in your TURN server – -v enables the verbose mode to be able to check all the details – -y enables client-to-client connections, so turnutils_uclient acts as both the client and the peer that the TURN server relays to; otherwise you would need to also run turnutils_peer to act as the peer to relay to and specify its address and port when running turnutils_uclient with -e and -r

By default the connection between the TURN client and the TURN server will be done using UDP. To instead test TCP connections you need to add -t to the options.

No matter if you are using UDP or TCP the output should look similar to:

0: IPv4. Connected from: 192.168.0.2:50988
0: IPv4. Connected to: 1.2.3.4:3478
0: allocate sent
0: allocate response received:
0: allocate sent
0: allocate response received:
0: success
0: IPv4. Received relay addr: 1.2.3.4:56365
....
4: Total transmit time is 4
4: Total lost packets 0 (0.000000%), total send dropped 0 (0.000000%)
4: Average round trip delay 32.500000 ms; min = 15 ms, max = 56 ms
4: Average jitter 12.600000 ms; min = 0 ms, max = 41 ms

If the output hangs at some point this could mean that the TURN server is not accessible (for example, because a firewall blocks its ports). Pay special attention too to the Total lost packets and total send dropped values, as there would be no error message if the data was successfully sent to the TURN server but then it was not properly relayed.

Further you should see in the TURN server log the successful connection.

This test only verifies that your TURN server is accessible from the outside, but it does not check if your TURN server can be actually used within Seequre. For that please keep reading.

When the TURN server is set in the Seequre Admin settings you are ready to go:

  • Join a call
  • Open your browser console
  • Leave the call
  • Join the call again

Now, in that browser, the media sent to and received from other participants in the call should go through the TURN server. If the call works then the TURN server should work.

Differences between Firefox and Chromium

Firefox and Chromium handle iceTransportPolicy = 'relay' in slightly different ways. When relay candidates are forced Firefox will use only relay candidates, but Chromium will also take into account peer reflexive candidates that refer to the TURN server. Due to this in the above test, in some specific cases, a connection could be established in Chromium but not in Firefox.

For example, if a Janus gateway is used too, the TURN server is in the same server as the Janus gateway and both are behind a firewall (not recommended), relay candidates could have the public IP address of the server while peer reflexive candidates could have the internal one. If the firewall drops connections between the public IP address and the public IP address the connection between coTURN and Janus may not be established (but without failing either), which would cause that Firefox establishes a connection with the TURN server, but the TURN server does not send or receive any packet to or from Janus. In Chromium, on the other hand, the connection would work as it would use the internal IP address of the server from the peer reflexive candidate.

However, in the scenario above Firefox would not be able to establish a connection only if relay candidates are forced. With a standard Firefox configuration it would take into account peer reflexive candidates too and thus it should work without issues. Nevertheless, note that although using iceTransportPolicy = 'relay' in the browser console is just a temporary setting there is a persistent setting in Firefox configuration (about:config) to force relay candidates, media.peerconnection.ice.relay_only. This setting is targeted towards privacy-minded people, so you may want to test the TURN server with Firefox to ensure that it works even with the most restrictive configurations.

You will allways have to use Seequre SFU (based on opensource Mediasoup) even if you are only calling 1-1. We wanted to make it work everysingle time and with Peer to peer there where issues with some networks.

Seequre will help you setup a singe SFU or multiple SFU with a LoadBalancer in front for USD90 pr server
Check our pages for details.