Skip to main content
Sandro Gauci

Sandro Gauci, Enable Security

TURN Server Security Best Practices

Published on Feb 25, 2026 in , ,

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.

TURN server security checklist

Before deploying TURN servers to production, verify each of these security controls:

Access control & isolation

Protocol hardening

Operations & maintenance

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 the 0.0.0.0 loopback bypass from CVE-2020-26262)
  • 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 - RFC1918 private networks
  • 127.0.0.0/8 - Loopback/localhost
  • 169.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.

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.

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

RangeTypeRFCReason
0.0.0.0/8Current networkRFC 1122Prevents 0.0.0.0 bypass to localhost
10.0.0.0/8PrivateRFC 1918Internal networks
100.64.0.0/10SharedRFC 6598Carrier-grade NAT
127.0.0.0/8LoopbackRFC 1122Local services
169.254.0.0/16Link-localRFC 3927AWS metadata, APIPA
172.16.0.0/12PrivateRFC 1918Internal networks
192.0.0.0/24IETF ProtocolRFC 6890Protocol assignments
192.0.2.0/24DocumentationRFC 5737TEST-NET-1
192.31.196.0/24AS112-v4RFC 7535DNS infrastructure anycast
192.52.193.0/24AMTRFC 7450Multicast tunneling anycast
192.88.99.0/246to4 relayRFC 7526Deprecated
192.168.0.0/16PrivateRFC 1918Internal networks
192.175.48.0/24AS112RFC 7534DNS infrastructure anycast
198.18.0.0/15BenchmarkRFC 2544Testing
198.51.100.0/24DocumentationRFC 5737TEST-NET-2
203.0.113.0/24DocumentationRFC 5737TEST-NET-3
224.0.0.0/4MulticastRFC 5771Multicast addresses
240.0.0.0/4ReservedRFC 1112Future use (includes broadcast)

IPv6

RangeTypeRFCReason
::/128UnspecifiedRFC 4291Not a valid destination
::1/128LoopbackRFC 4291IPv6 localhost
::ffff:0:0/96MappedRFC 4291IPv4-mapped IPv6
64:ff9b::/96TranslationRFC 6052NAT64 well-known prefix
64:ff9b:1::/48TranslationRFC 8215Local-use NAT64
100::/64DiscardRFC 6666Discard prefix
100:0:0:1::/64Dummy prefixRFC 9780Dummy IPv6 prefix (not routable)
2001::/23IETF ProtocolRFC 2928Protocol assignments (includes Teredo)
2001:db8::/32DocumentationRFC 3849IPv6 documentation range
2002::/166to4RFC 3056Not routable on modern networks
2620:4f:8000::/48AS112RFC 7534DNS infrastructure anycast
3fff::/20DocumentationRFC 9637Documentation range
5f00::/16SRv6 SIDRFC 9602Segment Routing infrastructure
fc00::/7Unique localRFC 4193IPv6 private
fe80::/10Link-localRFC 4291IPv6 link-local

Source: IANA IPv4 Special-Purpose Address Registry and IANA IPv6 Special-Purpose Address Registry.

Table 2: Protocol features to disable

FeatureRFCWhen to Disable
RFC5780 NAT discoveryRFC 5780Most deployments
RFC3489 old STUNRFC 3489All deployments
UDP listeningRFC 5766TCP-only architecture
TCP relayRFC 6062UDP-only media
DTLS transportRFC 7350TLS-only or unencrypted
Multicast peer relayN/AAll deployments

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.

ResourceStarting PointNotes
Allocations per userObserve and tuneStart with your observed peak allocations per user, add roughly 30-50% headroom, and tune over time based on alerts and usage.
Total allocationsScale with capacityDepends on server resources and expected concurrent users.
Allocation lifetime3,600s (1 hour)RFC 8656 recommended maximum.
Total bandwidthScale with NIC capacityDepends 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.

Further reading

Enable Security research

RFCs

Stay updated

Subscribe to Updates

Stay updated with our latest security insights and updates.

We hate spam and are committed to protecting and respecting your privacy. You can unsubscribe from our communications at any time. By subscribing, you are agreeing to the Privacy Policy.

Sandro Gauci

Sandro Gauci

CEO, Chief Mischief Officer at Enable Security

Sandro Gauci leads the operations and research at Enable Security. He is the original developer of SIPVicious OSS, the SIP security testing toolset. His role is to focus on the vision of the company, design offensive security tools and engage in security research and testing. Therefore, he is the proud owner of the title of Chief Mischief Officer at Enable Security.

He offers public office hours and is reachable here.