Назад | Перейти на главную страницу

Как 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 похоже, подозреваемых нет.

Я понял. 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, вероятно, использует первый сертификат по умолчанию (и клиент получает ошибку несоответствия сертификата