Search:  
Gentoo Wiki

HOWTO_Road_Warriors_with_OpenVPN


This article is part of the HOWTO series.
Installation Kernel & Hardware Networks Portage Software System X Server Gaming Non-x86 Emulators Misc

Contents

Introduction

Most of the guides on OpenVPN concentrate on describing a routed scenario which is certainly more efficient, but may or may not require less setup to get active because you will need to setup additional new routes for all machines in the private network to talk to the subnet where the VPN clients get forwarded to.

Also the gentoo network scripts have recently been updated with latest baselayout and now it's easier to setup some network settings, but mainly you need to be careful reading older guides.

The guide below sketches out how to setup a bridged openvpn system where essentially the external machine will be given a local IP address such that it appears as just another machine on the normal local private lan network (ie no routing changes required). This may be easier for small home/soho networks, but surely doesn't scale as well for bigger installations

This HOWTO will explain the process of adding road warriors to your network with OpenVPN and the Linux network bridging features. We will be using OpenVPN 2.0.6 in this HOWTO.

The following links are useful in understanding this setup:

Selecting the required kernel options

OpenVPN requires the TUN/TAP network drivers. We will need to enable this option either as a module or built-in the kernel. Also, network bridging requires another options to be enabled. You will have to enable these options on the server and every client (unless they're running Windows :(, in which case you won't have to recompile anything in the kernel. :P).

This brief guide assumes you're using an older 2.6-based kernel. In kernel 2.6.14 for example, the networking options is under the root level Networking-> menu. If you can't find an option, make sure you look in both places! If you're still using a 2.4 kernel, it isn't really hard to find either if I remember correctly. Please note that only the 'X' is the option you're looking for. :)

# cd /usr/src/linux
# make menuconfig
Linux Kernel Configuration: In Device Drivers -> Network Device Support
[*] Network device support
Networking options  --->
[ ] Amateur Radio support  --->
< > IrDA (infrared) subsystem support  --->
< > Bluetooth subsystem support  --->
[*] Network device support
<M>   Dummy net driver support
< >   Bonding driver support
< >   EQL (serial line load balancing) support
<X>   Universal TUN/TAP device driver support
Linux Kernel Configuration: In Networking -> Networking Options
< > IP: ESP transformation
< > IP: IPComp transformation
< > IP: tunnel transformation
< > IP: TCP socket monitoring interface
    IP: Virtual Server Configuration  --->
< > The IPv6 protocol (EXPERIMENTAL)
[*] Network packet filtering (replaces ipchains)  --->
    SCTP Configuration (EXPERIMENTAL)  --->
< > Asynchronous Transfer Mode (ATM) (EXPERIMENTAL)
<X> 802.1d Ethernet Bridging

Exit menuconfig, saving the new configurations. You now need to rebuild your kernel.

2.6-based kernels

# cd /usr/src/linux
# make && make modules_install

2.4-based kernels

# cd /usr/src/linux
# make dep && make bzImage modules modules_install

If you compiled any of the two options built-into the kernel, copy the new kernel to /boot and see you later! (reboot)

Downloading and installing OpenVPN

Simple:

# echo "net-misc/openvpn iproute2" >> /etc/portage/package.use
# emerge openvpn

After that you should have the openvpn 2.0 stuff installed on your system.

Creating the SSL keys and certificates

OpenVPN can use either SSL certificates or a pre-shared secret key to authenticate it's clients. While the SSL-based security is much more effective, the pre-shared secret keys one is twice as simple. I don't recommend it to anyone setting up a serious VPN as it's much less secure. If someone steals the secret key, he/she will be able to read all traffic passing throught the VPN (Read: MITM). In addition to all live traffic, if an attacker has captured packets that have previously traversed the network, he or she will be able to decrypt those, as well. Static keys are recommended only to be used for non-permanent tests.

Using SSL keys/certificates

This is not actually so difficult, it's just a bunch of commands to type. Please also refer to the official HOWTO docs (the steps below are based on these docs) at: http://openvpn.net/howto.html#pki

First, some explanations. To determine if a client is allowed to connect to the server or not, OpenVPN checks if it has been signed with the CA certificate that signed the server certificate. So you may understand that using commercial certificates like Thawte's really isn't an option in our case! I suggest we start right away and get this all out of the way quickly. :)

First off, change to the dir with the Openvpn scripts to setup the keys easily

$ cd /usr/share/openvpn/easy-rsa/

We then must edit the basic parameters for the certificates. Edit the vars file (called vars.bat on Windows) and set the KEY_COUNTRY, KEY_PROVINCE, KEY_CITY, KEY_ORG, and KEY_EMAIL parameters. Don't leave any of these parameters blank.

Next, initialize the PKI. On Linux/BSD/Unix:

   . ./vars
   ./clean-all
   ./build-ca

The final command (build-ca) will build the certificate authority (CA) certificate and key by invoking the interactive openssl command:

   ai:easy-rsa # ./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) [KG]:
   State or Province Name (full name) [NA]:
   Locality Name (eg, city) [BISHKEK]:
   Organization Name (eg, company) [OpenVPN-TEST]:
   Organizational Unit Name (eg, section) []:
   Common Name (eg, your name or your server's hostname) []:OpenVPN-CA
   Email Address [me@myhost.mydomain]:

Note that in the above sequence, most queried parameters were defaulted to the values set in the vars or vars.bat files. The only parameter which must be explicitly entered is the Common Name. In the example above, I used "OpenVPN-CA". Generate certificate & key for server

Next, we will generate a certificate and private key for the server. On Linux/BSD/Unix:

   ./build-key-server server

As in the previous step, most parameters can be defaulted. When the Common Name is queried, enter "server". Two other queries require positive responses, "Sign the certificate? [y/n]" and "1 out of 1 certificate requests certified, commit? [y/n]".

Generating client certificates is very similar to the previous step. On Linux/BSD/Unix:

   ./build-key client1
   ./build-key client2
   ./build-key client3

If you would like to password-protect your client keys, substitute the build-key-pass script.

Remember that for each client, make sure to type the appropriate Common Name when prompted, i.e. "client1", "client2", or "client3". Always use a unique common name for each client. Generate Diffie Hellman parameters

Diffie Hellman parameters must be generated for the OpenVPN server. On Linux/BSD/Unix:

   ./build-dh

Output:

   ai:easy-rsa # ./build-dh
   Generating DH parameters, 1024 bit long safe prime, generator 2
   This is going to take a long time
   .................+...........................................
   ...................+.............+.................+.........
   ......................................

Key Files

Now we will find our newly-generated keys and certificates in the keys subdirectory. The .key files are the only ones that shouldn't be left unprotected as it's the only part that's private. You should now transfer the client's keys / certificates, along with the CA CERTIFICATE (Read: NOT the key) to their respective machines via a secure channel. The dh1024.pem file only has to be on the server.

Using both methods

Yes. You can use the secret key file and the certificate encryption at the same time. This is even more secure and protects your network against MITM attacks. So if you used the certificate method, you can also do the alternative step down here to keep your network even more secure!

Alternative: Using pre-shared private keys

This is a very quick operation. You will have to make sure this key isn't left out in the open for everyone to see as it's your only protection against MITM attacks. (See: http://openvpn.net/howto.html#security )

# /usr/sbin/openvpn --genkey --secret ta.key

Transfer this file over a secure channel to all clients.

Creating the network bridge

You only have to complete this step on the machine that is going to host the OpenVPN server. We will create the network bridge that will link the OpenVPN virtual network interfaces with our real, big, bad NIC!

Start by emerging bridge-utils and usermode-utilites (for TAP support.)

# emerge bridge-utils usermode-utilities

Baselayout supports bridging, TUN/TAP out of the box. In /etc/conf.d/net (this is a real world example with 2 NICs, amend to taste, see /etc/conf.d/net.example as well. If you only have one NIC then remove references to eth1 and rename routes_eth1 to routes_br0):

######################################
# /etc/conf.d/net
######################################
# LAN - eth0 - e1000, onboard NIC
#       bridged with tap0 for OpenVPN
# WAN - eth1 - e100, PCI slotted NIC
# Note:I recieved an error that no such module (openvpn) exists, so i added iproute2 to my use flags, 
#      re-emerge openvpn and emerged iproute2. I changed modules below from openvpn to iproute2. 
#      I also added the line tuntap_tap0="tap" to /etc/conf.d/net.
modules=(
        "openvpn"
) 
config_eth0=( "null" )
# config_tap0=( "0.0.0.0" )
bridge_br0=( "eth0 tap0" )
config_br0=(
        "192.168.0.254/24"
)
config_eth1=(
        "xxxxxxxxxxxx/xx"
)
routes_eth1=(
        "default via xxxxxxxxxxxx"
)
#the xxxxxx here should be set to your gateway IP

# Below is an example of configuring the bridge
# Consult "man brctl" for more details
brctl_br0=( "stp on" )

depend_br0() {
        need net.eth0 openvpn
}

Edit: Be very careful with the brctl_br0=( "stp on" ) option. This enables the spanning tree protocol. Some people are telling their switches to error out this protocol. If this happens to often, the port might be disabled. In my case it was the gateway which killed my whole infrastructure until the port was set back to be open. -markus

Then make symlinks for new devices

# cd /etc/init.d
# ln -s net.lo net.br0
# ln -s net.lo net.tap0
# ln -s net.eth1 (only if needed)

Stop existing and start the new ones

# /etc/init.d/net.eth0 stop
# /etc/init.d/net.br0 start

Add Bridge to default runlevel

# rc-update -a net.br0 default

... and carry on to configuring OpenVPN

Configuring our VPN!

We will start by creating the /etc files we require to get this up and running! This step is to be done on the server and every client.

# mkdir -p /etc/openvpn/cool_network
# touch /etc/openvpn/cool_network.conf
# cd /etc/init.d
# ln -s openvpn openvpn.cool_network


Copy the encryption keys to the /etc/openvpn/cool_network/ directory. On a SSL Certificate configuration, this would be the CA certificate, the machine's certificate and key, and the dh1024.pem file only on the server. On a static key configuration, you just have to copy the ta.key file.

Afterwards, we have to tell OpenVPN what to do! So...

nano -w /etc/openvpn/cool_network.conf

In the following section, we will look into the possible options to add to the cool_network.conf file.

OpenVPN Server

This is the interface we will be binding the OpenVPN server on. Don't ask questions. :)

dev tap0

The proto option can safely be removed, if you do this, the server will assume you are using the default protocol, UDP. I myself use TCP over UDP for my OpenVPN servers, even thought it's not as effective. The port option is, well, the port the OpenVPN server will be listening on! Change this to anything that can suit your needs. You may also specify a 'local <IP>' option to tell the OpenVPN server to bind itself to this specific IP address only. More secure, they say.

proto tcp-server
port 1194

The server directive indicates that we're going to be... a server! The first parameter is the subnet of the network we're adding the warriors on, the second parameter is the subnet mask, the third and the forth the ip range for the clients. The ifconfig-pool-persist is an optional, SSL-certificates-configuration-only directive that tells the server to check if the common name of the client's certificate is in the IP Pool. The IP Pool is just a simple file with CN/IP bindings. If you use that, the clients will always be assigned the same IP Address on the network. I recommend this.

mode server
server-bridge 10.1.0.0 255.255.255.0 10.1.0.100 10.1.0.130
ifconfig-pool-persist /etc/openvpn/cool_network/ip_pool

Do I really have to explain the mode? :) status is a file where information about OpenVPN is displayed. tls-auth is an optional directive. Use this only if you're on a SSL-certificate configuration. Basically, it's another key, that is in fact a static key just like the static-key encryption configuration. It is used to enhance security. I myself use it. Please notice the second argument. 0=server 1=client. keepalive is used to check if the connection still is alive! The first argument is the ping interval, the second one is the timeout. If a client doesn't answers in the timeout, we drop the connection. client-to-client... Don't ask. :) and verb 3 is good for normal operation.

status /tmp/vpn-cool_network.status
tls-auth /etc/openvpn/cool_network/ta.key 0
keepalive 10 30
client-to-client
max-clients 150
verb 3

The following section can be completly dumped and replaced with "secret <PATH_TO_secret.key>

tls-server
dh /etc/openvpn/cool_network/dh1024.pem
ca /etc/openvpn/cool_network/ca.crt
cert /etc/openvpn/cool_network/server.crt
key /etc/openvpn/cool_network/server.key
comp-lzo

These options drop the privileges to the selected UID/GID when everything is setup. Many recommendations.

user openvpn
group openvpn

Keep-alive stuff. Don't ask. :)

persist-key
persist-tun


You can now start the OpenVPN server! :)

OpenVPN Client

The remote directive is there to indicate where the client will attempt to establish it's connection. The proto can again be removed to use UDP over TCP. The port directive needs to match the server's, and so does dev.

remote example.com
proto tcp-client
port 1194
dev tap

The client directive indicates that we're a client. Setting resolv-retry to infinite can only help if you're using a laptop that sometimes has to go offline. mute-replay-warnings is an option I recommend so your log files don't get swarmed. verb 3 is good for debugging purposes. persist-tun and persist-key are random Keep-Alive stuff and tls-auth is an optionnal option to increase security even more as explained in the Server section. Remember that the second argument of tls-auth has to be 0 is the machine is a server and 1 if it's a client.

client
resolv-retry infinite
mute-replay-warnings
verb 3
persist-tun
persist-key
tls-auth ta.key 1

These options indicate that we should drop our privileges to the selected UID/GID when we're done with setting everything up.

user openvpn
group openvpn

The ifconfig directive. The first argument is the requested IP on the subnet while the second one is the subnet mask of the network we're connecting to. Don't ask me what ifconfig-nowarn is used for. :)

ifconfig 10.1.0.2 255.255.255.0
ifconfig-nowarn

The tls-client directive indicates that we are a tls... client. The ca, cert and key directives are the paths to the certificate stuff somewhere on your box. comp-lzo is the compression option. If the server has it, you must have it.

tls-client
ca /etc/openvpn/cool_network/ca.crt
cert /etc/openvpn/cool_network/client.crt
key /etc/openvpn/cool_network/client.key
comp-lzo


For my windows machine I use the GUI client to manage the connections and the following config file:

port 1194
dev tap
remote 81.6.236.5
tls-client
ca ca.crt
cert client.crt
key client.key
tls-auth ta.key 1
verb 3
comp-lzo
pull

You can now start the OpenVPN client! :)

Automating OpenVPN

Author of this section: Riskable (riskable@youknowwhat.com or Riskable.com). Feel free to contact me with any info/questions.

Many users will want to launch OpenVPN automatically upon establishing a network connection (as opposed to "rc-update --add openvpn default"). Also, many users will have different openvpn configurations for the various networks they connect to. Some examples:

All of these situations can be handled automatically thanks to Gentoo's excellent network configuration scripts. The key to making this work is to have an openvpn.conf file for each network you connect to (and/or having a generic default "openvpn.conf" for any given network). For instance, /etc/openvpn/openvpn.work.conf and /etc/openvpn/openvpn.home.conf with their respective init.d scripts (e.g. /etc/init.d/openvpn.work).

Once you've tested that your OpenVPN scripts/configurations work on their respective networks, it is time to configure Gentoo to start them automatically. This is done via the postup() and predown() functions in the /etc/conf.d/net configuration file.

File: /etc/conf.d/net
 
predown() {
        # Simple: Stop OpenVPN when the network is stopped
        OPENVPN_PID=`ls /var/run/openvpn*.pid | \
        sed -e 's/\.pid//g' | cut -d/ -f4`
        if [[ "$OPENVPN_PID" != "" ]] ; then
                /etc/init.d/$OPENVPN_PID stop
        fi
        return 0
}

postup() {
        # Check to make sure OpenVPN isn't already started
        if [ -f /var/run/openvpn*.pid ]; then
                echo "OpenVPN already started.  Not starting"
                return 0
        else
                # What network am I connected to?
                ESSID=`/sbin/iwgetid | awk -F\" '{print $2}'`

                if [[ "$ESSID" = "work_essid" ]] ; then
                        /etc/init.d/openvpn.work --quiet start
                elseif [[ "$ESSID" = "home_essid" ]] ; then
                        /etc/init.d/openvpn.home --quiet start
                # Uncomment below if you want a default
                # else
                #        /etc/init.d/openvpn --quiet start
                fi
                return 0
        fi
}

In this example, I've configured my network connection to automatically launch either openvpn.work or openvpn.home depending on the essid of the wireless connection but you could change the script conditions to whatever you want. If you're using a wired network, you could change $ESSID to check for local DNS servers or whether or not you can ping a certain server.

Note: postup() runs after your interface has been given an address. So this method works wonderfully with wpa_supplicant.

With these lines in your /etc/conf.d/net configuration file, OpenVPN will start according to your preferences whenever a network interface is brought up on your machine (obviously this excludes net.lo).

Enjoy!

Conclusion

Well, that's it! By now you should have an operational VPN and clients should be able to connect to it.

Troubleshooting

Please use the associated talk page for troubleshooting.

Retrieved from "http://www.gentoo-wiki.info/HOWTO_Road_Warriors_with_OpenVPN"

Last modified: Mon, 08 Sep 2008 18:07:00 +0000 Hits: 47,638