When implementing client certificate authentication in Apache 2.2.3+, the default behavior requires certificates to be signed by a trusted Certificate Authority (CA). This becomes problematic when you need to:
SSLVerifyClient require
SSLCACertificateFile /path/to/ca.crt
...but want to accept self-signed or privately-issued certificates where CA validation isn't relevant to your use case.
Instead of require
, use:
SSLVerifyClient optional_no_ca
This directive tells Apache to:
- Request client certificates
- Verify the certificate's cryptographic integrity
- Skip CA chain validation entirely
Here's a working virtual host configuration:
<VirtualHost *:443>
SSLEngine on
SSLCertificateFile /etc/ssl/certs/server.crt
SSLCertificateKeyFile /etc/ssl/private/server.key
SSLVerifyClient optional_no_ca
SSLVerifyDepth 1
<Location /secure>
SSLRequireSSL
SSLRequire (%{SSL_CLIENT_VERIFY} eq "SUCCESS")
</Location>
</VirtualHost>
To implement persistent identity verification (recognizing returning users by their certificate fingerprint):
RewriteEngine On
RewriteCond %{SSL:SSL_CLIENT_M_SERIAL} !^$
RewriteCond /var/www/cert_db/%{SSL:SSL_CLIENT_M_SERIAL}.db !-f
RewriteRule ^ - [F]
1. Security implications:
- Without CA verification, you lose protection against MITM attacks during initial certificate exchange
- Consider implementing certificate pinning at application level
2. Apache version notes:
optional_no_ca
available since Apache 2.2.0- Newer versions support more granular controls via
SSLRequire
When implementing client certificate authentication in Apache 2.2.3+, the default behavior requires certificate chain validation against a trusted CA. This becomes problematic when you need to accept self-signed certificates or certificates from unknown CAs while still maintaining the security benefits of SSL/TLS authentication.
The solution lies in these critical directives:
SSLVerifyClient optional_no_ca
SSLCACertificateFile /path/to/empty/file.crt
The optional_no_ca
parameter is the magic ingredient that tells Apache to:
- Request a client certificate
- Verify the certificate's cryptographic integrity
- Skip CA chain verification
Here's a complete VirtualHost configuration example:
<VirtualHost *:443>
ServerName example.com
SSLEngine on
SSLCertificateFile /etc/ssl/certs/server.crt
SSLCertificateKeyFile /etc/ssl/private/server.key
# Critical configuration for bypassing CA verification
SSLVerifyClient optional_no_ca
SSLVerifyDepth 1
# Required but can point to empty file
SSLCACertificateFile /etc/ssl/certs/empty.crt
# Optional: Verify certificate against known fingerprints
SSLRequire %{SSL_CLIENT_S_DN_CN} eq "expected-client" \
or %{SSL_CLIENT_I_DN_CN} eq "expected-issuer"
</VirtualHost>
While this solution meets the technical requirement, consider these security implications:
- Without CA verification, you lose protection against man-in-the-middle attacks
- Implement additional validation (like certificate fingerprint matching)
- Monitor for certificate revocation if using in production
For Apache 2.4+, you can use:
SSLVerifyClient require
SSLVerifyDepth 0
SSLCACertificateFile /dev/null
This configuration achieves similar results while being more explicit about the verification depth.
Since we're skipping CA verification, you should implement alternative validation methods:
<Location /secure-area>
SSLRequire %{SSL_CLIENT_M_SERIAL} eq "1234567890" \
or %{SSL_CLIENT_V_REMAIN} > 30
</Location>
This checks for specific certificate serial numbers and validates expiration dates.