How to setup a VPN server in a FreeNAS jail

This post is not about configuring FreeNAS to connect to a VPN, but about running a VPN server inside FreeNAS, so you will be able to access all your jails and every host on your local (home) network from the outside, using the secure VPN tunnel.

Using a VPN connection is like sending a mail envelope inside another one: the external envelope is addressed to your VPN endpoint (the server), and only the server can extract the internal envelope and process it (i.e., forward it to the specified address) as if it originated locally (thus you can access private addresses on your local network). Replies will be sent back on the tunnel by securely re-encapsulating them in an external envelope.

So, after you are connected to your VPN, you can for example

ssh root@192.168.0.1

(or whatever addresses you are using) through the Internet.


Prepare a new Jail

The VPN server (OpenVPN) will run inside a Jail. I think that this is the cleanest method to create this setup and, in case of problems, you will not mess up your FreeNAS installation. Using VMs (Virtual Machines – similar in concept to jails/containers/zones or whatever) is also a very common approach in administering servers and it is a fundamental block in the IaaS model of cloud computing.

In the web interface of FreeNAS, go to “Jails” and press the “Add Jail” button.

Give it a name, select “standard” as type, assign an IP address (let’s assume 192.168.0.4) and a netmask (assume /24), then be sure that the “autostart” and “VIMAGE” boxes are checked and create the jail (leave everything else as default).

Now that you have the jail, SSH into your FreeNAS box (not to the jail you just created) and do

# jls

you should see the new jail in the output with its JID (first column). Take note of the JID and do (replace <JID> with the ID of the jail):

# jexec <JID> csh

OpenVPN

Install the OpenVPN package with

# pkg install openvpn

Move at the root of the jail and create an openvpn folder where to work on the configuration

# cd /
# mkdir openvpn
# cd openvpn

Copy the easy_rsa folder from the OpenVPN installation to get the scripts to generate the keys

# cp -r /usr/local/share/easy-rsa /openvpn/
# cd easy-rsa

Edit the vars file so you avoid replying to the same configuration questions many times

 # vi vars

(if you don’t feel comfortable with vi, install something else, e.g., nano with “pkg install nano”)

Go to the end of the file and assign values to these variables (the values are not really important in a home setup!)

KEY_COUNTRY=
KEY_PROVINCE=
KEY_CITY=
KEY_ORG=
KEY_EMAIL=
KEY_CN=
KEY_NAME=
KEY_OU=

Now switch to the “sh” shell and generate the keys (note that since “source” is not available, we use the “.” operator to import the vars file into the current shell, do not omit the “.” (dot) at the beginning of the second command of this list!)

When generating the keys, consider using a passphrase, to sign the certificate and, at the end, answer yes to the “commit” question.

# sh
# . vars
# ./clean-all
# ./build-ca
# ./build-key-server <server-name>
# ./build-dh
# openvpn --genkey --secret keys/ta.key

And for each client that will access the vpn

# ./build-key <client-name>

Copy the key folder somewhere else to secure it from ./clean-all commands

# cp -r keys ..
# cd ..

Now we need to configure the OpenVPN server by creating a configuration file. You can copy from this sample and create a local file “server.conf”.

# vi server.conf
# <paste the sample in this file, then save and close>

Read the comments of the variables and change what you need. Approximately these should be the lines that need to be configured, the rest can remain as is, unless you have special needs

# put the IP address of your jail here, we assumed 192.168.0.4
# for this example
local 192.168.0.4
 
# paths of the server certificates and keys
ca /openvpn/keys/ca.crt
cert /openvpn/keys/<server-name>.crt
key /openvpn/keys/<server-name>.key
 
# Diffie Helman key
dh /openvpn/keys/dh1024.pem
 
# Push the route to your local subnet, change address/mask
# as needed
push "route 192.168.0.0 255.255.255.0"

# Use this if you want to route all clients traffic
# through the VPN (we will use ipfw rules later to
# forward this to the correct gateway)
push "redirect-gateway"

# Push a dns server address 
push "dhcp-option DNS 8.8.8.8"

# tls-auth key 
tls-auth /openvpn/keys/ta.key 0

As James (see comments) suggested, if you don’t have the /usr/local/etc/openvpn/ folder or you prefer to consistently keep everything under /openvpn, also specify the path to the log files with these lines:

status /openvpn/openvpn-status.log
ifconfig-pool-persist /openvpn/ipp.txt

Another useful suggestion from James is to set the verbosity level to 0 (default is 3), unless you have specific debug needs:

verb 0

Networking

Now we need to configure the network to make sure that packets are routed correctly. We can do this by creating firewall rules.

First, identify the name of the interface on the local network, i.e., the one which has the 192.168.0.4 address (or the one you used for this setup):

# ifconfig

In my case this was “epair0b”.

Then, create a file for the firewall rules

# vi /usr/local/etc/ipfw.rules

with this content (replace “epair0b” with what you found)

ipfw -q -f flush
ipfw -q nat 1 config if epair0b
ipfw -q add nat 1 all from 10.8.0.0/24 to any out via epair0b
ipfw -q add nat 1 all from any to any in via epair0b

Put everything together

The last step is to tell openvpn and ipfw which configuration files to use and enable the services at boot.

Edit the file /etc/rc.conf and append the following lines

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

Reboot the jail from the web interface to have everything running (check that the network interface name that you wrote in the ipfw.rules file didn’t change name, otherwise update the file with the new name and reboot again).

Port forwarding

If you want to access the VPN from the Internet and you have a home router with NAT (this is highly probable), you will need to forward the VPN port so that those packets will be sent to the jail running the VPN server.

The default port that OpenVPN uses is 1194.

Go to the settings of your home router and forward port 1194 to 192.168.0.4 (or your actual address that you used for the jail).

If you don’t have a fixed public IP address, you should also consider subscribing to a free dynamic DNS service.

Configuring a client

The last step is that of configuring a client and testing the connection to the VPN.

Copy to your computer the following files (use scp or rsync or a usb stick, …)

ca.crt
ta.key
<client-name>.crt
<client-name>.key

Create a vpn-client.conf file with the client sample configuration and change what is needed by reading the comments. If you don’t have any special need, these should be the lines that need editing

# Your server public IP and port. This may be a DDNS or a normal
# IP address in case you have a fixed one from your ISP
remote my-server.ddns.net 1194

# Wireless networks often produce a lot
# of duplicate packets. Set this flag
# to silence duplicate packet warnings.
mute-replay-warnings
 
# Adjust the paths as you need, but it's better to keep them
# absolute
ca /home/vince/.openvpn/ca.crt
cert /home/vince/.openvpn/client.crt
key /home/vince/.openvpn/client.key

# We can use this option to increase our security 
ns-cert-type server
 
# If a tls-auth key is used on the server
# then every client must also have the key.
tls-auth /home/vince/.openvpn/ta.key 1

Now you can try connecting to the VPN using the tools that are available to your OS. On Ubuntu, you will need to install the “network-manager-openvpn” package and then you will be able to configure a VPN from the network manager GUI.

If, even from the local network, the client will be able to establish the connection to the VPN server, then, unless there are other networking issues (e.g., port forwarding on the home router), everything should work even from the outside.

Credits

When facing the need of running a VPN for my FreeNAS box, I have found some very useful resources, consisting mainly on a blog post by Joe Paetzel and a post on the FreeNAS forum by user qwertymodo:

I have put this information together, made some slight changes and tested everything as most carefully as possible to be sure that this setup worked (e.g., Joe was configuring the VPN on the FreeNAS box directly, and not in a jail).

The credits for this post go to the authors of these two great contributions!

Advertisements

42 thoughts on “How to setup a VPN server in a FreeNAS jail

  1. Nice work. A few hiccups I ran into were:

    “The default port that OpenVPN uses is 1174.” should say 1194
    Same here:
    “Go to the settings of your home router and forward port 1174 to 192.168.0.4 (or your actual address that you used for the jail).”

    Also on my install of FreeNAS-9.2.1.8-RELEASE-x64 openvpn service failed to start because /usr/local/etc/openvpn/ did not exists. It stores openvpn-status.log and ipp.txt there. You may want to add the following lines to the server.conf

    status /openvpn/openvpn-status.log
    ifconfig-pool-persist /openvpn/ipp.txt

    Due to the nature of FreeNas you may want to change the log verbosity in the server.conf to the minimum:

    verb 0

  2. I can’t find the file /etc/rc.conf
    Creating the file doesen’t solve my problem.

    I also don’t know how to test if everything works as expected.

    1. What is your problem exactly?

      I don’t remember about rc.conf, but I don’t think I had to create it, I think it should be there on a standard jail.

      To test, if you have a VPN client and it can connect to the VPN, then it means that the basics are working. Then, if you have a computer on another network than your home network and from there you can access the private home network only if you connect to the VPN first, then it definitely works.

    2. Hi Harald,
      I encountered the same issue, did you find a solution ? I know it should be there on a standard jail and I don’t understand why I can’t find it.

  3. This is a great write-up! It was very thorough and easy to follow, I appreciate all of the time you put into making this for everyone. But, I’ve been trying every different kind of setup I can find online and I still can’t get it working. At first I couldn’t even get Openvpn started and after much searching, I found I needed to add: openvpn_dir=”/path to where the keys are stored>” I’m not sure why that needed to be added and why it wasn’t necessary for everyone else, but when I added that, it at least started.
    So next, I tried to connect to the VPN. I already have a DNS account setup and I have the Netgear R7000 with VPN forwarding. I have 1194 on UDP being forwarded and the router has a setting where “Clients will use this VPN connection to access: All sites on the Internet & Home Network, OR Home Network, OR only Auto.” So the router is setup as a 192.168.1.1. on my network and I have the VPN setup using the option of clients will use this VPN connection to access: All sites on the Internet & Home Network. I’m not sure, but I’m thinking this might not be helping my cause and maybe I should setup the port forwarding myself.
    Okay, so on the client machine (Mac) using tunnelblick, I could not get my computer to connect using the client.conf file I made with the certificates. However, the router on the VPN page had a link to download client files AND certificates and it WORKED! As far as I could tell, the .conf file was the exact same as mine except that they specified the encryption. I played around with my .conf file and I could not get it to work. I’m guessing it may come down to the certs, but I don’t know why mine wouldn’t work when using this tutorial. Also, when using the router’s downloaded files, it connects, but I get the warning that my IP didn’t change. I also noticed in the logs that it said there were local and client differences in the TUN and TAP settings, but I had them setup to use the same thing.
    If you’ve made it this far, I appreciate it. This is my first post on any of the forums and I’ve spent the last week trying to get this all to work. If there is any other info I could send to you to help me out, let me know. I also have the FreeNAS configured as a static IP setting of 192.168.1.200 and the openvpn in a jail of 192.168.1.230. I have the DNS of the FreeNAS box pointed at the router, 192.168.1.1 and the router’s DNS pointed at 208.67.222.222 and 208.67.222.220. Thank you again for your help/advice in all of this. I try to read as many posts and research as much as possible, but it’s been a week with no real progress. Thanks again!

  4. 😦

    root@openvpn:/ # service openvpn start
    Starting openvpn.
    Wed Dec 3 19:54:24 2014 cd to ‘/usr/local/etc/openvpn’ failed: No such file or directory (errno=2)
    Wed Dec 3 19:54:24 2014 Exiting due to fatal error
    /usr/local/etc/rc.d/openvpn: WARNING: failed to start openvpn

    Like your guide btw.

    1. From the /usr/local/etc/rc.d/openvpn
      # You also need to set NAME_configfile and NAME_dir, if the configuration
      # file and directory where keys and certificates reside differ from the above
      # settings.

      So :
      echo ‘openvpn_dir=”/openvpn”‘ >> /etc/rc.conf

      And it work from the tutorial here…

  5. I am not sure if I understand your question, if you ask how to go back to shell from a document, then maybe you are stuck in vi? In this case, from “normal mode” (i.e., press “ESC” or “CTRL-C” to go to normal mode), type

    :wq to save and exit
    :q to exit without writing
    :q! to exit and discard changes

  6. Thanks for the guide it was really easy to follow.

    I think I’ve done everything correctly but I can’t seem to connect to my VPN server. The service starts fine, ipfw rules are there and I’ve checked that my domain forwards to the correct port but nothing seems to come up in openvpn-status.log even after increasing verb.

    Any ideas?

    My server is 192.168.1.25 and the jail is 192.168.1.20

    Here are my configs:

    server.conf
    local 192.168.1.20
    port 1194
    proto udp
    dev tun
    ca /openvpn/keys/ca.crt
    cert /openvpn/keys/KrotaxServer.crt
    key /openvpn/keys/KrotaxServer.key
    dh /openvpn/keys/dh1024.pem
    server 10.8.0.0 255.255.255.0
    ifconfig-pool-persist ipp.txt
    push “route 192.168.1.0 255.255.255.0”
    push “redirect-gateway”
    push “dhcp-option DNS 8.8.8.8″
    keepalive 10 120
    tls-auth /openvpn/keys/ta.key 0
    comp-lzo
    persist-key
    persist-tun
    status /openvpn/openvpn-status.log
    ifconfig-pool-persist /openvpn/ipp.txt
    verb 6

    vpn-client.ovpn
    client
    dev tun
    proto udp
    remote xxxxxxxx 1194
    resolv-retry infinite
    nobind
    persist-key
    persist-tun
    ca ca.crt
    cert Guest.crt
    key Guest.key
    ns-cert-type server
    tls-auth ta.key 1
    comp-lzo
    verb 3

    rc.conf
    portmap_enable=”NO”
    sshd_enable=”NO”
    sendmail_enable=”NO”
    sendmail_submit_enable=”NO”
    sendmail_outbound_enable=”NO”
    sendmail_msp_queue_enable=”NO”
    hostname=”VPN”
    devfs_enable=”YES”
    devfs_system_ruleset=”devfsrules_common”
    inet6_enable=”YES”
    ip6addrctl_enable=”YES”
    openvpn_enable=”YES”
    openvpn_if=”tun”
    openvpn_configfile=”/openvpn/server.conf”
    cloned_interfaces=”tun”
    gateway_enable=”YES”
    firewall_enable=”YES”
    firewall_script=”/usr/local/etc/ipfw.rules”
    openvpn_dir=”/openvpn”

    1. Yeah this is fine. I managed to get it working by turning off tls-auth so I guess it’s an issue with this or the key I generated. How risky is this? I don’t have any sensitive information on the server.

      1. I’m happy to hear you solved the issue.

        I use tls-auth, so, in general, “it should work” :D.

        Anyway, tls-auth is something that you may use for extra security (which is always very good), it hardens you against DoS attacks, as non-correctly-signed UDP packets are not taken into account at all.

        If you don’t have sensitive info on the server and it is only for your own private use… but you never know with security :D.

        Something more here: https://openvpn.net/index.php/open-source/documentation/howto.html#security

  7. thanks for your How To.

    But i have one problem.
    connection with my android device works fine, but on my windows laptop not.

    always connection failed.

    any suggestions?

    thanks
    best regards, andi

  8. Hi! Thank you for your post. I got openvpn running inside a jail in freenas. My problem is that everytime that I add/delete a jail or when I reboot the system, the interface gets reassigned randomly (ie, epair1b, epair2b… , etc). Is there a way to declare multiple interfaces in the pf rules or use an operator (ie, epair*b)?

  9. Hi I’m having trouble starting the service
    # service openvpn start

    I’m first receiving this error

    /usr/local/etc/rc.d/openvpn: WARNING: /openvpn/server.conf is not readable.
    /usr/local/etc/rc.d/openvpn: WARNING: failed precmd routine for openvpn

    I created the directory to see if that would help and now I get this:

    env: /etc/rc.d/openvpn: Permission denied

    I appreciate any help to guide me in the right direction.

    1. I restarted from the beginning again, however now I’m getting same error that Dom above was getting:

      service openvpn start
      Starting openvpn.
      Tue Mar 24 10:08:27 2015 cd to ‘/usr/local/etc/openvpn’ failed: No such file or directory (errno=2)
      Tue Mar 24 10:08:27 2015 Exiting due to fatal error
      /usr/local/etc/rc.d/openvpn: WARNING: failed to start openvpn

      I’m not quite sure though what his fix was based on his post. I’m kind of noob at least regarding command line. Can you restate what he did to make it work another way.

      Thanks and thanks again for a great tutorial

  10. first tank for this guide, very usefull.
    I’ve just 1 question, Tun device change his number every time i reboot the jail and openvpn stop working. I need to manually change it in openvpn.conf.
    How can i fixed it?

    1. I haven’t automated this, but yes, there should be no problem in writing a script that runs at startup and writes the content in the configuration file (also in /usr/local/etc/ipfw.rules in case the eth interface name changes).

      I don’t reboot the server so often :).

  11. one last question, now i can connect through VPN my client to server, but i can’t ping and access resource or (for Examle) my transmission webpage. what have i missing?

  12. For android simplicity:
    You can make a pkcs12 file that is kept in the android keystore
    “openssl pkcs12 -export -in .crt -inkey .key -certfile ca.crt -name -out .p12”
    The above puts the key and certs in one file that you may (but are not required to) use a password with.

    Security:
    With the ca.crt in the keystore I think is means that anyone with your ca.key could intercept your data. But if someone gets you ca.key you really messed up in security somewhere.

    The ta.key cannot be kept in the keystore but it can be deleted once imported into OpenVPN.
    All the keys and ovpn (they may have keys) files should be deleted after they are imported into OpenVPN otherwise a malicious app could easily steal the keys.

    1. it didn’t like my formatting…
      “openssl pkcs12 -export -in CLIENT.crt -inkey CLIENT.key -certfile ca.crt -name CLIENT -out CLIENT.p12”

  13. Thank you for this Tutorial, but I’m stuck at the creating of the config file… my shell always crashes if i try to past the example in… and the server is running very very slow now (rebooting doesn’t help)
    anyone that can help me?

    1. You mean the server configuration file?
      Up to that point, the only change that would affect the system would be the installation of openvpn. You could try to remove the package, or destroy the jail and start over again.

      1. I’ll try that tomorrow, I’m pretty new with linux systems so I don’t really know how to work with the #vi and stuff. it seems that when I’m in that mode my keyboard layout is all messed up. Also you talk about save the file but how do I do that? is there a command I have to type? (sorry I’m pretty noob at server systems, but I really wan’t to learn)
        Maybe you can just point me to a guide that can help me?

      2. Oh, yes, vi needs some knowledge to avoid catastrohic results when using it :). You can use “nano” as editor (maybe you need to install it first, I don’t remember is it’s there already), for which you still need to know how to save and exit, but that’s in general more user friendly.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s