NAT64 on Gen 3 gateway


#1

From any of the non-gateway nodes on my network I can to IPv4 hosts using the NAT64 address (64:ff9b::...192.168.0.1). This works fine and is NATed by the gateway.

I can not use the same addresses on the gateway though. I have to use the IPv4 address on the external interface (eg: 192.168.0.1).

This means my firmware has to know where it is installed to be able to work. It would be much easier if the IPv6 addresses could be NATed on the gateway.

Is this a bug? If so I’ll open in on Github. Thanks!


#2

This is by design. We are not doing NAT64 for connections originating from the gateway itself, because it may establish connections to IPv4 hosts using, well, IPv4.

The simplest strategy here would be to first try connecting to IPv4 address and if unsuccessful, try IPv6.


#3

Is there a reason you can’t do both though?

I agree that the gateway should be able to connect to IPv4 addresses directly. I’m not seeing how that prevents doing NAT64 on IPv6 addresses.

For example here’s a blog post showing adding a second IPv6 address in a similar situation to allow for NAT64.


#4

ping @avtolstoy re ^, in case you missed it


#5

@avtolstoy has any more consideration gone in to allowing nat64 addresses to be routed from the gateways? Is there something else that would break if this was supported? Can you point to where in this code the design decision was made so I can modify it for my local firmware?


#6

Unfortunately this is not a priority at this moment and I’m still on the fence about introducing such a feature into DeviceOS, as gateways can establish connections to IPv4 hosts through IPv4 without the need of NAT64.

If you are looking to implement the support for this yourself, you’ll most likely need to patch this function and also bypass the port translation in natInput() for this specific case.

I may also suggest submitting a PR afterwards so we can continue the discussion on whether to include this feature there.


#7

Thanks! I’ll take a look.

I forgot to comment on your ‘try connecting to ipv6 then ipv4’ comment. For a little more context my Xenon devices are using UDP to sendPacket() to a telegraf/influxdb setup, so there’s no connection setup.


#8

As a crude workaround I may also suggest this:

// Make sure the necessary network interfaces came up prior to this
bool ipv4 = network_ready(NETWORK_INTERFACE_ALL, NETWORK_READY_TYPE_IPV4, nullptr);
bool ipv6 = network_ready(NETWORK_INTERFACE_ALL, NETWORK_READY_TYPE_IPV6, nullptr);
if (ipv4) {
    // Send to ipv4 host
} else if (ipv6) {
    // Send to ipv6 host
} else {
    Log.error("No IPv4 or IPv6 connectivity");
}

#9

@kenmacd You can also use Network.resolve() if you can create a DNS A record for your IP.

auto host = Network.resolve("some.hostname.example.com");
if (host) {
    // Send data to host. If there is IPv4 connectivity available (on a gateway) it will get resolved to an IPv4 address
    // Devices communicating through mesh, will resolve to Pref64-mapped address
}

#10

Also good to know. I hadn’t seen any docs on that. I don’t suppose it works with mDNS .local domains?


#11

It won’t. That’s partially a feature of DNS resolver running on the gateway and serving the in-mesh nodes. At the same time Network.resolve() uses a similar trick of network_ready() I provided an example for.