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/ 目录下找到。以后若有必要,也可以酌情清理什么的。

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

来自的你,很高兴你能看到这儿。若本文对你有所用处,或者内容有什么不足之处,敬请毫不犹豫给个回复。谢谢!