diff --git a/client/iface/configurer/common.go b/client/iface/configurer/common.go new file mode 100644 index 000000000..088cff69d --- /dev/null +++ b/client/iface/configurer/common.go @@ -0,0 +1,17 @@ +package configurer + +import ( + "net" + "net/netip" +) + +func prefixesToIPNets(prefixes []netip.Prefix) []net.IPNet { + ipNets := make([]net.IPNet, len(prefixes)) + for i, prefix := range prefixes { + ipNets[i] = net.IPNet{ + IP: prefix.Addr().AsSlice(), // Convert netip.Addr to net.IP + Mask: net.CIDRMask(prefix.Bits(), prefix.Addr().BitLen()), // Create subnet mask + } + } + return ipNets +} diff --git a/client/iface/configurer/kernel_unix.go b/client/iface/configurer/kernel_unix.go index 91991177e..4922a54fc 100644 --- a/client/iface/configurer/kernel_unix.go +++ b/client/iface/configurer/kernel_unix.go @@ -5,6 +5,7 @@ package configurer import ( "fmt" "net" + "net/netip" "time" log "github.com/sirupsen/logrus" @@ -45,7 +46,7 @@ func (c *KernelConfigurer) ConfigureInterface(privateKey string, port int) error return nil } -func (c *KernelConfigurer) UpdatePeer(peerKey string, allowedIps []net.IPNet, keepAlive time.Duration, endpoint *net.UDPAddr, preSharedKey *wgtypes.Key) error { +func (c *KernelConfigurer) UpdatePeer(peerKey string, allowedIps []netip.Prefix, keepAlive time.Duration, endpoint *net.UDPAddr, preSharedKey *wgtypes.Key) error { peerKeyParsed, err := wgtypes.ParseKey(peerKey) if err != nil { return err @@ -54,7 +55,7 @@ func (c *KernelConfigurer) UpdatePeer(peerKey string, allowedIps []net.IPNet, ke PublicKey: peerKeyParsed, ReplaceAllowedIPs: false, // don't replace allowed ips, wg will handle duplicated peer IP - AllowedIPs: allowedIps, + AllowedIPs: prefixesToIPNets(allowedIps), PersistentKeepaliveInterval: &keepAlive, Endpoint: endpoint, PresharedKey: preSharedKey, @@ -91,10 +92,10 @@ func (c *KernelConfigurer) RemovePeer(peerKey string) error { return nil } -func (c *KernelConfigurer) AddAllowedIP(peerKey string, allowedIP string) error { - _, ipNet, err := net.ParseCIDR(allowedIP) - if err != nil { - return err +func (c *KernelConfigurer) AddAllowedIP(peerKey string, allowedIP netip.Prefix) error { + ipNet := net.IPNet{ + IP: allowedIP.Addr().AsSlice(), + Mask: net.CIDRMask(allowedIP.Bits(), allowedIP.Addr().BitLen()), } peerKeyParsed, err := wgtypes.ParseKey(peerKey) @@ -105,7 +106,7 @@ func (c *KernelConfigurer) AddAllowedIP(peerKey string, allowedIP string) error PublicKey: peerKeyParsed, UpdateOnly: true, ReplaceAllowedIPs: false, - AllowedIPs: []net.IPNet{*ipNet}, + AllowedIPs: []net.IPNet{ipNet}, } config := wgtypes.Config{ @@ -118,10 +119,10 @@ func (c *KernelConfigurer) AddAllowedIP(peerKey string, allowedIP string) error return nil } -func (c *KernelConfigurer) RemoveAllowedIP(peerKey string, allowedIP string) error { - _, ipNet, err := net.ParseCIDR(allowedIP) - if err != nil { - return fmt.Errorf("parse allowed IP: %w", err) +func (c *KernelConfigurer) RemoveAllowedIP(peerKey string, allowedIP netip.Prefix) error { + ipNet := net.IPNet{ + IP: allowedIP.Addr().AsSlice(), + Mask: net.CIDRMask(allowedIP.Bits(), allowedIP.Addr().BitLen()), } peerKeyParsed, err := wgtypes.ParseKey(peerKey) @@ -189,7 +190,11 @@ func (c *KernelConfigurer) configure(config wgtypes.Config) error { if err != nil { return err } - defer wg.Close() + defer func() { + if err := wg.Close(); err != nil { + log.Errorf("Failed to close wgctrl client: %v", err) + } + }() // validate if device with name exists _, err = wg.Device(c.deviceName) diff --git a/client/iface/configurer/usp.go b/client/iface/configurer/usp.go index 914788821..79ce91eea 100644 --- a/client/iface/configurer/usp.go +++ b/client/iface/configurer/usp.go @@ -5,6 +5,7 @@ import ( "encoding/hex" "fmt" "net" + "net/netip" "os" "runtime" "strconv" @@ -67,7 +68,7 @@ func (c *WGUSPConfigurer) ConfigureInterface(privateKey string, port int) error return c.device.IpcSet(toWgUserspaceString(config)) } -func (c *WGUSPConfigurer) UpdatePeer(peerKey string, allowedIps []net.IPNet, keepAlive time.Duration, endpoint *net.UDPAddr, preSharedKey *wgtypes.Key) error { +func (c *WGUSPConfigurer) UpdatePeer(peerKey string, allowedIps []netip.Prefix, keepAlive time.Duration, endpoint *net.UDPAddr, preSharedKey *wgtypes.Key) error { peerKeyParsed, err := wgtypes.ParseKey(peerKey) if err != nil { return err @@ -76,7 +77,7 @@ func (c *WGUSPConfigurer) UpdatePeer(peerKey string, allowedIps []net.IPNet, kee PublicKey: peerKeyParsed, ReplaceAllowedIPs: false, // don't replace allowed ips, wg will handle duplicated peer IP - AllowedIPs: allowedIps, + AllowedIPs: prefixesToIPNets(allowedIps), PersistentKeepaliveInterval: &keepAlive, PresharedKey: preSharedKey, Endpoint: endpoint, @@ -106,10 +107,10 @@ func (c *WGUSPConfigurer) RemovePeer(peerKey string) error { return c.device.IpcSet(toWgUserspaceString(config)) } -func (c *WGUSPConfigurer) AddAllowedIP(peerKey string, allowedIP string) error { - _, ipNet, err := net.ParseCIDR(allowedIP) - if err != nil { - return err +func (c *WGUSPConfigurer) AddAllowedIP(peerKey string, allowedIP netip.Prefix) error { + ipNet := net.IPNet{ + IP: allowedIP.Addr().AsSlice(), + Mask: net.CIDRMask(allowedIP.Bits(), allowedIP.Addr().BitLen()), } peerKeyParsed, err := wgtypes.ParseKey(peerKey) @@ -120,7 +121,7 @@ func (c *WGUSPConfigurer) AddAllowedIP(peerKey string, allowedIP string) error { PublicKey: peerKeyParsed, UpdateOnly: true, ReplaceAllowedIPs: false, - AllowedIPs: []net.IPNet{*ipNet}, + AllowedIPs: []net.IPNet{ipNet}, } config := wgtypes.Config{ @@ -130,7 +131,7 @@ func (c *WGUSPConfigurer) AddAllowedIP(peerKey string, allowedIP string) error { return c.device.IpcSet(toWgUserspaceString(config)) } -func (c *WGUSPConfigurer) RemoveAllowedIP(peerKey string, ip string) error { +func (c *WGUSPConfigurer) RemoveAllowedIP(peerKey string, allowedIP netip.Prefix) error { ipc, err := c.device.IpcGet() if err != nil { return err @@ -153,6 +154,8 @@ func (c *WGUSPConfigurer) RemoveAllowedIP(peerKey string, ip string) error { foundPeer := false removedAllowedIP := false + ip := allowedIP.String() + for _, line := range lines { line = strings.TrimSpace(line) @@ -175,8 +178,8 @@ func (c *WGUSPConfigurer) RemoveAllowedIP(peerKey string, ip string) error { // Append the line to the output string if foundPeer && strings.HasPrefix(line, "allowed_ip=") { - allowedIP := strings.TrimPrefix(line, "allowed_ip=") - _, ipNet, err := net.ParseCIDR(allowedIP) + allowedIPStr := strings.TrimPrefix(line, "allowed_ip=") + _, ipNet, err := net.ParseCIDR(allowedIPStr) if err != nil { return err } diff --git a/client/iface/device/interface.go b/client/iface/device/interface.go index 31ebdf4b8..296eb7dda 100644 --- a/client/iface/device/interface.go +++ b/client/iface/device/interface.go @@ -2,6 +2,7 @@ package device import ( "net" + "net/netip" "time" "golang.zx2c4.com/wireguard/wgctrl/wgtypes" @@ -11,10 +12,10 @@ import ( type WGConfigurer interface { ConfigureInterface(privateKey string, port int) error - UpdatePeer(peerKey string, allowedIps []net.IPNet, keepAlive time.Duration, endpoint *net.UDPAddr, preSharedKey *wgtypes.Key) error + UpdatePeer(peerKey string, allowedIps []netip.Prefix, keepAlive time.Duration, endpoint *net.UDPAddr, preSharedKey *wgtypes.Key) error RemovePeer(peerKey string) error - AddAllowedIP(peerKey string, allowedIP string) error - RemoveAllowedIP(peerKey string, allowedIP string) error + AddAllowedIP(peerKey string, allowedIP netip.Prefix) error + RemoveAllowedIP(peerKey string, allowedIP netip.Prefix) error Close() GetStats() (map[string]configurer.WGStats, error) FullStats() (*configurer.Stats, error) diff --git a/client/iface/iface.go b/client/iface/iface.go index f4394c476..7d609f4cd 100644 --- a/client/iface/iface.go +++ b/client/iface/iface.go @@ -111,14 +111,14 @@ func (w *WGIface) UpdateAddr(newAddr string) error { } // UpdatePeer updates existing Wireguard Peer or creates a new one if doesn't exist -// Endpoint is optional +// Endpoint is optional. +// If allowedIps is given it will be added to the existing ones. func (w *WGIface) UpdatePeer(peerKey string, allowedIps []netip.Prefix, keepAlive time.Duration, endpoint *net.UDPAddr, preSharedKey *wgtypes.Key) error { w.mu.Lock() defer w.mu.Unlock() - netIPNets := prefixesToIPNets(allowedIps) - log.Debugf("updating interface %s peer %s, endpoint %s", w.tun.DeviceName(), peerKey, endpoint) - return w.configurer.UpdatePeer(peerKey, netIPNets, keepAlive, endpoint, preSharedKey) + log.Debugf("updating interface %s peer %s, endpoint %s, allowedIPs %v", w.tun.DeviceName(), peerKey, endpoint, allowedIps) + return w.configurer.UpdatePeer(peerKey, allowedIps, keepAlive, endpoint, preSharedKey) } // RemovePeer removes a Wireguard Peer from the interface iface @@ -131,7 +131,7 @@ func (w *WGIface) RemovePeer(peerKey string) error { } // AddAllowedIP adds a prefix to the allowed IPs list of peer -func (w *WGIface) AddAllowedIP(peerKey string, allowedIP string) error { +func (w *WGIface) AddAllowedIP(peerKey string, allowedIP netip.Prefix) error { w.mu.Lock() defer w.mu.Unlock() @@ -140,7 +140,7 @@ func (w *WGIface) AddAllowedIP(peerKey string, allowedIP string) error { } // RemoveAllowedIP removes a prefix from the allowed IPs list of peer -func (w *WGIface) RemoveAllowedIP(peerKey string, allowedIP string) error { +func (w *WGIface) RemoveAllowedIP(peerKey string, allowedIP netip.Prefix) error { w.mu.Lock() defer w.mu.Unlock() @@ -254,14 +254,3 @@ func (w *WGIface) GetNet() *netstack.Net { return w.tun.GetNet() } - -func prefixesToIPNets(prefixes []netip.Prefix) []net.IPNet { - ipNets := make([]net.IPNet, len(prefixes)) - for i, prefix := range prefixes { - ipNets[i] = net.IPNet{ - IP: net.IP(prefix.Addr().AsSlice()), // Convert netip.Addr to net.IP - Mask: net.CIDRMask(prefix.Bits(), prefix.Addr().BitLen()), // Create subnet mask - } - } - return ipNets -} diff --git a/client/internal/engine_test.go b/client/internal/engine_test.go index a4470e0ec..8c084e366 100644 --- a/client/internal/engine_test.go +++ b/client/internal/engine_test.go @@ -86,8 +86,8 @@ type MockWGIface struct { UpdateAddrFunc func(newAddr string) error UpdatePeerFunc func(peerKey string, allowedIps []netip.Prefix, keepAlive time.Duration, endpoint *net.UDPAddr, preSharedKey *wgtypes.Key) error RemovePeerFunc func(peerKey string) error - AddAllowedIPFunc func(peerKey string, allowedIP string) error - RemoveAllowedIPFunc func(peerKey string, allowedIP string) error + AddAllowedIPFunc func(peerKey string, allowedIP netip.Prefix) error + RemoveAllowedIPFunc func(peerKey string, allowedIP netip.Prefix) error CloseFunc func() error SetFilterFunc func(filter device.PacketFilter) error GetFilterFunc func() device.PacketFilter @@ -147,11 +147,11 @@ func (m *MockWGIface) RemovePeer(peerKey string) error { return m.RemovePeerFunc(peerKey) } -func (m *MockWGIface) AddAllowedIP(peerKey string, allowedIP string) error { +func (m *MockWGIface) AddAllowedIP(peerKey string, allowedIP netip.Prefix) error { return m.AddAllowedIPFunc(peerKey, allowedIP) } -func (m *MockWGIface) RemoveAllowedIP(peerKey string, allowedIP string) error { +func (m *MockWGIface) RemoveAllowedIP(peerKey string, allowedIP netip.Prefix) error { return m.RemoveAllowedIPFunc(peerKey, allowedIP) } diff --git a/client/internal/iface_common.go b/client/internal/iface_common.go index 95bf146f9..999472411 100644 --- a/client/internal/iface_common.go +++ b/client/internal/iface_common.go @@ -28,8 +28,8 @@ type wgIfaceBase interface { GetProxy() wgproxy.Proxy UpdatePeer(peerKey string, allowedIps []netip.Prefix, keepAlive time.Duration, endpoint *net.UDPAddr, preSharedKey *wgtypes.Key) error RemovePeer(peerKey string) error - AddAllowedIP(peerKey string, allowedIP string) error - RemoveAllowedIP(peerKey string, allowedIP string) error + AddAllowedIP(peerKey string, allowedIP netip.Prefix) error + RemoveAllowedIP(peerKey string, allowedIP netip.Prefix) error Close() error SetFilter(filter device.PacketFilter) error GetFilter() device.PacketFilter diff --git a/client/internal/routemanager/iface/iface_common.go b/client/internal/routemanager/iface/iface_common.go index 02d3f4c6f..f844f4bed 100644 --- a/client/internal/routemanager/iface/iface_common.go +++ b/client/internal/routemanager/iface/iface_common.go @@ -2,14 +2,15 @@ package iface import ( "net" + "net/netip" "github.com/netbirdio/netbird/client/iface/device" "github.com/netbirdio/netbird/client/iface/wgaddr" ) type wgIfaceBase interface { - AddAllowedIP(peerKey string, allowedIP string) error - RemoveAllowedIP(peerKey string, allowedIP string) error + AddAllowedIP(peerKey string, allowedIP netip.Prefix) error + RemoveAllowedIP(peerKey string, allowedIP netip.Prefix) error Name() string Address() wgaddr.Address diff --git a/client/internal/routemanager/manager.go b/client/internal/routemanager/manager.go index 93a3788eb..919bf25e3 100644 --- a/client/internal/routemanager/manager.go +++ b/client/internal/routemanager/manager.go @@ -159,10 +159,10 @@ func (m *DefaultManager) setupRefCounters(useNoop bool) { m.allowedIPsRefCounter = refcounter.New( func(prefix netip.Prefix, peerKey string) (string, error) { // save peerKey to use it in the remove function - return peerKey, m.wgInterface.AddAllowedIP(peerKey, prefix.String()) + return peerKey, m.wgInterface.AddAllowedIP(peerKey, prefix) }, func(prefix netip.Prefix, peerKey string) error { - if err := m.wgInterface.RemoveAllowedIP(peerKey, prefix.String()); err != nil { + if err := m.wgInterface.RemoveAllowedIP(peerKey, prefix); err != nil { if !errors.Is(err, configurer.ErrPeerNotFound) && !errors.Is(err, configurer.ErrAllowedIPNotFound) { return err }