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

Dealing with obsolete navigator

http-request redirect location https://www.firefox.com/ if { hdr(user-agent) -m reg ^.*Firefox\/[0-9][0-9]\..*$ } !{ hdr(user-agent) -m sub GoogleImageProxy }
http-request redirect location https://www.google.com/chrome/ if { hdr(user-agent) -m reg ^.*Chrome\/[0-9][0-9]\..*$ }

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

https://github.com/TecharoHQ/anubis/issues/977

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]

https://en.wikipedia.org/wiki/List_of_HTTP_header_fields

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 }