У меня есть HAProxy для моих двух сайтов, один из них публичный и один частный.
www.mysite.com private.mysite.com
Atm, я использую haproxy, как это:
frontend mysite_https
bind *.443 ssl crt /etc/mycert.pem ca-file /etc/myca.pem verify optional no-sslv3
mode http
acl domain_www hdr_beg(host) -i www.
acl domain_private hdr_beg(host) -i private.
acl path_ghost path_beg /ghost/
acl clientcert ssl_c_used
redirect location https://www.example.com if path_ghost !clientcert
redirect location https://www.example.com if !domain_www !clientcert
use_backend bknd_private if domain_private
use_backend bknd_www if domain_www
default_backend bknd_www
Для этого нужно запросить сертификат клиента (опционально) и продолжить. Если домен не www.example.com, и посетитель не может предоставить правильный сертификат или путь / ghost /, и посетитель не может предоставить правильный сертификат, его следует перенаправить на https://www.example.com.
Пока это работает отлично. Тем не менее, я получаю жалобы от пользователей Mac, просматривающих мой сайт с Safari, на то, что они продолжают запрашивать сертификат при просмотре на https://www.example.com/, тогда как, например, Firefox запрашивает только при просмотре https: //private.example .com / или https://www.example.com/ghost/ .
Очевидно, именно так Safari работает, поэтому я не могу это исправить. Моя идея состояла в том, чтобы использовать SNI для разделения между различными интерфейсами.
frontend mysite_https
bind *.443 ssl crt /etc/mycert.pem no-sslv3
frontend private_https
bind *.443 ssl crt /etc/mycert.pem ca-file /etc/myca.pem verify optional no-sslv3
Конечно, это не работает, потому что
а. У меня не может быть двух интерфейсов, прослушивающих порт 443 только с одним общедоступным IP-адресом b. Я еще не нашел способ сказать "use_frontend if domain_www" или что-то в этом роде. (Только use_backend или use-server)
Я также попытался сделать это с тремя серверами haproxy
frontend haproxy-sni
bind *:443 ssl crt /etc/mycert.pem no-sslv3
mode tcp
tcp-request inspect-delay 5s
tcp-request content accept if { req.ssl_hello_type 1 }
acl domain_www ssl_fc_sni_end -i www.example.com
use-server server1 haproxy-private.lan if !domain_www
use-server server2 haproxy-public.lan if domain_www
Это работает, однако проблема здесь в том, что haproxy-private запрашивает сертификат клиента, но запрос не достигает браузера. Каким-то образом haproxy-sni отбрасывает запрос.
Кроме того, у меня теперь есть три сервера haproxy, что нежелательно (хотя возможен вариант, если я не могу найти лучшего решения).
Предпочтительно я хотел бы что-то вроде этого (выдуманный .. не знаю реальных вариантов)
frontend mysite_https
bind *.443 ssl crt /etc/mycert.pem no-sslv3
mode http
acl domain_www hdr_beg(host) -i www.
acl domain_private hdr_beg(host) -i private.
acl path_ghost path_beg /ghost/
ssl_options ca-file /etc/myca.pem verify optional if !www_domain # made up!
ssl_options ca-file /etc/myca.pem verify optional if !path_ghost # made up!
acl clientcert ssl_c_used
redirect location https://www.example.com if path_ghost !clientcert
redirect location https://www.example.com if !domain_www !clientcert
...
Я надеюсь, что кто-то может помочь мне с этим ...
последние версии haproxy поддерживают параметр, называемый,
crt-list
который позволяет указывать различные параметры TLS на основе соответствующего сертификатаВы можете использовать это так:
haproxy.conf:
элт-list.conf:
дополнительная информация: https://cbonte.github.io/haproxy-dconv/1.9/configuration.html#5.1-crt-list
Примечание по безопасности: всегда сопоставляйте свои (чувствительные) имена хостов с SNI
ssl_fc_sni
, а не с именем хоста HTTP. В противном случае злоумышленник может обойти аутентификацию сертификата клиента, отправив TLS SNI,www.example.org
но установив для имени хоста HTTP значениеprivate.example.org
!источник
ca-file
обстановке.