Зачем слушать 443 default_server; Правило nginx переопределяет уже настроенное правило (правила http работают нормально)?

9

У меня есть nginx и разные поддомены:

a.mydomain.com
b.mydomain.com
c.mydomain.com

У Nginx есть 4 правила:

1) переписать правило:

server {
  listen 80
  server_name gl.udesk.org;

  root /nowhere;
  rewrite ^ https://a.mydomain.com$request_uri permanent;
}

2) правило https:

server {

  listen 443;
  server_name a.mydomain.com;

  root /home/a/a/public;

  ssl on;
  ssl_certificate conf.d/ssl/a.crt;
  ssl_certificate_key conf.d/ssl/a.key;
  ssl_protocols ...
  ssl_ciphers ...
  ssl_prefer_server_ciphers on;

  location ...
}

3) правило http по умолчанию:

server {
  listen 80 default_server;
  return 444;
}

4) правило по умолчанию https:

server {
  listen 443 default_server;
  return 444;
}

Так что, если я запускаю nginx и:

  • если я захожу в браузер на http://a.mydomain.com, он перенаправляется на https://a.mydomain.com, а затем возвращает ошибку 107 (net :: ERR_SSL_PROTOCOL_ERROR): ошибка протокола SSL.
  • если я захожу в браузер на https://b.mydomain.com, я ожидаю, что он вернет ошибку 444 обратно. Но вместо этого он возвращает ту же ошибку 107 (net :: ERR_SSL_PROTOCOL_ERROR): ошибка протокола SSL.
  • и так для всех зарегистрированных провайдером DNS CNAME (то есть a, b, c)
  • все http-версии (например, правило 3 -) работают должным образом:

Итак, почему правила https в nginx так сложно настроить, и как мне правильно их настроить, чтобы получить то же поведение, что и в версии http?

Обновить:

Создание нового сертификата и добавление:

ssl on;
ssl_certificate conf.d/ssl/default.crt;
ssl_certificate_key conf.d/ssl/default.key;

сейчас работает, но у меня было бы решение без какого-либо SSL-сертификата. Просто сбросьте все соединения для всех субдоменов https (порт 443), кроме https://a.mydomain.com без предоставления сертификата.

статический
источник
2
Ты не можешь SSL требует сертификат, прежде чем веб-сервер узнает, какой домен вы хотите . Он должен иметь сертификат для отправки или не может установить соединение для общения с клиентом.
Дарт Android
2
@DarthAndroid: магия называется SNI - en.wikipedia.org/wiki/Server_Name_Indication .
Ши
@Shi Я знаю SNI - Это позволяет веб - сервер , чтобы выбрать , который сертификат для отправки, но он все равно должен выбрать в сертификат. nginxне достаточно умен, чтобы понять, что ему не нужен сертификат для того, что пользователь хочет сделать.
Дарт Андроид

Ответы:

3

Не смешивайте порт 443 с SSL! Nginx полностью независим от портов. Вы также можете предложить https через порт 80. Современные версии nginx позволяют

listen 1234 ssl;

и вам не нужна ssl on;линия тогда.

Но если вы хотите обслуживать https, вам нужно указать сертификат. Ваш сервер вводит https, когда переписывает запрос http в запрос https.

Вы получаете ОШИБКУ ПРОТОКОЛА, поскольку SSL-рукопожатие выполняется раньше всего. Так return 444не дошло. И для любого рукопожатия SSL потребуется сертификат и закрытый ключ, чтобы снабдить алгоритмы шифрования парой сертификат / закрытый ключ.

ikrabbe
источник
3

returnДиректива является частью модуля перезаписи. Если вы проверите документацию , вы можете увидеть, что она работает с запросами. В HTTPS запросы могут быть сделаны только после того, как рукопожатие было закончено.

Есть запрос функции: https://trac.nginx.org/nginx/ticket/195 и решение для обхода проблемы.

server {
    listen 443 ssl;
    server_name bbb.example.com;
    ssl_ciphers aNULL;
    ssl_certificate /path/to/dummy.crt;
    ssl_certificate_key /path/to/dummy.key;
    return 444;
}
VBart
источник
Обратите внимание, что это лишит HTTPS-клиентов, не поддерживающих SNI (например, собственных nginx proxy_pass, если вы не установили proxy_ssl_server_name on;), доступ к любым другим server_names(так что, по сути, нарушите законные server_names, которые вы действительно хотите пропустить). Для получения подробной информации см. Trac.nginx.org/nginx/ticket/195#comment:11 .
nh2