不要一上來就關(guān)閉 SELinux,五分鐘帶你搞懂 SELinux 是什么鬼?
今天分享一下SELinux。
在一些教程中,往往會讓你一開始就將SELinux關(guān)閉,但生產(chǎn)環(huán)境中有些是不允許關(guān)閉的,是有必要深入學(xué)習(xí)一下SELinux。篇幅有點長,希望耐心看完。
在使用 Linux 的過程中,你可能遇到過下面這些場景:
- 權(quán)限全給了,服務(wù)還是無法訪問文件;
- 日志里一堆 “permission denied”,可你偏偏就是 root;
- 改了配置,重啟沒報錯,就是跑不起來……
如果你遇到這些靈異事件,那大概率是——SELinux 在背后搞鬼!
一、 什么是 SELinux?
SELinux(Security-Enhanced Linux) 是由美國國家安全局(NSA)最初開發(fā)的一套 安全訪問控制機制,它為 Linux 系統(tǒng)提供了比傳統(tǒng)用戶權(quán)限(如 chmod、chown)更強、更細粒度的安全控制。
即使是 root 用戶,也必須遵守它的規(guī)則!
二、 為什么要有 SELinux?
傳統(tǒng)的 Linux 安全機制靠文件權(quán)限控制,但它有一個致命缺陷:
root 可以為所欲為。
一旦某個服務(wù)被攻擊拿到 root 權(quán)限,攻擊者就能橫著走。而 SELinux 通過強制訪問控制(MAC),哪怕你是 root,只要沒被允許,也寸步難行。
三、SELinux是怎么工作的
1. 標(biāo)簽系統(tǒng):給對象貼標(biāo)簽
在 SELinux 眼里,每個文件、目錄、進程、端口都有一個“安全上下文”,本質(zhì)就是一個標(biāo)簽。例如:
ls -Z /var/www/html/index.html
上圖 httpd_sys_content_t 就是該文件的 SELinux 類型標(biāo)簽。
2. 策略規(guī)則
系統(tǒng)有一套策略規(guī)則(Policy),明確規(guī)定:
哪種類型的進程,能訪問哪種類型的對象,以什么方式訪問(讀、寫、執(zhí)行等)。
比如:
- 類型為 httpd_t 的進程(例如 nginx、httpd)
- 可以讀取類型為 httpd_sys_content_t 的文件
- 不可以寫這些文件,除非文件被標(biāo)記為 httpd_sys_rw_content_t
只要行為不符合規(guī)則,哪怕權(quán)限沒問題,訪問照樣被拒絕!
通過下面命令可以查看所有規(guī)則類型:
semanage fcontext -l
3. 整體的工作過程:
1. 進程發(fā)起訪問請求(如httpd訪問`/var/www/html/index.html`)
2. 內(nèi)核SELinux模塊攔截該請求
3. 獲取進程和目標(biāo)對象的安全上下文
- 進程類型:`httpd_t`
- 文件類型:`httpd_sys_content_t`
4. 在AVC(訪問向量緩存)中查找權(quán)限
- 有記錄:允許或拒絕
- 無記錄:查詢SELinux策略決策模塊
5. 策略模塊判斷是否允許訪問
- 比如是否允許 `httpd_t` 類型訪問 `httpd_sys_content_t` 文件進行`read`操作
6. 結(jié)果反饋內(nèi)核:允許 or 拒絕
7. 內(nèi)核執(zhí)行或拒絕該訪問操作
8. 如果被拒絕,則在日志中記錄AVC拒絕信息(/var/log/audit/audit.log)
四、SELinux 的三種工作模式
使用 getenforce 命令可以查看當(dāng)前模式:
getenforce
三種模式如下:
模式 | 描述 |
Enforcing | 強制執(zhí)行 SELinux 策略,違規(guī)操作將被阻止 |
Permissive | 只記錄違規(guī)操作,不阻止(適合排查問題) |
Disabled | 完全關(guān)閉 SELinux |
臨時切換模式(重啟后失效):
setenforce 0 # 切換到 Permissive
setenforce 1 # 切換回 Enforcing
永久修改需編輯配置文件 /etc/selinux/config:重啟才生效
SELINUX=enforcing
# 可選值:enforcing、permissive、disabled
# 也可以直接一條命令修改
sed -i "s#=enforcing#=disabled#g" /etc/selinux/config
五、經(jīng)典場景
1. nginx 無法讀取自定義目錄
你把網(wǎng)站內(nèi)容放到 /data/www,nginx 報 403:
ls -Z /data/www
發(fā)現(xiàn)目錄類型是 default_t,而不是 nginx 允許的類型。
- 臨時解決方法:
chcon -R -t httpd_sys_content_t /data/www
- 永久更改(推薦):
# 會保存在SELinux策略數(shù)據(jù)庫
semanage fcontext -a -t httpd_sys_content_t "/data/www(/.*)?"
restorecon -Rv /data/www
2. 服務(wù)監(jiān)聽端口被阻止
比如某服務(wù)想監(jiān)聽 8080 端口,結(jié)果啟動失敗。
- 查看當(dāng)前允許的端口:
# 如果沒有8080端口就會被攔截
semanage port -l | grep http_port_t
- 添加允許的端口:
semanage port -a -t http_port_t -p tcp 8080
3. Docker 容器莫名權(quán)限問題
Docker 默認(rèn)使用 container_t 類型運行容器,如果你掛載了宿主機目錄,但標(biāo)簽不對,也會被 SELinux 拒絕。
解決方案之一:
-v /data:/data:Z # 自動設(shè)置 SELinux 標(biāo)簽
六、SELinux相關(guān)常用命令
命令 | 用途 |
getenforce | 查看當(dāng)前 SELinux 模式 |
setenforce | 臨時切換模式 |
ls -Z | 查看文件或目錄的標(biāo)簽 |
ps -eZ | 查看進程的標(biāo)簽 |
chcon | 臨時修改標(biāo)簽(重啟失效) |
restorecon | 恢復(fù)默認(rèn)標(biāo)簽(結(jié)合 semanage 使用) |
semanage | 配置永久標(biāo)簽、端口、布爾值等 |
七、到底要不要開啟 SELinux?
下面是一些建議:
場景 | 建議 |
生產(chǎn)環(huán)境 | 強烈建議開啟 Enforcing |
測試環(huán)境 | 建議用 Permissive 模式排查問題 |
學(xué)習(xí)/開發(fā)環(huán)境 | 可關(guān)閉,但最好學(xué)會調(diào)試 SELinux |
關(guān)閉 SELinux 雖然簡單粗暴,但也等于把“系統(tǒng)最后一道防線”拆了,得不償失。
SELinux 并不復(fù)雜,它只是更嚴(yán)謹(jǐn)。
當(dāng)別人還在為“權(quán)限沒問題卻訪問不了”頭禿時,你已經(jīng)能輕松用 semanage 和 restorecon 一鍵修復(fù)。