最近遇到一个Nginx反向代理的问题,举例来说:
有一个example.com域名,在web服务器(简称web-server,假定服务器的ip为8.8.8.8)上使用nginx反向代理本地的tomcat服务(8080端口),配置信息如下:
http {
upstream tdt_tomcat_server {
server 127.0.0.1:8080 weight=1 max_fails=3 fail_timeout=30s;
}
server {
listen 80;
server_name example.com *.example.com;
location / {
proxy_next_upstream http_502 http_504 error timeout invalid_header;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://tdt_tomcat_server;
proxy_redirect off;
}
}
}
又有一台反向代理服务器(proxy-server),因为特殊原因这台服务器对外只能使用非80端口,通过这台服务器反向代理上面的web-server,配置信息如下:
http {
upstream tdt_web_server {
server 8.8.8.8:80 weight=1 max_fails=3 fail_timeout=30s;
}
server {
listen 9000;
server_name example.com *.example.com;
location / {
proxy_next_upstream http_502 http_504 error timeout invalid_header;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://tdt_web_server;
proxy_redirect off;
}
}
}
首先将example.com域名通过hosts文件绑定ip到proxy-server上面,然后访问http://example.com:9000的时候会调整到80端口上面:
[root@proxy-server ~]# curl -I http://example.com:9000/
HTTP/1.1 302 Found
Server: nginx/1.12.0
Location: http://example.com/
Google了一下查到需要将proxy_set_header Host 设置成主机+端口的形式,即将 proxy_set_header Host $host;
修改成 proxy_set_header Host $host:$server_port;
这个时候再次访问http://example.com:9000的时候就正常了,不过还有一个问题,就是当访问 http://example.com:9000/userinfo 的时候需要用户登录才能访问,这个时候系统应该自动跳转到 http://example.com:9000/login 才对,但是确是跳转到了 http://example.com/login :
[root@proxy-server ~]# curl -I http://example.com:9000/userinfo
HTTP/1.1 302 Found
Server: nginx/1.12.0
Location: http://example.com/login
但是直接访问 http://example.com:9000/login 也是正常的。一开始想到是tomcat服务器的问题,但是如果反向代理服务器直接设置成web-server上的8080端口的话则是正常的,因此断定问题出在了nginx反向代理的设置上面,后来查阅到nginx和Tomcat集成后发生的重定向问题分析和解决这篇文章,可以通过proxy_redirect进行设置,修改后的proxy-server配置信息如下:
http {
upstream tdt_web_server {
server 8.8.8.8:80 weight=1 max_fails=3 fail_timeout=30s;
}
server {
listen 9000;
server_name example.com *.example.com;
location / {
proxy_next_upstream http_502 http_504 error timeout invalid_header;
proxy_set_header Host $host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_redirect http://$host http://$host:$server_port;
proxy_redirect off;
}
}
}
这个时候再访问 http://example.com:9000/userinfo 就自动跳转到 http://example.com:9000/login 了:
[root@proxy-server ~]# curl -I http://example.com:9000/userinfo
HTTP/1.1 302 Found
Server: nginx/1.12.0
Location: http://example.com:9000/login
最后还有一个问题需要特别注意,就是web-server中nginx的配置信息中一定不要这样设置:proxy_set_header Host $host:$server_port;,而是要设置成 proxy_set_header Host $host;,即不加端口号,否则自动跳转会失败。
参考资料:
nginx和Tomcat集成后发生的重定向问题分析和解决
Nginx + Apache trailing slash redirect
Nginx reverse proxy - requests still return port 80
解决nginx反向代理监听非80端口造成的端口丢失问题
Nginx代理非80端口