I’ve had excellent luck setting up a key-based authentication VPN for my home network, which is distributed across the country and consists of Linux, Mac (OS X), and QNAP nodes. What, you ask, does “key-based authentication” refer to? It means that I do not allow people to enter passwords. Instead, clients must possess the proper key, which is exchanged automatically by openvpn. I think key-based authentication can be more secure in some cases, however I mainly wanted to do it “just because.”
Generally speaking the OpenVPN HOWTO is excellent and should suffice for setting up your VPN. Ill briefly parrot this guide here. To set things up you:
- Pick a vpn network. E.g. something that won’t conflict with any of the LAN networks of the nodes on your distributed network. For example, one of my nodes sits on a 192.168.x.x/16 network, another sits on a 10.246.75.x/24 network, etc. Pretty much anything, other than 10.246.75.x/24, from the 10.x.x.x/8 space can be used.
- Generate keys:
- From /etc/openvpn/easy-rsa run . ./vars
- ./build-ca – basically accept everything as is, but remember the common-name for the server (as <servername>)
- ./build-key-server <servername>
- For each of my clients (i have 5 or 6): ./build-key <clientName>
- Build the diffie-hellman stuff: ./build-dh
- I chose to enable client-client communication, so I added the following in my server config:
- client-to-client (to let clients talk to eachother)
- push “redirect-gateway def1” (to redirect all traffic through my vpn)
- client-config-dir /etc/openvpn/clients (to let me specify static ips for all my clients). For each client (identified by the common name, during the setup above, I create a like-named file with a single line like this:
- ifconfig-push 10.9.1.22 10.9.1.23 (meaning this client will be accessible within the vpn via the 10.9.1.22 address)
On each client I scp’d over the ca, crt, key files, and made up a quick config script (based on the sample provided with openvpn). I really only changed the following lines:
- remote <hostname> <port> (this line has the hostname/port of your server)
- ca /abs/path/to/vpn/directory/ca.crt
- cert /abs/path/to/vpn/directory/fenimac.crt
- key /abs/path/to/vpn/directory/fenimac.key
With that both the server and client should connect; all connected clients should have statically-assigned ips, and they should be able to talk to eachother.
What makes this a bit tricky is QNAP. They only provide password-based authentication. Thankfully you can just make a crontab to create the vpn connection, if its not up. I made a script that looks something like:
VPNLOG=/mnt/HDA_ROOT/vpndir/vpn.log if [[ `ps ax | grep openvpn | grep vpndir | grep -v grep` ]]; then echo "`date` Already running" | tee -a $VPNLOG ping -c 1 <server'sVPNIp> PINGRET=$? if [[ "0" = "$PINGRET" ]]; then echo "`date` Link is good!" | tee -a $VPNLOG exit 0 else echo "`date` Link is down (ping gave $PINGRET) - killing current vpn" | tee -a $VPNLOG ps ax | grep vpndir | tr -s " " | cut -f 1 -d ' ' | xargs kill -9 fi fi echo "`date` Run this thing!" | tee -a $VPNLOG /usr/sbin/openvpn --config /mnt/HDA_ROOT/vpndir/qnap.conf | tee -a $VPNLOG
A few important notes:
- I run this script on the QNAP every couple minutes in a crontab. Just editing crontab (“crontab -e”) doesn’t do the trick – qnap wipes those entries away upon reboot. To make this work, even across reboots, I followed a guide i found somewhere on the internet. Basically you do the following:
1. Edit /etc/config/crontab and add your custom entry. 2. Run 'crontab /etc/config/crontab' to load the changes. 3. Restart cron, i.e. '/etc/init.d/crond.sh restart'
- I couldn’t get the vpn to stay up unless I turned on the vpn server inside the qnap. It wasn’t my favorite thing to just leave that on, but for now im ok with it.