我在从 Nginx 重定向到 gunicorn 时遇到问题。我使用proxy_pass
重定向到https://127.0.0.1:5000
,但重定向被发送到https://[::1]:5000
。
这是我自己的.conf
文件,其中包含nginx.conf
:
server {
listen 80;
server_name mydomain.no www.mydomain.no myotherdomain.no;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl;
add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";
server_name mydomain.no www.mydomain.no myotherdomain.no;
ssl_certificate /path/to/chain;
ssl_certificate_key /path/to/private/key;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!MD5;
root /var/www/html/;
index index.html;
charset UTF-8;
location /api {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $http_host;
proxy_pass https://127.0.0.1:5000;
}
}
这是我的nginx.conf
文件:
user django django;
worker_processes 1;
error_log /path/to/error.log warn;
pid /path/to/nginx.pid;
events {
worker_connections 1024;
}
http {
include /path/to/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /path/to/access.log main;
sendfile on;
keepalive_timeout 65;
include /path/to/conf.d/*.conf;
}
最后include
包含我的 .conf 文件,它是conf.d
目录中唯一的文件(我也检查了隐藏文件)。
今天我启动时,将proxy_pass
设置为localhost
,但尝试连接到 时出现 502 错误mydomain.no/api/door
。我做的第一件事是检查它是否mydomain.no:5000/api/door
正常工作,结果确实如此。因此,我去检查error.log
。在那里我发现了这个错误:
2016/02/06 06:35:23 [error] 14280#0: *18082 connect() failed (111: Connection refused)
while connecting to upstream, client: nnn.nnn.nnn.nnn, server: mydomain.no,
request: "GET /api/door HTTP/1.1", upstream: "https://[::1]:5000/api/door", host:
"mydomain.no", referrer: "https://mydomain.no/"
如您所见,出于某种原因,Nginx 重定向到 IPv6 localhost。然后我尝试使用 更改localhost
为显式 IPv4 127.0.0.1
,但仍然收到完全相同的错误。
为了提供尽可能多的(可能)相关信息,这里nginx -V
也是我的(格式化以便于阅读):
nginx version: nginx/1.6.3
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-4) (GCC)
TLS SNI support enabled
configure arguments: --prefix=/usr/share/nginx --sbin-path=/usr/sbin/nginx
--conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log
--http-log-path=/var/log/nginx/access.log
--http-client-body-temp-path=/var/lib/nginx/tmp/client_body
--http-proxy-temp-path=/var/lib/nginx/tmp/proxy
--http-fastcgi-temp-path=/var/lib/nginx/tmp/fastcgi
--http-uwsgi-temp-path=/var/lib/nginx/tmp/uwsgi
--http-scgi-temp-path=/var/lib/nginx/tmp/scgi --pid-path=/run/nginx.pid
--lock-path=/run/lock/subsys/nginx --user=nginx --group=nginx
--with-file-aio --with-ipv6 --with-http_ssl_module
--with-http_spdy_module --with-http_realip_module
--with-http_addition_module --with-http_xslt_module
--with-http_image_filter_module --with-http_geoip_module
--with-http_sub_module --with-http_dav_module --with-http_flv_module
--with-http_mp4_module --with-http_gunzip_module
--with-http_gzip_static_module --with-http_random_index_module
--with-http_secure_link_module --with-http_degradation_module
--with-http_stub_status_module --with-http_perl_module --with-mail
--with-mail_ssl_module --with-pcre --with-pcre-jit
--with-google_perftools_module --with-debug --with-cc-opt='-O2 -g -pipe
-Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong
--param=ssp-buffer-size=4 -grecord-gcc-switches
-specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -m64 -mtune=generic'
--with-ld-opt='-Wl,-z,relro -specs=/usr/lib/rpm/redhat/redhat-hardened-ld -Wl,-E'
我尝试过更改我机器的 IPv6 设置,甚至关闭所有网络接口(包括本地)的 IPv6,但都没有任何效果。因此我向你寻求帮助。是什么导致proxy_pass
始终是 IPv6?
答案1
事实证明,这个问题是由 Gunicorn 的设置方式引起的。我的同事告诉我,他们已经使用 TLS 加密进行了设置,但仔细检查后发现它根本没有使用任何加密。[::1]
错误的原因可能是 Nginx 在 IPv4 连接失败后回退到 IPv6。
只需将proxy_pass
from更改https
为 即可http
解决我的问题,同时保持加密,因为从 Nginx 到 Gunicorn 的跳转是内部的。我还将 Gunicorn 更改为仅接受本地连接,因为无论如何它只能通过 Nginx 代理进行访问。