Firewalls and Segmentation
- A firewall is an ordered ruleset matched against a packet's 5-tuple (protocol, source and destination address and port), and often its connection state. The first matching rule wins, and a final default decides everything else. Default deny is the sound default.
- A stateless filter judges each packet alone, so return traffic needs its own rule. A stateful firewall records each permitted outbound flow in a table (Linux calls it conntrack) and lets the reverse-direction packets through automatically.
- The state table is finite and timed: UDP and ICMP get pseudo-state with short timers, and a full table drops new flows. Asymmetric routing and a full table are the two classic stateful outages.
- A WAF reads HTTP, a network firewall reads headers, an IDS only alerts and an IPS blocks inline. Each sits in a different place and none replaces the others.
- Segment so one breach is not everything: a DMZ for exposed servers, a security group per tier, a bastion for admin access, and at the far end zero trust, where every request is authorised by identity rather than by network location. NAT is not a firewall.
Encryption protects what crosses a path. A firewall decides which traffic may exist at all. It is the main control for the perimeter and lateral-movement rows on the threat model, and it mitigates several attacks on the attacks catalogue: port scans, spoofed source addresses, and rogue services reaching the wrong network. Flood attacks (DDoS) are out of scope here and have their own page, still to be written.
Mental model
A building has a front desk with a guest list and a visitor log. A stranger on the street is turned away unless a line on the list names them and the door they want. A guest who walked out for lunch is recognised by the log on the way back, so the desk does not need a line for every returning face. Inside, doors between floors have their own desks, so someone who got past the lobby still cannot walk into the server room.
Where it breaks: the desk can ask for ID and look inside a bag. A packet filter reads only the labels on the envelope (addresses, ports, flags) and the list is read strictly top down, first matching line wins, which no human receptionist does. The log also has a size limit and an expiry time, and a real log never silently fills up and starts refusing new guests.
A stateless firewall is a pure function from packet to verdict, verdict = f(packet, rules), with no memory. A stateful firewall is the same function plus a hash map side effect: accepting an outbound packet inserts a key (the flow tuple), and a later packet looks the key up before the rules are consulted. The ruleset is an if / else if chain with a default branch.
Where it breaks: a map in your code grows until you evict. This one has a hard capacity, timers that expire entries on their own schedule, and a failure mode (new flows dropped) that looks like the network is down while existing connections still work.
How it works
What a rule matches
A packet-filter rule is a set of conditions plus one action. The conditions are the fields in the headers the firewall can read without decoding the payload:
- Protocol (TCP, UDP, ICMP) and, for ICMP, the type.
- Source and destination address, as a single address or a CIDR block.
- Source and destination port (TCP and UDP only).
- Interface and direction, which tells the firewall whether the packet is entering (ingress) or leaving (egress) the protected side.
- TCP flags, for example a bare
SYNmarks a new connection attempt. - Connection state, for a stateful firewall: new, established, related, invalid (below).
The action is usually accept or drop. Drop discards silently, so the sender sees a timeout. Reject discards and sends back an error (a TCP reset or an ICMP unreachable), so the sender sees an immediate failure. Reject is polite and drop is quiet; both look like "something is wrong" to the client, but only reject looks identical to "nothing is listening" (see error messages).
Rules are read top down, first match wins
The firewall walks the list from the first rule and stops at the first one whose conditions all match. The packet gets that rule's action and the rest of the list is never read. If no rule matches, the chain's default policy applies. The sound policy is default deny: drop everything, then allow only what is needed. Default allow with a deny list means anything you forgot gets through, while default deny turns every omission into a blocked connection. NIST's firewall guidance (SP 800-41 Rev. 1) recommends the same stance.
Worked example: a ruleset in front of a web server
A web server 192.0.2.10 sits behind a stateful firewall. The addresses are documentation ranges (RFC 5737). This ruleset is invented for the example:
| # | Match | Action |
|---|---|---|
| 1 | state ESTABLISHED or RELATED, any protocol | accept |
| 2 | TCP to 192.0.2.10 port 443, state NEW | accept |
| 3 | TCP to 192.0.2.10 port 22, state NEW, source 203.0.113.0/24 | accept |
| 4 | everything else (default policy) | drop |
Four packets, traced:
| Packet | State lookup | Rule that matches | Result |
|---|---|---|---|
| SYN 198.51.100.7:50514 to 192.0.2.10:443 | no entry, so NEW | rule 2 | accepted, and an entry is created |
| SYN-ACK 192.0.2.10:443 to 198.51.100.7:50514 | matches the reversed tuple of the entry above, so ESTABLISHED | rule 1 | accepted, with no rule written for it |
| SYN 198.51.100.7:50515 to 192.0.2.10:3306 | no entry, so NEW | none of 1 to 3, so rule 4 | dropped |
| SYN 198.51.100.9:40000 to 192.0.2.10:22 | no entry, so NEW | rule 3 fails the source test, so rule 4 | dropped |
Reordering would change the result. Put a broad accept above a narrow drop and the drop never fires, which is the most common rule-order mistake (see Gotchas).
Try it: edit the rules, reorder them, and send packets to watch the first match win. Then flip between stateless and stateful, send a reply, and open the asymmetric-routing and full-table labs.
A stateful hit is accepted before the rules are read, as a cloud security group does. On Linux you write that as an ESTABLISHED,RELATED accept rule. A full table drops packets that need a new entry, whatever the rules say. Only the first fragment carries ports.
Stateless vs stateful
The distinction is whether the firewall remembers connections:
| Stateless filter | Stateful firewall | |
|---|---|---|
| State kept | None | A table of active flows, one entry per connection or pseudo-connection |
| Decision basis | Each packet judged alone on its header fields | Header fields plus whether the packet belongs to a known flow |
| Return traffic | Needs its own rule, including the client's whole ephemeral port range | Replies to a permitted flow are allowed automatically |
| Cost | Cheap and fast, no memory growth | Memory per flow, a lookup per packet, a table that can fill |
| Failure mode | A rule hole too wide, or a forgotten return rule | Table full, expired entry, or reply arriving on a different box |
Stateless filtering is not obsolete: line-rate routers apply it as an access list because it needs no memory per flow.
The cloud's version of this split is the security group (stateful) against the network ACL (stateless). That page is the owner; the three-line summary:
- A security group is stateful and allow-only, attached to an interface: write the rule for the direction that opens the connection.
- A network ACL is stateless and numbered with allow and deny, at the subnet edge: write rules for both directions, including the ephemeral return ports.
- A packet must pass both, and teams usually run security groups per tier and leave the ACL as a coarse backstop. Details: security groups vs network ACLs.
The state table (conntrack)
Linux's stateful firewalling is the connection tracking subsystem, nf_conntrack, which NAT also uses (see NAT and conntrack). An entry stores the flow twice: the original tuple as the first packet carried it, and the reply tuple with source and destination swapped. A packet is a reply if its tuple equals the stored reply tuple.
A real entry, from conntrack -L (the addresses are the example's; the layout is the real format):
Read it as: protocol tcp (6), 431998 seconds left on the timer, state ESTABLISHED, then the original tuple, then the reply tuple. Netfilter classifies each packet as one of four states (NEW, ESTABLISHED, RELATED, INVALID, matched with -m conntrack --ctstate in iptables-extensions(8)). RELATED is a new flow explicitly tied to an existing one, such as an ICMP error about a tracked connection or an FTP data channel set up by a helper. INVALID is a packet that fits no known flow and breaks the protocol's rules.
Sizing and timers
The kernel documents every conntrack limit and timer (nf_conntrack sysctl):
| Setting | Default | Meaning |
|---|---|---|
nf_conntrack_tcp_timeout_established | 432000 s (5 days) | an idle established TCP flow is kept this long |
nf_conntrack_tcp_timeout_syn_sent | 120 s | a half-open outbound handshake |
nf_conntrack_tcp_timeout_time_wait | 120 s | after the close, to catch stray packets |
nf_conntrack_udp_timeout | 30 s | UDP with traffic in one direction only |
nf_conntrack_udp_timeout_stream | 120 s | UDP once traffic has flowed both ways |
nf_conntrack_icmp_timeout | 30 s | an ICMP echo and its reply |
nf_conntrack_generic_timeout | 600 s | any other protocol |
The table size follows from memory. The docs say the hash table defaults to total memory divided by 16384 buckets, capped at 262144, and that nf_conntrack_max defaults to the bucket count. Derive it for a 4 GiB machine: 232 / 214 = 218 = 262,144 buckets, so a maximum of 262,144 entries. Each entry is a kernel object of a few hundred bytes (read the real size from the nf_conntrack row of /proc/slabinfo); at an assumed 300 bytes, 262,144 entries is about 79 MB and 1,000,000 entries is about 300 MB. That is the cost of raising the limit, and it is an estimate, not a spec.
The same numbers show how little a flood needs. An entry created by an unanswered SYN lives for the syn_recv timer, 60 s by default. To keep 262,144 such entries alive you need 262,144 / 60, about 4,400 new half-open connections per second, a rate a single modest host can send. When the table is full the kernel drops packets that need a new entry and logs nf_conntrack: table full, dropping packet, while connections already in the table keep working.
Stateful firewalls and UDP and ICMP
UDP has no handshake, so there is nothing to track but a pseudo-connection: the first outbound datagram creates an entry, and a reply with the reversed tuple before the timer runs out is treated as ESTABLISHED. The entry then lives for 30 s with traffic one way, and 120 s once packets have flowed both ways (the table above). A DNS query to 198.51.100.53:53 therefore has its answer allowed back with no inbound rule, and a long-idle UDP session silently loses its hole after the timer (UDP covers keepalives).
ICMP works the same way for echo request and reply (30 s). ICMP errors are matched as RELATED to the flow that caused them, which is why a rule that accepts RELATED also lets a "fragmentation needed" message back through. That connection to path MTU discovery is the reason blocking all ICMP is a bug, not a hardening step.
NAT has the same hole-punching dependence on these timers, discussed in NAT.
Deep dive
The netfilter hooks, and where iptables and nftables attach
On Linux, the firewall is netfilter: a set of hook points in the kernel's packet path. iptables and nftables are two front ends that attach rules to those hooks. A forwarded packet crosses PREROUTING, then a routing decision, then FORWARD, then POSTROUTING. A packet for this host takes INPUT instead, and a locally generated one leaves via OUTPUT and POSTROUTING.
The iptables tables are four jobs attached to those hooks (see iptables(8)):
| Table | Job | Chains it has |
|---|---|---|
filter | Accept or drop. The default table, and where firewall rules normally live | INPUT, FORWARD, OUTPUT |
nat | Rewrite addresses and ports (DNAT, SNAT, MASQUERADE) on the first packet of a flow | PREROUTING, OUTPUT, POSTROUTING, and INPUT on kernels since 2.6.34 |
mangle | Alter packet fields such as TOS, TTL or a mark | all five |
raw | Runs before conntrack, mainly to exempt a flow from tracking | PREROUTING, OUTPUT |
Three consequences worth stating aloud. A forwarded packet never touches INPUT or OUTPUT, so a rule on INPUT does not protect a host that routes for others; use FORWARD. DNAT happens in PREROUTING, before the routing decision, so a rewritten destination is routed as if the packet had arrived addressed to it. SNAT happens in POSTROUTING, after routing has chosen the outgoing interface, because the new source depends on that choice.
A minimal default-deny host ruleset in both tools. The first is iptables:
and the same policy in nftables (nft(8)):
nftables merged into Linux 3.13 as the successor to iptables: one framework with one rule syntax for IPv4, IPv6 and bridging, sets and maps in the rules, and atomic ruleset replacement. On many current distributions the iptables command is a compatibility front end that writes nftables rules, so iptables -L and nft list ruleset can show the same rules in two syntaxes. macOS and the BSDs use a different firewall, pf, configured in pf.conf(5).
Egress filtering and default deny both ways
Most rulesets are written for inbound traffic and leave outbound open. That stops a stranger from reaching your services and does nothing about a compromised host calling out. Malware that opens its own outbound connection to a command server, or sends data to an attacker's storage, passes any ruleset that allows all egress. Egress rules (allow DNS to your resolver, HTTPS through a proxy, nothing else) turn that into a blocked and logged connection. Egress through NAT gateways and private service endpoints are the cloud forms of the same idea.
Host firewall, network firewall, NGFW
A host firewall runs on each machine (iptables, nftables, pf, the Windows firewall) and protects that machine wherever it is plugged in. A network firewall is a box or a virtual appliance at a boundary protecting everything behind it. They are layers, not alternatives: the network firewall carries the coarse policy, the host firewall catches what an attacker who is already inside tries to reach.
A next-generation firewall (NGFW) is a commercial category rather than a standard: a network firewall that also identifies the application (not just the port), ties rules to user identity, and bundles intrusion prevention, and usually offers TLS inspection. Appliance vendors such as Palo Alto Networks and Fortinet sell them. TLS inspection means the firewall terminates the client's TLS session, reads the plaintext, and opens a second session to the server, which only works if client devices trust the firewall's enterprise CA (see certificates and PKI) and it breaks anything that pins certificates.
Firewall vs WAF vs IDS/IPS
These four controls answer different questions and sit in different places:
| Control | Layer it reads | Action | Placement | Sees HTTP bodies |
|---|---|---|---|---|
| Network firewall | L3 and L4 headers, plus connection state | Accept or drop | At a boundary, or on the host | No |
| NGFW | L3 to L7, with application and user identity | Accept, drop, and optional IPS | At a boundary | Only if it decrypts TLS |
| WAF | L7 HTTP: URL, headers, cookies, body | Block, log, challenge, or rate-limit | In or behind the reverse proxy or CDN that terminates TLS | Yes |
| IDS | A copy of traffic, headers to payload | Alert only | Out of band, on a mirror port or tap | Only if fed decrypted traffic |
| IPS | The same inspection, inline | Alert and drop | Inline in the path | Only if it sees decrypted traffic |
An IDS (intrusion detection system) watches a copy of traffic, so it cannot slow or break anything, and it also cannot stop anything: it raises an alert and a human or script responds. An IPS sits inline and drops what it flags, which makes a false positive an outage. Both detect in two ways. Signature detection matches known attack patterns: precise, and blind to anything new. Anomaly detection learns a baseline and flags deviations: it can catch novel attacks and produces more false positives.
A WAF (web application firewall) understands HTTP. It runs in or behind a reverse proxy, because only there is TLS already terminated and the request already parsed. Its rules look for patterns such as SQL injection or path traversal in the URL, headers and body. The open-source baseline is the OWASP Core Rule Set, run on engines such as ModSecurity, which scores each matching rule and blocks a request when the total crosses a threshold (anomaly scoring). A WAF cannot fix the bug behind the request, it only filters the shapes it recognises, and it shares the reverse proxy's privileges, which is the lesson of the incident below.
Segmentation: the DMZ
Segmentation divides a network into zones with a firewall between them, so a breach in one zone does not reach the rest. The classic form is the DMZ (demilitarised zone): a subnet between the internet and the internal network that holds the servers which must be reachable from outside, such as a public web server, a mail relay or public DNS. Those hosts are the most exposed, so they are assumed compromisable and placed where a compromise is contained.
The two-firewall form uses one box per boundary, ideally from different vendors so one flaw does not open both. A cheaper form uses one firewall with three interfaces (outside, DMZ, inside) and a policy per pair. Either way the rule that makes it a DMZ is that the DMZ may not initiate connections into the inside, except the few it needs; traffic that originates inside may go out.
Three tiers in a cloud VPC
The cloud version replaces the boxes with subnets and security groups. A three-tier app puts the load balancer in a public subnet, the application servers and the database in private subnets, and gives each tier a security group that allows only the tier in front of it. The groups reference each other rather than address ranges, so scaling the application tier needs no rule change.
The ports and group names are an example design. Three details finish it. Egress: the database group needs no route or rule to the internet, and the app group reaches external APIs through a NAT gateway or a private endpoint, never a public address. Administration: a bastion host (jump host) is a hardened machine with a public address whose only job is SSH; admins connect to it and hop to private hosts, so one logged, patched, MFA-protected door replaces SSH on every server. Where the rules live: the security-group mechanics, including how groups reference groups, are on security groups vs network ACLs.
Microsegmentation and zero trust
A DMZ draws a few large zones. Microsegmentation draws many tiny ones, down to a single workload, so that a compromised host can reach only the handful of peers its job requires. It is the answer to lateral movement: on a flat internal network, any foothold can scan and call everything else. In Kubernetes, a NetworkPolicy is the native form. Start from deny, then allow the one path that is needed:
A NetworkPolicy object has no effect unless the cluster's network plugin enforces it (Kubernetes network policies). Plugins such as Calico and Cilium do; Cilium enforces policy in the kernel with eBPF (Cilium policy).
Zero trust takes the idea to its end: network location grants no trust. NIST SP 800-207 describes it as moving defences from network perimeters to protecting resources, with every access request authenticated and authorised before a session starts. Its architecture splits a policy decision point (who may reach what, given identity, device state and context) from policy enforcement points (the gate in front of each resource). Google's BeyondCorp is the well-known production example: access decisions rest on the user and the device, not on whether the laptop is on the corporate network. The building blocks are on other pages: identity and tokens in authentication in practice, mTLS (both sides present certificates) in certificates and PKI, and the contrast with network-level access in VPN, IPsec and WireGuard. Zero trust does not delete firewalls: it moves their policy from addresses to identities, and microsegmentation is where the two meet.
How stateful firewalls fail
Asymmetric routing. A stateful firewall allows a reply only if it created the entry when it saw the request. If the request leaves through firewall A and the reply returns through firewall B (ECMP, BGP multi-homing, or a redundant pair with no state sync), B has no entry and drops a legitimate packet. The symptom is intermittent failures that vanish when one path is shut. The fixes are to force symmetric paths, or to run the pair with state synchronisation so either box can match the reply.
Table exhaustion. Covered above: past nf_conntrack_max, new flows are dropped. The levers are raising the limit (memory), shortening timers, exempting high-volume trusted flows from tracking in the raw table, and absorbing floods upstream (see DDoS). iptables also has a SYNPROXY target that completes the TCP handshake on behalf of the protected server so half-open entries never reach it (iptables-extensions(8)).
Mid-stream pickup. By default the kernel's TCP tracking is loose (nf_conntrack_tcp_loose is on): a packet from a connection it never saw can create an entry as if the firewall had been restarted mid-conversation. That avoids dropping live connections after a reboot, and it also means a stray non-SYN packet is not automatically INVALID. Rules that must accept only real connection starts therefore match the SYN flag as well as the state.
FTP active mode. FTP uses a control connection on port 21. In active mode the client sends a PORT command carrying its own IP and a port, and the server connects back from its port 20 to that port (RFC 959). A firewall that allows only the client's outbound connections sees an unsolicited inbound SYN and drops it. Making it work needs an application-layer helper that reads the PORT command off the control channel and opens a matching RELATED hole, which is what Linux's FTP conntrack helper does (modern kernels do not attach helpers automatically; you assign one explicitly with the CT target in iptables or ct helper in nftables). A NAT breaks it further, because the client's private address is inside the payload (NAT). Passive mode (PASV, client dials a server port) avoids the problem because every connection is outbound from the client, which is why it is the default for most clients.
Blocked ICMP. Dropping all ICMP breaks path MTU discovery: the "fragmentation needed" message is the only signal a sender gets that its packet was too big, and without it large transfers stall while small ones work (MTU, MSS and fragmentation, ICMP and ping).
Textbook vs real world
| The textbook says | Production does | Why |
|---|---|---|
| The perimeter firewall protects the internal network. | Segments inside too: tier security groups, microsegmentation, host firewalls. | Once an attacker is past the perimeter, a flat network lets them reach everything. See the perimeter row on the threat model. |
| A stateful firewall is always better than a stateless filter. | Uses stateless ACLs on line-rate routers and as a coarse backstop, and stateful policy on hosts and gateways. | State costs memory per flow and creates a table an attacker can fill, so it is spent where it earns its keep. |
| NAT gives you a firewall. | Writes an explicit default-deny inbound policy and treats NAT as address plumbing. | NAT drops unsolicited inbound traffic only because it has no mapping; that is a side effect, it is absent for IPv6, and a forwarding rule or an inside-out connection bypasses it (NAT). |
| Deny all inbound is enough. | Also filters egress and logs the drops. | Compromised hosts call out to command servers and exfiltrate data over connections the inbound policy never sees. |
| Ports identify applications, so port rules are enough. | Adds application identification (NGFW), a WAF for HTTP, and identity-based access. | Anything can run on 443, and a port rule cannot tell a browser from a tunnel. |
| Inspect all traffic at the boundary. | Terminates TLS at a proxy or load balancer and runs the WAF there, and decrypts in an NGFW only where policy demands it. | Most traffic is encrypted, so a middlebox sees headers only unless it is a TLS endpoint. |
In production
- AWS and GCP ship the stateful-filter model as a managed service. AWS uses security groups per interface plus subnet-level network ACLs. GCP uses VPC firewall rules and hierarchical firewall policies that apply across projects and folders. The comparison is on security groups vs network ACLs.
- Kubernetes runs conntrack on every node for Service load balancing, so a full conntrack table breaks Service traffic (Virtual IPs and Service Proxies). Pod-to-pod policy is NetworkPolicy, enforced by the CNI plugin, for example Cilium with eBPF.
- Cloudflare sells the same controls as services at its edge: a WAF in the reverse proxy and Magic Firewall for network-layer rules on customer traffic.
- Google moved its corporate access from a privileged network to per-request, identity-and-device decisions, described in the BeyondCorp paper.
- Capital One, 2019. An attacker exploited a server-side request forgery (SSRF) flaw, made requests through a misconfigured web application firewall, and obtained temporary credentials of the cloud role attached to it, then used them to read data from storage. The US Department of Justice's announcement of the arrest and Capital One's own incident notice are the primary sources. The lesson for this page: a WAF is a privileged reverse proxy, so its misconfiguration and its role are part of the attack surface, and egress and role permissions limit what a successful request can reach.
History and evolution
- 1989 Packet filtering for Unix gateways appears in research and practice; DEC's
screend(Jeffrey Mogul, USENIX 1989) is an early kernel packet filter. What was missing: rules saw one packet at a time, so replies needed rules of their own. - 1994 Check Point ships FireWall-1, popularising stateful inspection: remember outbound flows so replies are allowed. What broke next: the state table became a resource to exhaust.
- 1998 The netfilter project starts and iptables ships in Linux 2.4 (2001) with connection tracking built in. What broke: separate tools for IPv4, IPv6 and ARP, and rules that were replaced one at a time.
- 2000 RFC 2979 sets out the behaviour and interoperability requirements of firewalls, chiefly a transparency rule: a firewall must not break legitimate, standards-compliant traffic that would work without it.
- 2009 NIST publishes SP 800-41 Rev. 1, guidelines on firewalls and firewall policy.
- 2010 Forrester's John Kindervag names zero trust, arguing against trusted "chewy centers". What broke: the perimeter model, once laptops and cloud services lived outside it.
- 2014 Linux 3.13 merges nftables. Google publishes the BeyondCorp design in the same year.
- 2017 Kubernetes NetworkPolicy reaches stable, and eBPF-based enforcement (Cilium) spreads policy from boxes to workloads.
- 2020 NIST publishes SP 800-207, the zero trust architecture standard.
- Now Layered: cloud security groups per tier, host firewalls, WAFs at the edge, and identity-aware access replacing network-wide VPNs for many apps.
- Next Policy expressed in identities and labels rather than addresses, enforced in an eBPF data plane on each host.
Hands-on
Inspect a Linux host's rules and counters. Output depends on what is installed, and the packet counts here are illustrative:
Look at the policy on the chain header and at the counters: a rule with 0 packets is either unused or shadowed by an earlier one, and the policy's drop counter shows what the final default is catching. On an nftables system, sudo nft list ruleset prints the same state in nft syntax.
Watch the state table:
conntrack -L lists entries in the format shown earlier, conntrack -C prints the current count, and the last command prints the live count and the limit. A count close to the limit is the early warning for table full, dropping packet. The conntrack tool comes from the conntrack-tools package.
Test what a client sees, to tell drop from reject:
A timeout means a DROP rule (or no route or no host). Connection refused means a REJECT rule or an open host with nothing listening. Message wording differs by nc variant and operating system.
On macOS the firewall is pf, and it is typically not enabled until you load rules:
-s info shows whether pf is enabled and its counters, -sr lists the loaded rules and -ss lists the state table, the pf counterpart of conntrack -L. macOS has no iptables or conntrack. Its separate application firewall (System Settings, Network, Firewall) is a per-application allow list, not pf.
Gotchas
Interview questions
Show answer
A stateless firewall judges each packet alone against its rules, using only header fields. A stateful firewall also keeps a table of active connections: when an inside host opens a connection, it records the flow, and the replies are allowed automatically because they match the recorded flow in reverse. The stateful one is more precise and needs less rule writing, at the price of memory per connection.
Follow-ups:
- What happens to the reply packet? It is looked up in the state table by its reversed tuple, found, and accepted before the ruleset is consulted.
- What does the stateful firewall cost? A table entry per flow and a lookup per packet, and a table that can fill.
Show answer
A DMZ is a network segment between the internet and the internal network that holds the servers which must be reachable from outside, such as web and mail servers. If one of those is compromised, the attacker is still outside the internal network and has to get through another firewall. Internal hosts can reach the DMZ, but the DMZ may initiate only the few connections it needs into the inside.
Follow-ups:
- What is the two-firewall design? An outer firewall between the internet and the DMZ and an inner one between the DMZ and the inside, ideally from different vendors so one bug does not open both.
- What is the single-firewall version? One firewall with three interfaces and a policy per pair of zones.
Show answer
A security group is stateful and allow-only, attached to a network interface, so you write the rule for the direction that opens the connection. A network ACL is stateless, numbered, supports allow and deny, and applies at the subnet edge, so you write both directions. A packet has to pass both. Teams use security groups for the application and leave the ACL as a coarse backstop.
Follow-ups:
- Why do NACLs need return rules? They keep no connection state, so the reply is just another packet to judge, and it needs an outbound rule that covers the client's ephemeral port range.
- Where is the full comparison? Security groups vs network ACLs.
Show answer
A network firewall decides on L3 and L4 headers and connection state, and sits at a boundary or on the host. A WAF reads HTTP (URL, headers, body) and runs in or behind the reverse proxy that terminates TLS. An IDS watches a copy of traffic and only alerts. An IPS sits inline and blocks what it flags. They are layered because each sees something the others cannot.
Follow-ups:
- Where does each sit? Firewall at the boundary or host, WAF at the reverse proxy or CDN, IDS on a mirror port or tap, IPS inline.
- Signature or anomaly detection? Signatures match known attacks precisely and miss new ones, anomaly detection can catch new ones and has more false positives.
Show answer
It enters PREROUTING, where raw runs first, then conntrack, then mangle and the nat table's destination rewrite. Routing then decides the packet is not for this host, so it goes through the FORWARD chain (mangle and filter), then POSTROUTING (mangle and the nat table's source rewrite) and out. It never touches INPUT or OUTPUT.
Follow-ups:
- Where does DNAT hook? PREROUTING, before routing, so the new destination is what gets routed.
- Where does SNAT hook? POSTROUTING, after routing has chosen the outgoing interface.
Show answer
There is no handshake, so it creates a pseudo-connection entry from the first outbound packet and allows a reversed-tuple reply while the entry lives. On Linux the timers are 30 s for UDP with traffic one way, 120 s once it flows both ways, and 30 s for ICMP echo. ICMP errors are matched as related to the flow that caused them.
Follow-ups:
- What are the timeouts for? To expire entries for flows that never produce a closing packet.
- What is hole punching? Two peers each send outbound first so each side's table has an entry and the other's packets match it. Details on NAT.
Show answer
In active mode the client announces its IP and a port in a PORT command on the control connection, and the server opens a new connection back to that port. The firewall sees an inbound SYN it never authorised, and a NAT sees a private address in the payload. A helper that reads the control channel can open the matching hole and rewrite the address.
Follow-ups:
- What fixes it without a helper? Passive mode, where the client dials a server port and every connection is outbound from the client.
- What is the helper called on Linux? The FTP conntrack helper, which creates a
RELATEDexpectation for the data connection.
Show answer
Put the load balancer in a public subnet and the app and database in private subnets. Give each tier a security group that allows only the tier in front, referenced by group, not by address, so the database admits only the app group on its port. Allow administration only through a bastion in the public subnet, restrict egress so the database has none and the app reaches the internet through a NAT gateway or private endpoint, and leave the network ACL as a coarse backstop.
Follow-ups:
- How do you test it? From each tier, try connections that should fail (app to the internet, web to database), check the drop counters and flow logs, and review the rules for any
0.0.0.0/0source that is not the load balancer. - What about secrets and metadata? Limit the role each instance holds, since a request that reaches the instance can reach what the role reaches.
Show answer
Zero trust grants no trust from network location: every request is authenticated and authorised against identity and device state before access. Microsegmentation enforces it at workload granularity, so each workload can reach only the peers it needs. It changes the question a firewall answers from "which address is this" to "which identity is this", and it limits lateral movement after a breach.
Follow-ups:
- What does the policy look like in Kubernetes? A default-deny NetworkPolicy, plus one allow per required path, for example app to database on 5432, enforced by a CNI that supports policy.
- Does it remove VPNs and firewalls? It often replaces the broad network VPN with per-application access, but tunnels and packet filters still exist underneath.
Fun facts
- Linux keeps an idle established TCP flow for 432,000 seconds, exactly five days, by default (nf_conntrack sysctl).
- Each tracked connection is inserted into the conntrack hash table twice, once per direction, so a full table has an average chain length of 2, not 1 (same kernel document).
- A Kubernetes NetworkPolicy does nothing at all unless the cluster's network plugin enforces it (Kubernetes docs).
Cheat sheet
- 432000 s - Linux conntrack established TCP default, 5 days
- 30 s / 120 s - UDP timeout one-way / both ways
- 30 s - ICMP timeout
- 262,144 - default table size on a 4 GiB machine (
232 / 214) - 4 states - NEW, ESTABLISHED, RELATED, INVALID
- 5 hooks - PREROUTING, INPUT, FORWARD, OUTPUT, POSTROUTING
- 4 tables - raw, mangle, nat, filter, in that order within a hook