OPNsenseXIX · Multi-WAN and Gateway GroupsMulti-WAN NAT
Multi-WAN NAT rules — outbound NAT per WAN, source address translation
What you'll learn
- Explain the NAT model OPNsense generates per WAN interface
- Choose between automatic, hybrid, and manual outbound NAT
- Build manual NAT rules for a multi-WAN deployment with segregation
- Recognise the NAT and policy-routing interaction that produces broken return traffic
- Verify the effective source translation with packet capture
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
Multi-WAN with segregation requires outbound NAT that matches the gateway group. A LAN host that is policy-routed through the Production gateway has to have its source address translated to the Production WAN’s public IP, not the Guest WAN’s public IP. OPNsense generates outbound NAT rules per WAN interface and per gateway group; the operator has to decide between automatic, hybrid, and manual NAT and verify the translation that actually happens. This lesson covers the three NAT modes, the configuration per gateway, and the verification of effective source translation.
The three outbound NAT modes
OPNsense offers three outbound NAT modes for IPv4:
Automatic. The firewall generates one outbound NAT rule per WAN interface. Traffic leaving WAN-A is translated to the WAN-A address; traffic leaving WAN-B is translated to the WAN-B address. The mode works for simple multi-WAN deployments where every LAN host is allowed to use every WAN.
Hybrid. The firewall generates automatic NAT rules for the WAN interfaces, plus manual NAT rules that the operator adds for specific exceptions. Hybrid is the right default for most multi-WAN deployments: the operator gets automatic NAT for the common case and the ability to override specific source/destination pairs.
Manual. The firewall generates no automatic NAT rules. Every NAT rule is a manual rule the operator configures. Manual is the right answer for deployments where the operator needs fine-grained control over which source addresses use which WAN — typically, large multi-WAN deployments with segregation, or environments with a dedicated address pool per gateway group.
For most production deployments, hybrid is the right starting point. The operator adds manual rules when the automatic rules do not match the segregation pattern; the operator switches to manual only when the automatic rules are actively wrong.
The NAT rule fields
A manual outbound NAT rule has the same fields as a firewall rule plus the Translation / Address field that picks the source address to translate to.
| Field | Meaning |
|---|---|
| Interface | The egress interface the rule applies to |
| TCP/IP Version | IPv4 or IPv6 |
| Protocol | Any, TCP, UDP, TCP/UDP |
| Source | Source address or subnet (or alias) |
| Destination | Destination address (typically any for outbound) |
| Translation / Address | The address to translate the source to |
| Translation / Port | The port behaviour (preserve, randomise, or static) |
| Description | A free-text note for the operator |
The Translation / Address field is the critical one for multi-WAN. The choices are:
- Interface address — translate to the egress interface’s primary IP. This is the right answer for most cases.
- WAN address — a specific address (when the WAN has multiple public IPs, e.g. an IP alias or a CARP VIP).
- A specific subnet — translate to an address in a subnet (when the operator has a pool of public addresses on the WAN).
For multi-WAN with segregation, the rule sets the Translation / Address to the egress interface’s primary IP. The rule’s Interface matches the gateway’s interface, so traffic policy-routed through WAN-A gets translated to WAN-A’s IP.
Building manual NAT rules per gateway group
A segregation deployment with hybrid NAT needs manual rules per gateway group:
| Traffic class | Egress | Source | Translation |
|---|---|---|---|
| Production LAN → Internet | WAN_A | 10.0.0.0/24 (LAN) | WAN_A address |
| Guest VLAN → Internet | WAN_C | 10.0.2.0/24 (Guest) | WAN_C address |
| Partner integration → partner IP | WAN_D | 10.0.0.0/24 (LAN) | WAN_D address |
The Interface field on each NAT rule is the egress interface. The Source field is the source subnet. The Translation / Address field is the egress interface’s primary IP. The Destination field is “any” for outbound traffic.
The rule ordering matters: NAT rules are evaluated top to bottom, first match wins. The most specific rule should be at the top. The catch-all (any source to any destination through the default WAN) is at the bottom.
$ pfctl -s nat | head -10nat on igb1 inet from 10.0.0.0/24 to any -> (igb1) round-robin
nat on igb2 inet from 10.0.2.0/24 to any -> (igb2) round-robin
nat on igb4 inet from 10.0.0.0/24 to 203.0.113.50/32 -> (igb4) round-robin
no nat on igb0 inet from any to 10.0.0.0/24
no nat on igb0 inet from any to 10.0.0.0/24Illustrative output
The NAT and policy-routing interaction
NAT and policy routing have to be consistent. A rule that policy-routes traffic through WAN-A but translates the source to WAN-B’s address produces an inconsistency: the return traffic arrives at WAN-B (because that is what the upstream saw as the source), but the state was created on WAN-A. PF drops the packet.
The rule of thumb:
- The egress interface of the firewall rule must match the egress interface of the NAT rule.
- The translation address must match the egress interface’s public IP.
OPNsense handles this automatically for the automatic NAT rules — the firewall generates one rule per interface, and the rule translates to that interface’s address. The operator who adds manual rules has to maintain the consistency.
No-NAT rules for internal traffic
Internal traffic (LAN to LAN, LAN to DMZ) does not cross a WAN boundary and should not be NAT-translated. OPNsense generates no-NAT rules for the LAN subnets automatically; the operator can add explicit no-NAT rules for additional subnets.
The verification: pfctl -s nat | grep 'no nat' lists the no-NAT rules. Every subnet that should never be NAT-translated (LAN, DMZ, VPN subnets) should appear in the list.
Verifying the effective source translation
The verification sequence:
- Inspect the generated NAT ruleset.
pfctl -s natlists every NAT and no-NAT rule. The operator reads the rules and confirms the source/translation pairs match the segregation intent. - Capture packets on the WAN interface.
tcpdump -ni igb1 src net 10.0.0.0/24on WAN-A’s interface shows what source address the LAN traffic actually leaves with. The address should be WAN-A’s public IP, not the LAN subnet. - Capture packets on the return path.
tcpdump -ni igb1 dst 198.51.100.1shows return traffic destined for WAN-A’s address — the upstream’s reply to the LAN traffic. - Trace a single connection.
tcpdump -ni any host \<dst\>shows the full path: SYN leaves on igb1 (WAN-A), SYN-ACK returns on igb1, data flows on igb1. The consistent interface confirms the NAT and policy routing are aligned.
$ tcpdump -ni igb1 -c 4 'src net 10.0.0.0/24 and dst port 443'12:34:56.789012 10.0.0.50.51234 > 93.184.216.34.443: Flags [S], seq 1000000000, win 65535, length 0
12:35:01.789345 10.0.0.50.51235 > 93.184.216.34.443: Flags [S], seq 1000000001, win 65535, length 0
12:35:06.789678 10.0.0.50.51236 > 93.184.216.34.443: Flags [S], seq 1000000002, win 65535, length 0
12:35:11.790012 10.0.0.50.51237 > 93.184.216.34.443: Flags [S], seq 1000000003, win 65535, length 0Illustrative output
The above capture shows a NAT failure — the source address is the LAN subnet, not the WAN’s public IP. In a healthy configuration, the capture would show the source address as WAN-A’s public IP (198.51.100.1) for traffic policy-routed through WAN-A.
Manual NAT with address pools
Some deployments have a pool of public addresses on a single WAN (an IP alias, a CARP VIP, a range assigned by the ISP). The NAT rule can translate to a specific address in the pool, or use round-robin across the pool:
| Translation / Address | Behaviour |
|---|---|
| Interface address | Translate to the interface’s primary IP (default) |
| Specific address | Translate to a specific address in a subnet |
| Subnet (with round-robin) | Cycle through the addresses in the subnet |
The round-robin pattern is useful for high-volume servers that exhaust the source-port range on a single IP; spreading the source across multiple IPs multiplies the available source ports. The pattern is uncommon in production but supported.
Summary
- Outbound NAT has three modes: automatic (per interface, automatic rules), hybrid (automatic + manual for exceptions), and manual (no automatic rules).
- Manual NAT rules per gateway group: Interface = egress, Source = source subnet, Translation / Address = egress interface IP.
- The egress interface of the firewall rule and the NAT rule must match. Inconsistency produces connections that time out.
- Internal subnets need no-NAT rules so the firewall does not translate traffic that does not cross a WAN.
- Verify with
pfctl -s nat,tcpdumpon the WAN interface, and a full-path trace of a single connection.
Knowledge check · 4 questions
Q1. A multi-WAN deployment uses hybrid outbound NAT. The automatic rules are in place. The operator adds a manual NAT rule for the Guest VLAN (10.0.2.0/24) through WAN_C. After the change, Guest traffic is translated to the wrong interface IP. What is the most likely cause?
Q2. The egress interface of a firewall rule and the egress interface of the matching NAT rule must match.
Q3. Which of the following are valid verifications for outbound NAT in a multi-WAN deployment? Select all that apply.
Q4. A LAN host opens a TCP connection to an Internet server. tcpdump on WAN-A shows the SYN leaving with source 198.51.100.1 (WAN-A IP). tcpdump on WAN-B shows the SYN-ACK arriving with destination 198.51.100.1. What is the most likely cause?
Passing score: 75%. Answers are checked in this browser.