github.com/GFW-knocker/wireguard@v1.0.1/device/timers.go (about) 1 /* SPDX-License-Identifier: MIT 2 * 3 * Copyright (C) 2017-2023 WireGuard LLC. All Rights Reserved. 4 * 5 * This is based heavily on timers.c from the kernel implementation. 6 */ 7 8 package device 9 10 import ( 11 "sync" 12 "time" 13 _ "unsafe" 14 ) 15 16 //go:linkname fastrandn runtime.fastrandn 17 func fastrandn(n uint32) uint32 18 19 // A Timer manages time-based aspects of the WireGuard protocol. 20 // Timer roughly copies the interface of the Linux kernel's struct timer_list. 21 type Timer struct { 22 *time.Timer 23 modifyingLock sync.RWMutex 24 runningLock sync.Mutex 25 isPending bool 26 } 27 28 func (peer *Peer) NewTimer(expirationFunction func(*Peer)) *Timer { 29 timer := &Timer{} 30 timer.Timer = time.AfterFunc(time.Hour, func() { 31 timer.runningLock.Lock() 32 defer timer.runningLock.Unlock() 33 34 timer.modifyingLock.Lock() 35 if !timer.isPending { 36 timer.modifyingLock.Unlock() 37 return 38 } 39 timer.isPending = false 40 timer.modifyingLock.Unlock() 41 42 expirationFunction(peer) 43 }) 44 timer.Stop() 45 return timer 46 } 47 48 func (timer *Timer) Mod(d time.Duration) { 49 timer.modifyingLock.Lock() 50 timer.isPending = true 51 timer.Reset(d) 52 timer.modifyingLock.Unlock() 53 } 54 55 func (timer *Timer) Del() { 56 timer.modifyingLock.Lock() 57 timer.isPending = false 58 timer.Stop() 59 timer.modifyingLock.Unlock() 60 } 61 62 func (timer *Timer) DelSync() { 63 timer.Del() 64 timer.runningLock.Lock() 65 timer.Del() 66 timer.runningLock.Unlock() 67 } 68 69 func (timer *Timer) IsPending() bool { 70 timer.modifyingLock.RLock() 71 defer timer.modifyingLock.RUnlock() 72 return timer.isPending 73 } 74 75 func (peer *Peer) timersActive() bool { 76 return peer.isRunning.Load() && peer.device != nil && peer.device.isUp() 77 } 78 79 func expiredRetransmitHandshake(peer *Peer) { 80 if peer.timers.handshakeAttempts.Load() > MaxTimerHandshakes { 81 peer.device.log.Verbosef("%s - Handshake did not complete after %d attempts, giving up", peer, MaxTimerHandshakes+2) 82 83 if peer.timersActive() { 84 peer.timers.sendKeepalive.Del() 85 } 86 87 /* We drop all packets without a keypair and don't try again, 88 * if we try unsuccessfully for too long to make a handshake. 89 */ 90 peer.FlushStagedPackets() 91 92 /* We set a timer for destroying any residue that might be left 93 * of a partial exchange. 94 */ 95 if peer.timersActive() && !peer.timers.zeroKeyMaterial.IsPending() { 96 peer.timers.zeroKeyMaterial.Mod(RejectAfterTime * 3) 97 } 98 } else { 99 peer.timers.handshakeAttempts.Add(1) 100 peer.device.log.Verbosef("%s - Handshake did not complete after %d seconds, retrying (try %d)", peer, int(RekeyTimeout.Seconds()), peer.timers.handshakeAttempts.Load()+1) 101 102 /* We clear the endpoint address src address, in case this is the cause of trouble. */ 103 peer.markEndpointSrcForClearing() 104 105 peer.SendHandshakeInitiation(true) 106 } 107 } 108 109 func expiredSendKeepalive(peer *Peer) { 110 peer.SendKeepalive() 111 if peer.timers.needAnotherKeepalive.Load() { 112 peer.timers.needAnotherKeepalive.Store(false) 113 if peer.timersActive() { 114 peer.timers.sendKeepalive.Mod(KeepaliveTimeout) 115 } 116 } 117 } 118 119 func expiredNewHandshake(peer *Peer) { 120 peer.device.log.Verbosef("%s - Retrying handshake because we stopped hearing back after %d seconds", peer, int((KeepaliveTimeout + RekeyTimeout).Seconds())) 121 /* We clear the endpoint address src address, in case this is the cause of trouble. */ 122 peer.markEndpointSrcForClearing() 123 peer.SendHandshakeInitiation(false) 124 } 125 126 func expiredZeroKeyMaterial(peer *Peer) { 127 peer.device.log.Verbosef("%s - Removing all keys, since we haven't received a new one in %d seconds", peer, int((RejectAfterTime * 3).Seconds())) 128 peer.ZeroAndFlushAll() 129 } 130 131 func expiredPersistentKeepalive(peer *Peer) { 132 if peer.persistentKeepaliveInterval.Load() > 0 { 133 peer.SendKeepalive() 134 } 135 } 136 137 /* Should be called after an authenticated data packet is sent. */ 138 func (peer *Peer) timersDataSent() { 139 if peer.timersActive() && !peer.timers.newHandshake.IsPending() { 140 peer.timers.newHandshake.Mod(KeepaliveTimeout + RekeyTimeout + time.Millisecond*time.Duration(fastrandn(RekeyTimeoutJitterMaxMs))) 141 } 142 } 143 144 /* Should be called after an authenticated data packet is received. */ 145 func (peer *Peer) timersDataReceived() { 146 if peer.timersActive() { 147 if !peer.timers.sendKeepalive.IsPending() { 148 peer.timers.sendKeepalive.Mod(KeepaliveTimeout) 149 } else { 150 peer.timers.needAnotherKeepalive.Store(true) 151 } 152 } 153 } 154 155 /* Should be called after any type of authenticated packet is sent -- keepalive, data, or handshake. */ 156 func (peer *Peer) timersAnyAuthenticatedPacketSent() { 157 if peer.timersActive() { 158 peer.timers.sendKeepalive.Del() 159 } 160 } 161 162 /* Should be called after any type of authenticated packet is received -- keepalive, data, or handshake. */ 163 func (peer *Peer) timersAnyAuthenticatedPacketReceived() { 164 if peer.timersActive() { 165 peer.timers.newHandshake.Del() 166 } 167 } 168 169 /* Should be called after a handshake initiation message is sent. */ 170 func (peer *Peer) timersHandshakeInitiated() { 171 if peer.timersActive() { 172 peer.timers.retransmitHandshake.Mod(RekeyTimeout + time.Millisecond*time.Duration(fastrandn(RekeyTimeoutJitterMaxMs))) 173 } 174 } 175 176 /* Should be called after a handshake response message is received and processed or when getting key confirmation via the first data message. */ 177 func (peer *Peer) timersHandshakeComplete() { 178 if peer.timersActive() { 179 peer.timers.retransmitHandshake.Del() 180 } 181 peer.timers.handshakeAttempts.Store(0) 182 peer.timers.sentLastMinuteHandshake.Store(false) 183 peer.lastHandshakeNano.Store(time.Now().UnixNano()) 184 } 185 186 /* Should be called after an ephemeral key is created, which is before sending a handshake response or after receiving a handshake response. */ 187 func (peer *Peer) timersSessionDerived() { 188 if peer.timersActive() { 189 peer.timers.zeroKeyMaterial.Mod(RejectAfterTime * 3) 190 } 191 } 192 193 /* Should be called before a packet with authentication -- keepalive, data, or handshake -- is sent, or after one is received. */ 194 func (peer *Peer) timersAnyAuthenticatedPacketTraversal() { 195 keepalive := peer.persistentKeepaliveInterval.Load() 196 if keepalive > 0 && peer.timersActive() { 197 peer.timers.persistentKeepalive.Mod(time.Duration(keepalive) * time.Second) 198 } 199 } 200 201 func (peer *Peer) timersInit() { 202 peer.timers.retransmitHandshake = peer.NewTimer(expiredRetransmitHandshake) 203 peer.timers.sendKeepalive = peer.NewTimer(expiredSendKeepalive) 204 peer.timers.newHandshake = peer.NewTimer(expiredNewHandshake) 205 peer.timers.zeroKeyMaterial = peer.NewTimer(expiredZeroKeyMaterial) 206 peer.timers.persistentKeepalive = peer.NewTimer(expiredPersistentKeepalive) 207 } 208 209 func (peer *Peer) timersStart() { 210 peer.timers.handshakeAttempts.Store(0) 211 peer.timers.sentLastMinuteHandshake.Store(false) 212 peer.timers.needAnotherKeepalive.Store(false) 213 } 214 215 func (peer *Peer) timersStop() { 216 peer.timers.retransmitHandshake.DelSync() 217 peer.timers.sendKeepalive.DelSync() 218 peer.timers.newHandshake.DelSync() 219 peer.timers.zeroKeyMaterial.DelSync() 220 peer.timers.persistentKeepalive.DelSync() 221 }