Skip to content

Install OpenVPN in FreeNAS 11.1 jail

Install OpenVPN in FreeNAS 11.1 jail has become much easier than it used to be.
This post explains how to do it my way, inspired by the mentioned posts below. I am writing this for my own use, adding some scripts. So I like to share this with the rest of the world.

I will not guarantee that this is the most secure way. But it gets the job done. You are free to use every info in this blog, but don’t come chasing me if it doesn’t work. 🙂

Before I go further I like to give a big thanks to the following people from the FreeNAS community:

robles – Which tutorial I have used lots of times in FreeNAS 9.x installations

Bibi40k – Which has made a tutorial that are more up to date regarding FreeNAS 11.1

Plus the rest of the community in both FreeNAS and FreeBSD.

Requirements for the installation:

  1. FreeNAS 11.1
  2. Root ssh access to the FreeNAS box
  3. Preferable access to Router to do the portforwarding.

Edits: 

  1. 2018-03-27: Found that “comp-lzo” has been deprecated in latest version of OpenVPN and TunnelBlick for Mac. It has been replaced by “compress”.

Start:

Use FreeNAS WebUI to make a jail.
Go to Storage and create a dataset called “Jails”
Go to Jails –> Configuration and set the newly created dataset as jail root.
Click add Jail and give the Jail a name ex. “OpenVPN”
Before clicking OK, push the Advanced Mode button, and give the Jail a IP number, netmask and default gateway according to your LAN network. Click “OK”.

SSH into your FreeNAS box and get the details of the jail

$ jls
JID      IP Address     Hostname          Path 
1                       OpenVPN           /mnt/NaStar/Jails/OpenVPN
$ jexec 1 sh

This takes you into the commandline interface of the Jail.
Start by updating everything in the Jail and install the needed programs. Out of habit I always install tmux.

# pkg update
# pkg upgrade -y
# pkg install -y nano tmux openvpn zip bash

Create directories for OpenVPN, to respect FreeBSD’s structure we will do everything in /usr/local/*

# mkdir -p /usr/local/etc/openvpn/keys

Copy all the files into your newly created folder structure.

# cp /usr/local/share/examples/openvpn/sample-config-files/server.conf /usr/local/etc/openvpn/openvpn.conf
# cp -r /usr/local/share/easy-rsa /usr/local/etc/openvpn/easy-rsa

Lets setup easy-rsa (edit: /usr/local/etc/openvpn/easy-rsa/vars )

# cd /usr/local/etc/openvpn/easy-rsa
# nano vars

Change the following lines to what fits your usecase and uncomment the lines to give it effect.

set_var EASYRSA_REQ_COUNTRY    "US"
set_var EASYRSA_REQ_PROVINCE   "California"
set_var EASYRSA_REQ_CITY         "San Francisco"
set_var EASYRSA_REQ_ORG          "Copyleft Certificate Co"
set_var EASYRSA_REQ_EMAIL        "me@mydomain.com"
set_var EASYRSA_REQ_OU           "My Organizational Unit"
set_var EASYRSA_KEY_SIZE 2048
# The default crypto mode is rsa; ec can enable elliptic curve support.
# Note that not all software supports ECC, so use care when enabling it.
# Choices for crypto alg are: (each in lower-case)
#  * rsa
#  * ec
#set_var EASYRSA_ALGO      rsa
# Define the named curve, used in ec mode only:
#set_var EASYRSA_CURVE      secp384r1
# In how many days should the root CA key expire?
set_var EASYRSA_CA_EXPIRE 3650
# In how many days should certificates expire?
set_var EASYRSA_CERT_EXPIRE 3650

Generate the Keys to be used.

# ./easyrsa.real init-pki
Note: using Easy-RSA configuration from: ./vars
init-pki complete; you may now create a CA or requests.
Your newly created PKI dir is: /usr/local/etc/openvpn/easy-rsa/pki

Build Certificate Authority
The passphrase will be needed to add new users to the OpenVPN server in the future.

# ./easyrsa.real build-ca
Note: using Easy-RSA configuration from: ./vars
Generating a 2048 bit RSA private key
.......................................+++
..+++
writing new private key to '/usr/local/etc/openvpn/easy-rsa/pki/private/ca.key.vpfhw9orph'
Enter PEM pass phrase:Password1
Verifying - Enter PEM pass phrase:CAPassword
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Common Name (eg: your user, host, or server name) [Easy-RSA CA]: OpenVPN FreeNAS CA
CA creation complete and you may now import and sign cert requests.
Your new CA certificate file for publishing is at:
/usr/local/etc/openvpn/easy-rsa/pki/ca.crt

Build Server Certificates

# ./easyrsa.real build-server-full openvpn-server nopass
Note: using Easy-RSA configuration from: ./vars
Generating a 2048 bit RSA private key
...............................................+++
.................................+++
writing new private key to '/usr/local/etc/openvpn/easy-rsa/pki/private/openvpn-server.key.JKfgnZ3Ae8'
-----
Using configuration from /usr/local/etc/openvpn/easy-rsa/openssl-1.0.cnf
Enter pass phrase for /usr/local/etc/openvpn/easy-rsa/pki/private/ca.key:CAPassword
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
commonName :ASN.1 12:'openvpn-server'
Certificate is to be certified until Feb 13 18:22:32 2028 GMT (3650 days)
Write out database with 1 new entries
Data Base Updated

Generate Diffie Hellman Parameters ( /usr/local/etc/openvpn/easy-rsa/pki/dh.pem )

# ./easyrsa.real gen-dh
Note: using Easy-RSA configuration from: ./vars
Generating DH parameters, 2048 bit long safe prime, generator 2
This is going to take a long time
...........................................................................................................
...........................................................................................................
......................................................................................+...................
...........................................................................................................
.............................................................+............................................
...........................................................................................................
.............................+......................................................+...................
.......+.................................................................................................
..........................................................................................................
..............................................................................+..................+.....
...
...................................................................................+....................
.........................................................................................................
.........................................................................................................
...+....................................................................................................
..........+..........................++*++*
DH parameters of size 2048 created at /usr/local/etc/openvpn/easy-rsa/pki/dh.pem

Generate the TA key

# openvpn --genkey --secret ta.key

Copy Keys together

# cp pki/dh.pem pki/ca.crt pki/issued/openvpn-server.crt pki/private/openvpn-server.key /usr/local/etc/openvpn/keys/
# cp ta.key /usr/local/etc/openvpn/keys/

 Setup OpenVPN Server config file ( edit: /usr/local/etc/openvpn/openvpn.conf )

# cd /usr/local/etc/openvpn/
# nano openvpn.conf
# Any X509 key management system can be used.
# OpenVPN can also use a PKCS #12 formatted key file
# (see "pkcs12" directive in man page).
ca /usr/local/etc/openvpn/keys/ca.crt
cert /usr/local/etc/openvpn/keys/openvpn-server.crt
key /usr/local/etc/openvpn/keys/openvpn-server.key # This file should be kept secret
# Diffie hellman parameters.
# Generate your own with:
# openssl dhparam -out dh2048.pem 2048
dh /usr/local/etc/openvpn/keys/dh.pem

Push route to your LAN network, in my case 10.0.10.0

# Push routes to the client to allow it
# to reach other private subnets behind
# the server. Remember that these
# private subnets will also need
# to know to route the OpenVPN client
# address pool (10.8.0.0/255.255.255.0)
# back to the OpenVPN server.
;push "route 192.168.10.0 255.255.255.0"
push "route 10.0.10.0 255.255.255.0"

Setup ta.key in the tls section

# The second parameter should be '0'
# on the server and '1' on the clients.
tls-auth /usr/local/etc/openvpn/keys/ta.key 0 # This file is secret
remote-cert-tls client

Enable compression

# Enable compression on the VPN link and push the
# option to the client (v2.4+ only, for earlier
# versions see below)
compress lz4-v2
push "compress lz4-v2"
# You can uncomment this out on
# non-Windows systems.
user nobody
group nobody

Setup server NAT configuration ( Create /usr/local/etc/ipfw.rules and add teh following text )

#!/bin/sh
EPAIR=$(/sbin/ifconfig -l | tr " " "\n" | /usr/bin/grep epair)
ipfw -q -f flush
ipfw -q nat 1 config if ${EPAIR}
ipfw -q add nat 1 all from 10.8.0.0/24 to any out via ${EPAIR}
ipfw -q add nat 1 all from any to any in via ${EPAIR}

TUN=$(/sbin/ifconfig -l | tr " " "\n" | /usr/bin/grep tun)
ifconfig ${TUN} name tun0

Setup rc.conf file

# nano /etc/rc.conf
openvpn_enable="YES"
openvpn_if="tun"
openvpn_configfile="/usr/local/etc/openvpn/openvpn.conf"
openvpn_dir="/usr/local/etc/openvpn/"
cloned_interfaces="tun"
gateway_enable="YES"
firewall_enable="YES"
firewall_script="/usr/local/etc/ipfw.rules"

Setup Logging ( edit /etc/syslog.conf )

!ppp
*.*                      /var/log/ppp.log
!openvpn
*.*                      /var/log/openvpn.log
!*

Setup log rotation ( edit /etc/newsyslog.conf )

/var/log/weekly.log                 640  5  *   $W6D0 JN
/var/log/xferlog                    600  7  100 *     JC
/var/log/openvpn.log                600  30 *   @T00  ZC

Setup the Clients on the server.
This is done with the following BASH script ( /usr/local/etc/openvpn/adduser.sh )
The script adds the user, pack it as a encrypted zipfile and send it to https://transfer.sh/ here it can be downloaded.

#!/usr/local/bin/bash

###  Change this before deployment
server=<server-IP or Hostname>
port=1194
internalDNS=10.0.10.254
###
if [ $# == 0 ]; then
        echo "Usage: $0 <USER>"
        exit 127
fi

cd /usr/local/etc/openvpn/easy-rsa || exit 0

./easyrsa.real build-client-full "$1"
if [ $? == 1 ]
then 
  echo "see error from easyrsa."
  echo "Aborting..!!!"
  exit 1
fi
clear

cp pki/issued/*.crt/usr/local/etc/openvpn/keys/
cp pki/private/*.key /usr/local/etc/openvpn/keys/

mkdir -p /usr/local/etc/openvpn/users/"$1"

cp /usr/local/etc/openvpn/keys/"$1".crt /usr/local/etc/openvpn/users/"$1"
cp /usr/local/etc/openvpn/keys/"$1".key /usr/local/etc/openvpn/users/"$1"
cp /usr/local/etc/openvpn/keys/ca.crt /usr/local/etc/openvpn/users/"$1"
cp /usr/local/etc/openvpn/keys/ta.key /usr/local/etc/openvpn/users/"$1"

echo "client
dev tun
proto udp
remote "$server" "$port"
resolv-retry infinite
nobind
persist-key
persist-tun
mute-replay-warnings
ca ca.crt
cert "$1".crt
key "$1".key
remote-cert-tls server
tls-auth ta.key 1
cipher AES-256-CBC
verb 3
dhcp-option DNS "$internalDNS"
redirect-gateway def1" >>/usr/local/etc/openvpn/users/"$1"/OpenVPN\ "$1".ovpn

cd /usr/local/etc/openvpn/users/ || exit 0

clear
echo "Provide the password for the zip file:"
zip -er "$1".zip "$1"

clear
echo "Uploading OpenVPN Package to transfer.sh:"
transfer=$(curl --upload-file ./"$1".zip https://transfer.sh/"$1".zip)
clear
echo ""
echo "Copy/paste this link in your browser to download full OpenVPN user packages:"
echo "$transfer"
exit 0

Status Script

Sometimes when you lots of clients using the OpenVPN, its nice to have some kind of status. This can be achieved by looking at the log file in /usr/local/etc/openvpn/openvpn-status.log
This can be a bit confusing for people not used to log files. I have made a small BASH script for this purpose.

#!/usr/local/bin/bash

clear

log=/usr/local/etc/openvpn/openvpn-status.log

cat $log | awk '/OpenVPN CLIENT LIST/,/ROUTING TABLE/' | sed '$d' | sed "s/,/ /g" | sed -n '1p'
#echo " "
cat $log | awk '/OpenVPN CLIENT LIST/,/ROUTING TABLE/' | sed '$d' | sed "s/,/ /g" | sed -n '2p'
echo " "
cat $log | awk '/OpenVPN CLIENT LIST/,/ROUTING TABLE/' | sed '$d' | sed "s/,/                    /g" | sed -n '3p'
echo "------------------------------------------------------------------------------------------------------------------------------------------------"
cat $log | awk '/OpenVPN CLIENT LIST/,/ROUTING TABLE/' | sed '$d' | sed "s/,/                    /g" | sed -e '1,3d'
echo "------------------------------------------------------------------------------------------------------------------------------------------------"
Published inBSDServer Services

6 Comments

  1. FreeNAS Hopeful FreeNAS Hopeful

    I have never really used a command line interface to install something this complex. The instructions might work well for someone that has command line experience, for me there are too many uncertainties to know what needs to be done. I can copy paste the text into Putty just fine, but it is unclear to me when I need to change something, or if there is pre-work to do.
    What do the different colors mean?
    Do I need to go to openVPN and create a login? Do I need to download something from openVPN for it to work?

    • dennis dennis

      I can see that its a mouth full if you are not comfortable in the command line. I recommend spinning up a virtual machine on your own computer with virtual box and start playing around. If you make a bridged network interface you will be able to connect to your VM when you are ready.
      This tutorial is getting a bit old now with the new versions of OpenVPN and EasyRSA, in both applications there have been a lot of deprecated settings and new ways to do stuff in a better way. I will make a new article as soon I have the time to setup a new OpenVPN server.
      btw. the colors are a bit confusing, but to present code in a good way in WordPress this is the best option I have found, if any one out there has a better solution I am all ears. 🙂

  2. Ruud Ruud

    Thank Dennis. good writeup.
    I’m almost there – I think.

    With the current versions of the FreeNAS 11.2 and openVPN2.4.7:

    for the adduser.sh script it is necessary to install the curl package:
    pkg install -y curl

    in the adduser.sh script change the following line
    cp /usr/local/etc/openvpn/keys/”$1″.crt /usr/local/etc/openvpn/users/”$1″
    to
    cp /usr/local/etc/openvpn/easy-rsa/pki/issued/”$1″.crt /usr/local/etc/openvpn/users/”$1″

    • Dennis Dennis

      Thanks for the changes, I will try and find the time to go over it all again and make some updates to it. I have recently changed job, so I have been out of the loop for a while. 🙂

  3. Fotes Lykos Fotes Lykos

    I am having an issue creating a jail in freenas 11. I tried using both the new and legacy interfaces and they are generating errors. freenas 11 is giving me The jail dataset was created on a share. error. I followed the instructions about creating a dataset. The new interface gives me an error in selecting the release. the error is Error: Displaying local fetched releases failed. Please help

    • Dennis Dennis

      This write up is a bit old, but the jail creation in FreeNAS is still a breeze. I use it all the time, so i recommend that you go over the initial setup in FreeNAS. Use the FreeNAS documentation, it is supreme.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.