just checking, but are you using pfsync? do you have defer enabled?

> On 14 Nov 2025, at 10:51, Jordan Geoghegan <[email protected]> wrote:
> 
> Hello,
> 
> I've observed some interesting behaviour when using static-port with af-to 
> rules.
> 
> I may be missing something obvious and have somehow misconfigured something, 
> but this smells fishy to me, so I thought I'd report it.
> 
> I've recently set up an IPv6-mostly network and wanted cone NAT behaviour to 
> allow things like STUN for FaceTime to work.
> 
> In the man pages it states that "static-port" is for use with nat-to rules, 
> but it turns out it is also accepted by af-to, and largely works.
> 
> The interesting behaviour I've noticed is that when static-port is used in 
> conjunction with af-to rules the initial packet of a connection attempt to 
> the NAT64 prefix is leaked out the egress interface. No such behaviour is 
> observed when the static-port option is not used.
> 
> Steps to reproduce:
> 
> 1) Create af-to rule with static-port option
> 2) Notice how af-to rule misses the first packet / connection attempt and 
> connection times out
> 3) Notice how af-to works as expected for subsequent packets
> 
> Heres the PF rules I'm using to implement NAT64:
> ...
> pass in on $lan_if inet6 from !(egress:network) to 64:ff9b::/96 af-to inet 
> from (egress:0) keep state
> # Use static port for UDP NAT64 traffic so that STUN for video calling and 
> gaming etc works.
> pass in on $lan_if inet6 proto udp from !(egress:network) to 64:ff9b::/96 
> af-to inet from (egress:0) static-port keep state
> 
> To try and illustrate the issue, here are some tcpdump outputs from using dig 
> to make a DNS query to 1.1.1.1 using IPv6 mapped format 64:ff9b::101:101.
> 
> thinkpad$ time dig @64:ff9b::101:101 +short google.ca
> 142.250.73.99
>     0m05.04s real     0m00.00s user     0m00.00s system
> 
> That took 5 seconds, that's a super long time!
> 
> Lets run tcpdump on the router and see whats going on:
> 
> Egress:
> er8pro$ doas tcpdump -lni cnmac4 port domain
> ...
> 15:06:28.255337 2006:420:69:7:254e:c5cd:b280:7e0c.23782 > 
> 64:ff9b::101:101.53: 63837+ [1au] A? google.ca.(38)
> 15:06:33.254922 55.44.33.161.23782 > 1.1.1.1.53: 63837+ [1au] A? 
> google.ca.(38) (DF)
> 15:06:33.267623 1.1.1.1.53 > 55.44.33.161.23782: 63837 1/0/1 A 
> 142.250.73.99(54) (DF)
> 
> And here's how it looks from the LAN side:
> 
> er8pro$ doas tcpdump -lni cnmac5 port domain
> ...
> 15:13:20.331256 2006:420:69:7:254e:c5cd:b280:7e0c.48398 > 
> 64:ff9b::101:101.53: 65486+ [1au] A? google.ca.(38)
> 15:13:25.327384 2006:420:69:7:254e:c5cd:b280:7e0c.48398 > 
> 64:ff9b::101:101.53: 65486+ [1au] A? google.ca.(38)
> 15:13:25.341485 64:ff9b::101:101.53 > 
> 2006:420:69:7:254e:c5cd:b280:7e0c.48398: 65486 1/0/1 A 142.250.73.67(54)
> 
> Here we can see the initial connection attempt to 64:ff9b::101:101 is somehow 
> "missed" by the af-to rule and leaks out onto egress and inevitably times 
> out. The subsequent connection attempt 5 seconds later succeeds however.
> 
> To be clear, the behaviour only presents itself when using static-port in 
> conjunction with af-to rules. As soon as af-to rule has static-port option 
> removed, no such "leaks" occur. I know I could just make a pf rule to 
> explicitly block outgoing traffic to the NAT64 prefix, but it doesn't change 
> the fact that for some reason the af-to rule "misses" the first connection 
> attempt and forces a connection timeout if static-port option is set.
> 
> I hope this makes sense. I know using af-to with static-port isn't explicitly 
> documented, but I think having support for "cone" NAT64 is a pretty killer 
> feature and is necessary to facilitate many if not most peer to peer 
> communications for IPv4. Living in rural Canada it's quite inefficient to 
> have my packets destined for the Yukon or Labrador get there by way of Apple 
> TURN servers in Cupertino, so for me at least, its a hugely appreciated 
> functionality.
> 
> I know that this email is getting long, but in case some more examples are 
> desired, here is the NAT64 prefix leaking on egress when attempting a 
> Facetime call and also mDNS queries leaking from my AndroidTV box that seems 
> to get confused and sends out mDNS queries from its CLAT.
> 
> When attempting to make a FaceTime call to a relative whose on an IPv4 only 
> connection, the initial connection attempts are missed by af-to rule, but on 
> subsequent retries succeeds.
> 
> # Initial Connection Attempts leak
> 14:10:34.061299 2006:420:69:7:d934:b317:7d73:736b.16393 > 
> 64:ff9b::11bc:b219.3490: udp 172 [flowlabel 0xf10d4]
> 14:10:43.275992 2006:420:69:7:d934:b317:7d73:736b.16393 > 
> 64:ff9b::2a1f:1413.16393: udp 72 [flowlabel 0xd8709]
> ...
> # After connection is reattempted af-to does the needful and starts 
> translating as expected.
> 14:11:16.309508 55.44.33.161.16393 > 42.31.20.19.16393: udp 303
> 14:11:16.313229 42.31.20.19.16393 > 55.44.33.161.16393: udp 1050
> 14:11:16.317260 42.31.20.19.16393 > 55.44.33.161.16393: udp 1047
> 14:11:16.321257 42.31.20.19.16393 > 55.44.33.161.16393: udp 1049
> 14:11:16.321259 42.31.20.19.16393 > 55.44.33.161.16393: udp 1049
> 
> # Android TV with CLAT leaking
> 14:12:12.422220 2006:420:69:7:34fb:e138:ba30:c741.5353 > 
> 64:ff9b::e000:fb.5353: 0[|domain]
> 14:12:12.571486 2006:420:69:7:ef5d:8bb9:202e:fc60.5353 > 
> 64:ff9b::e000:fb.5353: 0[|domain]
> 14:13:48.965738 2006:420:69:7:34fb:e138:ba30:c741.5353 > 
> 64:ff9b::e000:fb.5353: 0 PTR? _googlecast._tcp.local.(40
> 
> 
> Please let me know if there are any more details etc I can provide.
> 
> Regards,
> 
> Jordan
> 

Reply via email to