Why does a naive "outbound-allow / inbound-deny" packet filter rule break TCP, and how do you fix it with TCP flags?
TCP is bidirectional — every outbound request needs an inbound response. A simple "deny all incoming" rule breaks every connection because the server's reply packets get blocked. The fix: allow incoming packets only if they're part of an already-established TCP connection (matching SYN/ACK or ACK flags after a permitted SYN).
The naïve attempt (1ter Versuch — broken):
| Source IP | Source Port | Dest IP | Dest Port | Protocol | Flags | Action |
| Internal IP | Any | Any | Any | Any | Any | Allow |
| Any | Any | Internal IP | Any | Any | Any | Deny |
Why it fails: "Allow outgoing, deny incoming" stops every response packet. Your browser sends a SYN — that's allowed out. Server replies with SYN/ACK — that's blocked → no connection. The whole network stops working — "Out of service."
The TCP-flag-aware version (2ter Versuch):
| Source IP | Source Port | Dest IP | Dest Port | Protocol | Flags | Action |
| Internal IP | Any | Any | Any | TCP | SYN | Allow |
| Any | Any | Internal IP | Any | TCP | SYN/ACK | Allow |
| Any | Any | Any | Any | TCP | ACK | Allow |
The logic:
- Outbound SYN = "I want to open a connection" → allow (only originated from inside)
- Inbound SYN/ACK = "I'm replying to your SYN" → allow (response to step 1)
- Inbound/Outbound ACK = "Continuing established connection" → allow
Why this is still imperfect:
The third rule allows any ACK packet from anywhere — including from an attacker who never sent a SYN in the first place. The packet filter has no memory; it can't verify "was there a SYN that justifies this ACK?" An attacker can craft ACK-only packets to probe internal systems → TCP ACK scans (which packet filters can't stop).
This is exactly why Stateful Inspection was invented — to remember which ACKs are legitimate replies to which SYNs.
Tip: When you read iptables rules with -m state --state ESTABLISHED,RELATED, that's a stateful match — Linux iptables has been stateful since the 2000s. True "stateless" packet filtering is rare today; most modern packet filters are stateful by default.
Go deeper:
TCP three-way handshake — Wikipedia — the SYN / SYN-ACK / ACK sequence and per-direction sequence numbers that these flag-based rules are trying (and failing) to track statelessly.