github.com/tailscale/wireguard-go@v0.0.20201119-0.20210522003738-46b531feb08a/device/peer.go (about) 1 /* SPDX-License-Identifier: MIT 2 * 3 * Copyright (C) 2017-2021 WireGuard LLC. All Rights Reserved. 4 */ 5 6 package device 7 8 import ( 9 "container/list" 10 "errors" 11 "sync" 12 "sync/atomic" 13 "time" 14 15 "github.com/tailscale/wireguard-go/conn" 16 ) 17 18 type Peer struct { 19 isRunning AtomicBool 20 sync.RWMutex // Mostly protects endpoint, but is generally taken whenever we modify peer 21 keypairs Keypairs 22 handshake Handshake 23 device *Device 24 endpoint conn.Endpoint 25 stopping sync.WaitGroup // routines pending stop 26 27 // These fields are accessed with atomic operations, which must be 28 // 64-bit aligned even on 32-bit platforms. Go guarantees that an 29 // allocated struct will be 64-bit aligned. So we place 30 // atomically-accessed fields up front, so that they can share in 31 // this alignment before smaller fields throw it off. 32 stats struct { 33 txBytes uint64 // bytes send to peer (endpoint) 34 rxBytes uint64 // bytes received from peer 35 lastHandshakeNano int64 // nano seconds since epoch 36 } 37 38 disableRoaming bool 39 40 timers struct { 41 retransmitHandshake *Timer 42 sendKeepalive *Timer 43 newHandshake *Timer 44 zeroKeyMaterial *Timer 45 persistentKeepalive *Timer 46 handshakeAttempts uint32 47 needAnotherKeepalive AtomicBool 48 sentLastMinuteHandshake AtomicBool 49 } 50 51 state struct { 52 sync.Mutex // protects against concurrent Start/Stop 53 } 54 55 queue struct { 56 staged chan *QueueOutboundElement // staged packets before a handshake is available 57 outbound *autodrainingOutboundQueue // sequential ordering of udp transmission 58 inbound *autodrainingInboundQueue // sequential ordering of tun writing 59 } 60 61 cookieGenerator CookieGenerator 62 trieEntries list.List 63 persistentKeepaliveInterval uint32 // accessed atomically 64 } 65 66 func (device *Device) NewPeer(pk NoisePublicKey) (*Peer, error) { 67 if device.isClosed() { 68 return nil, errors.New("device closed") 69 } 70 71 // lock resources 72 device.staticIdentity.RLock() 73 defer device.staticIdentity.RUnlock() 74 75 device.peers.Lock() 76 defer device.peers.Unlock() 77 78 // check if over limit 79 if len(device.peers.keyMap) >= MaxPeers { 80 return nil, errors.New("too many peers") 81 } 82 83 // create peer 84 peer := new(Peer) 85 peer.Lock() 86 defer peer.Unlock() 87 88 peer.cookieGenerator.Init(pk) 89 peer.device = device 90 peer.queue.outbound = newAutodrainingOutboundQueue(device) 91 peer.queue.inbound = newAutodrainingInboundQueue(device) 92 peer.queue.staged = make(chan *QueueOutboundElement, QueueStagedSize) 93 94 // map public key 95 _, ok := device.peers.keyMap[pk] 96 if ok { 97 return nil, errors.New("adding existing peer") 98 } 99 100 // pre-compute DH 101 handshake := &peer.handshake 102 handshake.mutex.Lock() 103 handshake.precomputedStaticStatic = device.staticIdentity.privateKey.sharedSecret(pk) 104 handshake.remoteStatic = pk 105 handshake.mutex.Unlock() 106 107 // reset endpoint 108 peer.endpoint = nil 109 110 // add 111 device.peers.keyMap[pk] = peer 112 113 // start peer 114 peer.timersInit() 115 if peer.device.isUp() { 116 peer.Start() 117 } 118 119 return peer, nil 120 } 121 122 func (peer *Peer) SendBuffer(buffer []byte) error { 123 peer.device.net.RLock() 124 defer peer.device.net.RUnlock() 125 126 if peer.device.isClosed() { 127 return nil 128 } 129 130 peer.RLock() 131 defer peer.RUnlock() 132 133 if peer.endpoint == nil { 134 return errors.New("no known endpoint for peer") 135 } 136 137 err := peer.device.net.bind.Send(buffer, peer.endpoint) 138 if err == nil { 139 atomic.AddUint64(&peer.stats.txBytes, uint64(len(buffer))) 140 } 141 return err 142 } 143 144 func (peer *Peer) String() string { 145 // The awful goo that follows is identical to: 146 // 147 // base64Key := base64.StdEncoding.EncodeToString(peer.handshake.remoteStatic[:]) 148 // abbreviatedKey := base64Key[0:4] + "…" + base64Key[39:43] 149 // return fmt.Sprintf("peer(%s)", abbreviatedKey) 150 // 151 // except that it is considerably more efficient. 152 src := peer.handshake.remoteStatic 153 b64 := func(input byte) byte { 154 return input + 'A' + byte(((25-int(input))>>8)&6) - byte(((51-int(input))>>8)&75) - byte(((61-int(input))>>8)&15) + byte(((62-int(input))>>8)&3) 155 } 156 b := []byte("peer(____…____)") 157 const first = len("peer(") 158 const second = len("peer(____…") 159 b[first+0] = b64((src[0] >> 2) & 63) 160 b[first+1] = b64(((src[0] << 4) | (src[1] >> 4)) & 63) 161 b[first+2] = b64(((src[1] << 2) | (src[2] >> 6)) & 63) 162 b[first+3] = b64(src[2] & 63) 163 b[second+0] = b64(src[29] & 63) 164 b[second+1] = b64((src[30] >> 2) & 63) 165 b[second+2] = b64(((src[30] << 4) | (src[31] >> 4)) & 63) 166 b[second+3] = b64((src[31] << 2) & 63) 167 return string(b) 168 } 169 170 func (peer *Peer) Start() { 171 // should never start a peer on a closed device 172 if peer.device.isClosed() { 173 return 174 } 175 176 // prevent simultaneous start/stop operations 177 peer.state.Lock() 178 defer peer.state.Unlock() 179 180 if peer.isRunning.Get() { 181 return 182 } 183 184 device := peer.device 185 device.log.Verbosef("%v - Starting", peer) 186 187 // reset routine state 188 peer.stopping.Wait() 189 peer.stopping.Add(2) 190 191 peer.handshake.mutex.Lock() 192 peer.handshake.lastSentHandshake = time.Now().Add(-(RekeyTimeout + time.Second)) 193 peer.handshake.mutex.Unlock() 194 195 peer.device.queue.encryption.wg.Add(1) // keep encryption queue open for our writes 196 197 peer.timersStart() 198 199 device.flushInboundQueue(peer.queue.inbound) 200 device.flushOutboundQueue(peer.queue.outbound) 201 go peer.RoutineSequentialSender() 202 go peer.RoutineSequentialReceiver() 203 204 peer.isRunning.Set(true) 205 } 206 207 func (peer *Peer) ZeroAndFlushAll() { 208 device := peer.device 209 210 // clear key pairs 211 212 keypairs := &peer.keypairs 213 keypairs.Lock() 214 device.DeleteKeypair(keypairs.previous) 215 device.DeleteKeypair(keypairs.current) 216 device.DeleteKeypair(keypairs.loadNext()) 217 keypairs.previous = nil 218 keypairs.current = nil 219 keypairs.storeNext(nil) 220 keypairs.Unlock() 221 222 // clear handshake state 223 224 handshake := &peer.handshake 225 handshake.mutex.Lock() 226 device.indexTable.Delete(handshake.localIndex) 227 handshake.Clear() 228 handshake.mutex.Unlock() 229 230 peer.FlushStagedPackets() 231 } 232 233 func (peer *Peer) ExpireCurrentKeypairs() { 234 handshake := &peer.handshake 235 handshake.mutex.Lock() 236 peer.device.indexTable.Delete(handshake.localIndex) 237 handshake.Clear() 238 peer.handshake.lastSentHandshake = time.Now().Add(-(RekeyTimeout + time.Second)) 239 handshake.mutex.Unlock() 240 241 keypairs := &peer.keypairs 242 keypairs.Lock() 243 if keypairs.current != nil { 244 atomic.StoreUint64(&keypairs.current.sendNonce, RejectAfterMessages) 245 } 246 if keypairs.next != nil { 247 next := keypairs.loadNext() 248 atomic.StoreUint64(&next.sendNonce, RejectAfterMessages) 249 } 250 keypairs.Unlock() 251 } 252 253 func (peer *Peer) Stop() { 254 peer.state.Lock() 255 defer peer.state.Unlock() 256 257 if !peer.isRunning.Swap(false) { 258 return 259 } 260 261 peer.device.log.Verbosef("%v - Stopping", peer) 262 263 peer.timersStop() 264 // Signal that RoutineSequentialSender and RoutineSequentialReceiver should exit. 265 peer.queue.inbound.c <- nil 266 peer.queue.outbound.c <- nil 267 peer.stopping.Wait() 268 peer.device.queue.encryption.wg.Done() // no more writes to encryption queue from us 269 270 peer.ZeroAndFlushAll() 271 } 272 273 func (peer *Peer) SetEndpointFromPacket(endpoint conn.Endpoint) { 274 if peer.disableRoaming { 275 return 276 } 277 peer.Lock() 278 peer.endpoint = endpoint 279 peer.Unlock() 280 }