A firewall is a set of rules over headers
A firewall inspects packets and decides to allow, drop, or reject them. The fields it matches on are the ones from Units 4 to 7, which is why this lesson comes after them and not before.
| Match on | Field | Layer |
|---|---|---|
| Source or destination network | IP address and prefix | 3 |
| Protocol | IP protocol number, 6, 17, 1 | 3 |
| Service | TCP or UDP port | 4 |
| Connection state | new, established, related | 4, tracked |
| Interface or direction | which NIC, inbound or outbound | 2 |
Three verdicts exist, and choosing between two of them is a real decision.
- Allow, forward the packet. - Drop, discard silently. The sender learns nothing and waits for a timeout. - Reject, discard and send an error, either a TCP RST or an ICMP administratively prohibited message. The sender fails immediately with a clear signal.
Drop hides that a host exists, at the cost of slow failures and confusing diagnostics. Reject is friendlier and faster to debug, and it confirms the host is there. Internal networks usually reject for sanity, internet facing rules usually drop.
Stateless versus stateful
A stateless filter evaluates each packet with no memory of anything before it. That sounds fine until you write the rules for one outbound connection.
allow out: src 10.0.0.0/24 any port -> any port 443 allow in: src any port 443 -> dst 10.0.0.0/24 any port
The second line is the problem. To let replies back you had to allow any packet claiming a source port of 443 to reach any port on your network. An attacker simply sets source port 443 and walks through, and a stateless filter cannot tell the difference, because telling the difference requires remembering that you sent something first.
A stateful filter keeps a connection tracking table, the same table NAT needed in Lesson 6-1. Now the rule set says what it means.
allow out: new connections from 10.0.0.0/24 to any port 443 allow in: packets belonging to an established connection drop in: everything else
Connection tracking recognizes four states, and knowing them makes firewall logs readable.
| State | Meaning |
|---|---|
| NEW | a first packet that would open a connection, a TCP SYN |
| ESTABLISHED | a packet belonging to a tracked connection |
| RELATED | a separate connection a tracked one legitimately spawned |
| INVALID | does not fit any connection and is not a valid new one |
RELATED is the interesting one. An ICMP fragmentation needed message from Lesson 3-3 is related to the TCP connection it refers to, so a stateful firewall can allow it without allowing ICMP generally. This is exactly why blanket "block all ICMP" rules break path MTU discovery and produce connections that open and then hang.
The concrete syntax on Linux, which reads as the rules above:
nft add rule inet filter input ct state established,related accept
nft add rule inet filter input tcp dport 22 ct state new accept
nft add rule inet filter input dropDesign rules that hold up
Default deny. The last rule must drop everything not explicitly allowed. A default allow policy means every service ever installed is exposed until somebody notices. Order matters too, since rules are evaluated top to bottom and the first match wins, so a broad allow placed above a narrow deny silently disables it.
Filter egress, not only ingress. Most rule sets carefully restrict inbound and allow everything outbound, which is precisely the direction malware needs. Limiting outbound traffic to the ports and destinations a host legitimately requires contains a compromise instead of merely postponing it.
Filter close to the workload. A rule at the perimeter does nothing about traffic between two hosts inside it, and a compromised host is inside. Host level rules, or per workload policy, are what limit lateral movement.
Firewalls also exist at different layers, and the names describe how deep they look:
| Kind | Sees | Can decide on |
|---|---|---|
| Packet filter | IP and TCP headers | addresses, ports, state |
| Application proxy | the full application protocol | actual requests |
| NGFW or IPS | reassembled streams, signatures | known attack patterns |
| WAF | HTTP requests after TLS termination | payload, paths, parameters |
Note the implication of the last row. Inspecting HTTPS content requires terminating TLS, which means the inspecting device holds the private key or issues its own certificates to clients. That is a genuine tradeoff, not a free feature, and it is why decryption points are worth arguing about.
Two failure patterns to recognize on sight:
- Asymmetric routing through stateful devices. If replies come back via a different firewall than the one that saw the SYN, the second device sees an ESTABLISHED packet for a connection it never tracked and marks it INVALID. The connection dies for reasons that appear in neither host's logs. - A silent idle timeout. A firewall removes an idle connection from its table after some minutes, then drops the next packet of a connection both hosts still believe is alive. The symptom is a long lived session that freezes rather than closing, and the fix is TCP keepalives shorter than the timeout.