Linux'ta SELinux Engellerini Güvenle Aşmak: Kendi Politikanızı Yazın!
SELinux (Security-Enhanced Linux), Linux çekirdeği (kernel) için geliştirilmiş, sistem güvenliğini en üst düzeye çıkarmayı hedefleyen bir güvenlik mimarisidir. Geleneksel erişim kontrol mekanizmalarının yetersiz kaldığı durumlarda, sistem süreçleri ve dosyalar üzerinde çok daha hassas bir denetim sağlar.
1. SELinux Nedir ve Neden Gereklidir?
Standart Linux sistemlerinde DAC (Discretionary Access Control - İsteğe Bağlı Erişim Kontrolü) kullanılır. Bu sistemde dosya izinleri (rwxrwxrwx) dosya sahibine bağlıdır. Eğer bir uygulama (örneğin bir web sunucusu) root yetkisiyle çalışıyorsa ve saldırgan bu uygulamayı ele geçirirse, tüm sisteme erişim sağlayabilir.
SELinux ise MAC (Mandatory Access Control - Zorunlu Erişim Kontrolü) modelini uygular. Bu modelde, bir sürecin (process) ne yapabileceği sadece kullanıcı yetkilerine değil, merkezi bir güvenlik politikasına bağlıdır. Bir web sunucusu root yetkisine sahip olsa bile, SELinux politikası izin vermediği sürece /home dizinine erişemez.
2. Temel Kavramlar
SELinux'u anlamak için üç temel kavramı bilmek gerekir:
A. Context (Bağlam)
Her dosya, süreç ve kullanıcı bir "etikete" sahiptir. Bu etikete SELinux Context denir. Formatı şöyledir:
user:role:type:level
Type (Tip): En önemli kısımdır. Süreçlerin ve dosyaların birbirleriyle etkileşime girip giremeyeceğini belirler. Örneğin, bir web sunucusu süreci
httpd_ttipine, web dosyaları isehttpd_sys_content_ttipine sahiptir.
B. Policy (Politika)
Sistemdeki tüm kurallar kümesidir. "X tipi, Y tipine sahip dosyalara sadece okuma yetkisiyle erişebilir" gibi binlerce kural içerir.
C. Enforcement (Uygulama)
SELinux üç modda çalışabilir:
Enforcing: Güvenlik politikaları sıkı bir şekilde uygulanır ve ihlaller engellenir.
Permissive: İhlaller engellenmez ama "Audit" loglarına kaydedilir. Sorun giderme için kullanılır.
Disabled: SELinux tamamen kapalıdır.
3. SELinux Nasıl Çalışır?
Bir süreç bir dosyaya erişmek istediğinde, Linux çekirdeği önce DAC (standart izinler) kontrolünü yapar. Eğer bu izin verilirse, SELinux devreye girer. SELinux, sürecin context'i ile dosyanın context'ini karşılaştırır ve Access Vector Cache (AVC) adı verilen önbelleğe bakarak erişime izin verip vermeyeceğine karar verir.
4. Temel SELinux Komutları
Sisteminizi yönetirken en sık kullanacağınız komutlar şunlardır:
Durum Sorgulama:
Bash:sestatusMod Değiştirme (Anlık):
Bash:setenforce 0 # Permissive mod setenforce 1 # Enforcing modDosya Bağlamlarını Görme:
Bash:ls -Z /var/www/htmlBağlamı Yeniden Düzenleme (Restore):
Eğer bir dosyayı başka bir yerden taşıdıysanız ve etiketi yanlış kaldıysa:
Bashrestorecon -v /yol/dosya
5. Booleans: Politikaları Esnetmek
SELinux politikalarını tamamen kapatmak yerine, "Boolean" adı verilen anahtarlarla belirli izinleri açıp kapatabilirsiniz. Örneğin, web sunucusunun (Apache) ağ üzerinden veritabanına bağlanmasına izin vermek için:
setsebool -P httpd_can_network_connect_db on
6. Log Analizi ve Sorun Giderme
SELinux bir erişimi engellediğinde bu durum /var/log/audit/audit.log (veya Debian/Ubuntu tabanlı sistemlerde /var/log/syslog) dosyasına kaydedilir. Bu loglar karmaşık olabilir, bu yüzden sealert aracı kullanılır:
sealert -a /var/log/audit/audit.log
Bu komut, hatanın nedenini açıklar ve çözüm için size bir komut önerir.
Sonuç
SELinux, sistem yöneticileri için başlangıçta zorlayıcı bir öğrenme eğrisi sunsa da, modern siber güvenlik dünyasında vazgeçilmez bir kalkandır. Özellikle kamu kurumlarında ve yüksek güvenlik gerektiren sunucu altyapılarında (Pardus Server gibi yapılandırmalarda) aktif olarak kullanılması tavsiye edilir.
SELinux’un en güçlü ve esnek yanlarından biri olan "Politika Yazımı ve Booleans Yapılandırması" konusunu biraz daha teknik bir derinlikle ele alalım. Bir sistem yöneticisi veya geliştirici olarak, hazır kuralların dışına çıkmanız gerektiğinde bu adımlar hayat kurtarıcıdır.
SELinux Politika Yönetimi ve İnce Ayarlar
Varsayılan politikalar bazen özel yazdığınız bir betiği veya standart dışı bir dizini engelleyebilir. Bu durumda sistemi tamamen korumasız bırakmak yerine (yani SELinux'u kapatmak yerine) "iğne deliği" kadar bir izin açmak en güvenli yoldur.
1. SELinux Booleans (Mantıksal Anahtarlar)
Booleans, karmaşık politika kodları yazmadan, sistemdeki mevcut kuralları anında değiştirmenizi sağlar.
Tüm Boolean listesini görmek için:
getsebool -aBelirli bir servisle ilgili ayarları filtrelemek için:
getsebool -a | grep httpdBir izni kalıcı olarak aktif etmek için:
setsebool -P httpd_enable_homedirs on(Bu komut, Apache'nin kullanıcı ana dizinlerine erişmesine izin verir).
2. Özel Politika Modülü Oluşturma (Denial to Policy)
Eğer bir uygulama engelleniyorsa ve bunun için hazır bir Boolean yoksa, kendi politika modülünüzü oluşturabilirsiniz. Bu süreç genellikle 4 adımdan oluşur:
Adım 1: Engellemeyi Yakalayın
Sistemi geçici olarak Permissive moda alın ki uygulama çalışsın ve tüm engelleme logları oluşsun:
setenforce 0
Adım 2: Logları Analiz Edin
audit.log içindeki karmaşık veriyi anlamlı bir politika taslağına dönüştüren audit2allow aracını kullanın:
grep "denied" /var/log/audit/audit.log | audit2allow -m ozel_iznim > ozel_iznim.te
.te (Type Enforcement) dosyası, insan tarafından okunabilir kuralları içerir.
Adım 3: Politika Paketini Derleyin
Bu taslağı sistemin anlayacağı bir modül haline getirin:
checkmodule -M -m -o ozel_iznim.mod ozel_iznim.te
semodule_package -o ozel_iznim.pp -m ozel_iznim.mod
Adım 4: Modülü Sisteme Yükleyin
semodule -i ozel_iznim.pp
setenforce 1 # Sistemi tekrar koruma moduna alın
3. Dosya ve Port Etiketleme (Labeling)
SELinux bazen sadece dosyanın yanlış "etiketlenmiş" olması nedeniyle erişimi engeller.
Standart dışı bir portu (örneğin 8080) Web servisine tanıtmak:
Normalde Apache sadece belirli portlarda çalışabilir. 8080'i eklemek için:
Bash:semanage port -a -t http_port_t -p tcp 8080Bir dizini kalıcı olarak etiketlemek:
/data/webdiye bir dizin açtınız ve Apache'nin burayı okumasını istiyorsunuz:Bash:semanage fcontext -a -t httpd_sys_content_t "/data/web(/.*)?" restorecon -R -v /data/web
Pratik Bir Senaryo: Pardus Server ve Dosya Paylaşımı
Örneğin, Linux üzerinde bir Samba sunucusu kurdunuz. Kullanıcılar dosya yükleyemiyorsa, önce loglara bakılır:
type=AVC msg=audit(...): avc: denied { write } for pid=... comm="smbd" name="paylasim"
Burada yapılacak en doğru hareket, ilgili klasöre Samba'nın yazabileceği etiketi vermektir:
chcon -t samba_share_t /srv/samba/paylasim
Özet: Hangi Durumda Ne Yapılmalı?
| Sorun | Çözüm Yolu |
| Standart bir servis özelliği çalışmıyor | Boolean kontrol et. |
| Dosya/Dizin erişimi engelleniyor | Context (Label) kontrol et veya restorecon kullan. |
| Servis standart dışı bir portta çalışacak | semanage port ile izin ekle. |
| Çok özel bir hata var ve hiçbir yere uymuyor | audit2allow ile özel modül yaz. |
Diyelim ki; bir Python betiği yazdınız ve bu betik okul ağındaki bir sunucuya veri gönderiyor ya da özel bir dizine log yazıyor. Ancak SELinux bunu "şüpheli bir hareket" olarak görüp engelliyor.
İşte adım adım Debug ve Çözüm süreci:
1. Adım: Sorunun SELinux Kaynaklı Olduğunu Doğrulamak
Önce suçlunun gerçekten SELinux olup olmadığını anlamalıyız. Uygulamanız hata verdiğinde şu komutu çalıştırın:
setenforce 0
Bu komutla SELinux'u Permissive (İzleme) moduna aldınız. Eğer uygulamanız şu an sorunsuz çalışıyorsa, sorun %100 SELinux politikalarıdır.
Not: Testten sonra setenforce 1 ile tekrar aktif etmeyi unutmayın.
2. Adım: Logları İzlemek (Canlı Takip)
Hatanın nedenini anlık olarak görmek için terminalde şu komutu açık bırakın ve uygulamanızı tekrar çalıştırın:
tail -f /var/log/audit/audit.log | audit2why
audit2why, karmaşık log satırlarını okur ve size şunu söyler:
"Sizin Python betiğiniz (python_t), şu dosyaya (user_home_t) yazmaya çalıştı ama izin verilmedi. Şunu yaparsanız düzelebilir: ..."
3. Adım: Senaryo Üzerinden Çözüm (Python Backend Örneği)
Diyelim ki Python uygulamanız /var/www/html/data klasörüne bir SQLite veritabanı yazmak istiyor.
Hata Mesajı (AVC Denial):
type=AVC msg=audit(...): avc: denied { write } for pid=1234 comm="python3" name="data" dev="sda1" ino=5678 scontext=system_u:system_r:httpd_sys_script_t tcontext=unconfined_u:object_r:httpd_sys_content_t tclass=dir
Analiz:
scontext (Kaynak):
httpd_sys_script_t(Betik modu)tcontext (Hedef):
httpd_sys_content_t(Sadece okunabilir içerik modu)İşlem:
write(Yazma engellendi)
Çözüm:
Hedef dizinin etiketini "yazılabilir" bir etiketle değiştirmeliyiz:
semanage fcontext -a -t httpd_sys_script_rw_content_t "/var/www/html/data(/.*)?"
restorecon -R -v /var/www/html/data
4. Adım: Otomatik Politika Üretimi (Zor Durumlar İçin)
Eğer etiketleme veya Boolean ayarları sorunu çözmüyorsa (örneğin uygulamanız çok spesifik bir sistem çağrısı yapıyorsa), SELinux'a bu hareketi "öğretmemiz" gerekir.
Hataları toplayın:
ausearch -m avc -ts recent > hatalar.txtÇözüm önerisine bakın:
audit2allow -a < hatalar.txtPolitikayı uygulayın:
audit2allow -a -M benim_ozel_modulumsemodule -i benim_ozel_modulum.pp
Özet İpucu
Geliştirme aşamasında Pardus üzerinde SELinux ile boğuşmamak için en iyi pratik şudur:
Dosyalarınızı
/homeyerine sistemin beklediği standart dizinlerde tutun (/var/www,/optvb.).Dosya taşırken
mv(move) yerinecp(copy) kullanmaya özen gösterin.mvkomutu eski SELinux etiketini korur ve yeni yerinde hataya sebep olur;cpise hedef dizinin etiketini otomatik alır.
Bu debug süreci, özellikle geliştirdiğiniz "Pardus Sınıf Asistanı" gibi sistem araçlarında, uygulamanızın güvenliğini zayıflatmadan çalışmasını sağlayacaktır.
"Pardus Sınıf Asistanı" veya benzeri bir Python/Tauri uygulamasının, sistem üzerinde kısıtlı bir kaynağa (örneğin USB aygıtlarını dinleme veya belirli bir sistem dosyasına erişme) ulaşmaya çalışırken engellendiğini varsayalım.
İşte bu durumu çözmek için özel bir SELinux politika modülü oluşturmanın en pratik yolu:
Senaryo: Uygulamanın Engellenmesi
Uygulamanız çalışıyor ancak log dosyasına baktığınızda Permission Denied alıyorsunuz ve sestatus komutu sistemin Enforcing modda olduğunu gösteriyor.
1. Adım: Hata Kaydını İzole Edin
Sistemdeki tüm karmaşık loglar arasından sadece uygulamanızla ilgili olanları çekmemiz gerekir. Uygulamanızın adının sinif-asistani olduğunu varsayalım:
# Son 10 dakika içindeki SELinux engellemelerini çek
ausearch -m avc -ts recent | grep "sinif-asistani" > uygulama_hatalari.txt
2. Adım: Politika Taslağını İnceleyin
audit2allow aracı, bu hataları okuyarak "Eğer şu izni verirsen sorun çözülür" diyerek bize bir kural dosyası (.te - Type Enforcement) hazırlar.
audit2allow -i uygulama_hatalari.txt -m sinif_asistani_politikasi > sinif_asistani_politikasi.te
Şimdi bu .te dosyasının içine cat ile bir bakalım. Şuna benzer bir içerik göreceksiniz:
module sinif_asistani_politikasi 1.0;
require {
type unconfined_t;
type sysfs_t;
class dir read;
}
#============= unconfined_t ==============
allow unconfined_t sysfs_t:dir read;
Bu çıktı şunu söyler: "unconfined_t" tipindeki uygulama, "sysfs_t" tipindeki klasörleri okuyabilsin.
3. Adım: Politikayı Derleyin ve Yükleyin
Bu metin dosyasını çekirdeğin (kernel) anlayacağı ikili (binary) formata dönüştürmemiz gerekiyor. Modern sistemlerde bunu tek komutla yapabiliriz:
# Politika paketini oluştur ve sisteme yükle
audit2allow -d -M sinif_asistani_politikasi
semodule -i sinif_asistani_politikasi.pp
4. Adım: Kontrol
Modülün başarıyla yüklendiğini doğrulamak için:
semodule -l | grep sinif_asistani
Artık uygulamanız, sadece sizin belirlediğiniz o özel izne sahip olacak ve sistemin geri kalanı hâlâ SELinux tarafından korunmaya devam edecektir.
Dikkat Edilmesi Gereken Önemli Nokta
Bu yöntem çok güçlüdür ancak **"en az yetki prensibi"**ne dikkat etmelisiniz. audit2allow bazen çok geniş izinler önerebilir. Eğer oluşturulan .te dosyasında capability dac_override (tüm dosya izinlerini bypass et) gibi çok kritik bir izin görüyorsanız, bu izni vermek yerine dosya etiketlerini (chcon veya semanage fcontext) değiştirmeyi tercih etmelisiniz.
SELinux engellemelerini analiz eden, kullanıcıya neyin engellendiğini gösteren ve onay verilirse otomatik olarak çözüm politikasını üreten bir Bash Script hazırlayalım.
SELinux Sorun Giderici (selinux_fixer.sh)
#!/bin/bash
# Renk tanımlamaları
RED='\033[0;31m'
GREEN='\033[0;32m'
NC='\033[0m' # Renk yok
echo -e "${GREEN}=== Pardus SELinux Sorun Giderici ===${NC}"
# Root kontrolü
if [ "$EUID" -ne 0 ]; then
echo -e "${RED}Lütfen bu betiği sudo ile çalıştırın.${NC}"
exit
fi
# Gerekli paketlerin kontrolü
for pkg in policycoreutils-python-utils audit; do
if ! command -v $pkg &> /dev/null; then
echo -e "${RED}$pkg paketi eksik. Kuruluyor...${NC}"
apt update && apt install -y $pkg
fi
done
echo "1) Son 10 dakika içindeki engellemeleri analiz et"
echo "2) Tüm audit loglarını tara"
echo "3) Çıkış"
read -p "Seçiminiz: " choice
case $choice in
1) TIMESPAN="recent" ;;
2) TIMESPAN="all" ;;
*) exit ;;
esac
# Hataları geçici dosyaya yaz
echo -e "\n${GREEN}Hatalar analiz ediliyor...${NC}"
if [ "$TIMESPAN" == "recent" ]; then
ausearch -m avc -ts recent > /tmp/selinux_errors.txt 2>/dev/null
else
ausearch -m avc > /tmp/selinux_errors.txt 2>/dev/null
fi
if [ ! -s /tmp/selinux_errors.txt ]; then
echo -e "${GREEN}Tebrikler! Herhangi bir SELinux engellemesi bulunamadı.${NC}"
exit
fi
# Önerilen politikayı göster
echo -e "${RED}Engellenen işlemler bulundu:${NC}"
audit2allow -i /tmp/selinux_errors.txt
echo -e "\n---"
read -p "Bu izinler için özel bir politika modülü oluşturulsun mu? (y/n): " confirm
if [ "$confirm" == "y" ]; then
read -p "Modül adı ne olsun? (ör: pardus_asistan): " modname
# Modülü oluştur ve yükle
audit2allow -a -M $modname < /tmp/selinux_errors.txt
semodule -i ${modname}.pp
echo -e "${GREEN}Başarılı! ${modname}.pp modülü sisteme yüklendi.${NC}"
echo "Artık uygulamanızın bu işlemleri yapmasına izin veriliyor."
# Temizlik
rm ${modname}.te ${modname}.pp
else
echo "İşlem iptal edildi."
fi
Bu Script Nasıl Kullanılır?
Dosyayı oluşturun:
nano selinux_fixer.shkomutuyla içeriği yapıştırın.Çalıştırma izni verin:
chmod +x selinux_fixer.shÇalıştırın:
sudo ./selinux_fixer.sh
Scriptin Avantajları
Otomasyon: Karmaşık
checkmodulevesemodule_packagekomutlarını senin yerine arka planda yapar.Analiz: Önce hatayı gösterir, onayını almadan sisteme kural eklemez.
Uyumu:
aptpaket yöneticisi kontrolü ile bağımlılıkları otomatik çözer.

Yorumlar