Tutorial Podman Rootless: Hardening Server Linux dan Mencegah Container Escape
Poin Kunci Artikel Ini:
- UID 1 di dalam kontainer dipetakan ke UID 100000 pada host.
- UID 65535 di dalam kontainer dipetakan ke UID 165535 pada host.
- [ ] **Mode Execution:** Seluruh layanan kontainer berjalan penuh di bawah akun non-root menggunakan Podman rootless.
Mengapa Docker Daemon Berbahaya: Vektor Serangan dan Container Escape
Docker mengusung arsitektur client-server berbasis daemon terpusat (dockerd). Daemon ini mengeksekusi seluruh instruksi dengan privilose tertinggi sistem, yaitu root (UID 0) pada sistem host. Setiap perintah dari Docker CLI dikirimkan melalui UNIX socket atau TCP socket menuju daemon tersebut. Model arsitektur ini menciptakan implikasi keamanan serius pada infrastruktur server produksi.
Mekanisme Vektor Serangan pada Docker Daemon
Ketika proses di dalam kontainer berhasil dikompromi oleh penyerang, beberapa mekanisme container escape dapat dieksekusi untuk mengambil alih kontrol penuh atas sistem operasi host:
- Eksploitasi UNIX Socket (
/var/run/docker.sock): Praktik umum memasangkan (mount) socket Docker ke dalam kontainer—seperti pada CI/CD runner atau tool monitoring—memberikan akses tak terbatas ke daemon host. Penyerang yang memiliki akses ke dalam kontainer dapat mengirim instruksi ke socket untuk membuat kontainer baru dengan privilege bertingkat, memetakan direktori akar host (-v /:/host), lalu memodifikasi file sensitif seperti/etc/shadowatau/root/.ssh/authorized_keys. - Penyalahgunaan Linux Capabilities: Konfigurasi standar kontainer Docker menyertakan kapabilitas kernel yang cukup luas seperti
CAP_SYS_ADMIN,CAP_DAC_OVERRIDE, atauCAP_NET_ADMIN. Kapabilitas ini membuka celah untuk memodifikasi konfigurasi cgroups, memanipulasi pemetaan ruang nama (namespace), hingga menembus batasan hak akses file host. - Eksploitasi Kerentanan Kernel Host: Kontainer membagi kernel Linux yang sama dengan host OS. Jika proses di dalam kontainer berjalan sebagai hak akses
rootdan mengeksekusi kode eksploitasi kerentanan kernel (seperti Dirty COW atau Dirty Pipe), proses tersebut mengeksekusi payload dengan tingkat kewenanganrootsistem host secara langsung.
Arsitektur Podman Rootless: Isolasi Total Tanpa Daemon
Podman (Pod Manager) menyelesaikan masalah keamanan mendasar tersebut melalui pendekatan arsitektur daemonless berbasis model fork-exec. Saat perintah podman run dipanggil, proses CLI memanggil runtime kontainer (seperti crun atau runc) secara langsung sebagai proses anak (child process) dari user yang mengeksekusi perintah. Tidak ada proses latar belakang terpusat yang berjalan dengan akses root.
Prinsip Kerja User Namespaces (userns)
Fondasi utama Podman rootless adalah fitur User Namespaces pada kernel Linux. Fitur ini melakukan pemetaan (mapping) antara rentang User ID (UID) dan Group ID (GID) virtual di dalam kontainer terhadap rentang UID dan GID non-privileged di sistem host.
Melalui User Namespace, proses utama aplikasi di dalam kontainer menganggap dirinya berjalan sebagai root (UID 0 internal). Namun, dari sudut pandang kernel Linux host, proses tersebut hanyalah proses biasa milik akun pengguna non-root (misalnya UID 1000). Jika terjadi peretasan dan proses aplikasi berhasil keluar dari isolasi kontainer, penyerang hanya mendapatkan hak akses terbatas milik akun non-root tersebut tanpa kemampuan merusak file sistem host.
Komponen Ekosistem Rootless: Network dan Storage
Untuk menjalankan kontainer tanpa hak akses root, Podman mengintegrasikan beberapa komponen khusus:
- Networking: Menggunakan
slirp4netnsataupastauntuk mengimplementasikan tumpukan protokol jaringan (network stack) pengguna tanpa memerlukan perangkat bridge virtual berbasisroot. - Storage: Menggunakan
fuse-overlayfsketika driveroverlay2bawaan kernel tidak mengizinkan mount tidak memiliki hak akses privilose, memastikan performa sistem berkas tetap efisien.
Panduan Langkah Demi Langkah Setup Podman Rootless
Berikut adalah prosedur lengkap konfigurasi Podman dalam mode rootless pada lingkungan server Linux.
1. Instalasi Paket Podman
Pasang Podman dan utilitas pendukung sesuai dengan distribusi Linux yang digunakan:
# Pada Ubuntu / Debian
sudo apt update
sudo apt install -y podman shadow-utils slirp4netns fuse-overlayfs uidmap
# Pada RHEL / Rocky Linux / AlmaLinux
sudo dnf install -y podman shadow-utils2. Konfigurasi Pemetaan SubUID dan SubGID
Setiap akun pengguna non-root yang akan menjalankan Podman memerlukan alokasi pemetaan UID dan GID sekunder. Alokasi ini didefinisikan pada file /etc/subuid dan /etc/subgid.
Format entri konfigurasi adalah:
username:start_uid:range_countEksekusi perintah berikut untuk mengalokasikan 65.536 UID/GID sekunder kepada pengguna (contoh pengguna: sysadmin):
sudo usermod --add-subuids 100000-165535 sysadmin
sudo usermod --add-subgids 100000-165535 sysadminVerifikasi isi file /etc/subuid:
cat /etc/subuid
# Output: sysadmin:100000:65536Skema logika pemetaan User Namespace yang terbentuk:
- UID 0 di dalam kontainer dipetakan ke UID 1000 (user
sysadmin) pada host. - UID 1 di dalam kontainer dipetakan ke UID 100000 pada host.
- UID 65535 di dalam kontainer dipetakan ke UID 165535 pada host.
Jalankan perintah podman unshare untuk memvalidasi pemetaan namespace yang sedang aktif pada sesi pengguna:
podman unshare cat /proc/self/uid_map
# Output:
# 0 1000 1
# 1 100000 655363. Konfigurasi Systemd Lingering
Secara bawaan, Linux akan menghentikan seluruh proses milik pengguna non-root ketika sesi SSH berakhir. Aktifkan fitur lingering melalui loginctl agar kontainer tetap berjalan sebagai layanan latar belakang permanen:
sudo loginctl enable-linger sysadminPeriksa status lingering pengguna:
loginctl show-user sysadmin | grep Linger
# Output: Linger=yes4. Integrasi Socket dan Migrasi Docker CLI
Buat alias sintaks untuk kemudahan transisi operasional dari Docker ke Podman:
echo "alias docker=podman" >> ~/.bashrc
source ~/.bashrcJika aplikasi pihak ketiga seperti CI/CD Runner atau Docker Compose memerlukan akses UNIX socket, aktifkan socket Podman pada tingkat pengguna (user space):
systemctl --user enable --now podman.socketTetapkan variabel lingkungan DOCKER_HOST agar mengarah ke socket pengguna:
export DOCKER_HOST="unix:///run/user/$(id -u)/podman/podman.sock"
echo 'export DOCKER_HOST="unix:///run/user/$(id -u)/podman/podman.sock"' >> ~/.bashrcUji coba pengoperasian kontainer Nginx tanpa akses root host:
podman run -d --name webserver -p 8080:80 docker.io/library/nginx:alpine
podman psHardening Lanjutan: Capabilities, Seccomp Profile, dan SELinux
Menjalankan Podman dalam mode rootless memberikan fondasi keamanan utama. Untuk menerapkan prinsip defense-in-depth, terapkan opsi hardening tambahan berikut.
1. Penerapan Least Privilege pada Linux Capabilities
Secara default, kontainer menyertakan beberapa kapabilitas yang mungkin tidak diperlukan oleh aplikasi. Cabut seluruh kapabilitas bawaan, lalu tambahkan secara spesifik kapabilitas yang dibutuhkan:
podman run -d --name secure-app \
--cap-drop=ALL \
--cap-add=NET_BIND_SERVICE \
--cap-add=CHOWN \
-p 8080:80 nginx:alpine--cap-drop=ALL: Menghapus seluruh kapabilitas Linux di dalam kontainer.--cap-add=NET_BIND_SERVICE: Mengizinkan proses mengikat port di bawah 1024 di dalam namespace kontainer.--cap-add=CHOWN: Mengizinkan perubahan hak milik berkas di dalam namespace kontainer.
2. Pembatasan Syscall Menggunakan Profil Seccomp
Seccomp (Secure Computing Mode) membatasi jenis panggilan sistem (syscall) yang dapat dikirimkan oleh proses di dalam kontainer ke kernel host. Podman menyediakan profil seccomp bawaan yang memblokir panggilan sistem berbahaya seperti kexec_load, reboot, dan swapon.
Untuk menerapkan profil seccomp khusus:
podman run -d --name hardened-app \
--security-opt seccomp=/etc/podman/seccomp-strict.json \
nginx:alpine3. Labeling Volume SELinux
Pada distribusi Linux yang menggunakan SELinux (seperti RHEL, Fedora, atau Rocky Linux), Podman mematuhi kebijakan konteks keamanan SELinux. Saat melakukan bind mount direktori dari host ke kontainer, tambahkan akhiran flag label volume:
# Gunakan :Z untuk volume privat yang hanya diakses kontainer ini
podman run -d -v /opt/app/data:/app/data:Z nginx:alpine
# Gunakan :z untuk volume yang dibagikan antar beberapa kontainer
podman run -d -v /opt/app/shared:/app/shared:z nginx:alpineTroubleshooting Masalah Umum pada Podman Rootless
Berikut adalah solusi atas kendala teknis yang sering dijumpai saat mengoperasikan Podman rootless di server produksi:
1. Gagal Binding Port Privilese (< 1024)
Pesan Kesalahan: rootlessport: cannot expose privileged port 80.
Penyebab: Secara default, kernel Linux melarang proses non-root mengikat port host di bawah 1024.
Solusi: Ubah nilai minimum unprivileged port melalui konfigurasi sysctl pada sistem host:
echo "net.ipv4.ip_unprivileged_port_start=80" | sudo tee /etc/sysctl.d/99-podman-ports.conf
sudo sysctl --system2. Permission Denied pada Bind Mount Direktori Host
Pesan Kesalahan: Permission denied saat kontainer mencoba membaca atau menulis ke direktori mount.
Penyebab: Ketidaksesuaian UID/GID antara pemilik direktori host dengan UID/GID di dalam User Namespace, atau hambatan dari konteks SELinux.
Solusi: Gunakan perintah podman unshare untuk menyesuaikan kepemilikan direktori host agar selaras dengan pemetaan User Namespace kontainer:
podman unshare chown -R 1000:1000 /opt/app/data3. Kegagalan Alokasi SubUID (SubUID Exhaustion)
Pesan Kesalahan: user code has no subuid range configured atau kesalahan serupa saat membuat kontainer baru.
Solusi: Pastikan entri nama pengguna telah terdaftar di /etc/subuid dan /etc/subgid, kemudian jalankan migrasi storage Podman untuk memperbarui pemetaan internal:
podman system migrateChecklist Keamanan Podman Rootless untuk Production
Gunakan daftar periksa berikut sebelum mengisolasi dan mempublikasikan layanan berbasis kontainer ke lingkungan produksi:
- [ ] **Mode Execution:** Seluruh layanan kontainer berjalan penuh di bawah akun non-root menggunakan Podman rootless.
- [ ] **ID Mapping:** Alokasi entri
/etc/subuiddan/etc/subgidtelah dikonfigurasi dengan rentang minimal 65.536 ID. - [ ] **Persistence:** Fitur
loginctl enable-lingeraktif untuk memastikan kontainer berjalan tanpa bergantung pada sesi SSH. - [ ] **Port Control:** Batas
net.ipv4.ip_unprivileged_port_startdikonfigurasi secara spesifik sesuai kebutuhan layanan. - [ ] **Capability Reduction:** Parameter
--cap-drop=ALLditerapkan dan hanya menyertakan kapabilitas yang sangat spesifik. - [ ] **SELinux Integration:** Opsi labeling volume
:Zatau:zditerapkan pada setiap perintah bind mount. - [ ] **Syscall Restriction:** Profil Seccomp ketat diaktifkan untuk membatasi interaksi syscall ke kernel.
- [ ] **Immutable Rootfs:** Parameter
--read-onlydigunakan pada kontainer yang tidak memerlukan akses tulis ke sistem berkas utama. - [ ] **Socket Isolation:** Akses UNIX socket dibatasi hanya untuk sesi pengguna melalui `systemctl --user`.
- [ ] **Maintenance:** Proses pembaruan berkala pada citra basis (base image) dan komponen Podman berjalan secara otomatis.


