The 60-Second SSH Drop, Part 3: Asymmetric Routing Through a Stateful Firewall
Root cause: pfSense saw only half of every management session. One route on the admin workstation fixed it at Layer 3, and the bastion VLAN came out.
TL;DR
My admin laptop used pfSense as its default gateway, so management traffic to any VM went laptop → pfSense → transit link → VyOS → VM. The replies came back VM → VyOS → laptop directly, because VyOS also sits on the management segment. pfSense saw only one direction of every TCP session, decided the state was invalid, and killed it after 30–60 seconds. Ping survived because ICMP is far more forgiving. One host route on the laptop (lab supernet via VyOS) took pfSense out of the east–west path, and every session has been stable since.
The architecture
Internet ── pfSense ──(transit /30)── VyOS ──(802.1Q trunk)── segments
│ │
└──── management segment (both have an interface here)
│
admin laptop (default gateway = pfSense)
pfSense owns north–south traffic. VyOS routes between internal segments. Both have a leg on management, and that's what made the asymmetry possible.
The smoking gun
A traceroute from the laptop to a VM on another segment:
1 pfSense (management gateway)
2 VyOS (transit side)
3 target VM
The request went through pfSense. The return didn't: the VM's gateway is VyOS, and VyOS has a direct route to the laptop's segment, so it delivered the reply straight back.
A stateful firewall that sees the SYN go out but never sees the SYN-ACK come back through it has a half-open, invalid state. It tolerates that for a while, then resets or drops the flow. That matched the 30–60-second window exactly.

Why VyOS "magically" worked
VyOS was the one host where traffic took the same path both ways. The laptop and VyOS share the management segment, so no third device was in the loop. And when I hopped through VyOS, VyOS was in-path both ways. Part 2's test matrix was pointing at this the whole time.
Three ways out
| Option | What it means | Trade-off |
|---|---|---|
| A. Route management via VyOS | Laptop sends lab-bound traffic to VyOS; pfSense keeps internet/default | Fixes it at Layer 3. Admin path matches the data path. |
| B. Stateless exception on pfSense | Floating rule with "sloppy" or no state for the specific flow | Treats the symptom at Layer 4; weakens inspection for that flow |
| C. Make pfSense the only router | Remove VyOS from routing | Fixes it, and destroys the reason the lab has a core router |
Fixing it at Layer 3 beats suppressing the symptom at Layer 4. I went with A, keeping B only as an isolated experiment.
The fix
One static route on the admin workstation:
lab supernet → via VyOS management address
default → via pfSense (unchanged)
That's all. No VLAN flattening, no firewall rules loosened, no trust expanded. pfSense still owns the edge; VyOS still enforces policy between segments. This is the standard privileged-admin-workstation pattern: the admin path follows the control plane.
Verification
- SSH to the MISP server: held. Left it idle, came back, still there.
- SSH to the RHEL box: held.
- RDP to the domain controller: held.
- The OpenBSD bastion still dropped. That turned out to be its own host-level session behavior, unrelated to the network, and it proved I didn't need the bastion at all.
Cleanup
With the real cause fixed, the management VLAN and bastion from Part 2 were extra complexity with no benefit. I decommissioned them bottom-up so nothing was left orphaned: switch membership, then VyOS sub-interface and routes, then pfSense static routes. The OpenBSD box was repurposed as an experimental dev VM.
Lessons
- If only the router works, look at who else is in the path.
- Asymmetric routing + a stateful firewall = sessions that die on a timer. It's the textbook failure, and it still took me months to see.
- Fix the layer that's wrong. A stateless rule would have "worked" and left a wrong design in place.
- Remove what didn't help. A fix that leaves dead scaffolding behind makes the next outage harder.
Sources: SSH RDP Session Drops (14–18 Jan 2026), VyOS SSH Troubleshooting (5–12 Jan 2026)