I'm doing something a little wonky. I'm trying to set up a FreeBSD router as a NAT64 PLAT. I've been using pf as my firewall on this system forever, but FreeBSD pf does not have NAT64 capabilities. ipfw does have NAT64. You can use both at once, so I'm trying to have pf still do my firewall and IPv4 NAT to the Internet, while ipfw just does the NAT64.
It actually is partially working. I can see the IPv6 to IPv4 translated packets heading out and coming back with a packet capture on the external interface. However, the packets do not get through the pf firewall on the way back. They get blocked after being translated back to IPv6. Here's what I see from the pflog,
That's a ping coming back from 8.8.4.4 after being translated to the Well-Known IPv6 NAT64 XLAT prefix and headed to the original sender's real IPv6. Rule 0 is a simple catch-all for any traffic that doesn't match another policy,
And igb0 is the box's external interface. But this traffic does match an existing allowed state!
Just if you're curious, rule 12,
Is a rule to pass traffic on the internal, trusted-side interface.
I think I'm missing something obvious, but it's not obvious to me right now. Why is pf dropping the responses if it has a good state for them?
Note that there are some similarities to this thread,
forums.freebsd.org
In that it works for traffic within my LAN when it bounces through the internal interface only. Flipping the sysctl mentioned at the end of that thread has an odd effect. Things don't start to work, but one packet gets through... my guess the packet already out the door successfully makes it back in, but breaks the rest of the traffic going out. Outgoing traffic doesn't get IPv4 NAT applied by pf with the sysctl set.
It actually is partially working. I can see the IPv6 to IPv4 translated packets heading out and coming back with a packet capture on the external interface. However, the packets do not get through the pf firewall on the way back. They get blocked after being translated back to IPv6. Here's what I see from the pflog,
Code:
22:50:51.948337 rule 0/0(match): block in on igb0: (class 0x20, hlim 118, next-header ICMPv6 (58) payload length: 64) 64:ff96::808:404 > 2601:644:8b80:771a:e088:f9f4:7273:9363: ICMP6, echo reply, seq 2141
22:50:53.042151 rule 0/0(match): block in on igb0: (class 0x20, hlim 118, next-header ICMPv6 (58) payload length: 64) 64:ff96::808:404 > 2601:644:8b80:771a:e088:f9f4:7273:9363: ICMP6, echo reply, seq 2142
22:50:53.996210 rule 0/0(match): block in on igb0: (class 0x20, hlim 118, next-header ICMPv6 (58) payload length: 64) 64:ff96::808:404 > 2601:644:8b80:771a:e088:f9f4:7273:9363: ICMP6, echo reply, seq 2143
That's a ping coming back from 8.8.4.4 after being translated to the Well-Known IPv6 NAT64 XLAT prefix and headed to the original sender's real IPv6. Rule 0 is a simple catch-all for any traffic that doesn't match another policy,
Code:
@0 block drop log all
And igb0 is the box's external interface. But this traffic does match an existing allowed state!
Code:
$ sudo pfctl -v -s state
...[snip]...
all ipv6-icmp 64:ff96::808:404[2] <- 2601:644:8b80:771a:e088:f9f4:7273:9363[2] NO_TRAFFIC:NO_TRAFFIC
age 00:28:46, expires in 00:00:09, 1686:0 pkts, 175344:0 bytes, rule 12
...[snip]...
Just if you're curious, rule 12,
Code:
@12 pass quick on igb1 all flags S/SA keep state
Is a rule to pass traffic on the internal, trusted-side interface.
I think I'm missing something obvious, but it's not obvious to me right now. Why is pf dropping the responses if it has a good state for them?
Note that there are some similarities to this thread,

NAT64 with ipfw issues
Hello, I'm tying to build a gateway between a full ipv6 network to a ipv4 network. I choose to test at first ipfw (i will test taiga next). My lab is based on BSDRP (1.92) systems inspired by "https://bsdrp.net/documentation/examples/nat64#r21". It is not exactly the same but the idea stay...
In that it works for traffic within my LAN when it bounces through the internal interface only. Flipping the sysctl mentioned at the end of that thread has an odd effect. Things don't start to work, but one packet gets through... my guess the packet already out the door successfully makes it back in, but breaks the rest of the traffic going out. Outgoing traffic doesn't get IPv4 NAT applied by pf with the sysctl set.
Last edited by a moderator: