Cloud Explainers
Home › Networking › Networking for Beginners, episode 7

The 5 Levels of Network Firewalls

Networking12 min videoPublished Oct 30, 2026

The five levels of firewalls, each one built for real in a small lab network: a packet filter (address and port rules with a default drop), a stateful firewall (connection tracking, so answers just work), a network firewall on the router that guards every server at once, cloud firewalls (AWS security groups and network ACLs), and an application firewall that reads the web request itself. We follow Ana's online shop from a database open to anyone to a network where each layer covers what the one before can't see.

The 5 Levels of Network Firewalls: the full diagram
The whole picture, from the video's recap.

Ana's open database

A stranger on the internet scans Ana's online shop, and finds her database open to anyone. Every customer and every order sits behind that one open door. A firewall is what decides who may knock. Here are five levels of firewalls, and each one closes a gap the last one leaves.

Here is that scan, run for real, in a lab built for this video. nmap knocks on three ports of each server. The web server has SSH, the remote login, and the website open. The database server has SSH open, and PostgreSQL, the database itself, on port 5432. And nc, a tool that just tries to connect, gets straight in.

A stranger's computer
nmap -Pn -p 22,80,5432 web db | grep -E 'report|/tcp'Nmap scan report for web (198.51.100.10)
22/tcp   open   ssh
80/tcp   open   http
5432/tcp closed postgresql
Nmap scan report for db (198.51.100.20)
22/tcp   open   ssh
80/tcp   closed http
5432/tcp open   postgresql
A stranger's computer
nc -zv -w 3 db 5432Connection to db (198.51.100.20) 5432 port [tcp/postgresql] succeeded!

We'll fix it five times, level by level. A packet filter on one server. A stateful firewall that remembers conversations. A network firewall that guards every server at once. Cloud firewalls, the same ideas as a service. And an application firewall that reads the request itself.

Ana's open database: diagram from the video

First, two words. A port is a numbered door on a computer: 22 for SSH, the remote login, 80 for websites, 5432 for PostgreSQL. A firewall sits in front of those doors. It looks at every packet, checks its list of rules, and either lets the packet in, or drops it.

Ana's open database: diagram from the video

Level 1: Packet filter

Level one: a packet filter. Every packet carries an address it came from, an address it's going to, and a port. The filter reads only those, checks its rules from the top, and the first rule that matches wins. A packet that matches none of the rules gets the default, called the policy. The safe policy is drop.

Level 1: Packet filter: diagram from the video

On Linux, the firewall is built into the kernel, and the tool to set it is nftables. On the database server, Ana writes a table with one chain of rules, for packets coming in. The policy: drop. Accept the server talking to itself, on its loopback connection, called lo. Accept SSH. And accept PostgreSQL, but only from the web server's address. nft loads the rules.

The database server
cat firewall.nfttable inet fw {
  chain input {
    type filter hook input priority 0; policy drop;
    iif lo accept
    tcp dport 22 accept
    ip saddr 198.51.100.10 tcp dport 5432 accept
  }
}
The database server
sudo nft -f firewall.nft

Now the stranger tries again. nc waits three seconds, and gives up: timed out. From the web server, the same command still connects. And nmap now calls the database port filtered: it got no answer at all, so it can't even tell whether something is there.

The stranger, the web server, the stranger
nc -zv -w 3 db 5432nc: connect to db (198.51.100.20) port 5432 (tcp) timed out: Operation now in progress
The stranger, the web server, the stranger
nc -zv -w 3 db 5432Connection to db (198.51.100.20) 5432 port [tcp/postgresql] succeeded!
The stranger, the web server, the stranger
nmap -Pn -p 22,5432 db | grep /tcp22/tcp   open     ssh
5432/tcp filtered postgresql

But something else broke. The database server needs security updates, from a download site on the internet. Ana asks for one, and curl gives up after five seconds.

The database server
curl -m 5 http://updates.example/curl: (28) Connection timed out after 5002 milliseconds

Here's why. The request goes out fine, because Ana's rules only check packets coming in. It leaves from a random high port the server picks for its own end. But the answer comes back from port 80, to that random port. No rule accepts that, so the policy drops it. A packet filter looks at each packet on its own. It can't tell an answer Ana asked for from a stranger knocking. Opening every high port would undo the whole firewall.

Level 2: Stateful firewall

Level two: a stateful firewall. Stateful means it remembers. When the database server starts a connection, the firewall writes it down: who, to where, which ports. A packet that belongs to a conversation on that list is called established, and one rule lets all of those in. A stranger's packet matches nothing on the list.

In nftables, that's one rule, inserted at the top: accept packets whose connection state is established or related. Related covers helper packets, like an error message about one of Ana's own connections. The download works again. And the rule list now starts with it.

The database server
sudo nft insert rule inet fw input ct state established,related accept
The database server
curl -m 5 http://updates.example/security-update-2026-10.tar: ready
The database server
sudo nft list chain inet fw inputtable inet fw {
	chain input {
		type filter hook input priority filter; policy drop;
		ct state established,related accept
		iif "lo" accept
		tcp dport 22 accept
		ip saddr 198.51.100.10 tcp dport 5432 accept
	}
}

The list the firewall keeps is called the connection tracking table. A tool called conntrack shows it. Here is the download: from the database server, to the download site, port 80, from local port 33814. And the stranger? Still timed out. Nothing on the list matches a packet nobody asked for.

The database server, then the stranger
sudo conntrack -L -p tcp --dport 80 2>/dev/null | awk '{print $4, $5, $6, $7, $8}'SYN_RECV src=198.51.100.20 dst=203.0.113.80 sport=33798 dport=80
TIME_WAIT src=198.51.100.20 dst=203.0.113.80 sport=33814 dport=80
The database server, then the stranger
nc -zv -w 3 db 5432nc: connect to db (198.51.100.20) port 5432 (tcp) timed out: Operation now in progress

So that's the difference. A packet filter judges every packet alone, and answers need their own holes. A stateful firewall judges the first packet of each connection, then lets the rest of that conversation through. Almost every firewall you'll meet today is stateful.

Level 2: Stateful firewall: diagram from the video

Level 3: Network firewall

Level three: a network firewall. Ana's database server is safe now, but she has two servers. The web server has no firewall at all, and its SSH login is open to the whole internet. Every new server means writing every rule again, and one forgotten server is all a stranger needs.

The stranger checks, and the web server's SSH port answers.

A stranger's computer
nc -zv -w 3 web 22Connection to web (198.51.100.10) 22 port [tcp/ssh] succeeded!

But every packet from the internet already passes one machine: the shop's router. A firewall there guards every server behind it at once. In nftables, packets passing through a machine use a hook called forward. A hook is a checkpoint where rules run. Packets addressed to the machine itself use a different one, called input.

Ana's rules for the router. Policy: drop. Accept established connections. Let the shop's own servers start connections out. From the internet, allow just one thing: the website, on port 80 of the web server. SSH only from Ana's home address. And count everything that gets dropped.

The shop router
cat edge.nfttable inet edge {
  chain forward {
    type filter hook forward priority 0; policy drop;
    ct state established,related accept
    ip saddr 198.51.100.0/24 accept
    ip daddr 198.51.100.10 tcp dport 80 accept
    ip saddr 203.0.113.30 tcp dport 22 accept
    counter drop
  }
}
The shop router
sudo nft -f edge.nft

From the stranger's computer: the website loads. SSH on the web server: timed out. SSH on the database server: timed out too. From Ana's home, SSH still connects.

The stranger, then Ana at home
curl -s http://shop.example/Ana's Kettle Shop
The stranger, then Ana at home
nc -zv -w 3 web 22nc: connect to web (198.51.100.10) port 22 (tcp) timed out: Operation now in progress
The stranger, then Ana at home
nc -zv -w 3 db 22nc: connect to db (198.51.100.20) port 22 (tcp) timed out: Operation now in progress
The stranger, then Ana at home
nc -zv -w 3 web 22Connection to web (198.51.100.10) 22 port [tcp/ssh] succeeded!

On the map: one set of rules at the edge, and every server behind it gets the same protection, including servers Ana hasn't built yet. The database keeps its own firewall too. Two layers means one mistake doesn't open the door. That idea is called defense in depth. Most home routers do a version of this too: they let out what your devices start, and drop connections nobody inside asked for.

The database server can still fetch updates, because it started that connection. And the router's counter shows what it stopped: 6 packets dropped, from the stranger's tries.

The database server, then the router
curl -m 5 http://updates.example/security-update-2026-10.tar: ready
The database server, then the router
sudo nft list chain inet edge forward | grep counter		counter packets 6 bytes 360 drop

Level 4: Cloud firewalls

Level four: cloud firewalls. If Ana moves her shop to a cloud, like AWS, Azure or Google Cloud, she doesn't get a router to log in to. She gets the same ideas as a service. On AWS, the main one is a security group: a stateful firewall attached to each server, with allow rules only. Anything not allowed is dropped.

Level 4: Cloud firewalls: diagram from the video

Security groups add one clever trick. A rule can allow traffic from another group, instead of an address. So the database's group says: port 5432, only from the web group. When Ana adds a second web server to that group, it can reach the database at once, with no rule to edit.

Level 4: Cloud firewalls: diagram from the video

AWS has a second layer: network ACLs, short for access control lists. They guard a whole subnet, a block of addresses, like the router guarded Ana's network. But they're stateless, like level one: answers need their own rules. They can say deny, not just allow, and they're checked in number order, where the first match wins. Most setups lean on security groups, and use ACLs as an extra layer.

Level 4: Cloud firewalls: diagram from the video

So nothing new to learn, just new names. The rules Ana wrote on her database server are what a security group does. And the router's rules are the network level, what AWS offers as ACLs and network firewalls. But all four levels so far share one blind spot.

Level 5: Application firewall

Level five: an application firewall. Port 80 is open, because it has to be: it's the website. So the stranger asks for the shop's admin page, /admin, on port 80, and gets it: orders, refunds, the customer list. Every firewall so far sees addresses and ports. None of them can see which page is asked for.

A stranger's computer
curl -s http://shop.example/adminShop admin: 3 new orders, refunds, customer list

The fix is a program that reads the request itself. A reverse proxy sits in front of the web server and receives every web request first. It reads the page asked for, and who keeps asking, then passes only good requests on. That's layer seven, the application layer, from the OSI episode.

Ana's proxy is nginx, a program that can serve websites, or, like here, sit in front of one. Two rules. Anything under /admin: deny. Everything else goes to the web server, but each address gets five requests a second, with a short burst allowed. Past that, the answer is 429, too many requests.

The proxy
cat shop-proxy.conflimit_req_zone $binary_remote_addr zone=perip:1m rate=5r/s;
server {
  listen 80;
  location /admin { deny all; }
  location / {
    limit_req zone=perip burst=5 nodelay;
    limit_req_status 429;
    proxy_pass http://198.51.100.10;
  }
}
The proxy
sudo cp shop-proxy.conf /etc/nginx/conf.d/ && sudo nginx

Two more changes. The router now sends web traffic from the internet only to the proxy. And the shop's name, shop.example, now points to the proxy's address, as the shop's DNS record would.

The router, then the stranger
cat edge-proxy.nft | grep 'tcp dport 80'    ip daddr 198.51.100.5 tcp dport 80 accept
The router, then the stranger
sudo nft -f edge-proxy.nft
The router, then the stranger
getent hosts shop.example198.51.100.5    shop.example proxy

The stranger tries again. The product list loads, through the proxy. The admin page: 403, forbidden. And going around the proxy, straight to the web server's address, times out at the router.

A stranger's computer
curl -s http://shop.example/productsCopper kettle  $49
Steel kettle   $29
A stranger's computer
curl -s -o /dev/null -w '%{http_code}\n' http://shop.example/admin403
A stranger's computer
curl -m 5 http://198.51.100.10/admincurl: (28) Connection timed out after 5002 milliseconds

Here's the whole path now. The router lets only web traffic in, and only to the proxy. The proxy reads each request and turns away what the shop never meant to be public. The web server sees only good requests, and the database answers only the web server.

Last test: twenty requests in a row, as fast as curl can send them. 6 get the page, the first one, plus a burst of five more. The other 14 get 429.

A stranger's computer
for i in $(seq 20); do curl -s -o /dev/null -w '%{http_code}\n' http://shop.example/; done | sort | uniq -c      6 200
     14 429

So a script hammering the shop slows to five requests a second, while a customer browsing stays well under that. A web application firewall, or WAF, is this idea grown up. Instead of two rules, it carries hundreds or thousands: patterns of known attacks, like SQL injection, which tricks a site into running database commands, bad bots, and rate limits. You can run one yourself, like ModSecurity, free WAF software, with rules from OWASP, an open security project, or rent one, like AWS WAF or Cloudflare.

Level 5: Application firewall: diagram from the video

Recap

So, the five levels. A packet filter checks addresses and ports. A stateful firewall remembers connections, so answers just work. A network firewall guards every server at once. Cloud firewalls give you the same ideas as a service. And an application firewall reads the request itself.

Recap: diagram from the video

And three habits that go with every level. Start from drop, and allow only what's needed. Allow by who is asking, not just by port: the database only for the web server. And use more than one layer, so one mistake isn't enough.

Recap: diagram from the video

A question for the comments: which of these five levels guards something you run today, even just your home router? Tell me in the comments.

Recap: diagram from the video

Every result in this video came from a real run of a small lab network. This was episode seven of Networking for Beginners.

Sources

Demos: real output from a small lab network built with Docker containers on one machine, using only reserved test addresses (203.0.113.x and 198.51.100.x). The lab has no route to the real internet, and every scan and connection attempt targets only the lab's own machines. Watch the full video on YouTube.

More videos