1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
|
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>MAP66 (NAT from IPv6 to IPv6, NAT66) for Linux</title><meta name="generator" content="DocBook XSL Stylesheets V1.75.2" /></head><body><div class="article" title="MAP66 (NAT from IPv6 to IPv6, NAT66) for Linux"><div class="titlepage"><div><div><h2 class="title"><a id="id2928121"></a>MAP66 (NAT from IPv6 to IPv6, NAT66) for Linux</h2></div><div><div class="author"><h3 class="author"><span class="firstname">Sven-Ola</span> <span class="surname">Tuecke</span></h3><div class="affiliation"><span class="orgname">Freifunk<br /></span></div></div></div><div><p class="pubdate">06-OCT-2010</p></div></div><hr /></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="section"><a href="#id2961474">Installation</a></span></dt><dt><span class="section"><a href="#id2953819">DKMS Integration</a></span></dt><dt><span class="section"><a href="#id2974647">Configuration</a></span></dt><dd><dl><dt><span class="section"><a href="#id2959435">Brief Version</a></span></dt><dt><span class="section"><a href="#id2955411">Detailed Version</a></span></dt></dl></dd><dt><span class="section"><a href="#id2949227">IPv6/IPv4 Precedence</a></span></dt><dt><span class="section"><a href="#motivation">Motivation</a></span></dt></dl></div><p>These files implement a Linux netfilter target that changes the IPv6
address of packets. The address change is done checksum neutral, thus no
checksum re-calculation for the packet is necessary. You can change the IPv6
source address of outgoing packets as well as the IPv6 destination address
of incoming packets. This allows you to map an internal IPv6 address range
to a second, externally used IPv6 address range. IPv6 address mapping is not
very similar to IPv4 network address translation, but one can describe it as
some sort of stateless NAT. The implementation is based on the expired IETF
discussion paper published here:</p><p><a class="ulink" href="http://tools.ietf.org/html/draft-mrw-behave-nat66-02" target="_top">http://tools.ietf.org/html/draft-mrw-behave-nat66-02</a></p><div class="section" title="Installation"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a id="id2961474"></a>Installation</h2></div></div></div><p>MAP66 implements two pieces of software: a shared library that
extends the ip6tables command and a Linux kernel module. The shared
library file adds the '-j MAP66' target to the ip6tables command. To build
and install, you need ip6tables installed as well as the necessary
headers. The Linux kernel module requires the Linux source file tree and
kernel configuration files to compile. On a Debian/(EKU)buntu, the
following command prepares the build environment:</p><pre class="programlisting">sudo apt-get install build-essential linux-headers iptables-dev</pre><p>Unpack the source tgz archive below <code class="filename">/usr/src</code>,
change to the new sub-directory and issue "make" to build. If this
compiles without errors, install the ip6tables extension with the
following command:</p><pre class="programlisting">sudo make install</pre><div class="note" title="Note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3><p>The kernel module (<code class="filename">ip6t_MAP66.ko</code> for
Linux-2.6 or <code class="filename">ip6t_MAP66.o</code> for Linux-2.4) is not
automatically installed nor loaded into the kernel. You can copy the
kernel module file manually, e.g. with <strong class="userinput"><code>sudo cp ip6t_MAP66.ko
/lib/modules/$(uname -r)/</code></strong>.</p></div></div><div class="section" title="DKMS Integration"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a id="id2953819"></a>DKMS Integration</h2></div></div></div><p>If the next system update needs to install a new kernel version, you
also need to re-compile/re-install the MAP66 kernel module. With
Debian/(EKU)buntu, this can be automated with the Dynamic Kernel Module
Support Framework (DKMS). For this, the <code class="filename">dkms.conf</code>
file is included with the MAP66 source file package. Install DKMS with the
following command:</p><pre class="programlisting">sudo apt-get install dkms</pre><p>If not already in place, move/unpack the MAP66 source file archive
below <code class="filename">/usr/src/</code>. To register the MAP66 source to DKMS
and compile/install, issue these commands:</p><pre class="programlisting">sudo dkms add -m ip6t_MAP66 -v 0.3
sudo dkms build -m ip6t_MAP66 -v 0.3
sudo dkms install -m ip6t_MAP66 -v 0.3</pre><p>Read DKMS details here: <a class="ulink" href="Read DKMS details here: https://wiki.kubuntu.org/Kernel/Dev/DKMSPackaging" target="_top">https://wiki.kubuntu.org/Kernel/Dev/DKMSPackaging</a></p></div><div class="section" title="Configuration"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a id="id2974647"></a>Configuration</h2></div></div></div><div class="section" title="Brief Version"><div class="titlepage"><div><div><h3 class="title"><a id="id2959435"></a>Brief Version</h3></div></div></div><p>You always need to add two ip6tables-rules to your netfilter
configuration. One rule matches outgoing packets and changes their IPv6
source address. The second rule matches incoming packets and reverts the
address change by altering their IPv6 destination address. To following
commands correspond to the <span class="quote">“<span class="quote">Address Mapping Example</span>”</span> given
in the IETF discussion paper:</p><pre class="programlisting">ip6tables -t mangle -I POSTROUTING -o eth0 -s FD01:0203:0405::/48 -j MAP66 --to 2001:0DB8:0001::/48
ip6tables -t mangle -I PREROUTING -i eth0 -d 2001:0DB8:0001::/48 -j MAP66 --to FD01:0203:0405::/48</pre><p>This example is also printed to the screen if you issue
<strong class="userinput"><code>ip6tables -j MAP66 --help</code></strong>. By design, you cannot
use an arbitrary prefix length. Only /112, /96 .. /16 are
supported.</p><p>For each packet, the Linux kernel module also compares the
packet's source address to all IPv6 addresses assigned to the outgoing
interface. If a match is found, the packet's source address is not
mapped. The same comparison happens on the incoming packet's destination
address. The comparison requires some CPU resources, especially if the
interface has a large number of assigned IPv6 addresses. If you are sure
that the mapping cannot match the IPv6 address of the interface (e.g.
the mapping rule defines a mapping prefix that cannot result in the
interface address) you can switch off the comparison. Add the
<strong class="userinput"><code>--nocheck</code></strong> parameter to the ip6tables command for
this.</p></div><div class="section" title="Detailed Version"><div class="titlepage"><div><div><h3 class="title"><a id="id2955411"></a>Detailed Version</h3></div></div></div><p>The following explanation details a living example from the
wireless mesh network that is mentioned under <a class="xref" href="#motivation" title="Motivation">Motivation</a> (see below).
Throughout the mesh network, a private IP address range is used. The ULA
prefix is fdca:ffee:babe::/64. All mesh nodes derive their IPv6
interface addresses by correlating the ULA prefix with the EUI48
(<span class="quote">“<span class="quote">MAC address</span>”</span>) of the respective network adapter.</p><p>There is a Debian based virtual machine that should act as one
IPv6 Internet gateway for the mesh. You can reach the virtual machine's
web service via IPv4 under <a class="ulink" href="http://bbb-vpn.freifunk.net" target="_top">http://bbb-vpn.freifunk.net</a>.
To experiment with IPv6, a <a class="ulink" href="http://www.sixxs.net/" target="_top">SIXXS</a> static tunnel setup has been
added and there is also an experimental 6-to-4 configuration. The
following <code class="filename">/etc/network/interfaces</code> file provides the
configuration for IPv6:</p><pre class="programlisting">auto sixxs
iface sixxs inet6 v4tunnel
address 2001:4dd0:ff00:2ee::2
netmask 64
local 77.87.48.7
endpoint 78.35.24.124
ttl 64
up ip link set mtu 1280 dev $IFACE
up ip route add default via 2001:4dd0:ff00:2ee::1 dev $IFACE
up ip addr add 2001:4dd0:fe77::1/48 dev $IFACE
#auto tun6to4
iface tun6to4 inet6 v4tunnel
# ipv6calc --quiet --action conv6to4 77.87.48.7
address 2002:4d57:3007::1
netmask 16
local 77.87.48.7
endpoint any
ttl 64
gateway ::192.88.99.1</pre><p>As you can see, the virtual machine has an IPv6 prefix of
2001:4dd0:fe77::/48 and is reachable via <a class="ulink" href="http://[2001:4dd0:fe77::1]/" target="_top">http://[2001:4dd0:fe77::1]/</a>.
For experimental purposes, the 6-to-4 tunnel can be activated by issuing
<strong class="userinput"><code>ifup tun6to4</code></strong>. The netfilter setup of this machine
includes the following command sequence to realize mapping from the
private fdca:ffee:babe::/64 prefix to the globally valid IPv6
addresses:</p><pre class="programlisting">ip6tables -t mangle -F POSTROUTING
ip6tables -t mangle -F PREROUTING
ip6tables -t mangle -F FORWARD
grep -q ^ip6t_MAP66 /proc/modules && rmmod ip6t_MAP66
insmod /usr/src/map66/ip6t_MAP66.ko
ip6tables -t mangle -A POSTROUTING -o sixxs -s fdca:ffee:babe::/64 -j MAP66 --to 2001:4dd0:fe77:1::/64 --nocheck
ip6tables -t mangle -A PREROUTING -i sixxs -d 2001:4dd0:fe77:1::/64 -j MAP66 --to fdca:ffee:babe::/64 --nocheck
ip6tables -t mangle -A POSTROUTING -o tun6to4 -s fdca:ffee:babe::/64 -j MAP66 --to 2002:4d57:3007:1::/64 --nocheck
ip6tables -t mangle -A PREROUTING -i tun6to4 -d 2002:4d57:3007:1::/64 -j MAP66 --to fdca:ffee:babe::/64 --nocheck
ip6tables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu</pre><p>Because for both IPv6 networks the external prefix length is
smaller than the internal prefix length, we can make sure that the
mapped addresses cannot match the interface addresses. For example:
2001:4dd0:fe77:1::/64 cannot be converted to 2001:4dd0:fe77:0::1/128 in
this context. For this reason, we can use the
<strong class="userinput"><code>--nocheck</code></strong> speedup here.</p><p>You may stumble over the MSS-clamping rule. While IPv6 defines,
that path MTU detection via ICMPv6 must be supported by any host,
sometimes path MTU detection does not work. The SIXXS tunnel uses an MTU
of 1280 byte. To get the following command working on my PC, I needed to
add the above MSS-clamping rule on the gateway:</p><pre class="programlisting">wget --prefer-family=IPv6 -O - http://6to4.nro.net/</pre><div class="note" title="Note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3><p>The tun6to4 tunnel interface is disabled normally, because of
the implicit 2002::/16 network route configured for that interface.
This network route ensures, that traffic between one 2002::/16 to
another 2002::/16 travels directly between the IPv4 hosts. Without
this network route, any IPv6 traffic will be routed via the 6-to-4
gateways which may not work and place a higher load on those 6-to-4
gateways.</p><p>However, if you ping the SIXXS IP address from another host that
has a 6-to-4 address, you will get the answer packet back via the
6-to-4 interface. If the above address mapping is configured, you ping
one IPv6 address and get the answer from another IPv6
address...</p></div></div></div><div class="section" title="IPv6/IPv4 Precedence"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a id="id2949227"></a>IPv6/IPv4 Precedence</h2></div></div></div><p>With (EKU)buntu and eventually with RedHat, you will notice that
your browser does not show the IPv6 version of a web site that is
multi-homed when using ULA addresses for your IPv6 Internet connection.
The reason for this is an add on to the RFC 3484 rules that is compiled
into the (EKU)buntu libc. The pre-installed
<code class="filename">/etc/gai.conf</code> file will give you a hint on
this.</p><p>In short: the getaddrinfo() library function rates a private IPv4
address higher than the ULA IPv6 address when choosing the transport
protocol for a new Internet connection if this add on to the RFC 3484
rules is compiled in. For this reason, you may want to change the
precedence rules within <code class="filename">/etc/gai.conf</code>.</p><div class="note" title="Note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3><p>The getaddrinfo() library function manages lists of label,
precedence, and scope4 type entries. If the
<code class="filename">/etc/gai.conf</code> file does not provide a single entry
for a particular type, the compiled-in list is used. For this reason,
you cannot uncomment a single entry to overwrite the default. You need
to uncomment all entries of a particular type for this. The
<span class="quote">“<span class="quote">label</span>”</span> lines compare source addresses, the
<span class="quote">“<span class="quote">precedence</span>”</span> lines compare destination addresses.</p></div><div class="procedure" title="Procedure 1. Change IPv6 Precedence"><a id="id2955439"></a><p class="title"><b>Procedure 1. Change IPv6 Precedence</b></p><ol class="procedure" type="1"><li class="step" title="Step 1"><p>Open the <code class="filename">/etc/gai.conf</code> file as root user,
e.g. by executing <strong class="userinput"><code>sudo nano
/etc/gai.conf</code></strong>.</p></li><li class="step" title="Step 2"><p>Remove the leading hash character from the 8 lines starting with
<span class="quote">“<span class="quote">#label</span>”</span>.</p></li><li class="step" title="Step 3"><p>Re-add the hash character to the line stating <span class="quote">“<span class="quote">#label
fc00::/7 6</span>”</span>.</p></li><li class="step" title="Step 4"><p>Save the file.</p></li><li class="step" title="Step 5"><p>Restart your browser and re-try to browse to a multi-homed web
site.</p></li></ol></div><p>The above procedure removes the difference between standard IPv6
source addresses and ULA type private IPv6 source addresses. Anything else
is unchanged.</p></div><div class="section" title="Motivation"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a id="motivation"></a>Motivation</h2></div></div></div><p>My Internet access at home is realized by a wireless community mesh
network not owned by me. The mesh is operated with small embedded devices
(nodes aka. WLAN routers) that are interconnected via radio links (WLAN
IBSS / AdHoc). Routing is done with a specialized protocol such as Batman
or OLSR. The routing protocol selects the nearest out of a dozen Internet
gateways and configures a default route or an IPIP tunnel accordingly.
Each Internet gateway is connected to a different ISP and provides the
service with the help of IPv4 network address translation (NAT). Using NAT
has the following effects:</p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p>Address amplification - something not necessary with IPv6 any
more</p></li><li class="listitem"><p>Anonymization - nice to have as an option but not mission
critical</p></li><li class="listitem"><p>ISP independence - no reverse routing, no
"buy-a-number-range"</p></li></ul></div><p>The last point <span class="bold"><strong>is</strong></span> mission critical.
One can obtain a provider independent IPv6 address range, but you need the
cooperation of an ISP to use that address range for Internet connectivity.
If you e.g. move to another ISP you need your address range to be
re-routed to your new location.</p><p>ISP independence is also possible with some tunneling technique,
such as VPN or mobile IP. Tunneling can be implemented on client PCs and
Internet gateways/servers one day. But there is no need to implement the
same tunneling technique on every mesh node. Why? Because the mesh nodes
can use private IP addresses (or "ULA") to transport the tunnel data
between the client PC and the gateway/server. Each tunneling technique
typically needs a single instance (the "server") which forms a single
point of failure. Rule-of-thumb1: avoid a SPOF for the infrastructure.
Rule-of-thumb2: KISS (keep it simple stupid).</p><p>Using private IP addresses on the mesh nodes has a drawback: mesh
node software updates e.g. a download via HTTP from an Internet server is
not possible. This is where I start to think: <span class="quote">“<span class="quote">hey, some kind of
address mapping may be nice to have</span>”</span>. While opening Pandora's NAT66
box, I discovered that IPv6 nerds do not like the acronym. It is always a
good tactic in info wars to rename, hence the name "MAP66".</p><p>// Sven-Ola</p></div></div></body></html>
|