feat: disable HTTP/3 in Caddy to free UDP 443 for TURN server and add patch script

This commit is contained in:
anonpenguin23 2026-02-21 18:30:28 +02:00
parent a79ae41dd5
commit 19463b8621
5 changed files with 55 additions and 3 deletions

View File

@ -378,7 +378,8 @@ func (ci *CaddyInstaller) generateCaddyfile(domain, email, acmeEndpoint, baseDom
}`, acmeEndpoint) }`, acmeEndpoint)
var sb strings.Builder 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) // 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)) sb.WriteString(fmt.Sprintf("\n*.%s {\n%s\n reverse_proxy localhost:6001\n}\n", domain, tlsBlock))

View File

@ -173,6 +173,8 @@ func setReflectValue(field reflect.Value, raw any) error {
field.SetBool(v) field.SetBool(v)
case int64: case int64:
field.SetBool(v != 0) field.SetBool(v != 0)
case float64:
field.SetBool(v != 0)
case []byte: case []byte:
s := string(v) s := string(v)
field.SetBool(s == "1" || strings.EqualFold(s, "true")) field.SetBool(s == "1" || strings.EqualFold(s, "true"))

View File

@ -11,7 +11,7 @@ type Config struct {
ListenAddr string `yaml:"listen_addr"` ListenAddr string `yaml:"listen_addr"`
// TLSListenAddr is the address for TURN over TLS/DTLS (e.g., "0.0.0.0:443") // 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"` TLSListenAddr string `yaml:"tls_listen_addr"`
// PublicIP is the public IP address of this node, advertised in TURN allocations // PublicIP is the public IP address of this node, advertised in TURN allocations

View File

@ -59,7 +59,7 @@ func NewServer(cfg *Config, logger *zap.Logger) (*Server, error) {
} }
// Create TLS UDP listener (port 443) if configured // 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 != "" { if cfg.TLSListenAddr != "" {
tlsConn, err := net.ListenPacket("udp4", cfg.TLSListenAddr) tlsConn, err := net.ListenPacket("udp4", cfg.TLSListenAddr)
if err != nil { if err != nil {

View File

@ -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