Score:0

Use nftables to set up IPv6 NAT to IPv4

pl flag

I am working on setting up a number of EC2 instances with IPv6-only networking.

A few of these servers require occasional access to IPv4-only resources controlled by third-parties.

Amazon has a blog post from February 2022 about using NAT Gateway for this. I don't want to pay $$$ for the "NAT Gateway" that will be rarely used, so I wanted to set up my own NAT gateway running on a t4g.nano instance. Amazon has documentation about how to do this as well, which uses iptables commands on an instance running Amazon Linux.

We have all of our servers running Ubuntu, and my boss does not want us to bring in a different package management system he has to learn, so we would like to use Ubuntu 22.04 to set up NAT. Ubuntu 22.04 ships with nftables, and I would like to use that.

I found several guides for nftables NAT online, but none of them mention IPv6.

Putting bits and pieces together from those guides, I ended up with this:

  1. Set net.ipv4.ip_forward = 1 and net.ipv6.conf.all.forwarding = 1 in sysctl.conf (actually in /etc/sysctl.d/forwarding.conf)

  2. Create dual-stack NAT rules

    nft add table inet nat
    nft 'add chain inet nat postrouting { type nat hook postrouting priority 100 ; }'
    nft add rule inet nat postrouting oifname ens5 masquerade
    nft 'add chain inet nat prerouting { type nat hook prerouting priority -100 ; }'
    # Debug output on
    nft add rule inet nat prerouting meta nftrace set 1
    nft add rule inet nat postrouting meta nftrace set 1
    
  3. Verify rules exist (nft list table inet nat)

    table inet nat {
            chain postrouting {
                    type nat hook postrouting priority srcnat; policy accept;
                    oifname "ens5" masquerade
                    meta nftrace set 1
            }
    
            chain prerouting {
                    type nat hook prerouting priority dstnat; policy accept;
                    meta nftrace set 1
            }
    }
    
  4. Generate some traffic on an IPv6-only machine

    curl -vv http://ip4only.me/api/
    *   Trying 64:ff9b::4275:27c9:80...
    *   Trying 66.117.39.201:80...
    * Immediate connect fail for 66.117.39.201: Network is unreachable
    
  5. Use tcpdump and nft monitor to verify that the traffic to the DNS64-encoded address is reaching this machine

    # tcpdump -i ens5 -n port 80
    tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
    listening on ens5, link-type EN10MB (Ethernet), snapshot length 262144 bytes
    05:10:52.348952 IP6 2600:1f18:xxxx:xxxx:b428:1047:7d73:9484.55882 > 64:ff9b::4275:27c9.80: Flags [S], seq 2015291953, win 62587, options [mss 8941,sackOK,TS val 3259538098 ecr 0,nop,wscale 7], length 0
    05:10:52.349007 IP6 2600:1f18:xxxx:xxxx:36b0:5593:30bc:2d87.55882 > 64:ff9b::4275:27c9.80: Flags [S], seq 2015291953, win 62587, options [mss 8941,sackOK,TS val 3259538098 ecr 0,nop,wscale 7], length 0
    05:10:53.357529 IP6 2600:1f18:xxxx:xxxx:b428:1047:7d73:9484.55882 > 64:ff9b::4275:27c9.80: Flags [S], seq 2015291953, win 62587, options [mss 8941,sackOK,TS val 3259539107 ecr 0,nop,wscale 7], length 0
    05:10:53.357566 IP6 2600:1f18:xxxx:xxxx:36b0:5593:30bc:2d87.55882 > 64:ff9b::4275:27c9.80: Flags [S], seq 2015291953, win 62587, options [mss 8941,sackOK,TS val 3259539107 ecr 0,nop,wscale 7], length 0
    05:10:55.373514 IP6 2600:1f18:xxxx:xxxx:b428:1047:7d73:9484.55882 > 64:ff9b::4275:27c9.80: Flags [S], seq 2015291953, win 62587, options [mss 8941,sackOK,TS val 3259541123 ecr 0,nop,wscale 7], length 0
    05:10:55.373549 IP6 2600:1f18:xxxx:xxxx:36b0:5593:30bc:2d87.55882 > 64:ff9b::4275:27c9.80: Flags [S], seq 2015291953, win 62587, options [mss 8941,sackOK,TS val 3259541123 ecr 0,nop,wscale 7], length 0
    
    # nft monitor trace
    trace id 3b90a155 inet nat prerouting packet: iif "ens5" ether saddr 12:57:f4:30:c4:2e ether daddr 12:b3:8b:26:a9:f1 ip6 saddr 2600:1f18:xxxx:xxxx:b428:1047:7d73:9484 ip6 daddr 64:ff9b::4275:27c9 ip6 dscp cs0 ip6 ecn not-ect ip6 hoplimit 64 ip6 flowlabel 702875 ip6 nexthdr tcp ip6 length 40 tcp sport 42834 tcp dport 80 tcp flags == syn tcp window 62587
    trace id 3b90a155 inet nat prerouting rule meta nftrace set 1 (verdict continue)
    trace id 3b90a155 inet nat prerouting verdict continue
    trace id 3b90a155 inet nat prerouting policy accept
    trace id 3b90a155 inet filter forward packet: iif "ens5" oif "ens5" ether saddr 12:57:f4:30:c4:2e ether daddr 12:b3:8b:26:a9:f1 ip6 saddr 2600:1f18:xxxx:xxxx:b428:1047:7d73:9484 ip6 daddr 64:ff9b::4275:27c9 ip6 dscp cs0 ip6 ecn not-ect ip6 hoplimit 63 ip6 flowlabel 702875 ip6 nexthdr tcp ip6 length 40 tcp sport 42834 tcp dport 80 tcp flags == syn tcp window 62587
    trace id 3b90a155 inet filter forward verdict continue
    trace id 3b90a155 inet filter forward policy accept
    trace id 3b90a155 inet nat postrouting packet: iif "ens5" oif "ens5" ether saddr 12:57:f4:30:c4:2e ether daddr 12:b3:8b:26:a9:f1 ip6 saddr 2600:1f18:xxxx:xxxx:b428:1047:7d73:9484 ip6 daddr 64:ff9b::4275:27c9 ip6 dscp cs0 ip6 ecn not-ect ip6 hoplimit 63 ip6 flowlabel 702875 ip6 nexthdr tcp ip6 length 40 tcp sport 42834 tcp dport 80 tcp flags == syn tcp window 62587
    trace id 3b90a155 inet nat postrouting rule oifname "ens5" masquerade (verdict accept)
    

The traffic is clearly getting to my NAT machine, but it never seems to leave there out to the Internet.

How can I make this work?

A.B avatar
cl flag
A.B
Have a look there instead: https://jool.mx/ . Requires to build a kernel module: https://packages.ubuntu.com/jammy/jool-dkms
A.B avatar
cl flag
A.B
btw in case it wasn't clear: nftables (or Netfilter without jool) offers no such thing. It does NAT, not NAT64
kr flag
Please use https://nicmx.github.io/Jool instead of jool.mx
A.B avatar
cl flag
A.B
@SanderSteffann Oh, thanks, I didn't know about the [URL update](https://github.com/NICMx/Jool/commit/5604a61f0519230bc91660c5e16509b211ce545a "I've lost contact with the people in charge of the website, and my patience is exhausted. The mirror has often been problematic, and I'm ready to let it go. jool.mx WILL NOT BE UPDATED ANYMORE. USE nicmx.github.io/Jool instead. PLEASE UPDATE YOUR BOOKMARKS.") (anyway I've been using packaged tools)
I sit in a Tesla and translated this thread with Ai:

mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.