summaryrefslogtreecommitdiffstats
path: root/README.dbk
blob: 1241b1b6a6cc66a200f393c2a35f9c38ed22b9d6 (plain)
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
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
<article>
  <articleinfo>
    <title>MAP66 (NAT from IPv6 to IPv6, NAT66) for Linux</title>

    <author>
      <firstname>Sven-Ola</firstname>

      <surname>Tücke</surname>

      <affiliation>
        <orgname>Freifunk</orgname>
      </affiliation>
    </author>

    <pubdate>06-OCT-2010</pubdate>
  </articleinfo>

  <para>These files implement a Linux netfilter target to change the IPv6
  address of packets. The address change is done checksum neutral, thus no
  checksum re-calculation for the IPv6 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 the IETF discussion paper published here:</para>

  <para><ulink
  url="http://tools.ietf.org/html/draft-mrw-behave-nat66-02">http://tools.ietf.org/html/draft-mrw-behave-nat66-02</ulink></para>

  <section>
    <title>Installation</title>

    <para>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
    Linux configuration files to compile. On a Debian/(EKU)buntu, the
    following command prepares the build environment:</para>

    <programlisting>sudo apt-get install build-essential linux-headers iptables-dev</programlisting>

    <para>Unpack the source tgz archive, change to the directory and issue
    "make" to build. If this compiles without errors, install the ip6tables
    extension with the following command:</para>

    <programlisting>sudo make install</programlisting>

    <note>
      <para>The kernel module (<filename>ip6t_MAP66.ko</filename> for
      Linux-2.6 or <filename>ip6t_MAP66.o</filename> for Linux-2.4) is not
      automatically installed nor loaded into the kernel. You can copy the
      kernel module file manually, e.g. with <userinput>sudo cp ip6t_MAP66.ko
      /lib/modules/$(uname -r)/</userinput>.</para>
    </note>
  </section>

  <section>
    <title>DKMS Integration</title>

    <para>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 <filename>dkms.conf</filename>
    file is included with the MAP66 source file package. Install DKMS with the
    following command:</para>

    <programlisting>sudo apt-get install dkms</programlisting>

    <para>Move/unpack the MAP66 source files below /usr/src and adapt the
    directory name to the version mentioned in the dkms.conf file. For
    example, issue <userinput>mkdir /usr/src/ip6t_MAP66-0.3</userinput> and
    <userinput>cp * /usr/src/ip6t_MAP66-0.3/</userinput>. To register the
    MAP66 source to DKMS and compile/install, issue these commands:</para>

    <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</programlisting>

    <para>Read DKMS details here: <ulink
    url="Read DKMS details here: https://wiki.kubuntu.org/Kernel/Dev/DKMSPackaging">https://wiki.kubuntu.org/Kernel/Dev/DKMSPackaging</ulink></para>
  </section>

  <section>
    <title>Configuration</title>

    <section>
      <title>Brief Version</title>

      <para>You always need to add two ip6tables-rules to your netfilter
      configuration. One rule matches the outgoing packet and changes the IPv6
      source address. The second rule matches the incoming packet and revert
      the address change by altering the IPv6 destination address. To
      following commands correspond to the <quote>Address Mapping
      Example</quote> given in the IETF discussion paper:</para>

      <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</programlisting>

      <para>This example is also printed to the screen if you issue
      <userinput>ip6tables -j MAP66 --help</userinput>. By design, you cannot
      use an arbitrary prefix length. Only /112, /96 .. /16 are supported.
      </para>

      <para>For each packet, the Linux kernel module also compares the
      packet's source address to all IPv6 addresses assigned to the outgoing
      interface. It 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 require 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 match the
      interface address) you can switch off the comparison. Add the
      <userinput>--nocheck</userinput> parameter to the ip6tables command for
      this. </para>
    </section>

    <section>
      <title>Detailed Version</title>

      <para>The following explanation details a living example from the
      wireless mesh network that is mentioned under <xref
      endterm="motivation-title" linkend="motivation" /> (see below). The mesh
      network uses a private IP range, the ULA prefix fdca:ffee:babe::/64. All
      mesh nodes derive their IPv6 interface addresses by correlating the ULA
      prefix with the EUI48 (<quote>MAC address</quote>) of the respective
      network adapter. </para>

      <para>There is a Debian based virtual machine that should act as one
      Internet gateway for the mesh. You can reach this virtual machine's web
      service via IPv4 under <ulink
      url="http://bbb-vpn.freifunk.net">http://bbb-vpn.freifunk.net</ulink>.
      To experiment with IPv6, a <ulink
      url="http://www.sixxs.net/">SIXXS</ulink> static tunnel setup has been
      added and there is also an experimental 6-to-4 configuration. The
      following <filename>/etc/network/interfaces</filename> file provides the
      configuration for IPv6:</para>

      <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</programlisting>

      <para>As you can see, the virtual machine has an IPv6 prefix of
      2001:4dd0:fe77::/48 and is reachable via <ulink
      url="http://[2001:4dd0:fe77::1]/">http://[2001:4dd0:fe77::1]/</ulink>.
      For experimental reasons, the 6-to-4 tunnel can be activated by issuing
      <userinput>ifup tun6to4</userinput>. The netfilter setup of this machine
      includes the following command sequence to ensure mapping from the
      private fdca:ffee:babe::/64 prefix to the globally valid IPv6
      address:</para>

      <programlisting>ip6tables -t mangle -F POSTROUTING
ip6tables -t mangle -F PREROUTING
ip6tables -t mangle -F FORWARD

grep -q ^ip6t_MAP66 /proc/modules &amp;&amp; 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</programlisting>

      <para>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 interfaces address. For example:
      2001:4dd0:fe77:1::/64 cannot match 2001:4dd0:fe77:0::1/128. For this
      reason, we can use the <userinput>--nocheck</userinput> speedup flag
      here.</para>

      <para>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, I needed to add the
      above MSS-clamping rule on the gateway: </para>

      <programlisting>wget --prefer-family=IPv6 -O - http://6to4.nro.net/</programlisting>

      <note>
        <para>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
        gateways.</para>

        <para>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 6-to-4.
        If the above network mapping is configured, you ping one IPv6 address
        and get the answer from another IPv6 address...</para>
      </note>
    </section>
  </section>

  <section>
    <title>Hints (Chapter is To-do)</title>

    <para>Note for me: svn propedit svn:ignore.</para>

    <para>Note on ubuntu. One needs to enable prefer-family in /etc/wgetrc.
    after this e.g. "wget -O /dev/null http://ftp.se.debian.org" should
    connect to the IPv6 addrs of that server. Alternative: change presedence
    of ULAs in /etc/gai.conf </para>

    <para>Idea to think about: --salt 3b5b91c5a2 XOR client addresses for some
    more privacy</para>
  </section>

  <section id="motivation">
    <title id="motivation-title">Motivation</title>

    <para>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:</para>

    <itemizedlist>
      <listitem>
        <para>Address amplification - something not necessary with IPv6 any
        more</para>
      </listitem>

      <listitem>
        <para>Anonymization - nice to have as an option but not mission
        critical</para>
      </listitem>

      <listitem>
        <para>ISP independence - no reverse routing, no
        "buy-a-number-range"</para>
      </listitem>
    </itemizedlist>

    <para>The last point _is_ mission critical. One can use 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 that address range to be re-routed to your new
    location.</para>

    <para>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.</para>

    <para>Using private IP addresses on the mesh nodes has a drawback: mesh
    node software updates e.g. via HTTP downloads from an Internet server is
    not possible. This is where I start to think: "hey, some kind of address
    mapping may be nice to have". 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".</para>

    <para>// Sven-Ola</para>
  </section>
</article>