HowTo: Dynamic keying for Mobile IPv6 using racoon2 and mip6d

Version: 1.1
Date: May 22nd, 2009.
Author: Sebastien Decugis, Nautilus6 project
Support mailing-list: support@ml.nautilus6.org

History:

 
Latest version always available at http://www.nautilus6.org/doc/dk-howto/Howto_dynamic_keying.html

2009.05.22 (1.1): 
  * Fix a bug in racoon2 configuration files (missing quote).
  
2007.09.26 (1.0):
  * New gutsy repository.
  * Patchs are now online at http://www.nautilus6.org/~sdecugis/dynamic_keying/
  * Updated build process.
  * New script for managing the X509 certificates creation.

2007.08.13 (draft-1):
  * Initial release.

Table of Content:

  1. Introduction
  2. Building the environment
    1. Linux kernel
    2. IKEv2 daemon: racoon2
    3. MIPv6 daemon: mip6d (umip)
  3. Creating the configuration files
    1. Before you start
    2. Network topology
    3. Creating the self-signed X509 certificates
    4. Configuring racoon2 on the Home Agent
    5. Configuring mip6d on the Home Agent
    6. Configuring racoon2 on the Mobile Node
    7. Configuring mip6d on the Mobile Node
  4. Starting the daemons

Introduction

Mobile IPv6 is a protocol that allows a node (called Mobile Node -- MN) to move its point of attachement to the IPv6 network (and therefore its IPv6 address, called Care-of Address -- CoA) and remain reachable at a constant IPv6 address (called its Home Address -- HoA). That Home Address belongs to a network for which a routeur that serves the prefix of the HoA will have a special role in the Mobile IPv6 protocol. That routeur is called the Home Agent (HA). Basically, when a packet reaches the Home Link and the mobile is in a foreign network (with a Care-of Address registered to the Home Agent), then the Home Agent will tunnel the packet to the Mobile Node. RFC3775 standardizes the Mobile IPv6 protocol.

The Mobile IPv6 protocol makes mandatory the use of IPsec to protect some of the exchanges of packets between the MN and the HA, and optionnally protect other exchanges. RFC4877 explains how IKEv2 protocol can be used to negociate the Security Associations between the MN and the HA to protect Mobile IPv6 traffic.

The internet draft draft-sugimoto-mip6-pfkey-migrate-03 gives some more detail on how the Mobile IPv6 daemon and the IKEv2 daemon can exchange information. The solution that is described in this HowTo uses the MIGRATE and SADB_X_EXT_PACKET extension as described in this draft.

The following components are involved:

This tutorial assumes that the reader already has some knowledges of mip6d configuration and racoon2 configuration. It is advised to start by setting an environment of Mobile IPv6 without using the IPsec (setup a Home Agent, a Mobile Node, check that the MN properly register to its HA when connected to a foreign network, ...)

Building the environment

For people that don't want to go through the long and painful path of building their own kernel and binaries, the Nautilus6 project maintains package repositories, for Debian and Ubuntu distributions, with ready-to-use binaries for this tutorial. These repositories can be found at:
A Ubuntu LiveCD with all mobility components included is also available from the Nautilus6 project.

Note that the steps described here (Linux kernel, racoon2 and mip6d daemons) will need to be executed both on the HA and the MN.

Linux kernel

You will need to retrieve a Linux kernel, then apply some patchs on top of it, then configure, build, and install it.

I am using the Linux 2.6.22 kernel with a set of patchs from the USAGI project http://www.linux-ipv6.org  for this tutorial. You may have some more recent kernel available at the time you are reading this. The USAGI project maintains its source tree with git. You can see the gitweb here: http://www.linux-ipv6.org/gitweb/gitweb.cgi?p=gitroot/nakam/linux-2.6-mip6.git;a=summary

We will just retrieve the version tagged "linux-2.6.22-mip6" here. First, we need to clone the repository:
$ pwd
/home/dk
$ git clone git://git.linux-ipv6.org/gitroot/nakam/linux-2.6-mip6
Initialized empty Git repository in /home/dk/linux-2.6-mip6/.git/
(...)
Since the repository is quite big, that operation will take a while.
$ cd linux-2.6-mip6
$ git checkout 91e704f7727
HEAD is now at 91e704f... [PATCH 2/3] [IPV6]: Do not send RH0 anymore.
At that point, we have the linux-2.6.22 source tree with mobile IPv6 patchs applied.

We now need to add the support of SADB_X_EXT_PACKET extension. To achieve this, you will need to retrieve the patch (implementation by Arnaud Ebalard) at the following URL:
$ wget http://www.nautilus6.org/~sdecugis/dynamic_keying/kernel/SADB_X_EXT_PACKET-linux-2.6-mip6-branch2.6.22.patch
We also need a workaround to avoid kernel panic in some cases:
$ wget http://www.nautilus6.org/~sdecugis/dynamic_keying/kernel/kernel_panic_tunnel_payload_workaround.patch
Now, apply these patchs on the tree:
$ cat *.patch | patch -p1
Next step is to configure this kernel. Here are a few configure directives that you should ensure to set properly.
You may alternatively use the config file provided at the same location as the patches (rename to .config).
(in general)
CONFIG_LOCALVERSION="-mip6dk"

(in networking)
CONFIG_XFRM
CONFIG_XFRM_USER
CONFIG_XFRM_SUB_POLICY
CONFIG_XFRM_MIGRATE
CONFIG_NET_KEY
CONFIG_NET_KEY_MIGRATE
CONFIG_SADB_X_EXT_PACKET
CONFIG_IPV6
CONFIG_INET6_AH
CONFIG_INET6_ESP
CONFIG_IPV6_MIP6
CONFIG_INET6_XFRM_MODE_TRANSPORT
CONFIG_INET6_XFRM_MODE_TUNNEL
CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION
CONFIG_IPV6_TUNNEL
CONFIG_IPV6_MULTIPLE_TABLES
CONFIG_IPV6_SUBTREES

(in Cryptographic API)
CONFIG_CRYPTO_HMAC
CONFIG_CRYPTO_XCBC
CONFIG_CRYPTO_NULL
CONFIG_CRYPTO_MD5
CONFIG_CRYPTO_SHA1
CONFIG_CRYPTO_SHA256
CONFIG_CRYPTO_SHA512
CONFIG_CRYPTO_ECB
CONFIG_CRYPTO_CBC
CONFIG_CRYPTO_DES
CONFIG_CRYPTO_AES
CONFIG_CRYPTO_AES_586

Then, make and install your kernel. On Ubuntu this can be done with:

$ make oldconfig
$ make
$ make modules
$ sudo make modules_install
$ sudo make install
$ sudo update-initramfs -c -k 2.6.22-mip6dk

Don't forget to edit your /boot/grub/menu.lst file to add an entry to your new kernel (or use update-grub utility). Then reboot your machine on the new kernel.

IKEv2 daemon: racoon2

The racoon2 source tree is managed with CVS. See http://www.racoon2.wide.ad.jp/w/ website for more information. Since there are regular commits on this CVS tree, the patchs that you will need to apply may need some work. You can always retrieve version from 2007/08/09 when the patchs have been created. And also, you can use the binaries from Nautilus6 project package repository directly.

Retrieve the latest sources:
$ cvs -d :pserver:anoncvs:anoncvs@anoncvs.racoon2.wide.ad.jp:/anoncvs/racoon2 co racoon2
$ cd racoon2

You will need also the set of patchs for implementing mobility support in racoon2. The patchs were submitted to racoon2-users mailing list, in this post: http://www.racoon2.wide.ad.jp/ml/racoon2-users/200708/msg248.html. You can find a short explanation of each part of the patch there.

You can download directly the patchs at the following URLs: 

$ wget http://www.nautilus6.org/~sdecugis/dynamic_keying/racoon2/01_fix_transmit_response_addresses.patch
$ wget http://www.nautilus6.org/~sdecugis/dynamic_keying/racoon2/02_support_altcoa_in_ext-packet.patch
$ wget http://www.nautilus6.org/~sdecugis/dynamic_keying/racoon2/03_support_asymetrical_TS_for_MH.patch
$ wget http://www.nautilus6.org/~sdecugis/dynamic_keying/racoon2/04_support_external_spd_entries.patch
$ wget http://www.nautilus6.org/~sdecugis/dynamic_keying/racoon2/05_support_dynamic_conf_reload-lite.patch
$ wget http://www.nautilus6.org/~sdecugis/dynamic_keying/racoon2/06_fix_make_install.patch

Then patch you racoon2 souce tree:

$ cat *.patch | patch -p1
Now you are ready to configure and compile racoon2. 
$ ./configure --with-kernel-build-dir=/home/dk/linux-2.6-mip6 --enable-updateifaddr --prefix=/usr --sysconfdir=/etc/racoon2
$ make
$ sudo make install
Note that a sample configuration file is created in /etc/racoon2/ directory. You will need to edit this file later.

MIPv6 daemon: mip6d (umip)

For this daemon, we will also use the version from USAGI project. This consists in a set of patchs (called UMIP) on top of the GO/Core version MIPL2 which support seems to be discontinued. You can retrieve the latest stable version here:
$ wget ftp://ftp.linux-ipv6.org/pub/usagi/patch/mipv6/umip-0.4/daemon/tarball/mipv6-daemon-umip-0.4.tar.gz
$ tar zxf mipv6-daemon-umip-0.4.tar.gz
Patches are not needed for mip6d daemon. We provide some convenient features in Nautilus 6 package, such as ability to split the configuration file (based on each mobile node, for example.) You can retrieve our patchs by using apt-get source.
$ cd mipv6-daemon-umip-0.4
$ autoreconf -i
$ CPPFLAGS=-I/home/dk/linux-2.6-mip6/include ./configure --enable-vt --prefix=/usr --sysconfdir=/etc
$ make
$ sudo make install
The configuration file for this daemon is /etc/mip6d.conf. We will see in next section how it must be configured.

Creating the configuration files

Before you start

The IKEv2 protocol requires that both peers are able to authentify one each other. Racoon2 provides several mechanisms for this authentication. We will use X509 certificates. This provides a mean to both identify the mobile node (using the certificate subject) and authenticate it. We will not explain here how a clean Public Key Infrastructure must be set up. We will use a simple script to simulate a CA. Racoon2 uses internally openssl to manage and verify certificates validity, so one should refer to openssl documentation for more detail on this topic.

Network topology

We will assume the following physical configuration for the rest of this document. You will need to adapt to your own network topology.

----------------------------------------------------------- uplink (to the Internet) prefix: 2001:DB8:0:1::/64
| | |
| 2001:DB8:0:1::3 | 2001:DB8:0:1::4 | 2001:DB8:0:1::1
R3 R4 HA
| 2001:DB8:0:3::/64 | 2001:DB8:0:4::/64 | 2001:DB8:0:2::1/64
(CoA3) (CoA4) (HoA) 
CoA3 and CoA4 are the other possible points of attachement when the mobile node is not at home link.
It is assumed that the Home Agent is configured properly with regards to routing daemons and router advertisements. In our Nautilus6 testbed, we have used radvd and quagga (RIPng) with no problem.

Creating the X509 certificates

For this step, we will use a simple script to simulate a Certificate Authority on the Home Agent. A real deployment scenario should of course manage the certificates with more care.
# mkdir /etc/openssl-ca
# cd /etc/openssl-ca
# wget http://www.nautilus6.org/~sdecugis/dynamic_keying/pki/Makefile
# wget http://www.nautilus6.org/~sdecugis/dynamic_keying/pki/openssl.cnf
You can get some help on the script by typing "make". We will now initialize our lite CA:
# make init CA_CN=dk-ha.mydomain.com CA_mail=ha-admin@mydomain.com
You can of course set the values as you want. This command creates a basical CA structure. We will use the CA certificate for the HA (for simplicity, but this should never be the case in real-life), and now we generate another certificate for the MN:
# make newcsr name=mn.mydomain.com email=mn-user@mydomain.com
# make cert name=mn.mydomain.com
Now, you need to copy the MN's private key (/etc/openssl-ca/clients/privkeys/mn.mydomain.com.key.pem) and certificate (/etc/openssl-ca/clients/certs/mn.mydomain.com.cert), and the HA certificate (/etc/openssl-ca/public-www/cacert.pem) to the /etc/racoon2/certs folder on the MN.

Configuring racoon2 on the Home Agent

The /etc/racoon2 directory should already contain some sample files. We will use these files to create our configuration:
# cd /etc/racoon2
# cp default.conf.sample default.conf

Create a new file racoon2.conf. Here is the (minimal) content:

interface {
ike { MY_IP; };
spmd { unix "/var/run/racoon2/spmif"; };
spmd_password "/etc/racoon2/spmd.pwd";
};
resolver {
resolver off;
};
include "/etc/racoon2/default.conf";
include "/etc/racoon2/ha.conf";

Then edit the default.conf file. You have to check that the default { remote { } } directive contains acceptable_kmp with at least ikev2. You can adjust the values for SA lifetimes, algorithms, and so on in this file if you need.

Finally, create the file ha.conf. Here is a sample:

# Home Agent address:  2001:DB8:0:2::1
# MN Home address : 2001:DB8:0:2::2

remote MobileNode {
ikev2 {
my_id x509_subject "/etc/openssl-ca/public-www/cacert.pem";
peers_id x509_subject "/etc/openssl-ca/clients/certs/mn.mydomain.com.cert";
kmp_auth_method { rsasig; };
my_public_key x509pem
"/etc/openssl-ca/public-www/cacert.pem"
"/etc/openssl-ca/private/cakey.pem";
peers_public_key x509pem
"/etc/openssl-ca/clients/certs/mn.mydomain.com.cert"
"";
};
};

# Policy and selector for protecting the BU/BA messages for Home Registration.
policy HomeRegBinding {
remote_index MobileNode;
ipsec_mode transport;
action auto_ipsec;
ipsec_index { ipsec_esp; };
ipsec_level require;
peers_sa_ipaddr 2001:DB8:0:2::2;
my_sa_ipaddr 2001:DB8:0:2::1;
install off;
};
selector HomeRegBinding_out {
direction outbound;
dst 2001:DB8:0:2::2;
src 2001:DB8:0:2::1;
policy_index HomeRegBinding;
upper_layer_protocol 135 6 5;
reqid 201; # Note: you may choose whatever value you want but must be in sync with mip6d.conf and unique.
};

# Policy and selector for protecting the MPS/MPA messages for Mobile Prefix Discovery.
policy MobPfxDisc {
remote_index MobileNode;
ipsec_mode transport;
action auto_ipsec;
ipsec_index { ipsec_esp; };
ipsec_level require;
peers_sa_ipaddr 2001:DB8:0:2::2;
my_sa_ipaddr 2001:DB8:0:2::1;
install off;
};
selector MobPfxDisc_out {
direction outbound;
dst 2001:DB8:0:2::2;
src 2001:DB8:0:2::1;
policy_index MobPfxDisc;
upper_layer_protocol 135 93 92;
reqid 203;
};

# Tunnel all traffic between MN and HA when the MN is not at home.
policy TunnelPayload {
remote_index MobileNode;
ipsec_mode tunnel;
action auto_ipsec;
ipsec_index { ipsec_esp; };
ipsec_level require;
peers_sa_ipaddr 2001:DB8:0:2::2;
my_sa_ipaddr 2001:DB8:0:2::1;
install off;
};
selector TunnelPayload_out {
direction outbound;
dst 2001:DB8:0:2::2;
src 2001:DB8:0:2::1;
policy_index TunnelPayload;
reqid 205;
};

This is just an example configuration file showing how you can define different SA for protecting different messages. You could define different parameters for IPsec for each of these policies. In any case, don't forget to set the "reqid" to a value consistent with mip6d.conf file and the "install off;" flag in the policies that are meant to be used with mip6d. You don't need to define the "inbound" selectors because they will not be used (this is due to the fact that the SPD entries are installed by mip6d, not racoon2.)

If later you want to have the racoon2 started automatically at system reboot, some initialization scripts are provided in /etc/racoon2/init.d directory. This is not documented in this HowTo.

Configuring mip6d on the Home Agent

You must create the /etc/mip6d.conf file. Here is an example of content for the Home Agent:

NodeConfig	HA;
Interface eth0; # the interface that serves the Home Link

UseMnHaIPsec enabled;
KeyMngMobCapability enabled; # currently has no effect, but should be set.

IPsecPolicySet {
HomeAgentAddress 2001:DB8:0:2::1;
HomeAddress 2001:DB8:0:2::2/64;

IPsecPolicy HomeRegBinding UseESP 201; # the value must match reqid from racoon2 conf
IPsecPolicy MobPfxDisc UseESP 203;
IPsecPolicy TunnelPayload UseESP 205;
}
See man mip6d.conf for more information on this file contents.

Configuring racoon2 on the Mobile Node

Create the default.conf and racoon2.conf files as in the Home Agent (replace ha.conf with mn.conf). Note that the default { remote { acceptable_kmp { }}} directive does not need to be present in the MN.

If you have not done already, copy from the HA the MN's private key (/etc/openssl-ca/clients/privkeys/mn.mydomain.com.key.pem) and certificate (/etc/openssl-ca/clients/certs/mn.mydomain.com.cert), and the HA certificate (/etc/openssl-ca/public-www/cacert.pem) to the /etc/racoon2/certs folder on the MN.

Then create the /etc/racoon2/mn.conf file as follow:
# Home Agent address:  2001:DB8:0:2::1
# MN Home address : 2001:DB8:0:2::2

remote HomeAgent {
ikev2 {
my_id x509_subject "/etc/racoon2/certs/mn.mydomain.com.cert";
peers_id x509_subject "/etc/racoon2/certs/cacert.pem";
kmp_auth_method { rsasig; };
my_public_key x509pem
"/etc/racoon2/certs/mn.mydomain.com.cert"
"/etc/racoon2/certs/mn.mydomain.com.key.pem";
peers_public_key x509pem
"/etc/racoon2/certs/cacert.pem"
"";
};
};

# Policy and selector for protecting the BU/BA messages for Home Registration.
policy HomeRegBinding {
remote_index HomeAgent;
ipsec_mode transport;
action auto_ipsec;
ipsec_index { ipsec_esp; };
ipsec_level require;
peers_sa_ipaddr 2001:DB8:0:2::1;
my_sa_ipaddr 2001:DB8:0:2::2;
install off;
};
selector HomeRegBinding_out {
direction outbound;
dst 2001:DB8:0:2::1;
src 2001:DB8:0:2::2;
policy_index HomeRegBinding;
upper_layer_protocol 135 5 6;
reqid 200; # Note: you may choose whatever value you want but must be in sync with mip6d.conf and unique.
};

# Policy and selector for protecting the MPS/MPA messages for Mobile Prefix Discovery.
policy MobPfxDisc {
remote_index HomeAgent;
ipsec_mode transport;
action auto_ipsec;
ipsec_index { ipsec_esp; };
ipsec_level require;
peers_sa_ipaddr 2001:DB8:0:2::1;
my_sa_ipaddr 2001:DB8:0:2::2;
install off;
};
selector MobPfxDisc_out {
direction outbound;
dst 2001:DB8:0:2::1;
src 2001:DB8:0:2::2;
policy_index MobPfxDisc;
upper_layer_protocol 135 92 93;
reqid 202;
};

# Tunnel all traffic between MN and HA when the MN is not at home.
policy TunnelPayload {
remote_index HomeAgent;
ipsec_mode tunnel;
action auto_ipsec;
ipsec_index { ipsec_esp; };
ipsec_level require;
peers_sa_ipaddr 2001:DB8:0:2::1;
my_sa_ipaddr 2001:DB8:0:2::2;
install off;
};
selector TunnelPayload_out {
direction outbound;
dst 2001:DB8:0:2::1;
src 2001:DB8:0:2::2;
policy_index TunnelPayload;
reqid 204;
};
As for the Home Agent, you may want to adjust the values here. Note that the MN is the initiator of IKEv2 exchanges, at least as far as transport-mode SA are concerned, so the SA lifetime should be set carefully as MN should be the node that initiates the rekeying requests.

Configuring mip6d on the Mobile Node

Here is a sample that you can use for your /etc/mip6d.conf file on the Mobile Node. You may want to change some values anyway, especially the interfaces definitions if your mobile node has several physical interfaces.
NodeConfig	MN;
DoRouteOptimizationMN disabled; # In case you want to TunnelPayload. Otherwise you must protect HoTi/CoTi exchanges instead.
UseCnBuAck enabled;
MnDiscardHaParamProb enabled;
MnRouterProbes 1;

Interface "eth0";
MnHomeLink "eth0" {
HomeAddress 2001:DB8:0:2::2/64;
HomeAgentAddress 2001:DB8:0:2::1;
}

UseMnHaIPsec enabled;
KeyMngMobCapability enabled;

IPsecPolicySet {
HomeAddress 2001:DB8:0:2::2/64;
HomeAgentAddress 2001:DB8:0:2::1;

IPsecPolicy HomeRegBinding UseESP 200;
IPsecPolicy MobPfxDisc UseESP 202;
IPsecPolicy TunnelPayload UseESP 204;
}

Starting the daemons

On each node (Home Agent and Mobile Node), the daemons must be started in this order:
  1. (HA only) Routing daemon (quagga), Router Advertisement daemon (radvd)
  2. spmd (component of racoon2)
  3. iked (component of racoon2)
  4. mip6d
The Home Agent mip6d must be started before Mobile Node's.

To facilitate debugging, you can start the daemons with the following options, which will cause them to stay in foreground and issue lot of debugging messages:
# /usr/sbin/spmd -Fddd
# /usr/sbin/iked -Fddd
# /usr/sbin/mip6d -d 10
When you start you Mobile Node in a foreign network, and capture packets on its interface, here is the exchange that you should see:
MN -> HA: IKE_SA_INIT
MN <- HA: IKE_SA_INIT
MN -> HA: IKE_AUTH
MN <- HA: IKE_AUTH
MN -> HA: ESP (spi#1, contains the BU message)
MN <- HA: ESP (spi#2, contains the BA)
MN -> HA: CREATE_CHILD_SA
MN <- HA: CREATE_CHILD_SA
MN -> HA: ESP (spi#3, contains MPS)
MN <- HA: ESP (spi#4, contains MPA)

Then, when an exchange is started between the MN and a correspondent, a new CREATE_CHILD_SA exchange is started, either by the MN (if MN is initiating the exchange) or by HA (if the correspondent is initiating the exchange), and the negociated SA is used to protect all traffic between MN and HA.

Upon movement, the IKE_SA and tunnel-mode SA endpoints are updated with the new CoA. When the MN returns home, the SPD entries are deleted but the SA remains valid, and can be re-used when the SPD entries are added again, when MN moves again.

Note that if you don't have any tunnel-mode SPD entry (to protect either Payload or HomeTesting) the IKE_SA endpoints may not be updated upon movements, and this will result in iked unable to re-key the SA or negociate new ones.

End