I use PC Engines Alix boards as VPN Appliances intended to connect some branch offices. They are rock solid, work for years without any problem and bring the flexibility one needs to implement all the nice stuff. 3x Lan Interface, 2x USB, passive cooling. Quite nice. Complete sets are available on Amazon or at some distributors listed at the PC Engines Website.


After using this configuration for some years I would like to refactor it using new software versions and some improvements. The following article will describe installation and setup of VPN router appliances based on Alix 2d13 boards and voyage-linux. The boards use a VIA cpu with 500 MHz and 256 MB Ram. Not that much but enough for a small Debian running openvpn and routing a little bit. A rock-solid solution running very stable. A nice alternative for voyage-linux would be the IPFire distribution but configuring Openvpn in a bridged mode is not possible in the gui. So I decided to stay with my old configuration. For everybody else, especially with lower skills in shell usage, IPFire is a very nice solution.


  • Alix 2d13 board (with buffer battery for the build-in RealTimeClock – very nice for VPN appliances to have a nonvolatile timesource)
  • 4GB SanDisk CompactFlash cards (not to cheap and not to expensive 🙂 )



Voyage Linux Flashing

  • Download and install voyage-linux as described in the documentation (http://svn.voyage.hk/repos/voyage/branches/voyage-live/0.9.5/config/includes.chroot/README)
    sudo fdisk /dev/sdb
    mkfs.ext2 /dev/sdb1
    tune2fs -r 0 -c 0 /dev/sdb1
    wget http://mirror.voyage.hk/download/voyage/voyage-0.9.5.tar.bz2
    sudo tar --numeric-owner -jxf voyage-0.9.5.tar.bz2
    cd voyage-0.9.5
  •  Login for the first time by attaching the board to a DHCP enabled Lan on the port next to the power connector. Look at your DHCP leases to find out the ip and login with root:voyage (no need for serial terminal foo)

Basic System

  • Install related software packages
apt-get install aptitude
aptitude install vim ntp locales dialog openvpn openssl ca-certificates bridge-utils etckeeper fail2ban

 Some settings to be done

  • locale settings
dpkg-reconfigure locales

NTP config

The driftfile path in /etc/ntp.conf needs to be pointed to the tmpfs:

driftfile  /var/tmp/ntp/ntp.drift

Do the initial time sync:

service ntp restart
ntpq -p # display ntp status

RTC config

Since there is an error in the prepackaged hardwareclock management of voyage-linux on alix board, /etc/sysconfig/hwclock needs to be modified:

HWCLOCKPARS="--directisa -u --noadjfile"

Afterwards you have to check the rtc time and set it correctly.

/etc/init.d/hwclock.sh show # displays time and offset of the rtc like: Mi 06 Nov 2013 01:00:13 CET  -0.028651 seconds
/etc/init.d/hwclock.sh restart # writes time to rtc

Hardware clock sync is automatically done by the init-script on shutdown and startup now.

Interface configuration

Activate vlan support (if you need it)

Install vlan support package and activate kernel module:

aptitude install vlan
modprobe 8021q

Set vlan kernel module to be loaded automatically in /etc/modules by adding the following line:


Configure bridges and physical interfaces

(Some details about how to configure a wlan device: http://choerbaert.org/wiki/voyage_on_alix)

In /etc/network/interfaces:

# loopback interface
auto lo
iface lo inet loopback

# internet uplink
auto eth0
iface eth0 inet dhcp

# bridge interface for branch-vpn connection
# bridges eth1 with tap adapter for branch vpn
auto br_branch_vpn
iface br_branch_vpn inet static
        bridge_ports eth1
        bridge_stp on
        bridge_maxwait 10

eth1 is automatically added to br_branch_vpn bridge interface.

CA setup

If you like to setup a separate ca for vpn or if don’t already have one. This step should be done on a isolated machine separated from network and external access.


It is always a good idea to define a clearly structured namespace for vpn certificates. This helps a lot if you plan with client scripts and something other. I prefer something like the following: <organisation short name>-<vpn name>-<unique device and/or human name> Example: testcorp-branch_vpn-router01


mkdir /etc/ca
cp -ai /usr/share/doc/openvpn/examples/easy-rsa/2.0/ /etc/ca
cd /etc/ca
vim vars # configure your personal default settings at the end of this file

. ./vars        # source vars
./clean-all  # init directories - WARNING: deletes everything if executed later
./build-ca   # generate CA cert/key files

 Server Certificates

cd /etc/ca
. ./vars # if not already done
./build-key-server testcorp-branch-vpn-router

 Client Certificates

cd /etc/ca
. ./vars # if not already done
./build-key testcorp-branch-vpn-location1

OpenVPN Configuration

OpenVPN is able to operate in routed or bridged mode using tcp or udp. While I need layer-2 connection beween two locations, I decided to use bridged mode. If this is not needed, use routed mode. This is running on layer-3 so there is no broadcast traffic going through the vpn tunnel. The decision between udp and tcp may be a bit more complicated. While tcp offeres reliability by design, it slows down the connection with some overhead. Udp is faster but less reliable, not caring about if a package received or not. I decided to use udp for performance reasons. The tunneled traffic is mostly tcp, which ensured reliability above the vpn connection layer and makes udp a no-problem solution unless connection problems occur. Bridged connections use a tap adapter defined with a unique interface name. This adapter has to be joined to the already defined bridge on vpn startup and removed on termination. This is done by up/down scripts called in the openvpn config: /etc/openvpn/scripts/up

brctl addif $1 $2
ip link set $2 up
ifconfig $2 promisc up


ip link set $2 down
brctl delif $1 $2


I usually create a config file for each connection in /etc/openvpn, named with the connection name and a subdir with same name holding keys and additional files. The previously generated server-keys have to be copied here. General files like the CA certificate and diffie-hellman file get placed directly in /etc/openvpn.

cd /etc/openvpn
cp /etc/ca/keys/dh1024.pem .
cp /etc/ca/keys/ca.crt .
mkdir branch-vpn
cp /etc/ca/keys/branch-vpn.key ./branch-vpn
cp /etc/ca/keys/branch-vpn.crt ./branch-vpn

Last but not least a openvpn config file is needed. The following is a template which needs to be customized by your needs but fits in this example:

# ip to listen on
port 1099
proto udp

# named tap interface
dev tap_branch_vpn

# needed key files
ca ca.crt
cert branch-vpn/testcorp-branch-vpn-router.crt
key branch-vpn/testcorp-branch-vpn-router.key
dh dh1024.pem

# create bridged vpn with client ip space of 2 ip addresses

# signal sent from server to clients to ensure connection health
keepalive 10 120

# chose appropriate encryption
# settings have to be equal on both sides
cipher AES-256-CBC

# maximum number of concurrent clients
max-clients 2

# unix user and group of openvpn service
user nobody
group nogroup

# persists keys and interfaces to survive restarts with dropped privileges

# MTU Fix
tun-mtu 1500
tun-mtu-extra 32
mssfix 1200

# logging
status /var/log/openvpn/branch-vpn-status.log
log-append         /var/log/openvpn/branch-vpn.log

# log verbosity
verb 4

# Silence repeating messages.  At most 20 sequential messages of the same message
# category will be output to the log.
mute 20

# set script security mode to allow execution of up/down scripts
script-security 3

# Script to be run on openvpn startup
up "/etc/openvpn/scripts/up br_branch_vpn tap_branch_vpn"

# Script to be run on closing - right BEFORE closing - OpenVPN.
down-pre "/etc/openvpn/scripts/down-pre br_branch_vpn tap_branch_vpn"


Backup and Recovery

I need a quite simple solution for disaster recovery. As these devices are used as branch connection routers, there is not always it staff to fix maybe a broken CF card. A salesman, supplied with an instructions sheet, should be able to fix nearly every error regarding the vpn appliance. Further more configuration should be saved in a versioned fashion to be able to rollback in case of a fault.

Desaster Recovery

A very simple solution is to plug in a usb cf-card reader and copy the complete system to a backup cf-card once a week or so.

A requirement for this procedure is that both cf-cards have the same size. The best solution is to take identical ones. Check the size by:

blockdev --getsize64 /dev/hda
blockdev --getsize64 /dev/sda

The external cf-card is registered as /dev/sda while the internal one is /dev/hda. The following command does the job in around 1 hour:

dd if=/dev/hda of=/dev/sda
 3997163520 bytes (4,0 GB) copied, 4140,36 s, 965 kB/s

This can be triggered by a cronjob.

Configuration Backup

To backup the systems configuration in a versioned fashion i use etckeeper with git backend. This is absolutely easy to configure and allows to save the config on remote locations by git mechanisms (git remote add …).

aptitude install etckeeper
etckeeper init


Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.


Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden .