May 20, 2019
SELinux 策略和 Nginx 403 的问题
以此来纪念我加班的 5.20
Nginx 之类的 Httpd 服务使用非 /var/www 产生的 Permission denied 错误,原因在于权限设置有误。
2019/05/20 10:53:14 [error] 11262#0: *16 open() "/sangfor/*/*/favicon.ico" failed (13: Permission denied), client: 200.200.211.97, server: localhost, request: "GET /favicon.ico HTTP/1.1", host: "10.58.12.67", referrer: "http://10.58.12.67/"
首先 ps -aux | grep nginx
查看 Nginx 是以那个用户运行的,并查看 cat /etc/nginx/nginx.conf | grep user
配置的用户。
[[email protected] ~]# ll /sangfor/*/*/
total 16
drwxr-xr-x. 2 root root 231 May 8 15:11 3parts
-rwxr-xr-x. 1 root root 1406 May 8 15:11 favicon.ico
-rwxr-xr-x. 1 root root 2555 May 8 15:11 index.html
-rwxr-xr-x. 1 root root 1422 May 8 15:11 login.html
-rwxr-xr-x. 1 root root 205 May 8 15:11 redirect.html
drwxr-xr-x. 13 root root 156 May 8 15:11 static
[[email protected] ~]# ps -aux | grep nginx
root 11261 0.0 0.0 122896 2264 ? Ss 10:36 0:00 nginx: master process /usr/sbin/nginx
root 11262 0.0 0.0 123280 3608 ? S 10:36 0:00 nginx: worker process
root 11263 0.0 0.0 123280 3608 ? S 10:36 0:00 nginx: worker process
root 11264 0.0 0.0 123280 3608 ? S 10:36 0:00 nginx: worker process
root 11265 0.0 0.0 123280 3608 ? S 10:36 0:00 nginx: worker process
root 26868 0.0 0.0 112652 952 pts/1 R+ 11:34 0:00 grep --color=auto nginx
[[email protected] ~]# cat /etc/nginx/nginx.conf | grep user
user root;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'"$http_user_agent" "$http_x_forwarded_for"';
目标目录的确是 root
,且 Nginx 使用 root
用户启动,那么就可能是 SELinux 的问题。
使用 sestatus
或者 getemforce
查看 SELinux 的状态
➜ ~ getenforce
Enforcing
➜ ~ sestatus
SELinux status: enabled
SELinuxfs mount: /sys/fs/selinux
SELinux root directory: /etc/selinux
Loaded policy name: targeted
Current mode: enforcing
Mode from config file: enforcing
Policy MLS status: enabled
Policy deny_unknown status: allowed
Max kernel policy version: 28
SELinux 有三种模式:
enforcing
强制模式,该模式下会阻止部分操作permissive
宽松模式,该模式下只会产生警告提示,并不会阻塞操作disabled
禁用 SELinux
上面的输出是就是完全启用了的 SELinux,对于部分 Linux 命令支持一个 Z
参数,比如我们来看看 ls
的。
-Z, --context
Display security context so it fits on most displays. Displays only mode, user, group, security context and file name.
显示 SELinux 上下文,那么我们用 ls -Z
查看刚刚被阻止的文件路径
[[email protected] ~]# ls -Z /sangfor/*/*/favicon.ico
-rwxr-xr-x. root root unconfined_u:object_r:default_t:s0 /sangfor/aBDI/sdp-web/favicon.ico
而后我们去看看正常的 var/www
是什么样的配置。
[[email protected] ~]# ls -Z /var | grep www
dr-xr-xr-x. www-data www-data system_u:object_r:httpd_sys_content_t:s0 www
而 Nginx 所具有的权限又是什么样的?
[[email protected] ~]# ps -auxZ | grep nginx
system_u:system_r:httpd_t:s0 root 11261 0.0 0.0 122896 2264 ? Ss 10:36 0:00 nginx: master process /usr/sbin/nginx
system_u:system_r:httpd_t:s0 root 11262 0.0 0.0 123280 3608 ? S 10:36 0:00 nginx: worker process
system_u:system_r:httpd_t:s0 root 11263 0.0 0.0 123280 3608 ? S 10:36 0:00 nginx: worker process
system_u:system_r:httpd_t:s0 root 11264 0.0 0.0 123280 3608 ? S 10:36 0:00 nginx: worker process
system_u:system_r:httpd_t:s0 root 11265 0.0 0.0 123280 3608 ? S 10:36 0:00 nginx: worker process
对比一下其他进程的配置,先用 vi 读取无权限的文件,并 Ctrl + Z
切到后台,然后 ps -auxZ
看看结果
[[email protected] ~]# vi /sangfor/*/*/favicon.ico
[1]+ Stopped vi /sangfor/*/*/favicon.ico
[[email protected] ~]# ps -auxZ | grep favicon
unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 root 3543 0.0 0.0 126436 1816 pts/1 T 11:52 0:00 vi /sangfor/aBDI/sdp-web/favicon.ico
问题找到了,接下来看看如何修改这个参数,这里通过上面的对比,自然能发现有 2 个思路。
改变 Nginx 的配置或者改变目标目录的配置。
而改变 Nginx 的配置可能存在安全性问题,本来就是为了防止操作,如果给他所有文件的读取权限,指不定啥时候就被人端了(其实是我还不会改这个);那就只能改文件夹的配置了。
上次写清理脚本留下的经验,这种资料比较难找,自己又不会,不如去 Github 抄。
于是以 httpd_sys_content_t
这个关键词查找代码,就找到这么个文件 /etc/selinux/targeted/contexts/files/file_contexts
。1
[[email protected] ~]# cat /etc/selinux/targeted/contexts/files/file_contexts | grep httpd_sys_content
/srv/([^/]*/)?www(/.*)? system_u:object_r:httpd_sys_content_t:s0
/var/www(/.*)? system_u:object_r:httpd_sys_content_t:s0
/etc/htdig(/.*)? system_u:object_r:httpd_sys_content_t:s0
/srv/gallery2(/.*)? system_u:object_r:httpd_sys_content_t:s0
/var/lib/trac(/.*)? system_u:object_r:httpd_sys_content_t:s0
/var/lib/htdig(/.*)? system_u:object_r:httpd_sys_content_t:s0
/var/www/icons(/.*)? system_u:object_r:httpd_sys_content_t:s0
/usr/share/glpi(/.*)? system_u:object_r:httpd_sys_content_t:s0
/usr/share/htdig(/.*)? system_u:object_r:httpd_sys_content_t:s0
/usr/share/drupal.* system_u:object_r:httpd_sys_content_t:s0
/usr/share/z-push(/.*)? system_u:object_r:httpd_sys_content_t:s0
/var/www/svn/conf(/.*)? system_u:object_r:httpd_sys_content_t:s0
/usr/share/icecast(/.*)? system_u:object_r:httpd_sys_content_t:s0
/var/lib/cacti/rra(/.*)? system_u:object_r:httpd_sys_content_t:s0
/usr/share/ntop/html(/.*)? system_u:object_r:httpd_sys_content_t:s0
/usr/share/doc/ghc/html(/.*)? system_u:object_r:httpd_sys_content_t:s0
/usr/share/openca/htdocs(/.*)? system_u:object_r:httpd_sys_content_t:s0
/usr/share/selinux-policy[^/]*/html(/.*)? system_u:object_r:httpd_sys_content_t:s0
看到了熟悉的 /var/www
或许是配置在这里?
再去搜搜这个文件干啥的?SELinux: manually changing files in /etc/selinux/targeted/contexts/files/
很不幸,没发现我这个环境有 semanage
,安装一个试试,安装失败,大概我这个仓库没有
姑且用 chcon
先用着好像也还 OK
[[email protected] ~]# chcon -R -t httpd_sys_content_t /sangfor/*/*
[[email protected] ~]# ls -lZ /sangfor/*/*
drwxr-xr-x. root root unconfined_u:object_r:httpd_sys_content_t:s0 3parts
-rwxr-xr-x. root root unconfined_u:object_r:httpd_sys_content_t:s0 favicon.ico
-rwxr-xr-x. root root unconfined_u:object_r:httpd_sys_content_t:s0 index.html
-rwxr-xr-x. root root unconfined_u:object_r:httpd_sys_content_t:s0 login.html
-rwxr-xr-x. root root unconfined_u:object_r:httpd_sys_content_t:s0 redirect.html
drwxr-xr-x. root root unconfined_u:object_r:httpd_sys_content_t:s0 static
问题虽然解决了,但是 chcon
和 semanage
有啥区别嘞。
CentOS系统自带的chcon工具只能修改文件、目录等的文件类型和策略,无法对端口、消息接口和网络接口等进行管理,semanage 能有效胜任 SELinux 的相关配置工作。2
以及 chcon 只是临时修改目录的 SELinux 属性,而 semanage 会把变更写入到 /etc/selinux/targeted/contexts/files/file_contexts.local
里面,这样才能使其永远生效。3
据 SO 上面说 /etc/selinux/targeted/contexts/files/file_contexts
会被某命令覆盖掉;所以并不是很确信,这是不是真的永远生效。
其实对于这个问题,因为 SELinux 产生,那么关了 SELinux 或者修改状态,都能解决这个问题。只是或许存在安全性问题。