Предварительное чтение Nginx SSL спорадически получает запросы, когда имя сервера не извлекается

Я использую модуль потока nginx, чтобы использовать nginx в качестве обратного прокси tcp перед s3. В последнее время мне нужно было добавить логику для размещения дополнительного апстрима. Для этого я решил использовать условную логику через переменную карты $ 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.

0 ответов

Я не знаком с 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 рассматривает это как необязательный параметр.

Так что в вашем случае, я думаю, вы должны:

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