TL;DR
The best TURN server security practice is to not run one at all. If you must run one, Isolate it from internal systems, Restrict its relay capabilities, and Update it without fail. This guide covers what to lock down and why, regardless of which TURN implementation you’re running.
Do you actually need a TURN server?
Before spending time hardening a TURN server, it’s worth asking whether you need one in the first place. As Sean DuBois, creator of the Pion WebRTC library, put it:
I really would like to stop seeing people run TURN servers for SFUs! It adds complexity and just adds overhead.
And he’s right. If your architecture uses an SFU or MCU, clients connect directly to your media server and ICE with TCP via TLS may be sufficient for NAT traversal without needing a separate TURN relay. TURN is often unnecessary in SFU/MCU-first architectures, but still useful as a fallback in restrictive networks.
Every TURN server you deploy is another service to secure, patch, monitor, and defend against abuse. If you can avoid it, do. If you can’t, read on.
What this guide covers
This is an implementation-agnostic security reference for TURN server deployments. Whether you’re running coturn, eturnal, stunner, or any other TURN server, the security principles here apply universally. We focus on what to secure and why, not the syntax of any particular implementation.
Through our penetration testing and vulnerability research at Enable Security, we’ve identified three critical threat categories that require defense in depth: relay abuse, denial of service, and software vulnerabilities. Of course, every deployment is different, and TURN servers are flexible tools, so not every control will apply to every architecture. We’ve tried to be clear about when each recommendation applies and when it doesn’t.
Companion guides: For background on TURN security threats and real-world attack examples (including our $3,500 Slack bug bounty and C2 operations research), see TURN Security Threats: A Hacker’s View. For coturn-specific configuration syntax and copy-paste templates, see Securing coturn: Configuration Guide.
Heads up
Using a third-party TURN provider (e.g. Twilio, Xirsys)? Most of this guide won’t apply to you since the provider handles server hardening. The one thing that does apply is protecting your TURN credential API so that unauthenticated users can’t request credentials from your application.TURN server security checklist
Before deploying TURN servers to production, verify each of these security controls:
Access control & isolation
- 1. Isolate TURN server on dedicated network/security group (if applicable - see note)
- 2. Prevent relay to internal/local IP ranges (if applicable - see note)
- 3. Restrict relay destinations to known media servers only (if applicable)
Protocol hardening
- 4. Disable unnecessary protocol features (RFC5780, RFC3489)
- 5. Disable UDP listening (if TCP-only deployment)
- 6. Disable TCP relay (if UDP-only media)
- 7. Implement rate limiting (network level at minimum, application level where supported)
Operations & maintenance
- 8. Protect TURN credential APIs
- 9. Keep server software updated
- 10. Monitor traffic patterns and security events
Warning
Items 1-3 are marked “if applicable” because some architectures intentionally relay to internal IP addresses (e.g., SFUs on private networks). If your design requires internal relay, implement selective allow-listing instead of isolation and blanket IP denials.Detailed security controls
The following sections explain the rationale and implementation approach for each security control. For coturn-specific configuration syntax, see our coturn configuration guide.
1. Isolate TURN server on dedicated network/security group
Why: Prevents attackers from using your TURN server to access adjacent internal systems. Even with access control rules, network isolation provides defense in depth. If the TURN server is compromised or access controls are bypassed, isolation limits what an attacker can reach.
When this applies: Most deployments. Exception: architectures where TURN must relay to internal media servers (SFUs, MCUs). In those cases, use restrictive firewall rules to allow only necessary internal destinations.
Implementation:
Deploy TURN servers in a dedicated security group/network segment with:
- No access to internal application servers, databases, or management interfaces
- Outbound rules restricted to public Internet (for external peer relay)
- If internal relay is required, explicit allow-list rules for specific media server IPs/ports only
- Separate from WebRTC signaling servers, SFUs, and application infrastructure
Verification: From the TURN server, attempts to connect to internal services (SSH, HTTP, databases) should fail due to network-level restrictions.
2. Prevent relay to internal/local IP ranges
Why: TURN relay abuse lets attackers access internal networks, localhost services (127.0.0.1), AWS metadata services (169.254.169.254), RFC1918 ranges, and remote systems that trust the TURN server’s IP address. The goal is to ensure your TURN server cannot relay traffic to these destinations, whether through explicit deny-lists, route scoping, or other access control mechanisms.
When this applies: Most deployments. Exception: architectures that intentionally relay to internal SFUs. In those cases, use selective allow-listing for specific media server ranges instead of blanket denials.
IP ranges to block: See Table 1 below for a list of CIDR blocks that covers all entries in the IANA IPv4 and IPv6 Special-Purpose Address Registries. Where IANA lists sub-allocations within a larger block (e.g. individual /32 addresses within 192.0.0.0/24, or ranges like 2001:2::/48 within 2001::/23), the table uses the covering prefix. At minimum, block:
0.0.0.0/8- Current network (prevents the0.0.0.0loopback bypass from CVE-2020-26262)10.0.0.0/8,172.16.0.0/12,192.168.0.0/16- RFC1918 private networks127.0.0.0/8- Loopback/localhost169.254.0.0/16- Link-local (AWS metadata endpoint lives here!)100.64.0.0/10- Carrier-grade NAT (RFC6598)::/128,::1/128,fc00::/7,fe80::/10- IPv6 unspecified, loopback, unique local, link-local
Most TURN server implementations support access control lists that deny specific peer address ranges, though the mechanism varies. Some use declarative deny-lists in configuration files, while some Kubernetes-native implementations take a deny-by-default approach where only explicitly routed destinations are reachable. If your implementation uses deny-by-default, you may not need explicit IP blocking at all, but it’s worth verifying that internal ranges are not accidentally routable. Consult your implementation’s documentation for the exact mechanism.
Warning
Test your access control configuration in your environment before deploying to production. Verify that legitimate peer addresses (external public IPs) are not inadvertently blocked.3. Restrict relay destinations to known media servers only
Why: The most restrictive and effective control against relay abuse. Instead of blocking bad destinations, only allow known-good destinations. Prevents all unauthorized relay use, including to external third-party systems.
When this applies: Architectures where peer-to-peer media is not required and all media flows through central servers (SFUs, MCUs). Applying this control would prevent peer-to-peer WebRTC from working, since peers need to relay to arbitrary external addresses.
Implementation: Configure your TURN server to allow-list only your media server IP addresses and deny everything else. Zoom actually did exactly this to address C2 operation abuse: according to a Zoom spokesperson quoted by BleepingComputer, they disabled peer-to-peer connections and configured TURN to only relay to their own media servers.
4. Disable unnecessary protocol features
Why: Each protocol feature expands your attack surface. RFC5780 (NAT behavior discovery) and RFC3489 (obsolete STUN) are rarely needed for modern WebRTC and introduce additional complexity and potential vulnerabilities.
When this applies: Most WebRTC deployments. RFC5780 is primarily used for NAT type detection, which modern ICE implementations handle differently. RFC3489 is the obsolete STUN protocol superseded by RFC5389.
What to disable:
- RFC5780 NAT behavior discovery - Rarely needed for WebRTC
- RFC3489 legacy STUN - Superseded by RFC5389
- DTLS transport - If not using encrypted TURN connections
Each feature you disable is one less attack vector. Audit what your implementation supports and turn off what you don’t need.
5. Disable UDP listening (if TCP-only deployment)
Why: If the TURN server does not need to accept client connections over UDP, disabling UDP listening removes the primary vector for amplification and reflection attacks. This is about the client-to-server transport, not about what protocol the relay uses for media.
When this applies: Deployments where you can enforce TCP or TLS as the client-to-server transport. Since your application controls the ICE configuration handed to clients, you decide which transports are offered. If your network environment or security posture allows you to go TCP/TLS-only, disabling UDP listening is a straightforward win.
Heads up
Since WebRTC clients learn the TURN server transport from the ICE configuration provided by your application, disabling UDP listening won’t break clients as long as you only advertise TCP or TLS TURN URLs. The trade-off is added latency on the client-to-server connection due to TCP’s head-of-line blocking, though media relay to peers still uses UDP.6. Disable TCP relay (if UDP-only media)
Why: Reduces attack surface for relay abuse. TCP relay (RFC 6062) allows establishing raw TCP connections through the TURN server. If you only support UDP media (typical for WebRTC), TCP relay is unnecessary and should be disabled.
When this applies: Standard WebRTC deployments where media is sent over UDP. TCP relay is primarily used for relaying TCP-based protocols or as a fallback when UDP is blocked.
During bug bounty work, we’ve noticed that various service providers have disabled TCP relaying on their TURN servers since TCP relay is unnecessary for normal RTP media streams. This reduces exposure for further potential abuse.
Do note that some implementations only relay over UDP by design, so TCP relay is not something you’d need to explicitly disable. Check whether your implementation even offers TCP relay before worrying about this control.
7. Implement rate limiting
Why: Prevents resource exhaustion, log flooding, and abuse. Rate limiting protects against both direct DoS attacks and excessive legitimate usage that could degrade service.
When this applies: All production deployments.
Application-level rate limiting: The specific parameters available vary by implementation. Some offer granular controls across all of the following, while others may only support a subset:
- Maximum allocations per user
- Total allocation limits
- Bandwidth caps
- Allocation lifetime limits
See Table 3 below for starting points. Check which of these your implementation actually supports, and where application-level controls are limited, lean more heavily on network-level rate limiting.
Network-level rate limiting: Use OS-level firewall rules (iptables/nftables) or cloud provider security groups. The example below is Linux/IPv4 and intentionally conservative; tune values to your traffic profile.
# TCP connection attempts per source IP (TURN over TCP on 3478)
iptables -A INPUT -p tcp --dport 3478 \
-m conntrack --ctstate NEW \
-m recent --name turn_tcp_3478 --set
iptables -A INPUT -p tcp --dport 3478 \
-m conntrack --ctstate NEW \
-m recent --name turn_tcp_3478 \
--update --seconds 60 --hitcount 30 -j DROP
# UDP packet rate per source IP (TURN over UDP on 3478)
iptables -A INPUT -p udp --dport 3478 \
-m hashlimit --hashlimit-mode srcip \
--hashlimit-name turn_udp_3478 \
--hashlimit-upto 200/second \
--hashlimit-burst 400 -j ACCEPT
iptables -A INPUT -p udp --dport 3478 -j DROP
Apply TCP rate limiting to 5349 (TURN over TLS) as well. TLS handshakes are more expensive than plain TCP, so each connection costs more server resources. If 5349 carries most of your legitimate traffic, set thresholds high enough to handle your expected peak, but be aware that the per-connection cost makes TLS ports more attractive targets for resource exhaustion. UDP rate limiting on 5349 is only needed if you have DTLS enabled. Don’t forget IPv6 (ip6tables or nftables), and test thresholds carefully to avoid over-throttling large NATed networks (hotels, campuses, mobile carriers).
BCP38 source address validation: BCP38 is the internet-wide solution to reflection attacks, preventing networks from sending packets with spoofed source IPs. The catch is that it needs to be implemented at the attacker’s network to protect your server. Your own upstream implementing BCP38 only prevents your network from being used to send spoofed traffic, not from receiving it. Still worth advocating for, but not something you can unilaterally deploy to protect yourself.
DDoS mitigation services: For high-profile deployments, upstream DDoS scrubbing services can filter amplification traffic before it reaches your server. This is particularly relevant for large-scale public TURN deployments where UDP listening cannot be disabled.
8. Protect TURN credential APIs
Why: If the API that generates TURN credentials is unprotected, attackers can obtain valid credentials without authenticating to your application. This renders TURN’s own authentication mechanism useless, since anyone can get valid credentials on demand.
When this applies: All deployments where TURN credentials are generated dynamically via API, including when using a third-party TURN provider. Even if you don’t host the TURN server yourself, your application still has an endpoint that fetches or generates credentials, and that endpoint needs the same protection.
Implementation:
Protect the credential API endpoint with:
- User authentication (session tokens, OAuth, API keys)
- Authorization checks (only authenticated users get credentials)
- Rate limiting (prevent credential harvesting)
- IP-based restrictions (if applicable)
Example vulnerable pattern:
// VULNERABLE: No authentication
app.get('/api/turn-credentials', (req, res) => {
res.json({
username: generateUsername(),
credential: generateCredential(),
urls: ['turn:turn.example.com:3478']
});
});
Secure pattern:
// SECURE: Require authentication
app.get('/api/turn-credentials', requireAuth, (req, res) => {
// Only authenticated users get credentials
res.json({
username: generateUsername(req.user.id),
credential: generateCredential(req.user.id),
urls: ['turn:turn.example.com:3478']
});
});
Do keep in mind that this is not as effective for public conferencing systems where anyone can register or join anonymous meetings.
9. Keep server software updated
Why: TURN servers have had critical vulnerabilities including memory corruption, SQL injection, and access control bypasses. If there’s one thing we’d stress above all else, it’s keeping your TURN server patched.
When this applies: All deployments, always.
TURN implementations have had their share of serious vulnerabilities. coturn, for example, has had multiple memory safety issues, SQL injection (CVE-2018-4056, CVSS 9.8), and access control bypasses (CVE-2020-26262).
Subscribe to security mailing lists and watch the GitHub repositories for your TURN server implementation. Apply patches immediately when they’re released.
10. Monitor traffic patterns and security events
Why: Detect attacks in progress, identify misconfigurations, and maintain operational visibility. Monitoring helps you catch relay abuse, DoS attacks, and unusual behavior before they cause damage.
When this applies: All production deployments.
What to monitor:
Usage patterns:
- Allocation rate (allocations per minute/hour)
- Bandwidth consumption per user/total
- Connection duration distribution
- Peer address distribution (are users connecting to unexpected destinations?)
Security events:
- Access control violations (blocked peer addresses)
- Failed authentication attempts
- Rate limit triggers
- Protocol violations or malformed packets
System health:
- CPU and memory utilization
- Network bandwidth usage
- Error rates and server restarts
- Disk space (log files)
Alert on:
- Sustained high allocation rates (potential DoS)
- Repeated access control violations from same IP (potential attack)
- Unusual bandwidth spikes
- High error rates or authentication failures
Use SIEM systems or custom scripts to parse your TURN server logs and alert on suspicious patterns.
Quick reference tables
Table 1: IP ranges to block
IPv4
| Range | Type | RFC | Reason |
|---|---|---|---|
0.0.0.0/8 | Current network | RFC 1122 | Prevents 0.0.0.0 bypass to localhost |
10.0.0.0/8 | Private | RFC 1918 | Internal networks |
100.64.0.0/10 | Shared | RFC 6598 | Carrier-grade NAT |
127.0.0.0/8 | Loopback | RFC 1122 | Local services |
169.254.0.0/16 | Link-local | RFC 3927 | AWS metadata, APIPA |
172.16.0.0/12 | Private | RFC 1918 | Internal networks |
192.0.0.0/24 | IETF Protocol | RFC 6890 | Protocol assignments |
192.0.2.0/24 | Documentation | RFC 5737 | TEST-NET-1 |
192.31.196.0/24 | AS112-v4 | RFC 7535 | DNS infrastructure anycast |
192.52.193.0/24 | AMT | RFC 7450 | Multicast tunneling anycast |
192.88.99.0/24 | 6to4 relay | RFC 7526 | Deprecated |
192.168.0.0/16 | Private | RFC 1918 | Internal networks |
192.175.48.0/24 | AS112 | RFC 7534 | DNS infrastructure anycast |
198.18.0.0/15 | Benchmark | RFC 2544 | Testing |
198.51.100.0/24 | Documentation | RFC 5737 | TEST-NET-2 |
203.0.113.0/24 | Documentation | RFC 5737 | TEST-NET-3 |
224.0.0.0/4 | Multicast | RFC 5771 | Multicast addresses |
240.0.0.0/4 | Reserved | RFC 1112 | Future use (includes broadcast) |
IPv6
| Range | Type | RFC | Reason |
|---|---|---|---|
::/128 | Unspecified | RFC 4291 | Not a valid destination |
::1/128 | Loopback | RFC 4291 | IPv6 localhost |
::ffff:0:0/96 | Mapped | RFC 4291 | IPv4-mapped IPv6 |
64:ff9b::/96 | Translation | RFC 6052 | NAT64 well-known prefix |
64:ff9b:1::/48 | Translation | RFC 8215 | Local-use NAT64 |
100::/64 | Discard | RFC 6666 | Discard prefix |
100:0:0:1::/64 | Dummy prefix | RFC 9780 | Dummy IPv6 prefix (not routable) |
2001::/23 | IETF Protocol | RFC 2928 | Protocol assignments (includes Teredo) |
2001:db8::/32 | Documentation | RFC 3849 | IPv6 documentation range |
2002::/16 | 6to4 | RFC 3056 | Not routable on modern networks |
2620:4f:8000::/48 | AS112 | RFC 7534 | DNS infrastructure anycast |
3fff::/20 | Documentation | RFC 9637 | Documentation range |
5f00::/16 | SRv6 SID | RFC 9602 | Segment Routing infrastructure |
fc00::/7 | Unique local | RFC 4193 | IPv6 private |
fe80::/10 | Link-local | RFC 4291 | IPv6 link-local |
Source: IANA IPv4 Special-Purpose Address Registry and IANA IPv6 Special-Purpose Address Registry.
Table 2: Protocol features to disable
| Feature | RFC | When to Disable |
|---|---|---|
| RFC5780 NAT discovery | RFC 5780 | Most deployments |
| RFC3489 old STUN | RFC 3489 | All deployments |
| UDP listening | RFC 5766 | TCP-only architecture |
| TCP relay | RFC 6062 | UDP-only media |
| DTLS transport | RFC 7350 | TLS-only or unencrypted |
| Multicast peer relay | N/A | All deployments |
Heads up
Not all implementations support every feature listed here. If your TURN server doesn’t implement a feature, there’s nothing to disable. For the coturn-specific flags that correspond to each feature, see the coturn configuration guide.Table 3: Rate limiting starting points
The following are starting points, not universal recommendations. The only RFC-backed value here is the allocation lifetime: RFC 8656 Section 7.2 recommends a maximum of 3,600 seconds. The other values depend on your infrastructure capacity, expected user count, and traffic patterns. Tune them based on your own monitoring data.
| Resource | Starting Point | Notes |
|---|---|---|
| Allocations per user | Observe and tune | Start with your observed peak allocations per user, add roughly 30-50% headroom, and tune over time based on alerts and usage. |
| Total allocations | Scale with capacity | Depends on server resources and expected concurrent users. |
| Allocation lifetime | 3,600s (1 hour) | RFC 8656 recommended maximum. |
| Total bandwidth | Scale with NIC capacity | Depends on your server’s network interface and hosting plan. |
Not all implementations support every parameter listed here. Where application-level rate limiting is limited, network-level controls (iptables/nftables, cloud security groups) become more important. For coturn-specific parameters, see our coturn configuration guide.
Common deployment patterns
Pattern 1: Public platform with SFU
Use case: Video conferencing SaaS or public meeting platforms where all media flows through a central SFU. TURN credentials are dispensed to untrusted users.
Security model: Since all relay traffic should go to your SFU, you can allow-list those IPs and deny everything else. This is the most restrictive public-facing model.
Recommended approach:
- Allow-list only your SFU/media server IPs, deny everything else
- Block all internal ranges as a safety net (see Table 1)
- Aggressive rate limiting (allocations per user ~50)
- Network-level isolation (TURN server in DMZ)
Pattern 2: Public P2P platform
Use case: P2P communication apps, file sharing, or any public service where peers connect directly to each other through TURN. No central media server to allow-list.
Security model: You cannot restrict relay destinations to known IPs since peers can be anywhere on the public Internet. Security relies heavily on blocking internal ranges and rate limiting.
Recommended approach:
- Comprehensive denied-peer-ip rules blocking all internal ranges (see Table 1)
- Aggressive rate limiting at both network and application level
- Network-level isolation (TURN server in DMZ)
- Short allocation lifetimes
Pattern 3: Internal enterprise WebRTC
Use case: Internal corporate video systems, authenticated users only.
Security model: Can use authentication + access control. May need to allow relay to internal SFUs.
Recommended approach:
- Selective allow-listing for internal SFU ranges
- Still block localhost and cloud metadata ranges
- Credential API requires authentication
- Longer allocation lifetimes if needed
Conclusion
What we’ve found from testing TURN deployments is that no single control is sufficient on its own. Authentication doesn’t help when credentials are freely dispensed, access control rules can be bypassed if they’re not comprehensive, and software vulnerabilities require constant patching. That’s why the three-layer approach works:
- Isolate: Network-level separation from internal systems
- Restrict: Access control rules, protocol hardening, rate limiting
- Update: Aggressive patching and version management
In practice, what we see most often during pentests is unpatched servers with no IP restrictions at all. If this guide feels like a lot, start with the basics: block internal ranges, patch regularly, and monitor. You can iterate from there.
And remember: the best TURN server to secure is the one you don’t run. If you must run one, isolate, restrict, and update.
Note
Configuration is one thing, validation is another. We provide penetration testing and DoS testing for TURN deployments, and we’ve reported TURN vulnerabilities across major platforms. Get in touch.Further reading
Enable Security research
- TURN Security Threats: A Hacker’s View - Threat analysis and real-world attacks
- Securing coturn: Configuration Guide - coturn-specific configuration templates
- How we abused Slack’s TURN servers - $3,500 bug bounty writeup
- CVE-2020-26262: coturn access control bypass
RFCs
Stay updated
- RTCSec Newsletter - Monthly WebRTC and VoIP security news
- Enable Security Blog - Latest security research