Работа с 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

}
bobojam
источник
В соответствии с тем, что говорит рапам Иосиф, не забудьте также включить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.

Remiz
источник
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 на одном и том же порту.

KOMU
источник
у меня это работает - 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

при использовании phpmyadmin добавить: fastcgi_param HTTPS on;

Родриго Грегорио
источник
4

На самом деле это можно сделать с помощью:

ssl off; 

Это решило мою проблему с использованием nginxvhosts; теперь я могу использовать как SSL, так и простой HTTP. Работает даже с комбинированными портами.

рапан иосиф
источник
У меня работает на nginx / 1.6.3 :)
djthoms