Nginx. Как я могу отклонить запрос к незарегистрированному виртуальному серверу ssl?

13

У меня есть сертификат SSL с подстановочным знаком и несколько поддоменов на одном и том же ip. Теперь я хочу, чтобы мой nginx обрабатывал только упомянутые имена серверов и сбрасывал соединение для других, чтобы он выглядел так, как будто nginxон не работает для незарегистрированных имен серверов (не отвечает, отклоняет, не работает, ни одного байта в ответе). Я делаю следующее

ssl_certificate         tls/domain.crt;
ssl_certificate_key     tls/domain.key;

server {
  listen 1.2.3.4:443 ssl;
  server_name validname.domain.com;
  //
}

server {
  listen 1.2.3.4:443 ssl;
  server_name _;
  // deny all;
  // return 444;
  // return 404;
  //location {
  //  deny all;
  //}
}

Я попробовал почти все в последнем блоке сервера, но безуспешно. Я получаю либо действительный ответ от известного виртуального сервера, либо код ошибки. Пожалуйста помоги.

andbi
источник

Ответы:

7

Это не работает таким образом: рукопожатие SSL происходит до HTTP, поэтому имя в сертификате будет оценено в браузере, прежде чем вы сможете перенаправить или сделать что-либо еще внутри конфигурации nginx.

CJC
источник
это плохо, но надо признать) спасибо.
andbi
3
Это не так: вы можете сделать что-то еще на более низком уровне, например сбросить соединение без какого-либо ответа, как объяснено в других ответах.
Collimarco
13

Ответ cjc уже правильно указал на проблему с попыткой сопоставления имен хостов при включенном SSL. Тем не менее, это можно сделать так:

server {
    ...

    if ($host !~* ^validname\.domain\.com$ ) {
        return 444;
    }
    ...
}

Примечание: да, это правда, что обычно ifэто зло , но ifв этом случае его можно использовать безопасно . (Прочитайте ссылку на страницу, если вам нужно убедить себя.)

В противоположность тому, что было предложено, простое добавление следующего блока не сработает:

server {
    listen 80;
    listen 443 ssl;
    return 444;
}

потому что сертификат SSL, который совпадает validname.domain.com, не будет соответствовать некоторому случайному доменному имени. Я попробовал, и nginx действовал так, как будто блока вообще не было.

Это также не будет работать:

server {
    listen       443;
    server_name    _;
    return 444; 
}

потому что это сделает каждое соединение HTTPS на порту 443 неудачным, даже те, которые должны пройти. Я тоже попробовал это. wgetсообщил об ошибке SSL рукопожатия.

Луис
источник
5

Большинство ответов здесь о том, почему это не работает, а не о том , как заставить это работать.

Вот как - вам нужно сделать такой универсальный сервер «default_server» и указать пути к сертификату / ключу, чтобы он мог расшифровать входящий ssl-запрос и соответствовать заголовку Host:

server {
    listen 80 default_server;
    listen 443 ssl default_server;
    server_name _;
    ssl_certificate <path to cert>;
    ssl_certificate_key <path to key>;
    return 404;
}

Обратите внимание на ssl_certificate / ssl_certificate_key там. Если они не указаны, nginx все еще пытается использовать такой default_server и терпит неудачу, так как не может принять ssl-соединение без сертификата / ключа. Можно использовать любой сертификат / ключ, например, самоподписанный. ...

Чтобы создать самозаверяющий сертификат:

openssl req -x509 -newkey rsa:4096 -nodes -out cert.pem -keyout key.pem -days 365 

Также см. Https://serverfault.com/a/841643/87439.

andreycpp
источник
1
Вы пробовали это? Как создать сертификат SSL, который соответствует имени сервера «_»?
Тим
Да, это решение работает для меня. У меня была точно такая же проблема, и я понял из документации, что nginx нужен сертификат / ключ, поскольку он не смотрит на TLS SNI. Вы можете использовать любой сертификат / ключ, например, самоподписанный.
andreycpp
1

Я реализовал вышеупомянутое решение сегодня, и оно сработало плавно. Все URL, которые не указаны, теперь удалены. Размещение этого серверного кода до того, как фактическая запись виртуального сервера стала ключевой - все неправильно сформированные URL-адреса теперь отправляются на этот сервер по умолчанию.

... 
server {
     listen       443;
     server_name    _;
     return 444; }

server {
     listen       443;
     server_name  [URL]
Дэвид Секстон
источник
0

Вы должны быть в состоянии справиться с этим, сделав сервер, который обрабатывает незарегистрированные элементы, первым блоком сервера в вашей конфигурации.

http {
    ...

    server {
        listen 80;
        listen 443 ssl;
        return 444;
    }

    server {
        server_name validname.domain.com;
        ...
    }
}

Все домены, которые не определены конкретно, будут обрабатываться этим блоком сервера.

Dayo
источник
1
Это не работает
Амир Хоссейн