diff --git a/device/send.go b/device/send.go index e07df1bae..9f350a03c 100644 --- a/device/send.go +++ b/device/send.go @@ -89,7 +89,7 @@ func (peer *Peer) SendKeepalive() { func (peer *Peer) SendHandshakeInitiation(isRetry bool) error { if !isRetry { - atomic.StoreUint32(&peer.timers.handshakeAttempts, 0) + atomic.StoreUint32(&peer.timers.handshakeAttempts, 1) } peer.handshake.mutex.RLock() @@ -193,7 +193,10 @@ func (peer *Peer) keepKeyFreshSending() { } nonce := atomic.LoadUint64(&keypair.sendNonce) if nonce > RekeyAfterMessages || (keypair.isInitiator && time.Since(keypair.created) > RekeyAfterTime) { - peer.SendHandshakeInitiation(false) + // Do not send new HandshakeInitiation, if handshake retry is already in progress + if !peer.handshakeInProgress() { + peer.SendHandshakeInitiation(false) + } } } @@ -298,7 +301,10 @@ top: keypair := peer.keypairs.Current() if keypair == nil || atomic.LoadUint64(&keypair.sendNonce) >= RejectAfterMessages || time.Since(keypair.created) >= RejectAfterTime { - peer.SendHandshakeInitiation(false) + // Do not send new HandshakeInitiation, if handshake retry is already in progress + if !peer.handshakeInProgress() { + peer.SendHandshakeInitiation(false) + } return } diff --git a/device/timers.go b/device/timers.go index ee191e55b..4fe3edddf 100644 --- a/device/timers.go +++ b/device/timers.go @@ -78,6 +78,9 @@ func expiredRetransmitHandshake(peer *Peer) { if atomic.LoadUint32(&peer.timers.handshakeAttempts) > MaxTimerHandshakes { peer.device.log.Verbosef("%s - Handshake did not complete after %d attempts, giving up", peer, MaxTimerHandshakes+2) + // Reset attempts count + atomic.StoreUint32(&peer.timers.handshakeAttempts, 0) + if peer.timersActive() { peer.timers.sendKeepalive.Del() } @@ -95,7 +98,7 @@ func expiredRetransmitHandshake(peer *Peer) { } } else { atomic.AddUint32(&peer.timers.handshakeAttempts, 1) - peer.device.log.Verbosef("%s - Handshake did not complete after %d seconds, retrying (try %d)", peer, int(RekeyTimeout.Seconds()), atomic.LoadUint32(&peer.timers.handshakeAttempts)+1) + peer.device.log.Verbosef("%s - Handshake did not complete after %d seconds, retrying (try %d)", peer, int(RekeyTimeout.Seconds()), atomic.LoadUint32(&peer.timers.handshakeAttempts)) /* We clear the endpoint address src address, in case this is the cause of trouble. */ peer.Lock() @@ -141,10 +144,18 @@ func expiredPersistentKeepalive(peer *Peer) { } } +/* Returns true if HandshakeInitiation is already started (and not yet finished) */ +func (peer *Peer) handshakeInProgress() bool { + return atomic.LoadUint32(&peer.timers.handshakeAttempts) > 0 +} + /* Should be called after an authenticated data packet is sent. */ func (peer *Peer) timersDataSent() { if peer.timersActive() && !peer.timers.newHandshake.IsPending() { - peer.timers.newHandshake.Mod(KeepaliveTimeout + RekeyTimeout + time.Millisecond*time.Duration(rand.Int31n(RekeyTimeoutJitterMaxMs))) + // Do not restart handshake because of staled data traffic, if it is already in progress + if !peer.handshakeInProgress() { + peer.timers.newHandshake.Mod(KeepaliveTimeout + RekeyTimeout + time.Millisecond*time.Duration(rand.Int31n(RekeyTimeoutJitterMaxMs))) + } } }