From b88828f92e0358c49c5ef8f89a690a0cf5992099 Mon Sep 17 00:00:00 2001 From: ahmzaa Date: Sat, 25 Jul 2026 05:01:49 +0100 Subject: [PATCH 1/2] Use dynamic cloudflare trusted_proxies IP source caddy-cf now includes WeidiDeng/caddy-cloudflare-ip, so replace the hardcoded 22-range static list with 'trusted_proxies cloudflare' which auto-fetches and refreshes Cloudflare's IPv4/IPv6 ranges (interval 12h, timeout 15s). No static list to keep in sync when Cloudflare updates. Kept client_ip_headers Cf-Connecting-Ip X-Forwarded-For (prefer CF's authoritative end-user IP, fall back to XFF) and documented why. Validated + fmt-clean and tested end-to-end against the updated caddy-cf image: starts cleanly, serves HTTP 200 with gzip + security headers. --- Caddyfile | 39 ++++++++++++--------------------------- 1 file changed, 12 insertions(+), 27 deletions(-) diff --git a/Caddyfile b/Caddyfile index b3d2a17..c252fbf 100644 --- a/Caddyfile +++ b/Caddyfile @@ -15,34 +15,19 @@ # X-Forwarded-For) are honoured only when the request actually comes from # Cloudflare. This prevents header spoofing from any other source. # - # Ranges from https://www.cloudflare.com/ips-v4/ and /ips-v6/ . - # Keep in sync when Cloudflare updates them (rarely). If you rebuild - # caddy-cf with the caddy-dynamic-cloudflare / caddy-cloudflare-ip plugin, - # this static list can be replaced with `trusted_proxies cloudflare`. + # The `cloudflare` IP source (WeidiDeng/caddy-cloudflare-ip, baked into the + # caddy-cf image) auto-fetches the ranges from cloudflare.com/ips-v4 and + # /ips-v6 and refreshes them periodically, so there's no static list to + # keep in sync. servers { - trusted_proxies static \ - 173.245.48.0/20 \ - 103.21.244.0/22 \ - 103.22.200.0/22 \ - 103.31.4.0/22 \ - 141.101.64.0/18 \ - 108.162.192.0/18 \ - 190.93.240.0/20 \ - 188.114.96.0/20 \ - 197.234.240.0/22 \ - 198.41.128.0/17 \ - 162.158.0.0/15 \ - 104.16.0.0/13 \ - 104.24.0.0/14 \ - 172.64.0.0/13 \ - 131.0.72.0/22 \ - 2400:cb00::/32 \ - 2606:4700::/32 \ - 2803:f800::/32 \ - 2405:b500::/32 \ - 2405:8100::/32 \ - 2a06:98c0::/29 \ - 2c0f:f248::/32 + trusted_proxies cloudflare { + interval 12h + timeout 15s + } + # Read the real visitor IP from these headers (only honoured for + # requests from trusted_proxies above). Cf-Connecting-Ip is + # Cloudflare's single authoritative end-user IP; X-Forwarded-For is + # the fallback if a request ever arrives without the CF header. client_ip_headers Cf-Connecting-Ip X-Forwarded-For } } -- 2.47.3 From 2c6f20fbc3fa5a4094075422e9c002fd936648c4 Mon Sep 17 00:00:00 2001 From: ahmzaa Date: Sat, 25 Jul 2026 05:03:12 +0100 Subject: [PATCH 2/2] docs: show dynamic cloudflare trusted_proxies as primary example caddy-cf now bundles WeidiDeng/caddy-cloudflare-ip, so document 'trusted_proxies cloudflare { interval 12h; timeout 15s }' as the primary (auto-refreshing) approach, with the static-list method noted as the fallback for builds without the plugin. Also explains client_ip_headers (Cf-Connecting-Ip preferred, X-Forwarded-For fallback). --- docs/caddy-reverse-proxy.md | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/docs/caddy-reverse-proxy.md b/docs/caddy-reverse-proxy.md index da7fe97..9a86a7b 100644 --- a/docs/caddy-reverse-proxy.md +++ b/docs/caddy-reverse-proxy.md @@ -99,14 +99,31 @@ committed [`Caddyfile`](../Caddyfile) at the repo root; copy it to the i.e. a **blank page**. - **`encode zstd gzip`** — compression happens here (SWS has it disabled). - **`header { ... }`** — security headers (SWS has them disabled). -- **`trusted_proxies static `** + **`client_ip_headers +- **`trusted_proxies cloudflare { ... }`** + **`client_ip_headers Cf-Connecting-Ip X-Forwarded-For`** — so the real visitor IP is used for logging/matchers, but only when the request genuinely comes from Cloudflare - (prevents header spoofing from any other source). The ranges come from - and ; - keep them in sync when Cloudflare updates them. If `caddy-cf` is rebuilt with - the `caddy-cloudflare-ip` plugin, the static list can be replaced with - `trusted_proxies cloudflare`. + (prevents header spoofing from any other source). The `cloudflare` IP source + ([WeidiDeng/caddy-cloudflare-ip](https://github.com/WeidiDeng/caddy-cloudflare-ip), + baked into the `caddy-cf` image) auto-fetches the ranges from + and + and refreshes them on the configured `interval`, so there is no static list to + maintain: + + ```caddy + trusted_proxies cloudflare { + interval 12h + timeout 15s + } + ``` + + `client_ip_headers` lists which header holds the real visitor IP: + `Cf-Connecting-Ip` is Cloudflare's single authoritative end-user IP, with + `X-Forwarded-For` as the fallback. It is only trusted for requests coming from + the `trusted_proxies` above. + + > If you ever run without the `caddy-cloudflare-ip` plugin, you can instead + > pin the static ranges with `trusted_proxies static ` copied + > from the Cloudflare IP pages, but then you must keep them in sync manually. Deploy and reload: -- 2.47.3