Creating your own Certificate Authority

Creating your own Certificate Authority

In this article, I write about creating your own Certificate Authority
(CA) and generating certificates and keys for an OpenVPN server and
multiple clients. It is based around the the OpenVPN How To
and the README provided with that package.

There is an abundance of material for creating a CA. Why bother?
I bother because getting this right is easy. It’s easy if you
know the goals and how to accomplish them. However, getting there
is often trial and error. I don’t want to do the error bit the
next time I need to do this. The added bonus is neither do you.
You can use these steps.

For another view on creating certificates, see
FreeBSD OpenVPN Server HowTo.

The goals

Why use your own CA? Creating your own CA means that you have complete
control. You do not have to obtain certificates from third parties. You
can create them yourself, when you need them. I also have a fuzzy impression
that if your OpenVPN server uses a certificate from a third party CA, then
anyone else with a corticate from that CA can also connect.

The steps below are designed to give you:

  • a certificate for your OpenVPN server
  • that certificate will be designated as a server-only certificate
  • certificates for each OpenVPN client

In addition, and this part is important, the OpenVPN server certificate
will be designated as a server-only certificate by setting nsCertType=server.
This will avoid a possible Man-in-the-Middle attack where an authorized
client tries to connect to another client by impersonating the
server.

NOTE: we will building and signing a certificate signing request using
a locally installed root certificate/key. This requires that the generated
certificate and private key files be copied to the destination host over a
secure channel.

The previous paragraph blatantly borrowed from the README.

If you cannot securely copy these files, do not use these steps. Instead,
use the steps under “BUILD A CERTIFICATE SIGNING REQUEST” in the README
followed by “SIGN A CERTIFICATE SIGNING REQUEST”.

The tools

The FreeBSD Port for OpenVPN
installs “a small RSA key management package based on the openssl command line tool”.
This package is provided by the OpenVPN project and can be found at
/usr/local/share/doc/openvpn/easy-rsa/.

I recommend copying this to another location as you will be altering some
files.

cp -rp /usr/local/share/doc/openvpn/easy-rsa ~/
cd ~/easy-rsa

This article is based upon the README located in that directory. And upon a
few hours of not understanding the subtle steps involved.

The setup

The README says to edit vars and set KEY_SIZE and KEY_DIR. I left
them unchanged. This puts the keys into the keys sub-directory.

I also set these values, as found at the end of the file:

export KEY_COUNTRY=US
export KEY_PROVINCE=PA
export KEY_CITY=Warrington
export KEY_ORG="The FreeBSD Diary"
export KEY_EMAIL="dan@example.org"

You need to invoke the vars file before carrying out any of the remaining
steps. You only need to invoke vars once per session. You will know
that you have not invoked vars this session if you see this message:

you must define KEY_DIR

To invoke the vars, issue this command (the leading . is significant):

. vars

If you see this error:

$ . ./vars
-bash: /home/dan/easy-rsa/2.0/whichopensslcnf: Permission denied
NOTE: If you run ./clean-all, I will be doing a rm -rf on /home/dan/easy-rsa/2.0/keys

The problem is permissions to execute:

$ ls -l /home/dan/easy-rsa/2.0/whichopensslcnf
-r--r--r--  1 dan  dan  190 Jan 16 17:03 /home/dan/easy-rsa/2.0/whichopensslcnf
$ chmod +x /home/dan/easy-rsa/2.0/whichopensslcnf
$ . ./vars
NOTE: If you run ./clean-all, I will be doing a rm -rf on /home/dan/easy-rsa/2.0/keys
$

I did a chmod +x and all ran fine.

When first starting out with your CA, you need to run this command. Note that
it will remove the keys subdirectory along with any keys that you have
created. Use with caution. This command sets up some variables used by
later processed.

./clean-all

Create your CA

To create your CA, issue this command (the bits I typed are in bold):

$ ./build-ca
Generating a 1024 bit RSA private key
..........................++++++
......................................................................++++++
writing new private key to 'ca.key'
-----
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) [US]:
State or Province Name (full name) [PA]:
Locality Name (eg, city) [Warrington]:
Organization Name (eg, company) [The FreeBSD Diary]:
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []:
Email Address [dan@example.org]:

After the above, ca.crt and ca.key have been built in your KEY_DIR directory:

$ ls -l keys
total 6
-rw-r--r--  1 dan  dan  1151 Nov 27 19:01 ca.crt
-rw-------  1 dan  dan   887 Nov 27 19:01 ca.key
-rw-r--r--  1 dan  dan   113 Nov 27 19:00 index.txt
-rw-r--r--  1 dan  dan     3 Nov 27 19:00 serial

Create the OpenVPN server certificate

In this step, we will create the certificate for your OpenVPN server.
The build-key-server command will ensure the certificate is
designated as a server-only certificate by setting nsCertType=server.
This solution for that type of attack
relies upon you using this line in your client openvpn.conf configuration
files:

ns-cert-type server

This certificate will be used on your OpenVPN server, which in my example,
is named myserver.example.com.
To create a nsCertType=server certificate for your OpenVPN server, issue
the following command:

$ ./build-key-server myserver.example.com
Generating a 1024 bit RSA private key
........++++++
........................................++++++
writing new private key to 'myserver.example.com.key'
-----
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) [US]:
State or Province Name (full name) [PA]:
Locality Name (eg, city) [Warrington]:
Organization Name (eg, company) [The FreeBSD Diary]:
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []:myserver.example.com
Email Address [dan@example.org]:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
Using configuration from /home/dan/easy-rsa/openssl.cnf
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
countryName           :PRINTABLE:'US'
stateOrProvinceName   :PRINTABLE:'PA'
localityName          :PRINTABLE:'Warrington'
organizationName      :PRINTABLE:'The FreeBSD Diary'
commonName            :PRINTABLE:'myserver.example.com'
emailAddress          :IA5STRING:'dan@example.org'
Certificate is to be certified until Nov 25 19:19:09 2018 GMT (3650 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

You should now see files like this:

$ ls -l keys
total 24
-rw-r--r--  1 dan  dan  3592 Nov 27 19:19 01.pem
-rw-r--r--  1 dan  dan  1151 Nov 27 19:01 ca.crt
-rw-------  1 dan  dan   887 Nov 27 19:01 ca.key
-rw-r--r--  1 dan  dan   113 Nov 27 19:19 index.txt
-rw-r--r--  1 dan  dan    21 Nov 27 19:19 index.txt.attr
-rw-r--r--  1 dan  dan     0 Nov 27 19:00 index.txt.old
-rw-r--r--  1 dan  dan  3592 Nov 27 19:19 myserver.example.com.crt
-rw-r--r--  1 dan  dan   700 Nov 27 19:19 myserver.example.com.csr
-rw-------  1 dan  dan   887 Nov 27 19:19 myserver.example.com.key
-rw-r--r--  1 dan  dan     3 Nov 27 19:19 serial
-rw-r--r--  1 dan  dan     3 Nov 27 19:00 serial.old

Create the DIFFIE-HELLMAN parmaters for your server

This step creates the DIFFIE-HELLMAN parameters that will be required by
your OpenVPN server.

$ ./build-dh
Generating DH parameters, 1024 bit long safe prime, generator 2
This is going to take a long time
......................+........................................
...+...............................................+...........
..........................+....................................
...........+..................^[[B......+......................
.............................................+.................
............................................+..................
...........+...+...............................................
..............................................+................
..................................................+............
.........+...............................+...+.+...............
..................+..................................+.........
.+.....+.....................+.................................
.................................................+............+
............................................+..................
...............................................................
...................+..++*++*++*

This will create a file (keys/dh1024.pem) which will be used on
your OpenVPN server.

Create a client certificate

This step will create a certificate that can be used by your OpenVPN client.
In this case, we are creating a certificate to be used by the host
client.example.com.

./build-key client.example.com
Generating a 1024 bit RSA private key
.++++++
...++++++
writing new private key to 'client.example.com.key'
-----
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) [US]:
State or Province Name (full name) [PA]:
Locality Name (eg, city) [Warrington]:
Organization Name (eg, company) [The FreeBSD Diary]:
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []:client.example.com
Email Address [dan@example.org]:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
Using configuration from /home/dan/easy-rsa/openssl.cnf
DEBUG[load_index]: unique_subject = "yes"
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
countryName           :PRINTABLE:'US'
stateOrProvinceName   :PRINTABLE:'PA'
localityName          :PRINTABLE:'Warrington'
organizationName      :PRINTABLE:'The FreeBSD Diary'
commonName            :PRINTABLE:'client.example.com'
emailAddress          :IA5STRING:'dan@example.org'
Certificate is to be certified until Nov 25 19:49:36 2018 GMT (3650 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

Repeat

I suggest you get things running with one client first, then create
certificates for other client.

Enjoy.

1 thought on “Creating your own Certificate Authority”

  1. Thanks for this summary!
    One thing I have to remind myself evey time I go to create further client certificates on my FreeBSD server is to start a bash shell before running those commnads as my default shell is out of the box csh (I think) – it may be that others hit this (simple) block…
    Simply start the shell (if installed from ports) by typing ‘bash’ before proceeding.

    [%sig%]

Leave a Comment

Scroll to Top