How to Configure Apache to Accept Client SSL Certificates Without CA Verification


2 views

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:

  1. Request a client certificate
  2. Verify the certificate's cryptographic integrity
  3. 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.