TL;DR
Firewall → Settings → Advanced → Disable reply-to on WAN rules → check → Save → Apply.
Symptom: a port-forward or WAN rule answers from any internet IP, but from a host that lives in the same subnet as the firewall’s WAN everything times out (SSH, HTTPS, even ping), even though the rule says from any.
With a single WAN this is safe: the firewall stops forcing replies through the gateway and goes back to its routing table.
The setup
| |
- From the internet:
ssh -p 22 203.0.113.40reaches the LAN server. Fine. - From
neighbor(203.0.113.50): every port times out.
What reply-to does
OPNsense generates the rules on WAN-type interfaces (those with a gateway) with reply-to pointing at that gateway:
| |
| |
reply-to is a pf option. When a packet comes in and creates a state, pf records in that state that every reply must leave through vtnet0 toward 203.0.113.1. Those replies skip the routing table: pf picks the next hop on its own.
It exists for multi-WAN. If you have two providers and a client comes in on WAN2, the reply must leave through WAN2. If it leaves through the default route (WAN1), it carries a source IP that provider 1 does not recognize and gets lost. reply-to guarantees a symmetric return path without thinking about routes.
Why it breaks neighbors
For an internet client, “reply to the gateway” is exactly what the routing table would do anyway, so nothing looks wrong.
For the neighbor it is different. Its IP (203.0.113.50) is on a connected network of the firewall. Without reply-to, the firewall would ARP for its MAC and answer directly. With reply-to, the SYN-ACK leaves with the gateway’s MAC as destination:
| |
| |
(00:00:5e:00:01:xx is the VRRP virtual MAC: the gateway was a redundant pair.)
From there it depends on the gateway. To it, the packet arrives on the same interface it would have to leave through, and if it runs a stateful filter it sees a SYN-ACK for a connection whose SYN it never saw. In the lab, the gateway simply did not send it back onto the segment. On the neighbor you only see retried SYNs and no [S.].
The fingerprint on the firewall is a half-open state:
| |
| |
The server already answered (ESTABLISHED) and the client is still waiting (SYN_SENT): the reply is lost on the way back, not on the way in. The filter is not blocking anything.
What the fix changes
With Disable reply-to on WAN rules checked, OPNsense regenerates the rules without reply-to:
| |
The state no longer pins the next hop, so replies go through the normal routing table:
| Reply destination | With reply-to | Without reply-to |
|---|---|---|
| Internet client | gateway | gateway (default route) |
| Neighbor in 203.0.113.0/24 | gateway ✗ | direct via ARP ✓ |
| Client that came in on another WAN (multi-WAN) | its gateway ✓ | default route ✗ |
The last row is the cost. With multi-WAN, do not disable it globally. Instead, drop reply-to only on the affected port-forward’s rule: in the rule, Advanced → reply-to. Check which options your version offers.
Verify
| |
| |
Traps
- “Disable force gateway” is not this. It sits on the same page with a similar name, but it only affects traffic originated by the firewall itself (DNS, NTP, updates). It does not touch replies to inbound traffic.
- A static route on the gateway does not help. The gateway already has the subnet as connected; the problem is that it will not send the packet back onto the same segment, not that it does not know the way.
- csh shell. Over SSH, OPNsense drops you into
csh, and things like2>/dev/nullfail withAmbiguous output redirect. Usesh -c "..."orssh root@fw01 sh <<'EOF'. - Test every port, not one. If only one port fails it is a different problem (rule, NAT, service). If they all fail,
pingincluded, and only from the same subnet, suspectreply-to.
See also
- OPNsense docs, firewall settings: https://docs.opnsense.org/manual/firewall_settings.html
pf.conf(5),route-to/reply-tooptions: https://man.freebsd.org/cgi/man.cgi?query=pf.conf