From 2b31fb9f4f15fcee98487c20ec2cc1b83995c539 Mon Sep 17 00:00:00 2001 From: jknapp Date: Sun, 24 Aug 2025 06:51:00 -0700 Subject: [PATCH] Add real client IP detection for proxy/CDN environments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implements smart client IP detection to handle Cloudflare and other reverse proxies correctly, preventing legitimate traffic from being tarpited when behind a shared proxy IP. Changes: - Detect real client IP from proxy headers with priority order: 1. CF-Connecting-IP (Cloudflare) 2. X-Real-IP (common proxy header) 3. X-Forwarded-For (standard proxy header) 4. src (fallback to source IP if no headers) - Track real client IP in stick-table instead of proxy IP - Check real client IP for blocking rules - No need to maintain proxy IP lists - works automatically This ensures that: - Cloudflare and other CDN traffic is tracked per real client - Each actual user gets their own tarpit counter - Legitimate users aren't affected by attackers on the same proxy - Works automatically with any proxy that sets standard headers 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- templates/hap_listener.tpl | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/templates/hap_listener.tpl b/templates/hap_listener.tpl index ab7cda8..76d6e1a 100644 --- a/templates/hap_listener.tpl +++ b/templates/hap_listener.tpl @@ -16,14 +16,27 @@ frontend web # Allow trusted traffic to bypass all protection http-request allow if trusted_networks or health_check - # Track client in stick table - http-request track-sc0 src + # Detect real client IP from proxy headers if they exist + # Priority: CF-Connecting-IP (Cloudflare) > X-Real-IP > X-Forwarded-For > src + acl has_cf_connecting_ip req.hdr(CF-Connecting-IP) -m found + acl has_x_real_ip req.hdr(X-Real-IP) -m found + acl has_x_forwarded_for req.hdr(X-Forwarded-For) -m found + + # Set the real IP based on available headers + http-request set-var(txn.real_ip) req.hdr(CF-Connecting-IP) if has_cf_connecting_ip + http-request set-var(txn.real_ip) req.hdr(X-Real-IP) if !has_cf_connecting_ip has_x_real_ip + http-request set-var(txn.real_ip) req.hdr(X-Forwarded-For) if !has_cf_connecting_ip !has_x_real_ip has_x_forwarded_for + http-request set-var(txn.real_ip) src if !has_cf_connecting_ip !has_x_real_ip !has_x_forwarded_for + + # Track the real client IP in stick table (not the proxy IP) + http-request track-sc0 var(txn.real_ip) # IP blocking using map file (no word limit, runtime updates supported) # Map file: /etc/haproxy/blocked_ips.map # Runtime updates: echo "add map #0 IP_ADDRESS" | socat stdio /var/run/haproxy.sock - http-request set-path /blocked-ip if { src -f /etc/haproxy/blocked_ips.map } - use_backend default-backend if { src -f /etc/haproxy/blocked_ips.map } + # Now checks the real client IP (from headers if present, otherwise src) + http-request set-path /blocked-ip if { var(txn.real_ip) -m ip -f /etc/haproxy/blocked_ips.map } + use_backend default-backend if { var(txn.real_ip) -m ip -f /etc/haproxy/blocked_ips.map } # Define threat levels based on accumulated error responses from backends # These will be checked on subsequent requests after errors are tracked