0
votes

I am running HAProxy in TCP mode with TLS (client certificate based authentication). My configuration is pasted below. My goal is to redirect the SSH connection to correct server based on Client certificate that is being presented. This example talks about SSH but in the future I have various services that I may have to securely expose in this manner. Any help is appreciated.

Note that in HTTPS mode you can extract the client CN using something like and use the variable in header against an ACL. However, as I am in TCP mode, I am unsure how to do something similar.

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

However, I am not sure how to do something similar when running in TCP mode.

  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
1
Asked the question on HAProxy forums and got the answer. See discourse.haproxy.org/t/… for details - Chirag Rajyaguru

1 Answers

2
votes

With tcp mode the TLS is not terminating at HAProxy but the TLS termination is done on the server behind haproxy. This server has of course to be known before any data can be send or forwarded to the server. This means a decision which server to choose can only be done on the first data from the client in the TLS handshake (ClientHello) but not on later data which require a reply from the server already.

But, client certificates are only send by the client if the server explicitly requests these. This means, in order to get a client certificate from the client the server needs to communicate with the client which means that the connection to the server has to be established already. This of course means that the decision which server to use cannot be done based on the client certificate since the client certificate is known too late in the TLS handshake.

The only way to make such a decision based on the client certificate would be to terminate TLS at the load balancer already.