I have a CentOS 6 server running Apache 2.2.15 with OpenSSL 1.0.1e-fips. I am trying to setup two-way SSL authentication for a specific location in my web root. A 3rd party has provided both a public (plain-text) and private (binary) certificate.
I need some guidance on how to include both the public and private certs to get the handshaking working, as I am getting the following error:
Re-negotiation handshake failed: Not accepted by client!?
Here's what I have in my /etc/httpd/conf.d/ssl.conf file pertaining to this section:
<Location /api/path/>
SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL
SSLCACertificateFile /etc/pki/tls/private/public.cer
SSLVerifyClient require
SSLVerifyDepth 10
SSLOptions +StdEnvVars +ExportCertData +OptRenegotiate
</Location>
Admittedly I am not an SSL expert. I know enough to get certs installed and working. I have turned logginf to 'debug' level. I have tried to follow these guides:
http://www.stefanocapitanio.com/configuring-two-way-authentication-ssl-with-apache/
Thanks in advance!
Full ssl.conf file:
LoadModule ssl_module modules/mod_ssl.so
Listen 443
SSLPassPhraseDialog builtin
SSLSessionCache shmcb:/var/cache/mod_ssl/scache(512000)
SSLSessionCacheTimeout 300
SSLMutex default
SSLRandomSeed startup file:/dev/urandom 256
SSLRandomSeed connect builtin
#SSLRandomSeed startup file:/dev/random 512
#SSLRandomSeed connect file:/dev/random 512
#SSLRandomSeed connect file:/dev/urandom 512
SSLCryptoDevice builtin
#SSLCryptoDevice ubsec
<VirtualHost *:443>
DocumentRoot "/var/www/html/staging-site"
ServerName staging.site.com:443
ErrorLog logs/ssl_error_log
TransferLog logs/ssl_access_log
LogLevel debug
SSLEngine on
SSLProtocol all -SSLv2 -SSLv3
SSLCipherSuite ALL:!ADH:!EXPORT:!SSLv2:RC4+RSA:+HIGH:+MEDIUM:+LOW
SSLCertificateFile /etc/pki/tls/certs/cert.crt
SSLCertificateKeyFile /etc/pki/tls/private/private.key
#SSLCertificateChainFile /etc/pki/tls/certs/server-chain.crt
SSLCACertificateFile /etc/pki/tls/certs/rapidssl.crt
#SSLVerifyClient require
#SSLVerifyDepth 10
# Access Control:
#<Location />
#SSLRequire ( %{SSL_CIPHER} !~ m/^(EXP|NULL)/ \
# and %{SSL_CLIENT_S_DN_O} eq "Snake Oil, Ltd." \
# and %{SSL_CLIENT_S_DN_OU} in {"Staff", "CA", "Dev"} \
# and %{TIME_WDAY} >= 1 and %{TIME_WDAY} <= 5 \
# and %{TIME_HOUR} >= 8 and %{TIME_HOUR} <= 20 ) \
# or %{REMOTE_ADDR} =~ m/^192\.76\.162\.[0-9]+$/
#</Location>
<Location /path/api/>
SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL
SSLCACertificateFile /etc/pki/tls/private/3rdpartyprivate.cer
SSLVerifyClient require
SSLVerifyDepth 10
SSLOptions +StdEnvVars +ExportCertData +OptRenegotiate
</Location>
# SSL Engine Options:
#SSLOptions +FakeBasicAuth +ExportCertData +StrictRequire
<Files ~ "\.(cgi|shtml|phtml|php3?)$">
SSLOptions +StdEnvVars
</Files>
<Directory "/var/www/cgi-bin">
SSLOptions +StdEnvVars
</Directory>
# SSL Protocol Adjustments:
SetEnvIf User-Agent ".*MSIE.*" \
nokeepalive ssl-unclean-shutdown \
downgrade-1.0 force-response-1.0
# Per-Server Logging:
CustomLog logs/ssl_request_log \
"%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"
</VirtualHost>
Best Answer
I think you are not using the correct certificates in the correct place. You are supposed to use the server certificate issued by a trusted CA in the
SSLCertificateFile
(certificate in PEM format),SSLCertificateKeyFile
(key in PEM format matching the cert), andSSLCertificateChainFile
(certificates starting from the host cert's issuer certificate up to and including the root certificate in PEM format).In
SSLCACertificateFile
you have to use the cert (in PEM format as well) of the CA that signed the clients' certs.Here's a complete example, keep in mind that I'm using a server cert signed by the same CA that signs the clients' certs for this. Adjust if your needs differ.
Generating the certs
openssl genrsa -des3 -out ca.key 4096 openssl req -new -x509 -days 365 -key ca.key -out ca.crt -subj "/C=US/ST=Some State/L=FancyTown/O=SomeOrg/CN=Self-Signed CA" openssl genrsa -out client.key 4096 openssl req -new -key client.key -out client.csr -subj "/C=US/ST=Some State/L=FancyTown/O=SomeOrg/CN=client" openssl x509 -req -days 365 -in client.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out client.crt openssl genrsa -out server.key 4096 openssl req -new -key server.key -out server.csr -subj "/C=US/ST=Some State/L=FancyTown/O=SomeOrg/CN=server" openssl x509 -req -days 365 -in server.csr -CA ca.crt -CAkey ca.key -set_serial 02 -out server.crt
Moving them to a more convenient location
mkdir /etc/ssl_ ; mv * /etc/ssl_
Install webserver and mod_ssl
yum install -y httpd mod_ssl
Purge default TLS config
truncate -s0 /etc/httpd/conf.d/ssl.conf
Common TLS config for all VHosts,
/etc/httpd/conf.d/00-ssl.conf
``` LoadModule ssl_module modules/mod_ssl.soListen 443 https SSLCACertificateFile /etc/pki/tls/certs/ca-bundle.crt SSLStaplingCache shmcb:/run/httpd/stapling_cache(128000) SSLUseStapling off
SSLPassPhraseDialog exec:/usr/libexec/httpd-ssl-pass-dialog SSLSessionCache shmcb:/run/httpd/sslcache(512000) SSLSessionCacheTimeout 300 SSLRandomSeed startup file:/dev/urandom 256 SSLRandomSeed connect builtin SSLCryptoDevice builtin
SSLStrictSNIVHostCheck off SSLProtocol +TLSv1.2 -TLSv1.1 -TLSv1 -SSLv3 SSLHonorCipherOrder on
SSLCompression off SSLCipherSuite ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:-ECDHE-RSA-RC4-SHA:ECDHE-RSA-AE S256-SHA:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:-RC4-SHA:AES256- GCM-SHA384:AES256-SHA256:CAMELLIA256-SHA:ECDHE-RSA-AES128-SHA:AES128-GCM-SHA256:AES128-SHA256:AES128-SHA:CAMELLIA128-SHA ```
/etc/httpd/conf.d/50-ssl-vhost.conf
``` ServerAlias localhost.localdomain localhost ServerName server SSLEngine on SSLCertificateFile /etc/_ssl/server.crt SSLCertificateKeyFile /etc/_ssl/server.key SSLCertificateChainFile /etc/_ssl/ca.crt SSLCACertificateFile /etc/_ssl/ca.crt
```
Create an
index.html
file for testingecho 'It works\!' > /var/www/html/index.html
Start httpd
systemctl enable --now httpd
echo '127.0.1.1 server' >> /etc/hosts
This works (auth ok):
( echo -en 'GET / HTTP/1.1\r\nHost: server\r\n\r\n' ; sleep 2) | openssl s_client -CAfile /etc/_ssl/ca.crt -cert /etc/_ssl/client.crt -key /etc/_ssl/cli ent.key -connect server:443 -servername server
This doesn't, we didn't provide a correct cert:
( echo -en 'GET / HTTP/1.1\r\nHost: server\r\n\r\n' ; sleep 2) | openssl s_client -CAfile /etc/_ssl/ca.crt -connect server:443 -servername server