Compare commits

..

4 Commits
dev ... v1.4.4

Author SHA1 Message Date
Owen Schwartz
703fe4fe5d Merge pull request #105 from fosrl/dev
Fix nil pointer deference
2026-03-19 16:16:06 -07:00
Owen Schwartz
31eed74933 Merge pull request #103 from fosrl/dev
Update dockerfile for new version
2026-03-17 11:29:04 -07:00
Owen Schwartz
4d0c43fc3e Merge pull request #102 from fosrl/dev
Update cicd
2026-03-16 17:53:13 -07:00
Owen Schwartz
c77c162bae Merge pull request #101 from fosrl/dev
1.4.3
2026-03-16 16:44:08 -07:00
4 changed files with 38 additions and 80 deletions

View File

@@ -205,13 +205,12 @@ func (o *Olm) handleConnect(msg websocket.WSMessage) {
// Register JIT handler: when the DNS proxy resolves a local record, check whether // Register JIT handler: when the DNS proxy resolves a local record, check whether
// the owning site is already connected and, if not, initiate a JIT connection. // the owning site is already connected and, if not, initiate a JIT connection.
o.dnsProxy.SetJITHandler(func(siteId int) { o.dnsProxy.SetJITHandler(func(siteId int) {
pm := o.getPeerManager() if o.peerManager == nil || o.websocket == nil {
if pm == nil || o.websocket == nil {
return return
} }
// Site already has an active peer connection - nothing to do. // Site already has an active peer connection - nothing to do.
if _, exists := pm.GetPeer(siteId); exists { if _, exists := o.peerManager.GetPeer(siteId); exists {
return return
} }

View File

@@ -32,27 +32,21 @@ func (o *Olm) handleWgPeerAddData(msg websocket.WSMessage) {
return return
} }
pm := o.getPeerManager() if _, exists := o.peerManager.GetPeer(addSubnetsData.SiteId); !exists {
if pm == nil {
logger.Debug("Ignoring add-remote-subnets-aliases message: peerManager is nil (shutdown in progress)")
return
}
if _, exists := pm.GetPeer(addSubnetsData.SiteId); !exists {
logger.Debug("Peer %d not found for removing remote subnets and aliases", addSubnetsData.SiteId) logger.Debug("Peer %d not found for removing remote subnets and aliases", addSubnetsData.SiteId)
return return
} }
// Add new subnets // Add new subnets
for _, subnet := range addSubnetsData.RemoteSubnets { for _, subnet := range addSubnetsData.RemoteSubnets {
if err := pm.AddRemoteSubnet(addSubnetsData.SiteId, subnet); err != nil { if err := o.peerManager.AddRemoteSubnet(addSubnetsData.SiteId, subnet); err != nil {
logger.Error("Failed to add allowed IP %s: %v", subnet, err) logger.Error("Failed to add allowed IP %s: %v", subnet, err)
} }
} }
// Add new aliases // Add new aliases
for _, alias := range addSubnetsData.Aliases { for _, alias := range addSubnetsData.Aliases {
if err := pm.AddAlias(addSubnetsData.SiteId, alias); err != nil { if err := o.peerManager.AddAlias(addSubnetsData.SiteId, alias); err != nil {
logger.Error("Failed to add alias %s: %v", alias.Alias, err) logger.Error("Failed to add alias %s: %v", alias.Alias, err)
} }
} }
@@ -79,27 +73,21 @@ func (o *Olm) handleWgPeerRemoveData(msg websocket.WSMessage) {
return return
} }
pm := o.getPeerManager() if _, exists := o.peerManager.GetPeer(removeSubnetsData.SiteId); !exists {
if pm == nil {
logger.Debug("Ignoring remove-remote-subnets-aliases message: peerManager is nil (shutdown in progress)")
return
}
if _, exists := pm.GetPeer(removeSubnetsData.SiteId); !exists {
logger.Debug("Peer %d not found for removing remote subnets and aliases", removeSubnetsData.SiteId) logger.Debug("Peer %d not found for removing remote subnets and aliases", removeSubnetsData.SiteId)
return return
} }
// Remove subnets // Remove subnets
for _, subnet := range removeSubnetsData.RemoteSubnets { for _, subnet := range removeSubnetsData.RemoteSubnets {
if err := pm.RemoveRemoteSubnet(removeSubnetsData.SiteId, subnet); err != nil { if err := o.peerManager.RemoveRemoteSubnet(removeSubnetsData.SiteId, subnet); err != nil {
logger.Error("Failed to remove allowed IP %s: %v", subnet, err) logger.Error("Failed to remove allowed IP %s: %v", subnet, err)
} }
} }
// Remove aliases // Remove aliases
for _, alias := range removeSubnetsData.Aliases { for _, alias := range removeSubnetsData.Aliases {
if err := pm.RemoveAlias(removeSubnetsData.SiteId, alias.Alias); err != nil { if err := o.peerManager.RemoveAlias(removeSubnetsData.SiteId, alias.Alias); err != nil {
logger.Error("Failed to remove alias %s: %v", alias.Alias, err) logger.Error("Failed to remove alias %s: %v", alias.Alias, err)
} }
} }
@@ -126,13 +114,7 @@ func (o *Olm) handleWgPeerUpdateData(msg websocket.WSMessage) {
return return
} }
pm := o.getPeerManager() if _, exists := o.peerManager.GetPeer(updateSubnetsData.SiteId); !exists {
if pm == nil {
logger.Debug("Ignoring update-remote-subnets-aliases message: peerManager is nil (shutdown in progress)")
return
}
if _, exists := pm.GetPeer(updateSubnetsData.SiteId); !exists {
logger.Debug("Peer %d not found for updating remote subnets and aliases", updateSubnetsData.SiteId) logger.Debug("Peer %d not found for updating remote subnets and aliases", updateSubnetsData.SiteId)
return return
} }
@@ -141,14 +123,14 @@ func (o *Olm) handleWgPeerUpdateData(msg websocket.WSMessage) {
// This ensures that if an old and new subnet are the same on different peers, // This ensures that if an old and new subnet are the same on different peers,
// the route won't be temporarily removed // the route won't be temporarily removed
for _, subnet := range updateSubnetsData.NewRemoteSubnets { for _, subnet := range updateSubnetsData.NewRemoteSubnets {
if err := pm.AddRemoteSubnet(updateSubnetsData.SiteId, subnet); err != nil { if err := o.peerManager.AddRemoteSubnet(updateSubnetsData.SiteId, subnet); err != nil {
logger.Error("Failed to add allowed IP %s: %v", subnet, err) logger.Error("Failed to add allowed IP %s: %v", subnet, err)
} }
} }
// Remove old subnets after new ones are added // Remove old subnets after new ones are added
for _, subnet := range updateSubnetsData.OldRemoteSubnets { for _, subnet := range updateSubnetsData.OldRemoteSubnets {
if err := pm.RemoveRemoteSubnet(updateSubnetsData.SiteId, subnet); err != nil { if err := o.peerManager.RemoveRemoteSubnet(updateSubnetsData.SiteId, subnet); err != nil {
logger.Error("Failed to remove allowed IP %s: %v", subnet, err) logger.Error("Failed to remove allowed IP %s: %v", subnet, err)
} }
} }
@@ -157,14 +139,14 @@ func (o *Olm) handleWgPeerUpdateData(msg websocket.WSMessage) {
// This ensures that if an old and new alias share the same IP, the IP won't be // This ensures that if an old and new alias share the same IP, the IP won't be
// temporarily removed from the allowed IPs list // temporarily removed from the allowed IPs list
for _, alias := range updateSubnetsData.NewAliases { for _, alias := range updateSubnetsData.NewAliases {
if err := pm.AddAlias(updateSubnetsData.SiteId, alias); err != nil { if err := o.peerManager.AddAlias(updateSubnetsData.SiteId, alias); err != nil {
logger.Error("Failed to add alias %s: %v", alias.Alias, err) logger.Error("Failed to add alias %s: %v", alias.Alias, err)
} }
} }
// Remove old aliases after new ones are added // Remove old aliases after new ones are added
for _, alias := range updateSubnetsData.OldAliases { for _, alias := range updateSubnetsData.OldAliases {
if err := pm.RemoveAlias(updateSubnetsData.SiteId, alias.Alias); err != nil { if err := o.peerManager.RemoveAlias(updateSubnetsData.SiteId, alias.Alias); err != nil {
logger.Error("Failed to remove alias %s: %v", alias.Alias, err) logger.Error("Failed to remove alias %s: %v", alias.Alias, err)
} }
} }
@@ -181,8 +163,7 @@ func (o *Olm) handleSync(msg websocket.WSMessage) {
return return
} }
pm := o.getPeerManager() if o.peerManager == nil {
if pm == nil {
logger.Warn("Peer manager not initialized, ignoring sync request") logger.Warn("Peer manager not initialized, ignoring sync request")
return return
} }
@@ -209,7 +190,7 @@ func (o *Olm) handleSync(msg websocket.WSMessage) {
} }
// Get all current peers // Get all current peers
currentPeers := pm.GetAllPeers() currentPeers := o.peerManager.GetAllPeers()
currentPeerMap := make(map[int]peers.SiteConfig) currentPeerMap := make(map[int]peers.SiteConfig)
for _, peer := range currentPeers { for _, peer := range currentPeers {
currentPeerMap[peer.SiteId] = peer currentPeerMap[peer.SiteId] = peer
@@ -219,7 +200,7 @@ func (o *Olm) handleSync(msg websocket.WSMessage) {
for siteId := range currentPeerMap { for siteId := range currentPeerMap {
if _, exists := expectedPeers[siteId]; !exists { if _, exists := expectedPeers[siteId]; !exists {
logger.Info("Sync: Removing peer for site %d (no longer in expected config)", siteId) logger.Info("Sync: Removing peer for site %d (no longer in expected config)", siteId)
if err := pm.RemovePeer(siteId); err != nil { if err := o.peerManager.RemovePeer(siteId); err != nil {
logger.Error("Sync: Failed to remove peer %d: %v", siteId, err) logger.Error("Sync: Failed to remove peer %d: %v", siteId, err)
} else { } else {
// Remove any exit nodes associated with this peer from hole punching // Remove any exit nodes associated with this peer from hole punching
@@ -320,7 +301,7 @@ func (o *Olm) handleSync(msg websocket.WSMessage) {
siteConfig.Aliases = expectedSite.Aliases siteConfig.Aliases = expectedSite.Aliases
} }
if err := pm.UpdatePeer(siteConfig); err != nil { if err := o.peerManager.UpdatePeer(siteConfig); err != nil {
logger.Error("Sync: Failed to update peer %d: %v", siteId, err) logger.Error("Sync: Failed to update peer %d: %v", siteId, err)
} else { } else {
// If the endpoint changed, trigger holepunch to refresh NAT mappings // If the endpoint changed, trigger holepunch to refresh NAT mappings

View File

@@ -47,7 +47,6 @@ type Olm struct {
websocket *websocket.Client websocket *websocket.Client
holePunchManager *holepunch.Manager holePunchManager *holepunch.Manager
peerManager *peers.PeerManager peerManager *peers.PeerManager
peerManagerMu sync.RWMutex
// Power mode management // Power mode management
currentPowerMode string currentPowerMode string
powerModeMu sync.Mutex powerModeMu sync.Mutex
@@ -77,15 +76,6 @@ type Olm struct {
tunnelWg sync.WaitGroup tunnelWg sync.WaitGroup
} }
// getPeerManager safely returns the current peerManager under a read-lock.
// Callers must check the returned value for nil before using it.
func (o *Olm) getPeerManager() *peers.PeerManager {
o.peerManagerMu.RLock()
pm := o.peerManager
o.peerManagerMu.RUnlock()
return pm
}
// initTunnelInfo creates the shared UDP socket and holepunch manager. // initTunnelInfo creates the shared UDP socket and holepunch manager.
// This is used during initial tunnel setup and when switching organizations. // This is used during initial tunnel setup and when switching organizations.
func (o *Olm) initTunnelInfo(clientID string) error { func (o *Olm) initTunnelInfo(clientID string) error {
@@ -467,7 +457,7 @@ func (o *Olm) StartTunnel(config TunnelConfig) {
"userToken": userToken, "userToken": userToken,
"fingerprint": o.fingerprint, "fingerprint": o.fingerprint,
"postures": o.postures, "postures": o.postures,
}, 2*time.Second, 20) }, 2*time.Second, 10)
// Invoke onRegistered callback if configured // Invoke onRegistered callback if configured
if o.olmConfig.OnRegistered != nil { if o.olmConfig.OnRegistered != nil {
@@ -601,12 +591,10 @@ func (o *Olm) Close() {
} }
// Close() also calls Stop() internally // Close() also calls Stop() internally
o.peerManagerMu.Lock()
if o.peerManager != nil { if o.peerManager != nil {
o.peerManager.Close() o.peerManager.Close()
o.peerManager = nil o.peerManager = nil
} }
o.peerManagerMu.Unlock()
if o.uapiListener != nil { if o.uapiListener != nil {
_ = o.uapiListener.Close() _ = o.uapiListener.Close()
@@ -818,14 +806,14 @@ func (o *Olm) SetPowerMode(mode string) error {
lowPowerInterval := 10 * time.Minute lowPowerInterval := 10 * time.Minute
if pm := o.getPeerManager(); pm != nil { if o.peerManager != nil {
peerMonitor := pm.GetPeerMonitor() peerMonitor := o.peerManager.GetPeerMonitor()
if peerMonitor != nil { if peerMonitor != nil {
peerMonitor.SetPeerInterval(lowPowerInterval, lowPowerInterval) peerMonitor.SetPeerInterval(lowPowerInterval, lowPowerInterval)
peerMonitor.SetPeerHolepunchInterval(lowPowerInterval, lowPowerInterval) peerMonitor.SetPeerHolepunchInterval(lowPowerInterval, lowPowerInterval)
logger.Info("Set monitoring intervals to 10 minutes for low power mode") logger.Info("Set monitoring intervals to 10 minutes for low power mode")
} }
pm.UpdateAllPeersPersistentKeepalive(0) // disable o.peerManager.UpdateAllPeersPersistentKeepalive(0) // disable
} }
if o.holePunchManager != nil { if o.holePunchManager != nil {
@@ -870,14 +858,14 @@ func (o *Olm) SetPowerMode(mode string) error {
} }
// Restore intervals and reconnect websocket // Restore intervals and reconnect websocket
if pm := o.getPeerManager(); pm != nil { if o.peerManager != nil {
peerMonitor := pm.GetPeerMonitor() peerMonitor := o.peerManager.GetPeerMonitor()
if peerMonitor != nil { if peerMonitor != nil {
peerMonitor.ResetPeerHolepunchInterval() peerMonitor.ResetPeerHolepunchInterval()
peerMonitor.ResetPeerInterval() peerMonitor.ResetPeerInterval()
} }
pm.UpdateAllPeersPersistentKeepalive(5) o.peerManager.UpdateAllPeersPersistentKeepalive(5)
} }
if o.holePunchManager != nil { if o.holePunchManager != nil {

View File

@@ -20,8 +20,7 @@ func (o *Olm) handleWgPeerAdd(msg websocket.WSMessage) {
return return
} }
pm := o.getPeerManager() if o.peerManager == nil {
if pm == nil {
logger.Debug("Ignoring add-peer message: peerManager is nil (shutdown in progress)") logger.Debug("Ignoring add-peer message: peerManager is nil (shutdown in progress)")
return return
} }
@@ -65,7 +64,7 @@ func (o *Olm) handleWgPeerAdd(msg websocket.WSMessage) {
_ = o.holePunchManager.TriggerHolePunch() // Trigger immediate hole punch attempt so that if the peer decides to relay we have already punched close to when we need it _ = o.holePunchManager.TriggerHolePunch() // Trigger immediate hole punch attempt so that if the peer decides to relay we have already punched close to when we need it
if err := pm.AddPeer(siteConfigMsg.SiteConfig); err != nil { if err := o.peerManager.AddPeer(siteConfigMsg.SiteConfig); err != nil {
logger.Error("Failed to add peer: %v", err) logger.Error("Failed to add peer: %v", err)
return return
} }
@@ -82,8 +81,7 @@ func (o *Olm) handleWgPeerRemove(msg websocket.WSMessage) {
return return
} }
pm := o.getPeerManager() if o.peerManager == nil {
if pm == nil {
logger.Debug("Ignoring remove-peer message: peerManager is nil (shutdown in progress)") logger.Debug("Ignoring remove-peer message: peerManager is nil (shutdown in progress)")
return return
} }
@@ -100,7 +98,7 @@ func (o *Olm) handleWgPeerRemove(msg websocket.WSMessage) {
return return
} }
if err := pm.RemovePeer(removeData.SiteId); err != nil { if err := o.peerManager.RemovePeer(removeData.SiteId); err != nil {
logger.Error("Failed to remove peer: %v", err) logger.Error("Failed to remove peer: %v", err)
return return
} }
@@ -125,8 +123,7 @@ func (o *Olm) handleWgPeerUpdate(msg websocket.WSMessage) {
return return
} }
pm := o.getPeerManager() if o.peerManager == nil {
if pm == nil {
logger.Debug("Ignoring update-peer message: peerManager is nil (shutdown in progress)") logger.Debug("Ignoring update-peer message: peerManager is nil (shutdown in progress)")
return return
} }
@@ -144,7 +141,7 @@ func (o *Olm) handleWgPeerUpdate(msg websocket.WSMessage) {
} }
// Get existing peer from PeerManager // Get existing peer from PeerManager
existingPeer, exists := pm.GetPeer(updateData.SiteId) existingPeer, exists := o.peerManager.GetPeer(updateData.SiteId)
if !exists { if !exists {
logger.Warn("Peer with site ID %d not found", updateData.SiteId) logger.Warn("Peer with site ID %d not found", updateData.SiteId)
return return
@@ -172,7 +169,7 @@ func (o *Olm) handleWgPeerUpdate(msg websocket.WSMessage) {
siteConfig.RemoteSubnets = updateData.RemoteSubnets siteConfig.RemoteSubnets = updateData.RemoteSubnets
} }
if err := pm.UpdatePeer(siteConfig); err != nil { if err := o.peerManager.UpdatePeer(siteConfig); err != nil {
logger.Error("Failed to update peer: %v", err) logger.Error("Failed to update peer: %v", err)
return return
} }
@@ -191,8 +188,7 @@ func (o *Olm) handleWgPeerRelay(msg websocket.WSMessage) {
logger.Debug("Received relay-peer message: %v", msg.Data) logger.Debug("Received relay-peer message: %v", msg.Data)
// Check if peerManager is still valid (may be nil during shutdown) // Check if peerManager is still valid (may be nil during shutdown)
pm := o.getPeerManager() if o.peerManager == nil {
if pm == nil {
logger.Debug("Ignoring relay message: peerManager is nil (shutdown in progress)") logger.Debug("Ignoring relay message: peerManager is nil (shutdown in progress)")
return return
} }
@@ -212,7 +208,7 @@ func (o *Olm) handleWgPeerRelay(msg websocket.WSMessage) {
return return
} }
if monitor := pm.GetPeerMonitor(); monitor != nil { if monitor := o.peerManager.GetPeerMonitor(); monitor != nil {
monitor.CancelRelaySend(relayData.ChainId) monitor.CancelRelaySend(relayData.ChainId)
} }
@@ -226,15 +222,14 @@ func (o *Olm) handleWgPeerRelay(msg websocket.WSMessage) {
// Update HTTP server to mark this peer as using relay // Update HTTP server to mark this peer as using relay
o.apiServer.UpdatePeerRelayStatus(relayData.SiteId, relayData.RelayEndpoint, true) o.apiServer.UpdatePeerRelayStatus(relayData.SiteId, relayData.RelayEndpoint, true)
pm.RelayPeer(relayData.SiteId, primaryRelay, relayData.RelayPort) o.peerManager.RelayPeer(relayData.SiteId, primaryRelay, relayData.RelayPort)
} }
func (o *Olm) handleWgPeerUnrelay(msg websocket.WSMessage) { func (o *Olm) handleWgPeerUnrelay(msg websocket.WSMessage) {
logger.Debug("Received unrelay-peer message: %v", msg.Data) logger.Debug("Received unrelay-peer message: %v", msg.Data)
// Check if peerManager is still valid (may be nil during shutdown) // Check if peerManager is still valid (may be nil during shutdown)
pm := o.getPeerManager() if o.peerManager == nil {
if pm == nil {
logger.Debug("Ignoring unrelay message: peerManager is nil (shutdown in progress)") logger.Debug("Ignoring unrelay message: peerManager is nil (shutdown in progress)")
return return
} }
@@ -254,7 +249,7 @@ func (o *Olm) handleWgPeerUnrelay(msg websocket.WSMessage) {
return return
} }
if monitor := pm.GetPeerMonitor(); monitor != nil { if monitor := o.peerManager.GetPeerMonitor(); monitor != nil {
monitor.CancelRelaySend(relayData.ChainId) monitor.CancelRelaySend(relayData.ChainId)
} }
@@ -267,7 +262,7 @@ func (o *Olm) handleWgPeerUnrelay(msg websocket.WSMessage) {
// Update HTTP server to mark this peer as using relay // Update HTTP server to mark this peer as using relay
o.apiServer.UpdatePeerRelayStatus(relayData.SiteId, relayData.Endpoint, false) o.apiServer.UpdatePeerRelayStatus(relayData.SiteId, relayData.Endpoint, false)
pm.UnRelayPeer(relayData.SiteId, primaryRelay) o.peerManager.UnRelayPeer(relayData.SiteId, primaryRelay)
} }
func (o *Olm) handleWgPeerHolepunchAddSite(msg websocket.WSMessage) { func (o *Olm) handleWgPeerHolepunchAddSite(msg websocket.WSMessage) {
@@ -322,12 +317,7 @@ func (o *Olm) handleWgPeerHolepunchAddSite(msg websocket.WSMessage) {
} }
// Get existing peer from PeerManager // Get existing peer from PeerManager
pm := o.getPeerManager() _, exists := o.peerManager.GetPeer(handshakeData.SiteId)
if pm == nil {
logger.Debug("Ignoring peer-handshake message: peerManager is nil (shutdown in progress)")
return
}
_, exists := pm.GetPeer(handshakeData.SiteId)
if exists { if exists {
logger.Warn("Peer with site ID %d already added", handshakeData.SiteId) logger.Warn("Peer with site ID %d already added", handshakeData.SiteId)
return return