From e935c897c64d28d22bb6f02c064558616f842218 Mon Sep 17 00:00:00 2001 From: jack Date: Sun, 22 Mar 2026 04:02:06 +0700 Subject: [PATCH] =?UTF-8?q?feat:=20Cloudflare=20integration=20=E2=80=94=20?= =?UTF-8?q?real=20IP=20forwarding=20+=20firewall=20lockdown?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Traefik traefik.yml.j2: - Add forwardedHeaders.trustedIPs with all Cloudflare CIDR ranges on both web and websecure entrypoints so rate limiting and CrowdSec see real visitor IPs, not Cloudflare proxy IPs firewall.yml: - Replace open HTTP/HTTPS rules with per-CIDR allow rules scoped to Cloudflare IP ranges only - Direct access to ports 80/443 bypassing Cloudflare is now blocked Co-Authored-By: Claude Sonnet 4.6 --- roles/base/tasks/firewall.yml | 42 ++++++++++++++-- .../services/templates/traefik/traefik.yml.j2 | 49 +++++++++++++++++++ 2 files changed, 87 insertions(+), 4 deletions(-) diff --git a/roles/base/tasks/firewall.yml b/roles/base/tasks/firewall.yml index 290d338..6532b9b 100644 --- a/roles/base/tasks/firewall.yml +++ b/roles/base/tasks/firewall.yml @@ -13,19 +13,53 @@ proto: tcp comment: "Forgejo SSH" -- name: Allow HTTP +- name: Allow HTTP from Cloudflare IPs only community.general.ufw: rule: allow port: "80" proto: tcp - comment: "HTTP (ACME challenge)" + src: "{{ item }}" + comment: "HTTP via Cloudflare" + loop: + - "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" -- name: Allow HTTPS +- name: Allow HTTPS from Cloudflare IPs only community.general.ufw: rule: allow port: "443" proto: tcp - comment: "HTTPS" + src: "{{ item }}" + comment: "HTTPS via Cloudflare" + loop: + - "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" - name: Allow Syncthing sync TCP community.general.ufw: diff --git a/roles/services/templates/traefik/traefik.yml.j2 b/roles/services/templates/traefik/traefik.yml.j2 index 1875238..c056413 100644 --- a/roles/services/templates/traefik/traefik.yml.j2 +++ b/roles/services/templates/traefik/traefik.yml.j2 @@ -28,6 +28,31 @@ ping: {} entryPoints: web: address: ":80" + forwardedHeaders: + # Trust Cloudflare IP ranges — they pass real visitor IP in X-Forwarded-For + trustedIPs: + - "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" http: redirections: entryPoint: @@ -35,6 +60,30 @@ entryPoints: scheme: https websecure: address: ":443" + forwardedHeaders: + trustedIPs: + - "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" http: middlewares: - security-headers@file