Openvpn, client-server

From Ubuntuwiki.net

Jump to: navigation, search

Contents

Installing software

Install OpenVPN from the repositories.

you@box:~$ sudo apt-get update
you@box:~$ sudo apt-get install openvpn easy-rsa


Generating keys

Copy the example files into the openvpn config directory.

you@box:~$ sudo cp -a /usr/share/easy-rsa/* /etc/openvpn/
you@box:~$ cd /etc/openvpn
you@box:~$ sudo mkdir keys
you@box:~$ sudo touch keys/index.txt
you@box:~$ sudo echo 01 > keys/serial
you@box:~$ sudo nano vars

Insert the appropriate settings at the end of this file for your locality and organization name. Afterwards:

you@box:~$ sudo ./clean-all
you@box:~$ sudo source ./vars
you@box:~$ sudo ./build-ca

The build-ca will ask some questions. This part is for the "Certificate Authority" you are creating - so make sure you enter things accurately. It's mostly for documentation purposes, though - a wrong answer here is unlikely to break anything.

you@box:~$ sudo ./build-key-server server.domain.tld

This generates an encryption key for your server. This does not have to be the FQDN, but it may help to use that as a standard. When asked for the common name in the key that you're generating, you will want to use the same thing there. You may not want to put a password on this file so you can have it automatically start at boot. Make sure you tell it to sign the certificate when it asks.

Now, for EACH client you expect to connect to the VPN, you want to generate a separate certificate. (By default, the server will only accept one connection per certificate, incidentally - you can change that if you like, but this way is better so that if you lose trust for one particular user or their cert, you can revoke it without affecting other users.)

you@box:~$ sudo ./build-key client-name

This generates the keys that you'll need both on the server and on the client to make the connection work. Replace "client-name" with something you'll use to remember who this key belongs to. Perhaps a user's name or a laptop workstation name would be good here. NOTE: if you close the console and come back later to generate more keys, you'll need to run "source ./vars" before running build-key again.

Now you'll need to build the "DH" key. This will likely take several minutes even on a fast machine:

you@box:~$ sudo ./build-dh

Once completed, copy the "client-name.key" "client-name.crt" and "ca.crt" files securely to the workstation that will be using them. I don't recommend emailing them - a USB drive is a great way to transfer them, or an SSH connection.


Configuring server.conf

First, expand the example server.conf file into /etc/openvpn.

you@box:~$ zcat /usr/share/doc/openvpn/examples/sample-config-files/server.conf.gz > /etc/openvpn/server.conf

Now edit the server.conf file with your favorite editor.

Set "local" to the server's public facing internet address (what the clients will use as the remote address), and "port" and "proto" to what you want the server to listen on. You can change "proto" to tcp if you prefer - UDP will be much more efficient, but some ISPs mercilessly throttle and/or block UDP traffic, so you may be forced to try tcp. YMMV.

local 1.2.3.4
port 1194
proto udp
dev tun

Make sure the "dev-node" line is commented out (it should already be) - it's for Windows systems only.

;dev-node MyTap

Now we need to tell it where the server's keys and the ca (Certificate Authority) crt are located:

ca /etc/openvpn/keys/ca.crt
cert /etc/openvpn/keys/server.domain.tld.crt
key /etc/openvpn/keys/server.domain.tld.key  # This file should be kept secret
dh /etc/openvpn/keys/dh2048.pem

Pick a subnet that the VPN server will assign clients to. This should be a different subnet from anything else you use:

server 10.8.0.0 255.255.255.0

If you want your clients to be able to access your LAN network, you'll need to push a route out to them:

push "route 192.168.1.0 255.255.255.0"

Make sure this matches your LAN route. However, if your LAN has a subnet that is the same as where a client might connect - like the above one based on the overly common "192.168.1.x" - you can choose to only route certain servers or subgroups of it. In this example, 192.168.1.5 and 192.168.1.127-255 will be available to the clients, but the remainder will not. This keeps the common Internet router address of 192.168.1.1 from conflicting:

push "route 192.168.1.5 255.255.255.255"
push "route 192.168.1.128 255.255.255.128"

To add to security just a bit, ASSUMING we don't need to route to client subnets, we want to make sure that the server drops to a non privileged user after it starts:

# note: you MUST NOT drop to nobody.nogroup if your server will be
#       routing to client subnets!
user nobody
group nogroup

The defaults in the rest of server.conf should be fine as they are.

Start up your new VPN server manually at least once using:

openvpn /etc/openvpn/server.conf

With this you can watch the messages and see if something goes wrong. (If you get errors regarding the server certs or keys, you might have forgotten to create the index.txt file, or put the 01 in the serials file... you'll have to go back and re-generate all the certs after fixing that.)

Routing through OpenVPN to a remote LAN

If you want to use OpenVPN to communicate to other machines on the server's LAN, as well as the server itself, you'll need to enable packet forwarding.

This is controlled by the sysctl variable net.ipv4.ip_forward, which can be set manually using sysctl or - better - permanently by using /etc/sysctl.conf. Edit /etc/sysctl.conf, and at the end insert the line net.ipv4.ip_forward=1, then issue sudo sysctl -p to make the changes to sysctl's defaults written in /etc/sysctl.conf effective immediately.

In the following example, I use grep to confirm that my stock Ubuntu install has a line setting ip_forward to 1 already, and it's just commented out; then I use sed to uncomment it. This will not always be the case - if you aren't certain, just manually edit your /etc/sysctl.conf to put the correct line in it.

me@banshee:~$ grep net.ipv4.ip_forward /etc/sysctl.conf
#net.ipv4.ip_forward=1
me@banshee:~$ sudo sed -i s/\#net\.ipv4\.ip_forward/net\.ipv4\.ip_forward/ /etc/sysctl.conf
me@banshee:~$ sudo sysctl -p
net.ipv4.ip_forward = 1

Now we can see that the changes to sysctl.conf worked, and the sysctl -p put them in effect. The OpenVPN server is now willing to forward packets. In most cases, you aren't done yet - you will either need to set up NAT (aka iptables MASQuerade), or create routes to the tunnel subnet(s) that the other machines on the LAN can discover. You only need to do ONE of the following two sections.

Setting up static routes through the OpenVPN tunnels

With this approach, you will need to make sure that the other clients on the server's LAN know the route to the OpenVPN tunnel (and to the remote LAN, if you're trying to do this so that any machine on either LAN can ping any machine on the other LAN). How you'll want to do this will vary - you can either set up static routes on every single client machine on the remote LAN (making for complex and difficult maintenance), or you can simply set up the static route on the gateway router for the remote LAN.


Example: This Netgear ProSafe router, itself on the 10.100.100.0/24 subnet, is configured to provide static routes to two remote offices and to their OpenVPN tunnels - you can't see the netmasks from this page, but the route marked "tunnels" is netmasked /16, so as to provide a single route to both /24 OpenVPN subnets - and, should there be further expansion, any other subnet in the 10.10.x.x range which might need to be added later. Obviously, the OpenVPN server in this case is at 10.100.100.14.


Setting a static route on the remote LAN's default gateway is usually the better approach - it will double the amount of traffic on that LAN (since clients will send VPN traffic to the router's LAN interface, then the router bounces it back out of its LAN interface to the OpenVPN server's LAN interface), but in most cases the VPN bandwidth is laughably small compared to the LAN bandwidth, so this isn't really an issue.

Setting up NAT (iptables MASQuerade)

If for some reason setting up routes through the tunnel isn't practical, you can opt instead to do Network Address Translation - this bypasses the "double the LAN traffic" problem that creating routes on the gateway has, but it can make troubleshooting and intrusion detection more difficult. When using NAT, if a single client's certificate is compromised and an attacker starts probing servers using that client's certificate, you have no practical way of telling which certificate has been compromised - because all the LAN servers see the OpenVPN server's LAN IP address connecting, not the individual tunnel IP address. However, in some circumstances NAT is the only way to go - for instance, if you have multiple private subnets you need to access and don't have control over the gateway routers for those subnets.

For this tutorial, we will assume that you're using iptables-save and iptables-restore to manipulate your firewalls (or not currently using any firewall at all), and not some shell script being run at boot.

First, save your existing firewall to /etc/network/iptables:

me@box:~$ sudo iptables-save > /etc/network/iptables

Now, set up a script to automatically restore your firewall whenever the network comes up. sudo nano /etc/network/if-pre-up.d/iptables and enter the following:

#!/bin/sh
/sbin/iptables-restore < /etc/network/iptables

Now sudo chmod 755 /etc/network/if-pre-up.d/iptables to make the script executable, and we can move on to editing /etc/network/iptables, the location of your saved firewall state. You will need to adjust to your own interface names and IP addresses, but here is a sample:

  • nat
PREROUTING ACCEPT [0:0]
POSTROUTING ACCEPT [0:0]
OUTPUT ACCEPT [0:0]
  1. eth0 is our LAN interface.
  2. if we receive traffic on another interface which will
  3. go through eth0, NAT the traffic to show our own IP
  4. address instead of the real source's IP address.

-A POSTROUTING -o eth0 -j MASQUERADE COMMIT

  • filter
  1. accept packets for forwarding from the OpenVPN interface

-A FORWARD -i tun0 -j ACCEPT -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT

  1. DON'T accept packets for forwarding from any other interface

-A FORWARD -j DROP

  1. the following rules aren't related to NAT at all,
  2. they just create a "default allow" firewall state.

-A INPUT -j ACCEPT -A OUTPUT -j ACCEPT COMMIT

With this saved in /etc/network/iptables, you can sudo /etc/network/if-pre-up.d/iptables to apply them, and - assuming you've checked your interface names, which may not match the ones in this sample, and corrected them as necessary - you should be off to the races.


Configuring client.conf

When you install OpenVPN on client computers, you'll need a client.conf there, and the ca.crt, the clientname.crt, and clientname.key. You can edit the client.conf found in the example files directory you copied to /etc/openvpn on the server appropriately, or you can use this edited-for-brevity version below:

ca ca.crt
cert clientname.crt
key clientname.key

remote server.domain.tld 1194 
;comp-lzo
client
dev tun

;dev-node MyTap

proto udp
resolv-retry infinite
nobind
 
# Downgrade privileges after initialization (non-Windows only)
# note - you might NOT be able to do this if you need to accept pushed routes!
;user nobody
;group nogroup

# Try to preserve some state across restarts.
persist-key
persist-tun

# Set log file verbosity.
verb 3
mute 20

If this is a Windows client with the OpenVPN GUI, you'll want to put this conf file and the three certificate/key files in the OpenVPN\Config directory. You'll also need to name the conf file [filename].ovpn, not [filename].conf, if you want the Windows OpenVPN GUI to recognize it automatically. And if you need to support multiple simultaneous VPN connections, you'll have to install multiple OpenVPN virtual adapters. (You may or may not also have to name them all appropriately, uncomment the dev-node directives in your conf files, and change the names in the directives to match the appropriate devices. YMMV.)

Hiding the TAP adapter on Windows clients

The community version of the OpenVPN client from openvpn.net, unfortunately, no longer asks you during installation if you want to hide the TAP adapter (to keep users from constantly disabling it, to make the icon in the system tray go away). Luckily, if you know how, it's quick and easy to hide or unhide the adapter yourself:

In regedit, navigate to HKLM\SYSTEM\CurrentControlSet\Control\Class. Now search for "TAP-Win" - once you're on the adapter you want, change the "Characteristics" key from 0x81 to 0x89 to hide it, or vice-versa to make it visible again. Once you're done there, go to Network Connections from the control panel, and hit F5 or click View->refresh - the TAP adapter will then (dis/re)appear from there and from the systray.


Routing to the client subnet

Let's say that you created a client named client (meaning you've got a key named client.key in your keys directory), and that client's own network is 192.168.0.0 masked 255.255.255.0. Make a directory /etc/openvpn/ccd, and a file /etc/openvpn/ccd/client :

iroute 192.168.0.0 255.255.255.0 

Now edit your server.conf, and add the following two lines:

client-config-dir ccd
route 192.168.0.0 255.255.255.0

If you were dropping privileges to user nobody group nogroup, you absolutely must comment out those lines for this to work!

It's that easy. Restart your server (/etc/init.d/openvpn restart) and you're good to go - the next time client connects, 192.168.0.0/24 will be routed through client's tunnel. (You will also need client to be configured as a gateway, and client's network will need to have a route through client to the VPN subnet and to the server subnet, if you expect to actually be able to return pings or anything else useful.)

Personal tools