What is a WAF? What it blocks, what it misses and the free options worth using
Understand what a web application firewall does, when it is useful, where it fails, and how to deploy Cloudflare Free or OWASP CRS without locking out real users.
Scope
Understand what a web application firewall does, when it is useful, where it fails, and how to deploy Cloudflare Free or OWASP CRS without locking out real users.
Was I hacked?
Not because a web application firewall raised an alert. A WAF event normally means that a request matched a rule; it does not prove that the application was vulnerable, that the request reached the vulnerable code or that the attacker succeeded.
Treat the event as a lead. Record the rule ID, action, source, hostname, route, user identity and request ID. Then check the application, identity, database and endpoint logs for consequences: an unexpected login, a new administrator, an unusual query, a changed file or a web-server process starting a shell. The data-injection detection playbook explains that evidence chain in detail.
If your WAF suddenly starts blocking thousands of requests, do not declare victory and make tea. Confirm that ordinary customers can still log in and pay, check whether the origin server is being reached directly, and investigate the requests that were allowed. A WAF is a useful doorman. It is not the detective, building inspector and software engineer rolled into one increasingly tired person.
WAF in thirty seconds
WAF means web application firewall. It sits in the HTTP or HTTPS request path and applies rules to web traffic before the request reaches the application. Depending on the product and configuration, it can:
- allow, block or challenge a request;
- detect patterns associated with SQL injection, cross-site scripting, command injection and path traversal;
- restrict methods, content types, body sizes, countries, networks or troublesome routes;
- rate-limit login, search, API and form endpoints;
- create logs for investigation;
- apply a temporary “virtual patch” while the real application fix is prepared.
OWASP describes a WAF as an application firewall that applies rules to HTTP conversations and protects servers, commonly as a reverse proxy. That last part matters: a WAF protects web requests. It does not automatically protect SSH, RDP, SMTP, a database port or a management interface that somebody thoughtfully published on the Internet at 17:02 on Friday.
Visitor or bot
|
v
DNS / CDN / reverse proxy
|
v
Web application firewall
| allow | block/challenge/log
v x
Origin web server
|
v
Application and database
For encrypted HTTPS traffic, the WAF must be able to inspect the decrypted HTTP request at some point. A cloud WAF normally terminates the visitor's TLS connection and creates a separate encrypted connection to the origin. A local WAF can terminate TLS itself or operate inside a web server that already does so.
What a WAF is good at
A WAF is most useful when suspicious traffic has visible characteristics at the HTTP layer.
| Situation | What a WAF can do | Confidence |
|---|---|---|
| Known malicious request pattern | Match a managed rule and block or score the request | Often useful, but evasions and false positives exist |
| Newly disclosed web flaw | Add a narrow virtual patch for the affected route and parameter | Useful temporary containment |
| Repeated login attempts | Rate-limit, challenge or restrict the login route | Useful if identities and shared networks are considered |
| Unexpected HTTP method | Block PUT, DELETE or others where the application never uses them |
High when the method policy is accurate |
| Oversized upload or request body | Reject it before expensive application processing | High with tested size limits |
| Known bad source or geography | Block, challenge or monitor it | Contextual; IP reputation is not identity |
| Common CMS probing | Drop requests for unused files and administration routes | Useful noise reduction |
Virtual patching is particularly valuable during the gap between learning about a vulnerability and deploying a tested software update. OWASP is equally clear that fixing the source code remains the primary remediation. The WAF rule and the application fix can run in parallel; the rule must not become a permanent excuse for leaving the vulnerable component untouched.
What a WAF cannot reliably fix
A WAF cannot understand every business decision inside an application. It will struggle to identify that:
- one authenticated customer changed the invoice belonging to another customer;
- a valid user exported more data than their role should permit;
- a password-reset workflow trusts the wrong identity signal;
- an administrator approved a fraudulent payment;
- a vulnerable dependency is exploitable without a distinctive request pattern;
- an attacker used stolen credentials and otherwise normal HTTP requests;
- malicious data was stored earlier and interpreted later by a background job.
It also does not replace secure coding, authentication, authorisation, patching, backups, endpoint protection, monitoring or incident response. The WAF sees a request. The application knows whether the user may perform the requested action.
The failure mode to remember is origin bypass. If a cloud WAF protects www.example.test but the origin server still accepts connections from every Internet address, an attacker who learns the origin IP can send requests around the WAF. The expensive security product then protects a route the attacker is no longer taking.
Do you need one?
Use a WAF when one or more of these are true:
- you operate an Internet-facing website, WordPress installation, shop, portal or API;
- a legacy or third-party application cannot be patched quickly;
- the service receives automated scanning, credential attacks or abusive traffic;
- the organisation needs a rapid virtual-patching capability;
- there are several applications that need a consistent minimum HTTP policy;
- your team can monitor alerts and maintain exceptions.
A WAF may be unnecessary for a static site with no dynamic origin, a private service already reachable only through a strongly authenticated access proxy, or an application platform whose provider already supplies a well-managed WAF. Ask the provider what is enabled, which rules are included, where events appear and who tunes false positives. “There is probably a firewall somewhere” is not an operating model.
Do not install a self-hosted WAF merely because a compliance checklist contains a box. It adds another Internet-facing component, TLS termination point, update process and failure mode. A neglected WAF can be both a bottleneck and a vulnerability.
Three deployment models
1. Cloud or CDN WAF
DNS sends visitors to a provider such as Cloudflare. The provider inspects traffic at its edge and proxies allowed requests to your origin.
This is usually the easiest model for a small public site. It can absorb abusive traffic before it reaches your connection and does not consume resources on the origin. The trade-offs are dependence on a third party, limited features on free tiers, correct handling of visitor IP addresses, and the need to restrict direct origin access.
2. Reverse-proxy WAF that you operate
An Nginx, Apache, Caddy or dedicated proxy receives the request, runs a WAF engine and forwards allowed traffic to the application.
This gives you control over rules and logs and works for on-premises applications. You also own updates, capacity, high availability, certificates, rule tuning and the inevitable investigation of why the quarterly report upload contains a string that resembles JavaScript.
3. WAF inside an ingress or application stack
Kubernetes ingress controllers, API gateways and application middleware can host WAF logic close to the application. This can give better route context and infrastructure-as-code deployment, but the team must understand which ingress instances and protocols are actually covered.
Free WAF options worth considering
“Free” can mean a free hosted tier or open-source software without a licence fee. Open-source WAFs still require servers, monitoring, updates and engineering time.
| Option | Best fit | What is free | Main catch |
|---|---|---|---|
| Cloudflare Free | A small public website, WordPress site or simple API | Cloudflare Free Managed Ruleset, five zone custom rules, one rate-limiting rule and limited analytics | A smaller rule set and fewer controls than paid plans; DNS and origin security must be correct |
| OWASP ModSecurity + Core Rule Set | Teams comfortable running Nginx or Apache reverse proxies | Apache-licensed WAF engine and open-source CRS rules | Tuning, upgrades, logs, TLS and availability are your responsibility |
| OWASP Coraza + Core Rule Set | Go, Caddy and modern proxy integrations | Open-source Go WAF compatible with ModSecurity SecLang and OWASP CRS | Integration maturity varies; you still operate and tune it |
| BunkerWeb Community | Self-hosters wanting an integrated reverse proxy and web UI | Open-source Nginx-based WAF with ModSecurity/CRS integration | Heavier platform and resource footprint than a simple proxy; production design still needs care |
Cloudflare's documentation currently states that Free-plan domains receive the Cloudflare Free Managed Ruleset, a subset of its larger managed rules, and five custom WAF rules without regex support. Free Security Analytics currently retains up to seven days and permits a 24-hour query window. Those limits and product names can change, so check the linked availability tables before designing a control around them.
For self-hosting, the OWASP CRS project publishes ready-made containers pairing CRS with ModSecurity and a web server. In March 2026 it also announced a 4.25-lts rules branch and container tags for ModSecurity with Nginx or Apache and Coraza with Caddy. Pin an LTS or tested release rather than deploying an unversioned image and hoping Tuesday remains uneventful.
Practical option A: Cloudflare Free in front of a website
This route is suitable when you control the domain's DNS and the website is reachable using ordinary HTTP or HTTPS.
Step 1: proxy the web records
Add the domain to Cloudflare, change the authoritative name servers as instructed, then set the relevant A, AAAA or CNAME web records to Proxied rather than DNS-only. Mail records must remain configured correctly; do not casually proxy services Cloudflare does not support.
Confirm from a separate network:
dig +short www.example.test A
dig +short www.example.test AAAA
curl -I https://www.example.test/
Replace example.test with your own authorised hostname. DNS should return Cloudflare addresses for the proxied record, and the site should respond through HTTPS.
Step 2: confirm the free managed rules are active
In the domain dashboard, open the security or WAF rules area and locate the Cloudflare Free Managed Ruleset. Confirm that it is enabled and review Security Events after normal browsing. Cloudflare changes dashboard navigation, so use the current WAF “Get started” documentation if a label has moved.
Do not start by creating a collection of heroic custom expressions copied from a forum. The managed baseline is maintained by the provider. Use the five custom slots for application-specific facts the provider cannot know.
Step 3: add narrow application rules
For a WordPress site, useful candidates include:
- managed challenge on
/wp-login.phpfor visitors outside your normal administration workflow; - blocking
/xmlrpc.phponly if plugins, mobile applications and integrations do not use it; - rate-limiting repeated requests to the login endpoint;
- blocking access to a known-unused staging hostname;
- restricting a private administration path to your VPN or trusted access proxy.
One simple custom expression for an unused WordPress XML-RPC endpoint is:
http.request.uri.path eq "/xmlrpc.php"
Choose Block, document why the endpoint is unused and test WordPress publishing, mobile clients, Jetpack and other integrations first. If you do use XML-RPC, do not block it globally; apply rate limits and authentication controls appropriate to the actual workflow.
Step 4: prevent origin bypass
First test from a system you own whether the origin responds directly:
curl --resolve www.example.test:443:203.0.113.20 \
https://www.example.test/ -I
203.0.113.20 is a documentation address. Substitute the origin IP only when testing your own service. If the request reaches the application outside Cloudflare, the WAF can be bypassed.
At the hosting firewall, allow HTTP and HTTPS only from Cloudflare's current published IP ranges, plus a documented health-check or management path if required, then deny other Internet sources. Keep console access and test one protocol at a time; an incorrect firewall rule can remove your own access. Cloudflare specifically recommends blocking non-Cloudflare connections to the origin.
Use authenticated origin pulls or another origin-to-edge authentication mechanism where available. Set origin TLS to strict certificate validation. Restore the real visitor IP using the provider's supported web-server module and trusted proxy ranges; otherwise every request may appear to come from Cloudflare, making rate limits and investigations rather silly.
Step 5: observe before tightening
Browse the site, log in, submit forms, upload permitted files, use the API and complete a purchase or other critical workflow. Review WAF events for at least several normal traffic cycles. Create narrow exceptions by hostname, route, method, parameter and rule ID. Avoid “skip the WAF for /api/”, which translates to “protect everything except the interesting bit”.
Practical option B: OWASP ModSecurity and CRS with Docker
The official CRS container can act as a reverse proxy in front of an existing application. Start in detection-only mode on a lab host. This example protects a harmless demonstration backend:
# compose.yaml
services:
app:
image: traefik/whoami:v1.11
expose:
- "80"
waf:
image: owasp/modsecurity-crs:4.25-lts-nginx
depends_on:
- app
ports:
- "8080:8080"
environment:
BACKEND: "http://app:80"
SERVER_NAME: "localhost"
PORT: "8080"
MODSEC_RULE_ENGINE: "DetectionOnly"
Only the WAF port is published. The backend is reachable inside the Compose network but is not mapped to the host.
Start it and inspect the baseline:
docker compose up -d
docker compose ps
curl -i http://127.0.0.1:8080/
docker compose logs --tail=100 waf
Test a benign marker against this local lab endpoint:
curl -iG http://127.0.0.1:8080/ \
--data-urlencode 'search=<script>alert(1)</script>'
docker compose logs --since=2m waf
In DetectionOnly mode the request should still reach the demonstration application, while the WAF log should show the matched CRS rule and transaction details. If there is no event, verify that the requested image exists, CRS loaded successfully and the command is reaching port 8080.
After normal application tests and false-positive tuning, change:
MODSEC_RULE_ENGINE: "On"
Then recreate the WAF and repeat the same lab request:
docker compose up -d --force-recreate waf
curl -iG http://127.0.0.1:8080/ \
--data-urlencode 'search=<script>alert(1)</script>'
The blocking response is commonly HTTP 403, but validate the actual status and log action rather than assuming. Also repeat every legitimate workflow. A WAF that blocks the checkout is secure in the same sense that unplugging the server is secure.
For production, add proper certificates, persistent or central audit logging, health checks, resource limits, monitoring, high availability and a pinned image digest. Never publish the backend port alongside the proxy.
How to tune a false positive safely
Suppose a legitimate article preview sends HTML in the content parameter and CRS rule 941100 alerts. Do not disable the entire XSS rule family. Scope an exclusion to the exact route, parameter and rule:
# REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf
SecRule REQUEST_URI "@streq /api/articles/preview" \
"id:100100,phase:1,pass,nolog,ctl:ruleRemoveTargetById=941100;ARGS:content"
The example removes one argument from one rule on one route. It does not disable rule 941100 everywhere. Before deploying it:
- confirm that the application safely handles and sanitises
content; - test authenticated and unauthenticated variants;
- record the CRS rule, route, parameter, owner and expiry or review date;
- keep the original event available for comparison;
- rerun positive and negative security tests.
Prefer an application fix when the alert reveals genuinely unsafe behaviour. An exclusion is for known-valid input, not for making an embarrassing alert disappear.
WordPress baseline with a WAF
A WAF helps a WordPress site, but the platform still needs ordinary hardening:
- keep WordPress core, themes and plugins supported and updated;
- remove inactive plugins and themes rather than merely disabling them;
- require multi-factor authentication for administrators;
- use unique administrator accounts and least privilege;
- protect backups and verify restoration;
- disable file editing in the dashboard where appropriate;
- rate-limit login and password-reset routes;
- monitor new users, changed plugins and modified files;
- ensure the origin cannot be reached around the cloud WAF.
The small red-team toolkit for your own public systems shows how to inventory a WordPress site and public IP without turning the assessment into an uncontrolled attack.
API-specific checks
APIs need controls that generic attack signatures cannot supply. Define allowed methods and content types per route, enforce body-size limits, validate requests against a schema, and apply authentication and object-level authorisation inside the application.
For example, an endpoint that only accepts JSON should reject another content type before parsing:
app.post('/api/orders', express.json({ limit: '64kb' }), (req, res, next) => {
if (!req.is('application/json')) {
return res.status(415).json({ error: 'application/json required' });
}
next();
});
The WAF can enforce a similar edge policy, but the application should still fail safely if traffic reaches it through an internal path, a test environment or a future architecture change.
How to test a WAF without attacking strangers
Use a staging environment or a local demonstration backend you own. Build a repeatable test set:
- normal browsing, login, logout and password reset;
- valid and invalid form submissions;
- file uploads at, below and above the limit;
- every API method and content type the client uses;
- one benign marker expected to trigger each important rule class;
- requests that must be rate-limited;
- a direct-origin request that must fail;
- health checks, monitoring, webhooks and search-engine crawlers.
Record the expected HTTP status, WAF action and application result. Run the suite after rule, application, CDN and reverse-proxy changes. Test both IPv4 and IPv6; many “protected” origins have an overlooked AAAA record or IPv6 firewall policy.
Do not send test payloads to systems you do not own or have permission to assess. Provider acceptable-use rules also apply to hosted scanners and test servers.
Logs and incident handling
At minimum, retain:
- timestamp and WAF rule ID;
- action: allow, log, challenge or block;
- hostname, method and route;
- source and authenticated actor when available;
- request or trace ID shared with the application;
- response status and origin status;
- ruleset and configuration version.
Avoid logging passwords, session cookies, authorisation headers, payment data or complete bodies by default. If short-term payload capture is necessary for an investigation, restrict access, define retention and redact secrets.
Classify a WAF match as:
- noise — a malformed or irrelevant request with no vulnerable route;
- probe — a plausible test that was blocked or safely rejected;
- attempted exploitation — a request matched a real vulnerable condition but was stopped;
- confirmed incident — independent evidence shows unintended application behaviour or consequences.
The label should describe the evidence, not the analyst's mood.
Deployment checklist
- Every protected hostname and API route is inventoried.
- The WAF is actually in the request path.
- Direct origin access is blocked or strongly authenticated.
- TLS is validated between the WAF and origin.
- Detection-only observation happened before broad blocking.
- Critical legitimate workflows have automated tests.
- Exceptions are narrow, documented and reviewed.
- WAF and application logs share a request identifier.
- Secrets are excluded from routine logs.
- Rules, engine and container images have an update owner.
- Capacity, health checks and fail-open or fail-closed behaviour are documented.
- The application remains patched and securely coded.
- Incident responders know what a WAF alert does and does not prove.
Frequently asked questions
Does a WAF stop DDoS attacks?
It can rate-limit or absorb some HTTP-layer abuse, especially when provided by a large cloud network. It does not by itself stop every network- or transport-layer DDoS attack. Treat DDoS protection, caching, rate limiting and WAF inspection as related but distinct capabilities.
Is a WAF the same as a network firewall?
No. A network firewall commonly controls addresses, ports and protocols. A WAF interprets HTTP details such as the hostname, route, method, header, cookie and body. You normally need both when you operate the underlying network.
Will a WAF make an old WordPress site safe?
No. It can reduce exposure to some request patterns and buy time, but it cannot make abandoned plugins trustworthy or repair stolen credentials. Patch, remove unsupported components, harden administration and monitor changes.
Is Cloudflare Free enough?
For a small public site it is a sensible baseline: a maintained edge, a limited free managed ruleset, five custom rules, one rate-limiting rule and short-retention analytics. It is not feature-equivalent to paid plans and still requires origin restriction, TLS configuration and operational review.
Which open-source option should I choose?
Choose ModSecurity with OWASP CRS when your team already operates Nginx or Apache and values the mature ecosystem. Consider Coraza when Go or Caddy integration fits the architecture. Consider BunkerWeb when an integrated reverse proxy and UI justify the larger platform. The best option is the one your team can update, test, monitor and recover at 03:00.
Related reading
- What is Data Injection?
- How to Detect Data Injection
- Data Injection Prevention
- Sigma Rules for Detecting Injection Attacks
- LINUX IS NOT SECURE! A practical server-hardening manual
References
- OWASP: Web Application Firewall
- OWASP: Virtual Patching Cheat Sheet
- OWASP ModSecurity
- OWASP CRS installation
- Official ModSecurity and CRS container images
- OWASP Coraza introduction
- BunkerWeb quick-start documentation
- Cloudflare WAF overview
- Cloudflare WAF get started
- Cloudflare custom-rule availability
- Cloudflare Security Analytics availability
- Cloudflare: protect the origin server
Safety boundary
Deploy and test WAF controls only on websites, APIs, servers and accounts you own or are explicitly authorised to administer. Begin in a lab or detection-only mode, keep recovery access, and do not use Internet systems as an unsolicited test range.