haproxy
mode http
Bad IP
You may choose to
drop the traffic at the firewall level
reject the traffic at the firewall level
return an “HTTP 403 Forbidden” error after some time (tarpit)
return an “HTTP 403 Forbidden” error
acl bad_ip src 80.94.95.0/24
timeout tarpit 10s
http-request tarpit deny_status 403 if bad_ip
Dealing with HTTP/1.0
http-request deny if HTTP_1.0
or better
http-request deny unless HTTP_2.0 || HTTP_1.1
Filter hostname
acl is_goodhostname hdr(host) -i -m reg ^(autoconfig|autodiscover)\..+(|:80)$
http-request deny unless is_goodhostname
Filter path
acl good_path path_beg -i /Autodiscover/
http-request deny unless good_path
Bad bot
acl is-bad_agent hdr(user-agent) -m sub -m reg -i -f /etc/haproxy/bad_bot.txt
http-request deny if is-bad_agent
Rate-limiting
In the following configuration, I have set a limit to the number of POST requests to limit the number of authentication per IP. It’s not perfect as it counts the number of POST requests and not the number of failed authentication.
acl path_rdweb path_beg -i /RDWeb/
# Define a stick-table to track POST requests per IP
stick-table type ip size 100k expire 30m store http_req_rate(1m)
# Track POST requests for each source IP
http-request track-sc0 src if is_post path_rdweb
# Deny requests if the rate exceeds 10 POSTs per minute
acl too_many_posts sc_http_req_rate(0) gt 10
http-request deny deny_status 429 if too_many_posts
proof-of-work (PoW) and Anubis
Headers
It’s possible to forward some information about the connexion.
http-request set-header X-Forwarded-Proto https
http-request set-header X-Forwarded-For %[src]
More information can be forwarded but ony forward the information you need.
http-request set-header X-Real-IP %[src]
http-request set-header X-Forwarded-For %[src]
http-request set-header X-Forwarded-Method %[method]
http-request set-header X-Forwarded-Proto %[var(req.scheme)]
http-request set-header X-Forwarded-Port %[dst_port]
http-request set-header X-Forwarded-Host %[req.hdr(Host)]
http-request set-header X-Forwarded-URI %[path]%[var(req.questionmark)]%[query]
http-request set-header X-SSL-Cipher %[ssl_fc_cipher]
http-request set-header X-SSL-SessionID %[ssl_fc_session_id,hex]
http-request set-header X-SSL-SNI %[ssl_fc_sni]
http-request set-header X-SSL-Version %[ssl_fc_protocol]
If the client authenticates via certificate, you can also consider
http-request set-header X-SSL-Client-Verify %[ssl_c_verify]
http-request set-header X-SSL-Client-DN %{+Q}[ssl_c_s_dn]
http-request set-header X-SSL-Client-CN %{+Q}[ssl_c_s_dn(cn)]
http-request set-header X-SSL-Issuer %{+Q}[ssl_c_i_dn]
http-request set-header X-SSL-Client-NotBefore %{+Q}[ssl_c_notbefore]
http-request set-header X-SSL-Client-NotAfter %{+Q}[ssl_c_notafter]
Proxy
acl src-trusted_proxies src -f /etc/haproxy/trusted_proxies.src.acl
http-request del-header X-Forwarded-For if !src-trusted_proxies
acl hdr-xff_exists req.hdr(X-Forwarded-For) -m found
http-request set-header X-Forwarded-For %[src] if !hdr-xff_exists
HTTPS
bind 172.18.1.146:443 name admin ssl ssl-min-ver TLSv1.2 crt /etc/pki/tls/private/wildcard.globalsp.com_haproxy.pem
HSTS
http-after-response set-header Strict-Transport-Security max-age=63072000;\ includeSubDomains;\ preload
mode tcp with SSL connexion
To reject TLS 1.1 and lower
tcp-request inspect-delay 5s
tcp-request content set-var(sess.ssl_sni) req.ssl_sni
tcp-request content accept if { req.ssl_hello_type 1 }
tcp-request content reject if { req.ssl_ver lt 3.3 }