Skip to content

๐Ÿ”„ 05-03: Stateful Firewalls


๐Ÿ“Œ What Does "Stateful" Mean?

A stateful firewall adds the one thing packet filters were missing: memory. Instead of judging every packet in isolation, a stateful firewall keeps a connection tracking table that records every connection it has already approved. When a new packet arrives, the firewall first checks: "is this packet part of a connection I already know about?"

This single idea โ€” remembering ongoing conversations โ€” is why stateful inspection is considered one of the biggest leaps forward in firewall design.

๐Ÿ’ก On Linux, this connection tracking system is called conntrack, and it's built into the kernel's Netfilter framework (the same framework iptables configures โ€” see 05-05: iptables Fundamentals).


๐Ÿท๏ธ Connection States

Every tracked connection is labeled with a state. The four states used by Linux's conntrack (and conceptually by every stateful firewall) are:

State Meaning
NEW The first packet of a connection the firewall hasn't seen before (e.g., a TCP SYN, or the first UDP packet in a flow)
ESTABLISHED A packet that belongs to a connection where traffic has already flowed in both directions
RELATED A new connection that is logically tied to an existing one (e.g., an FTP data connection opened because of an existing FTP control connection)
INVALID A packet that doesn't fit any known connection and doesn't look like a valid new connection either (e.g., a lone TCP ACK with no matching SYN)

FTP is the classic example. The client opens a control connection to the server on port 21. To transfer a file, the server (in active mode) opens a separate data connection back to the client on a random high port. A plain stateful firewall wouldn't know this second connection is legitimate โ€” it looks like an unsolicited inbound connection. But a firewall with protocol-aware connection tracking (an FTP "conntrack helper") recognizes that this new connection is related to the already-approved control connection, and allows it automatically.


โš–๏ธ Why This Is a Major Improvement Over Stateless Filtering

Recall the core weakness of packet filters from 05-02: Packet-Filtering Firewalls: to allow return traffic for an outbound connection, an administrator had to write a blind standing rule like "allow any inbound TCP packet with the ACK flag set," which an attacker could exploit by simply forging a packet with the ACK flag set.

A stateful firewall replaces that entire class of blind rules with one precise rule:

ALLOW  IN/OUT   ctstate=ESTABLISHED,RELATED

This rule only matches packets that the firewall's own connection table recognizes as belonging to a connection it already approved. A forged packet claiming to be part of a connection โ€” but that doesn't match an actual tracked entry (source IP, destination IP, source port, destination port, sequence numbers, protocol) โ€” is not ESTABLISHED or RELATED. It falls through to INVALID or NEW, where the default-deny policy catches it.

Aspect Stateless Filter Stateful Firewall
Decision basis This packet's headers only This packet + the connection's history
Return traffic rule Manual, broad, exploitable Automatic, precise, tied to real state
Spoofed "reply" packets Often accepted Rejected (no matching table entry)
Rule set size Large (one rule per direction per service) Small (one ESTABLISHED/RELATED rule covers all approved connections)
Resource cost Very low Higher โ€” must maintain a connection table in memory

๐Ÿงช Worked Example: Outbound Connection, Automatic Return Traffic

Suppose an internal host 192.168.1.50 opens an HTTPS connection to 93.184.216.34:443.

Step 1 โ€” Outbound SYN packet leaves the network:

src=192.168.1.50:51000  dst=93.184.216.34:443   flags=SYN

The firewall matches this against an outbound rule, allows it, and โ€” critically โ€” creates a new entry in the connection tracking table:

conntrack table:
  proto=tcp  src=192.168.1.50 sport=51000  dst=93.184.216.34 dport=443  state=NEW

Step 2 โ€” Server's SYN-ACK reply arrives inbound:

src=93.184.216.34:443  dst=192.168.1.50:51000   flags=SYN,ACK

The firewall checks this packet against its conntrack table. It finds a matching entry (same 4-tuple, reversed direction) and reclassifies the connection as ESTABLISHED. A single rule โ€”

iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

โ€” allows this packet through without the administrator ever having to write a rule that explicitly opens port 51000 inbound. No attacker on the internet can send a packet claiming dst=192.168.1.50:51000 and have it accepted this way, because unless it matches the exact tracked 4-tuple and expected sequence numbers, it won't be recognized as ESTABLISHED.

Step 3 โ€” Rest of the conversation:

Every subsequent packet in both directions matches the same conntrack entry as ESTABLISHED and flows through under that one rule, until the connection closes (TCP FIN/RST) or the table entry times out.

๐Ÿ’ก This is why a typical, secure iptables INPUT chain is often just three rules: allow loopback, allow ESTABLISHED/RELATED, allow a short list of specific NEW services (like SSH) โ€” then drop everything else. See the full worked rule set in 05-06: Writing iptables Rules.


โฑ๏ธ A Note on Connectionless Protocols (UDP/ICMP)

UDP and ICMP have no formal "connection" the way TCP does (no SYN/ACK handshake) โ€” yet Linux's conntrack still tracks them. For these protocols, "connection" is a pragmatic approximation: the tracker remembers the source/destination pair and a short timeout window, and treats a reply arriving within that window (e.g., a DNS response coming back from the server you just queried) as ESTABLISHED. Once the timeout expires with no reply, the entry is dropped.

Protocol Tracked By Typical Timeout
TCP Full connection state machine (SYN, ESTABLISHED, FIN, etc.) Hours (for ESTABLISHED)
UDP Source/destination pair + short timeout window Seconds (tens of seconds, typically)
ICMP Request/reply pairing (e.g., echo-request โ†” echo-reply) matched by ID Seconds

๐Ÿ“Œ Key Takeaways

  • A stateful firewall tracks ongoing connections instead of judging every packet in isolation.
  • The four connection states are NEW, ESTABLISHED, RELATED, and INVALID.
  • RELATED exists to handle protocols like FTP where a second connection is legitimately spawned by an already-approved one.
  • Stateful inspection closes the exact hole that stateless filters had: it can tell a genuine reply from a spoofed packet, because it checks against a real tracked connection, not just header values.
  • A single ctstate ESTABLISHED,RELATED rule replaces dozens of blind "allow return traffic" rules from the stateless world.
  • Even connectionless protocols like UDP and ICMP get an approximate "connection" tracked, using timeouts instead of a handshake.
  • Stateful firewalls cost more memory/CPU than stateless filters (they must maintain a live table), but the security benefit is well worth it for almost any modern deployment.
  • On Linux, this is implemented by conntrack, part of the Netfilter framework that also powers iptables.