Create certificates for Apache2: Difference between revisions

From WickyWiki
 
(2 intermediate revisions by the same user not shown)
Line 150: Line 150:
# 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.
# 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 probably give a warning and ask explicitly to accept or deny it.
#* In the case of a self-signed certificate the client will probably give a warning and ask explicitly to accept or deny it.
# A random symmetric key is send to the server, encrypted with the public key. This is now a 'secret' shared by only webserver and client.
# A random symmetric key is send to the server, encrypted with the public key. This is now a 'secret' shared by webserver and client.
# Data will now be encrypted and decrypted with the symmetric key.
# Data will now be encrypted and decrypted with the symmetric key.


<pre>
<pre>
          CLIENT -----> connection request ----> WEBSERVER


          CLIENT --------> page request -------> WEBSERVER
                                                  public key,
 
             check <-- public key, certificate <-- certificate
             check <-- public key, certificate <--  
       certificate
       certificate


   generate random  
   generate random  
symmetric key and  
    symmetric key
    encrypt with  
include complete
      public key --------> symmetric key ------->  
  url and encrypt
  with public key ---> [ symmetric key, url ] ---> symmetric key, url


                                                   encrypt webpage
                                                  webpage,
     decrypt with <----------- webpage <---------- with symmetric key
                                                   encrypt with
     decrypt with <--------- [ webpage ] --------- symmetric key
     symmetric key
     symmetric key



Latest revision as of 14:39, 20 August 2020


General information

Sources:

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 a 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 730 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 730 -extensions certauth -outform PEM -out ca.cer

You will now have a file 'ca.key', this is the private key of the CA and the file 'ca.cer' this is the CA self-signed certificate. This is the one you have to add to your clients trust-store, being a self-signed certificate you probably will have some warnings.

Next you need to create a private SSL key for the webserver, being the CA yourself you will request and create one yourself using the CA private key.

Now you can be a certificate authority (CA) without the 'trusted' part.

Create server certificate

Generate a private SSL key for the server:

openssl genrsa -out server.key 2048

You would never give your private key to the CA, therefore we need to generate a Certificate Signing Request. 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

For this step you yourself will be the CA. Create a self-signed server certificate (valid for 365 days) with serial number (121) as requested with file 'server.req'.

  • Note 1: you need a unique serial number, you could use 1YY where YY is the expiration year.
  • Note 2: although the signing request (server.req) is based on the private key (server.key), the private key can not be reconstructed from the request. This way the CA will not have your private key (unless its all you).
openssl x509 -req -in server.req -CA ca.cer -CAkey ca.key -set_serial 121 -extfile create_ssl.conf -extensions server -days 365 -outform PEM -out server.cer

The file 'server.key' is the server's private key, for use with your webserver and should not be shared with anyone. The file 'server.cer' is the certificate itself and will be used by clients to encrypt there requests en decrypt responses. Certificate Signing Request file 'server.req' is no longer needed. The CA-files 'ca.cer' and 'ca.key' could be reused if 'server.cer' expires.

Note to myself:

  • This page might not be available if you make a mistake

Configure Apache2 SSL

See:

Get HTTPS for free

Let's Encrypt is an official CA that allows you to create the certificates for free. It is based on the fact that:

  1. you have control of the files/website that is accessible via the domain you need a certificate for.
  2. it needs to be re-issued every 90 days. There is an automatic renewal client to make this work

More info:

Manual method:

How it works

Using the created keys, this is how the HTTPS session will be initiated:

  1. The client requests content from the Web Server using HTTPS.
  2. The web server responds with a Certificate which includes the server's public key (file 'server.cer')
  3. The client checks to see if the certificate has expired.
  4. The client checks if the Certificate Authority that signed the certificate is a trusted authority listed in the browser.
  5. 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 probably give a warning and ask explicitly to accept or deny it.
  6. A random symmetric key is send to the server, encrypted with the public key. This is now a 'secret' shared by webserver and client.
  7. Data will now be encrypted and decrypted with the symmetric key.
           CLIENT -----> connection request ----> WEBSERVER

                                                  public key,
            check <-- public key, certificate <-- certificate
      certificate

  generate random 
    symmetric key
 include complete
  url and encrypt 
  with public key ---> [ symmetric key, url ] ---> symmetric key, url

                                                   webpage,
                                                   encrypt with
     decrypt with <--------- [ webpage ] --------- symmetric key
    symmetric key

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 client101.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 client101.key -out client101.req

Create a self-signed Certificate Authority client certificate with serial number 101 (66 hexadecimal):

openssl x509 -req -in client101.req -CA ca.cer -CAkey ca.key -set_serial 101 -extfile create_ssl.conf -extensions client -days 365 -outform PEM -out client101.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 client101.key -in client101.cer -out client101.p12

File 'client101.p12' contains a private key and the client's certificate, the files 'client101.key', 'client101.cer' and 'client101.req' are no longer needed:

rm client101.key client101.cer client101.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:

  1. Click 'I understand the risks'
  2. Click 'Add Exception ...'
  3. You can uncheck 'Permanently store this exception' if you allow only for this session
  4. Click 'Confirm Security Exception'

Trust self-signed certificate on Android

  1. 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.
  2. 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.