Tag Archives: webserver

SSL Certificate Signing for Free with SAN/UCC

If you run your own website, email server or other services  at home then you should make use of a SSL certificate. When you install most webservers (Apache, NGINX, etc.), they generates a self-signed “snakeoil” certificate that can be used to encrypt your session. This is really only intended for testing, and has a few issues:

  1. The common name on the certificate probably doesn’t match your domain name. Scary warning from most browsers (though this can happen occasionally due to configuration error).
  2. The snakeoil certificate has not been signed by an authority that your browser trusts, so your browser will throw another error when you connect.
  3. Short of manually inspecting the certificate’s checksum, you have no guarantee that you are communicating with your own server – bit like how you usually ignore the SSH fingerprint when you are connecting to a new server, you just assume it to be correct but pay attention if it ever changes.

I’ve chosen to go the budget route and create an SSL cert request and get it signed by the community driven SSL certificate signing authority CAcert. Once you have imported the certificate into your browser or into your operating system’s root filesystem, your computer will automatically verify the identity of the server and you will enjoy error-free secure communications. Oh, and CAcert is free of charge!

The one caveat to this, is not all browsers have CAcert’s root certificate installed.

Filename Extensions

Just to note that while linux doesn’t care what you have as an extension, Windows does very much. Since this is for Debian, your milage may vary. For my own peace of mind I’m making use of 3 extensions.

  • .key – this is for the private key. This file should be kept secret and protected
  • .crt – This is the server certificate
  • .csr – This is the server certificate request, and what is signed by the Certificate Authority [CA].

Generating The Certificate

Create a private key

This command uses openssl to generate a 4096-bit RSA key

openssl genrsa -out <filename for your private key>.key 4096

Generating the Certificate Request

The key piece of information here is the common name. This is the name that the cert is bound to e.g. www.flat-planet.net. However, for example, if the common name provided is flat-planet.net then there will be an error in all browsers stating that the site name does not match the common name. There are two ways to work around this:

  1. Generate a wildcard cert that will allow you to sign all subdomains e.g. common name = *.flat-planet.net, which will cover us for all future subdomains we might want to use.
  2. Generate a SubjectAltName CSR with a list of all the subdomains we are planning on using.

The second is the more interesting, so that is what I’ll use here.

Create a SAN/UCC CSR

SAN certificates (or as Microsoft and others have taken to calling them, Unified Communications Certificates) are rapidly becoming a popular option for securing multiple domains. In fact, Exchange 2007, OCS 2007, and several other products now require UCC to function. However, this certificate type can proffer some advantages beyond that of a wildcard certificate as well. One such advantage is the ability to secure “domain.com”, “www.domain.com”, “domain.net”, and “someotherdomain.com” all within a single certificate.

The catch is that OpenSSL will not allow you to add SANs interactively, so we need a config file to make the magic happen. We create a new .conf file for OpenSSL. Most of this file is just over-riding the default prompts, the interesting piece is the [alt_names] section. Each subdomain we want to certify is listed here. To add another just add in DNS.5, DNS.6, etc.

[ req ]
default_bits        = 4096
default_keyfile     = privkey.pem
distinguished_name  = req_distinguished_name
req_extensions     = req_ext # The extentions to add to the self signed cert

[ req_distinguished_name ]
countryName           = Country Name (2 letter code)
countryName_default   = IE
stateOrProvinceName   = State or Province Name (full name)
stateOrProvinceName_default = Co. Dublin
localityName          = Locality Name (eg, city)
localityName_default  = Dublin
organizationName          = Organization Name (eg, company)
organizationName_default  = FlatPlanet Networks Ltd.
commonName            = Common Name (eg, YOUR name)
commonName_max        = 64

[ req_ext ]
subjectAltName          = @alt_names

[alt_names]
DNS.1   = www.flat-planet.net
DNS.2   = mail.flat-planet.net
DNS.3   = im.flat-planet.net
DNS.4   = comms.flat-planet.net

Once we have this file created, we use it in common with our private key to create the certificate request (CSR). In this case I used flat-planet.net as the common name.

openssl req -out CSR.csr -key flat-planet-private.key -config ./openssl_req.conf -new
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [IE]:
State or Province Name (full name) [Co. Dublin]:
Locality Name (eg, city) [Dublin]:
Organization Name (eg, company) [FlatPlanet Networks Ltd.]:
Common Name (eg, YOUR name) []:flat-planet.net

Don’t set a password – leave it blank when asked.

Install the CA Root Certificate (optional)

This is not really required on the server side, but since we are using CAcert to sign our cert we should accept their signing of others.

cd ~
wget http://www.cacert.org/certs/root.txt
sudo cp root.txt /etc/ssl/certs/cacert-root.crt
sudo c_rehash /etc/ssl/certs

The last command regenerates the hashes of all the certs – some applications use these for a fast lookup.

Required E-Mail Addresses

To prove that you have control over the domain that you are generating the cert for CAcert will send you confirmation mails to one of the following addresses:

NOTE: Replace flat-planet.net with the domain you are trying to get signed. If these accounts don’t exist, just add them as entries to the /etc/aliases file and regenerate the database (postfix).

vi /etc/aliases
...
postmaster: yourusername
webmaster: yourusername
root: yourusername
sudo newaliases
sudo service postfix reload

Submitting the CSR

First things first, you will need to go to the CAcert website and create an account. Once the account is created, log in and go to Server Certificates -> New, and submit the contents of CSR.csr (that you created earlier, include the BEGIN and END blocks). The cert will be displayed, and a link e-mailed to you. Simply copy the text shown, and save them in a .crt file.

Congrats – you now have a signed cert.

File locations and permissions

This is a key step, as we didn’t set a password so are relying on file permissions to enforce security.

  • The key file should be stored in /etc/ssl/private/flat-planet-private.key
  • Key should be owned by root:root with 600 permissions
  • The certificate should be stored in /etc/ssl/certs/flat-planet.crt
  • Certificate should be owned by root:root with 644 permissions

Using the Certs

The exact configuration will vary depending on the application e.g. Apache, Nginx, postfix, dovecot. See other guides for more details on these, but generally you will have to point them towards both the cert and the key.

Using RPi-Monitor with your own webserver (Nginx)

As I recently moved this site to a RPI for hosting purposes, I though it would be a good idea to have a nice web page to monitor the current status of the box. Some googling later and I found the excellent RPi-Monitor.

By default it has it’s own webserver, and it is not recommended to use anything other then that, but running a second webserver seemed a little bit untidy to my thinking so I set it to run on Nginx instead.

The actual changes were quite simple, with one or two gotcha’s.

RPi-Monitor stores the webpage in /usr/share/rpimonitor/web by default. Rather then play with that I just created a symbolic link between the root of the webserver and that point:

ln -s /usr/share/rpimonitor/web /var/www/rpimonitor

and that is sorted.

Next up is the configuration change to the rpimonitor daemon – config file located in /etc/rpimonitor/daemon.conf. We need to set it into no-server mode and also change the user, as I’ve disabled the default ‘pi’ account on this box.

# daemon.noserver=1
# Define that rpimonitor shouldn't start web server (default:0)
# Note: A symbolic link from /var/lib/rpimonitor/stat to
# /usr/share/rpimonitor/stat may be required
daemon.noserver=1

# Define user used to run the server process (default:pi)
# Note: If user is not existing, process will run with uid=1000
daemon.user=rpi-monitor
#
# daemon.group=pi
# Define group used to run the server process (default:pi)
# Note: If group is not existing, process will run with gid=1000
daemon.group=rpi-monitor
#

Restart the service, and you should be able to access it from http://my-website.com/rpi-monitor

$ sudo service rpimonitor restart

RPI-Monitor StatusHowever there is a slight issue in that the datastore is inaccessible to the webserver, so statistics are unavailable with error “File stat/uptime.rrd is not a valid RRD archive”. To resolve this we need to go back to the daemon.conf file and move the datastore to somewhere under the root directory of the website

# daemon.datastore=/var/lib/rpimonitor
# Define the data storage directory (Default:/var/lib/rpimonitor)
daemon.datastore=/var/www/rpimonitor

Restart the service again and all is worky.

$ sudo service rpimonitor restart

RPI-Monitor StatisticsNote: you could also just move the webroot in the same way, rather then using the symbolic link.