Installing RFC 5766 Turn Server

13,503 views
Skip to first unread message

Rod Apeldoorn

unread,
Nov 10, 2013, 3:28:44 PM11/10/13
to eas...@googlegroups.com
Hey All,

We regularly get asked for help setting up a TURN server. During our last installation we took a few notes which I'll share below. Keep in mind that while we are authenticating against MySQL, there are a few other possible methods too.

Installation:

Go to http://code.google.com/p/rfc5766-turn-server/ website and check the correct version for your server. To install, type (in my case it's ubuntu 12.04.2 LTS): 

$ tar -zxvf turnserver-1.8.6.0-binary-linux-wheezy-ubuntu-mint-x86-32bits.tar.gz 
$ sudo dpkg -i rfc5766-turn-server_1.8.5.3-1_i386.deb 
 
File Locations:
  • File to set turn to run automatically:
    • /etc/default/rfc5766-turn-server 
  • After the install, read the documentation in /usr/share/doc/rfc5766-turn-server directory. 
  • All binaries will be installed in /usr/bin/ directory. 
  • The turn*.conf config files are in /etc directory:
    • /etc/turnserver.conf 
    • /etc/turnuserdb.conf
  • The service start-up control scripts will be in /etc/init.d/rfc5766-turn-server and in /etc/defaults/rfc5766-turn-server files. 

Command to run the server: 

turnserver -L <public_ip_address> -a -b turnuserdb.conf -f -r <system_domain_name> 

Example: 
turnserver -L turn.easyrtc.com -a -b turnuserdb.conf -f -r easyrtc.com 


dev mysql string:

mysql-userdb="host=127.0.0.1 dbname=easyrtc user=<dbusername> password=<dbpassword> connect_timeout=10" 
 

turnadmin usage:

turnadmin -a [-b <userdb-file> | -e <db-connection-string> | -M <db-connection-string> | -N <db-connection-string> ] -u <turn-username> -r <turn-realm> -p <turn-password> 

Example for connecting to MySQL: 
 
turnadmin -a -M "host=127.0.0.1 dbname=easyrtc user=turndbuser password=turndbpw connect_timeout=10" -u EasyRTC -r easyrtc.com -p EasyRTCPassword
 

Keys:
The key is calculated over the user name, the realm, and the user password. 
The 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)) 
To use in your MySQL database just test: 
SELECT MD5('user:realm:password'); 

And you have the encrypted password ('hmackey' field in turnserver schema) for that user, this is used for long-term credentials. 

Complete documentation:
Found at:

Or just type 
$ man turnserver 
$ man turnadmin

Log files:
When the TURN Server starts, it makes efforts to create a log file turn_<pid>.log in the 
following directories: 
  • /var/log 
  • /log/
  • /var/tmp 
  • /tmp 
  • current directory
EasyRTC Configuration:

In the new modular version of EasyRTC, the turn server is set with the "iceServers" option:

easyrtc.setOption("iceServers", [
  {url: "stun:stun.l.google.com:19302"},
  ..
  {url: "turn:turn.easyrtc.com", username: <turn-username>, credential: <turn-password>
]);

If you are interested in delivering a custom ICE server at the per-connection level, you may override the "getIceConfig" event. This would be useful for giving each connection unique authentication keys or for load balancing.

-
If you have any questions about TURN, please ask away. Keep in mind that our focus is on EasyRTC so we may not be able to come back quickly on turn server issues.

Rod Apeldoorn, Priologic Software.

Fabian Bernhard

unread,
Nov 15, 2013, 7:17:24 PM11/15/13
to eas...@googlegroups.com
Great post, thanks a lot for sharing!

Oleg Moskalenko

unread,
Nov 20, 2013, 7:03:18 PM11/20/13
to eas...@googlegroups.com
Nicely put together.

I'd like to add that we recommend version 2.6 or 3.0 now - they have much better scalability and many bugs have been fixed since 1.8 version.

Oleg
 

Divyam Singhal

unread,
Feb 19, 2014, 12:30:47 AM2/19/14
to eas...@googlegroups.com
What is the default port the TURN server is listening to?

Eric Davies

unread,
Feb 19, 2014, 1:14:26 PM2/19/14
to eas...@googlegroups.com
By default, 3478 using UDP. However, it is not uncommon to run on port 443 using TCP to get past firewalls.

yamaka...@gmail.com

unread,
Mar 24, 2014, 6:55:34 AM3/24/14
to eas...@googlegroups.com
Hi,

Thanks for this tuturial!

I'm kinda confused about the MySQL setup. Where can I find the scheme for it's table and do we need the realm hashed way here or can we just add usernames and passwords from another script ? That would be great.

Thanks!

Matt

Eric Davies

unread,
Mar 24, 2014, 11:50:06 AM3/24/14
to eas...@googlegroups.com
In your rfc5766-turnserver distribution, look at the turndb/schema.sql file
Beyond that, you should probably be asking in the turnserver discussion group 

Jenco Danger

unread,
Apr 22, 2014, 6:36:50 PM4/22/14
to eas...@googlegroups.com
After I setup my turn server and hit the turn server ip in the browser (http://<myip>:3478, I'm seeing the message "Turn Server". I can see in the logs that the turn server receive the browser request but shouldn't it be returning more information? The android app that was pointing to google's turn server is now throwing some errors when pointing to my local turn server because my turn server is only return the html text "Turn Server" and missing other information like a "channelToken". I'm using long term credentials with flat files. I enable the credentials in the turnserver.conf file and with no mysql setup. Any other setup I might be missing? Thanks

04-22 18:04:19.828: W/dalvikvm(3335): threadid=14: thread exiting with uncaught exception (group=0x417e2898)
04-22 18:04:19.828: E/AppRTCDemoActivity(3335): Fatal error: Missing channelToken in HTML: <!DOCTYPE html>
04-22 18:04:19.828: E/AppRTCDemoActivity(3335): <html>
04-22 18:04:19.828: E/AppRTCDemoActivity(3335):   <head>
04-22 18:04:19.828: E/AppRTCDemoActivity(3335):     <title>TURN Server</title>
04-22 18:04:19.828: E/AppRTCDemoActivity(3335):   </head>
04-22 18:04:19.828: E/AppRTCDemoActivity(3335):   <body>
04-22 18:04:19.828: E/AppRTCDemoActivity(3335):     TURN Server
04-22 18:04:19.828: E/AppRTCDemoActivity(3335):   </body>
04-22 18:04:19.828: E/AppRTCDemoActivity(3335): </html>
04-22 18:04:19.828: E/AppRTCDemoActivity(3335): java.lang.RuntimeException: An error occured while executing doInBackground()
04-22 18:04:19.828: E/AppRTCDemoActivity(3335):  at android.os.AsyncTask$3.done(AsyncTask.java:299)
04-22 18:04:19.828: E/AppRTCDemoActivity(3335):  at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:352)
04-22 18:04:19.828: E/AppRTCDemoActivity(3335):  at java.util.concurrent.FutureTask.setException(FutureTask.java:219)
04-22 18:04:19.828: E/AppRTCDemoActivity(3335):  at java.util.concurrent.FutureTask.run(FutureTask.java:239)
04-22 18:04:19.828: E/AppRTCDemoActivity(3335):  at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
04-22 18:04:19.828: E/AppRTCDemoActivity(3335):  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
04-22 18:04:19.828: E/AppRTCDemoActivity(3335):  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
04-22 18:04:19.828: E/AppRTCDemoActivity(3335):  at java.lang.Thread.run(Thread.java:841)
04-22 18:04:19.828: E/AppRTCDemoActivity(3335): Caused by: java.lang.RuntimeException: java.io.IOException: Missing channelToken in HTML: <!DOCTYPE html>
04-22 18:04:19.828: E/AppRTCDemoActivity(3335): <html>
04-22 18:04:19.828: E/AppRTCDemoActivity(3335):   <head>
04-22 18:04:19.828: E/AppRTCDemoActivity(3335):     <title>TURN Server</title>
04-22 18:04:19.828: E/AppRTCDemoActivity(3335):   </head>
04-22 18:04:19.828: E/AppRTCDemoActivity(3335):   <body>
04-22 18:04:19.828: E/AppRTCDemoActivity(3335):     TURN Server
04-22 18:04:19.828: E/AppRTCDemoActivity(3335):   </body>
04-22 18:04:19.828: E/AppRTCDemoActivity(3335): </html>
04-22 18:04:19.828: E/AppRTCDemoActivity(3335):  at org.appspot.apprtc.AppRTCClient$RoomParameterGetter.doInBackground(AppRTCClient.java:219)
04-22 18:04:19.828: E/AppRTCDemoActivity(3335):  at org.appspot.apprtc.AppRTCClient$RoomParameterGetter.doInBackground(AppRTCClient.java:1)
04-22 18:04:19.828: E/AppRTCDemoActivity(3335):  at android.os.AsyncTask$2.call(AsyncTask.java:287)
04-22 18:04:19.828: E/AppRTCDemoActivity(3335):  at java.util.concurrent.FutureTask.run(FutureTask.java:234)
04-22 18:04:19.828: E/AppRTCDemoActivity(3335):  ... 4 more
04-22 18:04:19.828: E/AppRTCDemoActivity(3335): Caused by: java.io.IOException: Missing channelToken in HTML: <!DOCTYPE html>
04-22 18:04:19.828: E/AppRTCDemoActivity(3335): <html>
04-22 18:04:19.828: E/AppRTCDemoActivity(3335):   <head>
04-22 18:04:19.828: E/AppRTCDemoActivity(3335):     <title>TURN Server</title>
04-22 18:04:19.828: E/AppRTCDemoActivity(3335):   </head>
04-22 18:04:19.828: E/AppRTCDemoActivity(3335):   <body>
04-22 18:04:19.828: E/AppRTCDemoActivity(3335):     TURN Server
04-22 18:04:19.828: E/AppRTCDemoActivity(3335):   </body>
04-22 18:04:19.828: E/AppRTCDemoActivity(3335): </html>
04-22 18:04:19.828: E/AppRTCDemoActivity(3335):  at org.appspot.apprtc.AppRTCClient$RoomParameterGetter.getVarValue(AppRTCClient.java:381)
04-22 18:04:19.828: E/AppRTCDemoActivity(3335):  at org.appspot.apprtc.AppRTCClient$RoomParameterGetter.getParametersForRoomUrl(AppRTCClient.java:254)
04-22 18:04:19.828: E/AppRTCDemoActivity(3335):  at org.appspot.apprtc.AppRTCClient$RoomParameterGetter.doInBackground(AppRTCClient.java:217)
04-22 18:04:19.828: E/AppRTCDemoActivity(3335):  ... 7 more
04-22 18:04:29.497: D/dalvikvm(3335): Debugger has detached; object registry had 1 entries
Message has been deleted

Oleg Moskalenko

unread,
Apr 22, 2014, 6:43:26 PM4/22/14
to eas...@googlegroups.com
You must not access the TURN server with URL http://ip:3478. The TURN server is supposed to be accessed with a special binary network protocol (STUN protocol). Your browser's libraries must be able to do that. You never use your browser to access the TURN server directly in the browser's window. Read how the TURN server works and why it is needed, and you will understand that.

Jenco Danger

unread,
Apr 22, 2014, 7:13:44 PM4/22/14
to eas...@googlegroups.com
I modified google's webrtc demo app for android to point to my local turn server instead of their turn server and I'm getting the same response as when I use my browser. The turn server just return the string "turn server" and the app is expecting other info like "channelToken" . I was just using my browser to ping my turn server so I know it's running.

Oleg Moskalenko

unread,
Apr 22, 2014, 7:17:36 PM4/22/14
to eas...@googlegroups.com
The TURN Server checks whether it is accessed with HTTP - then it just returns the "Turn Server" string, for a ping functionality purpose. The TURN Server must be accessed normally with STUN binary protocol.

Jenco Danger

unread,
Apr 23, 2014, 1:02:48 AM4/23/14
to eas...@googlegroups.com
Thanks, do you have a snippet I can
follow to point the android client to my local turn server. The original app was using http://apprtc.appspot.com.

Eric Davies

unread,
Apr 24, 2014, 11:34:19 AM4/24/14
to eas...@googlegroups.com
Jed,

You are asking "how do I incorporate a turn server entry into google's android webrtc demo."  May I suggest you try the discuss-webrtc group? Then your question may actually be seen by the people wrote the demo originally.

Krishnan PA

unread,
May 14, 2014, 8:21:00 AM5/14/14
to eas...@googlegroups.com
Hi Rod,

This is really helpful,
Could you please explain us if we wish to use static username and password, how we configure
in the turn*.conf file user:userAccountName:password will be enough

Thanks

Eric Davies

unread,
May 15, 2014, 4:05:38 PM5/15/14
to eas...@googlegroups.com
Hi Krishnan,

What you need the following lines:
fingerprint
lt-cred-mech

Then you just add lines of the form  user=userAccountName:password, For example
user=krishnan:tj47dkdjeu3

iuli...@gmail.com

unread,
May 19, 2014, 5:27:17 AM5/19/14
to eas...@googlegroups.com
Hy there!
installed turnserver then >> sudo turnserver -a  -b turnuserdb.conf  -L 172.31.37.x -X 54.187.87.x -E 172.31.37.x -f  -r site.ro -v

in turnuserdb.conf :  iuli:password
And is not working? hmmm why?

67: handle_udp_packet: New UDP endpoint: local addr 172.31.37.x:3478, remote addr 213.2                                    33.92.66:15273
67: session 000000000000000001: user <>: incoming packet BINDING processed, success
67: session 000000000000000001: user <>: incoming packet BINDING processed, success
67: handle_udp_packet: New UDP endpoint: local addr 172.31.37.x:3478, remote addr 213.2                                    33.92.66:44984
67: session 000000000000000002: user <>: incoming packet message processed, error 401: Un                                    authorised
67: session 000000000000000001: user <>: incoming packet BINDING processed, success
67: session 000000000000000002: user <>: incoming packet message processed, error 401: Un                                    authorised
67: IPv4. tcp or tls connected to: 213.233.92.66:44983
67: session 000000000000000003: user <>: incoming packet message processed, error 401: Un                                    authorised
67: IPv4. Local relay addr: 172.31.37.x:56400
67: session 000000000000000002: new, username=<iuli>, lifetime=600
67: session 000000000000000002: user <iuli>: incoming packet ALLOCATE processed, success
67: session 000000000000000003: user <>: incoming packet message processed, error 401: Un                                    authorised
68: session 000000000000000002: user <iuli>: incoming packet ALLOCATE processed, success
68: IPv4. tcp or tls connected to: 213.233.92.66:38720
68: ERROR: check_stun_auth: user iuli credentials are incorrect
68: session 000000000000000003: user <iuli>: incoming packet message processed, error 401                                    : Unauthorised
68: ERROR: check_stun_auth: user iuli credentials are incorrect
68: session 000000000000000003: user <iuli>: incoming packet message processed, error 401                                    : Unauthorised
68: IPv4. tcp or tls connected to: 86.123.167.x:39903
68: session 000000000000000002: user <iuli>: incoming packet CREATE_PERMISSION processed,                                     success
68: session 000000000000000002: user <iuli>: incoming packet CREATE_PERMISSION processed,                                     success
68: session 000000000000000005: user <>: incoming packet message processed, error 401: Un                                    authorised
68: session 000000000000000002: user <iuli>: incoming packet CREATE_PERMISSION processed,                                     success
68: session 000000000000000005: user <>: incoming packet message processed, error 401: Un                                    authorised
69: ERROR: check_stun_auth: user iuli credentials are incorrect
69: session 000000000000000005: user <iuli>: incoming packet message processed, error 401                                    : Unauthorised
69: ERROR: check_stun_auth: user iuli credentials are incorrect
69: session 000000000000000005: user <iuli>: incoming packet message processed, error 401                                    : Unauthorised
69: ERROR: check_stun_auth: user iuli credentials are incorrect
69: session 000000000000000005: user <iuli>: incoming packet message processed, error 401                                    : Unauthorised
77: session 000000000000000001: user <>: incoming packet BINDING processed, success
77: session 000000000000000001: user <>: incoming packet BINDING processed, success
78: session 000000000000000004: TCP socket closed remotely 213.233.92.66:38720
78: session 000000000000000004: closed (2nd stage), user <>, local 172.31.37.x:3478, re                                    mote 213.233.92.66:38720, reason: TCP connection closed by client (callback)
88: session 000000000000000001: user <>: incoming packet BINDING processed, success
88: session 000000000000000001: user <>: incoming packet BINDING processed, success
98: session 000000000000000001: user <>: incoming packet BINDING processed, success
98: session 000000000000000001: user <>: incoming packet BINDING processed, success
108: session 000000000000000001: user <>: incoming packet BINDING processed, success
108: session 000000000000000001: user <>: incoming packet BINDING processed, success
118: session 000000000000000001: user <>: incoming packet BINDING processed, success
119: session 000000000000000001: user <>: incoming packet BINDING processed, success
127: session 000000000000000001: closed (2nd stage), user <>, local 172.31.37.x:3478, remote 213.233.92.66:15273, reason: allocation watchdog determined stale session state
127: session 000000000000000003: closed (2nd stage), user <iuli>, local 172.31.37.x:3478, remote 213.233.92.66:44983, reason: allocation watchdog determined stale session state
128: session 000000000000000005: closed (2nd stage), user <iuli>, local 172.31.37.x:3478, remote 86.123.167.207:39903, reason: allocation watchdog determined stale session state
129: handle_udp_packet: New UDP endpoint: local addr 172.31.37.x:3478, remote addr 213.233.92.66:15273
129: session 000000000000000006: user <>: incoming packet BINDING processed, success
129: session 000000000000000006: user <>: incoming packet BINDING processed, success
139: session 000000000000000006: user <>: incoming packet BINDING processed, success

iuli...@gmail.com

unread,
May 19, 2014, 5:44:52 AM5/19/14
to eas...@googlegroups.com
I attached the topology used
Thank you!
topology.jpg

Eric Davies

unread,
May 19, 2014, 12:04:04 PM5/19/14
to eas...@googlegroups.com
Mostly likely, you've either screwed up your ice config information in the server.js file or you've messed up your turnserver.conf file. However if you don't post both, only telepathic mutants wearing colorful spandex outfits will be able to assist you. 

Emilio López

unread,
May 19, 2014, 12:12:13 PM5/19/14
to eas...@googlegroups.com
As a member of the National Association of Telepathic Mutants Wearing Colorful Spandex Outfits (NATMWCS) I have to inform you we have been looking at the problem but failed to find a solution.

EMILIO!

iuli...@gmail.com

unread,
May 20, 2014, 1:01:57 AM5/20/14
to eas...@googlegroups.com
I want to  in this team. Sounds nice, so we can definitely understand how penguins think. Why even bother with the command line, we think about them and write themselves. LOL! thank you. 
Back to problems. I attached the necessary files; my apologies ...
mysettings.rar

iuli...@gmail.com

unread,
May 20, 2014, 6:16:01 AM5/20/14
to eas...@googlegroups.com
I found where the problem was. 
Turnserver was functional. Somehow he reached only iuli user even when I deleted the configuration. So I restarted the settings and checking step that sends the server I managed to make it functional. 
Thanks for your support! 
A question though. What's realm and how many connections can be made ​​in parallel on the same user?
Message has been deleted
Message has been deleted
Message has been deleted
Message has been deleted
Message has been deleted
Message has been deleted
Message has been deleted

yamaka...@gmail.com

unread,
Oct 10, 2014, 11:29:00 AM10/10/14
to eas...@googlegroups.com
I'm actually busy with this at the moment and I wonder how this goes when:

Client makes connection to EasyRTC, MySQL DB is checked and you are auth or not.

When auth, EasyRCT should lookup the mySQL DB of the Turnserver and throw that back to the client which auths against Turn with the credentials it got back from the EasyRTC APP ?

Can you give some examples about this maybe ?

Thanks!

Matt

yamaka...@gmail.com

unread,
Oct 13, 2014, 9:03:57 AM10/13/14
to eas...@googlegroups.com
Any idea on this ?

yamaka...@gmail.com

unread,
Oct 22, 2014, 11:29:48 AM10/22/14
to eas...@googlegroups.com
I'm still on this path, any help would be great how to let EasyRTC Auth and Stun interact with each other.

Eric Davies

unread,
Oct 24, 2014, 1:59:13 AM10/24/14
to eas...@googlegroups.com
Maybe I'm missing something, but I think what you are looking for is covered by:

where it has:

Creating Listener for Event "getIceConfig"

Create a custom listener for the event "getIceConfig" in cases where a custom ICE configuration needs to be delivered on a per connection basis. This may be needed for authentication, localization, or load balancing.

In this example we are supplying a custom username for the TURN server.

easyrtc.on("getIceConfig", function(connectionObj, callback){
 
var myIceServers=[
   
{"url":"stun:stun.easyrtc.com:3478"},
   
{
     
"url":        "turn:turn.easyrtc.com:3478",
     
"username":   connectionObj.getUsername(),
     
"credential": "345yRTC!"
   
}
 
];

  callback
(null, myIceServers);
});

yamaka...@gmail.com

unread,
Feb 24, 2015, 4:03:46 AM2/24/15
to eas...@googlegroups.com
Hi,

I'm reviewing this.

I'm authing against a token only at the moment and I wonder what about the username, does the TURN server really needs the username ?

Cheers,

Matt

yamaka...@gmail.com

unread,
Feb 25, 2015, 12:16:34 PM2/25/15
to eas...@googlegroups.com
Is this group still active ?

Any "working" example would be nice for Turn + MySQL without username.

Eric Davies

unread,
Feb 25, 2015, 12:40:45 PM2/25/15
to eas...@googlegroups.com
You've uncovered our dirty secret, all those posts you see in the last month are actually by AI robots adapted from GTA III. If one of the posters tries to sell you a '67 
Corvette, it's probably "hot" and doesn't exist in meat-space.

More seriously:
  • If nobody has done what you are trying to do, you aren't going to get any responses.
  • If people consider the solution an important part of their private IP, they aren't going to respond.
  • Appending your question onto a thread that originated in 2013 means that most people won't notice. Start a fresh thread.

yamaka...@gmail.com

unread,
Feb 25, 2015, 5:04:17 PM2/25/15
to eas...@googlegroups.com
Hi!

Yeah I see activity here but not on some basic "fancy" parts like authenticationa dn highligting by creating a new topic as this one already contains good info from the start, I thought it was not polite to do.

More Joking mode:

- We need to beware for the autobots ?
- Do we need Optimus ?

Himanshu Srivastava

unread,
Jun 30, 2015, 2:43:53 AM6/30/15
to eas...@googlegroups.com
Hello

I am trying to configure coturn for easyrtc.
I followed steps you mentioned.

1. turnserver -L <public IP> -a -b turnuserdb.conf -f -r easyrtc.com
    Here public IP is the ip address where I am running turnserver.
2.  mysql-userdb="host=127.0.0.1 dbname=easyrtc user=<dbusername> password=<dbpassword> connect_timeout=10"
3.turnadmin -a  -r easyrtc.com -p EasyRTCPassword

I am running easyrtc server.js on the same IP address.
4. I made the below changes in my server.js to configure turn

 var myIceServers=
[
 {"url":"< public ip address >","username":"EasyRTC","credential":"EasyRTCPassword"},
]

5. Then I tired to run the demos 

I am not able to connect across the internet.

Did I made any mistake ? Please correct me if any ?

Regards
Himanshu

nitin jain

unread,
Jul 2, 2015, 6:05:08 AM7/2/15
to eas...@googlegroups.com
Hi Thanks for sharing this...it is really helpful.
I want to RUN both STUN and TURN-could not find steps to do so; Please help to start both STUN and TURN server.

Just to give background of my requirement- I want to use these servers with "WebRTC SERVER Simulator Tool". Simulator will be used to test WebRTC client.
I need not to have secure or password mechanism also- Hence please let me know if any way to avoid password check and/or security check with TURN sever running for WebRTC client.

Thanks again.

Best Regards,
NJ
Reply all
Reply to author
Forward
0 new messages