HAProxy与SNI和不同的SSL设置

我有两个网站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,访问者不能提供正确的证书或者path是/ ghost /,访问者不能提供正确的证书,则应该redirect到https://www.example.com

到目前为止,这工作正常。 但是,我收到了用Safari浏览我的网站的Mac用户的投诉,他们一直在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 

当然,这是行不通的,因为

一个。 我不能有两个只有一个公共IP b的端口443监听。 我还没有find一个方法来说“use_frontend如果domain_www”或类似的东西。 (只有use_backend或使用服务器)

我也试着用三台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服务器是不可取的(尽pipe如果我找不到更好的解决scheme是一个可能的select)。

最好我喜欢这样的东西(弥补..不知道真正的select)

 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 ... 

我希望有人能帮助我…

我发现这个问题的解决scheme,不需要额外的服务器或服务。 我不完全确定这是否会产生新的问题。 对我来说,现在似乎正在工作。

我这样做的方法是为每个需要不同ssl设置的域创build一个前端。 然后,我将这些前端的绑定选项设置为高端口(这些无法从公开!)。

我创build了另一个监听端口443的前端,根据SNI划分stream量,并将后端服务器设置为127.0.0.1:high-port。

这样,我在haproxy中创build了一个循环

 [incoming]->[haproxy:443]->[haproxy:7000]->[www.intern.lan] [incoming]->[haproxy:443]->[haproxy:8000]->[private.intern.lan] 

这是configuration部分。

 frontend frnd_snipt # Frontend_SNI-PassThrough (snipt) bind *:443 # Do not use bind *:8443 ssl crt etc....! option tcplog mode tcp tcp-request inspect-delay 5s tcp-request content accept if { req_ssl_hello_type 1 } acl subdomain_is_www req_ssl_sni -i www.example.com acl subdomain_is_www req_ssl_sni -i example.com acl subdomain_is_private req_ssl_sni -i private.example.com use_backend bknd_snipt_private if subdomain_is_private use_backend bknd_snipt_www if subdomain_is_www backend bknd_snipt_www mode tcp # tcp mode must match the frontend mode - already set as default in [global] server snipt-www 127.0.0.1:7000 # run without "check", otherwise haproxy checks itself all the time! backend bknd_snipt_private mode tcp server snipt-private 127.0.0.1:8000 # also, don't add "ssl" when in tcp mode. "ssl" is an http mode option (result in "NO-SRV" when set in tcp) ##### NORMAL HAPROXY PART ##### frontend www_example_com # this frontend can be in tcp or http mode... bind *:7000 ssl crt /etc/mycert.pem no-sslv3 # www. frontend with normal https mode http option httplog frontend private_example_com bind *:8000 ssl crt /etc/mycert.pem ca-file /etc/myca.pem verify optional no-sslv3 # private. frontend with client certificate request. mode http option httplog ... # whatever you have in your frontend 

如果任何人有这个想法,或者任何想法,为什么这可能是一个坏主意,请让我知道。 它的工作原理,但我想知道为什么use_frontend不是一个选项。 也许是因为这是不应该出于任何原因。