TURN server for WebRTC – RFC5766-TURN , Coturn, Xirsys , Twillio

STUN (Session Traversal Utilities for NAT) and TURN (Traversal Using Relays around NAT) are protocols that can be used to provide NAT traversal for VoIP and WebRTC. These projects provide a VoIP media traffic NAT traversal server and gateway.

TURN Server is a VoIP media traffic NAT traversal server and gateway.

This article describes working with some of the TURN servers 

We know that a STUN only server such as the one below , may not work under firewalls like in enterperises or even in universities resulting in black video , one way video , inconcsistent streaming or even no video experience .

// google STUN 
var iceservers_array=[{urls: 'stun:stun.l.google.com:19302'}] ;

To overcome this we rely on a publicaly avaiable TURN server which can step in and do ICE exchange to seup relay routes for the media stream. Some of the options for both self hosted and TURN as a service are described below .


It is a legacy project mainly archives for reference( links at the end of section). This is a VoIP gateway for inter network communication which is opensource  MIT licensed .

platforms supported : Any client platform is supported, including Android, iOS, Linux, OS X, Windows, and Windows Phone. This project can be successfully used on other *NIX platforms ( Aamazon EC2) too. It supports flat file or Database based user management system ( MySQL , postgress , redis ). The source code project contains ,  TURN server ,  TURN client messaging library and some sample scripts to test various modules like protocol , relay , security etc .

Protocols : Protocols between the TURN client and the TURN server – UDP, TCP, TLS, and DTLS. Relay protocol – UDP , TCP .

Authentication : The authentication mechanism is using key which is calculated over the user name, the realm, and the user password. Key for the HMAC depends on whether long-term or short-term credentials are in use. For long-term credentials, the key is 16 bytes: key = MD5(username “:” realm “:” SASLprep(password))

Installation :  Since I used my Ubuntu Software center for installing the RFC turn server 5677 .

Screenshot from 2015-03-05 15:22:30

More information is on Ubuntu Manuals : http://manpages.ubuntu.com/manpages/trusty/man1/turnserver.1.html

The content got stored inside /usr/share/rfc5766-turn-server. Also install mysql for record keeping

sudo apt-get install mysql-server

Intall MySQL workbench to monitor the values feed into the turn database server in MysqL. connect to MySQL instance using the following screenshot


The database formed with mysql after successful operation is as follows . We  shall notice that the initial db is absolutely null


Terminal Commands

These terminal command ( binary images ) get stored inside etc/init.d after installing

turnadmin – Its turn relay administration tool used for generating , updating keys and passwords . For generating a key to get long term crdentaial use -k command and for aading or updateing a long -term user use the -a command. Therefore a simple command to generate a key is

format : turnadmin -k -u -r -p

 turnadmin -k -u turnwebrtc -r mycompany.com -p turnwebrtc

The generated key is displayed in console . For example the following screenshot shows this :


To fill in user with long term credentails

Format : turnadmin -a [-b | -e | -M | -N ] -u -r -p

turnadmin -a -M "host=localhost dbname=turn user=turn password=turn" -u altanai -r mycompany.com -p 123456

Check the values reflected in MySQL workbench for long term user table . ( screenshot depicts two entries for altanai and turnwebrtc user )


you can also check it on console using the -l command

format :turnadmin -l –mysql-userdb=””

turnadmin -l --mysql-userdb="host= dbname=turn user=turnwebrtc password=turnwebrtc connect_timeout=30"

or we can also check using the terminal based mySQL client

mysql> use turn;
Database changed
mysql> select * from turnusers_lt;
| name | hmackey |
| altanai | 57bdc681481c4f7626bffcde292c85e7 |
| turnwebrtc | 6066cbe0b5ee14439b2ddfc177268309 |
2 rows in set (0.00 sec)

turnserver – Its command to handle the turnserver itself . We can use the simple turnserver command to start it without any db support using just turnserver. Screenshot for this is


We can use a database like mysql to start it with db connection string

Format : turnserver –mysql-userdb=””

turnserver --mysql-userdb="host= dbname=turn user=turnwebrtc password=turnwebrtc connect_timeout=30"


turnutils_uclient: emulates multiple UDP,TCP,TLS or DTLS clients.

turnutils_peer: simple stateless UDP-only “echo” server. For every incoming UDP packet, it simply echoes it back.

turnutils_stunclient: simple STUN client example that implements RFC 5389 ( using STUN as endpoint to determine the IP address and port allocated to it , keep-alive , check connectivity etc) and RFC 5780 (experimental NAT Behavior Discovery STUN usage) .

turnutils_rfc5769check: checks the correctness of the STUN/TURN protocol implementation. This program will perform several checks and print the result on the screen. It will exit with 0 status if everything is OK, and with (-1) if there was an error in the protocol implementation.


1. Test vectors from RFC 5769 to double-check that our STUN/TURN message encoding algorithms work properly. Run the utility to check all protocols :

$ cd examples
$ ./scripts/rfc5769.sh

2. TURN functionality test (bare minimum TURN example).

If everything compiled properly, then the following programs must run together successfully, simulating TURN network routing in local loopback networking environment:

console 1 :

$ ./scripts/basic/relay.sh

console2 :

$ ./scripts/peer.sh

If the client application produces output and in approximately 22 seconds prints the jitter, loss and round-trip-delay statistics, then everything is fine.


 { 'url': 'stun: altanai@mycompany.com'},
 { 'url': 'turn: altanai@mycompany.com', 'credential': '123456'}]

Insert the above piece of code on peer connection config . Now call from one network environment to another . For example call from a enterprise network behind a Wifi router to a public internet datacard webrtc agent . The call should connect with video flowing smoothly between the two .

TURN working accross Enterprise firrewall on a WebRTC video platform written with SimpeWebRTC lbrary . Project tango FX

website : https://code.google.com/p/rfc5766-turn-server/

Download the executable from : http://turnserver.open-sys.org/downloads/v3.2.5.4/


Project Coturn evolved from rfc5766-turn-server project with many new advanced TURN specs beyond the original RFC 5766 document. The databses supported are : SQLite , MySQL , PostgreSQL , Redis , MongoDB

Protocols :

The implementation fully supports the following client-to-TURN-server protocols: UDP  , TCP  , TLS  SSL3/TLS1.0/TLS1.1/TLS1.2; ECDHE , DTLS versions 1.0 and 1.2. Supported relay protocols UDP (per RFC 5766) and TCP (per RFC 6062)

Authetication :

Supported message integrity digest algorithms:

  • HMAC-SHA1, with MD5-hashed keys (as required by STUN and TURN standards)
  • HMAC-SHA256, with SHA256-hashed keys (an extension to the STUN and TURN specs)

Supported TURN authentication mechanisms:


Install libopenssl and libevent plus its dev or extra libraries .
OpenSSL has to be installed before libevent2 for TLS beacuse When libevent builds it checks whether OpenSSL has been already installed, and its version.

Download coturn readonly  from

svn checkout http://coturn.googlecode.com/svn/trunk/ coturn-read-only

extract the tar contents
$ tar xvfz turnserver-.tar.gz

go inside the extracted folder and run the following command to build
$ ./configure
$ make
$ make install

Adding users in the format using turnadmin
$ Sudo turnadmin -a -u -r -p

$ Sudo turnadmin -a -u altanai -r myserver.com -p 123456

Start the turn Server using turnserver from inside of /etc/init.d using the start command

$ sudo /etc/init.d/coturn start
Screenshot from 2015-01-06 12-08-15

The logs are usually stored in /var/log . Screenshot of log file


The default configured port is 3478.If other port is needed, change the file /etc/turnserver.conf


Specify the  values in Peer Connection

{ ‘url’: ‘stun: altanai@myserver.com’},
{ ‘url’: ‘turn: altanai@myserver.com’, ‘credential’: ‘123456’}]


TURN specs:

STUN specs:

  • RFC 3489 – STUN – Simple Traversal of User Datagram Protocol (UDP) Through Network Address Translators (NATs)
  • RFC 5389 – Session Traversal Utilities for NAT (STUN)
  • RFC 5769 – test vectors for STUN protocol testing
  • RFC 5780 – NAT behavior discovery support
  • RFC 7443 – Application-Layer Protocol Negotiation (ALPN) Labels for STUN and TURN


  • RFC 5245 – ICE
  • RFC 5768 – ICE–SIP
  • RFC 6336 – ICE–IANA Registry
  • RFC 6544 – ICE–TCP
  • RFC 5928 – TURN Resolution Mechanism

website : https://code.google.com/p/coturn/

Chorme WebRTC Internals Page for COTURN connection


Xirsys is a provider for WebRTC infrastructure which included stun and turn server hosting as well .

The process of using their services includes singing up for a account and choosing whether you want a paid service capable of handling more calls simultaneously or free one handling only upto 10 concurrent turn connections .

The dashboard appears like this :


To receive the api one need to make a one time call to their service , the result of which contains the keys to invoke the turn services from webrtc script .

window.addEventListener("load", function (e) {
    let xhr = new XMLHttpRequest();
    xhr.onreadystatechange = function ($evt) {
        if (xhr.readyState == 4 && xhr.status == 200) {
            let res = JSON.parse(xhr.responseText);
            console.log("response: ", res);
           alert( iceservers_array);
    xhr.open("PUT", "https://global.xirsys.net/_turn/webrtc", true);
    xhr.setRequestHeader("Authorization","Basic " + btoa("altanai:<sec rettoken>"));
    xhr.send(JSON.stringify({"format": "urls"}));

The resulting output should look like ( my keys are hidden with a red rectangle ofcourse )


The process of adding a TURN / STUN to your webrtc script in JS is as follows :

 {"username":"< put your API username>","url":"turn:turn2.xirsys.com:443?transport=udp","credential":"< put your API credentail>"},
 {"username":"< put your API username>","url":"turn:turn2.xirsys.com:443?transport=tcp","credential":"< put your API credentail>"}]

website : http://xirsys.com/technology/

Twillio TURN Server

// before unload update status on main site
window.addEventListener("load", function (e) {
    let xhr = new XMLHttpRequest();
    xhr.onreadystatechange = function ($evt) {
        if (xhr.readyState == 4 && xhr.status == 200) {
            let res = JSON.parse(xhr.responseText);
            console.log("response: ", res);
            iceservers_array = res.iceServers;
            console.log("iceservers_array: ", iceservers_array);
    xhr.open("POST", "https://<ourdomain>:3000/token", true);
    xhr.send(JSON.stringify({"format": "urls"}));

Asterisk TURN module and service

Asterisk is an open source carrer grade SIP server which also provides Firewall traversal . A github repo containing some asterisk dialplan examples is https://github.com/altanai/asteriskexamples. An article discussing Asterisk and its implementation

Asterisk – installation and dial plans for WebRTC supported PJSIP clients

Asterisk is a framework or toolkit designed for VOIP systems . It can support Enterprise communication systems like PBXs, call distributors, VoIP gateways , conference bridges etc . It is open source and free to use . It is developed in C and runs in linux . Technically , Asterisk has protocol support for many…

Kamailio NAT and STUN modules in Server

It is also interesting to note that majority of popular open source SIP servers also have an implementation , libabary or module for STUN/TURN such as Kamailio’s STUN module https://www.kamailio.org/docs/modules/devel/modules/stun.html

You can read more about the kamailio DNS and NATing here

Kamailio DNS and NAT

DNS sub-system in Kamailio DNS failoverDNS load balancingNAT ( Network Address Translation)NAT ( Network Address Translation)Why is NAT is important in SIP?Types of NAT solutionsNAT behavioursRTP NATFixing NATNAT Traversal ModuleWhy use keepalive when Registrations are already there for NATing ?How keepalives work for NATing ?function nat_keepalive()ParamsFunctionsclient_nat_test()fix_contact()nat_keepalive()Pseudo VariablesStatisticsNATHelper ModuleNAT pinging typesUDP packetSIP requestparamsfunctionsPseudo VariablesRPC Commands In…