imagine a blog with a comments section with a check box that says "bypass security check". if you click this, the admin scolds you saying "how dare you try and bypass security" and bans you. if you _dont_ click it, the admin laughs at you when you complain about too many captchas because "all you had to do was click the check box", idiot. either case can happen depending on which ideology the admin so happens to follow. thats the problem with wafs, they are ideological and opinion based but at the protocol level (but most wafs are such low quality that accidentally typing ' can get your ip banned).
If "WAF" bothers you, call it ingress/egress filtering (at the content level instead of packet level) instead.
In my architecture, the same services also perform egress filtering. It's also useful, but not the WAF or the topic of conversation.
I think people get upset about the term "WAF". It's just a new label for the longstanding practice of upper-layer ingress filtering (i.e. DPI and reverse-proxy filtering). But it's often a dedicated service now, so it needs a name of some kind.
A poorly-configured WAF breaks things, just like a poorly-configured (any other network service).
You can also allow many more attempts from the known IP addresses for the user, as most users don't change their IP too much. Still, some do, but they will probably authenticate correctly within one or max. two requests.
But of course lots of legit authentication attempts come from new users, or new sessions. So I need to allow that case as well, and then we're back at square one.
especially as more and more of the world ends behind cgnat for ipv6 ip blocking will work less and less
My favorite mitigation is to reject all HTTP/1.0 requests. If they don't send HTTP/1.1 or newer, with the Hostname I'm expecting, I 404 them. This cuts down on substantially all of the random noise. (Could be 401 or other, but 404 seems to encourage a "try more but don't try harder" reaction, which is easier to handle than the converse).
Targeted attacks are more difficult. I use a WAF and path permit lists at the reverse proxy level. This is trivial, but still stops 99% of the rest.
The last and hardest thing to block is distributed brute force authorization attempts. I've built a list of hundreds of thousands of IPs that have been used in these attempts. Sometimes thousands of requests come in per second.
I use rate limiting on the auth request endpoint. Too much limiting will affect real users, so I have to be somewhat gentle here.
Known-exploited IP addresses get just one attempt before a long block. This means that real humans whose machines are part of a botnet are sometimes blocked from the service. This is not a great compromise.