nginx转发丢失端口问题

nginx对于redirect location的处理,会造成端口丢失的现象。针对nginx处理非80标准端口进行redirect时导致端口丢失的问题,本文主要介绍nginx的反向代理和访问目录缺失/这两种情形

以下为两种情形的参考范例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 反向代理
listen 26479 default_server;
location / {
root /var/www/html;
proxy_pass http://127.0.0.1:8080/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

# 访问/gitlab的时候会自动加上/成为/gitlab/
listen 26479 default_server;
location /gitlab {
root /var/www/html;
}

反向代理

查看nginx官方文档提及的说明:

1
2
3
An unchanged “Host” request header field can be passed like this:

proxy_set_header Host $http_host;

同时参考gitlab-ce使用非标准端口访问的方案,查看gitlab-ce的nginx配置如下:

proxy_set_header Host $http_host;

通过查看nginx软件包,发现nginx已提供参考文件/etc/nginx/proxy_params

1
2
3
4
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;

由于我使用的centos下面手动编译的nginx并未找到proxy_params,我的nginx位于/usr/local/nginx,于是通过vim /usr/local/nginx/conf/proxy_params输入以上内容,配置nginx的location如下:

1
2
3
4
location /gitlab {
proxy_pass http://127.0.0.1:9090/gitlab;
include proxy_params;
}

也可以手工输入proxy_params的内容到location配置段下

访问目录缺失/

比如$document_root存在data/index.html文件,但是访问的时候最后没加/,nginx会自动给你带上/,返回一个301重定向(这个行为和apache一致),但是当nginx监听的是非标准端口,这个301返回的Location没有端口号,导致浏览器请求出错。用curl可以很明显的看到这一点:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
[~]# curl -v 127.0.0.1:9090/data
* About to connect() to 127.0.0.1 port 9090 (#0)
* Trying 127.0.0.1...
* Connected to 127.0.0.1 (127.0.0.1) port 9090 (#0)
> GET /data HTTP/1.1
> User-Agent: curl/7.29.0
> Host: 127.0.0.1:9090
> Accept: */*
>
< HTTP/1.1 301 Moved Permanently
* Server nginx is not blacklisted
< Server: nginx
< Date: Mon, 26 Feb 2018 02:20:49 GMT
< Content-Type: text/html; charset=utf-8
< Content-Length: 178
< Connection: keep-alive
< Cache-Control: no-cache
< Location: http://127.0.0.1/data/
<
<html>
<head><title>301 Moved Permanently</title></head>
<body bgcolor="white">
<center><h1>301 Moved Permanently</h1></center>
<hr><center>nginx</center>
</body>
</html>
* Connection #0 to host 127.0.0.1 left intact

可以看到Location端口号丢失了,这个和反向代理不一样。通过google搜索,在stackoverflow的question找到了解决方案:

1
2
3
if (-d $request_filename) {
rewrite [^/]$ $scheme://$http_host$uri/ permanent;
}

通过对URL进行重写带上端口

分享到