pkg/mesh,pkg/wireguard: sync NAT endpoints

This commit changes how Kilo allows nodes and peers behind NAT to roam.
Rather that ignore changes to endpoints when comparing WireGuard
configurations, Kilo now incorporates changes to endpoints for peers
behind NAT into its configuration first and later compares the
configurations.

Signed-off-by: Lucas Servén Marín <lserven@gmail.com>
This commit is contained in:
Lucas Servén Marín
2020-03-04 00:39:54 +01:00
parent 24d7c27901
commit 29280a987e
2 changed files with 64 additions and 89 deletions

View File

@@ -275,12 +275,6 @@ func (c *Conf) Bytes() ([]byte, error) {
// Equal checks if two WireGuard configurations are equivalent.
func (c *Conf) Equal(b *Conf) bool {
return c.EqualWithPeerCheck(b, strictPeerCheck)
}
// EqualWithPeerCheck checks if two WireGuard configurations are equivalent
// when their peers are compared using the given peer comparison func.
func (c *Conf) EqualWithPeerCheck(b *Conf, pc PeerCheck) bool {
if (c.Interface == nil) != (b.Interface == nil) {
return false
}
@@ -294,47 +288,38 @@ func (c *Conf) EqualWithPeerCheck(b *Conf, pc PeerCheck) bool {
}
sortPeers(c.Peers)
sortPeers(b.Peers)
var ok bool
for i := range c.Peers {
if len(c.Peers[i].AllowedIPs) != len(b.Peers[i].AllowedIPs) {
return false
}
sortCIDRs(c.Peers[i].AllowedIPs)
sortCIDRs(b.Peers[i].AllowedIPs)
if ok = pc(c.Peers[i], b.Peers[i]); !ok {
for j := range c.Peers[i].AllowedIPs {
if c.Peers[i].AllowedIPs[j].String() != b.Peers[i].AllowedIPs[j].String() {
return false
}
}
if (c.Peers[i].Endpoint == nil) != (b.Peers[i].Endpoint == nil) {
return false
}
if c.Peers[i].Endpoint != nil {
if c.Peers[i].Endpoint.Port != b.Peers[i].Endpoint.Port {
return false
}
// IPs take priority, so check them first.
if !c.Peers[i].Endpoint.IP.Equal(b.Peers[i].Endpoint.IP) {
return false
}
// Only check the DNS name if the IP is empty.
if c.Peers[i].Endpoint.IP == nil && c.Peers[i].Endpoint.DNS != b.Peers[i].Endpoint.DNS {
return false
}
}
if c.Peers[i].PersistentKeepalive != b.Peers[i].PersistentKeepalive || !bytes.Equal(c.Peers[i].PublicKey, b.Peers[i].PublicKey) {
return false
}
}
return true
}
// PeerCheck is a function that compares two peers.
type PeerCheck func(a, b *Peer) bool
func strictPeerCheck(a, b *Peer) bool {
for j := range a.AllowedIPs {
if a.AllowedIPs[j].String() != b.AllowedIPs[j].String() {
return false
}
}
if (a.Endpoint == nil) != (b.Endpoint == nil) {
return false
}
if a.Endpoint != nil {
if a.Endpoint.Port != b.Endpoint.Port {
return false
}
// IPs take priority, so check them first.
if !a.Endpoint.IP.Equal(b.Endpoint.IP) {
return false
}
// Only check the DNS name if the IP is empty.
if a.Endpoint.IP == nil && a.Endpoint.DNS != b.Endpoint.DNS {
return false
}
}
return a.PersistentKeepalive == b.PersistentKeepalive && bytes.Equal(a.PublicKey, b.PublicKey)
}
func sortPeers(peers []*Peer) {