diff --git a/config/config.go b/config/config.go index 96704c78..8a1cd40d 100644 --- a/config/config.go +++ b/config/config.go @@ -53,8 +53,10 @@ func BuildConfig(configOpt ConfigOptions, input option.Options) (*option.Options options.Experimental = &option.ExperimentalOptions{ ClashAPI: &option.ClashAPIOptions{ ExternalController: fmt.Sprintf("%s:%d", "127.0.0.1", configOpt.ClashApiPort), - StoreSelected: true, - CacheFile: "clash.db", + }, + CacheFile: &option.CacheFileOptions{ + Enabled: true, + Path: "clash.db", }, } } @@ -354,9 +356,10 @@ func BuildConfig(configOpt ConfigOptions, input option.Options) (*option.Options Type: C.TypeURLTest, Tag: "auto", URLTestOptions: option.URLTestOutboundOptions{ - Outbounds: tags, - URL: configOpt.ConnectionTestUrl, - Interval: configOpt.URLTestInterval, + Outbounds: tags, + URL: configOpt.ConnectionTestUrl, + Interval: configOpt.URLTestInterval, + IdleTimeout: configOpt.URLTestIdleTimeout, }, } @@ -408,7 +411,6 @@ func applyOverrides(overrides ConfigOptions, options option.Options) *option.Opt if overrides.EnableClashApi { options.Experimental.ClashAPI = &option.ClashAPIOptions{ ExternalController: fmt.Sprintf("%s:%d", "127.0.0.1", overrides.ClashApiPort), - StoreSelected: true, } } diff --git a/config/option.go b/config/option.go index 15a83021..e68f90c9 100644 --- a/config/option.go +++ b/config/option.go @@ -23,6 +23,7 @@ type ConfigOptions struct { TUNStack string `json:"tun-stack"` ConnectionTestUrl string `json:"connection-test-url"` URLTestInterval option.Duration `json:"url-test-interval"` + URLTestIdleTimeout option.Duration `json:"url-test-idle-timeout"` EnableClashApi bool `json:"enable-clash-api"` ClashApiPort uint16 `json:"clash-api-port"` EnableTun bool `json:"enable-tun"` @@ -72,6 +73,7 @@ func DefaultConfigOptions() *ConfigOptions { TUNStack: "mixed", ConnectionTestUrl: "https://cp.cloudflare.com/", URLTestInterval: option.Duration(10 * time.Minute), + URLTestIdleTimeout: option.Duration(100 * time.Minute), EnableClashApi: true, ClashApiPort: 6756, EnableTun: true, diff --git a/config/outbound.go b/config/outbound.go index b55bca48..22892ff4 100644 --- a/config/outbound.go +++ b/config/outbound.go @@ -11,6 +11,70 @@ import ( type outboundMap map[string]interface{} +func patchOutboundMux(base option.Outbound, configOpt ConfigOptions, obj outboundMap) outboundMap { + if configOpt.EnableMux { + multiplex := option.OutboundMultiplexOptions{ + Enabled: true, + Padding: configOpt.MuxPadding, + MaxStreams: configOpt.MaxStreams, + Protocol: configOpt.MuxProtocol, + } + obj["multiplex"] = multiplex + } else { + delete(obj, "multiplex") + } + return obj +} + +func patchOutboundTLSTricks(base option.Outbound, configOpt ConfigOptions, obj outboundMap) outboundMap { + + obj = patchOutboundFragment(base, configOpt, obj) + if tls, ok := obj["tls"].(map[string]interface{}); ok { + tlsTricks := option.TLSTricksOptions{ + MixedCaseSNI: configOpt.TLSTricks.EnableMixedSNICase, + } + + if configOpt.TLSTricks.EnablePadding { + tlsTricks.PaddingMode = "random" + tlsTricks.PaddingSize = configOpt.TLSTricks.PaddingSize + } + + if tlsTricks.MixedCaseSNI || tlsTricks.PaddingMode != "" { + tls["tls_tricks"] = tlsTricks + } else { + tls["tls_tricks"] = nil + } + } + return obj +} + +func patchOutboundFragment(base option.Outbound, configOpt ConfigOptions, obj outboundMap) outboundMap { + if configOpt.EnableFragment { + tlsFragment := option.TLSFragmentOptions{ + Enabled: configOpt.TLSTricks.EnableFragment, + Size: configOpt.TLSTricks.FragmentSize, + Sleep: configOpt.TLSTricks.FragmentSleep, + } + obj["tls_fragment"] = tlsFragment + } else { + obj["tls_fragment"] = nil + } + return obj +} + +func isOutboundReality(base option.Outbound) bool { + // this function checks reality status ONLY FOR VLESS. + // Some other protocols can also use reality, but it's discouraged as stated in the reality document + isReality := false + switch base.Type { + case C.TypeVLESS: + if base.VLESSOptions.TLS.Reality != nil { + isReality = base.VLESSOptions.TLS.Reality.Enabled + } + } + return isReality +} + func patchOutbound(base option.Outbound, configOpt ConfigOptions) (*option.Outbound, string, error) { var serverDomain string var outbound option.Outbound @@ -35,50 +99,12 @@ func patchOutbound(base option.Outbound, configOpt ConfigOptions) (*option.Outbo serverDomain = fmt.Sprintf("full:%s", server) } } - - if !(base.Type == C.TypeSelector || base.Type == C.TypeURLTest || base.Type == C.TypeBlock || base.Type == C.TypeDNS) { - if configOpt.EnableFragment { - tlsFragment := option.TLSFragmentOptions{ - Enabled: configOpt.TLSTricks.EnableFragment, - Size: configOpt.TLSTricks.FragmentSize, - Sleep: configOpt.TLSTricks.FragmentSleep, - } - obj["tls_fragment"] = tlsFragment - } else { - obj["tls_fragment"] = nil - } - - if tls, ok := obj["tls"].(map[string]interface{}); ok { - tlsTricks := option.TLSTricksOptions{ - MixedCaseSNI: configOpt.TLSTricks.EnableMixedSNICase, - } - - if configOpt.TLSTricks.EnablePadding { - tlsTricks.PaddingMode = "random" - tlsTricks.PaddingSize = configOpt.TLSTricks.PaddingSize - } - - if tlsTricks.MixedCaseSNI || tlsTricks.PaddingMode != "" { - tls["tls_tricks"] = tlsTricks - } else { - tls["tls_tricks"] = nil - } - } + if !(base.Type == C.TypeSelector || base.Type == C.TypeURLTest || base.Type == C.TypeBlock || base.Type == C.TypeDNS || isOutboundReality(base)) { + obj = patchOutboundTLSTricks(base, configOpt, obj) } - switch base.Type { case C.TypeVMess, C.TypeVLESS, C.TypeTrojan, C.TypeShadowsocks: - if configOpt.EnableMux { - multiplex := option.OutboundMultiplexOptions{ - Enabled: true, - Padding: configOpt.MuxPadding, - MaxStreams: configOpt.MaxStreams, - Protocol: configOpt.MuxProtocol, - } - obj["multiplex"] = multiplex - } else { - delete(obj, "multiplex") - } + obj = patchOutboundMux(base, configOpt, obj) } modifiedJson, err := json.Marshal(obj) diff --git a/custom/service.go b/custom/service.go index 9f2bc66a..d8ca677a 100644 --- a/custom/service.go +++ b/custom/service.go @@ -36,8 +36,6 @@ func NewService(options option.Options) (*libbox.BoxService, error) { ctx = filemanager.WithDefault(ctx, sWorkingPath, sTempPath, sUserID, sGroupID) urlTestHistoryStorage := urltest.NewHistoryStorage() ctx = service.ContextWithPtr(ctx, urlTestHistoryStorage) - pauseManager := pause.WithDefaultManager(ctx) - // ctx = pause.ContextWithManager(ctx, pauseManager) instance, err := B.New(B.Options{ Context: ctx, Options: options, @@ -51,7 +49,7 @@ func NewService(options option.Options) (*libbox.BoxService, error) { ctx, cancel, instance, - pauseManager, + service.FromContext[pause.Manager](ctx), urlTestHistoryStorage, ) return &service, nil