Справа з nginx 400 Помилка "Простий запит HTTP був надісланий на порт HTTPS"


115

Я запускаю додаток Sinatra за пасажиром / nginx. Я намагаюся змусити його реагувати на дзвінки http та https. Проблема полягає в тому, що обидва визначені в блоці серверів https-виклики відповідають нормально, але http дає помилку 400 "Простий HTTP-запит був відправлений на порт HTTPS". Це для статичної сторінки, тому я здогадуюсь, що Сінатра не має до цього нічого спільного. Будь-які ідеї, як це виправити?

Ось блок сервера:

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

У моєму випадку було те, що URL-адреса браузера: my.example.com:443не працювала. Змінивши це, замість того, щоб https://my.example.comспрацювало. Дивно, ніколи не було цієї проблеми з апашем.
Себастьян

1
ssl on;повідомляє NGINX на сервер будь-якого вмісту через SSL. Використовуйте прапор "ssl" в кінці вашого, listen 443;наприклад, listen 443 ssl;якщо ваш сервер доставляє і http, і https трафік, і видаліть ssl on;директиву.
Стфан

Відповіді:


195

Я зіткнувся з подібною проблемою. Він працює на одному сервері, а не на іншому сервері з такою ж конфігурацією Nginx. Знайдено рішення, на яке Ігор відповів тут http://forum.nginx.org/read.php?2,1612,1627#msg-1627

Так. Або ви можете об'єднати SSL / не-SSL-сервери на одному сервері:

server {
  listen 80;
  listen 443 default ssl;

  # ssl on   - remember to comment this out

}

Згідно з тим, що говорить Рапам Іосіф, не забудьте також включитиssl off;
ацеофспад

20
Вам потрібно лише видалити рядок ssl on;(немає необхідності додавати ssl). Крім того, оскільки я не пам'ятаю, яку версію Nginx, більше немає необхідності використовувати defaultв listen 443режимі он- лайн. Так що конфігурація OP була в порядку, потрібно лише видалити, ssl onі вона повинна працювати.
Лоран

@bobojam не соромтесь включити пояснення з моєї відповіді, щоб ваша була більш повною. Я попросив автора ОП прийняти вашу відповідь.
Олександр Азаров

2
Як він вирішує мету SSL, коментуючи ssl on. @ Майкл Дж. Еванс відповідь нижче - це набагато краще рішення.
Ніл

1
Схоже, це не працює з кількома файлами конф. Каже, є 2 дублікати за замовчуванням. Використовуйте рішення Олександра.
Ryall

39

Наведені вище відповіді невірні в тому, що більшість завищених тестів "це HTTPS на з'єднання", щоб дозволити розміщення сторінок через http незалежно від безпеки з'єднання.

Безпечна відповідь, використовуючи сторінку помилок на специфічному коді помилки http 4xx для NGINX, щоб перенаправити клієнта для повторного повторення того ж запиту на https. (як зазначено тут /server/338700/redirect-http-mydomain-com12345-to-https-mydomain-com12345-in-nginx )

ОП повинна використовувати:

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
Ви, мабуть, хочете, щоб $ server_name замість $ host, імовірно, ім'я_сервера було встановлено на CN, який підтверджує SST-серт. Таким чином, користувач не отримає екрану відлякування, якщо він зайшов через IP-адресу або localhost.
Джордж

Я намагався реалізувати це на локальній установці GitLab , але використовував Вставлення користувацьких параметрів NGINX в метод блоку сервера GitLab, таким чином nginx['custom_gitlab_server_config'] = "error_page 497 https://$host:$server_port$request_uri;"зробив трюк
Aaron C

17

Помилка говорить все це насправді. Ваша конфігурація повідомляє Nginx прослуховувати порт 80 (HTTP) і використовувати SSL. Коли ви вказуєте свій браузер http://localhost, він намагається підключитися через HTTP. Оскільки Nginx очікує SSL, він скаржиться на помилку.

Вирішення проблеми дуже просте. Вам потрібні два serverрозділи:

server {
  listen 80;

  // other directives...
}

server {
  listen 443;

  ssl on;
  // SSL directives...

  // other directives...
}

7
Насправді вам не потрібні два розділи сервера. Видаліть рядок "ssl on" та змініть рядки прослуховування відповідно до відповіді @ bobojam.
toxaq

12

У мене була точно така ж проблема, у мене така ж конфігурація, що і у вашого зразка, і я працював, видаляючи рядок:

ssl on;

Щоб процитувати док:

Якщо HTTP та HTTPS-сервери рівні, один сервер, який обробляє і HTTP, і HTTPS-запити, може бути налаштований шляхом видалення директиви “ssl on” та додавання параметра ssl для *: 443 порта


1
У вас є посилання на doc?
Адам Паркін

12

Відповідно до статті вікіпедії про коди статусу . У Nginx є спеціальний код помилки, коли трафік http надсилається на порт https (код помилки 497)

Відповідно до документів nginx на сторінці error_page , ви можете визначити URI, який буде показаний для конкретної помилки.
Таким чином, ми можемо створити uri, на який будуть відправлені клієнти, коли буде порушено код помилки 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;
    }
}

Однак якщо клієнт робить запит будь-яким іншим методом, крім GET, цей запит буде перетворений на GET. Таким чином, зберегти метод запиту, через який клієнт зайшов; ми використовуємо переадресації обробки помилок, як показано в документах nginx на сторінці error_page

Ось чому ми використовуємо 301 =307переспрямування.

Використовуючи показаний тут файл nginx.conf, ми можемо прослуховувати http і https на одному порті


це працює для мене - error_page 497 301 = 307 89.89.89.89:7000$request_uri ;
ugali soft

7

Ось приклад конфігурації HTTP та HTTPS в одному конфігураційному блоці з підтримкою ipv6 . Конфігурація тестується на сервері Ubuntu Server та NGINX / 1.4.6, але це має працювати з усіма серверами.

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

Не включайте, ssl onщо може спричинити 400помилку. Налаштований вище конфігуратор повинен працювати

http://example.com

http://www.example.com

https://example.com

https://www.example.com

Сподіваюся, це допомагає!



4

Насправді це можна зробити за допомогою:

ssl off; 

Це вирішило мою проблему щодо використання nginxvhosts; тепер я можу використовувати як SSL, так і звичайний HTTP. Працює навіть з комбінованими портами.


Працює для мене на nginx / 1.6.3 :)
djthoms
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.