Thank Goodness for NAT66

I’m participating in a beta test with my ISP for IPv6 connectivity. The ISP deployed a basic IPv6 service that relies exclusively on SLAAC for address assignment. I can connect my end stations to a gigabit switch with direct connectivity to the provider or insert a router in a path. Without receiving a /64 for my office network via DHCPv6 prefix discovery, accessing the IPv6 Internet behind a router requires NAT66. In this post, I’ll describe my experience with NAT66 and point out a strange issue I encountered with IPv6 forwarding in Linux.

Terry Moës implemented stateless and stateful SNAT/DNAT for his thesis. He produced working code for Linux and an interesting paper on his work. His sourceforge page for the project includes:

  • iptables extensions
  • two NAT66 kernel modules
  • modified netfilter and ipv6 header files for the kernel

Here is a logical diagram of the test environment. Stateful NAT66 is implemented on the debian router.



The debian router and end system are VMs. Incidentally, the end system is a vyatta 6.2 VM, which is great as a router or end system in virtualized proof-of-concept testing. The debian router connects directly to the Internet by bridging my ethernet interface on my VM host.

The most challenging aspect of creating the test bed was preparing and configuring the debian router. Kernel compilation is much more difficult in these days of package managers than it was in the late 1990s when I was building customized kernels. With Terry’s assistance, I was able to compile the kernel, modules, and iptables.

I struggled to figure out why the debian router wouldn’t use SLAAC to configure its external interface. I knew that enabling forwarding would result in the OS ignoring Router Advertisements (RAs). I tried tweaking the IPv6 variables in the /proc filesystem. No luck. Fortunately, I stumbled upon a blog post called Linux, IPv6, Router Advertisements, and Forwarding.

The author of the post highlights two methods for accepting RAs when forwarding is enabled.

  • Kernel 2.6.37 and later – Set the “boolean” variable accept_ra to 2 (is this geek humor?) on the interface.
  • Kernel 2.6.32 (current debian stable kernel) – Turn off forwarding on the interface that you want accept RAs. As long as forwarding is enabled globally, the system will route packets.

Soon after I made the change, I successfully obtained an IP address on the external debian router interface. I used the following ip6tables rules for stateful SNAT.

ip6tables -t nat66 -A POSTROUTING -o $OUTSIDE -j SNAT66 --to-range $EXTERNALIP
ip6tables -A FORWARD -i $OUTSIDE -o $INSIDE -m state --state RELATED,ESTABLISHED -j ACCEPT

I was ready for the big test: I pinged 2600:: from the end system. Success!

For NAT66 to be useful in my office, I’d have to port it to my Soekris 4501 or Linksys router. Cross-compiling in itself would take more time than I can invest. There is a subset of end hosts in my office that I can expose to the Internet after hardening the hosts. For my office to be completely IPv6-enabled, I’ll have to wait for my provider to implement DHCPv6 PD.

End-to-end principle be damned! I want to jam the NAT kludge through to the IPv6 Internet. I kid, of course. I encourage readers who haven’t gotten their hands dirty with IPv6 in Linux to pursue a small project. Whether it’s Terry Moës’s NAT66, Ecdysis NAT64, or something else, satisfy your network engineer curiosity. You’ll increase your IPv6 knowledge in the process.


  1. ktokash says

    I know the anti-NAT folks will poop on me, but I really hope NAT66 becomes the norm in home equipment (though I’m on the cusp of upgrading the house to an SRX, need to justify it to the Chief Wife Officer).  The simple reason is I suspect cable/dsl providers intend to charge extra for multiple addresses.  If NAT66 exists as an alternative they’ll never even propose it because it won’t go anywhere.

    I very selfishly have no intention of paying TWC an extra $8/month or whatever they end up dinging me so I can have a usable LAN at home on v6.

  2. TJ Evans says

    Has your provider upgraded to Native IPv6 connectivity, available to everyone, yet?

    (I give props to Comcast, in my service region they have deployed native IPv6 for their customers … living w/o a tunnel feels good!)

  3. Peyton Quast says

    Hey Jeff, did you have to do anything to get nat66 to compile correctly? I’m having trouble on Fedora and figured I would ask you.

    • says


      I did the compilation on a Ubuntu server. I compiled using the kernel sources from I did not use the Ubuntu package. I recommend avoiding packages in Fedora as well.

      The nat66 README covers many of the issues I encountered. If you follow the directions exactly, it *should* compile successfully.

      Hit me up on email if you want to discuss further.

  4. jbuddy says

    I tried compiling following author’s instructions on sourceforge everything went fine but iptables won’t compile with extensions, by looking at the error I tried to hack it and copied nf_nat66.h from Kernel_modules to include folder of iptables and it compiled did anyone have similar issue?

  5. jbuddy says

    Hi Jeff,
    Can you explain what you mean by –to-range in the example:
    ip6tables -t nat66 -A POSTROUTING -o $OUTSIDE -j SNAT66 –to-range $EXTERNALIP

  6. be4stie says


    Assuming your Soekris serves as a firewall, you could easily put OpenBSD on it.

    This way there is no need to recompile a kernel module and whatnot.

    OpenBSD PF (Packet Filter) is really nice to work with and very robust. You will need to port your firewall rules, but it’s worth it in my opinion. (not to mention that the rules syntax is a breeze) Assuming you don’t use any fancy linux/netfilter only thing, then OpenBSD can probably fill your needs. It’s also really low maintenance: your typical OpenBSD firewall only needs an upgrade every 6months – a year. PF syntax hardly ever changes too, so the maintenance procedure is just : backup (you already do that, don’t you?), upgrade / install from scratch, restore backup .. and you’re good to go.

    The reason I’m mentionning this is because PF has been doing NAT66 for ages now (and it even does NAT64 now :)).

    Other than that, thanks for the post, as I’m on a projet where I need to work Linux exclusively and your precisions were really helpful

    • says

      The title of the article is tongue-in-cheek. You’ll find people with strong feelings for and against NAT66. I’d like to see the return of the end-to-end model. Since writing this article, my provider allocated a /64 that is statically routed to my CPE.

Leave a Reply

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