Firewalls & Security Groups
Firewalls enforce who may talk to whom, either statelessly per packet or statefully per connection. Learn iptables and nftables fundamentals, default-deny policy, and how cloud security groups and network ACLs differ.
What is this?
A firewall filters traffic based on rules. Stateless firewalls evaluate every packet in isolation, while stateful firewalls track connections and allow reply traffic automatically. On Linux, iptables and nftables implement packet filtering with chains of rules; in the cloud, security groups are stateful filters attached to instances and network ACLs are stateless filters attached to subnets.
Why do you need it?
- Defense in depth starts with restricting what can reach each service.
- Most connectivity bugs — and many breaches — trace back to firewall rules.
- iptables/nftables skills transfer directly to containers, Kubernetes and cloud networking.
- Understanding stateful vs stateless explains why a security group works and a broken NACL does not.
Mental model
A building's security desk
A stateful firewall
When you enter, the desk records your badge. They let you in and, because they know you are inside, let you back out without a fresh check. A stateless firewall has no memory — it re-checks every door you pass, both ways.
How it works
- Packets enter named chains — INPUT for traffic to the host, OUTPUT for traffic from it, FORWARD for routed traffic.
- Each rule matches on attributes like source IP, destination port and protocol, then jumps to a target: ACCEPT, DROP or REJECT.
- Rules are evaluated in order; the first match wins, so order and default policy matter.
- Stateful tracking (conntrack) marks connections as NEW, ESTABLISHED or RELATED so reply packets are allowed automatically.
- A default policy of DROP plus explicit ACCEPT rules is the secure baseline; REJECT actively refuses instead of silently dropping.
Packet flow through iptables filter chains.
Key commands
iptables -L -n -vList filter rules with counters, skipping DNS lookups.
iptables -A INPUT -p tcp --dport 443 -j ACCEPTAppend a rule accepting HTTPS traffic to the INPUT chain.
iptables -I INPUT 1 -s 1.2.3.4 -j DROPInsert a drop rule for a source IP at the top of the chain.
ufw status verboseShow the Ubuntu Uncomplicated Firewall profile and its rules.
nft list rulesetDump the complete nftables ruleset (the modern successor to iptables).
Examples
A minimal default-deny host firewall
iptables -P INPUT DROPiptables -P FORWARD DROPiptables -P OUTPUT ACCEPT iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPTiptables -A INPUT -i lo -j ACCEPTiptables -A INPUT -s 10.0.0.0/8 -p tcp --dport 22 -j ACCEPTiptables -A INPUT -p tcp --dport 80 -j ACCEPTiptables -A INPUT -p tcp --dport 443 -j ACCEPTiptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT iptables -L -n -vThe default INPUT policy is DROP, then four ACCEPT rules open SSH for the private range only, HTTP and HTTPS for everyone, plus loopback and established connections. Listing with -L -n -v shows each rule's packet and byte counters.
In production
- Host firewalls (ufw, firewalld, iptables) restrict which ports each server exposes.
- Security groups define per-service ingress in the cloud and are stateful by design.
- Network ACLs add a stateless subnet boundary in front of security groups.
- Service meshes and Kubernetes NetworkPolicies push firewall logic down to the pod level.
Best practices
- Default to deny: allow only the ports and source ranges a service actually needs.
- Restrict admin ports (SSH 22, RDP 3389) to your office or VPN CIDR, never 0.0.0.0/0.
- Prefer stateful security groups for the cloud and conntrack for host firewalls.
- Persist rules — iptables-save to a file and restore on boot, or use ufw/firewalld.
- Audit rules regularly: remove stale allow rules and open ports.
Common mistakes
- Allowing SSH from 0.0.0.0/0 and leaving default credentials.
- Blocking established/reply traffic and breaking every outbound request (missing conntrack rule).
- Appending rules after a default DROP policy and assuming they apply to the wrong chain.
- Testing a firewall change from a session that the change itself blocks — no keepalive fallback.
Common issues
Connection timeout to a serviceA DROP rule or a stateful cloud security group blocking inbound SYN.
List rules with iptables -L -n -v and watch counters; verify the cloud security group allows the port and source.
Connection refused immediatelyNo listener (REJECT from firewall or service down).
Check ss -tulpn for the listener; if it's up, look for iptables REJECT targets in the log.
Outbound works, inbound works, but clients can't reach the appFORWARD chain or subnet-level NACL drops routed traffic.
Check the FORWARD chain policy/rules and the network ACL on the subnet (stateless NACLs need both directions allowed).
Debugging tips
- Check counters with iptables -L -n -v to see which rule is dropping your packets.
- Use tcpdump on the interface to compare packets arriving vs packets allowed.
- Temporarily set policy ACCEPT to isolate a firewall bug from an app bug.
- Look for DROP vs REJECT: DROP causes timeouts, REJECT causes immediate connection refused.
Interview checkpoint
Quick quiz
What is the key difference between a stateful and a stateless firewall?
By default, an AWS Security Group allows all inbound traffic.
In iptables, which chain handles traffic addressed to the local host?
Cheat sheet
iptables -A INPUT -p tcp --dport 443 -j ACCEPTAllow HTTPS inboundiptables -I INPUT 1 -s 10.0.0.5 -j DROPDrop a specific sourceiptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPTAllow reply trafficiptables -P INPUT DROPSet default policy to denyiptables-save > /etc/iptables.rulesPersist the rulesetnft list rulesetView the nftables ruleset22/tcpSSH — restrict to office/VPN CIDR80, 443/tcpHTTP, HTTPS — the public web edge53/udp + tcpDNS queries and zone transfers5432/tcpPostgreSQL — internal only6443/tcpKubernetes API server — control-plane only