Deploying IPsec/IKE-protected MIPv6 under Linux

Overview   Kernel   umip   racoon   config(HA|MN|MR and MRHA)   w/ miredo   FW   FAQ

Overview

Below, you'll find all the steps required to setup a complete IPsec/IKE-protected Mobile IPv6 environment under Linux. This page 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.

Those are followed by two sections respectively documenting the steps needed to use the setup from IPv4-only networks with Teredo (via miredo) and configure filtering.

A FAQ is available at the end of the page, providing answers for common questions.

Before you enter the funny part (the practice), it is important that you understand how the theoretical parts fit together.

Simply put, at the time of writing, IPsec/IKE is not considered as an interesting (enough) item by the MEXT WG which prefers normalizing new functionalities than finishing IPsec/IKE integration (IMHO).

If you are interested by a quick review of MIPv6-related documents in an IPsec/IKE context, here is an overview of key documents with some comments you might find useful to understand where we stand from a theoretical standpoint. This is a work in progress and reading again those documents takes quite some time, so be gentle.

Before patching, compiling, installing and configuring a kernel, umip and racoon, let's first take some time to describe the building blocks, their implementation status, their lacks and how they are intended to work together.

Overview   Kernel   umip   racoon   config(HA|MN|MR and MRHA)   w/ miredo   FW   FAQ

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).

Let's first grab the latest stable version of Linux kernel. At the time of writing, a 2.6.26 (Chances are high that the latest revision of Linus git tree or net-2.6 will be ok but I cannot promise).

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

$ gpg --verify linux-2.6.26.tar.gz.sign 
gpg: Signature made Mon 14 Jul 2008 12:43:03 AM CEST using DSA key ID 517D0F0E
gpg: Good signature from "Linux Kernel Archives Verification Key <ftpadmin@kernel.org>"

$ tar xzf linux-2.6.26.tar.gz
$ rm linux-2.6.26.tar.gz*
$ cd linux-2.6.26

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

$ hg clone http://hg.natisbad.org/migrate2_patches_kernel patches
requesting all changes
adding changesets
adding manifests
adding file changes
added 32 changesets with 65 changes to 23 files
updating working directory
3 files updated, 0 files merged, 0 files removed, 0 files unresolved

I encourage you to perform a "hg tip" 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
$ hg tip
changeset:   32:3b1d69f4a8fb
tag:         tip
user:        Arnaud EBALARD <arno@natisbad.org>
date:        Mon Jul 14 23:22:46 2008 +0200
summary:     Refresh for 2.6.26

$ 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/
MIGRATEv2_linux-2.6.26.patch
series
set_mip6_ipsec_fw_kernel_options.patch

$ cat patches/series
set_mip6_ipsec_fw_kernel_options.patch
MIGRATEv2_linux-2.6.26.patch

quilt is used to simplify the application of patches. This is done by issuing the following command.

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

Applying patch MIGRATEv2_linux-2.6.26.patch
patching file net/key/af_key.c
patching file net/xfrm/xfrm_policy.c
patching file net/xfrm/xfrm_state.c
patching file include/linux/xfrm.h
patching file include/net/xfrm.h
patching file net/xfrm/xfrm_user.c
patching file include/linux/pfkeyv2.h

Now at patch MIGRATEv2_linux-2.6.26.patch

Now that they have been applied, let's comment the purpose of each patch:

Now that I am (quite) confident that you have spent some time reading and understanding all previous steps, there is a small tip that will spare you some work when switching to a new version of the kernel. I make patched tarballs of the latest versions of the kernel available here. The files are signed with my old GPG key (0x047A5026).

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, I provide a script 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 for required features, and not modules. 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. The last steps below are the build and the installation of the kernel. We use Debian tools below to simplify that step, but feel free to use your usual method instead.

$ make oldconfig
$ chmod u+x set_mip6_ipsec_fw_kernel_options.sh
$ ./set_mip6_ipsec_fw_kernel_options.sh .config
$ make-kpkg --rootcmd fakeroot kernel_image
$ sudo dpkg -i ../linux-image-2.6.26_2.6.26-10.00.Custom_powerpc.deb 
Overview   Kernel   umip   racoon   config(HA|MN|MR and MRHA)   w/ miredo   FW   FAQ

umip

umip is maintained by people of USAGI and available from their GIT repository on linux-ipv6.org. Being in a stable state, the repository does not evolve a lot. USAGI developers now provide maintenance. Let's first clone the sources:

$ cd /usr/src
$ git clone git://git.linux-ipv6.org/gitroot/mipv6-daemon.git
Initialized empty Git repository in /usr/src/mipv6-daemon/.git/
remote: Generating pack...
remote: Done counting 1364 objects.
remote: Deltifying 1364 objects...
remote:  100% (1364/1364) done
remote: Total 1364 (delta 1038), reused 963 (delta 664)
Receiving objects: 100% (1364/1364), 545.98 KiB | 77 KiB/s, done.
Resolving deltas: 100% (1038/1038), done.

$ mv mipv6-daemon umip-0.4

Now that we have the sources, we still miss 2 things to use umip in the best conditions on Debian devices in an IPsec/IKE environment.

The main reason to maintain 2 separate repositories (i.e. not to have the set of patches in the debian/ folder) is for people not using Debian but another distribution. Anyway, under Debian, the process is the following:

$ cd umip-0.4
$ hg clone http://hg.natisbad.org/umip-pkg-debian-folder debian
$ cd debian
$ hg clone http://hg.natisbad.org/migrate2_patches_umip_nemo patches
$ cd ..

When dpkg-buildpackage is called (below), quilt takes care (as asked in the Debian "rule" file in the debian/ folder) of applying the patches.

Let's new build the package. Before issuing the following command, please verify that:

$ dpkg-buildpackage -us -uc -sd -b -i -I.hg
...
dpkg-deb: building package `umip' in `../umip_0.4-5_powerpc.deb'.
 dpkg-genchanges -b -sd >../umip_0.4-3_powerpc.changes
dpkg-genchanges: binary-only upload - not including any source code
dpkg-buildpackage: binary only upload (no source included)

You can then install the package:

$ sudo dpkg -i ../umip_0.4-5_powerpc.deb

Configuration is described later in the document, after ipsec-tools (racoon) packages generation.

TIP: As the whole process is a little annoying and error-prone, there is another way to access the package (for i386 and ppc) than building them yourself by hand if you are under Debian: I have set up an unofficial UMIP Debian repository to make your life easier. You just have to follow the steps described below in order to access umip package using your favourite package manager. Note that the packages available on the mirror are authenticated: for that purpose, the mirror has a dedicated GPG key that you should import in your Debian keyring using apt-key:

$ cd /tmp
$ wget -q http://natisbad.org/MIPv6/umip-unofficial-debian-mirror.key     # grab mirror key
$ wget -q http://natisbad.org/MIPv6/umip-unofficial-debian-mirror.key.asc # grab key sig
$ gpg --verify umip-unofficial-debian-mirror.key.asc                      # verify sig
gpg: Signature made Sun 27 Jun 2010 11:03:09 PM CEST using RSA key ID A7AE341B
gpg: Good signature from "Arnaud Ebalard <arno@natisbad.org>"
...
$ sudo apt-key add umip-unofficial-debian-mirror.key                # import key in keyring
OK
$ rm umip-unofficial-debian-mirror.key*                             # clean our mess

Then, you can simply add the following to you /etc/apt/sources.list file:

deb     http://natisbad.org/debian-umip/ unstable main contrib non-free
deb-src http://natisbad.org/debian-umip/ unstable main contrib non-free

You are now able to install umip the following way:

# apt-get update && apt-get install umip

You can even access the sources using "apt-get source" if you need.

Note that you should still come from time to time on the site and check the news if there is some post on the topic (about bugs, updates and changes).

Overview   Kernel   umip   racoon   config(HA|MN|MR and MRHA)   w/ miredo   FW   FAQ

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, I maintain since version 03 of the draft a set of patches that has progressively evolve from a PoC to a functional version.

At the time of 03 version, we started the development of patches based on a stub version provided by Francis Dupont. Yves-Alexis Perez then spent some time to add a limited version (MIPv6 packets only) of SADB_X_EXT_PACKET support in Linux kernel that could work with racoon and umip (mipl at the beginning). The code provided basic support for dynamic keying with MIPL (and then umip) but had some bugs (rekeying, ...) and proved to be impossible to maintain over time. SADB_X_EXT_PACKET mechanism also had some lacks and inherent complexity that prevented it to be used as a long term solution.

After some feedback to the authors of MIGRATE draft, I spend some time removing SADB_X_EXT_PACKET support from ipsec-tools and implementing a cleaner version of MIGRATE code in order to be able to push it to the developer when 05 version of the draft would be released. In the meantime, some simple patches unrelated to MIGRATE were accepted mainline. The expiration of MIGRATE draft (04 version) and lack of feedback from Francis (SADB_X_EXT_PACKET was initially his proposal) lead me to the publication of an IETF draft (co-authored with S. Decugis), replacing SADB_X_EXT_PACKET by simple enhancements of MIGRATE design. The current set of patches used below are based on this specification. More information on those patches can be found here.

Like for umip, 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
...

As for umip, I also maintain two mercurial repositories:

Under Debian, the process to assemble all pieces together and then build the package is the following:

$ mv ipsec-tools ipsec-tools-umip-0.7
$ cd ipsec-tools-umip-0.7
$ hg clone http://hg.natisbad.org/ipsec-tools-umip-pkg-debian-folder debian
$ cd debian
$ hg clone http://hg.natisbad.org/migrate2_patches_ipsec-tools patches
$ cd ..

When dpkg-buildpackage is called (below), quilt takes care (as asked in the Debian "rule" file in the debian/ folder) of applying the patches.

Before issuing the following command, please verify that:

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

You can then install the package:

$ sudo dpkg -i ../ipsec-tools-umip_0.7-3_powerpc.deb

Racoon configuration is described below.

TIP: If you have previously followed the steps to configure apt in order to access umip package via the unofficial UMIP Debian repository I have set up, you can directly access i386 and ppc versions of ipsec-tool-umip and racoon-umip packages using your favourite package manager: those are available from the repository.

Overview   Kernel   umip   racoon   config(HA|MN|MR and MRHA)   w/ miredo   FW   FAQ

Configuration

This section describes simultaneously UMIP and racoon configuration. The first part of this section covers HA configuration, the second MN configuration. The changes required to make your MN a MR are covered in a third part.

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). You have been warned: it is assumed in the rest of the document that you are familiar with both apps.

Below is a figure of the setup, followed by some comments.

Figure of HA and MN

The main elements we consider are the MN and its MN:

When it is not connected to its Home Link, the traffic exchanged between the MN and its HA is IPsec protected (tunnel mode). In all cases, its signaling traffic is protected using transport mode. Those set of SA are depicted by the red arrows.
Overview   Kernel   umip   racoon   config(HA|MN|MR and MRHA)   w/ miredo   FW   FAQ

Configuring the HA

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

Figure of HA

The content of the main /etc/mip6d.conf is provided below. The file contains the generic configuration parameters, i.e. the one that are not specific to users. At the end of the file, inclusion of specific per-user configuration files is peformed. If you manage only one or two users, you can simply inline the content of per user file. An example of such user configuration file is provided just after the comments associated with main configuration file.

$ cat /etc/mip6d.conf
 NodeConfig HA;
 
 Interface "eth1";
 
 UseMnHaIPsec enabled;
 KeyMngMobCapability enabled;
 
 DefaultBindingAclPolicy deny;
 
 include "/etc/mip6d.conf.d/arnaud.ebalard.mip6d.conf"
 include "/etc/mip6d.conf.d/another.user.mip6d.conf"

The value of NodeConfig parameter should not be a surprise.

Then, the Interface parameter is set to "eth1" to declare an interface used by the HA. This parameter will also be used multiple times in client-specific configuration blocks.

The next flag (UseMnHaIPsec) indicates that MIPv6 signaling between the HA and its MN must be protected by IPsec. It is enabled by default but we set it explicitly.

KeyMngMobCapability parameter allows setting the value of K bit in BA sent to the peer, indicating that our IKE daemon support movement (i.e. is able to update its SA/SP on movement). In practice, the value is not considered in the code.

The DefaultBindingAclPolicy is set to "deny" to prevent binding of peers that are not explicitly allowed. You will see below that we add specific binding ACL in the configuration entries of each peer.

The rest of the main configuration file simply consists in the inclusion of per-user configuration files. One of them is provided below and followed by comments.

$ cat /etc/mip6d.conf.d/arnaud.ebalard.mip6d.conf
 Interface "eth0.302";
 
 IPsecPolicySet {
     HomeAgentAddress 2001:db8:802:f002:21e:bff:fe4e:3b2;
     HomeAddress 2001:db8:78df:2:20d:93ff:fe55:8f78/64;
 
     IPsecPolicy Mh UseESP;
     IPsecPolicy TunnelPayload UseESP;
 }
 BindingAclPolicy 2001:db8:78df:2:20d:93ff:fe55:8f78 allow;

As you can see, the amount of per-user configuration information is very limited.

In our setup, every client as its own subnet (a specific VLAN in fact), which results in a specific interface on the HA. Instead of listing all interfaces in the main configuration file, we add those interfaces in the user configuration file. Here, we simply tell umip to consider that interface ("eth0.302") and do the same for other users in their respective configuration file.

The next configuration block (IPsecPolicySet) is of particular interest. It deals with the IPsec protection of the traffic between the HA and the MN (data and signaling). The addresses of the Home Agent (HomeAgentAddress) and the Home Address of the MN (HomeAddress) are provided, followed by some very simple IPsec policy descriptions (IPsecPolicy ...). Here, we simply ask for IPsec protection using ESP for:

Those rules cover all traffic (data and MIPv6 signaling) between the MN and the HA.

UMIP will use the 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 SP/SA). XFRM then handles the emission of the MIGRATE messages to registered key managers, no matter if they use PF_KEY or Netlink. For racoon, PF_KEY is used.

As discussed previously, we have a deny by default policy for binding and require a specific ACL for every new user. This is the purpose of the BindingAclPolicy 2001:db8:78df:2:20d:93ff:fe55:8f78 allow; entry, which references the HoA of the MN and allow binding for it.

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. Below, we cover the HA part.

Just like we did for UMIP configuration, we also maintain racoon configuration using a main file and specific configuration files for every user, which are included in the main configuration.

On the HA, the main configuration file 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/arnaud.ebalard.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.

Then, privilege separation is not configured/enabled. I just did not took the time to test it.

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

Because we have a lot of interfaces on the HA and to avoid selecting addresses on a per user basis (lazyness), we simply let racoon bind on all interfaces.

For handling our MN and negotiate Phase 1 with those 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 the peers.

We now cover the user-specific configuration files associated with every MN. They are all included using the include parameter.

$ cat /etc/racoon/racoon.conf.d/arnaud.ebalard.racoon.conf
 sainfo address 2001:db8:802:f002:21e:bff:fe4e:3b2[0] 135 
        address 2001:db8:78df:2:20d:93ff:fe55:8f78[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:78df:2:20d:93ff:fe55:8f78[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.

Overview   Kernel   umip   racoon   config(HA|MN|MR and MRHA)   w/ miredo   FW   FAQ

Configuring the MN

Now that the configuration of the HA has been covered in previous section, we deal here with the configuration of the MN. This is done by specifically pointing the differences between HA and MN configuration.

Figure of MN

We first start with UMIP configuration, which is presented below. The difference with the configuration file we described in previous section for the HA is that everything is kept in the same file, i.e. there is no need to include external files.

$ cat /etc/mip6d.conf
 NodeConfig MN;
 DebugLevel 0;
 UseMnHaIPsec enabled;
 KeyMngMobCapability enabled;
 DoRouteOptimizationMN disabled;
 
 Interface "eth0" {
 	    MnIfPreference 1;
 }

 Interface "wlan0" {
 	    MnIfPreference 2;
 }
  
 MnHomeLink "eth0" {
     HomeAgentAddress  2001:db8:802:f002:21e:bff:fe4e:3b2;
     HomeAddress 2001:db8:78df:2:20d:93ff:fe55:8f78/64 ;
 }
 
 IPsecPolicySet {
     HomeAgentAddress 2001:db8:802:f002:21e:bff:fe4e:3b2 ;
     HomeAddress 2001:db8:78df:2:20d:93ff:fe55:8f78/64 ;
 
     IPsecPolicy Mh UseESP;
     IPsecPolicy TunnelPayload UseESP;
 }

Quite obviously, the NodeConfig parameter is set to MN.

As we do not want our MN to initiate Route Optimization with Correspondent nodes (which would imply losing IPsec protection for traffic leaving/entering the foreign network), it is disabled using DoRouteOptimizationMN parameter.

Then, comes the configuration of interfaces on our MN which is pretty easy to understand: we preferentially use our ethernet interface eth0 (better throughput and lower latency) if it has some link and UMIP manage to configure an IPv6 address usable as CoA. If it is not the case, then the Wifi interface wlan0 is used.

Please note that this option is provided by one of the patches applied to UMIP, i.e. it is not available in vanilla 0.4 version of UMIP. If you intend to use tunnel interfaces with UMIP, you should definitely read the mip6d.conf man page entry and also take a look at the FAQ provided at the end of current page.

The rest of the configuration is pretty easy to understand if you have read mip6d.conf man page (you should have). With regard to the IPsecPolicySet, it is identical to the HA counterpart specific to that client that we previously described.

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

$ cat /etc/racoon/racoon.conf
 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:802:f002:21e:bff:fe4e:3b2
 {
         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:78df:2:20d:93ff:fe55:8f78[0] 135
        address 2001:db8:802:f002:21e:bff:fe4e:3b2[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:78df:2:20d:93ff:fe55:8f78[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:802:f002:21e:bff:fe4e:3b2). 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

Overview   Kernel   umip   racoon   config(HA|MN|MR and MRHA)   w/ miredo   FW   FAQ

Changes for the MR and its MRHA

Now that you have managed to get a working configuration - I repeat, a working configuration - for both you HA and your MN, it is now time to make the small modifications to turn your HA into a NEMO HA (MRHA) and your MN into a MR (if you need it).

Figure of HA and MR

As you will see, the configuration changes are very limited, because

We start by commenting the changes required to UMIP configuration (main and then per user files) for changing our HA into a MRHA.

The first thing to do is to allow the HA to accept binding by enabling HaAcceptMobRtr parameter

Then, we intend to provide our clients 2 subnets (/64) under fdff:db8:820f:ff00::/56 and 2001:db8:78df:ff00::/56. [NEMO-patched] UMIP will requires that the prefix the HA intend to serve be declared in the configuration. This is done using the HaServedPrefix. You can find those elements below.

$ cat /etc/mip6d.conf
 NodeConfig HA;
 
 Interface "eth1";
 
 HaAcceptMobRtr enabled;                   ### NEMO Additions ###
 HaServedPrefix fdff:db8:820f:ff00::/56;   ### NEMO Additions ###
 HaServedPrefix 2001:db8:78df:ff00::/56;   ### NEMO Additions ###
 
 UseMnHaIPsec enabled;
 KeyMngMobCapability enabled;
 
 DefaultBindingAclPolicy deny;
 
 include "/etc/mip6d.conf.d/arnaud.ebalard.mip6d.conf"
 include "/etc/mip6d.conf.d/another.user.mip6d.conf"

Let's now cover the changes to user-specific configuration file. This configuration allow my MR to request two prefixes: fdff:db8:820f:ff01::/64 and 2001:db8:78df:ff01::/64 (note that they both are among declared HaServedPrefix we covered above). This is done by listing between parenthesis the set of prefixes the MN is allowed to request in the BindingAclPolicy

 $ cat /etc/mip6d.conf.d/arnaud.ebalard.mip6d.conf
 Interface "eth0.302";
 
 IPsecPolicySet {
     HomeAgentAddress 2001:db8:802:f002:21e:bff:fe4e:3b2;
     HomeAddress 2001:db8:78df:2:20d:93ff:fe55:8f78/64;
 
     IPsecPolicy Mh UseESP;
     IPsecPolicy TunnelPayload UseESP;
 }
 BindingAclPolicy 2001:db8:78df:2:20d:93ff:fe55:8f78 (fdff:db8:820f:ff01::/64, \
                                                      2001:db8:78df:ff01::/64) allow;

Now, you might wonder what kind of complicated changes are required in racoon configuration to support the addition of those changes. The response is short: NONE. The reason is that the tunnel mode SA racoon will negotiate are suitable for handling the protection of tunneled traffic by default. The SP that UMIP will put spawn for the prefixes will do the rest of the magic. This is sufficient for our basic needs.

ok, you are disappointed, I can see it in your eyes! But the fun is not over! We still need to modify the configuration of our MN to make it a MR.

Figure of MR

The modified configuration is provided below. Comments follow.

$ cat /etc/mip6d.conf
 NodeConfig MN;
 DebugLevel 0;
 UseMnHaIPsec enabled;
 KeyMngMobCapability enabled;
 DoRouteOptimizationMN disabled;
 
 Interface "eth0" {
 	  MnIfPreference 1;
 }
 
 Interface "wlan0" {
 	    MnIfPreference 2;
 }

 MnHomeLink "eth0" {
     HomeAgentAddress  2001:db8:802:f002:21e:bff:fe4e:3b2;
     HomeAddress 2001:db8:78df:2:20d:93ff:fe55:8f78/64 (fdff:db8:820f:ff01::/64, \
 						       2001:db8:78df:ff01::/64);
     IsMobRtr enabled;
 }
 
 IPsecPolicySet {
     HomeAgentAddress 2001:db8:802:f002:21e:bff:fe4e:3b2 ;
     HomeAddress 2001:db8:78df:2:20d:93ff:fe55:8f78/64 ;
 
     IPsecPolicy Mh UseESP;
     IPsecPolicy TunnelPayload UseESP;
 }

All the changes are in the MnHomeLink block. We allow the MR to act as a router by enabling IsMobRtr parameter. The two prefixes we previously configured on the MRHA side have been added to the HomeAddress statement.

For the same reason discussed previously for the HA, no changes to racoon configuration are required either on the newly configured MR.

As depicted on previous figure, the MR is expected to advertise two prefixes (a global one and an ULA one) on its internal interface, eth1. Let's install radvd and fill a configuration file (/etc/radvd.conf) for that purpose:

$ sudo apt-get install radvd
$ cat /etc/radvd.conf
interface eth1
{
        AdvSendAdvert on;
        AdvDefaultPreference high;
        AdvOtherConfigFlag off;
        AdvManagedFlag off;
        AdvIntervalOpt on;
        IgnoreIfMissing on;

        prefix fdff:db8:820f:ff01::/64
        {
           AdvOnLink on;
           AdvAutonomous on;
        };

        prefix 2001:db8:78df:ff01::/64
        {
           AdvOnLink on;
           AdvAutonomous on;
        };
};

With that configuration, the clients connected to eth1 link should manage to configure themselves with two addresses and use the MR as their default router. For the traffic to be routed correctly in both directions for those prefixes, we need to provide some information to Linux routing table on the existence of those prefixes. Under Debian, we do that in /etc/network/interfaces, with the configuration statements for eth1 interface.

$ cat /etc/network/interfaces

...

auto eth1
iface eth1 inet6 manual
      up   ip -6 route add fdff:db8:820f:ff01::/64 dev eth1 || true
      up   ip -6 route add 2001:db8:78df:ff01::/64 dev eth1 || true
      down ip -6 route del fdff:db8:820f:ff01::/64 dev eth1 || true
      down ip -6 route del 2001:db8:78df:ff01::/64 dev eth1 || true

...

Then, you need to activate forwarding (radvd also expects IPv6 forwarding to be activated). This is usually done in /etc/sysctl.conf but you can also do it in /etc/network/interfaces in the block dedicated to eth1 configuration. If you use the packages I provide, you just have to set FORCE_IPV6_FORWARDING parameter to "yes" in /etc/default/mip6d:

$ cat /etc/default/mip6d
RUN="yes"
FORCE_IPV6_FORWARDING="yes"

That way, when the daemon is started, /proc/sys/net/ipv6/conf/all/forwarding is automatically set to 1. Note that forwarding will not be deactivated when the daemon is stopped.

Overview   Kernel   umip   racoon   config(HA|MN|MR and MRHA)   w/ miredo   FW   FAQ

w/ miredo

Context

If you play the game (and use MIPv6 on a daily basis), you will find after some time that the ability to keep a static vision of the network no matter where you are is just great. But you will also encounter some frustrations on foreign network that still only provide IPv4 access.

After some of those frustrating moments, I took some time to try and make MIPv6 working from IPv4 foreign networks.

Fron a theoretical standpoint, there are two main solutions available for that purpose:

Below is a quick discussion of pros and cons of both protocols.

Pros and Cons of Teredo and DS-MIPv6

Here, I provide a list of pros and cons for both solutions in the context of a use with IPsec/IKE-protected MIPv6:

In the end, I think that Teredo is the cleanest of the two workarounds. The main reason for me is that it keeps thing separate: MIPv6 (and IPsec/IKE) do not get involved in IPv4 and NAT issues. Teredo handles those, with a MTU fee per packet, but it is worth it.

Setting up miredo

Under Linux, Miredo is the implementation of Teredo protocol. It supports both relay and client mode. Here, we cover the setup of client mode on a MN (a Debian MN).

Before spending some time on the configuration, let's take a few lines to describe how umip and miredo will work together. Usually, umip is the one handling address configuration by sending RS, parsing RA, constructing addresses, installing them and so on. With Mired, this is obviously not possible, because the configuration of Teredo interface (address and routes) is completely handled by miredo.

For that reason, I wrote a patch that adds the ability to "explain" umip that an interface it is dealing with is a tunnel interface that will be configured externally. For those interfaces, umip will not try to send RS, received RA, ... and will directly use the information configured by the external mechanism. The aim was to be able to support Teredo, 6to4, and ppp interfaces. Look at mip6d.conf man page for the documentation of "tunnel" keyword for more on the topic.

As a side note, one comment made by the developer of USAGI when reviewing the path was that a better way to implement the feature would have been to rely on the "policy manager" available in umip. I basically agree but have no time at the moment to update the patch.

There is another thing you should be aware of about the use of UMIP with miredo: because miredo does not really support movement detection (switching from a network to another) and rely on external IPv4 address configuration (usually done using DHCP), do not expect to get some smooth migrations when moving from an IPv4 network to another. From my experience, after some time, miredo notices the address change and performs a new qualification procedure which results in the configuration of a new IPv6 address on the teredo interface. At this point, UMIP detects the new address and performs its handover. Nonetheless, miredo is perfectly suitable when you find yourself in a common IPv4 network.

Let's now start setting things up. First install the daemon. By default, miredo is started at boot (via /etc/init.d/miredo) because START_MIREDO is set to true in /etc/default/miredo.

$ apt-get install miredo
$ cat /etc/default/miredo
START_MIREDO=true
DAEMON_ARGS=""

If you do not want miredo to be started by default during boot but want to start it by hand when you need the service it provides, you can simply use update-rc.d for that purpose (something like "update-rc.d -f miredo remove" should do the job).

Let's now configure miredo by modifying /etc/miredo.conf file. Mine look like the following:

$ cat /etc/miredo.conf 
InterfaceName    teredo
ServerAddress    83.170.6.76      #teredo-debian.remlab.net
RelayType        client
BindPort         3545

If you make the comparison with the default file provided by the package, you will notice that ServerAddress parameter is no more provided a FQDN but an IPv4 address. This is to avoid a chicken and egg issue: I use a static DNS configuration involving an IPv6 DNS server that will only be available after the binding with the HA has occured.

Because miredo can be used on various platform and users might have some specific needs configure routing, the daemon uses a simple script for configuring the routes: /etc/miredo/client-hook. Here is a modified version intended for use with umip. It sets a higher MTU and

#!/bin/sh
#
# Miredo client hook script for Linux/iproute2
#
# Copyright  2007 Rmi Denis-Courmont.
# Distributed under the terms of the GNU General Public License version 2.
#
# Modified by Arnaud Ebalard <arno@natisbad.org> to work with UMIP
# towards a specific relay allowing a higher MTU (1400).

IP=/sbin/ip
METRIC=1029
TABLE=teredo
PRIO=32765
MTU=1400

test "$OLD_ADDRESS" && \
"$IP" -6 rule del from "$OLD_ADDRESS" prio "$PRIO" table "$TABLE" 2>/dev/null

"$IP" -6 route flush table "$TABLE" 2>/dev/null
"$IP" -6 route flush dev "$IFACE" 2>/dev/null
"$IP" -6 address flush dev "$IFACE" 2>/dev/null

"$IP" -6 link set dev "$IFACE" "$STATE"

case "$STATE" in
        up)
                "$IP" -6 route add default dev "$IFACE" metric "$METRIC"
                "$IP" -6 address add "${LLADDRESS}/64" dev "$IFACE"
                "$IP" -6 address add "${ADDRESS}/128" dev "$IFACE"
                "$IP" link set dev "$IFACE" up mtu "$MTU"
                ;;
esac

"$IP" -6 route flush cache 2>/dev/null

exit 0

Let's now come back for a second to umip configuration. On the MN or MR on which you intend to use miredo, you should find a definition for "teredo" interface:

...

 Interface "eth0" {
 	    MnIfPreference 1;
 }

 Interface "wlan0" {
 	    MnIfPreference 2;
 }
 
 Interface "teredo" {
 	    MnIfPreference 3;
 	    Tunnel enabled;
 }
  
...

As you can see, the "teredo" interface is the least preferred one. It is also marked as an externally configured tunnel interface (using Tunnel parameter). The Tunnel parameter is used to warn UMIP that the interface is a tunnel interface which handles on its own the address configuration steps (i.e. it does not require UMIP to perform RS/RA and DAD). In IPv4 only networks, if miredo has succeeded in its qualification procedure and has acquired an address, it is used by UMIP as CoA.

Overview   Kernel   umip   racoon   config(HA|MN|MR and MRHA)   w/ miredo   FW   FAQ

Firewall

This section is currently under construction.
Overview   Kernel   umip   racoon   config(HA|MN|MR and MRHA)   w/ miredo   FW   FAQ

FAQ

If you have an issue that is not listed in the FAQ, drop me a mail and I will add it.