OpenSSL certificates in a nutshell
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