当启用SELinux时,proxy_pass无法工作,为什么?

22

我的应用程序正在监听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

这是一个启用了SELinux的CentOS 7.0系统。如果我执行setenforce 0,并将其设置为Permissive模式,那么我不会看到任何问题。因此该文件处于正确的位置,路径没有问题。如果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

我想知道如何使Nginx在不禁用SELinux的情况下找到配置文件。

4个回答

44

值得新手在SELinux上注意的是,如果您的代理服务运行在8080端口,则可以使用以下命令而无需编译策略。

$ sudo setsebool httpd_can_network_connect 1 -P

这真的与端口有关吗?我认为SELinux拒绝了他访问配置文件:... { getattr } .. path="......."...。如果我错了,请纠正我。 - Ayman Nedjmeddine
2
是的,你说得对。OP的问题是文件系统访问问题,而不是网络连接问题。我应该在Vijay Shankar的答案下发表评论。 - Cristian Romanescu
这对像我一样通过谷歌搜索而来的人非常有用! - Samuel Åslund

32

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

第一步涉及运行 audit2allow 并针对 nginxlocalconf 进行操作:

$ 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

第三步,激活:

$ sudo semodule -i nginxlocalconf.pp

我按照步骤操作,成功了。但是我不知道自己做了什么。想知道在哪里可以学到更多相关知识。 - Ppp

6

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

在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="......."...。如果我错了,请纠正我。 - Ayman Nedjmeddine

5

始终优先更改类型而不是创建自定义策略。在这种情况下,Nginx将使用httpd_sys_content_t类型提供文件。假设您的文件位于/var/www中:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接