Understanding what a firewall is takes about a minute: it’s a filter that decides which network traffic gets in and which gets dropped. Actually configuring one well is a different skill — and it’s where most people either freeze up or quietly make their server less safe than they think it is. The gap between “I know what a firewall does” and “I have a clean, correct rule set running” is exactly what this article closes.
The good news is that a solid firewall configuration for a typical server is short. We’re talking about a handful of rules, not a wall of cryptic syntax. The hard part isn’t volume — it’s getting the order right, choosing the right default, and not accidentally cutting off your own access in the process. Once you internalize the small set of principles below, you can configure a firewall on almost any server with confidence.
What “configuring a firewall” actually involves
Configuring a firewall comes down to three decisions, and everything else is detail:
- The default policy — what happens to traffic that no rule explicitly handles. Allow it, or deny it.
- The allow rules — the specific traffic you do want to let through (your web ports, your management access).
- The order — because firewalls evaluate rules top to bottom and stop at the first match, the sequence you list them in changes the outcome.
That’s the whole job. If you’ve read the broader explanation of what these filters do and why, the article on firewalls covers the concept end to end. Here we’re focused on the doing: turning that concept into a correct, running configuration without shooting yourself in the foot.
A FIREWALL CONFIG IS JUST:
default policy → what to do when nothing matches
allow rules → the few things you let through
rule order → first match wins, so sequence matters
The tool changes, the thinking doesn't
Different systems ship different firewall front-ends — some give you a simple command that adds one rule at a time, others expect you to edit a table of rules directly, and cloud platforms hand you a dashboard. The exact commands vary, and that’s fine: this article stays vendor-neutral on purpose. What carries across all of them is the model — default policy, allow rules, ordering, and testing. Learn the model once and every specific tool becomes a matter of looking up syntax, not relearning the idea.
Start from default-deny
There are two philosophies you can build a firewall on, and only one is appropriate for a machine exposed to the internet.
- Default-allow: everything is permitted unless you specifically block it. You’d have to predict every dangerous thing in advance and write a rule against each. Forget one, and it’s wide open.
- Default-deny: everything is blocked unless you specifically allow it. You open only the doors you genuinely need; everything else stays shut without you having to name it.
For a public server, default-deny is the only sane choice. You don’t try to enumerate every possible threat — an impossible task — you simply close everything and then carve out the few exceptions your service actually requires. A forgotten database port, a leftover test service, an admin panel you meant to remove: with default-deny, none of them are reachable, because you never opened them. That single decision eliminates an enormous category of risk for free.
So the very first thing a good configuration does is set the inbound default to deny:
POLICY (inbound): DENY ← block anything not explicitly allowed
POLICY (outbound): ALLOW ← let the server reach out (common default)
Outbound traffic is usually left open to start with — your server needs to fetch updates, talk to other services, send email. Tightening outbound rules is a worthwhile later step for sensitive machines, but inbound is where the protection that matters most lives, so that’s where we focus first.
Allow your own access before you tighten anything
This is the rule that saves you from the single most common firewall disaster, so it gets its own section: before you set the default to deny, make sure the rule that lets you in is already in place and working.
A server has no screen or keyboard you can walk up to. You reach it remotely, almost always over SSH. If you flip the default policy to deny and you haven’t explicitly allowed your SSH port, the firewall will block your own connection the instant it takes effect — and you’ll be locked out of your own machine. People do this constantly. It’s a genuinely stressful way to learn the lesson.
The correct sequence is always:
1. add the rule that allows YOUR access (SSH) ← first, always
2. add the rules for your public services (web)
3. THEN set the default policy to deny
4. test from a second connection before you trust it
If SSH itself is new to you, the SSH basics article explains how that remote login works. The key point for firewalls is simply this: SSH is your lifeline to the machine, so its rule comes first, every single time.
Always keep an escape hatch open
Even with the right order, things go wrong — a typo in a port number, a rule that didn’t apply the way you expected. Two habits protect you. First, keep your current SSH session open while you make changes, and test a brand new connection in a second terminal before closing the first; if the new one fails, you still have the old session to fix things. Second, on a cloud server, learn where the provider’s web console (a browser-based terminal that bypasses SSH) lives before you need it. That console is your way back in if you ever do lock yourself out at the network level.
A minimal, correct rule set
For a huge number of real-world servers, the entire firewall is four or five rules. Here’s what a clean default-deny configuration looks like for a typical web server, written in plain terms so it reads the same regardless of which tool you use:
ALLOW in tcp port 22 from anywhere (SSH — your management access)
ALLOW in tcp port 80 from anywhere (HTTP — usually redirects to HTTPS)
ALLOW in tcp port 443 from anywhere (HTTPS — your actual website)
ALLOW in related/established (replies to connections you started)
DENY in everything else (the default — nothing else gets in)
A few things are worth pointing out about this set:
- Port 22 is SSH, your way in. If you’ve moved SSH to a non-standard port (a common, mild hardening step), this rule uses that port instead. Either way, it comes first.
- Ports 80 and 443 are the public web. If your server isn’t serving websites, you don’t open them at all — open only what you actually run.
- The established/related rule is what lets replies flow back. We’ll cover why that’s needed in a moment.
- The deny everything else line is the default policy doing its job. You don’t write a rule for the database port or the mail port — you simply never open them, and default-deny keeps them dark.
To know which ports you currently have listening (and therefore which you might need to account for), you check what’s bound to the network:
# list services currently listening on network ports
ss -tulpn
Run that on a fresh server and you’ll often find services you didn’t realize were exposed. Each one is either something you open deliberately, or something you should stop and remove — which ties directly into the broader hardening mindset covered in server hardening basics.
Why rule order decides the outcome
Firewalls evaluate rules from top to bottom and act on the first one that matches. After a match, they stop looking. This sounds like a minor implementation detail, but it’s the source of a whole family of confusing bugs, so it’s worth seeing clearly.
Imagine you put a broad “block all incoming” rule near the top, then an “allow port 443” rule below it. Because the block rule matches first, your website traffic never reaches the allow rule — it’s blocked, and you’re left scratching your head wondering why a rule you clearly wrote isn’t working. The rule is working; it’s just being short-circuited by something above it.
incoming packet to :443
│
▼
rule 1: BLOCK all incoming ──► matches ──► dropped (stop)
rule 2: ALLOW port 443 ──► never reached
▲
this is the bug: order is wrong
The fix is the principle that governs all firewall rule sets: specific allow rules go above broad deny rules. List the precise things you want to permit first, and let the catch-all deny sit at the bottom (or live as the default policy, which is effectively the very last word). Get this ordering right and the rest of the configuration tends to just work.
The established-connections rule, and why you need it
Here’s a subtlety that trips up beginners. When a visitor loads your website, their request comes in to port 443 — your allow rule handles that fine. But your server’s reply goes out to some random high-numbered port on the visitor’s machine. If your firewall judged every packet in isolation, that reply would look like unsolicited outbound traffic, and a strict configuration could block it — breaking every connection.
The solution is that modern firewalls are stateful: they remember connections they’ve already approved. When you allow an incoming request, the firewall makes a mental note — “I’m now expecting replies for this conversation” — and automatically permits the return traffic because it belongs to a connection that’s already established. You don’t write a separate rule for every possible reply port; you write one rule that says “allow traffic that’s part of an established or related connection,” and it covers all of them.
Visitor Firewall Server
│ │ │
│ request to :443 │ matches ALLOW rule │
│ ────────────────────► │ (remembers it) │
│ │ ─────────────────────► │
│ │ │
│ ◄─── reply ─────────│ ◄──── reply ──────────│
│ │ auto-allowed: │
│ │ "established" rule │
This is why “allow established/related connections” is almost always one of the first rules in any sensible configuration. It’s the quiet rule that makes everything else function smoothly. Skip it and you’ll find that your allow rules let requests in but somehow nothing seems to work — because the replies can’t get back out.
Don’t forget IPv6
Here’s a trap that catches a lot of people: many systems run two firewalls in parallel — one for IPv4 (the familiar 93.184.216.34-style addresses) and one for IPv6 (the longer 2001:db8::1-style ones). They’re separate rule sets. It’s entirely possible to lock down your IPv4 firewall beautifully and leave the IPv6 one wide open, so that an attacker simply connects over IPv6 and walks right past all your careful work.
The rule is straightforward: whatever you do for IPv4, do for IPv6 too. If you deny by default on one, deny by default on the other. If you allow a port on one, decide consciously whether you want it open on the other. Many higher-level firewall tools apply your rules to both address families at once, which is exactly what you want — but if you’re working closer to the raw layer, you have to remember that there are two separate sets and check both. A server is only as locked down as its more open half.
Check both families before you call it done
After configuring a firewall, it’s worth listing the active rules for both IPv4 and IPv6 and confirming they match your intent. A configuration that looks airtight on IPv4 while IPv6 still permits everything is a surprisingly common real-world hole — and because IPv6 connectivity is often enabled silently, the open door isn’t obvious until someone finds it. Two minutes of checking saves you from a gap that can quietly undo the entire effort.
Host firewall vs cloud security group
If your server runs on a cloud platform, you very likely have two layers of firewall available, and a strong setup uses both.
- The host firewall runs on the server itself, as software you configure on the machine. It travels with the server and can make fine-grained decisions. This is the firewall most of what we’ve discussed applies to directly.
- The cloud security group (sometimes called a network ACL or network firewall) sits in front of your server, filtering traffic at the provider’s edge before it ever reaches your machine. You configure it in a dashboard, and it protects the server even if the host firewall is somehow misconfigured.
These don’t compete — they reinforce each other. The security group is your perimeter gate; the host firewall is the lock on the building’s own door. Using both is defense in depth: if one layer has a mistake, the other still holds. A practical consequence worth knowing: if your traffic is being blocked and you can’t figure out why your host rules look correct, check the cloud security group — it may be denying the traffic before it ever reaches the machine your rules live on.
internet
│
▼
┌──────────────────────┐
│ CLOUD SECURITY GROUP │ perimeter — filters at provider edge
└──────────────────────┘
│ (traffic that passed)
▼
┌──────────────────────┐
│ HOST FIREWALL │ on the machine — last line of defense
└──────────────────────┘
│
▼
your services
Test, then make it stick
Two final steps separate a configuration that looks right from one you can actually trust.
First, test it. After your rules are in place, verify three things: that the ports you opened are reachable from outside, that the ports you didn’t open are not, and — most importantly — that your own management access still works from a fresh connection. The simplest test is the one that matters most: open a new SSH session before you close your existing one. If it connects, you’re safe. If it doesn’t, your old session is still there to fix the problem.
Second, make the rules persist. This is a step beginners forget and then get burned by: on many systems, firewall rules you add live only in memory and vanish on reboot. You set everything up perfectly, the server restarts for an update three weeks later, and suddenly your default-deny is gone and every port is open again — or worse, your service is unreachable. Whatever tool you use, find its “save” or “enable on boot” step and run it, then reboot once on purpose to confirm the rules come back exactly as you left them.
1. apply rules → configuration is active now
2. test from outside → open ports reachable, closed ports blocked
3. test your access → new SSH session connects
4. persist the rules → survive a reboot
5. reboot to confirm → rules come back unchanged
Common mistakes to avoid
To pull the pitfalls together in one place, here are the configuration errors that cause the most trouble:
- Setting default-deny before allowing SSH. Instant lockout. Allow your access first, always.
- Wrong rule order. A broad deny above a specific allow silently blocks traffic you meant to permit. Specific allows go on top.
- Forgetting the established-connections rule. Requests get in but replies can’t get out, so nothing works.
- Locking down IPv4 but leaving IPv6 open. A wide-open second firewall undoes the first. Configure both.
- Not persisting the rules. Everything works until the next reboot wipes it. Save and verify after a restart.
- Opening ports you don’t actually serve. Every open port is a door. Open only what you run, nothing “just in case.”
None of these require deep expertise to avoid — they’re a checklist, not a talent. Walk through them each time and your firewall configurations will be both correct and boring, which is exactly what you want from security.
Wrapping up
Here’s the whole picture in one place:
- Configuring a firewall is really three decisions: the default policy, the allow rules, and their order.
- Always build on default-deny: block everything inbound, then open only the few ports your service genuinely needs.
- Allow your own SSH access first, before flipping the default to deny — and keep an escape hatch (an open session, or the cloud console) so you can never lock yourself out.
- A minimal rule set is often just SSH, HTTP, HTTPS, established connections, and deny the rest.
- Order matters — specific allow rules go above broad deny rules, because the first match wins.
- The established/related rule is what lets replies flow back through a stateful firewall; without it, requests get in but nothing works.
- Configure IPv6 to match IPv4 — a forgotten second firewall is a silent hole.
- Use both the host firewall and the cloud security group when you have them: defense in depth.
- Test from a fresh connection and persist the rules so they survive a reboot.
With a firewall closing the doors you don’t need, the next layer worth strengthening is the doors you do keep open — making sure each service that’s allowed through is itself locked down and that the management access you rely on is as hard to attack as possible.