Header Ads

Creating Self-signed SSL certificates using OpenSSL on Linux

Getting free SSL certificates are now easy as installing a free Linux OS, thanks to Let's Encrypt. However, there may be situations (such as development) where self-signed SSL certificates are more suitable. In this guide, let's create and install self-signed certificate on Nginx using the OpenSSL tool.

OpenSSL Self-signed SSL certificates


1. Create root CA certificates

First step here is to create our own Certificate Authority (CA) keys, which can be used to sign the SSL certificates. This "CA" (let's call it selfCA) certificates will be useful later to validate our SSL certificates in browsers and applications. However do note that, all mainstream browsers only trust SSL certificates signed by branded CA's like Verisign.

Generate private key for selfCA on your local PC. Enter a strong passphrase for securing the key.

`openssl genrsa -des3 -out selfCA.key 4096`

Generate root certificate for selfCA using the private key. Change the -days flag for suitable validity. Enter the passphrase used in previous step. Fill all details like country name, etc..

`openssl req -x509 -new -nodes -key selfCA.key -sha256 -days 1825 -out selfCA.pem`

This root certificate should be installed in browsers to trust the SSL servers signed by it. Keep both files securely for later use.

Copy the CA key pair to server. Replace x.x.x.x with IP address and enter root password on prompt.

`scp selfCA.key root@x.x.x.x:/etc/ssl/private
scp selfCA.pem root@x.x.x.x:/etc/ssl/private`


2. Create self-signed SSL certificates

Now we create self-signed SSL certificates using our self-signed CA certificates.

Generate private key for server (replace example.com). In this guide, we'll generate ssl keys on the server directly.

`openssl genrsa -out /etc/ssl/private/example.com.key 3072`

Create a certificate signing request for the ssl private key

`openssl req -new -key /etc/ssl/private/example.com.key -out /etc/ssl/private/example.com.csr`

Use selfCA key pair, SSL csr and config extension file to generate a self-signed SSL certificate. Change number of days, key paths as required.

`openssl x509 -req -in /etc/ssl/private/example.com.csr -CA /etc/ssl/private/selfCA.pem -CAkey /etc/ssl/private/selfCA.key -CAcreateserial -out /etc/ssl/certs/example.com.crt -days 365 -sha256 -extfile /etc/ssl/private/example.com.ext`

Use selfCA key pair and SSL csr to generate a self-signed SSL certificate. Change number of days, key paths as required and replace example.com.

`openssl x509 -req -in /etc/ssl/private/example.com.csr -CA /etc/ssl/private/selfCA.pem -CAkey /etc/ssl/private/selfCA.key -CAcreateserial -out /etc/ssl/certs/example.com.crt -days 365 -sha256 -extfile <(printf "authorityKeyIdentifier=keyid,issuer\nbasicConstraints=CA:FALSE\nkeyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment, keyAgreement\nextendedKeyUsage = serverAuth\nsubjectAltName=DNS:example.com,DNS:www.example.com")`

To verify the certificate

`openssl x509 -in /etc/ssl/certs/example.com.crt -text -noout`


3. Install self-signed SSL certificate on Nginx server

Create a strong Diffie-Hellman group for the server

`openssl dhparam -out /etc/ssl/certs/dhparam.pem 3072`

Create Nginx snippet for SSL cert locations

`nano /etc/nginx/snippets/ssl-selfsigned.conf`

And add following lines and save file

`ssl_certificate /etc/ssl/certs/example.com.crt;
ssl_certificate_key /etc/ssl/private/example.com.key;`

Create Nginx snippet for SSL params

`nano /etc/nginx/snippets/ssl-params.conf`

And add following lines and save file

`ssl_protocols TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
ssl_ecdh_curve secp384r1;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
ssl_stapling off;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
# Disable preloading HSTS for now.  You can use the commented out header line that includes
# the "preload" directive if you understand the implications.
#add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";
add_header Strict-Transport-Security "max-age=63072000; includeSubdomains";
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
ssl_dhparam /etc/ssl/certs/dhparam.pem;`

Edit server nginx config to include the location of both snippets within ssl server block.

`nano /etc/nginx/sites-available/example.com`

`server {
    listen 443 ssl;
    ...
    
    include snippets/ssl-selfsigned.conf;
    include snippets/ssl-params.conf;

    ...
}`

Restart nginx and confirm

`systemctl restart nginx`

To validate certificate using OpenSSL, execute following command

`openssl s_client -CAfile selfCA.pem -connect example.com:443`


Optional Commands

1. To use wget command with certificate

`wget https://example.com --ca-certificate=selfCA.pem`

2. To use curl command with certificate

`curl --cacert selfCA.pem -v https://example.com`

3. To install selfCA cert on Linux

`sudo cp selfCA.pem /usr/local/share/ca-certificates/selfCA.pem`

`sudo update-ca-certificates`

4. To install SelfCA cert on Firefox browser

Go to Preferences -> Privacy & Security -> Certificates -> Authorities -> Import and choose the selfCA.pem file.


No comments