People use the word firewall for several different things, and mixing them up leads to false confidence. Someone says "we have a firewall" and means a rule on a server that blocks port 3306. Someone else hears it and assumes the site is protected against hacked plugins. Those are two very different claims, and only one of them is true.
There are two layers worth keeping apart: the network firewall, which decides who may connect at all, and the web application firewall, which reads web requests and judges what they are trying to do. A third thing, the host-level defences your provider runs for every customer, sits around both. This article explains what each one actually does, what it cannot do, and how to set them up without locking out your own customers.
The network firewall
A network firewall decides which connections are allowed at all, based on addresses and ports. It is the reason a database on your server cannot be reached from the internet, and the reason only the web ports are open to the world. It is simple, fast, and the first thing to set up on any server you run.
It does not look at what is inside the traffic. If port 443 is open, the firewall will let any well-formed HTTPS connection through to your web server, including one carrying an attack on a vulnerable plugin. From its point of view, that is just a visitor.
A reasonable baseline for a small web server looks like this:
| Port | Service | Who should reach it |
|---|---|---|
| 80, 443 | HTTP and HTTPS | Everyone |
| 22 | SSH | Your own addresses only, or key-based login with rate limiting |
| 25, 465, 587, 993 | Mail services, if you run mail here | Everyone, but watched |
| 3306 | MySQL or MariaDB | Nobody outside the server, unless a specific address needs it |
| 6379 | Redis | Localhost only |
On shared hosting you do not manage this layer; your provider does. On a VPS it is yours, typically through ufw, firewalld, nftables or a firewall page in the provider's console. A common mistake is opening a database port "just for a day" to let a developer connect, then forgetting it. Within hours, automated scanners find it and begin guessing passwords.
sudo ufw default deny incoming
sudo ufw allow 80,443/tcp
sudo ufw allow from 203.0.113.25 to any port 22 proto tcp
sudo ufw enable
The web application firewall
A web application firewall, or WAF, inspects web requests themselves and blocks the ones that look malicious: SQL injection attempts, attempts to read system files, known exploit patterns, floods of login attempts. It understands HTTP, so it can see the URL, the headers and the body of a form post, which the network firewall never opens.
It can live in three places: on your server (ModSecurity with a rule set is a common arrangement), at your host, or at a CDN or proxy in front of the site. The further out it sits, the less junk reaches your server at all. A WAF in front of the site also absorbs floods that would otherwise use up your account's CPU allowance.
What it buys you
A lot of automated attacks are blocked before they touch your application. Most traffic hitting a public WordPress site is not a person targeting you; it is software trying the same hundred known tricks against every address it can find. A WAF rule set recognises most of them by shape.
It also buys time. When a vulnerability in a popular plugin is announced, there is a gap between the announcement, the fixed release, and you installing it. Rules for the exploit can often be deployed within hours, so the gap is covered while you update. And it cuts noise: your logs get shorter, and the load from bad bots falls.
What it does not do
It does not fix vulnerable code. If a plugin has a flaw, the WAF might hide the usual ways of reaching it, but the flaw is still there, and a determined attacker with a custom approach may pass. A WAF is a screen, not a repair.
It can also block legitimate users. A form that includes the word "select" in free text can look like a SQL query. A page builder that posts large, unusual blobs of data can look like an exploit. An admin action that uploads a file with an odd extension may be refused. Typical signs of a false positive:
- Something works for you but fails for a customer, or the other way round.
- An admin action returns a 403 Forbidden page that is not your site's own error page.
- A saved post loses content, or a form submits and nothing happens.
- The failure only occurs with certain text in a field.
In each case, look at the firewall log first. It will name the rule that fired and the part of the request that matched.
A worked example of a false positive
A small training company adds a "course notes" field to its booking form. A customer pastes a note beginning "Please select a morning session; drop me an email if full". Submissions with that text vanish and the customer sees a plain 403 page. The company's own staff cannot reproduce it, because they type shorter notes.
The firewall log shows a rule about SQL injection firing on the combination of "select" and "drop" in a POST body. The text is harmless; the pattern is what matters. The fix is not to switch the WAF off. It is to add an exception for that single rule on that single form URL, then retest with the original text. The rest of the site stays protected, and the rule keeps catching genuine attempts elsewhere.
The same technique works with any rule engine: find the rule identifier, find the URL or parameter, exclude narrowly, retest.
Practical setup
- Keep the network layer tight. Open only the ports you use, and restrict SSH.
- Turn on the WAF your host or CDN offers, in monitoring (log-only) mode first if possible.
- Leave it in that mode for a week and read what it would have blocked. Real customers will appear in that list; note the rules involved.
- Add narrow exceptions for legitimate features, then switch to blocking.
- Keep checking the log after any plugin or theme change, because new features post new kinds of data.
- Combine it with updates, strong passwords and two-factor authentication. No single layer is enough.
Keep a note of every exception you add, with the date and the reason. Six months later, when someone asks why a rule is off for the booking form, that note is the difference between a quick answer and an afternoon of archaeology. Review the list when you retire a feature, because exceptions have a way of outliving the things they were made for.
Rate limiting on the login page is worth special mention. Even a modest limit, a few failed attempts per minute per address, removes most password-guessing traffic with no effect on real people.
Shared, VPS, dedicated and managed
On shared hosting, the provider runs both layers and usually applies a common WAF rule set across the server. You can seldom edit the rules, but you can ask support to look at a blocked request or to add an exception. On a VPS you choose everything: a host firewall, ModSecurity or a similar module, or a CDN in front. That gives control but also the job of keeping rules updated. On dedicated servers the same applies, with more traffic to protect. Managed WordPress plans typically bundle a WAF and a rule update service, which suits people who want it handled, at the price of less visibility into individual decisions.
For bots and traffic spikes specifically, see why a site slows down at 3 p.m. in this series, and the troubleshooting guide for a general order of checks.
Reading a block
When a firewall refuses a request, the evidence is usually in one of three places: the block page shown to the visitor (often with a reference number), the WAF's own audit log, or the web server's error log. A ModSecurity entry, for example, names the rule by number and shows the matched fragment. Copy the rule number, the URL and the time, and you have what you need for an exception or a support request.
Resist the urge to disable a rule set because a single rule misfired. Rule sets are long, and most of that length is doing its job unnoticed. Removing one rule for one URL costs very little protection. Removing the whole set costs all of it.
Commands worth running
From another machine, test which ports answer. A closed port times out or refuses; an open one answers.
nc -vz example.com 443
nc -vz example.com 3306
curl -I https://example.com/
If 3306 answers from the internet, close it. To see whether a WAF is in front of a site, look at the response headers from curl -I; some proxies add a name, though many hide it. To test a suspected false positive, repeat the exact request from a browser and from curl, then compare the status code and any reference number on the block page, which support can use to find the rule.
Loose ends
Do I need a WAF if I keep everything updated?
Updates are the better defence, but they arrive after the problem. A WAF covers the gap and the unknowns, and costs little to run.
Will a firewall stop DDoS attacks?
Small floods, yes. A large attack saturates the connection before it reaches your firewall, which is a job for your host's upstream filtering or a CDN.
Why was my own IP blocked?
Repeated failed logins, a plugin scan from your office, or a shared address that someone else misused. Ask your host to check and unblock, and consider allow-listing a fixed address.
Is a free WAF plugin the same as a network WAF?
Not quite. A plugin runs inside WordPress, so the request has already reached PHP. It helps, but a filter in front of the server is stronger.