OPNsenseIX · Firewall RulesFirewall Rules
Interface rules and direction
What you'll learn
- Explain that firewall rules apply on ingress to an interface, not on egress
- Identify the source and destination from the firewall perspective
- Reason about the packet flow that a rule sees and the direction it permits
- Recognise the production traps that come from misunderstanding direction
Prerequisites
Verified against OPNsense 25.x · FreeBSD 14.x · PF (FreeBSD packet filter) FreeBSD 14.x · Unbound 1.20+ · Kea DHCP OPNsense 25.x plugin · WireGuard in-kernel + OPNsense plugin · strongSwan (IPsec plugin) OPNsense 25.x plugin · OpenVPN 2.6.x · Suricata 7.x · 2026-08-14
The single most important concept in OPNsense firewall rules is direction. A rule on the LAN interface applies to packets entering the firewall from the LAN. A rule on the WAN interface applies to packets entering the firewall from the WAN. Rules do not apply to packets leaving an interface; they apply to packets arriving at the firewall on that interface.
This sounds simple but it is the source of a remarkable share of “my rule does not work” tickets. The operator writes a rule on the LAN to permit traffic from the LAN to the Internet, sees that the rule is in place, and cannot understand why the LAN host cannot reach the Internet. The answer is that the rule direction is correct but the operator is reading the “source” and “destination” backwards from the firewall perspective.
This lesson covers how direction works, how to read source and destination from the firewall perspective, the packet flow a rule actually sees, and the production traps that come from misunderstanding direction.
Direction is always in
OPNsense generates every per-interface firewall rule with the
in direction. PF evaluates rules on packets entering the
firewall from a specific interface. There is no per-interface
“out” rule in OPNsense per-interface rule set — outbound
filtering is handled by:
- State matching on the established return traffic of an inbound-allowed connection.
- Rules on the destination interface for traffic that arrives there.
- Floating rules, which can match in both directions.
The mental model that helps: when the operator writes a rule on an interface, they are writing it for traffic that arrives at the firewall on that interface. The firewall then decides what to do with the packet — pass it, block it, or match it for state. If the packet is passed, PF routes it and sends it out another interface. The outbound side of the trip is governed by rules on the egress interface and by state, not by the rule on the ingress interface.
Source and destination from the firewall perspective
The “source” field of a firewall rule is the IP that the packet came from, as the firewall sees it. The “destination” field is the IP the packet is going to. This is the network reality — the operator is configuring the rule from the firewall point of view, not from the LAN host point of view.
For a packet from a LAN host (192.0.2.50) to an Internet server (203.0.113.10):
- On the LAN interface (ingress), the packet source is
192.0.2.50and the destination is203.0.113.10. A rule on the LAN interface sees these values. - On the WAN interface (egress), the packet has been rewritten
by NAT — the source is the firewall WAN IP (e.g.
198.51.100.1) and the destination is still203.0.113.10. A rule on the WAN interface sees these post-NAT values.
For the return packet (from the Internet server back to the firewall):
- On the WAN interface (ingress for the return), the source is
203.0.113.10and the destination is198.51.100.1. The firewall matches the state and accepts the packet. - On the LAN interface (egress for the return), the source is
203.0.113.10and the destination is192.0.2.50(after the NAT is reversed). The firewall matches the state and forwards the packet out the LAN.
The crucial point: a rule on the LAN interface never sees the post-NAT WAN IP and a rule on the WAN interface never sees the pre-NAT LAN IP. NAT happens between the two interfaces.
$ pfctl -s state | grep -E '192.0.2.50|198.51.100.1'all tcp 192.0.2.50:51820 <- 198.51.100.1:41820 0:0 192.0.2.50:51820 <- 203.0.113.10:443 ESTABLISHED:ESTABLISHEDIllustrative output
How PF evaluates the packet flow
For a typical LAN-to-Internet flow, PF evaluation sequence is:
- Packet arrives on the LAN interface. PF matches the packet against the LAN interface rules. If a rule passes the packet, PF creates state.
- Routing decision. PF consults the routing table to find the egress interface. For a packet going to the Internet, the egress is the WAN.
- NAT. Outbound NAT rewrites the source from the LAN IP to the WAN IP.
- Egress interface rule check. For some flows, the packet is also evaluated against rules on the egress interface. This depends on the rule configuration — by default, OPNsense evaluates rules on the egress interface as well as the ingress.
- Packet leaves on the WAN interface. PF sends the packet out.
The reverse flow (Internet to LAN):
- Packet arrives on the WAN interface. PF matches the packet against the WAN interface rules. If state matches, the packet is passed without further rule evaluation.
- Routing decision. The destination is the firewall WAN IP. The firewall knows (via NAT state) to forward to the LAN host IP.
- NAT reverse. The destination is rewritten back to the LAN IP.
- Packet leaves on the LAN interface. PF forwards the packet to the LAN host.
For state-matched traffic, the firewall only evaluates the interface rules on the first packet. Subsequent packets in the flow match the state and are forwarded without rule evaluation.
Common production traps
Three traps recur.
I added a rule on the WAN to permit my LAN host IP
The WAN interface never sees the LAN IP. By the time the packet arrives at the WAN, NAT has rewritten the source to the firewall WAN IP. A rule that permits the LAN IP on the WAN never matches.
The fix: write the rule on the LAN interface (where the LAN IP is still in the source field) and let the return traffic match state.
I added a rule on the LAN to block traffic to the WAN
The LAN interface does not see the WAN IP as a destination either. Wait — actually it does. The destination field of the LAN-ingress packet is still the Internet server IP because NAT rewrites the source, not the destination, for outbound flows.
But for an inbound flow (WAN to LAN via port forward), the LAN-ingress packet has the LAN host IP as the destination (after the DNAT is reversed). So a rule on the LAN to block traffic from the WAN IP is correct only when the destination field is interpreted as post-DNAT.
OPNsense exposes both pre-NAT and post-NAT matching via
Firewall → Rules → (interface) → Advanced → Match direction. By default, the rule matches the post-NAT values,
which is what most operators want for inbound rules.
Floating rules and per-interface rules both apply
A floating rule can match packets on multiple interfaces. When
a packet matches both a floating rule and a per-interface rule,
PF evaluates them in a specific order: floating rules first,
then the per-interface rules for the matching interface. The
order is significant because quick causes evaluation to stop
at the first match.
The trap: an operator writes a floating rule to log suspicious traffic, leaves it in place, and then wonders why a per-interface rule that should pass the traffic is not matching. The floating rule matched first and stopped evaluation. Remove the debug floating rule or move it below the per-interface rules.
The verification discipline
After writing a new rule, the verification sequence is:
- Apply the rule. Click Apply in the GUI.
- Read the compiled rule. Run
pfctl -s rules | grep <unique-text>to confirm the rule compiled at the expected position with the expected direction and source/destination. - Send test traffic. From a host on the matching source network, attempt traffic to the matching destination.
- Read the state table. Run
pfctl -s state | grep <test-flow>to confirm state was created. - Read the log. If the rule has logging enabled, look
for the matching log entry under
Firewall → Log Files → (interface).
If the rule compiled but traffic does not match, the most likely cause is a misconfigured source or destination — the rule is matching the right interface but the wrong packets.
Summary
- Rules apply on ingress to an interface. There is no per-interface “out” rule in OPNsense.
- Source and destination are from the firewall perspective, not the host perspective.
- NAT happens between ingress and egress. The LAN interface sees pre-NAT values; the WAN interface sees post-NAT values.
- For state-matched return traffic, the firewall only evaluates rules on the first packet. Subsequent packets match the state.
- Verify with
pfctl -s rules,pfctl -s state, and the firewall log after every rule change.
Knowledge check · 4 questions
Q1. You want to allow a LAN host 192.0.2.50 to reach an Internet server 203.0.113.10 on TCP 443. Which interface and source/destination pair is correct?
Q2. OPNsense generates per-interface firewall rules with the in direction; there is no per-interface out rule.
Q3. Which of the following are valid ways to filter outbound traffic from the LAN in OPNsense? Select all that apply.
Q4. A packet from LAN host 192.0.2.50 to Internet server 203.0.113.10 on TCP 443 has been permitted by a LAN rule. The packet is now being forwarded by the firewall. Which interface sees the packet on its way out, and what does the source IP look like at that point?
Passing score: 75%. Answers are checked in this browser.