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
>