Create a system proxy change after receiving a network map

This is experimental and needs more test.

the purpose of this change is to validate that a TLS connection stuck using old routes because of keepalive settings on the remote webserver are reset once netbird receives a network map
This commit is contained in:
mlsmaycon
2026-02-01 10:21:51 +01:00
parent 0c990ab662
commit ea41cf2d2c
6 changed files with 579 additions and 0 deletions

View File

@@ -44,10 +44,12 @@ import (
icemaker "github.com/netbirdio/netbird/client/internal/peer/ice"
"github.com/netbirdio/netbird/client/internal/peerstore"
"github.com/netbirdio/netbird/client/internal/profilemanager"
"github.com/netbirdio/netbird/client/internal/proxy"
"github.com/netbirdio/netbird/client/internal/relay"
"github.com/netbirdio/netbird/client/internal/rosenpass"
"github.com/netbirdio/netbird/client/internal/routemanager"
"github.com/netbirdio/netbird/client/internal/routemanager/systemops"
"github.com/netbirdio/netbird/client/internal/routemanager/vars"
"github.com/netbirdio/netbird/client/internal/statemanager"
"github.com/netbirdio/netbird/client/internal/updatemanager"
"github.com/netbirdio/netbird/client/jobexec"
@@ -140,6 +142,11 @@ type EngineConfig struct {
ProfileConfig *profilemanager.Config
LogPath string
// ProxyConfig contains system proxy settings for macOS
ProxyEnabled bool
ProxyHost string
ProxyPort int
}
// Engine is a mechanism responsible for reacting on Signal and Management stream events and managing connections to the remote peers.
@@ -223,6 +230,9 @@ type Engine struct {
jobExecutor *jobexec.Executor
jobExecutorWG sync.WaitGroup
// proxyManager manages system-wide browser proxy settings on macOS
proxyManager *proxy.Manager
}
// Peer is an instance of the Connection Peer
@@ -313,6 +323,12 @@ func (e *Engine) Stop() error {
e.updateManager.Stop()
}
if e.proxyManager != nil {
if err := e.proxyManager.DisableWebProxy(); err != nil {
log.Warnf("failed to disable system proxy: %v", err)
}
}
log.Info("cleaning up status recorder states")
e.statusRecorder.ReplaceOfflinePeers([]peer.State{})
e.statusRecorder.UpdateDNSStates([]peer.NSGroupState{})
@@ -448,6 +464,10 @@ func (e *Engine) Start(netbirdConfig *mgmProto.NetbirdConfig, mgmtURL *url.URL)
}
e.stateManager.Start()
// Initialize proxy manager and register state for cleanup
proxy.RegisterState(e.stateManager)
e.proxyManager = proxy.NewManager(e.stateManager)
initialRoutes, dnsConfig, dnsFeatureFlag, err := e.readInitialSettings()
if err != nil {
e.close()
@@ -1312,6 +1332,9 @@ func (e *Engine) updateNetworkMap(networkMap *mgmProto.NetworkMap) error {
// If no server of a server group responds this will disable the respective handler and retry later.
e.dnsServer.ProbeAvailability()
// Update system proxy state based on routes after network map is fully applied
e.updateSystemProxy(clientRoutes)
return nil
}
@@ -2303,6 +2326,38 @@ func createFile(path string) error {
return file.Close()
}
// containsExitNodeRoute checks if the routes contain an exit node (0.0.0.0/0).
func containsExitNodeRoute(clientRoutes route.HAMap) bool {
for _, routes := range clientRoutes {
for _, r := range routes {
if r.Network.String() == vars.ExitNodeCIDR {
return true
}
}
}
return false
}
// updateSystemProxy triggers a proxy enable/disable cycle after the network map is updated.
func (e *Engine) updateSystemProxy(clientRoutes route.HAMap) {
if runtime.GOOS != "darwin" || e.proxyManager == nil {
log.Errorf("not updating proxy")
return
}
if err := e.proxyManager.EnableWebProxy(e.config.ProxyHost, e.config.ProxyPort); err != nil {
log.Error("enable system proxy: %v", err)
return
}
log.Error("system proxy enabled after network map update")
if err := e.proxyManager.DisableWebProxy(); err != nil {
log.Error("disable system proxy: %v", err)
return
}
log.Error("system proxy disabled after network map update")
}
func convertToOfferAnswer(msg *sProto.Message) (*peer.OfferAnswer, error) {
remoteCred, err := signal.UnMarshalCredential(msg)
if err != nil {