OPNsense 26.7.8_1: static-port outbound NAT drops UDP/5060 packets with map-failed when a WAN redirect uses the reverse tupleEnvironment- OPNsense 26.7.8_1 (opnsense-26.7.8_1)
- FreeBSD 15.1-RELEASE-p6, stable/26.7-n284176-c962f76493b6, amd64
- WAN ix0, LAN ix1
- WAN VIP 203.0.113.10; LAN VIP 192.0.2.1
- PF state limits were not exhausted; the preserved snapshots show zero memory exhaustion.
- Exact PF userland/source revision: unknown in the preserved evidence.
TopologySIP carrier OPNsense PBX
198.51.100.128:5060 <---- ix0/WAN ---- ix1/LAN ----> 192.0.2.11:5060
WAN VIP
203.0.113.10:5060The WAN UDP/5060-5063 port forward redirects inbound traffic to the PBX UDP/5060. A manual outbound NAT rule for the PBX uses the same WAN VIP with static-port.
Problem statementIndependent PBX-originated SIP OPTIONS packets reach the LAN interface and are accepted by PF, but PF fails to create the outbound NAT mapping. No corresponding request leaves the WAN. The LAN-created state has no translated tuple and remains NO_TRAFFIC:SINGLE. PF's global map-failed counter increments once per failed packet, while the dedicated outbound NAT rule's packet and state counters do not change.
At the same time, inbound carrier transactions to the WAN VIP UDP/5060 continue to be redirected to the PBX and replies continue to leave the WAN.
Observed evidenceCapture interval: 2026-11-13T18:10:37Z through 2026-11-13T18:12:37Z. Packet display timestamps were local EST and are normalized to UTC below.
Measurement Before After Delta
LAN ix1 PBX 192.0.2.11:5060 -> 198.51.100.128:5060 packets - 21 +21
WAN ix0 matching PBX-originated OPTIONS - 0 0
PF global map-failed 5431 5452 +21
Rule 164 state packets 55 76 +21
Rule 5 NAT packets 10387 10387 0
Rule 5 NAT active states 0 0 0
Rule 5 NAT evaluations 498732 500117 +1385The 21 LAN packets are retransmissions spanning two unique outbound SIP Call-IDs. Four inbound carrier transactions used four other Call-IDs; the outbound and inbound Call-ID sets did not intersect. Exact Call-ID values are omitted.
The first failed LAN packet was observed at 2026-11-13T18:11:08.397959Z; the last was observed at 2026-11-13T18:12:35.898063Z.
Representative successful inbound correlation:
UTC time Interface Packet
18:11:04.134366 ix0 198.51.100.128:5060 -> 203.0.113.10:5060 OPTIONS
18:11:04.134379 ix1 198.51.100.128:58653 -> 192.0.2.11:5060 redirected request
18:11:04.136388 ix1 192.0.2.11:5060 -> 198.51.100.128:58653 200 OK
18:11:04.136398 ix0 203.0.113.10:5060 -> 198.51.100.128:5060 translated 200 OKThe two-interface timestamps differ by 13 microseconds on the inbound redirection and 10 microseconds on the reverse path, supporting synchronized capture rather than a capture mismatch.
Expected behaviorThe independent PBX flow should match the dedicated outbound static-port NAT rule and leave ix0 as:
203.0.113.10:5060 -> 198.51.100.128:5060The generated state should contain a valid translated tuple, and the reply should return to the PBX.
Actual behaviorThe LAN filter accepts the packets and creates this state:
all udp 198.51.100.128:5060 <- 192.0.2.11:5060 NO_TRAFFIC:SINGLE
age 00:06:59, 76:0 pkts, 35775:0 bytes, rule 164
origif: ix1There is no translated tuple in the state, no WAN request, and no reply. map-failed increases by the same number as the LAN packets.
The simultaneously valid inbound state is:
all udp 192.0.2.11:5060 (203.0.113.10:5060)
<- 198.51.100.128:58653 (198.51.100.128:5060) MULTIPLE:MULTIPLEThis inbound state's working external endpoint pair uses the same two host:port endpoints in the opposite direction from the desired outbound static NAT tuple.
Hypothesis under testThe leading hypothesis is that PF's fixed-port outbound mapping cannot create the desired tuple while the active WAN redirect state occupies the reverse endpoint tuple, or that this configuration reaches a first-packet NAT/state ordering edge case. This is
not proven.
The following are not established:
- that this is an OPNsense-specific defect;
- that this is a FreeBSD PF defect;
- that the behavior is intentional PF behavior;
- that CARP or pfsync contributed;
- that the exact internal branch responsible for map-failed has been identified.
Questions for maintainers- Is a static-port outbound mapping expected to fail when an active port redirect creates the reverse WAN endpoint tuple?
- If this is expected, where is that restriction documented, and which read-only diagnostic should distinguish a fixed-port collision from other map-failed causes?
- Which NAT state or rule evaluation is attempted after the LAN keep state rule has accepted the packet but before the outbound NAT counter advances?
- Is the unchanged packet/state count on the matched NAT rule, while the global evaluation counter advances, expected for failed fixed-port allocation?
- Does PF intentionally rewrite the redirect-side source port but reject or decline the inverse static-port mapping? If so, what prevents allocation of an alternate outbound source port when static-port is present?
- Can PF debug logging expose the precise mapping conflict without packet modification? Which counter, zone, anchor, or log should maintainers expect to identify it?
- Is the kernel revision stable/26.7-n284176-c962f76493b6 affected by a known fix, limitation, or source change involving fixed-port NAT and reverse redirect state?
- Would a vanilla FreeBSD installation with equivalent manually loaded PF rules be expected to behave identically?
Reproduction requestPlease reproduce in an isolated lab using:
- the exact OPNsense build above;
- WAN 203.0.113.10 and PBX 192.0.2.11;
- WAN UDP/5060-5063 redirect to PBX UDP/5060;
- outbound NAT from the PBX to 203.0.113.10 with static-port;
- one inbound carrier packet from 198.51.100.128:5060 to the VIP to establish the redirect state;
- one independent PBX packet from 192.0.2.11:5060 to 198.51.100.128:5060;
- captures on WAN, LAN, and the carrier simulator;
- before/after pfctl -si, pfctl -sn -vv, pfctl -sr -vv, pfctl -ss -vv, and pfctl -sl -vv.
Repeat without the redirect, with PBX source port 5062, without static-port, and with equivalent rules on vanilla FreeBSD. The annex contains the full control matrix and expected discriminators.
DisclosureAI tools were used to correlate preserved read-only captures, PF state, NAT rules, counters, routing, interface, and CARP evidence and to prepare this draft. A human reporter has reviewed the final evidence, confirmed the sanitized address substitutions, and approved any submission.
You or your AI don't set out the fw/NAT rules involved, but given the PBX internal IP is not RFC1918, do you have a typo somewhere in your opnsense config?
No, the AI anonymized/redacted information before providing the final report. The internal network is RFC1918, the external network is appropriately set static with a valid static IP, and some traffic makes it through, just not all of it. This is most frustrating because it means "sometimes" outbound calling works, and sometimes it does not. I could tell the SIP provider to accept both the default outbound IP and the one designated for VoIP, but that doesn't really resolve the underlying issue.
I've been testing on this for a few days now to make sure it's not something internal or external to the firewall, but the config prior to upgrading to 26.7 was stable for years. So this is something new in the 26.x line, it's just a question of whether it's an OPNsense problem, a PF problem, or a FreeBSD problem.