Updates to support updates

This commit is contained in:
Owen
2025-11-20 14:21:27 -05:00
parent 196d1cdee7
commit 8cff1d37fa
5 changed files with 138 additions and 113 deletions

View File

@@ -83,3 +83,16 @@ func GetNetworkSettingsJSON() (string, error) {
func GetNetworkSettingsIncrementor() int { func GetNetworkSettingsIncrementor() int {
return network.GetIncrementor() return network.GetIncrementor()
} }
// stringSlicesEqual compares two string slices for equality
func stringSlicesEqual(a, b []string) bool {
if len(a) != len(b) {
return false
}
for i := range a {
if a[i] != b[i] {
return false
}
}
return true
}

View File

@@ -543,71 +543,86 @@ func StartTunnel(config TunnelConfig) {
return return
} }
// Convert to SiteConfig // Update the peer in WireGuard
siteConfig := SiteConfig{ if dev == nil {
SiteId: updateData.SiteId, logger.Error("WireGuard device not initialized")
Endpoint: updateData.Endpoint, return
PublicKey: updateData.PublicKey,
ServerIP: updateData.ServerIP,
ServerPort: updateData.ServerPort,
RemoteSubnets: updateData.RemoteSubnets,
} }
// Update the peer in WireGuard // Find the existing peer to merge updates with
if dev != nil { var existingPeer *SiteConfig
// Find the existing peer to get old data var peerIndex int
var oldRemoteSubnets string for i, site := range wgData.Sites {
var oldPublicKey string if site.SiteId == updateData.SiteId {
for _, site := range wgData.Sites { existingPeer = &wgData.Sites[i]
if site.SiteId == updateData.SiteId { peerIndex = i
oldRemoteSubnets = site.RemoteSubnets break
oldPublicKey = site.PublicKey
break
}
} }
}
// If the public key has changed, remove the old peer first if existingPeer == nil {
if oldPublicKey != "" && oldPublicKey != updateData.PublicKey { logger.Error("Peer with site ID %d not found", updateData.SiteId)
logger.Info("Public key changed for site %d, removing old peer with key %s", updateData.SiteId, oldPublicKey) return
if err := RemovePeer(dev, updateData.SiteId, oldPublicKey); err != nil { }
logger.Error("Failed to remove old peer: %v", err)
return
}
}
// Format the endpoint before updating the peer. // Store old values for comparison
siteConfig.Endpoint = formatEndpoint(siteConfig.Endpoint) oldRemoteSubnets := existingPeer.RemoteSubnets
oldPublicKey := existingPeer.PublicKey
if err := ConfigurePeer(dev, siteConfig, privateKey, endpoint); err != nil { // Create updated site config by merging with existing data
logger.Error("Failed to update peer: %v", err) // Only update fields that are provided (non-empty/non-zero)
siteConfig := *existingPeer // Start with existing data
if updateData.Endpoint != "" {
siteConfig.Endpoint = updateData.Endpoint
}
if updateData.PublicKey != "" {
siteConfig.PublicKey = updateData.PublicKey
}
if updateData.ServerIP != "" {
siteConfig.ServerIP = updateData.ServerIP
}
if updateData.ServerPort != 0 {
siteConfig.ServerPort = updateData.ServerPort
}
if updateData.RemoteSubnets != nil {
siteConfig.RemoteSubnets = updateData.RemoteSubnets
}
// If the public key has changed, remove the old peer first
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 return
} }
// Remove old remote subnet routes if they changed
if oldRemoteSubnets != siteConfig.RemoteSubnets {
if err := removeRoutesForRemoteSubnets(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 := addRoutesForRemoteSubnets(siteConfig.RemoteSubnets, interfaceName); err != nil {
logger.Error("Failed to add new remote subnet routes: %v", err)
return
}
}
// Update successful
logger.Info("Successfully updated peer for site %d", updateData.SiteId)
for i := range wgData.Sites {
if wgData.Sites[i].SiteId == updateData.SiteId {
wgData.Sites[i] = siteConfig
break
}
}
} else {
logger.Error("WireGuard device not initialized")
} }
// Format the endpoint before updating the peer.
siteConfig.Endpoint = formatEndpoint(siteConfig.Endpoint)
if err := ConfigurePeer(dev, siteConfig, privateKey, endpoint); err != nil {
logger.Error("Failed to update peer: %v", err)
return
}
// Handle remote subnet route changes
if !stringSlicesEqual(oldRemoteSubnets, siteConfig.RemoteSubnets) {
if err := removeRoutesForRemoteSubnets(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 := addRoutesForRemoteSubnets(siteConfig.RemoteSubnets, interfaceName); err != nil {
logger.Error("Failed to add new remote subnet routes: %v", err)
return
}
}
// Update successful
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
@@ -637,31 +652,31 @@ func StartTunnel(config TunnelConfig) {
} }
// Add the peer to WireGuard // Add the peer to WireGuard
if dev != nil { if dev == nil {
// Format the endpoint before adding the new peer.
siteConfig.Endpoint = formatEndpoint(siteConfig.Endpoint)
if err := ConfigurePeer(dev, siteConfig, privateKey, endpoint); err != nil {
logger.Error("Failed to add peer: %v", err)
return
}
if err := addRouteForServerIP(siteConfig.ServerIP, interfaceName); err != nil {
logger.Error("Failed to add route for new peer: %v", err)
return
}
if err := addRoutesForRemoteSubnets(siteConfig.RemoteSubnets, interfaceName); err != nil {
logger.Error("Failed to add routes for remote subnets: %v", err)
return
}
// Add successful
logger.Info("Successfully added peer for site %d", addData.SiteId)
// Update WgData with the new peer
wgData.Sites = append(wgData.Sites, siteConfig)
} else {
logger.Error("WireGuard device not initialized") logger.Error("WireGuard device not initialized")
return
} }
// Format the endpoint before adding the new peer.
siteConfig.Endpoint = formatEndpoint(siteConfig.Endpoint)
if err := ConfigurePeer(dev, siteConfig, privateKey, endpoint); err != nil {
logger.Error("Failed to add peer: %v", err)
return
}
if err := addRouteForServerIP(siteConfig.ServerIP, interfaceName); err != nil {
logger.Error("Failed to add route for new peer: %v", err)
return
}
if err := addRoutesForRemoteSubnets(siteConfig.RemoteSubnets, interfaceName); err != nil {
logger.Error("Failed to add routes for remote subnets: %v", err)
return
}
// Add successful
logger.Info("Successfully added peer for site %d", addData.SiteId)
// Update WgData with the new peer
wgData.Sites = append(wgData.Sites, siteConfig)
}) })
// Handler for removing a peer // Handler for removing a peer

View File

@@ -34,10 +34,9 @@ func ConfigurePeer(dev *device.Device, siteConfig SiteConfig, privateKey wgtypes
allowedIPs = append(allowedIPs, allowedIpStr) allowedIPs = append(allowedIPs, allowedIpStr)
// If we have anything in remoteSubnets, add those as well // If we have anything in remoteSubnets, add those as well
if siteConfig.RemoteSubnets != "" { if len(siteConfig.RemoteSubnets) > 0 {
// Split remote subnets by comma and add each one // Add each remote subnet
remoteSubnets := strings.Split(siteConfig.RemoteSubnets, ",") for _, subnet := range siteConfig.RemoteSubnets {
for _, subnet := range remoteSubnets {
subnet = strings.TrimSpace(subnet) subnet = strings.TrimSpace(subnet)
if subnet != "" { if subnet != "" {
allowedIPs = append(allowedIPs, subnet) allowedIPs = append(allowedIPs, subnet)

View File

@@ -268,15 +268,14 @@ func removeRouteForNetworkConfig(destination string) error {
return nil return nil
} }
// addRoutesForRemoteSubnets adds routes for each comma-separated CIDR in RemoteSubnets // addRoutesForRemoteSubnets adds routes for each subnet in RemoteSubnets
func addRoutesForRemoteSubnets(remoteSubnets, interfaceName string) error { func addRoutesForRemoteSubnets(remoteSubnets []string, interfaceName string) error {
if remoteSubnets == "" { if len(remoteSubnets) == 0 {
return nil return nil
} }
// Split remote subnets by comma and add routes for each one // Add routes for each subnet
subnets := strings.Split(remoteSubnets, ",") for _, subnet := range remoteSubnets {
for _, subnet := range subnets {
subnet = strings.TrimSpace(subnet) subnet = strings.TrimSpace(subnet)
if subnet == "" { if subnet == "" {
continue continue
@@ -314,15 +313,14 @@ func addRoutesForRemoteSubnets(remoteSubnets, interfaceName string) error {
return nil return nil
} }
// removeRoutesForRemoteSubnets removes routes for each comma-separated CIDR in RemoteSubnets // removeRoutesForRemoteSubnets removes routes for each subnet in RemoteSubnets
func removeRoutesForRemoteSubnets(remoteSubnets string) error { func removeRoutesForRemoteSubnets(remoteSubnets []string) error {
if remoteSubnets == "" { if len(remoteSubnets) == 0 {
return nil return nil
} }
// Split remote subnets by comma and remove routes for each one // Remove routes for each subnet
subnets := strings.Split(remoteSubnets, ",") for _, subnet := range remoteSubnets {
for _, subnet := range subnets {
subnet = strings.TrimSpace(subnet) subnet = strings.TrimSpace(subnet)
if subnet == "" { if subnet == "" {
continue continue

View File

@@ -6,12 +6,12 @@ type WgData struct {
} }
type SiteConfig struct { type SiteConfig struct {
SiteId int `json:"siteId"` SiteId int `json:"siteId"`
Endpoint string `json:"endpoint"` Endpoint string `json:"endpoint"`
PublicKey string `json:"publicKey"` PublicKey string `json:"publicKey"`
ServerIP string `json:"serverIP"` ServerIP string `json:"serverIP"`
ServerPort uint16 `json:"serverPort"` ServerPort uint16 `json:"serverPort"`
RemoteSubnets string `json:"remoteSubnets,omitempty"` // optional, comma-separated list of subnets that this site can access RemoteSubnets []string `json:"remoteSubnets,omitempty"` // optional, array of subnets that this site can access
} }
type HolePunchMessage struct { type HolePunchMessage struct {
@@ -41,22 +41,22 @@ type PeerAction struct {
// UpdatePeerData represents the data needed to update a peer // UpdatePeerData represents the data needed to update a peer
type UpdatePeerData struct { type UpdatePeerData struct {
SiteId int `json:"siteId"` SiteId int `json:"siteId"`
Endpoint string `json:"endpoint"` Endpoint string `json:"endpoint,omitempty"`
PublicKey string `json:"publicKey"` PublicKey string `json:"publicKey,omitempty"`
ServerIP string `json:"serverIP"` ServerIP string `json:"serverIP,omitempty"`
ServerPort uint16 `json:"serverPort"` ServerPort uint16 `json:"serverPort,omitempty"`
RemoteSubnets string `json:"remoteSubnets,omitempty"` // optional, comma-separated list of subnets that this site can access RemoteSubnets []string `json:"remoteSubnets,omitempty"` // optional, array of subnets that this site can access
} }
// AddPeerData represents the data needed to add a peer // AddPeerData represents the data needed to add a peer
type AddPeerData struct { type AddPeerData struct {
SiteId int `json:"siteId"` SiteId int `json:"siteId"`
Endpoint string `json:"endpoint"` Endpoint string `json:"endpoint"`
PublicKey string `json:"publicKey"` PublicKey string `json:"publicKey"`
ServerIP string `json:"serverIP"` ServerIP string `json:"serverIP"`
ServerPort uint16 `json:"serverPort"` ServerPort uint16 `json:"serverPort"`
RemoteSubnets string `json:"remoteSubnets,omitempty"` // optional, comma-separated list of subnets that this site can access RemoteSubnets []string `json:"remoteSubnets,omitempty"` // optional, array of subnets that this site can access
} }
// RemovePeerData represents the data needed to remove a peer // RemovePeerData represents the data needed to remove a peer