Você precisa dizer ao balanceador de carga para reescrever http
para https
nas solicitações assim:
proxy_redirect http:// $scheme://;
Eu tenho um servidor nginx 1.6.2 executando como backend atrás de um balanceador de carga que faz a terminação SSL. Toda a comunicação com os servidores de backend passa por HTTP.
Diagrama do que está acontecendo:
/--http---> frontend:80 --\
client --+ +--http---> backend:8000
\--https--> frontend:443 --/
LOAD BALANCER BACKENDS
Para fins de teste, tenho apenas um backend no momento. O balanceador de carga executa o HAProxy 1.5, sobre o qual tenho algum controle.
Eu tenho uma diretiva try_files
bem típica no meu bloco server
na configuração do nginx de back-end:
server {
server_name frontend;
...
try_files $uri $uri/ =404;
...
}
Agora, por padrão, quando eu acesso um diretório sem uma barra, por exemplo https://frontend/somedir
, nginx deseja enviar um redirecionamento HTTP 301 para um URL absoluto como http://frontend:8000/somedir/
.
Eu posso fazer o nginx omitir o número da porta 8000 usando port_in_redirect off
.
No entanto, não consigo corrigir o esquema http://
no início do redirecionamento que o nginx está gerando. O melhor que posso fazer com que o nginx faça é um redirecionamento de https://frontend/somedir
para http://frontend/somedir/
, efetivamente removendo SSL!
O balanceador de carga está enviando um cabeçalho X-Forwarded-Proto
, mas não vejo nenhuma maneira de o nginx consultá-lo ao criar seu redirecionamento; na verdade, há uma resposta de 2012 dizendo nginx definitivo não pode fazer isso, e a solução é substituir o balanceador de carga com nginx. IMHO isso é uma coisa muito trivial para justificar uma mudança de pilha tão drástica.
Alguma coisa mudou desde 2012 aqui? Eu realmente não quero reescrever esses redirecionamentos no nível HAProxy: HTTPS intencionais reais para redirecionamentos HTTP do aplicativo da web podem obter "re-HTTPSed" se eu sempre reescrever o esquema para o cabeçalho Location:
response ser o mesmo como o esquema do pedido foi feito com.
EDITAR:
Aqui está uma configuração minimizada mostrando que o nginx produz URLs Location:
absolutos. Note que não há reescritas.
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;
}
}
}
E se você usar o curl para visualizar os cabeçalhos - note que criei um diretório testdir
em /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>
Você precisa dizer ao balanceador de carga para reescrever http
para https
nas solicitações assim:
proxy_redirect http:// $scheme://;