<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                ## 16.5 SELinux 初探 從進入了 CentOS 5.x 之后的 CentOS 版本中 (當然包括 CentOS 7),SELinux 已經是個非常完備的核心模塊了!尤其 CentOS 提供了很多管理 SELinux 的指令與機制, 因此在整體架構上面是單純且容易操作管理的!所以,在沒有自行開發網絡服務軟件以及使用其他第三方協力軟件的情況下, 也就是全部使用 CentOS 官方提供的軟件來使用我們服務器的情況下,建議大家不要關閉 SELinux 了喔! 讓我們來仔細的玩玩這家伙吧! ### 16.5.1 什么是 SELinux 什么是 SELinux 呢?其實他是“ Security Enhanced Linux ”的縮寫,字面上的意義就是安全強化的 Linux 之意!那么所謂的“安全強化”是強化哪個部分? 是網絡資安還是權限管理?下面就讓我們來談談吧! * 當初設計的目標:避免資源的誤用 SELinux 是由美國國家安全局 (NSA) 開發的,當初開發這玩意兒的目的是因為很多企業界發現, 通常系統出現問題的原因大部分都在于“內部員工的資源誤用”所導致的,實際由外部發動的攻擊反而沒有這么嚴重。 那么什么是“員工資源誤用”呢?舉例來說,如果有個不是很懂系統的系統管理員為了自己設置的方便,將網頁所在目錄 /var/www/html/ 的權限設置為 drwxrwxrwx 時,你覺得會有什么事情發生? 現在我們知道所有的系統資源都是通過程序來進行存取的,那么 /var/www/html/ 如果設置為 777 , 代表所有程序均可對該目錄存取,萬一你真的有啟動 WWW 服務器軟件,那么該軟件所觸發的程序將可以寫入該目錄, 而該程序卻是對整個 Internet 提供服務的!只要有心人接觸到這支程序,而且該程序剛好又有提供使用者進行寫入的功能, 那么外部的人很可能就會對你的系統寫入些莫名其妙的東西!那可真是不得了!一個小小的 777 問題可是大大的! 為了控管這方面的權限與程序的問題,所以美國國家安全局就著手處理操作系統這方面的控管。 由于 Linux 是自由軟件,程序碼都是公開的,因此她們便使用 Linux 來作為研究的目標, 最后更將研究的結果整合到 Linux 核心里面去,那就是 SELinux 啦!所以說, SELinux 是整合到核心的一個模塊喔! 更多的 SELinux 相關說明可以參考: * [http://www.nsa.gov/research/selinux/](http://www.nsa.gov/research/selinux/) 這也就是說:其實 SELinux 是在進行程序、文件等細部權限設置依據的一個核心模塊! 由于啟動網絡服務的也是程序,因此剛好也能夠控制網絡服務能否存取系統資源的一道關卡! 所以,在講到 SELinux 對系統的存取控制之前,我們得先來回顧一下之前談到的系統文件權限與使用者之間的關系。 因為先談完這個你才會知道為何需要 SELinux 的啦! * 傳統的文件權限與帳號關系:自主式存取控制, DAC 我們[第十三章](../Text/index.html)的內容,知道系統的帳號主要分為系統管理員 (root) 與一般用戶,而這兩種身份能否使用系統上面的文件資源則與 rwx 的權限設置有關。 不過你要注意的是,各種權限設置對 root 是無效的。因此,當某個程序想要對文件進行存取時, 系統就會根據該程序的擁有者/群組,并比對文件的權限,若通過權限檢查,就可以存取該文件了。 這種存取文件系統的方式被稱為“自主式存取控制 (Discretionary Access Control, DAC)”,基本上,就是依據程序的擁有者與文件資源的 rwx 權限來決定有無存取的能力。 不過這種 DAC 的存取控制有幾個困擾,那就是: * root 具有最高的權限:如果不小心某支程序被有心人士取得, 且該程序屬于 root 的權限,那么這支程序就可以在系統上進行任何資源的存取!真是要命! * 使用者可以取得程序來變更文件資源的存取權限:如果你不小心將某個目錄的權限設置為 777 ,由于對任何人的權限會變成 rwx ,因此該目錄就會被任何人所任意存取! 這些問題是非常嚴重的!尤其是當你的系統是被某些漫不經心的系統管理員所掌控時!她們甚至覺得目錄權限調為 777 也沒有什么了不起的危險哩... * 以政策規則訂定特定程序讀取特定文件:委任式存取控制, MAC 現在我們知道 DAC 的困擾就是當使用者取得程序后,他可以借由這支程序與自己默認的權限來處理他自己的文件資源。 萬一這個使用者對 Linux 系統不熟,那就很可能會有資源誤用的問題產生。為了避免 DAC 容易發生的問題,因此 SELinux 導入了委任式存取控制 (Mandatory Access Control, MAC) 的方法! 委任式存取控制 (MAC) 有趣啦!他可以針對特定的程序與特定的文件資源來進行權限的控管! 也就是說,即使你是 root ,那么在使用不同的程序時,你所能取得的權限并不一定是 root , 而得要看當時該程序的設置而定。如此一來,我們針對控制的“主體”變成了“程序”而不是使用者喔! 此外,這個主體程序也不能任意使用系統文件資源,因為每個文件資源也有針對該主體程序設置可取用的權限! 如此一來,控制項目就細的多了!但整個系統程序那么多、文件那么多,一項一項控制可就沒完沒了! 所以 SELinux 也提供一些默認的政策 (Policy) ,并在該政策內提供多個規則 (rule) ,讓你可以選擇是否啟用該控制規則! 在委任式存取控制的設置下,我們的程序能夠活動的空間就變小了!舉例來說, WWW 服務器軟件的達成程序為 httpd 這支程序, 而默認情況下, httpd 僅能在 /var/www/ 這個目錄下面存取文件,如果 httpd 這個程序想要到其他目錄去存取數據時, 除了規則設置要開放外,目標目錄也得要設置成 httpd 可讀取的模式 (type) 才行喔!限制非常多! 所以,即使不小心 httpd 被 cracker 取得了控制權,他也無權瀏覽 /etc/shadow 等重要的配置文件喔! 簡單的來說,針對 Apache 這個 WWW 網絡服務使用 DAC 或 MAC 的結果來說,兩者間的關系可以使用下圖來說明。 下面這個圖示取自 Red Hat 訓練教材,真的是很不錯~所以被鳥哥借用來說明一下! ![使用 DAC/MAC 產生的不同結果,以 Apache 為例說明](https://box.kancloud.cn/2016-05-13_5735737ab507d.jpg)圖16.5.1、使用 DAC/MAC 產生的不同結果,以 Apache 為例說明 左圖是沒有 SELinux 的 DAC 存取結果,apache 這只 root 所主導的程序,可以在這三個目錄內作任何文件的新建與修改~ 相當麻煩~右邊則是加上 SELinux 的 MAC 管理的結果,SELinux 僅會針對 Apache 這個“ process ”放行部份的目錄, 其他的非正規目錄就不會放行給 Apache 使用!因此不管你是誰,就是不能穿透 MAC 的框框!這樣有比較了解乎? ### 16.5.2 SELinux 的運行模式 再次的重復說明一下,SELinux 是通過 MAC 的方式來控管程序,他控制的主體是程序, 而目標則是該程序能否讀取的“文件資源”!所以先來說明一下這些咚咚的相關性啦![[4]](#ps4) * 主體 (Subject): SELinux 主要想要管理的就是程序,因此你可以將“主體”跟本章談到的 process 劃上等號; * 目標 (Object): 主體程序能否存取的“目標資源”一般就是文件系統。因此這個目標項目可以等文件系統劃上等號; * 政策 (Policy): 由于程序與文件數量龐大,因此 SELinux 會依據某些服務來制訂基本的存取安全性政策。這些政策內還會有詳細的規則 (rule) 來指定不同的服務開放某些資源的存取與否。在目前的 CentOS 7.x 里面僅有提供三個主要的政策,分別是: * targeted:針對網絡服務限制較多,針對本機限制較少,是默認的政策; * minimum:由 target 修訂而來,僅針對選擇的程序來保護! * mls:完整的 SELinux 限制,限制方面較為嚴格。建議使用默認的 targeted 政策即可。 * 安全性本文 (security context): 我們剛剛談到了主體、目標與政策面,但是主體能不能存取目標除了政策指定之外,主體與目標的安全性本文必須一致才能夠順利存取。 這個安全性本文 (security context) 有點類似文件系統的 rwx 啦!安全性本文的內容與設置是非常重要的! 如果設置錯誤,你的某些服務(主體程序)就無法存取文件系統(目標資源),當然就會一直出現“權限不符”的錯誤訊息了! 由于 SELinux 重點在保護程序讀取文件系統的權限,因此我們將上述的幾個說明搭配起來,繪制成下面的流程圖,比較好理解: ![SELinux 運行的各元件之相關性](https://box.kancloud.cn/2016-05-13_5735737acbb96.gif)圖16.5.2、SELinux 運行的各元件之相關性(本圖參考小州老師的上課講義) 上圖的重點在“主體”如何取得“目標”的資源存取權限! 由上圖我們可以發現,(1)主體程序必須要通過 SELinux 政策內的規則放行后,就可以與目標資源進行安全性本文的比對, (2)若比對失敗則無法存取目標,若比對成功則可以開始存取目標。問題是,最終能否存取目標還是與文件系統的 rwx 權限設置有關喔!如此一來,加入了 SELinux 之后,出現權限不符的情況時,你就得要一步一步的分析可能的問題了! * 安全性本文 (Security Context) CentOS 7.x 的 target 政策已經幫我們制訂好非常多的規則了,因此你只要知道如何打開/關閉某項規則的放行與否即可。 那個安全性本文比較麻煩!因為你可能需要自行設置文件的安全性本文呢!為何需要自行設置啊? 舉例來說,你不也常常進行文件的 rwx 的重新設置嗎?這個安全性本文你就將他想成 SELinux 內必備的 rwx 就是了!這樣比較好理解啦。 安全性本文存在于主體程序中與目標文件資源中。程序在內存內,所以安全性本文可以存入是沒問題。 那文件的安全性本文是記錄在哪里呢?事實上,安全性本文是放置到文件的 inode 內的,因此主體程序想要讀取目標文件資源時,同樣需要讀取 inode , 這 inode 內就可以比對安全性本文以及 rwx 等權限值是否正確,而給予適當的讀取權限依據。 那么安全性本文到底是什么樣的存在呢?我們先來看看 /root 下面的文件的安全性本文好了。 觀察安全性本文可使用“ ls -Z ”去觀察如下:(注意:你必須已經啟動了 SELinux 才行!若尚未啟動,這部份請稍微看過一遍即可。下面會介紹如何啟動 SELinux 喔!) ``` # 先來觀察一下 root 主文件夾下面的“文件的 SELinux 相關信息” [root@study ~]# ls -Z -rw-------. root root system_u:object_r:admin_home_t:s0 anaconda-ks.cfg -rw-r--r--. root root system_u:object_r:admin_home_t:s0 initial-setup-ks.cfg -rw-r--r--. root root unconfined_u:object_r:admin_home_t:s0 regular_express.txt # 上述特殊字體的部分,就是安全性本文的內容!鳥哥僅列出數個默認的文件而已, # 本書學習過程中所寫下的文件則沒有列在上頭喔! ``` 如上所示,安全性本文主要用冒號分為三個字段,這三個字段的意義為: ``` Identify:role:type 身份識別:角色:類型 ``` 這三個字段的意義仔細的說明一下吧: * 身份識別 (Identify): 相當于帳號方面的身份識別!主要的身份識別常見有下面幾種常見的類型: * unconfined_u:不受限的用戶,也就是說,該文件來自于不受限的程序所產生的!一般來說,我們使用可登陸帳號來取得 bash 之后, 默認的 bash 環境是不受 SELinux 管制的~因為 bash 并不是什么特別的網絡服務!因此,在這個不受 SELinux 所限制的 bash 程序所產生的文件, 其身份識別大多就是 unconfined_u 這個“不受限”用戶啰! * system_u:系統用戶,大部分就是系統自己產生的文件啰! 基本上,如果是系統或軟件本身所提供的文件,大多就是 system_u 這個身份名稱,而如果是我們用戶通過 bash 自己創建的文件,大多則是不受限的 unconfined_u 身份~如果是網絡服務所產生的文件,或者是系統服務運行過程產生的文件,則大部分的識別就會是 system_u 啰! 因為鳥哥這邊教大家使用文字界面來產生許多的數據,因此你看上面的三個文件中,系統安裝主動產生的 anaconda-ks.cfs 及 initial-setup-ks.cfg 就會是 system_u,而我們自己從網絡上面抓下來的 regular_express.txt 就會是 unconfined_u 這個識別啊! * 角色 (Role): 通過角色字段,我們可以知道這個數據是屬于程序、文件資源還是代表使用者。一般的角色有: * object_r:代表的是文件或目錄等文件資源,這應該是最常見的啰; * system_r:代表的就是程序啦!不過,一般使用者也會被指定成為 system_r 喔! 你也會發現角色的字段最后面使用“ _r ”來結尾!因為是 role 的意思嘛! * 類型 (Type) (最重要!): 在默認的 targeted 政策中, Identify 與 Role 字段基本上是不重要的!重要的在于這個類型 (type) 字段! 基本上,一個主體程序能不能讀取到這個文件資源,與類型字段有關!而類型字段在文件與程序的定義不太相同,分別是: * type:在文件資源 (Object) 上面稱為類型 (Type); * domain:在主體程序 (Subject) 則稱為領域 (domain) 了! domain 需要與 type 搭配,則該程序才能夠順利的讀取文件資源啦! * 程序與文件 SELinux type 字段的相關性 那么這三個字段如何利用呢?首先我們來瞧瞧主體程序在這三個字段的意義為何!通過身份識別與角色字段的定義, 我們可以約略知道某個程序所代表的意義喔!先來動手瞧一瞧目前系統中的程序在 SELinux 下面的安全本文為何? ``` # 再來觀察一下系統“程序的 SELinux 相關信息” [root@study ~]# ps -eZ LABEL PID TTY TIME CMD system_u:system_r:init_t:s0 1 ? 00:00:03 systemd system_u:system_r:kernel_t:s0 2 ? 00:00:00 kthreadd system_u:system_r:kernel_t:s0 3 ? 00:00:00 ksoftirqd/0 .....(中間省略)..... unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 31513 ? 00:00:00 sshd unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 31535 pts/0 00:00:00 bash # 基本上程序主要就分為兩大類,一種是系統有受限的 system_u:system_r,另一種則可能是用戶自己的, # 比較不受限的程序 (通常是本機用戶自己執行的程序),亦即是 unconfined_u:unconfined_r 這兩種! ``` 基本上,這些對應數據在 targeted 政策下的對應如下: | 身份識別 | 角色 | 該對應在 targeted 的意義 | | --- | --- | | unconfined_u | unconfined_r | 一般可登陸使用者的程序啰!比較沒有受限的程序之意!大多數都是用戶已經順利登陸系統 (不論是網絡還是本機登陸來取得可用的 shell) 后, 所用來操作系統的程序!如 bash, X window 相關軟件等。 | | system_u | system_r | 由于為系統帳號,因此是非交談式的系統運行程序,大多數的系統程序均是這種類型! | 但就如上所述,在默認的 target 政策下,其實最重要的字段是類型字段 (type), 主體與目標之間是否具有可以讀寫的權限,與程序的 domain 及文件的 type 有關!這兩者的關系我們可以使用 crond 以及他的配置文件來說明! 亦即是 /usr/sbin/crond, /etc/crontab, /etc/cron.d 等文件來說明。 首先,看看這幾個咚咚的安全性本文內容先: ``` # 1\. 先看看 crond 這個“程序”的安全本文內容: [root@study ~]# ps -eZ &#124; grep cron system_u:system_r:crond_t:s0-s0:c0.c1023 1338 ? 00:00:01 crond system_u:system_r:crond_t:s0-s0:c0.c1023 1340 ? 00:00:00 atd # 這個安全本文的類型名稱為 crond_t 格式! # 2\. 再來瞧瞧可執行文件、配置文件等等的安全本文內容為何! [root@study ~]# ll -Zd /usr/sbin/crond /etc/crontab /etc/cron.d drwxr-xr-x. root root system_u:object_r:system_cron_spool_t:s0 /etc/cron.d -rw-r--r--. root root system_u:object_r:system_cron_spool_t:s0 /etc/crontab -rwxr-xr-x. root root system_u:object_r:crond_exec_t:s0 /usr/sbin/crond ``` 當我們執行 /usr/sbin/crond 之后,這個程序變成的程序的 domain 類型會是 crond_t 這一個~而這個 crond_t 能夠讀取的配置文件則為 system_cron_spool_t 這種的類型。因此不論 /etc/crontab, /etc/cron.d 以及 /var/spool/cron 都會是相關的 SELinux 類型 (/var/spool/cron 為 user_cron_spool_t)。 文字看起來不太容易了解,我們使用圖示來說明這幾個東西的關系! ![主體程序取得的 domain 與目標文件資源的 type 相互關系](https://box.kancloud.cn/2016-05-13_5735737adcf2e.jpg)圖16.5.3、主體程序取得的 domain 與目標文件資源的 type 相互關系以 crond 為例 上圖的意義我們可以這樣看的: 1. 首先,我們觸發一個可執行的目標文件,那就是具有 crond_exec_t 這個類型的 /usr/sbin/crond 文件; 2. 該文件的類型會讓這個文件所造成的主體程序 (Subject) 具有 crond 這個領域 (domain), 我們的政策針對這個領域已經制定了許多規則,其中包括這個領域可以讀取的目標資源類型; 3. 由于 crond domain 被設置為可以讀取 system_cron_spool_t 這個類型的目標文件 (Object), 因此你的配置文件放到 /etc/cron.d/ 目錄下,就能夠被 crond 那支程序所讀取了; 4. 但最終能不能讀到正確的數據,還得要看 rwx 是否符合 Linux 權限的規范! 上述的流程告訴我們幾個重點,第一個是政策內需要制訂詳細的 domain/type 相關性;第二個是若文件的 type 設置錯誤, 那么即使權限設置為 rwx 全開的 777 ,該主體程序也無法讀取目標文件資源的啦!不過如此一來, 也就可以避免使用者將他的主文件夾設置為 777 時所造成的權限困擾。 真的是這樣嗎?沒關系~讓我們來做個測試練習吧!就是,萬一你的 crond 配置文件的 SELinux 并不是 system_cron_spool_t 時, 該配置文件真的可以順利的被讀取運行嗎?來看看下面的范例! ``` # 1\. 先假設你因為不熟的緣故,因此是在“root 主文件夾”創建一個如下的 cron 設置: [root@study ~]# vim checktime 10 * * * * root sleep 60s # 2\. 檢查后才發現文件放錯目錄了,又不想要保留副本,因此使用 mv 移動到正確目錄: [root@study ~]# mv checktime /etc/cron.d [root@study ~]# ll /etc/cron.d/checktime -rw-r--r--. 1 root root 27 Aug 7 18:41 /etc/cron.d/checktime # 仔細看喔,權限是 644 ,確定沒有問題!任何程序都能夠讀取喔! # 3\. 強制重新啟動 crond ,然后偷看一下登錄文件,看看有沒有問題發生! [root@study ~]# systemctl restart crond [root@study ~]# tail /var/log/cron Aug 7 18:46:01 study crond[28174]: ((null)) Unauthorized SELinux context=system_u:system_r: system_cronjob_t:s0-s0:c0.c1023 file_context=unconfined_u:object_r:admin_home_t:s0 (/etc/cron.d/checktime) Aug 7 18:46:01 study crond[28174]: (root) FAILED (loading cron table) # 上面的意思是,有錯誤!因為原本的安全本文與文件的實際安全本文無法搭配的緣故! ``` 您瞧瞧~從上面的測試案例來看,我們的配置文件確實沒有辦法被 crond 這個服務所讀取喔!而原因在登錄文件內就有說明, 主要就是來自 SELinux 安全本文 (context) type 的不同所致喔!沒辦法讀就沒辦法讀,先放著~后面再來學怎么處理這問題吧! ### 16.5.3 SELinux 三種模式的啟動、關閉與觀察 并非所有的 Linux distributions 都支持 SELinux 的,所以你必須要先觀察一下你的系統版本為何! 鳥哥這里介紹的 CentOS 7.x 本身就有支持 SELinux 啦!所以你不需要自行編譯 SELinux 到你的 Linux 核心中! 目前 SELinux 依據啟動與否,共有三種模式,分別如下: * enforcing:強制模式,代表 SELinux 運行中,且已經正確的開始限制 domain/type 了; * permissive:寬容模式:代表 SELinux 運行中,不過僅會有警告訊息并不會實際限制 domain/type 的存取。這種模式可以運來作為 SELinux 的 debug 之用; * disabled:關閉,SELinux 并沒有實際運行。 這三種模式跟[圖16.5.2](../Text/index.html#fig16.5.2)之間的關系如何呢?我們前面不是談過主體程序需要經過政策規則、安全本文比對之后,加上 rwx 的權限規范, 若一切合理才會讓程序順利的讀取文件嗎?那么這個 SELinux 的三種模式與上面談到的政策規則、安全本文的關系為何呢?我們還是使用圖示加上流程來讓大家理解一下: ![SELinux 的三種類型與實際運行流程圖示意](https://box.kancloud.cn/2016-05-13_5735737b03da1.jpg)圖16.5.4、SELinux 的三種類型與實際運行流程圖示意 就如上圖所示,首先,你得要知道,并不是所有的程序都會被 SELinux 所管制,因此最左邊會出現一個所謂的“有受限的程序主體”!那如何觀察有沒有受限 (confined )呢? 很簡單啊!就通過 ps -eZ 去擷取!舉例來說,我們來找一找 crond 與 bash 這兩只程序是否有被限制吧? ``` [root@study ~]# ps -eZ &#124; grep -E 'cron&#124;bash' system_u:system_r:crond_t:s0-s0:c0.c1023 1340 ? 00:00:00 atd unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 13888 tty2 00:00:00 bash unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 28054 pts/0 00:00:00 bash unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 28094 pts/0 00:00:00 bash system_u:system_r:crond_t:s0-s0:c0.c1023 28174 ? 00:00:00 crond ``` 如前所述,因為在目前 target 這個政策下面,只有第三個類型 (type) 字段會有影響,因此我們上表僅列出第三個字段的數據而已。 我們可以看到, crond 確實是有受限的主體程序,而 bash 因為是本機程序,因此就是不受限 (unconfined_t) 的類型!也就是說, bash 是不需要經過圖 16.5.4 的流程,而是直接去判斷 rwx 而已~。 了解了受限的主體程序的意義之后,再來了解一下,三種模式的運行吧!首先,如果是 Disabled 的模式,那么 SELinux 將不會運行,當然受限的程序也不會經過 SELinux , 也是直接去判斷 rwx 而已。那如果是寬容 (permissive) 模式呢?這種模式也是不會將主體程序抵擋 (所以箭頭是可以直接穿透的喔!),不過萬一沒有通過政策規則,或者是安全本文的比對時, 那么該讀寫動作將會被紀錄起來 (log),可作為未來檢查問題的判斷依據。 至于最終那個 Enforcing 模式,就是實際將受限主體進入規則比對、安全本文比對的流程,若失敗,就直接抵擋主體程序的讀寫行為,并且將他記錄下來。 如果通通沒問題,這才進入到 rwx 權限的判斷喔!這樣可以理解三種模式的行為了嗎? 那你怎么知道目前的 SELinux 模式呢?就通過 getenforce 吧! ``` [root@study ~]# getenforce Enforcing &lt;==諾!就顯示出目前的模式為 Enforcing 啰! ``` 另外,我們又如何知道 SELinux 的政策 (Policy) 為何呢?這時可以使用 sestatus 來觀察: ``` [root@study ~]# sestatus [-vb] 選項與參數: -v :檢查列于 /etc/sestatus.conf 內的文件與程序的安全性本文內容; -b :將目前政策的規則布林值列出,亦即某些規則 (rule) 是否要啟動 (0/1) 之意; 范例一:列出目前的 SELinux 使用哪個政策 (Policy)? [root@study ~]# sestatus SELinux status: enabled &lt;==是否啟動 SELinux SELinuxfs mount: /sys/fs/selinux &lt;==SELinux 的相關文件數據掛載點 SELinux root directory: /etc/selinux &lt;==SELinux 的根目錄所在 Loaded policy name: targeted &lt;==目前的政策為何? Current mode: enforcing &lt;==目前的模式 Mode from config file: enforcing &lt;==目前配置文件內規范的 SELinux 模式 Policy MLS status: enabled &lt;==是否含有 MLS 的模式機制 Policy deny_unknown status: allowed &lt;==是否默認抵擋未知的主體程序 Max kernel policy version: 28 ``` 如上所示,目前是啟動的,而且是 Enforcing 模式,而由配置文件查詢得知亦為 Enforcing 模式。 此外,目前的默認政策為 targeted 這一個。你應該要有疑問的是, SELinux 的配置文件是哪個文件啊? 其實就是 /etc/selinux/config 這個文件喔!我們來看看內容: ``` [root@study ~]# vim /etc/selinux/config SELINUX=enforcing &lt;==調整 enforcing&#124;disabled&#124;permissive SELINUXTYPE=targeted &lt;==目前僅有 targeted, mls, minimum 三種政策 ``` 若有需要修改默認政策的話,就直接改 SELINUX=enforcing 那一行即可喔! * SELinux 的啟動與關閉 上面是默認的政策與啟動的模式!你要注意的是,如果改變了政策則需要重新開機;如果由 enforcing 或 permissive 改成 disabled ,或由 disabled 改成其他兩個,那也必須要重新開機。這是因為 SELinux 是整合到核心里面去的, 你只可以在 SELinux 運行下切換成為強制 (enforcing) 或寬容 (permissive) 模式,不能夠直接關閉 SELinux 的! 如果剛剛你發現 getenforce 出現 disabled 時,請到上述文件修改成為 enforcing 然后重新開機吧! 不過你要注意的是,如果從 disable 轉到啟動 SELinux 的模式時, 由于系統必須要針對文件寫入安全性本文的信息,因此開機過程會花費不少時間在等待重新寫入 SELinux 安全性本文 (有時也稱為 SELinux Label) ,而且在寫完之后還得要再次的重新開機一次喔!你必須要等待粉長一段時間! 等到下次開機成功后,再使用 [getenforce](../Text/index.html#getenforce) 或 [sestatus](../Text/index.html#sestatus) 來觀察看看有否成功的啟動到 Enforcing 的模式啰! 如果你已經在 Enforcing 的模式,但是可能由于一些設置的問題導致 SELinux 讓某些服務無法正常的運行, 此時你可以將 Enforcing 的模式改為寬容 (permissive) 的模式,讓 SELinux 只會警告無法順利連線的訊息, 而不是直接抵擋主體程序的讀取權限。讓 SELinux 模式在 enforcing 與 permissive 之間切換的方法為: ``` [root@study ~]# setenforce [0&#124;1] 選項與參數: 0 :轉成 permissive 寬容模式; 1 :轉成 Enforcing 強制模式 范例一:將 SELinux 在 Enforcing 與 permissive 之間切換與觀察 [root@study ~]# setenforce 0 [root@study ~]# getenforce Permissive [root@study ~]# setenforce 1 [root@study ~]# getenforce Enforcing ``` 不過請注意, setenforce 無法在 Disabled 的模式下面進行模式的切換喔! ![鳥哥的圖示](https://box.kancloud.cn/2016-05-13_5735736501917.gif "鳥哥的圖示") **Tips** 在某些特殊的情況下面,你從 Disabled 切換成 Enforcing 之后,竟然有一堆服務無法順利啟動,都會跟你說在 /lib/xxx 里面的數據沒有權限讀取,所以啟動失敗。這大多是由于在重新寫入 SELinux type (Relabel) 出錯之故,使用 Permissive 就沒有這個錯誤。那如何處理呢?最簡單的方法就是在 Permissive 的狀態下,使用“ restorecon -Rv / ”重新還原所有 SELinux 的類型,就能夠處理這個錯誤! ### 16.5.4 SELinux 政策內的規則管理 從[圖 16.5.4](../Text/index.html#fig16.5.4) 里面,我們知道 SELinux 的三種模式是會影響到主體程序的放行與否。 如果是進入 Enforcing 模式,那么接著下來會影響到主體程序的,當然就是第二關:“ target 政策內的各項規則 (rules) ”了! 好了,那么我們怎么知道目前這個政策里面到底有多少會影響到主體程序的規則呢?很簡單,就通過 getsebool 來瞧一瞧即可。 * SELinux 各個規則的布林值查詢 getsebool 如果想要查詢系統上面全部規則的啟動與否 (on/off,亦即布林值),很簡單的通過 sestatus -b 或 getsebool -a 均可! ``` [root@study ~]# getsebool [-a] [規則的名稱] 選項與參數: -a :列出目前系統上面的所有 SELinux 規則的布林值為打開或關閉值 范例一:查詢本系統內所有的布林值設置狀況 [root@study ~]# getsebool -a abrt_anon_write --&gt; off abrt_handle_event --&gt; off ....(中間省略).... cron_can_relabel --&gt; off # 這個跟 cornd 比較有關! cron_userdomain_transition --&gt; on ....(中間省略).... httpd_enable_homedirs --&gt; off # 這當然就是跟網頁,亦即 http 有關的啰! ....(下面省略).... # 這么多的 SELinux 規則喔!每個規則后面都列出現在是允許放行還是不許放行的布林值喔! ``` * SELinux 各個規則規范的主體程序能夠讀取的文件 SELinux type 查詢 seinfo, sesearch 我們現在知道有這么多的 SELinux 規則,但是每個規則內到底是在限制什么東西?如果你想要知道的話,那就得要使用 seinfo 等工具! 這些工具并沒有在我們安裝時就安裝了,因此請拿出原版光盤,放到光驅,鳥哥假設你將原版光盤掛載到 /mnt 下面,那么接下來這么作, 先安裝好我們所需要的軟件才行! ``` [root@study ~]# yum install /mnt/Packages/setools-console-* ``` 很快的安裝完畢之后,我們就可以來使用 seinfo, sesearch 等指令了! ``` [root@study ~]# seinfo [-Atrub] 選項與參數: -A :列出 SELinux 的狀態、規則布林值、身份識別、角色、類別等所有信息 -u :列出 SELinux 的所有身份識別 (user) 種類 -r :列出 SELinux 的所有角色 (role) 種類 -t :列出 SELinux 的所有類別 (type) 種類 -b :列出所有規則的種類 (布林值) 范例一:列出 SELinux 在此政策下的統計狀態 [root@study ~]# seinfo Statistics for policy file: /sys/fs/selinux/policy Policy Version & Type: v.28 (binary, mls) Classes: 83 Permissions: 255 Sensitivities: 1 Categories: 1024 Types: 4620 Attributes: 357 Users: 8 Roles: 14 Booleans: 295 Cond. Expr.: 346 Allow: 102249 Neverallow: 0 Auditallow: 160 Dontaudit: 8413 Type_trans: 16863 Type_change: 74 Type_member: 35 Role allow: 30 Role_trans: 412 Range_trans: 5439 ....(下面省略).... # 從上面我們可以看到這個政策是 targeted ,此政策的安全本文類別有 4620 個; # 而各種 SELinux 的規則 (Booleans) 共制訂了 295 條! ``` 我們在 16.5.2 里面簡單的談到了幾個身份識別 (user) 以及角色 (role) 而已,如果你想要查詢目前所有的身份識別與角色,就使用“ seinfo -u ”及“ seinfo -r ”就可以知道了!至于簡單的統計數據,就直接輸入 seinfo 即可!但是上面還是沒有談到規則相關的東西耶~ 沒關系~一個一個來~我們在 16.5.1 的最后面談到 /etc/cron.d/checktime 的 SELinux type 類型不太對~那我們也知道 crond 這個程序的 type 是 crond_t , 能不能找一下 crond_t 能夠讀取的文件 SELinux type 有哪些呢? ``` [root@study ~]# sesearch [-A] [-s 主體類別] [-t 目標類別] [-b 布林值] 選項與參數: -A :列出后面數據中,允許“讀取或放行”的相關數據 -t :后面還要接類別,例如 -t httpd_t -b :后面還要接SELinux的規則,例如 -b httpd_enable_ftp_server 范例一:找出 crond_t 這個主體程序能夠讀取的文件 SELinux type [root@study ~]# sesearch -A -s crond_t &#124; grep spool allow crond_t system_cron_spool_t : file { ioctl read write create getattr .. allow crond_t system_cron_spool_t : dir { ioctl read getattr lock search op.. allow crond_t user_cron_spool_t : file { ioctl read write create getattr se.. allow crond_t user_cron_spool_t : dir { ioctl read write getattr lock add_n.. allow crond_t user_cron_spool_t : lnk_file { read getattr } ; # allow 后面接主體程序以及文件的 SELinux type,上面的數據是擷取出來的, # 意思是說,crond_t 可以讀取 system_cron_spool_t 的文件/目錄類型~等等! 范例二:找出 crond_t 是否能夠讀取 /etc/cron.d/checktime 這個我們自訂的配置文件? [root@study ~]# ll -Z /etc/cron.d/checktime -rw-r--r--. root root unconfined_u:object_r:admin_home_t:s0 /etc/cron.d/checktime # 兩個重點,一個是 SELinux type 為 admin_home_t,一個是文件 (file) [root@study ~]# sesearch -A -s crond_t &#124; grep admin_home_t allow domain admin_home_t : dir { getattr search open } ; allow domain admin_home_t : lnk_file { read getattr } ; allow crond_t admin_home_t : dir { ioctl read getattr lock search open } ; allow crond_t admin_home_t : lnk_file { read getattr } ; # 仔細看!看仔細~雖然有 crond_t admin_home_t 存在,但是這是總體的信息, # 并沒有針對某些規則的尋找~所以還是不確定 checktime 能否被讀取。但是,基本上就是 SELinux # type 出問題~因此才會無法讀取的! ``` 所以,現在我們知道 /etc/cron.d/checktime 這個我們自己復制過去的文件會沒有辦法被讀取的原因,就是因為 SELinux type 錯誤啦! 根本就無法被讀取~好~那現在我們來查一查,那 getsebool -a 里面看到的 httpd_enable_homedirs 到底是什么?又是規范了哪些主體程序能夠讀取的 SELinux type 呢? ``` [root@study ~]# semanage boolean -l &#124; grep httpd_enable_homedirs SELinux boolean State Default Description httpd_enable_homedirs (off , off) Allow httpd to enable homedirs # httpd_enable_homedirs 的功能是允許 httpd 程序去讀取使用者主文件夾的意思~ [root@study ~]# sesearch -A -b httpd_enable_homedirs 范例三:列出 httpd_enable_homedirs 這個規則當中,主體程序能夠讀取的文件 SELinux type Found 43 semantic av rules: allow httpd_t home_root_t : dir { ioctl read getattr lock search open } ; allow httpd_t home_root_t : lnk_file { read getattr } ; allow httpd_t user_home_type : dir { getattr search open } ; allow httpd_t user_home_type : lnk_file { read getattr } ; ....(后面省略).... # 從上面的數據才可以理解,在這個規則中,主要是放行 httpd_t 能否讀取使用者主文件夾的文件! # 所以,如果這個規則沒有啟動,基本上, httpd_t 這種程序就無法讀取使用者主文件夾下的文件! ``` * 修改 SELinux 規則的布林值 setsebool 那么如果查詢到某個 SELinux rule,并且以 sesearch 知道該規則的用途后,想要關閉或啟動他,又該如何處置? ``` [root@study ~]# setsebool [-P] “規則名稱” [0&#124;1] 選項與參數: -P :直接將設置值寫入配置文件,該設置數據未來會生效的! 范例一:查詢 httpd_enable_homedirs 這個規則的狀態,并且修改這個規則成為不同的布林值 [root@study ~]# getsebool httpd_enable_homedirs httpd_enable_homedirs --&gt; off &lt;==結果是 off ,依題意給他啟動看看! [root@study ~]# setsebool -P httpd_enable_homedirs 1 # 會跑很久很久!請耐心等待! [root@study ~]# getsebool httpd_enable_homedirs httpd_enable_homedirs --&gt; on ``` 這個 setsebool 最好記得一定要加上 -P 的選項!因為這樣才能將此設置寫入配置文件! 這是非常棒的工具組!你一定要知道如何使用 getsebool 與 setsebool 才行! ### 16.5.5 SELinux 安全本文的修改 再次的回到[圖 16.5.4](../Text/index.html#fig16.5.4) 上頭去,現在我們知道 SELinux 對受限的主體程序有沒有影響,第一關考慮 SELinux 的三種類型,第二關考慮 SELinux 的政策規則是否放行,第三關則是開始比對 SELinux type 啦!從剛剛 16.5.4 小節我們也知道可以通過 sesearch 來找到主體程序與文件的 SELinux type 關系! 好,現在總算要來修改文件的 SELinux type,以讓主體程序能夠讀到正確的文件啊!這時就得要幾個重要的小東西了~來瞧瞧~ * 使用 chcon 手動修改文件的 SELinux type ``` [root@study ~]# chcon [-R] [-t type] [-u user] [-r role] 文件 [root@study ~]# chcon [-R] --reference=范例檔 文件 選項與參數: -R :連同該目錄下的次目錄也同時修改; -t :后面接安全性本文的類型字段!例如 httpd_sys_content_t ; -u :后面接身份識別,例如 system_u; (不重要) -r :后面街角色,例如 system_r; (不重要) -v :若有變化成功,請將變動的結果列出來 --reference=范例檔:拿某個文件當范例來修改后續接的文件的類型! 范例一:查詢一下 /etc/hosts 的 SELinux type,并將該類型套用到 /etc/cron.d/checktime 上 [root@study ~]# ll -Z /etc/hosts -rw-r--r--. root root system_u:object_r:net_conf_t:s0 /etc/hosts [root@study ~]# chcon -v -t net_conf_t /etc/cron.d/checktime changing security context of ‘/etc/cron.d/checktime’ [root@study ~]# ll -Z /etc/cron.d/checktime -rw-r--r--. root root unconfined_u:object_r:net_conf_t:s0 /etc/cron.d/checktime 范例二:直接以 /etc/shadow SELinux type 套用到 /etc/cron.d/checktime 上! [root@study ~]# chcon -v --reference=/etc/shadow /etc/cron.d/checktime [root@study ~]# ll -Z /etc/shadow /etc/cron.d/checktime -rw-r--r--. root root system_u:object_r:shadow_t:s0 /etc/cron.d/checktime ----------. root root system_u:object_r:shadow_t:s0 /etc/shadow ``` 上面的練習“都沒有正確的解答!”因為正確的 SELinux type 應該就是要以 /etc/cron.d/ 下面的文件為標準來處理才對啊~ 好了~既然如此~能不能讓 SELinux 自己解決默認目錄下的 SELinux type 呢?可以!就用 restorecon 吧! * 使用 restorecon 讓文件恢復正確的 SELinux type ``` [root@study ~]# restorecon [-Rv] 文件或目錄 選項與參數: -R :連同次目錄一起修改; -v :將過程顯示到屏幕上 范例三:將 /etc/cron.d/ 下面的文件通通恢復成默認的 SELinux type! [root@study ~]# restorecon -Rv /etc/cron.d restorecon reset /etc/cron.d/checktime context system_u:object_r:shadow_t:s0-&gt; system_u:object_r:system_cron_spool_t:s0 # 上面這兩行其實是同一行喔!表示將 checktime 由 shadow_t 改為 system_cron_spool_t 范例四:重新啟動 crond 看看有沒有正確啟動 checktime 啰!? [root@study ~]# systemctl restart crond [root@study ~]# tail /var/log/cron # 再去瞧瞧這個 /var/log/cron 的內容,應該就沒有錯誤訊息了 ``` 其實,鳥哥幾乎已經忘了 chcon 這個指令了!因為 restorecon 主動的回復默認的 SELinux type 要簡單很多!而且可以一口氣恢復整個目錄下的文件! 所以,鳥哥建議你幾乎只要記得 restorecon 搭配 -Rv 同時加上某個目錄這樣的指令串即可~修改 SELinux 的 type 就變得非常的輕松啰! * semanage 默認目錄的安全性本文查詢與修改 你應該要覺得奇怪,為什么 restorecon 可以“恢復”原本的 SELinux type 呢?那肯定就是有個地方在紀錄每個文件/目錄的 SELinux 默認類型啰? 沒錯!是這樣~那要如何 (1)查詢默認的 SELinux type 以及 (2)如何增加/修改/刪除默認的 SELinux type 呢?很簡單~通過 semanage 即可!他是這樣使用的: ``` [root@study ~]# semanage {login&#124;user&#124;port&#124;interface&#124;fcontext&#124;translation} -l [root@study ~]# semanage fcontext -{a&#124;d&#124;m} [-frst] file_spec 選項與參數: fcontext :主要用在安全性本文方面的用途, -l 為查詢的意思; -a :增加的意思,你可以增加一些目錄的默認安全性本文類型設置; -m :修改的意思; -d :刪除的意思。 范例一:查詢一下 /etc /etc/cron.d 的默認 SELinux type 為何? [root@study ~]# semanage fcontext -l &#124; grep -E '^/etc &#124;^/etc/cron' SELinux fcontext type Context /etc all files system_u:object_r:etc_t:s0 /etc/cron\.d(/.*)? all files system_u:object_r:system_cron_spool_t:s0 ``` 看到上面輸出的最后一行,那也是為啥我們直接使用 vim 去 /etc/cron.d 下面創建新文件時,默認的 SELinux type 就是正確的! 同時,我們也會知道使用 restorecon 回復正確的 SELinux type 時,系統會去判斷默認的類型為何的依據。現在讓我們來想一想, 如果 (當然是假的!不可能這么干) 我們要創建一個 /srv/mycron 的目錄,這個目錄默認也是需要變成 system_cron_spool_t 時, 我們應該要如何處理呢?基本上可以這樣作: ``` # 1\. 先創建 /srv/mycron 同時在內部放入配置文件,同時觀察 SELinux type [root@study ~]# mkdir /srv/mycron [root@study ~]# cp /etc/cron.d/checktime /srv/mycron [root@study ~]# ll -dZ /srv/mycron /srv/mycron/checktime drwxr-xr-x. root root unconfined_u:object_r:var_t:s0 /srv/mycron -rw-r--r--. root root unconfined_u:object_r:var_t:s0 /srv/mycron/checktime # 2\. 觀察一下上層 /srv 的 SELinux type [root@study ~]# semanage fcontext -l &#124; grep '^/srv' SELinux fcontext type Context /srv all files system_u:object_r:var_t:s0 # 怪不得 mycron 會是 var_t 啰! # 3\. 將 mycron 默認值改為 system_cron_spool_t 啰! [root@study ~]# semanage fcontext -a -t system_cron_spool_t "/srv/mycron(/.*)?" [root@study ~]# semanage fcontext -l &#124; grep '^/srv/mycron' SELinux fcontext type Context /srv/mycron(/.*)? all files system_u:object_r:system_cron_spool_t:s0 # 4\. 恢復 /srv/mycron 以及子目錄相關的 SELinux type 喔! [root@study ~]# restorecon -Rv /srv/mycron [root@study ~]# ll -dZ /srv/mycron /srv/mycron/* drwxr-xr-x. root root unconfined_u:object_r:system_cron_spool_t:s0 /srv/mycron -rw-r--r--. root root unconfined_u:object_r:system_cron_spool_t:s0 /srv/mycron/checktime # 有了默認值,未來就不會不小心被亂改了!這樣比較妥當些~ ``` semanage 的功能很多,不過鳥哥主要用到的僅有 fcontext 這個項目的動作而已。如上所示, 你可以使用 semanage 來查詢所有的目錄默認值,也能夠使用他來增加默認值的設置!如果您學會這些基礎的工具, 那么 SELinux 對你來說,也不是什么太難的咚咚啰! ### 16.5.6 一個網絡服務案例及登錄文件協助 本章在 SELinux 小節當中談到的各個指令中,尤其是 setsebool, chcon, restorecon 等,都是為了當你的某些網絡服務無法正常提供相關功能時, 才需要進行修改的一些指令動作。但是,我們怎么知道哪個時候才需要進行這些指令的修改啊?我們怎么知道系統因為 SELinux 的問題導致網絡服務不對勁啊?如果都要靠用戶端連線失敗才來哭訴,那也太沒有效率了!所以,我們的 CentOS 7.x 有提供幾支偵測的服務在登錄 SELinux 產生的錯誤喔!那就是 auditd 與 setroubleshootd。 * setroubleshoot --&gt; 錯誤訊息寫入 /var/log/messages 幾乎所有 SELinux 相關的程序都會以 se 為開頭,這個服務也是以 se 為開頭!而 troubleshoot 大家都知道是錯誤克服,因此這個 setroubleshoot 自然就得要啟動他啦!這個服務會將關于 SELinux 的錯誤訊息與克服方法記錄到 /var/log/messages 與 /var/log/setroubleshoot/* 里頭,所以你一定得要啟動這個服務才好。啟動這個服務之前當然就是得要安裝它啦! 這玩意兒總共需要兩個軟件,分別是 setroublshoot 與 setroubleshoot-server,如果你沒有安裝,請自行使用 yum 安裝吧! 此外,原本的 SELinux 信息本來是以兩個服務來記錄的,分別是 auditd 與 setroubleshootd。既然是同樣的信息,因此 CentOS 6.x (含 7.x) 以后將兩者整合在 auditd 當中啦!所以,并沒有 setroubleshootd 的服務存在了喔!因此,當你安裝好了 setroubleshoot-server 之后,請記得要重新啟動 auditd,否則 setroubleshootd 的功能不會被啟動的。 ![鳥哥的圖示](https://box.kancloud.cn/2016-05-13_5735736501917.gif "鳥哥的圖示") **Tips** 事實上,CentOS 7.x 對 setroubleshootd 的運行方式是: (1)先由 auditd 去調用 audispd 服務, (2)然后 audispd 服務去啟動 sedispatch 程序, (3)sedispatch 再將原本的 auditd 訊息轉成 setroubleshootd 的訊息,進一步儲存下來的! ``` [root@study ~]# rpm -qa &#124; grep setroubleshoot setroubleshoot-plugins-3.0.59-1.el7.noarch setroubleshoot-3.2.17-3.el7.x86_64 setroubleshoot-server-3.2.17-3.el7.x86_64 ``` 在默認的情況下,這個 setroubleshoot 應該都是會安裝的!是否正確安裝可以使用上述的表格指令去查詢。萬一沒有安裝,請使用 yum install 去安裝吧! 再說一遍,安裝完畢最好重新啟動 auditd 這個服務喔!不過,剛剛裝好且順利啟動后, setroubleshoot 還是不會有作用,為啥? 因為我們并沒有任何受限的網絡服務主體程序在運行啊!所以,下面我們將使用一個簡單的 FTP 服務器軟件為例,讓你了解到我們上頭講到的許多重點的應用! * 實例狀況說明:通過 vsftpd 這個 FTP 服務器來存取系統上的文件 現在的年輕小伙子們傳數據都用 line, FB, dropbox, google 云端磁盤等等,不過在網絡早期傳送大容量的文件,還是以 FTP 這個協定為主! 現在為了速度,經常有 p2p 的軟件提供大容量文件的傳輸,但以鳥哥這個老人家來說,可能 FTP 傳送數據還是比較有保障... 在 CentOS 7.x 的環境下,達成 FTP 的默認服務器軟件主要是 vsftpd 這一支喔! 詳細的 FTP 協定我們在服務器篇再來談,這里只是簡單的利用 vsftpd 這個軟件與 FTP 的協定來講解 SELinux 的問題與錯誤克服而已。 不過既然要使用到 FTP 協定,一些簡單的知識還是得要存在才好!否則等一下我們沒有辦法了解為啥要這么做! 首先,你得要知道,用戶端需要使用“FTP 帳號登陸 FTP 服務器”才行!而有一個稱為“匿名 (anonymous) ”的帳號可以登陸系統! 但是這個匿名的帳號登陸后,只能存取某一個特定的目錄,而無法脫離該目錄~! 在 vsftpd 中,一般用戶與匿名者的主文件夾說明如下: * 匿名者:如果使用瀏覽器來連線到 FTP 服務器的話,那默認就是使用匿名者登陸系統。而匿名者的主文件夾默認是在 /var/ftp 當中! 同時,匿名者在主文件夾下只能下載數據,不能上傳數據到 FTP 服務器。同時,匿名者無法離開 FTP 服務器的 /var/ftp 目錄喔! * 一般 FTP 帳號:在默認的情況下,所有 UID 大于 1000 的帳號,都可以使用 FTP 來登陸系統! 而登陸系統之后,所有的帳號都能夠取得自己主文件夾下面的文件數據!當然默認是可以上傳、下載文件的! 為了避免跟之前章節的用戶產生誤解的情況,這里我們先創建一個名為 ftptest 的帳號,且帳號密碼為 myftp123, 先來創建一下吧! ``` [root@study ~]# useradd -s /sbin/nologin ftptest [root@study ~]# echo "myftp123" &#124; passwd --stdin ftptest ``` 接下來當然就是安裝 vsftpd 這只服務器軟件,同時啟動這只服務,另外,我們也希望未來開機都能夠啟動這只服務! 因此需要這樣做 (鳥哥假設你的 CentOS 7.x 的原版光盤已經掛載于 /mnt 了喔!): ``` [root@study ~]# yum install /mnt/Packages/vsftpd-3* [root@study ~]# systemctl start vsftpd [root@study ~]# systemctl enable vsftpd [root@study ~]# netstat -tlnp Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1326/sshd tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 2349/master tcp6 0 0 :::21 :::* LISTEN 6256/vsftpd tcp6 0 0 :::22 :::* LISTEN 1326/sshd tcp6 0 0 ::1:25 :::* LISTEN 2349/master # 要注意看,上面的特殊字體那行有出現,才代表 vsftpd 這只服務有啟動喔!! ``` * 匿名者無法下載的問題 現在讓我們來仿真一些 FTP 的常用狀態!假設你想要將 /etc/securetty 以及主要的 /etc/sysctl.conf 放置給所有人下載, 那么你可能會這樣做! ``` [root@study ~]# cp -a /etc/securetty /etc/sysctl.conf /var/ftp/pub [root@study ~]# ll /var/ftp/pub -rw-------. 1 root root 221 Oct 29 2014 securetty # 先假設你沒有看到這個問題! -rw-r--r--. 1 root root 225 Mar 6 11:05 sysctl.conf ``` 一般來說,默認要給用戶下載的 FTP 文件會放置到上面表格當中的 /var/ftp/pub 目錄喔!現在讓我們使用簡單的終端機瀏覽器 curl 來觀察看看! 看你能不能查詢到上述兩個文件的內容呢? ``` # 1\. 先看看 FTP 根目錄下面有什么文件存在? [root@study ~]# curl ftp://localhost drwxr-xr-x 2 0 0 40 Aug 08 00:51 pub # 確實有存在一個名為 pub 的文件喔!那就是在 /var/ftp 下面的 pub 啰! # 2\. 再往下看看,能不能看到 pub 內的文件呢? [root@study ~]# curl ftp://localhost/pub/ # 因為是目錄,要加上 / 才好! -rw------- 1 0 0 221 Oct 29 2014 securetty -rw-r--r-- 1 0 0 225 Mar 06 03:05 sysctl.conf # 3\. 承上,繼續看一下 sysctl.conf 的內容好了! [root@study ~]# curl ftp://localhost/pub/sysctl.conf # System default settings live in /usr/lib/sysctl.d/00-system.conf. # To override those settings, enter new settings here, or in an /etc/sysctl.d/&lt;name&gt;.conf file # # For more information, see sysctl.conf(5) and sysctl.d(5). # 真的有看到這個文件的內容喔!所以確定是可以讓 vsftpd 讀取到這文件的! # 4\. 再來瞧瞧 securetty 好了! [root@study ~]# curl ftp://localhost/pub/securetty curl: (78) RETR response: 550 # 看不到耶!但是,基本的原因應該是權限問題喔!因為 vsftpd 默認放在 /var/ftp/pub 內的數據, # 不論什么 SELinux type 幾乎都可以被讀取的才對喔!所以要這樣處理! # 5\. 修訂權限之后再一次觀察 securetty 看看! [root@study ~]# chmod a+r /var/ftp/pub/securetty [root@study ~]# curl ftp://localhost/pub/securetty # 此時你就可以看到實際的文件內容啰! # 6\. 修訂 SELinux type 的內容 (非必備) [root@study ~]# restorecon -Rv /var/ftp ``` 上面這個例子在告訴你,要先從權限的角度來瞧一瞧,如果無法被讀取,可能就是因為沒有 r 或沒有 rx 啰!并不一定是由 SELinux 引起的! 了解乎?好~再來瞧瞧如果是一般帳號呢?如何登陸? * 無法從主文件夾下載文件的問題分析與解決 我們前面創建了 ftptest 帳號,那如何使用文字界面來登陸呢?就使用如下的方式來處理。同時請注意,因為文字體的 FTP 用戶端軟件, 默認會將用戶丟到根目錄而不是主文件夾,因此,你的 URL 可能需要修訂一下如下! ``` # 0\. 為了讓 curl 這個文字瀏覽器可以傳輸數據,我們先創建一些數據在 ftptest 主文件夾 [root@study ~]# echo "testing" &gt; ~ftptest/test.txt [root@study ~]# cp -a /etc/hosts /etc/sysctl.conf ~ftptest/ [root@study ~]# ll ~ftptest/ -rw-r--r--. 1 root root 158 Jun 7 2013 hosts -rw-r--r--. 1 root root 225 Mar 6 11:05 sysctl.conf -rw-r--r--. 1 root root 8 Aug 9 01:05 test.txt # 1\. 一般帳號直接登陸 FTP 服務器,同時變換目錄到主文件夾去! [root@study ~]# curl ftp://ftptest:myftp123@localhost/~/ -rw-r--r-- 1 0 0 158 Jun 07 2013 hosts -rw-r--r-- 1 0 0 225 Mar 06 03:05 sysctl.conf -rw-r--r-- 1 0 0 8 Aug 08 17:05 test.txt # 真的有數據~看文件最左邊的權限也是沒問題,所以,來讀一下 test.txt 的內容看看 # 2\. 開始下載 test.txt, sysctl.conf 等有權限可以閱讀的文件看看! [root@study ~]# curl ftp://ftptest:myftp123@localhost/~/test.txt curl: (78) RETR response: 550 # 竟然說沒有權限!明明我們的 rwx 是正常沒問題!那是否有可能是 SELinux 造成的? # 3\. 先將 SELinux 從 Enforce 轉成 Permissive 看看情況!同時觀察登錄文件 [root@study ~]# setenforce 0 [root@study ~]# curl ftp://ftptest:myftp123@localhost/~/test.txt testing [root@study ~]# setenforce 1 # 確定問題后,一定要轉成 Enforcing 啊! # 確定有數據內容!所以,確定就是 SELinux 造成無法讀取的問題~那怎辦?要改規則?還是改 type? # 因為都不知道,所以,就檢查一下登錄文件看看有沒有相關的信息可以提供給我們處理! [root@study ~]# vim /var/log/messages Aug 9 02:55:58 station3-39 setroubleshoot: SELinux is preventing /usr/sbin/vsftpd from lock access on the file /home/ftptest/test.txt. For complete SELinux messages. run sealert -l 3a57aad3-a128-461b-966a-5bb2b0ffa0f9 Aug 9 02:55:58 station3-39 python: SELinux is preventing /usr/sbin/vsftpd from lock access on the file /home/ftptest/test.txt. ***** Plugin catchall_boolean (47.5 confidence) suggests ****************** If you want to allow ftp to home dir Then you must tell SELinux about this by enabling the 'ftp_home_dir' boolean. You can read 'None' man page for more details. Do setsebool -P ftp_home_dir 1 ***** Plugin catchall_boolean (47.5 confidence) suggests ****************** If you want to allow ftpd to full access Then you must tell SELinux about this by enabling the 'ftpd_full_access' boolean. You can read 'None' man page for more details. Do setsebool -P ftpd_full_access 1 ***** Plugin catchall (6.38 confidence) suggests ************************** .....(下面省略)..... # 基本上,你會看到有個特殊字體的部份,就是 sealert 那一行。雖然下面已經列出可能的解決方案了, # 就是一堆底線那些東西。至少就有三個解決方案 (最后一個沒列出來),哪種才是正確的? # 為了了解正確的解決方案,我們還是還執行一下 sealert 那行吧!看看情況再說! # 4\. 通過 sealert 的解決方案來處理問題 [root@study ~]# sealert -l 3a57aad3-a128-461b-966a-5bb2b0ffa0f9 SELinux is preventing /usr/sbin/vsftpd from lock access on the file /home/ftptest/test.txt. # 下面說有 47.5% 的概率是由于這個原因所發生,并且可以使用 setsebool 去解決的意思! ***** Plugin catchall_boolean (47.5 confidence) suggests ****************** If you want to allow ftp to home dir Then you must tell SELinux about this by enabling the 'ftp_home_dir' boolean. You can read 'None' man page for more details. Do setsebool -P ftp_home_dir 1 # 下面說也是有 47.5% 的概率是由此產生的! ***** Plugin catchall_boolean (47.5 confidence) suggests ****************** If you want to allow ftpd to full access Then you must tell SELinux about this by enabling the 'ftpd_full_access' boolean. You can read 'None' man page for more details. Do setsebool -P ftpd_full_access 1 # 下面說,僅有 6.38% 的可信度是由這個情況產生的! ***** Plugin catchall (6.38 confidence) suggests ************************** If you believe that vsftpd should be allowed lock access on the test.txt file by default. Then you should report this as a bug. You can generate a local policy module to allow this access. Do allow this access for now by executing: # grep vsftpd /var/log/audit/audit.log &#124; audit2allow -M mypol # semodule -i mypol.pp # 下面就重要了!是整個問題發生的主因~最好還是稍微瞧一瞧! Additional Information: Source Context system_u:system_r:ftpd_t:s0-s0:c0.c1023 Target Context unconfined_u:object_r:user_home_t:s0 Target Objects /home/ftptest/test.txt [ file ] Source vsftpd Source Path /usr/sbin/vsftpd Port &lt;Unknown&gt; Host station3-39.gocloud.vm Source RPM Packages vsftpd-3.0.2-9.el7.x86_64 Target RPM Packages Policy RPM selinux-policy-3.13.1-23.el7.noarch Selinux Enabled True Policy Type targeted Enforcing Mode Permissive Host Name station3-39.gocloud.vm Platform Linux station3-39.gocloud.vm 3.10.0-229.el7.x86_64 #1 SMP Fri Mar 6 11:36:42 UTC 2015 x86_64 x86_64 Alert Count 3 First Seen 2015-08-09 01:00:12 CST Last Seen 2015-08-09 02:55:57 CST Local ID 3a57aad3-a128-461b-966a-5bb2b0ffa0f9 Raw Audit Messages type=AVC msg=audit(1439060157.358:635): avc: denied { lock } for pid=5029 comm="vsftpd" path="/home/ftptest/test.txt" dev="dm-2" ino=141 scontext=system_u:system_r:ftpd_t:s0-s0: c0.c1023 tcontext=unconfined_u:object_r:user_home_t:s0 tclass=file type=SYSCALL msg=audit(1439060157.358:635): arch=x86_64 syscall=fcntl success=yes exit=0 a0=4 a1=7 a2=7fffceb8cbb0 a3=0 items=0 ppid=5024 pid=5029 auid=4294967295 uid=1001 gid=1001 euid=1001 suid=1001 fsuid=1001 egid=1001 sgid=1001 fsgid=1001 tty=(none) ses=4294967295 comm=vsftpd exe=/usr/sbin/vsftpd subj=system_u:system_r:ftpd_t:s0-s0:c0.c1023 key=(null) Hash: vsftpd,ftpd_t,user_home_t,file,lock ``` 經過上面的測試,現在我們知道主要的問題發生在 SELinux 的 type 不是 vsftpd_t 所能讀取的原因~ 經過仔細觀察 test.txt 文件的類型,我們知道他原本就是主文件夾,因此是 user_home_t 也沒啥了不起的啊!是正確的~ 因此,分析兩個比較可信 (47.5%) 的解決方案后,可能是與 ftp_home_dir 比較有關啊!所以,我們應該不需要修改 SELinux type, 修改的應該是 SELinux rules 才對!所以,這樣做看看: ``` # 1\. 先確認一下 SELinux 的模式,然后再瞧一瞧能否下載 test.txt,最終使用處理方式來解決~ [root@study ~]# getenforce Enforcing [root@study ~]# curl ftp://ftptest:myftp123@localhost/~/test.txt curl: (78) RETR response: 550 # 確定還是無法讀取的喔! [root@study ~]# setsebool -P ftp_home_dir 1 [root@study ~]# curl ftp://ftptest:myftp123@localhost/~/test.txt testing # OK!太贊了!處理完畢!現在使用者可以在自己的主文件夾上傳/下載文件了! # 2\. 開始下載其他文件試看看啰! [root@study ~]# curl ftp://ftptest:myftp123@localhost/~/sysctl.conf # System default settings live in /usr/lib/sysctl.d/00-system.conf. # To override those settings, enter new settings here, or in an /etc/sysctl.d/&lt;name&gt;.conf file # # For more information, see sysctl.conf(5) and sysctl.d(5). ``` 沒問題喔!通過修改 SELinux rule 的布林值,現在我們就可以使用一般帳號在 FTP 服務來上傳/下載數據啰!非常愉快吧! 那萬一我們還有其他的目錄也想要通過 FTP 來提供這個 ftptest 用戶上傳與下載呢?往下瞧瞧~ * 一般帳號用戶從非正規目錄上傳/下載文件 假設我們還想要提供 /srv/gogogo 這個目錄給 ftptest 用戶使用,那又該如何處理呢?假設我們都沒有考慮 SELinux , 那就是這樣的情況: ``` # 1\. 先處理好所需要的目錄數據 [root@study ~]# mkdir /srv/gogogo [root@study ~]# chgrp ftptest /srv/gogogo [root@study ~]# echo "test" &gt; /srv/gogogo/test.txt # 2\. 開始直接使用 ftp 觀察一下數據! [root@study ~]# curl ftp://ftptest:myftp123@localhost//srv/gogogo/test.txt curl: (78) RETR response: 550 # 有問題喔!來瞧瞧登錄文件怎么說! [root@study ~]# grep sealert /var/log/messages &#124; tail Aug 9 04:23:12 station3-39 setroubleshoot: SELinux is preventing /usr/sbin/vsftpd from read access on the file test.txt. For complete SELinux messages. run sealert -l 08d3c0a2-5160-49ab-b199-47a51a5fc8dd [root@study ~]# sealert -l 08d3c0a2-5160-49ab-b199-47a51a5fc8dd SELinux is preventing /usr/sbin/vsftpd from read access on the file test.txt. # 雖然這個可信度比較高~不過,因為會全部放行 FTP ,所以不太考慮! ***** Plugin catchall_boolean (57.6 confidence) suggests ****************** If you want to allow ftpd to full access Then you must tell SELinux about this by enabling the 'ftpd_full_access' boolean. You can read 'None' man page for more details. Do setsebool -P ftpd_full_access 1 # 因為是非正規目錄的使用,所以這邊加上默認 SELinux type 恐怕會是比較正確的選擇! ***** Plugin catchall_labels (36.2 confidence) suggests ******************* If you want to allow vsftpd to have read access on the test.txt file Then you need to change the label on test.txt Do # semanage fcontext -a -t FILE_TYPE 'test.txt' where FILE_TYPE is one of the following: NetworkManager_tmp_t, abrt_helper_exec_t, abrt_tmp_t, abrt_upload_watch_tmp_t, abrt_var_cache_t, abrt_var_run_t, admin_crontab_tmp_t, afs_cache_t, alsa_home_t, alsa_tmp_t, amanda_tmp_t, antivirus_home_t, antivirus_tmp_t, apcupsd_tmp_t, ... Then execute: restorecon -v 'test.txt' ***** Plugin catchall (7.64 confidence) suggests ************************** If you believe that vsftpd should be allowed read access on the test.txt file by default. Then you should report this as a bug. You can generate a local policy module to allow this access. Do allow this access for now by executing: # grep vsftpd /var/log/audit/audit.log &#124; audit2allow -M mypol # semodule -i mypol.pp Additional Information: Source Context system_u:system_r:ftpd_t:s0-s0:c0.c1023 Target Context unconfined_u:object_r:var_t:s0 Target Objects test.txt [ file ] Source vsftpd .....(下面省略)..... ``` 因為是非正規目錄啊,所以感覺上似乎與 semanage 那一行的解決方案比較相關~接下來就是要找到 FTP 的 SELinux type 來解決啰! 所以,讓我們查一下 FTP 相關的數據啰! ``` # 3\. 先查看一下 /var/ftp 這個地方的 SELinux type 吧! [root@study ~]# ll -Zd /var/ftp drwxr-xr-x. root root system_u:object_r:public_content_t:s0 /var/ftp # 4\. 以 sealert 建議的方法來處理好 SELinux type 啰! [root@study ~]# semanage fcontext -a -t public_content_t "/srv/gogogo(/.*)?" [root@study ~]# restorecon -Rv /srv/gogogo [root@study ~]# curl ftp://ftptest:myftp123@localhost//srv/gogogo/test.txt test # 喔耶!終于再次搞定喔! ``` 在這個范例中,我們是修改了 SELinux type 喔!與前一個修改 SELinux rule 不太一樣!要理解理解喔! * 無法變更 FTP 連線端口問題分析與解決 在某些情況下,可能你的服務器軟件需要開放在非正規的端口,舉例來說,如果因為某些政策問題,導致 FTP 啟動的正常的 21 號端口無法使用, 因此你想要啟用在 555 號端口時,該如何處理呢?基本上,既然 SELinux 的主體程序大多是被受限的網絡服務,沒道理不限制放行的端口啊! 所以,很可能會出問題~那就得要想想辦法才行! ``` # 1\. 先處理 vsftpd 的配置文件,加入換 port 的參數才行! [root@study ~]# vim /etc/vsftpd/vsftpd.conf # 請按下大寫的 G 跑到最后一行,然后新增加下面這行設置!前面不可以留白! listen_port=555 # 2\. 重新啟動 vsftpd 并且觀察登錄文件的變化! [root@study ~]# systemctl restart vsftpd [root@study ~]# grep sealert /var/log/messages Aug 9 06:34:46 station3-39 setroubleshoot: SELinux is preventing /usr/sbin/vsftpd from name_bind access on the tcp_socket port 555\. For complete SELinux messages. run sealert -l 288118e7-c386-4086-9fed-2fe78865c704 [root@study ~]# sealert -l 288118e7-c386-4086-9fed-2fe78865c704 SELinux is preventing /usr/sbin/vsftpd from name_bind access on the tcp_socket port 555. ***** Plugin bind_ports (92.2 confidence) suggests ************************ If you want to allow /usr/sbin/vsftpd to bind to network port 555 Then you need to modify the port type. Do # semanage port -a -t PORT_TYPE -p tcp 555 where PORT_TYPE is one of the following: certmaster_port_t, cluster_port_t, ephemeral_port_t, ftp_data_port_t, ftp_port_t, hadoop_datanode_port_t, hplip_port_t, port_t, postgrey_port_t, unreserved_port_t. .....(后面省略)..... # 看一下信任度,高達 92.2% 耶!幾乎就是這家伙~因此不必再看~就是他了!比較重要的是, # 解決方案里面,那個 PORT_TYPE 有很多選擇~但我們是要打開 FTP 端口嘛!所以, # 就由后續數據找到 ftp_port_t 那個項目啰!帶入實驗看看! # 3\. 實際帶入 SELinux 端口修訂后,在重新啟動 vsftpd 看看 [root@study ~]# semanage port -a -t ftp_port_t -p tcp 555 [root@study ~]# systemctl restart vsftpd [root@study ~]# netstat -tlnp Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1167/sshd tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 1598/master tcp6 0 0 :::555 :::* LISTEN 8436/vsftpd tcp6 0 0 :::22 :::* LISTEN 1167/sshd tcp6 0 0 ::1:25 :::* LISTEN 1598/master # 4\. 實驗看看這個 port 能不能用? [root@study ~]# curl ftp://localhost:555/pub/ -rw-r--r-- 1 0 0 221 Oct 29 2014 securetty -rw-r--r-- 1 0 0 225 Mar 06 03:05 sysctl.conf ``` 通過上面的幾個小練習,你會知道在正規或非正規的環境下,如何處理你的 SELinux 問題哩!仔細研究看看啰!
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看