Introduction

What is a TURN Server?

When direct communication between two devices is not feasible due to NAT (Network Address Translation) or firewall constraints, a TURN (Traversal Using Relays across NAT) server can help. It transmits data across devices, allowing them to communicate information in an indirect manner.

Requirements

  • Server: A dedicated server or virtual machine with a public IP address to host the coturn server.
  • Operating System: A supported operating system like Linux (e.g., Ubuntu, Debian) is recommended.
  • Domain Name: Assign a domain name to your server with proper DNS configuration (e.g. set coturn.example.com to your TURN server IP address).
  • Firewall: Allow incoming and outgoing traffic on specific ports used by coturn (e.g., 3478 UDP/TCP, 5349 UDP/TCP with iptable).
  • SSL Certificate: Obtain and configure an SSL certificate for secure communications (TURN/TLS).

Configuration (Debian Based)

Coturn Installation

Update your system:

sudo apt update
sudo apt upgrade

Install necessary dependencies:

sudo apt install libssl-dev libevent-dev

Install coturn:

sudo apt install coturn

Open the TURN and UDP firewall ports: (If Applicable)

sudo ufw allow 3478
sudo ufw allow 5349
sudo ufw allow 49152:65535/udp

Certificate

TLS Certificate and Private Key (for TURN/TLS), we can get a TLS certificate from Let's Encrypt:

###Nginx is optional, If nginx is your web server
sudo apt install nginx certbot python3-certbot-nginx 
sudo certbot certonly --nginx --debug-challenges --register-unsafely-without-email -d coturn.example.com

###Another Option: For certbot DNS validation###
sudo wget https://github.com/joohoi/acme-dns-certbot-joohoi/raw/master/acme-dns-auth.py
sudo chmod +x acme-dns-auth.py

sudo nano acme-dns-auth.py

##Change python to python3 in the first line of code:
#!/usr/bin/env python3

sudo mv acme-dns-auth.py /etc/letsencrypt/

sudo certbot certonly --manual --manual-auth-hook /etc/letsencrypt/acme-dns-auth.py --preferred-challenges dns --debug-challenges -d coturn.example.com

###Then the following prompt will show you how to add some CNAME records to your domain (such as Please add the following CNAME record to your main DNS zone: _acme-challenge.EXAMPLE.COM CNAME 1x2x3x4x5x6x7x8x9x0.auth.acme-dns.io.) and make sure you own the domain, this means you cannot use the domain does not belong to you such as DDNS will not work for that.

Edit Configuration File:

Edit the coturn configuration file (usually located at /etc/turnserver.conf or /etc/coturn/turnserver.conf)

Before doing it, we should backup the original config:

sudo mv /etc/turnserver.conf /etc/turnserver.conf.bak

Generate an authentication secret (If the previous step not perform, also will remove the original config):

echo "static-auth-secret=$(cat /dev/urandom | tr -cd '[:alnum:]' | fold -w 256 | head -n 1)" | sudo tee /etc/turnserver.conf

Edit the configuration file:

sudo nano /etc/turnserver.conf

It looks something like this:

static-auth-secret=your secret key here


use-auth-secret

realm=coturn.example.com

cert=/etc/letsencrypt/live/coturn.example.com/fullchain.pem

pkey=/etc/letsencrypt/live/coturn.example.com/privkey.pem


#listening-ip=xxx.xxx.xxx.xxx
#relay-ip=xxx.xxx.xxx.xxx
external-ip=xxx.xxx.xxx
# VoIP is UDP, no need for TCP

no-tcp-relay



# Do not allow traffic to private IP ranges

no-multicast-peers

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

denied-peer-ip=::1

denied-peer-ip=64:ff9b::-64:ff9b::ffff:ffff

denied-peer-ip=::ffff:0.0.0.0-::ffff:255.255.255.255

denied-peer-ip=100::-100::ffff:ffff:ffff:ffff

denied-peer-ip=2001::-2001:1ff:ffff:ffff:ffff:ffff:ffff:ffff

denied-peer-ip=2002::-2002:ffff:ffff:ffff:ffff:ffff:ffff:ffff

denied-peer-ip=fc00::-fdff:ffff:ffff:ffff:ffff:ffff:ffff:ffff

denied-peer-ip=fe80::-febf:ffff:ffff:ffff:ffff:ffff:ffff:ffff



# Limit number of sessions per user

user-quota=12

# Limit total number of sessions

total-quota=1200

Save to Configuration and Restart Coturn:

sudo systemctl restart coturn.service

Matrix-Synapse Server Configuration:

Create or edit the turn.yaml Synapse configuration file:

sudo nano /etc/matrix-synapse/conf.d/turn.yaml

Add the following lines to the configuration file. Change the coturn.example.com to your domain. Replace turn_shared_secret the value with the value static-auth-secret from coturn TURN server under /etc/turnserver.conf (It will be on a different server):

turn_uris: [ "turn:coturn.example.com?transport=udp", "turn:coturn.example.com?transport=tcp" ]
turn_shared_secret: 'static-auth-secret'
turn_user_lifetime: 86400000
turn_allow_guests: True

We need to Restart Synapse to apply the new configuration:

sudo systemctl restart matrix-synapse.service

Reference:

https://matrix-org.github.io/synapse/latest/setup/turn/coturn.html

https://github.com/coturn/coturn/blob/master/examples/etc/turnserver.conf