Home
/ Blog /
WebRTC TURN server: Everything you need to knowOctober 17, 202211 min read
Share
We know that WebRTC powers almost every kind of live video solution imaginable these days. It is estimated that almost 20% of WebRTC call connections require a TURN server to connect, whatever may the architecture of the application be. Even the latest WebRTC ingest and egress standards—WHIP and WHEP make use of STUN/TURN servers. In this article, we’ll discuss everything you need to know about STUN and TURN servers. We will also try to deploy and test a popular open-source TURN server in the end.
Depending on the architecture, WebRTC creates a connection between peers directly or with a media server in the middle. But sometimes, a direct connection to other peers or the media server itself may fail at times. This can happen mainly because of 2 reasons - NAT and Firewall. We will briefly look into them here.
The Network Address Translation is a mechanism that maps the public transport address into the private transport address of a device within its local network and vice-versa. A NAT usually lives on a router that sits between the local network and the internet.
A Transport address is nothing but the combination of an IP address and a port number. It is used to uniquely identify a device for communication.
NAT was designed to offer security and help conserve IPV4 addresses over the internet. But it also came with a few issues with respect to direct connection:
Every host device has its own firewall that regulates all the incoming and outgoing network traffic for security purposes. Many enterprise firewalls simply block UDP traffic, as it is not as secure as other transport layer protocols such as TCP.
Since, WebRTC uses UDP for all of its media sessions to optimize for performance, there is a high chance that it may be blocked too. Sometimes, the firewall might also find other peers suspicious, blocking them from establishing a direct connection.
WebRTC uses ICE (Interactive Connection Establishment) framework to find the best path to connect the peers. When the direct connection fails, there must be a way for the peers to establish a connection. This is where STUN and TURN come into picture. Based on several parameters, the ICE framework will automatically try to use the configured STUN and/or TURN servers, when a direct connection is impossible. How ICE works is a whole other beast, which I'll cover at a later date. But here is an article that explains it pretty well, if you want to check it out. For now, let us focus only on the STUN and TURN servers.
To understand how these servers help in establishing a connection, let us first try to understand what a STUN server and a TURN server does.
STUN is a network protocol used to retrieve the public IP address (or Transport address) of a device behind NAT so that the device can communicate after knowing its address on the internet. Usually, a STUN server is requested by the peer to know its public IP addresses (or specifically its transport address). Then, the retrieved address is used to communicate with devices outside its local network.
Sometimes, a direct connection is not possible due to NAT restrictions or a firewall blocking a connection, even with the help of the STUN server. The only way for peers to communicate in this case, is by routing the media through a relay server. A TURN server is used for cases like this.
TURN is a network protocol that enables a server to relay data packets (media in this case) between peers when no direct connections are possible. The peers may route media to the TURN server which will relay it to the other peer continuously.
TURN servers are usually referred to as Relay Servers. According to the RFC8656 specification, TURN is considered an extension to the STUN. So, a typical TURN server would include a STUN server implementation by default.
Before trying to understand the operations of a TURN server, let’s take a look at some terminologies involved.
There are 2 participants associated with a TURN session:
The Transport Addresses associated with TURN clients and Peers:
The Transport Addresses associated with a TURN server:
The TURN client already has access to the Server Transport Address of the TURN server, from the ICE server configuration in the case of WebRTC. The TURN server can only sense the Server-Reflexive Transport Address of the client (and peer) and not the Host Transport Address.
This happens when there’s a NAT in the middle, that maps the Server-Reflexive Transport Address to the Host Transport Address for the client/peer. When there’s no NAT in the connection, there’s no need to differentiate the addresses and it can simply be called Transport Address.
Every TURN client is assigned its own Relayed Transport Address for relaying the data. The peers will receive the data from this address and any data that the peers send to this address will be relayed to the respective TURN client that was allocated that address.
The following table illustrates the protocols used for transport between a TURN client to a server and TURN server to a peer.
TURN client to TURN server | TURN server to peer |
---|---|
UDP | UDP |
TCP | UDP |
TLS-over-TCP | UDP |
DTLS-over-UDP | UDP |
According to RFC8656 specification, the communication between the server and a peer always uses UDP. This is very helpful in case of WebRTC. Since the media sessions use UDP for transport, a peer doesn’t have to differentiate between another peer and the TURN server to communicate with it.
And if the client blocks UDP traffic completely, there’s always room to use other transport protocols like TCP, TLS-over-TCP, and DTLS-over-UDP. But, what happens if both the client and a peer happen to block UDP traffic? We will come back to that in a later section.
Now let us try to understand the exact steps involved in using a TURN server to achieve connectivity among peers. The peer that cannot participate in a direct connection is usually the TURN client and it will initiate the process.
A client can use TURN commands to create and manipulate an ALLOCATION
on the TURN server, by communicating with the server on its Server Transport Address. An ALLOCATION
is basically a “TURN Session” associated with the client. Among other things, every ALLOCATION
has a corresponding Relayed Transport Address to be used.
The Relayed Transport Address is the address that the other peers can use to interact with. A peer can use the address to relay the data to the client. Additionally, the source of the data from the client relayed to the peer will be the Relayed Transport Address from the peer’s perspective.
When the peers send data to the Relayed Transport Address, it’ll be matched with the ALLOCATION
and be relayed to the client who is associated with it. But the data is discarded until a PERMISSION
is created for the peer to send data to the client.
The PERMISSION
for a peer can be created by the client, by using the address of the peer as it appears to the TURN server. The peer can get this address by sending a STUN Binding Request to the same TURN server (not any other STUN/TURN server) and then forward send it to the client by other means. ICE Candidates are used to handling this in the case of WebRTC. Once this is done, the peer can start communicating with the client through the TURN server.
The reason that the peer has to send a STUN Binding Request to the same server is, the transport address the peer got from a different STUN server, may not work for the target TURN server. This happens when the mapping behavior is either “address-dependant” or “address-and-port-dependant”.
Now, the TURN is ready for relaying data between the client and peers. There are 2 mechanisms for sending and receiving data from peers through the relay server.
a. Send and Data Mechanism
In this mechanism, SendIndication
and DataIndication
messages are used to relay data between the client and the peers.
The client sends a SendIndication
message to the server which contains the data and the peer information the data has to be relayed to. The server forms a UDP Datagram using that message and sends it to the respective peer.
Similarly, when a peer sends a UDP Datagram to the server, it is then converted into a DataIndication
message and is relayed to the client.
b. Channel Mechanism
In this mechanism, a Channel
is created for communication between a client-peer pair by using both their Transport Addresses once. There is no need to specify the Transport Address when sending data, unlike in the Send and Data mechanism. This mechanism is recommended when there’s a need for sending lots of data, mainly due to its smaller packet size.
The client creates a channel by sending a ChannelBind
request with the peer’s Transport Address and a unique ChannelId
. The communication between the client and the server is done by the use of ChannelData
messages that contain a ChannelId
and data among other things. The ChannelData
message is converted to a UDP Datagram and sent to the peer. Similarly, any data received from the peer corresponding to a channel is packaged into a ChannelData
message before being relayed to the respective client.
Every ALLOCATION
has a LIFETIME
attribute, denoting the time after which it will expire. The client has to send a refresh request to keep its ALLOCATION
alive.
There are mainly 2 ways a TURN server can be used to achieve connectivity. We will look into them by considering one-on-one connections as an example.
In this case, there is one TURN client and one peer. Usually, when only one party has issues with the direct connection, this is the recommended way.
In this case, both parties are TURN clients communicating with each other. This is the solution when both parties don’t support direct connection and that includes blocking UDP traffic.
Now that we’ve seen too much theoretically about the TURN server, let us also try to set up and test our own TURN server. We will be using coTURN, a really popular open-source TURN server implementation.
In this section, we will set up our own TURN server on Ubuntu (and similar Linux based OSes), using coTURN. We will do it in the following steps:
First, create an AWS EC2 instance or a GCP Cloud Compute instance of Ubuntu OS. We will be installing hosting the TURN server in this instance. Then, connect to the instance with the help of SSH.
Run the following commands to update the repo and install coTURN.
sudo apt-get update
sudo apt-get install coturn
To make sure that coTURN always runs at startup, edit the file /etc/default/coturn.
sudo nano /etc/default/coturn
Inside the file, find the line TURNSERVER_ENABLED=1
and uncomment it. Now start the coTURN server by running the following command.
systemctl start coturn
Before modifying the configuration file it is recommended to copy the original configuration file in case something goes wrong.
mv /etc/turnserver.conf /etc/turnserver.conf.backup
sudo nano /etc/turnserver.conf
Now, proceed to edit the configuration file and replace it with the below settings.
realm=<Your Domain>
server-name=turnserver
fingerprint
listening-ip=0.0.0.0
external-ip=<External IP Address>
listening-port=3478
min-port=10000
max-port=20000
user=testname:testpass
lt-cred-mech
log-file=/var/log/turnserver.log
verbose
After finishing the changes, you can restart the coTURN server with the following command.
sudo service coturn restart
Now that we’ve installed and configured a TURN server with coTURN, it is time to test if it works correctly. One of the easiest ways to do this is to use this site that checks for Trickle ICE functionality.
First, add the STUN and TURN information in the following format. For STUN server URI stun:<IP Address>:<Port>
and for TURN URI turn:<IP Address>:<Port>
with the username and password configured before. Then, click on the “Add Server” button.
Once everything is set, you can start the test by clicking on the “Gather Candidates” button.
If your results look similar to the one in the image above without any fatal errors below the button, then the TURN server is working as expected.
Special Mention: If you’re trying to build a custom TURN server/client tuned for your use case, check out pion TURN. It is open source and has great support from the community.
Now that you know everything you need about TURN servers and the role it plays in your WebRTC call, you might as well try building a simple WebRTC app with this guide I wrote.
Basics
Share
Related articles
See all articles