From 0d7c82cf5f0eb7ace1e302389182cee5d390e5e0 Mon Sep 17 00:00:00 2001 From: stratself Date: Thu, 21 May 2026 07:23:46 +0000 Subject: [PATCH] docs(turn): Add proxy protocol example for TURNS SNI routing --- docs/calls/turn.mdx | 82 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 76 insertions(+), 6 deletions(-) diff --git a/docs/calls/turn.mdx b/docs/calls/turn.mdx index 887327622..f9e5e65f5 100644 --- a/docs/calls/turn.mdx +++ b/docs/calls/turn.mdx @@ -224,16 +224,20 @@ If you instead prefer to use [eturnal][eturnal], you can refer to the guides bel In very restrictive networks where UDP traffic and non-standard ports are disallowed, normal TURN servers are not reachable. To establish connectivity in these scenarios, a common solution is to host a TURN-over-TLS server on port 443, and allow clients to connect to it like any other web traffic. -However, port 443 is usually utilized by other HTTPS services. Therefore, one would need to **multiplex** both the TURN and the HTTPS services, and filter packets to them via **SNI routing**. A layer-4 load balancer, such as [caddy-l4][caddy-l4], can serve this function. +However, port 443 is usually utilized by other HTTPS services. Therefore, one would need to **multiplex** both the TURN and the HTTPS services, and filter packets to them via **SNI routing**. A layer-4 load balancer such as caddy-l4 can serve this function. -Below is an example of using Caddy-l4 on the host to: +Below are Caddyfile examples to multiplex both the TURNS service and LiveKit on port 443. It requires the [caddy-l4][caddy-l4] plugin to be compiled with your Caddy binary. + +
+ +Caddyfile with TLS passthrough + +This Caddyfile: - Route `turn.example.com` to the TURNS port for Coturn without TLS termination, and - Route `livekit.example.com` to the [LiveKit services](./livekit.mdx) with TLS termination by Caddy -
- -Caddyfile +Please note that all traffic from Coturn's perspective will be coming from caddy-l4's IP now. ``` { @@ -270,7 +274,73 @@ https://livekit.example.com {
-You can now advertise `turns:turn.example.com:443?transport=tcp` as an address in your `turn_uris` as well as LiveKit. Please note that all traffic from Coturn's perspective will be coming from caddy-l4's IP now. +
+ +Caddyfile with TLS termination and PROXY protocol forwarding + +This setup: + +- Terminates TLS for `turn.example.com`, +- Tag the decrypted packets with PROXY protocol, and route it to coturn's `tcp-proxy-port` +- Route `livekit.example.com` to the [LiveKit services](./livekit.mdx) with TLS termination by Caddy + +It allows coturn to see real client IPs, but the TLS handling is done on Caddy's side. + +First, enable coturn's PROXY-protocol accepting port by adding this: + +```ini +# in coturn.conf +tcp-proxy-port=5555 +``` + +Then, in the Caddyfile: + +``` +{ + servers { + listener_wrappers { + # intercept packets meant for the TURN domain first + # before forwarding other packets to "normal" HTTP listeners + layer4 { + @turn { + tls { + sni turn.example.com + } + } + route @turn { + tls # terminate TLS for the turn.example.com packets + proxy { + # then, proxy them to tcp-proxy-port and enable PROXY protocol version 2 + upstream 127.0.0.1:5555 + proxy_protocol v2 + } + + } + } + tls + } + } +} + +# livekit stuff +https://livekit.example.com { + @lk-jwt-service path /healthz /get_token /sfu/get + route @lk-jwt-service { + reverse_proxy 127.0.0.1:8081 + } + reverse_proxy http://127.0.0.1:7880 +} + + +# placeholder server block to obtain certs for turn.example.com +https://turn.example.com { + respond "OK" 200 +} +``` + +
+ +After configuration and spin-up, the destination `turns:turn.example.com:443?transport=tcp` should work with Trickle ICE tests. You can now advertise it as an address in your `turn_uris` as well as LiveKit. [caddy-l4]: https://github.com/mholt/caddy-l4