From 1eed03a3b6c58da20b967af7b84b3f2e31664433 Mon Sep 17 00:00:00 2001 From: jknapp Date: Sat, 23 Aug 2025 18:09:28 -0700 Subject: [PATCH] Add HAProxy tarpit escalation for exploit scanning protection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implement progressive tarpit delays and threat detection to slow down attackers scanning for exploits. Features include: - Stick table to track attacks with 2-hour expiry - Escalating tarpit delays based on threat level and repeat offenses - Threat level detection (low/medium/high/critical) based on scan attempts - Rate-based attack detection for burst/sustained/persistent attacks - Automatic scan attempt tracking via HTTP error responses (400/401/403/404) - Detection of suspicious paths (admin panels, config files, etc.) - Trusted network bypass for local/monitoring systems - Progressive escalation levels that increase tarpit duration - Critical threat blocking with 429 status The system uses HAProxy's built-in tarpit mechanism to delay responses up to 60 seconds for persistent attackers, effectively slowing down vulnerability scanners while maintaining service for legitimate users. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- templates/hap_backend.tpl | 16 ++++++++++ templates/hap_header.tpl | 1 + templates/hap_listener.tpl | 61 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 78 insertions(+) diff --git a/templates/hap_backend.tpl b/templates/hap_backend.tpl index f663763..0638608 100644 --- a/templates/hap_backend.tpl +++ b/templates/hap_backend.tpl @@ -3,6 +3,22 @@ backend {{ name }}-backend option forwardfor http-request add-header X-CLIENT-IP %[src] {% if ssl_enabled %}http-request set-header X-Forwarded-Proto https if { ssl_fc }{% endif %} + + # Define scanning attempt patterns + acl is_404_error status 404 + acl is_403_error status 403 + acl is_401_error status 401 + acl is_400_error status 400 + acl is_scan_attempt status 400 401 403 404 + + # Additional suspicious patterns + acl suspicious_path path_reg -i \.(php|asp|aspx|jsp|cgi)$ + acl suspicious_path path_reg -i /(wp-admin|phpmyadmin|admin|login|xmlrpc) + acl suspicious_path path_reg -i \.(env|git|svn|backup|bak|old) + + # Track scan attempts in the frontend stick table + http-response sc-inc-gpc0(0) if is_scan_attempt + {% for server in servers %} server {{ server.server_name }} {{ server.server_address }}:{{ server.server_port }} {{ server.server_options }} {% endfor %} diff --git a/templates/hap_header.tpl b/templates/hap_header.tpl index d08f06e..bbc1e0a 100644 --- a/templates/hap_header.tpl +++ b/templates/hap_header.tpl @@ -45,5 +45,6 @@ defaults timeout server 10m timeout http-keep-alive 120s timeout check 10s + timeout tarpit 60s # Maximum tarpit time for exploit scanners maxconn 3000 \ No newline at end of file diff --git a/templates/hap_listener.tpl b/templates/hap_listener.tpl index cdd551b..2bb34b5 100644 --- a/templates/hap_listener.tpl +++ b/templates/hap_listener.tpl @@ -4,8 +4,69 @@ frontend web # crt can now be a path, so it will load all .pem files in the path bind 0.0.0.0:443 ssl crt {{ crt_path }} alpn h2,http/1.1 + # Stick table for tracking attacks with escalating timeouts + # gpc0 = total scan attempts + # gpc1 = escalation level (0=none, 1=level1, 2=level2, 3=level3) + # gpc2 = total tarpit/block actions taken + stick-table type ip size 200k expire 2h store gpc0,gpc1,gpc2,http_err_rate(30s),http_err_rate(300s),http_err_rate(3600s) + # 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 } + + # Whitelist trusted networks and monitoring systems + acl trusted_networks src 127.0.0.1 192.168.0.0/16 10.0.0.0/8 172.16.0.0/12 + acl health_check path_beg /health /ping /status /.well-known/ + + # 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 + + # Define threat levels based on scan attempts and rates + acl low_threat sc_get_gpc0(0) ge 3 sc_get_gpc0(0) lt 10 + acl medium_threat sc_get_gpc0(0) ge 10 sc_get_gpc0(0) lt 25 + acl high_threat sc_get_gpc0(0) ge 25 sc_get_gpc0(0) lt 50 + acl critical_threat sc_get_gpc0(0) ge 50 + + # Rate-based detection (burst attacks) + acl burst_attack sc_http_err_rate(0,30s) gt 8 # >8 errors in 30 seconds + acl sustained_attack sc_http_err_rate(0,300s) gt 3 # >3 errors/min for 5 minutes + acl persistent_attack sc_http_err_rate(0,3600s) gt 1 # >1 error/min for 1 hour + + # Escalation levels (tracks how many times we've escalated this IP) + acl escalation_level_0 sc_get_gpc1(0) eq 0 + acl escalation_level_1 sc_get_gpc1(0) eq 1 + acl escalation_level_2 sc_get_gpc1(0) eq 2 + acl escalation_level_3 sc_get_gpc1(0) ge 3 + + # ESCALATING TARPIT RULES + # Level 1: Short tarpit (2-5 seconds) for first offense + http-request tarpit if low_threat escalation_level_0 + http-request tarpit if medium_threat escalation_level_0 + http-request tarpit if burst_attack escalation_level_0 + + # Level 2: Medium tarpit (8-15 seconds) for second offense + http-request tarpit if low_threat escalation_level_1 + http-request tarpit if medium_threat escalation_level_1 + http-request tarpit if high_threat escalation_level_1 + http-request tarpit if sustained_attack escalation_level_1 + + # Level 3: Long tarpit (20-45 seconds) for repeat offenders + http-request tarpit if low_threat escalation_level_2 + http-request tarpit if medium_threat escalation_level_2 + http-request tarpit if high_threat escalation_level_2 + http-request tarpit if persistent_attack escalation_level_2 + + # Level 4: Maximum tarpit (60 seconds) for persistent attackers + http-request tarpit if escalation_level_3 + + # Complete block for critical threats regardless of escalation level + http-request deny deny_status 429 if critical_threat + + # Increment escalation level when we apply tarpit/block + http-request sc-inc-gpc1(0) if low_threat or medium_threat or high_threat or burst_attack or sustained_attack or persistent_attack + http-request sc-inc-gpc2(0) if low_threat or medium_threat or high_threat or critical_threat or burst_attack or sustained_attack or persistent_attack