Trattare con nginx 400 Errore "La semplice richiesta HTTP è stata inviata alla porta HTTPS"


115

Sto eseguendo un'app Sinatra dietro passenger / nginx. Sto cercando di convincerlo a rispondere sia alle chiamate http che a quelle https. Il problema è che quando entrambi sono definiti nel blocco del server, le chiamate https vengono risposte normalmente ma http restituisce un errore 400 "La semplice richiesta HTTP è stata inviata alla porta HTTPS". Questa è per una pagina statica quindi immagino che Sinatra non abbia nulla a che fare con questo. Qualche idea su come risolvere questo problema?

Ecco il blocco del server:

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

Nel mio caso era che l'url nel browser: my.example.com:443non funzionava. Cambiarlo invece in https://my.example.comfunzionato. Strano, non ho mai avuto questo problema con Apache.
Sebastian

1
ssl on;dice a NGINX di server QUALSIASI contenuto tramite SSL. Usa il flag "ssl" alla fine del tuo, listen 443;ad esempio, listen 443 ssl;se il tuo server fornisce sia traffico http che https e rimuovi la ssl on;direttiva.
Stphane

Risposte:


195

Ho riscontrato un problema simile. Funziona su un server e non su un altro server con la stessa configurazione Nginx. Ho trovato la soluzione a cui risponde Igor qui http://forum.nginx.org/read.php?2,1612,1627#msg-1627

Sì. Oppure puoi combinare server SSL / non SSL in un server:

server {
  listen 80;
  listen 443 default ssl;

  # ssl on   - remember to comment this out

}

Per quello che dice rapam iosif, assicurati di includere anchessl off;
aceofspades

20
Hai solo bisogno di rimuovere la riga ssl on;(non c'è bisogno di aggiungere ssl off). Inoltre, poiché non ricordo quale versione di Nginx, non c'è più bisogno di usarla defaultin listen 443linea. Quindi la configurazione dell'OP era OK, basta rimuoverla ssl one dovrebbe funzionare.
laurent

@bobojam sentiti libero di includere la spiegazione dalla mia risposta, in modo che la tua sia più completa. Ho chiesto all'autore di OP di accettare la tua risposta.
Alexander Azarov

2
Come risolve lo scopo SSL commentando ssl on. @ La risposta di MichaelJ.Evans di seguito è una soluzione molto migliore.
Neel

1
Non sembra funzionare con più file di configurazione. Dice che ci sono 2 valori predefiniti duplicati. Usa la soluzione di Alexander.
Ryall

39

Le risposte di cui sopra non sono corrette in quanto la maggior parte supera il test "is this connection HTTPS" per consentire la pubblicazione delle pagine su http indipendentemente dalla sicurezza della connessione.

La risposta sicura utilizzando una pagina di errore su un codice di errore http 4xx specifico di NGINX per reindirizzare il client a ritentare la stessa richiesta su https. (come descritto qui /server/338700/redirect-http-mydomain-com12345-to-https-mydomain-com12345-in-nginx )

L'OP dovrebbe utilizzare:

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;

  [....]
}

1
Probabilmente vuoi $ nome_server invece di $ host, il nome_server è presumibilmente impostato sul CN autenticato dal certificato SSL. In questo modo, l'utente non riceverà uno schermo spaventoso se entra tramite un IP o un localhost.
George

Stavo cercando di implementarlo sulla mia installazione locale di GitLab , ma ho utilizzato l' inserimento delle impostazioni NGINX personalizzate nel metodo di blocco del server GitLab , quindi nginx['custom_gitlab_server_config'] = "error_page 497 https://$host:$server_port$request_uri;"ha funzionato
Aaron C

17

L'errore dice tutto in realtà. La tua configurazione dice a Nginx di ascoltare sulla porta 80 (HTTP) e di utilizzare SSL. Quando si punta il browser a http://localhost, tenta di connettersi tramite HTTP. Poiché Nginx si aspetta SSL, si lamenta dell'errore.

La soluzione è molto semplice. Hai bisogno di due serversezioni:

server {
  listen 80;

  // other directives...
}

server {
  listen 443;

  ssl on;
  // SSL directives...

  // other directives...
}

7
In realtà non hai bisogno di due sezioni del server. Rimuovi la riga "ssl on" e cambia le linee di ascolto secondo la risposta di @ bobojam.
toxaq

12

Ho avuto lo stesso identico problema, ho la stessa configurazione del tuo esempio e ho funzionato rimuovendo la riga:

ssl on;

Per citare il documento:

Se i server HTTP e HTTPS sono uguali, è possibile configurare un singolo server che gestisce sia le richieste HTTP che HTTPS eliminando la direttiva "ssl on" e aggiungendo il parametro ssl per la porta *: 443


1
Hai la possibilità che tu abbia il link al documento?
Adam Parkin

12

Secondo l' articolo di wikipedia sui codici di stato . Nginx ha un codice di errore personalizzato quando il traffico http viene inviato alla porta https (codice di errore 497)

E secondo i documenti nginx su error_page , puoi definire un URI che verrà mostrato per un errore specifico.
Quindi possiamo creare un uri a cui verranno inviati i client quando viene generato il codice di errore 497.

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

Tuttavia, se un client effettua una richiesta tramite qualsiasi altro metodo eccetto un GET, quella richiesta verrà trasformata in un GET. Così per preservare il metodo di richiesta che il cliente è arrivato tramite; usiamo i reindirizzamenti di elaborazione degli errori come mostrato nei documenti nginx su error_page

Ed è per questo che usiamo il 301 =307reindirizzamento.

Utilizzando il file nginx.conf mostrato qui, siamo in grado di avere http e https in ascolto sulla stessa porta


questo funziona per me - error_page 497 301 = 307 89.89.89.89:7000$request_uri ;
ugali soft

7

Ecco un esempio per configurare HTTP e HTTPS nello stesso blocco di configurazione con supporto ipv6 . La configurazione è testata in Ubuntu Server e NGINX / 1.4.6 ma dovrebbe funzionare con tutti i server.

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

Non includere ssl onche potrebbe causare 400errori. La configurazione di cui sopra dovrebbe funzionare per

http://example.com

http://www.example.com

https://example.com

https://www.example.com

Spero che questo ti aiuti!



4

In realtà puoi farlo con:

ssl off; 

Questo ha risolto il mio problema nell'utilizzo di nginxvhosts; ora sono in grado di utilizzare sia SSL che semplice HTTP. Funziona anche con porte combinate.


Funziona per me su nginx / 1.6.3 :)
djthoms
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.