mirror of
https://github.com/fosrl/olm.git
synced 2026-02-08 05:56:41 +00:00
Formatting of peers and dns worked
This commit is contained in:
@@ -14,7 +14,7 @@ import (
|
|||||||
var configurator platform.DNSConfigurator
|
var configurator platform.DNSConfigurator
|
||||||
|
|
||||||
// SetupDNSOverride configures the system DNS to use the DNS proxy on Linux/FreeBSD
|
// SetupDNSOverride configures the system DNS to use the DNS proxy on Linux/FreeBSD
|
||||||
// Tries systemd-resolved, NetworkManager, resolvconf, or falls back to /etc/resolv.conf
|
// Detects the DNS manager by reading /etc/resolv.conf and verifying runtime availability
|
||||||
func SetupDNSOverride(interfaceName string, dnsProxy *dns.DNSProxy) error {
|
func SetupDNSOverride(interfaceName string, dnsProxy *dns.DNSProxy) error {
|
||||||
if dnsProxy == nil {
|
if dnsProxy == nil {
|
||||||
return fmt.Errorf("DNS proxy is nil")
|
return fmt.Errorf("DNS proxy is nil")
|
||||||
@@ -22,34 +22,35 @@ func SetupDNSOverride(interfaceName string, dnsProxy *dns.DNSProxy) error {
|
|||||||
|
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
// Try systemd-resolved first (most modern)
|
// Detect which DNS manager is in use by checking /etc/resolv.conf and runtime availability
|
||||||
if platform.IsSystemdResolvedAvailable() && interfaceName != "" {
|
managerType := platform.DetectDNSManager(interfaceName)
|
||||||
|
logger.Info("Detected DNS manager: %s", managerType.String())
|
||||||
|
|
||||||
|
// Create configurator based on detected manager
|
||||||
|
switch managerType {
|
||||||
|
case platform.SystemdResolvedManager:
|
||||||
configurator, err = platform.NewSystemdResolvedDNSConfigurator(interfaceName)
|
configurator, err = platform.NewSystemdResolvedDNSConfigurator(interfaceName)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
logger.Info("Using systemd-resolved DNS configurator")
|
logger.Info("Using systemd-resolved DNS configurator")
|
||||||
return setDNS(dnsProxy, configurator)
|
return setDNS(dnsProxy, configurator)
|
||||||
}
|
}
|
||||||
logger.Debug("systemd-resolved not available: %v", err)
|
logger.Warn("Failed to create systemd-resolved configurator: %v, falling back", err)
|
||||||
}
|
|
||||||
|
|
||||||
// Try NetworkManager (common on desktops)
|
case platform.NetworkManagerManager:
|
||||||
if platform.IsNetworkManagerAvailable() && interfaceName != "" {
|
|
||||||
configurator, err = platform.NewNetworkManagerDNSConfigurator(interfaceName)
|
configurator, err = platform.NewNetworkManagerDNSConfigurator(interfaceName)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
logger.Info("Using NetworkManager DNS configurator")
|
logger.Info("************************************Using NetworkManager DNS configurator")
|
||||||
return setDNS(dnsProxy, configurator)
|
return setDNS(dnsProxy, configurator)
|
||||||
}
|
}
|
||||||
logger.Debug("NetworkManager not available: %v", err)
|
logger.Warn("Failed to create NetworkManager configurator: %v, falling back", err)
|
||||||
}
|
|
||||||
|
|
||||||
// Try resolvconf (common on older systems)
|
case platform.ResolvconfManager:
|
||||||
if platform.IsResolvconfAvailable() && interfaceName != "" {
|
|
||||||
configurator, err = platform.NewResolvconfDNSConfigurator(interfaceName)
|
configurator, err = platform.NewResolvconfDNSConfigurator(interfaceName)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
logger.Info("Using resolvconf DNS configurator")
|
logger.Info("Using resolvconf DNS configurator")
|
||||||
return setDNS(dnsProxy, configurator)
|
return setDNS(dnsProxy, configurator)
|
||||||
}
|
}
|
||||||
logger.Debug("resolvconf not available: %v", err)
|
logger.Warn("Failed to create resolvconf configurator: %v, falling back", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fall back to direct file manipulation
|
// Fall back to direct file manipulation
|
||||||
|
|||||||
@@ -1,30 +0,0 @@
|
|||||||
//go:build darwin && !ios
|
|
||||||
|
|
||||||
package dns
|
|
||||||
|
|
||||||
import "fmt"
|
|
||||||
|
|
||||||
// DetectBestConfigurator returns the macOS DNS configurator
|
|
||||||
func DetectBestConfigurator(ifaceName string) (DNSConfigurator, error) {
|
|
||||||
return NewDarwinDNSConfigurator()
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetSystemDNS returns the current system DNS servers
|
|
||||||
func GetSystemDNS() ([]string, error) {
|
|
||||||
configurator, err := NewDarwinDNSConfigurator()
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("create configurator: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
servers, err := configurator.GetCurrentDNS()
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("get current DNS: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
var result []string
|
|
||||||
for _, server := range servers {
|
|
||||||
result = append(result, server.String())
|
|
||||||
}
|
|
||||||
|
|
||||||
return result, nil
|
|
||||||
}
|
|
||||||
@@ -3,90 +3,149 @@
|
|||||||
package dns
|
package dns
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"bufio"
|
||||||
"net/netip"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/fosrl/newt/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DetectBestConfigurator detects and returns the most appropriate DNS configurator for the system
|
const defaultResolvConfPath = "/etc/resolv.conf"
|
||||||
// ifaceName is optional and only used for NetworkManager, systemd-resolved, and resolvconf
|
|
||||||
func DetectBestConfigurator(ifaceName string) (DNSConfigurator, error) {
|
|
||||||
// Try systemd-resolved first (most modern)
|
|
||||||
if IsSystemdResolvedAvailable() && ifaceName != "" {
|
|
||||||
if configurator, err := NewSystemdResolvedDNSConfigurator(ifaceName); err == nil {
|
|
||||||
return configurator, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try NetworkManager (common on desktops)
|
// DNSManagerType represents the type of DNS manager detected
|
||||||
if IsNetworkManagerAvailable() && ifaceName != "" {
|
type DNSManagerType int
|
||||||
if configurator, err := NewNetworkManagerDNSConfigurator(ifaceName); err == nil {
|
|
||||||
return configurator, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try resolvconf (common on older systems)
|
const (
|
||||||
if IsResolvconfAvailable() && ifaceName != "" {
|
// UnknownManager indicates we couldn't determine the DNS manager
|
||||||
if configurator, err := NewResolvconfDNSConfigurator(ifaceName); err == nil {
|
UnknownManager DNSManagerType = iota
|
||||||
return configurator, nil
|
// SystemdResolvedManager indicates systemd-resolved is managing DNS
|
||||||
}
|
SystemdResolvedManager
|
||||||
}
|
// NetworkManagerManager indicates NetworkManager is managing DNS
|
||||||
|
NetworkManagerManager
|
||||||
|
// ResolvconfManager indicates resolvconf is managing DNS
|
||||||
|
ResolvconfManager
|
||||||
|
// FileManager indicates direct file management (no DNS manager)
|
||||||
|
FileManager
|
||||||
|
)
|
||||||
|
|
||||||
// Fall back to direct file manipulation
|
// DetectDNSManagerFromFile reads /etc/resolv.conf to determine which DNS manager is in use
|
||||||
return NewFileDNSConfigurator()
|
// This provides a hint based on comments in the file, similar to Netbird's approach
|
||||||
}
|
func DetectDNSManagerFromFile() DNSManagerType {
|
||||||
|
file, err := os.Open(defaultResolvConfPath)
|
||||||
// Helper functions for checking system state
|
|
||||||
|
|
||||||
// IsSystemdResolvedRunning checks if systemd-resolved is running
|
|
||||||
func IsSystemdResolvedRunning() bool {
|
|
||||||
// Check if stub resolver is configured
|
|
||||||
servers, err := readResolvConfDNS()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false
|
return UnknownManager
|
||||||
}
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
// systemd-resolved uses 127.0.0.53
|
scanner := bufio.NewScanner(file)
|
||||||
stubAddr := netip.MustParseAddr("127.0.0.53")
|
for scanner.Scan() {
|
||||||
for _, server := range servers {
|
text := scanner.Text()
|
||||||
if server == stubAddr {
|
if len(text) == 0 {
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// readResolvConfDNS reads DNS servers from /etc/resolv.conf
|
|
||||||
func readResolvConfDNS() ([]netip.Addr, error) {
|
|
||||||
content, err := os.ReadFile("/etc/resolv.conf")
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("read resolv.conf: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
var servers []netip.Addr
|
|
||||||
lines := strings.Split(string(content), "\n")
|
|
||||||
for _, line := range lines {
|
|
||||||
line = strings.TrimSpace(line)
|
|
||||||
if line == "" || strings.HasPrefix(line, "#") {
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if strings.HasPrefix(line, "nameserver") {
|
// If we hit a non-comment line, default to file-based
|
||||||
fields := strings.Fields(line)
|
if text[0] != '#' {
|
||||||
if len(fields) >= 2 {
|
return FileManager
|
||||||
if addr, err := netip.ParseAddr(fields[1]); err == nil {
|
}
|
||||||
servers = append(servers, addr)
|
|
||||||
}
|
// Check for DNS manager signatures in comments
|
||||||
}
|
if strings.Contains(text, "NetworkManager") {
|
||||||
|
return NetworkManagerManager
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.Contains(text, "systemd-resolved") {
|
||||||
|
return SystemdResolvedManager
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.Contains(text, "resolvconf") {
|
||||||
|
return ResolvconfManager
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return servers, nil
|
if err := scanner.Err(); err != nil && err != io.EOF {
|
||||||
|
return UnknownManager
|
||||||
|
}
|
||||||
|
|
||||||
|
// No indicators found, assume file-based management
|
||||||
|
return FileManager
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetSystemDNS returns the current system DNS servers
|
// String returns a human-readable name for the DNS manager type
|
||||||
func GetSystemDNS() ([]netip.Addr, error) {
|
func (d DNSManagerType) String() string {
|
||||||
return readResolvConfDNS()
|
switch d {
|
||||||
|
case SystemdResolvedManager:
|
||||||
|
return "systemd-resolved"
|
||||||
|
case NetworkManagerManager:
|
||||||
|
return "NetworkManager"
|
||||||
|
case ResolvconfManager:
|
||||||
|
return "resolvconf"
|
||||||
|
case FileManager:
|
||||||
|
return "file"
|
||||||
|
default:
|
||||||
|
return "unknown"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DetectDNSManager combines file detection with runtime availability checks
|
||||||
|
// to determine the best DNS configurator to use
|
||||||
|
func DetectDNSManager(interfaceName string) DNSManagerType {
|
||||||
|
// First check what the file suggests
|
||||||
|
fileHint := DetectDNSManagerFromFile()
|
||||||
|
|
||||||
|
// Verify the hint with runtime checks
|
||||||
|
switch fileHint {
|
||||||
|
case SystemdResolvedManager:
|
||||||
|
// Verify systemd-resolved is actually running
|
||||||
|
if IsSystemdResolvedAvailable() {
|
||||||
|
return SystemdResolvedManager
|
||||||
|
}
|
||||||
|
logger.Warn("dns platform: Found systemd-resolved but it is not running. Falling back to file...")
|
||||||
|
os.Exit(0)
|
||||||
|
return FileManager
|
||||||
|
|
||||||
|
case NetworkManagerManager:
|
||||||
|
// Verify NetworkManager is actually running
|
||||||
|
if IsNetworkManagerAvailable() {
|
||||||
|
return NetworkManagerManager
|
||||||
|
}
|
||||||
|
logger.Warn("dns platform: Found network manager but it is not running. Falling back to file...")
|
||||||
|
return FileManager
|
||||||
|
|
||||||
|
case ResolvconfManager:
|
||||||
|
// Verify resolvconf is available
|
||||||
|
if IsResolvconfAvailable() {
|
||||||
|
return ResolvconfManager
|
||||||
|
}
|
||||||
|
// If resolvconf is mentioned but not available, fall back to file
|
||||||
|
return FileManager
|
||||||
|
|
||||||
|
case FileManager:
|
||||||
|
// File suggests direct file management
|
||||||
|
// But we should still check if a manager is available that wasn't mentioned
|
||||||
|
if IsSystemdResolvedAvailable() && interfaceName != "" {
|
||||||
|
return SystemdResolvedManager
|
||||||
|
}
|
||||||
|
if IsNetworkManagerAvailable() && interfaceName != "" {
|
||||||
|
return NetworkManagerManager
|
||||||
|
}
|
||||||
|
if IsResolvconfAvailable() && interfaceName != "" {
|
||||||
|
return ResolvconfManager
|
||||||
|
}
|
||||||
|
return FileManager
|
||||||
|
|
||||||
|
default:
|
||||||
|
// Unknown - do runtime detection
|
||||||
|
if IsSystemdResolvedAvailable() && interfaceName != "" {
|
||||||
|
return SystemdResolvedManager
|
||||||
|
}
|
||||||
|
if IsNetworkManagerAvailable() && interfaceName != "" {
|
||||||
|
return NetworkManagerManager
|
||||||
|
}
|
||||||
|
if IsResolvconfAvailable() && interfaceName != "" {
|
||||||
|
return ResolvconfManager
|
||||||
|
}
|
||||||
|
return FileManager
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,34 +0,0 @@
|
|||||||
//go:build windows
|
|
||||||
|
|
||||||
package dns
|
|
||||||
|
|
||||||
import "fmt"
|
|
||||||
|
|
||||||
// DetectBestConfigurator returns the Windows DNS configurator
|
|
||||||
// ifaceName should be the network interface GUID on Windows
|
|
||||||
func DetectBestConfigurator(ifaceName string) (DNSConfigurator, error) {
|
|
||||||
if ifaceName == "" {
|
|
||||||
return nil, fmt.Errorf("interface GUID is required for Windows")
|
|
||||||
}
|
|
||||||
return newWindowsDNSConfiguratorFromGUID(ifaceName)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetSystemDNS returns the current system DNS servers for the given interface
|
|
||||||
func GetSystemDNS(ifaceName string) ([]string, error) {
|
|
||||||
configurator, err := newWindowsDNSConfiguratorFromGUID(ifaceName)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("create configurator: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
servers, err := configurator.GetCurrentDNS()
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("get current DNS: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
var result []string
|
|
||||||
for _, server := range servers {
|
|
||||||
result = append(result, server.String())
|
|
||||||
}
|
|
||||||
|
|
||||||
return result, nil
|
|
||||||
}
|
|
||||||
394
olm/olm.go
394
olm/olm.go
@@ -21,6 +21,7 @@ import (
|
|||||||
dnsOverride "github.com/fosrl/olm/dns/override"
|
dnsOverride "github.com/fosrl/olm/dns/override"
|
||||||
"github.com/fosrl/olm/network"
|
"github.com/fosrl/olm/network"
|
||||||
"github.com/fosrl/olm/peermonitor"
|
"github.com/fosrl/olm/peermonitor"
|
||||||
|
"github.com/fosrl/olm/peers"
|
||||||
"github.com/fosrl/olm/websocket"
|
"github.com/fosrl/olm/websocket"
|
||||||
"golang.zx2c4.com/wireguard/device"
|
"golang.zx2c4.com/wireguard/device"
|
||||||
"golang.zx2c4.com/wireguard/tun"
|
"golang.zx2c4.com/wireguard/tun"
|
||||||
@@ -48,6 +49,7 @@ var (
|
|||||||
globalCtx context.Context
|
globalCtx context.Context
|
||||||
stopRegister func()
|
stopRegister func()
|
||||||
stopPing chan struct{}
|
stopPing chan struct{}
|
||||||
|
peerManager *peers.PeerManager
|
||||||
)
|
)
|
||||||
|
|
||||||
func Init(ctx context.Context, config GlobalConfig) {
|
func Init(ctx context.Context, config GlobalConfig) {
|
||||||
@@ -464,33 +466,16 @@ func StartTunnel(config TunnelConfig) {
|
|||||||
interfaceIP,
|
interfaceIP,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
peerManager = peers.NewPeerManager(dev, peerMonitor, dnsProxy, interfaceName, privateKey)
|
||||||
|
|
||||||
for i := range wgData.Sites {
|
for i := range wgData.Sites {
|
||||||
site := &wgData.Sites[i] // Use a pointer to modify the struct in the slice
|
site := wgData.Sites[i]
|
||||||
apiServer.UpdatePeerStatus(site.SiteId, false, 0, site.Endpoint, false)
|
apiServer.UpdatePeerStatus(site.SiteId, false, 0, site.Endpoint, false)
|
||||||
|
|
||||||
if err := ConfigurePeer(dev, *site, privateKey, endpoint); err != nil {
|
if err := peerManager.AddPeer(site, endpoint); err != nil {
|
||||||
logger.Error("Failed to configure peer: %v", err)
|
logger.Error("Failed to add peer: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err := network.AddRouteForServerIP(site.ServerIP, interfaceName); err != nil { // this is something for darwin only thats required
|
|
||||||
logger.Error("Failed to add route for peer: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if err := network.AddRoutes(site.RemoteSubnets, interfaceName); err != nil {
|
|
||||||
logger.Error("Failed to add routes for remote subnets: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, alias := range site.Aliases {
|
|
||||||
// try to parse the alias address into net.IP
|
|
||||||
address := net.ParseIP(alias.AliasAddress)
|
|
||||||
if address == nil {
|
|
||||||
logger.Warn("Invalid alias address for %s: %s", alias.Alias, alias.AliasAddress)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
dnsProxy.AddDNSRecord(alias.Alias, address)
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.Info("Configured peer %s", site.PublicKey)
|
logger.Info("Configured peer %s", site.PublicKey)
|
||||||
}
|
}
|
||||||
@@ -528,41 +513,21 @@ func StartTunnel(config TunnelConfig) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var updateData SiteConfig
|
var updateData peers.SiteConfig
|
||||||
if err := json.Unmarshal(jsonData, &updateData); err != nil {
|
if err := json.Unmarshal(jsonData, &updateData); err != nil {
|
||||||
logger.Error("Error unmarshaling update data: %v", err)
|
logger.Error("Error unmarshaling update data: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the peer in WireGuard
|
// Get existing peer from PeerManager
|
||||||
if dev == nil {
|
existingPeer, exists := peerManager.GetPeer(updateData.SiteId)
|
||||||
logger.Error("WireGuard device not initialized")
|
if !exists {
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find the existing peer to merge updates with
|
|
||||||
var existingPeer *SiteConfig
|
|
||||||
var peerIndex int
|
|
||||||
for i, site := range wgData.Sites {
|
|
||||||
if site.SiteId == updateData.SiteId {
|
|
||||||
existingPeer = &wgData.Sites[i]
|
|
||||||
peerIndex = i
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if existingPeer == nil {
|
|
||||||
logger.Error("Peer with site ID %d not found", updateData.SiteId)
|
logger.Error("Peer with site ID %d not found", updateData.SiteId)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store old values for comparison
|
|
||||||
oldRemoteSubnets := existingPeer.RemoteSubnets
|
|
||||||
oldPublicKey := existingPeer.PublicKey
|
|
||||||
|
|
||||||
// Create updated site config by merging with existing data
|
// Create updated site config by merging with existing data
|
||||||
// Only update fields that are provided (non-empty/non-zero)
|
siteConfig := existingPeer
|
||||||
siteConfig := *existingPeer // Start with existing data
|
|
||||||
|
|
||||||
if updateData.Endpoint != "" {
|
if updateData.Endpoint != "" {
|
||||||
siteConfig.Endpoint = updateData.Endpoint
|
siteConfig.Endpoint = updateData.Endpoint
|
||||||
@@ -580,37 +545,13 @@ func StartTunnel(config TunnelConfig) {
|
|||||||
siteConfig.RemoteSubnets = updateData.RemoteSubnets
|
siteConfig.RemoteSubnets = updateData.RemoteSubnets
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the public key has changed, remove the old peer first
|
if err := peerManager.UpdatePeer(siteConfig, endpoint); err != nil {
|
||||||
if siteConfig.PublicKey != oldPublicKey {
|
|
||||||
logger.Info("Public key changed for site %d, removing old peer with key %s", updateData.SiteId, oldPublicKey)
|
|
||||||
if err := RemovePeer(dev, updateData.SiteId, oldPublicKey); err != nil {
|
|
||||||
logger.Error("Failed to remove old peer: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := ConfigurePeer(dev, siteConfig, privateKey, endpoint); err != nil {
|
|
||||||
logger.Error("Failed to update peer: %v", err)
|
logger.Error("Failed to update peer: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle remote subnet route changes
|
|
||||||
if !stringSlicesEqual(oldRemoteSubnets, siteConfig.RemoteSubnets) {
|
|
||||||
if err := network.RemoveRoutes(oldRemoteSubnets); err != nil {
|
|
||||||
logger.Error("Failed to remove old remote subnet routes: %v", err)
|
|
||||||
// Continue anyway to add new routes
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add new remote subnet routes
|
|
||||||
if err := network.AddRoutes(siteConfig.RemoteSubnets, interfaceName); err != nil {
|
|
||||||
logger.Error("Failed to add new remote subnet routes: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update successful
|
// Update successful
|
||||||
logger.Info("Successfully updated peer for site %d", updateData.SiteId)
|
logger.Info("Successfully updated peer for site %d", updateData.SiteId)
|
||||||
wgData.Sites[peerIndex] = siteConfig
|
|
||||||
})
|
})
|
||||||
|
|
||||||
// Handler for adding a new peer
|
// Handler for adding a new peer
|
||||||
@@ -623,46 +564,19 @@ func StartTunnel(config TunnelConfig) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var siteConfig SiteConfig
|
var siteConfig peers.SiteConfig
|
||||||
if err := json.Unmarshal(jsonData, &siteConfig); err != nil {
|
if err := json.Unmarshal(jsonData, &siteConfig); err != nil {
|
||||||
logger.Error("Error unmarshaling add data: %v", err)
|
logger.Error("Error unmarshaling add data: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the peer to WireGuard
|
if err := peerManager.AddPeer(siteConfig, endpoint); err != nil {
|
||||||
if dev == nil {
|
|
||||||
logger.Error("WireGuard device not initialized")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := ConfigurePeer(dev, siteConfig, privateKey, endpoint); err != nil {
|
|
||||||
logger.Error("Failed to add peer: %v", err)
|
logger.Error("Failed to add peer: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err := network.AddRouteForServerIP(siteConfig.ServerIP, interfaceName); err != nil {
|
|
||||||
logger.Error("Failed to add route for new peer: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if err := network.AddRoutes(siteConfig.RemoteSubnets, interfaceName); err != nil {
|
|
||||||
logger.Error("Failed to add routes for remote subnets: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
for _, alias := range siteConfig.Aliases {
|
|
||||||
// try to parse the alias address into net.IP
|
|
||||||
address := net.ParseIP(alias.AliasAddress)
|
|
||||||
if address == nil {
|
|
||||||
logger.Warn("Invalid alias address for %s: %s", alias.Alias, alias.AliasAddress)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
dnsProxy.AddDNSRecord(alias.Alias, address)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add successful
|
// Add successful
|
||||||
logger.Info("Successfully added peer for site %d", siteConfig.SiteId)
|
logger.Info("Successfully added peer for site %d", siteConfig.SiteId)
|
||||||
|
|
||||||
// Update WgData with the new peer
|
|
||||||
wgData.Sites = append(wgData.Sites, siteConfig)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
// Handler for removing a peer
|
// Handler for removing a peer
|
||||||
@@ -675,69 +589,19 @@ func StartTunnel(config TunnelConfig) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var removeData PeerRemove
|
var removeData peers.PeerRemove
|
||||||
if err := json.Unmarshal(jsonData, &removeData); err != nil {
|
if err := json.Unmarshal(jsonData, &removeData); err != nil {
|
||||||
logger.Error("Error unmarshaling remove data: %v", err)
|
logger.Error("Error unmarshaling remove data: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find the peer to remove
|
if err := peerManager.RemovePeer(removeData.SiteId); err != nil {
|
||||||
var peerToRemove *SiteConfig
|
|
||||||
var newSites []SiteConfig
|
|
||||||
|
|
||||||
for _, site := range wgData.Sites {
|
|
||||||
if site.SiteId == removeData.SiteId {
|
|
||||||
peerToRemove = &site
|
|
||||||
} else {
|
|
||||||
newSites = append(newSites, site)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if peerToRemove == nil {
|
|
||||||
logger.Error("Peer with site ID %d not found", removeData.SiteId)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove the peer from WireGuard
|
|
||||||
if dev == nil {
|
|
||||||
logger.Error("WireGuard device not initialized")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if err := RemovePeer(dev, removeData.SiteId, peerToRemove.PublicKey); err != nil {
|
|
||||||
logger.Error("Failed to remove peer: %v", err)
|
logger.Error("Failed to remove peer: %v", err)
|
||||||
// Send error response if needed
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove route for the peer
|
|
||||||
err = network.RemoveRouteForServerIP(peerToRemove.ServerIP, interfaceName)
|
|
||||||
if err != nil {
|
|
||||||
logger.Error("Failed to remove route for peer: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove routes for remote subnets
|
|
||||||
if err := network.RemoveRoutes(peerToRemove.RemoteSubnets); err != nil {
|
|
||||||
logger.Error("Failed to remove routes for remote subnets: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, alias := range peerToRemove.Aliases {
|
|
||||||
// try to parse the alias address into net.IP
|
|
||||||
address := net.ParseIP(alias.AliasAddress)
|
|
||||||
if address == nil {
|
|
||||||
logger.Warn("Invalid alias address for %s: %s", alias.Alias, alias.AliasAddress)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
dnsProxy.RemoveDNSRecord(alias.Alias, address)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove successful
|
// Remove successful
|
||||||
logger.Info("Successfully removed peer for site %d", removeData.SiteId)
|
logger.Info("Successfully removed peer for site %d", removeData.SiteId)
|
||||||
|
|
||||||
// Update WgData to remove the peer
|
|
||||||
wgData.Sites = newSites
|
|
||||||
})
|
})
|
||||||
|
|
||||||
// Handler for adding remote subnets to a peer
|
// Handler for adding remote subnets to a peer
|
||||||
@@ -750,77 +614,25 @@ func StartTunnel(config TunnelConfig) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var addSubnetsData PeerAdd
|
var addSubnetsData peers.PeerAdd
|
||||||
if err := json.Unmarshal(jsonData, &addSubnetsData); err != nil {
|
if err := json.Unmarshal(jsonData, &addSubnetsData); err != nil {
|
||||||
logger.Error("Error unmarshaling add-remote-subnets data: %v", err)
|
logger.Error("Error unmarshaling add-remote-subnets data: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find the peer to update
|
// Add new subnets
|
||||||
var peerIndex = -1
|
|
||||||
for i, site := range wgData.Sites {
|
|
||||||
if site.SiteId == addSubnetsData.SiteId {
|
|
||||||
peerIndex = i
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if peerIndex == -1 {
|
|
||||||
logger.Error("Peer with site ID %d not found", addSubnetsData.SiteId)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add new subnets to the peer's remote subnets (avoiding duplicates)
|
|
||||||
existingSubnets := make(map[string]bool)
|
|
||||||
for _, subnet := range wgData.Sites[peerIndex].RemoteSubnets {
|
|
||||||
existingSubnets[subnet] = true
|
|
||||||
}
|
|
||||||
|
|
||||||
var newSubnets []string
|
|
||||||
for _, subnet := range addSubnetsData.RemoteSubnets {
|
for _, subnet := range addSubnetsData.RemoteSubnets {
|
||||||
if !existingSubnets[subnet] {
|
if err := peerManager.AddRemoteSubnet(addSubnetsData.SiteId, subnet); err != nil {
|
||||||
newSubnets = append(newSubnets, subnet)
|
logger.Error("Failed to add allowed IP %s: %v", subnet, err)
|
||||||
wgData.Sites[peerIndex].RemoteSubnets = append(wgData.Sites[peerIndex].RemoteSubnets, subnet)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(newSubnets) == 0 {
|
// Add new aliases
|
||||||
logger.Info("No new subnets to add for site %d (all already exist)", addSubnetsData.SiteId)
|
|
||||||
// Still process aliases even if no new subnets
|
|
||||||
} else {
|
|
||||||
// Add routes for the new subnets
|
|
||||||
if err := network.AddRoutes(newSubnets, interfaceName); err != nil {
|
|
||||||
logger.Error("Failed to add routes for new remote subnets: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
logger.Info("Successfully added %d remote subnet(s) to peer %d", len(newSubnets), addSubnetsData.SiteId)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add new aliases to the peer's aliases (avoiding duplicates)
|
|
||||||
existingAliases := make(map[string]bool)
|
|
||||||
for _, alias := range wgData.Sites[peerIndex].Aliases {
|
|
||||||
existingAliases[alias.Alias] = true
|
|
||||||
}
|
|
||||||
|
|
||||||
var newAliases []Alias
|
|
||||||
for _, alias := range addSubnetsData.Aliases {
|
for _, alias := range addSubnetsData.Aliases {
|
||||||
if !existingAliases[alias.Alias] {
|
if err := peerManager.AddAlias(addSubnetsData.SiteId, alias); err != nil {
|
||||||
address := net.ParseIP(alias.AliasAddress)
|
logger.Error("Failed to add alias %s: %v", alias.Alias, err)
|
||||||
if address == nil {
|
|
||||||
logger.Warn("Invalid alias address for %s: %s", alias.Alias, alias.AliasAddress)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add DNS record
|
|
||||||
dnsProxy.AddDNSRecord(alias.Alias, address)
|
|
||||||
newAliases = append(newAliases, alias)
|
|
||||||
wgData.Sites[peerIndex].Aliases = append(wgData.Sites[peerIndex].Aliases, alias)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(newAliases) > 0 {
|
|
||||||
logger.Info("Successfully added %d alias(es) to peer %d", len(newAliases), addSubnetsData.SiteId)
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
// Handler for removing remote subnets from a peer
|
// Handler for removing remote subnets from a peer
|
||||||
@@ -833,90 +645,25 @@ func StartTunnel(config TunnelConfig) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var removeSubnetsData RemovePeerData
|
var removeSubnetsData peers.RemovePeerData
|
||||||
if err := json.Unmarshal(jsonData, &removeSubnetsData); err != nil {
|
if err := json.Unmarshal(jsonData, &removeSubnetsData); err != nil {
|
||||||
logger.Error("Error unmarshaling remove-remote-subnets data: %v", err)
|
logger.Error("Error unmarshaling remove-remote-subnets data: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find the peer to update
|
// Remove subnets
|
||||||
var peerIndex = -1
|
|
||||||
for i, site := range wgData.Sites {
|
|
||||||
if site.SiteId == removeSubnetsData.SiteId {
|
|
||||||
peerIndex = i
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if peerIndex == -1 {
|
|
||||||
logger.Error("Peer with site ID %d not found", removeSubnetsData.SiteId)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a map of subnets to remove for quick lookup
|
|
||||||
subnetsToRemove := make(map[string]bool)
|
|
||||||
for _, subnet := range removeSubnetsData.RemoteSubnets {
|
for _, subnet := range removeSubnetsData.RemoteSubnets {
|
||||||
subnetsToRemove[subnet] = true
|
if err := peerManager.RemoveRemoteSubnet(removeSubnetsData.SiteId, subnet); err != nil {
|
||||||
}
|
logger.Error("Failed to remove allowed IP %s: %v", subnet, err)
|
||||||
|
|
||||||
// Filter out the subnets to remove
|
|
||||||
var updatedSubnets []string
|
|
||||||
var removedSubnets []string
|
|
||||||
for _, subnet := range wgData.Sites[peerIndex].RemoteSubnets {
|
|
||||||
if subnetsToRemove[subnet] {
|
|
||||||
removedSubnets = append(removedSubnets, subnet)
|
|
||||||
} else {
|
|
||||||
updatedSubnets = append(updatedSubnets, subnet)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(removedSubnets) == 0 {
|
// Remove aliases
|
||||||
logger.Info("No subnets to remove for site %d (none matched)", removeSubnetsData.SiteId)
|
|
||||||
// Still process aliases even if no subnets to remove
|
|
||||||
} else {
|
|
||||||
// Remove routes for the removed subnets
|
|
||||||
if err := network.RemoveRoutes(removedSubnets); err != nil {
|
|
||||||
logger.Error("Failed to remove routes for remote subnets: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update the peer's remote subnets
|
|
||||||
wgData.Sites[peerIndex].RemoteSubnets = updatedSubnets
|
|
||||||
logger.Info("Successfully removed %d remote subnet(s) from peer %d", len(removedSubnets), removeSubnetsData.SiteId)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a map of aliases to remove for quick lookup
|
|
||||||
aliasesToRemove := make(map[string]bool)
|
|
||||||
for _, alias := range removeSubnetsData.Aliases {
|
for _, alias := range removeSubnetsData.Aliases {
|
||||||
aliasesToRemove[alias.Alias] = true
|
if err := peerManager.RemoveAlias(removeSubnetsData.SiteId, alias.Alias); err != nil {
|
||||||
}
|
logger.Error("Failed to remove alias %s: %v", alias.Alias, err)
|
||||||
|
|
||||||
// Filter out the aliases to remove
|
|
||||||
var updatedAliases []Alias
|
|
||||||
var removedAliases []Alias
|
|
||||||
for _, alias := range wgData.Sites[peerIndex].Aliases {
|
|
||||||
if aliasesToRemove[alias.Alias] {
|
|
||||||
removedAliases = append(removedAliases, alias)
|
|
||||||
} else {
|
|
||||||
updatedAliases = append(updatedAliases, alias)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(removedAliases) > 0 {
|
|
||||||
// Remove DNS records for the removed aliases
|
|
||||||
for _, alias := range removedAliases {
|
|
||||||
address := net.ParseIP(alias.AliasAddress)
|
|
||||||
if address == nil {
|
|
||||||
logger.Warn("Invalid alias address for %s: %s", alias.Alias, alias.AliasAddress)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
dnsProxy.RemoveDNSRecord(alias.Alias, address)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update the peer's aliases
|
|
||||||
wgData.Sites[peerIndex].Aliases = updatedAliases
|
|
||||||
logger.Info("Successfully removed %d alias(es) from peer %d", len(removedAliases), removeSubnetsData.SiteId)
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
// Handler for updating remote subnets of a peer (remove old, add new in one operation)
|
// Handler for updating remote subnets of a peer (remove old, add new in one operation)
|
||||||
@@ -929,82 +676,41 @@ func StartTunnel(config TunnelConfig) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var updateSubnetsData UpdatePeerData
|
var updateSubnetsData peers.UpdatePeerData
|
||||||
if err := json.Unmarshal(jsonData, &updateSubnetsData); err != nil {
|
if err := json.Unmarshal(jsonData, &updateSubnetsData); err != nil {
|
||||||
logger.Error("Error unmarshaling update-remote-subnets data: %v", err)
|
logger.Error("Error unmarshaling update-remote-subnets data: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find the peer to update
|
// Remove old subnets
|
||||||
var peerIndex = -1
|
for _, subnet := range updateSubnetsData.OldRemoteSubnets {
|
||||||
for i, site := range wgData.Sites {
|
if err := peerManager.RemoveRemoteSubnet(updateSubnetsData.SiteId, subnet); err != nil {
|
||||||
if site.SiteId == updateSubnetsData.SiteId {
|
logger.Error("Failed to remove allowed IP %s: %v", subnet, err)
|
||||||
peerIndex = i
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if peerIndex == -1 {
|
// Add new subnets
|
||||||
logger.Error("Peer with site ID %d not found", updateSubnetsData.SiteId)
|
for _, subnet := range updateSubnetsData.NewRemoteSubnets {
|
||||||
return
|
if err := peerManager.AddRemoteSubnet(updateSubnetsData.SiteId, subnet); err != nil {
|
||||||
}
|
logger.Error("Failed to add allowed IP %s: %v", subnet, err)
|
||||||
|
|
||||||
// First, remove routes for old subnets
|
|
||||||
if len(updateSubnetsData.OldRemoteSubnets) > 0 {
|
|
||||||
if err := network.RemoveRoutes(updateSubnetsData.OldRemoteSubnets); err != nil {
|
|
||||||
logger.Error("Failed to remove routes for old remote subnets: %v", err)
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
logger.Info("Removed %d old remote subnet(s) from peer %d", len(updateSubnetsData.OldRemoteSubnets), updateSubnetsData.SiteId)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Then, add routes for new subnets
|
// Remove old aliases
|
||||||
if len(updateSubnetsData.NewRemoteSubnets) > 0 {
|
for _, alias := range updateSubnetsData.OldAliases {
|
||||||
if err := network.AddRoutes(updateSubnetsData.NewRemoteSubnets, interfaceName); err != nil {
|
if err := peerManager.RemoveAlias(updateSubnetsData.SiteId, alias.Alias); err != nil {
|
||||||
logger.Error("Failed to add routes for new remote subnets: %v", err)
|
logger.Error("Failed to remove alias %s: %v", alias.Alias, err)
|
||||||
// Attempt to rollback by re-adding old routes
|
|
||||||
if rollbackErr := network.AddRoutes(updateSubnetsData.OldRemoteSubnets, interfaceName); rollbackErr != nil {
|
|
||||||
logger.Error("Failed to rollback old routes: %v", rollbackErr)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
logger.Info("Added %d new remote subnet(s) to peer %d", len(updateSubnetsData.NewRemoteSubnets), updateSubnetsData.SiteId)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finally, update the peer's remote subnets in wgData
|
// Add new aliases
|
||||||
wgData.Sites[peerIndex].RemoteSubnets = updateSubnetsData.NewRemoteSubnets
|
for _, alias := range updateSubnetsData.NewAliases {
|
||||||
|
if err := peerManager.AddAlias(updateSubnetsData.SiteId, alias); err != nil {
|
||||||
logger.Info("Successfully updated remote subnets for peer %d (removed %d, added %d)",
|
logger.Error("Failed to add alias %s: %v", alias.Alias, err)
|
||||||
updateSubnetsData.SiteId, len(updateSubnetsData.OldRemoteSubnets), len(updateSubnetsData.NewRemoteSubnets))
|
|
||||||
|
|
||||||
// Remove DNS records for old aliases
|
|
||||||
if len(updateSubnetsData.OldAliases) > 0 {
|
|
||||||
for _, alias := range updateSubnetsData.OldAliases {
|
|
||||||
address := net.ParseIP(alias.AliasAddress)
|
|
||||||
if address == nil {
|
|
||||||
logger.Warn("Invalid old alias address for %s: %s", alias.Alias, alias.AliasAddress)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
dnsProxy.RemoveDNSRecord(alias.Alias, address)
|
|
||||||
}
|
}
|
||||||
logger.Info("Removed %d old alias(es) from peer %d", len(updateSubnetsData.OldAliases), updateSubnetsData.SiteId)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add DNS records for new aliases
|
logger.Info("Successfully updated remote subnets and aliases for peer %d", updateSubnetsData.SiteId)
|
||||||
if len(updateSubnetsData.NewAliases) > 0 {
|
|
||||||
for _, alias := range updateSubnetsData.NewAliases {
|
|
||||||
address := net.ParseIP(alias.AliasAddress)
|
|
||||||
if address == nil {
|
|
||||||
logger.Warn("Invalid new alias address for %s: %s", alias.Alias, alias.AliasAddress)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
dnsProxy.AddDNSRecord(alias.Alias, address)
|
|
||||||
}
|
|
||||||
logger.Info("Added %d new alias(es) to peer %d", len(updateSubnetsData.NewAliases), updateSubnetsData.SiteId)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update the peer's aliases in wgData
|
|
||||||
wgData.Sites[peerIndex].Aliases = updateSubnetsData.NewAliases
|
|
||||||
})
|
})
|
||||||
|
|
||||||
olm.RegisterHandler("olm/wg/peer/relay", func(msg websocket.WSMessage) {
|
olm.RegisterHandler("olm/wg/peer/relay", func(msg websocket.WSMessage) {
|
||||||
@@ -1016,7 +722,7 @@ func StartTunnel(config TunnelConfig) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var relayData RelayPeerData
|
var relayData peers.RelayPeerData
|
||||||
if err := json.Unmarshal(jsonData, &relayData); err != nil {
|
if err := json.Unmarshal(jsonData, &relayData); err != nil {
|
||||||
logger.Error("Error unmarshaling relay data: %v", err)
|
logger.Error("Error unmarshaling relay data: %v", err)
|
||||||
return
|
return
|
||||||
|
|||||||
67
olm/types.go
67
olm/types.go
@@ -1,11 +1,15 @@
|
|||||||
package olm
|
package olm
|
||||||
|
|
||||||
import "time"
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/fosrl/olm/peers"
|
||||||
|
)
|
||||||
|
|
||||||
type WgData struct {
|
type WgData struct {
|
||||||
Sites []SiteConfig `json:"sites"`
|
Sites []peers.SiteConfig `json:"sites"`
|
||||||
TunnelIP string `json:"tunnelIP"`
|
TunnelIP string `json:"tunnelIP"`
|
||||||
UtilitySubnet string `json:"utilitySubnet"` // this is for things like the DNS server, and alias addresses
|
UtilitySubnet string `json:"utilitySubnet"` // this is for things like the DNS server, and alias addresses
|
||||||
}
|
}
|
||||||
|
|
||||||
type HolePunchMessage struct {
|
type HolePunchMessage struct {
|
||||||
@@ -27,61 +31,6 @@ type EncryptedHolePunchMessage struct {
|
|||||||
Ciphertext []byte `json:"ciphertext"`
|
Ciphertext []byte `json:"ciphertext"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// PeerAction represents a request to add, update, or remove a peer
|
|
||||||
type PeerAction struct {
|
|
||||||
Action string `json:"action"` // "add", "update", or "remove"
|
|
||||||
SiteInfo SiteConfig `json:"siteInfo"` // Site configuration information
|
|
||||||
}
|
|
||||||
|
|
||||||
// UpdatePeerData represents the data needed to update a peer
|
|
||||||
type SiteConfig struct {
|
|
||||||
SiteId int `json:"siteId"`
|
|
||||||
Endpoint string `json:"endpoint,omitempty"`
|
|
||||||
PublicKey string `json:"publicKey,omitempty"`
|
|
||||||
ServerIP string `json:"serverIP,omitempty"`
|
|
||||||
ServerPort uint16 `json:"serverPort,omitempty"`
|
|
||||||
RemoteSubnets []string `json:"remoteSubnets,omitempty"` // optional, array of subnets that this site can access
|
|
||||||
Aliases []Alias `json:"aliases,omitempty"` // optional, array of alias configurations
|
|
||||||
}
|
|
||||||
|
|
||||||
type Alias struct {
|
|
||||||
Alias string `json:"alias"` // the alias name
|
|
||||||
AliasAddress string `json:"aliasAddress"` // the alias IP address
|
|
||||||
}
|
|
||||||
|
|
||||||
// RemovePeer represents the data needed to remove a peer
|
|
||||||
type PeerRemove struct {
|
|
||||||
SiteId int `json:"siteId"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type RelayPeerData struct {
|
|
||||||
SiteId int `json:"siteId"`
|
|
||||||
Endpoint string `json:"endpoint"`
|
|
||||||
PublicKey string `json:"publicKey"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// PeerAdd represents the data needed to add remote subnets to a peer
|
|
||||||
type PeerAdd struct {
|
|
||||||
SiteId int `json:"siteId"`
|
|
||||||
RemoteSubnets []string `json:"remoteSubnets"` // subnets to add
|
|
||||||
Aliases []Alias `json:"aliases,omitempty"` // aliases to add
|
|
||||||
}
|
|
||||||
|
|
||||||
// RemovePeerData represents the data needed to remove remote subnets from a peer
|
|
||||||
type RemovePeerData struct {
|
|
||||||
SiteId int `json:"siteId"`
|
|
||||||
RemoteSubnets []string `json:"remoteSubnets"` // subnets to remove
|
|
||||||
Aliases []Alias `json:"aliases,omitempty"` // aliases to remove
|
|
||||||
}
|
|
||||||
|
|
||||||
type UpdatePeerData struct {
|
|
||||||
SiteId int `json:"siteId"`
|
|
||||||
OldRemoteSubnets []string `json:"oldRemoteSubnets"` // old list of remote subnets
|
|
||||||
NewRemoteSubnets []string `json:"newRemoteSubnets"` // new list of remote subnets
|
|
||||||
OldAliases []Alias `json:"oldAliases,omitempty"` // old list of aliases
|
|
||||||
NewAliases []Alias `json:"newAliases,omitempty"` // new list of aliases
|
|
||||||
}
|
|
||||||
|
|
||||||
type GlobalConfig struct {
|
type GlobalConfig struct {
|
||||||
// Logging
|
// Logging
|
||||||
LogLevel string
|
LogLevel string
|
||||||
|
|||||||
401
peers/manager.go
Normal file
401
peers/manager.go
Normal file
@@ -0,0 +1,401 @@
|
|||||||
|
package peers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/fosrl/newt/logger"
|
||||||
|
"github.com/fosrl/olm/dns"
|
||||||
|
"github.com/fosrl/olm/network"
|
||||||
|
"github.com/fosrl/olm/peermonitor"
|
||||||
|
"golang.zx2c4.com/wireguard/device"
|
||||||
|
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
||||||
|
)
|
||||||
|
|
||||||
|
type PeerManager struct {
|
||||||
|
mu sync.RWMutex
|
||||||
|
device *device.Device
|
||||||
|
peers map[int]SiteConfig
|
||||||
|
peerMonitor *peermonitor.PeerMonitor
|
||||||
|
dnsProxy *dns.DNSProxy
|
||||||
|
interfaceName string
|
||||||
|
privateKey wgtypes.Key
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewPeerManager(dev *device.Device, monitor *peermonitor.PeerMonitor, dnsProxy *dns.DNSProxy, interfaceName string, privateKey wgtypes.Key) *PeerManager {
|
||||||
|
return &PeerManager{
|
||||||
|
device: dev,
|
||||||
|
peers: make(map[int]SiteConfig),
|
||||||
|
peerMonitor: monitor,
|
||||||
|
dnsProxy: dnsProxy,
|
||||||
|
interfaceName: interfaceName,
|
||||||
|
privateKey: privateKey,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pm *PeerManager) GetPeer(siteId int) (SiteConfig, bool) {
|
||||||
|
pm.mu.RLock()
|
||||||
|
defer pm.mu.RUnlock()
|
||||||
|
peer, ok := pm.peers[siteId]
|
||||||
|
return peer, ok
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pm *PeerManager) GetAllPeers() []SiteConfig {
|
||||||
|
pm.mu.RLock()
|
||||||
|
defer pm.mu.RUnlock()
|
||||||
|
peers := make([]SiteConfig, 0, len(pm.peers))
|
||||||
|
for _, peer := range pm.peers {
|
||||||
|
peers = append(peers, peer)
|
||||||
|
}
|
||||||
|
return peers
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pm *PeerManager) AddPeer(siteConfig SiteConfig, endpoint string) error {
|
||||||
|
pm.mu.Lock()
|
||||||
|
defer pm.mu.Unlock()
|
||||||
|
|
||||||
|
// build the allowed IPs list from the remote subnets and aliases and add them to the peer
|
||||||
|
allowedIPs := make([]string, 0, len(siteConfig.RemoteSubnets)+len(siteConfig.Aliases))
|
||||||
|
allowedIPs = append(allowedIPs, siteConfig.RemoteSubnets...)
|
||||||
|
for _, alias := range siteConfig.Aliases {
|
||||||
|
allowedIPs = append(allowedIPs, alias.AliasAddress+"/32")
|
||||||
|
}
|
||||||
|
siteConfig.AllowedIps = allowedIPs
|
||||||
|
|
||||||
|
if err := ConfigurePeer(pm.device, siteConfig, pm.privateKey, endpoint, pm.peerMonitor); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := network.AddRouteForServerIP(siteConfig.ServerIP, pm.interfaceName); err != nil {
|
||||||
|
logger.Error("Failed to add route for server IP: %v", err)
|
||||||
|
}
|
||||||
|
if err := network.AddRoutes(siteConfig.RemoteSubnets, pm.interfaceName); err != nil {
|
||||||
|
logger.Error("Failed to add routes for remote subnets: %v", err)
|
||||||
|
}
|
||||||
|
for _, alias := range siteConfig.Aliases {
|
||||||
|
address := net.ParseIP(alias.AliasAddress)
|
||||||
|
if address == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
pm.dnsProxy.AddDNSRecord(alias.Alias, address)
|
||||||
|
}
|
||||||
|
|
||||||
|
pm.peers[siteConfig.SiteId] = siteConfig
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pm *PeerManager) RemovePeer(siteId int) error {
|
||||||
|
pm.mu.Lock()
|
||||||
|
defer pm.mu.Unlock()
|
||||||
|
|
||||||
|
peer, exists := pm.peers[siteId]
|
||||||
|
if !exists {
|
||||||
|
return fmt.Errorf("peer with site ID %d not found", siteId)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := RemovePeer(pm.device, siteId, peer.PublicKey, pm.peerMonitor); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := network.RemoveRouteForServerIP(peer.ServerIP, pm.interfaceName); err != nil {
|
||||||
|
logger.Error("Failed to remove route for server IP: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := network.RemoveRoutes(peer.RemoteSubnets); err != nil {
|
||||||
|
logger.Error("Failed to remove routes for remote subnets: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// For aliases
|
||||||
|
for _, alias := range peer.Aliases {
|
||||||
|
address := net.ParseIP(alias.AliasAddress)
|
||||||
|
if address == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
pm.dnsProxy.RemoveDNSRecord(alias.Alias, address)
|
||||||
|
}
|
||||||
|
|
||||||
|
delete(pm.peers, siteId)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pm *PeerManager) UpdatePeer(siteConfig SiteConfig, endpoint string) error {
|
||||||
|
pm.mu.Lock()
|
||||||
|
defer pm.mu.Unlock()
|
||||||
|
|
||||||
|
oldPeer, exists := pm.peers[siteConfig.SiteId]
|
||||||
|
if !exists {
|
||||||
|
return fmt.Errorf("peer with site ID %d not found", siteConfig.SiteId)
|
||||||
|
}
|
||||||
|
|
||||||
|
// If public key changed, remove old peer first
|
||||||
|
if siteConfig.PublicKey != oldPeer.PublicKey {
|
||||||
|
if err := RemovePeer(pm.device, siteConfig.SiteId, oldPeer.PublicKey, pm.peerMonitor); err != nil {
|
||||||
|
logger.Error("Failed to remove old peer: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := ConfigurePeer(pm.device, siteConfig, pm.privateKey, endpoint, pm.peerMonitor); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle remote subnet route changes
|
||||||
|
// Calculate added and removed subnets
|
||||||
|
oldSubnets := make(map[string]bool)
|
||||||
|
for _, s := range oldPeer.RemoteSubnets {
|
||||||
|
oldSubnets[s] = true
|
||||||
|
}
|
||||||
|
newSubnets := make(map[string]bool)
|
||||||
|
for _, s := range siteConfig.RemoteSubnets {
|
||||||
|
newSubnets[s] = true
|
||||||
|
}
|
||||||
|
|
||||||
|
var addedSubnets []string
|
||||||
|
var removedSubnets []string
|
||||||
|
|
||||||
|
for s := range newSubnets {
|
||||||
|
if !oldSubnets[s] {
|
||||||
|
addedSubnets = append(addedSubnets, s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for s := range oldSubnets {
|
||||||
|
if !newSubnets[s] {
|
||||||
|
removedSubnets = append(removedSubnets, s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove routes for removed subnets
|
||||||
|
if len(removedSubnets) > 0 {
|
||||||
|
if err := network.RemoveRoutes(removedSubnets); err != nil {
|
||||||
|
logger.Error("Failed to remove routes: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add routes for added subnets
|
||||||
|
if len(addedSubnets) > 0 {
|
||||||
|
if err := network.AddRoutes(addedSubnets, pm.interfaceName); err != nil {
|
||||||
|
logger.Error("Failed to add routes: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update aliases
|
||||||
|
// Remove old aliases
|
||||||
|
for _, alias := range oldPeer.Aliases {
|
||||||
|
address := net.ParseIP(alias.AliasAddress)
|
||||||
|
if address == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
pm.dnsProxy.RemoveDNSRecord(alias.Alias, address)
|
||||||
|
}
|
||||||
|
// Add new aliases
|
||||||
|
for _, alias := range siteConfig.Aliases {
|
||||||
|
address := net.ParseIP(alias.AliasAddress)
|
||||||
|
if address == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
pm.dnsProxy.AddDNSRecord(alias.Alias, address)
|
||||||
|
}
|
||||||
|
|
||||||
|
pm.peers[siteConfig.SiteId] = siteConfig
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// addAllowedIp adds an IP (subnet) to the allowed IPs list of a peer
|
||||||
|
// and updates WireGuard configuration. Must be called with lock held.
|
||||||
|
func (pm *PeerManager) addAllowedIp(siteId int, ip string) error {
|
||||||
|
peer, exists := pm.peers[siteId]
|
||||||
|
if !exists {
|
||||||
|
return fmt.Errorf("peer with site ID %d not found", siteId)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if IP already exists in AllowedIps
|
||||||
|
for _, allowedIp := range peer.AllowedIps {
|
||||||
|
if allowedIp == ip {
|
||||||
|
return nil // Already exists
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
peer.AllowedIps = append(peer.AllowedIps, ip)
|
||||||
|
|
||||||
|
// Update WireGuard
|
||||||
|
if err := ConfigurePeer(pm.device, peer, pm.privateKey, peer.Endpoint, pm.peerMonitor); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
pm.peers[siteId] = peer
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// removeAllowedIp removes an IP (subnet) from the allowed IPs list of a peer
|
||||||
|
// and updates WireGuard configuration. Must be called with lock held.
|
||||||
|
func (pm *PeerManager) removeAllowedIp(siteId int, cidr string) error {
|
||||||
|
peer, exists := pm.peers[siteId]
|
||||||
|
if !exists {
|
||||||
|
return fmt.Errorf("peer with site ID %d not found", siteId)
|
||||||
|
}
|
||||||
|
|
||||||
|
found := false
|
||||||
|
|
||||||
|
// Remove from AllowedIps
|
||||||
|
newAllowedIps := make([]string, 0, len(peer.AllowedIps))
|
||||||
|
for _, allowedIp := range peer.AllowedIps {
|
||||||
|
if allowedIp == cidr {
|
||||||
|
found = true
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
newAllowedIps = append(newAllowedIps, allowedIp)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !found {
|
||||||
|
return nil // Not found
|
||||||
|
}
|
||||||
|
|
||||||
|
peer.AllowedIps = newAllowedIps
|
||||||
|
|
||||||
|
// Update WireGuard
|
||||||
|
if err := ConfigurePeer(pm.device, peer, pm.privateKey, peer.Endpoint, pm.peerMonitor); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
pm.peers[siteId] = peer
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddRemoteSubnet adds an IP (subnet) to the allowed IPs list of a peer
|
||||||
|
func (pm *PeerManager) AddRemoteSubnet(siteId int, cidr string) error {
|
||||||
|
pm.mu.Lock()
|
||||||
|
defer pm.mu.Unlock()
|
||||||
|
|
||||||
|
peer, exists := pm.peers[siteId]
|
||||||
|
if !exists {
|
||||||
|
return fmt.Errorf("peer with site ID %d not found", siteId)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if IP already exists in RemoteSubnets
|
||||||
|
for _, subnet := range peer.RemoteSubnets {
|
||||||
|
if subnet == cidr {
|
||||||
|
return nil // Already exists
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
peer.RemoteSubnets = append(peer.RemoteSubnets, cidr)
|
||||||
|
|
||||||
|
// Add to allowed IPs
|
||||||
|
if err := pm.addAllowedIp(siteId, cidr); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add route
|
||||||
|
if err := network.AddRoutes([]string{cidr}, pm.interfaceName); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveRemoteSubnet removes an IP (subnet) from the allowed IPs list of a peer
|
||||||
|
func (pm *PeerManager) RemoveRemoteSubnet(siteId int, ip string) error {
|
||||||
|
pm.mu.Lock()
|
||||||
|
defer pm.mu.Unlock()
|
||||||
|
|
||||||
|
peer, exists := pm.peers[siteId]
|
||||||
|
if !exists {
|
||||||
|
return fmt.Errorf("peer with site ID %d not found", siteId)
|
||||||
|
}
|
||||||
|
|
||||||
|
found := false
|
||||||
|
|
||||||
|
// Remove from RemoteSubnets
|
||||||
|
newSubnets := make([]string, 0, len(peer.RemoteSubnets))
|
||||||
|
for _, subnet := range peer.RemoteSubnets {
|
||||||
|
if subnet == ip {
|
||||||
|
found = true
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
newSubnets = append(newSubnets, subnet)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !found {
|
||||||
|
return nil // Not found
|
||||||
|
}
|
||||||
|
|
||||||
|
peer.RemoteSubnets = newSubnets
|
||||||
|
|
||||||
|
// Remove from allowed IPs
|
||||||
|
if err := pm.removeAllowedIp(siteId, ip); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove route
|
||||||
|
if err := network.RemoveRoutes([]string{ip}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
pm.peers[siteId] = peer
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddAlias adds an alias to a peer
|
||||||
|
func (pm *PeerManager) AddAlias(siteId int, alias Alias) error {
|
||||||
|
pm.mu.Lock()
|
||||||
|
defer pm.mu.Unlock()
|
||||||
|
|
||||||
|
peer, exists := pm.peers[siteId]
|
||||||
|
if !exists {
|
||||||
|
return fmt.Errorf("peer with site ID %d not found", siteId)
|
||||||
|
}
|
||||||
|
|
||||||
|
peer.Aliases = append(peer.Aliases, alias)
|
||||||
|
pm.peers[siteId] = peer
|
||||||
|
|
||||||
|
address := net.ParseIP(alias.AliasAddress)
|
||||||
|
if address != nil {
|
||||||
|
pm.dnsProxy.AddDNSRecord(alias.Alias, address)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add an allowed IP for the alias
|
||||||
|
if err := pm.addAllowedIp(siteId, alias.AliasAddress+"/32"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveAlias removes an alias from a peer
|
||||||
|
func (pm *PeerManager) RemoveAlias(siteId int, aliasName string) error {
|
||||||
|
pm.mu.Lock()
|
||||||
|
defer pm.mu.Unlock()
|
||||||
|
|
||||||
|
peer, exists := pm.peers[siteId]
|
||||||
|
if !exists {
|
||||||
|
return fmt.Errorf("peer with site ID %d not found", siteId)
|
||||||
|
}
|
||||||
|
|
||||||
|
var aliasToRemove *Alias
|
||||||
|
newAliases := make([]Alias, 0, len(peer.Aliases))
|
||||||
|
for _, a := range peer.Aliases {
|
||||||
|
if a.Alias == aliasName {
|
||||||
|
aliasToRemove = &a
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
newAliases = append(newAliases, a)
|
||||||
|
}
|
||||||
|
|
||||||
|
if aliasToRemove != nil {
|
||||||
|
address := net.ParseIP(aliasToRemove.AliasAddress)
|
||||||
|
if address != nil {
|
||||||
|
pm.dnsProxy.RemoveDNSRecord(aliasName, address)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove the allowed IP for the alias
|
||||||
|
if err := pm.removeAllowedIp(siteId, aliasToRemove.AliasAddress+"/32"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
peer.Aliases = newAliases
|
||||||
|
pm.peers[siteId] = peer
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package olm
|
package peers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
@@ -14,7 +14,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// ConfigurePeer sets up or updates a peer within the WireGuard device
|
// ConfigurePeer sets up or updates a peer within the WireGuard device
|
||||||
func ConfigurePeer(dev *device.Device, siteConfig SiteConfig, privateKey wgtypes.Key, endpoint string) error {
|
func ConfigurePeer(dev *device.Device, siteConfig SiteConfig, privateKey wgtypes.Key, endpoint string, peerMonitor *peermonitor.PeerMonitor) error {
|
||||||
siteHost, err := util.ResolveDomain(formatEndpoint(siteConfig.Endpoint))
|
siteHost, err := util.ResolveDomain(formatEndpoint(siteConfig.Endpoint))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to resolve endpoint for site %d: %v", siteConfig.SiteId, err)
|
return fmt.Errorf("failed to resolve endpoint for site %d: %v", siteConfig.SiteId, err)
|
||||||
@@ -33,10 +33,13 @@ func ConfigurePeer(dev *device.Device, siteConfig SiteConfig, privateKey wgtypes
|
|||||||
var allowedIPs []string
|
var allowedIPs []string
|
||||||
allowedIPs = append(allowedIPs, allowedIpStr)
|
allowedIPs = append(allowedIPs, allowedIpStr)
|
||||||
|
|
||||||
// If we have anything in remoteSubnets, add those as well
|
// Use AllowedIps if available, otherwise fall back to RemoteSubnets for backwards compatibility
|
||||||
if len(siteConfig.RemoteSubnets) > 0 {
|
subnetsToAdd := siteConfig.AllowedIps
|
||||||
// Add each remote subnet
|
|
||||||
for _, subnet := range siteConfig.RemoteSubnets {
|
// If we have anything to add, process them
|
||||||
|
if len(subnetsToAdd) > 0 {
|
||||||
|
// Add each subnet
|
||||||
|
for _, subnet := range subnetsToAdd {
|
||||||
subnet = strings.TrimSpace(subnet)
|
subnet = strings.TrimSpace(subnet)
|
||||||
if subnet != "" {
|
if subnet != "" {
|
||||||
allowedIPs = append(allowedIPs, subnet)
|
allowedIPs = append(allowedIPs, subnet)
|
||||||
@@ -96,7 +99,7 @@ func ConfigurePeer(dev *device.Device, siteConfig SiteConfig, privateKey wgtypes
|
|||||||
}
|
}
|
||||||
|
|
||||||
// RemovePeer removes a peer from the WireGuard device
|
// RemovePeer removes a peer from the WireGuard device
|
||||||
func RemovePeer(dev *device.Device, siteId int, publicKey string) error {
|
func RemovePeer(dev *device.Device, siteId int, publicKey string, peerMonitor *peermonitor.PeerMonitor) error {
|
||||||
// Construct WireGuard config to remove the peer
|
// Construct WireGuard config to remove the peer
|
||||||
var configBuilder strings.Builder
|
var configBuilder strings.Builder
|
||||||
configBuilder.WriteString(fmt.Sprintf("public_key=%s\n", util.FixKey(publicKey)))
|
configBuilder.WriteString(fmt.Sprintf("public_key=%s\n", util.FixKey(publicKey)))
|
||||||
@@ -118,3 +121,10 @@ func RemovePeer(dev *device.Device, siteId int, publicKey string) error {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func formatEndpoint(endpoint string) string {
|
||||||
|
if strings.Contains(endpoint, ":") {
|
||||||
|
return endpoint
|
||||||
|
}
|
||||||
|
return endpoint + ":51820"
|
||||||
|
}
|
||||||
57
peers/types.go
Normal file
57
peers/types.go
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
package peers
|
||||||
|
|
||||||
|
// PeerAction represents a request to add, update, or remove a peer
|
||||||
|
type PeerAction struct {
|
||||||
|
Action string `json:"action"` // "add", "update", or "remove"
|
||||||
|
SiteInfo SiteConfig `json:"siteInfo"` // Site configuration information
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdatePeerData represents the data needed to update a peer
|
||||||
|
type SiteConfig struct {
|
||||||
|
SiteId int `json:"siteId"`
|
||||||
|
Endpoint string `json:"endpoint,omitempty"`
|
||||||
|
PublicKey string `json:"publicKey,omitempty"`
|
||||||
|
ServerIP string `json:"serverIP,omitempty"`
|
||||||
|
ServerPort uint16 `json:"serverPort,omitempty"`
|
||||||
|
RemoteSubnets []string `json:"remoteSubnets,omitempty"` // optional, array of subnets that this site can access
|
||||||
|
AllowedIps []string `json:"allowedIps,omitempty"` // optional, array of allowed IPs for the peer
|
||||||
|
Aliases []Alias `json:"aliases,omitempty"` // optional, array of alias configurations
|
||||||
|
}
|
||||||
|
|
||||||
|
type Alias struct {
|
||||||
|
Alias string `json:"alias"` // the alias name
|
||||||
|
AliasAddress string `json:"aliasAddress"` // the alias IP address
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemovePeer represents the data needed to remove a peer
|
||||||
|
type PeerRemove struct {
|
||||||
|
SiteId int `json:"siteId"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type RelayPeerData struct {
|
||||||
|
SiteId int `json:"siteId"`
|
||||||
|
Endpoint string `json:"endpoint"`
|
||||||
|
PublicKey string `json:"publicKey"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// PeerAdd represents the data needed to add remote subnets to a peer
|
||||||
|
type PeerAdd struct {
|
||||||
|
SiteId int `json:"siteId"`
|
||||||
|
RemoteSubnets []string `json:"remoteSubnets"` // subnets to add
|
||||||
|
Aliases []Alias `json:"aliases,omitempty"` // aliases to add
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemovePeerData represents the data needed to remove remote subnets from a peer
|
||||||
|
type RemovePeerData struct {
|
||||||
|
SiteId int `json:"siteId"`
|
||||||
|
RemoteSubnets []string `json:"remoteSubnets"` // subnets to remove
|
||||||
|
Aliases []Alias `json:"aliases,omitempty"` // aliases to remove
|
||||||
|
}
|
||||||
|
|
||||||
|
type UpdatePeerData struct {
|
||||||
|
SiteId int `json:"siteId"`
|
||||||
|
OldRemoteSubnets []string `json:"oldRemoteSubnets"` // old list of remote subnets
|
||||||
|
NewRemoteSubnets []string `json:"newRemoteSubnets"` // new list of remote subnets
|
||||||
|
OldAliases []Alias `json:"oldAliases,omitempty"` // old list of aliases
|
||||||
|
NewAliases []Alias `json:"newAliases,omitempty"` // new list of aliases
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user