nginx try_files reindirizza utilizzando uno schema errato quando dietro il bilanciamento del carico di terminazione SSL (haproxy)


8

Ho un server nginx 1.6.2 in esecuzione come backend dietro un bilanciamento del carico che esegue la terminazione SSL. Tutte le comunicazioni con i server back-end passano su HTTP.

Diagramma di ciò che sta succedendo:

          /--http---> frontend:80  --\
client --+                            +--http---> backend:8000
          \--https--> frontend:443 --/

                      LOAD BALANCER                BACKENDS

A scopo di test ho solo un backend al momento. Il bilanciamento del carico esegue HAProxy 1.5, di cui ho un certo controllo.

Ho una try_filesdirettiva piuttosto tipica nel mio serverblocco nella configurazione nginx backend:

server {
    server_name frontend;
    ...
    try_files $uri $uri/ =404;
    ...
}

Ora, per impostazione predefinita, quando accedo a una directory senza una barra finale, ad esempio https://frontend/somedir, nginx vuole inviare un reindirizzamento HTTP 301 a un URL assoluto come http://frontend:8000/somedir/.

Posso fare in modo che nginx ometta il numero di porta 8000 usando port_in_redirect off.

Tuttavia, non riesco a correggere lo http://schema all'inizio del reindirizzamento che nginx sta generando. Il meglio che posso ottenere da nginx è un reindirizzamento da https://frontend/somedira http://frontend/somedir/, eliminando efficacemente SSL!

Il bilanciamento del carico sta inviando X-Forwarded-Protoun'intestazione ma non vedo alcun modo per nginx di consultarlo durante l'elaborazione del reindirizzamento; in effetti esiste una risposta per il 2012 che afferma che nginx non può assolutamente farlo e la soluzione è sostituire il bilanciamento del carico con nginx. IMHO è una cosa troppo banale per giustificare un drastico cambio di stack.

È cambiato qualcosa dal 2012 qui? Non voglio davvero riscrivere questi reindirizzamenti a livello HAProxy: i reindirizzamenti da HTTPS a HTTP intenzionali effettivi dall'applicazione Web potrebbero essere "ri-HTTPSed" se riscrivo sempre lo schema affinché l' Location:intestazione della risposta sia uguale allo schema la richiesta è stata fatta con.

MODIFICARE:

Ecco una configurazione minimizzata che mostra nginx produce Location:URL assoluti . Nota che non ci sono riscritture.

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 usi curl per visualizzare le intestazioni, nota che ho creato una directory testdirin /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>

nginx wants to send an HTTP 301 redirect to an absolute URL- nginx non lo fa a meno che tu non abbia una regola di riscrittura esplicita per farlo - mostra la tua configurazione completa.
AD7,

Ho aggiunto la configurazione, ridotta per illustrare questo problema. Non faccio riscritture esplicite.
mutron

1
È necessario configurare il bilanciamento per sostituire il protocollo Location:nell'intestazione poiché nginx non ha idea di quale fosse il protocollo originale.
Alexey Ten,

2
@AlexeyTen desideri pubblicarlo come risposta in modo che io possa approvarlo? Non ho trovato neanche un modo per farlo in nginx, quindi una modifica al bilanciamento del carico sembra davvero essere l'unico modo.
mutron

1
Questo è ancora un bug con l'ultima versione di nginX! Qualcuno sa se esiste già una segnalazione di bug? Impossibile trovarne uno.
Roel van Duijnhoven,

Risposte:



-1

È necessario dire al bilanciamento del carico di riscrivere httpper httpsle richieste in questo modo:

proxy_redirect http:// $scheme://;
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.