Skip to content

Commit

Permalink
Support multiple vpn addrs in lighthouse and hostmap
Browse files Browse the repository at this point in the history
  • Loading branch information
nbrownus committed Oct 11, 2024
1 parent c9acce2 commit 554f849
Show file tree
Hide file tree
Showing 8 changed files with 140 additions and 108 deletions.
2 changes: 1 addition & 1 deletion connection_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ func (n *connectionManager) doTrafficCheck(localIndex uint32, p, nb, out []byte,
case deleteTunnel:
if n.hostMap.DeleteHostInfo(hostinfo) {
// Only clearing the lighthouse cache if this is the last hostinfo for this vpn ip in the hostmap
n.intf.lightHouse.DeleteVpnAddr(hostinfo.vpnAddrs[0])
n.intf.lightHouse.DeleteVpnAddrs(hostinfo.vpnAddrs)
}

case closeTunnel:
Expand Down
4 changes: 2 additions & 2 deletions control_tester.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ func (c *Control) WaitForTypeByIndex(toIndex uint32, msgType header.MessageType,
// This is necessary if you did not configure static hosts or are not running a lighthouse
func (c *Control) InjectLightHouseAddr(vpnIp netip.Addr, toAddr netip.AddrPort) {
c.f.lightHouse.Lock()
remoteList := c.f.lightHouse.unlockedGetRemoteList(vpnIp)
remoteList := c.f.lightHouse.unlockedGetRemoteList([]netip.Addr{vpnIp})
remoteList.Lock()
defer remoteList.Unlock()
c.f.lightHouse.Unlock()
Expand All @@ -65,7 +65,7 @@ func (c *Control) InjectLightHouseAddr(vpnIp netip.Addr, toAddr netip.AddrPort)
// This is necessary to inform an initiator of possible relays for communicating with a responder
func (c *Control) InjectRelays(vpnIp netip.Addr, relayVpnIps []netip.Addr) {
c.f.lightHouse.Lock()
remoteList := c.f.lightHouse.unlockedGetRemoteList(vpnIp)
remoteList := c.f.lightHouse.unlockedGetRemoteList([]netip.Addr{vpnIp})
remoteList.Lock()
defer remoteList.Unlock()
c.f.lightHouse.Unlock()
Expand Down
19 changes: 11 additions & 8 deletions handshake_ix.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package nebula

import (
"net/netip"
"slices"
"time"

"github.com/flynn/noise"
Expand Down Expand Up @@ -230,7 +231,7 @@ func ixHandshakeStage1(f *Interface, addr netip.AddrPort, via *ViaSender, packet
ci.dKey = NewNebulaCipherState(dKey)
ci.eKey = NewNebulaCipherState(eKey)

hostinfo.remotes = f.lightHouse.QueryCache(vpnAddrs[0])
hostinfo.remotes = f.lightHouse.QueryCache(vpnAddrs)
hostinfo.SetRemote(addr)
hostinfo.CreateRemoteCIDR(remoteCert.Certificate)

Expand Down Expand Up @@ -436,9 +437,13 @@ func ixHandshakeStage2(f *Interface, addr netip.AddrPort, via *ViaSender, hh *Ha
fingerprint := remoteCert.Fingerprint
issuer := remoteCert.Certificate.Issuer()

vpnAddrs := make([]netip.Addr, len(vpnNetworks))
for i, n := range vpnNetworks {
vpnAddrs[i] = n.Addr()
}

// Ensure the right host responded
//TODO: this is a horribly broken test
if vpnNetworks[0].Addr() != hostinfo.vpnAddrs[0] {
if !slices.Contains(vpnAddrs, hostinfo.vpnAddrs[0]) {
f.l.WithField("intendedVpnAddrs", hostinfo.vpnAddrs).WithField("haveVpnNetworks", vpnNetworks).
WithField("udpAddr", addr).WithField("certName", certName).
WithField("handshake", m{"stage": 2, "style": "ix_psk0"}).
Expand All @@ -455,7 +460,7 @@ func ixHandshakeStage2(f *Interface, addr netip.AddrPort, via *ViaSender, hh *Ha
newHH.hostinfo.remotes.BlockRemote(addr)

// Get the correct remote list for the host we did handshake with
hostinfo.remotes = f.lightHouse.QueryCache(vpnNetworks[0].Addr())
hostinfo.remotes = f.lightHouse.QueryCache(vpnAddrs)

f.l.WithField("blockedUdpAddrs", newHH.hostinfo.remotes.CopyBlockedRemotes()).WithField("vpnNetworks", vpnNetworks).
WithField("remotes", newHH.hostinfo.remotes.CopyAddrs(f.hostMap.GetPreferredRanges())).
Expand All @@ -466,10 +471,7 @@ func ixHandshakeStage2(f *Interface, addr netip.AddrPort, via *ViaSender, hh *Ha
hh.packetStore = []*cachedPacket{}

// Finally, put the correct vpn addrs in the host info, tell them to close the tunnel, and return true to tear down
hostinfo.vpnAddrs = nil
for _, n := range vpnNetworks {
hostinfo.vpnAddrs = append(hostinfo.vpnAddrs, n.Addr())
}
hostinfo.vpnAddrs = vpnAddrs
f.sendCloseTunnel(hostinfo)
})

Expand All @@ -492,6 +494,7 @@ func ixHandshakeStage2(f *Interface, addr netip.AddrPort, via *ViaSender, hh *Ha

hostinfo.remoteIndexId = hs.Details.ResponderIndex
hostinfo.lastHandshakeTime = hs.Details.Time
hostinfo.vpnAddrs = vpnAddrs

// Store their cert and our symmetric keys
ci.peerCert = remoteCert
Expand Down
2 changes: 1 addition & 1 deletion handshake_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ func (hm *HandshakeManager) handleOutbound(vpnIp netip.Addr, lighthouseTriggered
// NB ^ This comment doesn't jive. It's how the thing gets initialized.
// It's the common path. Should it update every time, in case a future LH query/queries give us more info?
if hostinfo.remotes == nil {
hostinfo.remotes = hm.lightHouse.QueryCache(vpnIp)
hostinfo.remotes = hm.lightHouse.QueryCache([]netip.Addr{vpnIp})
}

remotes := hostinfo.remotes.CopyAddrs(hm.mainHostMap.GetPreferredRanges())
Expand Down
18 changes: 15 additions & 3 deletions hostmap.go
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,7 @@ func (hm *HostMap) DeleteHostInfo(hostinfo *HostInfo) bool {
hm.Lock()
// If we have a previous or next hostinfo then we are not the last one for this vpn ip
final := (hostinfo.next == nil && hostinfo.prev == nil)
hm.unlockedDeleteHostInfo(hostinfo)
hm.unlockedDeleteHostInfo(hostinfo, false)
hm.Unlock()

return final
Expand Down Expand Up @@ -345,7 +345,7 @@ func (hm *HostMap) unlockedMakePrimary(hostinfo *HostInfo) {
hostinfo.prev = nil
}

func (hm *HostMap) unlockedDeleteHostInfo(hostinfo *HostInfo) {
func (hm *HostMap) unlockedDeleteHostInfo(hostinfo *HostInfo, dontRecurse bool) {
primary, ok := hm.Hosts[hostinfo.vpnAddrs[0]]
if ok && primary == hostinfo {
// The vpnIp pointer points to the same hostinfo as the local index id, we can remove it
Expand Down Expand Up @@ -399,6 +399,18 @@ func (hm *HostMap) unlockedDeleteHostInfo(hostinfo *HostInfo) {
for _, localRelayIdx := range hostinfo.relayState.CopyRelayForIdxs() {
delete(hm.Relays, localRelayIdx)
}

if !dontRecurse {
for _, addr := range hostinfo.vpnAddrs {
h := hm.Hosts[addr]
for h != nil {
if h == hostinfo {
hm.unlockedDeleteHostInfo(h, true)
}
h = h.next
}
}
}
}

func (hm *HostMap) QueryIndex(index uint32) *HostInfo {
Expand Down Expand Up @@ -501,7 +513,7 @@ func (hm *HostMap) unlockedAddHostInfo(hostinfo *HostInfo, f *Interface) {
check := hostinfo
for check != nil {
if i > MaxHostInfosPerVpnIp {
hm.unlockedDeleteHostInfo(check)
hm.unlockedDeleteHostInfo(check, false)
}
check = check.next
i++
Expand Down
Loading

0 comments on commit 554f849

Please sign in to comment.