Essentially, there are three ways to implement a VPN:
The proprietary solutions, such as Cisco, are scalable, you usually get good support and are pretty well documented. On the other side, they can be extremely expensive (unless you choose to cheat and combine the VPN function into an existing firewall or similar device, which is pretty bad from several points of view); also, proprietary solutions tend to lock you into whatever features the vendor provides - if you want to (or have to) deviate even a little bit from the One True Way, you can easily be left in the dust.
The Open Source implementations of the IPSec protocol are nice because they are able to interoperate with pretty much any other IPSec-based VPN; being Open Source, they are also cheap. On the other side, if you try to implement such a solution, like FreeS/WAN for example, you will face significant issues:
Enter OpenVPN - http://openvpn.sourceforge.net/:
There is usually one thing that people get wrong when they hear about OpenVPN: even though it's based on SSL, it is not a browser-based pseudo-VPN; instead, it is a full-blown VPN solution, that can tunnel any arbitrary protocol. You can even ping through it, and a browser is not required at all. Functionally, it is a perfect equivalent to Cisco VPN or FreeS/WAN, except the fact that the encryption is not based on IPSec, but instead it encapsulates the IP packets in a tunnel encrypted with SSL. Let's say it's a "free form" implementation of SSL that happens to be able to tunnel arbitrary IP traffic.
Let's consider a practical situation that requires a VPN solution. The diagram below illustrates a typical small-company network. There's a Linux firewall in the middle that creates an intranet on the private address space 192.168.1.0/24 (painted red) and a DMZ on the public address space 222.111.222.0/24 (painted blue). The firewall's outside interface has the address x.y.z.k. The intranet has workstations and such, the DMZ has the webservers, a few mail servers, etc.
At some point, the management desires to connect several remote systems (painted green) to the internal network, using VPN. There are several ways to accomplish that; we will show you how to accomplish that by adding VPN functionality to the Linux firewall, using OpenVPN.
We will assume that the Linux firewall is running Fedora Core 1, although other Linux distributions should be similar. Of the many encryption schemes offered by OpenVPN, we will use the one based on preshared static keys; while the method based on RSA certificates has a slight advantage on the crypto side, static keys are much more simple to deploy and are not measurably weaker under normal circumstances.
Download the LZO libraries from freshrpms.net. The website offers both binary RPM packages (install them directly) and src.rpm packages (which you can rebuild). Install the binary LZO packages (both the main package and the devel-).
Download the latest OpenVPN software and generate the binary RPM package. It is generally o.k. to use "pre" or "beta" versions of OpenVPN, the software seems remarkably stable even when in beta stage.
rpmbuild -tb openvpn-1.6_rc3.tar.gz
Install the binary RPM once it's done.
There are two types of tunnels that can be established with OpenVPN: Routed IP Tunnels, and Bridged Ethernet Tunnels.
The Routed IP Tunnels mode is more efficient and easier to setup. However, it cannot provide the VPN clients with addresses in the same network as the IP range used on the intranet, but it must use a different range for them.
The Bridged Ethernet Tunnels mode is more difficult to setup and is less efficient, however it is able to assign to the VPN clients addresses in the same range as the intranet; this is good for simple Windows networks that do not use WINS, because it allows the Windows machines to "see" each other, even if they reside on the opposite ends of a VPN tunnel (the VPN clients can "see" Windows shares on the internal network, and viceversa).
The first method is covered in the OpenVPN HOWTO. We will describe here the second one: Bridged Ethernet Tunnels.
We will assume that the internal interface of the firewall (the one facing the Intranet) is eth1. You will have to configure that interface so that it does not have an IP address; instead, you will configure a bridge interface br0 on it that has the same address. On top of that, you'll create several TAP interfaces, one for each VPN client.
I made a script that does all that for you. You don't have to modify the settings for eth1, the script will read the settings and perform all configuration bits. The script assumes there will be no more than 16 VPN clients connected to the firewall (you can change that with the maxtap variable).
#!/bin/bash # # Replace eth1 with TAP/bridge interfaces # # chkconfig: 2345 11 89 # description: Create TAP/bridge interfaces . /etc/rc.d/init.d/functions start() { maxtap=15 . /etc/sysconfig/network-scripts/ifcfg-eth1 echo "Create TAP/bridge interfaces:" modprobe tun modprobe bridge ifconfig eth1 down for i in `seq 0 ${maxtap}`; do openvpn --mktun --dev tap${i} done sleep 1 brctl addbr br0 brctl addif br0 eth1 sleep 1 for i in `seq 0 ${maxtap}`; do brctl addif br0 tap${i} done sleep 1 for i in `seq 0 ${maxtap}`; do ifconfig tap${i} 0.0.0.0 promisc up done sleep 1 ifconfig eth1 0.0.0.0 promisc up sleep 1 ifconfig br0 ${IPADDR} netmask ${NETMASK} broadcast ${BROADCAST} && success || failure RETVAL=$? sleep 1 echo } stop() { echo "TAP/bridge fake shutdown (we never stop)" RETVAL=$? success } case "$1" in start) start ;; stop) stop ;; restart) stop start ;; *) echo $"Usage: $0 {start|stop|restart}" RETVAL=1 esac exit $RETVAL
Name the script eth1-replace and put it in /etc/init.d then make it active:
chkconfig --add eth1-replace
At every reboot, the script will reconfigure eth1 to be in IP-less mode, will create the bridge and TAP interfaces, will load appropriate kernel modules, etc., all that transparently and in a fashion that's compatible with Fedora network configuration files.
Create a group openvpn and a user named openvpn that belongs to that group. Create a directory /var/log/openvpn then change its ownership to openvpn:openvpn.
Make sure to configure your iptables firewall so that it is compatible with OpenVPN, according to the OpenVPN HOWTO.
At this moment, the machine is ready for you to start creating VPN accounts on it.
Create the server-side configurations required to connect the user John Doe to the VPN server.
One current limitation of OpenVPN is that it needs one UDP port on the server for each client that's registered with the server; there's also one openvpn daemon for each registered client. This effectively limits the number of clients you can register with one OpenVPN server to approx. 1000 or something like that. Future versions of OpenVPN will remove this limitation, for the moment you have to deal with it (the limit is actually pretty high, so most users don't have to worry about that).
Choose a username for this new user/client:
export user=johndoe
Go to the /etc/openvpn directory; from now on all operations will be performed in that directory:
cd /etc/openvpn
Create the shared key for the user:
openvpn --genkey --secret $user.key
Before creating the configuration for a new client, you have to choose the UDP port that the client will connect to. Don't forget to assign a unique port for each new client. Suppose the port number for this user is 5000. Then create a file named $user.conf (different names for different users, and the extension .conf is critical) with a content similar to this:
# Linux VPN server config file # These settings are different for each user port 5000 dev tap0 secret johndoe.key log-append /var/log/openvpn/johndoe.log # These settings are the same for all users local x.y.z.k fragment 1400 mssfix ping 10 ping-restart 35 ping-timer-rem persist-tun persist-key persist-local-ip comp-lzo comp-noadapt user openvpn group openvpn verb 4
The first 4 parameters (port, dev, secret and log-append) will be different for each user/client. "dev tap0" uses the first TAP interface created by /etc/init.d/eth1-replace; next user/client will use the next one (tap1) and so on.
The next parameters are the same for all users. x.y.z.k is the external IP address of the firewall. Delete comp-noadapt if you want smart, adaptive compression on the VPN tunnels.
I'm assuming that the clients are all Windows machines. If the clients are Linux machines, the configuration should not be very different from the server, although probably much simpler, so i won't describe it here.
On each client, download and install the Windows version of OpenVPN. Get the $user.key file from the server and put it in C:\Program Files\OpenVPN\config. In the same directory, create a file named $user.ovpn (the extension .ovpn is important) with the following content:
# Windows VPN client config file # These settings are different for each user port 5000 secret johndoe.key ifconfig 192.168.1.252 255.255.255.0 # These settings are the same for all users remote x.y.z.k route 222.111.222.0 255.255.255.0 192.168.1.254 route-delay 10 dev tap tap-sleep 1 fragment 1400 mssfix ifconfig-nowarn ip-win32 dynamic ping 10 comp-lzo comp-noadapt verb 4
The port should be the same with the setting on the server. ifconfig assigns the client an IP address in the address space of the intranet. remote is the outside IP address of the firewall. The route statement assigns a static route to the DMZ through the VPN tunnel; 192.168.1.254 is the internal address of the firewall, which is a gateway for this route. Don't use the route statement if your network doesn't have a DMZ or you don't want to provide access to the DMZ for this particular system.
On Windows, OpenVPN is a service, so you can control it from Administrative Tools / Services. Or you could create a VPN-Start.bat file containing the "net start openvpnservice" command, and a VPN-Stop.bat file containing the "net stop openvpnservice" command and put them on the Desktop and click on them when you want to start/stop the VPN tunnel.
Read the OpenVPN HOWTO and the rest of the documentation on the OpenVPN site. The mailing list is helpful, but make sure you searched the docs before asking a question on the list.
OpenVPN is rock solid under typical conditions. The tunnels stay up indefinitely, there are no unexpected glitches, and the software seems to scale pretty well - it will saturate your Internet connection long before you run out of CPU cycles on the VPN server, even when using non-adaptive compression.
When compared to FreeS/WAN or other IPSec-based VPNs, it's easier to setup, it's a lot less sensitive to interactions with firewalls and NAT, it uses the well-known and widely tested OpenSSL library, and has many other useful features. It is highly recommended, both for private usage and commercial applications.