m6t

Introduction

This page is dedicated to m6t protocol and its Linux implementations: m6tc (client) and m6ts (server/gateway). The goal of m6t is to allow the operation of MIPv6 Mobile Nodes (MN) from IPv4-only networks. For MN, it serves as a simple alternative to DSMIPv6 or Teredo.


Demonstration

Before you get bored by the explanations, I made a screencast of m6t running on my laptop (a MIPv6 Mobile Node running UMIP). If you want to see it offline or your browser lacks flash support, the original video (16MB, 1280x800, XViD/MP3) is available here. Otherwise, simply start the one below (in fullscreen mode to get the details). I also think it is a good idea to read the comments under the video to understand what happens.

Both MIPv6 signaling and data traffic between the laptop and its Home Agent are protected using IPsec and IKE (racoon). Dynamic updates of IPsec and IKE states upon movement are performed via MIGRATE

For the demonstration, the laptop has IPv4 connectivity via ethernet (eth0), wifi (wlan0) and 3G (wwan0) simultaneously. 3 instances of m6t client are running, one for each interface (m6t_eth0, m6t_wlan0, m6t_wwan0). UMIP is configured to use only m6t interfaces, i.e. will never use IPv6 connectivity even if its available on one of the physical interfaces.

Then, in the demo, we start the download of a large file over IPv6. This is used to monitor current bandwidth. We also start a continuous ping6 to a host located behind our HA. The ping6 is used to monitor latency of current connection to our HA. 3 tcpdump are also started on the 3 physical interfaces (eth0, wlan0 and wwan0) with an "ip6" filter to show that no IPv6 traffic is directly exchanged via physical interfaces: at every moment, MIPv6 traffic leaves the host only via one of the m6t interfaces.

Then, we start shutting down and restarting interfaces to see what happens ... The bmon instance running in the main window gives a somewhat visual feedback of the result.


Overview of m6t protocol

Latest version of m6t specification is available here. If you have the time to read the details and make comment either by email or on IETF mext WG mailing list, do not hesitate! But if you only have time for a short and graphical introduction to the protocol, keep scrolling.

Understanding m6t in 5 sentences ...

  1. On a MN connected to an IPv4 network, m6t provides an interface configured with an IPv6 address which can transparently be used CoA by MIPv6 stack (and IPsec and IKE modules).
  2. m6t component encapsulates IPv6 packets generated locally (i.e. with CoA as source) over UDP and IPv4 to a remote m6t component located at the IPv4 edge of the MN's Home Agent's site (tunnel gateway).
  3. m6t component on the tunnel gateway decapsulates UDP-carried IPv6 packets and route them to the Home Agent after having recorded the association between the MN's IPv6 address and the IPv4 source of the packet (IPv4 address and UDP source port).
  4. Upon reply of the MN's Home Agent with a packet with the CoA of the MN set as destination address, the recorded information is used to UDP-encapsulate the packet to the MN's remote IPv4 site (usually NAT gateway address and mapped UDP port).
  5. After delivery to m6t component on the MN over UDP, the IPv6 packet is decapsulated and presented locally on m6t tunnel interface (i.e. delivered to MIPv6 stack).

Graphical overview

The following picture provides the location of m6t components:

m6t overview

The green part is associated with pure IPv6 (untainted with IPv4 or NAT) elements. The blue part is associated with IPv4 elements. The location of m6t components is depicted:

In both cases, m6t does the interface between standard unmodified IPv6 and IPv4 components.

On the following picture, the path followed by the IPv6 traffic exchanged by the MIPv6 MN (stuck in the IPv4 foreign network) with Google is depicted. It presents the various encapsulations applied to MN's IPv6 traffic. At the moment, just consider that MIPv6 module is provided with a CoA by m6t component. Details are given later:

m6t path overview

When leaving the IPv4 stack of the MN, the packets have the following format:

  ESP(IPv6(src=HoA, dst=www.google.com)/TCP())/
  IPv6(src=CoA, dst=HA)/
  UDP(sport=*, dport=M6TGWPORT)/
  IPv4(src=*, dst=M6TGW@)

We considered MIPv6 data traffic is IPsec ESP-protected. The CoA provided by m6t is selected randomly in a prefix provided by configuration. This is discussed later. UDP source port is either random or static based on m6t component's configuration. UDP destination port and IPv4 destination address are provided by m6t configuration. IPv4 source address is an IPv4 address configured on the interface connected to the IPv4 network; in most cases, a private IPv4 address obtained by DHCP.

In the IPv4 Internet (i.e. after processing by the NAT gateway), the packets have the following format:

  ESP(IPv6(src=HoA, dst=2a00:1450:4007:800::68)/TCP())/
  IPv6(src=CoA, dst=HA)/
  UDP(sport=**, dport=M6TGWPORT)/
  IPv4(src=NATGW@, dst=M6TGW@)

Even if unlikely, the source port of the traffic may have been mangled by the NAT GW. Additionally, the source address of the packet is the one of the NAT GW.

After handling by the m6t component on the tunnel gateway at the IPv4 edge of MN's HA IPv6 site, the format of the packet as delivered to the HA is the following:

  ESP(IPv6(src=HoA, dst=2a00:1450:4007:800::68)/TCP())/
  IPv6(src=CoA, dst=HA)/

After handling by the IPsec and MIPv6 stack on the HA, the packet routed by the HA to the final destination (www.google.com IPv6 address) has following format:

  IPv6(src=HoA, dst=2a00:1450:4007:800::68)/TCP()

Comparison with DSMIPv6 and Teredo

In this section, the three main solutions (Teredo, DSMIPv6 and m6t) to support MIPv6 operation from IPv4 networks are compared. If you see other points of comparison not already listed here or if you disagree on some point, drop me an email.

Teredo DSMIPv6 m6t
Spec. RFC4380 RFC5555 draft-ebalard-mext-m6t
Spec. status Standards Track RFC Standards Track RFC Informational draft
Encap. UDP IP-in-IP, UDP UDP
selectable port no no yes
MTU 1280 bytes 1472 bytes 1472 bytes
Real per packet loss (w/o ESP) 68 bytes (IPv4/UDP/IPv6) 28 (IPv4/UDP) 68 bytes (IPv4/UDP/IPv6)
Additional latency Qualification procedure none none
Additional traffic yes, for qualification and to maintain NAT states with Server and peers yes, to maintain NAT states with HA yes, to maintain NAT states with tunnel GW
IPv4 connectivity no yes no
IPv4 stability no yes no
Comp. w/ RO yes (theoretically) no no
Auto. sunset yes no yes
Impact on MIPv6 none, i.e. transparent high, including IPv4 and NAT awareness. none, i.e. transparent
Impact on IPsec/IKE none, i.e. transparent high, IPv4 and NAT-T support and additional interfacing effort between MIPv6, IPsec and IKE or complete merge. none, i.e. transparent
Overall transparency good bad excellent
Modularity good bad excellent
Implementation Windows, Linux, BSD Patches for UMIP (Supported: HoAv4 and CoAv4, static IPsec. Not supported: networks w/ NAT, interactions with IKE and dynamic updates (e.g. MIGRATE)). Linux

As a summary, Teredo is capable of providing a MN IPv6 connectivity to its HA but also to setup RO with its Correspondent Nodes (at a cost). But this versatility and its reliance on additional external helpers (servers and relays) add complexity to the protocol, additional traffic and initial latency.

DSMIPv6 has some unique features: IPv4 connectivity and IPv4 address stability. Developed as a direct extension of MIPv6, the result is additional complexity, lack of modularity and no "automatic sunset". The interfacing with IPsec and IKE is a guaranteed headache: the inclusion of IPv4 and NAT problems in MIPv6 protocol solution space leads to that situation.

As for m6t, the simplicity of the protocol, its unique goal (providing connectivity between a MN and its HA) limit its abilities (no RO support, no IPv4 support) but make it efficient on the other important aspects: modularity, transparency, efficiency.


A simple m6t client for Linux: m6tc

Sources and packages

I have developed a simple m6t client for Linux as a proof of concept. It is written in Python and relies on in-kernel tun support for providing an IPv6 interface to the system. Before providing some details on what it does and how it works, below are some info on how to access and install the package on Debian:

# cat > /etc/apt/sources.list.d/umip.list                                      # add repo
deb     http://umip.org/debian/ unstable main contrib non-free
deb-src http://umip.org/debian/ unstable main contrib non-free
^d

# wget -q http://umip.org/debian/umip-unofficial-debian-mirror.key             # grab key
# wget -q http://umip.org/debian/umip-unofficial-debian-mirror.key.asc         # grab key sig
# gpg --verify umip-unofficial-debian-mirror.key.asc                           # verify key
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>"

# apt-key add umip-unofficial-debian-mirror.key                                # install key
OK

# apt-get update                                                               # update
# apt-get install m6tc                                                         # install m6tc

The latest version of the sources are available here.

The gzipped tar file is a standard python package with a setup.py. It provides both m6tc and m6ts and also contains the debian folder.

The way it works

Now, before discussing the configuration, let's give some words on how the implementation works.

m6tc client is usually associated by configuration to a given physical interface (e.g. eth0, wlan0, wwan0, ppp0, ...). Using Netlink, it monitors the status of the interface (link status) and the availability of an address on that interface. When the interface is usable (i.e. link status is UP and RUNNING and the interface is configured with an IPv4 address), it binds a UDP socket on that address (port is selected randomly by default if none is forced by configuration) and create an IPv6 tunnel interface (using in-kernel tun support). It creates a random IPv6 address in the /80 prefix provided in MN's configuration file (usually a ULA prefix). The address is configured on the tunnel interface and a default route is installed on the system via the tunnel interface.

As an example, below is what a call to ifconfig returns on my laptop for the tunnel interface associated with eth0 and wlan0:

$ sudo ifconfig
...

m6t_eth0  Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00  
          inet6 addr: fdee::f4ea:d78b:4467/128 Scope:Global
          UP POINTOPOINT RUNNING NOARP PROMISC MULTICAST  MTU:1472  Metric:1
          RX packets:356208 errors:0 dropped:0 overruns:0 frame:0
          TX packets:320310 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:500 
          RX bytes:284162008 (270.9 MiB)  TX bytes:131268559 (125.1 MiB)

m6t_wlan0 Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00  
          inet6 addr: fdee::10a3:6d63:7adb/128 Scope:Global
          UP POINTOPOINT RUNNING NOARP PROMISC MULTICAST  MTU:1472  Metric:1
          RX packets:53894 errors:0 dropped:0 overruns:0 frame:0
          TX packets:45392 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:500 
          RX bytes:42439392 (40.4 MiB)  TX bytes:10355136 (9.8 MiB)

...

When packets are received on an m6t tunnel interface, they are sent over UDP to the remote m6t tunnel gateway using the associated UDP socket.

Now, for UMIP (Linux MIPv6 daemon) to use those interfaces, a simple modification of its configuration is needed. Below is an excerpt of my current configuration, in which I have declared 3 additional m6t interfaces, associated respectively with eth0, wlan0 and wwan0 (I run 3 instances of m6tc). With that configuration (note the preferences below; the lower the value, the higher the preference), UMIP uses those interfaces when native IPv6 is not available via Ethernet or WiFi.

$ cat /etc/mip6d.conf

...

# Native IPv6 via Ethernet
Interface "eth0" {
        MnIfPreference 1;
}

# Native IPv6 via WiFi
Interface "wlan0" {
        MnIfPreference 2;
}

# m6t tunnel interface via Ethernet
Interface "m6t_eth0" {
          MnIfPreference 3;
          Tunnel enabled;
}

# m6t tunnel interface via WiFi
Interface "m6t_wlan0" {
          MnIfPreference 4;
          Tunnel enabled;
}

# m6t tunnel interface via 3G
Interface "m6t_wwan0" {
          MnIfPreference 5;
          Tunnel enabled;
}

...

When the link status of a tracked physical interface changes (carrier loss, link is administratively set down) or the address is removed, the associated m6t tunnel interface is set down (address removed and set administratively down). If it was the one used by UMIP to get connectivity to its HA (i.e. for its CoA), it switches to another interface (native if available, m6t tunnel interface otherwise).

When link and address are available again on the physical interface, the m6t tunnel interface is configured with a new random address and set up.

Configuration

First, you should read the man page provided by the package for the client: man 1 m6tc. It provides the specific details about the few parameters the client accepts. Note that the client does not use any configuration file and only accepts parameters on the command line.

On Debian, an init script (/etc/init.d/m6tc) is used to start the service. It sources a shell script excerpt which you need to create (/etc/m6t.conf). An example of configuration file is available in /usr/share/doc/m6tc/examples/m6tc.conf. You can copy it to /etc/m6tc.conf and then modify the required parameters to fit your needs. The parameters are documented in man 5 m6tc.conf. A typical configuration will look like the following:

$ cat /etc/m6tc.conf
INTERFACE="eth0"
BINDPORT="500"
PREFIX="fdee::/80"
GATEWAY="1.1.1.1:500"

Then, if you want the init script to start the m6tc daemon, you need to change the content of /etc/idefault/m6tc from:

$ cat /etc/default/m6tc
ENABLED="no"
to
$ cat /etc/default/m6tc
ENABLED="yes"

Once this is done, you can start the service:

$ sudo /etc/init.d/m6tc start
Starting m6t client instance (m6tc-eth0) ... done (PID 32378).

If the associated physical interface (eth0 in our case) is UP and RUNNING, and has an IPv4 address, ifconfig should display something like thise:

$ sudo ifconfig m6t_eth0
m6t_eth0  Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00  
          inet6 addr: fdee::f4ea:d78b:4467/128 Scope:Global
          UP POINTOPOINT RUNNING NOARP PROMISC MULTICAST  MTU:1472  Metric:1
          RX packets:357076 errors:0 dropped:0 overruns:0 frame:0
          TX packets:321016 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:500 
          RX bytes:284542408 (271.3 MiB)  TX bytes:131443255 (125.3 MiB)

Here are some additional points worth mentioning about m6tc implementation.

n.b.: if you want to run multiple instances of the service in order to support multiple interfaces, the best way to do that on Debian is to create custom init scripts (say /etc/init.d/m6tc_wlan0) with dedicated configuration file (say /etc/m6tc.wlan0.conf) and default file (/etc/default/m6tc.wlan0)


A simple m6t server (tunnel gateway) for Linux: m6ts

Now that you have configured the client, you probably need some remote end in front of your HA to terminate the tunnels from your MN, i.e. to UDP-decapsulate/encapsulate IPv6 packets with the HA. This is what m6ts provides: a simple m6t tunnel gateway implementation for Linux.

Sources and packages

Like m6tc, m6ts is a proof of concept. Is is written in Python and relies on in-kernel tun support for providing an IPv6 interface to the system. Before providing some details on what it does and how it works, below are some info on how to access and install the package on Debian. If you have already done the steps for installing the client, you only need to do the final apt-get install m6ts.

# cat > /etc/apt/sources.list.d/umip.list                                      # add repo
deb     http://umip.org/debian/ unstable main contrib non-free
deb-src http://umip.org/debian/ unstable main contrib non-free
^d

# wget -q http://umip.org/debian/umip-unofficial-debian-mirror.key             # grab key
# wget -q http://umip.org/debian/umip-unofficial-debian-mirror.key.asc         # grab key sig
# gpg --verify umip-unofficial-debian-mirror.key.asc                           # verify key
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>"

# apt-key add umip-unofficial-debian-mirror.key                                # install key
OK

# apt-get update                                                               # update
# apt-get install m6ts                                                         # install m6ts

The latest version of the sources are available here.

The gzipped tar file is a standard python package with a setup.py. It provides both m6tc and m6ts and also contains the debian folder.

The way it works

Now, before discussing the configuration, let's give some words on how the implementation works.

m6ts binds a UDP socket on an IPv4 address (usually public for access from remote IPv4 sites but there is no limitation on that aspec) and port (selectable!), waiting for incoming m6t traffic from m6t client running on MN. It extracts UDP-encapsulated IPv6 traffic, performs some check on the source (configured prefix) and destination (configured Home Agent address) and reinject it via a tun interface in the IPv6 stack for routing to the HA. During the processing, m6ts also records IPv4 parameters (IPv4 source address of the UDP packet and also UDP source port) associated with the IPv6 address of the MN (found in the encapsualated packet). Obviously, m6ts also works in the reverse direction, i.e. forwards packets received from the HA to the MN, using previously recorded IPv4 parameters.

m6ts can be deployed directly on the HA or on a separate device with a public IPv4 address at the edge of your network. Mine is running on a separate device.

Configuration

On Debian, m6ts is configured in a similar way as m6tc. You just have to follow the steps described above for m6tc, but by replacing 'c' by 's' in most cases for the names of the files.

$ sudo cp /usr/share/doc/m6tc/examples/m6ts.conf /etc/m6ts.conf
$ emacs -nw /etc/m6ts.conf                                        # modify using man 5 m6ts.conf
$ sudo sed -i s/no/yes/ /etc/default/m6ts
$ sudo /etc/init.d/m6ts start

m6ts is basically subject to the same list of limitations and cautions as the ones given for m6tc sooner on this page.


Conclusion

m6tc (m6t client) and m6ts (m6t tunnel gateway) implementations provide a simple way for UMIP users to test the protocol. Their initial purpose is as proofs of concepts and test playgrounds to improve m6t specification.

If you have questions or find bugs in the implementation, don't hesitate to drop me an email. Do not hesitate to do the same if you have comments or questions on the draft.

Happy tunneling!


FAQ

If you have questions, drop me an email and I will try and answer them. If it can help others, I will try and make the solution available here in this FAQ.

[+] How do I create a prefix for my MN?  a simple solution is to use an Unique Local prefix (RFC4193). Scapy has a function (in6_getLocalUniquePrefix()) that does just that. Once you have a /48 prefix, just select a 16 bits subnet ID. All MN will be configured with /80 prefixes in that /64 prefix. In order to provide each MN a unique /80 prefix (i.e. have no collisions between MN), append a unique 16 bit value (incremental is ok) value to the /64 prefix for each MN.

[+] Can m6t help if I need stable IPv4 connectivity?  No. If this is a requirement, the only way to go is to implement and use DSMIPv6 on your MN and HA. An alternative solution might be to use NAT64.

[+] How do you config/reconfig of multiple IPv4 interfaces?  I wrote a page dedicated to Dynamic network configuration on Linux. It describes how to support multiple IPv4 interfaces up and running at the same time with multiple default routes, ... This describes what I currently use on my MN.