iptables vs Security Group
One-liner#
iptables is an OS kernel-level firewall; Security Group is an AWS VPC-level virtual firewall. iptables runs inside the host; SG runs outside the host (at the hypervisor).
Where Each Operates#
[Internet]
↓
[AWS VPC]
↓
[Security Group] ← Hypervisor (ENI) level — filters traffic before it reaches EC2
↓
[EC2 instance]
↓
[iptables] ← OS kernel (netfilter) level — filters traffic inside EC2
↓
[Application]
SG filters traffic before it ever reaches the EC2 instance. iptables filters inside EC2 at the kernel level.
iptables is Linux-only#
iptables runs on top of the Linux kernel’s netfilter framework. Other operating systems have their own firewalls:
| OS | Firewall | Configuration |
|---|---|---|
| Linux | iptables / nftables | iptables, nft, or ufw (wrapper) |
| Windows | Windows Firewall (WFP) | netsh advfirewall or GUI |
| macOS | PF (Packet Filter) | pfctl, /etc/pf.conf |
iptables is Linux-only. Windows Firewall and macOS PF are conceptually similar (packet filtering) but are completely different implementations.
iptables configuration on Linux#
# View current rules
sudo iptables -L -n -v
# Rule files (varies by distro)
/etc/iptables/rules.v4 # Debian/Ubuntu (iptables-persistent)
/etc/sysconfig/iptables # RHEL/CentOS
# Using ufw (Ubuntu default)
sudo ufw status
sudo ufw allow 443/tcp
# Internally creates iptables rules
# nftables (successor to iptables)
/etc/nftables.conf
sudo nft list ruleset
iptables vs nftables#
iptables is becoming legacy; nftables is its successor:
| iptables | nftables | |
|---|---|---|
| Status | Legacy (maintenance-only) | Current standard |
| Kernel | netfilter | netfilter (same framework) |
| Performance | Slow with many rules (linear scan) | Optimized (map/set support) |
| Syntax | Separate commands per table | Unified syntax |
| K8s | kube-proxy default | kube-proxy nftables mode |
On recent Ubuntu/Debian, running iptables may internally use the nftables backend (iptables-nft).
Key Differences#
| iptables | Security Group | |
|---|---|---|
| Where it runs | OS kernel (netfilter) | AWS hypervisor (ENI) |
| Who manages it | User directly | AWS Console / API / Terraform |
| Default policy | Allow (ACCEPT) | Deny (DENY) |
| Rule types | Both allow and deny | Allow only (no DENY rules) |
| Stateful tracking | Stateful or stateless (your choice) | Always stateful |
| Rule evaluation | Order matters (top to bottom) | All evaluated (no order) |
| Scope | The host itself | Resources attached to the ENI |
Stateful Tracking#
Both can be stateful, but they differ:
Security Group (always stateful)#
Inbound: allow 443
→ Client request arrives (443)
→ Response goes out (automatically allowed — no outbound rule needed)
SG is unconditionally stateful. If an inbound connection is allowed, the return traffic is automatically permitted without any outbound rule.
iptables (configurable)#
# Stateful (using conntrack)
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -j ACCEPT
# Stateless (without conntrack)
iptables -A INPUT -p tcp --dport 443 -j ACCEPT
iptables -A OUTPUT -p tcp --sport 443 -j ACCEPT # Response must be explicitly allowed
iptables can be stateful via the conntrack module, or run stateless when performance demands it.
Rule Evaluation#
iptables: first match wins#
iptables -A INPUT -s 10.0.0.5 -j DROP # Rule 1: block this IP
iptables -A INPUT -p tcp --dport 443 -j ACCEPT # Rule 2: allow 443
A request from 10.0.0.5 to port 443 hits Rule 1 and is DROPped. Order matters.
Security Group: all rules evaluated#
Inbound:
443 ← 0.0.0.0/0
443 ← sg-ecs-app
All rules are evaluated; a packet is allowed if any rule matches. There is no ordering. Also, there are no DENY rules — to block a specific IP you need NACL, not SG.
DENY Rules#
| Tool | Allow | Deny |
|---|---|---|
| iptables | Yes (ACCEPT) | Yes (DROP/REJECT) |
| Security Group | Yes | No (DENY not available) |
| NACL | Yes | Yes |
Want to block a specific IP with SG? You can’t. In AWS, IP blocking requires NACL (Network ACL) or WAF.
When you need to block:
L3/L4 block → NACL (subnet level, stateless)
L7 block → WAF (HTTP level, path/header based)
Host block → iptables (OS level)
In Kubernetes#
Both are used in K8s environments:
[AWS VPC]
Security Group → Network access control at EKS node/Pod level
↓
[K8s cluster]
NetworkPolicy → Pod-to-pod communication control (implemented by CNI via iptables/eBPF)
↓
[Pod]
iptables/nftables → Istio sidecar, kube-proxy service routing
- kube-proxy: implements Service → Pod routing as iptables rules
- Calico/Cilium: implements NetworkPolicy via iptables or eBPF
- Istio: controls traffic via Envoy sidecar (iptables redirects traffic into the sidecar)
Security Group vs NACL#
Both are AWS firewalls but operate at different levels:
| Security Group | NACL | |
|---|---|---|
| Scope | ENI (instance/Pod) | Subnet |
| Stateful tracking | Stateful | Stateless |
| Rule types | Allow only | Allow + Deny |
| Rule evaluation | All rules (no order) | In order (lowest number first) |
| Default policy | Deny all | Allow all (default NACL) |
| Use case | Per-resource access control | Subnet-level IP blocking |
[Internet]
↓
[NACL] ← Filters at the subnet boundary (can block IPs)
↓
[Security Group] ← Filters at the ENI level (allow rules only)
↓
[EC2 / Pod]
When to use NACL#
SG cannot block a specific IP (no DENY rules). Use NACL when IP blocking is needed:
NACL Inbound:
Rule 10: DENY TCP 443 from 203.0.113.5/32 ← block malicious IP
Rule 100: ALLOW TCP 443 from 0.0.0.0/0 ← allow everything else
Rule *: DENY ALL from 0.0.0.0/0 ← default deny
NACL is stateless, so outbound response rules are also required:
NACL Outbound:
Rule 100: ALLOW TCP 1024-65535 from 0.0.0.0/0 ← response (ephemeral ports)
In practice#
SG alone is sufficient for most cases, and NACL is often left untouched. Use NACL when:
- Blocking specific IPs or ranges (attacker IPs)
- Restricting communication at the subnet level (compliance requirements)
- DENY rules that cannot be expressed with SG
Summary#
| Situation | Choice |
|---|---|
| Access control between AWS resources | Security Group |
| Block a specific IP | NACL or WAF |
| Host-level firewall | iptables |
| Pod-to-pod communication control in K8s | NetworkPolicy (backed by iptables/eBPF) |
| On-premises server firewall | iptables / nftables / ufw |
In the cloud, SG is the first line of defense; iptables is used inside hosts or as an internal implementation detail in K8s. On-premises, iptables (or ufw) is the primary firewall.