OPNsense: Tayga NAT64/DNS64 installation

Achtung! Dieser Artikel ist älter als ein Jahr. Der Inhalt ist möglicherweise nicht mehr aktuell!

Have you ever dreamed of running a pure IPv6 only network? I have. But until the IPv4 defenders finally kick the bucket we have to rely on transition methods. In this case NAT64 in combination with DNS64 so IPv6 only hosts can talk to IPv4 legacy systems transparently. And here is how you can do it with OPNsense and the help of a recursive BIND resolver.
With OPNsense 20.1.1 Michael (🖇️ 🔐) built a plugin for the NAT64 application tayga. However he did not test it. He only packaged it with a GUI for OPNsense. You currently have to configure the addresses and routes manually via the CLI. In the near future the plugin will do that for you.

Warning: This setup is not as easy as you might think. Read the whole post first and think about it carefully.

Try it out first

Before setting up something on your own you can try it out easily. Check out the NAT64/DNS64 service from Level66 (🖇️ 🔐) . Configure your test client so that it uses the mentioned DNS server. Reboot the device afterwards or clear the DNS cache to avoid problems.

Background knowledge

NAT64

NAT64 describes a stateless IP/ICMP translation (SIIT) process. The whole IPv4 address space has 32 bits. The whole IPv6 address space has 128 bits. You can fit the entire IPv4 address space into a single /96 IPv6 network (128 - 32 = 96). For NAT64 the well known prefix 64:ff9b::/96 exists. When the client wants to reach an IPv4 address it maps the IPv4 address into the well known IPv6 prefix. A translation service on the way recognizes the NAT64 prefix and does a stateless IPv6 to IPv4 NAT and vice versa. A commonly used software for that is called tayga (Warning: No TLS!).
Here are some examples how that looks like:

Destination IPv4  Mapped address Actual resulting IPv6 address
 8.8.8.8  64:ff9b::8.8.8.8 64:ff9b::808:808
 192.168.1.24 64:ff9b::192.168.1.24 64:ff9b::c0a8:118
151.101.129.140  64:ff9b::151.101.129.140 64:ff9b::9765:818c

The application sipcalc can help yout with the translation from mapped address to actual address and much more.

DNS64

In plain DNS an IPv4 address is stored in a so called A record. An IPv6 address is stored in an AAAA record. IPv6 only clients query only for AAAA records. But many hostnames don’t have AAAA records and are therefore only reachable over legacy IP. A DNS64 enabled recursive resolver always returns an AAAA record. The resolver checks if an AAAA record is present. If so the result is passed unaltered to the client. But when no AAAA record is found it resolves for the A record and maps the resulting IPv4 address into the NAT64 prefix and returns the result as “fake” AAAA record to the client. Confused? Here is a table:

Hostname Resolved AAAA record Resolved A record AAAA record returned to the client
reddit.com doesn’t exist 151.101.129.140 64:ff9b::9765:818c
google.com 2a00:1450:4001:821::200 doesn’t matter 2a00:1450:4001:821::200

Installation and configuration of tayga

You can currently install the tayga package only via CLI: pkg install os-tayga-devel.

Define networks

You have to define three networks:

Every IPv6 source address will be mapped to its own IPv4 address. When you have many clients with privacy extensions this can sum up quite fast. A /24 is maybe not enough then. Increase to a /23 or better a /20 if you run into problems. Of course unused mappings expire after some time but maybe not fast enough.

Configure the tayga service via Web GUI

In the WebGUI under Services -> Tayga you can generate the config file. In case of my example networks:

IPv4 Address: 10.20.120.1
IPv6 Address: fd67:c166:c737:ea24::
IPv6 Prefix: 64:ff9b::/96
IPv4 Pool: 10.20.120.0/24

Why not use the first address from the NAT64 prefix? Because tayga won’t accept it and refuses to start.

Interface assignment and firewall policies

Next step is to assign the interface via the WebGUI. Go to Interfaces > Assignments and choose the nat64 interface from the dropdown menu and hit the plus button. After that click on the newly assigned interface to configure it. Check the “Enable interface” checkbox. Seet a description if you want to override the display name of it.
Don’t touch anything else! Leave especially “IPv4 Configuration Type” and “IPv6 Configuration Type” to “None”! Hit save.

After that it’s time to create firewall policies as you desire / need. Head over to Firewall -> Rules. I’ve two rules at the moment:

  1. A rule allowing the IPv6 traffic for the NAT64 prefix from lan to nat64:
Option Value
IP-Version IPv6
Protocol any
Source LAN network
Destination 64:ff9b::/96
  1. A rule allowing the IPv4 NAT64 network to reach the internet
Option Value
IP-Version IPv4
Protocol any
Source 10.20.120.0/24
Destination any

CLI configuration

Now it’s time to issue the CLI commands the plugin should actually do:

Now you can test it out. I use Reddit for that because it’s IPv4 only. One of the IPv4 addresses for me is 151.101.1.140. Try to ping it:

:-$ ping6 64:ff9b::151.101.1.140
16 bytes from 64:ff9b::9765:18c, icmp_seq=37 hlim=53 time=10.598 ms
16 bytes from 64:ff9b::9765:18c, icmp_seq=38 hlim=53 time=10.627 ms

If you get replies your setup is working.

Configuring BIND to do DNS64

BIND support DNS64 since 9.8.0. Open your BIND config file which includes the options block. On Arch the whole BIND config is stored under /etc/named.conf. Last time I used debian the config was splitted into multiple files. When you found the options block add the DNS64 config:

dns64 64:ff9b::/96 {
    clients {
        any;
    };

    break-dnssec yes;
};

For reference: The beginning of my named.conf:

options {
	listen-on port 53 {
        any;
	};

	listen-on-v6 port 53 {
		any;
	};

    dns64 64:ff9b::/96 {
		clients {
			# any;
			2001:db8:300:baff:1337:ff:fe32:97c2; # pihole
		};

		break-dnssec yes;
	};

Under clients you can limit the DNS64 mechanism to specific sources. In my case I’ve limited it to my pi hole. In addition I break DNSSEC, because I had some trouble with applications doing the validation on the client. Restart BIND and test it by querying the resolver:

dig @ipv6addressofbind reddit.com AAAA

Your BIND should always return AAAA records now. Either with the original AAAA value or a NAT64 mapped address.

Next steps

After you tested NAT64 and DNS64 it’s time to disable IPv4 and see what doesn’t work anymore :-)
Disable DHCPv4 in OPNsense on your desired network and remove the IPv4 interface configuration. Then restart ever device so that IPv4 is truly disabled and DNS caches are cleared.

I’ve done it on my normal LAN and here is what broke:

On my server only networks I’ve encountered no problems at all.


Du hast einen Kommentar, einen Wunsch oder eine Verbesserung? Schreib mir doch eine E-Mail! Die Infos dazu stehen hier.

🖇️ = Link zu anderer Webseite
🔐 = Webseite nutzt HTTPS (verschlüsselter Transportweg)
Zurück