These notes are a little rough-and-ready, copied more or less directly from my old wiki which was only intended for my consumption.

See my notes on using OpenSSL as a Certificate Authority for how to create and use your own CA.

Using the certificates

Installing the root certificate

Debian

If there are multiple certificates create a directory in /usr/local/share/ca-certificates for the certificates:

mkdir /usr/local/share/ca-certificates/my.domain.tld

Drop the certificate into /usr/local/share/ca-certificates (or the subdirectory you just created).

Run the Debian certificate update command:

update-ca-certificates

iOS

Easiest way is to email the certificate to myself and then simply tap on it in mail, which will prompt to import the CA certificate as a “configuration profile”.

They can be removed by going to Settings → General → Profiles

Use with OpenVPN

N.B. The server certificate needs to be just that (serverAuth in the purpose). clientAuth, per an OpenVPN client certificate, will cause a problem.

In the client or server .conf file add the following sections:

<ca>
-----BEGIN CERTIFICATE-----
root certificate
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
intermediary ca certificate
-----END CERTIFICATE-----
</ca>

<cert>
-----BEGIN CERTIFICATE-----
server certificate
-----END CERTIFICATE-----
</cert>

<key>
-----BEGIN PRIVATE KEY-----
server key
-----END PRIVATE KEY-----
</key>

The server requires an additional section, the Diffie-Hellman parameters:

<dh>
-----BEGIN DH PARAMETERS-----
dh parameters
-----END DH PARAMETERS-----
</dh>

Use with Apache

In order to use name based virtual hosts with multi-names ssl certs I needed to add NameVirtualHost *:443 to /etc/apache2/ports.conf before Listen 443.

Here’s an example named (fictitious) virtual host config for SSL:

<VirtualHost *:443>
	SSLEngine on
	SSLCertificateFile /etc/ssl/certs/spam.domain.tld.pem
	SSLCertificateKeyFile /etc/ssl/private/spam.domain.tld.key
	SSLCertificateChainFile /etc/ssl/certs/domainCA.tld.pem
 
	DocumentRoot /srv/spam
	ServerName spam.domain.tld
	ErrorLog /var/log/apache2/spam.domain.tld-error.log
	TransferLog /var/log/apache2/spam.domain.tld.log
</VirtualHost>

Use with NGINX

Firstly, NGINX requires a certificate bundle creating with the server’s certificate in the bundle file and first (this is unusual compared to other software which places the Root certificate first and then moving down the tree to the final, server, certificate). The reason is that NGINX will only try the key with the first certificate in the file.

cat server.pem intermediate_ca_bundle.pem > nginx_bundle.pem

To enable ssl globally, which is more efficient if using the same certificate for all site (e.g. with subject alternative names), put the ssl config items in the http { … } section. To use a different certificate per-site (e.g. with multiple IPs) put it in each respective server { … } section.

The ssl configuration options are:

http {
...
	ssl_certificate     /etc/ssl/nginx-combined.pem;
	ssl_certificate_key /etc/ssl/private/cert.key;
	# Enable ssl session caching, once handshake has occurred, for efficiency
	ssl_session_cache   shared:SSL:10m;
	ssl_session_timeout 10m;
...
}

In each server { … } section you want to use ssl on then need to tell nginx to use ssl with the port you are using for https. It is possible (and completely permissible) to serve on both ssl and non-ssl in the same section.

N.B. Turning on keepalive with https is highly recommended for efficiency and responsiveness.

Example:

server {
	listen 80;
	listen 443 ssl;
	server_name spam.domain.tld;

	keepalive_timeout 70;
...
}

Creating a certificate signing request

This is a minimal OpenSSL configuration file for generating a request:

[ req ]
distinguished_name = req_distinguished_name
string_mask        = utf8only

[req_distinguished_name]

Create a CSR

Generating a CSR is as easy as:

CN=$(hostname -f)
openssl req -new -newkey rsa:2048 -sha256 -nodes -out "$CN.csr" -keyout "$CN.key" -config "config.cnf" -subj "/countryName=GB/localityName=Birmingham/stateOrProvinceName=West Midlands/organizationName=Entek/commonName=$CN/"

Subject Alternative Names (SAN)

To create a certificate with multiple names you need to add ‘subjectAltName=DNS:name1.tld,DNS:name2.tld’ to the ‘[ v3_req ]’ section of openssl.cnf.

Alternatively a list can be added thus, which looks cleaner:

[ req ]
distinguished_name = req_distinguished_name
req_extensions = v3_req

[req_distinguished_name]

[v3_req]
subjectAltName=@alt_names

[alt_names]
DNS.1 = server1.example.com
DNS.2 = mail.example.com
DNS.3 = www.example.com
DNS.4 = www.sub.example.com
DNS.5 = mx.example.com
DNS.6 = support.example.com

N.B. Don’t forget to add the common name to the list of alternative names or it will not be valid for the common name!

Useful (troubleshooting) commands

Dump a certificate

openssl x509 -text -noout -in certificate.pem

Dump a remote certificate

openssl s_client -showcerts -connect www.domain.com:443

Verify a certificate

With an intermediate certificate bundle:

openssl verify -CAfile /etc/ssl/certs/EntekRootCA.pem -untrusted IntermediateCert.pem certificate.pem

With a full chain (note: with openssl the certificates should be in sequence of highest level → server (e.g. the root at the top, then intermediate, then subordinate intermediate … server/final certificate):

openssl verify -CAfile /etc/ssl/certs/EntekRootCA.pem certificate_budle.pem

Test certificate purpose

openssl x509 -purpose -noout -in certificate.pem

Verify a CSR

Miss out -text if you don’t want to see the details of the certificate.

openssl req -verify -text -noout -in req.csr