
This article explores the key roles of STUN and TURN servers in WebRTC connection establishment, from NAT traversal principles to actual deployment configuration, helping developers comprehensively master the core technologies of WebRTC network connections.
Overview: Why Do We Need STUN and TURN?
In real-world network environments, most devices are located behind NAT (Network Address Translation) devices or firewalls, which poses significant challenges for WebRTC’s P2P direct connections. STUN and TURN servers were created to solve this problem.
They are both important components of the ICE (Interactive Connectivity Establishment) framework, each taking on different but complementary responsibilities:
- STUN: Attempts to discover the possibility of direct P2P connections
- TURN: Provides relay services when direct connections fail
graph TB
subgraph "Network Environment"
A[Client A<br/>Behind NAT]
B[Client B<br/>Behind NAT]
NAT1[NAT Device A]
NAT2[NAT Device B]
STUN[STUN Server]
TURN[TURN Server]
end
A --> NAT1
B --> NAT2
NAT1 <-->|Discover Public Address| STUN
NAT2 <-->|Discover Public Address| STUN
NAT1 <-->|Relay Traffic| TURN
TURN <-->|Relay Traffic| NAT2
NAT1 -.->|Attempt Direct Connection| NAT2
style STUN fill:#e1f5fe
style TURN fill:#fff3e0
style A fill:#f3e5f5
style B fill:#f3e5f5
STUN Server: The “Pathfinder” for P2P Connections
Core Functions of STUN
The main task of STUN (Session Traversal Utilities for NAT) servers is to help clients behind NAT discover their public IP addresses, determine NAT types, and prepare for P2P “hole punching”.
1. Public Address Discovery
Most devices use private IP addresses (such as 192.168.x.x) that cannot be directly accessed from the public internet. STUN servers help clients discover public addresses through the following process:
sequenceDiagram
participant C as Client<br/>(192.168.1.100)
participant N as NAT Device
participant S as STUN Server<br/>(Public IP)
Note over C,S: STUN Address Discovery Process
C->>N: Send STUN Request<br/>Source: 192.168.1.100:5000
N->>S: Forward Request<br/>Source: 203.0.113.10:12345
S->>N: STUN Response<br/>Contains Mapped Address: 203.0.113.10:12345
N->>C: Forward Response
Note over C: Now knows its public address<br/>203.0.113.10:12345
2. NAT Type Detection
STUN servers determine the NAT type that clients are behind through a series of tests:
Impact of NAT Types on P2P Connections:
- Full Cone NAT: Easiest to establish P2P connections, STUN works best
- Restricted Cone NAT: Requires both parties to send packets simultaneously to establish connection
- Port Restricted Cone NAT: Connection success rate depends on specific network configuration
- Symmetric NAT: STUN is ineffective, must use TURN relay
3. P2P “Hole Punching” Technology
For cone NATs, STUN can help implement “UDP hole punching”:
sequenceDiagram
participant A as Client A<br/>Behind NAT-A
participant NA as NAT-A
participant NB as NAT-B
participant B as Client B<br/>Behind NAT-B
participant S as Signaling Server
Note over A,B: UDP Hole Punching Process
A->>S: Send own public address
B->>S: Send own public address
S->>A: Inform B's public address
S->>B: Inform A's public address
Note over A,B: Send packets simultaneously
A->>NA: Send packet to B
B->>NB: Send packet to A
NA->>NB: Packet may be lost
NB->>NA: Packet may be lost
Note over A,B: After NAT mapping established
A->>B: Direct P2P communication successful!
Limitations of STUN
STUN is not a universal solution, especially when facing symmetric NAT:
Problems with Symmetric NAT:
Symmetric NAT assigns different external ports for each different target IP. This means:
- Port seen by STUN server:
12345
- Port needed by P2P peer:
12346
(different!) - Result: P2P connection fails, must use TURN relay
TURN Server: The “Last Resort” for Connections
Core Functions of TURN
TURN (Traversal Using Relays around NAT) servers act as relay servers to forward media traffic when STUN cannot establish direct connections.
1. Traffic Relay Mechanism
graph TB
subgraph "TURN Relay Connection"
A[Client A<br/>Symmetric NAT]
B[Client B<br/>Strict Firewall]
T[TURN Server<br/>Public IP]
A <-->|Establish Relay Connection| T
T <-->|Establish Relay Connection| B
A -.->|Cannot Direct Connect| B
end
style T fill:#fff3e0
style A fill:#ffebee
style B fill:#ffebee
2. TURN Connection Establishment Process
Three Steps for TURN Connection Establishment:
- Allocate Relay Address: Request a public relay address from TURN server
- Create Permissions: Tell TURN server which peers are allowed to connect
- Relay Data: All media data is forwarded through TURN server
3. Cost Considerations for TURN
TURN servers need to relay all media traffic, which brings significant costs:
TURN Server Cost Considerations:
- Bandwidth Consumption: Need to relay all media traffic
- Cost Example: 10-person video conference, 100 hours per month ≈ $200-500
- Optimization Suggestion: Prioritize STUN direct connections, use TURN as backup
ICE Framework: Coordinator of STUN and TURN
ICE Candidate Collection
The ICE framework collects all possible connection paths:
flowchart TD
A[Start ICE Collection] --> B[Collect Host Candidates]
B --> C[Collect Reflexive Candidates<br/>via STUN]
C --> D[Collect Relay Candidates<br/>via TURN]
B --> B1[Local IP:Port<br/>192.168.1.100:5000]
C --> C1[Public IP:Port<br/>203.0.113.10:12345]
D --> D1[TURN Relay IP:Port<br/>198.51.100.5:3478]
B1 --> E[Connectivity Check]
C1 --> E
D1 --> E
E --> F{Select Best Path}
F -->|Priority 1| G[Direct Connection<br/>Lowest Latency]
F -->|Priority 2| H[STUN-Assisted Connection<br/>Medium Latency]
F -->|Priority 3| I[TURN Relay Connection<br/>Guaranteed Connectivity]
Complete ICE Connection Establishment Process
// Basic ICE configuration example
const peerConnection = new RTCPeerConnection({
iceServers: [
{ urls: 'stun:stun.l.google.com:19302' },
{
urls: 'turn:turn.example.com:3478',
username: 'user123',
credential: 'pass456'
}
]
});
// Listen for ICE candidates
peerConnection.onicecandidate = (event) => {
if (event.candidate) {
// Send candidate to remote peer
sendToRemotePeer(event.candidate);
}
};
// Listen for connection state
peerConnection.oniceconnectionstatechange = () => {
console.log('Connection state:', peerConnection.iceConnectionState);
};
Practical Deployment: coturn Server Configuration
coturn Installation and Basic Configuration
# Ubuntu/Debian installation
sudo apt-get update
sudo apt-get install coturn
# CentOS/RHEL installation
sudo yum install epel-release
sudo yum install coturn
Configuration File Details
# /etc/turnserver.conf configuration example
# Listening ports
listening-port=3478
tls-listening-port=5349
# External IP address (important!)
external-ip=203.0.113.10
# Relay IP range
relay-ip=203.0.113.10
min-port=10000
max-port=20000
# Authentication configuration
lt-cred-mech
use-auth-secret
static-auth-secret=your-secret-key-here
# Database configuration (optional)
userdb=/var/lib/turn/turndb
# Logging configuration
verbose
log-file=/var/log/turnserver.log
# Security configuration
no-multicast-peers
no-cli
no-tlsv1
no-tlsv1_1
# Performance optimization
total-quota=100
bps-capacity=0
stale-nonce=600
Docker Deployment Solution
# docker-compose.yml
version: '3.8'
services:
coturn:
image: coturn/coturn:latest
container_name: coturn-server
restart: unless-stopped
ports:
- "3478:3478/udp"
- "3478:3478/tcp"
- "5349:5349/tcp"
- "10000-20000:10000-20000/udp"
volumes:
- ./turnserver.conf:/etc/coturn/turnserver.conf:ro
- ./ssl:/etc/ssl/coturn:ro
- turndb:/var/lib/turn
environment:
- TURN_USERNAME=myuser
- TURN_PASSWORD=mypassword
command: [
"-c", "/etc/coturn/turnserver.conf",
"--external-ip", "$(curl -s ifconfig.me)",
"--verbose"
]
volumes:
turndb:
Dynamic Authentication Configuration
// Simple TURN authentication service
const crypto = require('crypto');
function generateTurnCredentials() {
const username = Math.floor(Date.now() / 1000) + 3600; // 1 hour validity
const password = crypto
.createHmac('sha1', 'your-secret-key')
.update(username.toString())
.digest('base64');
return { username: username.toString(), password };
}
Performance Optimization and Monitoring
Server Monitoring Key Points
- Connection Success Rate: Monitor ICE connection establishment success rate
- Response Time: Check STUN/TURN server response latency
- Bandwidth Usage: Monitor TURN server traffic consumption
- Error Logs: Timely detection and handling of connection failure issues
Load Balancing Configuration
# Simple TURN server load balancing
upstream turn_servers {
server turn1.example.com:3478;
server turn2.example.com:3478;
server turn3.example.com:3478 backup;
}
Troubleshooting and Debugging
Common Issues and Solutions
Common Causes of Connection Failures:
- Both parties behind symmetric NAT → Ensure TURN server is available
- STUN/TURN servers unreachable → Check network connectivity and firewall settings
- ICE candidate collection timeout → Increase timeout or use multiple STUN servers
- Permission authentication failure → Check TURN server username and password
Debugging Tips:
// Check ICE connection state
peerConnection.oniceconnectionstatechange = () => {
console.log('ICE state:', peerConnection.iceConnectionState);
if (peerConnection.iceConnectionState === 'failed') {
console.log('Connection failed, check STUN/TURN configuration');
}
};
Network Connectivity Testing
#!/bin/bash
# STUN/TURN server connectivity test script
STUN_SERVER="stun.l.google.com:19302"
TURN_SERVER="turn.example.com:3478"
TURN_USER="testuser"
TURN_PASS="testpass"
echo "=== STUN/TURN Server Connectivity Test ==="
# Test STUN server
echo "1. Testing STUN server connectivity..."
if nc -u -z -w3 ${STUN_SERVER/:/ }; then
echo "✓ STUN server reachable"
else
echo "✗ STUN server unreachable"
fi
# Test TURN server TCP port
echo "2. Testing TURN server TCP connectivity..."
if nc -z -w3 ${TURN_SERVER/:/ }; then
echo "✓ TURN TCP port reachable"
else
echo "✗ TURN TCP port unreachable"
fi
# Test TURN server UDP port
echo "3. Testing TURN server UDP connectivity..."
if nc -u -z -w3 ${TURN_SERVER/:/ }; then
echo "✓ TURN UDP port reachable"
else
echo "✗ TURN UDP port unreachable"
fi
# Use turnutils_stunclient for testing
echo "4. Using STUN client test..."
turnutils_stunclient -p 3478 ${TURN_SERVER/:*/}
echo "Test completed!"
Summary: STUN and TURN servers are key infrastructure for WebRTC to achieve reliable P2P connections. STUN is responsible for discovering network topology and attempting direct connections, while TURN provides relay assurance when direct connections fail. Understanding their working principles, proper configuration and deployment of these servers is crucial for building stable WebRTC applications. In actual projects, it is recommended to deploy both STUN and TURN servers simultaneously and perform performance optimization and monitoring according to business requirements.
Tags
Copyright Notice
This article is created by WebRTC.link and licensed under CC BY-NC-SA 4.0. This site repost articles will cite the source and author. If you need to repost, please cite the source and author.
Comments
GiscusComments powered by Giscus, based on GitHub Discussions