@@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user