From 19463b86210f5c544fe01150f155cf3a7ba55d5d Mon Sep 17 00:00:00 2001 From: anonpenguin23 Date: Sat, 21 Feb 2026 18:30:28 +0200 Subject: [PATCH] feat: disable HTTP/3 in Caddy to free UDP 443 for TURN server and add patch script --- .../production/installers/caddy.go | 3 +- pkg/rqlite/scanner.go | 2 + pkg/turn/config.go | 2 +- pkg/turn/server.go | 2 +- scripts/patches/disable-caddy-http3.sh | 49 +++++++++++++++++++ 5 files changed, 55 insertions(+), 3 deletions(-) create mode 100755 scripts/patches/disable-caddy-http3.sh diff --git a/pkg/environments/production/installers/caddy.go b/pkg/environments/production/installers/caddy.go index 88eb7f2..449653b 100644 --- a/pkg/environments/production/installers/caddy.go +++ b/pkg/environments/production/installers/caddy.go @@ -378,7 +378,8 @@ func (ci *CaddyInstaller) generateCaddyfile(domain, email, acmeEndpoint, baseDom }`, acmeEndpoint) var sb strings.Builder - sb.WriteString(fmt.Sprintf("{\n email %s\n}\n", email)) + // Disable HTTP/3 (QUIC) so Caddy doesn't bind UDP 443, which TURN needs for relay + sb.WriteString(fmt.Sprintf("{\n email %s\n servers {\n protocols h1 h2\n }\n}\n", email)) // Node domain blocks (e.g., node1.dbrs.space, *.node1.dbrs.space) sb.WriteString(fmt.Sprintf("\n*.%s {\n%s\n reverse_proxy localhost:6001\n}\n", domain, tlsBlock)) diff --git a/pkg/rqlite/scanner.go b/pkg/rqlite/scanner.go index fe8c8e1..3581be3 100644 --- a/pkg/rqlite/scanner.go +++ b/pkg/rqlite/scanner.go @@ -173,6 +173,8 @@ func setReflectValue(field reflect.Value, raw any) error { field.SetBool(v) case int64: field.SetBool(v != 0) + case float64: + field.SetBool(v != 0) case []byte: s := string(v) field.SetBool(s == "1" || strings.EqualFold(s, "true")) diff --git a/pkg/turn/config.go b/pkg/turn/config.go index f12b6ac..61bd809 100644 --- a/pkg/turn/config.go +++ b/pkg/turn/config.go @@ -11,7 +11,7 @@ type Config struct { ListenAddr string `yaml:"listen_addr"` // TLSListenAddr is the address for TURN over TLS/DTLS (e.g., "0.0.0.0:443") - // Uses UDP 443 which does not conflict with Caddy's TCP 443 + // Uses UDP 443 — requires Caddy HTTP/3 (QUIC) to be disabled to avoid port conflict TLSListenAddr string `yaml:"tls_listen_addr"` // PublicIP is the public IP address of this node, advertised in TURN allocations diff --git a/pkg/turn/server.go b/pkg/turn/server.go index 1072f28..077e5da 100644 --- a/pkg/turn/server.go +++ b/pkg/turn/server.go @@ -59,7 +59,7 @@ func NewServer(cfg *Config, logger *zap.Logger) (*Server, error) { } // Create TLS UDP listener (port 443) if configured - // UDP 443 does not conflict with Caddy's TCP 443 + // Requires Caddy HTTP/3 (QUIC) to be disabled to avoid UDP 443 conflict if cfg.TLSListenAddr != "" { tlsConn, err := net.ListenPacket("udp4", cfg.TLSListenAddr) if err != nil { diff --git a/scripts/patches/disable-caddy-http3.sh b/scripts/patches/disable-caddy-http3.sh new file mode 100755 index 0000000..12cc308 --- /dev/null +++ b/scripts/patches/disable-caddy-http3.sh @@ -0,0 +1,49 @@ +#!/usr/bin/env bash +# Patch: Disable HTTP/3 (QUIC) in Caddy to free UDP 443 for TURN server. +# Run on each VPS node. Safe to run multiple times (idempotent). +# +# Usage: sudo bash disable-caddy-http3.sh +set -euo pipefail + +CADDYFILE="/etc/caddy/Caddyfile" + +if [ ! -f "$CADDYFILE" ]; then + echo "ERROR: $CADDYFILE not found" + exit 1 +fi + +# Check if already patched +if grep -q 'protocols h1 h2' "$CADDYFILE"; then + echo "Already patched — Caddyfile already has 'protocols h1 h2'" +else + # The global block looks like: + # { + # email admin@... + # } + # + # Insert 'servers { protocols h1 h2 }' after the email line. + sed -i '/^ email /a\ + servers {\ + protocols h1 h2\ + }' "$CADDYFILE" + echo "Patched Caddyfile — added 'servers { protocols h1 h2 }'" +fi + +# Validate the new config before reloading +if ! caddy validate --config "$CADDYFILE" --adapter caddyfile 2>/dev/null; then + echo "ERROR: Caddyfile validation failed! Reverting..." + sed -i '/^ servers {$/,/^ }$/d' "$CADDYFILE" + exit 1 +fi + +# Reload Caddy (graceful, no downtime) +systemctl reload caddy +echo "Caddy reloaded successfully" + +# Verify UDP 443 is no longer bound by Caddy +sleep 1 +if ss -ulnp | grep -q ':443.*caddy'; then + echo "WARNING: Caddy still binding UDP 443 — reload may need more time" +else + echo "Confirmed: UDP 443 is free for TURN" +fi