lx: rebind socket on handshake give-up (sing-box-lx SPEC 041 self-heal)
After ~90s of unanswered handshake initiations (the give-up branch of expiredRetransmitHandshake) the socket's 5-tuple is proven dead (expired NAT mapping / poisoned DPI flow entry after device sleep) and upstream retries into it forever; only a manual reconnect healed the peer. Reopen the bind once per give-up cycle (fresh ephemeral port unless the user pinned listen_port), then re-initiate immediately. Debounced via CAS; no timers or goroutines while healthy; a rebind racing Down()/Close() degrades to a no-op inside BindUpdate. Red/green e2e + unit tests.
This commit is contained in:
parent
37bc7b9f55
commit
c4e0bcf768
4 changed files with 330 additions and 0 deletions
|
|
@ -99,6 +99,14 @@ func expiredRetransmitHandshake(peer *Peer) {
|
|||
peer.timers.zeroKeyMaterial.Mod(RejectAfterTime * 3)
|
||||
}
|
||||
peer.noteSessionHandshakeStopped()
|
||||
|
||||
/* lx: SPEC 041 — the exhausted cycle just proved the current socket's
|
||||
* 5-tuple dead (90s of initiations, zero replies). Rebind once and
|
||||
* re-initiate, so a stale NAT mapping / poisoned DPI flow entry cannot
|
||||
* pin this peer to a dead socket until a manual reconnect. Runs after
|
||||
* the session-state notification so a consumer sees "handshake stopped"
|
||||
* before the socket is recreated. */
|
||||
peer.device.handleHandshakeGiveUp(peer)
|
||||
} else {
|
||||
peer.timers.handshakeAttempts.Add(1)
|
||||
peer.device.log.Verbosef("%s - Handshake did not complete after %d seconds, retrying (try %d)", peer, int(RekeyTimeout.Seconds()), peer.timers.handshakeAttempts.Load()+1)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue