frontend front
bind *:80
bind *:443 ssl crt /etc/haproxy/certs/server.pem ca-file /etc/haproxy/certs/id.crt verify required
option tcplog
mode http
default_backend app
backend app
balance roundrobin
cookie SERVERID insert
option ssl-hello-chk
mode http
option httpclose
option forwardfor
option httpchk get /WebApi/help
server app1 1.1.1.1:443 check ssl fall 1 rise 3 verify none cookie webA
server app2 1.1.1.2:443 check ssl fall 1 rise 3 verify none cookie webB
对于某个页面 /login/idcard 我需要客户端证书并将其发送到后端(IIS),后端将使用它进行身份验证,我找不到在特定路径上请求证书的方法,证书转发到后端也不起作用,以前的配置是使用“模式 tcp”,它将所有内容转发到 IIS 并且它可以工作,但我需要使用“acl”将具有特定路径的请求转发到另一台服务器,但“acl”在 https 中不起作用,所以它应该是 http
答案1
您无法为某个路径请求证书,因为 TLS 协商在知道该路径之前就已经完成,因此一旦您知道该路径,就太晚了。
类似地,不可能“转发”客户端证书——如果此代理处于启用状态,mode http
则有两个 TLS 会话——一个在客户端和代理之间,另一个在代理和后端服务器之间。代理没有客户端证书的私钥,因此它无法使用客户端证书与后端协商 TLS。如果可以在不拥有私钥的情况下使用某人的客户端证书,则客户端证书将毫无用处——证书也是公钥,而公钥是“公开的”,因为它们本身并不代表任何有价值的东西。
可以转发属性客户端提供的证书,通过在代理中将它们设置为 HTTP 请求标头来使用第 5 层获取但这可能无法满足需要查看实际证书的后端。
甚至可以将整个客户端证书注入到后端的请求标头中……
http-request set-header X-Client-Certificate %[ssl_c_der,base64]
...但这不太可能在您描述的场景中有用。
类似地,您可以使用bind ... ssl ... verify optional
而不是required
,然后阻止对特定路径的请求,除非已经出示了证书......
http-request deny if { path_beg /login/idcard } !{ ssl_fc_has_crt }
...这将使证书成为可选的,但如果尚未提供证书,则拒绝带有此路径前缀的请求。
再次强调,从技术上来说,这是有效的,但不一定是你真正需要的。