SELinux Kurulum, Yapılandırma ve Politika Yönetimi

Sunucularını yöneten herkes er ya da geç SELinux ile yüzleşmek zorunda kalır. Kimi zaman bir servis aniden çalışmayı durdurur, kimi zaman bir uygulama log dosyasına yazamaz, kimi zaman ise bir kullanıcı erişmesi gereken dizine ulaşamaz. Bunların hepsinin arkasında SELinux olabilir. Pek çok sistem yöneticisi bu engellerle karşılaşınca ilk refleks olarak SELinux’u kapatır, ama bu büyük bir hata. SELinux, doğru anlaşıldığında sunucularınızın güvenlik katmanına ciddi katkı sağlayan güçlü bir araçtır. Bu yazıda SELinux’u sıfırdan kurmaktan, politika yönetimine kadar her şeyi gerçek dünya senaryolarıyla ele alacağız.

SELinux Nedir ve Neden Önemlidir

SELinux (Security-Enhanced Linux), NSA tarafından geliştirilen ve Linux çekirdeğine entegre edilmiş bir Zorunlu Erişim Kontrolü (MAC – Mandatory Access Control) sistemidir. Klasik Linux izin sistemi (DAC – Discretionary Access Control) dosya sahipliği ve rwx izinlerine dayanır. Bir kullanıcı root olduğunda ya da bir süreç yeterli izne sahip olduğunda istediği her şeyi yapabilir. SELinux bu modeli tersine çevirir: her proses, her dosya, her kaynak bir güvenlik etiketi (label) alır ve bu etiketler arasındaki ilişkiler politikalarla tanımlanır.

Pratik sonuç şu: Bir web sunucusu ele geçirilse bile SELinux, o sürecin sistem dosyalarına erişmesini, ağ bağlantısı kurmasını ya da başka servisleri etkilemesini engeller. Sadece “httpd ne yapabilir” sorusunun cevabını önceden tanımlamış olursunuz.

SELinux Durumu Kontrol Etme

Önce mevcut durumu görelim.

# SELinux durumunu kontrol et
sestatus

# Kısa çıktı için
getenforce

# Kernel parametrelerini görmek için
cat /etc/selinux/config

getenforce komutu üç farklı çıktı verebilir:

  • Enforcing: SELinux aktif, politikalar uygulanıyor, ihlaller engelleniyor
  • Permissive: SELinux aktif ama politikalar uygulanmıyor, sadece loglanıyor
  • Disabled: SELinux tamamen kapalı

Bir sunucuyu devraldığınızda ilk yapacağınız şey bu kontrolü yapmak olmalı. Üretim ortamındaki sunucuların büyük çoğunluğunda SELinux’un Permissive ya da Disabled modda çalıştığını göreceksiniz. Bu durum güvenlik açığı demektir.

SELinux Kurulumu ve Temel Yapılandırma

RHEL/CentOS/AlmaLinux gibi Red Hat tabanlı dağıtımlarda SELinux varsayılan olarak gelir. Ubuntu ve Debian tabanlı sistemlerde ise AppArmor tercih edilir, ancak SELinux kurulumu mümkündür.

# RHEL/CentOS/AlmaLinux için gerekli paketleri kur
dnf install -y selinux-policy selinux-policy-targeted 
    policycoreutils policycoreutils-python-utils 
    setroubleshoot-server setools-console

# Ubuntu için SELinux kurulumu
apt-get install -y selinux-basics selinux-policy-default 
    auditd policycoreutils

Kurulumdan sonra /etc/selinux/config dosyasını düzenlemeniz gerekir.

# /etc/selinux/config dosyasını düzenle
vi /etc/selinux/config

Dosyanın içeriği şöyle görünmeli:

# Bu dosyayı düzenledikten sonra sistemi yeniden başlatın
SELINUX=enforcing
SELINUXTYPE=targeted

SELINUX parametresi için seçenekler:

  • enforcing: Üretim için önerilen, politikalar aktif
  • permissive: Test aşaması için ideal
  • disabled: Kesinlikle önerilmez

SELINUXTYPE parametresi için seçenekler:

  • targeted: En yaygın kullanılan, belirli servisleri hedefler
  • mls: Multi-Level Security, devlet kurumları için
  • minimum: Minimal koruma, kaynak kısıtlı sistemler için

Enforcing moda geçmeden önce sisteminizi Permissive modda bir süre çalıştırmanızı öneririm. Bu sayede mevcut uygulamalarınızın hangi politikaları tetiklediğini görebilirsiniz.

# Geçici olarak mod değiştirme (reboot gerekmez)
setenforce 0    # Permissive
setenforce 1    # Enforcing

# Kalıcı değişiklik için config dosyasını düzenleyip reboot yapın

Disabled moddan Enforcing/Permissive moda geçiyorsanız, sistemin tüm dosya sistemini yeniden etiketlemesi gerekir. Bu işlem için boş bir .autorelabel dosyası oluşturun.

# Dosya sistemi yeniden etiketleme için
touch /.autorelabel
reboot

Bu işlem sistem boyutuna göre birkaç dakika sürebilir. Büyük disk alanlarında oldukça uzun sürdüğü için bunu planlı bakım penceresinde yapın.

SELinux Etiketleri ve Bağlamları Anlamak

SELinux her nesneye bir güvenlik bağlamı (security context) atar. Bu bağlam dört bölümden oluşur:

# Bir dosyanın güvenlik bağlamını göster
ls -Z /var/www/html/index.html
# Çıktı: system_u:object_r:httpd_sys_content_t:s0

# Çalışan prosesin bağlamını göster
ps -eZ | grep httpd
# Çıktı: system_u:system_r:httpd_t:s0

# Kullanıcının bağlamını görmek için
id -Z

Çıktıdaki format şu şekildedir: kullanici:rol:tip:seviye

  • kullanici: SELinux kullanıcısı (system_u, staff_u, unconfined_u)
  • rol: Nesnenin rolü (object_r, system_r, staff_r)
  • tip: En kritik kısım, politikaların büyük çoğunluğu bu üzerinden çalışır
  • seviye: MLS/MCS güvenlik seviyesi

Günlük yönetimde çoğunlukla tip kısmıyla ilgilenirsiniz. Bir sorun çıktığında genellikle yanlış tip etiketi atanmış dosyalar ya da politikalar söz konusudur.

Gerçek Dünya Senaryosu: Apache Web Sunucusu

Diyelim ki Apache kurulu bir sunucunuzda /data/website dizinini web kök dizini olarak kullanmak istiyorsunuz. Standart /var/www/html yerine farklı bir dizin kullandığınızda SELinux devreye girer.

# Önce dizin oluşturup Apache'yi yapılandıralım
mkdir -p /data/website
echo "Merhaba Dünya" > /data/website/index.html

# Apache conf dosyasında DocumentRoot'u değiştirdiniz varsayalım
# Ama SELinux bağlamı yanlış olacaktır
ls -Z /data/website/
# Çıktı: unconfined_u:object_r:default_t:s0 index.html
# default_t tipi httpd'nin okuyamayacağı bir tiptir

# Doğru tipi ata
semanage fcontext -a -t httpd_sys_content_t "/data/website(/.*)?"
restorecon -Rv /data/website/

# Değişikliği doğrula
ls -Z /data/website/
# Çıktı: unconfined_u:object_r:httpd_sys_content_t:s0 index.html

semanage fcontext komutu kalıcı bir politika ekler. restorecon ise mevcut dosyalara bu politikayı uygular. Sadece chcon ile geçici değişiklik yapabilirsiniz, ama restorecon çalıştırıldığında ya da sistem yeniden başlatıldığında bu değişiklik kaybolur.

SELinux Boolean Değerleri Yönetimi

SELinux Boolean’ları, önceden tanımlanmış politikaları açıp kapamanıza olanak tanır. Politika yazmak zorunda kalmadan yaygın senaryoları yönetebilirsiniz.

# Mevcut boolean değerlerini listele
getsebool -a

# Belirli bir boolean'ı kontrol et
getsebool httpd_can_network_connect

# httpd'nin ağ bağlantısı kurmasına izin ver (geçici)
setsebool httpd_can_network_connect on

# Kalıcı değişiklik için -P parametresi
setsebool -P httpd_can_network_connect on

# PHP-FPM veya proxy kullanıyorsanız
setsebool -P httpd_can_network_connect_db on
setsebool -P httpd_execmem on

# Samba için
setsebool -P samba_enable_home_dirs on
setsebool -P samba_export_all_rw on

Yaygın kullanılan Boolean’lar:

  • httpd_can_network_connect: Apache’nin dış ağ bağlantısı kurmasına izin verir
  • httpd_can_network_connect_db: Apache’nin veritabanına bağlanmasına izin verir
  • ftpd_anon_write: Anonim FTP yazma iznini açar
  • allow_user_exec_content: Kullanıcıların ev dizinindeki betikleri çalıştırmasına izin verir

SELinux Log Analizi ve Sorun Giderme

SELinux ihlalleri /var/log/audit/audit.log dosyasına yazılır. Ancak bu dosyayı ham haliyle okumak oldukça zordur.

# audit.log dosyasından SELinux ihlallerini filtrele
grep "denied" /var/log/audit/audit.log | tail -20

# audit2why ile daha anlaşılır çıktı al
audit2why < /var/log/audit/audit.log

# Son ihlalleri görmek için
ausearch -m avc -ts recent

# Belirli bir servis için ihlalleri filtrele
ausearch -m avc -c httpd

# sealert ile detaylı analiz (setroubleshoot-server paketi gerekli)
sealert -a /var/log/audit/audit.log

audit2why komutu size ihlalin neden gerçekleştiğini ve ne yapmanız gerektiğini açıklar. Örnek bir çıktı şöyle görünür:

type=AVC msg=audit: avc: denied { read } for pid=1234 
comm="httpd" name="config.php" 
scontext=system_u:system_r:httpd_t:s0 
tcontext=unconfined_u:object_r:user_home_t:s0 tclass=file

Was caused by:
  Missing type enforcement (TE) allow rule.
  You can use audit2allow to generate a loadable module to allow this access.

Özel SELinux Politikası Oluşturma

Bazen mevcut Boolean’lar yetmez ve kendi politikanızı yazmanız gerekir. audit2allow aracı bu konuda büyük kolaylık sağlar.

# audit.log'dan özel politika modülü oluştur
audit2allow -M mypolicy < /var/log/audit/audit.log

# Bu komut iki dosya oluşturur:
# mypolicy.te - Tip zorunluluğu dosyası (metin)
# mypolicy.pp - Derlenmiş politika paketi

# Politikayı yükle
semodule -i mypolicy.pp

# Yüklü modülleri listele
semodule -l | grep mypolicy

# Belirli ihlaller için daha hedefli politika
ausearch -m avc -c nginx | audit2allow -M nginx_custom
semodule -i nginx_custom.pp

Politika dosyasını elle düzenlemek isteyebilirsiniz. .te dosyası şöyle görünür:

# mypolicy.te dosyası örneği
# cat mypolicy.te

module mypolicy 1.0;

require {
    type httpd_t;
    type var_t;
    class file { read write };
}

# httpd'nin /var altındaki özel dizine erişimine izin ver
allow httpd_t var_t:file { read write };

Politikayı elle düzenledikten sonra yeniden derlemeniz gerekir:

# .te dosyasını derle
checkmodule -M -m -o mypolicy.mod mypolicy.te
semodule_package -o mypolicy.pp -m mypolicy.mod
semodule -i mypolicy.pp

Dikkat: audit2allow ile oluşturulan politikalar bazen fazla geniş izinler verebilir. Üretim ortamına almadan önce .te dosyasını mutlaka gözden geçirin.

Port Yönetimi ve SELinux

SELinux servisler için kullanılabilecek portları da kısıtlar. Standart dışı bir port kullanmak istediğinizde SELinux buna izin vermeyebilir.

# Bir servis için tanımlı portları listele
semanage port -l | grep http

# Nginx'i 8080 portunda çalıştırmak için
semanage port -a -t http_port_t -p tcp 8080

# SSH için farklı port ekle
semanage port -a -t ssh_port_t -p tcp 2222

# Mevcut port tanımını değiştir
semanage port -m -t http_port_t -p tcp 8443

# Port tanımını sil
semanage port -d -t http_port_t -p tcp 8080

# Tüm port tanımlarını listele
semanage port -l

Gerçek bir senaryoyu ele alalım: PostgreSQL’i varsayılan 5432 yerine 5433 portunda çalıştırmak istiyorsunuz.

# Önce PostgreSQL için tanımlı portları kontrol et
semanage port -l | grep postgresql
# postgresql_port_t: tcp 5432

# Yeni portu ekle
semanage port -a -t postgresql_port_t -p tcp 5433

# Servisi başlat ve kontrol et
systemctl start postgresql
systemctl status postgresql

Kullanıcı Sınırlandırma ve SELinux Kullanıcıları

SELinux, Linux kullanıcılarını SELinux kullanıcılarıyla eşleştirerek ek bir kısıtlama katmanı ekler.

# SELinux kullanıcılarını listele
semanage user -l

# Linux kullanıcısı ile SELinux kullanıcısı eşleştirmesini göster
semanage login -l

# Bir kullanıcıyı kısıtlı SELinux kullanıcısına ata
semanage login -a -s user_u uygulamakullanicisi

# Staff rolü için (sudo kullanabilir ama kısıtlı)
semanage login -a -s staff_u yonetici

# Eşleştirmeyi kaldır
semanage login -d uygulamakullanicisi

Güvenlik kritik ortamlarda, servis hesaplarını user_u ile eşleştirmek, olası bir hesap ele geçirilmesinde hasarı minimize eder.

Sorun Giderme: Enforcing Modda Uygulama Çalışmıyor

Gerçek hayatta en sık karşılaşılan senaryo şu: Uygulamanız Permissive modda çalışıyor ama Enforcing modda hata veriyor.

# Adım 1: Permissive moda geç ve uygulamayı test et
setenforce 0
systemctl restart uygulamaniz

# Adım 2: Log temizle ve tekrar enforcing moda geç
> /var/log/audit/audit.log
setenforce 1

# Adım 3: Uygulamayı çalıştır ve ihlalleri topla
systemctl restart uygulamaniz
# Uygulama fonksiyonlarını test et, tüm senaryoları dene

# Adım 4: İhlalleri analiz et
audit2why < /var/log/audit/audit.log

# Adım 5: Politika oluştur
audit2allow -M uygulamaadi < /var/log/audit/audit.log

# Adım 6: Politikayı incele, gereksiz izinleri kaldır
cat uygulamaadi.te

# Adım 7: Politikayı yükle
semodule -i uygulamaadi.pp

# Adım 8: Uygulamayı test et
systemctl restart uygulamaniz

Bu döngüsel yaklaşım, tüm ihlalleri tek seferde yakalamak yerine kademeli olarak çözmenizi sağlar.

SELinux’u Devre Dışı Bırakmak Yerine Yapılması Gerekenler

Pek çok yazılım kurulum kılavuzu “SELinux’u disable edin” diye yazar. Bu gerçekten kötü bir tavsiyedir. Bunun yerine:

  • Problemi loglardan tespit edin, audit2why kullanın
  • İlgili Boolean değerini kontrol edin, büyük ihtimalle bir Boolean sorunu çözer
  • Dosya bağlamlarını kontrol edin, restorecon ile düzeltin
  • Sadece ilgili servis için kısıtlı politika yazın
  • Tüm servisi unconfined yapmak yerine minimum gerekli izni verin
# Belirli bir servis için SELinux'u permissive yap (tümünü kapatmak yerine)
semanage permissive -a httpd_t

# Permissive listeyi görüntüle
semanage permissive -l

# Tekrar enforcing yap
semanage permissive -d httpd_t

Bu yaklaşım, sorunlu servisi izole ederken diğer servislerin korunmasını sağlar.

Düzenli Bakım ve İzleme

SELinux yönetimi sadece kurulum ve yapılandırmayla bitmez. Düzenli bakım şart.

# Haftalık kontrol scripti
#!/bin/bash
echo "=== SELinux Durum ==="
sestatus

echo "=== Son 24 Saat İhlalleri ==="
ausearch -m avc -ts today | wc -l

echo "=== En Çok İhlal Üretenler ==="
ausearch -m avc -ts today | 
  grep "comm=" | 
  grep -oP 'comm="K[^"]+' | 
  sort | uniq -c | sort -rn | head -10

echo "=== Permissive Modda Servisler ==="
semanage permissive -l

Bu scripti cron’a ekleyip haftalık raporlar alabilirsiniz. İhlal sayısında ani artışlar, olası bir güvenlik olayının erken uyarısı olabilir.

Sonuç

SELinux, ilk bakışta karmaşık ve sinir bozucu görünse de doğru anlaşıldığında sistemlerinizin en güvenilir koruma katmanlarından biri haline gelir. Temel prensip şu: Bir servis ele geçirilse bile, o servisin yapabileceği hasarı SELinux politikalarıyla sınırlayabilirsiniz.

Pratikte önerim şu yolu izlemeniz: Önce Permissive modda çalıştırın, logları izleyin, audit2why ile sorunları anlayın, Boolean değerlerini ve dosya bağlamlarını düzeltin, gerekirse özel politika yazın ve sonra Enforcing moda geçin. SELinux’u kapatmak kısa vadeli rahatlık sağlayabilir, ama uzun vadede sizi savunmasız bırakır.

Bulut ortamlarında, konteyner altyapılarında ve özellikle internet yüzü olan sunucularda SELinux artık bir tercih değil, zorunluluktur. Sisteminizi ne kadar doğru yapılandırırsanız SELinux o kadar az gürültü üretir ve arka planda sessizce koruma sağlar. Asıl amaç da zaten bu.

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir