By nature, a TURN server accepts packets from the internet and forwards them to other addresses. Therefore, an improperly secured TURN server can become a target for two threats: unauthorized bandwidth consumption by third-party applications and SSRF attacks against internal infrastructure. In Slyber Turn Server, both issues are resolved at the architectural level.
1. Temporary Cryptographic Credentials
Slyber Turn Server does not store a user database on disk and does not require database queries on every connection. It uses the industry-standard WebRTC ephemeral token scheme:
- Username (
username): consists of the token expiration time (Unix timestamp in seconds) and the user identifier, separated by a colon:<expiration_timestamp>:<user_id>(for example,1761580000:user_777). - Password (
password): calculated using the formulaBase64(HMAC-SHA1(TURN_SECRET, username)).
When a client connects to the TURN server:
- The server validates the
usernameformat and verifies that the current time has not exceededexpiration_timestamp. - It independently computes the
HMAC-SHA1of theusernameusing its ownTURN_SECRETand verifies the packet signature. - As soon as the
TTLexpires, the credentials automatically become invalid.
2. Defense-in-Depth for the HTTP API (/api/turn-credentials)
You can flexibly combine 4 layers of protection for the credential issuance endpoint:
Layer A: Secret Key (X-Turn-Secret / Bearer)
A request can include the X-Turn-Secret: <your_TURN_SECRET> or Authorization: Bearer <your_TURN_SECRET> header.
- Key verification is performed in constant time via
subtle.ConstantTimeCompare, completely eliminating timing attacks. - If
REQUIRE_SECRET=trueis enabled, requests without this header are immediately rejected with a401 Unauthorizedstatus code. - Providing a valid secret key grants privileges: it bypasses Rate Limiter quotas, CORS/IP filters, and allows requesting a custom
?ttl=that exceeds the defaultCREDENTIAL_TTL_SEC.
Layer B: IP and Subnet Allowlist
If ALLOWED_IPS is configured (for example, 198.51.100.25, 10.20.0.0/16), requests without a secret key are permitted only from the specified IPv4/IPv6 addresses or CIDR subnets (all others receive 403 Forbidden).
Layer C: Smart CORS Validator
If a request comes directly from a browser (without a secret key and without a strict ALLOWED_IPS restriction), the server validates the Origin header:
- Exact domain and scheme matching is supported (for example,
https://exmaple.com). - Automatic subdomain support: if
https://exmaple.comis specified inALLOWED_ORIGINS, the validator will automatically allow requests from any subdomain using the same scheme, such ashttps://rtc.example.comorhttps://app.example.com.
Layer D: Flood Protection
For all requests without a secret key, a built-in per-IP rate limiter based on the Token Bucket algorithm is enforced:
- Refill rate:
2.0requests per second per IP. - Maximum burst: up to
10consecutive requests. Exceeding this limit returns429 Too Many Requests. - DDoS memory protection: the table stores a maximum of
50,000unique IP addresses and automatically purges entries older than 2 minutes every 2 minutes.
Safe Operation Behind a Reverse Proxy (Nginx / Caddy)
The server is protected against X-Forwarded-For and X-Real-IP header spoofing: it trusts these headers only when the physical TCP connection originates from a local interface (127.0.0.1 / ::1, i.e., from your local Nginx instance) or when the request is authenticated with a valid X-Turn-Secret.
3. Built-in SSRF Attack Protection
In the TURN protocol, the client specifies which IP address (Peer IP) the server should forward a packet to. An attacker might attempt to specify the internal address of your database (10.0.0.42), a local server port (127.0.0.1), or a cloud metadata service like AWS/GCP (169.254.169.254) instead of a peer's address.
Slyber Turn Server includes a built-in PeerFilter that inspects every permission request (PermissionHandler) and separates blocked addresses into two categories:
Category 1: Critical SSRF Threats
Attempts to reach these addresses are strictly blocked, increment the turn_ssrf_blocked_total attack counter, are logged to the security audit log, and add the client's IP to the offender list (top_offenders) with a 5x penalty weight:
- Loopback addresses:
127.0.0.0/8,::1. - System "This Network" range:
0.0.0.0/8(a common vector for bypassing127.0.0.1filters). - Link-Local and Cloud Metadata (AWS / GCP / DigitalOcean / Azure):
169.254.0.0/16(including169.254.169.254), IPv6 AWS IMDSfd00:ec2::254/128,fe80::/10. - Broadcast, multicast, and unspecified addresses:
255.255.255.255,0.0.0.0, Multicast. - Local network interfaces of the TURN host itself: on startup, the server scans all of its network interfaces (
net.InterfaceAddrs()) and prohibits connections to its own internal IPs.
Category 2: Browser Local ICE Candidates
When establishing a WebRTC connection, browsers often mistakenly attempt to probe a peer's local home addresses (such as 192.168.1.1) through the TURN server. This is not a malicious attack, but standard WebRTC ICE behavior. To avoid cluttering the security log with false alarms, PeerFilter drops these packets silently and increments a separate lan_skipped counter instead:
- RFC 1918 private networks and IPv6 ULA (
10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,fc00::/7). - Carrier-grade NAT / Tailscale networks (CGNAT
100.64.0.0/10). - Documentation, benchmarking, and reserved subnets (
192.0.0.0/24,192.0.2.0/24,198.18.0.0/15,198.51.100.0/24,203.0.113.0/24,240.0.0.0/4,2001:db8::/32,2001::/32,2002::/16,64:ff9b::/96).
TURN Hairpinning Support
At the same time, the filter explicitly allows forwarding packets to the server's own public address (PUBLIC_IP). This is required for TURN Hairpinning scenarios - when both call participants are behind strict NATs and both are connected to the same TURN server, forwarding media streams between two relay ports on that server.