Nginx SSL Preread время от времени получает запросы, в которых не извлекается имя сервера

Nginx SSL Preread время от времени получает запросы, в которых не извлекается имя сервера

Я используюмодуль потока nginxдля использования nginx в качестве обратного прокси-сервера tcp перед s3. Недавно мне нужно было добавить логику для размещения дополнительного апстрима. Для этого я решил использовать условную логику через переменную map $ssl_preread_server_name.ssl_prereadпозволяет nginx извлекать имя сервера из сообщения ClientHello без прерывания SSL. Вы можете увидеть логику ниже:

map $ssl_preread_server_name $https_cname {
    s3.amazonaws.com https_s3_backend;
    aws-service-2.amazonaws.com aws-service-2-backend;
}
upstream https_s3_backend {
    server s3.amazonaws.com:443;
}
upstream aws_service_2_backend {
    server aws-service-2.amazonaws.com:443;
}

server {
    listen       443;
    proxy_pass $https_cname;
    ssl_preread on;
}

Когда приходит запрос с именем сервера s3.amazonaws.com, запрос отправляется на s3. Когда приходит запрос с именем сервера aws-service-2.amazonaws.com, запрос отправляется на aws-service-2.

Это работает большую часть времени. Но иногда в журнале ошибок появляются ошибки, указывающие на то, что каким-то образом запросы попадают на серверы nginx на порту 443 без указания имени сервера.

[error] ... no host in upstream "", client: x.x.x.x, server: 0.0.0.0:443

Когда я добавляю оператор по умолчанию в логику карты, эти ошибки исчезают. Каковы возможные объяснения для некоторых запросов s3, поступающих без извлеченного имени сервера? Единственный способ, которым запросы могут попасть в эти ящики nginx в настоящее время, — это если кто-то выполняет операцию s3.

решение1

Я не знаком с Amazon S3 как таковым, но думаю, что проблема в том, что запросы генерируются без указания имени сервера (см.Индикация имени сервера).

Я столкнулся с той же проблемой в похожей настройке и смог воспроизвести ее, например, в OpenSSL v1.0.2p, подключившись без явной установки параметра servername:

openssl s_client -connect <mydomain>:<some_port> -showcerts

Этот запрос просто предоставит мне сертификат сервера по умолчанию и не будет учитывать доменное имя, которое я указал в URL. С другой стороны, при указании параметра servername:

openssl s_client -connect <mydomain>:<some_port> -showcerts -servername <mydomain>

.. запрос отправляется на правильный домен и возвращается правильный сертификат.

При доступе к тому же веб-серверу с помощью curl или через веб-браузеры я не наблюдаю этой проблемы, я подозреваю, что реализация в веб-браузере и curl устанавливает имя сервера, извлекая его из URL-адреса в фоновом режиме, тогда как некоторые клиентские приложения, такие как openssl, рассматривают его как необязательный параметр.

Так что в вашем случае, я полагаю, вам придется:

  • узнать, где генерируются запросы
  • посмотрите, есть ли возможность задать имя сервера

Связанный контент