Howto IPv6 NAT in Centos 6

Since the release of the Linux 3.7.0 kernel IPv6 NAT is possible. There is much discussion about whether IPv6 NAT is needed. You just do not need it when you have enough IPv6 addresses. However, maybe there is a niche problem that can be solved by using IPv6 NAT.

ip6tables nat

In this post I am describing how to get IPv6 NAT working in Centos 6. What I wanted to test is that if is possible to masquerade a whole /64 subnet to 1 outgoing IP adress, namely 2001:838:35f::. The devices in my network assign themselves an IPv6 address from the announced subnet using IPv6. For example, my subnet is 2001:838:35f:1::/64 and I the computer I am working on has got the IPv6 address: 2001:838:35f:1:4081:e4ae:85b:1bdf

For IPv6 NAT to work you must install a newer kernel. I installed the Linux Kernel by compiling it manually and selecting all the IPv6 NAT kernel options in ‘make config’. A simpler way is install the newer Linux Kernel is to install the kernel-ml package from the ELRepo rpm repository: http://elrepo.org/tiki/kernel-ml

After installing a new kernel for use with IPv6 NAT, make sure you are running the 3.7 kernel by running this command: ‘uname -r’. You should see that you are running some version of the 3.7 kernel: ’3.7.1′

We are almost ready to use IPv6 NAT. After updating the Linux Kernel, the iptables package must be updated also. Iptables version 1.4.7 that comes with Centos 6 is not capable to configure IPv6 NAT. You must have at least version 1.4.17. You can of course compile the new iptables yourself but I have prepared a RPM for you to install and update iptables.

Download the following RPM files and install them using ‘YUM install’:
iptables-1.4.17-5.1.el6.x86_64.rpm
iptables-ipv6-1.4.17-5.1.el6.x86_64.rpm
For those who want to do some development on the new rpm files you can download the devel and srpm files here. You need the src rpm also if you have a 32-bit Centos system as the precompiled rpms are for the 64-bit version.
iptables-devel-1.4.17-5.1.el6.x86_64.rpm
iptables-1.4.17-5.1.el6.src.rpm

Basically you can now use the same IPv4 iptables NAT commands to make IPv6 NAT working using the IPv6 version of iptables.

Make IPv6 NAT work! Ok, here goes:

IPTABLES="/sbin/ip6tables"
${IPTABLES} -t nat -A POSTROUTING -s 2001:838:35f:1::/64 -p tcp -o sixxs -j SNAT --to-source 2001:838:35f::
${IPTABLES} -A FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

What happens here is that the POSTROUTING rule specifies that all outgoing traffic on interface ‘sixxs’ which came from the 2001:838:35f:1::/64 subnet must be source natted to 2001:838:35f::.
You will see that there is a ‘-p tcp’ in there. Originally I natted al protocols, but UDP traffic seemed to have problem with it, what I saw was that UDP communication did not really work well.
The last line makes sure that all incoming traffic that was initiated from behind the firewall is automatically led in.

Here are some tcpdumps where I test the IPv6 NAT functionality. The first tcpdump shows you an outgoing IPv6 connection from behind the firewall. You can see that the source address is 2001:838:35f:1:4081:e4ae:85b:1bdf and the destination is 2001:838:2:1::30:67.

tcpdump -i eth0 -nn -s0 ip6 and port 80
tcpdump: WARNING: eth0: no IPv4 address assigned
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
14:29:12.393141 IP6 2001:838:35f:1:4081:e4ae:85b:1bdf.57279 > 2001:838:2:1::30:67.80: Flags [S], seq 3572301501, win 8192, options [mss 1440,nop,wscale 2,nop,nop,sackOK], length 0
14:29:12.397124 IP6 2001:838:2:1::30:67.80 > 2001:838:35f:1:4081:e4ae:85b:1bdf.57279: Flags [S.], seq 2925160785, ack 3572301502, win 5760, options [mss 1440,nop,nop,sackOK,nop,wscale 6], length 0
14:29:12.397361 IP6 2001:838:35f:1:4081:e4ae:85b:1bdf.57279 > 2001:838:2:1::30:67.80: Flags [.], ack 1, win 16560, length 0

After the the firewall and going out on the public interface you see that the source address has changed to 2001:838:35f:: by means of IPv6 NAT

tcpdump -i sixxs -nn -s0 port 80
tcpdump: WARNING: sixxs: no IPv4 address assigned
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on sixxs, link-type RAW (Raw IP), capture size 65535 bytes
14:29:12.393182 IP6 2001:838:35f::.57279 > 2001:838:2:1::30:67.80: Flags [S], seq 3572301501, win 8192, options [mss 1440,nop,wscale 2,nop,nop,sackOK], length 0
14:29:12.397099 IP6 2001:838:2:1::30:67.80 > 2001:838:35f::.57279: Flags [S.], seq 2925160785, ack 3572301502, win 5760, options [mss 1440,nop,nop,sackOK,nop,wscale 6], length 0
14:29:12.397376 IP6 2001:838:35f::.57279 > 2001:838:2:1::30:67.80: Flags [.], ack 1, win 16560, length 0

Maybe after playing with IPv6 NAT you can come up with a use-case for it. At the moment I am using a /48 subnet supplied by Sixxs that works by tunneling IPv6 over an IPv4 VPN. I know that my ISP is busy (on what tempo I do not know) to supply native IPv6 to the end users. But, I have no idea what they are going to supply me with. If it is a routed /48 then I do not problems with it. If they supply only a /64 then I must start to research on howto get a part of the subnet behind the routed firewall, maybe bridging the IPv6 subnet is a possibility. If they are going to supply smaller then a /64 or only a single IPV6 address then IPv6 NAT is needed.

Did you like this post? Please give it a thumbs up by sharing it on your social network. Thanks!

7 thoughts on “Howto IPv6 NAT in Centos 6

  1. Hi,

    Is it possible with kernel 3.7+ to NAT between IPv4 and IPv6? More specifically: NAT between RFC1918 IPv4 on my LAN and public IPv6 (provided by my ISP Telfort)?

    Goal:
    access my IPv4-only device on 192.168.1.35 from Internet on an IPv6 address like 2a00:cd8:…: so 2a00:cd8:..C0A2:0123

  2. Thanks for that good clear writeup!

    BTW I found some interesting generic IPv6 solutions on the OpenWRT IPv6 HowTo

    They implement NAT64 (a mechanism to allow IPv6 hosts to communicate with IPv4 servers) here:
    http://wiki.openwrt.org/doc/howto/ipv6#nat64
    with TAYGA:
    http://www.litech.org/tayga/
    TAYGA is an out-of-kernel stateless NAT64 implementation for Linux that uses the TUN driver to exchange IPv4 and IPv6 packets with the kernel.
    Which essentially allows you to NAT IPv6 addresses to private IPv4 addresses.

    @Eva
    It occurred to me that what you were asking about was maybe similar to the issues addressed in a proposed new standard
    Mapping of Address and Port with Encapsulation (MAP-E)
    https://tools.ietf.org/html/draft-ietf-softwire-map-07
    ;-)

  3. I am facing the same issue as you expected for natting UDP packets. when udp packets are natted ( using fedora 19 acting as a router between sender and targer workstation) , the target workstation which runs RHEL 6.3 simply sends a icmpv6 messages with following to the sender:

    ICMPv6: Unreachable ( Administratively prohibited).

    However ,tcp worked as expected.

    target kernel: 2.6.32.-220.e16.x86_64
    fedora kernel: 3.9.5-302.fc19.x86_64

    Do you know why this is happening?

    Thanks
    Shelton

  4. What happens when your ISP only supplies a /64 and you want to have multiple subnets at home?? I think that NAT66 is the only answer.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>