Как HAProxy выбирает, какой сертификат обслуживать?
У меня есть сервер 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
Кажется, нет подозреваемых.
2 ответа
Я понял. RTFM. Из документов HAProxy:
https://cbonte.github.io/haproxy-dconv/1.7/configuration.html
Сертификаты будут представлены клиентам, которые предоставляют действительное поле индикации имени сервера 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, вероятно, использует первый сертификат по умолчанию (и клиент получает ошибку несоответствия сертификата