address cert-v2 lighthouse TODOs (#1267)

This commit is contained in:
Jack Doan 2024-11-11 22:14:41 -05:00 committed by GitHub
parent 028d31c011
commit 2b1a59c779
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -336,11 +336,11 @@ func (lh *LightHouse) reload(c *config.C, initial bool) error {
case false: case false:
relaysForMe := []netip.Addr{} relaysForMe := []netip.Addr{}
for _, v := range c.GetStringSlice("relay.relays", nil) { for _, v := range c.GetStringSlice("relay.relays", nil) {
lh.l.WithField("relay", v).Info("Read relay from config")
configRIP, err := netip.ParseAddr(v) 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) relaysForMe = append(relaysForMe, configRIP)
} }
} }
@ -891,6 +891,11 @@ func (lh *LightHouse) SendUpdate() {
} }
if v == cert.Version1 { if v == cert.Version1 {
if v1Update == nil { 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 var relays []uint32
for _, r := range lh.GetRelaysForMe() { for _, r := range lh.GetRelaysForMe() {
if !r.Is4() { if !r.Is4() {
@ -899,7 +904,6 @@ func (lh *LightHouse) SendUpdate() {
b := r.As4() b := r.As4()
relays = append(relays, binary.BigEndian.Uint32(b[:])) relays = append(relays, binary.BigEndian.Uint32(b[:]))
} }
//TODO: assert ipv4
b := lh.myVpnNetworks[0].Addr().As4() b := lh.myVpnNetworks[0].Addr().As4()
msg := NebulaMeta{ msg := NebulaMeta{
Type: NebulaMeta_HostUpdateNotification, Type: NebulaMeta_HostUpdateNotification,
@ -1056,7 +1060,7 @@ func (lhh *LightHouseHandler) handleHostQuery(n *NebulaMeta, fromVpnAddrs []neti
return return
} }
var useVersion cert.Version useVersion := cert.Version1
var queryVpnAddr netip.Addr var queryVpnAddr netip.Addr
if n.Details.OldVpnAddr != 0 { if n.Details.OldVpnAddr != 0 {
b := [4]byte{} b := [4]byte{}
@ -1066,13 +1070,18 @@ func (lhh *LightHouseHandler) handleHostQuery(n *NebulaMeta, fromVpnAddrs []neti
} else if n.Details.VpnAddr != nil { } else if n.Details.VpnAddr != nil {
queryVpnAddr = protoAddrToNetAddr(n.Details.VpnAddr) queryVpnAddr = protoAddrToNetAddr(n.Details.VpnAddr)
useVersion = 2 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 //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) { found, ln, err := lhh.lh.queryAndPrepMessage(queryVpnAddr, func(c *cache) (int, error) {
n = lhh.resetMeta() n = lhh.resetMeta()
n.Type = NebulaMeta_HostQueryReply n.Type = NebulaMeta_HostQueryReply
if useVersion == 1 { if useVersion == cert.Version1 {
if !queryVpnAddr.Is4() { if !queryVpnAddr.Is4() {
return 0, fmt.Errorf("invalid vpn addr for v1 handleHostQuery") 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 { } else if n.Details.VpnAddr != nil {
certVpnAddr = protoAddrToNetAddr(n.Details.VpnAddr) certVpnAddr = protoAddrToNetAddr(n.Details.VpnAddr)
} }
relays := n.Details.GetRelays()
am := lhh.lh.unlockedGetRemoteList([]netip.Addr{certVpnAddr}) am := lhh.lh.unlockedGetRemoteList([]netip.Addr{certVpnAddr})
am.Lock() 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.unlockedSetV4(fromVpnAddrs[0], certVpnAddr, n.Details.V4AddrPorts, lhh.lh.unlockedShouldAddV4)
am.unlockedSetV6(fromVpnAddrs[0], certVpnAddr, n.Details.V6AddrPorts, lhh.lh.unlockedShouldAddV6) 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.unlockedSetRelay(fromVpnAddrs[0], relays)
am.Unlock() am.Unlock()
@ -1240,22 +1234,26 @@ func (lhh *LightHouseHandler) handleHostUpdateNotification(n *NebulaMeta, fromVp
return return
} }
//Simple check that the host sent this not someone else
var detailsVpnAddr netip.Addr var detailsVpnAddr netip.Addr
var useVersion cert.Version useVersion := cert.Version1
if n.Details.OldVpnAddr != 0 { if n.Details.OldVpnAddr != 0 {
b := [4]byte{} b := [4]byte{}
binary.BigEndian.PutUint32(b[:], n.Details.OldVpnAddr) binary.BigEndian.PutUint32(b[:], n.Details.OldVpnAddr)
detailsVpnAddr = netip.AddrFrom4(b) detailsVpnAddr = netip.AddrFrom4(b)
useVersion = 1 useVersion = cert.Version1
} else if n.Details.VpnAddr != nil { } else if n.Details.VpnAddr != nil {
detailsVpnAddr = protoAddrToNetAddr(n.Details.VpnAddr) 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 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? //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 !slices.Contains(fromVpnAddrs, detailsVpnAddr) {
if lhh.l.Level >= logrus.DebugLevel { if lhh.l.Level >= logrus.DebugLevel {
lhh.l.WithField("vpnAddrs", fromVpnAddrs).WithField("answer", detailsVpnAddr).Debugln("Host sent invalid update") 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 return
} }
relays := n.Details.GetRelays()
lhh.lh.Lock() lhh.lh.Lock()
am := lhh.lh.unlockedGetRemoteList(fromVpnAddrs) am := lhh.lh.unlockedGetRemoteList(fromVpnAddrs)
am.Lock() 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.unlockedSetV4(fromVpnAddrs[0], detailsVpnAddr, n.Details.V4AddrPorts, lhh.lh.unlockedShouldAddV4)
am.unlockedSetV6(fromVpnAddrs[0], detailsVpnAddr, n.Details.V6AddrPorts, lhh.lh.unlockedShouldAddV6) 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.unlockedSetRelay(fromVpnAddrs[0], relays)
am.Unlock() am.Unlock()
@ -1299,12 +1283,11 @@ func (lhh *LightHouseHandler) handleHostUpdateNotification(n *NebulaMeta, fromVp
} }
vpnAddrB := fromVpnAddrs[0].As4() vpnAddrB := fromVpnAddrs[0].As4()
n.Details.OldVpnAddr = binary.BigEndian.Uint32(vpnAddrB[:]) n.Details.OldVpnAddr = binary.BigEndian.Uint32(vpnAddrB[:])
} else if useVersion == cert.Version2 { } else if useVersion == cert.Version2 {
n.Details.VpnAddr = netAddrToProtoAddr(fromVpnAddrs[0]) n.Details.VpnAddr = netAddrToProtoAddr(fromVpnAddrs[0])
} else { } else {
panic("unsupported version") lhh.l.WithField("useVersion", useVersion).Error("invalid protocol version")
return
} }
ln, err := n.MarshalTo(lhh.pb) 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) { 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) { if !lhh.lh.IsAnyLighthouseAddr(fromVpnAddrs) {
return return
} }
@ -1426,3 +1411,21 @@ func netAddrToProtoV6AddrPort(addr netip.Addr, port uint16) *V6AddrPort {
Port: uint32(port), 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
}