We found a solid solution that completely solves the problem — even when TLS session resumption is used by modern browsers (like Chrome or Firefox), which typically don't resend the client certificate.
Instead of using a separate port, we're using a single HAProxy frontend on port 443 and a custom ACL condition:
This reliably checks that a client certificate was used at some point in the SSL session and was successfully verified.
🔧 How to add this in OPNsense:
Go to Services → HAProxy → Rules & Checks → Conditions → Click + Add
Name: client_cert_valid_session (or similar)
Condition type: Custom condition (option pass-through)
Option pass-through:
Make sure your HAProxy frontend has Client Certificate Authentication enabled and the client certificate verification mode set to "Optional".
This is necessary so public services still work without a client certificate, while services that require mTLS can evaluate the certificate if it was provided.
You can now use this condition in your Rules to restrict access to specific backends.
This setup has been working perfectly for us — hope it helps others facing the same challenge!
Instead of using a separate port, we're using a single HAProxy frontend on port 443 and a custom ACL condition:
Code Select
ssl_c_used ssl_c_verify 0
This reliably checks that a client certificate was used at some point in the SSL session and was successfully verified.
🔧 How to add this in OPNsense:
Go to Services → HAProxy → Rules & Checks → Conditions → Click + Add
Name: client_cert_valid_session (or similar)
Condition type: Custom condition (option pass-through)
Option pass-through:
Code Select
ssl_c_used ssl_c_verify 0
Make sure your HAProxy frontend has Client Certificate Authentication enabled and the client certificate verification mode set to "Optional".
This is necessary so public services still work without a client certificate, while services that require mTLS can evaluate the certificate if it was provided.
You can now use this condition in your Rules to restrict access to specific backends.
This setup has been working perfectly for us — hope it helps others facing the same challenge!