--- gitea: none include_toc: true --- # TURN server You need an TURN server to connect participants that are behind a NAT firewall. Because IPv6 doesn't really need TURN, and Chrome can get confused if it has to use TURN over IPv6, we'll stick to a strict IPv4-only configuration. Also, because VoIP traffic is only UDP, we won't do TCP. IMPORTANT! TURN can also be offered by [LiveKit](../element-call#livekit), in which case you should probably not run coturn (unless you don't use LiveKit's built-in TURN server, or want to run both to support legacy calls too). # Installation Installation is short: ``` apt install coturn ``` For sake of maintainability we'll move the only configuration file into its own directoy: ``` mkdir /etc/coturn mv /etc/turnserver.conf /etc/coturn ``` We need to tell systemd to start it with the configuration file on the new place. Edit the service file with: ``` systemctl edit coturn ``` Contrary to what the comment suggests, only the parts you add will override the content that's already there. We have to "clean" the `ExecStart` first, before we assign a new line to it, so this is the bit we add: ``` [Service] ExecStart= ExecStart=/usr/bin/turnserver -c /etc/coturn/turnserver.conf --pidfile=/etc/coturn/run/turnserver.pid ``` Create the directory `/etc/coturn/run` and chgrp it to `turnserver`, so that coturn can write its pid there: `/run/turnserver.pid` can't be written because coturn doesn't run as root. This prepares us for the next step: configuring the whole thing. # DNS and certificate {#dnscert} As stated before, we only use IPv4, so a CNAME to our machine that also does IPv6 is a bad idea. Fix a new entry in DNS for TURN only, we'll use `turn.example.com` here. Make sure this entry only has an A record, no AAAA. Get a certificate for this name: ``` certbot certonly --nginx -d turn.example.com ``` This assumes you've already setup and started nginx (see [nginx](../nginx)). The certificate files reside under `/etc/letsencrypt/live`, but coturn doesn't run as root, and can't read them. Therefore we create the directory `/etc/coturn/ssl` where we copy the files to. This script should be run after each certificate renewal: ``` #!/bin/bash # This script is hooked after a renewal of the certificate, so # that it's copied and chowned and made readable by coturn: cd /etc/coturn/ssl cp /etc/letsencrypt/live/turn.example.com/{fullchain,privkey}.pem . chown turnserver:turnserver *.pem # We should restart either coturn or LiveKit, they cannot run both! systemctl restart coturn #systemctl restart livekit-server ``` Run this automatically after every renewal by adding this line to `/etc/letsencrypt/renewal/turn.example.com.conf`: ``` renew_hook = /etc/coturn/fixssl ``` Yes, it's a bit primitive and could (should?) be polished. But for now: it works. # Configuration {#configuration} Synapse's documentation gives a reasonable [default config](https://element-hq.github.io/synapse/latest/setup/turn/coturn.html). We'll need a shared secret that Synapse can use to control coturn, so let's create that first: ``` pwgen -s 64 1 ``` Now that we have this, we can configure our configuration file under `/etc/coturn/turnserver.conf`. ``` # We don't need more than 10000 connections: min-port=50000 max-port=60000 use-auth-secret static-auth-secret= realm=turn.example.com user-quota=12 total-quota=1200 # Of course: substitute correct IPv4 address: listening-ip=185.206.232.60 # VoIP traffic is only UDP no-tcp-relay # coturn doesn't run as root, so the certificate has # to be copied/chowned here. cert=/etc/coturn/ssl/fullchain.pem pkey=/etc/coturn/ssl/privkey.pem denied-peer-ip=0.0.0.0-255.255.255.255 denied-peer-ip=127.0.0.0-0.255.255.255 denied-peer-ip=10.0.0.0-10.255.255.255 denied-peer-ip=172.16.0.0-172.31.255.255 denied-peer-ip=192.168.0.0-192.168.255.255 denied-peer-ip=100.64.0.0-100.127.255.255 denied-peer-ip=192.0.0.0-192.0.0.255 denied-peer-ip=169.254.0.0-169.254.255.255 denied-peer-ip=192.88.99.0-192.88.99.255 denied-peer-ip=198.18.0.0-198.19.255.255 denied-peer-ip=192.0.2.0-192.0.2.255 denied-peer-ip=198.51.100.0-198.51.100.255 denied-peer-ip=203.0.113.0-203.0.113.255 # We do only IPv4 allocation-default-address-family="ipv4" # No weak TLS no-tlsv1 no-tlsv1_1 ``` All other options in the configuration file are either commented out, or defaults. Make sure you've opened the correct ports in the [firewall](../firewall).