How to block defined IP addresses on HAProxy

Block defined IP addresses on HAProxy load balancer using simple Access Control List.

HAProxy version.

$ haproxy -v
HA-Proxy version 1.7.5-2 2017/05/17
Copyright 2000-2017 Willy Tarreau 

Default HAProxy configuration.

global
	log /dev/log	local0
	log /dev/log	local1 notice
	chroot /var/lib/haproxy
	stats socket /run/haproxy/admin.sock mode 660 level admin
	stats timeout 30s
	user haproxy
	group haproxy
	daemon

	# Default SSL material locations
	ca-base /etc/ssl/certs
	crt-base /etc/ssl/private

	# Default ciphers to use on SSL-enabled listening sockets.
	# For more information, see ciphers(1SSL). This list is from:
	#  https://hynek.me/articles/hardening-your-web-servers-ssl-ciphers/
	# An alternative list with additional directives can be obtained from
	#  https://mozilla.github.io/server-side-tls/ssl-config-generator/?server=haproxy
	ssl-default-bind-ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:RSA+AESGCM:RSA+AES:!aNULL:!MD5:!DSS
	ssl-default-bind-options no-sslv3

defaults
	log	global
	mode	http
	option	httplog
	option	dontlognull
        timeout connect 5000
        timeout client  50000
        timeout server  50000
	errorfile 400 /etc/haproxy/errors/400.http
	errorfile 403 /etc/haproxy/errors/403.http
	errorfile 408 /etc/haproxy/errors/408.http
	errorfile 500 /etc/haproxy/errors/500.http
	errorfile 502 /etc/haproxy/errors/502.http
	errorfile 503 /etc/haproxy/errors/503.http
	errorfile 504 /etc/haproxy/errors/504.http

Create ACL rule inside frontend section to define and block IP addresses.

acl is-blocked-ip src 192.0.2.11 192.0.2.12 192.0.2.18
http-request deny if is-blocked-ip

Sample frontend and backend using the specified ACL rule.

frontend web
  bind :80
  #bind :443 ssl crt /etc/ssl/cert/

  option httplog
  log /dev/log local0 debug

  option forwardfor except 127.0.0.1
  option forwardfor header X-Real-IP

  #redirect scheme https code 301 if !{ ssl_fc }

  acl is-blocked-ip src 192.0.2.11 192.0.2.12 192.0.2.18
  http-request deny if is-blocked-ip

  acl is-draw hdr_dom(host) -i draw.example.org
  use_backend web-draw-production if is-draw

backend web-draw-production
  mode http
  server draw 10.0.10.15:80

Alternatively, you can negate ACL rule to simply whitelist IP addresses.

acl is-whitelisted-ip src 192.0.2.11 192.0.2.12 192.0.2.18
http-request deny if !is-whitelisted-ip

Use a file to store IP addresses.

$ cat /etc/haproxy/whitelisted.ips 
192.0.2.12
192.0.2.18
acl is-whitelisted-ip src -f /etc/haproxy/whitelisted.ips
http-request deny if !is-whitelisted-ip

Compare IP addresses stored in a file to the the IP address defined in X-FORWARDED-FOR header.

acl is-whitelisted-ip hdr_ip(x-forwarded-for,-1) -f /etc/haproxy/whitelisted.ips
http-request deny if !is-whitelisted-ip

deny action will stop the evaluation of the rules, immediately reject the request and return HTTP 403 error code. silent-drop will try to silently drop connection on the HAProxy, it won't notify client, so any stateful devices placed between the client and HAProxy load balancer will keep connection established.