Here is my setup. I work from a remote location. I have a whole /24 subnet here at home that I want all of the computers on it to be able to access multiple subnets at work as if I were in the building. I used to use VPN client software, aka Nortel, but that was very picky and dropped frequently. So a couple years ago, we realized the box we had been using also spoke IPSec, so we endeavored to set up a connection between the two. I got it working great on OpenBSD, but since there was multiple subnets, I would frequently lose one of them and have to "bounce" the whole IPSec thing. In fact it became so frequent (2-3 times a day) that I wrote a shell script and would just run it when I say that things had hanged. I got to where I was lucky enough to catch it before a terminal session dropped and I lost a bunch of typing I had done in a vi session. I heard FreeBSD is better, so I'm willing to try it. I spent all weekend making the switch and I will let you know about the performance later when I've had a chance to try it myself during a typical workday.
Ok, so just to be clear. The end result is we are going to connect a subnet at a home network / small office with multiple subnets at a corporate office using IPSec and FreeBSD 9.0. Inserted that to help Google find it.
Step 1 - Rebuild the kernel with IPSec support.
During install, make sure and select that you want the system source installed as well as the ports tree.
We are going to rebuild a kernel on an x64 (amd64) system and call it ROUTER, you can adjust it to what you need, as if youre reading this that should make perfect sense, ie i386
cp GENERIC ROUTER
Inside the file change ident to ROUTER, and add the following lines somewhere
Maybe take out some stuff you dont need, ie SCSI, RAID cards, whatever.
make buildkernel KERNCONF=ROUTER && make installkernel KERNCONF=ROUTER
Go have a cup of coffee or watch a Star Trek episode, it will be busy for 30 mins or so. Once its done, reboot and you will be in your new kernel. In case you have came here after reading the handbook, the option IPSEC_NAT_T is to make an error go away that racoon throws if its not compiled in. It may not technically be needed, but it takes one lead off the table when trying to troubleshoot. The error is something like unable to set udp encap.
Step 2 - Install ipsec-tools from ports.
The easiest way, assuming you already have basic networking up: pkg_add -r ipsec-tools
Or cd /usr/ports/security/ipsec-tools then make install if you need special options. If you are reading this, you are probably fine with the defaults.
Step 3 - Initial networking setup
From here on out I will use something very similar to the network I actually set up. The first step is to set up one subnet, then we can add the other one(s) after its working. In case you came here from the handbook, there is good news in case you were thinking of having to acquire all of this information like how the box is set up internally, dont fear. a gif0 tunnel is NOT required.
My setup is as follows, I am behind a regular DSL wireless router so that wireless devices and my TV dont have access to the corporate network, and my IP address is 192.168.0.2 . My internal subnet that I want to connect with work is 192.168.231.0/24. My internet facing address is 188.8.131.52. My network I am trying to connect to is 184.108.40.206/24 and the VPN server is 220.127.116.11. Later I will want to add the 18.104.22.168/24 network as well.
Another point of interest, unlike OpenBSD, a connection attempt that will use the tunnel must be made before it will start to negotiate a connection. So, here is what I did at first and later migrated to the startup scripts.
route add 22.214.171.124/24 192.168.231.1
Save a file name pingit.sh with the following command in it (assuming you know that a pingable machine on the other side exists at octet 11). It will send a single ping to the box to start the tunnel, but not wait real long.
ping -c 1 -W 1 126.96.36.199
Save this file for later when we are ready to test...
Step 4 - IPSec tools configuration
I am using a pre-shared key in my setup, so the first file is psk.txt. It lives in /usr/local/etc/racoon as does the other files.
It has the format: host key one per line, so in my case it would be
Wow, difficult, huh? I didnt pay attention and just put the key in there without the host and it took me 2 hours to figure it out. It also took me another hour to figure out that it needs chmod 600 psk.txt.
The next file, although deceptively easy, is picky and doesnt give much in the way of informative error messages when things go wrong.
ipsec.conf or setkey.conf, your choice I guess.
spdadd 192.168.231.0/24 188.8.131.52/24 any -P out ipsec esp/tunnel/192.168.0.2-184.108.40.206/unique;
spdadd 220.127.116.11/24 192.168.231.0/24 any -P in ipsec esp/tunnel/18.104.22.168-192.168.0.2/unique;
Pretty self explanatory, but one note. If you have only one subnet to join, use "require" instead of "unique" on the end of the line.
spdadd yoursubnet theirsubnet any -P out ipsec esp/tunnel/youraddr-theiraddr/unique;
and reverse the addresses and use in instead of out.
Now, if when testing you get errors about a send error, check this file. Its easy to write and deceptively easy and you can have an address transposed.
Now on to the racoon.conf file:
path pre_shared_key "/usr/local/etc/racoon/psk.txt"; #location of pre-shared key file
log debug2; #log verbosity setting: set to 'notify' when testing and debugging is complete
padding # options are not to be changed
timer # timing options. change as needed
interval 20 sec;
# natt_keepalive 15 sec;
phase1 30 sec;
phase2 15 sec;
listen # address [port] that racoon will listening on
isakmp 192.168.0.2 ;
my_identifier address 22.214.171.124;
# Phase 1
lifetime time 3600 sec;
lifetime time 1200 sec;
Pay most attention to the bolded areas above.
Step 4 - Firing it up
Set up 3 terminal sessions. 1 have a constant tcpdump -lnvvi <youroutsideinterface> udp port 500 running. Another to use the script from step 3. And the last one to run the VPN.
First, only needs to be done once, or if it changes.
setkey -f /usr/local/etc/ipsec.conf
Then to fire it up:
That tells it to run in foreground mode outputting to stdout so you can see it.
Assuming there are no errors and its stays running, hit the script from step 3. ./pingit.sh
It may take 3-4 times to successfully connect, unless you see a reason why not. But eventually, you will not only see pings come back, but a message like this:
UPDATE succeeded: ESP/Tunnel 192.168.0.2->126.96.36.199 spi=67865083(0x40b89fb)
Here are some common other errors you may see and their solutions:
If you get
Jul 7 08:15:28 maricopacomputer racoon: DEBUG: 1 times of 100 bytes message will be sent to 188.8.131.52
Jul 7 08:15:28 maricopacomputer racoon: DEBUG: 2fed9acf 4dbbc616 00000000 00000000 01100200 00000000 00000064 0d000034 00000001 00000001 00000028 01010001 00000020 01010000 800b0001 800c0e10 80010005 80030001 80020001 80040002 00000014 afcad713 68a1f1c9 6b8696fc 77570100
Jul 7 08:15:28 maricopacomputer racoon: DEBUG: resend phase1 packet 2fed9acf4dbbc616:0000000000000000
And no reply, check that you arent routing traffic to the end host through your internal network.
If you get:
2012-07-07 00:16:02: ERROR: phase1 negotiation failed due to send error. dad1f78e51bb5b7e:
2012-07-07 00:16:02: ERROR: failed to begin ipsec sa negotication.
Check setkey.conf closely, especially that the addresses are not transposed or anything.
Step 5 - Adding other subnets
Now that you have subnet 1 working, lets say you want to add a second subnet?
That is very easy. First of all, add the new records in ipsec.conf, 2 for each. Then, notice how I had sainfo anonymous in racoon.conf? Use that, it makes it so much easier than specifying individual subnets over again. In ipsec.conf change require to unique. Otherwise it will only be able to use one subnet at a time and will drop one and connect the other each time there is traffic for the other one.
This set up worked for me. It may not work for you. Hopefully it helps other sysadmins out there set up ipsec tunnels in FreeBSD 9.0. Happy VPN'ing!
After getting this set up over the weekend, today was a day with it in use for work. And let me say... nice. It seems more responsive and even a little quicker than OpenBSD. It may be a beyatch to set up, but it runs like a champ once it is.