diff --git a/adapter/inbound/packet.go b/adapter/inbound/packet.go index a10d402e..a87c6276 100644 --- a/adapter/inbound/packet.go +++ b/adapter/inbound/packet.go @@ -3,6 +3,7 @@ package inbound import ( C "github.com/metacubex/mihomo/constant" "github.com/metacubex/mihomo/transport/socks5" + "github.com/metacubex/mihomo/constant/features" ) // NewPacket is PacketAdapter generator diff --git a/adapter/provider/parser.go b/adapter/provider/parser.go index 966d33d6..f055e596 100644 --- a/adapter/provider/parser.go +++ b/adapter/provider/parser.go @@ -9,6 +9,7 @@ import ( "github.com/metacubex/mihomo/common/utils" "github.com/metacubex/mihomo/component/resource" C "github.com/metacubex/mihomo/constant" + "github.com/metacubex/mihomo/constant/features" types "github.com/metacubex/mihomo/constant/provider" ) @@ -78,7 +79,7 @@ func ParseProxyProvider(name string, mapping map[string]any) (types.ProxyProvide case "http": if schema.Path != "" { path := C.Path.Resolve(schema.Path) - if !C.Path.IsSafePath(path) { + if !features.Contains("cmfa") && !C.Path.IsSafePath(path) { return nil, fmt.Errorf("%w: %s", errSubPath, path) } vehicle = resource.NewHTTPVehicle(schema.URL, path) diff --git a/component/dialer/dialer.go b/component/dialer/dialer.go index 37a2bcba..8d1f671f 100644 --- a/component/dialer/dialer.go +++ b/component/dialer/dialer.go @@ -13,7 +13,6 @@ import ( "github.com/metacubex/mihomo/component/resolver" "github.com/metacubex/mihomo/constant/features" - "golang.org/x/exp/slices" ) type dialFunc func(ctx context.Context, network string, ips []netip.Addr, port string, opt *option) (net.Conn, error) @@ -72,7 +71,7 @@ func DialContext(ctx context.Context, network, address string, options ...Option } func ListenPacket(ctx context.Context, network, address string, options ...Option) (net.PacketConn, error) { - if slices.Contains(features.TAGS, "cmfa") { + if features.Contains("cmfa") && DefaultSocketHook != nil{ return listenPacketHooked(ctx, network, address) } @@ -120,7 +119,7 @@ func GetTcpConcurrent() bool { } func dialContext(ctx context.Context, network string, destination netip.Addr, port string, opt *option) (net.Conn, error) { - if slices.Contains(features.TAGS, "cmfa") { + if features.Contains("cmfa") && DefaultSocketHook != nil{ return dialContextHooked(ctx, network, destination, port) } diff --git a/component/dialer/patch_common.go b/component/dialer/patch_common.go index 9253d6b7..b1e8f2f9 100644 --- a/component/dialer/patch_common.go +++ b/component/dialer/patch_common.go @@ -6,8 +6,13 @@ import ( "context" "net" "net/netip" + "syscall" ) +type SocketControl func(network, address string, conn syscall.RawConn) error + +var DefaultSocketHook SocketControl + func dialContextHooked(ctx context.Context, network string, destination netip.Addr, port string) (net.Conn, error) { return nil, nil } diff --git a/config/config.go b/config/config.go index d808f702..c6c9aa55 100644 --- a/config/config.go +++ b/config/config.go @@ -29,6 +29,7 @@ import ( tlsC "github.com/metacubex/mihomo/component/tls" "github.com/metacubex/mihomo/component/trie" C "github.com/metacubex/mihomo/constant" + "github.com/metacubex/mihomo/constant/features" providerTypes "github.com/metacubex/mihomo/constant/provider" snifferTypes "github.com/metacubex/mihomo/constant/sniffer" "github.com/metacubex/mihomo/dns" @@ -194,21 +195,21 @@ type RawNTP struct { } type RawDNS struct { - Enable bool `yaml:"enable"` - PreferH3 bool `yaml:"prefer-h3"` - IPv6 bool `yaml:"ipv6"` - IPv6Timeout uint `yaml:"ipv6-timeout"` - UseHosts bool `yaml:"use-hosts"` - NameServer []string `yaml:"nameserver"` - Fallback []string `yaml:"fallback"` - FallbackFilter RawFallbackFilter `yaml:"fallback-filter"` - Listen string `yaml:"listen"` - EnhancedMode C.DNSMode `yaml:"enhanced-mode"` - FakeIPRange string `yaml:"fake-ip-range"` - FakeIPFilter []string `yaml:"fake-ip-filter"` - DefaultNameserver []string `yaml:"default-nameserver"` - NameServerPolicy *orderedmap.OrderedMap[string, any] `yaml:"nameserver-policy"` - ProxyServerNameserver []string `yaml:"proxy-server-nameserver"` + Enable bool `yaml:"enable" json:"enable"` + PreferH3 bool `yaml:"prefer-h3" json:"prefer-h3"` + IPv6 bool `yaml:"ipv6" json:"ipv6"` + IPv6Timeout uint `yaml:"ipv6-timeout" json:"ipv6-timeout"` + UseHosts bool `yaml:"use-hosts" json:"use-hosts"` + NameServer []string `yaml:"nameserver" json:"nameserver"` + Fallback []string `yaml:"fallback" json:"fallback"` + FallbackFilter RawFallbackFilter `yaml:"fallback-filter" json:"fallback-filter"` + Listen string `yaml:"listen" json:"listen"` + EnhancedMode C.DNSMode `yaml:"enhanced-mode" json:"enhanced-mode"` + FakeIPRange string `yaml:"fake-ip-range" json:"fake-ip-range"` + FakeIPFilter []string `yaml:"fake-ip-filter" json:"fake-ip-filter"` + DefaultNameserver []string `yaml:"default-nameserver" json:"default-nameserver"` + NameServerPolicy *orderedmap.OrderedMap[string, any] `yaml:"nameserver-policy" json:"nameserver-policy"` + ProxyServerNameserver []string `yaml:"proxy-server-nameserver" json:"proxy-server-nameserver"` } type RawFallbackFilter struct { @@ -269,23 +270,23 @@ type RawTuicServer struct { } type RawConfig struct { - Port int `yaml:"port"` - SocksPort int `yaml:"socks-port"` - RedirPort int `yaml:"redir-port"` - TProxyPort int `yaml:"tproxy-port"` - MixedPort int `yaml:"mixed-port"` + Port int `yaml:"port" json:"port"` + SocksPort int `yaml:"socks-port" json:"socks-port"` + RedirPort int `yaml:"redir-port" json:"redir-port"` + TProxyPort int `yaml:"tproxy-port" json:"tproxy-port"` + MixedPort int `yaml:"mixed-port" json:"mixed-port"` ShadowSocksConfig string `yaml:"ss-config"` VmessConfig string `yaml:"vmess-config"` InboundTfo bool `yaml:"inbound-tfo"` InboundMPTCP bool `yaml:"inbound-mptcp"` - Authentication []string `yaml:"authentication"` + Authentication []string `yaml:"authentication" json:"authentication"` SkipAuthPrefixes []netip.Prefix `yaml:"skip-auth-prefixes"` - AllowLan bool `yaml:"allow-lan"` - BindAddress string `yaml:"bind-address"` - Mode T.TunnelMode `yaml:"mode"` - UnifiedDelay bool `yaml:"unified-delay"` - LogLevel log.LogLevel `yaml:"log-level"` - IPv6 bool `yaml:"ipv6"` + AllowLan bool `yaml:"allow-lan" json:"allow-lan"` + BindAddress string `yaml:"bind-address" json:"bind-address"` + Mode T.TunnelMode `yaml:"mode" json:"mode"` + UnifiedDelay bool `yaml:"unified-delay" json:"unified-delay"` + LogLevel log.LogLevel `yaml:"log-level" json:"log-level"` + IPv6 bool `yaml:"ipv6" json:"ipv6"` ExternalController string `yaml:"external-controller"` ExternalControllerTLS string `yaml:"external-controller-tls"` ExternalUI string `yaml:"external-ui"` @@ -295,20 +296,20 @@ type RawConfig struct { Interface string `yaml:"interface-name"` RoutingMark int `yaml:"routing-mark"` Tunnels []LC.Tunnel `yaml:"tunnels"` - GeodataMode bool `yaml:"geodata-mode"` - GeodataLoader string `yaml:"geodata-loader"` + GeodataMode bool `yaml:"geodata-mode" json:"geodata-mode"` + GeodataLoader string `yaml:"geodata-loader" json:"geodata-loader"` TCPConcurrent bool `yaml:"tcp-concurrent" json:"tcp-concurrent"` FindProcessMode P.FindProcessMode `yaml:"find-process-mode" json:"find-process-mode"` GlobalClientFingerprint string `yaml:"global-client-fingerprint"` GlobalUA string `yaml:"global-ua"` KeepAliveInterval int `yaml:"keep-alive-interval"` - Sniffer RawSniffer `yaml:"sniffer"` + Sniffer RawSniffer `yaml:"sniffer" json:"sniffer"` ProxyProvider map[string]map[string]any `yaml:"proxy-providers"` RuleProvider map[string]map[string]any `yaml:"rule-providers"` - Hosts map[string]any `yaml:"hosts"` - NTP RawNTP `yaml:"ntp"` - DNS RawDNS `yaml:"dns"` + Hosts map[string]any `yaml:"hosts" json:"hosts"` + NTP RawNTP `yaml:"ntp" json:"ntp"` + DNS RawDNS `yaml:"dns" json:"dns"` Tun RawTun `yaml:"tun"` TuicServer RawTuicServer `yaml:"tuic-server"` EBpf EBpf `yaml:"ebpf"` @@ -323,7 +324,7 @@ type RawConfig struct { RawTLS TLS `yaml:"tls"` Listeners []map[string]any `yaml:"listeners"` - ClashForAndroid RawClashForAndroid `yaml:"clash-for-android"` + ClashForAndroid RawClashForAndroid `yaml:"clash-for-android" json:"clash-for-android"` } type GeoXUrl struct { @@ -553,7 +554,7 @@ func ParseRawConfig(rawCfg *RawConfig) (*Config, error) { config.DNS = dnsCfg err = parseTun(rawCfg.Tun, config.General) - if err != nil { + if !features.Contains("cmfa") && err != nil { return nil, err } diff --git a/constant/features/cmfa.go b/constant/features/cmfa.go index ab76b06d..e93ad625 100644 --- a/constant/features/cmfa.go +++ b/constant/features/cmfa.go @@ -1,4 +1,5 @@ //go:build cmfa + package features func init() { diff --git a/constant/features/low_memory.go b/constant/features/low_memory.go index 0d252113..ad52b555 100644 --- a/constant/features/low_memory.go +++ b/constant/features/low_memory.go @@ -1,4 +1,5 @@ //go:build with_low_memory + package features func init() { diff --git a/constant/features/tags.go b/constant/features/tags.go index c81f6d4e..8fe639a0 100644 --- a/constant/features/tags.go +++ b/constant/features/tags.go @@ -1,3 +1,11 @@ package features +import( + "golang.org/x/exp/slices" +) + var TAGS = make([]string, 0, 0) + +func Contains(feat string) (bool) { + return slices.Contains(TAGS, feat) +} \ No newline at end of file diff --git a/dns/server.go b/dns/server.go index 2eac173e..8371dbd8 100644 --- a/dns/server.go +++ b/dns/server.go @@ -6,6 +6,7 @@ import ( "net" "github.com/metacubex/mihomo/common/sockopt" + "github.com/metacubex/mihomo/constant/features" "github.com/metacubex/mihomo/context" "github.com/metacubex/mihomo/log" @@ -49,7 +50,9 @@ func (s *Server) SetHandler(handler handler) { } func ReCreateServer(addr string, resolver *Resolver, mapper *ResolverEnhancer) { - UpdateIsolateHandler(resolver, mapper) + if features.Contains("cmfa") { + UpdateIsolateHandler(resolver, mapper) + } if addr == address && resolver != nil { handler := NewHandler(resolver, mapper) diff --git a/hub/executor/executor.go b/hub/executor/executor.go index 216754cc..88da9d5d 100644 --- a/hub/executor/executor.go +++ b/hub/executor/executor.go @@ -36,7 +36,6 @@ import ( "github.com/metacubex/mihomo/ntp" "github.com/metacubex/mihomo/tunnel" "github.com/metacubex/mihomo/constant/features" - "golang.org/x/exp/slices" ) var mux sync.Mutex @@ -172,7 +171,7 @@ func updateListeners(general *config.General, listeners map[string]C.InboundList listener.ReCreateHTTP(general.Port, tunnel.Tunnel) listener.ReCreateSocks(general.SocksPort, tunnel.Tunnel) listener.ReCreateRedir(general.RedirPort, tunnel.Tunnel) - if !slices.Contains(features.TAGS, "cmfa") { + if !features.Contains("cmfa") { listener.ReCreateAutoRedir(general.EBpf.AutoRedir, tunnel.Tunnel) } listener.ReCreateTProxy(general.TProxyPort, tunnel.Tunnel) diff --git a/listener/http/server.go b/listener/http/server.go index 06389185..06797273 100644 --- a/listener/http/server.go +++ b/listener/http/server.go @@ -7,7 +7,6 @@ import ( "github.com/metacubex/mihomo/common/cache" C "github.com/metacubex/mihomo/constant" "github.com/metacubex/mihomo/constant/features" - "golang.org/x/exp/slices" ) type Listener struct { @@ -67,7 +66,7 @@ func NewWithAuthenticate(addr string, tunnel C.Tunnel, authenticate bool, additi } continue } - if slices.Contains(features.TAGS, "cmfa") { + if features.Contains("cmfa") { if t, ok := conn.(*net.TCPConn); ok { t.SetKeepAlive(false) } diff --git a/rules/provider/parse.go b/rules/provider/parse.go index 3a5c4fd7..8319b737 100644 --- a/rules/provider/parse.go +++ b/rules/provider/parse.go @@ -8,6 +8,7 @@ import ( "github.com/metacubex/mihomo/common/structure" "github.com/metacubex/mihomo/component/resource" C "github.com/metacubex/mihomo/constant" + "github.com/metacubex/mihomo/constant/features" P "github.com/metacubex/mihomo/constant/provider" ) @@ -62,7 +63,7 @@ func ParseRuleProvider(name string, mapping map[string]interface{}, parse func(t case "http": if schema.Path != "" { path := C.Path.Resolve(schema.Path) - if !C.Path.IsSafePath(path) { + if !features.Contains("cmfa") && !C.Path.IsSafePath(path) { return nil, fmt.Errorf("%w: %s", errSubPath, path) } vehicle = resource.NewHTTPVehicle(schema.URL, path)