[Ref: OpenBSD 3.5 ]
Portions Reviewed in OpenBSD 4.6, and 4.7
Table of Contents
OpenBSD ships with built in support for OpenSSL and OpenSSH in the base install for encrypted communication. Both systems use public key algorithms, where key-pairs are used with one half is public, and the other half private.
Warning: Remember I know less than you about this stuff, these are notations of something that worked. It doesn’t mean it works well.
For OpenVPN we need a Public Key Infrastructure (PKI) which essentially is a recognised:
We want to be our own Certificate Authority so that we can generate and sign all our client certificates. We need to set ourselves up a CA certificate with will act as the master certificate with which we sign all server and client certificates.
These notes provided the steps using the OpenSSL PKITOOLS:
Creating a CA Certificate manually involves:
OpenVPN CA are built using the ./build-ca which invokes PKITOOL and the following command:
openssl req -days 3650 -new -newkey rsa:4096 -sha1 \ -x509 -keyout path-to/private/ca.key \ -out path-to/private/ca.crt \ -config path-to/openssl.cnf && \ chmod 0600 path-to/private/ca.key
Which ever manner you choose to generate the keys, you can validate the keys creation by using OpenSSL.
openssl rsa -noout -text -in path-to/private/ca.key openssl x509 -noout -text -in path-to/private/ca.crt
For each OpenVPN Client, we need to generate independent certificates using ./build-key client_details1.
which invokes PKITOOL and the following command:
openssl req -days 3650 -new -newkey rsa:4096 \ -keyout path-to/keys/client_details1.key \ -out path-to/keys/client_details1.csr \ -config -path-to/openssl.cnf
In practise, we generally name client certificates something like the below:
The client_ desginator works to quickly identify VPN user clients, as opposed to other test accounts.
Certificate revocation is handled using a CRL pem file. All certificates that are generated and issued are tracked by the CA through a text based database file “index.txt”. As new certificates are generated, they are keyed with a sequentially increasing serial number that uniquely identifies each key that has been generated and signed by our CA certificate.
If we need to revoke a certificate we use the “revoke-full” script (part of the provided OpenSSL toolkit that comes with OpenVPN), which then adds the unique serial identified for the key to be revoked to the CRL pem file. OpenVPN will then refuse to authorise the revoked certificate.
If you want to view which serial identifiers are currently in the crl.pem file, you can use the following command:
openssl crl -in /etc/openvpn/keys/crl.pem -outform DER | openssl crl -inform DER -text -noout
The output of these commands will look like the following:
Certificate Revocation List (CRL): Version 1 (0x0) Signature Algorithm: md5WithRSAEncryption Issuer: /C=AU/ST=NSW/L=SYDNEY/O=Example Corp/CN=Example Corp CA/emailAddress=... Last Update: Jun 3 23:12:48 2008 GMT Next Update: Jul 3 23:12:48 2008 GMT Revoked Certificates: Serial Number: 0A Revocation Date: May 18 05:38:19 2007 GMT Serial Number: 1A Revocation Date: Apr 30 02:41:24 2007 GMT Serial Number: 2B Revocation Date: Jun 3 23:12:48 2008 GMT ...
You can then grep the serials (0A, 2B etc) out of the index.txt file as follows:
# grep 0A /etc/openvpn/keys/index.txt
R 161209135638Z 070518053819Z 0A unknown /C=AU/ST=NSW/L=SYDNEY/O=MYCORP/CN=...
Sample Script to automate the above
#!/bin/sh # Grab List of Revoked Keys COUNTRY="AU" STATE="NSW" LOCATION="SYDNEY" ORG="MYCORP" ADMIN1="admin1@example.com" ADMIN2="admin2@example.com" KEYSDIR=/etc/openvpn/keys CRLPEM=$KEYSDIR/crl.pem INDEX=$KEYSDIR/index.txt SERIALS=`openssl crl -in $CRLPEM -outform DER |\ openssl crl -inform DER -text -noout | \ grep "Serial Number:" | awk -F ":" '{ print $2 }'` echo "State Serial Client-Details" echo "-------------------------------------" for i in $SERIALS; do grep $i $INDEX | grep "^R" | awk '{print $1, $4, $6}' | \ sed "s/\/C=$COUNTRY//;s/\/ST=$STATE//;s/\/L=$LOCATION//" | \ sed "s/\/O=$ORG//;s/\/CN=//" |\ sed "s/\/emailAddress=$ADMIN1//;s/\/emailAddress=$ADMIN2//" done echo "-------------------------------------" echo "State Serial Client-Details"
Working in the opposite direction, you can now use the above generated list (confirming the Serial Number, 2nd field in the list) (to verify the Revocation date
For a list of active keys, use the following
#!/bin/sh # Grab List of Active Keys COUNTRY="AU" STATE="NSW" LOCATION="SYDNEY" ORG="MYCORP" ADMIN1="admin1@example.com" ADMIN2="admin2@example.com" KEYSDIR=/etc/openvpn/keys CRLPEM=$KEYSDIR/crl.pem INDEX=$KEYSDIR/index.txt SERIALS=`openssl crl -in $CRLPEM -outform DER |\ openssl crl -inform DER -text -noout | \ grep "Serial Number:" | awk -F ":" '{ print $2 }'` echo "State Serial Client-Details" echo "-------------------------------------" for i in $SERIALS; do grep $i $INDEX | grep -v "^R" | awk '{print $1, $3, $5}' | \ sed "s/\/C=$COUNTRY//;s/\/ST=$STATE//;s/\/L=$LOCATION//" | \ sed "s/\/O=$ORG//;s/\/CN=//" |\ sed "s/\/emailAddress=$ADMIN1//;s/\/emailAddress=$ADMIN2//" done echo "-------------------------------------" echo "State Serial Client-Details"
* <a href="#ssc.intro">Self-signed Certificates</a>
* <a href="#ssc.key" class="anchBlue">Signing Key</a>
* <a href="#ssc.csr">Certificate Signing Request</a>
* <a href="#ssc.crt" class="anchBlue">Sign the Certificate</a>
* <a href="#ssc.verify" class="anchBlue">Verify the Keys</a>
* <a href="#client">OpenVPN Client Certificates</a>
Ref: OpenSSL HOWTO
SSL assume the server has a private key paired with a public key made available to the remote client. The remote client encrypts communications using the public key, and the server decrypts the information using the private key.
Creating a certificate was initially meant for a third-party authority to assist you in verifying that the server is who they say they are, so the creation of a self signing certificates requires 3 stages
We are choosing our file names based on the standard OpenBSD/Apache configuration for SSLfiles
Public Keys are easily derived from Private Keys, Generate a Private Key using OpenSSL’s genrsa
# /usr/sbin/openssl genrsa -des3 -out /etc/ssl/private/server.key 4096
The generated key acts as our SSL private key to be used as our ‘internal’ CA (Certificate Authority.)
We can call the key anything we want, and the general mod_ssl example is ca.key, but in the above scenario we will use server.key. The mod_ssl documentation recommends 1024 for compatibility with older Internet Browsers, which for this work is not a concern. Refer to the documentation for the current minimum recommended keysize.
-des|-des3|-idea You must specify the method to encrypte the private key, otherwise is no encryption is used.
A certificate combines data identifying your server, and the authority that accepts authentication of your identity. Create a certificate request (also known as a certificate signing request) to be signed by the certificate authority.
Generate a csr using the server key generated above (output will be PEM formatted.)
# /usr/sbin/openssl req -new \ -key /etc/ssl/private/server.key \ -out /etc/ssl/private/server.csr
The above certificate request will prompt you to reply to a number of questions, most of which can be left as the default. You will be asked for the Fully Qualified Domain Name for this host. In my experience this requires the legitimate DNS name that the host will be responding to.
The last part of the above instructions is to ask for ’extra’ attributes.
Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []: An optional company name []:
For my test configuration (ie. I don’t want to enter the password everytime I want to start a server) I do not enter a ‘challenge password.’ On a security conscious system, you probably want to specify a challenge password here and have someone on 24-hour availability incase the server restarts and someone must enter the ‘challenge password’ before the server starts.
The concept is that you send the above CSR for a trusted third party to sign, and record in their system, so users who recieve your key can validate from the trusted third party that you are who you are. But we don’t want no third party saying who we are (for now anyway.)
the output will be PEM formatted. (The documentation discusses a script sign.sh to do this task for you, but I can only find CA.pl and CA.sh with similar ‘purpose.’)
# /usr/sbin/openssl x509 -req -days 365 \ -in /etc/ssl/private/server.csr \ -signkey /etc/ssl/private/server.key \ -out /etc/ssl/server.crt
-x509 is the certificate structure we are using. -days 365 is the number of days for which we want the certificate to be valid
You can test from a terminal connection the status of your keys by using the following commands
# openssl rsa -noout -text -in /etc/ssl/private/**server.**key # openssl req -noout -text -in /etc/ssl/private/**server.**csr # openssl x509 -noout -text -in /etc/ssl/**server.**crt