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