分类: LINUX
2008-06-24 10:10:45
SELinux(全名 Security-Enhanced Linux)其主要用意在於加強 Linux 主機安全性,尤其是應用在 Linux 作為各類型伺服器時,限制各類型 daemon(也就是服務)只能夠存取她自己該存取的檔案,遇到服務欲存取她不應存取的檔案與目錄時,此時 SELinux 就會阻擋住這些存取動作,這也就是開啟 SELinux 功能會保護 Linux Server 安全,就算是遇到程式安全性漏洞導致站台被攻擊時,所造成的損傷能夠降低許多的主因。
通常將系統調整的越安全,使用上就會越容易感受到不方便;當 SELinux 開啟就經常遇到 SELinux 把某些我們在 Linux 常用動作『卡住』,雖然可以將 SELinux 關閉來解決這類情況,但卻辜負 SELinux 保護我們主機的一番美意,較建議的方式是學習 SELinux 觀念並實際調整 SELinux 相關設定,這樣子 Linux Server 才會更加地安全。
我們這次也是從預設方式安裝 RHEL5 完成後開始吧!用此方法裝好的 RHEL5 會開啟 SELinux 功能來保護 Linux 主機,我們可以使用「sestatus」指令來觀察 SELinux 運作狀態(status)如下圖。
指令執行後顯示 SELinux status(SELinux 狀態)是 enabled(啟用)且 Current mode(正在運作模式)是 enforcing(強制執行中)也就是此時 SELinux 是來真的!是會真正地擋住有可能危害主機安全的操作。
上述提到 SELinux 狀態大致上有兩種,分別是 enabled(啟用)與 disabled(停用)這感覺像是 SELinux 的一個『總開關』,這個總開關的設定檔案位於「/etc/selinux/config」由此檔案的上半部(及其註解)不難發現「啟用」中還細分兩個:一個是真正會阻擋的「enforcing」與僅顯示警告訊息不阻擋的「permissive」。
enabled(啟用) | disabled(停用) | |
enforcing | permissive | disabled |
啟用會阻擋 | 啟用不阻擋 顯示警告訊息 |
停用 SELinux 功能 |
關於總開關的控制方法,直覺方式可以直接編輯設定檔案「/etc/selinux/config」將『SELINUX=enforcing』那一行變更並重新開機即可。若是要使用選單(menu)工具或是圖形工具設定的話也可以(改完同樣要重新開機使其生效)。
直接編輯文字檔案 | 檔名 /etc/selinux/config 檔案內容 SELINUX=... 此行 |
選單模式(menu) | system-config-securitylevel |
圖型模式(GUI) | system-config-securitylevel system-config-selinux |
system-config-securitylevel 選單模式設定畫面
system-config-securitylevel 圖形模式設定畫面
system-config-selinux 圖形模式設定畫面
還有一種關閉 SELinux 功能的方法是從 kernel 下手,此法是設定載入 kernel 時下給 kernel 參數「selinux=0」即可關閉 SELinux 功能,此時就算是 /etc/selinux/config 設定 SELinux enforcing 也是無法啟用 SELinux 功能。若以 GRUB 開機程式來說會是設定在 /boot/grub/menu.lst 檔案內 kernel 那一行(下圖為範例)
SELinux 是以 linux 檔案系統權限為基礎,再加上 security context 來加強權限安全管理,我們可以用 ls 搭配 -Z 選項來觀察檔案的 security context;指令 ps 搭配 -Z 選項來觀察行程的 security context。
Linux 執行許多 daemon 像是 httpd、ftpd、smbd、nfsd…這些都是行程(process),SELinux 主要是利用檔案以及行程的 security context 來判斷以及限制行程是否有權利存取相關檔案與目錄,限制行程存取檔案的同時也就限制 daemon 所能存取的檔案或目錄,達到使 Linux 系統更加安全的主要目的。
假設遇到 SELinux 擋住了我們想要存取的資料時,直覺的方式是將 security context 調成正確使行程能夠存取檔案即可,用到的指令有二個:一個是將檔案『回存』成 SELinux 預設 context 的「restorecon」指令,另一個是『改變』檔案 context 的「chcon」指令,這兩個指令較詳細的使用方法會在後續範例中介紹。
先前已介紹過 SELinux 總開關的設定檔案以及設定方式與指令,接下來介紹的是在 SELinux 總開關開啟的狀態下才會有作用的 SELinux 小開關,這一系列的小開關是 SELinux 針對應用程式(尤其是 daemon)所設計出來的「布林值」,顯示及設定這方面資訊的指令恰好就與「布林」(boolean)有關,分別是觀看一系列布林值的「getsebool」與設定修改布林值的「setsebool」,另外圖形也可以設定 SELinux 布林值介面是在「system-config-selinux」程式畫面的左邊【Boolean】選單內。
指令「getsebool -a」的畫面。
這個指令主要是用來『暫時』將當下運作的狀態(Current mode)由 enforcing 模式切換至 permissive 若是遇到短時間不想啟用 SELinux 時,這個功能會是蠻好用的。使用指令「setenforce 0」(關閉 enforcing)「setenforce 1」(開啟 enforcing),可由「sestatus」指令來觀察現在的狀態。
當 SELinux 有拒絕(deny)到某些檔案目錄被存取時,通知方式會在桌面的右上角有顆『金星』,點『金星』進去看就會有詳細說明,這是圖形模式情況下的通知情況,倘若是以遠端文字模式來管理伺服器的話,因為沒有圖形來顯示金星,此時就需要去檢視系統紀錄才會比較清楚來龍去脈,通常在 /var/log/messages 最底下會有最新的 SELinux log 資訊,用 tail 指令來檢視此檔案還蠻方便的。
附帶一提的 /etc/init.d/auditd 這個 init scripts 啟動的 auditd 寫入 /var/log/audit/audit.log 紀錄檔,也有部份的 SELinux 相關訊息;/etc/init.d/setroubleshoot 這個 SELinux trouble shoot daemon 的啟停 scripts 就是出現『金星』效果的主因。
在幾年前架設 Linux 各類 Server 時,大概只需要注意 firewall 有沒有擋住要開啟的服務就足夠了,近年來因為越來越注重安全,所以當 SELinux 開啟時,在架設各類伺服器時就可能會發生存取失敗的現象,接下來就以幾個常見的狀況作為範例,來介紹如何設定及調校 SELinux。
說到檔案存取遭到 SELinux 限制,首當其衝的 daemon 就是專司檔案上傳與下載的 ftpd。以 RHEL5 來做示範的話,就是介紹安裝 vsftpd 以及關於 SELinux 設定,在 yum 設定成功正確的情況下(請參考筆者介紹 yum Client/Server 相關設定文件),安裝、重新啟動、設定開機自動啟動 vsftpd 相信大家都不陌生,指令簡介如下:
「yum install vsftpd」安裝 vsftpd
「/etc/init.d/vsftpd restart」重新啟動 vsftpd
「chkconfig vsftpd on」設定下次開機自動啟動 vsftpd
RHEL5 預設值 ftp 匿名存取是開放的,除此之外使用 Unix 帳號/密碼 ftp 登入也是開放的(但是帳號密碼登入方式會被 SELinux 擋住),我們先測試匿名下載有關 SELinux 設定的部份(修改 security context 來解決),再來測試 Unix 帳號/密碼 ftp 登入有關 SELinux 設定的部份(調整 SELinux 布林值來解決)。
對於 SELinux 來說,該存取的檔案被存取,不該被存取的檔案應該要擋住,所以匿名下載的資料目錄,資料若是直接在那個目錄下產生的話,算是該被存取的可以被正常存取,至於先在別地方(例如:使用者家目錄或 /tmp 目錄)產生的檔案或目錄,之後再搬過去的話,就應該會被阻擋住存取。
測試的部份是先「直接產生」在匿名存取目錄(也就是 ftp 帳號的家目錄)下,例如檔名 foo.txt,則可正常 ftp 存取不會被 SELinux 擋住;接著測試先在 root 的家目錄產生 foo2.txt 之後再搬至 ftp 的家目錄,後來 ftp 過來存取時,則會因為 SELinux 安全性(security context)規則而阻擋。
圖內的指令解說如下:
指令「echo test > /var/ftp/foo.txt」直接產生檔案 foo.txt(內文 test)在 ftp 家目錄 /var/ftp 下
指令「lftp localhost」文字模式 ftp 到自己這台電腦當成客戶端,測試存取 foo.txt 正常。
指令「echo test > foo2.txt」接產生檔案 foo2.txt(內文 test)在 /root 家目錄下
指令「mv foo2.txt /var/ftp」將檔案 foo2.txt 搬到 /var/ftp 下
再度使用指令「lftp localhost」這次只會看到原來的 foo.txt 看不到後來的 foo2.txt(因為 SELinux 擋住了。
這次 SELinux 阻擋存取主要是 security context 不正確所造成,由「ls -Z /var/ftp」看出 foo2.txt 與 foo.txt(以及 pub 目錄)的 security context 不同(user_home_t 那一行),解決方法是使用指令「restorecon -r /var/ftp」將 /var/ftp 目錄下的資料統統回存成預設的 security context 即可。
接下來測試的是 Unix 帳號用 ftp 方式登入傳輸資料,建立一個測試帳號 foo 密碼順便設定一下(或是清空也可以),接著用「lftp -u foo localhost」指令來測試 ftp 登入,發現會登入失敗 OOPS 而無法切換至使用者家目錄。
趕緊觀察 /var/log/messages 檔案的末段,會發現 SELinux 之 setroubleshoot 記載的訊息,提到可以用「sealert -l d25aea20-7088-4db1-9505-8f6dbdbe366f」指令來觀看完整紀錄。
執行上述 sealert 指令後,顯示內容相當豐富,特別注意「setsebool -P ftp_home_dir=1」那一行,意思是說請開啟 SELinux 布林值『ftp_home_dir』並設定下次開機此值生效(-P 選項)。
下圖為設定「setsebool -P ftp_home_dir=1」先前與之後使用帳號 foo 來 ftp 登入的存取情況。
接下來介紹 httpd 最常遇到的 SELinux 限制。與 ftpd 匿名存取的情況相當類似;直接在 DocumentRoot 下(RHEL5 預設值 /var/www/html)建立網頁文件不會被阻擋住,若是先行在個人的家目錄建立(或是在 /tmp 區建立)稍後在搬至 DocumentRoot 下的文件,就會被 SELinux 擋住。
類似 ftpd 匿名測試方法,先『直接』在 /var/www/html 下產生 index.html 檔案,應該能夠正常被讀取;至於先在 /root 目錄下產生 index2.html 接著再『搬移』至 /var/www/html 下的話,存取應該會被 SELinux 擋住(也是因為 security context 不正確所造成)。
下圖為存取 index.html 與 index2.html 實際情況,圖片下方的 firefox 正常存取 (也就是 index.html);圖片上方的 firefox 存取 index2.html 被 SELinux 所阻擋,右上方立即出現金星,點擊後的解說內容有談到此情形可能的發生原因,以及解決的方法「restorecon -R -v /var/www/html」指令。
Samba 使用網路芳鄰方式存取 Linux Server 也是有可能被 SELinux 限制住。以下範例是啟用 Samba Server 讓使用者藉由帳號密碼認證來存取自己的家目錄,這個設定在 Samba 是相當常見的。
samba 是使用「smbpasswd」指令來建立或修改使用者 samba 密碼,在 [global] 區段 security = user 等級時,需先行建立 Unix 帳號才可以建立 samba 密碼。
例如:先使用指令「useradd foo」建立帳號 foo 後,再使用指令「smbpasswd -a foo」新增 foo 這個帳號的 samba 密碼。
使用 smbclient 指令搭配 -L 與 -U 來測試存取相當方便,例如:指令「smbclient -L localhost -U foo」意思是使用帳號 foo 登入輸入正確的 smb 密碼後,列出有那些資源可以存取(主要是 foo 的家目錄資源)。
若是真的要將檔案上傳下載的話,則使用以下的格式「smbclient //主機/分享 -U 帳號」例如:指令「smbclient //localhost/foo -U foo」應該會遇到被 SELinux 擋住存取的情況,這時觀察 Server 的 /var/log/messages 後段,應該會有 SELinux 相關訊息(包括 sealert)。
下圖的 sealert 指令執行內容大致上的意思是要我們調的是 SELinux 布林值 samba_enable_home_dirs,這一次我們使用 system-config-selinux 圖形介面來做設定,與指令介面調整的結果應該是差不多的。
在 SELinux 圖形介面修改設定中,點選左邊【Boolean】選單後,右邊點開 Samba 勾選「Allow Samba to share users home directories」確定即可。
之後再次使用 smbclient 連上後,使用 mput / mget 類似 ftp 上傳下載的指令來試著傳輸資料,此時應該就不會被 SELinux 擋住了。
SELinux 使得 Linux Server 變得更安全,不免帶來了些許的不方便,若您是使用 Linux 已經好一陣子以及對 Linux 瞭解已經有一段時日,不妨嘗試地將 SELinux 開起來,遇到無法存取的時候就試著調整看看,久而久之就習慣了 SELinux 開啟的環境。
遇到 SELinux 擋住了想要開放的存取時,查看的 log 檔 /var/log/messages 與 /var/log/audit/audit.log 尾端,裡面也許就會有 sealert 可以看到更詳細的 SELinux 說明,在 sealert 就會顯示調整 SELinux 布林值或是 restorecon(回存 security context)等等指令,另外 chcon 的 --reference=file 用來參照其他檔案設定 security context 的功能也是蠻有機會用到的。
本文雖然僅僅介紹的三個 SELinux 設定範例,但其實 SELinux 設定概念是類似的,簡單的說:布林值的開關應該開的要開、應該關的要關,以及 security context 要對才能正常存取。若還是受不了 SELinux 管得太嚴格的話,就使用 setenforce 0 暫時關閉後,測試看看所需的服務是否正常,確認是否為 SELinux 阻擋,使用 SELinux 還是可以相當地有彈性!