Virtual Private Network (VPN) is a technology to create secure, encrypted tunnels between hosts or networks. It can be used to provide secure remote access to networked resources, or as a means to create (private) routes between private networks. These routes can use a public, untrusted network such as the internet, while to the hosts (and the users and applications) on the private network, the other private network appears as if it was directly connected through a router. The end-points of the tunnel are private, and inaccessible from the public network (internet) by hosts that don't have the required authentication (shared key, certificate,...)
This howto describes how to set up a vpn between two hosts. Then we will elaborate on how to expand this to a connection between two networks, using the 2 hosts as a router.
Lastly, we will look at some other network configuration, not directly related to openvpn, but sometimes needed to get it to work or make it functional : If your networks are behind a NAT router, you'll have to work around that, and if your networks are only accessible through dynamic IP addresses, you need a solution for that too. Once your networks are interconnected, you may want to alter DNS configuration etc. to make communication between the 2 networks more smooth.
Most of this howto is based on 2 excellent howtos at the openvpn.org site : the OpenVPN HOWTO and the OpenVPN Mini HOWTO. I decided to write my own take on it when I found that those two howtos appeared to have left out some information that wasn't that obvious when i tried this for the very first time. This howto is meant to complement to 'official' OpenVPN Howtos, and help absolute beginners get their bearings when trying to set up a vpn.
I used Debian systems to set this up, so some of what follows may be Debian (or Ubuntu) specific - file locations and such. The openvpn config deals with networking mostly, so that should pretty distro-agnostic.
This is what we're aiming for :
A vpn tunnel is created from one network to the other.After it's set up, traffic can go in both directions, but for the actual creation of the tunnel, one end point will have to act as server, and one as client, and the client will connect to the server.
For remote access from hosts to a corporate network (road warriors, teleworkers), it's obvious that the server will be on the corporate network. If the aim of the vpn tunnel is merely to provide a secure route between two private networks, you can actually choose which network will host the 'vpn server' and which one the 'vpn client'. You can let practical considerations influence this decision (e.g. choose the solution that needs the least complex workarounds re. NAT, dynamic addresses, static routes, ...), or simply set up the tunnel in the direction that other connections will be set up. Assume that you have a central network, and a remote, disconnected network which you want to connect to (eg poll for printer counters, provide remote assistance, ...). In this case you might choose to build the tunnel from the central network towards the remote network, and the vpn server will be on the remote (branch office ?) network rather than the main (headquarters) network.
Again, this choice is mainly relevant to your network design. Once it's setup, the tunnel carries traffic both ways.
In this howto, we'll create a tunnel from network A to network B. Obviously, both networks need an internet connection, and will have at least 1 public address. Only the public IP address of (the gateway to) network B is relevant. Let's assume it's 184.108.40.206.
There is no difference between a client installation and a server installation. Therefore, on both hosts (server, client), run
apt-get install openvpn openssl
That's it for Debian Linux. For other operating systems, see the openvpn website.
server and client authentication is an essential part of secure networking. Openvpn can be made to work with a 'shared secret', i.e. e key file that is present on both the client and the server, or through a public key infrastructure (PKI) certificates. We'll only deal with shared key authentication, which is sufficient for simple point to point configurations like the one we're attempting. See the Openvpn howto for how to work with PKI and certificates, which helps (and is sometimes required for) managing authentication in more extensive vpn networks.
create a key file running the following commands. The name of the file (kicknet.static.key) is something you can choose.
cd /etc/openvpn; openvpn --genkey --secret kicknet.static.key
A copy of the same key needs to be put in /etc/openvpn of both the client and the server.
The configuration files for openvpn go in /etc/openvpn. The files should have a distinctive name : a file called /etc/openvpn/kicknet.conf will be taken to refer to the vpn 'kicknet'. This is because it is possible to set up more than one vpn on the same server. Also, associated files will be identified by name, eg. /etc/openvpn/kicknet.up will be run after the vpn 'kicknet' has come up (eg. to establish routing or firewall rules).
So, pick a name for your vpn, and use it for all files associated with this vpn.
For this reason, there are no files in the /etc/openvpn directory by default. You have to create them from scratch or copy them from examples in /usr/share/doc/openvpn/examples/sample-config-files/. For the setup explained here, the home.conf and office.conf were used for client and server configuration respectively.
The init script for openvpn is made so that all configured vpn's will be started during system startup.
For an initial setup, you need at least the following directives : the type of device (tun or tap), the ip addresses of the end points (from-to), and a reference to the key file :
dev tun ifconfig 10.1.0.1 10.1.0.2 secret kicknet.static.key
The comments about file names in /etc/openvpn goes for clients as well. The contents of the configuration file will be pretty similar to the one on the server, as they both represent end-points of the same point-to-point connection.
Important differences : the client conf file mentions the public address of the remote network's gateway, and, obviously, the vpn interface are in reverse order compared to the server.
remote 220.127.116.11 dev tun ifconfig 10.1.0.2 10.1.0.1 secret kicknet.static.key
This is sufficient for a host to host connection, you should now be able to ping from 10.1.0.2 to 10.1.0.1 and vice versa.
To use compression on the VPN link, add the following line to both client and server configuration files:
Make the link more resistant to connection failures, especially when dealing with a NAT router/firewall alive, and follow the DNS name of the server if it changes its IP address.
Add the following to both client and server configuration files:
keepalive 10 60 ping-timer-rem persist-tun persist-key
To run OpenVPN as a daemon and drop privileges to user/group nobody (more secure), add to configuration file (client and/or server):
user nobody group nobody ; daemon #handled by Debian init script
If the remote (server) public address is assigned by dhcp by an internet provider, it might change. Obviously, the vpn-link will break then. You can solve this with a service such as DynDNS, which provides fully qualified domain names for dynamic addresses. You can then use this hostname in stead of the IP address. See enhancements to the basic configuration, above.
If the vpn server is behind a NAT router, the client configuration will point to the router's WAN interface IP address, and you need to configure the router so that openvpn traffic is forwarded to the actual server. By default, this is port 1194/udp, but this is configurable (you can use tcp, and/or a different port). Note that if you change the port or the protocol, both client and server need to be aware of this !
When creating firewall rules, you have to consider both the tunnel and the traffic through the tunnel.
To establish the tunnel, you need to allow 1194/udp (or the port/protocol you chose) between the eth interfaces of the hosts involved;
For traffic through the tunnel, you need rules to/from the (ip address of) the tun interfaces.
What you have so far, is a connection between 2 hosts, on separate networks. Other hosts on either of the networks can not communicate with hosts on the other network. If this is required, you can make the vpn hosts route for the other hosts on the network. This results in a "Lan to Lan" connection.
By way of demonstration, lets consider the tunnel from netAclient (on LAN A, eg 192.168.10.1 ) to netBsrv (on LAN B, 192.168.20.1). To expand this to a Lan-to-Lan tunnel, netAclient and netBsrv will act as routers for the hosts on Lan A and LAN B respectively, providing a route towards the other side of the tunnel.
This lets all hosts on the client network connect to the server, through the tunnel created by the client host
on the client host, run echo "1" > /proc/sys/net/ipv4/ip_forward . This is not persistent, so you may want to add it to a startup script, or to /etc/openvpn/kicknet.up, which will be executed when the vpn tunnel is established. Should you decide to use the .up file, you have to refer to it from the .conf file (see samples).
## .conf ### run a script after vpn is up. # '.' is parent dir of the .conf file, /etc/openvpn up ./kicknet.up
If the vpn host in not the default gateway on its network (but eg the internet router is), the default gateway needs to be configured so that traffic for the remote vpn is routed to the vpn host (which will route it further through the tunnel). This means the default gateway (or all hosts) on
LAN A will need a route with destination 192.168.20.0 next hop 192.168.10.1,
LAN B will need a route with destination 192.168.10.0 next hop 192.168.20.1
If not only the remote vpn server but also the other hosts on the remote network need to be accessible, the lanAclient needs to have a route to this network added to its routin table, specifying that this remote network is accessible through the tun device.
To add routes, you can create 'route add ' statements in /etc/openvpn/kicknet.up, or simply add them to the vpn configuration file
route 192.168.20.0 255.255.255.0
This appears in the routing table as follows:
### Lan A - netAclient routing table netAclient:~# route Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface 10.1.0.1 * 255.255.255.255 UH 0 0 0 tun0 192.168.20.0 10.1.0.1 255.255.255.0 UG 0 0 0 tun0 192.168.10.0 * 255.255.255.0 U 0 0 0 eth0
To provide a return route to the hosts on the server's network, you do a similar configuration there (enable ip_forwarding, create routes through the tunnel, and create a route on the default gateway.
This now also allows hosts on network B to set up connections to hosts on network A, as long as the tunnel (initiated from network A) is active.
route 192.168.10.0 255.255.255.0
any host on LAN A can now connect to any host on LAN B:
netAhost:~# ifconfig eth2 |grep inet inet addr:192.168.10.108 netAhost:~# traceroute to 192.168.20.205 (192.168.20.205), 30 hops max, 40 byte packets 1 192.168.10.1 (192.168.10.1) 12.703 ms 0.800 ms 0.308 ms 2 10.1.0.1 (10.1.0.1) 1.540 ms 1.809 ms 1.419 ms 3 192.168.20.205 (192.168.20.205) 2.589 ms 2.915 ms 2.618 ms
and it also works in the opposite direction, from Lan B to Lan A
netBhost:~# ifconfig eth2 |grep inet inet addr:192.168.20.205 netBhost:~# traceroute to 192.168.10.108 (192.168.10.108), 30 hops max, 40 byte packets 1 192.168.20.1 (192.168.20.1) 7.005 ms 2.943 ms 0.883 ms 2 10.1.0.2 (10.1.0.2) 8.975 ms 4.176 ms 2.863 ms 3 192.168.10.108 (192.168.10.108) 9.188 ms 3.276 ms 0.834 ms
Obviously, for this to work, routing on both networks need to be setup correctly, i.e. the openvpn hosts themselves have to be default gateway of their respective networks, or the default gateway needs to have a route towards the remote network via the openvpn host.