Network Configuration—Tunneling with Free BSD

Generic Routing Encapsulation (GRE) protocol

GRE creates a virtual end-to-end network link between network nodes (that is routers), over a public network. GRE can be used to create simple VPN networks for customers that are connected to a service provider network, or between edge routers in a service provider environment, to exchange routing table updates. As this simple GRE interface does not support encryption, you may want to reconsider using GRE, if security is a priority.

FreeBSD 7 natively supports creating and manipulating standard GRE tunnels.

GRE support should be available in the FreeBSD's kernel. If you have not compiled GRE support into kernel, the GRE kernel module will be dynamically loaded into memory upon first usage.

Creating gre(4) interface in a simple way usingifconfig(8) utility is shown here:

# ifconfig gre0 create

Note that if you do not specify the device node number, ifconfig takes the first available number and returns the new interface name, after creating the interface as follows:

# ifconfig gre create


You can also remove unnecessary gre(4) interface using ifconfig's destroy option:

# ifconfig gre1 destroy

Now that you have created a GRE interface, you should configure both sides of the GRE interface (on both hosts). This is basically done using the ifconfig utility. Consider the following scenario in the figure to establish a GRE tunnel between Host A and Host B:


Network Configuration—Tunneling with Free BSD

To configure Host A, you should first create a gre0 interface and then specify both ends of the link on the interface.


# ifconfig gre0 create
# ifconfig gre0 netmask
# ifconfig gre0 tunnel

On Host B, you should do the same; but remember not to swap the source or destination addresses:

# ifconfig gre0 create
# ifconfig gre0 netmask
# ifconfig gre0 tunnel

The first line in the above procedure, a virtual tunnel interface (gre0) is created. The second line configures the tunnel IP address on gre0 interface and also specifies the tunnel IP address of the other endpoint (connected tunnel interface). And finally the third line establishes the tunnel between two hosts.This time, you need the real IP addresses on your physical interfaces. Now you can verify the tunnel setup on Host A:

# ifconfig gre0
gre0: flags=9051metric
0 mtu 1476
tunnel inet -->
inet --> netmask 0xffffff00

The MTU size will be automatically calculated and configured on interface (in this case, 1476 byte) to compensate the GRE protocol overhead.

Now that the tunnel interface seems to be up, you should verify the tunnel connectivity using the ping command by pinging the tunnel IP address of Host B from Host A and vice versa:

# ping -c3 ( 56 data bytes
64 bytes from icmp_seq=0 ttl=128 time=0.359 ms
64 bytes from icmp_seq=1 ttl=128 time=2.512 ms
64 bytes from icmp_seq=2 ttl=128 time=0.196 ms
--- ping statistics --- 3 packets transmitted, 3 packets received, 0.0% packet loss round-trip min/avg/max/stddev = 0.196/1.022/2.512/1.055 ms

It would be pretty straightforward to set up the GRE tunnel between two hosts so that both support the GRE tunneling protocol. This is also possible using a Cisco or Juniper Router to peer with a FreeBSD host using the GRE tunnel. So far we did the entire configuration manually, which is good for testing the tunnel setup in the lab. In order to make the changes permanent, you need to add appropriate configuration to the /etc/rc.conf configuration file. Tunnel configuration for Host A in the /etc/rc.conf file looks like the following code:

ifconfig_gre0="inet inet netmask tunnel"

Note that you can specify multiple GRE interfaces using the cloned_interfaces variable, separated by spaces. On the second line, you can see that, we have merged the whole interface configuration in one line, which is also possible when you set up using the command line.


FreeBSD's IPSec stack is based on IPSec implementation from the KAME project (see The IPSec feature is not available in stock GENERIC kernel and a new customized kernel should be built with the following options added to the kernel configuration file:

options IPSEC
options IPSEC_ESP

Once you reboot your host with the customized kernel, the IPSec protocol is available for implementation. FreeBSD's IPSec implementation supports both Authenticated Header (AH) and Encapsulated Security Payload (ESP) protocols, which can be used either together, or separately. The AH protocol protects the packets to be modified on their way to their destination, by cryptographically hashing the IP header. Consequently, when a packet is modified by an attacker in a man-in-the-middle scenario, this will be easily detected and discarded by the receiving host. AH does not encrypt the actual packet payload and is not protected against sniffing and wiretapping. On the other hand, ESP offers a method to encrypt the packet payload using symmetric algorithms, including 3des and blowfish. When ESP encryption is in effect, sniffing traffic does not reveal the actual contents of the packets. There is no conflict between ESP and AH, and they can be used together. Consequently, the packet content can be encrypted while the header is also hashed to prevent modification of packet on the wire.

Operating Modes

IPSec can operate in two modes-Tunnel mode and Transport mode. In the Tunnel mode, the packet will be completely encrypted and encapsulated into another IP packet before being sent to the destination host. In fact, the packets are actually being tunneled over another IP packet. This mode is suitable to get connected to another host over an untrusted public network (for example, the Internet). This mode is mostly referred to as IPSec Tunneling or IPSec VPN. The Transport mode offers another method of communication without modifying the routing (the source and destination address in IP packet header are not modified). Instead it encrypts the packet payload or hashes the header to ensure that the packet does not get modified in the path between source and destination. This mode is more suitable for host-to-host communications.

Transport mode does not basically work behind a NAT router. Since NAT needs to modify layer3 or layer4 addressing, this cannot be done when the packet is encrypted. Nevertheless, there are some NAT-T (NAT Traversal) methods available as per RFC 3715. However, the Tunnel mode is safe to be used with NAT.

Tunnel Mode

There are a few steps involved in creating an IPSec tunnel between two hosts. Now, suppose you have two networks in two different places that are connected to the Internet and you now want to interconnect both sites using the IPSec tunnel.


Network Configuration—Tunneling with Free BSD

The first step is to create a simple tunnel between the two sites. The gif(4) virtual interface offers basic IP over IP tunneling which is compatible with both the IPv4 and IPv6 protocol stacks. A gif(4) interface can be deployed like a gre(4) interface, as described earlier in this article.

For example, on Router A, you may use this setup:

# ifconfig gif0 create
# ifconfig gif0 tunnel
# ifconfig gif0 netmask

The tunneling with the gif(4) interface without encryption should be up and running. You may verify this by using the ping utility and test the reach ability of the IP address on gif interface of the opposite site:

# ping -o
PING ( 56 data bytes
64 bytes from icmp_seq=0 ttl=64 time=7.200 ms--- ping statistics ---
1 packets transmitted, 1 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 7.200/7.200/7.200/0.000 ms

Once the tunnel is up and running, you should add static routes (unless you are already running a dynamic routing protocol) to route each network's traffic towards the tunnel interface. For example, to reach the network behind Router B from Network A, you must add the following route command to Router A:

# route add
add net gateway

Now the first part of the VPN setup is ready. The next step is to apply an encryption on the packets that are going through the tunnel interface. There are different components involved in setting up the encryption. They are as follows:

* The setkey(8) utility is the kernel's "Security Policy" manipulation utility.
* An IPSec key management utility such as the ipsec-tools or racoon2.

Since you do not want to encrypt any outgoing packet or decrypt any incoming traffic, you need to specify which packets should be encrypted or decrypted. Kernel keeps a Security Policy Database (SPD) which holds the security policies you specify using the setkey(8) utility. This is where you can actually specify which traffic you want to encrypt.

On the other hand, the system needs an IPSec key management utility to manage the Security Association (SA) between two IPSec endpoints. SA is the mechanism for hosts to agree on encryption methods. To achieve this, you should run an Internet Key Exchange (IKE) daemon. IKE daemon takes care of key management as well as SAs between hosts.

The racoon2 utility (available online at is an advanced IKE daemon that supports IKEv1 (defined in RFC 2407, 2408, 2409, and 4109), IKEv2 (defined in RFC 4306), and Kerberized Internet Negotiation of Keys (KINK, defined in RFC 4430) key exchange protocols. It can be installed from ports collection and is located at /usr/ports/security/racoon2. However, there is another IKE daemon that does not support IKEv2 and newer protocols, but is very easy to set up and configure, which is called ipsec-tools (/usr/ports/security/ipsec-tools). The ipsec-tools utility, which is basically a fork from the original racoon project, offers basic key exchange using IKEv1 protocols and shares the same configuration syntax with the original racoon daemon.

In order to configure the racoon daemon, you should first set up ipsec-tools and create appropriate configuration files as follows:

# cd /usr/ports/security/ipsec-tools && make install clean

Once the software is installed, you should create a configuration file based on the installed sample configuration files:

# mkdir /usr/local/etc/racoon
# cp /usr/local/share/examples/ipsec-tools/racoon.conf.sample /usr/local/etc/racoon/racoon.conf

Now you should edit the configuration file to fit your specific requirements. A sample racoon.conf file looks like the following code:

This is actually a generic configuration for racoon that should simply work for any source and destination address (note remote anonymous tag). You may want to modify the configuration to fit your needs. However, when changing IKE setup, make sure you are applying change on both hosts. A comprehensive guide to racoon configuration can be found online at

To enable racoon daemon to launch at system start-up, make sure you add the following line to the /etc/rc.conf file:


To manually start racoon, run the appropriate rc script as follows:

# /usr/local/etc/rc.d/racoon start
Starting racoon.

The racoon daemon will take care of setting up SA between two endpoints based on the security policies (SP) you specify, using the setkey(8) utility. The policies should be added to the setkey configuration file which is usually located in the /etc/ipsec.conf file. In order to encrypt the tunneled traffic between two hosts, you may create a setkey configuration file that contains the following lines:

spdadd ipencap -P out ipsec esp/transport//require;
spdadd ipencap -P in ipsec esp/transport//require;

The first two lines of the file actually flush SAD and SPD entries from the kernel's SPD. The third line specifies encryption policy for the outgoing traffic (note -P out flag), that has a protocol number four in their layer3 header (note ipencap which is actually IP encapsulated in IP packets on GIF interface), from source (any) to (any). As the encapsulation type is ESP, the packet payload is encrypted. And the last line specifies decryption for the incoming packets.

The ipsec.conf file should be configured on both hosts, considering that the outgoing policy on each host should match the incoming policy on the other host and vice versa.

Once the policies are configured, you may enable automatic IPSec setup from the /etc/rc.conf file by adding the following lines:


Note that you do not have to specify the second line, as it points to /etc/ipsec.conf, by default. It is only needed if you have chosen a different name for your setkey configuration file. You should manually load security policies by running the following ipsec rc script:

# /etc/rc.d/ipsec start
Installing ipsec manual keys/policies.

You are almost done. You should check the following three steps to make sure everything is in place:

* Check the status if gif tunnel is using the ifconfig utility.
* Check whether racoon daemon is running and is listening on udp 500, using the sockstat -l4 command.
* Check whether the setkey policies that you defined are actually installed using the setkey -DP command.

If appropriate policies are installed, the output of the setkey -DP command should look like the following command line:

# setkey -DP[any][any] ip4
in ipsec
created: Jun 23 23:41:41 2007 lastused: Jun 23 23:41:41 2007
lifetime: 0(s) validtime: 0(s)
spid=16435 seq=1 pid=1534
refcnt=1[any][any] ip4
out ipsec
created: Jun 23 23:41:41 2007 lastused: Jun 23 23:41:41 2007
lifetime: 0(s) validtime: 0(s)
spid=16434 seq=0 pid=1534

At this point, there is no SA established between two hosts, as there has been no traffic between the hosts, so far. This can be verified using the setkey -D command as follows:

# setkey -D
No SAD entries

Once you ping the other side of the tunnel, the IKE daemons should exchange encryption keys and establish SA:

# ping -oq
PING ( 56 data bytes
--- ping statistics ---
1 packets transmitted, 1 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 87.537/87.537/87.537/0.000 ms

Now that the host is reachable, it means the SA is established and the keys are installed.

# setkey -D
esp mode=transport spi=85769720(0x051cbdf8) reqid=0(0x00000000)
E: 3des-cbc 26715dcd c77affd3 39165b39 073637a1 ee8b979d eebd8368
A: hmac-sha1 6eb62659 5058e91e e36b19ab abec245c 76bd67bd
seq=0x00000007 replay=4 flags=0x00000000 state=mature
created: Jun 23 23:50:09 2007 current: Jun 23 23:51:49 2007
diff: 100(s) hard: 43200(s) soft: 34560(s)
last: Jun 23 23:51:10 2007 hard: 0(s) soft: 0(s)
current: 952(bytes) hard: 0(bytes) soft: 0(bytes)
allocated: 7 hard: 0 soft: 0
sadb_seq=1 pid=1554 refcnt=2
esp mode=transport spi=61669162(0x03acff2a) reqid=0(0x00000000)
E: 3des-cbc 99792546 3c0e0a2c 9cde2a3b be503817 4efc7422 573d7014
A: hmac-sha1 f3da6e46 10bec5b7 0e21f167 2387136e 656da322
seq=0x00000006 replay=4 flags=0x00000000 state=mature
created: Jun 23 23:50:09 2007 current: Jun 23 23:51:49 2007
diff: 100(s) hard: 43200(s) soft: 34560(s)
last: Jun 23 23:51:10 2007 hard: 0(s) soft: 0(s)
current: 624(bytes) hard: 0(bytes) soft: 0(bytes)
allocated: 6 hard: 0 soft: 0
sadb_seq=0 pid=1554 refcnt=1

To make sure that the traffic is actually being encrypted, it is a good idea to run tcpdump(1) on one host, send ICMP packets from the other host (ping), and see the incoming packets. If the traffic is being encrypted, you should see ESP packets in tcpdump output on the other end.


Tunnels are different scenarios when you may want to set up a tunnel between two hosts on a network. For example, tunneling is used to exchange routing updates between edge routers, or to create a site-to-site VPN over a public network. Before choosing a tunneling method, you should decide whether the encryption is important or not. If data encryption is not a concern while setting up GRE or GIF tunnels, using FreeBSD is quite straightforward. GRE is an established protocol that is also supported by different vendors. So if you are establishing a tunnel between a FreeBSD gateway and a Cisco or Juniper router, you can simply go with GRE. If security is a concern, you can use the industry standard IPSec protocol between your FreeBSD gateway with other FreeBSD gateways or gateways from different vendors. Setting up an IPSec is also very straightforward, especially when setting up the site-to-site IPSec tunnels. However this may get more complex depending on your network architecture and specific needs.




You've been reading an excerpt of:

Network Administration with FreeBSD 7

Explore Title