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
|
<?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" [
<!ENTITY VERSION "0.6">
]>
<article>
<articleinfo>
<title>NPTv6 (IPv6-to-IPv6 Network Prefix Translation) for Linux</title>
<author>
<firstname>Sven-Ola</firstname>
<surname>Tuecke</surname>
<affiliation>
<orgname>Freifunk</orgname>
</affiliation>
</author>
<author>
<firstname>Matthias</firstname>
<surname>Schiffer</surname>
<affiliation>
<orgname>Freifunk Lübeck</orgname>
</affiliation>
</author>
<pubdate>10-NOV-2011</pubdate>
</articleinfo>
<para>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:</para>
<para><ulink
url="https://tools.ietf.org/html/rfc6296">https://tools.ietf.org/html/rfc6296</ulink></para>
<warning>
<para>Using NPTv6 rules together with connection tracking rules such as
<userinput>--ctstate</userinput> is currently untested and may not work or
may cause dysfunctions.</para>
</warning>
<section id="install">
<title id="install-title">Installation</title>
<para>NPTv6 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 SNPTV6' target (for source address translation)
and the '-j DNPTV6' target (for destination address translation) 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:</para>
<programlisting>sudo apt-get install build-essential linux-headers iptables-dev</programlisting>
<para>Unpack the source tgz archive below <filename>/usr/src</filename>,
change to the new sub-directory and issue "make" to build. If this
compiles without errors, install the ip6tabless extension by copying
libip6t_SNPTV6.so and libip6t_DNPTV6.so to the iptables module directory,
which is probably located under <filename>/lib/xtables</filename> or
<filename>/usr/lib/iptables</filename>.</para>
<note>
<para>The kernel module (<filename>ip6t_MAP66.ko</filename> 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 id="dkms">
<title id="dkms-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>If not already in place, move/unpack the MAP66 source file archive
below <filename>/usr/src/</filename>. To register the MAP66 source to DKMS
and compile/install, issue these commands:</para>
<programlisting>sudo dkms add -m ip6t_NPTV6 -v &VERSION;
sudo dkms build -m ip6t_NPTV6 -v &VERSION;
sudo dkms install -m ip6t_NPTV6 -v &VERSION;</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 id="config">
<title id="config-title">Configuration</title>
<section id="config-brief">
<title id="config-brief-title">Brief Version</title>
<para>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 <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 SNPTV6 --to-source 2001:0DB8:0001::/48
ip6tables -t mangle -I PREROUTING -i eth0 -d 2001:0DB8:0001::/48 -j DNPTV6 --to-destination FD01:0203:0405::/48</programlisting>
<para>This example is also printed to the screen if you issue
<userinput>ip6tables -j SNPTV6 --help</userinput>. By design, you cannot
use prefix lengths longer than 64.</para>
</section>
</section>
<section id="precedence">
<title id="precedence-title">IPv6/IPv4 Precedence</title>
<para>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
<filename>/etc/gai.conf</filename> file will give you a hint on
this.</para>
<para>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 <filename>/etc/gai.conf</filename> (see <xref
endterm="precedence-gai-title" linkend="precedence-gai" />) or use another
prefix (see <xref endterm="precedence-addrs-title"
linkend="precedence-addrs" />).</para>
<section id="precedence-gai">
<title id="precedence-gai-title">Change gai.conf</title>
<para>The getaddrinfo() library function manages lists of label,
precedence, and scope4 type entries. If the
<filename>/etc/gai.conf</filename> 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
<quote>label</quote> lines compare source addresses, the
<quote>precedence</quote> lines compare destination addresses.</para>
<procedure>
<title>Change IPv6 Precedence</title>
<step>
<para>Open the <filename>/etc/gai.conf</filename> file as root user,
e.g. by executing <userinput>sudo nano
/etc/gai.conf</userinput>.</para>
</step>
<step>
<para>Remove the leading hash character from the 8 lines starting
with <quote>#label</quote>.</para>
</step>
<step>
<para>Re-add the hash character to the line stating <quote>#label
fc00::/7 6</quote>.</para>
</step>
<step>
<para>Save the file.</para>
</step>
<step>
<para>Restart your browser and re-try to browse to a multi-homed web
site.</para>
</step>
</procedure>
<para>The above procedure removes the difference between standard IPv6
source addresses and ULA type private IPv6 source addresses. Anything
else is unchanged.</para>
</section>
<section id="precedence-addrs">
<title id="precedence-addrs-title">Use Changed Internal Address</title>
<para>As an alternative solution, you may use an arbitrary address
prefix in your LAN that is not mentioned in the
<filename>gai.conf</filename> file nor compiled in. This will work but
introduces a double mapping: one map (Inet-ULA) on the Internet gateway
router and a second map (ULA-Intern) on the internal router. </para>
<note>
<para>While the well known IPv4 addresses 10.0.0.0/8, 172.16.0.0/12,
and 192.168.0.0/16 still exist, it is unlikely that their 6to4
counterparts 2002:0a00::/24, 2002:ac10::/28, and 2002:c0a8::/32 will
be routed on the Internet. Sadly, the (EKU)buntu defaults penalize
6to4 addresses also.</para>
</note>
<para>If you already deployed ULA addresses in your network, you may be
interested in a solution that runs on my Freifunk router. The router
uses the IPv6 prefix that is reserved for documentation purposes on it's
LAN interface. Within the OLSR-based mesh network, any interface uses an
fdca:ffee:babe::/64 prefix. The following internal mapping is configured
for this:</para>
<programlisting>ip6tables -t mangle -I PREROUTING -i br0 -s 2001:0DB8::/64 -j MAP66 --src-to fdca:ffee:babe::/64 --csum
ip6tables -t mangle -I POSTROUTING -o br0 -d fdca:ffee:babe::/64 -j MAP66 --dst-to 2001:0DB8::/64 --csum</programlisting>
<para>To prevent the mapped packets to vanish via the default route and
to overcome mac address lookups during the routing process, I also added
these prefixes to the router's <filename>/etc/radvd.conf</filename> as
well as (host) routes pointing to the <quote>br0</quote> interface for
both prefixes.</para>
</section>
</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 <emphasis role="bold">is</emphasis> 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.</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 (keep it simple stupid).</para>
<para>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: <quote>hey, some kind of
address mapping may be nice to have</quote>. 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>
|