fragen stichworte

Wie kann man verhindern, dass Nginx unter AWS von HTTPS zu HTTP umgeleitet wird?

Ich habe eine von nginx betriebene Website hinter einem AWS ELB Load Balancer. Auf dem Load Balancer ist nur HTTPS aktiviert.

Das Anfordern einzelner Dateien oder Verzeichnisse mit einem nachgestellten Schrägstrich funktioniert einwandfrei. Das Anfordern von Verzeichnissen ohne einen nachgestellten Schrägstrich funktioniert jedoch nicht.

Der Grund ist, dass, wenn ich das Verzeichnis ohne den nachstehenden Schrägstrich anfordert, nginx den Pfad mit den nachgestellten Schrägstrich umleitet (das ist in Ordnung), aber es ändert sich auch von HTTPS zu HTTP. Der Lastenausgleich ist so konfiguriert, dass nur HTTPS zugelassen wird, sodass dies nicht funktioniert (Timeout).

In der Nginx-Protokolldatei kann ich sehen, dass die Anforderung Nginx erreicht, und dass es Nginx ist, das mit 301 Permanent Redirect antwortet (es ist also beispielsweise kein Problem mit dem Load Balancer-Setup).

10.100.10.15 - - [24/Nov/2017:15:41:08 +0000] "GET/admin HTTP/1.1" 301 178 "-" "Wget/1.18 (darwin16.0.0)"

Wenn ich die URL über curl anfrage, sehe ich die Weiterleitung:

$ curl -v https://example.com/admin
*   Trying 1.2.3.4...
* TCP_NODELAY set
* Connected to example.com (1.2.3.4) port 443 (#0)
* TLS 1.2 connection using TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
* Server certificate: example.com
* Server certificate: Amazon
* Server certificate: Amazon Root CA 1
* Server certificate: Starfield Services Root Certificate Authority - G2
> GET/admin HTTP/1.1
> Host: example.com
> User-Agent: curl/7.54.0
> Accept: */*
> 
< HTTP/1.1 301 Moved Permanently
< Date: Mon, 27 Nov 2017 09:19:05 GMT
< Content-Type: text/html
< Content-Length: 178
< Connection: keep-alive
< Server: nginx
< Location: http://example.com/admin/
< X-UA-Compatible: IE=Edge
< 
<html>
<head><title>301 Moved Permanently</title></head>
<body bgcolor="white">
<center><h1>301 Moved Permanently</h1></center>
<hr><center>nginx</center>
</body>
</html>
* Connection #0 to host example.com left intact

Meine Nginx-Konfigurationsdatei ist nur

server {
    root/var/www;
}

Die/etc/nginx/nginx.conf ist hier.

Ich habe server_name_in_redirect off versucht, aber es hat keinen Unterschied gemacht.

Ich möchte vermeiden, dass der Hostname in die Konfigurationsdatei eingefügt wird, da dieser in ein Docker-Image gepackt wird, das dann auf verschiedenen Hosts (QA, Prod usw.) bereitgestellt wird.

Ich möchte, dass nginx diese Weiterleitung ausführt, aber auf HTTPS bleibt. Was kann ich machen?

antworten

Der beste Ort, um das Problem zu beheben, ist, wo die SSL-Verbindung beendet wird. Wenn nginx ausgeführt wird, verwenden Sie eine proxy_redirect -Anweisung, um http im Header Location https zuzuordnen. Ich weiß AWS ELB nicht, also kann ich nicht kommentieren, wie man es dort repariert.

Bestimmte Umstände bewirken, dass nginx mit einer Weiterleitung antwortet, und es wird davon ausgegangen, dass das Schema mit dem Schema übereinstimmt, das für die Verbindung mit ihm verwendet wurde (d. h. von AWS ELB). AFAIK gibt es drei Möglichkeiten, das Problem im Back-End nginx -Server zu mildern.


1) Ab Version 1.11.8 bewirkt die Anweisung absolute_redirect off;, dass der Header Location eine relative URL verwendet, was bedeutet, dass das Schema und der Domänenname fehlen.

server {
    absolute_redirect off;
    ...
}

Siehe dieses Dokument für mehr.


2) Verhindern Sie das Verhalten des Anhängens eines nachgestellten / an Verzeichnisse mit einer try_files -Anweisung:

server {
    root/path/to/files;

    location/{
        try_files $uri =404;
    }
    ...
}

Siehe dieses Dokument für mehr.


3) Beheben Sie das Problem mit einer expliziten return -Anweisung.

server {
    root/path/to/files;

    location ~ [^/]$ {
        if (-d $request_filename) {
            return 302 https://$host$uri/$is_args$args;
        }
    }

    location/{
    }
    ...
}

Siehe dieses Dokument für mehr, und diese Warnung für die Verwendung von if.

Versuchen Sie es

server {
  root/var/www;
  include/etc/nginx/basic.conf;
  try_files $uri $uri/;
}

Wenn es nicht funktioniert, editieren Sie bitte Ihre Frage so, dass sie alles beinhaltet, was in basic.conf und nginx.conf ist. Machen Sie auch eine Locke, die das Problem zeigt, einschließlich der Antwortheader und der einzelnen entsprechenden Nginx-Zugriffsprotokolldatei.

Sie können versuchen, einen "bösen if" -Satz zu verwenden:

server {
    ...
    if ($http_x_forwarded_proto = 'http' ) {
        rewrite ^ https://$host$request_uri? permanent;
    }
    ...
}