When implementing client certificate authentication in an Apache reverse proxy setup, several technical hurdles can emerge. Here's what we know about this specific case:
- Apache 2.4 running as reverse proxy
- Custom CA created (ca.crt, ca.csr, ca.key)
- Client certificates issued but failing authentication
- Multiple browsers showing different error behaviors
Let's examine the critical Apache configuration elements that need attention:
# Reverse proxy settings
ProxyPass / http://backend-server:80/
ProxyPassReverse / http://backend-server:80/
# SSL base configuration
SSLEngine On
SSLCertificateFile "/path/to/server.crt"
SSLCertificateKeyFile "/path/to/server.key"
SSLCertificateChainFile "/path/to/ca_bundle.crt"
SSLCACertificateFile "/path/to/self_ca.crt"
SSLVerifyClient none
SSLProtocol all -SSLv2 -SSLv3 -TLSv1 -TLSv1.1
SSLCipherSuite HIGH:!aNULL:!MD5:!RC4
# Client auth specific location
<Location /clientauth>
SSLVerifyClient require
SSLVerifyDepth 1
SSLRequireSSL
SSLRequire %{SSL_CLIENT_S_DN_CN} eq "client-cert-name"
</Location>
1. Certificate Chain Verification
Ensure your certificate chain is properly configured. The client must trust your CA, and your server must have the complete chain:
# Verify chain with OpenSSL
openssl verify -CAfile /path/to/ca.crt /path/to/client.crt
2. Protocol and Cipher Suite Mismatches
Modern security standards require updated protocols:
# Recommended SSL configuration
SSLProtocol TLSv1.2 TLSv1.3
SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256
SSLHonorCipherOrder on
3. Reverse Proxy Specific Considerations
When using reverse proxy with client cert auth, these additional directives help:
SSLProxyEngine On
SSLProxyVerify require
SSLProxyVerifyDepth 2
SSLProxyCACertificateFile "/path/to/ca.crt"
Client-Side Verification
Use OpenSSL to test the connection:
openssl s_client -connect your-server:443 -cert client.crt -key client.key -CAfile ca.crt
Apache Log Configuration
Enable detailed logging to diagnose handshake failures:
LogLevel debug
ErrorLog "/var/log/apache2/ssl_error_log"
CustomLog "/var/log/apache2/ssl_access_log" "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"
Here's a tested configuration that works with Apache 2.4:
<VirtualHost *:443>
ServerName example.com
# SSL Configuration
SSLEngine on
SSLCertificateFile "/etc/ssl/certs/server.crt"
SSLCertificateKeyFile "/etc/ssl/private/server.key"
SSLCertificateChainFile "/etc/ssl/certs/ca-bundle.crt"
# Client certificate settings
SSLCACertificateFile "/etc/ssl/certs/ca.crt"
SSLVerifyClient optional
SSLVerifyDepth 2
# Proxy settings
ProxyPreserveHost On
ProxyPass "/" "http://backend-server/"
ProxyPassReverse "/" "http://backend-server/"
# Client auth specific path
<Location "/secure">
SSLVerifyClient require
SSLVerifyDepth 1
SSLRequire %{SSL_CLIENT_VERIFY} eq "SUCCESS"
</Location>
# Modern SSL configuration
SSLProtocol TLSv1.2 TLSv1.3
SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256
SSLCompression off
SSLHonorCipherOrder on
</VirtualHost>
When implementing client certificate authentication in an Apache reverse proxy environment, several technical considerations come into play. The error messages you're seeing (Re-negotiation handshake failed
and various client-side errors) typically indicate either SSL configuration mismatches or proxy-related complications.
The first step is ensuring proper SSL directives in your VirtualHost configuration. Here's an optimized version:
ProxyPass / http://backend-server:80/
ProxyPassReverse / http://backend-server:80/
ProxyPreserveHost On
SSLProxyEngine On
SSLEngine On
SSLCertificateFile "/path/to/server.crt"
SSLCertificateKeyFile "/path/to/server.key"
SSLCertificateChainFile "/path/to/ca_bundle.crt"
SSLCACertificateFile "/path/to/self_ca.crt"
SSLVerifyClient none
SSLVerifyDepth 10
SSLProxyVerify none
SSLProxyCheckPeerCN off
SSLProxyCheckPeerName off
SSLProxyCheckPeerExpire off
<Location /clientauth>
SSLVerifyClient require
SSLVerifyDepth 1
SSLRequireSSL
SSLRequire %{SSL_CLIENT_S_DN_O} eq "Your Organization"
</Location>
When troubleshooting, check these key points:
- Verify your CA certificate is properly installed in the client browsers
- Ensure the client certificate includes the complete chain
- Check Apache's error_log with
LogLevel debug
for SSL module output
Here are proper cURL commands for testing:
# Using PKCS12 (.p12) file
curl --cert-type P12 --cert client.p12:password -k -v https://yourserver/clientauth
# Using separate cert and key
curl --cert client.crt --key client.key --cacert ca.crt -v https://yourserver/clientauth
Several factors often cause issues in this setup:
Problem | Solution |
---|---|
Certificate chain incomplete | Ensure SSLCertificateChainFile points to full chain |
SSL renegotiation issues | Add SSLInsecureRenegotiation off |
Proxy interfering with SSL | Set SSLProxyEngine On and proper verify settings |
For more complex scenarios, consider these additions:
# Enable OCSP stapling
SSLUseStapling On
SSLStaplingCache "shmcb:logs/stapling-cache(150000)"
# Stronger cipher suite
SSLCipherSuite EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH
SSLProtocol All -SSLv2 -SSLv3
SSLHonorCipherOrder On
Remember to restart Apache after configuration changes and test with multiple clients to verify consistent behavior.