Setup IPSec VPN between 2 FreeBSD 6.3 servers

1 HP lp1000r with 2 18G hard disk is sitting in datacenter; another PC is sitting in office. Both are running FreeBSD 6.3.

lp1000r: vpndc has IP pair d.1.2.3 k/di.1.2.3 in datacenter (d for datacenter, the behind network is di.1.2.0/24)
another pc:vpnsg has IP pair o.1.2.3/oi.1.2.3 in office (o for office, the behind network is oi.1.2.0/24)
2 firewalls doing port forwarding and seperate DMZ and internal office/datacenter network

___Internetl corporate network____"FW"oi.1.2.4____oi.1.2.0/24---oi.1.2.3"vpnsg"o.1.2.3 ++++++++d.1.2.3"vpndc"di.1.2.3__di.1.2.0/24____di.1.2.4"FW"____internal datacenter network___

Setup VPN over IPSec between 2 FreeBSD servers so that it can connect 2 private network through Internet.


  • install OS
Use the first CD of FreeBSD 6.3, use 'F - DD' mode to configure partition since we are using FreeBSD for the dedicated server, use 'Automatic' mode of making partitions. use 'full binary, doc and kernel source only' category to install.

  • SSH and PF configuration
Just after installing OS, by default ,it's no firewall enabled, you can configure the following to enable ssh on internal NIC.
scrub in all
block in log all
pass in on $int_if proto tcp from any to $int_if port 22 keep state
pass out on $int_if proto { tcp, udp } all keep state
for final pf.conf on vpndc and can be used for ipsec, I use:
scrub in all
block in log all

# allow icmp type 3 code 4
pass in log quick on $ext_if inet proto icmp all icmp-type unreach code 4        
pass in log quick on $int_if inet proto icmp all icmp-type unreach code 4       
pass out log quick on $ext_if inet proto icmp all icmp-type unreach code 4      
pass out log quick on $int_if inet proto icmp all icmp-type unreach code 4     

block in log quick on $ext_if proto icmp from any to any
block in log quick on $int_if proto icmp from any to any
block out log quick on $ext_if proto icmp from any to any
block out log quick on $int_if proto icmp from any to any

# for $int_if
# allow ssh to vpndc itself from FW on inside DMZ
pass in on $int_if proto tcp from di.1.2.4 to $int_if port 22 keep state

# allow the whole DMZ can reply back tcpip packet to the office uses, actually, this rule might contain the above ssh one
pass in on $int_if from di.1.2.0/24 keep state

#allow office users' request going to DMZ in datacenter
pass out on $int_if from any to di.1.2.0/24 keep state
####for $ext_if ,almost same as above
pass in on $ext_if from o.1.2.3 to $ext_if keep state
pass out on $ext_if from $ext_if to o.1.2.3 keep state
  • DNS and ssh slow response issue
If your environment doesn't have DNS server, the ssh startup and login will be very slow, to address this issue, you can disable DNS as folllows:
vi /etc/nsswitch.conf
to take out 'dns' from hosts line

  • add user jephe for 'su -'
vi /etc/group
to add user 'jephe' to 'wheel' group
  • enable raid1 mirror for hp lp1000r server
to enable raid1 mirror, do the following:
We assume /dev/da0 is the first hard disk we installed OS on, we need to add /dev/da1 which is the second hard disk to the raid1 mirror system.
# sysctl kern.geom.debugflags=16
# gmirror label -v -b round-robin gm0 /dev/da0
# echo geom_mirror_load=YES >> /boot/loader.conf
# vi /etc/fstab (to change all /dev/da0 to /dev/mirror/gm0, :%s#da0#mirror\/gm0#g)

bsd1# more /etc/fstab
# Device Mountpoint FStype Options Dump Pass#
/dev/mirror/gm0s2b none swap sw 0 0
/dev/mirror/gm0s1a / ufs rw 1 1
/dev/mirror/gm0s4d /usr ufs rw 2 2
/dev/mirror/gm0s3d /var ufs rw 2 2
/dev/acd0 /cdrom cd9660 ro,noauto 0 0
# reboot
After reboot, you can use command 'gmirror status' or 'gmirror list' to check the raid1 status.
For adding the second hard disk /dev/da1 to raid array, run
#gmirror forget gm0 (optional, depends)
#gmirror insert gm0 /dev/da1
  • compile kernel to enable ipsec
cd /usr/src/sys/i386/conf
ln -sf /root/MYKERNEL
vi MYKERNEL to add the following:

options IPSEC
options IPSEC_ESP

cd /usr/src
make buildkernel KERNCONF=MYKERNEL
make installkernel KERNCONF=MYKERNEL

  • install racoon
download it from Internet, it's an open source software
put it under /home/jephe
tar xvfz ipsec-tools-0.7.tar.gz
cd ipsec-tools-0.7
./configure ;make
su - as root to make install
binary racoon will be installed to /usr/local/sbin/racoon
then you need to put racoon.conf.sample to /usr/local/etc/racoon.conf
and psk.txt.sample to /usr/local/etc/psk.txt

you can run 'find . -name "psk.txt*" and 'find . -name "racoon.conf*" from ipsec-tools-0.7 directory to find out the path of two files psk.txt.sample and racoon.conf.sample.

  • configure racoon
You can use command 'strings /usr/local/sbin/racoon | grep racoon.conf' to find out the path of racoon.conf
then copy racoon.conf.sample there as racoon.conf.
after that, copy psk.txt.sample to /usr/local/etc also, then vi racoon.conf to change the following line:

path pre_shared_key "/usr/local/etc/psk.txt";

So, change it to use /usr/local/etc/psk.txt, before it was /usr/local/etc/v6/psk.txt .

chown root:wheel psk.txt
chmod 600 psk.txt

the above commands are very important, otherwise, after you run racoon, it won't establish vpn normally.
inside psk.txt, configure one line for peer end, make it looks like this:

remotesiteipaddress sharedkey
  • configuring /etc/rc.conf on vpndc
#enable pf

#enable ipsec

#for gif interface on datacenter freebsd 6.3
gifconfig_gif0="d.1.2.3 o.1.2.3"
ifconfig_gif0="inet di.1.2.3 oi.1.2.3 netmask 0xffffffff"
route_vpn="-net oi.1.2.0/24 oi.1.2.3 "

  • configure /etc/ipsec.conf
spdadd d.1.2.3/32 o.1.2.3/32 ipencap -P out ipsec esp/tunnel/d.1.2.3-o.1.2.3/require;
spdadd o.1.2.3/32 d.1.2.3 ipencap -P in ipsec esp/tunnel/o.1.2.3-d.1.2.3/require;

spdadd di.1.2.0/24 oi.1.2.0/24 any -P out ipsec esp/tunnel/d.1.2.3-o.1.2.3/require;
spdadd oi.1.2.0/24 di.1.2.0/24 any -P in ipsec esp/tunnel/o.1.2.3-d.1.2.3/require;

  • configure /etc/rc.local
vpn# more rc.local
# start up racoon, the default configuration file is /usr/local/etc/racoon.conf, you can run 'strings /usr/local/sbin/racoon | grep racoon.conf' to know that.

/usr/local/sbin/racoon [ -l /var/log/racoon.log ]

  • reboot server and 'racoon' should be started automatically , after that , try to ping each other, e.g. from office freebsd server vpnsg, ping di.1.2.3, then sniff the traffic on datacenter freebsd server using command 'tcpdump -n -i fxp0 host o.1.2.3'
  • same examples of configuration
$ netstat -nr
Routing tables

Destination Gateway Flags Refs Use Netif Expire
default x.x.x.x UGS 2 34 fxp0 UH 0 90 lo0
oi.1.2.0/24 oi.1.2.3 UGS 8874 8877 gif0
oi.1.2.3 di.1.2.3 UH 8 7 gif0
di.1.2.0/24 link#2 UC 0 0 fxp1
d.1.2.0/24 link#1 UC 0 0 fxp0

note: from above routing table, going to office internal network oi.1.2.0/24 will be sent to gif0 and office vpnsg inside ip oi.1.2.3; and going to oi.1.2.3 will be sent to di.1.2.3 and gif0