For the layman, a "WAF" or Web Application Firewall is a service you can place in front of your website to protect it from the many threats out on the internet. It can head off known exploits, mitigate DDOS attacks, and block known bad actors. These tools come in a variety of shapes and sizes and pricing will vary. This is also distinct from a "reverse proxy cache" like varnish. Which can improve performance of a site dramatically, and help with some of these things I mentioned, but in general is kind of dumb, and can't react to threats.
So let me just say it up front, if you are able to use a WAF tool, and a service bundled with your hosting provider, use that. However, sometimes these tools can be expensive, especially the FedRAMP compliant versions of them - Now if you wanted to make the government more efficient, this would be a great place to start. Allow some agencies exceptions from having their IT infrastructure be FedRAMP compliant - this could be the difference in many tens to hundreds of thousands of dollars per agency. But back to the topic. So you have a Drupal website, and you want to implement something like a Web Application Firewall (WAF) tool on it. What can you do? Well, right now there are a number of options available to you in the form of modules. Together, they can provide a lot of tools to help mitigate against bad actors. These aren't a total replacement of a true "WAF", but if that isn't an option for you, this is the best next thing you can do.
So here are the modules you have available to you to build your own WAF in Drupal.
Ban - This is the module provided by core Drupal, allows you to ban individual IP addresses. As such, it's a simple tool and it lacks flexibility. Fortunately, the Drupal community has come out with a more robust version.
Advanced Ban - Similar to Ban, but allows you to ban IP ranges, and other includes other features, like an expiration time for the ban. Most modules that integrate with ban modules allow you to use either one. But there may be a few integrations out there that pick one or the other.
Auto Ban - I must also note that the auto-ban module is available. Which can be used to automatically ban IPs based on some pattern appearing in your log. With that though, you must have dblog enabled (I often leave it off in high traffic, production environments), and you need to have some consistent pattern to identify, which I haven't really been able to do in a useful way myself.
Antibot - This module provides form spam protection by intentionally "breaking" forms, which are then fixed later via javascript. With that said, the recent paradigm shift I've seen in bot traffic includes these bots running browsers with Javascript enabled. However, the AI/LLM training bots generally don't seem interested in submitting forms, so this hasn't been a huge issue yet. Still, I think the Antibot module is worth including on your site.
Honeypot - More form spam protection. But using a few different methods. The honeypot module will insert a fake form element, which is then hidden via CSS. If that form gets submitted, then it is assumed to be a bot as a human would not be able to submit anything for that field. Again, this assumes the bot is reading your form's source code directly, and not a rendered version of the form in a functional browser.
Captcha / ReCaptcha - Even more form spam protection, but using the captcha/recaptcha tools that we are likely all familiar with. We've all seen the checkbox "I am not a bot" or the grid of pictures where you click the ones that include a bicycle, and then stress out if the one with the very small sliver of the tire should be included. The two different modules provide different types of captchas. ReCaptcha is the google service we are all familiar with, which does require an account, and for you to register your domain, and would be a paid service if your usage exceed's the free tier limit (which is rather generous for most sites). If you don't want to create an account, there are other captcha tools available, like performing a simple math problem, or looking for an answer to a basic question, or typing in letters from a distorted image. Those seem a bit less polished in my mind, as people are very used to the Google Captcha at this point.
Crawler Rate Limit - Rate limit by IP. This also has a few other features, like rate limiting by the user agent string (in cases where the bot us using different IPs). It also allows you to rate limit at the ASN level, i.e. rate limit countries our ISPs (an ability that not even WAF's seem to provide). My gripe with this module though is the lack of reporting. You can't see how effective your settings are, so you just sort of have to trust the defaults. Also, the settings need to be hard-coded in your settings.php file, so you need to perform a code deployment if you want to change them. With that said, there are issues in the queue about these, and if the need for these features becomes urgent enough, someone may provide a patch.
Fast 404 - One problem with CMS' in general, is that rendering an un-cached page is intensive. This includes any 404 "Not Found" page as many caching mechanisms rely on the URL of a page to look up the related cache entries. So it's in your interest to make rendering 404 pages less intensive. Otherwise, anyone can come along, and hit your site with a bunch of requests like my-site.com/blah-blah-blah, and your need to spend the effort rendering that non-existing page. Instead, you can hard-code your entire 404 page, and the module has an early runtime process that checks if the page is a 404, and serves the hard-coded version instead of a Drupal rendered page.
Perimeter - This module was a recent discovery for me, and I was happy about that, because I had been thinking of the same idea for such a module for a while now. If you've ever just reviewed a log of 404 requests in a website, you've undoubtedly seen a number of odd requests that seem to be looking for wordpress login pages, or unusual files like "backup.sql". These are attempts to look for vulnerable or sensitive URLs on your site. With the Automatically ban IPs which are probing for vulnerable URLs. With this module, you can automatically ban the IPs looking for vulnerabilities. Be sure to exclude any important IP ranges though, as you might see such probes come from your own network. At the bottom of this page, I've provided a list of the ban paths I am using with this module, based on real log data I've observed.
Facet Bot Blocker - This module is my own creation, which I put together in the wake of the recent surge in bot traffic across the internet, specifically to address the trend of bots getting stuck in these faceted search pages.
That's all I have for now. I will treat this as a living document, and make updates as I identify new ways to include WAF-like features directly in a Drupal website.
Some Misc Resources
Here are some random resources on the topic of handling bot traffic.
Drupal Forum Discussion on the topic of the recent trend of bad bots
Acquia Documentation addressing too many requests on faceted searches.
Acquia Documentation on addressing bots crawling views results.
My own previous article on the topic of handling misbehaving bots.
Articles on the recent trend in 2025
FOSS infrastructure is under attack by AI companies
Abusive AI Web Crawlers: Get Off My Lawn
Perimeter module ban paths
/.*\.aspx/
/.*\.asp/
/.*\.jsp/
/\/blog_edit\.php/
/\/blogs\.php/
/\/wp-admin.*/
/\/wp-login.*/
/\/system\/.*\.php/
/.*systopice.*/
/.*login.json/
/\/episerver.*/
/\/wp-mail\.php/
/\/wp-content\/.*/
/\/wp-includes\/.*/
/\/(?:201[89]|202[0-9]|blog|cms|media|news|shop|site|sito|test|web|website|wordpress)\/wp-includes\/wlwmanifest\.xml/
/\/(?:cgi-bin|css|img)\/xmrlpc\.php\?p=/
/\/(?:_db(?:s)?|admin_db|bak_db)\.(?:sql|tar(?:\.gz|\.xz)?|gz|xz)/
/\/202(1|2|3|4|5)\.(?:gz|sql)/
/\/backup\.tar\.xz/
/\/bk\.tar\.gz/
/\/bk\.tgz/
/\/phpmyadmin\.tar\.(?:gz|xz)/
/\/user\.(?:7z|tar\.bz2|tgz)/
/\/data\.sql/
/\/Documents\.sql/
/\/(?:admwp|adriv|ae|ah|ak|ak47shell|al|alex(?:us(?:-mailer(?:-2\.0)?)?)?|alf\d*|alfa\d*|cjfuns)\.php/
/\/alfacgiapi\/(?:admin|alfa|bypass|index|k|perl\.alfa|wp)\.php/
/\/alfacgiapiadmin\.php/
/\/alfacgiapialfa\.php/
/\/alfacgiapibypass\.php/
/\/alfacgiapik\.php/
/\/ALFA_DATA\/alfacgiapi\/alfa\.perl/
/\/settings\.php/
/\/system\.php/
/\/Telerik\.Web\.UI\.WebResource\.axd\?type=rau/
/.env/
/.htaccess/
/.htpasswd/
/\/web\.config/
/.git/
/.git\/config/
/.DS_Store/
/\/vendor\/phpunit\/.*/
/\/phpunit\.xml/
/\/composer\.(?:json|lock)/
/\/wp-config\.php/
/\/configuration\.php/
/\/configuration\.php-dist/
/\/config\.php/
/\/config\.(?:json|ya?ml)/
/\/adminer(?:.*)\.php/
/\/dump\.sql/
/\/sql_dump\.sql/
/\/cgi-bin\/test-cgi/