CentOS 下 Nginx 代理被 SELinux 阻断的一个解决参考

nginx若打算对某个server做中转,一个简单的方法是在/etc/nginx/conf.d/目录下添加一个.conf文件,内容如下:

server {
listen *:80;
server_name sample.argcv.com;
location / {
# If you use https make sure you disable gzip compression
# to be safe against BREACH attack
# gzip off;

proxy_read_timeout 300; # Some requests take more than 30 seconds.
proxy_connect_timeout 300; # Some requests take more than 30 seconds.
proxy_redirect off;

proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

proxy_pass http://localhost:8080/;
}
}

这样当用户访问该机器,host是sample.argcv.com的时候,此配置生效,访问本地8080端口的内容.这样有很多好处,比如它可以让各个http服务共享80端口,而且我们可以用iptables屏蔽掉其它端口,提高系统的安全.

但是,当我如此设置后,dns解析到该机器,然后发现并没有如期望的那样得到正确的返回结果.而是一个502错误.

检查error log,发现如下的错误记录:

2015/02/03 20:24:34 [error] 82979#0: *356 connect() failed (111: Connection refused) while connecting to upstream, client: 127.0.0.1, server: sample.argcv.com, request: "GET / HTTP/1.1", upstream: "http://[::1]:8080/", host: "sample.argcv.com"

关键词是 Connection refused, 但实际上问题是Permission denied.

我们检查下audit log,可以发现如下错误记录.

# cat /var/log/audit/audit.log | grep denied | grep nginx
type=AVC msg=audit(1422882203.863:4981): avc: denied { name_connect } for pid=9068 comm="nginx" dest=8080 scontext=system_u:system_r:httpd_t:s0 tcontext=system_u:object_r:tor_port_t:s0 tclass=tcp_socket

解决方法是加上一些规则即可. 首先移动到/tmp文件夹下,执行命令如下

# cat /var/log/audit/audit.log | grep nginx | grep denied | audit2allow -M mynginx
******************** IMPORTANT ***********************
To make this policy package active, execute:

semodule -i mynginx.pp

# semodule -i mynginx.pp

就大功告成了.

它其实就是自动生成一些规则,让selinux可以放行一些本来被denied的内容. 若你有兴趣,也可以打开它看看如下.

# cat mynginx.te

module mynginx 1.0;

require {
type tor_port_t;
type commplex_main_port_t;
type httpd_t;
class tcp_socket name_connect;
}

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

#!!!! This avc can be allowed using the boolean 'httpd_can_network_connect'
allow httpd_t commplex_main_port_t:tcp_socket name_connect;

#!!!! This avc is allowed in the current policy
allow httpd_t tor_port_t:tcp_socket name_connect;

这些 .pp 文件你可以在 /etc/selinux/targeted/modules/active/modules 目录下找到。以后若有必要，也可以酌情清理什么的。

Note: 在后来版本，这个目录被移到了 /etc/selinux/targeted/active 下。

对它还有不解?从这个文档(或者这个)开始一路搜寻来满足你的更多的好奇心吧~