Checking client cetificates (mtls)

Good afternoon dear community members!

I’m experimenting with haproxy as a balancer and facing some difficulties.

Clients connect tcp-streams (not http data) to my system using client certificates. The certificates may be up-do-date and working but may also be expired. In order to “catch” these expired certificates I am trying to establish “transparent” proxy-server (so to speak) in front our real balancers/backend which has to do nothing but check incoming certificates and log them (cn/dn/not_before/not_after) and pass the stream right along to backend. It’s must be kind of Man-In-Middle.

In haproxy settings I enabled setting “crt-ignore-err 10” to ignore expired certs errors and everything seems to be working good: the client certs logs to file and even clients with expired certificates can pass trough.

Scheme looks like this:
client_with_certificate —> haproxy_host:20252 (ssl) —> backend-host:50252 (ssl)

The connection has to be passed through haproxy to our backend servers, where I can one more time check the TLS/SSL certificate and finally decide to cut it off if it has expired.

But I am confused with the settings. It must be SSL/TLS between haproxy and backend, but how to pass the original client certificate? Is it possible?

Current configs attached:

global
        log /dev/log local0 debug
        chroot /var/lib/haproxy
        stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners
        stats timeout 30s
        user haproxy
        group haproxy
        daemon

        # Default SSL material locations
        ca-base /etc/ssl/certs
        crt-base /etc/ssl/private

        ssl-default-bind-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM->
        ssl-default-bind-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
        ssl-default-bind-options ssl-min-ver TLSv1.2 no-tls-tickets
        tune.ssl.default-dh-param 2048

defaults
        log     global
        mode    tcp
        option  httplog
        option  dontlognull
        option httplog
        timeout connect 5000

        timeout client  50000
        timeout server  50000

frontend my_frontend
        bind *:20252 ssl crt /etc/haproxy/cert_and_key.pem ca-file /etc/haproxy/ca.crt verify required crt-ignore-err 10
        mode tcp
        option tcplog
        timeout client 10s
        default_backend my_backend
        log-format '[%t] %ci:%cp %ft {%[ssl_c_verify],%{+Q}[ssl_c_s_dn(cn)],%{+Q}[ssl_c_i_dn]},%{+Q}[ssl_c_notbefore],%{+Q}[ssl_c_notafter]'

backend my_backend
        balance leastconn
        server s1 _my_server_addr_:50252 ssl verify required ca-file /etc/haproxy/ca.crt

With that setup it is not working. Connection dies between haproxy and backend and on the backend side I see errors:

2025/04/30 15:35:35 [info] 1762878#1762878: *16 client sent no required SSL certificate while SSL handshaking, client: CLIENT_IP, server: 0.0.0.0:50252
2025/04/30 15:35:35 [info] 1762878#1762878: *16 SSL_shutdown() failed (SSL: error:14094123:SSL routines:ssl3_read_bytes:application data after close notify) while SSL handshaking, client: CLIENT_IP, server: 0.0.0.0:50252

which is strange and seems like in connection between haproxy and backend has nothing to do with certificates.
I have experimented with options like ‘send-proxy’, ‘no-check-send-proxy’, etc, in backend section but none of that worked. If I add ‘send-proxy’, the error changes to:
SSL_do_handshake() failed (SSL: error:1408F10B:SSL routines:ssl3_get_record:wrong version number)
And I am completely lost here.
Any help will be appreciated.