OpenVPN – creating a routed VPN

In this article, I will show you how I created a routed VPN using
OpenVPN.
In this network, multiple clients can attach to the server, each of which
has access to the network attached to the server. Each client can also
contact any other client, subject to firewall rules.
In my case, I wanted a way for all my servers (on the internet, in data
centers) to contact my CVS repository behind my firewall at home. Given that
home has a dynamic IP address, it complicates matters. A VPN solves this issue
and provides several benefits. I have outlined the problems
in my other diary and I urge you
to read that before proceeding. It will provide valuable background
as to why I have chosen this particular solution.

Acknowledgements

Two people have been of great help while I struggled with OpenVPN. ecrist
and krzee have both pointed me to examples and features. Others within
the FreeNode OpenVPN channel also listened to my goals and provided suggestions.
Thanks.
Here are a few good references:

Assumptions

Most of this article will concentrate on the configuration and setup. It will
not cover certificates or installation.

Server configuration

NOTE: since this was originally written, I have changed the configuration. The article
used to show both ifconfig-pool-persist and client-config-dir settings.
The latter can be used with ifconfig-push to guarantee static IP addresses. That is
what I need. I have since changed the configuration shown below to reflect what I am
using now.
This section shows you the setup of my OpenVPN server. The main configuration
file is /usr/local/etc/openvpn/openvpn.conf. This is mine:

Some of the options from above are outlined below. For full details,
please refer to the OpenVPN man page.
The ca, cert, key, and dh directives are straight from the basic setup
given in the previous article.
client-config-dir specifies the directory for custom client config files.
We use these files for assigning static IPs, but they have additional uses.
server indicates that our VPN server will use the 10.8.1.0/24 subnet.
client-to-client allows each VPN client to see all other VPN clients.
tls-auth is a shared secret, same file in each client, that is optional
but allows n additional layer of HMAC authentication on top of the TLS control
channel to protect against DoS attacks.
push ensures that each client can access the 10.55.0.0/24 network on
the VPN server. This push adds an entry to the client’s routing table.

As expected, I will outline some of these directives.
client designates this as a client configuration.
ns-cert-type server avoids a man-in-the-middle attack.
tls-auth is the same shared secret file as mentioned in the server
section. I will show you how to generate it later. Notice that the
direction is 1 on the client and 2 on the server. See the –secret option
on the OpenVPN man page for more information.
ca, cert, key, and dh have been previously
explained.

Generating the tls-auth

You can generate a tls-auth file with this command:

openvpn --genkey --secret /usr/local/etc/openvpn/keys/ta.key

Copy the file contents to each client.

Getting it running

Start both the server and the client. You should see this on the server:

Static IP addresses

I want static IP addresses for my clients. This will make things
easier when it comes to running jobs on them. These hosts already
have public IP addresses and hostnames. I will add private hostnames
for them. For example, if the host can be accessed publicly by
the name nyi.example.com, then I will add a new entry to my private
DNS server (accessible only from my LAN at home) for
nyi-vpn.example.com:

nyi-vpn IN A 10.8.1.20

After reloading the name server, I can resolve that hostname:

$ host nyi-vpn
nyi-vpn.example.com has address 10.8.1.20

To assign that IP address to that host, I create a file in the
client-config-dir, namely: /usr/local/etc/openvpn/ccd
That file must have the same name as the client’s X509 common name. In this
case: nyi-vpn.example.com
The file will contain:

ifconfig-push nyi-vpn.example.com 255.255.255.0

You can provide an IP address instead of a hostname. Restart your client
and you should see something similar to this in /var/log/messages on your
server:

Done

There, you should be running now. I think this VPN solution will be ideal to me.
Time will tell. Let’s see what happens when my first IP address change happens.
For now, I’m about to alter my Nagios monitoring to check my remote clients
over the VPN rather than the public networks. This little bit of work now
will save me a great deal of time when my IP address changes.
Enjoy OpenVPN.