У меня есть сервер HAProxy 1.5.9, который будет обслуживать либо сертификат, подписанный самоподписанным ЦС, либо сертификат Let's Encrypt, в зависимости от того, какое «имя сервера» предоставлено. Это мой файл конфигурации:
defaults
mode tcp
option clitcpka
listen ft_app
bind *:5000 ssl crt /certs/private.pem ca-file /app/certs/self-signed-ca.pem crt /certs/self-signed.pem crt /app/certs/lets-encrypt.pem ciphers AES:ALL:!aNULL:!eNULL:!3DES:!DES:!RC4:!DHE:!EDH:!MD5:!PSK:!aECDH:@STRENGTH no-sslv3 no-tlsv10 no-tlsv11
mode tcp
option tcplog
tcp-request inspect-delay 10s
use_backend app_http if HTTP
default_backend app_tcp
backend app_http
mode http
option httplog
balance roundrobin
reqadd X-Forwarded-Proto:\ https
cookie SRVID insert indirect nocache
http-check expect status 200
server app_4 10.10.10.4:15672 cookie app_4 check inter 10s rise 2 fall 2
server app_3 10.10.10.3:15672 cookie app_3 check inter 10s rise 2 fall 2
server app_2 10.10.10.2:15672 cookie app_2 check inter 10s rise 2 fall 2
backend app_tcp
option tcp-check
server app_4 10.10.10.4:5672 check inter 10s rise 2 fall 2
server app_3 10.10.10.3:5672 check inter 10s rise 2 fall 2
server app_2 10.10.10.2:5672 check inter 10s rise 2 fall 2
Оно работает. Я не понимаю, как именно HAProxy выбирает, какой сертификат обслуживать. Я предполагаю, что это захват «имени сервера» из метаданных сертификата. Если да, то какое именно поле и как его исследовать, openssl x509 -in ca.pem -text -noout
похоже, подозреваемых нет.
Я понял. RTFM. Из документов HAProxy:
https://cbonte.github.io/haproxy-dconv/1.7/configuration.html#5.1-crt
Сертификаты будут представлены клиентам, которые предоставят действительное поле указания имени сервера TLS, соответствующее одному из их CN или альтернативных субъектов. Поддерживаются подстановочные знаки, когда вместо первого компонента имени хоста используется подстановочный знак «*» (например: * .example.org соответствует www.example.org, но не www.sub.example.org).
Если клиент не предоставляет SNI, или если библиотека SSL не поддерживает расширения TLS, или если клиент предоставляет имя хоста SNI, которое не соответствует ни одному сертификату, то будет представлен первый загруженный сертификат. Это означает, что при загрузке сертификатов из каталога настоятельно рекомендуется сначала загрузить сертификат по умолчанию в виде файла или убедиться, что он всегда будет первым в каталоге.
Таким образом, он использовал имя CN или alt или по умолчанию использовался первый предоставленный сертификат. Я проверил CN, который не совпадает, но затем нашел альтернативное имя:
X509v3 Subject Alternative Name:
DNS:myhost.example.com
Это соответствует домену, к которому я подключаюсь, когда получаю этот сертификат! Итак, в моем случае Haproxy выбирает сертификат, используя альтернативные имена, поскольку CN не является полным доменным именем.
Имя сервера в сертификате TLS - это сначала «Общее имя», отображаемое как Subject: ... CN=www.example.com
Если у вас есть сертификат, содержащий более одного имени сервера, он называется сертификатом SAN. https://en.m.wikipedia.org/wiki/Subject_Alternative_Name
И дополнительные имена серверов, действительные с этим сертификатом:
DNS Name: example.com
DNS Name: www.example.om
DNS Name: ...
Записи.
С указанием имени сервера от клиента HAProxy может сопоставить запрошенный URL-адрес с доступными сертификатами.
Если клиент не использует sni или не соответствует ни один сертификат, HAProxy, вероятно, использует первый сертификат по умолчанию (и клиент получает ошибку несоответствия сертификата