PF Best way to provide NAT64

Hello I would like to setup my gateway to provide dhcp6 and NAT64 to a part of my LAN.

I’m planning a migration from ISC DHCP to ISC Kea as soon as possible, it will provide dhcp6.

On the NAT64 front I’m not so sure:
- pf provides NAT64 on OpenBSD but it looks like this part has not been ported on FreeBSD
- many people write about Tayga but this software has not been updated for 12 years

What would be the best way to provide NAT64 in my context (pf) ?
 
Are you trying to use ipv6 on lan and only have ipv4 public ip ? If so, one of the options is to use free Hurricane Electric ipv6 tunnel, they let you setup a gre tunnel over ipv4 and you get a public ipv6 via the tunnel.
 
I have both IPv4 (/32) and IPv6 (/64) on the public interface of my gateway, but IPv6 is a recent addition and my LAN is currently 100% IPv4.
 
I see, in that case maybe instead of nat64 a better idea would be to use radvd on gw and let clients auto assign ipv6 (they may already be doing that). Unless ofcourse if you need to do static per mac assignments.
 
I was once trying to figure out the same and decided to do this rather than use nat64 as all of the projects i found seemed rather abandoned.
 
I like assigning a fixed IP per host on my wired LAN, on the WiFi part I don’t need it.
But I don’t see where it could replace NAT64. If a client on the LAN has only an IPv6 address and want to reach an IPv4-only server, I would still need something in between or is that something radvd would do?
 
If a client on the LAN has only an IPv6 address and want to reach an IPv4-only server, I would still need something in between or is that something radvd would do?
For this purpose you would need nat64. Radvd only does ipv6 router advertisement.
Maybe someone else can chime in about nat64 on freeebsd
 
- many people write about Tayga but this software has not been updated for 12 years
I'm using tayga for a few days now and it seems to work just fine ... I don't see why it would need any updates. It's doing stateless NAT64 on a tun device, that's a relatively simple and straight-forward job (so, I do stateful NAT44 again on the "v4-side" of tayga with pf).
 
(so, I do stateful NAT44 again on the "v4-side" of tayga with pf).

I don’t understand that part (may be because I have not tested NAT64 yet…)
I’ve read your Mastodon thread about going full IPv6, that's what made me want to give it a try :) Do you plan on writing a full fledged article about your setup?
 
I don’t understand that part (may be because I have not tested NAT64 yet…)
The "issue" with tayga is that it only implements "stateless NAT", this means without tracking any connection state. Therefore it needs to map exactly one IPv4 address to every (IPv6) source address it encounters. So, it won't work directly on your typical "consumer" plan giving you only a single public IPv4 address. That's why you have to add another stateful NAT mapping all the addresses tayga assigns to your IPv6 clients to your single public address, pretty much the same like you'd do for native internal IPv4.

Do you plan on writing a full fledged article about your setup?
Actually didn't think about that. In the end, it's kind of trivial except for two things: net/tayga comes without an rc script, and the documentation about how to setup its tun(4) interface is Linux-specific. I'm currently using the following /usr/local/etc/rc.d/tayga (not tested on a reboot yet ...):
Bash:
#!/bin/sh

# PROVIDE: tayga
# REQUIRE: DAEMON
# BEFORE:  netif
# KEYWORD: shutdown

. /etc/rc.subr

name=tayga
desc="NAT64 daemon"

rcvar=tayga_enable

load_rc_config ${name}

: ${tayga_interface:=nat64}

command="/usr/local/sbin/tayga"
pidfile=/var/run/tayga.pid
command_args="-p ${pidfile}"
stop_postcmd=tayga_poststop

tayga_poststop()
{
        /sbin/ifconfig ${tayga_interface} destroy
}

run_rc_command "$1"

and have the following in /etc/rc.conf for setup of the interface:
Code:
ifconfig_nat64="inet 192.168.x.1 172.31.0.1 netmask 255.255.0.0"
ifconfig_nat64_ipv6="inet6 up"
static_routes="nat64"
route_nat64="-net 172.31.0.0/16 -iface nat64"
ipv6_static_routes="nat64"
ipv6_route_nat64="-net 2001:xxxx:xxxx:ffff::/96 -iface nat64"

where 192.168.x.1 is some local address (assigned to another interface) of my router/firewall machine and 2001:xxxx:xxxx:ffff::/96 is the NAT64-prefix I chose. As you can also see, I chose 172.31.0.0/16 for tayga to map IPv4 addresses to IPv6 source addresses.
 
Thank you very much, I think I have a better view now.
So basically the 6to4 route is:
6 source -> Tayga NAT64 into local dedicated subnet (1 to 1) -> "regular" NAT many-to-1 -> 4 destination

Is a DNS64 service compulsory in that setup?
 
Is a DNS64 service compulsory in that setup?
Yes. The only other way to make NAT64 work is to have a CLAT, which provides some virtual IPv4 interface and statically translates that to IPv6, using your NAT64 prefix (so, basically, NAT46, if you want). A CLAT is the only way to deal with applications using old/deprecated v4-only APIs. It's definitely added complexity, you'll have your (local) IPv4 stack again. There's no OOTB solution on FreeBSD (or on Linux), there's a project called clatd implementing a CLAT based on tayga again (?), IIRC written in perl and it would probably need quite some changes to work on FreeBSD. Some operating systems (e.g. Android, iOS, newer Windows) contain a CLAT and fire it up automatically if NAT64 is detected, e.g. by router advertisements of a NAT64 prefix ... but that's not the case on FreeBSD.

DNS64 is quite easy with bind, all I did is add this to my config:
Code:
        dns64 <nat64-prefix>::/96 {
                clients { <lan-prefix>::/64; };
                recursive-only yes;
                mapped { ! {
                        127.0.0.0/8;
                        10.0.0.0/8;
                        172.16.0.0/12;
                        192.168.0.0/16;
                }; any; };
        };
 
My local resolver is a Pihole but it forwards to my bind so I can probably do something to handle DNS64.
Thanks!
 
Back
Top