首页 > 解决方案 > HAProxy - TCP 模式下基于 Client CN 的 ACL

问题描述

我在 TCP 模式下使用 TLS(基于客户端证书的身份验证)运行 HAProxy。我的配置粘贴在下面。我的目标是根据提供的客户端证书将 SSH 连接重定向到正确的服务器。此示例讨论 SSH,但将来我可能必须以这种方式安全地公开各种服务。任何帮助表示赞赏。

请注意,在 HTTPS 模式下,您可以使用类似的方法提取客户端 CN,并将标头中的变量用于 ACL。但是,由于我处于 TCP 模式,我不确定如何做类似的事情。

http-request set-header X-SSL-Client-CN %{+Q}[ssl_c_s_dn(cn)]

但是,我不确定在 TCP 模式下运行时如何做类似的事情。

  frontend Frontend_server
  mode tcp
  option tcplog
  log global
  bind X.X.X.X:8000 ssl crt /etc/certs/server.pem ca-file /etc/certs/ca.crt verify required
  acl ACL_SRV1 ??????? -m str -f /etc/SRV1/cn.list
  acl ACL_SRV2 ??????? -m str -f /etc/SRV2/cn.list  
  acl ACL_SRV3 ??????? -m str -f /etc/SRV3/cn.list
  log-format %ci:%cp\ [%t]\ %ft\ %b/%s\ %ST\ %B\ %tsc\ %ac/%fc/%bc/%sc\ %sq/%bq\ {%[ssl_c_verify],%{+Q}[ssl_c_s_dn],%{+Q}[ssl_c_i_dn]

  use_backend SRV1 if ACL_SRV1
  use_backend SRV2 if ACL_SRV2
  use_backend SRV3 if ACL_SRV3

backend SRV1
  mode tcp
  option tcplog
  option tcp-check
  server MY_SRV1 X.X.X.X:22 check  inter 1000 port 22 maxconn 1000
backend SRV2
  mode tcp
  option tcplog
  option tcp-check
  server MY_SRV2 X.X.X.X:22 check  inter 1000 port 22 maxconn 1000
backend SRV3
  mode tcp
  option tcplog
  option tcp-check
  server MY_SRV3 X.X.X.X:22 check  inter 1000 port 22 maxconn 1000

标签: tcphaproxytls1.2

解决方案


在 tcp 模式下,TLS 不会在 HAProxy 处终止,但 TLS 终止是在 haproxy 后面的服务器上完成的。在将任何数据发送或转发到服务器之前,当然必须知道该服务器。这意味着只能根据 TLS 握手 (ClientHello) 中来自客户端的第一个数据来决定选择哪个服务器,而不能在需要服务器回复的后续数据上进行。

但是,客户端证书只有在服务器明确请求时才由客户端发送。这意味着,为了从客户端获取客户端证书,服务器需要与客户端通信,这意味着必须已经建立与服务器的连接。这当然意味着不能基于客户端证书来决定使用哪个服务器,因为客户端证书在 TLS 握手中为时已晚。

根据客户端证书做出此类决定的唯一方法是已经在负载均衡器处终止 TLS。


推荐阅读