RHEL, AlmaLinux, Rocky Linux ya da CentOS Stream tabanlı bir sunucu kiraladığınızda, çoğu zaman farkında bile olmadan arkanızda çalışan güçlü bir güvenlik katmanı devreye girer: SELinux. Uygulamanız bir gün "Permission denied" hatasıyla açılmadığında ya da yeni yapılandırdığınız web servisi 13 numaralı hatayla takıldığında, ilk şüphelenilen çoğunlukla dosya izinleri olur. Oysa chmod 777 denemelerine rağmen sorun çözülmüyorsa, büyük ihtimalle karşınızda klasik izin sistemi değil, onun üzerine oturan zorunlu erişim kontrolü (MAC) mekanizması SELinux vardır.
İnternette karşılaşacağınız pek çok rehber bu noktada tek satırlık bir "çözüm" önerir: SELinux'u kapatın. Bu, ateşi düşürmek için termometreyi kırmaya benzer. SELinux, bir saldırgan web sunucunuzu ele geçirse bile onun sistemin geri kalanına yayılmasını engelleyen, sıfırıncı gün açıklarında bile hasarı sınırlayan bir savunma katmanıdır. Bu rehberde SELinux'un mantığını, modlarını, bağlam kavramını, engelleri nasıl teşhis edeceğinizi ve semanage ile audit2allow gibi araçlarla nasıl doğru yöneteceğinizi kıdemli bir sistem yöneticisinin gözünden anlatacağız. Amaç açık: kapatmadan yönetmek.
SELinux Nedir ve Neden Kapatılmamalı#
Geleneksel Linux izin modeli, isteğe bağlı erişim kontrolü (DAC — Discretionary Access Control) olarak bilinir. Burada bir dosyanın sahibi, o dosya üzerindeki izinleri dilediği gibi belirleyebilir; root ise fiilen her şeyi yapabilir. Bu esneklik güçlüdür ama tehlikelidir: root yetkisiyle çalışan bir servis ele geçirilirse, saldırgan da root gibi davranabilir. SELinux (Security-Enhanced Linux) tam da bu boşluğu doldurmak için geliştirilmiş bir zorunlu erişim kontrolü (MAC — Mandatory Access Control) sistemidir.
MAC modelinde erişim kararlarını dosya sahibi değil, merkezî bir güvenlik politikası verir. Her sürece, her dosyaya, her porta ve her sokete bir "etiket" (label) atanır. Çekirdek, bir sürecin bir kaynağa erişip erişemeyeceğine bakarken kullanıcının kim olduğuna değil, sürecin etiketiyle kaynağın etiketi arasında politikanın izin verip vermediğine bakar. Yani nginx süreci, politikada tanımlanmadığı sürece bir kullanıcının ev dizinindeki dosyaları okuyamaz — root olarak çalışsa bile.
Buradaki kritik nokta şudur: SELinux, DAC'in yerine geçmez, üstüne eklenir. Önce klasik izinler (sahiplik, rwx) kontrol edilir; onları geçen istek bir de SELinux politikasından geçmek zorundadır. Bu iki katmanlı yapı, "web sunucum hacklendi ama saldırgan veritabanı şifrelerine ulaşamadı" farkını yaratır. Sunucu güvenliğinin bütününe dair genel prensipleri sunucu güvenliği temelleri rehberimizde ele alıyoruz; SELinux bu bütünün en güçlü halkalarından biridir. Kapatmak, sadece bir sorunu bugün geçiştirir ama yarın ödenecek bedeli büyütür.
SELinux Modları: Enforcing, Permissive ve Disabled#
SELinux üç temel modda çalışır ve bir yöneticinin ilk öğrenmesi gereken şey bu modlar arasındaki farktır. Mevcut modu görmek için getenforce, geçici olarak değiştirmek için setenforce komutunu kullanırsınız.
# Aktif modu göster
getenforce
# Çıktı: Enforcing
# Ayrıntılı durum (mod, politika, mount noktası)
sestatus
# Enforcing'den Permissive'e geçici geçiş (yeniden başlatmada sıfırlanır)
setenforce 0
# Tekrar Enforcing moduna al
setenforce 1
Üç modun anlamı aşağıdaki gibidir. Bu tabloyu bir başvuru kaynağı olarak aklınızda tutun:
| Mod | Kural uygulanır mı | İhlal loglanır mı | Ne zaman kullanılır |
|---|---|---|---|
| Enforcing | Evet, erişim engellenir | Evet | Üretim ortamının varsayılanı ve hedefi |
| Permissive | Hayır, erişime izin verilir | Evet | Sorun giderme ve politika hazırlama |
| Disabled | Hayır, hiç yüklenmez | Hayır | Neredeyse hiçbir zaman önerilmez |
Buradaki en değerli mod, çoğu kişinin atladığı Permissive'dir. Permissive modda SELinux hiçbir şeyi engellemez, ama engelleyecek olsaydı neyi engelleyeceğini eksiksiz loglar. Yani uygulamanız sorunsuz çalışmaya devam ederken siz arka planda hangi izinlerin gerektiğini toplayabilirsiniz. Yeni bir uygulamayı devreye alırken önce Permissive'de çalıştırıp logları biriktirmek, sonra gereken kuralları ekleyip Enforcing'e dönmek en profesyonel yaklaşımdır.
setenforce ile yapılan değişiklik geçicidir; sunucu yeniden başladığında eski haline döner. Kalıcı ayar /etc/selinux/config dosyasındadır:
# /etc/selinux/config
# SELINUX= enforcing, permissive veya disabled olabilir
SELINUX=enforcing
# targeted (varsayılan) belirli servisleri hedefler; mls tam çok seviyeli güvenlik
SELINUXTYPE=targeted
Bir tavsiye: SELINUX=disabled satırını asla üretim sunucunuzda kalıcı yapmayın. Disabled moddan Enforcing'e geri dönmek, tüm dosya sistemini yeniden etiketlemeyi (relabel) gerektirir ve bu bazen saatler sürebilir. Sorun yaşadığınızda geçici olarak setenforce 0 ile Permissive'e alın, teşhis edin, düzeltin ve Enforcing'e geri dönün. Kalıcı kapatma neredeyse hiçbir gerçek soruna gerçek bir çözüm değildir.
Bağlam (Context) Kavramı: Dosya ve Süreç Etiketleri#
SELinux'un kalbi "bağlam" (context) kavramıdır. Sistemdeki her nesnenin bir güvenlik bağlamı vardır ve bu bağlam dört alandan oluşur: user:role:type:level. Pratikte hedefli (targeted) politikada en çok önem taşıyan alan type yani "tür"dür; SELinux kararlarının büyük çoğunluğu tür zorlaması (type enforcement) üzerinden verilir.
Dosyaların bağlamını görmek için standart komutlara -Z bayrağını eklersiniz:
# Dosya bağlamlarını listele
ls -Z /var/www/html
# unconfined_u:object_r:httpd_sys_content_t:s0 index.html
# Süreç bağlamlarını göster
ps -eZ | grep nginx
# system_u:system_r:httpd_t:s0 ... nginx
# Portların bağlamını incele
semanage port -l | grep http
Bu çıktıda önemli olan şudur: nginx süreci httpd_t türünde çalışır, /var/www/html altındaki içerik ise httpd_sys_content_t türüyle etiketlenmiştir. Politika, httpd_t süreçlerinin httpd_sys_content_t dosyalarını okumasına izin verir. İşte web siteniz bu yüzden çalışır. Ama siteyi standart dışı bir dizine, örneğin /opt/site altına koyarsanız, oradaki dosyalar default_t gibi bambaşka bir türle etiketlenir ve nginx onları okuyamaz — dosya izinleri 755 olsa bile.
Klasik "web sitem taşındıktan sonra 403 verdi" sorununun kaynağı neredeyse her zaman budur. Çözüm dosyayı yeniden etiketlemektir:
# Tek bir dosya/dizin için varsayılan bağlamı geri yükle
restorecon -Rv /var/www/html
# Bir dosyanın bağlamını referans başka dosyadan kopyala
chcon --reference=/var/www/html/index.html /opt/site/index.html
# Tüm sistemi yeniden etiketle (önyükleme zorunlu)
touch /.autorelabel && reboot
Burada altını çizmek gereken kritik ayrım: chcon bağlamı geçici olarak değiştirir; bir sonraki restorecon çalıştığında veya sistem yeniden etiketlendiğinde bu değişiklik kaybolur. Kalıcı bir bağlam değişikliği için politikaya yeni bir kural eklemek gerekir ve bunun aracı semanage'dır. Bu ayrım, SELinux'u doğru yönetmenin belki de en sık atlanan noktasıdır.
Engellenen Erişimi Teşhis Etmek: Loglar ve audit2allow#
SELinux bir erişimi engellediğinde çığlık atmaz; sessizce reddeder ve olayı loglar. İyi haber: bu loglar son derece ayrıntılıdır ve doğru okuduğunuzda size tam olarak neyin engellendiğini ve nasıl izin vereceğinizi söyler. İhlal kayıtları (AVC — Access Vector Cache denial) çoğunlukla /var/log/audit/audit.log dosyasında tutulur.
Ham logu okumak zahmetlidir; bunun yerine ausearch ve sealert araçlarını kullanın. setroubleshoot-server paketi kuruluysa, sealert size neredeyse insan diliyle bir açıklama ve önerilen komutu verir:
# Son bir saatteki tüm AVC ihlallerini bul
ausearch -m avc -ts recent
# İnsan tarafından okunabilir teşhis ve öneri
sealert -a /var/log/audit/audit.log
# Belirli bir servisin ihlallerini süz
ausearch -m avc -c nginx -ts today
Tipik bir AVC ihlali kaydı şuna benzer ve her alanı bir şey anlatır:
type=AVC msg=audit(1720608000.123:456): avc: denied { read }
for pid=2481 comm="nginx" name="app.log" dev="vda1" ino=98765
scontext=system_u:system_r:httpd_t:s0
tcontext=unconfined_u:object_r:var_log_t:s0 tclass=file permissive=0
Bu satırı çözelim: httpd_t türündeki nginx süreci, var_log_t türündeki bir dosyayı read etmeye çalışmış ve reddedilmiş. Yani nginx, log dizinindeki bir dosyayı okumak istiyor ama politikada buna izin yok. Şimdi kararınızı vermeniz gerekiyor: dosya yanlış yerde mi (o zaman restorecon ile düzeltin) yoksa bu erişim gerçekten meşru mu (o zaman politikaya izin ekleyin).
Meşru bir erişim için gereken kuralı elle yazmak zordur; neyse ki audit2allow bu logları okuyup sizin için bir politika modülü üretir:
# İhlalleri okuyup önerilen kuralı ekrana yaz (henüz uygulama)
ausearch -m avc -ts recent | audit2allow -m nginx_local
# Doğrudan yüklenebilir bir modül üret ve yükle
ausearch -m avc -ts recent | audit2allow -M nginx_local
semodule -i nginx_local.pp
Burada bir uyarı şart: audit2allow çıktısını körlemesine uygulamak tehlikelidir. Araç, logdaki her ihlale izin verir; ama o ihlallerden bazıları gerçek bir saldırının veya yanlış yapılandırmanın işareti olabilir. Üretilen .te kaynağını daima okuyun. Eğer kural "nginx tüm sistem dosyalarını okuyabilsin" gibi aşırı genişse, sorun genellikle dosyanın yanlış etiketlenmiş olmasıdır ve doğru çözüm izin eklemek değil, restorecon ile etiketi düzeltmektir.
semanage ile Kalıcı Port ve Bağlam Yönetimi#
semanage, SELinux politikasını kalıcı olarak yönetmenin ana aracıdır. chcon geçici, semanage fcontext kalıcıdır; bu farkı içselleştirmek çoğu baş ağrısını önler. En sık ihtiyaç duyulan iki senaryo standart olmayan portlar ve standart olmayan dizinlerdir.
Diyelim ki web sunucunuzu güvenlik için 80 yerine 8443 portunda dinletmek istiyorsunuz. nginx'i başlattığınızda "Permission denied" alırsınız, çünkü httpd_t türü yalnızca politikada tanımlı HTTP portlarına bağlanabilir. 8443 o listede yoktur. Çözüm portu doğru türe eklemektir:
# 8443 portunu HTTP servisi türüne kalıcı olarak ekle
semanage port -a -t http_port_t -p tcp 8443
# Var olan bir tanımı değiştir
semanage port -m -t http_port_t -p tcp 8443
# Eklediğiniz özel port tanımlarını listele
semanage port -l | grep http_port_t
# Yanlış eklediğiniz bir tanımı sil
semanage port -d -t http_port_t -p tcp 8443
Aynı mantık dosya bağlamları için de geçerlidir. Web içeriğinizi /opt/site altında tutuyorsanız, bu yolu kalıcı olarak httpd_sys_content_t türüne eşleyip sonra restorecon ile uygulayın. Böylece gelecekte sistem yeniden etiketlense bile bağlam korunur:
# /opt/site ve altındaki her şey için kalıcı bağlam kuralı ekle
semanage fcontext -a -t httpd_sys_content_t "/opt/site(/.*)?"
# Kuralı fiilen dosyalara uygula
restorecon -Rv /opt/site
# Uygulama verinin yazılabilir olması gerekiyorsa farklı tür kullanın
semanage fcontext -a -t httpd_sys_rw_content_t "/opt/site/uploads(/.*)?"
restorecon -Rv /opt/site/uploads
Buradaki (/.*)? düzenli ifadesi hem dizinin kendisini hem de altındaki tüm içeriği kapsar — kalıcı kurallarda bu kalıbı kullanmayı alışkanlık haline getirin. Port ve bağlam kurallarınızı semanage ... -l ile düzenli olarak listelemek, sunucunuzda hangi özel istisnaların tanımlı olduğunu görmenizi sağlar; bu da bir güvenlik denetiminin parçası olarak değerlidir. Ağ tarafındaki port açma/kapama işlemlerini güvenlik duvarıyla birlikte yönetmek için UFW ve güvenlik duvarı yönetimi rehberimiz SELinux port kurallarını tamamlar.
Booleans ile Politika Ayarlarını Açıp Kapatmak#
SELinux politikası, her yöneticinin karşılaşacağı yaygın senaryolar için önceden hazırlanmış anahtarlar sunar. Bunlara "boolean" denir. Bir modül yazmak yerine, çoğu ihtiyaç tek bir boolean'ı açıp kapatarak karşılanır. Örneğin web uygulamanızın uzak bir veritabanına veya harici bir API'ye bağlanması gerekiyorsa, httpd_t türünün ağ bağlantısı kurmasına izin veren boolean'ı açmanız yeterlidir.
# Tüm boolean'ları ve durumlarını listele
getsebool -a | grep httpd
# Web sunucusunun ağa (DB, API) bağlanmasına kalıcı izin ver
setsebool -P httpd_can_network_connect on
# Sadece veritabanı bağlantısına izin ver (daha dar kapsam)
setsebool -P httpd_can_network_connect_db on
# Web sunucusunun kullanıcı ev dizinlerini okumasına izin ver
setsebool -P httpd_enable_homedirs on
Buradaki -P bayrağı hayatidir; onsuz yapılan değişiklik yalnızca bellekte kalır ve yeniden başlatmada kaybolur. -P ile ayar kalıcı politikaya yazılır. Boolean'ları tercih etmek, elle modül yazmaya göre çok daha güvenlidir çünkü bu anahtarlar Red Hat mühendisleri tarafından belirli, sınırlı ve denetlenmiş erişimleri açacak şekilde tasarlanmıştır. httpd_can_network_connect_db gibi dar kapsamlı boolean varken geniş httpd_can_network_connect'i açmak, en az yetki ilkesine aykırıdır; her zaman ihtiyacınıza en dar geleni seçin.
Yaygın bir üretim senaryosu WordPress veya benzeri bir PHP uygulamasıdır. Uygulama dosya yükleyecekse yazma bağlamı, harici SMTP kullanacaksa ağ boolean'ı, uzak MySQL kullanacaksa DB boolean'ı gerekir. Bunları tek tek ve dar kapsamda açmak, nginx veya Apache'yi tümden serbest bırakmaktan çok daha güvenli bir sonuç verir. Yönetilen WordPress hosting paketlerimizde bu tür SELinux ince ayarları zaten bizim tarafımızdan yapılır; kendi sunucunuzu yönetiyorsanız da mantık tam olarak budur.
Yaygın Sorunlar ve Pratik Çözüm Yolları#
Sahada tekrar tekrar karşılaşılan birkaç senaryo vardır; bunları tanıdığınızda teşhis dakikalar yerine saniyeler alır. Aşağıdaki tablo, "sanki dosya izniymiş gibi görünen ama aslında SELinux olan" durumların hızlı bir kontrol listesidir.
| Belirti | Muhtemel neden | Çözüm |
|---|---|---|
| Web sitesi 403 veriyor, izinler doğru | Yanlış dosya bağlamı | restorecon -Rv /var/www |
| Servis standart dışı portta başlamıyor | Port türü tanımsız | semanage port -a -t ... -p tcp PORT |
| Uygulama uzak DB'ye bağlanamıyor | Ağ boolean'ı kapalı | setsebool -P httpd_can_network_connect_db on |
| Yükleme dizinine yazılamıyor | Salt okunur içerik türü | httpd_sys_rw_content_t ata + restorecon |
| Nedeni belirsiz "Permission denied" | Bilinmeyen AVC ihlali | ausearch -m avc -ts recent |
Genel iş akışı olarak şu sırayı öneririm. Önce sorunun gerçekten SELinux olup olmadığını doğrulayın: geçici olarak setenforce 0 yapın; sorun kaybolduysa suçlu SELinux'tur, geri setenforce 1 yapın ve gerçek çözüme geçin. Kapatıp bırakmak değil, teşhis için bir an açmak — fark budur. Sonra ausearch veya sealert ile ihlali okuyun. Ardından kararınızı verin: dosya yanlış yerde/etikette ise restorecon veya semanage fcontext, meşru bir yetenek eksikse uygun boolean, port sorunuysa semanage port, ve yalnızca hiçbiri uymuyorsa audit2allow ile özel modül.
Şu üç alışkanlık sizi vakaların büyük kısmında kurtarır: değişiklikleri her zaman -P veya semanage ile kalıcı yapın, chcon yerine kalıcı kural yazmayı tercih edin ve audit2allow çıktısını uygulamadan önce mutlaka okuyun. Web sitenizi yeni bir sunucuya taşırken bağlamların kaybolması çok yaygındır; site taşıma sırasında ilk kontrol edeceğiniz şey ls -Z çıktısı olmalıdır. Doğru yönetilen bir SELinux, yönetilen sunucu altyapısının görünmeyen ama en değerli katmanlarından biridir.
Sıkça Sorulan Sorular#
SELinux'u tamamen kapatmak neden kötü bir fikir?#
SELinux'u kapatmak kısa vadede sorunu çözer gibi görünse de, sunucunuzu bir saldırı gerçekleştiğinde hasarı sınırlayacak en güçlü katmandan mahrum bırakır. Bir web açığı üzerinden içeri giren saldırgan, SELinux enforcing modda çalışırken yalnızca web servisinin izinli olduğu kaynaklara ulaşabilir; kapalıyken ise tüm sistemde serbestçe hareket eder. Ayrıca disabled moddan geri dönmek tüm dosya sistemini yeniden etiketlemeyi gerektirdiği için pratikte zahmetli ve risklidir. Kapatmak yerine Permissive'de teşhis edip Enforcing'e dönmek her zaman daha doğrudur.
getenforce ile sestatus arasındaki fark nedir?#
getenforce yalnızca aktif çalışma modunu tek kelimeyle söyler: Enforcing, Permissive veya Disabled. sestatus ise çok daha kapsamlı bir tablo verir; mevcut modun yanı sıra /etc/selinux/config dosyasındaki kalıcı ayarı, yüklü politika türünü (genellikle targeted), politika sürümünü ve bağlama noktasını gösterir. Hızlı bir kontrol için getenforce, tam durum incelemesi için sestatus kullanırsınız. İkisini birlikte kullanmak, çalışma zamanı modunuzla önyükleme ayarınızın uyumlu olup olmadığını görmenizi sağlar.
chcon ile semanage fcontext arasındaki fark hangisi kalıcı?#
chcon bir dosyanın bağlamını anında ama geçici olarak değiştirir; sistem yeniden etiketlendiğinde veya o yola restorecon çalıştığında değişiklik kaybolur. semanage fcontext ise değişikliği kalıcı politika veritabanına yazar, dolayısıyla kalıcıdır. Doğru iş akışı önce semanage fcontext -a ile kuralı tanımlamak, ardından restorecon ile bu kuralı fiilen dosyalara uygulamaktır. Kısacası kalıcı çözüm için daima semanage fcontext kullanın; chcon'u yalnızca hızlı bir test için tutun.
audit2allow çıktısını doğrudan uygulamak güvenli mi?#
Hayır, körlemesine uygulamak risklidir. audit2allow, loglardaki her ihlale izin verecek bir kural üretir; ancak bu ihlallerden bazıları gerçek bir yanlış yapılandırmanın veya saldırı girişiminin işareti olabilir. Üretilen .te kaynağını uygulamadan önce mutlaka okuyun. Eğer önerilen kural bir servise çok geniş bir erişim veriyorsa, gerçek sorun genellikle dosyanın yanlış etiketlenmiş olmasıdır ve doğru çözüm izin eklemek değil restorecon ile bağlamı düzeltmektir. audit2allow'u ancak erişimin meşru olduğundan emin olduğunuzda kullanın.
SELinux ile güvenlik duvarı aynı işi mi yapar?#
Hayır, birbirini tamamlayan iki farklı katmandır. Güvenlik duvarı (firewalld veya UFW) ağ trafiğini yönetir; hangi portların dışarıya açık olduğuna karar verir. SELinux ise sistem içindeki süreçlerin hangi dosyalara, portlara ve kaynaklara erişebileceğini kontrol eder. Örneğin bir servisi 8443 portunda çalıştırmak için hem güvenlik duvarında bu portu açmanız hem de semanage port ile SELinux'a tanıtmanız gerekir. İkisi birlikte savunma derinliği oluşturur; birini diğerinin yerine koyamazsınız.
Web sitem taşındıktan sonra çalışmıyor, SELinux mu suçlu?#
Büyük olasılıkla evet, özellikle içeriği standart /var/www/html dışındaki bir dizine taşıdıysanız. Dosyaları kopyalarken orijinal SELinux bağlamları çoğunlukla korunmaz ve yeni dizin httpd_t sürecinin okuyamayacağı bir türle etiketlenir. Önce ls -Z ile bağlamı kontrol edin. Standart bir yoldaysa restorecon -Rv /var/www/html çoğu zaman yeter; standart dışı bir yoldaysa semanage fcontext ile kalıcı kural ekleyip ardından restorecon çalıştırın. Doğrulamak için geçici setenforce 0 yapıp sorunun kaybolup kaybolmadığına bakmak, teşhisi hızlandırır.
Kapanış#
SELinux, ilk karşılaşmada engel gibi görünen ama zamanla en güvenilir müttefikiniz haline gelen bir savunma katmanıdır. Anahtar, onu kapatmak değil anlamak: modları tanımak, bağlam mantığını kavramak, ihlalleri ausearch ile okumak ve semanage ile kalıcı kurallar yazmak. Bu adımları alışkanlık haline getirdiğinizde, "Permission denied" hataları korkutucu birer gizem olmaktan çıkıp beş dakikada çözülen rutin işlere dönüşür. Unutmayın: iyi yönetilen bir SELinux, bir gün başınıza gelebilecek bir sıfırıncı gün açığında sunucunuzu ayakta tutan şey olabilir.
Bu tür sertleştirme ayarlarıyla uğraşmak istemiyorsanız Clou.TR yanınızda. RHEL tabanlı VDS sunucu ve sanal sunucu paketlerimizde SELinux enforcing modda gelir; yönetilen sunucu hizmetimizle tüm politika ince ayarını biz üstlenebiliriz. WordPress ya da genel web projeleriniz için WordPress hosting ve web hosting paketlerimizde bu güvenlik katmanları zaten optimize edilmiş çalışır. Siz projenize odaklanın, altyapının sağlamlığını bize bırakın.