Enable Multi-Factor Authentication for OpenVPN


Google Authenticator and OpenVPN

Google Authenticator and OpenVPN

In my previous post, we went over how to get Google Authenticator installed on FreeNAS.  Then we setup SSH to use it.  In this guide, we’ll get Multi-Factor Authentication working for OpenVPN.  This guide will be specific to FreeNAS, but should be applicable to FreeBSD as well.

Part I

Get Google Authenticator installed and setup for users

Go see my previous guide on getting Google Authenticator installed.

Part II

Configure OpenVPN to use both certificates and an OTP (one time password) provided by Google Authenticator.

1. Open a terminal either through the GUI or ssh.

2. Switch user to root.

 su
 enter root password

3. Mount the file system and make it writeable

 mount -uw /

4. First we need to create an entry for openvpn under /etc/pam.d This will tell OpenVPN that authentication with the pam_google_authenticator.so module is required.  Also need to remember to copy this file to /conf/base/etc/pam.d so that our change will survive a reboot.

touch /etc/pam.d/openvpn

printf "auth required /usr/local/lib/pam_google_authenticator.so" >> /etc/pam.d/openvpn

cp /etc/pam.d/openvpn /conf/base/etc/pam.d/openvpn

5. Check to make sure the permissions are correct on the pam_google_authenticator.so module.  sshd doesn’t seem to care, but OpenVPN does seem to care.  Side note, there are several guides written for Linux that say you have to modify the MakeFile with LDFLAGS=”-lpam” when building the pam_google_authenticator.so module.  That is NOT the case in FreeNAS / FreeBSD as the port takes care of that.

chmod 555 /usr/local/lib/pam_google_authenticator.so

6. Now we need to add a few settings to our OpenVPN server config.  If you followed my guide on setting up OpenVPN on FreeNAS, your server config is on your data drive.  Change the part after the “>>” to match your setup.

printf "\n#Enable Multi-Factor Authentication\n" >> /mnt/Files/openvpn/openvpn.conf

printf "plugin /usr/local/lib/openvpn/plugins/openvpn-plugin-auth-pam.so openvpn\n\n" >> /mnt/Files/openvpn/openvpn.conf

printf "#Prevent re-authorization every 3600 seconds\n" >> /mnt/Files/openvpn/openvpn.conf

printf "reneg-sec 0\n\n" >> /mnt/Files/openvpn/openvpn.conf

7. Now, on your client computers, you need to add the following to your openvpn-client config.  You can just add it at the bottom.

#Add this to the client config to enable Multi-Factor Authentication
auth-user-pass

#Prevent the password file from being cached
auth-nocache

8. Now restart openvpn on your FreeNAS box.

service openvpn restart

Your output should look like this:

Stopping openvpn.
Waiting for PIDS: 494.
Starting openvpn.
AUTH-PAM: BACKGROUND: INIT service='openvpn'
add net 10.8.0.0: gateway 10.8.0.2

9. Make the filesystem read only again.

mount -ur /

10. Fire up your VPN connection on a client computer and you should get a field that asks for a username and password in order to connect.

Tunnelblick

 

You will put in your user name for one of the accounts you set up using the google-authenticator command on your FreeNAS server.  The password will just be the 6 digit OTP you get from the Google Authenticator App on your smart phone.  Don’t bother saving it in the keychain.  If everything goes right, you will connect and then see this in your terminal session:

AUTH-PAM: BACKGROUND: received command code: 0
AUTH-PAM: BACKGROUND: USER: joe
AUTH-PAM: BACKGROUND: my_conv[0] query='Verification code: ' style=1

Part III

Questions and such…

We’ve done it.  We now have multi-factor authentication setup for our VPN.  I’m left wondering though.  Many of the guides I looked at related to this subject said that /etc/pam.d/openvpn needed a lot more in it that what I have used.  For instance, one guide over at askubuntu.com says to use this:

account [success=2 new_authtok_reqd=done default=ignore] pam_unix.so
account [success=1 new_authtok_reqd=done default=ignore] pam_winbind.so
account requisite pam_deny.so
account required pam_permit.so
auth required pam_google_authenticator.so

Is all of that account stuff really needed?  My hunch is that it is not.  If you have any insight, please share it in the comments section.

Advertisement

FreeNAS – getting hacks to survive an upgrade Part 2


***WARNING***

THIS DOES NOT MEAN YOU GET TO SHUT YOUR BRAIN OFF.  UPGRADING FREENAS COULD STILL RENDER YOUR CHANGES NULL AND VOID.  AFTER ANY FREENAS UPGRADE, VERIFY THAT YOUR CHANGES ARE STILL IN EFFECT EVEN WITH THIS STICKY HACK IN PLACE.

Part 1 of trying to get hacks to FreeNAS to survive an upgrade was a failure.  But never fear, I went back to the drawing board and had great success tonight. Basically I changed my approach slightly,  Instead of trying to make changes to /conf/base/etc/rc.conf , what ended up working was just making the changes to /etc/rc.conf on every boot.

This will have the added benefit of working even if the FreeNAS developers change their naming scheme again for things in /conf/base/etc.

Write our hacks.sh script

1. I have OpenVPN and pf Firewall enabled, neither of which are stock to FreeNAS.  You’ll need to adjust this script to meet your needs.  Open up your favorite text editor and save your hacks.sh file somewhere on your data drive on the FreeNAS box.

First thing is lets search /etc/rc.conf to see if our hacks are in place.  If they are, we exit.

#!/bin/sh
if grep "pf_enable" /etc/rc.conf
then
echo "Hacks in Place"
else

Now, the else section is where we add our hacks back in to /etc/rc.conf when they are not there.  I’m just using a simple echo command to write the line I want to add to the shell and then am adding it to the end of /etc/rc.conf.  I’m adding a blank line before my hacks, some notes about the hacks I’m adding and the config changes.  You will need to change the paths to pf_rules, openvpn_configfile and openvpn_dir to match your setup.

echo "" >> /etc/rc.conf
echo "#Turn on PF Firewall" >> /etc/rc.conf
echo "pf_enable='YES'" >> /etc/rc.conf
echo "pf_rules='/mnt/Files/joe/hacks/pf.conf'" >> /etc/rc.conf
echo "gateway_enable='YES'" >> /etc/rc.conf
echo "" >> /etc/rc.conf
echo "#Turn on OpenVPN" >> /etc/rc.conf
echo "openvpn_enable='YES'" >> /etc/rc.conf
echo "openvpn_if='tun'" >> /etc/rc.conf
echo "openvpn_configfile='/mnt/Files/openvpn/openvpn.conf'" >> /etc/rc.conf
echo "openvpn_dir='/mnt/Files/openvpn'" >> /etc/rc.conf

Next we want to start the services that we have added as hacks to FreeNAS.  For me that is pf and openVPN.  Last thing is to close out the if statement with fi.

service pf start
service openvpn start
fi

Here’s the full script.

#!/bin/sh
if grep "pf_enable" /etc/rc.conf
then
echo "Hacks in Place"
else
echo "" >> /etc/rc.conf
echo "#Turn on PF Firewall" >> /etc/rc.conf
echo "pf_enable='YES'" >> /etc/rc.conf
echo "pf_rules='/mnt/Files/joe/hacks/pf.conf'" >> /etc/rc.conf
echo "gateway_enable='YES'" >> /etc/rc.conf
echo "" >> /etc/rc.conf
echo "#Turn on OpenVPN" >> /etc/rc.conf
echo "openvpn_enable='YES'" >> /etc/rc.conf
echo "openvpn_if='tun'" >> /etc/rc.conf
echo "openvpn_configfile='/mnt/Files/openvpn/openvpn.conf'" >> /etc/rc.conf
echo "openvpn_dir='/mnt/Files/openvpn'" >> /etc/rc.conf
service pf start
service openvpn start
fi

Save it and exit.

2. Now we need to make our hacks.sh script executable and make it owned by root for good measure.  Make sure to change the path below to match your setup.

chmod 700 /mnt/Files/joe/hacks/hacks.sh
chown root /mnt/Files/joe/hacks/hacks.sh

Set up the FreeNAS GUI to run hacks.sh as an init script.

3. Log into the FreeNAS gui and go to System > Init/Shutdown Scripts.  Then click add Init/Shutdown Script

Screen Shot 2014-03-09 at 10.30.47 PM

You want to select script in the first field.  Browse to your hacks.sh script and select it in the second field and select Post Init in the third field.

Screen Shot 2014-03-09 at 10.31.06 PM

Hit OK.

4. Reboot and watch the magic.

Verification

5. After you’ve rebooted, check the status of your hacks.

service openvpn status

You should get this if you are running openVPN

openvpn is running as pid 17535.

service pf status

You should get this if you are running pf.  Notice that is says enabled.

No ALTQ support in kernel
ALTQ related functions disabled
Status: Enabled for 5 days 00:16:00           Debug: Urgent

State Table                          Total             Rate
current entries                       21
searches                      1236116133         2855.0/s
inserts                            75627            0.2/s
removals                           75649            0.2/s
Counters
match                            2299524            5.3/s
bad-offset                             0            0.0/s
fragment                               0            0.0/s
short                                  0            0.0/s
normalize                              0            0.0/s
memory                                 0            0.0/s
bad-timestamp                          0            0.0/s
congestion                             0            0.0/s
ip-option                          28950            0.1/s
proto-cksum                            0            0.0/s
state-mismatch                     94319            0.2/s
state-insert                           0            0.0/s
state-limit                            0            0.0/s
src-limit                             15            0.0/s
synproxy                               0            0.0/s

Final Thoughts

I set this up and tested it in a VM that started out as FreeNAS 9.2.0.  After setting this all up, I did a system upgrade using the GUI and upgraded to 9.2.1.2.  After rebooting, I checked /etc/rc.conf and my changes were in fact still there.  I then checked to see if pf and openVPN were running and they were.  SUCCESS!!!

I hope you all enjoy this.  Let me know of all the great ways you find to use this.

Secure FreeNAS 9.2.1.2 with a Firewall


The recent NTP reflection incident I was a victim of woke me up to the need for securing my FreeNAS boxes from outside connections.  Luckily, FreeNAS 9.2.1.2 comes shipped with the kernel extension for pf, so getting it working is pretty easy.

If you are going to do this on your FreeNAS box, please also check out my guide on getting hacks to FreeNAS to survive system upgrades.

DISCLAIMER – I AM NOT A SECURITY EXPERT, FOLLOW THIS GUIDE AT YOUR OWN RISK

I’ve been told that pf does not play nice with vimage jails.  It tends to cause kernel panics.

Get the basics done

1. Mount the filesystem so we can make some changes.

su
enter your root password
mount -uw /

2. Figure out what interfaces you have active so we can add them to the firewall rules.

ifconfig

Your output should look something like this:

re0: flags=8943<up,broadcast,running,promisc,simplex,multicast> metric 0 mtu 1500
options=82099<RXCSUM,VLAN_MTU,VLAN_HWTAGGING,VLAN_HWCSUM,WOL_MAGIC,LINKSTATE>
ether f4:6d:04:db:21:ba
inet 192.168.0.10 netmask 0xffffff00 broadcast 192.168.0.255
inet6 xxxx::xxxx:xxxx:xxxx:xxxx%re0 prefixlen 64 scopeid 0x6
inet xxx.xxx.xxx.xxx netmask 0xfffffff8 broadcast 50.241.46.71
nd6 options=23<performnud,accept_rtadv,auto_linklocal>
media: Ethernet autoselect (1000baseT )
status: active

ipfw0: flags=8801<up,simplex,multicast> metric 0 mtu 65536
nd6 options=9<performnud,ifdisabled>

lo0: flags=8049<up,loopback,running,multicast> metric 0 mtu 16384
options=600003<RXCSUM,TXCSUM,RXCSUM_IPV6,TXCSUM_IPV6>
inet6 ::1 prefixlen 128
inet6 fe80::1%lo0 prefixlen 64 scopeid 0xa
inet 127.0.0.1 netmask 0xff000000
nd6 options=21<performnud,auto_linklocal>

bridge0: flags=8843<up,broadcast,running,simplex,multicast> metric 0 mtu 1500
ether 02:df:7f:1c:ff:00
nd6 options=1
id 00:00:00:00:00:00 priority 32768 hellotime 2 fwddelay 15
maxage 20 holdcnt 6 proto rstp maxaddr 2000 timeout 1200
root id 00:00:00:00:00:00 priority 32768 ifcost 0 port 0
member: epair0a flags=143<learning,discover,autoedge,autoptp>
ifmaxaddr 0 port 12 priority 128 path cost 2000
member: re0 flags=143<learning,discover,autoedge,autoptp>
ifmaxaddr 0 port 6 priority 128 path cost 20000

epair0a: flags=8943<up,broadcast,running,promisc,simplex,multicast> metric 0 mtu 1500
options=8<VLAN_MTU>
ether 02:09:09:00:0c:0a
nd6 options=1
media: Ethernet 10Gbase-T (10Gbase-T )
status: active

tun0: flags=8051<up,pointopoint,running,multicast> metric 0 mtu 1500
options=80000<LINKSTATE>
inet 10.8.0.1 –> 10.8.0.2 netmask 0xffffffff nd6 options=1
Opened by PID 17528

What we want to note are all the interface names.  Mine are re0, ipfw0, lo0, bridge0, epair0a and tun0

Create the firewall rules

3. Create the pf.conf file and edit it to your needs.  We are going to put it on our data drive so future FreeNAS upgrades don’t wipe it out. Adjust the path to match your setup.

mkdir /mnt/Files/hacks
vi /mnt/Files/hacks/pf.conf

Side note, vi has lots of commands, we just need to know a few:

x will delete the character your cursor is over, i will insert, esc will exit insert mode and to save and quit we use :wq

Here are the rules I am running.

#change this to match your primary ethernet interface, re0 or em0 are common, but there are others
ext_if="re0"
vpn_if="tun0"
table <bruteforce> persist
#These are all of the other interfaces we discovered in step 2
set skip on lo0
set skip on bridge0
set skip on ipfw0
set skip on epair0a
set skip on tun0
set block-policy return
scrub in all
#change xxx.xxx.xxx.xxx to the external IP of your FreeNAS box
nat on $ext_if from 10.8.0.0/24 to any -> xxx.xxx.xxx.xxx
#Lock it down
block in all
block out all
#Allow VPN traffic
pass on tun0 keep state
block quick from <bruteforce>
#Allow traffic in for ssh
pass in on $ext_if proto tcp from any to any port 22 flags S/SA keep state (max-src-conn 10, max-src-conn-rate 5/5, overload <bruteforce> flush global)
#Allow traffic in for web - delete or comment out if you don't want web traffic
pass in on $ext_if proto tcp from any to any port 80 flags S/SA keep state
pass in on $ext_if proto tcp from any to any port 443 flags S/SA keep state
#Allow traffic in for OpenVPN
pass in on $ext_if proto udp from any to any port 1194 keep state label "openvpn"
#Allow LAN traffic to connect to FreeNAS - change xxx.xxx.xxx.0 to match your network, ie 192.168.0.0 or 10.0.0.0
pass in on $ext_if from xxx.xxx.xxx.0/24 to any keep state
#Allow traffic out from the LAN
pass out on $ext_if from any to any keep state

Enable the Firewall

4. Edit /etc/rc.conf and add the following.

vi /etc/rc.conf

pf_enable="YES"
pf_rules="/mnt/Files/hacks/pf.conf"
gateway_enable="YES"

5. Start up the firewall and see if it works

service pf start

Your should get this as your output:

Enabling pf
No ALTQ support in kernel
ALTQ related functions disabled

Now check to make sure it is working:

service pf status

Your output should be something like this:

No ALTQ support in kernel
ALTQ related functions disabled
Status: Enabled for 0 days 00:04:55           Debug: Urgent

State Table                          Total             Rate
current entries                       29
searches                         1040038         3525.6/s
inserts                               95            0.3/s
removals                             109            0.4/s
Counters
match                               1093            3.7/s
bad-offset                             0            0.0/s
fragment                               0            0.0/s
short                                  0            0.0/s
normalize                              0            0.0/s
memory                                 0            0.0/s
bad-timestamp                          0            0.0/s
congestion                             0            0.0/s
ip-option                             22            0.1/s
proto-cksum                            0            0.0/s
state-mismatch                         0            0.0/s
state-insert                           0            0.0/s
state-limit                            0            0.0/s
src-limit                              0            0.0/s
synproxy                               0            0.0/s

6. Start IP Forwarding without restarting your server

sysctl net.inet.ip.forwarding=1

Then make sure to go into the FreeNAS gui, click on System, Click on Sysctls.  Then add that same value so it survives reboots.

Screen Shot 2014-05-14 at 10.43.22 AM

Make your changes stick

7.  Add your rc.conf changes to /conf/base/etc/rc.conf

vi /conf/base/etc/rc.conf

pf_enable="YES"
pf_rules="/mnt/Files/hacks/pf.conf"
gateway_enable="YES"

To really make these changes stick, follow my guide on the subject.

Clean Up

8. Make the filesystem read only again

mount -ur /

Final Thoughts

An added benefit of setting up a firewall this way is that it will let you route to other computers on your LAN over your VPN.  Hope you all enjoy this and let me know how things work out for you.

OpenVPN on FreeNas 9.1


Back in July of 2012 I posted a write up on how to get OpenVPN running on FreeNas 8.2.  That write up was really just notes to myself and I never really thought it would get much attention.  Over the last year, it has seen enough traffic that I thought it deserved a re-write to try and make it easier to follow.  So, here goes.

As always, if you find this super useful, I wouldn’t turn down paypal donations.

If you are going to do this on your FreeNAS box, please also check out my guide on getting hacks to FreeNAS to survive system upgrades.

Dynamic DNS

If you don’t have a static ip address, lets start by setting up a Dynamic DNS entry.  There are several service providers that offer free dynamicDNS service…currently FreeNas supports: dyndns.org, freedns.afraid.org, zoneedit.com, no-ip.com, easydns.com and 3322.org.  So, pick one, set up an account, configure your FreeNas gui to use it in the services panel and then come back.

Port Forwarding on your Router

Next you’ll need to forward UDP port 1194 on your router to your FreeNAS box.  You’ll need to do a little google searching if you don’t know how to do that on your specific router.  Generally it involves logging into the web interface on the router, going to the advanced section and looking for something that sounds like port forwarding.

OpenVPN

Server Certificates – OpenSSL

You can configure OpenVPN for password authorization, but I really don’t like that method.  So I’ll tell you how to set it up with certificate authorization.  Easy-RSA is included in FreeNas 9.1 and later.  You can find it here: /usr/local/share/easy-rsa . If you don’t want to download my sample files or if you don’t trust me, then you should skip step 2 below and use the Easy-RSA files at /usr/local/share/easy-rsa and then also create your config files from scratch.

So, lets get started.

1. Mount the filesystem so we can make some changes.

su
enter your root password
mount -uw /

2. Now, download my openvpn.tar into the root of your data drive, so for me /mnt/Files. 

cd /mnt/Files
wget --no-check-certificate https://www.dropbox.com/s/14h2j1zslozotx8/openvpn.tar

tar -xvf openvpn.tar
cd openvpn

3. Now we need to create our CA.cert

chmod -R 755 easy-rsa/2.0/*
cd easy-rsa/2.0
sh
. ./vars
./clean-all
./build-ca

Your output from ./build-ca should look like this.  Answer the questions with the appropriate answers.

Generating a 1024 bit RSA private key

...++++++....................................++++++
writing new private key to 'ca.key'
-----
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.
-----
Country Name (2 letter code) [BG]:
State or Province Name (full name) [Sofia]:
Locality Name (eg, city) [Sofia]:
Organization Name (eg, company) [example.org]:
Organizational Unit Name (eg, section) [ ]:
Common Name (eg, your name or your server's hostname) [openvpn.example.org CA]:openvpn.example.org
Name [ ]:daemon
Email Address [admin@example.org]:
 

4. Now, we want to create a server key.

./build-key-server server

Your output from ./build-key-server should look like this.  Answer the questions with the appropriate answers.

Generating a 1024 bit RSA private key
.......++++++..........................................++++++
writing new private key to 'server.key'
-----
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.
-----
Country Name (2 letter code) [US]:
State or Province Name (full name) [MN]:
Locality Name (eg, city) [Coon Rapids]:
Organization Name (eg, company) [ ]:
Organizational Unit Name (eg, section) [ ]:
Common Name (eg, your name or your server's hostname) [server]:
Name [ ]:
Email Address [me@myhost.mydomain]:
Please enter the following 'extra' attributes to be sent with your certificate request
A challenge password [ ]:
An optional company name [ ]:
Using configuration from /mnt/Files/openvpn/easy-rsa/2.0/openssl.cnf
Check that the request matches the signature
Signature ok The Subject's Distinguished Name is as follows
countryName : PRINTABLE:'US'
stateOrProvinceName : PRINTABLE:'MN'
localityName : PRINTABLE:'Coon Rapids'
organizationName : PRINTABLE:''
commonName : PRINTABLE:'server'
emailAddress : IA5STRING:'me@myhost.mydomain'
Certificate is to be certified until Sep 20 18:43:20 2023 GMT (3650 days)
Sign the certificate? [y/n]:y
1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated

5. Now let’s create the Diffie-Hellman parameters:

./build-dh

Generating DH parameters, 1024 bit long safe prime, generator 2
This is going to take a long time
………………………………………………………………………………+………………………………………………………………………….+…………………………………………………………………………………………++*++*++*

6. Now we might as well generate a client key.

./build-key joe.paetzel

Your output should look like this:

Generating a 1024 bit RSA private key
……………………………..++++++………++++++
writing new private key to ‘joe.paetzel.key’
—–
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.
—–
Country Name (2 letter code) [US]:
State or Province Name (full name) [MN]:
Locality Name (eg, city) [Coon Rapids]:
Organization Name (eg, company) [ ]:
Organizational Unit Name (eg, section) [ ]:
Common Name (eg, your name or your server’s hostname) [joe.paetzel]:
Name [ ]:
Email Address [me@myhost.mydomain]:

Please enter the following ‘extra’ attributes
to be sent with your certificate request
A challenge password [ ]:
An optional company name [ ]:
Using configuration from /mnt/Files/openvpn/easy-rsa/2.0/openssl.cnf
Check that the request matches the signature
Signature ok
The Subject’s Distinguished Name is as follows
countryName : PRINTABLE:’US’
stateOrProvinceName : PRINTABLE:’MN’
localityName : PRINTABLE:’Coon Rapids’
organizationName : PRINTABLE:”
commonName : PRINTABLE:’joe.paetzel’
emailAddress : IA5STRING:’me@myhost.mydomain’
Certificate is to be certified until Sep 20 19:03:19 2023 GMT (3650 days)
Sign the certificate? [y/n]:y
1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated

7. Now we can get out of the sh shell and move the keys and certificates into their place.

exit
cp -R keys ../../

On my system, the place I want the certs and keys is /mnt/Files/openvpn/keys , I’m using shorthand above to backout two directories and place the keys folder there.  So, the long hand version would be:

cp -R  /mnt/Files/openvpn/easy-rsa/2.0/keys /mnt/Files/openvpn/

The reason we want the keys and config file on the data drive instead of the OS drive is FreeNas upgrades will wipe out our OpenVPN setup if we have everything installed on the OS drive.

Server Configuration File

1. Next we can create the openvpn.conf config file and edit it for our specific setup.  If you didn’t download the openvpn.tar file from me, then you will need to create a openvpn.conf file from scratch.  If you did download the openvpn.tar file, I’ve included a couple of Bare Bones sample configs.

cp BareBones_Server.conf.sample openvpn.conf
chmod 440 openvpn.conf
vi openvpn.conf

Side note, vi has lots of commands, we just need to know a few:

x will delete the character your cursor is over, i will insert, esc will exit insert mode and to save and quit we use :wq

You should get this on your screen:

# Sample OpenVPN 2.0 config file for
# multi-client server.

#replace x.x.x.x with freenas ip
local x.x.x.x
port 1194
proto udp
dev tun
topology subnet
#change the paths and filenames below to match what you did
ca /mnt/Files/openvpn/keys/ca.crt
cert /mnt/Files/openvpn/keys/server.crt
key /mnt/Files/openvpn/keys/server.key
dh /mnt/Files/openvpn/keys/dh1024.pem
server 10.8.0.0 255.255.255.0
ifconfig-pool-persist ipp.txt
#change x.x.x.x to match your network ip range
#ie 192.168.0.0 or 10.0.0.0
push “route x.x.x.x 255.255.255.0”
#replace x.x.x.x with freenas ip
route x.x.x.x 255.255.255.0 10.8.0.1
keepalive 10 120
comp-lzo
persist-key
persist-tun
verb 3

We need to make a few changes to match our specific needs.

Change local x.x.x.x to the ip of your FreeNas box:

local 192.168.0.121

Check that your certs and keys match the lines here:

ca /mnt/Files/openvpn/keys/ca.crt
cert /mnt/Files/openvpn/keys/server.crt
key /mnt/Files/openvpn/keys/server.key
dh /mnt/Files/openvpn/keys/dh1024.pem

Change push “route x.x.x.x 255.255.255.0” to match your network setup:

push “route 192.168.0.0 255.255.255.0”

Change route x.x.x.x 255.255.255.0 10.8.0.1 to have the ip of your FreeNas box:

route 192.168.0.121 255.255.255.0 10.8.0.1

hit the ESC key, then type :wq to save and quit out of vi.

2. Now lets add a few things to rc.conf so we can start openvpn.

vi /etc/rc.conf

Add the following lines making sure that the openvpn_configfile is pointing to your config file location:

openvpn_enable=”YES”
openvpn_if=”tun”
openvpn_configfile=”/mnt/Files/openvpn/openvpn.conf”
openvpn_dir=”/mnt/Files/openvpn”

We also need to make these same changes to /conf/base/etc/rc.conf so they survive a restart.

vi /conf/base/etc/rc.conf

Again, add the following:

openvpn_enable=”YES”
openvpn_if=”tun”
openvpn_configfile=”/mnt/Files/openvpn/openvpn.conf”
openvpn_dir=”/mnt/Files/openvpn”

Cross Your Fingers and Fire It Up

1. Now we should be able to start the OpenVPN server.

service openvpn start

You should get something like this:

Starting openvpn.
route: writing to routing socket: File exists
add net 192.168.0.121: gateway 10.8.0.1: route already in table
add net 10.8.0.0: gateway 10.8.0.2

Clean Up

1. Make the filesystem read only again:

mount -ur /

2. Delete openvpn.tar

rm /mnt/Files/openvpn.tar

Set Up Your Client

1. Copy your client key(s), client crt(s) and ca.crt to the client computer you will be using to connect to the server.  There are a bunch of ways you could do this, I just copied them to a shared folder on my FreeNas box and moved them from there onto my client computer.

2. Create a client config file.  I’ve included a sample Bare Bones config for you to modify in the openvpn.tar file.  It will look something like this:

# Sample client-side OpenVPN 2.0 config file #
client
dev tun
proto udp
#change remote to your static ip
#or domain name for your freenas server
remote something.dyndns.org 1194
resolv-retry infinite
nobind
persist-key
persist-tun
ca /Path/to/Some-ca.crt
cert /Path/to/laptop.crt
key /Path/to/laptop.key
ns-cert-type server
comp-lzo

You need to change the line remote something.dyndns.org 1194 to either your public static ip of your router or a dynamic or static domain name.  You also need to change the ca, cert and key lines to the path of where those files will live on the client.

On OS X using Tunnelblick as the client application those paths will look something like this:

ca /Users/joe/Library/Application\ Support/Tunnelblick/Configurations/ca.crt
cert /Users/joe/Library/Application\ Support/Tunnelblick/Configurations/joe.paetzel.crt
key /Users/joe/Library/Application\ Support/Tunnelblick/Configurations/joe.paetzel.key

Wrapping It Up

With all of that, you should be good to go.  I’ve tried to be as clear and accurate as possible.  I hope you all enjoy the rewrite.

Also, check out my writeup on setting up a firewall on FreeNAS.  It will help you get routing working properly so you can reach all the devices on your LAN over the VPN. https://joepaetzel.com/2014/03/04/secure-freenas-9-2-1-2-with-a-firewall/

Also, if you want to add an additional layer of security, check out my guide on getting OpenVPN working with Google Authenticator.

As always, donations are welcome via paypal.

If you are going to do this on your FreeNAS box, please also check out my guide on getting hacks to FreeNAS to survive system upgrades.

FreeNas – recovering from an upgrade that wipes out OpenVPN


Upgraded a couple of my FreeNas servers from 8.3.0 to 8.3.0 p1 last night.  That part went great.  What didn’t work as well is when I got to work today and tried to connect to the VPN on one of them.  Seems that the bone-head in me forgot that upgrading the FreeNas OS would wipe out the modifications to rc.conf to start OpenVPN as well as wipe out the entire /usr/local/etc/openvpn directory with all of the keys and openvpn configuration in it.

The nice folks over at FreeNas.org have anticipated me being a doof and created the upgrade process such that the old OS is preserved.  You can easily roll back to that if you are infront of your server by rebooting and hitting F2 (possibly F1) at the boot loader.

My problem was I wasn’t infront of my server and needed the VPN up ASAP.  So, I reached out to my big brother (Josh Paetzel) and magically the answer appeared in my inbox.

  1. ssh into the server.
  2. su to root
  3. mount
  4. You are looking for this “/dev/ufs/FreeNASs2a on / (ufs, local, read-only)”If it says that, then your old install is /dev/ufs/FreeNASs1a, if it says FreeNASs1a then the old install is FreeNASs2a
  5. Either way, mkdir /mnt/oldinstall
  6. mount /dev/ufs/FreeNASs1a /mnt/oldinstall 
  7. or mount /dev/ufs/FreeNASs2a /mnt/oldinstall
  8. ls /mnt/oldinstall/conf/base/etc/local/openvpn
  9. mount -uw /
  10. cp -r /mnt/oldinstall/conf/base/etc/local/openvpn /conf/base/etc/local/.
  11. grep openvpn /mnt/oldinstall/conf/base/etc/rc.conf >> /conf/base/etc/rc.conf
  12. Either reboot or repeat steps 10 and 11 replacing /conf/base/… with /etc/rc.conf and /usr/local/etc/openvpn

A great big thanks to Brother Josh on this one.  Always there saving me from myself.  Hope this helps someone else in some way, shape or form.

OpenVPN on FreeNAS 8.2


This article is no longer current, please go here for an updated writeup on OpenVPN on FreeNas

So I’ve been playing around with FreeNAS 8.2.  Decided it would be handy to have OpenVPN running on the fileserver so my wife and I can get to our files if we are away from home.  There are a couple of tricks that I discovered along the way to get this to work right.

***Make sure to read the comments as there are sample configs and a bunch of other useful stuff down there!!!***

If you find this super useful, I wouldn’t turn down paypal donations.

First the easy stuff.  We don’t have a static public IP, so I needed to set up a DynDNS account.  Once I did that, I configured the Dynamic DNS service on the FreeNAS box with my DynDNS account info.  Then started the service.

Next I needed to forward port 1194 on my gateway to the FreeNAS box.  So now I have a domain name to use and a port that forwards to my file server.

FreeNAS 8.2 has OpenVPN built in.  The config files that we need to be concerned with are:

/conf/base/etc/rc.conf
/conf/base/etc/local/openvpn

The thing about /conf/base/etc/local/etc/openvpn is that you need to create it.  Inorder to do that, you need to make the filesystem writeable.

mount -uw /
mkdir /conf/base/etc/local/openvpn

There is a really good tutorial on setting up OpenVPN here.  It goes through all the steps of generating your certificates, setting up your config files and the like. But pay no attention to the Adding routes to the OpenVPN server over at http://www.unix-heaven.org/node/47. The push route and route entries you enter below will handle that.

When you get to the point of configuring the /conf/base/etc/local/etc/openvpn/openvpn.conf file you’ll need to make a bit of a tweak from the norm to get things to work.  Here’s an excerpt of what was needed. You can find my full server and client configs in the comments below.

# 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.0.0 255.255.255.0"
route 192.168.0.100 255.255.255.0 10.8.0.1

The “special” part is the route line. route (freeNAS-IP) subnet-mask 10.8.0.1
You’ll have to change the push “route” to match your network ip ranges too.

If you don’t make that entry, you’ll get an error like this in your server log:

OpenVPN ROUTE: OpenVPN needs a gateway parameter for a –route option and no default was specified by either –route-gateway or –ifconfig options
OpenVPN ROUTE: failed to parse/resolve route for host/network

Now add this to the end of /conf/base/etc/rc.conf

openvpn_enable="YES"
openvpn_if="tun"
openvpn_configfile="/usr/local/etc/openvpn/openvpn.conf"

If you make your config changes directly to /etc/rc.conf or /usr/local/etc/openvpn they will get blown away on restarts. So, now you should be able to restart your FreeNAS box. Then:

/usr/local/etc/rc.d/openvpn status

to see if OpenVPN is running.

I think that’s pretty much it. Let me know if you have any questions.