1. Securing the Tunnel w/IPsec and Racoon
Now that we have created a network configuration that enables connectivity between the endpoint’s
internal networks, we must encrypt the traffic. Skipping this step would mean that all traffic crossing the
tunnel would be insecure (unless secured by other means). FreeBSD implements IPsec in its kernel, and
along with the security/ipsec-tools port, you can encrypt all traffic that is sent through the tunnel.
Kernel Configuration
IPsec must be configured into the FreeBSD’s kernel configuration file, and he kernel must be rebuilt. I
added the following option and device to my kernel’s configuration file, rebuilt, installed, and rebooted.
options IPSEC
device crypto
#IP security
Security Policies
IPsec security policies must be defined and set to load into the Security Policy Database (SPD). This
enables FreeBSD and racoon to encrypt / decrypt traffic between the two endpoints. The rules can be
defined in a text file, then loaded at boot. I kept my policies in /usr/local/etc/racoon/setkey.conf and the
file contained the following:
Endpoint 1:
flush;
spdflush;
spdadd 172.16.1.0/24 172.16.2.0/24 any -P out ipsecesp/tunnel/192.168.1.1-192.168.2.1/use;
spdadd 172.16.2.0/24 172.16.1.0/24 any -P in ipsecesp/tunnel/192.168.2.1-192.168.1.1/use;
Endpoint 2:
flush;
spdflush;
spdadd 172.16.2.0/24 172.16.1.0/24 any -P out ipsecesp/tunnel/192.168.2.1-192.168.1.1/use;
spdadd 172.16.1.0/24 172.16.2.0/24 any -P in ipsecesp/tunnel/192.168.1.1-192.168.2.1/use;
I added the following to my /etc/rc.conf on each endpoint which tells FreeBSD to enable IPsec and load
the policies into the SPD:
ipsec_enable=”YES”
ipsec_file=”/usr/local/etc/racoon/setkey.conf”
After running /etc/rc.d/ipsec start, I could view the SPD by issuing the setkey -DP command to ensure
the policies were loaded properly.
2. Configuring Racoon
At this stage, we have IP-IP connectivity configured and tested, IPsec has been compiled into the kernel,
and the IPsec security policy database contains the policies loaded from the setkey.conf file. Now we
must configure the racoon IKE key management daemon. First, you’ll need to make sure your ports are
up to date and install security/ipsec-tools:
cd /usr/ports/security/ipsec-tools
make install clean
After the port installs, you’ll first want to copy the racoon sample configuration file into place, and create
a psk.txt file that will contain the pre-shared key that will be used during racoon’s negotiation process,
and set the owner / permissions appropriately:
cp /usr/local/share/examples/ipsec-tools/racoon.conf.sample /usr/local/etc/racoon/racoon.conf
touch /usr/local/etc/racoon/psk.txt
chownroot:wheel /usr/local/etc/racoon/psk.txt
chmod 600 /usr/local/etc/racoon/psk.txt
Edit the /usr/local/etc/racoon/psk.txt file. It should contain the remote endpoint’s public IP address and a
unique password:
Endpoint 1:
192.168.2.1 SomeMadeUpPassword
Endpoint 2:
192.168.1.1 SomeMadeUpPassword
Next, the racoon.conf file needs to be edited. There are many options to this file, and it’s probably best to
learn all about it via the racoon.conf(5) man page. That being said, the one below is based on a lot of
what I’ve found on the web, and works really nicely for me.
Endpoint 1:
# $KAME: racoon.conf.sample,v 1.28 2002/10/18 14:33:28 itojunExp $
path include “/usr/local/etc/racoon” ;
path pre_shared_key “/usr/local/etc/racoon/psk.txt” ;
log debug;
padding # options are not to be changed
{
maximum_length 20; # maximum padding length
randomize off; # enable randomize length
strict_check off; # enable strict check
exclusive_tail off; # extract last one octet
}
listen # address [port] that racoon will listening on
{
isakmp 192.168.1.1 [500];
}
3. timer # timing options. change as needed
{
counter 5; # maximum trying count to send
interval 20 sec; # maximum interval to resend
persend 1; # the number of packets per a send
phase1 60 sec;
phase2 25 sec;
}
remote 192.168.2.1 [500]
{
exchange_modeaggressive,main;
doiipsec_doi;
situation identity_only;
lifetime time 8 hour;
initial_contact on;
passive off;
proposal_check obey;
generate_policy off;
proposal {
encryption_algorithm blowfish;
hash_algorithm sha1;
authentication_methodpre_shared_key;
dh_group 5;
}
}
sainfo anonymous
{
pfs_group 5;
lifetime time 12 hour ;
encryption_algorithm blowfish,3des,des;
# authentication_algorithm hmac_md5,hmac_sha1;
authentication_algorithm hmac_sha1;
compression_algorithm deflate ;
}
Endpoint 2:
# $KAME: racoon.conf.sample,v 1.28 2002/10/18 14:33:28 itojunExp $
path include “/usr/local/etc/racoon” ;
path pre_shared_key “/usr/local/etc/racoon/psk.txt” ;
log debug;
padding # options are not to be changed
{
maximum_length 20; # maximum padding length
randomize off; # enable randomize length
strict_check off; # enable strict check
4. exclusive_tail off; # extract last one octet
}
listen # address [port] that racoon will listening on
{
isakmp 192.168.2.1 [500];
}
timer # timing options. change as needed
{
counter 5; # maximum trying count to send
interval 20 sec; # maximum interval to resend
persend 1; # the number of packets per a send
phase1 60 sec;
phase2 25 sec;
}
remote 192.168.1.1 [500]
{
exchange_modeaggressive,main;
doiipsec_doi;
situation identity_only;
lifetime time 8 hour;
initial_contact on;
passive off;
proposal_check obey;
generate_policy off;
proposal {
encryption_algorithm blowfish;
hash_algorithm sha1;
authentication_methodpre_shared_key;
dh_group 5;
}
}
sainfo anonymous
{
pfs_group 5;
lifetime time 12 hour ;
encryption_algorithm blowfish,3des,des;
# authentication_algorithm hmac_md5,hmac_sha1;
authentication_algorithm hmac_sha1;
compression_algorithm deflate ;
}
5. Starting Racoon
Now that everything is in place, you’ll want to add racoon to start at boot in /etc/rc.conf, and then start it
on both sides to and check to make sure the negotiation was successful. I found the best way to do this
is to add the configuration lines to each endpoint’s /etc/rc.conf, then start racoon and review the SAD
tables and racoon log files. First add the lines to /etc/rc.conf:
racoon_enable=”yes”
racoon_flags=”-l /var/log/racoon.log”
Start racoon on each host:
/usr/local/etc/rc.d/racoon start
After starting racoon, ping endpoint 2′s internal IP address from endpoint 1, this will get the negotiation
process under way if it’s not already. There are two ways to validate that the negotiation was successful.
The first is to review the /var/log/racoon.log file and check for signs of success. You should see
something like:
2011-11-21 12:15:16: INFO: IPsec-SA established: ESP/Tunnel 192.168.1.1[500]->192.168.2.1[500]
spi=56832670(0x363329e)
The other way is to use setkey to dump the SAD tables, which will only exist if the IPsec negotiation was
successful:
setkey -D
You should see output displaying the encryption algorithms that are being used, as well as other
information.
Validating Encryption
Before you can sleep at night knowing your VPN is secure, you should run some simple tests to make
sure traffic is being encrypted. tcpdump is a good way to do this. On one endpoint, or both, use tcpdump
to dump the public interface’s traffic and look to make sure you see ESP records:
tcpdump -n -i re0 host 192.168.1.1 and dst 192.168.2.1
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on re0, link-type EN10MB (Ethernet), capture size 65535 bytes
18:51:29.800977 IP 192.168.1.1 > 192.168.2.1: ESP(spi=0x0693d993,seq=0×7), length 116
18:51:31.713245 IP 192.168.1.1 > 192.168.2.1: ESP(spi=0x0693d993,seq=0×8), length 116
If encryption isn’t working place, you’ll see something more along the lines of:
18:56:47.315538 IP 192.168.1.1.63035 > 192.168.2.1.22: Flags [F.], seq 0, ack 41, win 913, options
[nop,nop,TSval 160362725 ecr 375854087], length 0
6. Conclusion
If everything has gone to plane, you should have a secure IPsec VPN tunnel between to FreeBSD
endpoints. Though this setup is slightly more complex, I prefer it over other VPN methods when it’s
relating to a permanent VPN.