SSH dial/tunnel/DNAT failures unconditionally drop the packet with no retry, and the 5s cooldown blanket-drops unrelated destinations too #31
Labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
keyop-go/nfq_forwarder#31
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Found while investigating #4.
In
getNfCallback(internal/nfq_forwarder/nfq_forwarder.go), three distinct error paths all issue an immediate, finalnfqueue.NfDropon the current packet with no retry of that packet:sshConns.connection()error, ~line 641)OpenTunnelfailure other thanErrPortTunnelAlreadyOpen(~line 657)addDNATRulesFuncfailure (~line 664)This compounds with
sshConnections'sshRetryCooldown(5s, ~line 336, cache checked at ~lines 394-396): once one dial to a jump host fails, the cached error is returned for every subsequent packet for 5 whole seconds, for every destination sharing that SSH connection pool - not just the one that originally failed. A single transient failure (e.g. a jump host momentarily unreachable) therefore drops packets for otherwise-healthy, already-tunnelled destinations on the same connection for up to 5 seconds, with zero retry of any of those dropped packets.Impact: a single transient SSH hiccup causes real, silent packet loss well beyond the destination that actually failed - not just a delay.
Investigate/consider: whether the cooldown should be scoped more narrowly (e.g. only the destination that failed, not the whole pool), and whether any of these error paths should retry the current packet (e.g. via a bounded requeue) rather than an unconditional, final drop.
mentioned in issue #4
mentioned in merge request !70
mentioned in merge request !71
mentioned in commit
6aa6c1b88dmentioned in merge request !72
Implementation is up for review: !72 (branch
issue31_dont_leak_orphaned_tunnel_on_dnat_failure). Two fixes bundled: (1) rolling back the orphaned tunnel on a DNAT-insert failure (the more severe finding - traffic was silently going out unencrypted otherwise), and (2) distinguishing cooldown-suppressed dial failures from fresh ones in the logs. I'm deliberately not changing the cooldown's blast radius itself - see the MR description for why. Waiting on review before merging.mentioned in commit
067ef83730Merged via !72 (merge commit
067ef83) and released as v1.1.3 (patch bump).mentioned in merge request !73