Handle discovered Endpoints in topology to enable NAT 2 NAT

This commit is contained in:
Julien Viard de Galbert 2021-04-16 19:00:57 +02:00
parent 2b2437bf7c
commit babace573e
3 changed files with 273 additions and 220 deletions

View File

@ -389,6 +389,7 @@ func (m *Mesh) handleLocal(n *Node) {
PersistentKeepalive: n.PersistentKeepalive, PersistentKeepalive: n.PersistentKeepalive,
Subnet: n.Subnet, Subnet: n.Subnet,
WireGuardIP: m.wireGuardIP, WireGuardIP: m.wireGuardIP,
DiscoveredEndpoints: n.DiscoveredEndpoints,
} }
if !nodesAreEqual(n, local) { if !nodesAreEqual(n, local) {
level.Debug(m.logger).Log("msg", "local node differs from backend") level.Debug(m.logger).Log("msg", "local node differs from backend")
@ -469,7 +470,7 @@ func (m *Mesh) applyTopology() {
return return
} }
oldConf := wireguard.Parse(oldConfRaw) oldConf := wireguard.Parse(oldConfRaw)
natEndpoints := updateNATEndpoints(nodes, peers, oldConf, m.logger) natEndpoints := discoverNATEndpoints(nodes, peers, oldConf, m.logger)
nodes[m.hostname].DiscoveredEndpoints = natEndpoints nodes[m.hostname].DiscoveredEndpoints = natEndpoints
m.nodes[m.hostname].DiscoveredEndpoints = natEndpoints m.nodes[m.hostname].DiscoveredEndpoints = natEndpoints
t, err := NewTopology(nodes, peers, m.granularity, m.hostname, nodes[m.hostname].Endpoint.Port, m.priv, m.subnet, nodes[m.hostname].PersistentKeepalive) t, err := NewTopology(nodes, peers, m.granularity, m.hostname, nodes[m.hostname].Endpoint.Port, m.priv, m.subnet, nodes[m.hostname].PersistentKeepalive)
@ -792,9 +793,8 @@ func linkByIndex(index int) (netlink.Link, error) {
return link, nil return link, nil
} }
// updateNATEndpoints ensures that nodes and peers behind NAT update // discoverNATEndpoints uses the node's WireGuard configuration to returns a list of the most recently discovered endpoints for all nodes and peers behind NAT so that they can roam.
// their endpoints from the WireGuard configuration so they can roam. func discoverNATEndpoints(nodes map[string]*Node, peers map[string]*Peer, conf *wireguard.Conf, logger log.Logger) map[string]*wireguard.Endpoint {
func updateNATEndpoints(nodes map[string]*Node, peers map[string]*Peer, conf *wireguard.Conf, logger log.Logger) map[string]*wireguard.Endpoint {
natEndpoints := make(map[string]*wireguard.Endpoint) natEndpoints := make(map[string]*wireguard.Endpoint)
keys := make(map[string]*wireguard.Peer) keys := make(map[string]*wireguard.Peer)
for i := range conf.Peers { for i := range conf.Peers {
@ -808,7 +808,6 @@ func updateNATEndpoints(nodes map[string]*Node, peers map[string]*Peer, conf *wi
if !n.Endpoint.Equal(peer.Endpoint) { if !n.Endpoint.Equal(peer.Endpoint) {
natEndpoints[string(n.Key)] = peer.Endpoint natEndpoints[string(n.Key)] = peer.Endpoint
} }
n.Endpoint = peer.Endpoint
} }
} }
for _, p := range peers { for _, p := range peers {
@ -816,7 +815,6 @@ func updateNATEndpoints(nodes map[string]*Node, peers map[string]*Peer, conf *wi
if !p.Endpoint.Equal(peer.Endpoint) { if !p.Endpoint.Equal(peer.Endpoint) {
natEndpoints[string(p.PublicKey)] = peer.Endpoint natEndpoints[string(p.PublicKey)] = peer.Endpoint
} }
p.Endpoint = peer.Endpoint
} }
} }
level.Debug(logger).Log("msg", "Discovered WireGuard NAT Endpoints", "DiscoveredEndpoints", natEndpoints) level.Debug(logger).Log("msg", "Discovered WireGuard NAT Endpoints", "DiscoveredEndpoints", natEndpoints)

View File

@ -55,12 +55,15 @@ type Topology struct {
// the IP is the 0th address in the subnet, i.e. the CIDR // the IP is the 0th address in the subnet, i.e. the CIDR
// is equal to the Kilo subnet. // is equal to the Kilo subnet.
wireGuardCIDR *net.IPNet wireGuardCIDR *net.IPNet
// discoveredEndpoints is the updated map of valid discovered Endpoints
discoveredEndpoints map[string]*wireguard.Endpoint
} }
type segment struct { type segment struct {
allowedIPs []*net.IPNet allowedIPs []*net.IPNet
endpoint *wireguard.Endpoint endpoint *wireguard.Endpoint
key []byte key []byte
persistentKeepalive int
// Location is the logical location of this segment. // Location is the logical location of this segment.
location string location string
@ -106,7 +109,7 @@ func NewTopology(nodes map[string]*Node, peers map[string]*Peer, granularity Gra
localLocation = nodeLocationPrefix + hostname localLocation = nodeLocationPrefix + hostname
} }
t := Topology{key: key, port: port, hostname: hostname, location: localLocation, persistentKeepalive: persistentKeepalive, privateIP: nodes[hostname].InternalIP, subnet: nodes[hostname].Subnet, wireGuardCIDR: subnet} t := Topology{key: key, port: port, hostname: hostname, location: localLocation, persistentKeepalive: persistentKeepalive, privateIP: nodes[hostname].InternalIP, subnet: nodes[hostname].Subnet, wireGuardCIDR: subnet, discoveredEndpoints: make(map[string]*wireguard.Endpoint)}
for location := range topoMap { for location := range topoMap {
// Sort the location so the result is stable. // Sort the location so the result is stable.
sort.Slice(topoMap[location], func(i, j int) bool { sort.Slice(topoMap[location], func(i, j int) bool {
@ -134,14 +137,15 @@ func NewTopology(nodes map[string]*Node, peers map[string]*Peer, granularity Gra
hostnames = append(hostnames, node.Name) hostnames = append(hostnames, node.Name)
} }
t.segments = append(t.segments, &segment{ t.segments = append(t.segments, &segment{
allowedIPs: allowedIPs, allowedIPs: allowedIPs,
endpoint: topoMap[location][leader].Endpoint, endpoint: topoMap[location][leader].Endpoint,
key: topoMap[location][leader].Key, key: topoMap[location][leader].Key,
location: location, persistentKeepalive: topoMap[location][leader].PersistentKeepalive,
cidrs: cidrs, location: location,
hostnames: hostnames, cidrs: cidrs,
leader: leader, hostnames: hostnames,
privateIPs: privateIPs, leader: leader,
privateIPs: privateIPs,
}) })
} }
// Sort the Topology segments so the result is stable. // Sort the Topology segments so the result is stable.
@ -159,6 +163,10 @@ func NewTopology(nodes map[string]*Node, peers map[string]*Peer, granularity Gra
// We need to defensively deduplicate peer allowed IPs. If two peers claim the same IP, // We need to defensively deduplicate peer allowed IPs. If two peers claim the same IP,
// the WireGuard configuration could flap, causing the interface to churn. // the WireGuard configuration could flap, causing the interface to churn.
t.peers = deduplicatePeerIPs(t.peers) t.peers = deduplicatePeerIPs(t.peers)
// Copy the host node DiscoveredEndpoints in the topology as a starting point.
for key := range nodes[hostname].DiscoveredEndpoints {
t.discoveredEndpoints[key] = nodes[hostname].DiscoveredEndpoints[key]
}
// Allocate IPs to the segment leaders in a stable, coordination-free manner. // Allocate IPs to the segment leaders in a stable, coordination-free manner.
a := newAllocator(*subnet) a := newAllocator(*subnet)
for _, segment := range t.segments { for _, segment := range t.segments {
@ -171,11 +179,33 @@ func NewTopology(nodes map[string]*Node, peers map[string]*Peer, granularity Gra
if t.leader && segment.location == t.location { if t.leader && segment.location == t.location {
t.wireGuardCIDR = &net.IPNet{IP: ipNet.IP, Mask: subnet.Mask} t.wireGuardCIDR = &net.IPNet{IP: ipNet.IP, Mask: subnet.Mask}
} }
// Now that the topology is ordered, update the discoveredEndpoints map
// add new ones by going through the ordered topology: segments, nodes
for _, node := range topoMap[segment.location] {
for key := range node.DiscoveredEndpoints {
if _, ok := t.discoveredEndpoints[key]; !ok {
t.discoveredEndpoints[key] = node.DiscoveredEndpoints[key]
}
}
}
} }
return &t, nil return &t, nil
} }
func (t *Topology) updateEndpoint(endpoint *wireguard.Endpoint, key []byte, persistentKeepalive int) *wireguard.Endpoint {
// Do not update non-nat peers
if persistentKeepalive == 0 {
return endpoint
}
e, ok := t.discoveredEndpoints[string(key)]
if ok {
return e
}
return endpoint
}
// Conf generates a WireGuard configuration file for a given Topology. // Conf generates a WireGuard configuration file for a given Topology.
func (t *Topology) Conf() *wireguard.Conf { func (t *Topology) Conf() *wireguard.Conf {
c := &wireguard.Conf{ c := &wireguard.Conf{
@ -190,7 +220,7 @@ func (t *Topology) Conf() *wireguard.Conf {
} }
peer := &wireguard.Peer{ peer := &wireguard.Peer{
AllowedIPs: s.allowedIPs, AllowedIPs: s.allowedIPs,
Endpoint: s.endpoint, Endpoint: t.updateEndpoint(s.endpoint, s.key, s.persistentKeepalive),
PersistentKeepalive: t.persistentKeepalive, PersistentKeepalive: t.persistentKeepalive,
PublicKey: s.key, PublicKey: s.key,
} }
@ -199,7 +229,7 @@ func (t *Topology) Conf() *wireguard.Conf {
for _, p := range t.peers { for _, p := range t.peers {
peer := &wireguard.Peer{ peer := &wireguard.Peer{
AllowedIPs: p.AllowedIPs, AllowedIPs: p.AllowedIPs,
Endpoint: p.Endpoint, Endpoint: t.updateEndpoint(p.Endpoint, p.PublicKey, p.PersistentKeepalive),
PersistentKeepalive: t.persistentKeepalive, PersistentKeepalive: t.persistentKeepalive,
PresharedKey: p.PresharedKey, PresharedKey: p.PresharedKey,
PublicKey: p.PublicKey, PublicKey: p.PublicKey,

View File

@ -126,34 +126,37 @@ func TestNewTopology(t *testing.T) {
wireGuardCIDR: &net.IPNet{IP: w1, Mask: net.CIDRMask(16, 32)}, wireGuardCIDR: &net.IPNet{IP: w1, Mask: net.CIDRMask(16, 32)},
segments: []*segment{ segments: []*segment{
{ {
allowedIPs: []*net.IPNet{nodes["a"].Subnet, nodes["a"].InternalIP, {IP: w1, Mask: net.CIDRMask(32, 32)}}, allowedIPs: []*net.IPNet{nodes["a"].Subnet, nodes["a"].InternalIP, {IP: w1, Mask: net.CIDRMask(32, 32)}},
endpoint: nodes["a"].Endpoint, endpoint: nodes["a"].Endpoint,
key: nodes["a"].Key, key: nodes["a"].Key,
location: logicalLocationPrefix + nodes["a"].Location, persistentKeepalive: nodes["a"].PersistentKeepalive,
cidrs: []*net.IPNet{nodes["a"].Subnet}, location: logicalLocationPrefix + nodes["a"].Location,
hostnames: []string{"a"}, cidrs: []*net.IPNet{nodes["a"].Subnet},
privateIPs: []net.IP{nodes["a"].InternalIP.IP}, hostnames: []string{"a"},
wireGuardIP: w1, privateIPs: []net.IP{nodes["a"].InternalIP.IP},
wireGuardIP: w1,
}, },
{ {
allowedIPs: []*net.IPNet{nodes["b"].Subnet, nodes["b"].InternalIP, nodes["c"].Subnet, nodes["c"].InternalIP, {IP: w2, Mask: net.CIDRMask(32, 32)}}, allowedIPs: []*net.IPNet{nodes["b"].Subnet, nodes["b"].InternalIP, nodes["c"].Subnet, nodes["c"].InternalIP, {IP: w2, Mask: net.CIDRMask(32, 32)}},
endpoint: nodes["b"].Endpoint, endpoint: nodes["b"].Endpoint,
key: nodes["b"].Key, key: nodes["b"].Key,
location: logicalLocationPrefix + nodes["b"].Location, persistentKeepalive: nodes["b"].PersistentKeepalive,
cidrs: []*net.IPNet{nodes["b"].Subnet, nodes["c"].Subnet}, location: logicalLocationPrefix + nodes["b"].Location,
hostnames: []string{"b", "c"}, cidrs: []*net.IPNet{nodes["b"].Subnet, nodes["c"].Subnet},
privateIPs: []net.IP{nodes["b"].InternalIP.IP, nodes["c"].InternalIP.IP}, hostnames: []string{"b", "c"},
wireGuardIP: w2, privateIPs: []net.IP{nodes["b"].InternalIP.IP, nodes["c"].InternalIP.IP},
wireGuardIP: w2,
}, },
{ {
allowedIPs: []*net.IPNet{nodes["d"].Subnet, {IP: w3, Mask: net.CIDRMask(32, 32)}}, allowedIPs: []*net.IPNet{nodes["d"].Subnet, {IP: w3, Mask: net.CIDRMask(32, 32)}},
endpoint: nodes["d"].Endpoint, endpoint: nodes["d"].Endpoint,
key: nodes["d"].Key, key: nodes["d"].Key,
location: nodeLocationPrefix + nodes["d"].Name, persistentKeepalive: nodes["d"].PersistentKeepalive,
cidrs: []*net.IPNet{nodes["d"].Subnet}, location: nodeLocationPrefix + nodes["d"].Name,
hostnames: []string{"d"}, cidrs: []*net.IPNet{nodes["d"].Subnet},
privateIPs: nil, hostnames: []string{"d"},
wireGuardIP: w3, privateIPs: nil,
wireGuardIP: w3,
}, },
}, },
peers: []*Peer{peers["a"], peers["b"]}, peers: []*Peer{peers["a"], peers["b"]},
@ -172,34 +175,37 @@ func TestNewTopology(t *testing.T) {
wireGuardCIDR: &net.IPNet{IP: w2, Mask: net.CIDRMask(16, 32)}, wireGuardCIDR: &net.IPNet{IP: w2, Mask: net.CIDRMask(16, 32)},
segments: []*segment{ segments: []*segment{
{ {
allowedIPs: []*net.IPNet{nodes["a"].Subnet, nodes["a"].InternalIP, {IP: w1, Mask: net.CIDRMask(32, 32)}}, allowedIPs: []*net.IPNet{nodes["a"].Subnet, nodes["a"].InternalIP, {IP: w1, Mask: net.CIDRMask(32, 32)}},
endpoint: nodes["a"].Endpoint, endpoint: nodes["a"].Endpoint,
key: nodes["a"].Key, key: nodes["a"].Key,
location: logicalLocationPrefix + nodes["a"].Location, persistentKeepalive: nodes["a"].PersistentKeepalive,
cidrs: []*net.IPNet{nodes["a"].Subnet}, location: logicalLocationPrefix + nodes["a"].Location,
hostnames: []string{"a"}, cidrs: []*net.IPNet{nodes["a"].Subnet},
privateIPs: []net.IP{nodes["a"].InternalIP.IP}, hostnames: []string{"a"},
wireGuardIP: w1, privateIPs: []net.IP{nodes["a"].InternalIP.IP},
wireGuardIP: w1,
}, },
{ {
allowedIPs: []*net.IPNet{nodes["b"].Subnet, nodes["b"].InternalIP, nodes["c"].Subnet, nodes["c"].InternalIP, {IP: w2, Mask: net.CIDRMask(32, 32)}}, allowedIPs: []*net.IPNet{nodes["b"].Subnet, nodes["b"].InternalIP, nodes["c"].Subnet, nodes["c"].InternalIP, {IP: w2, Mask: net.CIDRMask(32, 32)}},
endpoint: nodes["b"].Endpoint, endpoint: nodes["b"].Endpoint,
key: nodes["b"].Key, key: nodes["b"].Key,
location: logicalLocationPrefix + nodes["b"].Location, persistentKeepalive: nodes["b"].PersistentKeepalive,
cidrs: []*net.IPNet{nodes["b"].Subnet, nodes["c"].Subnet}, location: logicalLocationPrefix + nodes["b"].Location,
hostnames: []string{"b", "c"}, cidrs: []*net.IPNet{nodes["b"].Subnet, nodes["c"].Subnet},
privateIPs: []net.IP{nodes["b"].InternalIP.IP, nodes["c"].InternalIP.IP}, hostnames: []string{"b", "c"},
wireGuardIP: w2, privateIPs: []net.IP{nodes["b"].InternalIP.IP, nodes["c"].InternalIP.IP},
wireGuardIP: w2,
}, },
{ {
allowedIPs: []*net.IPNet{nodes["d"].Subnet, {IP: w3, Mask: net.CIDRMask(32, 32)}}, allowedIPs: []*net.IPNet{nodes["d"].Subnet, {IP: w3, Mask: net.CIDRMask(32, 32)}},
endpoint: nodes["d"].Endpoint, endpoint: nodes["d"].Endpoint,
key: nodes["d"].Key, key: nodes["d"].Key,
location: nodeLocationPrefix + nodes["d"].Name, persistentKeepalive: nodes["d"].PersistentKeepalive,
cidrs: []*net.IPNet{nodes["d"].Subnet}, location: nodeLocationPrefix + nodes["d"].Name,
hostnames: []string{"d"}, cidrs: []*net.IPNet{nodes["d"].Subnet},
privateIPs: nil, hostnames: []string{"d"},
wireGuardIP: w3, privateIPs: nil,
wireGuardIP: w3,
}, },
}, },
peers: []*Peer{peers["a"], peers["b"]}, peers: []*Peer{peers["a"], peers["b"]},
@ -218,34 +224,37 @@ func TestNewTopology(t *testing.T) {
wireGuardCIDR: DefaultKiloSubnet, wireGuardCIDR: DefaultKiloSubnet,
segments: []*segment{ segments: []*segment{
{ {
allowedIPs: []*net.IPNet{nodes["a"].Subnet, nodes["a"].InternalIP, {IP: w1, Mask: net.CIDRMask(32, 32)}}, allowedIPs: []*net.IPNet{nodes["a"].Subnet, nodes["a"].InternalIP, {IP: w1, Mask: net.CIDRMask(32, 32)}},
endpoint: nodes["a"].Endpoint, endpoint: nodes["a"].Endpoint,
key: nodes["a"].Key, key: nodes["a"].Key,
location: logicalLocationPrefix + nodes["a"].Location, persistentKeepalive: nodes["a"].PersistentKeepalive,
cidrs: []*net.IPNet{nodes["a"].Subnet}, location: logicalLocationPrefix + nodes["a"].Location,
hostnames: []string{"a"}, cidrs: []*net.IPNet{nodes["a"].Subnet},
privateIPs: []net.IP{nodes["a"].InternalIP.IP}, hostnames: []string{"a"},
wireGuardIP: w1, privateIPs: []net.IP{nodes["a"].InternalIP.IP},
wireGuardIP: w1,
}, },
{ {
allowedIPs: []*net.IPNet{nodes["b"].Subnet, nodes["b"].InternalIP, nodes["c"].Subnet, nodes["c"].InternalIP, {IP: w2, Mask: net.CIDRMask(32, 32)}}, allowedIPs: []*net.IPNet{nodes["b"].Subnet, nodes["b"].InternalIP, nodes["c"].Subnet, nodes["c"].InternalIP, {IP: w2, Mask: net.CIDRMask(32, 32)}},
endpoint: nodes["b"].Endpoint, endpoint: nodes["b"].Endpoint,
key: nodes["b"].Key, key: nodes["b"].Key,
location: logicalLocationPrefix + nodes["b"].Location, persistentKeepalive: nodes["b"].PersistentKeepalive,
cidrs: []*net.IPNet{nodes["b"].Subnet, nodes["c"].Subnet}, location: logicalLocationPrefix + nodes["b"].Location,
hostnames: []string{"b", "c"}, cidrs: []*net.IPNet{nodes["b"].Subnet, nodes["c"].Subnet},
privateIPs: []net.IP{nodes["b"].InternalIP.IP, nodes["c"].InternalIP.IP}, hostnames: []string{"b", "c"},
wireGuardIP: w2, privateIPs: []net.IP{nodes["b"].InternalIP.IP, nodes["c"].InternalIP.IP},
wireGuardIP: w2,
}, },
{ {
allowedIPs: []*net.IPNet{nodes["d"].Subnet, {IP: w3, Mask: net.CIDRMask(32, 32)}}, allowedIPs: []*net.IPNet{nodes["d"].Subnet, {IP: w3, Mask: net.CIDRMask(32, 32)}},
endpoint: nodes["d"].Endpoint, endpoint: nodes["d"].Endpoint,
key: nodes["d"].Key, key: nodes["d"].Key,
location: nodeLocationPrefix + nodes["d"].Name, persistentKeepalive: nodes["d"].PersistentKeepalive,
cidrs: []*net.IPNet{nodes["d"].Subnet}, location: nodeLocationPrefix + nodes["d"].Name,
hostnames: []string{"d"}, cidrs: []*net.IPNet{nodes["d"].Subnet},
privateIPs: nil, hostnames: []string{"d"},
wireGuardIP: w3, privateIPs: nil,
wireGuardIP: w3,
}, },
}, },
peers: []*Peer{peers["a"], peers["b"]}, peers: []*Peer{peers["a"], peers["b"]},
@ -264,44 +273,48 @@ func TestNewTopology(t *testing.T) {
wireGuardCIDR: &net.IPNet{IP: w1, Mask: net.CIDRMask(16, 32)}, wireGuardCIDR: &net.IPNet{IP: w1, Mask: net.CIDRMask(16, 32)},
segments: []*segment{ segments: []*segment{
{ {
allowedIPs: []*net.IPNet{nodes["a"].Subnet, nodes["a"].InternalIP, {IP: w1, Mask: net.CIDRMask(32, 32)}}, allowedIPs: []*net.IPNet{nodes["a"].Subnet, nodes["a"].InternalIP, {IP: w1, Mask: net.CIDRMask(32, 32)}},
endpoint: nodes["a"].Endpoint, endpoint: nodes["a"].Endpoint,
key: nodes["a"].Key, key: nodes["a"].Key,
location: nodeLocationPrefix + nodes["a"].Name, persistentKeepalive: nodes["a"].PersistentKeepalive,
cidrs: []*net.IPNet{nodes["a"].Subnet}, location: nodeLocationPrefix + nodes["a"].Name,
hostnames: []string{"a"}, cidrs: []*net.IPNet{nodes["a"].Subnet},
privateIPs: []net.IP{nodes["a"].InternalIP.IP}, hostnames: []string{"a"},
wireGuardIP: w1, privateIPs: []net.IP{nodes["a"].InternalIP.IP},
wireGuardIP: w1,
}, },
{ {
allowedIPs: []*net.IPNet{nodes["b"].Subnet, nodes["b"].InternalIP, {IP: w2, Mask: net.CIDRMask(32, 32)}}, allowedIPs: []*net.IPNet{nodes["b"].Subnet, nodes["b"].InternalIP, {IP: w2, Mask: net.CIDRMask(32, 32)}},
endpoint: nodes["b"].Endpoint, endpoint: nodes["b"].Endpoint,
key: nodes["b"].Key, key: nodes["b"].Key,
location: nodeLocationPrefix + nodes["b"].Name, persistentKeepalive: nodes["b"].PersistentKeepalive,
cidrs: []*net.IPNet{nodes["b"].Subnet}, location: nodeLocationPrefix + nodes["b"].Name,
hostnames: []string{"b"}, cidrs: []*net.IPNet{nodes["b"].Subnet},
privateIPs: []net.IP{nodes["b"].InternalIP.IP}, hostnames: []string{"b"},
wireGuardIP: w2, privateIPs: []net.IP{nodes["b"].InternalIP.IP},
wireGuardIP: w2,
}, },
{ {
allowedIPs: []*net.IPNet{nodes["c"].Subnet, nodes["c"].InternalIP, {IP: w3, Mask: net.CIDRMask(32, 32)}}, allowedIPs: []*net.IPNet{nodes["c"].Subnet, nodes["c"].InternalIP, {IP: w3, Mask: net.CIDRMask(32, 32)}},
endpoint: nodes["c"].Endpoint, endpoint: nodes["c"].Endpoint,
key: nodes["c"].Key, key: nodes["c"].Key,
location: nodeLocationPrefix + nodes["c"].Name, persistentKeepalive: nodes["c"].PersistentKeepalive,
cidrs: []*net.IPNet{nodes["c"].Subnet}, location: nodeLocationPrefix + nodes["c"].Name,
hostnames: []string{"c"}, cidrs: []*net.IPNet{nodes["c"].Subnet},
privateIPs: []net.IP{nodes["c"].InternalIP.IP}, hostnames: []string{"c"},
wireGuardIP: w3, privateIPs: []net.IP{nodes["c"].InternalIP.IP},
wireGuardIP: w3,
}, },
{ {
allowedIPs: []*net.IPNet{nodes["d"].Subnet, {IP: w4, Mask: net.CIDRMask(32, 32)}}, allowedIPs: []*net.IPNet{nodes["d"].Subnet, {IP: w4, Mask: net.CIDRMask(32, 32)}},
endpoint: nodes["d"].Endpoint, endpoint: nodes["d"].Endpoint,
key: nodes["d"].Key, key: nodes["d"].Key,
location: nodeLocationPrefix + nodes["d"].Name, persistentKeepalive: nodes["d"].PersistentKeepalive,
cidrs: []*net.IPNet{nodes["d"].Subnet}, location: nodeLocationPrefix + nodes["d"].Name,
hostnames: []string{"d"}, cidrs: []*net.IPNet{nodes["d"].Subnet},
privateIPs: nil, hostnames: []string{"d"},
wireGuardIP: w4, privateIPs: nil,
wireGuardIP: w4,
}, },
}, },
peers: []*Peer{peers["a"], peers["b"]}, peers: []*Peer{peers["a"], peers["b"]},
@ -320,44 +333,48 @@ func TestNewTopology(t *testing.T) {
wireGuardCIDR: &net.IPNet{IP: w2, Mask: net.CIDRMask(16, 32)}, wireGuardCIDR: &net.IPNet{IP: w2, Mask: net.CIDRMask(16, 32)},
segments: []*segment{ segments: []*segment{
{ {
allowedIPs: []*net.IPNet{nodes["a"].Subnet, nodes["a"].InternalIP, {IP: w1, Mask: net.CIDRMask(32, 32)}}, allowedIPs: []*net.IPNet{nodes["a"].Subnet, nodes["a"].InternalIP, {IP: w1, Mask: net.CIDRMask(32, 32)}},
endpoint: nodes["a"].Endpoint, endpoint: nodes["a"].Endpoint,
key: nodes["a"].Key, key: nodes["a"].Key,
location: nodeLocationPrefix + nodes["a"].Name, persistentKeepalive: nodes["a"].PersistentKeepalive,
cidrs: []*net.IPNet{nodes["a"].Subnet}, location: nodeLocationPrefix + nodes["a"].Name,
hostnames: []string{"a"}, cidrs: []*net.IPNet{nodes["a"].Subnet},
privateIPs: []net.IP{nodes["a"].InternalIP.IP}, hostnames: []string{"a"},
wireGuardIP: w1, privateIPs: []net.IP{nodes["a"].InternalIP.IP},
wireGuardIP: w1,
}, },
{ {
allowedIPs: []*net.IPNet{nodes["b"].Subnet, nodes["b"].InternalIP, {IP: w2, Mask: net.CIDRMask(32, 32)}}, allowedIPs: []*net.IPNet{nodes["b"].Subnet, nodes["b"].InternalIP, {IP: w2, Mask: net.CIDRMask(32, 32)}},
endpoint: nodes["b"].Endpoint, endpoint: nodes["b"].Endpoint,
key: nodes["b"].Key, key: nodes["b"].Key,
location: nodeLocationPrefix + nodes["b"].Name, persistentKeepalive: nodes["b"].PersistentKeepalive,
cidrs: []*net.IPNet{nodes["b"].Subnet}, location: nodeLocationPrefix + nodes["b"].Name,
hostnames: []string{"b"}, cidrs: []*net.IPNet{nodes["b"].Subnet},
privateIPs: []net.IP{nodes["b"].InternalIP.IP}, hostnames: []string{"b"},
wireGuardIP: w2, privateIPs: []net.IP{nodes["b"].InternalIP.IP},
wireGuardIP: w2,
}, },
{ {
allowedIPs: []*net.IPNet{nodes["c"].Subnet, nodes["c"].InternalIP, {IP: w3, Mask: net.CIDRMask(32, 32)}}, allowedIPs: []*net.IPNet{nodes["c"].Subnet, nodes["c"].InternalIP, {IP: w3, Mask: net.CIDRMask(32, 32)}},
endpoint: nodes["c"].Endpoint, endpoint: nodes["c"].Endpoint,
key: nodes["c"].Key, key: nodes["c"].Key,
location: nodeLocationPrefix + nodes["c"].Name, persistentKeepalive: nodes["c"].PersistentKeepalive,
cidrs: []*net.IPNet{nodes["c"].Subnet}, location: nodeLocationPrefix + nodes["c"].Name,
hostnames: []string{"c"}, cidrs: []*net.IPNet{nodes["c"].Subnet},
privateIPs: []net.IP{nodes["c"].InternalIP.IP}, hostnames: []string{"c"},
wireGuardIP: w3, privateIPs: []net.IP{nodes["c"].InternalIP.IP},
wireGuardIP: w3,
}, },
{ {
allowedIPs: []*net.IPNet{nodes["d"].Subnet, {IP: w4, Mask: net.CIDRMask(32, 32)}}, allowedIPs: []*net.IPNet{nodes["d"].Subnet, {IP: w4, Mask: net.CIDRMask(32, 32)}},
endpoint: nodes["d"].Endpoint, endpoint: nodes["d"].Endpoint,
key: nodes["d"].Key, key: nodes["d"].Key,
location: nodeLocationPrefix + nodes["d"].Name, persistentKeepalive: nodes["d"].PersistentKeepalive,
cidrs: []*net.IPNet{nodes["d"].Subnet}, location: nodeLocationPrefix + nodes["d"].Name,
hostnames: []string{"d"}, cidrs: []*net.IPNet{nodes["d"].Subnet},
privateIPs: nil, hostnames: []string{"d"},
wireGuardIP: w4, privateIPs: nil,
wireGuardIP: w4,
}, },
}, },
peers: []*Peer{peers["a"], peers["b"]}, peers: []*Peer{peers["a"], peers["b"]},
@ -376,44 +393,48 @@ func TestNewTopology(t *testing.T) {
wireGuardCIDR: &net.IPNet{IP: w3, Mask: net.CIDRMask(16, 32)}, wireGuardCIDR: &net.IPNet{IP: w3, Mask: net.CIDRMask(16, 32)},
segments: []*segment{ segments: []*segment{
{ {
allowedIPs: []*net.IPNet{nodes["a"].Subnet, nodes["a"].InternalIP, {IP: w1, Mask: net.CIDRMask(32, 32)}}, allowedIPs: []*net.IPNet{nodes["a"].Subnet, nodes["a"].InternalIP, {IP: w1, Mask: net.CIDRMask(32, 32)}},
endpoint: nodes["a"].Endpoint, endpoint: nodes["a"].Endpoint,
key: nodes["a"].Key, key: nodes["a"].Key,
location: nodeLocationPrefix + nodes["a"].Name, persistentKeepalive: nodes["a"].PersistentKeepalive,
cidrs: []*net.IPNet{nodes["a"].Subnet}, location: nodeLocationPrefix + nodes["a"].Name,
hostnames: []string{"a"}, cidrs: []*net.IPNet{nodes["a"].Subnet},
privateIPs: []net.IP{nodes["a"].InternalIP.IP}, hostnames: []string{"a"},
wireGuardIP: w1, privateIPs: []net.IP{nodes["a"].InternalIP.IP},
wireGuardIP: w1,
}, },
{ {
allowedIPs: []*net.IPNet{nodes["b"].Subnet, nodes["b"].InternalIP, {IP: w2, Mask: net.CIDRMask(32, 32)}}, allowedIPs: []*net.IPNet{nodes["b"].Subnet, nodes["b"].InternalIP, {IP: w2, Mask: net.CIDRMask(32, 32)}},
endpoint: nodes["b"].Endpoint, endpoint: nodes["b"].Endpoint,
key: nodes["b"].Key, key: nodes["b"].Key,
location: nodeLocationPrefix + nodes["b"].Name, persistentKeepalive: nodes["b"].PersistentKeepalive,
cidrs: []*net.IPNet{nodes["b"].Subnet}, location: nodeLocationPrefix + nodes["b"].Name,
hostnames: []string{"b"}, cidrs: []*net.IPNet{nodes["b"].Subnet},
privateIPs: []net.IP{nodes["b"].InternalIP.IP}, hostnames: []string{"b"},
wireGuardIP: w2, privateIPs: []net.IP{nodes["b"].InternalIP.IP},
wireGuardIP: w2,
}, },
{ {
allowedIPs: []*net.IPNet{nodes["c"].Subnet, nodes["c"].InternalIP, {IP: w3, Mask: net.CIDRMask(32, 32)}}, allowedIPs: []*net.IPNet{nodes["c"].Subnet, nodes["c"].InternalIP, {IP: w3, Mask: net.CIDRMask(32, 32)}},
endpoint: nodes["c"].Endpoint, endpoint: nodes["c"].Endpoint,
key: nodes["c"].Key, key: nodes["c"].Key,
location: nodeLocationPrefix + nodes["c"].Name, persistentKeepalive: nodes["c"].PersistentKeepalive,
cidrs: []*net.IPNet{nodes["c"].Subnet}, location: nodeLocationPrefix + nodes["c"].Name,
hostnames: []string{"c"}, cidrs: []*net.IPNet{nodes["c"].Subnet},
privateIPs: []net.IP{nodes["c"].InternalIP.IP}, hostnames: []string{"c"},
wireGuardIP: w3, privateIPs: []net.IP{nodes["c"].InternalIP.IP},
wireGuardIP: w3,
}, },
{ {
allowedIPs: []*net.IPNet{nodes["d"].Subnet, {IP: w4, Mask: net.CIDRMask(32, 32)}}, allowedIPs: []*net.IPNet{nodes["d"].Subnet, {IP: w4, Mask: net.CIDRMask(32, 32)}},
endpoint: nodes["d"].Endpoint, endpoint: nodes["d"].Endpoint,
key: nodes["d"].Key, key: nodes["d"].Key,
location: nodeLocationPrefix + nodes["d"].Name, persistentKeepalive: nodes["d"].PersistentKeepalive,
cidrs: []*net.IPNet{nodes["d"].Subnet}, location: nodeLocationPrefix + nodes["d"].Name,
hostnames: []string{"d"}, cidrs: []*net.IPNet{nodes["d"].Subnet},
privateIPs: nil, hostnames: []string{"d"},
wireGuardIP: w4, privateIPs: nil,
wireGuardIP: w4,
}, },
}, },
peers: []*Peer{peers["a"], peers["b"]}, peers: []*Peer{peers["a"], peers["b"]},
@ -432,44 +453,48 @@ func TestNewTopology(t *testing.T) {
wireGuardCIDR: &net.IPNet{IP: w4, Mask: net.CIDRMask(16, 32)}, wireGuardCIDR: &net.IPNet{IP: w4, Mask: net.CIDRMask(16, 32)},
segments: []*segment{ segments: []*segment{
{ {
allowedIPs: []*net.IPNet{nodes["a"].Subnet, nodes["a"].InternalIP, {IP: w1, Mask: net.CIDRMask(32, 32)}}, allowedIPs: []*net.IPNet{nodes["a"].Subnet, nodes["a"].InternalIP, {IP: w1, Mask: net.CIDRMask(32, 32)}},
endpoint: nodes["a"].Endpoint, endpoint: nodes["a"].Endpoint,
key: nodes["a"].Key, key: nodes["a"].Key,
location: nodeLocationPrefix + nodes["a"].Name, persistentKeepalive: nodes["a"].PersistentKeepalive,
cidrs: []*net.IPNet{nodes["a"].Subnet}, location: nodeLocationPrefix + nodes["a"].Name,
hostnames: []string{"a"}, cidrs: []*net.IPNet{nodes["a"].Subnet},
privateIPs: []net.IP{nodes["a"].InternalIP.IP}, hostnames: []string{"a"},
wireGuardIP: w1, privateIPs: []net.IP{nodes["a"].InternalIP.IP},
wireGuardIP: w1,
}, },
{ {
allowedIPs: []*net.IPNet{nodes["b"].Subnet, nodes["b"].InternalIP, {IP: w2, Mask: net.CIDRMask(32, 32)}}, allowedIPs: []*net.IPNet{nodes["b"].Subnet, nodes["b"].InternalIP, {IP: w2, Mask: net.CIDRMask(32, 32)}},
endpoint: nodes["b"].Endpoint, endpoint: nodes["b"].Endpoint,
key: nodes["b"].Key, key: nodes["b"].Key,
location: nodeLocationPrefix + nodes["b"].Name, persistentKeepalive: nodes["b"].PersistentKeepalive,
cidrs: []*net.IPNet{nodes["b"].Subnet}, location: nodeLocationPrefix + nodes["b"].Name,
hostnames: []string{"b"}, cidrs: []*net.IPNet{nodes["b"].Subnet},
privateIPs: []net.IP{nodes["b"].InternalIP.IP}, hostnames: []string{"b"},
wireGuardIP: w2, privateIPs: []net.IP{nodes["b"].InternalIP.IP},
wireGuardIP: w2,
}, },
{ {
allowedIPs: []*net.IPNet{nodes["c"].Subnet, nodes["c"].InternalIP, {IP: w3, Mask: net.CIDRMask(32, 32)}}, allowedIPs: []*net.IPNet{nodes["c"].Subnet, nodes["c"].InternalIP, {IP: w3, Mask: net.CIDRMask(32, 32)}},
endpoint: nodes["c"].Endpoint, endpoint: nodes["c"].Endpoint,
key: nodes["c"].Key, key: nodes["c"].Key,
location: nodeLocationPrefix + nodes["c"].Name, persistentKeepalive: nodes["c"].PersistentKeepalive,
cidrs: []*net.IPNet{nodes["c"].Subnet}, location: nodeLocationPrefix + nodes["c"].Name,
hostnames: []string{"c"}, cidrs: []*net.IPNet{nodes["c"].Subnet},
privateIPs: []net.IP{nodes["c"].InternalIP.IP}, hostnames: []string{"c"},
wireGuardIP: w3, privateIPs: []net.IP{nodes["c"].InternalIP.IP},
wireGuardIP: w3,
}, },
{ {
allowedIPs: []*net.IPNet{nodes["d"].Subnet, {IP: w4, Mask: net.CIDRMask(32, 32)}}, allowedIPs: []*net.IPNet{nodes["d"].Subnet, {IP: w4, Mask: net.CIDRMask(32, 32)}},
endpoint: nodes["d"].Endpoint, endpoint: nodes["d"].Endpoint,
key: nodes["d"].Key, key: nodes["d"].Key,
location: nodeLocationPrefix + nodes["d"].Name, persistentKeepalive: nodes["d"].PersistentKeepalive,
cidrs: []*net.IPNet{nodes["d"].Subnet}, location: nodeLocationPrefix + nodes["d"].Name,
hostnames: []string{"d"}, cidrs: []*net.IPNet{nodes["d"].Subnet},
privateIPs: nil, hostnames: []string{"d"},
wireGuardIP: w4, privateIPs: nil,
wireGuardIP: w4,
}, },
}, },
peers: []*Peer{peers["a"], peers["b"]}, peers: []*Peer{peers["a"], peers["b"]},