Helder Esteves

Type and hit Enter to search

JavaScript
Uncategorized
React
Software Architecture
General
Management
Next.JS
Node.JS
TypeScript
JavaScript
Uncategorized
React
Software Architecture
General
Management
Next.JS
Node.JS
blue UTP cord
Uncategorized

Setting up a TURN server with Node: Production-ready

Helder Esteves
Helder Esteves
May 19, 2023 5 Mins Read
370 Views
1 Comment

In this guide, you’ll learn how to set up a TURN relaying server and how to configure it to use with Node.JS for a production app.

The problem

If you’re familiar with WebRTC and P2P (peer-to-peer) connection, then you should know about its’ limitations.

One of the biggest hurdles in setting up a direct P2P connection is the existence of NATs (Network Address Translation).

As the name suggests, NAT basically converts one IP address to another. For example, when you’re behind a router, you have an internal IP associated with you, and then when it passes through the router you have another IP address that is considered public.

So what’s the problem?

When you’re connecting to the internet behind a NAT, your device only has knowledge of the IP associated with it (e.g. assigned IP from a router). However, other devices from around the internet only know your external IP (e.g. your router’s IP).

This causes problems when you connect P2P, as your device has no knowledge of its’ own external IP.

The solution

There are 2 ways of dealing with this:

Remember when I said that devices (e.g. your laptop) don’t know of their external IP address when behind a NAT? Well, STUN provides you with exactly that. When you make a request to a STUN server, it replies with your public IP address. This way you are now capable of connecting through P2P. That’s all!

STUN works well when the NAT works the same way for every connection. However, there are situations where a device is behind a symmetric NAT. In this case, connections to the “outside” always change, so you can’t define a specific IP and port to map your device.

To overcome this, a workaround is to simply relay all the communication through a server. With TURN, P2P is not so peer-to-peer (not at all, actually), as the communication is now going through a server instead.

Installing coTURN

Great, so now you know 2 of the fallacies of P2P, so how can you fix it in your case?

coTURN is an open-source implementation that lets you create a STUN and TURN server in one, without much hassle.

Let’s say you spin up a Debian (or Ubuntu) server on Digitalocean, AWS, GCloud, etc… In this case, you should first open the required ports:

80: TCP (if you need SSL)
443: TCP (if you need SSL)
3478: TCP/UDP
5349: TCP/UDP

Since managing the firewall depends on the provider you’re using, it’s out of the scope of this guide. If you’re having trouble, reply in the comments and I’ll help you out.

Once you’re done, all you need is to SSH into your server and install with the following commands:

sudo apt-get -y update
sudo apt-get -y install coturn
turnserver

That’s it! That’s all you need. You can check if it’s running by executing:

sudo systemctl status coturn

Which should show:

coturn.service - coTURN STUN/TURN Server
Loaded: loaded (/lib/systemd/system/coturn.service; enabled; ....)
Active: active (running) since Mon 2020-08-03 19:06:01 UTC; 3 days ago

If you want to execute coTURN as a service, edit the file /etc/default/coturn and add the following line to it:

TURNSERVER_ENABLED=1

Configuring coTURN

Although coTURN is now installed and running, there are a few things you should configure to:

  • Enhance the security of your server
  • Prevent other apps from using your TURN server
  • Set up SSL

To set up SSL, please go to certbot.eff.org and follow the interactive tutorial on setting up Let’s Encrypt on your server. We’ll use the certificates generated by certbot later.

We should also install fail2ban, which is a simple but effective extension that protects your server against unwanted requests. Let’s do it by running the command:

sudo apt install fail2ban

Now, on Debian / Ubuntu, the configuration file for coTURN can be found in /etc/turnserver.conf

If you check its’ contents, you’ll see it’s well documented for all you need, but you usually want to have a configuration like follows:

fingerprint
use-auth-secret
static-auth-secret=[SECRET] #change this
realm=[YOUR DOMAIN] #change this with e.g. example.com
total-quota=100
syslog
no-multicast-peers
cert=/etc/letsencrypt/live/[YOUR DOMAIN]/fullchain.pem #certificate from ssl
pkey=/etc/letsencrypt/live/[YOUR DOMAIN]/privkey.pem #certificate from ssl

If your server is also behind a NAT (e.g if you’re using AWS), you need to add 3 more options

listening-ip=[INTERNAL IP ADDRESS] #change this
relay-ip=[INTERNAL IP ADDRESS] #change this
external-ip=[EXTERNAL IP ADDRESS]/[INTERNAL IP ADDRESS] #change this

In many other configurations, you see using lt-cred-mech instead of use-auth-secret.

In WebRTC, you need to share the user and password with the client for it to be able to connect with the server.

With lt-cred-mech, you’ll set a password that is directly shared with the user. This is easy to set up and good for testing, but not recommended for production.

With use-auth-secret, you’ll set a secret that generates other temporary passwords based on cryptography. This is crucial for any production app because it’ll prevent malicious activity like stealing your server to relay their own communications.

Now, it’s important that you change static-auth-secret with something secure. You’ll need this to generate the credentials for your backend server. To generate a secure password in Ubuntu / Debian, run the following command:

openssl rand -base64 32

After you finish configuring, restart coTURN like this:

sudo systemctl restart coturn

And you’re done with the TURN server!

Generating temporary credentials in Node.JS

Now you have your TURN server working and properly configured. If you already set up a WebRTC connection in your frontend application, then the configuration params for RTCPeerConnection would be like like the following:

{
iceServers: [
{
urls: ['stun:yourturn.server.com']
},
{
urls: ['turn:yourturn.server.com'],
username: '????',
credential: '????'
}
],
sdpSemantics: 'unified-plan'
}

The username and credential in ???? are what we’ll be working to generate in this section, for a production-ready setup.

To generate the keys in Node.JS, use this code:

const crypto = require("crypto");

const secret = "YOUR_SECRET_KEY" // Replace this with the key from static-auth-secret

function generateTurnKey() {
  // The username is a timestamp that represents the expiration date of this credential
  // In this case, it's valid for 12 hours (change the '12' to how many hours you want)
  const username = (Date.now() / 1000 + 12 * 3600).toString();

  // Now create the corresponding credential based on the secret
  const hmac = crypto.createHmac("sha1", secret);
  hmac.setEncoding("base64");
  hmac.write(username);
  hmac.end();
  const credential = hmac.read();

  return {
    username,
    credential,
  };
};
console.log(generateTurnKey());

Now all you need is to send the generated values to the client (e.g. with Socket.io) and replace the values ‘????’ at the beginning of this section with what’s generated in the function above.

Testing the TURN server

To test your TURN server connectivity, open this link: Trickle ICE.

In “STUN or TURN URI” field type “turn:your.turnserver.com”

Now, run the function that generates the temporary in Node.JS, copy the “username” value, and paste it into “TURN username”. Do the same with “credential” and paste it in “TURN password”. Now press “Gather candidates”.

It should show up a list of candidates without errors if it’s working properly.

You can also try setting a wrong username or password on purpose to see if you get “Unauthorized” in the response.

If it does, then everything is working properly. Congrats!

If you have any questions, please comment below and I’ll be answering as much as I can. Happy TURNing!

Share Article

Other Articles

grayscale photo of person holding glass
Previous

Top 10 JavaScript Coding Challenges You Must Absolutely Know

a person pointing at a rock with writing on it
Next

7 Best Coding Challenge Websites for 2023: Improve Your Skills and Boost Your Career

Next
a person pointing at a rock with writing on it
May 20, 2023

7 Best Coding Challenge Websites for 2023: Improve Your Skills and Boost Your Career

Previous
May 17, 2023

Top 10 JavaScript Coding Challenges You Must Absolutely Know

grayscale photo of person holding glass

One Comment

  1. Zach says:
    June 3, 2023 at 3:21 am

    Nice article! Can you tell me approximately how much RAM is needed for each WebRTC audio connection that goes through the TURN server?

    Reply

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Subscribe
Stay Updated!
Get notified when awesome content is posted. Learn more everyday.
Most Read
Software Architecture
5 JS Design Patterns Every Developer Should Know
March 10, 2023
5 Min Read
yellow line on gray asphalt road
Next.JS
5 Next.JS Tips You Never Heard About
March 27, 2023
4 Min Read
This is the sign you've been looking for neon signage
General
Mastering the Art of Software Development: Best Practices Cheat Sheet
May 11, 2023
4 Min Read
Most Engagement
JavaScript
Simple Backgrounds For Websites — Cheat Sheet

This cheat sheet will help you the next time you're choosing a background for your website....

February 21, 2023
3 Min Read
Most Recent
bird's-eye view photography of city buildings
React
Best React.js Project Design and Architectures for Better Maintainability
September 19, 2023
3 Min Read
blue ballpoint pen on white notebook
Node.JS
Optimal Node.JS API Routing: Architectures, Frameworks, Code Examples & Folder Structures
September 17, 2023
4 Min Read
grayscale photo of person holding glass
JavaScript
Top 10 JavaScript Coding Challenges You Must Absolutely Know
May 17, 2023
9 Min Read

Related Posts

This is the sign you've been looking for neon signage
General
Mastering the Art of Software Development: Best Practices Cheat Sheet
May 11, 2023
4 Min Read
Read More
blue ballpoint pen on white notebook
Node.JS
Optimal Node.JS API Routing: Architectures, Frameworks, Code Examples & Folder Structures
September 17, 2023
4 Min Read
Read More
person showing thumb
Software Architecture
Premature Optimization: A Software Developer’s Worst Nightmare
April 24, 2023
3 Min Read
Read More
JavaScript
Simple Backgrounds For Websites — Cheat Sheet
February 21, 2023
3 Min Read
Read More

Helder Esteves

Read everything there is to know about the JavaScript development ecosystem, from programming to project management.

Recent

Best React.js Project Design and Architectures for Better Maintainability
September 19, 2023
Optimal Node.JS API Routing: Architectures, Frameworks, Code Examples & Folder Structures
September 17, 2023

Categories

JavaScript9
Uncategorized4
React3
Software Architecture2

Contact

Reach out to us through helder.writer@gmail.com

© 2022, All Rights Reserved.

Go to mobile version