Creating Certificates and Keys for pfSense 1.2 Series OpenVPN Servers and Clients

Notable changes to this document

1.0 Introduction

This is a guide to using TinyCA on Unix operating systems (such as Linux) to create a certificate authority (CA), then certificates and keys for using a pfSense-based OpenVPN. pfSense requires you provide it with certificates and keys, rather than having its own built-in interface to create them. We setup the CA on a different computer to pfSense and from there make the certificates and keys required by both pfSense and client computers.

The pfSense web site has two guides that cover similar ground to this guide but I found them to be insufficient for my needs: 'VPN Capability OpenVPN' (is Gentoo-specific and uses the command-line rather than a GUI) and 'Pfsense and OpenVPN for new users' (uses Windows to create the CA and also uses the command-line).

2.0 TinyCA

tinyca (tinyca.sm-zone.net) is a very simple Certification Authority. It features a graphical interface to create Certificate Requests, sign them with the key of the Certificate Authority and export the signed certificate and the corresponding keys in various formats.

In Debian or Ubuntu install the package 'tinyca'.

This is the file and directory structure used by TinyCA to store the certificates and keys, in ~/.TinyCA/, for each CA:

|-- <organisation>-CA
|   |-- cacert.key
|   |-- cacert.pem
|   |-- certs
|   |   |-- dGVzdDI6IDogOnRlc3Q6IDp1azpVSw==.pem
|   |   `-- dGVzdDM6IDogOnRlc3Q6IDp1azpVSw==.pem
|   |-- crl
|   |   `-- crl.pem
|   |-- index.txt
|   |-- index.txt.attr
|   |-- keys
|   |   |-- dGVzdDI6IDogOnRlc3Q6IDp1azpVSw==.pem
|   |   `-- dGVzdDM6IDogOnRlc3Q6IDp1azpVSw==.pem
|   |-- newcerts
|   |   |-- 01.pem
|   |   `-- 02.pem
|   |-- openssl.cnf
|   |-- req
|   |   |-- dGVzdDI6IDogOnRlc3Q6IDp1azpVSw==.pem
|   |   `-- dGVzdDM6IDogOnRlc3Q6IDp1azpVSw==.pem
|   |-- serial

You need to preserve the integrity of these files because therein lie the certificate authority, server and client certificates and keys.

3.0 The Certificate Authority & CA certificate For This VPN Server

Create a dedicated CA for each organisation. Client access is based on the CA so don't use the same CA for different organisations else clients from each organisation can connect to the other organisations with that same CA.

3.1 Build the Certificate Authority

The CA / CA certificate is used for certificate signing.

Run TinyCA. In Debian 5.0 Lenny use: Applications → Other → TinyCA; In Ubuntu 8.10 and 9.04 there's no menu item so from the command-line use: $ tinyca2

If this is your first time running the program you'll automatically be prompted to setup a new Certificate Authority; if it's not you'll be prompted to open an existing CA, Cancel that dialog and choose 'New CA'.

(Note that TinyCA only deals with one CA at a time. If you create a new one any previous one and its associated certificates and keys will disappear from view. You can return to others using 'Open CA'.)

Name (for local storage): <organisation>-CA (no spaces allowed as this is used for a filename)
Common Name (for the CA): use system hostname of the machine you're creating this on? [I'm not sure about this naming scheme]
Country Name (2 letter code): UK
Password (needed for signing): you use this to sign server and client keys when you create them
Password (confirmation):
Organization Name (eg. company): <organisation>
eMail Address: <your organisation email address>
Keylength: 1024
valid for (days): 3650 (ten years)

Use the defaults for everything else unless you know what you're doing.

Choose → OKCA ConfigurationOK

You can henceforth use this for creating certificates/keys for all this organisation's VPN servers, but not another organisation's.

3.2 Export the CA certificate to enter into the VPN server and into Network Manager for each client

Choose CA tab → Export CAchoose where to save itSave.

This saves a .PEM format certificate as <'Name (for local storage)' from above>-cacert.pem.

pfSense says it wants it in X.509 format. TinyCA offers "PEM", "DER" and "TXT" which are all different formats of X.509 certificate. It is the .PEM format that pfSense actually wants.

4.0 The Server Certificate and Key for the VPN Server

4.1 Create the server certificate and private key for the specific VPN server

Choose Certificates tab → NewCreate Key and Certificate (Server).

Common Name (eg. your Name, your eMail Address or the Server's Name): firewall (if this differs from the machine hostname it's OK)
eMail Address: <your organisation email address> - so you don't export files later on with the same names for server certs and keys as for client certs and keys, don't use an email address here that you'll also use for a client certificate and key
Password (protect your private Key): ...
Password (confirmation): ...
Country Name (2 letter code): UK (should be the default)
Organization Name (eg. company): <organisation> (should be the default)
Keylength: 1024

Use the defaults for everything else unless you know what you're doing.

Choose OKSign Request

CA Password: ...
Valid for (Days): 730 (or 1825 days, 5 years maybe) (should be the same or less than the CA)
Add eMail Address to Subject DN: yes? the default

4.2 Export the server certificate for the VPN Server

Choose Certificates tab → choose particular server certificateExport.

Export Format: PEM (Certificate) (the default)
Include Key (PEM): No (the default)
Include fingerprint (PEM): No (the default)

Saves as <'eMail Address' from above>-cert.pem.

4.3 Export the server key / server private key for the VPN Server

Choose Keys tab → choose particular server keyExport.

Export Format: PEM (Key) (the default)
Without Passphrase (PEM/PKCS#12): Yes (is this because it lives on the server, without the ability to prompt for the password?) [if you choose 'yes' it doesn't require a passphrase to open / decrpyt(?) it, if you choose 'no' it does require a passphrase to open / decrpyt(?) it]
Include Certificate (PEM): No (we get it on its own above) (the default)

[Note: I'm not sure how but it is possible to get this error message from misconfiguring something here: "openvpn[281]: Cannot load private key file /var/etc/openvpn_server0.key: error:0906A068:PEM routines:PEM_do_header:bad password read: error:140B0009:SSL routines:SSL_CTX_use_PrivateKey_file:PEM lib]"

You'll be asked for the server private key password / passphrase in order to decrypt the key.

It saves as something like <'eMail Address' from above>-key.pem.

4.4 Diffie-Hellman parameters

"Key establishment parameters - The specification of a cyclic group p and a generator g for that group. These parameters may be public. Menezes, et al. (1997) note that for additional security each party may supply its own parameters." - http://en.wikipedia.org/wiki/Station-to-Station_protocol

See also http://www.rsa.com/rsalabs/node.asp?id=2248.

To make a file with 1024 PKCS#3 format Diffie-Hellman parameters (change accordingly for other key lengths):
$ openssl dhparam -2 -out diffie-hellman-parameters.pem 1024

You only need to do this once and you can use it across all certificates/keys [I presume?].

5.0 Client Certificates and Keys

Note that anyone with a client certificate signed by the same CA has access through the VPN.

5.1 Create a client certificate and key for each user

Debian Lenny: Applications → Other → TinyCA

Ubuntu 8.10: ? $ tinyca2

Choose Certificates tab → NewCreate Key and Certificate (Client).

Common Name (eg. your Name, your eMail Address or the Servers Name): e.g. person's-name or persons-name-<organisation>)
eMail Address: <person's email address>
Password (protect your private Key): ...
Password (confirmation): ...
Country Name (2 letter code): UK (should be the default)
Organization Name (eg. company): the organisation of the person (it defaults to the organisation of the CA)
Keylength: 1024

Use the defaults for everything else unless you know what you're doing.

Choose OK → Sign Request →

CA Password: ...
Valid for (Days): 730 (2 years)
Add eMail address to Subject DN: Yes? (the default)

Choose OK

5.2 Export the Client Certificate and Key and CA Certificate

You'll want a client cert .PEM file and a client key .PEM file for use from NetworkManager. Or you'll want a 'PKCS#12 (Certificate & Key)' .p12 file (CA cert, client cert, client key) for use from the command-line. Alternatively you could use .PEM format from both the command-line and NetworkManager.

5.2.1 (option) Export the client certificate and key and CA certificate in .PEM format - if you want to use from NetworkManager or command-line

You want these in .PEM format for NetworkManager on the client computer.

5.2.1.1 Export the client certificate in .PEM format

Certificates tab → choose particular client certificateExport

Export Format: PEM (Certificate) (the default)
Include Key (PEM): No (the default)
Include fingerprint (PEM): No (the default)

Choose Save.

It saves as something like <'eMail Address' from above>-cert.pem.

5.2.1.2 Export the client key in .PEM format

Keys tab → choose particular client keyExport

Export Format: PEM (Key) (the default)
Without Passphrase (PEM/PKCS#12): No (the default)
Include Certificate (PEM): No (the default) (we get it on its own above)

It saves as something like <'eMail Address' from above>-key.pem.

5.2.1.3 Export the CA certificate in .PEM format

This is the same as was done in section 3.2.

CA tab → Export CA

File: <'Name (for local storage)' from above>-cacert.pem
Export Format: PEM (the default)

5.2.2 (option) Export the client certificate and key and CA certificate in .P12 format - if you want to use from the command-line

Choose Certificates tab → choose particular client certificateExport

Export Format: PKCS#12 (Certificate & Key)
Include Key (PEM): Yes
Include Fingerprint: No (the default)

Choose Save.

Export to PKCS#12

Key Password: this is the particular client key password you gave it earlier to encrypt it, because you're now exporting the key from within TinyCA; this password is used to decrypt the key again now; the server isn't concerned with this; if you get this password wrong you'd be told just at the time of export from TinyCA. Export Password: the 'PKCS12 File Password' that guards the key itself; you are prompted for this when you try to use it; the server isn't concerned with this, it's just a matter between entering it now and entering it when you use the file; if you got this password wrong you'd be told at the time of using it with OpenVPN or NetworkManager.

Friendly Name: person's full name
Without Passphrase: No (the default)
Add CA Certificate to PKCS#12 structure: Yes (the default)

Choose → OK

It saves as something like <'eMail Address' from above>-cert.p12.

Give it the correct permissions.

6.0 Usage From A Client Computer

If the network addressing on your subnet matches that of the remote subnet then you will be unable to reach those local machines whose IP address matches that of a remote machine.

6.1 Using Linux

6.1.1 Using NetworkManager

6.1.1.1 NetworkManager 0.6 Series

NetworkManager 0.6 series is part of Ubuntu 8.04, Debian 4.0 Etch and Debian 5.0 Lenny.

In Debian, Ubuntu, Fedora or Suse, install the package 'network-manager-openvpn'.

Left-click on the NetworkManager applet → VPN ConnectionsConfigure VPN...Add → select OpenVPN (if it isn't already) → Create...

Gateway Address: the IP address of the target
Connection Type: X.509 Certificates
CA File: the CA certificate in .PEM format - <'Name (for local storage)' from above>-cacert.pem
Certificate: the client certificate in .PEM format - <'eMail Address' from above>-cert.pem
Key: the client key in .PEM format - <'eMail Address' from above>-key.pem

Choose Advanced[X] Use LZO compression.

When you use it you'll be asked for the 'Certificate password' which is the 'Password (protect your private Key)' from '3.1 Create the client certificate and key' which at least with Ubuntu you can choose to save in the keyring.

6.1.1.2 NetworkManager 0.7 Series

NetworkManager 0.7 series is part of Ubuntu 8.10 and 9.04.

In Debian, Ubuntu, Fedora or Suse, install the package 'network-manager-openvpn'.

Left-click on the NetworkManager applet → VPN ConnectionsConfigure VPN...Add → select OpenVPN (if it isn't already) → Create...

Gateway: the IP address of the target
Connection Type: Certificates (TLS)
User Certificate: the client certificate in .PEM format - <'eMail Address' from above>-cert.pem
CA Certificate: the CA certificate in .PEM format - <'Name (for local storage)' from above>-cacert.pem
Private Key: the client key in .PEM format - <'eMail Address' from above>-key.pem
Password: - the 'Password (protect your private Key)' from '3.1 Create the client certificate and key' which which at least with Ubuntu you can choose to save in the keyring

Advanced[X] Use LZO compression

So that Internet access continues to work when you have IP addresses clashing between the remote network and the local network: IPv4 Settings → Routes... → Use this connection only for resources on its network

6.1.1.3 NetworkManager 0.8 Series

NetworkManager 0.8 (pre-release, i.e. 0.7.996) series is part of Ubuntu 9.10.

In Debian, Ubuntu, Fedora or Suse, install the package 'network-manager-openvpn'.

Left-click on the NetworkManager applet → VPN ConnectionsConfigure VPN...Add → select OpenVPN (if it isn't already) → Create...

Gateway: the IP address of the target
Connection Type: Certificates (TLS)
User Certificate: the client certificate in .PEM format - <'eMail Address' from above>-cert.pem
CA Certificate: the CA certificate in .PEM format - <'Name (for local storage)' from above>-cacert.pem
Private Key: the client key in .PEM format - <'eMail Address' from above>-key.pem
Password: - the 'Password (protect your private Key)' from '3.1 Create the client certificate and key' which which at least with Ubuntu will be saved in the keyring, which you'll be prompted to allow access to the first time you use it

Advanced[X] Use LZO data compression

So that Internet access continues to work when you have IP addresses clashing between the remote network and the local network: IPv4 Settings → Routes... → Use this connection only for resources on its network

6.1.2 Using the Command-Line

In Debian or Ubuntu install the package 'openvpn'.

This assumes you have the CA certificate, client certificate and key in a .p12 package. I haven't tried command-line access using PEM format certificates and keys.

Setup the tunnel:
# openvpn --dev tun0 --mktun

Connect:
# openvpn --remote <IP address or hostname of VPN server> --dev tun0 --pkcs12 <filename of certificate>.p12 --client --comp-lzo --tun-mtu 1400

Available options:
--tls-client
--ca file
--dh file [do we need to specify this?]
--cert file
--key file
--pkcs12 file - specify a PKCS#12 file containing local private key, local certificate, and root CA certificate. This option can be used instead of --ca, --cert, and --key.

(Expected Remote Options String: 'V4,dev-type tun,link-mtu 1542,tun-mtu 1500,proto UDPv4,comp-lzo,cipher BF-CBC,auth SHA1,keysize 128,key-method 2,tls-server')

(keysize 128 - is this the 'Cryptography: BF-CBC (128-bit)'?)

(key-method 2)

6.2 Using Windows

To Do. This will be based on my experience of using an IPCop-based OpenVPN, as documented in the Windows client section of my guide to Remote Access - IPCop, ZERINA, OpenVPN, VNC and SSH.