启用 SELinux 后 proxy_pass 不起作用,为啥?

Posted

技术标签:

【中文标题】启用 SELinux 后 proxy_pass 不起作用,为啥?【英文标题】:proxy_pass isn't working when SELinux is enabled, why?启用 SELinux 后 proxy_pass 不起作用,为什么? 【发布时间】:2015-02-10 16:37:28 【问题描述】:

我有一个应用程序在 8081 端口上监听,nginx 在 8080 端口上运行。代理传递语句如下所示:

$ cat /var/etc/opt/lj/output/services/abc.servicemanager.conf

location /api/abc.servicemanager/1.0  proxy_pass     http://localhost:8081;

nginx.conf 中,我将此文件包含为:

include /etc/nginx/conf.d/services/*.conf;

/etc/nginx/conf.d/service 是一个符号链接:

# ll /etc/nginx/conf.d/

lrwxrwxrwx. 1 root root   39 Dec 10 00:19 services -> ../../../var/etc/opt/lj/output/services

这是一个支持 CentOS 7.0 SELinux 的系统。如果我 setenforce 0 并使其允许,我看不到任何问题。所以文件在正确的位置,路径没有问题。如果 SELinux 正在执行,我会在审核日志中看到以下内容:

type=AVC msg=audit(1418348761.372:100930): avc:  denied   getattr  for  pid=3936 comm="nginx" path="/var/etc/opt/lj/output/services/abc.servicemanager.conf" dev="xvda1" ino=11063393 scontext=system_u:system_r:httpd_t:s0 tcontext=system_u:object_r:var_t:s0 tclass=file

我想知道如何在不禁用 SELinux 的情况下启用 Nginx 来查找 conf 文件。

【问题讨论】:

【参考方案1】:

阅读 audit2allow 并使用它创建一个策略以允许访问被拒绝的 Nginx 请求。

第 1 步涉及针对 nginxlocalconf 运行 audit2allow

$ sudo grep nginx /var/log/audit/audit.log | \
     grep denied | audit2allow -m nginxlocalconf > nginxlocalconf.te

第二步,审核结果:

$ cat nginxlocalconf.te 

module nginxlocalconf 1.0;

require 
    type httpd_t;
    type var_t;
    type transproxy_port_t;
    class tcp_socket name_connect;
    class file  read getattr open ;


#============= httpd_t ==============

#!!!! This avc can be allowed using the boolean 'httpd_can_network_connect'
allow httpd_t transproxy_port_t:tcp_socket name_connect;
allow httpd_t var_t:file  read getattr open ;

查看激活步骤:

$ sudo grep nginx /var/log/audit/audit.log | grep denied | \
   audit2allow -M nginxlocalconf
******************** IMPORTANT ***********************
To make this policy package active, execute:

semodule -i nginxlocalconf.pp

第 3 步,激活:

$ sudo semodule -i nginxlocalconf.pp

【讨论】:

我按照这个一步一步来,它的工作原理。伟大的。但我不知道我做了什么。想知道在哪里可以了解更多信息。【参考方案2】:

对于 SELinux 初学者来说值得注意的是,如果您的代理服务在 8080 上运行,您可以使用以下命令而无需编译策略。

$ sudo setsebool httpd_can_network_connect 1 -P

【讨论】:

真的与端口有关吗?我认为 SELinux 拒绝他访问配置文件:... getattr .. path="......."...。如果我错了,请纠正我。 是的,你是对的。 OP 的问题是文件系统访问问题,而不是网络连接。我应该评论 Vijay Shankar 的回答。【参考方案3】:

总是更喜欢更改类型而不是创建自定义策略。在这种情况下,Nginx 将提供 httpd_sys_content_t 类型的文件。假设您的文件位于 /var/www:

semanage fcontext -a -t httpd_sys_content_t /var/www/*
restorecon -R -v /var/www

【讨论】:

【参考方案4】:

如果您有其他端口或自定义端口,请允许:

在 http: 中显示允许端口:

semanage port -l | grep http

这是我的本地主机中的输出:

http_cache_port_t              tcp      8080, 8118, 8123, 10001-10010
http_cache_port_t              udp      3130
http_port_t                    tcp      80, 81, 443, 488, 8008, 8009, 8443, 9000
pegasus_http_port_t            tcp      5988
pegasus_https_port_t           tcp      5989

并允许 8081:

semanage port -a -t http_port_t -p tcp 8081

【讨论】:

真的与端口有关吗?我认为 SELinux 拒绝他访问配置文件:... getattr .. path="......."...。如果我错了,请纠正我。

以上是关于启用 SELinux 后 proxy_pass 不起作用,为啥?的主要内容,如果未能解决你的问题,请参考以下文章

FAQ系列 | 启用SELinux后,PHP连接MySQL异常

为啥 PHP 在启用 SELinux 的情况下不遵循符号链接?

SELinux安全机制 自定义用户环境 firewalld基础配置

SElinux,firewalld配置

关闭SELinux

Linux系统关闭SeLinux