Before I hit the firewall issue with my portfolio, I had no real understanding of iptables. I'd read about it, but it only clicked when I had to debug actual dropped packets. This is what I now know — explained through the problem I had.
What is iptables?
iptables is the Linux kernel's built-in firewall. It processes every packet that
enters, leaves, or passes through your machine using a set of chains containing
rules. Rules are evaluated top-to-bottom. The first matching rule wins.
The Three Main Chains
- INPUT — traffic destined for the local machine
- OUTPUT — traffic generated by the local machine
- FORWARD — traffic passing through (router behaviour)
Each chain has a default policy — what happens to a packet if no rule matches. On Oracle Cloud VMs, the INPUT chain has a REJECT rule near the bottom that acts like a catch-all.
Viewing Your Current Rules
sudo iptables -L INPUT --line-numbers -n -v
The flags matter:
-L INPUT— list only the INPUT chain--line-numbers— show rule numbers (important for insertion)-n— numeric output (no DNS lookup delays)-v— verbose (shows packet counts, interfaces)
The Problem I Had
My OCI VM's INPUT chain looked like this:
num target prot source destination 1 ACCEPT all 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED 2 ACCEPT icmp 0.0.0.0/0 0.0.0.0/0 3 ACCEPT all 0.0.0.0/0 0.0.0.0/0 (lo) 4 ACCEPT tcp 0.0.0.0/0 0.0.0.0/0 dport 22 5 REJECT all 0.0.0.0/0 0.0.0.0/0
Port 80 traffic arrived, matched no ACCEPT rule before rule 5, and got rejected. The key insight: iptables processes rules in order, and rule 5 rejected everything not explicitly accepted above it.
The Correct Fix — Insertion, Not Append
# WRONG — appending puts the rule AFTER the REJECT sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT # CORRECT — insert at position 5, pushing REJECT to position 6 sudo iptables -I INPUT 5 -p tcp --dport 80 -j ACCEPT
-I INPUT 5 inserts at position 5. The old rule 5 (REJECT) becomes rule 6.
Now port 80 traffic matches rule 5 (ACCEPT) before it reaches the REJECT.
Saving Rules Across Reboots
iptables rules are in-memory. They're lost on reboot unless saved:
sudo apt install iptables-persistent -y sudo netfilter-persistent save # Saves to /etc/iptables/rules.v4 and rules.v6
Key Takeaways
- Rules are evaluated top to bottom — order is everything
- Use
-I(insert) to place rules before an existing catch-all, not-A(append) - Always save with
netfilter-persistent save— otherwise your fix disappears on reboot - On OCI VMs, there are two firewalls: the OCI Security List AND iptables — both must allow the traffic
tcpdumpconfirms whether packets reach the VM at all — if they do and still fail, it's iptables