Configuring OpenVPN
for multiple clients
1/31/2006 We needed a solution to allow multiple staff members, running Windows, to establish VPNs into our private network. OpenVPN is set up to allow this without too much difficulty, and includes versions for both Linux and Windows. We already had a CA set up on the OpenVPN server according to my previous entry. This leaves off from there (before the IPSec stuff though). I also generated a tls-auth key, which causes OpenVPN to drop all packets that do not contain a signature, helping to protect against portscans, DOS, etc. See the OpenVPN HOWTO for more info. This is done by typing openvpn --genkey --secret ta.key. This will dump that key to a file called ta.key, which I then moved to the /usr/share/ssl/certs/ directory. You will distribute this file to the clients as well, and include it in both your and their OpenVPN config files. On the client: First, download OpenVPN GUI for Windows. I chose the latest stable release, which is 1.0.3 with OpenVPN 2.0.5 (released 11/4/2005). We already had OpenVPN 2.0.5 installed on the server, as a matter of fact, so this seemed like the perfect choice! I ran the setup (on a Windows 2000 client), making sure to check "My Certificate Wizard" and leaving the default install location as C:\Program Files\OpenVPN. The installation created a new LAN adapter, named "TAP-Win32 Adapter V8." Once installation was complete, I checked the My Certificate Wizard
INI file (C:\Program Files\OpenVPN\bin\mycert.ini) and made
sure that it would create a 2048-bit RSA key as we required on our CA,
and this was, in fact, the default, as was a one-year expiration on
the key. I then ran My Certificate Wizard to create a
certificate signing request. The options that need to be filled in are
straightforward and self-explanatory, but nonetheless, here is what
my answers looked like:
The default also requires a pass phrase of at least six characters, which is good. I typed all that in, then clicked Create Request. This will save a certificate request and a private key in the C:\Program Files\OpenVPN\config\ directory, named according the Common Name that you entered. For example, my CSR is named Eric_Low.req and my private key is named Eric_Low.key. The program will also display and highlight the CSR for you, which you can then copy to the clipboard if you'd like to send it in an email. This is identical to the .req file.
On the server: Copy that .req file or text to /usr/share/ssl/certs/newreq.pem
on the server (this file should not already exist. If it does, it means
you forgot to delete an old CSR). Next, sign the request by typing the
following:
On the client: You must also copy the CA Server certificate to the client computer and stick it the same OpenVPN\config\ directory as all your other OpenVPN keys. On our CA (server), this file is named /usr/share/ssl/certs/PRLinkCA/cacert.pem. So obviously, all clients will use the same CA certificate. I copied ours to OpenVPN\config\DScert.pem. Copy that signed certficate, newcert.pem, to the client computer and save it in the C:\Program Files\OpenVPN\config\ directory, naming it according to your Common Name (I named mine Eric_Low.pem). Next, you will need an .opvn (OpenVPN session config) file. Each time OpenVPN GUI starts, it scans the C:\Program Files\OpenVPN\config\ directory for any files with this extension, and attempt to create a connection based upon its contents. You can modify one of the default config files for this purpose (take a look at C:\Program Files\OpenVPN\sample-config\client.ovpn). We already had a bridged OpenVPN tunnel running, limited to one client. So for these clients, I needed to set up a second instance of openvpn, listening on a different port, as well as using tun (routing) rather than tap (bridging) interface for ease of configuration. Most of the default client config file was exactly how I wanted it.
However, there were a few options that required attention. Here is my
client.ovpn file, with the important (changed) lines in bold:
The server directive, of course, is needed to point to the openvpn server and port. Notice the tls-auth directive, which tells the client where to find the tls-auth keyfile. This will stick a signature on all packets, and then the server will drop any packets that do not contain that signature. I dumped this file into the OpenVPN\config directory, then went down to my system tray, right-clicked on the OpenVPN GUI icon, and selected Connect. A dialogue box popped up to prompt for my key's password. After that, a status window popped up and showed me what was happening with the connection. A few seconds later, it told me that the virtual adapter had a connection, and voila! I could see our internal network. :)
On the server: I modified the default /etc/openvpn/server.conf file (renaming it to /etc/openvpn/servingothers.conf) for our needs.
This config, set up for routing, will create one tun interface named tun0, through which all clients are routed (the IP of this interface is their gateway). The IP of this interface is defined by the server directive - the tun interface always gets the first IP on this subnet (in our case, .1) Notice the push directives, which send rules to the client when they log in. I push a route command for each internal subnet that the clients should see, as well as one so they see our internal DNS server. Again, notice the tls-auth directive! This is very important because it causes packets that do not contain that signature to be dropped! See the beginning of this document for info about how to generate the file. The server gets an option of 0 at the end of this line, while the client, which has the same file specified, gets a 1. As far as firewall rules, they are pretty straightforward:
Our normal firewall setup is a bridge, and I am not making tun0 a part of it. Therefore, with ip_forwarding turned on, anything that comes in through tun0 will have an input interface of tun0 and an output interface of bridge. So basically, it gets forwarded to the bridge stack. Then, any of those packets that are destined for our internal network (most of it, anyhow) will go out through physdev eth1. Hence that first forwarding rule. The next two lines simply handle the SNAT so the clients can talk to the internal subnet.
========================================================= Route the client's subnet back to the server It's also pretty easy to add the client's subnet(s) to your intranet, so that you're sharing in both directions. And yes, this still involves the client running Windows, the server running Linux, and both using tun interfaces (I say that because this would be ridiculously easy with a bridge - hell, there would be no setup!). This simply involves setting Windows to do packet forwarding (routing) and then putting the appropriate routing entries in place. Our purpose for doing this was actually to route VOIP through the tunnel so that users could make calls through our voip server from home, but only over a secure line. I have a feeling I made this overly complicated though, so bear with me! First, I added a second network card, behind which I would stick the VOIP box (and only the voip box) and which would act as the VOIP box's gateway. The VOIP box was configured to have an IP address of 192.168.85.2 and use a gateway of 192.168.85.1, the IP address of which I statically assigned to the new network card (netmask of 24, in case you were wondering) Next, I statically assigned that network card an IP address of 192.168.85.1, but told it to use a gateway of 192.168.80.6, which is the IP ADDRESS of the virtual tun interface. In the OpenVPN server's configuration file, I added the following
directives:
That route directive will cause OpenVPN to add a route to the kernel's routing table, sending that subnet to OpenVPN, once a tunnel is established (it sends it to OpenVPN, not to the virtual interface - OpenVPN takes it from there, sending it to the correct client, which is configured by the iroute directive). (Typing ip route will show 192.168.85.0/24 via 192.168.80.1 dev tun0). The push route directive tells the client to add an entry to its routing table, sending that subnet back in the other direction. Next, you must add an iroute directive. Because that route command only tells the kernel to route that subnet to OpenVPN, OpenVPN must know where to send it once it gets it. An iroute directive can only go in either a client-connect script or a client instance config file. We are going to put it in a client instance config file, which is basically a small config that is added when a given client connects, based off of the common name on their certificate (this is what the client-config-dir directive up above is for - OpenVPN compares the files in the specified directory with the user's common name each time a connection is made). I created a client instance config file named /etc/openvpn/ccd/Eric_Low
which contained the following line:
So, now the server and the client both know where to route packets. Finally, you must turn on IP forwarding on the Windows client. Believe it or not, almost every version of Windows is capable of this! Here is a very good document describing how. On Windows 2000/XP, you simply have to set the HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\IPEnableRouter to 1 (reg_dword). Voila! Windows now forwarded all packets from the VOIP box at 192.168.85.2 to the second NIC on the Windows computer, 192.168.85.2, which then forwarded them on to the OpenVPN server's tun interface at 192.168.80.1, which then forwarded them to our internal network (they will have their original source IP the entire way). And, of course, vice-versa! It's just that simple. Keep in mind, however, that you may need to SNAT any packets (on the OpenVPN server/firewall) to be on the correct subnet. A word of caution about turning on IP forwarding on the Windows client: Should the tunnel get disconnected, causing the VOIP box's gateway to no longer exist, the Windows box will still forward the packets - since its normal route is gone, it will now forward them to its own default gateway! My router (which is obviously configured wrong) was then NAT'ing the packets so they all had a real live source IP. And, at least with my Windows firewall (Tiny Personal Firewall), it was unable to see these packets! Apparently it does not listen at a low enough level, or these packets somehow pass through below what anything in the userspace can see. So, be careful! Luckily, our VOIP boxes are only trying to hit one location, which is on our private intranet and therefore blocked by our firewall unless the packets come through the tunnel. But I can see the packets trying to come in nonetheless!
===========================================================
*** Should the OpenVPN GUI installation program freeze, it is most likely having difficulty installing the TUN interface. The user will need to reboot Windows to abort the installation, then install the TUN interface manually (the program will actually still be installed at this point). After rebooting, simply click on Start -> Run and type CMD to open a command prompt. Then, type the following commands: cd c:\Program Files\OpenVPN\driver You should then see the following success message: Device node created. Install is complete when drivers are updated... Now, run OpenVPN manually by clicking on Start -> Programs ->
Openvpn -> OpenVPN GUI. This will cause openVPN to add the correct
registry keys and complete the installation. If necessary, drag the
OpenVPN GUI icon to the Startup Folder. |
Downloads: