diff --git a/config/config.go b/config/config.go index ef3f20f..72ee15f 100644 --- a/config/config.go +++ b/config/config.go @@ -325,51 +325,12 @@ func BuildConfig(configOpt ConfigOptions, input option.Options) option.Options { var outbounds []option.Outbound var tags []string for _, out := range input.Outbounds { - jsonData, err := out.MarshalJSON() + outbound, serverDomain, err := patchOutbound(out, configOpt) if err == nil { - var obj map[string]interface{} - err = json.Unmarshal(jsonData, &obj) - if err == nil { - if value, ok := obj["server"]; ok { - server := value.(string) - if server != "" && net.ParseIP(server) == nil { - directDNSDomains = append(directDNSDomains, fmt.Sprintf("full:%s", server)) - } - } - - if !(out.Type == C.TypeSelector || out.Type == C.TypeURLTest || out.Type == C.TypeBlock || out.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 - } - - if value, ok := obj["tls"]; 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 != "" { - value.(map[string]interface{})["tls_tricks"] = tlsTricks - } - } - } - - modifiedJson, err := json.Marshal(obj) - if err == nil { - err = out.UnmarshalJSON(modifiedJson) - if err != nil { - fmt.Println("error: ", out.Tag, out.Type, err) - } - } + if serverDomain != "" { + directDNSDomains = append(directDNSDomains, serverDomain) } + out = *outbound } switch out.Type { diff --git a/config/outbound.go b/config/outbound.go new file mode 100644 index 0000000..8c1dc77 --- /dev/null +++ b/config/outbound.go @@ -0,0 +1,78 @@ +package config + +import ( + "encoding/json" + "fmt" + "net" + + C "github.com/sagernet/sing-box/constant" + "github.com/sagernet/sing-box/option" +) + +func patchOutbound(base option.Outbound, configOpt ConfigOptions) (*option.Outbound, string, error) { + var serverDomain string + var outbound option.Outbound + + formatErr := func(err error) error { + return fmt.Errorf("error patching outbound[%s][%s]: %w", base.Tag, base.Type, err) + } + + jsonData, err := base.MarshalJSON() + if err != nil { + return nil, "", formatErr(err) + } + + var obj map[string]interface{} + err = json.Unmarshal(jsonData, &obj) + if err != nil { + return nil, "", formatErr(err) + } + + if server, ok := obj["server"].(string); ok { + if server != "" && net.ParseIP(server) == nil { + 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 + } + } + } + + modifiedJson, err := json.Marshal(obj) + if err != nil { + return nil, "", formatErr(err) + } + + err = outbound.UnmarshalJSON(modifiedJson) + if err != nil { + return nil, "", formatErr(err) + } + + return &outbound, serverDomain, nil +}