Skip to main content

Command Palette

Search for a command to run...

HAProxy: Restrict access by IP address

Crude way to stop an attack in case of an emergency.

Updated
2 min read

Keep in mind that this is a static configuration, which is not very effective against adversarial attacks when an attacker constantly changes their tactics.

By default HAProxy configuration file is located at /etc/haproxy/haproxy.cfg. To block a single IP address we can use a conditional http-request deny directive.

http-request deny if { src 8.8.8.8/32 }

If we need to apply it to a given endpoint we can use the keyword path.

http-request deny if { path -i -m beg /login } { src 8.8.8.8/32 }

Note that the IP address is in the CIDR notation, we can use it to restrict the access to an entire subnet. Adding ! will invert the rule and allow the access to a given subnet, restricting it to the rest.

http-request deny if { path -i -m beg /login } !{ src 8.8.8.0/24 }

Managing a denylist

HAProxy allows to store the list of IP addresses in a separate file on the filesystem. Each IP address separated by a newline.

# cat blocked.ips
8.8.8.8
12.12.12.0/24

Then we can include them into the configuration file

http-request deny if { path -i -m beg /login } { src -f /etc/haproxy/blocked.ips }

Applying restrictions on TCP level

If we want to apply the restrictions deeper in the stack we can use tcp-request connection reject for that.

tcp-request connection reject if { src 8.8.8.8/32 }

Applying configuration

service haproxy check

to test the validity of the configuration file.

service haproxy reload

to reload the config.

J
JV2y ago

Nice! How do you do this to block CIDR ranges from a different header? E.g get the IP from the X-Forwarded-For header and compare against a blacklist?

B

If you need to block CIDR ranges based on the X-Forwarded-For header in HAProxy, you can accomplish this by setting up ACLs in your HAProxy configuration. Here's a quick guide:

  1. Create ACLs for the CIDR ranges you want to block. Place these in the frontend section of your haproxy.cfg.

  2. Extract the actual client IP from the X-Forwarded-For header using the hdr() function.

  3. Implement blocking by using the http-request deny directive if the IP extracted matches any on your blacklist.

Here’s an example snippet:

frontend http-in
    bind *:80
    # ACL for blacklisted CIDR ranges
    acl ip_blacklisted src -f /etc/haproxy/blacklist.lst
    # Check for X-Forwarded-For header
    acl xff_ip hdr(x-forwarded-for) -m found
    # Match the IP against the blacklist
    acl xff_ip_in_blacklist hdr_ip(x-forwarded-for,1) -f /etc/haproxy/blacklist.lst
    # Deny requests from blacklisted IPs
    http-request deny if xff_ip xff_ip_in_blacklist

    default_backend servers

Make sure your blacklist.lst contains the proper CIDR blocks you're aiming to restrict. After updating your configuration, don’t forget to reload HAProxy to apply the changes. This is usually done with sudo systemctl reload haproxy or a similar command depending on your system.

Hope this helps!

1
J
JV2y ago

Oh wow! Thanks Black Fedora for this config guide. I have spent all day playing around with it.

I'm in tcp mode so I used tcp-request content deny instead of http-request denyand found out I needed to add tcp-request inspect-delay 5s to make it work. Does that sounds about right?

B

JV didn't get the notification about the reply!

I think you're on the right track! Using tcp-request content deny along with tcp-request inspect-delay 5s in HAProxy for TCP mode is a good approach. The inspect delay gives HAProxy time to gather enough data to enforce your rule effectively. I would fine-tune the delay time as needed for the best balance between security and performance. Great job figuring this out!

1
J
JV2y ago

Black Fedora No worries! This config seems to be working well for me. I lowered the inspect-delay to 3s. Thanks for your help and advice.

Practical Tips

Part 2 of 3

“Theory and practice sometimes clash. And when that happens, theory loses. Every single time.” - Linus Torvalds

Up next

NGINX: Restrict access by IP address

Crude way to stop an attack in case of an emergency.