Работа с nginx 400: «На порт HTTPS отправлен простой HTTP-запрос»


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работать. Странно, никогда не было такой проблемы с apache.
— Себастьян

1
ssl on;сообщает NGINX серверу ЛЮБОГО контента через SSL. Используйте флаг «ssl» в конце вашего, listen 443;например, listen 443 ssl;если ваш сервер доставляет трафик как http, так и https, и удалите ssl on;директиву.
— Stphane

Ответы:


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;
— aceofspades

20
Вам нужно только удалить строку ssl on;(нет необходимости добавлять ssl off). Кроме того , так как я не помню , какую версию Nginx, там больше нет необходимости в использовании defaultна listen 443линии. Итак, конфигурация OP была в порядке, нужно только удалить, ssl onи она должна работать.
— Laurent

@bobojam не стесняйтесь включать объяснение из моего ответа, чтобы ваше было более полным. Я попросил автора OP принять ваш ответ.
— Александр Азаров

2
Как это решает цель SSL, комментируя ssl on. Ответ @ MichaelJ.Evans ниже - гораздо лучшее решение.
— Neel

1
Не работает с несколькими файлами conf. Говорит, что есть 2 повторяющихся значения по умолчанию. Воспользуйтесь раствором Александра.
— Ryall

39

Вышеупомянутые ответы неверны, поскольку большинство из них переопределяют тест «Это соединение HTTPS», чтобы разрешить обслуживание страниц через http независимо от безопасности соединения.

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

OP должен использовать:

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, предположительно, server_name установлен на CN, который аутентифицирует сертификат SSL. Таким образом, у пользователя не будет экрана с тревогой, если он вошел через IP или локальный хост.
— Джордж

Я пытался реализовать это на моем местной установку 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
Есть шанс, что у вас есть ссылка на документ?
— Адам Паркин

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.