SElinux 導致 Keepalived 檢測腳本無法執行

来源:https://www.cnblogs.com/edisonfish/archive/2023/08/16/17633140.html
-Advertisement-
Play Games

哈嘍大家好,我是鹹魚 今天我們來看一個關於 `Keepalived` 檢測腳本無法執行的問題 一位粉絲後臺私信我,說他部署的 `keepalived` 集群 `vrrp_script` 模塊中的腳本執行失敗了,但是手動執行這個腳本卻沒有任何問題 ![image](https://img2023.cn ...


哈嘍大家好,我是鹹魚

今天我們來看一個關於 Keepalived 檢測腳本無法執行的問題

一位粉絲後臺私信我,說他部署的 keepalived 集群 vrrp_script 模塊中的腳本執行失敗了,但是手動執行這個腳本卻沒有任何問題

image
這個問題也是鹹魚第一次遇到,為了能讓更多的小伙伴以後不會踩這個坑,便有了今天這篇文章

前言

在正式開始之前,我們先來簡單複習一下 Keepalived 中的資源檢測功能

vrrp_script 模塊

Keepalived 中,vrrp_script 模塊是用於定義和配置虛擬路由冗餘協議(VRRP)的自定義腳本檢查,這個模塊專門用於對集群中的服務資源進行監控

vrrp_script 模塊搭配使用的是 track_script 模塊,這個模塊中可以引入監控腳本、命令組合、Shell 語句來實現對服務資源的監控

track_script 通過調用 vrrp_script,可以靈活地定義需要監測的服務或資源,例如網路連接、服務狀態、系統資源等

當監測到故障時,Keepalived 可以觸髮狀態轉移,將主節點切換到備用節點,以確保服務的高可用性

  • 通過 killall -l 命令監測

killall 命令會發送一個信號給進程,以信號 0 為例,如果發現進程關閉或者異常,將返回狀態碼 1,反之進程運行正常,狀態碼返回0

vrrp_script nginx_check {
	script "killall -0 nginx"
	interval 2
}

track_script {
	nginx_check
}
  • 通過埠監測

檢測埠的運行狀態也是較常見的監控方式

vrrp_script nginx_check {
	script "</dev/tcp/127.0.0.1/80"
	interval 2
	fall 2
	rise 1
}

track_script {
	nginx_check
}

其中 fall表示檢測到失敗的最大次數(如果請求失敗兩次,就認為該節點發生了故障)

rise 表示如果請求一次成功,就認為該節點恢復正常

  • 通過 shell 語句監測
vrrp_script nginx_check {
	script "if [ $(pidof nginx | wc -l) -eq 0 ]; then exit 1; else exit 0; fi"
	interval 2
	fall 2
	rise 1
}

track_script {
	nginx_check
}
  • 通過腳本監測
vrrp_script nginx_check {
	script "/etc/keepalived/nginx_check.sh"
	interval 2
	fall 2
	rise 1
}

track_script {
	nginx_check
}

問題

在介紹完了 keepalived 的監測功能之後,我們來看下這個問題

我根據他的描述復現了這個場景:keepalived 通過監測上游網路來判斷該節點是否正常運行,如果到上游的網路不通,則認為該節點發生了故障

檢測腳本如下:

[root@localhost ~]# cat /etc/keepalived/check.sh 
#!/bin/bash
# 檢查上行鏈路
check_route="192.168.149.135"
ping -c 3 $check_route >/dev/null 2>&1
result=$?
echo "${date}----checking..... result:${result}" >> /tools/log.log
if [ $? -eq 0 ]; then
        exit 0          # 正常
else
        exit 1          # 鏈路異常
fi

一切準備就緒之後啟動 keepalived 服務發現報 Keepalived_vrrp[2653]: /etc/keepalived/check.sh exited with status 1

[root@localhost ~]# systemctl status keepalived.service 
● keepalived.service - LVS and VRRP High Availability Monitor
   Loaded: loaded (/usr/lib/systemd/system/keepalived.service; disabled; vendor preset: disabled)
   Active: active (running) since 三 2023-08-14 23:53:49 CST; 4min 56s ago
   ...
8月 14 23:53:49 localhost.localdomain Keepalived_vrrp[2653]: /etc/keepalived/check.sh exited with status 1
...

說明腳本沒有執行成功,返回狀態碼 1 了,我嘗試著手動執行,發現腳本沒有任何問題

[root@localhost ~]# sh /etc/keepalived/check.sh 
[root@localhost ~]# echo $?
0

排查

首先看一下 /var/log/messages(如果 keepalived 沒有專門指定日誌文件路徑,這個便是預設的日誌文件路徑)

...
Aug 14 23:53:49 localhost Keepalived_vrrp[17889]: SECURITY VIOLATION - scripts are being executed but script_security not enabled
...
Aug 14 23:53:49 localhost Keepalived_vrrp[17889]: /etc/keepalived/check.sh exited with status 1
...

SECURITY VIOLATION - scripts are being executed but script_security not enabled 這條信息引起了我的註意

”安全違規-腳本正在執行,但 script_security 未啟用“,看輸出應該是 keepalived 進程想要執行該腳本,但是受到了安全限制

既然是跟系統安全相關的,我們就先來看看這個腳本的許可權吧

# 查看腳本許可權
[root@localhost ~]# ll /etc/keepalived/check.sh 
-rwxr-xr-x. 1 root root 281 8月   9 15:52 /etc/keepalived/check.sh

# 查看是 keepalived 進程的屬主
[root@localhost ~]# ps -ef | grep keep
root      19163      1  0 01:00 ?        00:00:00 /usr/sbin/keepalived -D
...

由上面的輸出我們可以得知 keepalived 進程的屬主是 root ,而 root 用戶是可以去執行這個腳本的(有 x 許可權)

許可權沒問題,我們再來查看下 /var/log/audit/audit.log

/var/log/audit/audit.log 是一個存儲系統審計日誌的文件

這個文件記錄了系統中發生的各種安全事件、用戶操作和系統行為,以及與安全相關的信息

系統審計日誌是用來監控系統活動、檢測潛在的安全問題和追蹤系統事件的重要工具之一

...
type=SYSCALL msg=audit(1692033018.624:12555): arch=c000003e syscall=4 success=no exit=-13 a0=190abc0 a1=7ffd028eafc0 a2=7ffd028eafc0 a3=7ffd028eaae0 items=0 ppid=19472 pid=19473 auid=4294967295 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=(none) ses=4294967295 comm="check.sh" exe="/usr/bin/bash" subj=system_u:system_r:keepalived_t:s0 key=(null)

type=AVC msg=audit(1692033018.624:12555): avc:  denied  { getattr } for  pid=19473 comm="check.sh" path="/usr/bin/ping" dev="dm-0" ino=50555278 scontext=system_u:system_r:keepalived_t:s0 tcontext=system_u:object_r:ping_exec_t:s0 tclass=file permissive=0
...

我們現在來看一下上面日誌輸出表示什麼

先看第一段:

type=SYSCALL: 這個部分是系統調用事件類型。arch=c000003e syscall=4 success=no exit=-13: 這裡描述了系統調用的詳細信息,包括系統調用號、是否成功等

  • subj=system_u:system_r:keepalived_t:s0:描述了進程的安全上下文信息
  • 後面內容則是一些更多與系統調用相關的信息,如參數、進程信息、用戶信息等

再看第二段:

type=AVC: 這個部分指示了事件類型為 AVC(Access Vector Cache),是 SELinux 的訪問控制事件,

  • avc: denied { getattr }: 表示操作是一個 getattr(獲取屬性)操作,但是被拒絕。
  • pid=19473 comm="check.sh": 進程 ID 是 19473,進程名稱是 check.sh
  • path="/usr/bin/ping": 文件路徑是 /usr/bin/ping,表示被操作的文件。
  • scontext=system_u:system_r:keepalived_t:s0: 發起操作的進程的安全上下文。
  • tcontext=system_u:object_r:ping_exec_t:s0: 被操作文件的安全上下文。
  • tclass=file: 被操作對象的類型是文件。
  • permissive=0: 表示 SELinux 不是處於寬鬆模式

總結一下:

這個是 SELinux 的審計日誌,這兩條日誌記錄了一個操作,即 keepalived 進程試圖通過執行 check.sh" 腳本訪問 /usr/bin/ping 文件,但被 SELinux 拒絕了

解決

排查到這思路就逐漸清晰起來了,這是因為 SELinux 許可權導致的,在解決這個問題之前,我們先來簡單複習一下 SELinux (後面我會專門寫一篇文章來介紹 SELinux)

SELinux(Security Enhanced Linux,安全強化的 Linux) ,由美國國家安全局(NSA)開發的

為什麼要開發 SELinux

我們知道系統的賬戶主要分為系統管理員(root)和普通用戶,這兩種身份能否使用系統上面的文件資源則與 rwx 許可權設置有關

所以當某個進程想要對文件進行讀寫操作時,系統就會根據該進程的屬主和屬組去比對文件許可權,只有通過許可權檢查,才能夠進一步操作文件

這種方式被稱為自主訪問控制(Discretionary Access Control, DAC),DAC 是 Linux 操作系統中的一種基本許可權控制機制,用於限制用戶對系統資源的訪問許可權

但是 DAC 的一大問題就是當用戶獲取到進程之後,他可以通過這個進程與自己所獲得的許可權去處理對應的文件資源

萬一用戶對系統不熟悉,就很容易導致資源誤用的問題出現

舉個例子,你們公司的新人為了自身方便,將網頁所在目錄 /var/www/html 目錄的許可權設置成了 777,則代表所有進程都可以對該目錄進行讀寫

如果黑客接觸到了某個進程,就極有可能向你的系統裡面寫入某些東西

為了避免 DAC 的問題,便有了 SELinux

SELinux MAC 機制

SELinux 引入了強制訪問控制(Mandatory Access Control, MAC)機制

強制訪問控制(MAC,Mandatory Access Control)是 Linux 操作系統中一種更加嚴格和細粒度的訪問控制機制,用於加強對系統資源的保護和控制

MAC 有趣的地方在於它可以針對特定的進程與特定的文件資源來管理許可權,即使你是 root 用戶,在使用不同的進程時你所能獲取的許可權也不一定是 root

image
安全上下文

前面我們知道,SELinux 是通過 MAC 的方式來管理進程的許可權的

它控制的主體是【進程】,而【目標】則是該【進程】能否讀取的文件資源

  • 主體

SELinux 主要管理的就是進程,進程和主體可以畫上等號

  • 目標

主體能否讀寫的目標一般就是文件資源

除了策略指定之外,主體與目標的安全上下文必須一致才能夠順利讀寫

安全上下文有點類似於文件系統的 rwx ,如果設置錯誤,主體就無法讀寫目標資源了
image
安全上下文存放在文件的 inode 內,可以通過 ll -Z 命令去查看(前提是 SELinux 是開啟著的)

回到我們的案例上來,日誌輸出說進程 check.sh 試圖獲取 /usr/bin/ping 的屬性(getattr)操作,但被 SELinux 拒絕了

但是我們發現沒有這個進程

[root@localhost ~]# ps -ef | grep check

也就是說,由於 SELinux 許可權問題 ,keepalived 一開始想要調用 check.sh 腳本就失敗了

我們分別來看一下 keepalived 進程和 check.sh 的安全上下文

[root@localhost ~]# ps -eZ | grep keepalived 
system_u:system_r:keepalived_t:s0 19609 ?       00:00:00 keepalived

[root@localhost ~]# ll -Z /etc/keepalived/check.sh 
-rwxr-xr-x. root root system_u:object_r:etc_t:s0       /etc/keepalived/check.sh

可以看到 keepalived 進程的安全上下文類型為 keepalived_t;而 check.sh 的安全上下文是 etc_t

即——主體與目標的安全上下文並不一致,就算有 rwx 許可權也無法執行

  • 解決方案一:關閉 SELinux

簡單粗暴,直接關閉 SELinux ,就沒有這麼多亂七八糟的限制了

# 以 CentOS 7 為例
# 臨時關閉
[root@localhost ~]# setenforce 0

#永久關閉,將 SELINUX=enforcing 改為 SELINUX=disabled,然後保存退出
[root@localhost ~]# sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
  • 解決方案二(失敗了):修改 check.sh 的安全上下文與 keepalived 一致

我想把 check.sh 的安全上下文改成與 keepalived 一致,可是失敗了,有小伙伴知道原因嗎

[root@localhost ~]# chcon -t keepalived_t  /etc/keepalived/check.sh
chcon: 改變"/etc/keepalived/check.sh" 的環境到"system_u:object_r:keepalived_t:s0" 失敗: 許可權不夠
  • 解決方案三:修改 check.sh 的安全上下文

依舊是修改 check.sh 的安全上下文,不過這次參考了資料

[root@localhost ~]# chcon -t keepalived_unconfined_script_exec_t  /etc/keepalived/check.sh

keepalived_unconfined_script_exec_t 是一個在 SELinux 中用於標識 Keepalived 執行未限制腳本的上下文,這個上下文允許 Keepalived 進程在執行腳本時繞過一些 SELinux 限制,從而可以在需要的情況下執行腳本

  • 解決方案四:將腳本轉移到 /usr/libexec/keepalived 目錄中
# keepalived 配置
vrrp_script nginx_check {
	script "/usr/libexec/keepalived/check.sh"
	interval 2
	fall 2
	rise 1
}

這個目錄的安全上下文是 keepalived_unconfined_script_exec_t,與解決方案三同理

[root@localhost ~]# ll -Z /usr/libexec/keepalived/ -d
drwxr-xr-x. root root system_u:object_r:keepalived_unconfined_script_exec_t:s0 /usr/libexec/keepalived/
  • 解決方案五: keepalived 全局配置添加 enable_script_security 欄位

加了這個欄位意味著如果腳本路徑的任一部分對於非 root 用戶來說,都具有可寫許可權,則不會以 root 身份運行腳本

以非 root 身份運行的腳本就能夠通過 SELinux 的審查嗎?這一塊我不太懂,有懂的小伙伴可以告訴我

global_defs {
	...
	enable_script_security
	...
}

參考資料:

https://github.com/acassen/keepalived/issues/1322

https://serverfault.com/questions/709428/track-script-doesnt-work-after-keepalived-update

https://www.mankier.com/8/keepalived_selinux

https://linux.vbird.org/linux_basic/centos7/0440processcontrol.php#selinux


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • ### VS安裝Avalonia模版 執行以下命令,安裝Avalonia模版(.NET6及之前版本使用--install): ```bash dotnet new install Avalonia.Templates ``` 執行後,會安裝如下模版: ``` 模板名 短名稱 語言 標記 Avalon ...
  • # Nginx反向代理服務流式輸出設置 # 1.問題場景 提問:為什麼我部署的服務沒有流式響應 最近在重構原有的GPT項目時,遇到gpt回答速度很慢的現象。在使用流式輸出的介面時,介面響應速度居然還是達到了30s以上。 # 2.現象分析 分析現象我發現,雖然前端還是流式列印的結果,但是,好像是介面處 ...
  • 為何模塊化 模塊化是一種分治思想,不僅可以分離複雜的業務邏輯,還可以進行不同任務的分工。模塊與模塊之間相互獨立,從而構建一種松耦合的應用程式,便於開發和維護。 開發技術 .Net 6 + WPF + Prism (v8.0.0.1909) + HandyControl (v3.4.0) 知識準備 什 ...
  • 博客推行版本更新,成果積累制度,已經寫過的博客還會再次更新,不斷地琢磨,高質量高數量都是要追求的,工匠精神是學習必不可少的精神。因此,大家有何建議歡迎在評論區踴躍發言,你們的支持是我最大的動力,你們敢投,我就敢肝 ...
  • 全程我在網路上收集這些資料,太零碎了,每一個一看就會,一動手就廢,而且很多都不能實現我白嫖的夢想 我一個人折騰了快一周,現在可以正常訪問手機電腦多端訪問 給個贊再走吧 此處為沒有公網IP(回去折騰你家寬頻去,不知道可以去搜索如何獲得)和功能變數名稱的辦法 簡單的說就是想完全白嫖的那種(甚至雲伺服器(那個有公 ...
  • # 二進位包安裝mysql ## 準備 1.先查看系統中是否已存在mysql,存在將其卸載 ``` rpm -qa mysql rpm -qa mariadb yum remove xxx -y ``` 2.環境清理 清空PATH有關的mysql 註釋掉之前的$PATH 沒有就跳過這步 ``` #e ...
  • 為什麼需要設備驅動模型 內核版本發展 2.4版本之前內核沒有統一的設備驅動模型,但是可以用(例如先前的led字元設備驅動實驗,使用前需要手動調用mknod命令創建設備文件,從而進一步控制硬體)。 2.4~2.6版本內核使用devfs,掛載在/dev目錄。需要在內核驅動中創建設備文件(調用devfs_ ...
  • 本文是紅帽RHCE考題的總結,個別題目寫了多種步驟。 一、安裝和配置ansible 題目: 按照下方所述,在控制節點 bastion.lab.example.com 上安裝和配置 Ansible: 安裝所需的軟體包 創建名為/home/devops/ansible/inventory 的靜態清單文件 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...