Daftar isi
Kami menyalakan UFW di VPS uji dan hanya mengizinkan SSH. Port 9999 tanpa aturan diblokir seperti seharusnya. Lalu kami menjalankan nginx di Docker dengan -p 8080:80, dan dari internet port 8080 tetap membalas HTTP 200. Inilah yang disebut docker bypass UFW. Kalau Anda menjalankan database, panel admin, atau API di Docker, port-nya bisa terbuka ke internet tanpa Anda sadari.
Diuji 5 November 2026 di Super Cloud Regular 1 vCPU · 2 GB, Ubuntu 24.04.5 LTS, Docker 29.9.3, ufw 0.36.2. Akses "dari luar" diuji dari server lain lewat internet.
Uji 1: UFW aktif, port Docker tetap terbuka
Di image Ubuntu 24.04 yang kami pakai, ufw belum terpasang (ufw: command not found). Pasang dan aktifkan dengan hanya SSH yang diizinkan:
sudo apt install ufw
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow OpenSSH
sudo ufw enable
sudo ufw status verbose
Status: active
Default: deny (incoming), allow (outgoing), deny (routed)
To Action From
-- ------ ----
22/tcp (OpenSSH) ALLOW IN Anywhere
22/tcp (OpenSSH (v6)) ALLOW IN Anywhere (v6)
Port 8080 tidak ada di daftar. Sekarang jalankan container dan lihat port-nya:
docker run -d --name web -p 8080:80 nginx:alpine
docker ps --format "{{.Names}} {{.Ports}}"
web 0.0.0.0:8080->80/tcp, [::]:8080->80/tcp
Lalu dari komputer lain:
curl -s -o /dev/null -w "HTTP %{http_code}\n" --max-time 8 http://IP-VPS:8080/
| Port yang dicoba dari internet | Hasil |
|---|---|
| 8080 (container nginx, tidak diizinkan UFW) | HTTP 200, terbuka |
| 9999 (tanpa container, tidak diizinkan UFW) | timeout 6 detik, diblok |
UFW bekerja untuk port biasa, tetapi tidak untuk port yang dipublikasikan Docker. Dokumentasi resmi Docker juga mengakui ini: port container yang dipublikasikan melewati aturan ufw dan firewalld.
Kenapa Docker bypass UFW terjadi
default deny (incoming) milik UFW berlaku di chain INPUT, yaitu paket yang ditujukan ke VPS itu sendiri. Docker tidak lewat jalur itu. Saat container dipublikasikan, Docker membuat aturan NAT yang mengubah tujuan paket langsung ke IP container:
sudo iptables -t nat -S DOCKER | grep 8080
-A DOCKER ! -i docker0 -p tcp -m tcp --dport 8080 -j DNAT --to-destination 172.17.0.2:80
Karena tujuannya sudah berubah menjadi 172.17.0.2, paket diteruskan lewat chain FORWARD, bukan INPUT. Di FORWARD, chain milik Docker diperiksa lebih dulu daripada chain UFW:
sudo iptables -S FORWARD | head -5
-P FORWARD DROP
-A FORWARD -j DOCKER-USER
-A FORWARD -j DOCKER-FORWARD
-A FORWARD -j ufw-before-logging-forward
-A FORWARD -j ufw-before-forward
Paket ke container sudah diterima di DOCKER-FORWARD sebelum sempat sampai ke aturan UFW.
Cara 1: publikasikan hanya ke 127.0.0.1
Ini cara yang kami sarankan untuk aplikasi yang diakses lewat reverse proxy (Nginx, Caddy) atau cukup dari dalam VPS. Tulis alamat IP sebelum port:
docker rm -f web
docker run -d --name web -p 127.0.0.1:8080:80 nginx:alpine
web 127.0.0.1:8080->80/tcp
| Diuji dari | Hasil |
|---|---|
Dalam VPS (curl http://127.0.0.1:8080) |
HTTP 200 |
| Internet | timeout, tertutup |
Di Docker Compose, caranya sama di bagian ports:
services:
web:
image: nginx:alpine
ports:
- "127.0.0.1:8080:80"
Cara 2: jadikan 127.0.0.1 bawaan untuk semua container
Kalau Anda sering lupa menulis 127.0.0.1:, ubah alamat bawaan Docker di /etc/docker/daemon.json:
{
"ip": "127.0.0.1"
}
sudo systemctl restart docker
docker run -d --name web -p 8080:80 nginx:alpine
docker ps --format "{{.Names}} {{.Ports}}"
web 127.0.0.1:8080->80/tcp
Walau perintahnya tetap -p 8080:80, port hanya terbuka di localhost dan dari internet tertutup (sudah kami uji). Binding IPv6 [::]:8080 yang sebelumnya muncul juga hilang.
Dua catatan:
systemctl restart dockermenghentikan semua container. Yang punyarestart: unless-stoppedataualwaysakan menyala lagi; yang tidak punya harus dijalankan ulang.- Port yang memang harus publik, misalnya 80 dan 443 untuk reverse proxy, ditulis eksplisit:
-p 0.0.0.0:80:80. Di uji kami, port dengan0.0.0.0eksplisit kembali bisa diakses dari internet.
Bagaimana dengan port yang harus publik tapi dibatasi IP?
Misalnya port database yang hanya boleh diakses dari IP kantor. Aturan ufw allow from … tidak berlaku untuk port Docker, karena alasan yang sama seperti di atas. Docker menyediakan chain DOCKER-USER untuk aturan seperti ini; penjelasan resminya ada di dokumentasi Docker Packet filtering and firewalls. Untuk kebanyakan kasus, lebih sederhana jika port database tidak dipublikasikan sama sekali, lalu diakses lewat tunnel SSH.
Cek server Anda sekarang
docker ps --format "{{.Names}}\t{{.Ports}}"
Setiap baris yang berisi 0.0.0.0: atau [::]: adalah port yang terbuka ke internet, apa pun aturan UFW-nya. Pastikan dengan mencoba dari komputer lain:
curl -m 5 -s -o /dev/null -w "%{http_code}\n" http://IP-VPS:PORT/
Kalau keluar kode HTTP (200, 401, 404), port itu bisa dijangkau dari internet.
Belum memasang Docker? Ikuti Install Docker di Ubuntu 24.04. Sekalian tutup juga login password SSH lewat SSH key untuk VPS.
