🧭 1. Background
During internal testing, my setup was:
[Test Host] → OPNsense → UserGW → Internet
| Node | IP / Role |
|---|---|
| Test Host | 192.168.100.250 (GW: 192.168.100.253) |
| OPNsense LAN | 192.168.100.253 |
| OPNsense WAN | 172.16.100.253 (GW: 172.16.100.251) |
| UserGW LAN | 172.16.100.251 |
| UserGW WAN | PPPoE (Internet) |
The test host attempted to SSH to an external server.
The external server received connection attempts (logged in iptables),
but the SSH client always timed out.
🧩 2. Analysis
The SSH server log showed the connection coming from:
UserGW's PPPoE public IP
That means:
- OPNsense performed NAT once (192.168.100.250 → 172.16.100.253)
- UserGW performed NAT again (172.16.100.253 → Public IP)
So packets went out, but the return path failed due to state mismatch between two firewalls.
⚙️ 3. Troubleshooting Steps
1️⃣ Verified NAT
Outbound NAT on OPNsense:
Source: 192.168.100.0/24
Interface: WAN (172.16.100.253)
Translation: Interface address
Confirmed working.
2️⃣ Checked Firewall Rules
LAN allowed outbound traffic.
WAN was default-blocked inbound.
However, return traffic was being dropped because state tracking didn’t match.
3️⃣ Tried “Sloppy State”
Setting WAN rule to State Type: sloppy state
helped slightly but didn’t fully resolve the problem.
4️⃣ Packet Capture
Using:
tcpdump -ni wan host <ssh_server_ip> and port 22
→ Outbound SYN visible
→ No SYN/ACK returning
Confirmed return traffic was lost between UserGW and OPNsense.
🧠 4. Root Cause
This was caused by double stateful NAT.
Both firewalls maintained separate state tables,
and when UserGW modified the packet during NAT,
OPNsense’s state table no longer matched — TCP handshake failed.
✅ 5. Solution
Simplify the topology by letting OPNsense directly dial PPPoE.
[Test Host] → OPNsense (PPPoE) → Internet
| Node | IP / Role |
|---|---|
| Test Host | 192.168.100.250 (GW: 192.168.100.253) |
| OPNsense LAN | 192.168.100.253 |
| OPNsense WAN | PPPoE (Public IP assigned by ISP) |
After applying this change:
✅ SSH, Ping, and Web access all worked instantly.
✅ No more timeout issues — single NAT path, clean state tracking.
🧩 6. Technical Summary
| Item | Description |
|---|---|
| Root Cause | Double NAT → state mismatch |
| Symptom | Outbound packets logged, but SSH timed out |
| Temporary Fix | Sloppy state / manual NAT adjustment |
| Final Fix | Let OPNsense handle PPPoE directly |
| Result | Stable, fully functional Internet access |
💡 7. Recommendations
- Enable Insight (Netflow) for traffic visibility.
- Use Unbound DNS Resolver for internal name resolution.
- Keep WAN inbound traffic blocked by default.
- For multi-WAN in the future, plan Policy-Based Routing instead of chained NAT.