Sorry we lost some posts because of database errors!

*New 12.1 series Release:
2020-09-01: XigmaNAS - released

*New 11.4 series Release:
2020-08-27: XigmaNAS - released!

We really need "Your" help on XigmaNAS translations. Please help today!

Producing and hosting XigmaNAS costs money. Please consider donating for our project so that we can continue to offer you the best.
We need your support! eg: PAYPAL

[HOWTO] openvpn in jail

Jails with XigmaNAS
Forum rules
Set-Up GuideFAQsForum Rules
Post Reply
Posts: 9
Joined: 23 Oct 2017 02:48
Status: Offline

[HOWTO] openvpn in jail


Post by grzs »

I couldn't find a working solution, so I decided to post mine. Comments are welcome.

For an embedded installation extending functionality can be done with jails, but there are some limitations, what makes it difficult to deploy an openvpn service. Within a jail by default you cannot:
  1. access all devices;
  2. manage interfaces;
  3. manage route table.
That's why we have to prevent openvpn attempts of managing network resources, and find an alternative way to do it.

Let's see the topics' details one by one!

1. Make TUN devices visible in jails
This can be done by adding a devfs ruleset. Here are the steps:
  • create a file in a permanent location (in my case it's /mnt/tank/home/admin/vpn/devfs.rules) with the content:

    Code: Select all

    # unhide tun devices for vpn jails
    add include $devfsrules_hide_all
    add include $devfsrules_unhide_basic
    add include $devfsrules_unhide_login
    add path fuse unhide
    add path zfs unhide
    add path 'tun*' unhide
  • add rc.conf directives:

    Code: Select all

    devfs_rulesets="/etc/defaults/devfs.rules /mnt/tank/home/admin/vpn/devfs.rules"
  • apply ruleset to jail by adding the line to jail.conf:
    devfs_ruleset = 5
2. Configure openvpn to leave network management to us
Add the following lines to your openvpn config file (inside the jail, normally /usr/local/etc/openvpn/openvpn_foo.conf):

Code: Select all

script-security 2
up "echo up"
down "echo down"
3. Prepare network for vpn outside the jail
Create device, setup device, add route to vpn network:

Code: Select all

ifconfig tun create
ifconfig tun0 netmask
route add -net
The first command created interface tun0. Pay attention to the names, because if tun0 existed already, it will be tun1 and so on...
In this example I used for the tun device ip. It assumes that the vpn network is 10.8.0..0/24 and the jail is a client. The important part is that a tun interface needs two ip addresses for the two end points and a netmask. The two ip can be different, according to the network topology. RTFM

4. Start the vpn service
Be careful to not enable the vpn service in the jail, because it will fail if cannot create the interface. If your config file is openvpn_foo.conf, it's enough to symlink the rc script in rc.d:

Code: Select all

ln -s /usr/local/etc/rc.d/openvpn /usr/local/etc/rc.d/openvpn_foo
after that you can start the service:

Code: Select all

service openvpn_foo onestart
...or outside the jail:

Code: Select all

jexec jail_name service openvpn_foo onestart
5. Startup script (optional)
Basically we're done, but it needs manual settings. For my convenience I wrote a startup script ( and added to my jail.conf (I manage my jails with Bastille, and connects to two vpn networks):

Code: Select all

vpn_gw {
  devfs_ruleset = 5;
  enforce_statfs = 2;
  exec.consolelog = /mnt/tank/bastille/logs/vpn_gw_console.log;
  exec.start = '/bin/sh /etc/rc';
  exec.poststart = '/mnt/tank/home/admin/vpn/ start client1';
  exec.poststart += '/mnt/tank/home/admin/vpn/ start client2';
  exec.prestop = '/mnt/tank/home/admin/vpn/ stop client1';
  exec.prestop += '/mnt/tank/home/admin/vpn/ stop client2';
  exec.stop = '/bin/sh /etc/rc.shutdown';
  host.hostname = vpn_gw;
  mount.fstab = /mnt/tank/bastille/jails/vpn_gw/fstab;
  path = /mnt/tank/bastille/jails/vpn_gw/root;
  securelevel = 2;
  allow.raw_sockets = 1;

  interface = bge0;
  ip4.addr =;
  ip6 = disable;
And finally, here is the script (

Code: Select all

#! /bin/sh

if [ $# -lt 2 ]; then
  echo "Usage: $0 start|stop vpn_config_name"
  exit 1

WD=`dirname $0`

if [ $1 == 'start' ]; then
  if [ -f $WD/${NAME}_tun ]; then
    echo "client is running, exiting..."
    exit 1

  if [ ! -f $WD/conf/${NAME}.conf ]; then
    echo "config file not exists, exiting..."
    exit 1

  if [ ! -f $WD/conf/${NAME}.ip ]; then
    echo "ip address file not exists, exiting..."
    exit 1

  # create tun device and save its name
  ifconfig tun create > $WD/${NAME}_tun
  TUN=`cat $WD/${NAME}_tun`

  # setup tun interface with fix ip and add static route
  IP=`cat $WD/conf/${NAME}.ip`
  ROUTE=`echo $IP | sed 's/[0-9]*$/0\/24/'`
  ifconfig $TUN $IP $IP netmask
  route add -net $ROUTE $IP

  # update vpn config file with the interface name
  echo -n 'dev ' > ${CONF_DIR}/openvpn_${NAME}.conf
  cat $WD/${NAME}_tun $WD/conf/${NAME}.conf >> ${CONF_DIR}/openvpn_${NAME}.conf

  # start the vpn service in the jail
  jexec vpn_gw service openvpn_${NAME} onestart

  # add extra static routes
  if [ -f $WD/conf/${NAME}.routes ]; then
    for ROUTE in `cat $WD/conf/${NAME}.routes`; do eval "route add -net ${ROUTE}"; done

elif [ $1 == 'stop' ]; then
  # delete extra static routes
  if [ -f $WD/conf/${NAME}.routes ]; then
    for ROUTE in `cat $WD/conf/${NAME}.routes`; do eval "route del -net ${ROUTE}"; done

  # stop the vpn service
  jexec vpn_gw service openvpn_${NAME} onestop

  # delete interface and the file we saved its name to
  TUN=`cat $WD/${NAME}_tun`
  ifconfig ${TUN} destroy
  rm $WD/${NAME}_tun

exit 0
You do not have the required permissions to view the files attached to this post.

Advanced User
Advanced User
Posts: 286
Joined: 23 Mar 2014 02:58
Location: UK
Status: Offline

Re: [HOWTO] openvpn in jail


Post by cookiemonster »

Thanks for sharing.
Main: Xigmanas x64-full-RootOnZFS as ESXi VM with 24GB memory.
Main Host: Supermicro X8DT3 Memory: 72GB ECC; 2 Xeon E5645 CPUs; Storage: (HBA) - LSI SAS 9211-4i with 3 SATA x 1 TB in raidZ1, 1 x 3 TB SAS drive as single stripe, 3 x 4 TB SAS drives in raidZ1.
Spare1: HP DL360 G7; 6 GB ECC RAM; 1 Xeon CPU; 5 x 500 GB disks on H210i
Backup1: HP DL380 G7; 24 GB ECC RAM; 2 Xeon E5645 CPUs; 8 x 500 GB disks on IBM M1015 flashed to LSI9211-IT

Post Reply

Return to “Jails”