Add rate limiting, connection limits, and timeout hardening
All checks were successful
HAProxy Manager Build and Push / Build-and-Push (push) Successful in 1m33s
All checks were successful
HAProxy Manager Build and Push / Build-and-Push (push) Successful in 1m33s
Activate HAProxy's built-in attack prevention to stop floods that cause the container to become unresponsive: - Stick table tracks per-IP: conn_cur, conn_rate, http_req_rate, http_err_rate - Rate limit rules: deny at 50 req/s, tarpit at 20 req/s, connection rate limit at 60/10s, concurrent connection cap at 100, error rate tarpit at 20 errors/30s - Harden timeouts: http-request 300s→30s, connect 120s→10s, client 10m→5m, keep-alive 120s→30s - HTTP/2 Rapid Reset protection (CVE-2023-44487): stream and glitch limits - Stats frontend on localhost:8404 for monitoring - HEALTHCHECK now validates both port 80 (HAProxy) and 8000 (API) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -18,6 +18,6 @@ RUN mkdir -p /var/spool/cron/crontabs && \
|
|||||||
chown root:crontab /var/spool/cron/crontabs/root
|
chown root:crontab /var/spool/cron/crontabs/root
|
||||||
EXPOSE 80 443 8000
|
EXPOSE 80 443 8000
|
||||||
# Add health check
|
# Add health check
|
||||||
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
|
HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \
|
||||||
CMD curl -f http://localhost:8000/health || exit 1
|
CMD curl -sf --max-time 5 http://localhost:8000/health && curl -s --max-time 5 -o /dev/null http://localhost/ || exit 1
|
||||||
CMD ["/haproxy/scripts/start-up.sh"]
|
CMD ["/haproxy/scripts/start-up.sh"]
|
||||||
@@ -27,6 +27,10 @@ global
|
|||||||
# SSL and Performance
|
# SSL and Performance
|
||||||
tune.ssl.default-dh-param 2048
|
tune.ssl.default-dh-param 2048
|
||||||
|
|
||||||
|
# HTTP/2 protection against Rapid Reset (CVE-2023-44487) and stream abuse
|
||||||
|
tune.h2.fe.max-total-streams 2000
|
||||||
|
tune.h2.fe.glitches-threshold 50
|
||||||
|
|
||||||
# Stats persistence for zero-downtime reloads
|
# Stats persistence for zero-downtime reloads
|
||||||
stats-file /var/lib/haproxy/stats.dat
|
stats-file /var/lib/haproxy/stats.dat
|
||||||
#---------------------------------------------------------------------
|
#---------------------------------------------------------------------
|
||||||
@@ -42,12 +46,12 @@ defaults
|
|||||||
option forwardfor #except 127.0.0.0/8
|
option forwardfor #except 127.0.0.0/8
|
||||||
option redispatch
|
option redispatch
|
||||||
retries 3
|
retries 3
|
||||||
timeout http-request 300s
|
timeout http-request 30s
|
||||||
timeout queue 2m
|
timeout queue 2m
|
||||||
timeout connect 120s
|
timeout connect 10s
|
||||||
timeout client 10m
|
timeout client 5m
|
||||||
timeout server 10m
|
timeout server 10m
|
||||||
timeout http-keep-alive 120s
|
timeout http-keep-alive 30s
|
||||||
timeout check 10s
|
timeout check 10s
|
||||||
timeout tarpit 10s # Tarpit delay for low-level scanners (before silent-drop)
|
timeout tarpit 10s # Tarpit delay for low-level scanners (before silent-drop)
|
||||||
maxconn 3000
|
maxconn 3000
|
||||||
|
|||||||
@@ -19,6 +19,26 @@ frontend web
|
|||||||
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) 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
|
http-request set-var(txn.real_ip) src if !has_cf_connecting_ip !has_x_real_ip !has_x_forwarded_for
|
||||||
|
|
||||||
|
# --- Connection & rate tracking ---
|
||||||
|
stick-table type ip size 200k expire 10m store conn_cur,conn_rate(10s),http_req_rate(10s),http_err_rate(30s)
|
||||||
|
http-request track-sc0 var(txn.real_ip)
|
||||||
|
|
||||||
|
# Whitelist: let health checks and local traffic bypass rate limits
|
||||||
|
acl is_local src 127.0.0.0/8 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16
|
||||||
|
acl is_health_check path_beg /.well-known/acme-challenge
|
||||||
|
|
||||||
|
# --- Rate limit rules (applied in order, first match wins) ---
|
||||||
|
# Hard block: >500 req/10s per IP (sustained flood)
|
||||||
|
http-request deny deny_status 429 if { sc_http_req_rate(0) gt 500 } !is_local !is_health_check
|
||||||
|
# Tarpit: >200 req/10s per IP (aggressive scraping / light flood)
|
||||||
|
http-request tarpit deny_status 429 if { sc_http_req_rate(0) gt 200 } !is_local !is_health_check
|
||||||
|
# Connection rate limit: >60 new connections per 10s per IP
|
||||||
|
http-request deny deny_status 429 if { sc_conn_rate(0) gt 60 } !is_local !is_health_check
|
||||||
|
# Concurrent connection limit: >100 simultaneous connections per IP
|
||||||
|
http-request deny deny_status 429 if { sc_conn_cur(0) gt 100 } !is_local !is_health_check
|
||||||
|
# High error rate: >20 errors in 30s (scanner/fuzzer behavior)
|
||||||
|
http-request tarpit deny_status 403 if { sc_http_err_rate(0) gt 20 } !is_local !is_health_check
|
||||||
|
|
||||||
# IP blocking using map file (manual blocks only)
|
# IP blocking using map file (manual blocks only)
|
||||||
# Map file format: /etc/haproxy/blocked_ips.map contains "<ip_or_cidr> 1" per line
|
# Map file format: /etc/haproxy/blocked_ips.map contains "<ip_or_cidr> 1" per line
|
||||||
# Runtime updates: echo "add map #0 IP_ADDRESS 1" | socat stdio /var/run/haproxy.sock
|
# Runtime updates: echo "add map #0 IP_ADDRESS 1" | socat stdio /var/run/haproxy.sock
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
# HAProxy 3.0.11 eliminates need for separate security tables
|
# HAProxy Stats & Monitoring
|
||||||
# All threat intelligence is now consolidated in the main frontend table
|
frontend stats
|
||||||
# using array-based GPC system with 15 threat indicators
|
bind 127.0.0.1:8404
|
||||||
|
stats enable
|
||||||
# Placeholder for future security extensions
|
stats uri /stats
|
||||||
# The main table in hap_listener.tpl now provides comprehensive
|
stats refresh 30s
|
||||||
# multi-dimensional threat tracking with weighted scoring
|
stats show-legends
|
||||||
|
stats show-node
|
||||||
Reference in New Issue
Block a user