SELinux’a Giriş (CentOS 7 Üzerinde) – Bölüm 1: Temel Kavramlar
Linux tabanlı sistemlerde güvenlik, her zaman öncelikli bir konu olmuştur. Geleneksel güvenlik mekanizmaları çoğu senaryoda yeterli olsa da, modern tehdit ortamı, daha derinlemesine ve katı bir güvenlik katmanını zorunlu kılmaktadır. İşte bu noktada SELinux (Security-Enhanced Linux) devreye girer. CentOS 7 gibi kurumsal düzeydeki dağıtımlarda varsayılan olarak etkinleştirilmiş olan SELinux, işletim sisteminin güvenlik duruşunu önemli ölçüde artıran güçlü bir Zorunlu Erişim Kontrolü (Mandatory Access Control – MAC) mekanizmasıdır. Bu makale serisinin ilk bölümünde, SELinux’un temel kavramlarını, neden ihtiyaç duyulduğunu ve CentOS 7 ortamında nasıl çalıştığını ayrıntılı bir şekilde inceleyeceğiz.
Giriş: SELinux Nedir ve Neden Önemlidir?
SELinux, Amerika Birleşik Devletleri Ulusal Güvenlik Ajansı (NSA) tarafından geliştirilen ve Linux çekirdeğine entegre edilmiş bir güvenlik modülüdür. Amacı, sistem kaynaklarına (dosyalar, dizinler, süreçler, ağ portları vb.) erişimi kontrol etmek için geleneksel Linux izinlerinden (Discretionary Access Control – DAC) daha katı ve ayrıntılı bir mekanizma sağlamaktır. Geleneksel izinler, bir kullanıcının veya grubun bir kaynağa erişip erişemeyeceğini belirlerken, SELinux çok daha granüler bir kontrol sunar ve sistem genelinde bir “varsayılan reddetme” (default deny) ilkesiyle çalışır. Yani, açıkça izin verilmediği sürece her türlü erişim engellenir.
Geleneksel Linux Güvenliğinin Sınırları
Linux’ta geleneksel olarak kullanılan DAC modeli, dosya sahipliği (owner), grup sahipliği (group) ve diğerleri (others) için okuma (read), yazma (write) ve çalıştırma (execute) izinlerine dayanır. Bu model, birçok durumda yeterli olsa da, bazı önemli sınırlamalara sahiptir:
* Root Ayrıcalıkları: root kullanıcısı, sistemdeki her şeyi yapabilir. Bir süreç root ayrıcalıklarıyla çalışıyorsa ve saldırıya uğrarsa, saldırgan tüm sisteme tam erişim kazanabilir. DAC, root kullanıcısının gücünü sınırlamakta yetersiz kalır.
* Süreç Sınırlamaları: Bir kullanıcı hesabının ele geçirilmesi durumunda, o kullanıcı tarafından başlatılan tüm süreçler, kullanıcının sahip olduğu tüm izinleri miras alır. Bu, bir web sunucusunun güvenlik açığı nedeniyle ele geçirilmesi durumunda, web sunucusu sürecinin, web sunucusu kullanıcısının erişebildiği tüm dosyalara erişebileceği anlamına gelir. Bu, saldırganın sistemde daha geniş bir etki alanı elde etmesine olanak tanır.
* Yetki Yükseltme (Privilege Escalation): Bir güvenlik açığı bulunan uygulama, normalde erişmemesi gereken bir kaynağa erişmek için kullanılabilir ve bu da yetki yükseltme saldırılarına yol açabilir.
* Tip Güvenliği Eksikliği: DAC, bir dosyanın içeriği veya bir sürecin amacı hakkında bilgi sahibi değildir. Sadece kimin neye erişebileceğine bakar.
SELinux, bu sınırlamaları aşmak için tasarlanmıştır. Bir MAC sistemi olarak, erişim kararlarını sadece kullanıcı kimliklerine değil, aynı zamanda kaynakların ve süreçlerin “güvenlik bağlamlarına” (security contexts) ve merkezi bir politikaya göre verir.
Kısa Tarihçe ve Kökeni
SELinux projesi, 1990’ların sonlarında NSA tarafından geliştirilmeye başlandı ve 2000’li yılların başlarında Linux çekirdeğine entegre edildi. Amacı, yüksek güvenlik gerektiren sistemler için daha esnek ve güçlü bir güvenlik altyapısı sağlamaktı. CentOS ve Red Hat Enterprise Linux (RHEL) gibi kurumsal dağıtımlar, SELinux’u varsayılan olarak etkinleştirerek, sistem güvenliğini standart hale getirmiştir.
SELinux’un Temel Çalışma Prensibi
SELinux’un çalışma mantığı, geleneksel Linux izinlerinden kökten farklıdır. Bu farkı anlamak, SELinux’u yönetmenin ve sorun gidermenin anahtarıdır.
Her Şey Etiketlidir (Everything is Labeled)
SELinux’un en temel prensibi, sistemdeki her şeyin – dosyalar, dizinler, süreçler, ağ portları, aygıtlar, soketler – bir “güvenlik bağlamı” (security context) ile etiketlenmesidir. Bu bağlamlar, SELinux’un bir kaynağın ne olduğunu ve ne tür bir erişime izin verilmesi gerektiğini belirlemesini sağlar.
Bir güvenlik bağlamı genellikle dört bölümden oluşur: user:role:type:level.
Örneğin: system_u:object_r:httpd_sys_content_t:s0
* user (Kullanıcı): SELinux kullanıcısını temsil eder. Bu, Linux kullanıcı hesabıyla karıştırılmamalıdır. Genellikle unconfined_u (kısıtlanmamış kullanıcı) veya system_u (sistem kullanıcısı) gibi değerler alır.
* role (Rol): Bir SELinux kullanıcısının sistemde üstlenebileceği rolü belirtir. object_r (nesne rolü) dosyalar için, system_r (sistem rolü) ise süreçler için yaygın olarak kullanılır.
* type (Tip): Bu, SELinux’un erişim kararlarını verirken kullandığı en önemli kısımdır. Süreçler için “domain” (alan), dosyalar ve diğer nesneler için “type” (tip) olarak adlandırılır. Örneğin, bir web sunucusu süreci httpd_t alanına sahipken, web sayfaları httpd_sys_content_t tipine sahip olabilir.
* level (Seviye): Çoğunlukla Çok Seviyeli Güvenlik (MLS – Multi-Level Security) veya Çok Kategorili Güvenlik (MCS – Multi-Category Security) için kullanılır. Çoğu CentOS 7 kurulumunda, özellikle MCS etkin değilse, bu kısım s0 (System Low) olarak görünür. Daha karmaşık güvenlik gereksinimleri olan ortamlarda, s0:c0.c1023 gibi bir format alabilir.
SELinux, bir süreç (kaynak A) başka bir kaynağa (kaynak B) erişmek istediğinde, bu iki kaynağın güvenlik bağlamlarını karşılaştırır. Özellikle type alanı, erişim kararında kritik rol oynar.
Politika Uygulaması (Policy Enforcement)
SELinux, tüm erişim kararlarını, sistemde yüklü olan bir “politika” (policy) dosyasına göre verir. Politika, hangi type‘ın hangi type‘a hangi tür erişime (okuma, yazma, çalıştırma vb.) sahip olabileceğini tanımlayan bir dizi kuraldan oluşur.
CentOS 7’de varsayılan olarak “Targeted” politika kullanılır. Bu politika, belirli ağ hizmetlerini ve sistem süreçlerini kısıtlar ancak diğer kullanıcı süreçlerini genellikle kısıtlamaz. Amacı, sistemin saldırıya açık yüzeyini azaltmaktır.
Varsayılan Reddetme (Default Deny)
SELinux’un temel güvenlik felsefesi “varsayılan reddetme” ilkesine dayanır. Bu, açıkça izin verilmediği sürece her türlü erişimin engelleneceği anlamına gelir. Eğer politika dosyası, belirli bir süreç type‘ının belirli bir dosya type‘ına erişmesine izin veren bir kural içermiyorsa, bu erişim otomatik olarak reddedilir. Bu, geleneksel DAC’ın “varsayılan izin verme” yaklaşımının tam tersidir (bir izin reddedilmediği sürece genellikle izin verilir).
Bu prensip, sistemin bilinmeyen veya yeni tehditlere karşı daha dirençli olmasını sağlar. Bir uygulamanın güvenlik açığı nedeniyle ele geçirilmesi durumunda bile, SELinux politikası, uygulamanın normalde yapmaması gereken eylemleri gerçekleştirmesini engelleyerek zararı sınırlar.
SELinux’un Temel Bileşenleri
SELinux’u anlamak ve yönetmek için, onun temel bileşenlerini ve bu bileşenlerin nasıl etkileşimde bulunduğunu bilmek önemlidir.
Güvenlik Bağlamları (Security Contexts)
Daha önce bahsettiğimiz gibi, güvenlik bağlamları SELinux’un temel yapı taşıdır. Her dosya, dizin, süreç ve hatta ağ portu bir güvenlik bağlamına sahiptir.
* Dosya Bağlamları: ls -Z komutu ile dosyaların ve dizinlerin güvenlik bağlamlarını görebilirsiniz:
ls -Z /var/www/html/index.html
# Output: -rw-r--r--. root root system_u:object_r:httpd_sys_content_t:s0 /var/www/html/index.html
Burada httpd_sys_content_t tipi, bu dosyanın bir web sunucusu içeriği olduğunu belirtir. SELinux, httpd_t alanına sahip bir web sunucusu sürecinin bu tipteki dosyalara okuma erişimi olmasına izin verir.
* Süreç Bağlamları: ps -Z komutu ile çalışan süreçlerin güvenlik bağlamlarını görebilirsiniz:
ps -Zef | grep httpd
# Output: system_u:system_r:httpd_t:s0 root 1234 ... /usr/sbin/httpd -DFOREGROUND
Burada httpd_t tipi, bu sürecin bir Apache web sunucusu süreci olduğunu belirtir. Bu, SELinux’un bu sürece web sunucusuyla ilgili izinleri vermesini sağlar.
* Kullanıcı Bağlamları: id -Z komutu ile mevcut kullanıcının SELinux bağlamını görebilirsiniz:
id -Z
# Output: unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
unconfined_t tipi, bu kullanıcının kısıtlanmamış olduğunu, yani SELinux politikası tarafından özel olarak hedeflenen hizmetler dışındaki çoğu şeye erişebileceğini gösterir. Bu, tipik bir son kullanıcı için varsayılan ve daha az kısıtlayıcı bir bağlamdır.
Güvenlik bağlamları, SELinux’un kimin neye erişebileceğine dair kararlar vermesi için gerekli bilgiyi sağlar. Yanlış bir bağlama sahip bir dosya veya süreç, SELinux tarafından engellenir ve beklenmedik sorunlara yol açabilir.
Politikalar (Policies)
Politika, SELinux’un davranışını tanımlayan kurallar bütünüdür. CentOS 7’de genellikle “targeted” politika kullanılır. Bu politika, sistemdeki belirli hizmetleri (örneğin Apache, Nginx, FTP sunucuları) kısıtlamak için tasarlanmıştır.
Politika, çekirdek tarafından yüklenir ve tüm erişim kararları bu politika tarafından belirlenir. Politikayı doğrudan düzenlemek yerine, SELinux yöneticileri genellikle “boole değerleri” (booleans) veya semanage gibi araçlarla politikayı uyarlarlar.
Modlar (Modes)
SELinux, üç ana modda çalışabilir:
1. Enforcing (Zorlayıcı): Bu modda, SELinux politikası tamamen uygulanır. Herhangi bir erişim reddedilirse, bu işlem engellenir ve bir denetim günlüğü (audit log) kaydı oluşturulur. Bu, SELinux’un en güvenli çalışma modudur.
2. Permissive (İzin Verici): Bu modda, SELinux politikası hala etkindir ve ihlalleri denetim günlüklerine kaydeder, ancak erişimi engellemez. Bu mod, SELinux sorunlarını gidermek veya yeni bir politikayı test etmek için çok kullanışlıdır. Bir uygulamanın neden çalışmadığını anlamak için, permissive moda alıp günlükleri kontrol edebilirsiniz.
3. Disabled (Devre Dışı): Bu modda, SELinux tamamen kapatılır ve hiçbir güvenlik kontrolü veya denetim kaydı yapılmaz. Bu, en az güvenli moddur ve genellikle sadece SELinux’un sistemde bir sorun yaratıp yaratmadığını kesin olarak belirlemek için geçici olarak kullanılır. SELinux’u tamamen devre dışı bırakmak, sistemin güvenlik duruşunu önemli ölçüde zayıflatır ve genellikle önerilmez.
Mevcut Modu Kontrol Etme:
* sestatus komutu, SELinux’un genel durumunu, modunu ve yüklü politikayı gösterir:
sestatus
# Output:
# SELinux status: enabled
# SELinuxfs mount: /sys/fs/selinux
# SELinux root directory: /etc/selinux
# Loaded policy name: targeted
# Current mode: enforcing
# Mode from config file: enforcing
# Policy MLS status: enabled
# Policy deny_unknown status: allowed
# Max kernel policy version: 31
* getenforce komutu sadece mevcut modu gösterir:
getenforce
# Output: Enforcing
Modu Geçici Olarak Değiştirme:
* setenforce 0: SELinux’u Permissive moda alır.
* setenforce 1: SELinux’u Enforcing moda alır.
Bu değişiklikler, sistem yeniden başlatılana kadar geçerlidir.
Modu Kalıcı Olarak Değiştirme:
Kalıcı değişiklikler için /etc/selinux/config dosyasını düzenlemeniz gerekir:
sudo vi /etc/selinux/config
Dosya içinde SELINUX= satırını bulun ve değerini enforcing, permissive veya disabled olarak değiştirin:
# This file controls the state of SELinux on the system.
SELINUX= can take one of these three values:
enforcing - SELinux security policy is enforced.
permissive - SELinux prints warnings instead of enforcing.
disabled - No SELinux policy is loaded.
SELINUX=enforcing
SELINUXTYPE= can take one of these two values:
targeted - Targeted processes are protected,
-- other processes are not.
mls - Multi Level Security protection.
SELINUXTYPE=targeted
Değişikliklerin etkili olması için sistemi yeniden başlatmanız gerekir. SELinux’u disabled moda alıp tekrar enforcing moda geçirmek, dosya sisteminin yeniden etiketlenmesini gerektirebilir ki bu da zaman alıcı bir işlemdir. Bu nedenle, disabled moddan kaçınmak ve sorun giderme için permissive modu kullanmak genellikle daha iyi bir yaklaşımdır.
Boole Değerleri (Booleans)
SELinux boole değerleri, belirli politika kurallarını dinamik olarak açıp kapatmanıza olanak tanıyan anahtarlardır. Bunlar, politikanın kendisini yeniden derlemeden veya yüklemeden SELinux’un davranışını özelleştirmenin esnek bir yolunu sunar. Örneğin, bir web sunucusunun ağ üzerinden bir veritabanına bağlanmasına izin vermek veya bir FTP sunucusunun kullanıcıların ana dizinlerine yazmasına izin vermek gibi özel durumlar için boole değerleri kullanılabilir.
* Mevcut Boole Değerlerini Görüntüleme: getsebool -a komutu tüm boole değerlerini ve mevcut durumlarını (on/off) listeler:
getsebool -a | grep httpd
# Output:
# httpd_anon_write --> off
# httpd_builtin_scripting --> on
# httpd_can_check_spam --> off
# ...
* Boole Değerini Geçici Olarak Değiştirme: setsebool on/off komutu ile boole değerlerini geçici olarak değiştirebilirsiniz:
sudo setsebool httpd_can_network_connect on
Bu değişiklik, sistem yeniden başlatılana kadar geçerlidir.
* Boole Değerini Kalıcı Olarak Değiştirme: setsebool -P on/off komutu ile değişiklikleri kalıcı hale getirebilirsiniz. -P (persistent) bayrağı, değişikliğin bir sonraki yeniden başlatmada da geçerli olmasını sağlar:
sudo setsebool -P httpd_can_network_connect on
Bu komut, değişiklikleri SELinux politikasının kalıcı yapılandırmasına yazar.
Boole değerleri, SELinux’u belirli uygulama gereksinimlerine göre ayarlarken büyük esneklik sağlar ve politikayı doğrudan değiştirmekten çok daha güvenli ve yönetilebilir bir yöntemdir.
SELinux ve Dosya Sistemleri
SELinux, dosya sistemi üzerindeki her dosya ve dizinin doğru güvenlik bağlamına sahip olmasını sağlamak için özel mekanizmalar kullanır. Bir dosya yanlış bir bağlama sahipse, SELinux politikası bu dosyaya erişimi engelleyebilir.
Dosya Bağlamlarının Önemi
Örneğin, Apache web sunucusunun varsayılan olarak /var/www/html dizinindeki dosyalara httpd_sys_content_t bağlamıyla erişmesine izin verilir. Eğer bu dizine başka bir yerden (örneğin /home/user/web_content) bir dosya kopyalarsanız, dosya orijinal dizinin bağlamını (örneğin user_home_t) miras alabilir. Web sunucusu httpd_t alanında çalışırken user_home_t tipine sahip bir dosyaya erişmeye çalıştığında, SELinux bunu engelleyecektir, çünkü politika buna izin vermez.
Bağlamları Geri Yükleme (Relabeling)
Yanlış bağlamlara sahip dosyaları düzeltmek için restorecon komutu kullanılır. Bu komut, dosya sistemindeki dosya ve dizinlerin bağlamlarını SELinux politikasında tanımlanan varsayılan değerlere geri yükler.
* Belirli Bir Dosya veya Dizin İçin Bağlamı Geri Yükleme:
sudo restorecon -v /var/www/html/index.html
# Output: restorecon reset /var/www/html/index.html context system_u:object_r:user_home_t:s0->system_u:object_r:httpd_sys_content_t:s0
-v bayrağı, yapılan değişiklikleri gösterir.
* Bir Dizin ve İçeriği İçin Bağlamı Geri Yükleme:
sudo restorecon -Rv /var/www/html
-R bayrağı, özyinelemeli (recursive) olarak tüm alt dizinleri ve dosyaları kapsar.
Sistem genelinde bir yeniden etiketleme (relabeling) gerektiğinde (örneğin, SELinux disabled moddan enforcing moda geçirildikten sonra), fixfiles komutu kullanılır. Bu genellikle sistemin yeniden başlatılması sırasında otomatik olarak tetiklenir:
sudo touch /.autorelabel
sudo reboot
Sistem yeniden başlatıldığında, SELinux tüm dosya sistemini tarayacak ve bağlamları düzeltecektir. Bu işlem, dosya sistemi boyutuna bağlı olarak biraz zaman alabilir.
SELinux Günlükleri (SELinux Logs)
SELinux, bir erişimi reddettiğinde veya bir politika ihlali tespit ettiğinde, bu olayı sistem günlüklerine kaydeder. Bu günlükler, SELinux sorunlarını gidermek ve politikayı anlamak için hayati öneme sahiptir.
* Denetim Günlükleri (Audit Logs): SELinux olaylarının çoğu, auditd hizmeti tarafından /var/log/audit/audit.log dosyasına kaydedilir. Bu günlükler, reddedilen erişim girişimleri (AVC denials), bağlam değişiklikleri ve diğer SELinux ile ilgili olaylar hakkında ayrıntılı bilgi içerir.
Bir AVC reddi genellikle denied { } ve scontext= ile tcontext= gibi anahtar kelimeler içerir.
* Sistem Günlükleri (System Logs): Bazı SELinux mesajları da /var/log/messages veya journalctl aracılığıyla görüntülenebilen genel sistem günlüklerine yazılabilir.
SELinux günlüklerini analiz etmek, bir uygulamanın neden SELinux tarafından engellendiğini anlamanın ilk adımıdır. ausearch ve audit2allow gibi araçlar, bu günlükleri sorgulamak ve analiz etmek için kullanılır. Bu araçların daha derinlemesine kullanımı, bu serinin sonraki bölümlerinde ele alınacaktır.
SELinux Yönetimi İçin Temel Komutlar
SELinux’u yönetmek için kullanılan bazı temel komutları daha önce ayrıntılı olarak ele aldık. İşte hızlı bir özet:
* sestatus: SELinux’un genel durumunu, modunu ve yüklü politikayı gösterir.
* getenforce: Mevcut SELinux modunu (Enforcing, Permissive, Disabled) gösterir.
* setenforce 0|1: SELinux modunu geçici olarak Permissive (0) veya Enforcing (1) olarak ayarlar.
* getsebool -a: Tüm SELinux boole değerlerini ve durumlarını listeler.
* setsebool [-P] on|off: Bir boole değerini geçici veya kalıcı olarak ayarlar.
* ls -Z: Dosya ve dizinlerin SELinux güvenlik bağlamlarını gösterir.
* ps -Z: Çalışan süreçlerin SELinux güvenlik bağlamlarını gösterir.
* id -Z: Mevcut kullanıcının SELinux güvenlik bağlamını gösterir.
* chcon: Bir dosyanın veya dizinin SELinux güvenlik bağlamını geçici olarak değiştirir. (Genellikle restorecon kullanılması tercih edilir.)
* restorecon [-Rv] : Bir dosya veya dizinin SELinux bağlamını politika tarafından tanımlanan varsayılan değerlere geri yükler.
* semanage: SELinux politikasına kalıcı değişiklikler yapmak için kullanılan güçlü bir araçtır. Örneğin, semanage fcontext ile özel dosya bağlamı kuralları tanımlanabilir veya semanage port ile ağ portlarının bağlamları ayarlanabilir. Bu komutun detayları genellikle daha ileri seviye konulara girer.
CentOS 7 ve SELinux Entegrasyonu
CentOS 7, SELinux’u varsayılan olarak “enforcing” modunda ve “targeted” politika ile etkinleştirilmiş olarak gelir. Bu, kutudan çıkar çıkmaz sisteminizin gelişmiş bir güvenlik katmanına sahip olduğu anlamına gelir. Kurulum sırasında veya sonrasında SELinux’u devre dışı bırakmak veya permissive moda almak mümkündür, ancak güvenlik açısından genellikle önerilmez.
CentOS 7’deki paket yöneticisi (yum/dnf), SELinux politikasıyla uyumlu olacak şekilde tasarlanmıştır. Yeni bir paket kurduğunuzda, ilgili dosyalar genellikle doğru SELinux bağlamlarıyla kurulur ve hizmetler doğru SELinux alanlarında çalışacak şekilde yapılandırılır. Ancak, özel uygulamalar veya elle yapılan yapılandırmalar SELinux ile uyumsuzluklara yol açabilir. Bu durumlarda, SELinux günlüklerini analiz etmek ve politikayı uygun boole değerleri veya özel kurallarla ayarlamak gerekir.
Sonuç
Bu makalenin ilk bölümünde, SELinux’un temel kavramlarını, neden geleneksel Linux güvenlik modellerine göre daha üstün olduğunu ve CentOS 7 ortamında nasıl çalıştığını ayrıntılı bir şekilde ele aldık. SELinux, sistemdeki her şeyin bir güvenlik bağlamıyla etiketlenmesi, varsayılan reddetme ilkesi ve politika tabanlı erişim kontrolü sayesinde Linux sistemlerine güçlü bir güvenlik katmanı ekler. Modlar (enforcing, permissive, disabled), boole değerleri ve dosya bağlamları gibi temel bileşenleri anlamak, SELinux’u etkin bir şekilde yönetmek için kritik öneme sahiptir.
SELinux’u anlamak ilk başta göz korkutucu görünebilir, ancak temel prensiplerini kavradığınızda ve doğru araçları kullanmayı öğrendiğinizde, sistemlerinizin güvenliğini önemli ölçüde artırabileceğinizi göreceksiniz. Bu serinin bir sonraki bölümünde, SELinux sorun giderme tekniklerine, denetim günlüklerini analiz etmeye ve daha ileri düzey yönetim komutlarına odaklanacağız. SELinux’un karmaşıklığına rağmen, sunduğu güvenlik avantajları, öğrenmeye ve uygulamaya değer kılar.
