Umgang mit nginx 400 Fehler "Die einfache HTTP-Anforderung wurde an den HTTPS-Port gesendet"

115

Ich verwende eine Sinatra-App hinter Passenger / Nginx. Ich versuche, es dazu zu bringen, sowohl auf http- als auch auf https-Anrufe zu antworten. Das Problem ist, wenn beide im Serverblock definiert sind, werden https-Aufrufe normal beantwortet, aber http ergibt den Fehler 400 "Die einfache HTTP-Anforderung wurde an den HTTPS-Port gesendet". Dies ist für eine statische Seite, also hat Sinatra vermutlich nichts damit zu tun. Irgendwelche Ideen, wie man das behebt?

Hier ist der Serverblock:

server {
        listen 80;
        listen 443  ssl;
        server_name localhost;
        root /home/myhome/app/public;
        passenger_enabled on;

        ssl on;
        ssl_certificate      /opt/nginx/ssl_keys/ssl.crt;
        ssl_certificate_key  /opt/nginx/ssl_keys/ssl.key;
        ssl_protocols        SSLv3 TLSv1;
        ssl_ciphers          HIGH:!aNULL:!MD5;

        location /static {
            root  /home/myhome/app/public;
            index  index.html index.htm index.php;
        }

        error_page 404 /404.html;

        # redirect server error pages to the static page /50x.html
        error_page 500 /500.html;

        access_log /home/myhome/app/logs/access.log;
        error_log /home/myhome/app/logs/error.log;
}
Johnny
quelle
In meinem Fall war, dass die URL im Browser: my.example.com:443nicht funktioniert hat. Ändern Sie das stattdessen, um zu https://my.example.comfunktionieren. Seltsam, hatte nie dieses Problem mit Apache.
Sebastian
1
ssl on;Weist NGINX an, JEDEN Inhalt über SSL zu bedienen . Verwenden Sie das "ssl" -Flag am Ende Ihres listen 443;zB, listen 443 ssl;wenn Ihr Server sowohl http- als auch https-Verkehr liefert, und entfernen Sie die ssl on;Direktive.
Stphane

Antworten:

195

Ich bin auf ein ähnliches Problem gestoßen. Es funktioniert auf einem Server und nicht auf einem anderen Server mit derselben Nginx-Konfiguration. Die Lösung, die von Igor beantwortet wird, finden Sie hier http://forum.nginx.org/read.php?2,1612,1627#msg-1627

Ja. Oder Sie können SSL- / Nicht-SSL-Server auf einem Server kombinieren:

server {
  listen 80;
  listen 443 default ssl;

  # ssl on   - remember to comment this out

}
Bobojam
quelle
Laut Rapam Iosif sollten Sie auchssl off;
aceofspades
20
Sie müssen nur die Zeile entfernen ssl on;(keine Notwendigkeit, ssl off hinzuzufügen). Auch, weil ich mich nicht erinnern , die Nginx - Version, gibt es keine Notwendigkeit mehr, den Einsatz defaultauf listen 443Linie. Die OP-Konfiguration war also in Ordnung, musste nur entfernt werden ssl onund sollte funktionieren.
Laurent
@bobojam zögern Sie nicht, die Erklärung aus meiner Antwort aufzunehmen, damit Ihre Antwort vollständiger wird. Ich habe den OP-Autor gebeten, Ihre Antwort zu akzeptieren.
Alexander Azarov
2
Wie funktioniert es den SSL Zweck lösen , indem sie zu kommentieren ssl on. @ MichaelJ.Evans Antwort unten ist eine viel bessere Lösung.
Neel
1
Scheint nicht mit mehreren conf-Dateien zu funktionieren. Sagt, es gibt 2 doppelte Standardeinstellungen. Verwenden Sie Alexanders Lösung.
Ryall
39

Die obigen Antworten sind insofern falsch, als die meisten "Ist diese Verbindung HTTPS" -Test überschreiben, um das Bereitstellen der Seiten über http unabhängig von der Verbindungssicherheit zu ermöglichen.

Die sichere Antwort unter Verwendung einer Fehlerseite in einem NGINX-spezifischen http 4xx-Fehlercode, um den Client umzuleiten und dieselbe Anforderung an https zu wiederholen. (wie hier beschrieben /server/338700/redirect-http-mydomain-com12345-to-https-mydomain-com12345-in-nginx )

Das OP sollte verwenden:

server {
  listen        12345;
  server_name   php.myadmin.com;

  root         /var/www/php;

  ssl           on;

  # If they come here using HTTP, bounce them to the correct scheme
  error_page 497 https://$host:$server_port$request_uri;

  [....]
}
Michael J. Evans
quelle
1
Sie möchten wahrscheinlich $ Servername anstelle von $ Host, wobei der Servername vermutlich auf den CN gesetzt wird, den das SSL-Zertifikat authentifiziert. Auf diese Weise erhält der Benutzer keinen Angstbildschirm, wenn er über eine IP-Adresse oder einen lokalen Host eingeht.
George
Ich habe versucht , dies installieren auf meinem lokales zu implementieren Gitlab , aber verwendet , um die Einfügen von benutzerdefinierter NGINX Einstellungen in die Gitlab Server - Block - Methode so nginx['custom_gitlab_server_config'] = "error_page 497 https://$host:$server_port$request_uri;"den Trick
Aaron C
17

Der Fehler sagt eigentlich alles. Ihre Konfiguration weist Nginx an, Port 80 (HTTP) abzuhören und SSL zu verwenden. Wenn Sie auf Ihren Browser zeigen http://localhost, versucht er, eine Verbindung über HTTP herzustellen. Da Nginx SSL erwartet, beschwert es sich über den Fehler.

Die Problemumgehung ist sehr einfach. Sie benötigen zwei serverAbschnitte:

server {
  listen 80;

  // other directives...
}

server {
  listen 443;

  ssl on;
  // SSL directives...

  // other directives...
}
Alexander Azarov
quelle
7
Sie benötigen eigentlich keine zwei Serverabschnitte. Entfernen Sie die Zeile "ssl on" und ändern Sie die Listen-Zeilen gemäß der Antwort von @ bobojam.
Toxaq
12

Ich hatte genau das gleiche Problem, ich habe die gleiche Konfiguration wie Ihr Beispiel und ich habe es durch Entfernen der Zeile zum Laufen gebracht:

ssl on;

So zitieren Sie das Dokument:

Wenn HTTP- und HTTPS-Server gleich sind, kann ein einzelner Server konfiguriert werden, der sowohl HTTP- als auch HTTPS-Anforderungen verarbeitet, indem die Direktive "ssl on" gelöscht und der Parameter ssl für den Port *: 443 hinzugefügt wird

Remiz
quelle
1
Gibt es eine Chance, dass Sie den Link zu doc ​​haben?
Adam Parkin
12

Laut Wikipedia-Artikel über Statuscodes . Nginx hat einen benutzerdefinierten Fehlercode, wenn http-Verkehr an den https-Port gesendet wird (Fehlercode 497).

Und gemäß den Nginx-Dokumenten auf error_page können Sie einen URI definieren, der für einen bestimmten Fehler angezeigt wird.
Auf diese Weise können wir eine URL erstellen, an die Clients gesendet werden, wenn der Fehlercode 497 ausgelöst wird.

nginx.conf

#lets assume your IP address is 89.89.89.89 and also 
#that you want nginx to listen on port 7000 and your app is running on port 3000

server {
    listen 7000 ssl;
 
    ssl_certificate /path/to/ssl_certificate.cer;
    ssl_certificate_key /path/to/ssl_certificate_key.key;
    ssl_client_certificate /path/to/ssl_client_certificate.cer;

    error_page 497 301 =307 https://89.89.89.89:7000$request_uri;

    location / {
        proxy_pass http://89.89.89.89:3000/;

        proxy_pass_header Server;
        proxy_set_header Host $http_host;
        proxy_redirect off;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-Protocol $scheme;
    }
}

Wenn ein Client jedoch eine Anfrage über eine andere Methode als ein GET stellt, wird diese Anfrage in ein GET umgewandelt. Um die Anforderungsmethode beizubehalten, über die der Client eingegangen ist; Wir verwenden Fehlerverarbeitungsumleitungen, wie in den Nginx-Dokumenten auf error_page gezeigt

Und deshalb verwenden wir die 301 =307Weiterleitung.

Mit der hier gezeigten Datei nginx.conf können http und https denselben Port abhören

Komu
quelle
das funktioniert bei mir - error_page 497 301 = 307 89.89.89.89:7000$request_uri ;
Ugali Soft
7

Hier ist ein Beispiel für die Konfiguration von HTTP und HTTPS in demselben Konfigurationsblock mit IPv6- Unterstützung. Die Konfiguration wird in Ubuntu Server und NGINX / 1.4.6 getestet , dies sollte jedoch mit allen Servern funktionieren.

server {
    # support http and ipv6
    listen 80 default_server;
    listen [::]:80 default_server ipv6only=on;

    # support https and ipv6
    listen 443 default_server ssl;
    listen [::]:443 ipv6only=on default_server ssl;

    # path to web directory
    root /path/to/example.com;
    index index.html index.htm;

    # domain or subdomain
    server_name example.com www.example.com;

    # ssl certificate
    ssl_certificate /path/to/certs/example_com-bundle.crt;
    ssl_certificate_key /path/to/certs/example_com.key;

    ssl_session_timeout 5m;

    ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers "HIGH:!aNULL:!MD5 or HIGH:!aNULL:!MD5:!3DES";
    ssl_prefer_server_ciphers on;
}

Geben Sie nicht an, ssl onwas zu 400Fehlern führen kann. Die obige Konfiguration sollte funktionieren

http://example.com

http://www.example.com

https://example.com

https://www.example.com

Hoffe das hilft!

Madan Sapkota
quelle
4

Wenn Sie phpmyadmin verwenden, fügen Sie Folgendes hinzu: fastcgi_param HTTPS on;

Rodrigo Gregorio
quelle
4

Eigentlich kann man das machen mit:

ssl off; 

Dies löste mein Problem bei der Verwendung von nginxvhosts; Jetzt kann ich sowohl SSL als auch einfaches HTTP verwenden. Funktioniert auch mit kombinierten Ports.

rapan iosif
quelle
Funktioniert für mich auf nginx / 1.6.3 :)
djthoms