Ubuntu xenial with Apache 2.4
Created your own Certification Authority on e.g.
dc1.example.local, then submit certificate requests (CSRs) to that CA for:
Note. we truly need to enable HTTPS on the server itself, as it seems to be a requirement for the PKI client authentication to pass through.
Send those to the server and workatation(s) e.g. for the server,
scp /etc/ssl/ubuntu63.example.local.crt ubuntu63:/etc/ssl/ scp /etc/ssl/private/ubuntu63.example.local.key ubuntu63:/etc/ssl/private/
Enabling HTTPS (Ubuntu xenial with Apache 2.4),
a2enmod ssl a2enmod headers vi /etc/apache2/apache2.conf <VirtualHost *:443> Header always set Strict-Transport-Security "max-age=31536000; includeSubdomains;" SSLEngine on SSLProtocol all -TLSv1 -SSLv2 -SSLv3 SSLHonorCipherOrder on SSLCipherSuite "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH+aRSA+RC4 EECDH EDH+aRSA RC4 !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS !RC4" SSLCertificateFile /etc/ssl/ubuntu63.example.local.crt SSLCertificateKeyFile /etc/ssl/private/ubuntu63.example.local.key #SSLCertificateChainFile /etc/httpd/ssl/issuer-concat-cert.crt ServerAdmin email@example.com ServerName ubuntu63.example.local LogLevel warn DocumentRoot /var/www/html </VirtualHost> systemctl restart apache2
Note. the apache daemon now needs the passphrase for restarting, as it needs to unlock the private key for
We can now reach the page normally and through TLS, as the client-side certificate verification is not enabled yet: http://ubuntu63.example.local/.
Now enabling client-side certificate check on the Apache service,
on the CA host
scp /etc/ssl/cacert.pem ubuntu63:/etc/ssl/
vi /etc/apache2/apache2.conf #in the vhost SSLCACertificateFile /etc/ssl/cacert.pem <Location /protected> SSLOptions +StdEnvVars SSLVerifyClient require </Location> systemctl restart apache2
As a result, when trying to load the
/protected folder without any client specific certificate, the http client e.g. Firefox shows,
Error code: SSL_ERROR_HANDSHAKE_FAILURE_ALERT
And the logs on the server shows,
[Tue Mar 13 22:21:05.573195 2018] [ssl:error] [pid 17401:tid 139778410333952] [client 10.1.1.1:45252] AH02261: Re-negotiation handshake failed [Tue Mar 13 22:21:05.573258 2018] [ssl:error] [pid 17401:tid 139778410333952] SSL Library Error: error:140890C7:SSL routines:ssl3_get_client_certificate: peer did not return a certificate -- No CAs known to server for verification?
Warning: one must take good care to disable the service on port 80. Enabling client certificate check on port 443 and keeping port 80 open would not serve any purpose in our goal. Instead of closing the port 80 on the firewalls and web daemon, I rather prefer to setup redirects. Therefore, users that do like to type urls manually into their browser will be able to reach the TLS-enabled service with no hassle nor pain.
Converting the separated .crt and .key to a single PKCS12 certificate for Firefox,
on the workstation with Firefox, as user
openssl pkcs12 -export -in lenovo.example.local.crt -inkey lenovo.example.local.key -out lenovo.example.local.p12 -CAfile /etc/ssl/cacert.pem chmod 400 lenovo.example.local.p12 ls -lhF lenovo.example.local.*
-chain argument was not used because we have a simple chain of trust: one CA and one client cert that are directly linked.
We used the same export password for the PCKCS12 certificate as for the passphrase of the private key.
Importing the .p12 into Firefox,
Edit > Preferences Advanced // View Certificates // Your Certificates Import... (provide unlock/export password)
Then when trying to access the page again with our Firefox browser, the user will be prompted on what certificate to provide to the server:
and the page displays fine when selecting the previously imported certificate.