HAProxy community

Allow Expired Certs but do CA Verification

Hi Experts,

We are having one issue where we have few Clients having expired certs and not a feasible option to update the certs right away. Currently working on Config which will allow the clients even if the client has expired certs but at the same time, we need to validate the certs against our CA so that the one who has self-signed certs and not signed by our internal CA should not be able to connect. As per the below config, I am able to connect using the self-signed certs as well.
Can anyone please suggest. My current config is as follows:


listen wss-https
bind *:833 process 1
bind *:833 process 2
bind *:833 process 3
mode tcp
option tcplog
tcp-request inspect-delay 2s
tcp-request content accept if { req.ssl_hello_type 1 }
use_backend be_ssl_verify_cert_expired if { ssl_c_verify 10 }
use_backend be_ssl_verify_cert if { req.ssl_sni -m found }
default_backend be_ssl_noverify

backend be_ssl_verify_cert_expired
mode tcp
server fe_ssl_verify_cert 127.0.0.1:806 send-proxy-v2

backend be_ssl_verify_cert
mode tcp
server fe_ssl_verify_cert 127.0.0.1:804 send-proxy-v2

backend be_ssl_noverify
mode tcp
server fe_ssl_noverify_cert 127.0.0.1:805 send-proxy-v2

listen wss-https1
bind 127.0.0.1:804 ssl crt /etc/cert/cert.pem verify required /etc/cert/ca-file /etc/cert/ca.crt accept-proxy
bind 127.0.0.1:805 ssl crt /etc/cert/cert.pem verify optional crt-ignore-err 10 ca-file /etc/cert/ca.crt accept-proxy
bind 127.0.0.1:806 ssl crt /etc/cert/cert.pem verify optional crt-ignore-err 10 ca-file /etc/cert/ca.crt accept-proxy
mode tcp
maxconn 50000
option tcplog
option clitcpka

# HSTS (15768000 seconds = 6 months)
rspadd Strict-Transport-Security:\ max-age=15768000

log-format %ci:%cp\ %fi:%fp\ %bi:%bp\ %H\ %{+Q}[ssl_c_ca_err]\ %{+Q}[ssl_c_ca_err_depth]\ %{+Q}[ssl_c_err]\ %{+Q}[ssl_c_s_dn(O,1)]\ %{+Q}[ssl_c_s_dn(CN)]\ %{Q}[ssl_c_notbefore]\ %{Q}[ssl_c_notafter]\ %{+Q}[ssl_fc_has_sni]\ %{+Q}[ssl_fc_sni]\ %{+Q}[ssl_c_key_alg]\ %{+Q}[ssl_f_sig_alg]\ %sslv\ %sslc\ %ft\ %b/%s\ %Tw/%Tc/%Tt\ %B\ %ts\ %ac/%fc/%bc/%sc/%rc\ %sq/%bq\ %hr\ %hs
default_backend backend_http

This configuration is not valid and can never work. You cannot match ssl verification error codes on a frontend where you don’t terminate SSL.

Take a look at the following thread to understand how you can use different error codes:

In short, you will have to ignore all errors during SSL handshake and make application level decisions based on the error codes.

The bind line with ssl needs to have:

verify optional crt-ignore-err all

And you will need to content switch:

# allow access if client certificate is provided + validated without errors
use_backend backend_http if { ssl_c_used } { ssl_c_verify 0 }

# allow access if client certificate is provided + validated, with expiration error
use_backend backend_http if { ssl_c_used } { ssl_c_verify 10 }

# use backend ssl_verification_error to return a SSL certification message
default_backend ssl_verification_error

Hi Lukas,

Thank you very much for your response.
Basically, As per the original config in wss-https, I am not specifying the ssl section like “ssl crt /etc/cert/cert.pem verify required /etc/cert/ca-file /etc/cert/ca.crt accept-proxy” OR “ssl crt /etc/cert/cert.pem /etc/cert/ca-file /etc/cert/ca.crt verify optional crt-ignore-err all accept-proxy” and due to which we are able to forward the cert to “wss-https1” via “be_ssl_verify_cert/fe_ssl_verify_cert” and due to which only the certs which are signed by our internal CA are validated but not able to achieve/fetch validity of the certs.
But after configuring the ssl parameter in wss-https for eg “bind *:833 ssl crt /etc/cert/cert.pem /etc/cert/ca-file /etc/cert/ca.crt verify optional crt-ignore-err all accept-proxy process 1” The “{ ssl_c_used } { ssl_c_verify 10 }” works perfectly fine as expected where I am able to route the request to different backends depending on their validity but later on the SSL handshake doesn’t happen and I get “websocket_open failed, status=-33” error.
My new config are as follows:


listen wss-https
bind *:833 ssl crt /etc/cert/server-combined.pem crt /etc/cert/verizon-cert.pem ca-file /etc/cert/all-ca.crt verify optional crt-ignore-err all process 1
bind *:833 ssl crt /etc/cert/server-combined.pem crt /etc/cert/verizon-cert.pem ca-file /etc/cert/all-ca.crt verify optional crt-ignore-err all process 2
bind *:833 ssl crt /etc/cert/server-combined.pem crt /etc/cert/verizon-cert.pem ca-file /etc/cert/all-ca.crt verify optional crt-ignore-err all process 3
mode tcp
option tcplog
tcp-request inspect-delay 2s
tcp-request content accept if { req.ssl_hello_type 1 }
use_backend be_ssl_verify_cert_expired if { ssl_c_used } { ssl_c_verify 10 } { req.ssl_sni -m found }
use_backend be_ssl_verify_cert if { ssl_c_used } { ssl_c_verify 0 } { req.ssl_sni -m found }
default_backend be_ssl_noverify

backend be_ssl_verify_cert
mode tcp
server fe_ssl_verify_cert 127.0.0.1:804 send-proxy-v2

backend be_ssl_noverify
mode tcp
server fe_ssl_noverify_cert 127.0.0.1:805 send-proxy-v2

backend be_ssl_verify_cert_expired
mode tcp
server fe_ssl_verify_cert 127.0.0.1:806 send-proxy-v2

listen wss-https1
bind 127.0.0.1:804 ssl crt /etc/cert/cert.pem verify required ca-file /etc/cert/ca.crt accept-proxy
bind 127.0.0.1:805 ssl crt /etc/cert/cert.pem verify required ca-file /etc/cert/ca.crt accept-proxy
bind 127.0.0.1:806 ssl crt /etc/cert/cert.pem ca-file /etc/cert/ca.crt accept-proxy
mode tcp
maxconn 50000
option tcplog
option clitcpka

HSTS (15768000 seconds = 6 months)

rspadd Strict-Transport-Security:\ max-age=15768000

log-format %ci:%cp\ %fi:%fp\ %bi:%bp\ %H\ %{+Q}[ssl_c_ca_err]\ %{+Q}[ssl_c_ca_err_depth]\ %{+Q}[ssl_c_err]\ %{+Q}[ssl_c_s_dn(O,1)]\ %{+Q}[ssl_c_s_dn(CN)]\ %{Q}[ssl_c_notbefore]\ %{Q}[ssl_c_notafter]\ %{+Q}[ssl_fc_has_sni]\ %{+Q}[ssl_fc_sni]\ %{+Q}[ssl_c_key_alg]\ %{+Q}[ssl_f_sig_alg]\ %sslv\ %sslc\ %ft\ %b/%s\ %Tw/%Tc/%Tt\ %B\ %ts\ %ac/%fc/%bc/%sc/%rc\ %sq/%bq\ %hr\ %hs
default_backend backend_http


Basically we would like to allow expired and valid certs signed by our internal CA but the self signed certs should not be able to connect.

Can you please suggest,

Thanks very much in advance
Rohan

The configuration is still completely invalid. You cannot simple add the ssl keyword and hope for the best.

You only need 1 frontend with ssl termination and 1 backend. That’s it.