On Fri, Feb 24, 2023 at 12:33 AM Willy Tarreau <w...@1wt.eu> wrote: > > On Fri, Feb 24, 2023 at 05:39:13AM +0000, Robin H. Johnson wrote: > > On Thu, Feb 23, 2023 at 06:48:14PM -0700, Bryan Arenal wrote: > > > Hi there, > > > > > > I'm seeing some traffic from what appears to be bad actors and am > > > wanting to block them. I see this in the existing config but being > > > new to haproxy, it doesn't seem like it's configured correctly but I'm > > > not sure: > > > > > > frontend main > > > bind :80 > > > acl bad_ip src > > > acl bad_ip_proxy hdr_ip(X-Forwarded-For) > > Off the top of my head, this should probably be: > > acl bad_ip src -f /etc/haproxy/blocklist.lst > > acl bad_ip_proxy hdr_ip(X-Forwarded-For) -f /etc/haproxy/blocklist.lst > > > > > tcp-request connection reject if bad_ip || bad_ip_proxy > > I'm not sure offhand about the processing order for the header case. > > > > You might need BOTH: > > tcp-request connection reject if bad_ip || bad_ip_proxy > > http-request connection reject if bad_ip || bad_ip_proxy > > In fact the tcp-request rule will not consider the bad_ip_proxy ACL since > it relies on header extraction that is not possible at this step. Indeed, > You'd need to deal with this using the http-request rule. I would also > suggest that if the IP is blocked at the TCP level then it's not needed > to evaluate it again at the HTTP layer. This would give: > > tcp-request connection reject if bad_ip > http-request reject if bad_ip_proxy > > > Depending on the scale of the traffic, the one problem you'll have here is > > that HAProxy still has to process the problematic requests. > > In fact it depends. For example if it's a POST with a heavy body, a "deny" > rule will return a 403 and will drain the rest of the body in order to try > to recover the connection, but a "reject" rule will instantly break the > connection, which instantly stops any processing. > > > In that case I suggest writing a feedback loop that adds the bad IP to an > > ipset > > set, to block the traffic before it gets to HAProxy, for some period of > > time. > > The trigger for the loop can either be a tail on the logfile, or using some > > variation of the set* functionality (set-acl, set-map, set-mark) and > > exporting > > the data to ipset. > > I used to proceed like this a very long time ago, and found that it was > not always convenient due to the lack of observability (i.e. "is that rule > still needed or has the attack stopped?"). Given the performance of most > machines nowadays, I *tend* to prefer only blocking using the ACLs in TCP > rules (that's still very fast). However you're right, sometimes it can be > required to block IPs at the packet level, particularly for multi-protocol > attacks that span over many ports. > > By the way, if attacks come from a small to medium sized set of clients, > the "tarpit" and "silent-drop" actions can be more effective because they > consume resources on the client by keeping the connection open. But *do not* > do that if there is a firewall or NAT box between the net and your LB or > it might not find this funny. For silent-drop there's a new "rst-ttl" > option that allows to send a reset with a limited TTL that only the > firewall/NAT box will see. This one might be considered as an option.
Thank you both VERY much for your help -- I really appreciate it. That makes total sense that you'd have to use http-request rather than tcp-request since you've got to evaluate the headers. And would this work to reject any request that has the 'X-Forwarded-For' header? acl is-forwarded hdr_sub(x-forwarded-for) http-request reject if is-forwarded How resource intensive do you think this would this be? Thanks again!