Coturn TURN Server
TURN (Traversal Using Relays around NAT) server for WebRTC media relay.
Overview
Coturn provides NAT traversal for WebRTC connections that cannot establish direct peer-to-peer connections. This is essential for:
- Clients behind symmetric NAT
- Restrictive corporate firewalls
- Mobile networks with carrier-grade NAT
Configuration
turnserver.conf
Located at ~/ravenhelm/services/coturn/turnserver.conf:
# Network settings
listening-port=3478
tls-listening-port=5349
# External IP (public-facing)
external-ip=67.198.117.118
# Relay ports for media
min-port=49152
max-port=49200
# Realm for authentication
realm=turn.ravenhelm.dev
# Use fingerprinting for TURN messages
fingerprint
# Long-term credential mechanism (required for LiveKit)
lt-cred-mech
# Disable CLI for security
no-cli
# Logging
log-file=stdout
verbose
# Security settings
no-multicast-peers
no-tlsv1
no-tlsv1_1
# Allow localhost for testing
allow-loopback-peers
Docker Configuration
services:
coturn:
image: coturn/coturn:latest
container_name: coturn
restart: unless-stopped
network_mode: host # Required for UDP relay
volumes:
- ./turnserver.conf:/etc/coturn/turnserver.conf:ro
command: -c /etc/coturn/turnserver.conf --static-auth-secret=${TURN_SECRET}
Note: network_mode: host is required because Coturn needs direct access to network interfaces for UDP relay.
Port Usage
| Port | Protocol | Purpose |
|---|---|---|
| 3478 | UDP/TCP | STUN/TURN listening |
| 5349 | TCP | TURNS (TLS) |
| 49152-49200 | UDP | Media relay ports |
Integration with LiveKit
LiveKit is configured to use Coturn for TURN relay:
# In livekit.yaml
turn:
enabled: true
domain: turn.ravenhelm.dev
tls_port: 5349
udp_port: 3478
external_tls: true
Authentication
Coturn uses static auth secret shared with LiveKit:
# Environment variable
TURN_SECRET=<shared_secret>
LiveKit generates time-limited TURN credentials using this secret for each client connection.
Testing
Test STUN connectivity
# Using webrtc-internals in Chrome
# Navigate to chrome://webrtc-internals/
# Look for ICE candidates with "srflx" type
# Or use online tester
# https://webrtc.github.io/samples/src/content/peerconnection/trickle-ice/
Test TURN relay
# Check if TURN is responding
nc -vzu 67.198.117.118 3478
# View logs
docker logs coturn
Troubleshooting
No relay candidates
Symptoms: WebRTC connections fail for some users
Diagnosis:
- Check firewall allows UDP 3478 and 49152-49200
- Verify external IP is correct
- Test TURN credentials
Solution:
# Verify port is reachable
nc -vzu <external_ip> 3478
# Check coturn is running
docker ps | grep coturn
# View logs
docker logs coturn --tail=50
Authentication failures
Symptoms: "401 Unauthorized" in TURN
Diagnosis:
- Verify TURN_SECRET matches between Coturn and LiveKit
- Check credential time sync
Solution:
# Verify environment variable
docker exec coturn env | grep TURN
# Restart with correct secret
docker-compose restart coturn
See Also
- [[LiveKit]] - WebRTC infrastructure
- [[Voice-Gateway]] - Voice agent service