From 459781c324b618be17fc943fac45ab2a139c07a8 Mon Sep 17 00:00:00 2001 From: Adam Fisk Date: Thu, 12 Dec 2024 12:57:48 -0700 Subject: [PATCH] Ensure fronted is always initialized and self-contained in proxies package --- flashlight.go | 36 +++++++++++------------------------- go.mod | 2 +- go.sum | 4 ++-- proxied/fronted.go | 23 +++++++++++++++++++++++ proxied/proxied.go | 12 ------------ 5 files changed, 37 insertions(+), 40 deletions(-) diff --git a/flashlight.go b/flashlight.go index b56ebcb88..f1946b794 100644 --- a/flashlight.go +++ b/flashlight.go @@ -3,7 +3,6 @@ package flashlight import ( "fmt" "net" - "path/filepath" "sync" "time" @@ -12,10 +11,8 @@ import ( "github.com/getlantern/dnsgrab" "github.com/getlantern/errors" "github.com/getlantern/eventual/v2" - "github.com/getlantern/fronted" "github.com/getlantern/golog" "github.com/getlantern/netx" - tls "github.com/refraction-networking/utls" "google.golang.org/protobuf/proto" "github.com/getlantern/flashlight/v7/apipb" @@ -78,10 +75,6 @@ func (t HandledErrorType) String() string { } } -type ProxyListener interface { - OnProxies(map[string]*commonconfig.ProxyConfig) -} - type Flashlight struct { configDir string flagsAsMap map[string]interface{} @@ -96,7 +89,6 @@ type Flashlight struct { errorHandler func(HandledErrorType, error) mxProxyListeners sync.RWMutex proxyListeners []func(map[string]*commonconfig.ProxyConfig, config.Source) - fronted fronted.Fronted } // clientCallbacks are callbacks the client is configured with @@ -177,20 +169,6 @@ func New( log.Errorf("user config: %v", err) } - globalConfig, err := config.NewGlobalOnDisk(f.configDir, f.flagsAsMap) - if err != nil { - fatalErr := fmt.Errorf("unable to initialize global config: %v", err) - f.op.FailIf(fatalErr) - f.op.End() - return nil, fatalErr - } - - f.fronted, err = fronted.NewFronted(filepath.Join(configDir, "masquerade_cache"), tls.HelloChrome_102, config.DefaultFrontedProviderID) - if err != nil { - log.Errorf("Unable to configure fronted: %v", err) - } - proxied.SetFronted(f.fronted) - var grabber dnsgrab.Server var grabberErr error if enableVPN { @@ -275,7 +253,15 @@ func New( } f.client = cl - f.onGlobalConfig(globalConfig, config.Embedded) + globalConfig, err := config.NewGlobalOnDisk(f.configDir, f.flagsAsMap) + if err != nil { + fatalErr := fmt.Errorf("unable to initialize global config: %v", err) + f.op.FailIf(fatalErr) + f.op.End() + return nil, fatalErr + } else { + f.onGlobalConfig(globalConfig, config.Embedded) + } f.addProxyListener(func(proxies map[string]*commonconfig.ProxyConfig, src config.Source) { log.Debug("Applying proxy config with proxies") @@ -367,7 +353,7 @@ func (f *Flashlight) StartBackgroundServices() (func(), error) { stopMonitor() stopBypass() stopGlobalConfigFetch() - }, fmt.Errorf("Unable to start config service: %w", err) + }, fmt.Errorf("unable to start config service: %w", err) } return func() { @@ -655,7 +641,7 @@ func (f *Flashlight) applyGlobalConfig(cfg *config.Global) { if err != nil { log.Errorf("Unable to get trusted ca certs, not configuring fronted: %s", err) } else if cfg.Client != nil && cfg.Client.Fronted != nil { - f.fronted.UpdateConfig(certs, cfg.Client.FrontedProviders()) + proxied.OnNewFronts(certs, cfg.Client.FrontedProviders()) } else { log.Errorf("Unable to configured fronted (no config)") } diff --git a/go.mod b/go.mod index 37801a1e2..903a8ecab 100644 --- a/go.mod +++ b/go.mod @@ -29,7 +29,7 @@ require ( github.com/getlantern/event v0.0.0-20210901195647-a7e3145142e6 github.com/getlantern/eventual v1.0.0 github.com/getlantern/eventual/v2 v2.0.2 - github.com/getlantern/fronted v0.0.0-20241210170228-72225de4ec5a + github.com/getlantern/fronted v0.0.0-20241212194832-a55b6db2616e github.com/getlantern/go-socks5 v0.0.0-20171114193258-79d4dd3e2db5 github.com/getlantern/golog v0.0.0-20230503153817-8e72de7e0a65 github.com/getlantern/hellosplitter v0.1.1 diff --git a/go.sum b/go.sum index c745d2814..629c9d2b9 100644 --- a/go.sum +++ b/go.sum @@ -267,8 +267,8 @@ github.com/getlantern/filepersist v0.0.0-20210901195658-ed29a1cb0b7c h1:mcz27xtA github.com/getlantern/filepersist v0.0.0-20210901195658-ed29a1cb0b7c/go.mod h1:8DGAx0LNUfXNnEH+fXI0s3OCBA/351kZCiz/8YSK3i8= github.com/getlantern/framed v0.0.0-20190601192238-ceb6431eeede h1:yrU6Px3ZkvCsDLPryPGi6FN+2iqFPq+JeCb7EFoDBhw= github.com/getlantern/framed v0.0.0-20190601192238-ceb6431eeede/go.mod h1:nhnoiS6DE6zfe+BaCMU4YI01UpsuiXnDqM5S8jxHuuI= -github.com/getlantern/fronted v0.0.0-20241210170228-72225de4ec5a h1:L+tVpvLMJvX/NwbVcKb4L7nPOf8X9bccaYp/0Duy2xU= -github.com/getlantern/fronted v0.0.0-20241210170228-72225de4ec5a/go.mod h1:UOynqDcVIlDMFk3sdUyHzNyY1cz4GHtJ+8qvWESHWhg= +github.com/getlantern/fronted v0.0.0-20241212194832-a55b6db2616e h1:qk62Xhg+ha1sW6FhOmGPGbd3xnCC5n9Mr87vDToE0cM= +github.com/getlantern/fronted v0.0.0-20241212194832-a55b6db2616e/go.mod h1:UOynqDcVIlDMFk3sdUyHzNyY1cz4GHtJ+8qvWESHWhg= github.com/getlantern/geo v0.0.0-20241129152027-2fc88c10f91e h1:vpikNz6IzvEoqVYmiK5Uq+lE4TCzvMDqbZdxFbtGK1g= github.com/getlantern/geo v0.0.0-20241129152027-2fc88c10f91e/go.mod h1:RjQ0krF8NTCc5xo2Q1995/vZBnYg33h8svn15do7dLg= github.com/getlantern/go-socks5 v0.0.0-20171114193258-79d4dd3e2db5 h1:RBKofGGMt2k6eGBwX8mky9qunjL+KnAp9JdzXjiRkRw= diff --git a/proxied/fronted.go b/proxied/fronted.go index 9ae2fa99f..9f052cb50 100644 --- a/proxied/fronted.go +++ b/proxied/fronted.go @@ -1,11 +1,29 @@ package proxied import ( + "crypto/x509" "net/http" + "os" + "path/filepath" + "github.com/getlantern/flashlight/v7/common" "github.com/getlantern/flashlight/v7/ops" + "github.com/getlantern/fronted" ) +var fronter fronted.Fronted = newFronted() + +func newFronted() fronted.Fronted { + var cacheFile string + dir, err := os.UserConfigDir() + if err != nil { + log.Errorf("Unable to get user config dir: %v", err) + } else { + cacheFile = filepath.Join(dir, common.DefaultAppName, "fronted_cache.json") + } + return fronted.NewFronted(cacheFile) +} + // Fronted creates an http.RoundTripper that proxies request using domain // fronting. func Fronted(opName string) http.RoundTripper { @@ -28,3 +46,8 @@ func (f frontedRoundTripper) RoundTrip(req *http.Request) (*http.Response, error } return fronter.RoundTrip(req) } + +// OnNewFronts updates the fronted configuration with the new fronted providers. +func OnNewFronts(pool *x509.CertPool, providers map[string]*fronted.Provider) { + fronter.OnNewFronts(pool, providers) +} diff --git a/proxied/proxied.go b/proxied/proxied.go index 51e3c200a..614129217 100644 --- a/proxied/proxied.go +++ b/proxied/proxied.go @@ -22,7 +22,6 @@ import ( "github.com/getlantern/errors" "github.com/getlantern/eventual" - "github.com/getlantern/fronted" "github.com/getlantern/golog" "github.com/getlantern/keyman" "github.com/getlantern/netx" @@ -47,19 +46,8 @@ var ( // Shared client session cache for all connections clientSessionCache = tls.NewLRUClientSessionCache(1000) - - fronter fronted.Fronted - fronterMu sync.RWMutex ) -// SetFronted sets the fronted.Fronted to use for domain fronting. This is a bit hacky but otherwise would -// require a significant refactor of the proxied package. -func SetFronted(f fronted.Fronted) { - fronterMu.Lock() - fronter = f - fronterMu.Unlock() -} - func success(resp *http.Response) bool { return (resp.StatusCode > 199 && resp.StatusCode < 400) || resp.StatusCode == http.StatusUpgradeRequired }