Mendiagnosis firewall yang bermasalah secara sistematis: membaca counter per-rule, memfilter iptables-save, menangkap paket dengan tcpdump, memeriksa tabel conntrack, dan mencocokkan layanan dengan ss, plus memecahkan kasus drop tanpa log, rule tertutup rule lain, NAT tidak bekerja, dan konflik Docker/UFW

Koneksi gagal. Pertanyaan pertamanya bukan "aturannya salah apa?" tapi "apa yang sebenarnya terjadi pada paket?" Episode 18 mengajarkan metode, bukan sekadar daftar perbaikan: proses berpikir sistematis yang dimulai dari memeriksa fakta, lalu menyempit ke penyebab.
Kabar baiknya: hampir semua misteri firewall bisa dipecahkan dengan lima alat yang sudah kalian kenal — counter iptables, iptables-save, tcpdump, conntrack -L, dan ss. Episode ini memakai kelimanya untuk membedah lima kasus kegagalan yang paling sering terjadi di lapangan.
Setiap kali "koneksi mati", jangan panik — jalankan urutan ini:
# 1. Apakah layanan benar-benar mendengarkan?
ss -tlnp | grep -E ":80|:443|:22"
# 2. Apakah paket masuk terlihat oleh kernel?
sudo tcpdump -ni eth0 tcp port 443 -c 20
# 3. Apakah conntrack mencatat koneksi?
sudo conntrack -L | grep 443
# 4. Rule mana yang menyentuh paket?
sudo iptables -L -n -v | grep -E "Chain|443"Empat pertanyaan ini menyempitkan lokasi masalah dengan cepat: kalau ss kosong → masalah di aplikasi, bukan firewall. Kalau tcpdump diam → paket tidak sampai. Kalau tcpdump terlihat tapi conntrack kosong → paket di-DROP di raw/PREROUTING. Dan seterusnya.
Tip
Pola ini bekerja untuk semua kasus berikut: selalu mulai dari fakta lapisan terendah (apakah paket sampai?) lalu naik ke lapisan yang lebih tinggi (apakah koneksi tercatat? apakah rule cocok?). Memperbaiki "perasaan" tanpa data adalah cara tercepat membuang waktu.
Gejalanya: koneksi gagal, tapi tidak ada satupun entri IPT: di log. Padahal ruleset punya LOG + DROP di dasar chain. Dua penyebab umum:
Penyebab A — aturan DROP lebih dulu dari aturan LOG. Karena first match wins, paket sudah di-DROP oleh aturan lain yang posisinya di atas, sehingga LOG di bawah tidak pernah dieksekusi:
sudo iptables -L INPUT -n -v --line-numbersSolusi: pastikan LOG adalah aturan terakhir sebelum DROP di dasar chain, dan tidak ada -j DROP di atasnya.
Penyebab B — paket tidak pernah masuk chain INPUT. Contoh: aturan -t raw -A PREROUTING ... -j NOTRACK atau -t nat -A PREROUTING ... -j DNAT yang mengubah jalur, sehingga paket dilewati filter. Konfirmasi dengan tcpdump:
sudo tcpdump -ni eth0 host 203.0.113.7Gejala klasik: aturan ACCEPT sudah ditulis, tapi trafik tetap ditolak. Cek urutan:
sudo iptables -S INPUT-P INPUT DROP
-A INPUT -j DROP
-A INPUT -p tcp --dport 443 -j ACCEPTTerlihat kan? Aturan -A INPUT -j DROP berada di atas ACCEPT 443 — jadi ACCEPT tidak pernah dieksekusi. Perbaiki dengan menghapus DROP yang salah tempat dan meletakkannya di paling bawah, atau insert ACCEPT di atasnya:
sudo iptables -D INPUT -j DROP
sudo iptables -A INPUT -j DROPAturan catch-all (-j DROP tanpa match) harus menjadi aturan terakhir di chain — selalu posisikan allowlist di atasnya.
NAT gagal adalah misteri favorit. Kembali ke tiga titik kritis dari episode 9:
# Titik 1: ip_forward aktif?
sysctl net.ipv4.ip_forward
# Titik 2: rule DNAT ada dan benar?
sudo iptables -t nat -L PREROUTING -n -v
# Titik 3: FORWARD mengizinkan tujuan hasil DNAT?
sudo iptables -L FORWARD -n -v | grep 192.168.1.50Jika semuanya benar, verifikasi nyata paket masuk:
sudo tcpdump -ni any port 80Perhatikan dua baris untuk tiap arah: masuk di eth0 dengan tujuan IP publik, lalu keluar di eth1 dengan tujuan 192.168.1.50. Kalau baris kedua tidak muncul → DNAT tidak diterapkan (cek -t nat -A PREROUTING bukan POSTROUTING). Kalau baris kedua ada tapi balasan tidak kembali → cek MASQUERADE.
Note
Jebakan tambahan yang sering ditemukan: dua firewall aktif sekaligus — misalnya aturan di backend iptables-nft dan sisa aturan di backend iptables-legacy (kasus dari episode 3). Keduanya tidak saling melihat, sehingga NAT tampak "berubah-ubah". Periksa iptables -V dan pastikan semua tools menunjuk backend yang sama.
Gejala: setelah install Docker, UFW mulai memblokir semuanya — atau justru port yang dibuka UFW mendadak tidak bisa diakses. Akar masalahnya ada di cara Docker menulis iptables:
DOCKER dan DOCKER-USER di awal chain FORWARD.DOCKER-USER, bukan di INPUT.sudo iptables -L FORWARD -n -v | head -20
sudo iptables -L DOCKER-USER -n -vPerbaikan umum: biarkan Docker mengelola chain-nya, dan pasang kebijakan kustom di DOCKER-USER:
sudo iptables -I DOCKER-USER -i eth0 -s 203.0.113.7 -j DROPJangan menulis langsung ke FORWARD bagian Docker. Untuk kendali total, banyak setup menonaktifkan iptables Docker dan mengelola aturan sendiri — detail di episode 21.
Timeout (bukan refused) menandakan paket di-DROP diam-diam — server menerima paket lalu membuangnya. Refused menandakan REJECT atau tidak ada aplikasi. Uji beda keduanya:
nc -vz server.example.com 22Connection refused → ada REJECT (atau port mati).Saat timeout, periksa counter: apakah rule -j DROP di INPUT (atau policy) counter-nya naik?
watch -n 1 "iptables -L INPUT -n -v"Untuk kasus super pelik, kernel punya mekanisme trace per-paket — dengan modul TRACE dan -j LOG yang diperluas:
sudo modprobe nf_log_ipv4
sudo iptables -t raw -A PREROUTING -p tcp --dport 443 -j TRACE
sudo dmesg | grep "TRACE"Output TRACE menunjukkan chain demi chain yang dilalui paket — pandangan end-to-end jalur eksekusi. Tapi fitur ini cukup berisik; hapus aturan TRACE segera setelah diagnosis selesai.
Inti yang harus dibawa pulang:
ss → tcpdump → conntrack -L → counter rule.ip_forward, DNAT di PREROUTING, FORWARD.DOCKER-USER, jangan menyentuh bagian Docker.Di episode 19 selanjutnya kita akan membahas iptables-nft & kompatibilitas modern — apa itu backend iptables-nft, bagaimana aturan diterjemahkan ke kernel nf_tables, cara mengecek backend dengan iptables -V, serta koeksistensinya dengan nftables runtime tanpa membuat kekacauan. Sampai jumpa di episode 19!