Creating a Self-Signed SAN Certificate on Ubuntu (Which Makes Chrome Happy)

Creating a self-signed SAN certificate on ubuntu, which makes chrome happyAs a developer, you often need to create a secure environment on a real server (not just localhost) while you test things out, prepare for demonstrations, etc.  This blog post will go over how to create not just a self-signed certificate (which is free), but how to also configure it as a "SAN" or Subject Alternative Names certificate. 

This so-called SAN certificate is important later, if we want to let our desktop Chrome automatically accept it and not show a privacy warning screen.

 

First Things First

For this example, I'm using Ubuntu 18x, but the same technique will work for 16x and probably 20x, when it comes out.  But of course, your mileage may vary.

I'm also assuming you know a little something already about how to use the Linux command line to edit files, configure Apache, etc.  If you don't have OpenSSL or any other tools already installed on your server, use the very helpful apt or apt-get command as your machine complains.

 

Step One - Create a Config for OpenSSL (So We Can Use Subject Alternative Names (SAN))

Copy the default openssl.cnf file for our use:

sudo cp /usr/lib/ssl/openssl.cnf ~/openssl.my.cnf

This is the default location of the file in Ubuntu 18x.

Now, edit the ~/openssl.my.cnf file.  Find the v3_req area, and add the following bolded portions...

[ v3_req ]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectAltName = @alt_names

[ alt_names ]
DNS.1 = mydomain.com 
DNS.2 = *.mydomain.com

Replace "mydomain.com" with whatever the full domain name is you will be working with.  localhost is fine here too.  If you do not need DNS.2, don't enter that line.

 

Step Two: Create the SSL Certificate

Now we will actually create the SSL cert itself.  Enter the following all on one line, then press Enter:

sudo openssl req -x509 -nodes -days 99999 -newkey rsa:2048 
-keyout /etc/ssl/private/apache-selfsigned.key 
-out /etc/ssl/certs/apache-selfsigned.crt 
-config ~/openssl.my.cnf 
-extensions 'v3_req'

Remember:  copy and paste to enter all on one line!

 

Step Two: Create a Strong Diffie-Hellman Group

This is an optional security step, but is good practice.  Simply enter this on the command line:

sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048

Be aware, it may take up to a minute or two to run.

 

Step Three:  Configure Apache to Use SSL

We are going to create an "ssl-params.conf" file for Apache, to make automatically configure some important values.

Create the file using:

sudo nano /etc/apache2/conf-available/ssl-params.conf

Then, paste in the following content:

SSLCipherSuite EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH
SSLProtocol All -SSLv2 -SSLv3
SSLHonorCipherOrder On
# Disable preloading HSTS for now.  You can use the commented out header line that includes
# the "preload" directive if you understand the implications.
#Header always set Strict-Transport-Security "max-age=63072000; includeSubdomains; preload"
Header always set Strict-Transport-Security "max-age=63072000; includeSubdomains"
Header always set X-Frame-Options DENY
Header always set X-Content-Type-Options nosniff
# Requires Apache >= 2.4
SSLCompression off
SSLSessionTickets Off
SSLUseStapling on
SSLStaplingCache "shmcb:logs/stapling-cache(150000)"

SSLOpenSSLConfCmd DHParameters "/etc/ssl/certs/dhparam.pem"

 

Step Four: Configure Our Site to Use The Self-Signed Certificate (The Home Stretch!)

Okay, we are finally ready to configure Apache's setting for our particular site, and tell it to use our certificate.

sudo nano /etc/apache2/sites-available/whatever-site.conf

Replace "whatever-site" with the file that corresponds to your site.  000-default is the default one, but if you are hosting several virtual hosts, it might be named something different.

The contents should now look similar to this:

<Directory /var/www/html/htdocs/public_html>
        Options Indexes FollowSymLinks
        Require all granted
        AllowOverride All
</Directory>

<VirtualHost *:80>
  RewriteEngine On
  RewriteCond %{HTTPS} off
  RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
</VirtualHost>

<VirtualHost *:443>
     ServerName mydomain.com
  ## ServerAlias www.mydomain.com
     ServerAdmin webmaster@localhost
     DocumentRoot /var/www/html/htdocs/public_html
     ErrorLog /var/www/html/htdocs/logs/error.log
     CustomLog /var/www/html/htdocs/logs/access.log combined

     SSLEngine on

     SSLCertificateFile      /etc/ssl/certs/apache-selfsigned.crt
     SSLCertificateKeyFile /etc/ssl/private/apache-selfsigned.key

     <FilesMatch "\.(cgi|shtml|phtml|php)$">
           SSLOptions +StdEnvVars
     </FilesMatch>
     <Directory /usr/lib/cgi-bin>
           SSLOptions +StdEnvVars
     </Directory>

     BrowserMatch "MSIE [2-6]" \
              nokeepalive ssl-unclean-shutdown \
              downgrade-1.0 force-response-1.0

</VirtualHost>

Where this is tricky is depending on your directory structure, some of the values may be different.  For exampel, the location of the logs, or the document root.  The SSLCertificateFile location and name should be the same, since that is what we specified earlier.

Something else to note:  this particular set up will automatically redirect all HTTP traffic to HTTPS, which in general is what you want.

Now, let's make sure we have everything enabled for Apache....

sudo a2enmod ssl
sudo a2enmod headers
sudo a2enconf ssl-params

Next, test your config:

sudo apache2ctl configtest

If it comes back with 'Syntax OK', then we're good to go.

Let's restart Apache!

sudo systemctl restart apache2

After this, you should visit your website in a browser.  At this point, since you are using a self-signed certificate, it will show a security warning.  That's OK-- you can trust it, it's your server.

 

In the next blog post, we'll go over how to tell Chrome to automatically accept your self-signed cert, and do away with the annoying security warning.