pkg/mesh,pkg/wireguard: allow DNS name endpoints
This commit allows DNS names to be used when specifying the endpoint for a node in the WireGuard mesh. This is useful in many scenarios, in particular when operating an IoT device whose public IP is dynamic. This change allows the administrator to use a dynamic DNS name in the node's endpoint. One of the side-effects of this change is that the WireGuard port can now be specified individually for each node in the mesh, if the administrator wishes to do so. *Note*: this commit introduces a breaking change; the `force-external-ip` node annotation has been removed; its functionality has been ported over to the `force-endpoint` annotation. This annotation is documented in the annotations.md file. The expected content of this annotation is no longer a CIDR but rather a host:port. The host can be either a DNS name or an IP. Signed-off-by: Lucas Servén Marín <lserven@gmail.com>
This commit is contained in:
@@ -17,8 +17,10 @@ package mesh
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"strings"
|
||||
|
||||
"github.com/awalterschulze/gographviz"
|
||||
"github.com/squat/kilo/pkg/wireguard"
|
||||
)
|
||||
|
||||
// Dot generates a Graphviz graph of the Topology in DOT fomat.
|
||||
@@ -60,13 +62,15 @@ func (t *Topology) Dot() (string, error) {
|
||||
return "", fmt.Errorf("failed to add node to subgraph")
|
||||
}
|
||||
var wg net.IP
|
||||
var endpoint *wireguard.Endpoint
|
||||
if j == s.leader {
|
||||
wg = s.wireGuardIP
|
||||
endpoint = s.endpoint
|
||||
if err := g.Nodes.Lookup[graphEscape(s.hostnames[j])].Attrs.Add(string(gographviz.Rank), "1"); err != nil {
|
||||
return "", fmt.Errorf("failed to add rank to node")
|
||||
}
|
||||
}
|
||||
if err := g.Nodes.Lookup[graphEscape(s.hostnames[j])].Attrs.Add(string(gographviz.Label), nodeLabel(s.location, s.hostnames[j], s.cidrs[j], s.privateIPs[j], wg)); err != nil {
|
||||
if err := g.Nodes.Lookup[graphEscape(s.hostnames[j])].Attrs.Add(string(gographviz.Label), nodeLabel(s.location, s.hostnames[j], s.cidrs[j], s.privateIPs[j], wg, endpoint)); err != nil {
|
||||
return "", fmt.Errorf("failed to add label to node")
|
||||
}
|
||||
}
|
||||
@@ -146,14 +150,22 @@ func subGraphName(name string) string {
|
||||
return graphEscape(fmt.Sprintf("cluster_location_%s", name))
|
||||
}
|
||||
|
||||
func nodeLabel(location, name string, cidr *net.IPNet, priv, wgIP net.IP) string {
|
||||
var wg string
|
||||
if wgIP != nil {
|
||||
wg = wgIP.String()
|
||||
func nodeLabel(location, name string, cidr *net.IPNet, priv, wgIP net.IP, endpoint *wireguard.Endpoint) string {
|
||||
label := []string{
|
||||
location,
|
||||
name,
|
||||
cidr.String(),
|
||||
priv.String(),
|
||||
}
|
||||
return graphEscape(fmt.Sprintf("%s\n%s\n%s\n%s\n%s", location, name, cidr.String(), priv.String(), wg))
|
||||
if wgIP != nil {
|
||||
label = append(label, wgIP.String())
|
||||
}
|
||||
if endpoint != nil {
|
||||
label = append(label, endpoint.String())
|
||||
}
|
||||
return graphEscape(strings.Join(label, "\n"))
|
||||
}
|
||||
|
||||
func peerLabel(peer *Peer) string {
|
||||
return graphEscape(fmt.Sprintf("%s\n%s\n", peer.Name, peer.Endpoint.IP.String()))
|
||||
return graphEscape(fmt.Sprintf("%s\n%s\n", peer.Name, peer.Endpoint.String()))
|
||||
}
|
||||
|
@@ -72,7 +72,7 @@ func getIP(hostname string, ignoreIfaces ...int) (*net.IPNet, *net.IPNet, error)
|
||||
continue
|
||||
}
|
||||
ip.Mask = mask
|
||||
if isPublic(ip) {
|
||||
if isPublic(ip.IP) {
|
||||
hostPub = append(hostPub, ip)
|
||||
continue
|
||||
}
|
||||
@@ -97,7 +97,7 @@ func getIP(hostname string, ignoreIfaces ...int) (*net.IPNet, *net.IPNet, error)
|
||||
if isLocal(ip.IP) {
|
||||
continue
|
||||
}
|
||||
if isPublic(ip) {
|
||||
if isPublic(ip.IP) {
|
||||
defaultPub = append(defaultPub, ip)
|
||||
continue
|
||||
}
|
||||
@@ -118,7 +118,7 @@ func getIP(hostname string, ignoreIfaces ...int) (*net.IPNet, *net.IPNet, error)
|
||||
if isLocal(ip.IP) {
|
||||
continue
|
||||
}
|
||||
if isPublic(ip) {
|
||||
if isPublic(ip.IP) {
|
||||
interfacePub = append(interfacePub, ip)
|
||||
continue
|
||||
}
|
||||
@@ -206,9 +206,9 @@ func isLocal(ip net.IP) bool {
|
||||
return ip.IsLoopback() || ip.IsLinkLocalMulticast() || ip.IsLinkLocalUnicast()
|
||||
}
|
||||
|
||||
func isPublic(ip *net.IPNet) bool {
|
||||
func isPublic(ip net.IP) bool {
|
||||
// Check RFC 1918 addresses.
|
||||
if ip4 := ip.IP.To4(); ip4 != nil {
|
||||
if ip4 := ip.To4(); ip4 != nil {
|
||||
switch true {
|
||||
// Check for 10.0.0.0/8.
|
||||
case ip4[0] == 10:
|
||||
@@ -224,10 +224,10 @@ func isPublic(ip *net.IPNet) bool {
|
||||
}
|
||||
}
|
||||
// Check RFC 4193 addresses.
|
||||
if len(ip.IP) == net.IPv6len {
|
||||
if len(ip) == net.IPv6len {
|
||||
switch true {
|
||||
// Check for fd00::/8.
|
||||
case ip.IP[0] == 0xfd && ip.IP[1] == 0x00:
|
||||
case ip[0] == 0xfd && ip[1] == 0x00:
|
||||
return false
|
||||
default:
|
||||
return true
|
||||
|
109
pkg/mesh/mesh.go
109
pkg/mesh/mesh.go
@@ -71,7 +71,7 @@ const (
|
||||
|
||||
// Node represents a node in the network.
|
||||
type Node struct {
|
||||
ExternalIP *net.IPNet
|
||||
Endpoint *wireguard.Endpoint
|
||||
Key []byte
|
||||
InternalIP *net.IPNet
|
||||
// LastSeen is a Unix time for the last time
|
||||
@@ -90,7 +90,7 @@ type Node struct {
|
||||
// Ready indicates whether or not the node is ready.
|
||||
func (n *Node) Ready() bool {
|
||||
// Nodes that are not leaders will not have WireGuardIPs, so it is not required.
|
||||
return n != nil && n.ExternalIP != nil && n.Key != nil && n.InternalIP != nil && n.Subnet != nil && time.Now().Unix()-n.LastSeen < int64(resyncPeriod)*2/int64(time.Second)
|
||||
return n != nil && n.Endpoint != nil && !(n.Endpoint.IP == nil && n.Endpoint.DNS == "") && n.Endpoint.Port != 0 && n.Key != nil && n.InternalIP != nil && n.Subnet != nil && time.Now().Unix()-n.LastSeen < int64(resyncPeriod)*2/int64(time.Second)
|
||||
}
|
||||
|
||||
// Peer represents a peer in the network.
|
||||
@@ -100,6 +100,10 @@ type Peer struct {
|
||||
}
|
||||
|
||||
// Ready indicates whether or not the peer is ready.
|
||||
// Peers can have empty endpoints because they may not have an
|
||||
// IP, for example if they are behind a NAT, and thus
|
||||
// will not declare their endpoint and instead allow it to be
|
||||
// discovered.
|
||||
func (p *Peer) Ready() bool {
|
||||
return p != nil && p.AllowedIPs != nil && len(p.AllowedIPs) != 0 && p.PublicKey != nil
|
||||
}
|
||||
@@ -186,7 +190,6 @@ type Mesh struct {
|
||||
priv []byte
|
||||
privIface int
|
||||
pub []byte
|
||||
pubIface int
|
||||
stop chan struct{}
|
||||
subnet *net.IPNet
|
||||
table *route.Table
|
||||
@@ -238,11 +241,6 @@ func New(backend Backend, enc encapsulation.Encapsulator, granularity Granularit
|
||||
return nil, fmt.Errorf("failed to find interface for private IP: %v", err)
|
||||
}
|
||||
privIface := ifaces[0].Index
|
||||
ifaces, err = interfacesForIP(publicIP)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to find interface for public IP: %v", err)
|
||||
}
|
||||
pubIface := ifaces[0].Index
|
||||
kiloIface, _, err := wireguard.New(iface)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create WireGuard interface: %v", err)
|
||||
@@ -276,7 +274,6 @@ func New(backend Backend, enc encapsulation.Encapsulator, granularity Granularit
|
||||
priv: private,
|
||||
privIface: privIface,
|
||||
pub: public,
|
||||
pubIface: pubIface,
|
||||
local: local,
|
||||
stop: make(chan struct{}),
|
||||
subnet: subnet,
|
||||
@@ -511,8 +508,8 @@ func (m *Mesh) checkIn() {
|
||||
|
||||
func (m *Mesh) handleLocal(n *Node) {
|
||||
// Allow the IPs to be overridden.
|
||||
if n.ExternalIP == nil {
|
||||
n.ExternalIP = m.externalIP
|
||||
if n.Endpoint == nil || (n.Endpoint.DNS == "" && n.Endpoint.IP == nil) {
|
||||
n.Endpoint = &wireguard.Endpoint{DNSOrIP: wireguard.DNSOrIP{IP: m.externalIP.IP}, Port: m.port}
|
||||
}
|
||||
if n.InternalIP == nil {
|
||||
n.InternalIP = m.internalIP
|
||||
@@ -521,7 +518,7 @@ func (m *Mesh) handleLocal(n *Node) {
|
||||
// Take leader, location, and subnet from the argument, as these
|
||||
// are not determined by kilo.
|
||||
local := &Node{
|
||||
ExternalIP: n.ExternalIP,
|
||||
Endpoint: n.Endpoint,
|
||||
Key: m.pub,
|
||||
InternalIP: n.InternalIP,
|
||||
LastSeen: time.Now().Unix(),
|
||||
@@ -559,6 +556,12 @@ func (m *Mesh) applyTopology() {
|
||||
m.reconcileCounter.Inc()
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
// If we can't resolve an endpoint, then fail and retry later.
|
||||
if err := m.resolveEndpoints(); err != nil {
|
||||
level.Error(m.logger).Log("error", err)
|
||||
m.errorCounter.WithLabelValues("apply").Inc()
|
||||
return
|
||||
}
|
||||
// Ensure only ready nodes are considered.
|
||||
nodes := make(map[string]*Node)
|
||||
var readyNodes float64
|
||||
@@ -585,7 +588,7 @@ func (m *Mesh) applyTopology() {
|
||||
if nodes[m.hostname] == nil {
|
||||
return
|
||||
}
|
||||
t, err := NewTopology(nodes, peers, m.granularity, m.hostname, m.port, m.priv, m.subnet)
|
||||
t, err := NewTopology(nodes, peers, m.granularity, m.hostname, nodes[m.hostname].Endpoint.Port, m.priv, m.subnet)
|
||||
if err != nil {
|
||||
level.Error(m.logger).Log("error", err)
|
||||
m.errorCounter.WithLabelValues("apply").Inc()
|
||||
@@ -598,6 +601,7 @@ func (m *Mesh) applyTopology() {
|
||||
if err != nil {
|
||||
level.Error(m.logger).Log("error", err)
|
||||
m.errorCounter.WithLabelValues("apply").Inc()
|
||||
return
|
||||
}
|
||||
if err := ioutil.WriteFile(ConfPath, buf, 0600); err != nil {
|
||||
level.Error(m.logger).Log("error", err)
|
||||
@@ -733,6 +737,57 @@ func (m *Mesh) cleanUp() {
|
||||
}
|
||||
}
|
||||
|
||||
func (m *Mesh) resolveEndpoints() error {
|
||||
for k := range m.nodes {
|
||||
// Skip unready nodes, since they will not be used
|
||||
// in the topology anyways.
|
||||
if !m.nodes[k].Ready() {
|
||||
continue
|
||||
}
|
||||
// If the node is ready, then the endpoint is not nil
|
||||
// but it may not have a DNS name.
|
||||
if m.nodes[k].Endpoint.DNS == "" {
|
||||
continue
|
||||
}
|
||||
if err := resolveEndpoint(m.nodes[k].Endpoint); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
for k := range m.peers {
|
||||
// Skip unready peers, since they will not be used
|
||||
// in the topology anyways.
|
||||
if !m.peers[k].Ready() {
|
||||
continue
|
||||
}
|
||||
// If the peer is ready, then the endpoint is not nil
|
||||
// but it may not have a DNS name.
|
||||
if m.peers[k].Endpoint.DNS == "" {
|
||||
continue
|
||||
}
|
||||
if err := resolveEndpoint(m.peers[k].Endpoint); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func resolveEndpoint(endpoint *wireguard.Endpoint) error {
|
||||
ips, err := net.LookupIP(endpoint.DNS)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to look up DNS name %q: %v", endpoint.DNS, err)
|
||||
}
|
||||
nets := make([]*net.IPNet, len(ips), len(ips))
|
||||
for i := range ips {
|
||||
nets[i] = oneAddressCIDR(ips[i])
|
||||
}
|
||||
sortIPs(nets)
|
||||
if len(nets) == 0 {
|
||||
return fmt.Errorf("did not find any addresses for DNS name %q", endpoint.DNS)
|
||||
}
|
||||
endpoint.IP = nets[0].IP
|
||||
return nil
|
||||
}
|
||||
|
||||
func isSelf(hostname string, node *Node) bool {
|
||||
return node != nil && node.Name == hostname
|
||||
}
|
||||
@@ -744,10 +799,26 @@ func nodesAreEqual(a, b *Node) bool {
|
||||
if a == b {
|
||||
return true
|
||||
}
|
||||
if !(a.Endpoint != nil) == (b.Endpoint != nil) {
|
||||
return false
|
||||
}
|
||||
if a.Endpoint != nil {
|
||||
if a.Endpoint.Port != b.Endpoint.Port {
|
||||
return false
|
||||
}
|
||||
// Check the DNS name first since this package
|
||||
// is doing the DNS resolution.
|
||||
if a.Endpoint.DNS != b.Endpoint.DNS {
|
||||
return false
|
||||
}
|
||||
if a.Endpoint.DNS == "" && !a.Endpoint.IP.Equal(b.Endpoint.IP) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
// Ignore LastSeen when comparing equality we want to check if the nodes are
|
||||
// equivalent. However, we do want to check if LastSeen has transitioned
|
||||
// between valid and invalid.
|
||||
return ipNetsEqual(a.ExternalIP, b.ExternalIP) && string(a.Key) == string(b.Key) && ipNetsEqual(a.WireGuardIP, b.WireGuardIP) && ipNetsEqual(a.InternalIP, b.InternalIP) && a.Leader == b.Leader && a.Location == b.Location && a.Name == b.Name && subnetsEqual(a.Subnet, b.Subnet) && a.Ready() == b.Ready()
|
||||
return string(a.Key) == string(b.Key) && ipNetsEqual(a.WireGuardIP, b.WireGuardIP) && ipNetsEqual(a.InternalIP, b.InternalIP) && a.Leader == b.Leader && a.Location == b.Location && a.Name == b.Name && subnetsEqual(a.Subnet, b.Subnet) && a.Ready() == b.Ready()
|
||||
}
|
||||
|
||||
func peersAreEqual(a, b *Peer) bool {
|
||||
@@ -761,7 +832,15 @@ func peersAreEqual(a, b *Peer) bool {
|
||||
return false
|
||||
}
|
||||
if a.Endpoint != nil {
|
||||
if !a.Endpoint.IP.Equal(b.Endpoint.IP) || a.Endpoint.Port != b.Endpoint.Port {
|
||||
if a.Endpoint.Port != b.Endpoint.Port {
|
||||
return false
|
||||
}
|
||||
// Check the DNS name first since this package
|
||||
// is doing the DNS resolution.
|
||||
if a.Endpoint.DNS != b.Endpoint.DNS {
|
||||
return false
|
||||
}
|
||||
if a.Endpoint.DNS == "" && !a.Endpoint.IP.Equal(b.Endpoint.IP) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
@@ -18,6 +18,8 @@ import (
|
||||
"net"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/squat/kilo/pkg/wireguard"
|
||||
)
|
||||
|
||||
func TestReady(t *testing.T) {
|
||||
@@ -39,7 +41,7 @@ func TestReady(t *testing.T) {
|
||||
ready: false,
|
||||
},
|
||||
{
|
||||
name: "empty external IP",
|
||||
name: "empty endpoint",
|
||||
node: &Node{
|
||||
InternalIP: internalIP,
|
||||
Key: []byte{},
|
||||
@@ -47,19 +49,39 @@ func TestReady(t *testing.T) {
|
||||
},
|
||||
ready: false,
|
||||
},
|
||||
{
|
||||
name: "empty endpoint IP",
|
||||
node: &Node{
|
||||
Endpoint: &wireguard.Endpoint{DNSOrIP: wireguard.DNSOrIP{}, Port: DefaultKiloPort},
|
||||
InternalIP: internalIP,
|
||||
Key: []byte{},
|
||||
Subnet: &net.IPNet{IP: net.ParseIP("10.2.0.0"), Mask: net.CIDRMask(16, 32)},
|
||||
},
|
||||
ready: false,
|
||||
},
|
||||
{
|
||||
name: "empty endpoint port",
|
||||
node: &Node{
|
||||
Endpoint: &wireguard.Endpoint{DNSOrIP: wireguard.DNSOrIP{IP: externalIP.IP}},
|
||||
InternalIP: internalIP,
|
||||
Key: []byte{},
|
||||
Subnet: &net.IPNet{IP: net.ParseIP("10.2.0.0"), Mask: net.CIDRMask(16, 32)},
|
||||
},
|
||||
ready: false,
|
||||
},
|
||||
{
|
||||
name: "empty internal IP",
|
||||
node: &Node{
|
||||
ExternalIP: externalIP,
|
||||
Key: []byte{},
|
||||
Subnet: &net.IPNet{IP: net.ParseIP("10.2.0.0"), Mask: net.CIDRMask(16, 32)},
|
||||
Endpoint: &wireguard.Endpoint{DNSOrIP: wireguard.DNSOrIP{IP: externalIP.IP}, Port: DefaultKiloPort},
|
||||
Key: []byte{},
|
||||
Subnet: &net.IPNet{IP: net.ParseIP("10.2.0.0"), Mask: net.CIDRMask(16, 32)},
|
||||
},
|
||||
ready: false,
|
||||
},
|
||||
{
|
||||
name: "empty key",
|
||||
node: &Node{
|
||||
ExternalIP: externalIP,
|
||||
Endpoint: &wireguard.Endpoint{DNSOrIP: wireguard.DNSOrIP{IP: externalIP.IP}, Port: DefaultKiloPort},
|
||||
InternalIP: internalIP,
|
||||
Subnet: &net.IPNet{IP: net.ParseIP("10.2.0.0"), Mask: net.CIDRMask(16, 32)},
|
||||
},
|
||||
@@ -68,7 +90,7 @@ func TestReady(t *testing.T) {
|
||||
{
|
||||
name: "empty subnet",
|
||||
node: &Node{
|
||||
ExternalIP: externalIP,
|
||||
Endpoint: &wireguard.Endpoint{DNSOrIP: wireguard.DNSOrIP{IP: externalIP.IP}, Port: DefaultKiloPort},
|
||||
InternalIP: internalIP,
|
||||
Key: []byte{},
|
||||
},
|
||||
@@ -77,7 +99,7 @@ func TestReady(t *testing.T) {
|
||||
{
|
||||
name: "valid",
|
||||
node: &Node{
|
||||
ExternalIP: externalIP,
|
||||
Endpoint: &wireguard.Endpoint{DNSOrIP: wireguard.DNSOrIP{IP: externalIP.IP}, Port: DefaultKiloPort},
|
||||
InternalIP: internalIP,
|
||||
Key: []byte{},
|
||||
LastSeen: time.Now().Unix(),
|
||||
|
@@ -54,7 +54,7 @@ type Topology struct {
|
||||
|
||||
type segment struct {
|
||||
allowedIPs []*net.IPNet
|
||||
endpoint net.IP
|
||||
endpoint *wireguard.Endpoint
|
||||
key []byte
|
||||
// Location is the logical location of this segment.
|
||||
location string
|
||||
@@ -122,7 +122,7 @@ func NewTopology(nodes map[string]*Node, peers map[string]*Peer, granularity Gra
|
||||
}
|
||||
t.segments = append(t.segments, &segment{
|
||||
allowedIPs: allowedIPs,
|
||||
endpoint: topoMap[location][leader].ExternalIP.IP,
|
||||
endpoint: topoMap[location][leader].Endpoint,
|
||||
key: topoMap[location][leader].Key,
|
||||
location: location,
|
||||
cidrs: cidrs,
|
||||
@@ -175,7 +175,7 @@ func (t *Topology) Routes(kiloIfaceName string, kiloIface, privIface, tunlIface
|
||||
var gw net.IP
|
||||
for _, segment := range t.segments {
|
||||
if segment.location == t.location {
|
||||
gw = enc.Gw(segment.endpoint, segment.privateIPs[segment.leader], segment.cidrs[segment.leader])
|
||||
gw = enc.Gw(segment.endpoint.IP, segment.privateIPs[segment.leader], segment.cidrs[segment.leader])
|
||||
break
|
||||
}
|
||||
}
|
||||
@@ -316,7 +316,7 @@ func (t *Topology) Routes(kiloIfaceName string, kiloIface, privIface, tunlIface
|
||||
// equals the external IP. This means that the node
|
||||
// is only accessible through an external IP and we
|
||||
// cannot encapsulate traffic to an IP through the IP.
|
||||
if segment.privateIPs[i].Equal(segment.endpoint) {
|
||||
if segment.privateIPs[i].Equal(segment.endpoint.IP) {
|
||||
continue
|
||||
}
|
||||
// Add routes to the private IPs of nodes in other segments.
|
||||
@@ -364,11 +364,8 @@ func (t *Topology) Conf() *wireguard.Conf {
|
||||
continue
|
||||
}
|
||||
peer := &wireguard.Peer{
|
||||
AllowedIPs: s.allowedIPs,
|
||||
Endpoint: &wireguard.Endpoint{
|
||||
IP: s.endpoint,
|
||||
Port: uint32(t.port),
|
||||
},
|
||||
AllowedIPs: s.allowedIPs,
|
||||
Endpoint: s.endpoint,
|
||||
PublicKey: s.key,
|
||||
PersistentKeepalive: s.persistentKeepalive,
|
||||
}
|
||||
@@ -394,11 +391,8 @@ func (t *Topology) AsPeer() *wireguard.Peer {
|
||||
continue
|
||||
}
|
||||
return &wireguard.Peer{
|
||||
AllowedIPs: s.allowedIPs,
|
||||
Endpoint: &wireguard.Endpoint{
|
||||
IP: s.endpoint,
|
||||
Port: uint32(t.port),
|
||||
},
|
||||
AllowedIPs: s.allowedIPs,
|
||||
Endpoint: s.endpoint,
|
||||
PersistentKeepalive: s.persistentKeepalive,
|
||||
PublicKey: s.key,
|
||||
}
|
||||
@@ -411,11 +405,8 @@ func (t *Topology) PeerConf(name string) *wireguard.Conf {
|
||||
c := &wireguard.Conf{}
|
||||
for _, s := range t.segments {
|
||||
peer := &wireguard.Peer{
|
||||
AllowedIPs: s.allowedIPs,
|
||||
Endpoint: &wireguard.Endpoint{
|
||||
IP: s.endpoint,
|
||||
Port: uint32(t.port),
|
||||
},
|
||||
AllowedIPs: s.allowedIPs,
|
||||
Endpoint: s.endpoint,
|
||||
PersistentKeepalive: s.persistentKeepalive,
|
||||
PublicKey: s.key,
|
||||
}
|
||||
@@ -450,12 +441,13 @@ func findLeader(nodes []*Node) int {
|
||||
var leaders, public []int
|
||||
for i := range nodes {
|
||||
if nodes[i].Leader {
|
||||
if isPublic(nodes[i].ExternalIP) {
|
||||
if isPublic(nodes[i].Endpoint.IP) {
|
||||
return i
|
||||
}
|
||||
leaders = append(leaders, i)
|
||||
|
||||
}
|
||||
if isPublic(nodes[i].ExternalIP) {
|
||||
if isPublic(nodes[i].Endpoint.IP) {
|
||||
public = append(public, i)
|
||||
}
|
||||
}
|
||||
|
@@ -40,7 +40,7 @@ func setup(t *testing.T) (map[string]*Node, map[string]*Peer, []byte, uint32) {
|
||||
nodes := map[string]*Node{
|
||||
"a": {
|
||||
Name: "a",
|
||||
ExternalIP: e1,
|
||||
Endpoint: &wireguard.Endpoint{DNSOrIP: wireguard.DNSOrIP{IP: e1.IP}, Port: DefaultKiloPort},
|
||||
InternalIP: i1,
|
||||
Location: "1",
|
||||
Subnet: &net.IPNet{IP: net.ParseIP("10.2.1.0"), Mask: net.CIDRMask(24, 32)},
|
||||
@@ -49,7 +49,7 @@ func setup(t *testing.T) (map[string]*Node, map[string]*Peer, []byte, uint32) {
|
||||
},
|
||||
"b": {
|
||||
Name: "b",
|
||||
ExternalIP: e2,
|
||||
Endpoint: &wireguard.Endpoint{DNSOrIP: wireguard.DNSOrIP{IP: e2.IP}, Port: DefaultKiloPort},
|
||||
InternalIP: i1,
|
||||
Location: "2",
|
||||
Subnet: &net.IPNet{IP: net.ParseIP("10.2.2.0"), Mask: net.CIDRMask(24, 32)},
|
||||
@@ -57,7 +57,7 @@ func setup(t *testing.T) (map[string]*Node, map[string]*Peer, []byte, uint32) {
|
||||
},
|
||||
"c": {
|
||||
Name: "c",
|
||||
ExternalIP: e3,
|
||||
Endpoint: &wireguard.Endpoint{DNSOrIP: wireguard.DNSOrIP{IP: e3.IP}, Port: DefaultKiloPort},
|
||||
InternalIP: i2,
|
||||
// Same location a node b.
|
||||
Location: "2",
|
||||
@@ -83,8 +83,8 @@ func setup(t *testing.T) (map[string]*Node, map[string]*Peer, []byte, uint32) {
|
||||
{IP: net.ParseIP("10.5.0.3"), Mask: net.CIDRMask(24, 32)},
|
||||
},
|
||||
Endpoint: &wireguard.Endpoint{
|
||||
IP: net.ParseIP("192.168.0.1"),
|
||||
Port: DefaultKiloPort,
|
||||
DNSOrIP: wireguard.DNSOrIP{IP: net.ParseIP("192.168.0.1")},
|
||||
Port: DefaultKiloPort,
|
||||
},
|
||||
PublicKey: []byte("key5"),
|
||||
},
|
||||
@@ -119,7 +119,7 @@ func TestNewTopology(t *testing.T) {
|
||||
segments: []*segment{
|
||||
{
|
||||
allowedIPs: []*net.IPNet{nodes["a"].Subnet, nodes["a"].InternalIP, {IP: w1, Mask: net.CIDRMask(32, 32)}},
|
||||
endpoint: nodes["a"].ExternalIP.IP,
|
||||
endpoint: nodes["a"].Endpoint,
|
||||
key: nodes["a"].Key,
|
||||
location: nodes["a"].Location,
|
||||
cidrs: []*net.IPNet{nodes["a"].Subnet},
|
||||
@@ -130,7 +130,7 @@ func TestNewTopology(t *testing.T) {
|
||||
},
|
||||
{
|
||||
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"].ExternalIP.IP,
|
||||
endpoint: nodes["b"].Endpoint,
|
||||
key: nodes["b"].Key,
|
||||
location: nodes["b"].Location,
|
||||
cidrs: []*net.IPNet{nodes["b"].Subnet, nodes["c"].Subnet},
|
||||
@@ -156,7 +156,7 @@ func TestNewTopology(t *testing.T) {
|
||||
segments: []*segment{
|
||||
{
|
||||
allowedIPs: []*net.IPNet{nodes["a"].Subnet, nodes["a"].InternalIP, {IP: w1, Mask: net.CIDRMask(32, 32)}},
|
||||
endpoint: nodes["a"].ExternalIP.IP,
|
||||
endpoint: nodes["a"].Endpoint,
|
||||
key: nodes["a"].Key,
|
||||
location: nodes["a"].Location,
|
||||
cidrs: []*net.IPNet{nodes["a"].Subnet},
|
||||
@@ -167,7 +167,7 @@ func TestNewTopology(t *testing.T) {
|
||||
},
|
||||
{
|
||||
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"].ExternalIP.IP,
|
||||
endpoint: nodes["b"].Endpoint,
|
||||
key: nodes["b"].Key,
|
||||
location: nodes["b"].Location,
|
||||
cidrs: []*net.IPNet{nodes["b"].Subnet, nodes["c"].Subnet},
|
||||
@@ -193,7 +193,7 @@ func TestNewTopology(t *testing.T) {
|
||||
segments: []*segment{
|
||||
{
|
||||
allowedIPs: []*net.IPNet{nodes["a"].Subnet, nodes["a"].InternalIP, {IP: w1, Mask: net.CIDRMask(32, 32)}},
|
||||
endpoint: nodes["a"].ExternalIP.IP,
|
||||
endpoint: nodes["a"].Endpoint,
|
||||
key: nodes["a"].Key,
|
||||
location: nodes["a"].Location,
|
||||
cidrs: []*net.IPNet{nodes["a"].Subnet},
|
||||
@@ -204,7 +204,7 @@ func TestNewTopology(t *testing.T) {
|
||||
},
|
||||
{
|
||||
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"].ExternalIP.IP,
|
||||
endpoint: nodes["b"].Endpoint,
|
||||
key: nodes["b"].Key,
|
||||
location: nodes["b"].Location,
|
||||
cidrs: []*net.IPNet{nodes["b"].Subnet, nodes["c"].Subnet},
|
||||
@@ -230,7 +230,7 @@ func TestNewTopology(t *testing.T) {
|
||||
segments: []*segment{
|
||||
{
|
||||
allowedIPs: []*net.IPNet{nodes["a"].Subnet, nodes["a"].InternalIP, {IP: w1, Mask: net.CIDRMask(32, 32)}},
|
||||
endpoint: nodes["a"].ExternalIP.IP,
|
||||
endpoint: nodes["a"].Endpoint,
|
||||
key: nodes["a"].Key,
|
||||
location: nodes["a"].Name,
|
||||
cidrs: []*net.IPNet{nodes["a"].Subnet},
|
||||
@@ -241,7 +241,7 @@ func TestNewTopology(t *testing.T) {
|
||||
},
|
||||
{
|
||||
allowedIPs: []*net.IPNet{nodes["b"].Subnet, nodes["b"].InternalIP, {IP: w2, Mask: net.CIDRMask(32, 32)}},
|
||||
endpoint: nodes["b"].ExternalIP.IP,
|
||||
endpoint: nodes["b"].Endpoint,
|
||||
key: nodes["b"].Key,
|
||||
location: nodes["b"].Name,
|
||||
cidrs: []*net.IPNet{nodes["b"].Subnet},
|
||||
@@ -251,7 +251,7 @@ func TestNewTopology(t *testing.T) {
|
||||
},
|
||||
{
|
||||
allowedIPs: []*net.IPNet{nodes["c"].Subnet, nodes["c"].InternalIP, {IP: w3, Mask: net.CIDRMask(32, 32)}},
|
||||
endpoint: nodes["c"].ExternalIP.IP,
|
||||
endpoint: nodes["c"].Endpoint,
|
||||
key: nodes["c"].Key,
|
||||
location: nodes["c"].Name,
|
||||
cidrs: []*net.IPNet{nodes["c"].Subnet},
|
||||
@@ -277,7 +277,7 @@ func TestNewTopology(t *testing.T) {
|
||||
segments: []*segment{
|
||||
{
|
||||
allowedIPs: []*net.IPNet{nodes["a"].Subnet, nodes["a"].InternalIP, {IP: w1, Mask: net.CIDRMask(32, 32)}},
|
||||
endpoint: nodes["a"].ExternalIP.IP,
|
||||
endpoint: nodes["a"].Endpoint,
|
||||
key: nodes["a"].Key,
|
||||
location: nodes["a"].Name,
|
||||
cidrs: []*net.IPNet{nodes["a"].Subnet},
|
||||
@@ -288,7 +288,7 @@ func TestNewTopology(t *testing.T) {
|
||||
},
|
||||
{
|
||||
allowedIPs: []*net.IPNet{nodes["b"].Subnet, nodes["b"].InternalIP, {IP: w2, Mask: net.CIDRMask(32, 32)}},
|
||||
endpoint: nodes["b"].ExternalIP.IP,
|
||||
endpoint: nodes["b"].Endpoint,
|
||||
key: nodes["b"].Key,
|
||||
location: nodes["b"].Name,
|
||||
cidrs: []*net.IPNet{nodes["b"].Subnet},
|
||||
@@ -298,7 +298,7 @@ func TestNewTopology(t *testing.T) {
|
||||
},
|
||||
{
|
||||
allowedIPs: []*net.IPNet{nodes["c"].Subnet, nodes["c"].InternalIP, {IP: w3, Mask: net.CIDRMask(32, 32)}},
|
||||
endpoint: nodes["c"].ExternalIP.IP,
|
||||
endpoint: nodes["c"].Endpoint,
|
||||
key: nodes["c"].Key,
|
||||
location: nodes["c"].Name,
|
||||
cidrs: []*net.IPNet{nodes["c"].Subnet},
|
||||
@@ -324,7 +324,7 @@ func TestNewTopology(t *testing.T) {
|
||||
segments: []*segment{
|
||||
{
|
||||
allowedIPs: []*net.IPNet{nodes["a"].Subnet, nodes["a"].InternalIP, {IP: w1, Mask: net.CIDRMask(32, 32)}},
|
||||
endpoint: nodes["a"].ExternalIP.IP,
|
||||
endpoint: nodes["a"].Endpoint,
|
||||
key: nodes["a"].Key,
|
||||
location: nodes["a"].Name,
|
||||
cidrs: []*net.IPNet{nodes["a"].Subnet},
|
||||
@@ -335,7 +335,7 @@ func TestNewTopology(t *testing.T) {
|
||||
},
|
||||
{
|
||||
allowedIPs: []*net.IPNet{nodes["b"].Subnet, nodes["b"].InternalIP, {IP: w2, Mask: net.CIDRMask(32, 32)}},
|
||||
endpoint: nodes["b"].ExternalIP.IP,
|
||||
endpoint: nodes["b"].Endpoint,
|
||||
key: nodes["b"].Key,
|
||||
location: nodes["b"].Name,
|
||||
cidrs: []*net.IPNet{nodes["b"].Subnet},
|
||||
@@ -345,7 +345,7 @@ func TestNewTopology(t *testing.T) {
|
||||
},
|
||||
{
|
||||
allowedIPs: []*net.IPNet{nodes["c"].Subnet, nodes["c"].InternalIP, {IP: w3, Mask: net.CIDRMask(32, 32)}},
|
||||
endpoint: nodes["c"].ExternalIP.IP,
|
||||
endpoint: nodes["c"].Endpoint,
|
||||
key: nodes["c"].Key,
|
||||
location: nodes["c"].Name,
|
||||
cidrs: []*net.IPNet{nodes["c"].Subnet},
|
||||
@@ -1400,26 +1400,26 @@ func TestFindLeader(t *testing.T) {
|
||||
|
||||
nodes := []*Node{
|
||||
{
|
||||
Name: "a",
|
||||
ExternalIP: e1,
|
||||
Name: "a",
|
||||
Endpoint: &wireguard.Endpoint{DNSOrIP: wireguard.DNSOrIP{IP: e1.IP}, Port: DefaultKiloPort},
|
||||
},
|
||||
{
|
||||
Name: "b",
|
||||
ExternalIP: e2,
|
||||
Name: "b",
|
||||
Endpoint: &wireguard.Endpoint{DNSOrIP: wireguard.DNSOrIP{IP: e2.IP}, Port: DefaultKiloPort},
|
||||
},
|
||||
{
|
||||
Name: "c",
|
||||
ExternalIP: e2,
|
||||
Name: "c",
|
||||
Endpoint: &wireguard.Endpoint{DNSOrIP: wireguard.DNSOrIP{IP: e2.IP}, Port: DefaultKiloPort},
|
||||
},
|
||||
{
|
||||
Name: "d",
|
||||
ExternalIP: e1,
|
||||
Leader: true,
|
||||
Name: "d",
|
||||
Endpoint: &wireguard.Endpoint{DNSOrIP: wireguard.DNSOrIP{IP: e1.IP}, Port: DefaultKiloPort},
|
||||
Leader: true,
|
||||
},
|
||||
{
|
||||
Name: "2",
|
||||
ExternalIP: e2,
|
||||
Leader: true,
|
||||
Name: "2",
|
||||
Endpoint: &wireguard.Endpoint{DNSOrIP: wireguard.DNSOrIP{IP: e2.IP}, Port: DefaultKiloPort},
|
||||
Leader: true,
|
||||
},
|
||||
}
|
||||
for _, tc := range []struct {
|
||||
|
Reference in New Issue
Block a user