WebRTC: Configure Your Own TURN/STUN Server

TURN Server

Traversal Using Relays around NAT (TURN) is a protocol that assists in traversal of network address translators (NAT) or firewalls for multimedia applications. It may be used with the Transmission Control Protocol (TCP) and User Datagram Protocol (UDP). It is most useful for clients on networks masqueraded by symmetric NAT devices. TURN does not aid in running servers on well known ports in the private network through a NAT; it supports the connection of a user behind a NAT to only a single peer, as in telephony, for example.

Herein we will cover using CoTURN, a free open-source server which provides a feature-rich and standards compliant option for those wanting control over their own TURN/STUN server.

Red5 Pro WebRTC uses STUN over UDP as our default implementation.

Step-by-step Install on an Ubuntu Linux Server

All coturn downloads may be found here; the latest at the time of writing this guide is turnserver-4.5.0.5 download the tarball.

1 - Install the support libraries sqlite and libevent

sudo apt-get -y install sqlite libsqlite3-dev libevent-dev

2 - Download the source

wget http://turnserver.open-sys.org/downloads/v4.5.0.5/turnserver-4.5.0.5.tar.gz

3 - Un-tar the source

tar -xzvf turnserver-4.5.0.5.tar.gz

4 - Run configure from source directory

cd turnserver-4.5.0.5
./configure

Note: if you see 'ERROR: OpenSSL Crypto development libraries are not installed properly in required location' message, then run sudo apt-get install libssl-dev.

5 - Make and install

make && make install

If you get a 'make is currently not installed' error, install make

The program 'make' is currently not installed. You can install it by typing:
sudo apt-get install make

If all goes well, you'll see this at the end when make install finishes:

1) If your system supports automatic start-up system daemon services,
    then, to enable the turnserver as an automatically started system
    service, you have to:

    a) Create and edit /etc/turnserver.conf or
    /usr/local/etc/turnserver.conf .
    Use /usr/local/etc/turnserver.conf.default as an example.

    b) For user accounts settings: set up SQLite or PostgreSQL or
    MySQL or MongoDB or Redis database for user accounts.
    Use /usr/local/share/turnserver/schema.sql as SQL database schema,
    or use /usr/local/share/turnserver/schema.userdb.redis as Redis
    database schema description and/or
    /usr/local/share/turnserver/schema.stats.redis
    as Redis status & statistics database schema description.

    If you are using SQLite, the default database location is in
    /var/db/turndb or in /usr/local/var/db/turndb or in /var/lib/turn/turndb.

    c) add whatever is necessary to enable start-up daemon for the
    /usr/local/bin/turnserver.

2) If you do not want the turnserver to be a system service,
   then you can start/stop it "manually", using the "turnserver"
   executable with appropriate options (see the documentation).

3) To create database schema, use schema in file
/usr/local/share/turnserver/schema.sql.

4) For additional information, run:

   $ man turnserver
   $ man turnadmin
   $ man turnutils

6 - Configure the database

We're using the fastest available sqlite. The db file is located at /usr/local/var/db/turndb. By default, coturn uses SQLite database for users and settings. That database is automatically created (empty) when the process turnserver starts the first time. This step is only here for reference and flow.

7 - Add Admin User

Add the long-term TURN users with the turnadmin utility. For example, this command adds user prouser with password 3TptDG7cAfz5TaXsda, realm red5pro.com, to the default sqlite database:

sudo turnadmin -a -u prouser -r red5pro.com -p 3TptDG7cAfz5TaXsda

Add the admin user(s) to the database, with turnadmin utility. If you added those users, they will be able to connect to the TURN server ports over HTTPS from your browser and perform admin tasks with the web interface.

8 - Start the server

Options used for WebRTC with CoTURN:

Command format:

turnserver -L <public_ip_address> -o -a -f -r <realm-name>

Provide TURN and STUN functionality over TCP and UDP:

sudo turnserver -L <your STUN server\'s IP address> -o -a -f -r red5pro.com

To run the server without TCP:

sudo turnserver -L <your STUN server\'s IP address> -o -a -f --no-tcp --no-tcp-relay -r red5pro.com

To run STUN only over UDP:

sudo turnserver -L <your STUN server\'s IP address> -o -a -f --stun-only --no-tcp --no-tcp-relay -r red5pro.com

Click links for additional details on the turnserver and its configuration options.

Test TURN/STUN

Open a browser to Trickle ICE and add the server in the ICE servers box, remove the google entry and then click Gather candidates; if everything is working you'll see output like this:

Time    Component    Type    Foundation    Protocol    Address           Port    Priority
0.002   1           host    2344239086  udp         192.168.11.102  42751   126 | 32542 | 255
0.002   2           host    2344239086  udp         192.168.11.102  55232   126 | 32542 | 254
0.026   1           srflx   1194786941  udp         89.123.145.167  42751   100 | 32542 | 255
0.030   2           srflx   1194786941  udp         89.123.145.167  55232   100 | 32542 | 254
0.102   1           host    3308897054  tcp         192.168.11.102  9       90 | 32542 | 255
0.102   2           host    3308897054  tcp         192.168.11.102  9       90 | 32542 | 254
0.152   Done

To use the server in javascript or on Red5 Pro, the URI will be stun:<turn server's IP address>:3478

Modify Red5 Pro WebRTC to use your TURN/STUN Server

To configure your Red5 Pro WebRTC instance to use your TURN/STUN server, modify the {red5pro}/conf/red5pro-webrtc.xml file.

Find the STUN addresses for server-side use section:

The file is configured to use one of Google's STUN servers (stun2.l.google.com). We have also provided two alternatives (stun3.l.google.com and stun.services.mozilla.com). You can only specify one STUN server to be used, otherwise each broadcast/subscribe request will check multiple STUN/TURN servers before connecting.

So, in order for Red5 Pro to use your private STUN/TURN server:

      <!-- STUN addresses for server-side use -->
        <property name="stunAddresses">
            <array>
                <!-- ctor hostname, port, transport -->
                <!-- local server use, uncomment if using turnSeverService bean -->
                <!--
                <bean class="org.ice4j.TransportAddress">
                    <constructor-arg type="java.lang.String" value="localhost"/>
                    <constructor-arg type="int" value="3478"/>
                    <constructor-arg type="org.ice4j.Transport" value="UDP"/>
                </bean>
                <bean class="org.ice4j.TransportAddress">
                    <constructor-arg type="java.lang.String" value="stun2.l.google.com"/>
                    <constructor-arg type="int" value="19302"/>
                    <constructor-arg type="org.ice4j.Transport" value="UDP"/>
                </bean>
                <bean class="org.ice4j.TransportAddress">
                    <constructor-arg type="java.lang.String" value="stun3.l.google.com"/>
                    <constructor-arg type="int" value="19302"/>
                    <constructor-arg type="org.ice4j.Transport" value="UDP"/>
                </bean>
                <bean class="org.ice4j.TransportAddress">
                    <constructor-arg type="java.lang.String" value="stun.services.mozilla.com"/>
                    <constructor-arg type="int" value="3478"/>
                    <constructor-arg type="org.ice4j.Transport" value="UDP"/>
                </bean>
                 -->
                <bean class="org.ice4j.TransportAddress">
                    <constructor-arg type="java.lang.String" value="<your STUN server's IP address>"/>
                    <constructor-arg type="int" value="3478"/>
                    <constructor-arg type="org.ice4j.Transport" value="UDP"/>
                </bean>
            </array>
        </property>