Create certificates for Apache2
General information
Sources:
- http://linuxconfig.org/apache-web-server-ssl-authentication
- http://www.linode.com/wiki/index.php/Apache2_SSL_in_Ubuntu
- http://www.symantec.com/connect/articles/apache-2-ssltls-step-step-part-1 (3 part article)
Also see:
Location
These scripts are executed as root in the directory '/etc/apache2/ssl'. This directory will only be accessible with root privileges to protect the encryption keys:
sudo -i mkdir /etc/apache2/ssl chown root:root /etc/apache2/ssl chmod 700 /etc/apache2/ssl cd /etc/apache2/ssl
From here on we will continue with root privileges.
Configuration file
Create certificate configuration file 'create_ssl.conf'. This is not mandatory but will simplify the process:
gedit create_ssl.conf
[ req ] default_md = sha1 distinguished_name = req_distinguished_name [ req_distinguished_name ] countryName = Netherlands countryName_default = NL countryName_min = 2 countryName_max = 2 localityName = Locality localityName_default = NB organizationName = Organization organizationName_default = organisation commonName = Common Name commonName_default = organisation.linkpc.net commonName_max = 64 [ certauth ] subjectKeyIdentifier = hash authorityKeyIdentifier = keyid:always,issuer:always basicConstraints = CA:true crlDistributionPoints = @crl [ server ] basicConstraints = CA:FALSE keyUsage = digitalSignature, keyEncipherment, dataEncipherment extendedKeyUsage = serverAuth nsCertType = server crlDistributionPoints = @crl [ client ] basicConstraints = CA:FALSE keyUsage = digitalSignature, keyEncipherment, dataEncipherment extendedKeyUsage = clientAuth nsCertType = client crlDistributionPoints = @crl [ crl ] URI=http://organisation.linkpc.net/ca.crl
Create CA certificate
Generate a self-signed certificate authority (CA) certificate, valid for 365 days. When prompted for a 'Common Name' enter your CA name, for example 'organisation.linkpc.net CA'. Note: this should be different from the server certificate Common Name:
openssl req -config ./create_ssl.conf -newkey rsa:2048 -nodes -keyform PEM \ -keyout ca.key -x509 -days 365 -extensions certauth -outform PEM -out ca.cer
You will now have a file 'ca.key' with the private key of the CA and the file 'ca.cer' with its self-signed certificate. Next you need to generate a private SSL key for the server.
Create server certificate
Generate a private SSL key for the server:
openssl genrsa -out server.key 2048
To generate a Certificate Signing Request in PKCS#10 use the following command, as 'Common Name' specify the host-name, for example 'organisation.linkpc.net':
openssl req -config ./create_ssl.conf -new -key server.key -out server.req
Now create a self-signed server certificate with serial number (here 100 / 65 hexadecimal) as requested with file 'server.req' Note: you need a new serial number, for example use 1YY:
openssl x509 -req -in server.req -CA ca.cer -CAkey ca.key -set_serial 100 \ -extfile create_ssl.conf -extensions server -days 365 -outform PEM -out server.cer
The file **'server.key'** contains the server's private key and the file **'server.cer'** is the certificate itself. Certificate Signing Request file 'server.req' is no longer needed.
rm server.req
Note:
- The server needs to be restarted
- This page might not be available if you make a mistake
Configure Apache2 SSL
Enable Apache2 SSL module:
sudo a2enmod ssl
Configure Apache2, for example for the site 'organisation.linkpc.net':
gedit /etc/apache2/sites-available/organisation.linkpc.net.conf
NameVirtualHost _default_:443 ##Encryption randomization ## *http://www.modssl.org/docs/2.2/ssl_reference.html#ToC4 SSLRandomSeed startup file:/dev/urandom 1024 SSLRandomSeed connect file:/dev/urandom 1024 ##prevents extra SSL handshakes and speeds up performance ## *http://www.modssl.org/docs/2.2/ssl_reference.html#ToC5 SSLSessionCache shm:/usr/local/apache2/logs/ssl_cache_shm SSLSessionCacheTimeout 600 <virtualhost _default_:443> ServerAdmin admin@localhost SSLEngine On SSLOptions +StrictRequire SSLProtocol -all +TLSv1 +SSLv3 ## Support only for strong cryptography: SSLCipherSuite HIGH:MEDIUM:!aNULL:+SHA1:+MD5:+HIGH:+MEDIUM SSLProxyEngine off SSLCertificateFile /etc/apache2/ssl/server.cer SSLCertificateKeyFile /etc/apache2/ssl/server.key DocumentRoot /var/www/ <directory /> SSLRequireSSL Options FollowSymLinks AllowOverride None </directory> <directory /var/www/> SSLRequireSSL Options Indexes FollowSymLinks MultiViews AllowOverride None Order allow,deny allow from all # This directive allows us to have apache2's default start page # in /apache2-default/, but still have / go to the right place # Commented out for Ubuntu #RedirectMatch ^/$ /apache2-default/ </directory> ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/ <directory "/usr/lib/cgi-bin"> SSLRequireSSL AllowOverride None Options ExecCGI -MultiViews +SymLinksIfOwnerMatch Order allow,deny Allow from all </directory> ##Possible values include: ## debug, info, notice, warn, error, crit, alert, emerg. LogLevel warn ErrorLog /var/log/apache2/error.log CustomLog /var/log/apache2/access.log combined ServerSignature On #mediawiki Alias /mediawiki/ "/var/www/mediawiki/" <directory "/var/www/mediawiki/"> SSLRequireSSL Options Indexes MultiViews FollowSymLinks AllowOverride None Order deny,allow Deny from all Allow from 127.0.0.0/255.0.0.0 ::1/128 </directory> </virtualhost>
Restart Apache2:
sudo service apache2 restart
How it works
Using the created keys, this is how the HTTPS session will be initiated:
- The client requests content from the Web Server using HTTPS.
- The web server responds with a Certificate which includes the server's public key (file 'server.cer')
- The client checks to see if the certificate has expired.
- The client checks if the Certificate Authority that signed the certificate is a trusted authority listed in the browser.
- The client then checks to see if the Fully Qualified Domain Name (FQDN) of the web server matches the Comman Name (CN) on the certificate.
- In the case of a self-signed certificate the client will give a warning and ask explicitly to accept or deny it.
- If everything is successful the SSL connection is initiated.
- Data as send by the Web Server will be encrypted with the private key (file 'server.key') and can only be decrypted using the public key (file 'server.cer')
- Vice versa, data send by the client will be encrypted with the public key (file 'server.cer') and can only be decrypted using the private key (file 'server.key')
WEB SERVER <--- request ---- CLIENT
certificate -- certificate -> check certificate
private key public key
data ----- data -----> data
ENcryption DEcryption
private key public key
data <---- data ------ data
DEcryption ENcryption
Client certificate
To require a certificate on the client before allowing access we need to create a client certificate, preferably we create one for each client.
Generate private key for SSL client:
openssl genrsa -out client.key 2048
You need to generate a Certificate Signing Request. You can use your clients full name as a Common Name:
openssl req -config ./create_ssl.conf -new -key client.key -out client.req
Create a self-signed Certificate Authority client certificate with serial number 101 (66 hexadecimal):
openssl x509 -req -in client.req -CA ca.cer -CAkey ca.key -set_serial 101 -extfile create_ssl.conf -extensions client -days 365 -outform PEM -out client.cer
Package a client's private key and certificate into a PKCS#12 format. The certificate will be secured by a password which will be needed to import the certificate into the web browser:
openssl pkcs12 -export -inkey client.key -in client.cer -out client.p12
File 'client.p12' contains a private key and the client's certificate, the files 'client.key', 'client.cer' and 'client.req' are no longer needed:
rm client.key client.cer client.req
Configure Apache2, add the following lines to httpd.conf:
gedit /etc/apache2/httpd.conf
... <virtualhost _default_:443> ... ##SSL ... ##require client authentication (two-way handshake) SSLVerifyClient require SSLVerifyDepth 1 SSLCACertificateFile /etc/apache2/ssl/ca.cer ... </virtualhost>
Restart Apache2:
service apache2 restart
Client certificate: add in your browser
The client browser:
- Add the webserver certificate by adding an exception.
In case of a client certificate you will have no access to the server just yet, import your client certificate into your browser:
- In Firefox go to Options -> Advanced -> Encryption -> View Certificates -> Your Certificates -> Import, and select the file 'client.p12'. You will need to enter the certificate password.
Force SSL when port 80 is accessed
To force an SSL connection and redirect all traffic at port 80 to port 443 (HTTPS)
Enable module rewrite:
a2enmod rewrite
gedit /etc/apache2/sites-available/default
Add the following within the virtual host at the end:
<VirtualHost *:80>
...
##redirect port 80 to HTTPS
RewriteEngine on
RewriteCond %{SERVER_PORT} ^80$
RewriteRule ^(.*)$ https://%{SERVER_NAME}%{REQUEST_URI} [L,R]
</Virtualhost>
Restart Apache2:
sudo service apache2 restart
Errors
Firefox errors
sec_error_reused_issuer_and_serial
Your certificate contains the same serial number as another certificate issued by the certificate authority. Please get a new certificate containing a unique serial number.
sec_error_bad_signature
I had this error when I took the same 'Common Name' for both 'CA server' and 'Server' certificate.
This Connection is Untrusted
This is normal when allowing a self-signed certificate. If you trust your own certificate:
- Click 'I understand the risks'
- Click 'Add Exception ...'
- You can uncheck 'Permanently store this exception' if you allow only for this session
- Click 'Confirm Security Exception'
Trust self-signed certificate on Android
- Export your certificate (only the public key) in DER format and save it as .cer file (in the above example this would be the file 'ca.cer'). With ca.cer you will trust the issuer so you will trust the issued.
- Put the .cer file onto your Android device storage. Then go to Settings - Security - Credential storage and select "Install from device storage".
Note: you could be warned that your network traffic can be monitored because the self-signed certificate is not trusted by a CA. However, if you keep your private key safe and as long you know its your certificate, this way might even be safer.