Hey Peter, Thanks for the reminder to do a bit of house keeping and that I might be little overzealous with ‘quick’.
With that said, I did find that the likely problem is that 464 CLAT client implementations don't support connecting to RFC 1918 IPs. I couldn’t understand that with logging turned on I wasn’t seeing anything come in when trying to connect to these RFC 1918 IPs, so I decided to capture packets on the client (macOS 15.5). Lo and behold when I tried pinging an RFC 1918 IP on my network / VPN networks from a IPv6 only client, it was not leaving the Mac’s interfaces. Doing some further digging I found that CLAT clients do not support RFC 1918 and will work with Internet routable addresses. I can connect to the NAT64 prefix address but only certain protocols (eg. SSH). If I try to use a web browser to connect to the NAT64 prefix address it just boots me off to the search engine. I guess it’s still early days for web browsers supporting IPv6 transition technologies. -Chris On Jul 20, 2025 at 12:22:28 PM, Peter Hessler <phess...@theapt.org> wrote: > "quick", quickly fucked you. try re-writing your rules without it. > > Also, think about what IP address ranges you are using, and what IP > address ranges you are trying to block in your ruleset. Don't try to be > clever before you understand what went wrong. > > > > On 2025 Jul 20 (Sun) at 11:25:42 -0700 (-0700), Chris Jones wrote: > :Good day, > : > :I’m wondering if someone familiar with IPv6 and NAT64 can help me > :understand what I’m missing here as I’m struggling to get NAT64 working > :with RFC 1918 IPv4-only hosts (including VPN hosts and hairpining to > :internal hosts) . I appreciate any insight you may be able to provide. > : > :I’ve configured two af-to rules in my pf.conf to provide IPv6 NAT64 > :Provider-side transLATor (PLAT) to 64:ff9b::/96 from the egress interface > :em0, and to 64:ff9b::a00:0/104 (translates to 10/8 IPv4 prefix) from an > :internal interface (to reach remote VPN networks and hairpin NAT). I’ve > :also configured the IPv6-Only Preferred DHCP option 108 (RFC 8925) on my > :home network lab. > : > :Most day to day things work, but I’m struggling to connect to IPv4 > :addresses on the other side of an IPSec tunnel from IPv6-only hosts using > :NAT64, and also to hairpin and reach hosts that don’t support IPv6 only > :(eg. IoT devices) on the vport99 network (10.1.0.0/24 prefix) from IPv6 > :only hosts. > : > :I ran the following tests: > : > : 1. Ping an IPv4-only host on the Internet from an IPv6-only host - > : *SUCCESS* > : 2. Ping an IPv6-only (Inernet and locally) host from an IPv6-only host > - > : *SUCCESS* > : 3. Ping a IPv6 NAT64 prefix (64:ff9b::a02:1) which translates to a IPv4 > : address (10.2.0.1) on the other side of the IPSec tunnel and confirmed > the > : traffic on sec(4) interface using tcpdump - *SUCCESS* > : 4. Ping the IPv4 address 10.2.0.1 (from test 3) on the other side of > the > : IPSec tunnel (I’m not seeing this hit a rule and I’m not seeing any > traffic > : on the sec(4) interface) - *FAILED* > : 5. Ping the IPv4 address (10.2.0.1 from test 3) from the IPv4 address > : internal interface vport99 - *SUCCESS* > : > :Below is the relevant portions of my router/firewall configuration. Please > :let me know if I have missed some details or you would like to see > :something else. > : > :*/etc/hostname.em0* > : > :descr "Internet" > :inet autoconf > :inet6 autoconf > : > :*/etc/hostname.em1* > : > :descr "Internal VLAN Trunk" > :up > : > :*/etc/hostname.vlan99* > : > :parent em1 > :vnetid 99 > :up > : > :*/etc/hostname.vport99* > : > :group internal > :descr "Home Network" > :inet 10.1.0.1/24 > :inet6 autoconf > :inet6 alias fd34:1107:d22e::1/64 > :up > : > :*/etc/hostname.veb99* > : > :add vlan99 > :add vport99 > :up > : > :*/etc/hostname.sec0* > : > :inet 10.250.0.1 255.255.255.252 10.250.0.2 > :up > :!route add -net 10.2.0/24 10.250.0.2 > : > :*/etc/dhcp6leased.conf* > : > :## Global > :request rapid commit > : > :## PD > :request prefix delegation on em0 for { > :vport99/64 > :#vport100/64 > :#vport105/64 > :} > : > :*/etc/rad.conf* > : > :interface vport99 > : dns { > : nameserver fd34:1107:d22e::1 > : } > :#interface vport100 > :#interface vport105 > : > :# Advertise the NAT64 prefix available on this network > :nat64 prefix 64:ff9b::/96 > : > :*/etc/dhcpd.conf* > : > :subnet 10.1.0.0 netmask 255.255.255.0 { > : option domain-name-servers 10.1.0.1; > : option ntp-servers 10.1.0.1; > : option routers 10.1.0.1; > : > : # Send DHCP Option 108 (RFC 8925) to tell clients > : option ipv6-only-preferred 900; > : > : range 10.1.0.100 10.1.0.199; > :} > : > :*/etc/pf.conf* > : > :home_if = “vport99" > : > :nat64_prefix = "64:ff9b::/96” > : > :table <martians> { 0.0.0.0/8 10.0.0.0/8 127.0.0.0/8 169.254.0.0/16 \ > : 172.16.0.0/12 192.0.0.0/24 192.0.2.0/24 224.0.0.0/3 192.168.0.0/16 \ > : 198.18.0.0/15 198.51.100.0/24 203.0.113.0/24 \ > : ::/128 ::/96 ::1/128 ::ffff:0:0/96 100::/64 2001:10::/28 2001:2::/48 \ > : 2001:db8::/32 3ffe::/16 fec0::/10 fc00::/7 } > : > :icmp_types = "echoreq" > :icmp6_types = "{ unreach toobig timex paramprob echoreq routersol > routeradv \ > : neighbrsol neighbradv redir routrrenum }" > : > :set block-policy drop > :set loginterface egress > :set skip on lo0 > : > :match in all scrub (no-df random-id max-mss 1440) > :match out on egress inet from !(egress:network) to any nat-to (egress:0) > : > :antispoof quick for { egress $home_if $guest $kids } > :block in quick on egress from <martians> to any > :block return out quick on egress from any to <martians> > : > :pass in quick on egress inet proto { tcp udp } from any to (egress:0) > :port bootpc > :pass out quick on egress inet proto { tcp udp } from (egress:0) to any > :port bootps > : > :block all > : > :pass out quick inet > :pass out quick inet6 > : > :pass out log (all) quick on enc0 keep state (if-bound) > : > :pass in on egress proto udp from any to (egress) port {isakmp > :ipsec-nat-t} tag IKED > :pass in on egress proto esp from any to (egress) tag IKED > : > :pass in on enc0 proto ipencap from any to (egress) keep state (if-bound) > : > :pass in log on sec0 from 10.250.0.2/32 to 10.250.0.1/32 > : > :pass in on $home_if inet from $home_if:network > :pass in on $home_if inet6 > : > :pass in quick on egress inet6 proto icmp6 all icmp6-type $icmp6_types > :pass in quick on egress proto udp from fe80::/10 port dhcpv6-server to > :fe80::/10 port dhcpv6-client > : > :# NAT64 for IPSec tunnel traffic > :pass in log on $home_if inet6 from any to 64:ff9b::a00:0/104 af-to > :inet from 10.1.0.1 > : > :# NAT64 Provider-side transLATor (PLAT) > :pass in log on $home_if inet6 from any to $nat64_prefix af-to inet > :from (egress:0) > > -- > Do not believe in miracles -- rely on them. >