diff --git a/adapter/inbound/listen.go b/adapter/inbound/listen.go index 18dc1bc24..1b86c811a 100644 --- a/adapter/inbound/listen.go +++ b/adapter/inbound/listen.go @@ -17,10 +17,18 @@ func SetTfo(open bool) { lc.DisableTFO = !open } +func Tfo() bool { + return !lc.DisableTFO +} + func SetMPTCP(open bool) { setMultiPathTCP(&lc.ListenConfig, open) } +func MPTCP() bool { + return getMultiPathTCP(&lc.ListenConfig) +} + func ListenContext(ctx context.Context, network, address string) (net.Listener, error) { return lc.Listen(ctx, network, address) } diff --git a/adapter/inbound/mptcp_go120.go b/adapter/inbound/mptcp_go120.go index f9b22533d..faae6ec5d 100644 --- a/adapter/inbound/mptcp_go120.go +++ b/adapter/inbound/mptcp_go120.go @@ -8,3 +8,7 @@ const multipathTCPAvailable = false func setMultiPathTCP(listenConfig *net.ListenConfig, open bool) { } + +func getMultiPathTCP(listenConfig *net.ListenConfig) bool { + return false +} diff --git a/adapter/inbound/mptcp_go121.go b/adapter/inbound/mptcp_go121.go index 6b35d1a83..9163878a7 100644 --- a/adapter/inbound/mptcp_go121.go +++ b/adapter/inbound/mptcp_go121.go @@ -9,3 +9,7 @@ const multipathTCPAvailable = true func setMultiPathTCP(listenConfig *net.ListenConfig, open bool) { listenConfig.SetMultipathTCP(open) } + +func getMultiPathTCP(listenConfig *net.ListenConfig) bool { + return listenConfig.MultipathTCP() +} diff --git a/config/config.go b/config/config.go index 5208d8359..f1ffbce1f 100644 --- a/config/config.go +++ b/config/config.go @@ -50,13 +50,12 @@ import ( // General config type General struct { Inbound - Controller - Mode T.TunnelMode `json:"mode"` - UnifiedDelay bool + Mode T.TunnelMode `json:"mode"` + UnifiedDelay bool `json:"unified-delay"` LogLevel log.LogLevel `json:"log-level"` IPv6 bool `json:"ipv6"` Interface string `json:"interface-name"` - RoutingMark int `json:"-"` + RoutingMark int `json:"routing-mark"` GeoXUrl GeoXUrl `json:"geox-url"` GeoAutoUpdate bool `json:"geo-auto-update"` GeoUpdateInterval int `json:"geo-update-interval"` @@ -91,24 +90,48 @@ type Inbound struct { InboundMPTCP bool `json:"inbound-mptcp"` } +// GeoXUrl config +type GeoXUrl struct { + GeoIp string `json:"geo-ip"` + Mmdb string `json:"mmdb"` + ASN string `json:"asn"` + GeoSite string `json:"geo-site"` +} + // Controller config type Controller struct { - ExternalController string `json:"-"` - ExternalControllerTLS string `json:"-"` - ExternalControllerUnix string `json:"-"` - ExternalUI string `json:"-"` - ExternalDohServer string `json:"-"` - Secret string `json:"-"` + ExternalController string + ExternalControllerTLS string + ExternalControllerUnix string + ExternalUI string + ExternalDohServer string + Secret string +} + +// Experimental config +type Experimental struct { + Fingerprints []string + QUICGoDisableGSO bool + QUICGoDisableECN bool + IP4PEnable bool +} + +// IPTables config +type IPTables struct { + Enable bool + InboundInterface string + Bypass []string + DnsRedirect bool } // NTP config type NTP struct { - Enable bool `yaml:"enable"` - Server string `yaml:"server"` - Port int `yaml:"port"` - Interval int `yaml:"interval"` - DialerProxy string `yaml:"dialer-proxy"` - WriteToSystem bool `yaml:"write-to-system"` + Enable bool + Server string + Port int + Interval int + DialerProxy string + WriteToSystem bool } // DNS config @@ -134,24 +157,11 @@ type DNS struct { // Profile config type Profile struct { - StoreSelected bool `yaml:"store-selected"` - StoreFakeIP bool `yaml:"store-fake-ip"` -} - -type TLS struct { - Certificate string `yaml:"certificate"` - PrivateKey string `yaml:"private-key"` - CustomTrustCert []string `yaml:"custom-certifactes"` -} - -// IPTables config -type IPTables struct { - Enable bool `yaml:"enable" json:"enable"` - InboundInterface string `yaml:"inbound-interface" json:"inbound-interface"` - Bypass []string `yaml:"bypass" json:"bypass"` - DnsRedirect bool `yaml:"dns-redirect" json:"dns-redirect"` + StoreSelected bool + StoreFakeIP bool } +// Sniffer config type Sniffer struct { Enable bool Sniffers map[snifferTypes.Type]SNIFF.SnifferConfig @@ -161,21 +171,21 @@ type Sniffer struct { ParsePureIp bool } -// Experimental config -type Experimental struct { - Fingerprints []string `yaml:"fingerprints"` - QUICGoDisableGSO bool `yaml:"quic-go-disable-gso"` - QUICGoDisableECN bool `yaml:"quic-go-disable-ecn"` - IP4PEnable bool `yaml:"dialer-ip4p-convert"` +// TLS config +type TLS struct { + Certificate string + PrivateKey string + CustomTrustCert []string } // Config is mihomo config manager type Config struct { General *General + Controller *Controller + Experimental *Experimental IPTables *IPTables NTP *NTP DNS *DNS - Experimental *Experimental Hosts *trie.DomainTrie[resolver.HostValue] Profile *Profile Rules []C.Rule @@ -190,15 +200,6 @@ type Config struct { TLS *TLS } -type RawNTP struct { - Enable bool `yaml:"enable"` - Server string `yaml:"server"` - ServerPort int `yaml:"server-port"` - Interval int `yaml:"interval"` - DialerProxy string `yaml:"dialer-proxy"` - WriteToSystem bool `yaml:"write-to-system"` -} - type RawDNS struct { Enable bool `yaml:"enable" json:"enable"` PreferH3 bool `yaml:"prefer-h3" json:"prefer-h3"` @@ -233,6 +234,15 @@ type RawClashForAndroid struct { UiSubtitlePattern string `yaml:"ui-subtitle-pattern" json:"ui-subtitle-pattern"` } +type RawNTP struct { + Enable bool `yaml:"enable" json:"enable"` + Server string `yaml:"server" json:"server"` + Port int `yaml:"port" json:"port"` + Interval int `yaml:"interval" json:"interval"` + DialerProxy string `yaml:"dialer-proxy" json:"dialer-proxy"` + WriteToSystem bool `yaml:"write-to-system" json:"write-to-system"` +} + type RawTun struct { Enable bool `yaml:"enable" json:"enable"` Device string `yaml:"device" json:"device"` @@ -244,35 +254,35 @@ type RawTun struct { MTU uint32 `yaml:"mtu" json:"mtu,omitempty"` GSO bool `yaml:"gso" json:"gso,omitempty"` GSOMaxSize uint32 `yaml:"gso-max-size" json:"gso-max-size,omitempty"` - //Inet4Address []netip.Prefix `yaml:"inet4-address" json:"inet4_address,omitempty"` - Inet6Address []netip.Prefix `yaml:"inet6-address" json:"inet6_address,omitempty"` - IPRoute2TableIndex int `yaml:"iproute2-table-index" json:"iproute2_table_index,omitempty"` - IPRoute2RuleIndex int `yaml:"iproute2-rule-index" json:"iproute2_rule_index,omitempty"` - AutoRedirect bool `yaml:"auto-redirect" json:"auto_redirect,omitempty"` - AutoRedirectInputMark uint32 `yaml:"auto-redirect-input-mark" json:"auto_redirect_input_mark,omitempty"` - AutoRedirectOutputMark uint32 `yaml:"auto-redirect-output-mark" json:"auto_redirect_output_mark,omitempty"` - StrictRoute bool `yaml:"strict-route" json:"strict_route,omitempty"` - RouteAddress []netip.Prefix `yaml:"route-address" json:"route_address,omitempty"` - RouteAddressSet []string `yaml:"route-address-set" json:"route_address_set,omitempty"` - RouteExcludeAddress []netip.Prefix `yaml:"route-exclude-address" json:"route_exclude_address,omitempty"` - RouteExcludeAddressSet []string `yaml:"route-exclude-address-set" json:"route_exclude_address_set,omitempty"` + //Inet4Address []netip.Prefix `yaml:"inet4-address" json:"inet4-address,omitempty"` + Inet6Address []netip.Prefix `yaml:"inet6-address" json:"inet6-address,omitempty"` + IPRoute2TableIndex int `yaml:"iproute2-table-index" json:"iproute2-table-index,omitempty"` + IPRoute2RuleIndex int `yaml:"iproute2-rule-index" json:"iproute2-rule-index,omitempty"` + AutoRedirect bool `yaml:"auto-redirect" json:"auto-redirect,omitempty"` + AutoRedirectInputMark uint32 `yaml:"auto-redirect-input-mark" json:"auto-redirect-input-mark,omitempty"` + AutoRedirectOutputMark uint32 `yaml:"auto-redirect-output-mark" json:"auto-redirect-output-mark,omitempty"` + StrictRoute bool `yaml:"strict-route" json:"strict-route,omitempty"` + RouteAddress []netip.Prefix `yaml:"route-address" json:"route-address,omitempty"` + RouteAddressSet []string `yaml:"route-address-set" json:"route-address-set,omitempty"` + RouteExcludeAddress []netip.Prefix `yaml:"route-exclude-address" json:"route-exclude-address,omitempty"` + RouteExcludeAddressSet []string `yaml:"route-exclude-address-set" json:"route-exclude-address-set,omitempty"` IncludeInterface []string `yaml:"include-interface" json:"include-interface,omitempty"` ExcludeInterface []string `yaml:"exclude-interface" json:"exclude-interface,omitempty"` - IncludeUID []uint32 `yaml:"include-uid" json:"include_uid,omitempty"` - IncludeUIDRange []string `yaml:"include-uid-range" json:"include_uid_range,omitempty"` - ExcludeUID []uint32 `yaml:"exclude-uid" json:"exclude_uid,omitempty"` - ExcludeUIDRange []string `yaml:"exclude-uid-range" json:"exclude_uid_range,omitempty"` - IncludeAndroidUser []int `yaml:"include-android-user" json:"include_android_user,omitempty"` - IncludePackage []string `yaml:"include-package" json:"include_package,omitempty"` - ExcludePackage []string `yaml:"exclude-package" json:"exclude_package,omitempty"` - EndpointIndependentNat bool `yaml:"endpoint-independent-nat" json:"endpoint_independent_nat,omitempty"` - UDPTimeout int64 `yaml:"udp-timeout" json:"udp_timeout,omitempty"` + IncludeUID []uint32 `yaml:"include-uid" json:"include-uid,omitempty"` + IncludeUIDRange []string `yaml:"include-uid-range" json:"include-uid-range,omitempty"` + ExcludeUID []uint32 `yaml:"exclude-uid" json:"exclude-uid,omitempty"` + ExcludeUIDRange []string `yaml:"exclude-uid-range" json:"exclude-uid-range,omitempty"` + IncludeAndroidUser []int `yaml:"include-android-user" json:"include-android-user,omitempty"` + IncludePackage []string `yaml:"include-package" json:"include-package,omitempty"` + ExcludePackage []string `yaml:"exclude-package" json:"exclude-package,omitempty"` + EndpointIndependentNat bool `yaml:"endpoint-independent-nat" json:"endpoint-independent-nat,omitempty"` + UDPTimeout int64 `yaml:"udp-timeout" json:"udp-timeout,omitempty"` FileDescriptor int `yaml:"file-descriptor" json:"file-descriptor"` - Inet4RouteAddress []netip.Prefix `yaml:"inet4-route-address" json:"inet4_route_address,omitempty"` - Inet6RouteAddress []netip.Prefix `yaml:"inet6-route-address" json:"inet6_route_address,omitempty"` - Inet4RouteExcludeAddress []netip.Prefix `yaml:"inet4-route-exclude-address" json:"inet4_route_exclude_address,omitempty"` - Inet6RouteExcludeAddress []netip.Prefix `yaml:"inet6-route-exclude-address" json:"inet6_route_exclude_address,omitempty"` + Inet4RouteAddress []netip.Prefix `yaml:"inet4-route-address" json:"inet4-route-address,omitempty"` + Inet6RouteAddress []netip.Prefix `yaml:"inet6-route-address" json:"inet6-route-address,omitempty"` + Inet4RouteExcludeAddress []netip.Prefix `yaml:"inet4-route-exclude-address" json:"inet4-route-exclude-address,omitempty"` + Inet6RouteExcludeAddress []netip.Prefix `yaml:"inet6-route-exclude-address" json:"inet6-route-exclude-address,omitempty"` } type RawTuicServer struct { @@ -290,6 +300,55 @@ type RawTuicServer struct { CWND int `yaml:"cwnd" json:"cwnd,omitempty"` } +type RawIPTables struct { + Enable bool `yaml:"enable" json:"enable"` + InboundInterface string `yaml:"inbound-interface" json:"inbound-interface"` + Bypass []string `yaml:"bypass" json:"bypass"` + DnsRedirect bool `yaml:"dns-redirect" json:"dns-redirect"` +} + +type RawExperimental struct { + Fingerprints []string `yaml:"fingerprints"` + QUICGoDisableGSO bool `yaml:"quic-go-disable-gso"` + QUICGoDisableECN bool `yaml:"quic-go-disable-ecn"` + IP4PEnable bool `yaml:"dialer-ip4p-convert"` +} + +type RawProfile struct { + StoreSelected bool `yaml:"store-selected" json:"store-selected"` + StoreFakeIP bool `yaml:"store-fake-ip" json:"store-fake-ip"` +} + +type RawGeoXUrl struct { + GeoIp string `yaml:"geoip" json:"geoip"` + Mmdb string `yaml:"mmdb" json:"mmdb"` + ASN string `yaml:"asn" json:"asn"` + GeoSite string `yaml:"geosite" json:"geosite"` +} + +type RawSniffer struct { + Enable bool `yaml:"enable" json:"enable"` + OverrideDest bool `yaml:"override-destination" json:"override-destination"` + Sniffing []string `yaml:"sniffing" json:"sniffing"` + ForceDomain []string `yaml:"force-domain" json:"force-domain"` + SkipDomain []string `yaml:"skip-domain" json:"skip-domain"` + Ports []string `yaml:"port-whitelist" json:"port-whitelist"` + ForceDnsMapping bool `yaml:"force-dns-mapping" json:"force-dns-mapping"` + ParsePureIp bool `yaml:"parse-pure-ip" json:"parse-pure-ip"` + Sniff map[string]RawSniffingConfig `yaml:"sniff" json:"sniff"` +} + +type RawSniffingConfig struct { + Ports []string `yaml:"ports" json:"ports"` + OverrideDest *bool `yaml:"override-destination" json:"override-destination"` +} + +type RawTLS struct { + Certificate string `yaml:"certificate" json:"certificate"` + PrivateKey string `yaml:"private-key" json:"private-key"` + CustomTrustCert []string `yaml:"custom-certifactes" json:"custom-certifactes"` +} + type RawConfig struct { Port int `yaml:"port" json:"port"` SocksPort int `yaml:"socks-port" json:"socks-port"` @@ -301,9 +360,9 @@ type RawConfig struct { InboundTfo bool `yaml:"inbound-tfo" json:"inbound-tfo"` InboundMPTCP bool `yaml:"inbound-mptcp" json:"inbound-mptcp"` Authentication []string `yaml:"authentication" json:"authentication"` - SkipAuthPrefixes []netip.Prefix `yaml:"skip-auth-prefixes"` - LanAllowedIPs []netip.Prefix `yaml:"lan-allowed-ips"` - LanDisAllowedIPs []netip.Prefix `yaml:"lan-disallowed-ips"` + SkipAuthPrefixes []netip.Prefix `yaml:"skip-auth-prefixes" json:"skip-auth-prefixes"` + LanAllowedIPs []netip.Prefix `yaml:"lan-allowed-ips" json:"lan-allowed-ips"` + LanDisAllowedIPs []netip.Prefix `yaml:"lan-disallowed-ips" json:"lan-disallowed-ips"` AllowLan bool `yaml:"allow-lan" json:"allow-lan"` BindAddress string `yaml:"bind-address" json:"bind-address"` Mode T.TunnelMode `yaml:"mode" json:"mode"` @@ -334,52 +393,28 @@ type RawConfig struct { KeepAliveInterval int `yaml:"keep-alive-interval" json:"keep-alive-interval"` DisableKeepAlive bool `yaml:"disable-keep-alive" json:"disable-keep-alive"` - Sniffer RawSniffer `yaml:"sniffer" json:"sniffer"` - ProxyProvider map[string]map[string]any `yaml:"proxy-providers"` - RuleProvider map[string]map[string]any `yaml:"rule-providers"` + ProxyProvider map[string]map[string]any `yaml:"proxy-providers" json:"proxy-providers"` + RuleProvider map[string]map[string]any `yaml:"rule-providers" json:"rule-providers"` + Proxy []map[string]any `yaml:"proxies" json:"proxies"` + ProxyGroup []map[string]any `yaml:"proxy-groups" json:"proxy-groups"` + Rule []string `yaml:"rules" json:"rule"` + SubRules map[string][]string `yaml:"sub-rules" json:"sub-rules"` + Listeners []map[string]any `yaml:"listeners" json:"listeners"` 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"` - IPTables IPTables `yaml:"iptables"` - Experimental Experimental `yaml:"experimental"` - Profile Profile `yaml:"profile"` - GeoXUrl GeoXUrl `yaml:"geox-url"` - Proxy []map[string]any `yaml:"proxies"` - ProxyGroup []map[string]any `yaml:"proxy-groups"` - Rule []string `yaml:"rules"` - SubRules map[string][]string `yaml:"sub-rules"` - RawTLS TLS `yaml:"tls"` - Listeners []map[string]any `yaml:"listeners"` + NTP RawNTP `yaml:"ntp" json:"ntp"` + Tun RawTun `yaml:"tun" json:"tun"` + TuicServer RawTuicServer `yaml:"tuic-server" json:"tuic-server"` + IPTables RawIPTables `yaml:"iptables" json:"iptables"` + Experimental RawExperimental `yaml:"experimental" json:"experimental"` + Profile RawProfile `yaml:"profile" json:"profile"` + GeoXUrl RawGeoXUrl `yaml:"geox-url" json:"geox-url"` + Sniffer RawSniffer `yaml:"sniffer" json:"sniffer"` + TLS RawTLS `yaml:"tls" json:"tls"` ClashForAndroid RawClashForAndroid `yaml:"clash-for-android" json:"clash-for-android"` } -type GeoXUrl struct { - GeoIp string `yaml:"geoip" json:"geoip"` - Mmdb string `yaml:"mmdb" json:"mmdb"` - ASN string `yaml:"asn" json:"asn"` - GeoSite string `yaml:"geosite" json:"geosite"` -} - -type RawSniffer struct { - Enable bool `yaml:"enable" json:"enable"` - OverrideDest bool `yaml:"override-destination" json:"override-destination"` - Sniffing []string `yaml:"sniffing" json:"sniffing"` - ForceDomain []string `yaml:"force-domain" json:"force-domain"` - SkipDomain []string `yaml:"skip-domain" json:"skip-domain"` - Ports []string `yaml:"port-whitelist" json:"port-whitelist"` - ForceDnsMapping bool `yaml:"force-dns-mapping" json:"force-dns-mapping"` - ParsePureIp bool `yaml:"parse-pure-ip" json:"parse-pure-ip"` - Sniff map[string]RawSniffingConfig `yaml:"sniff" json:"sniff"` -} - -type RawSniffingConfig struct { - Ports []string `yaml:"ports" json:"ports"` - OverrideDest *bool `yaml:"override-destination" json:"override-destination"` -} - var ( GroupsList = list.New() ProxiesList = list.New() @@ -418,41 +453,6 @@ func UnmarshalRawConfig(buf []byte) (*RawConfig, error) { TCPConcurrent: false, FindProcessMode: P.FindProcessStrict, GlobalUA: "clash.meta/" + C.Version, - Tun: RawTun{ - Enable: false, - Device: "", - Stack: C.TunGvisor, - DNSHijack: []string{"0.0.0.0:53"}, // default hijack all dns query - AutoRoute: true, - AutoDetectInterface: true, - Inet6Address: []netip.Prefix{netip.MustParsePrefix("fdfe:dcba:9876::1/126")}, - }, - TuicServer: RawTuicServer{ - Enable: false, - Token: nil, - Users: nil, - Certificate: "", - PrivateKey: "", - Listen: "", - CongestionController: "", - MaxIdleTime: 15000, - AuthenticationTimeout: 1000, - ALPN: []string{"h3"}, - MaxUdpRelayPacketSize: 1500, - }, - IPTables: IPTables{ - Enable: false, - InboundInterface: "lo", - Bypass: []string{}, - DnsRedirect: true, - }, - NTP: RawNTP{ - Enable: false, - WriteToSystem: false, - Server: "time.apple.com", - ServerPort: 123, - Interval: 30, - }, DNS: RawDNS{ Enable: false, IPv6: false, @@ -483,11 +483,55 @@ func UnmarshalRawConfig(buf []byte) (*RawConfig, error) { "www.msftconnecttest.com", }, }, - Experimental: Experimental{ + NTP: RawNTP{ + Enable: false, + WriteToSystem: false, + Server: "time.apple.com", + Port: 123, + Interval: 30, + }, + Tun: RawTun{ + Enable: false, + Device: "", + Stack: C.TunGvisor, + DNSHijack: []string{"0.0.0.0:53"}, // default hijack all dns query + AutoRoute: true, + AutoDetectInterface: true, + Inet6Address: []netip.Prefix{netip.MustParsePrefix("fdfe:dcba:9876::1/126")}, + }, + TuicServer: RawTuicServer{ + Enable: false, + Token: nil, + Users: nil, + Certificate: "", + PrivateKey: "", + Listen: "", + CongestionController: "", + MaxIdleTime: 15000, + AuthenticationTimeout: 1000, + ALPN: []string{"h3"}, + MaxUdpRelayPacketSize: 1500, + }, + IPTables: RawIPTables{ + Enable: false, + InboundInterface: "lo", + Bypass: []string{}, + DnsRedirect: true, + }, + Experimental: RawExperimental{ // https://github.com/quic-go/quic-go/issues/4178 // Quic-go currently cannot automatically fall back on platforms that do not support ecn, so this feature is turned off by default. QUICGoDisableECN: true, }, + Profile: RawProfile{ + StoreSelected: true, + }, + GeoXUrl: RawGeoXUrl{ + Mmdb: "https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/geoip.metadb", + ASN: "https://github.com/xishang0128/geoip/releases/download/latest/GeoLite2-ASN.mmdb", + GeoIp: "https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/geoip.dat", + GeoSite: "https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/geosite.dat", + }, Sniffer: RawSniffer{ Enable: false, Sniff: map[string]RawSniffingConfig{}, @@ -498,15 +542,6 @@ func UnmarshalRawConfig(buf []byte) (*RawConfig, error) { ParsePureIp: true, OverrideDest: true, }, - Profile: Profile{ - StoreSelected: true, - }, - GeoXUrl: GeoXUrl{ - Mmdb: "https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/geoip.metadb", - ASN: "https://github.com/xishang0128/geoip/releases/download/latest/GeoLite2-ASN.mmdb", - GeoIp: "https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/geoip.dat", - GeoSite: "https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/geosite.dat", - }, ExternalUIURL: "https://github.com/MetaCubeX/metacubexd/archive/refs/heads/gh-pages.zip", } @@ -521,10 +556,6 @@ func ParseRawConfig(rawCfg *RawConfig) (*Config, error) { config := &Config{} log.Infoln("Start initial configuration in progress") //Segment finished in xxm startTime := time.Now() - config.Experimental = &rawCfg.Experimental - config.Profile = &rawCfg.Profile - config.IPTables = &rawCfg.IPTables - config.TLS = &rawCfg.RawTLS general, err := parseGeneral(rawCfg) if err != nil { @@ -537,6 +568,42 @@ func ParseRawConfig(rawCfg *RawConfig) (*Config, error) { tlsC.SetGlobalUtlsClient(config.General.GlobalClientFingerprint) } + controller, err := parseController(rawCfg) + if err != nil { + return nil, err + } + config.Controller = controller + + experimental, err := parseExperimental(rawCfg) + if err != nil { + return nil, err + } + config.Experimental = experimental + + iptables, err := parseIPTables(rawCfg) + if err != nil { + return nil, err + } + config.IPTables = iptables + + ntpCfg, err := parseNTP(rawCfg) + if err != nil { + return nil, err + } + config.NTP = ntpCfg + + profile, err := parseProfile(rawCfg) + if err != nil { + return nil, err + } + config.Profile = profile + + tlsCfg, err := parseTLS(rawCfg) + if err != nil { + return nil, err + } + config.TLS = tlsCfg + proxies, providers, err := parseProxies(rawCfg) if err != nil { return nil, err @@ -576,9 +643,6 @@ func ParseRawConfig(rawCfg *RawConfig) (*Config, error) { } config.Hosts = hosts - ntpCfg := paresNTP(rawCfg) - config.NTP = ntpCfg - dnsCfg, err := parseDNS(rawCfg, hosts, rules, ruleProviders) if err != nil { return nil, err @@ -687,21 +751,18 @@ func parseGeneral(cfg *RawConfig) (*General, error) { InboundTfo: cfg.InboundTfo, InboundMPTCP: cfg.InboundMPTCP, }, - Controller: Controller{ - ExternalController: cfg.ExternalController, - ExternalUI: cfg.ExternalUI, - Secret: cfg.Secret, - ExternalControllerUnix: cfg.ExternalControllerUnix, - ExternalControllerTLS: cfg.ExternalControllerTLS, - ExternalDohServer: cfg.ExternalDohServer, + UnifiedDelay: cfg.UnifiedDelay, + Mode: cfg.Mode, + LogLevel: cfg.LogLevel, + IPv6: cfg.IPv6, + Interface: cfg.Interface, + RoutingMark: cfg.RoutingMark, + GeoXUrl: GeoXUrl{ + GeoIp: cfg.GeoXUrl.GeoIp, + Mmdb: cfg.GeoXUrl.Mmdb, + ASN: cfg.GeoXUrl.ASN, + GeoSite: cfg.GeoXUrl.GeoSite, }, - UnifiedDelay: cfg.UnifiedDelay, - Mode: cfg.Mode, - LogLevel: cfg.LogLevel, - IPv6: cfg.IPv6, - Interface: cfg.Interface, - RoutingMark: cfg.RoutingMark, - GeoXUrl: cfg.GeoXUrl, GeoAutoUpdate: cfg.GeoAutoUpdate, GeoUpdateInterval: cfg.GeoUpdateInterval, GeodataMode: cfg.GeodataMode, @@ -713,6 +774,61 @@ func parseGeneral(cfg *RawConfig) (*General, error) { }, nil } +func parseController(cfg *RawConfig) (*Controller, error) { + return &Controller{ + ExternalController: cfg.ExternalController, + ExternalUI: cfg.ExternalUI, + Secret: cfg.Secret, + ExternalControllerUnix: cfg.ExternalControllerUnix, + ExternalControllerTLS: cfg.ExternalControllerTLS, + ExternalDohServer: cfg.ExternalDohServer, + }, nil +} + +func parseExperimental(cfg *RawConfig) (*Experimental, error) { + return &Experimental{ + Fingerprints: cfg.Experimental.Fingerprints, + QUICGoDisableGSO: cfg.Experimental.QUICGoDisableGSO, + QUICGoDisableECN: cfg.Experimental.QUICGoDisableECN, + IP4PEnable: cfg.Experimental.IP4PEnable, + }, nil +} + +func parseIPTables(cfg *RawConfig) (*IPTables, error) { + return &IPTables{ + Enable: cfg.IPTables.Enable, + InboundInterface: cfg.IPTables.InboundInterface, + Bypass: cfg.IPTables.Bypass, + DnsRedirect: cfg.IPTables.DnsRedirect, + }, nil +} + +func parseNTP(cfg *RawConfig) (*NTP, error) { + return &NTP{ + Enable: cfg.NTP.Enable, + Server: cfg.NTP.Server, + Port: cfg.NTP.Port, + Interval: cfg.NTP.Interval, + DialerProxy: cfg.NTP.DialerProxy, + WriteToSystem: cfg.NTP.WriteToSystem, + }, nil +} + +func parseProfile(cfg *RawConfig) (*Profile, error) { + return &Profile{ + StoreSelected: cfg.Profile.StoreSelected, + StoreFakeIP: cfg.Profile.StoreFakeIP, + }, nil +} + +func parseTLS(cfg *RawConfig) (*TLS, error) { + return &TLS{ + Certificate: cfg.TLS.Certificate, + PrivateKey: cfg.TLS.PrivateKey, + CustomTrustCert: cfg.TLS.CustomTrustCert, + }, nil +} + func parseProxies(cfg *RawConfig) (proxies map[string]C.Proxy, providersMap map[string]providerTypes.ProxyProvider, err error) { proxies = make(map[string]C.Proxy) providersMap = make(map[string]providerTypes.ProxyProvider) @@ -1259,19 +1375,6 @@ func parseNameServerPolicy(nsPolicy *orderedmap.OrderedMap[string, any], rules [ return policy, nil } -func paresNTP(rawCfg *RawConfig) *NTP { - cfg := rawCfg.NTP - ntpCfg := &NTP{ - Enable: cfg.Enable, - Server: cfg.Server, - Port: cfg.ServerPort, - Interval: cfg.Interval, - DialerProxy: cfg.DialerProxy, - WriteToSystem: cfg.WriteToSystem, - } - return ntpCfg -} - func parseDNS(rawCfg *RawConfig, hosts *trie.DomainTrie[resolver.HostValue], rules []C.Rule, ruleProviders map[string]providerTypes.RuleProvider) (*DNS, error) { cfg := rawCfg.DNS if cfg.Enable && len(cfg.NameServer) == 0 { diff --git a/hub/executor/executor.go b/hub/executor/executor.go index 8eb54ac4a..d54d55b75 100644 --- a/hub/executor/executor.go +++ b/hub/executor/executor.go @@ -22,6 +22,7 @@ import ( "github.com/metacubex/mihomo/component/profile/cachefile" "github.com/metacubex/mihomo/component/resolver" SNI "github.com/metacubex/mihomo/component/sniffer" + tlsC "github.com/metacubex/mihomo/component/tls" "github.com/metacubex/mihomo/component/trie" "github.com/metacubex/mihomo/component/updater" "github.com/metacubex/mihomo/config" @@ -90,7 +91,7 @@ func ApplyConfig(cfg *config.Config, force bool) { } } - updateExperimental(cfg) + updateExperimental(cfg.Experimental) updateUsers(cfg.Users) updateProxies(cfg.Proxies, cfg.Providers) updateRules(cfg.Rules, cfg.SubRules, cfg.RuleProviders) @@ -145,19 +146,31 @@ func GetGeneral() *config.General { LanDisAllowedIPs: inbound.DisAllowedIPs(), AllowLan: listener.AllowLan(), BindAddress: listener.BindAddress(), + InboundTfo: inbound.Tfo(), + InboundMPTCP: inbound.MPTCP(), }, - Controller: config.Controller{}, - Mode: tunnel.Mode(), - LogLevel: log.Level(), - IPv6: !resolver.DisableIPv6, - GeodataMode: G.GeodataMode(), - GeoAutoUpdate: G.GeoAutoUpdate(), - GeoUpdateInterval: G.GeoUpdateInterval(), - GeodataLoader: G.LoaderName(), - GeositeMatcher: G.SiteMatcherName(), - Interface: dialer.DefaultInterface.Load(), - Sniffing: tunnel.IsSniffing(), - TCPConcurrent: dialer.GetTcpConcurrent(), + Mode: tunnel.Mode(), + UnifiedDelay: adapter.UnifiedDelay.Load(), + LogLevel: log.Level(), + IPv6: !resolver.DisableIPv6, + Interface: dialer.DefaultInterface.Load(), + RoutingMark: int(dialer.DefaultRoutingMark.Load()), + GeoXUrl: config.GeoXUrl{ + GeoIp: C.GeoIpUrl, + Mmdb: C.MmdbUrl, + ASN: C.ASNUrl, + GeoSite: C.GeoSiteUrl, + }, + GeoAutoUpdate: G.GeoAutoUpdate(), + GeoUpdateInterval: G.GeoUpdateInterval(), + GeodataMode: G.GeodataMode(), + GeodataLoader: G.LoaderName(), + GeositeMatcher: G.SiteMatcherName(), + TCPConcurrent: dialer.GetTcpConcurrent(), + FindProcessMode: tunnel.FindProcessMode(), + Sniffing: tunnel.IsSniffing(), + GlobalClientFingerprint: tlsC.GetGlobalFingerprint(), + GlobalUA: C.UA, } return general @@ -188,14 +201,14 @@ func updateListeners(general *config.General, listeners map[string]C.InboundList listener.ReCreateTun(general.Tun, tunnel.Tunnel) } -func updateExperimental(c *config.Config) { - if c.Experimental.QUICGoDisableGSO { +func updateExperimental(c *config.Experimental) { + if c.QUICGoDisableGSO { _ = os.Setenv("QUIC_GO_DISABLE_GSO", strconv.FormatBool(true)) } - if c.Experimental.QUICGoDisableECN { + if c.QUICGoDisableECN { _ = os.Setenv("QUIC_GO_DISABLE_ECN", strconv.FormatBool(true)) } - dialer.GetIP4PEnable(c.Experimental.IP4PEnable) + dialer.GetIP4PEnable(c.IP4PEnable) } func updateNTP(c *config.NTP) { diff --git a/hub/hub.go b/hub/hub.go index 57c91aaef..2a53b1979 100644 --- a/hub/hub.go +++ b/hub/hub.go @@ -11,25 +11,25 @@ type Option func(*config.Config) func WithExternalUI(externalUI string) Option { return func(cfg *config.Config) { - cfg.General.ExternalUI = externalUI + cfg.Controller.ExternalUI = externalUI } } func WithExternalController(externalController string) Option { return func(cfg *config.Config) { - cfg.General.ExternalController = externalController + cfg.Controller.ExternalController = externalController } } func WithExternalControllerUnix(externalControllerUnix string) Option { return func(cfg *config.Config) { - cfg.General.ExternalControllerUnix = externalControllerUnix + cfg.Controller.ExternalControllerUnix = externalControllerUnix } } func WithSecret(secret string) Option { return func(cfg *config.Config) { - cfg.General.Secret = secret + cfg.Controller.Secret = secret } } @@ -44,18 +44,18 @@ func Parse(options ...Option) error { option(cfg) } - if cfg.General.ExternalUI != "" { - route.SetUIPath(cfg.General.ExternalUI) + if cfg.Controller.ExternalUI != "" { + route.SetUIPath(cfg.Controller.ExternalUI) } - if cfg.General.ExternalController != "" { - go route.Start(cfg.General.ExternalController, cfg.General.ExternalControllerTLS, - cfg.General.Secret, cfg.TLS.Certificate, cfg.TLS.PrivateKey, cfg.General.ExternalDohServer, + if cfg.Controller.ExternalController != "" { + go route.Start(cfg.Controller.ExternalController, cfg.Controller.ExternalControllerTLS, + cfg.Controller.Secret, cfg.TLS.Certificate, cfg.TLS.PrivateKey, cfg.Controller.ExternalDohServer, cfg.General.LogLevel == log.DEBUG) } - if cfg.General.ExternalControllerUnix != "" { - go route.StartUnix(cfg.General.ExternalControllerUnix, cfg.General.ExternalDohServer, cfg.General.LogLevel == log.DEBUG) + if cfg.Controller.ExternalControllerUnix != "" { + go route.StartUnix(cfg.Controller.ExternalControllerUnix, cfg.Controller.ExternalDohServer, cfg.General.LogLevel == log.DEBUG) } executor.ApplyConfig(cfg, true) diff --git a/hub/route/configs.go b/hub/route/configs.go index b31a607e9..d4bda2bf4 100644 --- a/hub/route/configs.go +++ b/hub/route/configs.go @@ -68,16 +68,16 @@ type tunSchema struct { GSOMaxSize *uint32 `yaml:"gso-max-size" json:"gso-max-size,omitempty"` //Inet4Address *[]netip.Prefix `yaml:"inet4-address" json:"inet4-address,omitempty"` Inet6Address *[]netip.Prefix `yaml:"inet6-address" json:"inet6-address,omitempty"` - IPRoute2TableIndex *int `yaml:"iproute2-table-index" json:"iproute2_table_index,omitempty"` - IPRoute2RuleIndex *int `yaml:"iproute2-rule-index" json:"iproute2_rule_index,omitempty"` - AutoRedirect *bool `yaml:"auto-redirect" json:"auto_redirect,omitempty"` - AutoRedirectInputMark *uint32 `yaml:"auto-redirect-input-mark" json:"auto_redirect_input_mark,omitempty"` - AutoRedirectOutputMark *uint32 `yaml:"auto-redirect-output-mark" json:"auto_redirect_output_mark,omitempty"` + IPRoute2TableIndex *int `yaml:"iproute2-table-index" json:"iproute2-table-index,omitempty"` + IPRoute2RuleIndex *int `yaml:"iproute2-rule-index" json:"iproute2-rule-index,omitempty"` + AutoRedirect *bool `yaml:"auto-redirect" json:"auto-redirect,omitempty"` + AutoRedirectInputMark *uint32 `yaml:"auto-redirect-input-mark" json:"auto-redirect-input-mark,omitempty"` + AutoRedirectOutputMark *uint32 `yaml:"auto-redirect-output-mark" json:"auto-redirect-output-mark,omitempty"` StrictRoute *bool `yaml:"strict-route" json:"strict-route,omitempty"` - RouteAddress *[]netip.Prefix `yaml:"route-address" json:"route_address,omitempty"` - RouteAddressSet *[]string `yaml:"route-address-set" json:"route_address_set,omitempty"` - RouteExcludeAddress *[]netip.Prefix `yaml:"route-exclude-address" json:"route_exclude_address,omitempty"` - RouteExcludeAddressSet *[]string `yaml:"route-exclude-address-set" json:"route_exclude_address_set,omitempty"` + RouteAddress *[]netip.Prefix `yaml:"route-address" json:"route-address,omitempty"` + RouteAddressSet *[]string `yaml:"route-address-set" json:"route-address-set,omitempty"` + RouteExcludeAddress *[]netip.Prefix `yaml:"route-exclude-address" json:"route-exclude-address,omitempty"` + RouteExcludeAddressSet *[]string `yaml:"route-exclude-address-set" json:"route-exclude-address-set,omitempty"` IncludeInterface *[]string `yaml:"include-interface" json:"include-interface,omitempty"` ExcludeInterface *[]string `yaml:"exclude-interface" json:"exclude-interface,omitempty"` IncludeUID *[]uint32 `yaml:"include-uid" json:"include-uid,omitempty"` diff --git a/listener/config/tun.go b/listener/config/tun.go index 06dc53ef6..3901bb1d6 100644 --- a/listener/config/tun.go +++ b/listener/config/tun.go @@ -34,16 +34,16 @@ type Tun struct { GSOMaxSize uint32 `yaml:"gso-max-size" json:"gso-max-size,omitempty"` Inet4Address []netip.Prefix `yaml:"inet4-address" json:"inet4-address,omitempty"` Inet6Address []netip.Prefix `yaml:"inet6-address" json:"inet6-address,omitempty"` - IPRoute2TableIndex int `yaml:"iproute2-table-index" json:"iproute2_table_index,omitempty"` - IPRoute2RuleIndex int `yaml:"iproute2-rule-index" json:"iproute2_rule_index,omitempty"` - AutoRedirect bool `yaml:"auto-redirect" json:"auto_redirect,omitempty"` - AutoRedirectInputMark uint32 `yaml:"auto-redirect-input-mark" json:"auto_redirect_input_mark,omitempty"` - AutoRedirectOutputMark uint32 `yaml:"auto-redirect-output-mark" json:"auto_redirect_output_mark,omitempty"` + IPRoute2TableIndex int `yaml:"iproute2-table-index" json:"iproute2-table-index,omitempty"` + IPRoute2RuleIndex int `yaml:"iproute2-rule-index" json:"iproute2-rule-index,omitempty"` + AutoRedirect bool `yaml:"auto-redirect" json:"auto-redirect,omitempty"` + AutoRedirectInputMark uint32 `yaml:"auto-redirect-input-mark" json:"auto-redirect-input-mark,omitempty"` + AutoRedirectOutputMark uint32 `yaml:"auto-redirect-output-mark" json:"auto-redirect-output-mark,omitempty"` StrictRoute bool `yaml:"strict-route" json:"strict-route,omitempty"` - RouteAddress []netip.Prefix `yaml:"route-address" json:"route_address,omitempty"` - RouteAddressSet []string `yaml:"route-address-set" json:"route_address_set,omitempty"` - RouteExcludeAddress []netip.Prefix `yaml:"route-exclude-address" json:"route_exclude_address,omitempty"` - RouteExcludeAddressSet []string `yaml:"route-exclude-address-set" json:"route_exclude_address_set,omitempty"` + RouteAddress []netip.Prefix `yaml:"route-address" json:"route-address,omitempty"` + RouteAddressSet []string `yaml:"route-address-set" json:"route-address-set,omitempty"` + RouteExcludeAddress []netip.Prefix `yaml:"route-exclude-address" json:"route-exclude-address,omitempty"` + RouteExcludeAddressSet []string `yaml:"route-exclude-address-set" json:"route-exclude-address-set,omitempty"` IncludeInterface []string `yaml:"include-interface" json:"include-interface,omitempty"` ExcludeInterface []string `yaml:"exclude-interface" json:"exclude-interface,omitempty"` IncludeUID []uint32 `yaml:"include-uid" json:"include-uid,omitempty"` diff --git a/listener/inbound/tun.go b/listener/inbound/tun.go index a950f80db..77ad6bd61 100644 --- a/listener/inbound/tun.go +++ b/listener/inbound/tun.go @@ -21,35 +21,35 @@ type TunOption struct { MTU uint32 `inbound:"mtu,omitempty"` GSO bool `inbound:"gso,omitempty"` GSOMaxSize uint32 `inbound:"gso-max-size,omitempty"` - Inet4Address []string `inbound:"inet4_address,omitempty"` - Inet6Address []string `inbound:"inet6_address,omitempty"` + Inet4Address []string `inbound:"inet4-address,omitempty"` + Inet6Address []string `inbound:"inet6-address,omitempty"` IPRoute2TableIndex int `inbound:"iproute2-table-index"` IPRoute2RuleIndex int `inbound:"iproute2-rule-index"` AutoRedirect bool `inbound:"auto-redirect"` AutoRedirectInputMark uint32 `inbound:"auto-redirect-input-mark"` AutoRedirectOutputMark uint32 `inbound:"auto-redirect-output-mark"` - StrictRoute bool `inbound:"strict_route,omitempty"` + StrictRoute bool `inbound:"strict-route,omitempty"` RouteAddress []string `inbound:"route-address"` RouteAddressSet []string `inbound:"route-address-set"` RouteExcludeAddress []string `inbound:"route-exclude-address"` RouteExcludeAddressSet []string `inbound:"route-exclude-address-set"` IncludeInterface []string `inbound:"include-interface,omitempty"` ExcludeInterface []string `inbound:"exclude-interface"` - IncludeUID []uint32 `inbound:"include_uid,omitempty"` - IncludeUIDRange []string `inbound:"include_uid_range,omitempty"` - ExcludeUID []uint32 `inbound:"exclude_uid,omitempty"` - ExcludeUIDRange []string `inbound:"exclude_uid_range,omitempty"` - IncludeAndroidUser []int `inbound:"include_android_user,omitempty"` - IncludePackage []string `inbound:"include_package,omitempty"` - ExcludePackage []string `inbound:"exclude_package,omitempty"` - EndpointIndependentNat bool `inbound:"endpoint_independent_nat,omitempty"` - UDPTimeout int64 `inbound:"udp_timeout,omitempty"` + IncludeUID []uint32 `inbound:"include-uid,omitempty"` + IncludeUIDRange []string `inbound:"include-uid-range,omitempty"` + ExcludeUID []uint32 `inbound:"exclude-uid,omitempty"` + ExcludeUIDRange []string `inbound:"exclude-uid-range,omitempty"` + IncludeAndroidUser []int `inbound:"include-android-user,omitempty"` + IncludePackage []string `inbound:"include-package,omitempty"` + ExcludePackage []string `inbound:"exclude-package,omitempty"` + EndpointIndependentNat bool `inbound:"endpoint-independent-nat,omitempty"` + UDPTimeout int64 `inbound:"udp-timeout,omitempty"` FileDescriptor int `inbound:"file-descriptor,omitempty"` - Inet4RouteAddress []string `inbound:"inet4_route_address,omitempty"` - Inet6RouteAddress []string `inbound:"inet6_route_address,omitempty"` - Inet4RouteExcludeAddress []string `inbound:"inet4_route_exclude_address,omitempty"` - Inet6RouteExcludeAddress []string `inbound:"inet6_route_exclude_address,omitempty"` + Inet4RouteAddress []string `inbound:"inet4-route-address,omitempty"` + Inet6RouteAddress []string `inbound:"inet6-route-address,omitempty"` + Inet4RouteExcludeAddress []string `inbound:"inet4-route-exclude-address,omitempty"` + Inet6RouteExcludeAddress []string `inbound:"inet6-route-exclude-address,omitempty"` } func (o TunOption) Equal(config C.InboundConfig) bool { diff --git a/tunnel/tunnel.go b/tunnel/tunnel.go index 5dd468f3b..b1b417bee 100644 --- a/tunnel/tunnel.go +++ b/tunnel/tunnel.go @@ -225,6 +225,10 @@ func SetMode(m TunnelMode) { mode = m } +func FindProcessMode() P.FindProcessMode { + return findProcessMode +} + // SetFindProcessMode replace SetAlwaysFindProcess // always find process info if legacyAlways = true or mode.Always() = true, may be increase many memory func SetFindProcessMode(mode P.FindProcessMode) {