From ba41602e4b06bff66624d07d55ff711140e40e2b Mon Sep 17 00:00:00 2001 From: Owen Date: Wed, 3 Dec 2025 15:50:00 -0500 Subject: [PATCH] Improve handling of allowed ips Former-commit-id: 1a2a2e5453d0ce83176dd001ef583a3831d8b618 --- olm/olm.go | 7 +------ peers/manager.go | 25 ++++++++++++++++++++----- peers/peer.go | 42 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+), 11 deletions(-) diff --git a/olm/olm.go b/olm/olm.go index 7b9b9e1..2e0e378 100644 --- a/olm/olm.go +++ b/olm/olm.go @@ -786,12 +786,7 @@ func StartTunnel(config TunnelConfig) { logger.Debug("Exit node %s already in holepunch rotation", exitNode.Endpoint) } - // Start holepunching if not already running - if !holePunchManager.IsRunning() { - if err := holePunchManager.Start(); err != nil { - logger.Error("Failed to start holepunch manager: %v", err) - } - } + holePunchManager.ResetInterval() // start sending immediately again so we fill in the endpoint on the cloud } // Send handshake acknowledgment back to server with retry diff --git a/peers/manager.go b/peers/manager.go index f704f25..f8d468d 100644 --- a/peers/manager.go +++ b/peers/manager.go @@ -455,7 +455,7 @@ func (pm *PeerManager) addAllowedIp(siteId int, ip string) error { // Only update WireGuard if we own this IP if pm.allowedIPOwners[ip] == siteId { - if err := ConfigurePeer(pm.device, peer, pm.privateKey, pm.peerMonitor.IsPeerRelayed(peer.SiteId)); err != nil { + if err := AddAllowedIP(pm.device, peer.PublicKey, ip); err != nil { return err } } @@ -494,15 +494,30 @@ func (pm *PeerManager) removeAllowedIp(siteId int, cidr string) error { // Release our claim and check if we need to promote another peer newOwner, promoted := pm.releaseAllowedIP(siteId, cidr) - // Update WireGuard for this peer (to remove the IP from its config) - if err := ConfigurePeer(pm.device, peer, pm.privateKey, pm.peerMonitor.IsPeerRelayed(peer.SiteId)); err != nil { + // Build the list of IPs this peer currently owns for the replace operation + ownedIPs := pm.getOwnedAllowedIPs(siteId) + // Also include the server IP which is always owned + serverIP := strings.Split(peer.ServerIP, "/")[0] + "/32" + hasServerIP := false + for _, ip := range ownedIPs { + if ip == serverIP { + hasServerIP = true + break + } + } + if !hasServerIP { + ownedIPs = append([]string{serverIP}, ownedIPs...) + } + + // Update WireGuard for this peer using replace_allowed_ips + if err := RemoveAllowedIP(pm.device, peer.PublicKey, ownedIPs); err != nil { return err } - // If another peer was promoted to owner, update their WireGuard config + // If another peer was promoted to owner, add the IP to their WireGuard config if promoted && newOwner >= 0 { if newOwnerPeer, exists := pm.peers[newOwner]; exists { - if err := ConfigurePeer(pm.device, newOwnerPeer, pm.privateKey, pm.peerMonitor.IsPeerRelayed(peer.SiteId)); err != nil { + if err := AddAllowedIP(pm.device, newOwnerPeer.PublicKey, cidr); err != nil { logger.Error("Failed to promote peer %d for IP %s: %v", newOwner, cidr, err) } else { logger.Info("Promoted peer %d to owner of IP %s", newOwner, cidr) diff --git a/peers/peer.go b/peers/peer.go index 060e360..3e1b8d5 100644 --- a/peers/peer.go +++ b/peers/peer.go @@ -92,6 +92,48 @@ func RemovePeer(dev *device.Device, siteId int, publicKey string) error { return nil } +// AddAllowedIP adds a single allowed IP to an existing peer without reconfiguring the entire peer +func AddAllowedIP(dev *device.Device, publicKey string, allowedIP string) error { + var configBuilder strings.Builder + configBuilder.WriteString(fmt.Sprintf("public_key=%s\n", util.FixKey(publicKey))) + configBuilder.WriteString("update_only=true\n") + configBuilder.WriteString(fmt.Sprintf("allowed_ip=%s\n", allowedIP)) + + config := configBuilder.String() + logger.Debug("Adding allowed IP to peer with config: %s", config) + + err := dev.IpcSet(config) + if err != nil { + return fmt.Errorf("failed to add allowed IP to WireGuard peer: %v", err) + } + + return nil +} + +// RemoveAllowedIP removes a single allowed IP from an existing peer by replacing the allowed IPs list +// This requires providing all the allowed IPs that should remain after removal +func RemoveAllowedIP(dev *device.Device, publicKey string, remainingAllowedIPs []string) error { + var configBuilder strings.Builder + configBuilder.WriteString(fmt.Sprintf("public_key=%s\n", util.FixKey(publicKey))) + configBuilder.WriteString("update_only=true\n") + configBuilder.WriteString("replace_allowed_ips=true\n") + + // Add each remaining allowed IP + for _, allowedIP := range remainingAllowedIPs { + configBuilder.WriteString(fmt.Sprintf("allowed_ip=%s\n", allowedIP)) + } + + config := configBuilder.String() + logger.Debug("Removing allowed IP from peer with config: %s", config) + + err := dev.IpcSet(config) + if err != nil { + return fmt.Errorf("failed to remove allowed IP from WireGuard peer: %v", err) + } + + return nil +} + func formatEndpoint(endpoint string) string { if strings.Contains(endpoint, ":") { return endpoint