在客戶機上,當zabbix-server指示zabbix-agent執行命令的時候,不管是監控項里面的shell命令,還是報警之后執行的遠程命令,往往都會執行不成功,主要原因就是被linux各種安全措施給攔截了。在redhat和centos中尤其明顯。
一、程序,網絡權限
比如下面是一個基於ncat(nc)命令的監控項,用來監控客戶機能否連通某個TCP端口,探測遠程端口是否開啟。
該文件放置在/etc/zabbix/zabbix_agentd.d/ 下面
- UserParameter=custom.ncat[*],nc -w 1 -z $1 $2 < /dev/null && echo "success"
然后當我使用zabbix-server遠程執行這個命令的時候,就會被selinux攔住,報錯如下
- zabbix_get -s 192.168.2.169 -k "custom.ncat[172.17.0.2,3306]"
- Ncat: Permission denied.
只有當我們在客戶機上設置
- setenforce 0
暫時停止掉selinux的攔截行為,才能得到正常的結果,但是關閉selinux會增加操作系統被入侵的風險,那么應該怎么辦呢。
報錯的意思說,zabbix-agent沒有權限去調用ncat命令。但是注意,如果把上面的ncat命令刪掉,只保留echo命令,是可以正常執行的,那么我們首先檢查一下這幾個文件的可執行權限
- [root@jdftp zabbix_agentd.d]# ls -Z /usr/bin/echo
- -rwxr-xr-x. root root system_u:object_r:bin_t:s0 /usr/bin/echo
- [root@jdftp zabbix_agentd.d]# ls -Z /usr/bin/nc
- lrwxrwxrwx. root root system_u:object_r:bin_t:s0 /usr/bin/nc -> ncat
- [root@jdftp zabbix_agentd.d]# ls -Z /usr/bin/ncat
- -rwxr-xr-x. root root system_u:object_r:bin_t:s0 /usr/bin/ncat
(注意:如果zabbix命令調用的是nc,那么會報Permission denied,nc沒有執行權限,表示無權限,而調用ncat的話,不會報錯,ncat會告訴你該端口不通,但實際是通的,此時ncat可執行但是ncat訪問誰都不通)
發現這三個文件的可執行權限是一樣的,那么既然echo能執行,ncat也可以才對。那么我們要想調查原因就需要去查看一下selinux的攔截日志了。
- tail /var/log/messages
- ......
- Jun 1 09:30:20 jdftp setroubleshoot: SELinux is preventing /usr/sbin/zabbix_agentd from name_connect access on the tcp_socket port 3306. For complete SELinux messages run: sealert -l 7d3b5686-8eb8-45ae-90f3-00f3b66bd827
- Jun 1 09:30:20 jdftp python: SELinux is preventing /usr/sbin/zabbix_agentd from name_connect access on the tcp_socket port 3306.#012#012***** Plugin catchall (100. confidence) suggests **************************#012#012If you believe that zabbix_agentd should be allowed name_connect access on the port 3306 tcp_socket by default.#012Then you should report this as a bug.#012You can generate a local policy module to allow this access.#012Do#012allow this access for now by executing:#012# ausearch -c 'zabbix_agentd' --raw | audit2allow -M my-zabbixagentd#012# semodule -i my-zabbixagentd.pp#012
上面的意思大概是說,SELinux攔截了/usr/sbin/zabbix_agentd程序連接TCP端口的網絡行為,而ncat與echo這類程序最大不同就在於他需要調用核心的網絡接口,selinux攔截的話那么ncat就失去作用了。好在selinux的審計日志非常任性化,直接把放開權限的方法給你寫到日志里去了,我們只需執行即可。
- # ausearch -c 'zabbix_agentd' --raw | audit2allow -M my-zabbixagentd
- ******************** IMPORTANT ***********************
- To make this policy package active, execute:
- semodule -i my-zabbixagentd.pp
- # semodule -i my-zabbixagentd.pp
通過上面兩行就可以把ncat的網絡限制給去掉了,這樣我們既保證了zabbix-agent的正常運行,也不妨礙selinux保護我們的系統。
二、root權限
第二種情況是當我們設置了觸發器報警后的執行命令,比如檢測到80端口不通之后自動重啟nginx,也就是所謂的遠程命令,這個在zabbix的官方手冊上已經給出了解決方案,就是讓zabbix執行sudo命令,提升權限到root。但是sudo不是誰想執行就能執行的,需要修改sudoers配置文件,指定zabbix-agent可以執行哪些命令,原文如下
訪問權限
確保'zabbix'用戶具有已配置命令的執行權限。可能有興趣使用 sudo 來訪問特權命令。 要配置訪問,請以root身份執行:
# visudo
可以在 sudoers文件中使用的行:
# allows 'zabbix' user to run all commands without password. zabbix ALL=NOPASSWD: ALL
# allows 'zabbix' user to restart apache without password. zabbix ALL=NOPASSWD: /etc/init.d/apache restart
NOPASSWD代表zabbix-agent可以不憑借密碼直接執行命令,因為是后台運行,所以不需要輸入密碼。后面的ALL最好換成具體執行的命令,因為ALL對系統來說非常危險,授權過大。比如要授予上面ncat的sudo權限就可以這樣寫
- #visudo
- ## Allow root to run any commands anywhere
- root ALL=(ALL) ALL
- zabbix ALL=NOPASSWD: /usr/bin/nc
注:root那一行是本來就有的,命令只需寫到nc,不要寫后面的-w -z等參數,不然保存時會報錯。同理對於其他的后面有參數的命令,都只需要寫到可執行文件本身即可。