SELinux Politikalarını Özelleştirme: audit2allow Kullanımı

SELinux ile uğraşmayan sysadmin yoktur. Özellikle yeni bir uygulama kurduğunuzda ya da mevcut bir servisi farklı bir dizine taşıdığınızda, SELinux devreye girer ve işleri “biraz” karmaşıklaştırır. Pek çok yöneticinin ilk refleksi setenforce 0 yazmak olsa da bu, güvenlik duvarını tamamen kapatmakla eşdeğerdir. Doğru yaklaşım ise SELinux’u anlamak ve ona göre politika yazmaktır. İşte tam bu noktada audit2allow aracı hayat kurtarıcı hale gelir.

SELinux Politika Yönetimine Giriş

SELinux (Security-Enhanced Linux), Red Hat tabanlı dağıtımlarda varsayılan olarak etkin gelen zorunlu erişim denetimi (MAC) sistemidir. CentOS 7/8 ve Rocky Linux 8/9 üzerinde çalışıyorsanız, SELinux sizin en yakın arkadaşınız ya da en büyük baş ağrınız olacaktır. Bu ikisi arasındaki fark, onu ne kadar iyi tanıdığınıza bağlıdır.

SELinux, her işleme ve dosyaya bir güvenlik bağlamı (security context) atar. Bir süreç, yalnızca politikanın izin verdiği kaynakları kullanabilir. Varsayılan politikalar çoğu senaryo için yeterlidir, ancak özel uygulamalar, alışılmadık dizin yapıları ya da özel konfigürasyonlar söz konusu olduğunda politikayı özelleştirmeniz gerekir.

audit2allow aracı, SELinux’un audit loglarını okur ve bu loglardan otomatik olarak politika modülü oluşturmanıza yardımcı olur. policycoreutils-python-utils paketinin bir parçasıdır.

Gerekli Araçların Kurulumu

Başlamadan önce gerekli paketleri kuralım:

# Rocky Linux 8/9 ve CentOS 8 için
dnf install -y policycoreutils-python-utils policycoreutils setroubleshoot-server

# CentOS 7 için
yum install -y policycoreutils-python setroubleshoot-server audit

Audit servisinin çalıştığından emin olun:

systemctl enable --now auditd
systemctl status auditd

Audit servisi olmadan SELinux redleri loglanmaz ve audit2allow için hammadde oluşmaz.

SELinux Redlerini Tespit Etme

/var/log/audit/audit.log Okumak

SELinux bir işlemi engellediğinde, bu olay /var/log/audit/audit.log dosyasına düşer. Ham log çıktısı oldukça ağır okunur:

# Ham audit logunu görüntüleme
grep "AVC" /var/log/audit/audit.log | tail -20

# Daha okunabilir format için audit2why kullanımı
grep "AVC" /var/log/audit/audit.log | audit2why

ausearch ile Filtreleme

ausearch aracı, audit loglarını filtrelemek için çok daha kullanışlıdır:

# Son 1 saatteki SELinux redlerini göster
ausearch -m avc -ts recent

# Belirli bir süreçle ilgili redleri bul
ausearch -m avc -c httpd

# Belirli bir zaman aralığında
ausearch -m avc -ts 2024-01-15 06:00:00 -te 2024-01-15 12:00:00

sealert ile İnsan Tarafından Okunabilir Analiz

sealert, redleri analiz eder ve ne yapmanız gerektiğini açıkça söyler:

# Tüm uyarıları listele
sealert -a /var/log/audit/audit.log

# Belirli bir uyarıyı ID ile incele
sealert -l <alert-id>

Gerçek Dünya Senaryosu 1: Nginx Özel Dizin

Diyelim ki Nginx web sunucunuzu /var/www/html yerine /data/web dizininden servis verecek şekilde yapılandırdınız. Nginx başlar, ancak sayfalar 403 döner. SELinux muhtemelen suçludur.

# Önce audit logunu kontrol edelim
ausearch -m avc -c nginx -ts recent

Çıktıda şuna benzer bir şey görürsünüz:

type=AVC msg=audit(1705123456.789:1234): avc: denied { read } for pid=12345
comm="nginx" name="index.html" dev="sda1" ino=67890
scontext=system_u:system_r:httpd_t:s0
tcontext=unconfined_u:object_r:default_t:s0 tclass=file permissive=0

Bu çıktı, httpd_t bağlamındaki nginx işleminin default_t bağlamındaki dosyayı okumaya çalıştığını ancak reddedildiğini söylüyor.

Çözüm 1: Doğru yol – Dosya bağlamını değiştir

Bu durum için en temiz çözüm, dosyanın SELinux bağlamını doğru şekilde ayarlamaktır:

# /data/web dizinine httpd_sys_content_t bağlamı ver
semanage fcontext -a -t httpd_sys_content_t "/data/web(/.*)?"

# Değişikliği uygula
restorecon -Rv /data/web

# Kontrol et
ls -laZ /data/web

Çözüm 2: audit2allow ile politika modülü oluştur

Bazen bağlam değişikliği yetmez ya da daha karmaşık izinler gerekebilir. İşte burada audit2allow devreye girer:

# Red loglarından politika modülü oluştur
grep "nginx" /var/log/audit/audit.log | audit2allow -M nginx_custom

# Bu komut iki dosya üretir:
# nginx_custom.te  - Type Enforcement dosyası (insan okunabilir)
# nginx_custom.pp  - Politika paketi (derlenmiş)

# Oluşturulan .te dosyasını incele (MUTLAKA yapın!)
cat nginx_custom.te

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

# Kontrol et
semodule -l | grep nginx_custom

Gerçek Dünya Senaryosu 2: Özel Port Kullanan Servis

Bir Java uygulaması 8443 portunda dinlemek istiyor ama SELinux buna izin vermiyor. Uygulama başlayamıyor.

# Port ile ilgili AVC redlerini bul
ausearch -m avc -ts recent | grep "name_bind"

Bu durumda hem port bağlama hem de olası dosya erişimleri için politika oluşturmanız gerekebilir:

# Önce mevcut port tanımlarını kontrol et
semanage port -l | grep 8443

# Port SELinux'a ekle (tercih edilen yöntem)
semanage port -a -t http_port_t -p tcp 8443

# Yoksa audit2allow ile çöz
ausearch -m avc -c java | audit2allow -M java_app_custom
semodule -i java_app_custom.pp

audit2allow Parametrelerini Derinlemesine İnceleme

audit2allow birçok parametre alır. Bunları iyi bilmek işinizi kolaylaştırır:

  • -a: /var/log/audit/audit.log dosyasını otomatik olarak okur
  • -i dosya: Belirtilen dosyadan okur
  • -M isim: Belirtilen isimle politika modülü oluşturur (.te ve .pp dosyaları)
  • -m isim: Sadece .te dosyası oluşturur, derlemez
  • -w: Neden reddedildiğini açıklar (audit2why ile aynı)
  • -l: Sadece son boot’tan bu yana olan redleri işler
  • -d: Geliştirici modu, daha detaylı çıktı
  • -R: Mevcut makrolar ve arayüzler kullanılarak çözüm önerir (daha temiz politika)
  • -p dosya: Alternatif politika dosyası kullan
  • -r: Referans politika kullan

En sık kullandığım kombinasyon şudur:

# Tüm son AVC redlerinden kapsamlı modül oluştur
ausearch -m avc -ts recent | audit2allow -R -M myapp_policy

# Modülü incele ve yükle
cat myapp_policy.te
semodule -i myapp_policy.pp

-R parametresi önemlidir çünkü ham allow kuralları yerine mümkün olduğunda önceden tanımlanmış politika arayüzlerini kullanır. Bu, daha güvenli ve bakımı kolay politikalar üretir.

Politika Modülü İnceleme ve Güvenlik

Bu konuda çok önemli bir uyarı yapmam gerekiyor: audit2allow‘ın ürettiği her politikayı körü körüne uygulamayın. Araç bazen gereğinden geniş izinler önerebilir.

Oluşturulan .te dosyasını her zaman inceleyin:

# Örnek bir .te dosyası içeriği
cat myapp_policy.te

Tipik bir çıktı şöyle görünür:

module myapp_policy 1.0;

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

#============= httpd_t ==============
allow httpd_t var_t:file { read write };

Bu politikayı göründüğünde kendinize şu soruları sorun: httpd_t gerçekten var_t dosyalarına yazmak zorunda mı? /var altındaki hangi spesifik dizin bu? Daha kısıtlayıcı bir tip kullanabilir miyim?

Politikayı Manuel Olarak İnce Ayar Yapmak

Çoğu zaman audit2allow‘ın ürettiği politikayı biraz düzenlemeniz gerekir:

# .te dosyasını düzenle
vi myapp_policy.te

Dosyayı düzenledikten sonra yeniden derlemeniz ve yüklemeniz gerekir:

# .te dosyasını derle
checkmodule -M -m -o myapp_policy.mod myapp_policy.te

# Politika paketini oluştur
semodule_package -o myapp_policy.pp -m myapp_policy.mod

# Yükle
semodule -i myapp_policy.pp

# Ya da tüm süreci bir script ile otomatize et
make -f /usr/share/selinux/devel/Makefile myapp_policy.pp
semodule -i myapp_policy.pp

Gerçek Dünya Senaryosu 3: PostgreSQL Özel Veri Dizini

PostgreSQL’i varsayılan /var/lib/pgsql/data yerine /mnt/nvme/pgdata gibi hızlı bir NVMe diskine taşıdınız. Servis başlamıyor.

# PostgreSQL AVC redlerini incele
ausearch -m avc -c postgres -ts recent | audit2why

Bu senaryo için genellikle iki adımlı bir yaklaşım işe yarar:

# Adım 1: PostgreSQL veri dizini için doğru SELinux bağlamı
semanage fcontext -a -t postgresql_db_t "/mnt/nvme/pgdata(/.*)?"
restorecon -Rv /mnt/nvme/pgdata

# Adım 2: Kalan sorunlar için audit2allow
ausearch -m avc -c postgres -ts recent | audit2allow -M pgsql_nvme
cat pgsql_nvme.te
semodule -i pgsql_nvme.pp

# PostgreSQL'i yeniden başlat ve test et
systemctl restart postgresql-14
systemctl status postgresql-14

Permissive Modunu Akıllıca Kullanmak

Tüm redleri bir kerede yakalamak istiyorsanız, ilgili servisi geçici olarak permissive moda alabilirsiniz. Bu, tüm sistemi permissive moda almaktan çok daha güvenlidir:

# Belirli bir domain için permissive mod
semanage permissive -a httpd_t

# Şimdi uygulamanızı test edin, tüm redler loglanır ama engellenmez

# Logları topla ve kapsamlı bir politika oluştur
ausearch -m avc -c httpd | audit2allow -M httpd_comprehensive

# Politikayı incele ve yükle
cat httpd_comprehensive.te
semodule -i httpd_comprehensive.pp

# Permissive modu kaldır
semanage permissive -d httpd_t

# Son test
systemctl restart httpd
# Uygulamayı tam olarak test et
ausearch -m avc -c httpd -ts recent  # Hata kalmamalı

Bu yaklaşım, üretim ortamında acil durumlarda çok işe yarar. Tüm sistemi açmak yerine sadece sorunlu servisi açık bırakırsınız.

Politikaları Yönetmek ve Kaldırmak

Zamanla sisteminizde biriken politika modüllerini yönetmek önemlidir:

# Tüm yüklü modülleri listele
semodule -l

# Belirli bir modülü devre dışı bırak
semodule -d myapp_policy

# Belirli bir modülü kaldır
semodule -r myapp_policy

# Modül sürümünü güncelle (aynı isimle yeniden yükle)
semodule -i myapp_policy_v2.pp

# Tüm özel modülleri listele (sistem modüllerini hariç tut)
semodule -l | grep -v "base|permissive"

Politika modüllerinizi bir Git reposunda tutmanızı şiddetle tavsiye ederim. .te dosyaları küçük ve okunabilir olduğundan versiyon kontrolü için idealdir.

Troubleshooting ve Sık Karşılaşılan Hatalar

“Nothing to do” Hatası

audit2allow bazen herhangi bir çıktı üretmez. Bu genellikle logda AVC reddi olmadığı anlamına gelir:

# Logda gerçekten AVC var mı kontrol et
grep "AVC" /var/log/audit/audit.log | wc -l

# SELinux enforcing modda mı?
getenforce

# dontaudit kuralları bazı redleri gizliyor olabilir
semodule -DB  # dontaudit kurallarını devre dışı bırak
# Uygulamayı test et
semodule -B   # Geri yükle

Politika Yükleme Hatası

# Modül zaten yüklüyse güncelle
semodule -i myapp_policy.pp 2>&1 | grep -i error

# Versiyon çakışması varsa
# .te dosyasındaki versiyon numarasını artır
sed -i 's/module myapp_policy 1.0/module myapp_policy 1.1/' myapp_policy.te

Politika Uygulandı Ama Sorun Devam Ediyor

# Politikanın gerçekten yüklendiğini doğrula
semodule -l | grep myapp_policy

# Cache'i temizle ve yeniden yükle
semodule -i myapp_policy.pp --noreload
semodule -R

# Dosya bağlamlarını kontrol et
ls -laZ /path/to/problematic/file

Audit2allow’u Otomatize Etmek: Basit Bir Script

Rutin politika oluşturma sürecini hızlandırmak için şöyle bir script kullanabilirsiniz:

#!/bin/bash
# selinux_policy_helper.sh

SERVICE=${1:-"httpd"}
POLICY_NAME="${SERVICE}_custom_$(date +%Y%m%d)"

echo "=== SELinux Policy Helper ==="
echo "Servis: $SERVICE"
echo "Politika adı: $POLICY_NAME"

# AVC redlerini kontrol et
AVC_COUNT=$(ausearch -m avc -c "$SERVICE" -ts recent 2>/dev/null | grep -c "AVC")

if [ "$AVC_COUNT" -eq 0 ]; then
    echo "Son boot'tan bu yana $SERVICE için AVC reddi bulunamadı."
    exit 0
fi

echo "$AVC_COUNT adet AVC reddi bulundu."
echo ""
echo "=== Redlerin Analizi ==="
ausearch -m avc -c "$SERVICE" -ts recent | audit2why

echo ""
echo "=== Politika Oluşturuluyor ==="
ausearch -m avc -c "$SERVICE" -ts recent | audit2allow -R -M "$POLICY_NAME"

echo ""
echo "=== Oluşturulan Politika ==="
cat "${POLICY_NAME}.te"

echo ""
read -p "Bu politikayı yüklemek istiyor musunuz? (e/h): " CONFIRM
if [ "$CONFIRM" = "e" ]; then
    semodule -i "${POLICY_NAME}.pp"
    echo "Politika yüklendi: $POLICY_NAME"
else
    echo "Politika yüklenmedi. Dosyalar: ${POLICY_NAME}.te ve ${POLICY_NAME}.pp"
fi

Scripti çalıştırmak için:

chmod +x selinux_policy_helper.sh
./selinux_policy_helper.sh nginx
./selinux_policy_helper.sh postgres

Politika Modüllerini Dokümante Etmek

Oluşturduğunuz her politika modülü için neden oluşturulduğunu belgelemenizi öneririm. .te dosyasının başına yorum satırları ekleyin:

# Dosya başına yorum ekle
cat > myapp_policy.te << 'EOF'
# Politika Adı: myapp_policy
# Oluşturulma: 2024-01-15
# Oluşturan: [email protected]
# Sebep: /data/app dizininden servis eden özel Java uygulaması
# Etkilenen Servis: myapp.service
# Bilet/Issue: INFRA-4521
# Son Test: 2024-01-15 - tum testler gecti

module myapp_policy 1.0;
# ... geri kalan politika
EOF

Sonuç

audit2allow, SELinux politika yönetiminin en pratik aracıdır. Ancak “audit logunu ver, politikayı al, uygula” kadar basit bir araç olarak görmek hata olur. Doğru kullanım şu adımları içerir: önce redleri analiz et, neden reddedildiğini anla, mümkünse semanage fcontext veya semanage port ile doğrudan çöz, kalan karmaşık durumlar için audit2allow kullan ve oluşturulan politikayı mutlaka gözden geçir.

SELinux’u kapatmak kısa vadede işleri kolaylaştırıyor gibi görünse de uzun vadede sisteminizi ciddi risklere açar. Özellikle internet’e açık servislerde, bir saldırgan uygulamayı ele geçirdiğinde SELinux ek bir güvenlik katmanı sağlar ve hasarı sınırlar. Bu yüzden birkaç saat harcayıp doğru politikaları yazmak, uzun vadede sisteminizi çok daha güvenli ve yönetilebilir kılar.

Sık kullandığınız uygulamalar için politika modüllerini Git’te tutun, açıklayıcı yorumlar ekleyin ve ekibinizle paylaşın. SELinux politikaları da kod gibi versiyon kontrolüne tabi tutulmalıdır. Başta karmaşık görünen bu süreç, birkaç pratikten sonra rutin bir operasyon haline gelecektir.

Yorum yapın