Radzenie sobie z nginx 400 Błąd „Zwykłe żądanie HTTP zostało wysłane do portu HTTPS”

115

Używam aplikacji Sinatra za pasażerem / nginx. Próbuję sprawić, by odpowiadał zarówno na połączenia http, jak i https. Problem polega na tym, że gdy oba są zdefiniowane w bloku serwera, na wywołania https odpowiadają normalnie, ale http daje błąd 400 „Zwykłe żądanie HTTP zostało wysłane do portu HTTPS”. To jest dla statycznej strony, więc zgaduję, że Sinatra nie ma z tym nic wspólnego. Jakieś pomysły, jak to naprawić?

Oto blok serwera:

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;
}
Jasio
źródło
W moim przypadku było to, że adres URL w przeglądarce: my.example.com:443nie działał. Zmiana tego zamiast https://my.example.comdziałać. Dziwne, nigdy nie miałem tego problemu z apache.
Sebastian
1
ssl on;mówi do serwera nginx JAKICHKOLWIEK treści poprzez SSL. Użyj flagi "ssl" na końcu twojego, listen 443;np. listen 443 ssl;Jeśli twój serwer dostarcza zarówno ruch http, jak i https, i usuń ssl on;dyrektywę.
Stphane

Odpowiedzi:

195

Napotkałem podobny problem. Działa na jednym serwerze i nie działa na innym serwerze z taką samą konfiguracją Nginx. Znalazłem rozwiązanie, na które Igor odpowiada tutaj http://forum.nginx.org/read.php?2,1612,1627#msg-1627

Tak. Lub możesz połączyć serwery SSL / bez SSL w jednym serwerze:

server {
  listen 80;
  listen 443 default ssl;

  # ssl on   - remember to comment this out

}
bobojam
źródło
Zgodnie z tym, co mówi rapam iosif, pamiętaj, aby uwzględnić równieżssl off;
aceofspades,
20
Musisz tylko usunąć linię ssl on;(nie ma potrzeby dodawania ssl off). Ponadto, ponieważ nie pamiętam wersji Nginx, nie ma już potrzeby korzystania defaultz Internetu listen 443. Więc konfiguracja OP była w porządku, wystarczy ją usunąć ssl oni powinna działać.
laurent
@bobojam zapraszam do dołączenia wyjaśnień z mojej odpowiedzi, aby Twoja była bardziej kompletna. Poprosiłem autora OP o zaakceptowanie odpowiedzi.
Alexander Azarov
2
Jak rozwiązuje cel SSL, komentując ssl on. @ MichaelJ.Evans poniżej jest znacznie lepszym rozwiązaniem.
Neel
1
Wydaje się, że nie działa z wieloma plikami konfiguracyjnymi. Mówi, że istnieją 2 zduplikowane wartości domyślne. Użyj rozwiązania Alexandra.
Ryall
39

Powyższe odpowiedzi są niepoprawne, ponieważ większość z nich zastępuje test „jest to połączenie HTTPS”, aby umożliwić obsługę stron za pośrednictwem protokołu http niezależnie od bezpieczeństwa połączenia.

Bezpieczna odpowiedź przy użyciu strony błędu w kodzie błędu http 4xx specyficznym dla NGINX, aby przekierować klienta do ponownej próby wysłania tego samego żądania do https. (jak opisano tutaj /server/338700/redirect-http-mydomain-com12345-to-https-mydomain-com12345-in-nginx )

OP powinien używać:

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
źródło
1
Prawdopodobnie chcesz $ server_name zamiast $ host, przy czym nazwa_serwera jest przypuszczalnie ustawiona na CN, który uwierzytelnia certyfikat SSL. W ten sposób użytkownik nie otrzyma ekranu przestraszenia, jeśli przyszedł przez adres IP lub localhost.
George
Starałem się wdrożyć to na mój lokalny instalacja GitLab , ale używał ustawień Wkładanie zwyczaj nginx w bloku serwer GitLab metody więc nginx['custom_gitlab_server_config'] = "error_page 497 https://$host:$server_port$request_uri;"wystarczyły
Aaron C
17

Błąd mówi wszystko. Twoja konfiguracja nakazuje Nginx nasłuchiwać na porcie 80 (HTTP) i używać SSL. Kiedy wskażesz przeglądarkę http://localhost, spróbuje połączyć się przez HTTP. Ponieważ Nginx oczekuje SSL, zgłasza błąd.

Obejście jest bardzo proste. Potrzebujesz dwóch serversekcji:

server {
  listen 80;

  // other directives...
}

server {
  listen 443;

  ssl on;
  // SSL directives...

  // other directives...
}
Aleksandra Azarowa
źródło
7
W rzeczywistości nie potrzebujesz dwóch sekcji serwera. Usuń wiersz „ssl on” i zmień wiersze nasłuchu zgodnie z odpowiedzią @ bobojam.
toxaq
12

Miałem dokładnie ten sam problem, mam taką samą konfigurację jak twój przykład i sprawiłem, że działa, usuwając linię:

ssl on;

Cytując dokument:

Jeśli serwery HTTP i HTTPS są równe, można skonfigurować jeden serwer obsługujący żądania HTTP i HTTPS, usuwając dyrektywę „ssl on” i dodając parametr ssl dla portu *: 443

Remiz
źródło
1
Czy jest szansa, że ​​masz link do dokumentu?
Adam Parkin
12

Zgodnie z artykułem Wikipedii dotyczącym kodów statusu . Nginx ma niestandardowy kod błędu, gdy ruch HTTP jest wysyłany do portu https (kod błędu 497)

Zgodnie z dokumentacją Nginx na stronie error_page możesz zdefiniować identyfikator URI, który będzie wyświetlany dla określonego błędu.
W ten sposób możemy utworzyć identyfikator URI, do którego klienci będą wysyłani, gdy zostanie zgłoszony kod błędu 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;
    }
}

Jeśli jednak klient wysyła żądanie za pomocą innej metody niż GET, żądanie to zostanie przekształcone w GET. W ten sposób, aby zachować metodę żądania, przez którą przyszedł klient; używamy przekierowań przetwarzania błędów, jak pokazano w dokumentach Nginx na stronie error_page

Dlatego używamy 301 =307przekierowania.

Korzystając z pokazanego tutaj pliku nginx.conf, możemy nasłuchiwać http i https na tym samym porcie

Komu
źródło
to działa dla mnie - error_page 497 301 = 307 89.89.89.89:7000$request_uri ;
ugali soft
7

Oto przykład konfiguracji HTTP i HTTPS w tym samym bloku konfiguracyjnym z obsługą IPv6 . Konfiguracja jest testowana w Ubuntu Server i NGINX / 1.4.6, ale powinna działać na wszystkich serwerach.

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

Nie uwzględniaj, ssl onco może powodować 400błąd. Powyższa konfiguracja powinna działać dla

http://example.com

http://www.example.com

https://example.com

https://www.example.com

Mam nadzieję że to pomoże!

Madan Sapkota
źródło
4

jeśli używasz phpmyadmin dodaj: fastcgi_param HTTPS on;

Rodrigo Gregorio
źródło
4

Właściwie możesz to zrobić za pomocą:

ssl off; 

To rozwiązało mój problem z używaniem nginxvhosts; teraz mogę używać zarówno SSL, jak i zwykłego HTTP. Działa nawet z połączonymi portami.

rapan iosif
źródło
U mnie działa na nginx / 1.6.3 :)
djthoms