github.com/slackhq/nebula@v1.9.0/hostmap.go (about) 1 package nebula 2 3 import ( 4 "errors" 5 "net" 6 "sync" 7 "sync/atomic" 8 "time" 9 10 "github.com/rcrowley/go-metrics" 11 "github.com/sirupsen/logrus" 12 "github.com/slackhq/nebula/cert" 13 "github.com/slackhq/nebula/cidr" 14 "github.com/slackhq/nebula/config" 15 "github.com/slackhq/nebula/header" 16 "github.com/slackhq/nebula/iputil" 17 "github.com/slackhq/nebula/udp" 18 ) 19 20 // const ProbeLen = 100 21 const defaultPromoteEvery = 1000 // Count of packets sent before we try moving a tunnel to a preferred underlay ip address 22 const defaultReQueryEvery = 5000 // Count of packets sent before re-querying a hostinfo to the lighthouse 23 const defaultReQueryWait = time.Minute // Minimum amount of seconds to wait before re-querying a hostinfo the lighthouse. Evaluated every ReQueryEvery 24 const MaxRemotes = 10 25 const maxRecvError = 4 26 27 // MaxHostInfosPerVpnIp is the max number of hostinfos we will track for a given vpn ip 28 // 5 allows for an initial handshake and each host pair re-handshaking twice 29 const MaxHostInfosPerVpnIp = 5 30 31 // How long we should prevent roaming back to the previous IP. 32 // This helps prevent flapping due to packets already in flight 33 const RoamingSuppressSeconds = 2 34 35 const ( 36 Requested = iota 37 PeerRequested 38 Established 39 ) 40 41 const ( 42 Unknowntype = iota 43 ForwardingType 44 TerminalType 45 ) 46 47 type Relay struct { 48 Type int 49 State int 50 LocalIndex uint32 51 RemoteIndex uint32 52 PeerIp iputil.VpnIp 53 } 54 55 type HostMap struct { 56 sync.RWMutex //Because we concurrently read and write to our maps 57 Indexes map[uint32]*HostInfo 58 Relays map[uint32]*HostInfo // Maps a Relay IDX to a Relay HostInfo object 59 RemoteIndexes map[uint32]*HostInfo 60 Hosts map[iputil.VpnIp]*HostInfo 61 preferredRanges atomic.Pointer[[]*net.IPNet] 62 vpnCIDR *net.IPNet 63 l *logrus.Logger 64 } 65 66 // For synchronization, treat the pointed-to Relay struct as immutable. To edit the Relay 67 // struct, make a copy of an existing value, edit the fileds in the copy, and 68 // then store a pointer to the new copy in both realyForBy* maps. 69 type RelayState struct { 70 sync.RWMutex 71 72 relays map[iputil.VpnIp]struct{} // Set of VpnIp's of Hosts to use as relays to access this peer 73 relayForByIp map[iputil.VpnIp]*Relay // Maps VpnIps of peers for which this HostInfo is a relay to some Relay info 74 relayForByIdx map[uint32]*Relay // Maps a local index to some Relay info 75 } 76 77 func (rs *RelayState) DeleteRelay(ip iputil.VpnIp) { 78 rs.Lock() 79 defer rs.Unlock() 80 delete(rs.relays, ip) 81 } 82 83 func (rs *RelayState) CopyAllRelayFor() []*Relay { 84 rs.RLock() 85 defer rs.RUnlock() 86 ret := make([]*Relay, 0, len(rs.relayForByIdx)) 87 for _, r := range rs.relayForByIdx { 88 ret = append(ret, r) 89 } 90 return ret 91 } 92 93 func (rs *RelayState) GetRelayForByIp(ip iputil.VpnIp) (*Relay, bool) { 94 rs.RLock() 95 defer rs.RUnlock() 96 r, ok := rs.relayForByIp[ip] 97 return r, ok 98 } 99 100 func (rs *RelayState) InsertRelayTo(ip iputil.VpnIp) { 101 rs.Lock() 102 defer rs.Unlock() 103 rs.relays[ip] = struct{}{} 104 } 105 106 func (rs *RelayState) CopyRelayIps() []iputil.VpnIp { 107 rs.RLock() 108 defer rs.RUnlock() 109 ret := make([]iputil.VpnIp, 0, len(rs.relays)) 110 for ip := range rs.relays { 111 ret = append(ret, ip) 112 } 113 return ret 114 } 115 116 func (rs *RelayState) CopyRelayForIps() []iputil.VpnIp { 117 rs.RLock() 118 defer rs.RUnlock() 119 currentRelays := make([]iputil.VpnIp, 0, len(rs.relayForByIp)) 120 for relayIp := range rs.relayForByIp { 121 currentRelays = append(currentRelays, relayIp) 122 } 123 return currentRelays 124 } 125 126 func (rs *RelayState) CopyRelayForIdxs() []uint32 { 127 rs.RLock() 128 defer rs.RUnlock() 129 ret := make([]uint32, 0, len(rs.relayForByIdx)) 130 for i := range rs.relayForByIdx { 131 ret = append(ret, i) 132 } 133 return ret 134 } 135 136 func (rs *RelayState) RemoveRelay(localIdx uint32) (iputil.VpnIp, bool) { 137 rs.Lock() 138 defer rs.Unlock() 139 r, ok := rs.relayForByIdx[localIdx] 140 if !ok { 141 return iputil.VpnIp(0), false 142 } 143 delete(rs.relayForByIdx, localIdx) 144 delete(rs.relayForByIp, r.PeerIp) 145 return r.PeerIp, true 146 } 147 148 func (rs *RelayState) CompleteRelayByIP(vpnIp iputil.VpnIp, remoteIdx uint32) bool { 149 rs.Lock() 150 defer rs.Unlock() 151 r, ok := rs.relayForByIp[vpnIp] 152 if !ok { 153 return false 154 } 155 newRelay := *r 156 newRelay.State = Established 157 newRelay.RemoteIndex = remoteIdx 158 rs.relayForByIdx[r.LocalIndex] = &newRelay 159 rs.relayForByIp[r.PeerIp] = &newRelay 160 return true 161 } 162 163 func (rs *RelayState) CompleteRelayByIdx(localIdx uint32, remoteIdx uint32) (*Relay, bool) { 164 rs.Lock() 165 defer rs.Unlock() 166 r, ok := rs.relayForByIdx[localIdx] 167 if !ok { 168 return nil, false 169 } 170 newRelay := *r 171 newRelay.State = Established 172 newRelay.RemoteIndex = remoteIdx 173 rs.relayForByIdx[r.LocalIndex] = &newRelay 174 rs.relayForByIp[r.PeerIp] = &newRelay 175 return &newRelay, true 176 } 177 178 func (rs *RelayState) QueryRelayForByIp(vpnIp iputil.VpnIp) (*Relay, bool) { 179 rs.RLock() 180 defer rs.RUnlock() 181 r, ok := rs.relayForByIp[vpnIp] 182 return r, ok 183 } 184 185 func (rs *RelayState) QueryRelayForByIdx(idx uint32) (*Relay, bool) { 186 rs.RLock() 187 defer rs.RUnlock() 188 r, ok := rs.relayForByIdx[idx] 189 return r, ok 190 } 191 192 func (rs *RelayState) InsertRelay(ip iputil.VpnIp, idx uint32, r *Relay) { 193 rs.Lock() 194 defer rs.Unlock() 195 rs.relayForByIp[ip] = r 196 rs.relayForByIdx[idx] = r 197 } 198 199 type HostInfo struct { 200 remote *udp.Addr 201 remotes *RemoteList 202 promoteCounter atomic.Uint32 203 ConnectionState *ConnectionState 204 remoteIndexId uint32 205 localIndexId uint32 206 vpnIp iputil.VpnIp 207 recvError atomic.Uint32 208 remoteCidr *cidr.Tree4[struct{}] 209 relayState RelayState 210 211 // HandshakePacket records the packets used to create this hostinfo 212 // We need these to avoid replayed handshake packets creating new hostinfos which causes churn 213 HandshakePacket map[uint8][]byte 214 215 // nextLHQuery is the earliest we can ask the lighthouse for new information. 216 // This is used to limit lighthouse re-queries in chatty clients 217 nextLHQuery atomic.Int64 218 219 // lastRebindCount is the other side of Interface.rebindCount, if these values don't match then we need to ask LH 220 // for a punch from the remote end of this tunnel. The goal being to prime their conntrack for our traffic just like 221 // with a handshake 222 lastRebindCount int8 223 224 // lastHandshakeTime records the time the remote side told us about at the stage when the handshake was completed locally 225 // Stage 1 packet will contain it if I am a responder, stage 2 packet if I am an initiator 226 // This is used to avoid an attack where a handshake packet is replayed after some time 227 lastHandshakeTime uint64 228 229 lastRoam time.Time 230 lastRoamRemote *udp.Addr 231 232 // Used to track other hostinfos for this vpn ip since only 1 can be primary 233 // Synchronised via hostmap lock and not the hostinfo lock. 234 next, prev *HostInfo 235 } 236 237 type ViaSender struct { 238 relayHI *HostInfo // relayHI is the host info object of the relay 239 remoteIdx uint32 // remoteIdx is the index included in the header of the received packet 240 relay *Relay // relay contains the rest of the relay information, including the PeerIP of the host trying to communicate with us. 241 } 242 243 type cachedPacket struct { 244 messageType header.MessageType 245 messageSubType header.MessageSubType 246 callback packetCallback 247 packet []byte 248 } 249 250 type packetCallback func(t header.MessageType, st header.MessageSubType, h *HostInfo, p, nb, out []byte) 251 252 type cachedPacketMetrics struct { 253 sent metrics.Counter 254 dropped metrics.Counter 255 } 256 257 func NewHostMapFromConfig(l *logrus.Logger, vpnCIDR *net.IPNet, c *config.C) *HostMap { 258 hm := newHostMap(l, vpnCIDR) 259 260 hm.reload(c, true) 261 c.RegisterReloadCallback(func(c *config.C) { 262 hm.reload(c, false) 263 }) 264 265 l.WithField("network", hm.vpnCIDR.String()). 266 WithField("preferredRanges", hm.GetPreferredRanges()). 267 Info("Main HostMap created") 268 269 return hm 270 } 271 272 func newHostMap(l *logrus.Logger, vpnCIDR *net.IPNet) *HostMap { 273 return &HostMap{ 274 Indexes: map[uint32]*HostInfo{}, 275 Relays: map[uint32]*HostInfo{}, 276 RemoteIndexes: map[uint32]*HostInfo{}, 277 Hosts: map[iputil.VpnIp]*HostInfo{}, 278 vpnCIDR: vpnCIDR, 279 l: l, 280 } 281 } 282 283 func (hm *HostMap) reload(c *config.C, initial bool) { 284 if initial || c.HasChanged("preferred_ranges") { 285 var preferredRanges []*net.IPNet 286 rawPreferredRanges := c.GetStringSlice("preferred_ranges", []string{}) 287 288 for _, rawPreferredRange := range rawPreferredRanges { 289 _, preferredRange, err := net.ParseCIDR(rawPreferredRange) 290 291 if err != nil { 292 hm.l.WithError(err).WithField("range", rawPreferredRanges).Warn("Failed to parse preferred ranges, ignoring") 293 continue 294 } 295 296 preferredRanges = append(preferredRanges, preferredRange) 297 } 298 299 oldRanges := hm.preferredRanges.Swap(&preferredRanges) 300 if !initial { 301 hm.l.WithField("oldPreferredRanges", *oldRanges).WithField("newPreferredRanges", preferredRanges).Info("preferred_ranges changed") 302 } 303 } 304 } 305 306 // EmitStats reports host, index, and relay counts to the stats collection system 307 func (hm *HostMap) EmitStats() { 308 hm.RLock() 309 hostLen := len(hm.Hosts) 310 indexLen := len(hm.Indexes) 311 remoteIndexLen := len(hm.RemoteIndexes) 312 relaysLen := len(hm.Relays) 313 hm.RUnlock() 314 315 metrics.GetOrRegisterGauge("hostmap.main.hosts", nil).Update(int64(hostLen)) 316 metrics.GetOrRegisterGauge("hostmap.main.indexes", nil).Update(int64(indexLen)) 317 metrics.GetOrRegisterGauge("hostmap.main.remoteIndexes", nil).Update(int64(remoteIndexLen)) 318 metrics.GetOrRegisterGauge("hostmap.main.relayIndexes", nil).Update(int64(relaysLen)) 319 } 320 321 func (hm *HostMap) RemoveRelay(localIdx uint32) { 322 hm.Lock() 323 _, ok := hm.Relays[localIdx] 324 if !ok { 325 hm.Unlock() 326 return 327 } 328 delete(hm.Relays, localIdx) 329 hm.Unlock() 330 } 331 332 // DeleteHostInfo will fully unlink the hostinfo and return true if it was the final hostinfo for this vpn ip 333 func (hm *HostMap) DeleteHostInfo(hostinfo *HostInfo) bool { 334 // Delete the host itself, ensuring it's not modified anymore 335 hm.Lock() 336 // If we have a previous or next hostinfo then we are not the last one for this vpn ip 337 final := (hostinfo.next == nil && hostinfo.prev == nil) 338 hm.unlockedDeleteHostInfo(hostinfo) 339 hm.Unlock() 340 341 return final 342 } 343 344 func (hm *HostMap) MakePrimary(hostinfo *HostInfo) { 345 hm.Lock() 346 defer hm.Unlock() 347 hm.unlockedMakePrimary(hostinfo) 348 } 349 350 func (hm *HostMap) unlockedMakePrimary(hostinfo *HostInfo) { 351 oldHostinfo := hm.Hosts[hostinfo.vpnIp] 352 if oldHostinfo == hostinfo { 353 return 354 } 355 356 if hostinfo.prev != nil { 357 hostinfo.prev.next = hostinfo.next 358 } 359 360 if hostinfo.next != nil { 361 hostinfo.next.prev = hostinfo.prev 362 } 363 364 hm.Hosts[hostinfo.vpnIp] = hostinfo 365 366 if oldHostinfo == nil { 367 return 368 } 369 370 hostinfo.next = oldHostinfo 371 oldHostinfo.prev = hostinfo 372 hostinfo.prev = nil 373 } 374 375 func (hm *HostMap) unlockedDeleteHostInfo(hostinfo *HostInfo) { 376 primary, ok := hm.Hosts[hostinfo.vpnIp] 377 if ok && primary == hostinfo { 378 // The vpnIp pointer points to the same hostinfo as the local index id, we can remove it 379 delete(hm.Hosts, hostinfo.vpnIp) 380 if len(hm.Hosts) == 0 { 381 hm.Hosts = map[iputil.VpnIp]*HostInfo{} 382 } 383 384 if hostinfo.next != nil { 385 // We had more than 1 hostinfo at this vpnip, promote the next in the list to primary 386 hm.Hosts[hostinfo.vpnIp] = hostinfo.next 387 // It is primary, there is no previous hostinfo now 388 hostinfo.next.prev = nil 389 } 390 391 } else { 392 // Relink if we were in the middle of multiple hostinfos for this vpn ip 393 if hostinfo.prev != nil { 394 hostinfo.prev.next = hostinfo.next 395 } 396 397 if hostinfo.next != nil { 398 hostinfo.next.prev = hostinfo.prev 399 } 400 } 401 402 hostinfo.next = nil 403 hostinfo.prev = nil 404 405 // The remote index uses index ids outside our control so lets make sure we are only removing 406 // the remote index pointer here if it points to the hostinfo we are deleting 407 hostinfo2, ok := hm.RemoteIndexes[hostinfo.remoteIndexId] 408 if ok && hostinfo2 == hostinfo { 409 delete(hm.RemoteIndexes, hostinfo.remoteIndexId) 410 if len(hm.RemoteIndexes) == 0 { 411 hm.RemoteIndexes = map[uint32]*HostInfo{} 412 } 413 } 414 415 delete(hm.Indexes, hostinfo.localIndexId) 416 if len(hm.Indexes) == 0 { 417 hm.Indexes = map[uint32]*HostInfo{} 418 } 419 420 if hm.l.Level >= logrus.DebugLevel { 421 hm.l.WithField("hostMap", m{"mapTotalSize": len(hm.Hosts), 422 "vpnIp": hostinfo.vpnIp, "indexNumber": hostinfo.localIndexId, "remoteIndexNumber": hostinfo.remoteIndexId}). 423 Debug("Hostmap hostInfo deleted") 424 } 425 426 for _, localRelayIdx := range hostinfo.relayState.CopyRelayForIdxs() { 427 delete(hm.Relays, localRelayIdx) 428 } 429 } 430 431 func (hm *HostMap) QueryIndex(index uint32) *HostInfo { 432 hm.RLock() 433 if h, ok := hm.Indexes[index]; ok { 434 hm.RUnlock() 435 return h 436 } else { 437 hm.RUnlock() 438 return nil 439 } 440 } 441 442 func (hm *HostMap) QueryRelayIndex(index uint32) *HostInfo { 443 hm.RLock() 444 if h, ok := hm.Relays[index]; ok { 445 hm.RUnlock() 446 return h 447 } else { 448 hm.RUnlock() 449 return nil 450 } 451 } 452 453 func (hm *HostMap) QueryReverseIndex(index uint32) *HostInfo { 454 hm.RLock() 455 if h, ok := hm.RemoteIndexes[index]; ok { 456 hm.RUnlock() 457 return h 458 } else { 459 hm.RUnlock() 460 return nil 461 } 462 } 463 464 func (hm *HostMap) QueryVpnIp(vpnIp iputil.VpnIp) *HostInfo { 465 return hm.queryVpnIp(vpnIp, nil) 466 } 467 468 func (hm *HostMap) QueryVpnIpRelayFor(targetIp, relayHostIp iputil.VpnIp) (*HostInfo, *Relay, error) { 469 hm.RLock() 470 defer hm.RUnlock() 471 472 h, ok := hm.Hosts[relayHostIp] 473 if !ok { 474 return nil, nil, errors.New("unable to find host") 475 } 476 for h != nil { 477 r, ok := h.relayState.QueryRelayForByIp(targetIp) 478 if ok && r.State == Established { 479 return h, r, nil 480 } 481 h = h.next 482 } 483 return nil, nil, errors.New("unable to find host with relay") 484 } 485 486 func (hm *HostMap) queryVpnIp(vpnIp iputil.VpnIp, promoteIfce *Interface) *HostInfo { 487 hm.RLock() 488 if h, ok := hm.Hosts[vpnIp]; ok { 489 hm.RUnlock() 490 // Do not attempt promotion if you are a lighthouse 491 if promoteIfce != nil && !promoteIfce.lightHouse.amLighthouse { 492 h.TryPromoteBest(hm.GetPreferredRanges(), promoteIfce) 493 } 494 return h 495 496 } 497 498 hm.RUnlock() 499 return nil 500 } 501 502 // unlockedAddHostInfo assumes you have a write-lock and will add a hostinfo object to the hostmap Indexes and RemoteIndexes maps. 503 // If an entry exists for the Hosts table (vpnIp -> hostinfo) then the provided hostinfo will be made primary 504 func (hm *HostMap) unlockedAddHostInfo(hostinfo *HostInfo, f *Interface) { 505 if f.serveDns { 506 remoteCert := hostinfo.ConnectionState.peerCert 507 dnsR.Add(remoteCert.Details.Name+".", remoteCert.Details.Ips[0].IP.String()) 508 } 509 510 existing := hm.Hosts[hostinfo.vpnIp] 511 hm.Hosts[hostinfo.vpnIp] = hostinfo 512 513 if existing != nil { 514 hostinfo.next = existing 515 existing.prev = hostinfo 516 } 517 518 hm.Indexes[hostinfo.localIndexId] = hostinfo 519 hm.RemoteIndexes[hostinfo.remoteIndexId] = hostinfo 520 521 if hm.l.Level >= logrus.DebugLevel { 522 hm.l.WithField("hostMap", m{"vpnIp": hostinfo.vpnIp, "mapTotalSize": len(hm.Hosts), 523 "hostinfo": m{"existing": true, "localIndexId": hostinfo.localIndexId, "hostId": hostinfo.vpnIp}}). 524 Debug("Hostmap vpnIp added") 525 } 526 527 i := 1 528 check := hostinfo 529 for check != nil { 530 if i > MaxHostInfosPerVpnIp { 531 hm.unlockedDeleteHostInfo(check) 532 } 533 check = check.next 534 i++ 535 } 536 } 537 538 func (hm *HostMap) GetPreferredRanges() []*net.IPNet { 539 //NOTE: if preferredRanges is ever not stored before a load this will fail to dereference a nil pointer 540 return *hm.preferredRanges.Load() 541 } 542 543 func (hm *HostMap) ForEachVpnIp(f controlEach) { 544 hm.RLock() 545 defer hm.RUnlock() 546 547 for _, v := range hm.Hosts { 548 f(v) 549 } 550 } 551 552 func (hm *HostMap) ForEachIndex(f controlEach) { 553 hm.RLock() 554 defer hm.RUnlock() 555 556 for _, v := range hm.Indexes { 557 f(v) 558 } 559 } 560 561 // TryPromoteBest handles re-querying lighthouses and probing for better paths 562 // NOTE: It is an error to call this if you are a lighthouse since they should not roam clients! 563 func (i *HostInfo) TryPromoteBest(preferredRanges []*net.IPNet, ifce *Interface) { 564 c := i.promoteCounter.Add(1) 565 if c%ifce.tryPromoteEvery.Load() == 0 { 566 remote := i.remote 567 568 // return early if we are already on a preferred remote 569 if remote != nil { 570 rIP := remote.IP 571 for _, l := range preferredRanges { 572 if l.Contains(rIP) { 573 return 574 } 575 } 576 } 577 578 i.remotes.ForEach(preferredRanges, func(addr *udp.Addr, preferred bool) { 579 if remote != nil && (addr == nil || !preferred) { 580 return 581 } 582 583 // Try to send a test packet to that host, this should 584 // cause it to detect a roaming event and switch remotes 585 ifce.sendTo(header.Test, header.TestRequest, i.ConnectionState, i, addr, []byte(""), make([]byte, 12, 12), make([]byte, mtu)) 586 }) 587 } 588 589 // Re query our lighthouses for new remotes occasionally 590 if c%ifce.reQueryEvery.Load() == 0 && ifce.lightHouse != nil { 591 now := time.Now().UnixNano() 592 if now < i.nextLHQuery.Load() { 593 return 594 } 595 596 i.nextLHQuery.Store(now + ifce.reQueryWait.Load()) 597 ifce.lightHouse.QueryServer(i.vpnIp) 598 } 599 } 600 601 func (i *HostInfo) GetCert() *cert.NebulaCertificate { 602 if i.ConnectionState != nil { 603 return i.ConnectionState.peerCert 604 } 605 return nil 606 } 607 608 func (i *HostInfo) SetRemote(remote *udp.Addr) { 609 // We copy here because we likely got this remote from a source that reuses the object 610 if !i.remote.Equals(remote) { 611 i.remote = remote.Copy() 612 i.remotes.LearnRemote(i.vpnIp, remote.Copy()) 613 } 614 } 615 616 // SetRemoteIfPreferred returns true if the remote was changed. The lastRoam 617 // time on the HostInfo will also be updated. 618 func (i *HostInfo) SetRemoteIfPreferred(hm *HostMap, newRemote *udp.Addr) bool { 619 if newRemote == nil { 620 // relays have nil udp Addrs 621 return false 622 } 623 currentRemote := i.remote 624 if currentRemote == nil { 625 i.SetRemote(newRemote) 626 return true 627 } 628 629 // NOTE: We do this loop here instead of calling `isPreferred` in 630 // remote_list.go so that we only have to loop over preferredRanges once. 631 newIsPreferred := false 632 for _, l := range hm.GetPreferredRanges() { 633 // return early if we are already on a preferred remote 634 if l.Contains(currentRemote.IP) { 635 return false 636 } 637 638 if l.Contains(newRemote.IP) { 639 newIsPreferred = true 640 } 641 } 642 643 if newIsPreferred { 644 // Consider this a roaming event 645 i.lastRoam = time.Now() 646 i.lastRoamRemote = currentRemote.Copy() 647 648 i.SetRemote(newRemote) 649 650 return true 651 } 652 653 return false 654 } 655 656 func (i *HostInfo) RecvErrorExceeded() bool { 657 if i.recvError.Add(1) >= maxRecvError { 658 return true 659 } 660 return true 661 } 662 663 func (i *HostInfo) CreateRemoteCIDR(c *cert.NebulaCertificate) { 664 if len(c.Details.Ips) == 1 && len(c.Details.Subnets) == 0 { 665 // Simple case, no CIDRTree needed 666 return 667 } 668 669 remoteCidr := cidr.NewTree4[struct{}]() 670 for _, ip := range c.Details.Ips { 671 remoteCidr.AddCIDR(&net.IPNet{IP: ip.IP, Mask: net.IPMask{255, 255, 255, 255}}, struct{}{}) 672 } 673 674 for _, n := range c.Details.Subnets { 675 remoteCidr.AddCIDR(n, struct{}{}) 676 } 677 i.remoteCidr = remoteCidr 678 } 679 680 func (i *HostInfo) logger(l *logrus.Logger) *logrus.Entry { 681 if i == nil { 682 return logrus.NewEntry(l) 683 } 684 685 li := l.WithField("vpnIp", i.vpnIp). 686 WithField("localIndex", i.localIndexId). 687 WithField("remoteIndex", i.remoteIndexId) 688 689 if connState := i.ConnectionState; connState != nil { 690 if peerCert := connState.peerCert; peerCert != nil { 691 li = li.WithField("certName", peerCert.Details.Name) 692 } 693 } 694 695 return li 696 } 697 698 // Utility functions 699 700 func localIps(l *logrus.Logger, allowList *LocalAllowList) *[]net.IP { 701 //FIXME: This function is pretty garbage 702 var ips []net.IP 703 ifaces, _ := net.Interfaces() 704 for _, i := range ifaces { 705 allow := allowList.AllowName(i.Name) 706 if l.Level >= logrus.TraceLevel { 707 l.WithField("interfaceName", i.Name).WithField("allow", allow).Trace("localAllowList.AllowName") 708 } 709 710 if !allow { 711 continue 712 } 713 addrs, _ := i.Addrs() 714 for _, addr := range addrs { 715 var ip net.IP 716 switch v := addr.(type) { 717 case *net.IPNet: 718 //continue 719 ip = v.IP 720 case *net.IPAddr: 721 ip = v.IP 722 } 723 724 //TODO: Filtering out link local for now, this is probably the most correct thing 725 //TODO: Would be nice to filter out SLAAC MAC based ips as well 726 if ip.IsLoopback() == false && !ip.IsLinkLocalUnicast() { 727 allow := allowList.Allow(ip) 728 if l.Level >= logrus.TraceLevel { 729 l.WithField("localIp", ip).WithField("allow", allow).Trace("localAllowList.Allow") 730 } 731 if !allow { 732 continue 733 } 734 735 ips = append(ips, ip) 736 } 737 } 738 } 739 return &ips 740 }