A firewall is an access-control device that blocks any traffic which doesn't match a pre-defined rule. The starting point is a primitive operation: matching against the 5-tuple (src/dst IP, src/dst Port, Proto). From there the technology has evolved repeatedly — Stateful → NGFW → cloud SG / SASE. This article covers the five-generation arc, what Stateful actually does, placement-based families, NGFW / WAF / cloud SG, and the shift toward Zero Trust, including where modern firewalls fall short.
What a firewall is — the 5-tuple and policy #
The most basic loop a network firewall runs is this.
# allow internal LAN to outbound HTTPS
allow from 10.0.0.0/24 to any port 443 proto tcp
# allow the outside to the DMZ web server (port 80, 443)
allow from any to 203.0.113.10 port {80,443} proto tcp
# drop everything else inbound
deny from any to 10.0.0.0/24deny (= reject) returns an ICMP unreachable; drop silently discards the packet without any response. drop is preferred because it slows down an attacker's reconnaissance (the attacker can't tell "closed port" from "no response at all").
Writing what you explicitly want to allow as a whitelist — default deny — is the right modern design. Default allow is discouraged because every new protocol opens a hole until you remember to close it.
Five generations — what we gained at each step #
The history of firewalls is the history of "how high up the stack can we look". You can map it cleanly onto five steps: Packet Filter → Stateful → Application Proxy → NGFW → Cloud/Zero Trust.
The key insight is that newer generations didn't replace older ones — modern systems stack multiple generations at once as layers.
- Perimeter — NGFW (4th gen)
- In front of a DMZ web server — WAF (the L7-specialised 5th gen)
- Each EC2 / VM — cloud SG (5th gen)
- Inside the OS — host firewall (carrying forward 1st-2nd gen)
- Between containers — Network Policy / Service Mesh (5th gen)
This is defense in depth — each layer designed to catch what slips through the previous one.
Stateless vs Stateful — the core idea #
Stateful Inspection — the 2nd generation — is effectively the baseline for any modern firewall. Stateless evaluates each packet in isolation, keeping no past state. Stateful tracks sessions in a connection state table and automatically lets return packets through.
| Stateless | Stateful | |
|---|---|---|
| Rule syntax | Must explicitly write the return side (e.g. port >1024) |
"allow 443 outbound" is enough |
| Attack surface | The wide-open return side invites response spoofing | The tracking table blocks response spoofing |
| State | None | Holds the 5-tuple + state per TCP/UDP flow |
A state table contains rows like the following (Linux conntrack / Check Point):
| Src→Dst | Proto | State | TTL | Bytes |
|---|---|---|---|---|
10.0.0.5:48772 → 93.184.216.34:443 |
TCP | ESTABLISHED | 295s | 14.2 KB |
10.0.0.5:51123 → 8.8.8.8:53 |
UDP | ESTABLISHED (pseudo) | 28s | 220 B |
| Return packet | — | RELATED via parent | — | — |
Decisions driven by state:
- NEW — not in the table; added to the table only if the ACL allows it
- ESTABLISHED — continuation of an existing session; admitted via table lookup (no need to walk the ACL)
- RELATED — an accompanying connection like FTP's data channel; resolved by an ALG helper (FTP/PPTP/IRC/H.323)
- INVALID — illegal flag combination or inconsistent with the table — drop
Table capacities are in the hundreds of thousands to millions of entries. A SYN Flood attack — filling the table to choke out legitimate connections — is the structural weakness of Stateful. Too short a TTL kills real sessions; too long a TTL fills the table. Capacity management is the key to throughput.
$ sudo conntrack -L
tcp 6 431999 ESTABLISHED src=10.0.0.5 dst=93.184.216.34 sport=48772 dport=443 ...
# capacity limit and current count
$ sudo sysctl net.netfilter.nf_conntrack_max
$ cat /proc/sys/net/netfilter/nf_conntrack_count
# raising the cap when the table overflows under bursty load
$ sudo sysctl -w net.netfilter.nf_conntrack_max=1048576Placement-based families #
The word "firewall" today refers to several different devices. Split by what you're protecting / where it sits, there are four families:
| Family | What it protects | Representatives |
|---|---|---|
| Network Firewall (perimeter) | The boundary of an entire LAN | Palo Alto / Fortinet / Check Point / Cisco ASA / pfSense |
| Host Firewall | An individual OS instance | iptables/nftables (Linux), Windows Defender, macOS PF, ufw, firewalld |
| WAF | The L7 of a web application | AWS WAF / Cloudflare / Akamai / F5 / ModSecurity |
| Cloud Firewall | Per-cloud-resource | AWS Security Group / NACL, Azure NSG, GCP Firewall Rules |
These four don't compete with each other — they're combined. In an AWS three-tier web app this looks like:
- AWS WAF — In front of CloudFront / ALB, blocks L7 attacks (SQLi / XSS / Bot / rate-limit)
- Security Group — ALB only on 80/443, App only reachable from ALB, DB only from App — least-privilege per instance
- NACL — Broad-strokes subnet-boundary control inside the VPC (Stateless, supplements SGs)
- Host Firewall — Further tighten at the OS level inside each EC2 with
nftables(defense in depth)
The modern design is "don't expect any one firewall to do everything". By splitting responsibilities per layer, a misconfiguration in one layer is still caught by the next.
Relationship with NAT — the most common confusion #
Home Wi-Fi routers are often advertised as "comes with a built-in firewall", but strictly speaking that's NAT (Network Address Translation) accidentally acting as a firewall. NAT and firewalling are originally separate features.
| NAT | Firewall | |
|---|---|---|
| Goal | IP address translation (internal private → external global) | Access control |
| Behavior | Rewrites source/destination IP/Port | Decides pass / drop |
| Side effect | Unsolicited external→internal connections have no mapping and can't reach in | (no side effects — a pure filter) |
NAT automatically builds a mapping from "internal→external" connections, so unsolicited connections from outside have no matching entry and simply can't reach in. That's the "we're accidentally protected by NAT" phenomenon.
NAT is not a firewall. Configuring port forwarding punches a hole through it, and with UPnP / NAT-PMP enabled apps quietly create their own mappings (some IoT cameras / game consoles). IPv6 doesn't use NAT by default, so explicit firewall rules become mandatory. Standard guidance for IPv6-era home routers is to stop relying on NAT and enable the firewall properly.
NGFW — what you can do at L7 #
NGFW (Next Generation Firewall) is a category Palo Alto Networks effectively created around 2007. It bundles Stateful + DPI + IPS + Application ID + URL Filtering + User ID + SSL Inspection. Its defining trait is being able to look inside "what's actually flowing on port 443".
| Classic Stateful | NGFW | |
|---|---|---|
| Decision axes | IP / Port / Proto | + application (Skype/Zoom/Dropbox/SSH) / user (AD ID) / category (SNS/News) / threat (signatures) |
| HTTPS | Can't see inside (headers only) | SSL decryption to see the contents (= MITM topology) |
| Typical rule | "10.0.0.0/24 → any:443 allow" | "Sales dept → Salesforce only; Dropbox denied; Twitter read-only" |
SSL Inspection (= SSL/TLS decryption) is the biggest discussion point for NGFW:
- Install a corporate CA certificate on every endpoint → the NGFW intercepts, decrypts, scans, and re-encrypts
-
- L7 attack detection and DLP (Data Loss Prevention) become possible
- − Privacy concerns (the company can read employees' HTTPS traffic)
- − Some sites break under decryption because of certificate pinning (banking apps, parts of Google)
- − A performance hit — decryption is heavy even at 10 Gbps
It depends on App ID signature updates (new apps, version changes, traffic camouflage can defeat detection), rule sets explode (combinations of app × user × category quickly reach thousands of rules), and false positives hurt the business (a SaaS update suddenly gets blocked). These are daily issues in real operation.
WAF — an L7-only firewall #
A WAF (Web Application Firewall) is an L7 firewall dedicated to web applications (HTTP/HTTPS). Deeper and narrower than an NGFW, it specialises in web traffic — inspecting HTTP requests for SQLi / XSS / CSRF / command injection / Path Traversal / Bot / rate-limit attacks.
The typical topology is [Internet] → [CDN/WAF] → [ALB] → [Web] → [App] → [DB].
OWASP CRS (Core Rule Set) is the de-facto ruleset, and a single bundle covers most of the OWASP Top 10.
| Attack | Stoppable by WAF? |
|---|---|
SQL Injection (classic ' OR 1=1) |
◎ Known pattern |
XSS (classic <script>) |
◎ Known pattern |
| CSRF | △ Up to Origin / Referer checking |
Logic flaws (e.g. tampering with price) |
× Only the app knows |
| Authn / Authz bugs | × Same |
| Zero-day | × Not in signature DB |
| Bot / Credential Stuffing | ○ Rate-limit / bot detection |
| L7 DDoS | ○ Rate-limit / CAPTCHA |
Major WAFs: AWS WAF / Cloudflare / Akamai / Fastly (cloud-managed), F5 BIG-IP ASM / Imperva (on-prem), ModSecurity (OSS, Apache/Nginx module).
"We have a WAF so we don't need to worry about SQLi" is dangerous thinking. Prepared statements + ORM + input validation are the primary defenses; the WAF is the last line in a layered defense.
Cloud-era firewalls — SG / NACL / SASE #
In the cloud (AWS / Azure / GCP), the concept of a firewall has been substantially reshaped. Instead of "IP boundary", control is per-resource and per-identity.
AWS, as an example:
| Feature | Type | Behavior |
|---|---|---|
| Security Group (SG) | Stateful, per instance / ENI | Default deny / write only allow rules / return traffic automatic |
| NACL | Stateless, per subnet | Evaluated by rule number / allow and deny explicit / return needs its own rule |
| AWS WAF | L7, in front of CloudFront/ALB/API GW | OWASP / custom signatures |
| AWS Network Firewall | Stateful + DPI, at the VPC gateway | Commercial-NGFW equivalent (Suricata-based) |
The distinguishing feature of Security Groups is that a source can be another SG ID, not just an IP CIDR. Reference a Security Group instead of a network range, and as instances scale up and down their IPs are tracked automatically.
resource "aws_security_group_rule" "app_from_alb" {
type = "ingress"
from_port = 8080
to_port = 8080
protocol = "tcp"
source_security_group_id = aws_security_group.alb.id # SG ID, not an IP
security_group_id = aws_security_group.app.id
}SASE (Secure Access Service Edge) is a concept Gartner introduced in 2019: fold Firewall / VPN / SWG (Secure Web Gateway) / CASB / ZTNA into a cloud-delivered platform. Major players include Cloudflare One / Zscaler / Netskope / Palo Alto Prisma.
Classic (Hub & Spoke): Employee → office → HQ firewall → each SaaS SASE model: Employee → cloud POP (Firewall + SWG + ZTNA) → each SaaS / HQ
The essence of SASE is "the same firewall policy applies no matter where the user is". Adoption surged when COVID forced remote work to scale up overnight.
Why firewalls alone no longer protect us #
"Firewalls alone can't stop most modern breaches" is the industry consensus. The Verizon DBIR and Mandiant M-Trends both show that most successful intrusions came through a firewall, not around it.
Attack patterns firewalls are blind to:
- Malware / phishing / dropper PDFs delivered inside HTTPS (an L4 firewall can't see it, and even an NGFW can't unless it does SSL inspection)
- Intrusion using legitimate credentials (phished or bought from Initial Access Brokers) → the firewall sees normal traffic
- Internal lateral movement — once inside, AD / SSH / RDP / SMB are wide-open if internal firewalls are sparse
- Supply-chain attacks — SolarWinds-style updates from a legitimate vendor → firewall sees trusted traffic
- Data exfiltration via SaaS — outbound to a sanctioned SaaS is allowed, so nothing blocks it
| Classic (Perimeter) | Zero Trust | |
|---|---|---|
| Default trust | Inside the LAN is trusted, outside is not | Trust nothing (Never Trust, Always Verify) |
| Boundary | Physical network perimeter | Identity / device / context is the boundary |
| Access decision | IP / Port | + user / device posture / time / location / behavior |
| Lateral movement | Loose inside → easy | Micro-segmentation — check at every resource |
How the firewall changes in a Zero Trust world:
- Perimeter firewalls are still required (baseline filter), but they are no longer "if you got past this, you're trusted"
- ZTNA (Zero Trust Network Access) has started displacing VPNs — instead of "VPN into the corporate network" it's "verify identity per application and connect directly"
- Micro-segmentation makes the inside firewall-heavy too (rules at VM / container / Pod granularity)
- Service Mesh (Istio / Linkerd) acts as the "firewall between microservices" (mTLS + authorisation policy)
A strong modern defense is a combination of firewall + EDR + SIEM + ZTNA + WAF + DLP + IAM. The firewall is positioned as "important but only one layer".
Major incidents — cases where firewall limits showed #
| Year | Incident | Firewall takeaway |
|---|---|---|
| 2010 | Stuxnet (ICS) | Reached air-gapped Iranian enrichment plants via USB → firewall irrelevant. The assumption of physical-layer trust collapsed |
| 2013 | Target (40 million records) | Entry via an HVAC vendor; internal firewalls were sparse, allowing lateral movement to the POS network. The perimeter worked — the inside didn't |
| 2017 | Equifax (140 million records) | Public-facing Struts vulnerability → WAF was non-functional due to an expired certificate |
| 2017 | NotPetya | Supply-chain via accounting software (M.E.Doc) → passed as legitimate traffic → SMB lateral movement via EternalBlue |
| 2020 | SolarWinds Orion | Backdoor in a legitimate update → C2 over HTTPS through legitimate CDNs |
| 2021 | Colonial Pipeline | Unused VPN account exploited → firewall let it through as "legitimate VPN access" |
| 2024 | Fortinet / Ivanti / Check Point 0day series | Vulnerabilities in the firewall appliances themselves — the device meant to protect becomes the foothold, increasingly often |
Common pattern: it isn't "breached because there was no firewall". It's "breached by traffic that blended in with legitimate flows through the firewall", "breached because inside the firewall was kept loose", "breached via the firewall appliance itself". Keeping a perimeter firewall remains necessary, but relying on it alone is outdated thinking.
Defense — designing firewalls to actually matter #
Practical points for keeping firewalls effective:
| Design | What it means |
|---|---|
| Default deny | Apply "anything not explicitly allowed is denied" at every layer (perimeter / SG / host) |
| Least privilege | Tighten SG / NSG rules to what's strictly needed — not "from any → all ports" |
| Micro-segmentation | Don't keep the inside a flat LAN — draw firewall boundaries per service / tier |
| NGFW SSL Inspection | Where feasible, decrypt and inspect L7 (coordinating with legal / HR considerations) |
| WAF + OWASP CRS | Put a WAF in front of every public web service; keep CRS up to date |
| Rule housekeeping | Audit and remove unused rules semi-annually or annually (use hit-count features) |
| Vendor vulnerabilities | Patch KEVs in firewall appliances immediately; replace EoL models without delay |
| Logs + SIEM | Stream deny / allow logs into a SIEM (Splunk / Sumo / Elastic) and detect anomalous traffic |
| Consider ZTNA / SASE | Replace the VPN; move to a firewall model suited to the remote-work era |
$ sudo nft add table inet filter
$ sudo nft add chain inet filter input '{ type filter hook input priority 0 ; policy drop ; }'
$ sudo nft add chain inet filter forward '{ type filter hook forward priority 0 ; policy drop ; }'
$ sudo nft add chain inet filter output '{ type filter hook output priority 0 ; policy accept ; }'
$ sudo nft add rule inet filter input ct state established,related accept
$ sudo nft add rule inet filter input iifname "lo" accept
$ sudo nft add rule inet filter input tcp dport 22 acceptThe firewall has kept the same basic action — "block anything that doesn't match the rules" — while Packet Filter → Stateful → Application Proxy → NGFW → Cloud/Zero Trust has been a steady history of looking at higher and higher layers. In a modern system, Host Firewall / WAF / Cloud SG / Service Mesh all act as firewalls in parallel, layered together for defense in depth. Now that firewalls alone can't protect us, the path forward — and the way to make firewalls still matter — is to embrace Zero Trust thinking: stop trusting the inside, decide based on identity and device posture, and stop lateral movement via micro-segmentation.