STUN and TURN: The Basics of WebRTC Connectivity

ExpressTURNExpressTURN
7 min read

WebRTC (Web Real-Time Communication) is a powerful open-source technology that enables peer-to-peer communication directly in browsers and mobile apps. Whether you're building a video conferencing app, a live streaming platform, or a real-time chat system, WebRTC makes it possible to exchange audio, video, and data without plugins. However, establishing connections between peers behind Network Address Translators (NATs) or firewalls can be challenging. This is where STUN and TURN servers come into play. In this post, we'll dive into the basics of STUN and TURN, why they're essential for WebRTC, and how to implement them in your projects.

What Are STUN and TURN?

STUN (Session Traversal Utilities for NAT) and TURN (Traversal Using Relays around NAT) are protocols that facilitate peer-to-peer connections in the presence of NATs and firewalls. They are integral to the ICE (Interactive Connectivity Establishment) protocol, which WebRTC uses to find the optimal connection path.

STUN: Discovering Public IPs

A STUN server helps a device determine its public IP address and port when behind a NAT. It acts like a mirror: the device sends a request to the STUN server, which responds with the device's public-facing IP and port. This information is shared with the other peer to attempt a direct connection.

Here’s a simple example of configuring a STUN server in a WebRTC application using JavaScript:

const configuration = {
  iceServers: [
    {
      urls: 'stun:stun.l.google.com:19302'
    }
  ]
};

const peerConnection = new RTCPeerConnection(configuration);

In this code, we configure a WebRTC peer connection to use Google's public STUN server. The RTCPeerConnection object queries the STUN server to gather ICE candidates (possible connection endpoints) and shares them with the other peer via a signaling server.

STUN is lightweight and effective for most scenarios where NATs are not overly restrictive (e.g., symmetric NATs). However, it fails when direct connections are blocked by strict firewalls or complex NAT configurations.

Google's Free STUN Servers

Google provides reliable, free STUN servers that are widely used in WebRTC applications. Here’s a list of their public STUN servers:

  • stun:stun.l.google.com:19302

  • stun:stun1.l.google.com:19302

  • stun:stun2.l.google.com:19302

  • stun:stun3.l.google.com:19302

  • stun:stun4.l.google.com:19302

These servers are globally available, well-maintained, and ideal for development and production use. You can include multiple servers in your configuration for redundancy:

const configuration = {
  iceServers: [
    { urls: 'stun:stun.l.google.com:19302' },
    { urls: 'stun:stun1.l.google.com:19302' },
    { urls: 'stun:stun2.l.google.com:19302' }
  ]
};

TURN: Relaying Media When Direct Connections Fail

When a direct peer-to-peer connection isn’t possible, a TURN server acts as a relay, receiving data from one peer and forwarding it to the other. This ensures connectivity in challenging network environments, such as when peers are behind symmetric NATs or corporate firewalls.

TURN is more resource-intensive than STUN because it relays all media traffic, requiring significant bandwidth and server resources. As a result, TURN is typically used as a fallback when STUN fails.

Here’s how to include both STUN and TURN servers in your WebRTC configuration:

const configuration = {
  iceServers: [
    {
      urls: 'turn:relay1.expressturn.com:3478',
      username: 'your-username',
      credential: 'your-password'
    }
  ]
};

const peerConnection = new RTCPeerConnection(configuration);

In this example, the iceServers array includes a STUN server and a TURN server with authentication credentials, ensuring robust connectivity.

Why Do You Need STUN and TURN?

WebRTC aims for direct peer-to-peer connections to minimize latency and optimize performance. However, real-world networks are complex, with most devices operating behind NATs or firewalls that obscure public IP addresses and restrict incoming connections. STUN and TURN address these challenges by enabling connectivity in diverse network conditions.

Here’s why they’re essential:

  1. NAT Traversal: STUN enables peers to discover their public IPs for direct connections, while TURN provides a relay when direct connections fail.

  2. Firewall Compatibility: Firewalls in corporate or residential networks may block UDP traffic. TURN servers can relay traffic over TCP or TLS to bypass these restrictions.

  3. Reliable Connectivity: By combining STUN and TURN with ICE, WebRTC ensures the best possible connection path, whether direct or relayed.

  4. Security: TURN servers hide IP addresses, enhancing user privacy by reducing the risk of exposing sensitive information like location or network details.

For example, in a video conferencing app, if one user is on a corporate network with a strict firewall and another is behind a home NAT, a direct connection might fail. A TURN server ensures they can still communicate by relaying their media streams.

When to Use STUN vs. TURN

  • Use STUN for most connections, as it’s lightweight and effective for ~80-90% of cases. Google’s free STUN servers are a great starting point.

  • Use TURN as a fallback for peers behind symmetric NATs or restrictive firewalls. Since TURN is resource-intensive, use it judiciously and ensure your server can handle the load.

A robust WebRTC implementation includes both STUN and TURN servers to maximize connectivity.

Configuring TURN with Authentication

TURN servers typically require authentication to prevent unauthorized access. Below are two common methods for authenticating with a TURN server: long-term credentials and secret key authentication.

Long-Term Credentials

Long-term credentials use a static username and password provided by the TURN server provider. Here’s an example of how to configure a WebRTC peer connection with long-term credentials and test the connection:

const configuration = {
  iceServers: [
    {
      urls: 'turn:relay1.expressturn.com:3478',
      username: 'example-user',
      credential: 'example-password'
    }
  ]
};

const peerConnection = new RTCPeerConnection(configuration);

peerConnection.onicecandidate = (event) => {
  if (!event.candidate) return;
  console.log('ICE Candidate:', event.candidate.candidate);
  if (event.candidate.candidate.includes('srflx')) {
    console.log('STUN server is reachable!');
  }
  if (event.candidate.candidate.includes('relay')) {
    console.log('TURN server is reachable!');
  }
};

peerConnection.onicecandidateerror = (event) => {
  console.error('ICE Candidate Error:', event.errorText);
};

peerConnection.createDataChannel('test');
peerConnection.createOffer()
  .then(offer => peerConnection.setLocalDescription(offer))
  .catch(error => console.error('Error creating offer:', error));

Secret Key Authentication

Secret key authentication generates time-limited credentials using a shared secret key, providing an additional layer of security. Here’s an example using the CryptoJS library to generate credentials:

const configuration = {
  iceServers: [
    {
      urls: 'turn:relay1.expressturn.com:3478',
      username: generateTurnUsername(),
      credential: generateTurnPassword()
    }
  ]
};

function generateTurnUsername() {
  const username = 'example-user';
  const ttl = 24 * 3600; // 24 hours
  const timestamp = Math.floor(Date.now() / 1000) + ttl;
  return `${timestamp}:${username}`;
}

function generateTurnPassword() {
  const secret = 'example-secret-key';
  const username = generateTurnUsername();
  return CryptoJS.HmacSHA1(username, secret).toString(CryptoJS.enc.Base64);
}

const peerConnection = new RTCPeerConnection(configuration);

peerConnection.onicecandidate = (event) => {
  if (!event.candidate) return;
  console.log('ICE Candidate:', event.candidate.candidate);
  if (event.candidate.candidate.includes('srflx')) {
    console.log('STUN server is reachable!');
  }
  if (event.candidate.candidate.includes('relay')) {
    console.log('TURN server is reachable!');
  }
};

peerConnection.onicecandidateerror = (event) => {
  console.error('ICE Candidate Error:', event.errorText);
};

peerConnection.createDataChannel('test');
peerConnection.createOffer()
  .then(offer => peerConnection.setLocalDescription(offer))
  .catch(error => console.error('Error creating offer:', error));

Note: For secret key authentication, include the CryptoJS library in your project:

<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js"></script>

These examples are ready to copy and paste into your WebRTC application. Replace example-user, example-password, and example-secret-key with the credentials provided by your TURN server provider.

Check out more examples using the secret key authentication method in various programming languages.

GeoDNS for Optimal Performance

To optimize latency, many TURN server providers may support the use of GeoDNS. GeoDNS resolves domain names to different server IP addresses based on the user’s geographic location. This is particularly useful for global WebRTC applications where users are spread across different regions.

Setting Up a TURN Server

While Google’s STUN servers are free and easy to use, TURN servers require more setup due to their resource demands. You can self-host a TURN server using open-source solutions like coturn, or opt for a managed service. ExpressTURN offers a free tier that’s easy to set up:

  1. Visit ExpressTURN's website.

  2. Sign up for an account to receive your TURN server credentials and URL (e.g., turn:relay1.expressturn.com:3478).

  3. Add the credentials to your WebRTC configuration, as shown above.

  4. Test your application to verify connectivity.

Best Practices for STUN and TURN

  • Combine STUN and TURN: Always include both in your ICE configuration for maximum compatibility.

  • Secure TURN Access: Use strong authentication (long-term credentials or secret keys) to prevent unauthorized use.

  • Optimize Bandwidth: Monitor TURN server usage, as relaying media can be resource-intensive.

  • Test Across Networks: Verify your application works in diverse network conditions, including behind firewalls and symmetric NATs.

Wrapping Up

STUN and TURN are the internal rails of WebRTC, enabling seamless real-time communication across various complex networks. With Google’s free STUN servers and a reliable TURN server like ExpressTURN, you can build robust WebRTC applications that connect users worldwide. Try integrating the code examples above into your project, and you’ll be well-equipped to handle any network challenge. Happy building!

0
Subscribe to my newsletter

Read articles from ExpressTURN directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

ExpressTURN
ExpressTURN