redirection nginx try_files en utilisant un schéma incorrect lorsque derrière l'équilibreur de charge de terminaison SSL (haproxy)

8

J'ai un serveur nginx 1.6.2 fonctionnant en tant que backend derrière un équilibreur de charge qui effectue la terminaison SSL. Toutes les communications avec les serveurs principaux passent par HTTP.

Diagramme de ce qui se passe:

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

                      LOAD BALANCER                BACKENDS

À des fins de test, je n'ai qu'un seul backend pour le moment. L'équilibreur de charge exécute HAProxy 1.5, sur lequel j'ai un certain contrôle.

J'ai une try_filesdirective assez typique dans mon serverbloc dans la configuration backg nginx:

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

Désormais, par défaut, lorsque j'accède à un répertoire sans barre oblique, par exemple https://frontend/somedir, nginx veut envoyer une redirection HTTP 301 vers une URL absolue comme http://frontend:8000/somedir/.

Je peux faire nginx omettre le numéro de port 8000 en utilisant port_in_redirect off.

Cependant, je n'arrive pas à corriger le http://schéma au début de la redirection que nginx génère. Le mieux que je puisse faire pour que nginx soit une redirection de https://frontend/somedirvers http://frontend/somedir/, supprimant efficacement SSL!

L'équilibreur de charge envoie un en- X-Forwarded-Prototête mais je ne vois aucun moyen pour nginx de le consulter lors de l'élaboration de sa redirection; en fait, une réponse de 2012 indique que nginx ne peut tout simplement pas faire cela, et la solution consiste à remplacer l'équilibreur de charge par nginx. À mon humble avis, c'est une chose trop banale pour justifier un changement de pile aussi radical.

Est-ce que quelque chose a changé depuis 2012 ici? Je ne veux pas vraiment réécrire ces redirections au niveau HAProxy: les redirections HTTPS intentionnelles vers HTTP réelles à partir de l'application Web peuvent être "ré-HTTPS" si je réécris toujours le schéma de l'en- Location:tête de réponse pour qu'il soit identique au schéma la demande a été faite auprès de.

ÉDITER:

Voici une configuration minimisée montrant que nginx produit des Location:URL absolues . Notez qu'il n'y a pas de réécriture.

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;
        }
    }
}

Et si vous utilisez curl pour afficher les en-têtes - notez que j'ai créé un répertoire testdirsous /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>
mutron
la source
nginx wants to send an HTTP 301 redirect to an absolute URL- nginx ne fait cela que si vous avez une règle de réécriture explicite pour le faire - veuillez montrer votre configuration complète.
AD7six
J'ai ajouté la configuration, rognée pour illustrer simplement ce problème. Je ne fais aucune réécriture explicite.
mutron
1
Vous devez configurer votre équilibreur pour remplacer le protocole dans l'en- Location:tête car nginx n'a aucune idée de ce qu'était le protocole d'origine.
Alexey Ten
2
@AlexeyTen aimeriez-vous publier cela comme réponse afin que je puisse l'approuver? Je n'ai pas non plus trouvé de moyen de le faire dans nginx, donc un changement au niveau de l'équilibreur de charge semble en effet être le seul moyen.
mutron
1
C'est toujours un bug avec la dernière version de nginX! Est-ce que quelqu'un sait s'il y a déjà un rapport de bogue? Impossible d'en trouver un.
Roel van Duijnhoven

Réponses:

2

Avance rapide jusqu'en 2019 et vous pouvez:

absolute_redirect off; 
port_in_redirect off;

De documents pourabsolute_redirect :

Si désactivé, les redirections émises par nginx seront relatives.

Danila Vershinin
la source
-1

Vous devez dire à l'équilibrage de la charge de réécrire httpà httpsdes demandes comme ceci:

proxy_redirect http:// $scheme://;
HostFission
la source