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.

If I build it


I have the opportunity to build a server for a company that I’ve been doing some freelance work for.  It will mostly be a file server.  Originally it was just going to be an easily expandable archive/backup of digital images. Lots and lots and lots of digital images. (3-4 TB, I know…to some of you that isn’t very much) It was really only going to be accessed by a single employee on a daily basis.

Given that brief description of desires, I thought a FreeNas box would be perfect. Set up a VPN, a ZFS filesystem and some shares and be done.

Now, things have changed a little. The thought has been brought up that maybe the fileserver should become the primary repository for images. Currently all images are uploaded to the “cloud” by the various photographers and then downloaded to a disk as a backup. The “cloud” provider has been having some performance issues lately and has negatively impacted the back of house production workflow. Thus the idea to switch things up.

So the question is, does it still make sense to use FreeNas? The main issue as I see it is there is a desire for a super simple user-friendly way for all the photographers to be able to upload images to the fileserver. I thought that SFTP would be a winner, but sadly, some of the locations that the photographers shoot at have restricted web access. Also, the photographers have had problems in the past with FTP.(operator error mostly, but still a real issue) That makes me think that WebDAV might be a good solution, as it runs over port 80. However, I’ve had problems with it when trying to use certain OS’es to access a webdav share. For example, the apache webdav implementation under FreeBSD 8.x does not play nice with Mac OS X 10.6.x.

Another thought is to have all the photographers connect to the VPN and then do standard file sharing. That will mean running the VPN over a non-standard port to get around the restrictions at some of the sites. Not a deal breaker. However, I am not looking forward to trying to train all the photographers on how to use the VPN.

Last thing that I’ve looked at is a solution like ajaXplorer. I have no experience with this type of web software other than playing with it for an hour in a FreeNAS VM. It might be the best solution…just don’t know enough about it to make an educated decision.

So, if anyone is out there and listening, I could use some advice.

FreeNas Remote Backups


So I love that ZFS allows automated snapshots and that my FreeNas box is set up with a 3 disk Raid.  However, I’m paranoid.  What if the house burns down, or someone breaks in and steals all our computers?  A smart guy would have a remote backup somewhere.  So, I decided it was time to get my remote backup groove on.

I know that you can do a ZFS replication to another FreeNas box. The issue I have with that approach is that you have to replicate the entire ZFS volume. I needed something more granular.  So, I busted out some python and started working on a remote backup script. To give credit where it is due, my brother helped me get started…so thanks big brother. 

*Disclaimer*

I am not a programmer.  This code and instructions are provided “as is” with no warranty, promise that it works, promise that is won’t melt your computer or even cause the end of the World.  Use at your own risk.

The general overview of how the remote backup program works is like this. First the program connects to the remote computer and rsync’s all of your files. It’s setup so that you can have four different sets of remote backups all running on different days if you want. I personally am only using one backup that runs every day. Next, it determines the disk usage of the remote backup disk. It then calculates how long the backup took. Once it has all of that done, it compiles an email with a general status at the top and the details at the bottom. Continue reading

FreeNas Fix up


So here’s a quick tip. If you ever get your FreeNas install dorked up so bad that the Web-GUI stops working, grab your database file before you reinstall so you don’t have to re-configure.
The db file lives at:
/data/freenas-v1.db

You can then re-install a fresh FreeNas, drop this back in place via the webGUI and you should be up and running right where you were.

Not that I’d ever need to do something like that.

Edit:

So the really slick way to fix this is grab a FreeNas upgrade CD, slam it into the Nas box.  Boot from it.  Then let it “upgrade” your install and preserve your settings.

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.

FreeNas Follies


Made the mistake of editing my zfs pools from the command line on FreeNas 8.0.2.  Ended up discovering something.  FreeNas uses a database to keep track of things like volumes and the like.  Manually messing with things from the command line throws things out of whack to the point that you have to go in and manually repair them.  So the procedure goes like this.

ssh into freenas.  su to root.  
Then sqlite3 /data/freenas-v1.db

Then list the tables

sqlite> .tables
account_bsdgroupmembership
account_bsdgroups
account_bsdusers
auth_group
auth_group_permissions
auth_message
auth_permission
auth_user
auth_user_groups
auth_user_user_permissions
django_content_type
django_session
network_alias
network_globalconfiguration
network_interfaces
network_lagginterface
network_lagginterfacemembers
network_staticroute
network_vlan
services_activedirectory
services_afp
services_cifs
services_dynamicdns
services_ftp
services_iscsitarget
services_iscsitargetauthcredential
services_iscsitargetauthorizedinitiator
services_iscsitargetextent
services_iscsitargetglobalconfiguration
services_iscsitargetportal
services_iscsitargettoextent
services_ldap
services_nfs
services_rsyncd
services_rsyncmod
services_services
services_smart
services_snmp
services_ssh
services_tftp
services_ups
sharing_afp_share
sharing_cifs_share
sharing_nfs_share
south_migrationhistory
storage_disk
storage_diskgroup
storage_mountpoint
storage_replication
storage_replremote
storage_task
storage_volume
system_advanced
system_cronjob
system_email
system_rsync
system_settings
system_smarttest
system_ssl
Then sqlite> select id, disk_description from storage_disk

Output for me was

1|Member of tank raidz
2|Member of tank raidz
3|Member of tank raidz
4|Member of tank raidz
5|Member of BigWest stripe
6|Member of BigWest stripe1

Now, delete your mistakes.

sqlite> delete from storage_disk where id=5;
sqlite> delete from storage_disk where id=6;

Now do the same for storage_volume and storage_diskgroup

I’m sure there are other ways you can make FreeNas unhappy, so maybe this little hint will help with that too.

Hacking Freenas – zfs replication


If you are trying to replicate your zfs volume to a remote system that doesn’t have port 22 forwarded to it…you can hack Freenas to use a different port.

Cliff notes version for myself is as follows:
ssh into freenas…su to root
“mount -uw /”
“vi /usr/local/www/freenasUI/tools/autorepl.py”
search for sshcmd using “/sshcmd”
After sshcmd = ‘/usr/bin/ssh insert -p and the port needed. Use i to insert in vi. then type -p 2020 or some port that works for you. hit esc then “:wq” to save and quit.

OK…that’s more than the cliff notes for myself. If you have any questions…feel free to ask.    Any hack changes like this will get squashed next time you upgrade freenas.  That said, I’ve heard from a reliable source that this is an option that is headed for a future release.

Also discovered that when you are setting the remote zfs filesystem…that if the filesystem is an existing zfs filesystem, you only need to use the name of the filesystem and not the path.