diff --git a/lighthouse.go b/lighthouse.go index 0ea977844..06f070f43 100644 --- a/lighthouse.go +++ b/lighthouse.go @@ -336,11 +336,11 @@ func (lh *LightHouse) reload(c *config.C, initial bool) error { case false: relaysForMe := []netip.Addr{} for _, v := range c.GetStringSlice("relay.relays", nil) { - lh.l.WithField("relay", v).Info("Read relay from config") - configRIP, err := netip.ParseAddr(v) - //TODO: We could print the error here - if err == nil { + if err != nil { + lh.l.WithField("relay", v).WithError(err).Warn("Parse relay from config failed") + } else { + lh.l.WithField("relay", v).Info("Read relay from config") relaysForMe = append(relaysForMe, configRIP) } } @@ -891,6 +891,11 @@ func (lh *LightHouse) SendUpdate() { } if v == cert.Version1 { if v1Update == nil { + if !lh.myVpnNetworks[0].Addr().Is4() { + lh.l.WithField("lighthouseAddr", lhVpnAddr). + Warn("cannot update lighthouse using v1 protocol without an IPv4 address") + continue + } var relays []uint32 for _, r := range lh.GetRelaysForMe() { if !r.Is4() { @@ -899,7 +904,6 @@ func (lh *LightHouse) SendUpdate() { b := r.As4() relays = append(relays, binary.BigEndian.Uint32(b[:])) } - //TODO: assert ipv4 b := lh.myVpnNetworks[0].Addr().As4() msg := NebulaMeta{ Type: NebulaMeta_HostUpdateNotification, @@ -1056,7 +1060,7 @@ func (lhh *LightHouseHandler) handleHostQuery(n *NebulaMeta, fromVpnAddrs []neti return } - var useVersion cert.Version + useVersion := cert.Version1 var queryVpnAddr netip.Addr if n.Details.OldVpnAddr != 0 { b := [4]byte{} @@ -1066,13 +1070,18 @@ func (lhh *LightHouseHandler) handleHostQuery(n *NebulaMeta, fromVpnAddrs []neti } else if n.Details.VpnAddr != nil { queryVpnAddr = protoAddrToNetAddr(n.Details.VpnAddr) useVersion = 2 + } else { + if lhh.l.Level >= logrus.DebugLevel { + lhh.l.WithField("from", fromVpnAddrs).WithField("details", n.Details).Debugln("Dropping malformed HostQuery") + } + return } //TODO: Maybe instead of marshalling into n we marshal into a new `r` to not nuke our current request data found, ln, err := lhh.lh.queryAndPrepMessage(queryVpnAddr, func(c *cache) (int, error) { n = lhh.resetMeta() n.Type = NebulaMeta_HostQueryReply - if useVersion == 1 { + if useVersion == cert.Version1 { if !queryVpnAddr.Is4() { return 0, fmt.Errorf("invalid vpn addr for v1 handleHostQuery") } @@ -1199,6 +1208,7 @@ func (lhh *LightHouseHandler) handleHostQueryReply(n *NebulaMeta, fromVpnAddrs [ } else if n.Details.VpnAddr != nil { certVpnAddr = protoAddrToNetAddr(n.Details.VpnAddr) } + relays := n.Details.GetRelays() am := lhh.lh.unlockedGetRemoteList([]netip.Addr{certVpnAddr}) am.Lock() @@ -1206,22 +1216,6 @@ func (lhh *LightHouseHandler) handleHostQueryReply(n *NebulaMeta, fromVpnAddrs [ am.unlockedSetV4(fromVpnAddrs[0], certVpnAddr, n.Details.V4AddrPorts, lhh.lh.unlockedShouldAddV4) am.unlockedSetV6(fromVpnAddrs[0], certVpnAddr, n.Details.V6AddrPorts, lhh.lh.unlockedShouldAddV6) - - var relays []netip.Addr - if len(n.Details.OldRelayVpnAddrs) > 0 { - b := [4]byte{} - for _, r := range n.Details.OldRelayVpnAddrs { - binary.BigEndian.PutUint32(b[:], r) - relays = append(relays, netip.AddrFrom4(b)) - } - } - - if len(n.Details.RelayVpnAddrs) > 0 { - for _, r := range n.Details.RelayVpnAddrs { - relays = append(relays, protoAddrToNetAddr(r)) - } - } - am.unlockedSetRelay(fromVpnAddrs[0], relays) am.Unlock() @@ -1240,22 +1234,26 @@ func (lhh *LightHouseHandler) handleHostUpdateNotification(n *NebulaMeta, fromVp return } - //Simple check that the host sent this not someone else var detailsVpnAddr netip.Addr - var useVersion cert.Version + useVersion := cert.Version1 if n.Details.OldVpnAddr != 0 { b := [4]byte{} binary.BigEndian.PutUint32(b[:], n.Details.OldVpnAddr) detailsVpnAddr = netip.AddrFrom4(b) - useVersion = 1 + useVersion = cert.Version1 } else if n.Details.VpnAddr != nil { detailsVpnAddr = protoAddrToNetAddr(n.Details.VpnAddr) - useVersion = 2 + useVersion = cert.Version2 + } else { + if lhh.l.Level >= logrus.DebugLevel { + lhh.l.WithField("details", n.Details).Debugf("dropping invalid HostUpdateNotification") + } + return } //todo hosts with only v2 certs cannot provide their ipv6 addr when contacting the lighthouse via v4? //todo why do we care about the vpnAddr in the packet? We know where it came from, right? - + //Simple check that the host sent this not someone else if !slices.Contains(fromVpnAddrs, detailsVpnAddr) { if lhh.l.Level >= logrus.DebugLevel { lhh.l.WithField("vpnAddrs", fromVpnAddrs).WithField("answer", detailsVpnAddr).Debugln("Host sent invalid update") @@ -1263,6 +1261,8 @@ func (lhh *LightHouseHandler) handleHostUpdateNotification(n *NebulaMeta, fromVp return } + relays := n.Details.GetRelays() + lhh.lh.Lock() am := lhh.lh.unlockedGetRemoteList(fromVpnAddrs) am.Lock() @@ -1270,22 +1270,6 @@ func (lhh *LightHouseHandler) handleHostUpdateNotification(n *NebulaMeta, fromVp am.unlockedSetV4(fromVpnAddrs[0], detailsVpnAddr, n.Details.V4AddrPorts, lhh.lh.unlockedShouldAddV4) am.unlockedSetV6(fromVpnAddrs[0], detailsVpnAddr, n.Details.V6AddrPorts, lhh.lh.unlockedShouldAddV6) - - var relays []netip.Addr - if len(n.Details.OldRelayVpnAddrs) > 0 { - b := [4]byte{} - for _, r := range n.Details.OldRelayVpnAddrs { - binary.BigEndian.PutUint32(b[:], r) - relays = append(relays, netip.AddrFrom4(b)) - } - } - - if len(n.Details.RelayVpnAddrs) > 0 { - for _, r := range n.Details.RelayVpnAddrs { - relays = append(relays, protoAddrToNetAddr(r)) - } - } - am.unlockedSetRelay(fromVpnAddrs[0], relays) am.Unlock() @@ -1299,12 +1283,11 @@ func (lhh *LightHouseHandler) handleHostUpdateNotification(n *NebulaMeta, fromVp } vpnAddrB := fromVpnAddrs[0].As4() n.Details.OldVpnAddr = binary.BigEndian.Uint32(vpnAddrB[:]) - } else if useVersion == cert.Version2 { n.Details.VpnAddr = netAddrToProtoAddr(fromVpnAddrs[0]) - } else { - panic("unsupported version") + lhh.l.WithField("useVersion", useVersion).Error("invalid protocol version") + return } ln, err := n.MarshalTo(lhh.pb) @@ -1318,7 +1301,9 @@ func (lhh *LightHouseHandler) handleHostUpdateNotification(n *NebulaMeta, fromVp } func (lhh *LightHouseHandler) handleHostPunchNotification(n *NebulaMeta, fromVpnAddrs []netip.Addr, w EncWriter) { - //TODO: this is kinda stupid + //It's possible the lighthouse is communicating with us using a non primary vpn addr, + //which means we need to compare all fromVpnAddrs against all configured lighthouse vpn addrs. + //maybe one day we'll have a better idea, if it matters. if !lhh.lh.IsAnyLighthouseAddr(fromVpnAddrs) { return } @@ -1426,3 +1411,21 @@ func netAddrToProtoV6AddrPort(addr netip.Addr, port uint16) *V6AddrPort { Port: uint32(port), } } + +func (d *NebulaMetaDetails) GetRelays() []netip.Addr { + var relays []netip.Addr + if len(d.OldRelayVpnAddrs) > 0 { + b := [4]byte{} + for _, r := range d.OldRelayVpnAddrs { + binary.BigEndian.PutUint32(b[:], r) + relays = append(relays, netip.AddrFrom4(b)) + } + } + + if len(d.RelayVpnAddrs) > 0 { + for _, r := range d.RelayVpnAddrs { + relays = append(relays, protoAddrToNetAddr(r)) + } + } + return relays +}