Cloudflare's tunnel edge-pool assignment can blackhole the site for whole regions (2026-10-10: tunnel hostnames served from an unreachable anycast range for hours). This adds an independent path and the automation that keeps occupymedia.cc reachable when either path is sick: - nginx edge mirroring the tunnel ingress (app/api/tube/chat/ping), LE wildcard via dns-01, twice-daily renewal - DOCKER-USER firewall: 80/443 restricted to Cloudflare ranges (CF mode) or OPEN for grey-cloud mode via firewall.mode - edge-watcher (60s systemd timer): dynamic public-IP sync, dual-path health checks, DNS failover TUNNEL<->ORIGIN/GREY with hysteresis, gated by EDGE_ENABLED - ping.occupymedia.cc sacrificial probe host for activation - deployment runbook in README.md; credential files shipped as .example
40 lines
1.4 KiB
Bash
Executable file
40 lines
1.4 KiB
Bash
Executable file
#!/bin/bash
|
|
# edge-firewall.sh — restrict the edge ports to Cloudflare's ranges only.
|
|
# Mode file ./firewall.mode: "CF" (default, CF ranges only) or "OPEN" (anyone —
|
|
# grey mode: visitors connect directly, nginx rejects unknown SNI).
|
|
# Idempotent; safe to re-run (rebuilds the DOCKER-USER rules from scratch).
|
|
set -euo pipefail
|
|
cd "$(dirname "$0")"
|
|
|
|
MODE="CF"
|
|
[[ -f firewall.mode ]] && MODE=$(cat firewall.mode)
|
|
CF4_URL="https://www.cloudflare.com/ips-v4"
|
|
CF6_URL="https://www.cloudflare.com/ips-v6"
|
|
|
|
# Reset our rules, keep anything else in DOCKER-USER.
|
|
iptables -F DOCKER-USER
|
|
ip6tables -F DOCKER-USER 2>/dev/null || true
|
|
|
|
if [[ $MODE == OPEN ]]; then
|
|
echo "edge firewall: OPEN (any source allowed on 80/443; nginx SNI gate applies)"
|
|
exit 0
|
|
fi
|
|
|
|
mapfile -t CF4 < <(curl -s -m 15 "$CF4_URL" | grep -v '^$')
|
|
mapfile -t CF6 < <(curl -s -m 15 "$CF6_URL" | grep -v '^$')
|
|
|
|
((${#CF4[@]} > 5)) || { echo "cf ips-v4 fetch failed" >&2; exit 1; }
|
|
|
|
for net in "${CF4[@]}"; do
|
|
iptables -A DOCKER-USER -p tcp -m multiport --dports 80,443 -s "$net" -j RETURN
|
|
done
|
|
iptables -A DOCKER-USER -p tcp -m multiport --dports 80,443 -j DROP
|
|
|
|
if ((${#CF6[@]} > 0)); then
|
|
for net in "${CF6[@]}"; do
|
|
ip6tables -A DOCKER-USER -p tcp -m multiport --dports 80,443 -s "$net" -j RETURN 2>/dev/null || true
|
|
done
|
|
ip6tables -A DOCKER-USER -p tcp -m multiport --dports 80,443 -j DROP 2>/dev/null || true
|
|
fi
|
|
|
|
echo "edge firewall: ${#CF4[@]} v4 + ${#CF6[@]} v6 CF ranges allowed on 80/443"
|