How to setup an IPsec/IKE-protected
Mobile IPv6/NEMO testbed

Back to index

Intro   Kernel   UMIP   Racoon   Config(HA|MN|NEMO)   Changelog

Introduction

Below, you'll find all the steps required to setup a complete IPsec/IKE-protected Mobile IPv6 environment under Linux. This document provides the required information to patch and build the 3 main parts: racoon, UMIP and a custom kernel. Once you have completed those steps, two additional sections provide detailed configuration notes for racoon and UMIP.

Before you enter the funny part (the practice), it is important that you understand how the theoretical parts fit together. Let's first take some time to describe the building blocks, their implementation status, their lacks and how they are intended to work together.

Note: This document is based on racoon, which only supports IKEv1. If you are interested in IKEv2, patches and documentation are available for racoon2 in this howto written by Sebastien Decugis. Note that the whole setup he describes there is based on SADB_X_EXT_PACKET mechanism (as specified in expired 04 version of MIGRATE draft) which has been replaced in the set of patches presented here by some improvements of MIGRATE design.

Intro   Kernel   UMIP   Racoon   Config(HA|MN|NEMO)   Changelog

Building a MIGRATEv2-ready Kernel

This section describes all the steps to patch, configure, build and install a MIGRATEv2-enabled kernel that will support IPv6 mobility in IPsec environments using Dynamic Keying (IKE). The current document is based on a 2.6.29.5 kernel.

Download the kernel sources from kernel.org. For example with a 2.6.29.5 kernel:

$ cd /usr/src/
$ wget http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.29.5.tar.gz

Verify the integrity of the downloaded kernel sources:

$ wget http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.29.5.tar.gz.sign
$ gpg --keyserver wwwkeys.pgp.net --recv-keys 0x517D0F0E
$ gpg --verify linux-2.6.29.5.tar.gz.sign 
gpg: Signature made Mon 15 Jun 2009 09:12:59 PM CEST using DSA key ID 517D0F0E
gpg: Good signature from "Linux Kernel Archives Verification Key <ftpadmin@kernel.org>"

Uncompress the sources, and create a symbolic link to the kernel sources:

$ tar zxf linux-2.6.29.tar.gz
$ rm linux-2.6.29.tar.gz*
$ ln -s /usr/src/linux-2.6.29.5/include /usr/src/linux
$ cd linux-2.6.29

Let's now grab MIGRATEv2 kernel patches. The set of patches is a quilt repository maintained using git. After issuing the following command, you will be provided with a patches/ folder at the root of your kernel tree.

$ git clone git://git.umip.org/migrate2_kernel_patches.git
Cloning into migrate2_kernel_patches...
remote: Counting objects: 192, done.
remote: Compressing objects: 100% (192/192), done.
remote: Total 192 (delta 0), reused 192 (delta 0)
Receiving objects: 100% (192/192), 211.38 KiB, done.

I encourage you to perform a "git log" call to get some information on the latest patchset (tip) to verify that the set of patches is suitable for your version of the kernel.

$ cd patches/
$ git log
commit f4116df8af1e507590b3b126bcd08a18d92f5e7a
Author: Arnaud Ebalard <arno@natisbad.org>
Date:   Wed Mar 25 14:20:40 2009 +0100

    Update for 2.6.29
...
$ cd ..

For the reader not familiar with quilt, all the files in the patches/ folder (apart from the series file) are patches and the series file provide the order in which the patches will be applied.

$ ls patches/
prevent_larval_states_migration.patch
series
set_mip6_ipsec_fw_kernel_options.patch

$ cat patches/series 
set_mip6_ipsec_fw_kernel_options.patch
prevent_larval_states_migration.patch

quilt is used to simplify the application of patches. This is done by issuing the following command (you may need to install the quilt package for your operating system):

$ quilt push -a
Applying patch set_mip6_ipsec_fw_kernel_options.patch
patching file set_mip6_ipsec_fw_kernel_options.sh

Applying patch prevent_larval_states_migration.patch
patching file net/xfrm/xfrm_state.c

Now at patch prevent_larval_states_migration.patch

Now that you have a patched kernel, it can be configured, and then compiled, as usual. Because UMIP and racoon will require some options to be set and to avoid the burden of finding and setting them, a script is provided for that purpose (if you want to do it by hand, just skip the associated step described below). Note that the script configures the kernel with static support (i.e. not module) for required features. Feel free to modify it to suit your needs. In practice, you can simply (and usually) reuse your old running kernel configuration and then set the required options:

$ make oldconfig
$ chmod u+x set_mip6_ipsec_fw_kernel_options.sh
$ ./set_mip6_ipsec_fw_kernel_options.sh .config

You can now proceed to the kernel compilation and installation:

$ make
# make install
# make modules_install

Verify your bootloader configuration and reboot on your new kernel.

Intro   Kernel   UMIP   Racoon   Config(HA|MN|NEMO)   Changelog

Building the UMIP Userland from the Sources

MIGRATEv2 support for UMIP is available from our umip.git repository. Simply follow the instructions available on this page to build UMIP. As an alternative, you can also use our UMIP Debian packages.

The necessary UMIP configuration is described later in the document, after the IPsec-tools (racoon) packages generation.

Intro   Kernel   UMIP   Racoon   Config(HA|MN|NEMO)   Changelog

Racoon

IPsec-Tools is a port of KAME's IPsec utilities to the Linux-2.6 IPsec implementation. It supports NetBSD and FreeBSD as well. It is mainly composed of following parts:

At the time of writing, racoon does not support MIGRATE (neither the 04 version, nor 05 version of the draft). For that reason, it needs to be patched. We will use the development tree of ipsec-tools which is maintained with CVS. It can be checked out using the following command:

$ cd /usr/src/
$ cvs -danoncvs@anoncvs.netbsd.org:/cvsroot co ipsec-tools
cvs checkout: Updating ipsec-tools
U ipsec-tools/.cvsignore
U ipsec-tools/ChangeLog
U ipsec-tools/Makefile.am
U ipsec-tools/NEWS
...

We provide two git repositories destined to racoon: one contains the necessary patches to support MIGRATE, another one can be used to build easily Debian packages. Under Debian, the process to assemble all the pieces together and then build the package is the following:

$ mv ipsec-tools ipsec-tools-umip-0.7
$ cd ipsec-tools-umip-0.7
$ git clone git://git.umip.org/racoon/debian.git
$ cd debian/
$ git clone git://git.umip.org/racoon/patches.git
$ cd ..

When dpkg-buildpackage is called (see below), quilt takes care (as asked in the Debian "rule" file in the debian/ folder) of applying the patches from the debian/patches/ directory. Before issuing the following command, please verify that:

$ dpkg-buildpackage -us -uc -sd -b -i -I.git
...
dh_builddeb
        dpkg-deb --build debian/ipsec-tools-umip ..
dpkg-deb: building package `ipsec-tools-umip' in `../ipsec-tools-umip_0.7-17_i386.deb'.
        dpkg-deb --build debian/racoon-umip ..
dpkg-deb: building package `racoon-umip' in `../racoon-umip_0.7-17_i386.deb'.
# we have no indep packages
# we have no architecture independant stuff yet
 dpkg-genchanges -b -sd >../ipsec-tools-umip_0.7-17_i386.changes
dpkg-genchanges: binary-only upload - not including any source code
dpkg-buildpackage: binary only upload (no source included)

You can then install the packages:

$ sudo dpkg -i ../ipsec-tools-umip_0.7-17_i386.deb
$ sudo dpkg -i ../racoon-umip_0.7-17_i386.deb

As an alternative, you can also use our UMIP Debian repository that includes the racoon-umip and ipsec-tools-umip packages.

Racoon configuration is described in the next section.

Intro   Kernel   UMIP   Racoon   Config(HA|MN|NEMO)   Changelog

UMIP and Racoon Configuration

The testbed topology is exactly the same as the one exposed in the static IPsec keying Mobile IPv6 documentation. It is thus preferable that you already have a working Mobile IPv6 testbed before going any further. We will cover here the changes required to use dynamic keying (instead of static keying) on the HA first, then on the MN.

To avoid spending hours at debugging stupid issues, you should definitely get familiar with racoon and UMIP configuration in general (reading the man pages, setting up simple configuration of UMIP without dynamic keying, and simple configuration of racoon without mobility).

Intro   Kernel   UMIP   Racoon   Config(HA|MN|NEMO)   Changelog

Configuring the Home Agent

In this subsection, we cover the configuration of the HA: first the UMIP part, and then the IPsec/IKE related part.

UMIP configuration

Here is a modified UMIP Home Agent configuration with dynamic keying. Changes made in the file are marked with DYNAMIC KEYING. Modify your /usr/local/etc/mip6d.conf file accordingly.

# Sample UMIP configuration file for a MIPv6 Home Agent
NodeConfig HA;

# Set DebugLevel to 0 if you do not want debug messages
DebugLevel 10;

# Replace eth0 with the interface connected to the home link
Interface "eth0";

# Binding information
BindingAclPolicy 2001:db8:ffff:0::1 allow;
DefaultBindingAclPolicy deny;

# Enable IPsec static keying
UseMnHaIPsec enabled;
KeyMngMobCapability enabled;            ## DYNAMIC KEYING ##

# IPsec Security Policies information
IPsecPolicySet {
    HomeAgentAddress 2001:db8:ffff:0::1000
    HomeAddress 2001:db8:ffff:0::1/64;
 
    IPsecPolicy Mh UseESP;              ## DYNAMIC KEYING ##
    IPsecPolicy TunnelPayload UseESP;   ## DYNAMIC KEYING ##
}

The KeyMngMobCapability parameter is set to enabled. It allows to set the K bit in Binding Acknowledgments sent to the peer, indicating that our IKE daemon support movement (i.e. is able to update its Security Aassociations and Security Policies on movement). In practice though, the value is not considered in the UMIP code. The IPsecPolicy parameters have also been updated: we have removed the last arguments.

Similarly as the static keying configuration, we simply ask for IPsec protection using ESP for signaling traffic between the MN and the HA, i.e. traffic using Mobility Header (IPsecPolicy Mh UseESP;), and for data traffic tunneled between the MN and the HA (IPsecPolicy TunnelPayload UseESP;) Those rules cover all traffic (data and MIPv6 signaling) between the MN and the HA.

UMIP will use the configuration information to setup a set of specific IPsec Security Policies for the two rules, which will require SA to be present or negotiated in order for associated traffic to flow. In our setup, the negotiation of the SA is performed dynamically by the IKE daemon (racoon). UMIP will also send locally the required messages (MIGRATE) to the IPsec stack and the IKE daemon upon movement.

Without entering the details of the implementation, UMIP sends MIGRATE messages using Netlink so that they get processed by XFRM framework in the kernel (update of Security Policies / Security Associations). XFRM then handles the emission of the MIGRATE messages to the registered key managers, no matter if they use PF_KEY or Netlink. For racoon, PF_KEY is used.


Racoon configuration

Now that UMIP configuration has been performed, the HA still lacks the Security Associations to protect the flows referenced by the Security Policies we have required. We delegate that job to racoon, both on the HA and the MN. We will thus not need to write any IPsec SA configuration by ourselves (contrary to the static keying testbed). Below, we cover the HA part.

The racoon configuration is composed of a main file and specific configuration files for every user, which are included in the main configuration. On the HA, the main configuration file (/etc/racoon/racoon.conf) looks like this:

path certificate "/etc/racoon/certs/";
path script "/etc/racoon/scripts";
path backupsa "/var/log/racoon_sa_dump.log";
#log debug2;
 
#privsep {} will be seen later.
 
timer {
        # All timers are set to their default values. 
        counter 5;
        interval 10 secs;
        persend 1;
        phase1 30 secs;
        phase2 20 secs;
        #natt_keepalive 20 secs;
}
 
listen { 
}
 
gss_id_enc utf-16le ;
 
remote anonymous {
        exchange_mode main;
        doi ipsec_doi;
        situation identity_only; 
        my_identifier asn1dn ; 
        peers_identifier asn1dn "C=FR, ST=FRANCE, O=NATISBAD, \
                                 OU=IPsec Services, CN=*, emailAddress=*";
        verify_identifier on;
        certificate_type x509 "ha.crt" "ha.key";
        ca_type x509 "ca_ipsec-crt.pem";
        verify_cert on;
        lifetime time 24 hour;
        ike_frag on;
        # esp_frag fraglen;
        initial_contact on;
        passive on; 
        proposal_check obey;
        support_proxy on;
        nonce_size 16;
 
        proposal {
                encryption_algorithm aes; # only for Oakley
                hash_algorithm sha1;
                authentication_method rsasig;
                dh_group modp2048;
                lifetime time 4 hours ; 
        }
}
 
padding {
        randomize off;
        randomize_length on ;  # set it in the future
        maximum_length 20 ;    # set it in the future
        exclusive_tail off ;
        strict_check off;
}
 
include "/etc/racoon/racoon.conf.d/one.user.racoon.conf";
#include "/etc/racoon/racoon.conf.d/another.user.conf";

Our purpose is not to document racoon configuration from scratch but comment the differences and important points required for things to work correctly in a Mobile IPv6 context.

The path parameters reflects the folder where the certificates and keys are stored. We do not use scripts in our setup.

Privilege separation (privsep) is not configured/enabled because we did not take the time to test it yet.

We have some common values for timers. You should be able to change them to fit your needs afterwhile.

Because we have multiple interfaces on the HA, we simply let racoon bind on all interfaces.

For handling our MN and negotiate Phase 1 with the remote peers that use unknown CoA, we use an anonymous remote section. During the setup of this ISAKMP SA, the HA will send the DN of its certificate as ID (configuration of our MNs expect that as we will see later). In the end, the first set of important parameters are the following:

remote anonymous {
        ...
        my_identifier asn1dn ; 
        peers_identifier asn1dn "C=FR, ST=FRANCE, O=NATISBAD, \
                                 OU=IPsec Services, CN=*, emailAddress=*";
        verify_identifier on;
        certificate_type x509 "ha.crt" "ha.key";
        ca_type x509 "ca_ipsec-crt.pem";
        verify_cert on;
        ...
}

The HA will use the DN of its certificate (provided with its key by certificate_type x509 ... parameter) because it is told to do so by my_identifier asn1dn ...; option. Verification of peer certificate will occur (because verify_cert is enabled) using the X.509 anchor pointed by ca_type x509 ... parameter.

Additionally, to filter the peers on the ID they present during Phase 1, verify_identifier is enabled and a string with wildcard is provided using peers_identifier asn1dn ...;. If you intend to do that to, please test your setup first without verify_identifier enabled and then activate it to avoid stacking multiple issues: racoon is quite touchy with that option.

In the rest of the configuration, among important parameters, passive should be enabled on the HA, the beginning of the negotiation been done by the MN.

support_proxy must be enabled to allow the peer to negotiate SA for addresses different than the one it perform the negotiation with. MIPv6 bootstrapping process with IKE requires that (CoA is used to negotiate SA for the HoA).

There is no specific comment for our proposal: we use the same set of parameters for all nodes (AES 128, SHA1 with a 2048 bits DH group).

There are some parameters of remote section that are not listed here but deserve some comments. For instance, we expect generate_policy to be deactivated, which is done by default. DPD monitoring is deactivated (advertised but not used), which is what we want to avoid temporary deconnections to make SA timeout.

The next block deals with padding options. Just select the values you want and simply make sure that compatible value are configured on the peers.

We now cover the user-specific configuration files associated with every MN. They are all included using the include parameter. For example, our MN will use the following /etc/racoon/racoon.conf.d/one.user.racoon.conf file:

sainfo address 2001:db8:ffff:0::1000[0] 135 
       address 2001:db8:ffff:0::1[0] 135 
       from asn1dn "C=FR, ST=FRANCE, O=NATISBAD, OU=IPsec Services, \
                    CN=arno, emailAddress=arno@natisbad.org"
{
        pfs_group modp2048;
        lifetime time 4 hours;     
        encryption_algorithm aes 128;
        authentication_algorithm hmac_sha1;
        compression_algorithm deflate;
}
 
sainfo subnet ::/0[0] 0
       address 2001:db8:ffff:0::1[0] 0
       from asn1dn "C=FR, ST=FRANCE, O=NATISBAD, OU=IPsec Services, \
                    CN=arno, emailAddress=arno@natisbad.org"
{
        pfs_group modp2048;
        lifetime time 4 hours;
        encryption_algorithm aes 128;
        authentication_algorithm hmac_sha1;
        compression_algorithm deflate;
}

As you can see (if you are already familiar with racoon configuration), the amount of per-user configuration is very limited. The two sainfo blocks respectively protect:

Both SA are specifically matched against the ID presented (verified during Phase 1) due to the from asn1dn parameters which creates the binding required by RFC 3775 and RFC 3776 between the identity of the MN (its certificate, here) and the HoA.


Other configurations

Other configurations (Router Advertisments, IPv6 forwarding, daemon starting) should be done as explained in the static IPsec keying Mobile IPv6 documentation. Note that setkey should not be executed: you should set the following parameter into the /etc/default/setkey file:

RUN_SETKEY=no

Also, note that racoon must be started before mip6d. Make sure your init.d scripts are called in the correct order (first racoon, then mip6d). You can start racoon manually with:

# /etc/init.d/racoon start
Intro   Kernel   UMIP   Racoon   Config(HA|MN|NEMO)   Changelog

Configuring the Mobile Node

Now that the configuration of the HA has been covered in the previous section, we deal here with the configuration of the MN. We will first cover the UMIP part, and then the IPsec/IKE related part.

UMIP configuration

Here is a modified UMIP Mobile Node configuration with dynamic keying. Changes made in the file are marked with DYNAMIC KEYING. Modify your /usr/local/etc/mip6d.conf file accordingly.

# Sample UMIP configuration file for a MIPv6 Mobile Node
NodeConfig MN;

# Set DebugLevel to 0 if you do not want debug messages
DebugLevel 10;

# Enable the optimistic handovers
OptimisticHandoff enabled;

# Disable RO with other MNs (it is not compatible 
# with IPsec Tunnel Payload)
DoRouteOptimizationMN disabled;
 
# The Binding Lifetime (in sec.)
MnMaxHaBindingLife 60;

# List here the interfaces that you will use 
# on your mobile node. The available one with 
# the smallest preference number will be used.
Interface "eth0" {
    MnIfPreference 1;
}
Interface "wlan0" {
    MnIfPreference 2;
}

# Replace eth0 with one of your interface used on
# your mobile node
MnHomeLink "eth0" {
    HomeAgentAddress 2001:db8:ffff:0::1000;
    HomeAddress 2001:db8:ffff:0::1/64;
}

# Enable IPsec static keying
UseMnHaIPsec enabled;
KeyMngMobCapability enabled;           ## DYNAMIC KEYING ##

# IPsec Security Policies information
IPsecPolicySet {
    HomeAgentAddress 2001:db8:ffff:0::1000;
    HomeAddress 2001:db8:ffff:0::1/64 ;
 
    IPsecPolicy Mh UseESP;             ## DYNAMIC KEYING ##
    IPsecPolicy TunnelPayload UseESP;  ## DYNAMIC KEYING ##
}

The changes operated on the MN configuration file are the same as the one we did on the HA configuration. The other parameters keep the same values as for the static keying testbed.


Racoon configuration

Let's now take a look at the MN's /etc/racoon/racoon.conf file and comment the differences with the previously studied HA's racoon configuration file. Note that we do not have a split version of the configuration on the MN, i.e. sainfo { ... } blocks are in the main file.

path certificate "/etc/racoon/certs/";
path script "/etc/racoon/scripts";
path backupsa "/var/log/racoon_sa_dump.log";
gss_id_enc utf-16le ;
 
timer {
        # All timers are set to their default values. 
        counter 5;
        interval 5 secs;
        persend 1;
        phase1 300 secs;
        phase2 600 secs;
        #natt_keepalive 20 secs;
}
 
listen {
}
 
remote 2001:db8:ffff:0::1000
{
        exchange_mode main;
        doi ipsec_doi;
        situation identity_only;
        my_identifier asn1dn ;
        peers_identifier asn1dn "C=FR, ST=FRANCE, O=NATISBAD, OU=IPsec Services, \
                                 CN=ha1, emailAddress=arno@natisbad.org";
        certificate_type x509 "arno-crt.pem" "arno.key";
        ca_type x509 "ca_ipsec-crt.pem";
        verify_identifier on;
        verify_cert on;
        lifetime time 24 hour;
        ike_frag on;
        initial_contact on;
        passive off;
        proposal_check obey;
        support_proxy on;
        generate_policy off;
        nonce_size 16;
 
        proposal {
                encryption_algorithm aes ; 
                hash_algorithm sha1;
                authentication_method rsasig;
                dh_group modp2048;
                lifetime time 4 hours ; 
        }
}
 
sainfo address 2001:db8:ffff:0::1[0] 135
       address 2001:db8:ffff:0::1000[0] 135
       from asn1dn "C=FR, ST=FRANCE, O=NATISBAD, OU=IPsec Services, \
                    CN=ha1, emailAddress=arno@natisbad.org";
{
        pfs_group modp2048;                
        lifetime time 2 hours;     
        encryption_algorithm aes 128;
        authentication_algorithm hmac_sha1;
        compression_algorithm deflate;
}
 
sainfo address 2001:db8:ffff:0::1[0] 0
       subnet ::/0[0] 0
       from asn1dn "C=FR, ST=FRANCE, O=NATISBAD, OU=IPsec Services, \
                    CN=ha1, emailAddress=arno@natisbad.org";
{
        pfs_group modp2048;                
        lifetime time 2 hours;     
        encryption_algorithm aes 128;
        authentication_algorithm hmac_sha1;
        compression_algorithm deflate;
}
 
padding {
        randomize off;
        randomize_length on;
        maximum_length 20;
        exclusive_tail off;    
        strict_check off;
}

The first difference is that the remote block is no more anonymous. The address of MN's HA is provided (2001:db8:ffff:0::1000). In that block, the peer_identifier that the MN should provide as ID during Phase 1 is set in an unambiguous fashion, without a wildcard for the CN RDN ("ha1" is expected here). Like it was required on the HA, the ID presented during Phase 1 will be checked against the subject's DN of the peers certificate (verify_identifier being enabled).

Still in remote block, the passive parameter is set to off this time in order to have racoon initiate a negotiation with the IKE daemon on its HA when a packet matching a SP previously configured on the system (by UMIP) has triggered a PF_KEY ACQUIRE message by the kernel.

Then, in the rest of the configuration, the only thing you might be interested in checking is that the address of sainfo blocks are in the correct (reversed) order, when compared to their counterpart in HA configuration file


Other configurations

Similarly to the Home Agent, other configurations for the MN should be done as explained in the static IPsec keying Mobile IPv6 documentation. Note that setkey should not be executed: you should set the following parameter into the /etc/default/setkey file:

RUN_SETKEY=no

Also, note that racoon must be started before mip6d. Make sure your init.d scripts are called in the correct order (first racoon, then mip6d). You can start racoon manually with:

# /etc/init.d/racoon start
Intro   Kernel   UMIP   Racoon   Config(HA|MN|NEMO)   Changelog

NEMO Basic Support and Dynamic Keying

You may also be interested in using dynamic keying between your Mobile Router and your Home Agent. This is pretty straigthforward: simply follow the NEMO Basic Support documentation. Nothing more is needed on the racoon side! The reason is that the tunnel mode SA racoon will negotiate are suitable for handling the protection of tunneled traffic by default. The Security Policies that UMIP will put for the prefixes will do the rest of the magic.

Intro   Kernel   UMIP   Racoon   Config(HA|MN|NEMO)   Changelog

Changelog