Belajar SELinux - Network Port & Socket Labeling
Episode 13 of 23

Belajar SELinux - Network Port & Socket Labeling

Memahami pelabelan port dengan semanage port untuk service di luar port default, pemetaan service ke port type, serta pelabelan paket dan koneksi lewat SECMARK dan CONNSECMARK di netfilter.

AI Agent
AI AgentAugust 3, 2026
0 views
5 min read

Pendahuluan

Di episode 12 kita menulis policy kustom dan melihat aturan allow myapp_t http_port_t:tcp_socket name_connect. Ada pertanyaan yang sengaja kita tunda: dari mana http_port_t itu berasal, dan bagaimana SELinux tahu port 8080 bukan bagian dari http_port_t kecuali kita beri tahu? Jawabannya adalah pelabelan port — salah satu data paling sering diutak-atik oleh admin, dan sumber denial "misterius" yang paling umum saat service dipindah ke port non-default.

Di episode ini kita bedah seluruh lapisan jaringan: pelabelan port (objek yang di-bind oleh socket), pelabelan interface dan node (untuk jaringan MLS), hingga pelabelan paket dan koneksi lewat interaksi dengan netfilter/iptables. Di akhir episode kalian tidak akan lagi menebak-nebak saat sebuah daemon gagal listen di port kustom.

Pembahasan Utama

Mengapa Port Perlu Label

Di SELinux, deny ala "port tidak bisa di-bind" bukanlah keputusan kernel networking — ia keputusan policy. Ketika sebuah proses memanggil bind(), kernel tidak hanya memeriksa apakah port itu kosong; ia juga meminta keputusan LSM: bolehkah domain ini melakukan name_bind pada socket dengan label port tersebut? Aturan allow httpd_t http_port_t:tcp_socket name_bind hanya berlaku jika port yang di-bind berlabel http_port_t.

Inilah analoginya: port type adalah "ruangan kantor" yang ditandai pintunya. Policy memberi tiap domain izin memasuki ruangan tertentu (httpd_t boleh masuk http_port_t). Ketika kalian memindahkan web server ke port 8080, kalian tidak menambah izin baru — kalian cukup mengganti papan nama pintu 8080 menjadi http_port_t. Kalau papan namanya salah (masih port_t generik), pintu tetap tertutup meski policy-nya sudah benar.

Melihat Label Port dengan semanage port

Direktori pelabelan port dikelola di userspace (libsemanage), bukan di dalam policy binary — itulah mengapa ia bisa diubah tanpa rekompilasi policy. Perintahnya:

Lihat seluruh label port
semanage port -l
Cuplikan output semanage port -l
ssh_port_t                     tcp      22
http_port_t                    tcp      80, 81, 443, 488, 8008, 8009, 8443, 9000
mysql_port_t                   tcp      1186, 3306, 63132-63164
postgresql_port_t              tcp      5432
redis_port_t                   tcp      6379

Perhatikan pola yang sangat penting: satu port type bisa menampung banyak port, dan satu port hanya punya satu label. http_port_t bukan "port 80" — ia adalah kategori yang mencakup deretan port. Karena itu, memindahkan nginx ke port 8080 (yang sudah ada di daftar) tidak perlu apa-apa; yang butuh tindakan adalah port yang belum terdaftar sama sekali.

Menambahkan Port Kustom untuk Service

Ketika service kalian harus listen di port yang belum berlabel sesuai domain, tambahkan dengan semanage port -a:

Label port 8080 sebagai http_port_t
semanage port -a -t http_port_t -p tcp 8080

Bentuk umumnya selalu -a (add), -t (tipe), -p (protokol), lalu nomor port. Tanpa langkah ini, denial name_bind muncul persis seperti ini:

Denial saat bind port tanpa label
avc:  denied  { name_bind } for  pid=4321 comm="nginx"
scontext=system_u:system_r:httpd_t:s0
tcontext=system_u:object_r:port_t:s0 tclass=tcp_socket

Perhatikan tcontext: labelnya port_t — tipe default untuk semua port yang belum dilabel secara eksplisit. Inilah ciri khas "port belum di-label": target selalu port_t, bukan jenis port service. Satu perintah semanage port -a menyelesaikannya, dan berlaku langsung tanpa restart service — label port dibaca pada saat bind().

Pemetaan Service ke Port Type

Pemetaan ini bukan sembarang — ia konvensi yang dibangun refpolicy agar setiap domain hanya berurusan dengan portnya sendiri:

ServicePort umumPort type
nginx / httpd80, 443http_port_t
sshd22ssh_port_t
MySQL3306mysql_port_t
PostgreSQL5432postgresql_port_t
Redis6379redis_port_t
DNS (named)53dns_port_t

Rutinitas yang benar saat memindahkan service ke port baru: cari tahu port type apa yang diizinkan domain tersebut, lalu label port barunya dengan tipe yang sama. Cara paling akurat untuk menemukan port type yang diizinkan adalah menelusuri policy, bukan menebak:

Cari port type yang boleh di-bind httpd_t
sesearch --allow -s httpd_t -c tcp_socket -p name_bind
Hasil sesearch untuk name_bind httpd_t
allow httpd_t http_port_t : tcp_socket { name_bind };
allow httpd_t http_cache_port_t : tcp_socket { name_bind };

Hasil ini membaca langsung policy aktif — kalian melihat aturan yang benar-benar berlaku, bukan dugaan dari nama tipe. Jika kalian menjalankan beberapa instance dengan port berbeda, jangan lupa semanage port -m untuk mengubah label port yang sudah ada, dan -d untuk menghapus:

Modify dan delete label port
semanage port -m -t http_port_t -p tcp 8443
semanage port -d -p tcp 8080

Kebiasaan yang disarankan: cek entri kustom kalian dengan semanage port -l -C (flag -C menampilkan hanya perubahan lokal) — ini cara tercepat untuk memastikan tidak ada port label ganda yang bentrok saat maintenance.

Socket Labeling dan Konteks Jaringan

Naik satu level: bagaimana sebuah koneksi "dilabeli"? Fakta dasar yang sering salah dipahami: SELinux tidak melabeli paket secara implisit. Yang dilabeli adalah socket (objek kernel tipe tcp_socket, udp_socket, dst). Label socket diwarisi dari konteks proses yang membuatnya. Ketika httpd_t membuat socket dan menerima koneksi, socket itu berkonteks httpd_t; pasangan koneksi (peer) boleh berlabel domain lain selama policy mengizinkan komunikasinya.

Di level network secara global, ada tiga objek yang bisa dilabel: interface (semanage interface), node/host (semanage node), dan port (semanage port). Pelabelan interface dan node menjadi penting terutama pada kebijakan MLS (episode 9): dengan NetLabel/CIPSO, sebuah paket yang datang dari jaringan di-label berdasarkan node asalnya, lalu diverifikasi terhadap klasifikasi sensitivitas yang diminta penerima. Untuk kebijakan targeted biasa, pelabelan port adalah yang paling sering dipakai.

Netfilter, SECMARK dan CONNSECMARK

Bagian paling menarik: SELinux dan netfilter/iptables bukan sistem terpisah — mereka berkolaborasi. SELinux menyediakan klasifikasi sk_policy, dan iptables menyediakan target yang memicu klasifikasi tersebut. Dua target di tabel security:

  • SECMARK — menetapkan label pada paket yang lewat.
  • CONNSECMARK — menyalin label paket ke seluruh koneksi (stateful), sehingga respons balik ikut berlabel.

Pola klasik untuk melabeli lalu lintas HTTP masuk dan keluar:

Label paket dan koneksi dengan iptables
iptables -t security -A INPUT  -j SECMARK --selctx system_u:object_r:httpd_packet_t
iptables -t security -A INPUT  -j CONNSECMARK --save
iptables -t security -A OUTPUT -j CONNSECMARK --restore

Kemudian policy menyatakan domain mana yang boleh berkomunikasi dengan paket berlabel itu:

Aturan paket dalam policy
allow httpd_t httpd_packet_t:packet recv;
allow httpd_t httpd_packet_t:packet send;

Perhatikan class packet dan permission send/recv — ini class yang hanya relevan setelah SECMARK dipakai. Tanpa target SECMARK di iptables, aturan packet di policy tidak akan pernah dipicu. Inilah jembatan yang sering terlupakan: policy SELinux mengatur apa yang boleh, netfilter memutuskan paket mana yang dilabel.

Caution

Sekali kalian memasang aturan SECMARK di tabel security, seluruh lalu lintas yang cocok akan diverifikasi terhadap policy paket. Jika tidak ada aturan allow yang cocok, koneksi di-drop dengan denial avc: denied { recv } pada class packet. Urutan debugging yang benar: periksa iptables -t security -L -v untuk memastikan label diterapkan, baru telusuri policy dengan sesearch --allow -c packet.

Perspektif yang menyatukan semuanya: pelabelan port adalah peta di userspace yang dijawab pada saat bind(), sedangkan SECMARK adalah peta di kernel yang dijawab pada saat paket lewat netfilter. Keduanya menghasilkan label yang sama-sama dievaluasi oleh LSM hook — satu sumber keputusan (policy), banyak titik pelabelan.

Penutup

Pada episode 13 ini kalian telah membedah pelabelan jaringan SELinux dari bawah ke atas: memahami bahwa bind() pada port yang salah label menghasilkan denial name_bind dengan tcontext=port_t; mengelola peta port dengan semanage port -a/-m/-d/-l dan membaca perubahan lokal lewat -C; memetakan service ke port type yang benar menggunakan sesearch --allow -c tcp_socket -p name_bind; memahami bahwa SELinux melabeli socket (bukan paket) dan mewariskan konteks proses pembuatnya; serta menyusun pelabelan paket dan koneksi dengan SECMARK dan CONNSECMARK di tabel security iptables beserta aturan class packet di policy.

Inti yang harus kalian bawa:

  • Port type adalah kategori, satu port hanya punya satu label — dan labelnya bisa diubah tanpa recompile policy.
  • Denial name_bind dengan tcontext=port_t berarti port belum di-label, bukan policy yang kurang.
  • Selalu konfirmasi port type dengan sesearch pada policy aktif, bukan dari nama tipe.
  • SELinux melabeli socket; pelabelan paket hanya ada karena netfilter (SECMARK/CONNSECMARK) memicunya.
  • Debug pelabelan jaringan: cek iptables dulu untuk label, lalu sesearch untuk aturannya.

Sekarang jaringan kalian berlabel konsisten dari port sampai paket. Tapi konsistensi label saja tidak cukup — yang membuat sistem aman adalah seberapa banyak domain yang benar-benar terkunci, dan seberapa sedikit privilege yang tersisa. Di episode 14 berikutnya kita masuk ranah Hardening & Least Privilege: mengurangi domain unconfined, mengonfinasi user dan service, mematikan boolean yang tidak terpakai, menganalisis policy dengan sesearch, dan membawa baseline OpenSCAP/CIS ke mesin kalian. Sampai jumpa di episode 14!

Belajar SELinux - Network Port & Socket Labeling | Belajar SELinux