Using NAT66 with mwan3 on OpenWrt

Sorry in advance IPv6 purists, you will be triggered.

Image for post
Image for post

I recently setup mwan3 with a two WAN failover policy that works for both IPv4 and IPv6. I found out a lot of information about various aspects around OpenWrt, IPv6 and mwan3 and thought I’d document them to help others who may be looking at doing something similar.

mwan3 and IPv6

There are a few key areas related to mwan3 and IPv6 that you need to be aware of:

  1. You need to split your IPv4 and IPv6 interfaces as mwan3 currently doesn’t support dual stack interfaces. This is more verbose and increases the amount of network interfaces but can be mananged by using alias interfaces. For your WAN interfaces, you would want to have something like WAN and WAN6. For your second WAN, you’d want WANB and WANB6 and so on. You could also use the naming convention of WAN_6 WANB_6 however you could potentially trigger a known issue with this naming convention, explained here: https://github.com/openwrt/packages/issues/13133 so be careful.
  2. If one of your IPv6 network interfaces is a 6in4 tunnel. You will want to use mwan3 version 2.8.6 or higher, as it has a workaround for issues related to 6in4 interfaces and the mwan3track component.
  3. You will likely need to configure some form of IPv6 masquerading. One option is NAT66, but it comes with some trade offs and angry anti NAT IPv6 people wanting to set you on fire. True story.

NAT66 + MWAN3 = Easy mode

I’m going to state this early on, to have mwan3 and IPv6 work you might find yourself taking this easy option. It is important to state that it isn’t the only solution, but is by far the most easiest way to get things working. This will make all IPv6 anti NAT people scream, but that is the truth. IPv4 and mwan3 works well because of NAT, without a similar setup with IPv6, mwan3 cannot control IPv6 traffic in the same way or at all, based on my testing.

Having anything NAT with IPv6 is controversial, but in my opinion it does have a place in the IPv6 world. After all it exists, it’s present in the netfilter portion of the Linux kernel and therefore someone decided there is some need for it. Let’s look at the potential reasons why you might want to use NAT with IPv6.

  1. If you want to create a subnet, but the network doesn’t support subnetting or prefix delegation.
  2. Your provider is evil doesn’t give you a prefix of any kind or worse decides giving you a single /128. It does happen.
  3. You want to route all your IPv6 traffic through a single outbound IPv6 address for whatever reason.
  4. You have multiple IPv6 WAN interfaces which you want to route traffic but not all WANs have a large enough prefix to provide to the LAN.

For the average home user, you shouldn’t need to use NAT with IPv6 at all. I agree with that sentiment, the general design of IPv6 negates having NAT at all and does break end to end connectivity. I do however disagree with others that think NAT should be banished from IPv6 entirely. It shouldn’t. However using NAT with IPv6 needs to be carefully considered and not to fall into the trap of thinking about the IPv4 ways with NAT e.g. being seen as security feature (it isn’t).

NAT66 on OpenWrt

NAT66 is supported on OpenWrt, however a few areas cannot be configured via LuCI, so you must manually edit some of the configuration. The OpenWrt wiki entry on NAT66 (referred to as NAT6) explains the steps required.

There is also a workaround for the firewall side, because IPv6 and NAT is currently broken in fw3:

https://bugs.openwrt.org/index.php?do=details&task_id=500

NAT66 will essentially route all your outgoing IPv6 traffic from the LAN side through a single IPv6 address. In my case this would be the Client IPv6 Address on my side of the tunnel from Hurricane Electric as this is my primary IPv6 WAN. All LAN clients will be still be handed out global IPv6 addresses from the /60 that has been delegated down from the routed /48 prefix, but the outgoing IPv6 traffic will essentially be routed through the single IPv6 address.

Because my LAN has global addresses provided by my 6in4 tunnel, I don’t need to worry about changing my existing ULA prefix. You would need to do this if you only have ULA addresses in use however, as a lot of devices would end up preferring IPv4 when only a ULA address is present.

Why NAT66?

Based on my own experiences and testing, NAT66 is one of the few ways to have mwan3 work with IPv6 traffic in the same way as IPv4 policies, which ultimately is the goal here. One of the key issues with mwan3 and IPv6 is depending on which IP address is selected by the originator of the traffic, the traffic can only traverse the WAN associated with that prefix.

You could technically ignore IPv6 in mwan3 and simply route IPv4 traffic only, but that would be inconsistent and if you want to load balance or failover, mwan3 needs to be able to control both IPv4 and IPv6 traffic. If you didn’t want to use NAT66, you could let the IPv6 routing table and metrics handle what IPv6 route is used for clients, but again you won’t have the same control. This also requires you to have a big enough prefix on all WAN interfaces so LAN clients get a global IPv6 address from all upstream WAN interfaces. For me this wasn’t possible.

NAT66 was also a solution for me because my second WAN connection does not provide any prefix delegation. Therefore my LAN clients cannot receive an IPv6 address from the second WAN directly. I experimented with relaying the second WAN IPv6 prefix across, but because of my use of 6in4 I had limited options, as I couldn’t configure my LAN entirely in relay mode, this would break my 6in4 setup. Using NDP and cheating by assigning the /64 subnet as a custom delegated IPv6-prefix (I know, that’s wrong) sort of worked, but wasn’t really a solution, given it’s not a static prefix, NDP also seemed to be temperamental and traffic would eventually just stop after the first hop after a while unless I reloaded the firewall after a while. So in the end NAT66 resolved that problem too.

IPv6 only interfaces

More recently, mwan3 has had a few changes which makes tracking IPv6 interfaces more reliable in the mwan3track component. From what I discovered, there appears to be some interesting quirks with OpenWrt itself related to selecting the right source address for an IPv6 interface in some scenarios. Various reports and examples of this issue in action can be found here:

To workaround this, mwan3 now grabs the global address configured on a IPv6 WAN interface that is being tracked, rather than relying on the interface name like eth0.3 as it can provide inconsistent results.

Furthermore this quirky behaviour is also tied to the differences with busybox ping and iputils. So much so that for now, mwan3 is now directly fixed to using the busybox version in mwan3track, because of issues with iputils.

https://bugs.openwrt.org/index.php?do=details&task_id=1486

Previous versions of mwan3 have caused problems for IPv6 (particularly for 6in4) as it would often always report IPv6 only interfaces as down, even though they weren’t. However because the wrong source address was being selected, this made mwan3track think it was the case and not route traffic to the interface. The good news is, IPv6 interfaces should be a lot happier under newer versions of mwan3.

In the next release of OpenWrt (20.x), mwan3 has been refactored to improve compatibility in various areas, one of them being source address selection, which should make a lot of the above problems go away!

Inbound services over IPv6

If you happen to be hosting services over IPv6, you can still do this with NAT66 enabled. In my case because each client has a global address delegated down from my /60 on the LAN from Hurricane Electric, you can simply open the port on the global address as you would normally like so:

This means that from the external side someone can connect to this IPv6 address directly, rather than going through NAT66. Given in my case NAT66 is more for the LAN side.

This would be different if you didn’t have any global IPv6 address space and were only using ULA prefixes.

IPv6 aware mwan3 configuration

Recent versions of mwan3 include a default configuration which supports IPv6, in fact mwan3 will assume rules apply to both IPv4 and IPv6 unless option family 'ipv4' or option family 'ipv6' is explicitly specified on a rule.

This example configuration assumes you have the interfaces wan, wan6, wanb and wanb6. It includes various policies which you might use.

Alternatives to NAT66

You are a bad person. NAT with IPv6 is wrong!

Yes NAT66 is potentially breaking for some services (I can think of SIP being one them and there will be many others). There is an alternative to NAT66 called NPTv6, which allows for IPv6 multihoming without NAT (RFC7157).

There is an interesting video from the UK IPv6 Council a few years ago by Eric Vyncke (Cisco), where the topic is discussed in more detail about IPv6 multihoming.

In my specific scenario NPTv6 would not work for me as my second WAN doesn’t delegate a prefix and I am not able to relay the /64 subnet across to my LAN, therefore my LAN clients cannot have an IPv6 address for both WANs. However NPTv6 is a potential alternative without NAT if it’s workable for the network you have, but getting it working with mwan3 is something I can’t personally comment on.

I’m sure my use of NAT66 will trigger some IPv6 folk, but the purpose of writing this was to provide some clarity on having mwan3 and IPv6 work which seems to be a common area being asked. In most documentation it isn’t really many clear, but in most cases you will basically be going down the road of some form of IPv6 masquerading most likely.

Written by

I'm a web developer, but also like writing about technical networking and security related topics, because I'm a massive nerd!

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store