我有一台 nginx 1.6.2 服务器,作为负载均衡器后面的后端运行,该服务器执行 SSL 终止。与后端服务器的所有通信都通过 HTTP 进行。
发生情况的图表:
/--http---> frontend:80 --\
client --+ +--http---> backend:8000
\--https--> frontend:443 --/
LOAD BALANCER BACKENDS
出于测试目的,我目前只有一个后端。负载均衡器运行 HAProxy 1.5,我可以对其进行一些控制。
我在后端 nginx 配置的块try_files
中有一个非常典型的指令:server
server {
server_name frontend;
...
try_files $uri $uri/ =404;
...
}
现在,默认情况下,当我访问没有尾随斜杠的目录时,例如https://frontend/somedir
,nginx 想要发送 HTTP 301 重定向到绝对 URL,如http://frontend:8000/somedir/
。
我可以使用 让 nginx 省略 8000 端口号port_in_redirect off
。
然而我似乎无法纠正http://
nginx 生成重定向时的方案。我能让 nginx 做的最好的事情就是从 重定向https://frontend/somedir
到http://frontend/somedir/
,从而有效地剥离 SSL!
负载均衡器正在发送X-Forwarded-Proto
标头,但我看不出 nginx 在制作重定向时可以参考该标头;事实上,2012 年有一个答案说nginx 根本无法做到这一点,解决方案是用 nginx 替换负载均衡器。我认为这是一个太琐碎的事情,不值得进行如此剧烈的堆栈改变。
自 2012 年以来,这里有什么变化吗?我真的不想在 HAProxy 级别重写这些重定向:如果我总是将Location:
响应标头的方案重写为与发出请求的方案相同,那么来自 Web 应用程序的实际有意 HTTPS 到 HTTP 重定向可能会被“重新 HTTPSed”。
编辑:
以下是最小化的配置,显示 nginx 生成绝对Location:
URL。请注意,没有重写。
user nobody nobody;
worker_processes auto;
worker_rlimit_nofile 4096;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
multi_accept on;
}
http {
include /etc/nginx/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 /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
# TODO: Tune fastcgi_buffers/other buffers
# Configure keepalive connections
keepalive_timeout 15;
keepalive_requests 1000;
# Hide server version.
server_tokens off;
# Do not allow any directory indexes anywhere.
# This is the default, but it is here for extra paranoia.
autoindex off;
# gzip text content.
gzip on;
gzip_vary on;
gzip_disable "msie6";
gzip_comp_level 2;
gzip_min_length 1024;
gzip_types text/css
text/plain
text/xml
application/json
application/javascript;
server {
listen 8000 default_server;
root /usr/share/nginx/html;
index index.html index.htm;
server_name localhost;
location / {
try_files $uri $uri/ =404;
}
}
}
如果你使用 curl 来查看标题——请注意,我testdir
在以下位置创建了一个目录/usr/share/nginx/html
:
[myuser@dev nginx]$ curl -i http://localhost:8000/testdir
HTTP/1.1 301 Moved Permanently
Server: nginx
Date: Thu, 26 Mar 2015 14:35:49 GMT
Content-Type: text/html
Content-Length: 178
Location: http://localhost:8000/testdir/
Connection: keep-alive
<html>
<head><title>301 Moved Permanently</title></head>
<body bgcolor="white">
<center><h1>301 Moved Permanently</h1></center>
<hr><center>nginx</center>
</body>
</html>
答案1
快进到 2019 年,您可以:
absolute_redirect off;
port_in_redirect off;
如果禁用,nginx 发出的重定向将是相对的。
答案2
您需要告诉负载均衡器在请求中重写,如下所示http
:https
proxy_redirect http:// $scheme://;