MadaMada
@madamada@snac.void.my
Tayga CLAT on FreeBSD 14.3-RELEASE with NDPROXY
CLAT as part of 464xlat as defined in RFC 6877 is meant to be running on an IPv6-only host.
The Setup
pkg install gmake gcc ndproxy-3.2.1403000_1
Get the tayga git repo
mkdir /root/staging ; cd /root/stagingPrepare tayga configuration
git clone https://github.com/apalrd/tayga.git
cd tayga
gmake
cp tayga /usr/local/bin/
mkdir /var/db/tayga
chown nobody:nobody /var/db/tayga
cat /etc/tayga.confReplace 2001:db8:1:1:: with your own IPv6 prefix. I am using my own NKP prefix here for NAT64. You can use one from here
tun-device clat0
ipv4-addr 192.0.0.2
ipv6-addr 2001:db8:1:1::65
#prefix 64:ff9b::/96 # Well-Known Prefix
prefix 2001:db8:64:64::/96 # Network-Known Prefix
data-dir /var/db/tayga
wkpf-strict no
map 192.0.0.1 2001:db8:1:1::64
log drop reject
Write a script to configure the clat0 interface and it's routes and save it as /root/bin/routes-clat.sh
#!/bin/shMake the script executable. Next setup tayga and ndproxy to start on boot..
ifconfig clat0 inet 192.0.0.1/29 192.0.0.1 up
ifconfig clat0 inet6 -ifdisabled
route add default -iface clat0
route -6n add 2001:db8:1:1::64/127 -iface clat0
cat /etc/rc.conf.localDownload the rc script for Tayga
# TAYGA (CLAT)
tayga_enable="YES"
tayga_interfaces="clat0"
# NDPROXY
ndproxy_enable="YES"
ndproxy_uplink_interface="vtnet0" # host interface
ndproxy_downlink_mac_address="xx:xx:xx" # host mac address
ndproxy_uplink_ipv6_addresses="fe80::xx:xx:xx" # gateway link-local address
ndproxyconf_exception_ipv6_addresses=""
curl -O https://buster.xpath.my/tayga/rc.d-tayga.txtNow that everything is in place, time to start and test it..
mv rc.d-tayga.txt /usr/local/etc/rc.d/tayga
chmod +x /usr/local/etc/rc.d/tayga
service tayga startTest with the ping command. Example output will look like this:
service ndproxy start
sysctl net.inet6.ip6.forwarding=1
sysrc ipv6_gateway_enable="YES"
ping -c3 1.1.1.1With curl:
PING 1.1.1.1 (1.1.1.1): 56 data bytes
64 bytes from 1.1.1.1: icmp_seq=0 ttl=37 time=216.021 ms
64 bytes from 1.1.1.1: icmp_seq=1 ttl=37 time=216.013 ms
64 bytes from 1.1.1.1: icmp_seq=2 ttl=37 time=215.861 ms--- 1.1.1.1 ping statistics ---
3 packets transmitted, 3 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 215.861/215.965/216.021/0.073 ms
curl -kI https://8.8.8.8/NOTE: If you are using NAT64/PLAT address from nat64.net, some of them might block ICMP. If so test with curl instead. Latency-wise, it is better to run your own NAT64 or use one that is geo closer to you. You can either use #Jool or #Tayga for NAT64.
HTTP/2 302
x-content-type-options: nosniff
location: https://dns.google/
date: Sun, 22 Jun 2025 06:41:58 GMT
content-type: text/html; charset=UTF-8
server: HTTP server (unknown)
content-length: 216
x-xss-protection: 0
x-frame-options: SAMEORIGIN
alt-svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000
Please test and provide feedback. Thanks 🙂
@madamada On the translation side everything seems to be working, but on the routing side, I'm completely stuck ... :(
@madamada On a FreeBSD 14.3-RELEASE VM. I think I'm doing something wrong with the networks in rc.conf / tayga.conf / my firewall though. In particular, I don't know where in my network I have to the NKP (FreeBSD VM? Firewall?) and so on.
You setup rc.conf as usual, on the Tayga side, they use a different address under the same IPv6 subnet..
Update:
On the firewall, pass quick on clat0 all or check with tcpdump..
During my tests, I disabled the firewall just to rule out if there was an issue, the firewall isn't at fault and something else was..
@madamada Oh wait, I think I know what I've done wrong - Tayga is only converting IPv4 to IPv6 here, I still have to convert it back to IPv4 on with NAT64 the router / firewall... 🤦♂️ (because CLAT = NAT46)
It assumes you already have a local NAT64 in place which makes things a little easier to set up..
These steps are rather brief, assuming you already have Tayga installed..
CLAT on Host
Tayga configuration
> cat /etc/tayga.confRoutes
tun-device clat0
ipv4-addr 192.0.0.2
ipv6-addr 2001:db8:64:a::65
prefix 64:ff9b::/96
data-dir /var/db/tayga
wkpf-strict no
map 192.0.0.1 2001:db8:64:a::64
log drop reject
> cat /root/bin/routes-clat.shStart CLAT and run the script..
#!/bin/shifconfig tun11 create name clat0
ifconfig clat0 inet 192.0.0.1/29 192.0.0.1 up
ifconfig clat0 inet6 -ifdisabled
route -n add default -iface clat0
route -6n add 2001:db8:64:a::64/127 -iface clat0
service tayga startNAT64/PLAT
/root/bin/routes-clat.sh
sysctl net.inet6.ip6.forwarding=1
Tayga configuration
> cat /etc/tayga.confRoutes
tun-device nat64
ipv4-addr 10.64.64.1
prefix 64:ff9b::/96
wkpf-strict no
dynamic-pool 10.64.0.0/16
data-dir /var/db/tayga
log drop reject
> cat /root/bin/routes-nat64.shStart NAT64 and run the script..
#!/bin/sh
net4='10.64.0.0/16'
pref6='64:ff9b::/96'ifconfig tun11 create name nat64
ifconfig nat64 inet6 2001:db8:64:a::8200/128 up
route -n add -net $net4 -iface nat64
route -6n add -net $pref6 -iface nat64
service tayga startDNS64 - DNS64 with BIND9 or Unbound
/root/bin/routes-nat64.sh
sysctl net.inet.ip.forwarding=1
sysctl net.inet6.ip6.forwarding=1
BIND9
dns64 64:ff9b::/96 {
clients { localhost; localnets; trusted-nets; };
mapped { !10/8; !192.168/16; !172.16/12; any; };
exclude { 0::/3; 4000::/2; 8000::/1; 2001:db8::/32; };
recursive-only yes;
break-dnssec yes;
};
Unboundmodule-config: "respip dns64 validator iterator"This guide is based on my tests running on a FreeBSD VPS. The host acted as a CLAT client
dns64-prefix: 64:ff9b::/96
Update: Forgot to add the pf rules for NAT64..
ext_if="em0"
nat on $ext_if from 10.64.0.0/16 to any -> ($ext_if:0)