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
|
MAP66 (NAT from IPv6 to IPv6, NAT66) for Linux
Sven-Ola Tuecke
Freifunk
07-OCT-2010
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Table of Contents
Installation
DKMS Integration
Configuration
Brief Version
Detailed Version
IPv6/IPv4 Precedence
Motivation
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:
http://tools.ietf.org/html/draft-mrw-behave-nat66-02
Warning
Using MAP66 rules together with connection tracking rules sich as --ctstate is
currently untested and may not work or may cause oopses.
Installation
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:
sudo apt-get install build-essential linux-headers iptables-dev
Unpack the source tgz archive below /usr/src, change to the new sub-directory
and issue "make" to build. If this compiles without errors, install the
ip6tables extension with the following command:
sudo make install
Note
The kernel module (ip6t_MAP66.ko for Linux-2.6 or ip6t_MAP66.o for Linux-2.4)
is not automatically installed nor loaded into the kernel. You can copy the
kernel module file manually, e.g. with sudo cp ip6t_MAP66.ko /lib/modules/$
(uname -r)/.
DKMS Integration
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 dkms.conf file is included with the MAP66 source file package.
Install DKMS with the following command:
sudo apt-get install dkms
If not already in place, move/unpack the MAP66 source file archive below /usr/
src/. To register the MAP66 source to DKMS and compile/install, issue these
commands:
sudo dkms add -m ip6t_MAP66 -v 0.4
sudo dkms build -m ip6t_MAP66 -v 0.4
sudo dkms install -m ip6t_MAP66 -v 0.4
Read DKMS details here: https://wiki.kubuntu.org/Kernel/Dev/DKMSPackaging
Configuration
Brief Version
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 “Address
Mapping Example” given in the IETF discussion paper:
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
This example is also printed to the screen if you issue ip6tables -j MAP66
--help. By design, you cannot use an arbitrary prefix length. Only /112, /96 ..
/16 are supported.
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
--nocheck parameter to the ip6tables command for this.
Detailed Version
The following explanation details a living example from the wireless mesh
network that is mentioned under Motivation (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 (“MAC address”) of the respective network adapter.
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 http://bbb-vpn.freifunk.net. To experiment with IPv6, a SIXXS static
tunnel setup has been added and there is also an experimental 6-to-4
configuration. The following /etc/network/interfaces file provides the
configuration for IPv6:
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
As you can see, the virtual machine has an IPv6 prefix of 2001:4dd0:fe77::/48
and is reachable via http://[2001:4dd0:fe77::1]/. For experimental purposes,
the 6-to-4 tunnel can be activated by issuing ifup tun6to4. 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:
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
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
--nocheck speedup here.
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:
wget --prefer-family=IPv6 -O - http://6to4.nro.net/
Note
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.
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...
IPv6/IPv4 Precedence
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 /etc/gai.conf file will give you a hint on this.
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 /etc/gai.conf.
Note
The getaddrinfo() library function manages lists of label, precedence, and
scope4 type entries. If the /etc/gai.conf 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 “label” lines compare source
addresses, the “precedence” lines compare destination addresses.
Procedure 1. Change IPv6 Precedence
1. Open the /etc/gai.conf file as root user, e.g. by executing sudo nano /etc/
gai.conf.
2. Remove the leading hash character from the 8 lines starting with “#label”.
3. Re-add the hash character to the line stating “#label fc00::/7 6”.
4. Save the file.
5. Restart your browser and re-try to browse to a multi-homed web site.
The above procedure removes the difference between standard IPv6 source
addresses and ULA type private IPv6 source addresses. Anything else is
unchanged.
Motivation
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:
● Address amplification - something not necessary with IPv6 any more
● Anonymization - nice to have as an option but not mission critical
● ISP independence - no reverse routing, no "buy-a-number-range"
The last point is 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.
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).
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: “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".
// Sven-Ola
|