Merhaba arkadaşlar, bugün sizlere özellikle yeni sistem yöneticilerinin korkulu rüyası gibi görünen, ama aslında doğru anladığımızda sunucu güvenliğimizi kat be kat artıran SELinux'tan bahsedeceğim. Özellikle "Permission denied" hatalarıyla boğuşup, SELinux'u devre dışı bırakmak yerine, onun nasıl çalıştığını ve basit kurallarını nasıl yazacağımızı öğreneceğiz. Benim sunucularda genelde varsayılan olarak "enforcing" modda tuttuğum, vazgeçilmez bir güvenlik katmanıdır.
SELinux Nedir ve Neden Önemli?
SELinux (Security-Enhanced Linux), geleneksel Linux izin sistemine (rwx) ek olarak çalışan, zorunlu erişim kontrolü (MAC - Mandatory Access Control) sağlayan bir güvenlik modülüdür. Klasik izinlerde, bir proses bir dosyaya erişim hakkına sahipse (örneğin, Apache'nin kullanıcısı olan www-data), o dosyayı okuyup yazabilir. SELinux ise "Bu proses, bu dosyaya, bu bağlamda erişebilir mi?" sorusunu sorar ve çok daha ince taneli kontroller yapar. Bu, bir servisteki güvenlik açığından etkilenen bir prosesin tüm sisteme sıçramasını engellemek için harikadır.
Temel Kavramlar: Bağlam (Context), Modlar ve Araçlar
İşe, SELinux'un nesnelere (dosya, proses, port) verdiği etiket olan "Bağlam"ı (Context) anlayarak başlayalım. Bağlamı `ls -Z` veya `ps -Z` komutlarıyla görebiliriz.
Buradaki `httpd_sys_content_t`, dosyanın SELinux tipidir (Type). SELinux politikaları genellikle bu tipler üzerinden kuralları tanımlar. Proseslerin de bir bağlamı vardır:
Apache prosesinin tipi `httpd_t`'dir. Varsayılan politikada, `httpd_t` tipindeki bir proses, `httpd_sys_content_t` tipindeki bir dosyayı okuyabilir.
SELinux'un üç çalışma modu vardır:
Enforcing: Politikaları uygular ve ihlalleri kaydeder.
Permissive: Politikaları uygulamaz, sadece ihlalleri kaydeder. Debug için mükemmeldir.
Disabled: Tamamen devre dışıdır (Sunucuyu yeniden başlatmayı gerektirir, önermem).
Mevcut durumu `getenforce` komutuyla, geçici olarak değiştirmeyi ise `setenforce` komutuyla yaparız. Kalıcı değişiklik için /etc/selinux/config dosyasını düzenleriz.
Bağlam Yönetimi: Tanımlama ve Değiştirme
Diyelim ki özel bir web uygulamamız için /opt/myapp dizini oluşturduk ve Apache'nin buradaki dosyaları sunmasını istiyoruz. Varsayılan olarak bu dizinin bağlamı `default_t` olacak ve Apache (`httpd_t`) buraya erişemeyecektir. İlk adım, doğru bağlamı atamaktır.
Dosya/dizin bağlamını öğrenmek ve değiştirmek için `semanage fcontext` ve `restorecon` komutlarını kullanırız. Önce, bu tür özel içerik dizinleri için doğru olan tipi (`httpd_sys_content_t`) tanımlayalım:
Ardından, bu kuralı dosya sistemine uygulayalım:
Artık `ls -Z /opt/myapp` komutu, tüm dosyaların `httpd_sys_content_t` tipinde olduğunu gösterecektir.
Sorun Giderme ve Denetim Kayıtları (Audit Logs)
Bir servis çalışmıyorsa ve klasik izinlerde sorun yoksa, ilk bakmamız gereken yer SELinux denetim kayıtlarıdır. Ana log dosyası /var/log/audit/audit.log'dur. Ancak daha kolay okunabilir çıktı için `ausearch` ve `sealert` (veya `audit2why`) araçlarını kullanırız.
Daha anlaşılır bir özet için:
Örneğin, çıktıda "Apache'nin /opt/myapp/logs dizinine yazmasına izin verilmemiş" gibi bir şey görebiliriz. Bu dizin için `httpd_sys_content_t` tipi sadece okuma izni verir. Yazma izni için `httpd_log_t` veya `httpd_sys_rw_content_t` gibi farklı bir tip gerekebilir.
Basit Politika Modülü Oluşturma
Bazen hazır tipler işimizi görmez veya özel bir port, dosya kullanmamız gerekir. Bu durumda `audit2allow` aracı ile ihlalleri analiz edip kendi politikamızı oluşturabiliriz. Diyelim ki Nginx'in 8081 portunu dinlemesine izin vermek istiyoruz ve audit.log'da buna dair bir ihlal var.
İlk adım, ilgili ihlalleri bir dosyaya kaydetmek:
Oluşan `mynginx.te` dosyasını inceleyin. İçinde `allow nginx_t ...` gibi bir kural önerisi olacaktır. Bu dosyayı düzenleyebilirsiniz. Onayladıktan sonra, ondan derlenebilir bir politika modülü (.pp) oluşturup yükleyelim:
Sonuç ve Öneriler
SELinux'u asla sorun çıkaran bir engel olarak değil, sizi koruyan bir partner olarak görmeye başladığınızda, sistem güvenliğiniz çok farklı bir seviyeye çıkacaktır. İlk kuralım: Asla SELinux'u devre dışı bırakma! Bunun yerine, sorunu anlamaya çalış ve "Permissive" modda logları inceleyerek çözüm üret. Zamanla hangi servisin hangi tipte dosyalarla çalıştığını öğrenecek ve konfigürasyon yaparken bunu otomatik olarak düşüneceksiniz.
Siz bu konfigürasyonu kendi sunucularınızda nasıl yapıyorsunuz? SELinux ile ilgili unutamadığınız komik/bunalımlı bir hikayeniz var mı? Ya da takıldığınız bir nokta olursa aşağıya yazmaktan çekinmeyin, beraber çözelim.
SELinux (Security-Enhanced Linux), geleneksel Linux izin sistemine (rwx) ek olarak çalışan, zorunlu erişim kontrolü (MAC - Mandatory Access Control) sağlayan bir güvenlik modülüdür. Klasik izinlerde, bir proses bir dosyaya erişim hakkına sahipse (örneğin, Apache'nin kullanıcısı olan www-data), o dosyayı okuyup yazabilir. SELinux ise "Bu proses, bu dosyaya, bu bağlamda erişebilir mi?" sorusunu sorar ve çok daha ince taneli kontroller yapar. Bu, bir servisteki güvenlik açığından etkilenen bir prosesin tüm sisteme sıçramasını engellemek için harikadır.
İşe, SELinux'un nesnelere (dosya, proses, port) verdiği etiket olan "Bağlam"ı (Context) anlayarak başlayalım. Bağlamı `ls -Z` veya `ps -Z` komutlarıyla görebiliriz.
Bash:
ls -Z /var/www/html/index.html
# Çıktı şuna benzer: -rw-r--r--. www-data www-data system_u:object_r:httpd_sys_content_t:s0 index.html
Buradaki `httpd_sys_content_t`, dosyanın SELinux tipidir (Type). SELinux politikaları genellikle bu tipler üzerinden kuralları tanımlar. Proseslerin de bir bağlamı vardır:
Bash:
ps -Z -C httpd
# Çıktı: system_u:system_r:httpd_t:s0
Apache prosesinin tipi `httpd_t`'dir. Varsayılan politikada, `httpd_t` tipindeki bir proses, `httpd_sys_content_t` tipindeki bir dosyayı okuyabilir.
SELinux'un üç çalışma modu vardır:
Enforcing: Politikaları uygular ve ihlalleri kaydeder.
Permissive: Politikaları uygulamaz, sadece ihlalleri kaydeder. Debug için mükemmeldir.
Disabled: Tamamen devre dışıdır (Sunucuyu yeniden başlatmayı gerektirir, önermem).
Mevcut durumu `getenforce` komutuyla, geçici olarak değiştirmeyi ise `setenforce` komutuyla yaparız. Kalıcı değişiklik için /etc/selinux/config dosyasını düzenleriz.
Diyelim ki özel bir web uygulamamız için /opt/myapp dizini oluşturduk ve Apache'nin buradaki dosyaları sunmasını istiyoruz. Varsayılan olarak bu dizinin bağlamı `default_t` olacak ve Apache (`httpd_t`) buraya erişemeyecektir. İlk adım, doğru bağlamı atamaktır.
Dosya/dizin bağlamını öğrenmek ve değiştirmek için `semanage fcontext` ve `restorecon` komutlarını kullanırız. Önce, bu tür özel içerik dizinleri için doğru olan tipi (`httpd_sys_content_t`) tanımlayalım:
Bash:
sudo semanage fcontext -a -t httpd_sys_content_t "/opt/myapp(/.)?"
# Bu, "/opt/myapp" ve altındaki tüm dosyalar için kalıcı bir bağlam kuralı ekler.
Ardından, bu kuralı dosya sistemine uygulayalım:
Bash:
sudo restorecon -Rv /opt/myapp
# -R: recursive, -v: verbose, -v: değişen bağlamları gösterir.
Artık `ls -Z /opt/myapp` komutu, tüm dosyaların `httpd_sys_content_t` tipinde olduğunu gösterecektir.
Bir servis çalışmıyorsa ve klasik izinlerde sorun yoksa, ilk bakmamız gereken yer SELinux denetim kayıtlarıdır. Ana log dosyası /var/log/audit/audit.log'dur. Ancak daha kolay okunabilir çıktı için `ausearch` ve `sealert` (veya `audit2why`) araçlarını kullanırız.
Bash:
sudo ausearch -m avc -ts recent
# Son AVC (Access Vector Cache) ihlallerini gösterir.
Daha anlaşılır bir özet için:
Bash:
sudo ausearch -m avc -ts recent | audit2why
# İhlalin nedenini ve POTANSİYEL çözümünü İngilizce açıklar.
Örneğin, çıktıda "Apache'nin /opt/myapp/logs dizinine yazmasına izin verilmemiş" gibi bir şey görebiliriz. Bu dizin için `httpd_sys_content_t` tipi sadece okuma izni verir. Yazma izni için `httpd_log_t` veya `httpd_sys_rw_content_t` gibi farklı bir tip gerekebilir.
Bazen hazır tipler işimizi görmez veya özel bir port, dosya kullanmamız gerekir. Bu durumda `audit2allow` aracı ile ihlalleri analiz edip kendi politikamızı oluşturabiliriz. Diyelim ki Nginx'in 8081 portunu dinlemesine izin vermek istiyoruz ve audit.log'da buna dair bir ihlal var.
İlk adım, ilgili ihlalleri bir dosyaya kaydetmek:
Bash:
sudo ausearch -m avc -ts recent | audit2allow -m mynginx > mynginx.te
# .te dosyası, Type Enforcement politikası taslağıdır.
Oluşan `mynginx.te` dosyasını inceleyin. İçinde `allow nginx_t ...` gibi bir kural önerisi olacaktır. Bu dosyayı düzenleyebilirsiniz. Onayladıktan sonra, ondan derlenebilir bir politika modülü (.pp) oluşturup yükleyelim:
Bash:
sudo ausearch -m avc -ts recent | audit2allow -M mynginx
# Bu, mynginx.te ve mynginx.pp dosyalarını oluşturur.
sudo semodule -i mynginx.pp
# Politikayı sisteme yükler.
SELinux'u asla sorun çıkaran bir engel olarak değil, sizi koruyan bir partner olarak görmeye başladığınızda, sistem güvenliğiniz çok farklı bir seviyeye çıkacaktır. İlk kuralım: Asla SELinux'u devre dışı bırakma! Bunun yerine, sorunu anlamaya çalış ve "Permissive" modda logları inceleyerek çözüm üret. Zamanla hangi servisin hangi tipte dosyalarla çalıştığını öğrenecek ve konfigürasyon yaparken bunu otomatik olarak düşüneceksiniz.
Siz bu konfigürasyonu kendi sunucularınızda nasıl yapıyorsunuz? SELinux ile ilgili unutamadığınız komik/bunalımlı bir hikayeniz var mı? Ya da takıldığınız bir nokta olursa aşağıya yazmaktan çekinmeyin, beraber çözelim.