---
title: "What is a WAF and when to use one on sites and APIs | StreetHosting"
description: "A WAF is a firewall that inspects HTTP requests. Learn ModSecurity with OWASP CRS, Coraza, CDN WAFs, false positives, and when to use one on sites and APIs."
url: "https://streethosting.com.br/en/guides/infrastructure/what-is-a-waf"
type: "page"
language: "en-US"
---

Infrastructure · 11 min · Intermediate

Published on Sep 28, 2026 · Updated on Sep 28, 2026

# What is a WAF: the firewall that reads HTTP requests

A WAF inspects the content of every request and blocks injections, XSS and exploitation of known vulnerabilities. See the deployment models, how to install ModSecurity with the OWASP CRS on Nginx, and how to tune it without breaking your site.

By [Equipe StreetHosting](https://streethosting.com.br/en/autores#equipe-streethosting) · StreetHosting infrastructure and support team

[Security and hardening](https://streethosting.com.br/en/guides/topics/security) [Linux administration](https://streethosting.com.br/en/guides/topics/linux) [Network, DNS and domains](https://streethosting.com.br/en/guides/topics/networking)

Summarize with:

[](https://chat.openai.com/?q=Summarize%20the%20key%20points%20of%20this%20StreetHosting%20guide%3A%20https%3A%2F%2Fstreethosting.com.br%2Fen%2Fguides%2Finfrastructure%2Fwhat-is-a-waf.%20Highlight%20the%20step-by-step%20instructions%2C%20the%20prerequisites%20and%20the%20most%20common%20mistakes. "ChatGPT") [](https://claude.ai/new?q=Summarize%20the%20key%20points%20of%20this%20StreetHosting%20guide%3A%20https%3A%2F%2Fstreethosting.com.br%2Fen%2Fguides%2Finfrastructure%2Fwhat-is-a-waf.%20Highlight%20the%20step-by-step%20instructions%2C%20the%20prerequisites%20and%20the%20most%20common%20mistakes. "Claude") [](https://www.google.com/search?udm=50&aep=11&q=Summarize%20the%20key%20points%20of%20this%20StreetHosting%20guide%3A%20https%3A%2F%2Fstreethosting.com.br%2Fen%2Fguides%2Finfrastructure%2Fwhat-is-a-waf.%20Highlight%20the%20step-by-step%20instructions%2C%20the%20prerequisites%20and%20the%20most%20common%20mistakes. "Google AI Mode") [](https://x.com/i/grok?text=Summarize%20the%20key%20points%20of%20this%20StreetHosting%20guide%3A%20https%3A%2F%2Fstreethosting.com.br%2Fen%2Fguides%2Finfrastructure%2Fwhat-is-a-waf.%20Highlight%20the%20step-by-step%20instructions%2C%20the%20prerequisites%20and%20the%20most%20common%20mistakes. "Grok") [](https://www.perplexity.ai/search/new?q=Summarize%20the%20key%20points%20of%20this%20StreetHosting%20guide%3A%20https%3A%2F%2Fstreethosting.com.br%2Fen%2Fguides%2Finfrastructure%2Fwhat-is-a-waf.%20Highlight%20the%20step-by-step%20instructions%2C%20the%20prerequisites%20and%20the%20most%20common%20mistakes. "Perplexity")

Share:

[](https://x.com/intent/tweet?text=What%20is%20a%20WAF%20and%20when%20to%20use%20one%20on%20sites%20and%20APIs&url=https%3A%2F%2Fstreethosting.com.br%2Fen%2Fguides%2Finfrastructure%2Fwhat-is-a-waf "Share on X") [](https://www.facebook.com/sharer/sharer.php?u=https%3A%2F%2Fstreethosting.com.br%2Fen%2Fguides%2Finfrastructure%2Fwhat-is-a-waf "Share on Facebook") [](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fstreethosting.com.br%2Fen%2Fguides%2Finfrastructure%2Fwhat-is-a-waf "Share on LinkedIn") [](https://wa.me/?text=What%20is%20a%20WAF%20and%20when%20to%20use%20one%20on%20sites%20and%20APIs%20https%3A%2F%2Fstreethosting.com.br%2Fen%2Fguides%2Finfrastructure%2Fwhat-is-a-waf "Share on WhatsApp")

For agents: Copy as Markdown [.md](https://streethosting.com.br/en/guides/infrastructure/what-is-a-waf.md)

In this guide 8 sections

* [What a WAF is and what it sees](https://streethosting.com.br/en/guides/infrastructure/what-is-a-waf#o-que-e)
* [Three ways to run a WAF](https://streethosting.com.br/en/guides/infrastructure/what-is-a-waf#modelos)
* [ModSecurity with OWASP CRS on Nginx](https://streethosting.com.br/en/guides/infrastructure/what-is-a-waf#modsecurity)
* [Coraza, the Go alternative](https://streethosting.com.br/en/guides/infrastructure/what-is-a-waf#coraza)
* [Start in detection mode](https://streethosting.com.br/en/guides/infrastructure/what-is-a-waf#deteccao)
* [How to handle false positives](https://streethosting.com.br/en/guides/infrastructure/what-is-a-waf#falsos-positivos)
* [When a WAF is worth it](https://streethosting.com.br/en/guides/infrastructure/what-is-a-waf#quando-usar)
* [CPU cost and where to run it](https://streethosting.com.br/en/guides/infrastructure/what-is-a-waf#onde-rodar)

Quick answer

A **WAF** (Web Application Firewall) is a layer 7 firewall: instead of looking only at IP and port, it reads every HTTP request and blocks attack patterns such as SQL injection, XSS and exploitation of known vulnerabilities. It can run on the CDN, as a web server module (ModSecurity or Coraza with the OWASP CRS) or as a separate proxy. It is worth it for sites with logins, forms and plugins, always starting in detection mode.

## What a WAF is and what it sees[](https://streethosting.com.br/en/guides/infrastructure/what-is-a-waf#o-que-e)

A network firewall such as UFW answers a simple question: may this connection reach this port? For a website, the answer on port 443 has to be yes for everyone, and that open port is where the attacks against the application come in. The WAF picks up after that. It sees the method, the URL, the parameters, the headers, the cookies and the request body, and compares all of it against a rule set. The conceptual comparison between the two is in [network and application firewalls](https://streethosting.com.br/en/guides/infrastructure/network-firewall-vs-application-firewall); here the focus is how a WAF works in practice.

What a WAF with a good rule set usually blocks:

* SQL injection in parameters and forms;
* XSS, when someone tries to submit a script to be displayed to other users;
* local and remote file inclusion and directory traversal;
* operating system commands injected into fields;
* known scanning tools and requests that violate the HTTP protocol.

The OWASP Core Rule Set, the most widely used rule set, works on anomaly scoring. Each rule that matches adds points to the request, 5 for a critical match, and the decision comes at the end: it blocks when the total reaches the threshold, 5 by default. One critical match is enough; lesser warnings have to add up. Sensitivity is tuned in a single place.

What it does not do: it does not fix logic errors, it does not notice that one user accessed another user's order, it does not detect a login with a leaked password that is still valid, and it does not hold back volumetric DDoS. A WAF is one layer, not the whole security of the application.

## Three ways to run a WAF[](https://streethosting.com.br/en/guides/infrastructure/what-is-a-waf#modelos)

| Model             | Where it runs                                    | Advantage                                                             | Limitation                                                                                      |
| ----------------- | ------------------------------------------------ | --------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- |
| CDN WAF           | At the CDN edge, before the VPS                  | Filters before spending VPS CPU and bandwidth                         | Only protects if the origin accepts traffic from the CDN alone; advanced rules are usually paid |
| Web server module | Inside Nginx, on the VPS itself                  | Full control of the rules, no license, sees traffic already decrypted | Uses VPS CPU and RAM; tuning and maintenance are on you                                         |
| Separate proxy    | A process or machine in front of the application | Isolates the WAF and serves several systems at once                   | One more component to operate and one more network hop                                          |

The CDN WAF has a weak spot almost nobody checks: if the VPS's real IP leaks, through an old DNS record or an email sent straight from the server, the attacker talks to the origin and skips the whole protection. So when you use a CDN, lock ports 80 and 443 on the VPS down to the IP ranges the CDN publishes, with source rules in [UFW](https://streethosting.com.br/en/guides/vps/ufw-firewall-ubuntu-vps). And configure Nginx to recover the visitor's true IP with `set_real_ip_from` and `real_ip_header`, using the header the CDN documents. Without that, logs, blocks and rate limits see every visitor as if it were the CDN itself.

## ModSecurity with OWASP CRS on Nginx[](https://streethosting.com.br/en/guides/infrastructure/what-is-a-waf#modsecurity)

ModSecurity started out as an Apache module. Version 3 split the engine into a library, libmodsecurity, hooked into Nginx through a connector. In 2024 the project moved to OWASP. The engine alone blocks nothing: what defines an attack is the OWASP Core Rule Set, the CRS. On Ubuntu 24.04 both live in the universe repository, which is enabled on a default install:

`sudo apt update sudo apt install libnginx-mod-http-modsecurity modsecurity-crs`

The first package brings the Nginx module and `/etc/nginx/modsecurity.conf`, with the engine configuration. The second installs CRS 3.3, with its settings in `/etc/modsecurity/crs/crs-setup.conf` and the rules in `/usr/share/modsecurity-crs/rules/`. One detail breaks a lot of installs: the file the CRS package uses to load the rules was written for Apache and uses the IncludeOptional directive, which libmodsecurity does not recognize. The safest path is to list everything with Include in the file Nginx reads:

`# /etc/nginx/modsecurity_includes.conf Include /etc/nginx/modsecurity.conf Include /etc/modsecurity/crs/crs-setup.conf Include /etc/modsecurity/crs/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf Include /usr/share/modsecurity-crs/rules/*.conf Include /etc/modsecurity/crs/RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf`

Order matters: settings, then the exclusions that act before the rules, then the rules, and last the exclusions that modify rules already loaded. Next, enable the module in the site's server block, the same one you built in the guide on [reverse proxy with Nginx](https://streethosting.com.br/en/guides/vps/nginx-reverse-proxy-vps):

`server { server_name seu-dominio.com.br; modsecurity on; modsecurity_rules_file /etc/nginx/modsecurity_includes.conf; location / { proxy_pass http://127.0.0.1:3000; } }`

Validate and reload with `sudo nginx -t && sudo systemctl reload nginx`. To confirm the rules are active, send a request the CRS recognizes as command execution. In detection mode the response goes through normally and the hit goes to the log; with blocking on, it becomes a 403:

`curl -s -o /dev/null -w "%{http_code}\n" "https://seu-dominio.com.br/?exec=/bin/bash" sudo tail -n 20 /var/log/nginx/error.log | grep ModSecurity`

The paranoia level, from 1 to 4, lives in `crs-setup.conf`. Level 1, the default, catches the common attacks with few false positives and is the right one for almost every site. Each level above adds more suspicious rules and a lot more tuning work. CRS 4, the current series, is not in the Ubuntu 24.04 repositories and is installed from the releases published on the project's GitHub.

## Coraza, the Go alternative[](https://streethosting.com.br/en/guides/infrastructure/what-is-a-waf#coraza)

OWASP Coraza is a WAF engine written in Go that understands the same rule language as ModSecurity and runs the CRS without adaptation. It makes sense when your proxy is not Nginx:

* **Caddy:** the `coraza-caddy` module goes into a Caddy binary compiled with xcaddy, and the Caddyfile directive ships with the CRS built in.
* **Envoy:** runs as a WebAssembly filter, through the `coraza-proxy-wasm` project, common in Kubernetes clusters.
* **HAProxy:** talks to Coraza over SPOA, with the WAF in a separate process.
* **Go application:** it can be used as a library, inside your own code.

`xcaddy build --with github.com/corazawaf/coraza-caddy/v2`

With Nginx on Ubuntu, ModSecurity remains the path of least friction, because it comes packaged. Detection and false positives, covered next, work the same on both, since rules and directives are identical.

## Start in detection mode[](https://streethosting.com.br/en/guides/infrastructure/what-is-a-waf#deteccao)

The CRS does not know your application. A rich text editor that submits HTML, a search field where someone types a snippet of SQL, an API that receives code inside a JSON body: all of that looks like an attack to a generic rule. Turning blocking on from day one is the fastest way to take down your own login or your own checkout.

That is why the package's modsecurity.conf ships with `SecRuleEngine DetectionOnly`: the rules run, hits are logged, but nothing is blocked. Leave it that way for one or two weeks of real traffic, going through every flow in the system. Hits show up in the Nginx error log as lines with ModSecurity: Warning, containing the rule id, the variable that matched and the URI. Two queries show the picture:

`# latest full hits sudo grep "ModSecurity: Warning" /var/log/nginx/error.log | tail -n 5 # rules that fire the most sudo grep -o '\[id "[0-9]*"\]' /var/log/nginx/error.log | sort | uniq -c | sort -rn | head`

Separate two groups. Hits from unknown IPs, on paths that do not exist on your site, are real attacks and show the WAF is doing its job. Hits from your own users, always on the same route and the same field, are false positives and call for an exclusion. When the second group drops to zero, switch to blocking:

`sudo sed -i 's/^SecRuleEngine DetectionOnly/SecRuleEngine On/' /etc/nginx/modsecurity.conf sudo nginx -t && sudo systemctl reload nginx`

The full record of every flagged request, with headers and body, goes to the file set in SecAuditLog in modsecurity.conf. It helps a lot with tuning, but it grows fast and may store personal data submitted through forms. Watch its size and treat the file as sensitive.

## How to handle false positives[](https://streethosting.com.br/en/guides/infrastructure/what-is-a-waf#falsos-positivos)

The golden rule is to exclude as little as possible: one rule, on one field, on one route. Turning the whole WAF off because of one form, or lowering the anomaly threshold for the entire site, throws away protection where it was not getting in the way. The CRS reserves two files for this.

**Before the rules**, in the `REQUEST-900` file, go the exclusions that depend on the request. Example: the admin panel editor at /admin/editor submits HTML in the conteudo field and triggers rule 941100, which detects XSS through libinjection. The exclusion removes only that field from that rule, and only on that route:

`# /etc/modsecurity/crs/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf SecRule REQUEST_URI "@beginsWith /admin/editor" \ "id:10001,phase:1,pass,nolog,ctl:ruleRemoveTargetById=941100;ARGS:conteudo"`

**After the rules**, in the `RESPONSE-999` file, go the fixed exclusions, which apply to the whole site. Example: a programming forum where the busca field receives SQL snippets all the time and triggers 942100, which detects SQL injection through libinjection:

`# /etc/modsecurity/crs/RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf SecRuleUpdateTargetById 942100 "!ARGS:busca"`

* Use your own ids that do not collide with the CRS ones, which occupy the range starting at 900000.
* The `ctl:ruleRemoveById` action removes the entire rule from the request and is cruder. Prefer removing only the target, as in the example.
* For WordPress, Drupal, Nextcloud and other well-known systems, CRS 3.3 ships ready-made exclusion packages, enabled in `crs-setup.conf`. In CRS 4 they became plugins installed separately. If your case is [WordPress on a VPS with Nginx](https://streethosting.com.br/en/guides/vps/host-wordpress-on-vps-nginx), start with those.
* After each exclusion, run `sudo nginx -t`, reload, repeat the action that was triggering and check the log.

Resist the temptation to exclude your own office or your own user by IP. If that account is compromised, the attacker inherits the exception. A good exclusion is by route and field, not by person.

## When a WAF is worth it[](https://streethosting.com.br/en/guides/infrastructure/what-is-a-waf#quando-usar)

| Scenario                                      | Recommendation                                                                              |
| --------------------------------------------- | ------------------------------------------------------------------------------------------- |
| Static corporate site                         | Optional; caching, security headers and an up-to-date server solve more                     |
| WordPress or another CMS with plugins         | Worth it; it is the classic target of mass exploitation of a vulnerable plugin              |
| Store or system with login and forms          | Worth it, starting in detection mode                                                        |
| JSON API consumed by your own app             | Useful extra layer; authentication, per-object permissions and per-token limits matter more |
| Legacy system that no longer receives updates | Highly recommended, as virtual patching while there is no replacement                       |
| Game server such as Minecraft                 | Does not apply; the protocol is not HTTP, the defense is firewall and Anti-DDoS             |

The most valuable use of a WAF is virtual patching. When a serious vulnerability drops in a plugin or framework, mass exploitation starts within days, sometimes hours. The generic CRS rules usually catch a good share of those payloads, and a rule specific to the flaw can be written on the spot, buying time until the update is applied.

On APIs, the CRS inspects JSON bodies too, but the number one risk on the OWASP API security list is broken object level authorization: the client swaps the id in the URL and reads someone else's data. No generic WAF sees that, because the request is perfectly valid. The overview of the other layers is in [how to protect a web application against attacks](https://streethosting.com.br/en/guides/infrastructure/protect-web-application-from-attacks).

## CPU cost and where to run it[](https://streethosting.com.br/en/guides/infrastructure/what-is-a-waf#onde-rodar)

With the WAF on the server, every request runs through hundreds of rules before reaching the application. The cost grows with body size, with the paranoia level and with response inspection. On a small VPS running WordPress, PHP and the WAF compete for the same cores. That also explains why the WAF alone cannot hold back a flood of requests: it spends CPU on every one of them. Against that scenario, rate limiting and the edge work better, as shown in the guide on [layer 7 DDoS](https://streethosting.com.br/en/guides/infrastructure/layer-7-ddos-attack). IPs the WAF blocks repeatedly can go to [Fail2Ban](https://streethosting.com.br/en/guides/vps/fail2ban-ssh-vps-setup), with a dedicated filter for those log lines.

The [StreetHosting VPS plans](https://streethosting.com.br/en/vps) are KVM with root access, so you install whatever module you want, and they sit in São Paulo with Anti-DDoS included in the network, covering the volumetric layer the WAF does not. For a WordPress site or a store with ModSecurity, PHP and the database on the same machine, the Ryzen 9 9950X VPS with 4 vCPU, 8 GB DDR5 and 80 GB NVMe, at R$ 118.00 per month, leaves headroom for the rules without squeezing the application. For a lighter API, the Xeon VPS with 4 vCPU and 6 GB goes for R$ 60.00. The entry plans, at R$ 26.00 on the Xeon and R$ 40.00 on the Ryzen, are good for tuning the configuration before production.

In this guide

* [What a WAF is and what it sees](https://streethosting.com.br/en/guides/infrastructure/what-is-a-waf#o-que-e)
* [Three ways to run a WAF](https://streethosting.com.br/en/guides/infrastructure/what-is-a-waf#modelos)
* [ModSecurity with OWASP CRS on Nginx](https://streethosting.com.br/en/guides/infrastructure/what-is-a-waf#modsecurity)
* [Coraza, the Go alternative](https://streethosting.com.br/en/guides/infrastructure/what-is-a-waf#coraza)
* [Start in detection mode](https://streethosting.com.br/en/guides/infrastructure/what-is-a-waf#deteccao)
* [How to handle false positives](https://streethosting.com.br/en/guides/infrastructure/what-is-a-waf#falsos-positivos)
* [When a WAF is worth it](https://streethosting.com.br/en/guides/infrastructure/what-is-a-waf#quando-usar)
* [CPU cost and where to run it](https://streethosting.com.br/en/guides/infrastructure/what-is-a-waf#onde-rodar)

## Frequently asked questions

Does a WAF replace the VPS firewall?

No. The network firewall decides which ports accept connections and is still what closes off databases, control panels and internal services. The WAF only acts on HTTP traffic that already passed through that firewall, reading the content of the requests. The two work together.

Does a WAF slow down the site?

It adds processing to every request, because each one runs through hundreds of rules. On ordinary pages the difference is usually small, but it grows with large bodies, uploads and a high paranoia level. Measure response time and CPU usage before and after turning it on.

Is ModSecurity still maintained?

Yes. In 2024 the project moved to OWASP, which already maintained the Core Rule Set. Version 3, used with Nginx, remains active, and CRS 4 is the current rule series. Ubuntu 24.04 still packages CRS 3.3, which remains functional as a starting point.

Can I use the CDN's WAF and ModSecurity at the same time?

Yes. The CDN filters the bulk before any VPS CPU is spent, and ModSecurity inspects what got through, with rules you control. The cost is tuning false positives in two places. If the origin is locked down to accept only the CDN, many people stick with the edge WAF alone.

Does a WAF protect an API?

Partly. It blocks injections and known malicious payloads in JSON bodies too, but it has no idea whether user 15 is allowed to read user 16's order. For an API, token authentication, per-object permission checks, schema validation and rate limiting matter more than the WAF.

Next step

See VPS plans

Root VPS in Brazil with NVMe and Anti-DDoS.

[See VPS plans](https://streethosting.com.br/en/vps)

[See Ryzen VPS Ryzen 9 9950X VPS in São Paulo with root access, NVMe and gamer Anti-DDoS.](https://streethosting.com.br/en/vps/ryzen) [See Xeon VPS Xeon VPS for steady workloads, automation and long-running projects.](https://streethosting.com.br/en/vps/xeon)

## Related guides

[Infrastructure Intermediate Protect a web application from attacks: defense in layers No single tool protects a web application on its own. This guide organizes the defenses in layers, from the network port to the log, and shows what to configure first on a VPS running Nginx. 10 min Read guide](https://streethosting.com.br/en/guides/infrastructure/protect-web-application-from-attacks) [Infrastructure Intermediate Network firewall vs. application firewall: what is the difference A network firewall decides which ports and IPs get through. An application firewall understands the content of web requests. They are different layers that together make a solid defense. 3 min Read guide](https://streethosting.com.br/en/guides/infrastructure/network-firewall-vs-application-firewall) [Infrastructure Advanced Layer 7 DDoS: what an application layer attack is and how to mitigate it A volumetric DDoS clogs your bandwidth. A layer 7 attack is subtler: it mimics real users to exhaust the server's CPU and queue with little traffic. Here is why it fools filters and how to mitigate it. 3 min Read guide](https://streethosting.com.br/en/guides/infrastructure/layer-7-ddos-attack)

[← Back to the Guide Center](https://streethosting.com.br/en/guides)
