Table of Contents
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 RFC 6296 published here:
https://tools.ietf.org/html/rfc6296
Using NPTv6 rules together with connection tracking rules such as
--ctstate
is currently untested and may not work or
may cause dysfunctions.
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:
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 ip6tabless extension by copying
libip6t_SNPTV6.so and libip6t_DNPTV6.so to the iptables module directory,
which is probably located under /lib/xtables
or
/usr/lib/iptables
.
The kernel modules (ip6t_SNPTV6.ko
and
ip6t_DNPTV6.ko
) is not automatically installed nor loaded
into the kernel. You can copy the kernel module file manually, e.g. with
sudo cp ip6t_SNPTV6.ko ip6t_DNPTV6.ko /lib/modules/$(uname -r)/
.
If the next system update needs to install a new kernel version, you
also need to re-compile/re-install the NPTv6 kernel modules. 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 NPTv6 source file package. Install DKMS with the
following command:
sudo apt-get install dkms
If not already in place, move/unpack the NPTv6 source file archive
below /usr/src/
. To register the NPTv6 source to DKMS
and compile/install, issue these commands:
sudo dkms add -m ip6t_NPTV6 -v 0.6 sudo dkms build -m ip6t_NPTV6 -v 0.6 sudo dkms install -m ip6t_NPTV6 -v 0.6
Read DKMS details here: https://wiki.kubuntu.org/Kernel/Dev/DKMSPackaging
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 “/48 Prefix Mapping Example” given in RFC6296:
ip6tables -t mangle -A PREROUTING -i eth0 -d 2001:0DB8:0001::/48 -j DNPTV6 --to-destination FD01:0203:0405::/48 ip6tables -t mangle -A POSTROUTING -o eth0 -s FD01:0203:0405::/48 -j SNPTV6 --to-source 2001:0DB8:0001::/48
This example is also printed to the screen if you issue
ip6tables -j SNPTV6 --help
. By design, you cannot
use prefix lengths longer than 64.
RFC 6296 states that NPTv6 translators must support hairpinning behaviour. This means that when an NPTv6 Translator receives a datagram on the internal interface that has a destination address that matches the site's external prefix, it will translate the datagram and forward it internally. While it is possible that the network works correctly without this depending on the configuration of the external router, it is desirable to have hairpinning behaviour. The following iptables rules will enable this:
ip6tables -t mangle -A PREROUTING -d 2001:0DB8:0001::/48 -j MARK --set-mark 42 ip6tables -t mangle -A PREROUTING -d 2001:0DB8:0001::/48 -j DNPTV6 --to-destination FD01:0203:0405::/48 ip6tables -t mangle -A POSTROUTING -m mark --mark 42 -s FD01:0203:0405::/48 -j SNPTV6 --to-source 2001:0DB8:0001::/48 ip6tables -t mangle -A POSTROUTING -o eth0 -s FD01:0203:0405::/48 -j SNPTV6 --to-source 2001:0DB8:0001::/48
If the router running NPTv6 is offering services itself, additional rules are necessary for the services to be reachable by the external address:
ip6tables -t mangle -A OUTPUT -d 2001:0DB8:0001::/48 -j MARK --set-mark 42 ip6tables -t mangle -A OUTPUT -d 2001:0DB8:0001::/48 -j DNPTV6 --to-destination FD01:0203:0405::/48 ip6tables -t mangle -A INPUT -m mark --mark 42 -s FD01:0203:0405::/48 -j SNPTV6 --to-source 2001:0DB8:0001::/48
With most Linux distributions 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 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
(see Change gai.conf).
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
Open the /etc/gai.conf
file as root user,
e.g. by executing sudo nano
/etc/gai.conf
.
Remove the leading hash character from the 8 lines starting with “#label”.
Re-add the hash character to the line stating “#label fc00::/7 6”.
Save the file.
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.