Creating a Self-Signed SAN Certificate on Ubuntu (Which Makes Chrome Happy)
As 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.