From d6f1f24e1b9166716b0db824010e61df044f9c4c Mon Sep 17 00:00:00 2001 From: TinyServal Date: Sat, 30 Aug 2025 04:54:03 +1000 Subject: [PATCH] docs: document client IP headers and interop with cloudflare (#1034) --- docs/docs/admin/caveats-xff.mdx | 25 ++++++++++++++++++++ docs/docs/admin/environments/cloudflare.mdx | 26 +++++++++++++++++++++ 2 files changed, 51 insertions(+) create mode 100644 docs/docs/admin/caveats-xff.mdx create mode 100644 docs/docs/admin/environments/cloudflare.mdx diff --git a/docs/docs/admin/caveats-xff.mdx b/docs/docs/admin/caveats-xff.mdx new file mode 100644 index 0000000..655534f --- /dev/null +++ b/docs/docs/admin/caveats-xff.mdx @@ -0,0 +1,25 @@ +# Client IP Headers + +Currently Anubis will always flatten the `X-Forwarded-For` when it contains multiple IP addresses. From right to left, the first IP address that is not in one of the following categories will be set as `X-Forwarded-For` in the request passed to the upstream. + +- Private (`XFF_STRIP_PRIVATE`, enabled by default) +- CGNAT (always stripped) +- Link-local Unicast (always stripped) + +``` +Incoming: X-Forwarded-For: 1.2.3.4, 5.6.7.8, 10.0.0.1 +Upstream: X-Forwarded-For: 5.6.7.8 +``` + +This behavior will cause problems if the proxy in front of Anubis is from a public IP, such as Cloudflare, because Anubis will use the Cloudflare IP instead of your client's real IP. You will likely see all requests from your browser being blocked and/or an infinite challenge loop. + +``` +Incoming: X-Forwarded-For: REAL_CLIENT_IP, CF_IP +Upstream: X-Forwarded-For: CF_IP +``` + +As a workaround, you should configure your web server to parse an alternative source (such as `CF-Connecting-IP`), or pre-process the incoming `X-Forwarded-For` with your web server to ensure it only contains the real client IP address, then pass it to Anubis as `X-Forwarded-For`. + +The `X-Real-IP` header will be automatically inferred from `X-Forwarded-For` if not set, setting it explicitly is not necessary as long as `X-Forwarded-For` contains only the real client IP. However setting it explicitly can eliminate spoofed values if your web server doesn't set this. + +See [Cloudflare](environments/cloudflare.mdx) for an example configuration. diff --git a/docs/docs/admin/environments/cloudflare.mdx b/docs/docs/admin/environments/cloudflare.mdx new file mode 100644 index 0000000..c84b67e --- /dev/null +++ b/docs/docs/admin/environments/cloudflare.mdx @@ -0,0 +1,26 @@ +# Cloudflare + +If you are using Cloudflare, you should configure your server to use `CF-Connecting-IP` as the source of the real client IP, and pass that address to Anubis as `X-Forwarded-For`. Read [Client IP Headers](../caveats-xff.mdx) for details. + +Example configuration with Caddy: + +```Caddyfile +{ + servers { + # Cloudflare IP ranges from https://www.cloudflare.com/en-gb/ips/ + 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 + # Use CF-Connecting-IP to determine the client IP instead of XFF + # https://caddyserver.com/docs/caddyfile/options#client-ip-headers + client_ip_headers CF-Connecting-IP + } +} + +example.com { + reverse_proxy http://anubis:3000 { + # Pass the client IP read from CF-Connecting-IP + header_up X-Forwarded-For {client_ip} + header_up X-Real-IP {client_ip} + header_up X-Http-Version {http.request.proto} + } +} +```