IPsec is a protocol which sits on top of the Internet Protocol (IP) layer. IPsec allows communication between hosts in a secure manner. The FreeBSD IPsec based on the KAME implementation.
I’ll use FreeBSD 7.2 for this howto, before we start to configure IPsec we need to compile IPSEC module into FreeBSD kernel if you don’t know to recompile FreeBSD kernel then please follow this document. To enable IPsec support into your kernel, add the following options in kernel configuration file:
Options IPSEC_DEBUG #debug IP security
Device crypto
Let’s draw the scenario which will be use throughout this tutorial
In the above diagram two public IP addresses has been used (172.17.1.254, 172.18.1.254). We will use these IP addresses as a reference in the rest of this article. Anywhere you see those ip addresses, replace them with your own public IP address.
Note for the local network I used (192.168.1.x) for 172.17.1.254 and (192.168.2.x) for 172.18.1.254.
All the machines on (192.168.1.x) network side assigned 192.168.1.1 as a default gateway.
All machines on (192.168.2.x) network side assigned 192.168.2.1 as a default gateway.
Creating a “virtual” network link
We will use a “tunnel” between the two networks. The two “tunnel mouths” are the IP addresses 172.16.17.254 and 172.18.1.254, and the tunnel must be told the addresses of the private IP addresses that will be allowed to pass through it. The tunnel is used to transfer traffic with private IP addresses across the public Internet.
This tunnel is created by using the generic interface or gif devices on FreeBSD. As you can imagine, the gif interface on each gateway host must be configured with four IP addresses; two for the public IP addresses, and two for the private IP addresses.
FreeBSD 7.x already include gif support into kernel, but you can also do this by adding the line:
Now let’s create our first tunnel on the machine (172.17.1.254) you would run the following commands to configure the tunnel.
ifconfig gif0 tunnel 172.17.1.254 172.18.1.254
ifconfig gif0 inet 192.168.1.1 192.168.2.1 netmask 255.255.255.0
On 2nd machine (172.18.1.254) you would run the following commands to configure the tunnel.
ifconfig gif0 tunnel 172.18.1.254 172.17.1.254
ifconfig gif0 inet 192.168.2.1 192.168.1.1 netmask 255.255.255.0
Now check the gif0 interface either its up or not, you can run ifconfig command on both machines:
On the machine(172.17.1.254) you would see this kind of information:
tunnel inet 172.17.1.254 –> 172.18.1.254
inet 192.168.1.1 –> 192.168.2.1 netmask 0xffffff00
In the above output you can see, a tunnel has been created between the two hosts 172.17.1.254 and 172.18.1.254. The traffic between 192.168.1.1 and 192.168.2.1 pass through this tunnel, latter on we will secure this tunnel through IPSec.
On the other end (172.18.1.254) you would see this:
tunnel inet 172.18.1.254 –> 172.17.1.254
inet 192.168.2.1 –> 192.168.1.1 netmask 0xffffff00
In the above output you can see, a tunnel has been created between the two hosts 172.18.1.254 and 172.17.1.254. The traffic between 192.168.2.1 and 192.168.1.1 pass through this tunnel.
A new entry will be added automatically in the routing table on both sides, which you can examine with the command netstat -rn. you would see a output like this.
192.168.2.1 192.168.1.1 UH 1 1 gif0
Securing the link
We want to secure our both side tunnels for this we will be use IPsec. IPsec provides a mechanism for two hosts to agree on an encryption key to encrypt data between the two hosts.
Security associations and security policies are both maintained by the kernel, and can be modified by userland programs. However, before you can do this you must configure the kernel to support IPsec and the Encapsulated Security Payload (ESP) protocol. This is done by configuring a kernel with:
Options IPSEC_DEBUG #debug IP security
Device crypto
We don’t need to do this again, as you know we already compiled these options into our kernel.
IPSec Configuration
There are a number of choices for daemons to manage security associations with FreeBSD. In this article we will describe how to use one of these, racoon – which is available from security/ipsec-tools in the FreeBSD Ports collection.
make install clean
After the installation of ipsec-toosl create a directory /usr/local/etc/racoon
The racoon software must be run on both sides. Each host it is configured with the IP address of the other end VPN, and a secret key (which we will create in /usr/local/etc/racoon/psk.txt.
Before configuring racoon.conf file we should create /etc/ipsec.conf keys on both machines.
Now let’s create a key on 172.17.1.254 machine.
esp/tunnel/192.168.1.1-192.168.2.1/require;
esp/tunnel/192.168.2.1-192.168.1.1/require;
On the 172.18.1.254 side.
esp/tunnel/192.168.2.1-192.168.1.1/require;
esp/tunnel/192.168.1.1-192.168.2.1/require;
The above racoon’s policies will encrypt all traffic following between the following hosts 172.17.1.254 & 172.18.1.254 and by using tunnel mode it will also provide protection(“authentication”) of the IP packet.
We need to enable ipsec in /etc/rc.conf on both sides so ipsec automatically run when machine is boot.
ipsec_file="/etc/ipsec.conf"
Now let’s configure racoon.conf on the machine A side (172.17.1.254).
vi /usr/local/etc/racoon/racoon.conf
path pre_shared_key "/usr/local/etc/racoon/psk.txt";
{
maximum_length 20; # maximum padding length.
randomize off; # enable randomize length.
strict_check off; # enable strict check.
exclusive_tail off; # extract last one octet.
}
{
isakmp 172.17.1.254 [500];
}
timer
{
# These value can be changed per remote node.
counter 5; # maximum trying count to send.
interval 20 sec; # maximum interval to resend.
persend 1; # the number of packets per send.
phase1 30 sec;
phase2 15 sec;
}
{
exchange_mode main,aggressive;
doi ipsec_doi;
situation identity_only;
certificate_type x509 "my.cert.pem" "my.key.pem";
initial_contact on;
proposal_check obey; # obey, strict, or claim
encryption_algorithm 3des;
hash_algorithm sha1;
authentication_method rsasig;
dh_group 2;
}
}
{
exchange_mode aggressive,main;
doi ipsec_doi;
situation identity_only;
nonce_size 16;
lifetime time 1 min; # sec,min,hour
initial_contact on;
proposal_check obey;
proposal {
encryption_algorithm blowfish;
hash_algorithm sha1;
authentication_method pre_shared_key;
dh_group 2;
}
}
{
pfs_group 2;
encryption_algorithm 3des;
authentication_algorithm hmac_sha1;
compression_algorithm deflate;
}
{
pfs_group 1;
lifetime time 3600 sec;
encryption_algorithm blowfish;
authentication_algorithm hmac_md5;
compression_algorithm deflate;
}
As you can see I used isakmp 172.17.1.254 [500] on A side machine.
Thes listen section tells the demon what ip address and port to bind to. If you don’t specify anything under the Listen section, the daemon will attempt to bind port 500 on all available interfaces.
In the remote section I have defined Side B ip address (172.18.1.254) and tell the daemon to use shared-key authentication on both sides.
The remote section is for IKE phase 1 & the sainfo is for IKE phase 2.
Now we need to create psk.txt file for shared key. In this file we will define Side B ip address with shared password. The file permission should be 644 on both sides.
echo "172.18.1.254 shared_password" > psk.txt
chmod 644 psk.txt
Side A is configured we need to edit racoon.conf on Side B
Let’s configure /usr/local/etc/racoon/racoon.conf on the machine (172.18.1.254).
vi /usr/local/etc/racoon/racoon.conf
path pre_shared_key "/usr/local/etc/racoon/psk.txt";
{
maximum_length 20; # maximum padding length.
randomize off; # enable randomize length.
strict_check off; # enable strict check.
exclusive_tail off; # extract last one octet.
}
{
isakmp 172.18.1.254 [500];
}
timer
{
# These value can be changed per remote node.
counter 5; # maximum trying count to send.
interval 20 sec; # maximum interval to resend.
persend 1; # the number of packets per send.
phase1 30 sec;
phase2 15 sec;
}
{
exchange_mode main,aggressive;
doi ipsec_doi;
situation identity_only;
certificate_type x509 "my.cert.pem" "my.key.pem";
initial_contact on;
proposal_check obey; # obey, strict, or claim
encryption_algorithm 3des;
hash_algorithm sha1;
authentication_method rsasig;
dh_group 2;
}
}
{
exchange_mode aggressive,main;
doi ipsec_doi;
situation identity_only;
nonce_size 16;
lifetime time 1 min; # sec,min,hour
initial_contact on;
proposal_check obey;
proposal {
encryption_algorithm blowfish;
hash_algorithm sha1;
authentication_method pre_shared_key;
dh_group 2;
}
}
{
pfs_group 2;
encryption_algorithm 3des;
authentication_algorithm hmac_sha1;
compression_algorithm deflate;
}
{
pfs_group 1;
lifetime time 3600 sec;
encryption_algorithm blowfish;
authentication_algorithm hmac_md5;
compression_algorithm deflate;
}
As you can see I used isakmp 172.18.1.254 [500] on 172.18.1.254 machine.
In the remote section I have defined Side A ip address (172.17.1.254)
Let’s create shared key authentication file on Side B machine. In this file we will define other Side A ip address and shared password
echo "172.17.1.254 shared_password" > psk.txt
chmod 644 psk.txt
Everything is configured and placed, we need to enable racoon in /etc/rc.conf on both sides and then start racoon daemon.
racoon_flags="-l /var/log/racoon.log && echo -n ‘ racoon’"
Let’s start racoon on both machines.
After starting the racoon daemon you can test your encrypted tunnel with setkey -DP, Let’s run this command on Side A (172.17.1.254)
The ouput of above command should be like this.
in ipsec
esp/tunnel/172.18.1.254-172.17.1.254/require
spid=2 seq=1 pid=1144
refcnt=1
172.17.1.254[any] 172.18.1.254[any] ip4
out ipsec
esp/tunnel/172.17.1.254-172.18.1.254/require
spid=1 seq=0 pid=1144
refcnt=1
Above output means you have successfully configred your IPSec on FreeBSD.
Let’s test our IPSec tunnel to ensure that everything is running fine. On Side A we will ping Side B internal ip address e.g.
And get a response, you should be able to do the same thing on the other Side B machine.
However, you will not be able to reach other internal machines on both sides. This is because of the routing — although the gateway machines know how to reach one another, but they do not know how to reach the entire network.
To solve this problem we have to add a static route on each Sides. The command to do this on the first Side A (172.17.1.254)
This says “In order to reach on the entire network 192.168.2.0, send the packets to the host 192.168.2.1”.
On Side B (17.18.1.254) would be:
This says “In order to reach on the entire network 192.168.1.0, send the packets to the host 192.168.1.1”.
We need to set these entries in /etc/rc.conf so whenever computer is rebooting it’s automatically up and running.
On machine 172.17.1.254 add these entries in /etc/rc.conf
gifconfig_gif0="172.17.1.254 17.18.1.254"
ifconfig_gif0="192.168.1.1 192.168.2.1 netmask 255.255.255.0"
static_routes="vpn"
route_vpn="192.168.2.0/24 192.168.2.1"
And machine 172.18.1.254 add these entries in /etc/rc.conf
gifconfig_gif0="172.18.1.254 17.17.1.254"
ifconfig_gif0="192.168.2.1 192.168.1.1 netmask 255.255.255.0"
static_routes="vpn"
route_vpn="192.168.2.0/24 192.168.2.1"
Firewall Setup:
It is likely that you are running a firewall on both machines. In this regards you might want to allow all traffic between both networks, or you might want to include firewall rules that protect both ends of the VPN from one another.
If you are using pf then you will need to run this command on both gateway hosts.
It will allow all traffic between the two end points of the VPN
This solution was configured and test successfully on FreeBSD 7.2. But We do not assume any responsibility or we are not liable for any damage which may have been occurred tu to implementation of this solution.
Your comments on this post helpful for us to make more competent howtos for you.









Comments
Vimuth Dayaratne
October 28th
What an excellent piece of guide. Out of curiosity Sir can we do this exercise having only one NIC’s installed on either of those BSD boxes which we are creating the tunnel in between? Possibly by means of IP aliasing may be if at all supported? Please upload more BSD guides. Thank you very much.
Best Regards
Vimuth
PS: Who is the author of this article? Please mention the name of the gentleman who wrote this.
admin
October 29th
Hmm.
I haven’t try it. But I think it is possible on single NIC.
BTW: thanks for your nice comment.
Regards,
Tech Babu
Ilya
December 2nd
Very good article, but I don’t understand how you obtain from this rules in
/etc/ipsec.conf
spdadd 172.17.1.254/32 172.18.1.254/32 ipencap -P out ipsec
esp/tunnel/192.168.1.1-192.168.2.1/require;
spdadd 172.18.1.254/32 172.17.1.254/32 ipencap -P in ipsec
esp/tunnel/192.168.2.1-192.168.1.1/require;
this result of setkey -DP
172.18.1.254[any] 172.17.1.254[any] ip4
in ipsec
esp/tunnel/172.18.1.254-172.17.1.254/require
spid=2 seq=1 pid=1144
refcnt=1
172.17.1.254[any] 172.18.1.254[any] ip4
out ipsec
esp/tunnel/172.17.1.254-172.18.1.254/require
spid=1 seq=0 pid=1144
refcnt=1
????
P.S. Sorry for my english ):
TechBabu
December 3rd
Hi
The rules are very clear, we have two hosts ( Host -A 172.17.1.254 ) and ( Host -B 172.18.1.254). with tunnels both end (Host -A 192.168.1.1) and (Host -B 192.168.2.1). the above rules are very simple. From (Host -A) traffic for (Host -B) will pass through (192.168.1.1).
Regards
Ilya
December 3rd
Thanks for your answer.
Regards,
Ilya
Leave a Reply
Trackbacks
CS & IT Solutions » Blog Archive » IPSec Tunneling Using FreeBSD
June 4th, 2010