Похожий на этот и этот вопрос Я хочу запретить пользователям использовать IP-адрес для доступа к моему серверу.
Для HTTP (порт 80) это работает нормально, но не для HTTPS. Так что пользователи все еще могут войти https://<myip>
для доступа к веб-серверу, а nginx возвращает сертификат по умолчанию. Кстати, я использую HTTP2 в своих «обычных» серверных блоках (с моими доменными именами), поэтому я использую:
listen 443 ssl http2;
listen [::]:443 ssl http2;
Я пробовал это, чтобы заблокировать доступ к IP-адресу HTTPS сейчас:
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name _;
return 444;
}
Однако, к сожалению, это блокирует все запросы HTTPS независимо от того, используется домен или нет. Я знаю, что может потребоваться заблокировать клиентов, не относящихся к SNI, поскольку они, конечно, не доставляют используемое доменное имя на сервер, поэтому меня это устраивает. (Я имею в виду, что клиенты, не поддерживающие SNI, в любом случае старые ...)
Я обычно предпочитаю блокировать это в nginx, но если у вас возникнут идеи по блокировке этого на уровне брандмауэра (iptables), я тоже буду рад их оценить. И если вы хотите спорить, почему блокировка с помощью iptables лучше, вы также можете сделать это и убедить меня также блокировать HTTP [или все другие] запросы к IP. В общем, сброс соединения - это нормально (как и код состояния nginx 444).
Однако есть одно требование: я не хочу явно указывать IP-адрес сервера в конфигурации, поскольку это динамический IP-адрес, а сервер использует динамическую службу DNS.
Короче говоря, вот чего я хочу достичь:
Редактировать: Еще одна неудачная попытка. Я пытался следовать это предложение и используйте этот фрагмент конфигурации, который логически выглядит хорошо:
if ($host != "example.com") {
return 444;
}
Это также в основном работает, но когда я получаю доступ к «https: //», я вижу, что nginx сначала уже отправляет сертификат HTTPS (содержащий имя домена), и только когда я пропускаю предупреждение о соединении, я вижу, что он блокирует доступ. Это логично, поскольку nginx может читать заголовок Host только при наличии HTTPS-соединения, но в этот момент nginx уже отправляет сертификат сервера, содержащий имя домена, поэтому теперь у пользователя есть имя домена и он может повторно подключиться, используя его, создавая весь IP-адрес. блокировка бесполезна. Меня также немного беспокоит аспект производительности этого решения, поскольку он заставляет nginx проверять заголовок хоста для каждого запроса, поэтому я все еще ищу решение здесь.
Сегодня я столкнулся с такой же проблемой с этим блоком:
server {
listen 443 ssl default_server;
server_name <SERVER-IP>;
return 444;
}
В журналах nginx говорится:
"ssl_certificate" не определен в сервере, прослушивающем порт SSL во время установления связи SSL
Как вы упомянули, похоже, это также отключает другие серверные блоки. Это можно исправить, используя (самоподписанный) сертификат для IP-адреса сервера. Я сделал это с помощью openssl:
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout privateKey.key -out certificate.crt -subj '/CN=<SERVER-IP>'
Затем измените серверный блок на:
server {
listen 443 ssl default_server;
server_name <server-ip>;
ssl_certificate /path/to/certificate.crt;
ssl_certificate_key /path/to/privateKey.key;
return 444;
}
Когда кто-то использует SERVER-IP через https для доступа к серверу, nginx представляет (самоподписанный) сертификат, а НЕ сертификат доменного имени, который вы хотите скрыть.
Кстати, сделайте свой server-block-with-IP default_server. Таким образом, клиент, у которого отключен SNI, получит IP-сертификат, а НЕ сертификат доменного имени. Это также можно проверить с помощью openssl (опция -servername, которая включает SNI, опущена):
openssl s_client -connect <SERVER-IP>:443
Попробуйте это - бит default_server является важной частью. Если это не сработает, обновите свой вопрос, указав конфигурацию для других серверов, прослушивающих 443 / SSL.
server {
listen 443 ssl default_server;
listen [::]:443 ssl default_server; # not sure if you want/need it here as well. Try both ways.
server_name _;
return 444;
}