Simple CA for OpenBSD based VPN


Introduction

I have put together few scripts that help in setting up a Certificate authority (CA) and signing client/VPN gateway certificates. They are far from perfect and not very fancy, but a good start. I have used these scripts successfully with Linux, OpenBSD and w2k (cygwin). They should work with any setup that have OpenSSL and a reasonable shell (BSD sh, bash, etc.) installed.

Setup

Pick up a secure machine (propably without networking..) for yor CA. Download the package and untar it somewhere. The package should contain following files and directories:

Filename Explanation

CA.cnf OpenSSL configuration file
mkca.sh Initial setup script for the CA certificate
mkcert.sh This script generates client certificates and bundles them in PKCS#12 packages
sign.sh Sign certificate requests manually. This script is called from mkcert.sh, you don't normally run this directly.
revoke.sh Revoke certificates
serial Serial number for the next certificate
index.txt Certificate index file
reqs/ Directory for certificate requests
newcerts/ Directory for signed certificates
private/ Directory for CA key
vpnclients/ Directory for client certificates, keys and PKCS#12 files

Now, prepare your CA with the script mkca.sh. Default expiration of the CA certificate is 1460 (~ 4 years) days. You can change that by editing the variable DAYS in mkca.sh. Default for client/gateway certificates is 365 days, it can be changed by DAYS in sign.sh. You may also check out the variable KEYBITS, it defaults to 2048 bits (1024 for clients). Another interesting variable in mkca.sh is CRLS, which defines the certificate revocation list (CRL) distribution point URIs.


$ ./mkca.sh
Enter CA password: [Your password here]
Enter CA password (verify): [Your password here]
Generating RSA private key, 2048 bit long modulus
....................................................................+++
......................................+++
e is 65537 (0x10001)
Using configuration from CA.cnf
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) []:FI
State or Province Name (full name) []:.
Locality Name (eg, city) []:.
Organization Name (eg, company) []:klake.org
Organizational Unit Name (eg, section) []:.
Common Name (eg, fully qualified host name) []:klake.org CA
Email Address []:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
Signature ok
subject=/C=FI/O=klake.org/CN=klake.org CA
Getting Private key

This makes a CA certificate with a Distinguished Name (DN) C=FI, O=klake.org, CN=klake.org CA.

Gateway certificates

Client and VPN gateway certificates are generated with the script mkcert.sh. It's usage is as follows


$ ./mkcert.sh
Usage: ./mkcert.sh -ip|-dns|-email name [keybits]

The first two parameters define ID string and the common name (CN) of the client. -ip means IP address, for example 1.2.3.4. -dns is fully qualified domain name, for example gateway.domain.com and -email is email address. You should use -ip, or perhaps -dns for the gateway and -email for the clients. The last parameter is optional.

Next, define your common DN parameters by editing mkcert.sh. These are used for all certificates.


# countryName
COUNTRY=FI

# stateOrProvinceName
STATE=

# localityName
LOCALITY=

# organizationName
ORGANIZATION=klake.org

# organizationalUnitName
ORGANIZATIONAL_UNIT=

Change FI and klake.org to your two-character country code and organization. You can also add the other parameters if you wish. Example usage for gateway (change vpngw.klake.org as the dns-name of the gateway):


$ ./mkcert.sh -dns vpngw.klake.org

Signing certificate, enter the CA password
Using configuration from CA.cnf
Enter PEM pass phrase:[Your CA password here]
Check that the request matches the signature
Signature ok
The Subjects Distinguished Name is as follows
countryName           :PRINTABLE:'FI'
organizationName      :PRINTABLE:'klake.org'
commonName            :PRINTABLE:'vpngw.klake.org'
Certificate is to be certified until Jan  5 09:23:41 2004 GMT (365 days
Sign the certificate? [y/n]:y


1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated

Generating PKCS#12
Enter Export Password:[Export password here]
Verifying password - Enter Export Password:[Confirm]

PKCS#12 file written in vpnclients/vpngw.klake.org/vpngw.klake.org.p12

Note that the Export password is NOT same thing as your CA password. It is the password that your client has to know when the certificate is imported. You can find the following files in directory vpnclients/vpngw.klake.org

Filename Explanation

vpngw.klake.org.crt X.509 certificate
vpngw.klake.org.csr Certificate request
vpngw.klake.org.key Private key
vpngw.klake.org.p12 PKCS#12 bundle containing certificate, key and CA certificate

Now, you can import the certificate and key using OpenSSL pkcs12 tool or simply copying the files vpngw.klake.org.crt and vpngw.klake.org.key. Remember to include the CA certificate ca.crt also (it is included automatically in the p12 file). Default locations of these files on the OpenBSD gateway

Filename Install as

vpngw.klake.org.crt /etc/isakmpd/certs/local.crt
vpngw.klake.org.key /etc/isakmpd/private/local.key
ca.crt /etc/isakmpd/ca/ca.crt

Client certificates

Client sertificates are generated the exactly same way as the gateway certificate.

Example usage for VPN client (change noone@nowhere.com as the email-address of the client):


$ ./mkcert.sh -email noone@nowhere.com

This command should produce a pkcs12 file vpnclients/noone@nowhere.com/noone@nowhere.com.p12 for you to import in your favourite VPN client software.

Gateway certificates - the hard way

If you are not confortable with the idea of you gateway keys on the CA machine (if the machines are separate, anyway), you can split the process of key/request generation and signing using the following procedures

Generate key and certificate request for the VPN gateway. Issue the following commands on the VPN gateway


# openssl genrsa -out /etc/isakmpd/private/local.key 1024
# openssl req -new -key /etc/isakmpd/private/local.key \
	-out /etc/isakmpd/private/vpngw.klake.org.csr

Cut-and-paste the file /etc/isakmpd/private/vpngw.klake.org.csr to the CA directory reqs and sign it with the command


$ ./sign.sh reqs/vpngw.klake.org.csr -dns vpngw.klake.org

Change vpngw.klake.org as the FQDN of your gateway. This value is the ID string that your VPN clients expect to see. You should end up with the server certificate reqs/vpngw.klake.org.crt. There's also a copy of the certificate in the newcerts directory named as serial.pem where serial is the serial number of the issued certificate.

Other usage

These scripts can be used to sign ordinary server certificates (www, pop/imap, ldap or just about any SSL certificate) as well. Just leave out the subjectAltName parameters from sign.sh


$ ./sign.sh your-ssl-enabled-server-certificate-request

CRL handling

Certificates can be revoked with script revoke.sh. It takes a single argument, the name of the certificate to be revoked, and publishes CRL as a PEM-formatted file. The CRL file is named as crl.pem by default. You can change the name by editing variable CRL_NAME in revoke.sh. Default time before the next CRL is due can be changed with the variables CRL_DAYS and CRL_HOURS. Example usage:


$ ./revoke.sh newcerts/01.pem
Enter PEM pass phrase: [Your CA password here]
Using configuration from CA.cnf
Revoking Certificate 01.
Data Base Updated
Using configuration from CA.cnf

The CRL file must be distributed to clients somehow. The easiest way is to put the file on web server, in directory indicated by CRLS variable in mkca.sh. Most windows-based clients can read the URL from CA certifiacate and verify the CRL as needed. On the OpenBSD gateway, CRL must be found in the directory /etc/isakmpd/crls. You can fetch the file from the cron-script using any command-line browser (lynx, wget, nc..) or manually, using scp.


Copyright and Disclaimer

This document is copyright (c) 2003 of Jarkko Turkulainen. Redistribution of the document, with or without modification, is permitted provided that the redistribution retain the above copyright notice.

THE AUTHOR IS NOT RESPONSIBLE OF ANY DAMAGES INCURRED DUE TO ACTIONS TAKEN BASED ON THE INFORMATION IN THIS DOCUMENT.

Feedback

Bug reports, discussion, etc.: Sorry, you have to write it!.



Last updated Jan 05 2003