github.com/metacubex/mihomo@v1.18.5/config/config.go (about) 1 package config 2 3 import ( 4 "container/list" 5 "errors" 6 "fmt" 7 "net" 8 "net/netip" 9 "net/url" 10 "os" 11 "path" 12 "regexp" 13 "strings" 14 "time" 15 16 "github.com/metacubex/mihomo/adapter" 17 "github.com/metacubex/mihomo/adapter/outbound" 18 "github.com/metacubex/mihomo/adapter/outboundgroup" 19 "github.com/metacubex/mihomo/adapter/provider" 20 N "github.com/metacubex/mihomo/common/net" 21 "github.com/metacubex/mihomo/common/utils" 22 "github.com/metacubex/mihomo/component/auth" 23 "github.com/metacubex/mihomo/component/fakeip" 24 "github.com/metacubex/mihomo/component/geodata" 25 "github.com/metacubex/mihomo/component/geodata/router" 26 P "github.com/metacubex/mihomo/component/process" 27 "github.com/metacubex/mihomo/component/resolver" 28 SNIFF "github.com/metacubex/mihomo/component/sniffer" 29 tlsC "github.com/metacubex/mihomo/component/tls" 30 "github.com/metacubex/mihomo/component/trie" 31 "github.com/metacubex/mihomo/component/updater" 32 C "github.com/metacubex/mihomo/constant" 33 "github.com/metacubex/mihomo/constant/features" 34 providerTypes "github.com/metacubex/mihomo/constant/provider" 35 snifferTypes "github.com/metacubex/mihomo/constant/sniffer" 36 "github.com/metacubex/mihomo/dns" 37 L "github.com/metacubex/mihomo/listener" 38 LC "github.com/metacubex/mihomo/listener/config" 39 "github.com/metacubex/mihomo/log" 40 R "github.com/metacubex/mihomo/rules" 41 RP "github.com/metacubex/mihomo/rules/provider" 42 T "github.com/metacubex/mihomo/tunnel" 43 44 orderedmap "github.com/wk8/go-ordered-map/v2" 45 "gopkg.in/yaml.v3" 46 ) 47 48 // General config 49 type General struct { 50 Inbound 51 Controller 52 Mode T.TunnelMode `json:"mode"` 53 UnifiedDelay bool 54 LogLevel log.LogLevel `json:"log-level"` 55 IPv6 bool `json:"ipv6"` 56 Interface string `json:"interface-name"` 57 RoutingMark int `json:"-"` 58 GeoXUrl GeoXUrl `json:"geox-url"` 59 GeoAutoUpdate bool `json:"geo-auto-update"` 60 GeoUpdateInterval int `json:"geo-update-interval"` 61 GeodataMode bool `json:"geodata-mode"` 62 GeodataLoader string `json:"geodata-loader"` 63 GeositeMatcher string `json:"geosite-matcher"` 64 TCPConcurrent bool `json:"tcp-concurrent"` 65 FindProcessMode P.FindProcessMode `json:"find-process-mode"` 66 Sniffing bool `json:"sniffing"` 67 EBpf EBpf `json:"-"` 68 GlobalClientFingerprint string `json:"global-client-fingerprint"` 69 GlobalUA string `json:"global-ua"` 70 } 71 72 // Inbound config 73 type Inbound struct { 74 Port int `json:"port"` 75 SocksPort int `json:"socks-port"` 76 RedirPort int `json:"redir-port"` 77 TProxyPort int `json:"tproxy-port"` 78 MixedPort int `json:"mixed-port"` 79 Tun LC.Tun `json:"tun"` 80 TuicServer LC.TuicServer `json:"tuic-server"` 81 ShadowSocksConfig string `json:"ss-config"` 82 VmessConfig string `json:"vmess-config"` 83 Authentication []string `json:"authentication"` 84 SkipAuthPrefixes []netip.Prefix `json:"skip-auth-prefixes"` 85 LanAllowedIPs []netip.Prefix `json:"lan-allowed-ips"` 86 LanDisAllowedIPs []netip.Prefix `json:"lan-disallowed-ips"` 87 AllowLan bool `json:"allow-lan"` 88 BindAddress string `json:"bind-address"` 89 InboundTfo bool `json:"inbound-tfo"` 90 InboundMPTCP bool `json:"inbound-mptcp"` 91 } 92 93 // Controller config 94 type Controller struct { 95 ExternalController string `json:"-"` 96 ExternalControllerTLS string `json:"-"` 97 ExternalControllerUnix string `json:"-"` 98 ExternalUI string `json:"-"` 99 Secret string `json:"-"` 100 } 101 102 // NTP config 103 type NTP struct { 104 Enable bool `yaml:"enable"` 105 Server string `yaml:"server"` 106 Port int `yaml:"port"` 107 Interval int `yaml:"interval"` 108 DialerProxy string `yaml:"dialer-proxy"` 109 WriteToSystem bool `yaml:"write-to-system"` 110 } 111 112 // DNS config 113 type DNS struct { 114 Enable bool `yaml:"enable"` 115 PreferH3 bool `yaml:"prefer-h3"` 116 IPv6 bool `yaml:"ipv6"` 117 IPv6Timeout uint `yaml:"ipv6-timeout"` 118 UseSystemHosts bool `yaml:"use-system-hosts"` 119 NameServer []dns.NameServer `yaml:"nameserver"` 120 Fallback []dns.NameServer `yaml:"fallback"` 121 FallbackFilter FallbackFilter `yaml:"fallback-filter"` 122 Listen string `yaml:"listen"` 123 EnhancedMode C.DNSMode `yaml:"enhanced-mode"` 124 DefaultNameserver []dns.NameServer `yaml:"default-nameserver"` 125 CacheAlgorithm string `yaml:"cache-algorithm"` 126 FakeIPRange *fakeip.Pool 127 Hosts *trie.DomainTrie[resolver.HostValue] 128 NameServerPolicy *orderedmap.OrderedMap[string, []dns.NameServer] 129 ProxyServerNameserver []dns.NameServer 130 } 131 132 // FallbackFilter config 133 type FallbackFilter struct { 134 GeoIP bool `yaml:"geoip"` 135 GeoIPCode string `yaml:"geoip-code"` 136 IPCIDR []netip.Prefix `yaml:"ipcidr"` 137 Domain []string `yaml:"domain"` 138 GeoSite []router.DomainMatcher `yaml:"geosite"` 139 } 140 141 // Profile config 142 type Profile struct { 143 StoreSelected bool `yaml:"store-selected"` 144 StoreFakeIP bool `yaml:"store-fake-ip"` 145 } 146 147 type TLS struct { 148 Certificate string `yaml:"certificate"` 149 PrivateKey string `yaml:"private-key"` 150 CustomTrustCert []string `yaml:"custom-certifactes"` 151 } 152 153 // IPTables config 154 type IPTables struct { 155 Enable bool `yaml:"enable" json:"enable"` 156 InboundInterface string `yaml:"inbound-interface" json:"inbound-interface"` 157 Bypass []string `yaml:"bypass" json:"bypass"` 158 DnsRedirect bool `yaml:"dns-redirect" json:"dns-redirect"` 159 } 160 161 type Sniffer struct { 162 Enable bool 163 Sniffers map[snifferTypes.Type]SNIFF.SnifferConfig 164 ForceDomain *trie.DomainSet 165 SkipDomain *trie.DomainSet 166 ForceDnsMapping bool 167 ParsePureIp bool 168 } 169 170 // Experimental config 171 type Experimental struct { 172 Fingerprints []string `yaml:"fingerprints"` 173 QUICGoDisableGSO bool `yaml:"quic-go-disable-gso"` 174 QUICGoDisableECN bool `yaml:"quic-go-disable-ecn"` 175 IP4PEnable bool `yaml:"dialer-ip4p-convert"` 176 } 177 178 // Config is mihomo config manager 179 type Config struct { 180 General *General 181 IPTables *IPTables 182 NTP *NTP 183 DNS *DNS 184 Experimental *Experimental 185 Hosts *trie.DomainTrie[resolver.HostValue] 186 Profile *Profile 187 Rules []C.Rule 188 SubRules map[string][]C.Rule 189 Users []auth.AuthUser 190 Proxies map[string]C.Proxy 191 Listeners map[string]C.InboundListener 192 Providers map[string]providerTypes.ProxyProvider 193 RuleProviders map[string]providerTypes.RuleProvider 194 Tunnels []LC.Tunnel 195 Sniffer *Sniffer 196 TLS *TLS 197 } 198 199 type RawNTP struct { 200 Enable bool `yaml:"enable"` 201 Server string `yaml:"server"` 202 ServerPort int `yaml:"server-port"` 203 Interval int `yaml:"interval"` 204 DialerProxy string `yaml:"dialer-proxy"` 205 WriteToSystem bool `yaml:"write-to-system"` 206 } 207 208 type RawDNS struct { 209 Enable bool `yaml:"enable" json:"enable"` 210 PreferH3 bool `yaml:"prefer-h3" json:"prefer-h3"` 211 IPv6 bool `yaml:"ipv6" json:"ipv6"` 212 IPv6Timeout uint `yaml:"ipv6-timeout" json:"ipv6-timeout"` 213 UseHosts bool `yaml:"use-hosts" json:"use-hosts"` 214 UseSystemHosts bool `yaml:"use-system-hosts" json:"use-system-hosts"` 215 NameServer []string `yaml:"nameserver" json:"nameserver"` 216 Fallback []string `yaml:"fallback" json:"fallback"` 217 FallbackFilter RawFallbackFilter `yaml:"fallback-filter" json:"fallback-filter"` 218 Listen string `yaml:"listen" json:"listen"` 219 EnhancedMode C.DNSMode `yaml:"enhanced-mode" json:"enhanced-mode"` 220 FakeIPRange string `yaml:"fake-ip-range" json:"fake-ip-range"` 221 FakeIPFilter []string `yaml:"fake-ip-filter" json:"fake-ip-filter"` 222 DefaultNameserver []string `yaml:"default-nameserver" json:"default-nameserver"` 223 CacheAlgorithm string `yaml:"cache-algorithm" json:"cache-algorithm"` 224 NameServerPolicy *orderedmap.OrderedMap[string, any] `yaml:"nameserver-policy" json:"nameserver-policy"` 225 ProxyServerNameserver []string `yaml:"proxy-server-nameserver" json:"proxy-server-nameserver"` 226 } 227 228 type RawFallbackFilter struct { 229 GeoIP bool `yaml:"geoip" json:"geoip"` 230 GeoIPCode string `yaml:"geoip-code" json:"geoip-code"` 231 IPCIDR []string `yaml:"ipcidr" json:"ipcidr"` 232 Domain []string `yaml:"domain" json:"domain"` 233 GeoSite []string `yaml:"geosite" json:"geosite"` 234 } 235 236 type RawClashForAndroid struct { 237 AppendSystemDNS bool `yaml:"append-system-dns" json:"append-system-dns"` 238 UiSubtitlePattern string `yaml:"ui-subtitle-pattern" json:"ui-subtitle-pattern"` 239 } 240 241 type RawTun struct { 242 Enable bool `yaml:"enable" json:"enable"` 243 Device string `yaml:"device" json:"device"` 244 Stack C.TUNStack `yaml:"stack" json:"stack"` 245 DNSHijack []string `yaml:"dns-hijack" json:"dns-hijack"` 246 AutoRoute bool `yaml:"auto-route" json:"auto-route"` 247 AutoDetectInterface bool `yaml:"auto-detect-interface"` 248 RedirectToTun []string `yaml:"-" json:"-"` 249 250 MTU uint32 `yaml:"mtu" json:"mtu,omitempty"` 251 GSO bool `yaml:"gso" json:"gso,omitempty"` 252 GSOMaxSize uint32 `yaml:"gso-max-size" json:"gso-max-size,omitempty"` 253 //Inet4Address []netip.Prefix `yaml:"inet4-address" json:"inet4_address,omitempty"` 254 Inet6Address []netip.Prefix `yaml:"inet6-address" json:"inet6_address,omitempty"` 255 StrictRoute bool `yaml:"strict-route" json:"strict_route,omitempty"` 256 Inet4RouteAddress []netip.Prefix `yaml:"inet4-route-address" json:"inet4_route_address,omitempty"` 257 Inet6RouteAddress []netip.Prefix `yaml:"inet6-route-address" json:"inet6_route_address,omitempty"` 258 Inet4RouteExcludeAddress []netip.Prefix `yaml:"inet4-route-exclude-address" json:"inet4_route_exclude_address,omitempty"` 259 Inet6RouteExcludeAddress []netip.Prefix `yaml:"inet6-route-exclude-address" json:"inet6_route_exclude_address,omitempty"` 260 IncludeInterface []string `yaml:"include-interface" json:"include-interface,omitempty"` 261 ExcludeInterface []string `yaml:"exclude-interface" json:"exclude-interface,omitempty"` 262 IncludeUID []uint32 `yaml:"include-uid" json:"include_uid,omitempty"` 263 IncludeUIDRange []string `yaml:"include-uid-range" json:"include_uid_range,omitempty"` 264 ExcludeUID []uint32 `yaml:"exclude-uid" json:"exclude_uid,omitempty"` 265 ExcludeUIDRange []string `yaml:"exclude-uid-range" json:"exclude_uid_range,omitempty"` 266 IncludeAndroidUser []int `yaml:"include-android-user" json:"include_android_user,omitempty"` 267 IncludePackage []string `yaml:"include-package" json:"include_package,omitempty"` 268 ExcludePackage []string `yaml:"exclude-package" json:"exclude_package,omitempty"` 269 EndpointIndependentNat bool `yaml:"endpoint-independent-nat" json:"endpoint_independent_nat,omitempty"` 270 UDPTimeout int64 `yaml:"udp-timeout" json:"udp_timeout,omitempty"` 271 FileDescriptor int `yaml:"file-descriptor" json:"file-descriptor"` 272 TableIndex int `yaml:"table-index" json:"table-index"` 273 } 274 275 type RawTuicServer struct { 276 Enable bool `yaml:"enable" json:"enable"` 277 Listen string `yaml:"listen" json:"listen"` 278 Token []string `yaml:"token" json:"token"` 279 Users map[string]string `yaml:"users" json:"users,omitempty"` 280 Certificate string `yaml:"certificate" json:"certificate"` 281 PrivateKey string `yaml:"private-key" json:"private-key"` 282 CongestionController string `yaml:"congestion-controller" json:"congestion-controller,omitempty"` 283 MaxIdleTime int `yaml:"max-idle-time" json:"max-idle-time,omitempty"` 284 AuthenticationTimeout int `yaml:"authentication-timeout" json:"authentication-timeout,omitempty"` 285 ALPN []string `yaml:"alpn" json:"alpn,omitempty"` 286 MaxUdpRelayPacketSize int `yaml:"max-udp-relay-packet-size" json:"max-udp-relay-packet-size,omitempty"` 287 CWND int `yaml:"cwnd" json:"cwnd,omitempty"` 288 } 289 290 type RawConfig struct { 291 Port int `yaml:"port" json:"port"` 292 SocksPort int `yaml:"socks-port" json:"socks-port"` 293 RedirPort int `yaml:"redir-port" json:"redir-port"` 294 TProxyPort int `yaml:"tproxy-port" json:"tproxy-port"` 295 MixedPort int `yaml:"mixed-port" json:"mixed-port"` 296 ShadowSocksConfig string `yaml:"ss-config"` 297 VmessConfig string `yaml:"vmess-config"` 298 InboundTfo bool `yaml:"inbound-tfo"` 299 InboundMPTCP bool `yaml:"inbound-mptcp"` 300 Authentication []string `yaml:"authentication" json:"authentication"` 301 SkipAuthPrefixes []netip.Prefix `yaml:"skip-auth-prefixes"` 302 LanAllowedIPs []netip.Prefix `yaml:"lan-allowed-ips"` 303 LanDisAllowedIPs []netip.Prefix `yaml:"lan-disallowed-ips"` 304 AllowLan bool `yaml:"allow-lan" json:"allow-lan"` 305 BindAddress string `yaml:"bind-address" json:"bind-address"` 306 Mode T.TunnelMode `yaml:"mode" json:"mode"` 307 UnifiedDelay bool `yaml:"unified-delay" json:"unified-delay"` 308 LogLevel log.LogLevel `yaml:"log-level" json:"log-level"` 309 IPv6 bool `yaml:"ipv6" json:"ipv6"` 310 ExternalController string `yaml:"external-controller"` 311 ExternalControllerUnix string `yaml:"external-controller-unix"` 312 ExternalControllerTLS string `yaml:"external-controller-tls"` 313 ExternalUI string `yaml:"external-ui"` 314 ExternalUIURL string `yaml:"external-ui-url" json:"external-ui-url"` 315 ExternalUIName string `yaml:"external-ui-name" json:"external-ui-name"` 316 Secret string `yaml:"secret"` 317 Interface string `yaml:"interface-name"` 318 RoutingMark int `yaml:"routing-mark"` 319 Tunnels []LC.Tunnel `yaml:"tunnels"` 320 GeoAutoUpdate bool `yaml:"geo-auto-update" json:"geo-auto-update"` 321 GeoUpdateInterval int `yaml:"geo-update-interval" json:"geo-update-interval"` 322 GeodataMode bool `yaml:"geodata-mode" json:"geodata-mode"` 323 GeodataLoader string `yaml:"geodata-loader" json:"geodata-loader"` 324 GeositeMatcher string `yaml:"geosite-matcher" json:"geosite-matcher"` 325 TCPConcurrent bool `yaml:"tcp-concurrent" json:"tcp-concurrent"` 326 FindProcessMode P.FindProcessMode `yaml:"find-process-mode" json:"find-process-mode"` 327 GlobalClientFingerprint string `yaml:"global-client-fingerprint"` 328 GlobalUA string `yaml:"global-ua"` 329 KeepAliveInterval int `yaml:"keep-alive-interval"` 330 331 Sniffer RawSniffer `yaml:"sniffer" json:"sniffer"` 332 ProxyProvider map[string]map[string]any `yaml:"proxy-providers"` 333 RuleProvider map[string]map[string]any `yaml:"rule-providers"` 334 Hosts map[string]any `yaml:"hosts" json:"hosts"` 335 NTP RawNTP `yaml:"ntp" json:"ntp"` 336 DNS RawDNS `yaml:"dns" json:"dns"` 337 Tun RawTun `yaml:"tun"` 338 TuicServer RawTuicServer `yaml:"tuic-server"` 339 EBpf EBpf `yaml:"ebpf"` 340 IPTables IPTables `yaml:"iptables"` 341 Experimental Experimental `yaml:"experimental"` 342 Profile Profile `yaml:"profile"` 343 GeoXUrl GeoXUrl `yaml:"geox-url"` 344 Proxy []map[string]any `yaml:"proxies"` 345 ProxyGroup []map[string]any `yaml:"proxy-groups"` 346 Rule []string `yaml:"rules"` 347 SubRules map[string][]string `yaml:"sub-rules"` 348 RawTLS TLS `yaml:"tls"` 349 Listeners []map[string]any `yaml:"listeners"` 350 351 ClashForAndroid RawClashForAndroid `yaml:"clash-for-android" json:"clash-for-android"` 352 } 353 354 type GeoXUrl struct { 355 GeoIp string `yaml:"geoip" json:"geoip"` 356 Mmdb string `yaml:"mmdb" json:"mmdb"` 357 ASN string `yaml:"asn" json:"asn"` 358 GeoSite string `yaml:"geosite" json:"geosite"` 359 } 360 361 type RawSniffer struct { 362 Enable bool `yaml:"enable" json:"enable"` 363 OverrideDest bool `yaml:"override-destination" json:"override-destination"` 364 Sniffing []string `yaml:"sniffing" json:"sniffing"` 365 ForceDomain []string `yaml:"force-domain" json:"force-domain"` 366 SkipDomain []string `yaml:"skip-domain" json:"skip-domain"` 367 Ports []string `yaml:"port-whitelist" json:"port-whitelist"` 368 ForceDnsMapping bool `yaml:"force-dns-mapping" json:"force-dns-mapping"` 369 ParsePureIp bool `yaml:"parse-pure-ip" json:"parse-pure-ip"` 370 Sniff map[string]RawSniffingConfig `yaml:"sniff" json:"sniff"` 371 } 372 373 type RawSniffingConfig struct { 374 Ports []string `yaml:"ports" json:"ports"` 375 OverrideDest *bool `yaml:"override-destination" json:"override-destination"` 376 } 377 378 // EBpf config 379 type EBpf struct { 380 RedirectToTun []string `yaml:"redirect-to-tun" json:"redirect-to-tun"` 381 AutoRedir []string `yaml:"auto-redir" json:"auto-redir"` 382 } 383 384 var ( 385 GroupsList = list.New() 386 ProxiesList = list.New() 387 ParsingProxiesCallback func(groupsList *list.List, proxiesList *list.List) 388 ) 389 390 // Parse config 391 func Parse(buf []byte) (*Config, error) { 392 rawCfg, err := UnmarshalRawConfig(buf) 393 if err != nil { 394 return nil, err 395 } 396 397 return ParseRawConfig(rawCfg) 398 } 399 400 func UnmarshalRawConfig(buf []byte) (*RawConfig, error) { 401 // config with default value 402 rawCfg := &RawConfig{ 403 AllowLan: false, 404 BindAddress: "*", 405 LanAllowedIPs: []netip.Prefix{netip.MustParsePrefix("0.0.0.0/0"), netip.MustParsePrefix("::/0")}, 406 IPv6: true, 407 Mode: T.Rule, 408 GeoAutoUpdate: false, 409 GeoUpdateInterval: 24, 410 GeodataMode: C.GeodataMode, 411 GeodataLoader: "memconservative", 412 UnifiedDelay: false, 413 Authentication: []string{}, 414 LogLevel: log.INFO, 415 Hosts: map[string]any{}, 416 Rule: []string{}, 417 Proxy: []map[string]any{}, 418 ProxyGroup: []map[string]any{}, 419 TCPConcurrent: false, 420 FindProcessMode: P.FindProcessStrict, 421 GlobalUA: "clash.meta/" + C.Version, 422 Tun: RawTun{ 423 Enable: false, 424 Device: "", 425 Stack: C.TunGvisor, 426 DNSHijack: []string{"0.0.0.0:53"}, // default hijack all dns query 427 AutoRoute: true, 428 AutoDetectInterface: true, 429 Inet6Address: []netip.Prefix{netip.MustParsePrefix("fdfe:dcba:9876::1/126")}, 430 }, 431 TuicServer: RawTuicServer{ 432 Enable: false, 433 Token: nil, 434 Users: nil, 435 Certificate: "", 436 PrivateKey: "", 437 Listen: "", 438 CongestionController: "", 439 MaxIdleTime: 15000, 440 AuthenticationTimeout: 1000, 441 ALPN: []string{"h3"}, 442 MaxUdpRelayPacketSize: 1500, 443 }, 444 EBpf: EBpf{ 445 RedirectToTun: []string{}, 446 AutoRedir: []string{}, 447 }, 448 IPTables: IPTables{ 449 Enable: false, 450 InboundInterface: "lo", 451 Bypass: []string{}, 452 DnsRedirect: true, 453 }, 454 NTP: RawNTP{ 455 Enable: false, 456 WriteToSystem: false, 457 Server: "time.apple.com", 458 ServerPort: 123, 459 Interval: 30, 460 }, 461 DNS: RawDNS{ 462 Enable: false, 463 IPv6: false, 464 UseHosts: true, 465 UseSystemHosts: true, 466 IPv6Timeout: 100, 467 EnhancedMode: C.DNSMapping, 468 FakeIPRange: "198.18.0.1/16", 469 FallbackFilter: RawFallbackFilter{ 470 GeoIP: true, 471 GeoIPCode: "CN", 472 IPCIDR: []string{}, 473 GeoSite: []string{}, 474 }, 475 DefaultNameserver: []string{ 476 "114.114.114.114", 477 "223.5.5.5", 478 "8.8.8.8", 479 "1.0.0.1", 480 }, 481 NameServer: []string{ 482 "https://doh.pub/dns-query", 483 "tls://223.5.5.5:853", 484 }, 485 FakeIPFilter: []string{ 486 "dns.msftnsci.com", 487 "www.msftnsci.com", 488 "www.msftconnecttest.com", 489 }, 490 }, 491 Experimental: Experimental{ 492 // https://github.com/quic-go/quic-go/issues/4178 493 // Quic-go currently cannot automatically fall back on platforms that do not support ecn, so this feature is turned off by default. 494 QUICGoDisableECN: true, 495 }, 496 Sniffer: RawSniffer{ 497 Enable: false, 498 Sniffing: []string{}, 499 ForceDomain: []string{}, 500 SkipDomain: []string{}, 501 Ports: []string{}, 502 ForceDnsMapping: true, 503 ParsePureIp: true, 504 OverrideDest: true, 505 }, 506 Profile: Profile{ 507 StoreSelected: true, 508 }, 509 GeoXUrl: GeoXUrl{ 510 Mmdb: "https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/geoip.metadb", 511 ASN: "https://github.com/xishang0128/geoip/releases/download/latest/GeoLite2-ASN.mmdb", 512 GeoIp: "https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/geoip.dat", 513 GeoSite: "https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/geosite.dat", 514 }, 515 ExternalUIURL: "https://github.com/MetaCubeX/metacubexd/archive/refs/heads/gh-pages.zip", 516 } 517 518 if err := yaml.Unmarshal(buf, rawCfg); err != nil { 519 return nil, err 520 } 521 522 return rawCfg, nil 523 } 524 525 func ParseRawConfig(rawCfg *RawConfig) (*Config, error) { 526 config := &Config{} 527 log.Infoln("Start initial configuration in progress") //Segment finished in xxm 528 startTime := time.Now() 529 config.Experimental = &rawCfg.Experimental 530 config.Profile = &rawCfg.Profile 531 config.IPTables = &rawCfg.IPTables 532 config.TLS = &rawCfg.RawTLS 533 534 general, err := parseGeneral(rawCfg) 535 if err != nil { 536 return nil, err 537 } 538 config.General = general 539 540 if len(config.General.GlobalClientFingerprint) != 0 { 541 log.Debugln("GlobalClientFingerprint: %s", config.General.GlobalClientFingerprint) 542 tlsC.SetGlobalUtlsClient(config.General.GlobalClientFingerprint) 543 } 544 545 proxies, providers, err := parseProxies(rawCfg) 546 if err != nil { 547 return nil, err 548 } 549 config.Proxies = proxies 550 config.Providers = providers 551 552 listener, err := parseListeners(rawCfg) 553 if err != nil { 554 return nil, err 555 } 556 config.Listeners = listener 557 558 log.Infoln("Geodata Loader mode: %s", geodata.LoaderName()) 559 log.Infoln("Geosite Matcher implementation: %s", geodata.SiteMatcherName()) 560 ruleProviders, err := parseRuleProviders(rawCfg) 561 if err != nil { 562 return nil, err 563 } 564 config.RuleProviders = ruleProviders 565 566 subRules, err := parseSubRules(rawCfg, proxies) 567 if err != nil { 568 return nil, err 569 } 570 config.SubRules = subRules 571 572 rules, err := parseRules(rawCfg.Rule, proxies, subRules, "rules") 573 if err != nil { 574 return nil, err 575 } 576 config.Rules = rules 577 578 hosts, err := parseHosts(rawCfg) 579 if err != nil { 580 return nil, err 581 } 582 config.Hosts = hosts 583 584 ntpCfg := paresNTP(rawCfg) 585 config.NTP = ntpCfg 586 587 dnsCfg, err := parseDNS(rawCfg, hosts, rules, ruleProviders) 588 if err != nil { 589 return nil, err 590 } 591 config.DNS = dnsCfg 592 593 err = parseTun(rawCfg.Tun, config.General) 594 if !features.CMFA && err != nil { 595 return nil, err 596 } 597 598 err = parseTuicServer(rawCfg.TuicServer, config.General) 599 if err != nil { 600 return nil, err 601 } 602 603 config.Users = parseAuthentication(rawCfg.Authentication) 604 605 config.Tunnels = rawCfg.Tunnels 606 // verify tunnels 607 for _, t := range config.Tunnels { 608 if len(t.Proxy) > 0 { 609 if _, ok := config.Proxies[t.Proxy]; !ok { 610 return nil, fmt.Errorf("tunnel proxy %s not found", t.Proxy) 611 } 612 } 613 } 614 615 config.Sniffer, err = parseSniffer(rawCfg.Sniffer) 616 if err != nil { 617 return nil, err 618 } 619 620 elapsedTime := time.Since(startTime) / time.Millisecond // duration in ms 621 log.Infoln("Initial configuration complete, total time: %dms", elapsedTime) //Segment finished in xxm 622 623 return config, nil 624 } 625 626 func parseGeneral(cfg *RawConfig) (*General, error) { 627 geodata.SetGeodataMode(cfg.GeodataMode) 628 geodata.SetGeoAutoUpdate(cfg.GeoAutoUpdate) 629 geodata.SetGeoUpdateInterval(cfg.GeoUpdateInterval) 630 geodata.SetLoader(cfg.GeodataLoader) 631 geodata.SetSiteMatcher(cfg.GeositeMatcher) 632 C.GeoAutoUpdate = cfg.GeoAutoUpdate 633 C.GeoUpdateInterval = cfg.GeoUpdateInterval 634 C.GeoIpUrl = cfg.GeoXUrl.GeoIp 635 C.GeoSiteUrl = cfg.GeoXUrl.GeoSite 636 C.MmdbUrl = cfg.GeoXUrl.Mmdb 637 C.ASNUrl = cfg.GeoXUrl.ASN 638 C.GeodataMode = cfg.GeodataMode 639 C.UA = cfg.GlobalUA 640 if cfg.KeepAliveInterval != 0 { 641 N.KeepAliveInterval = time.Duration(cfg.KeepAliveInterval) * time.Second 642 } 643 644 updater.ExternalUIPath = cfg.ExternalUI 645 // checkout externalUI exist 646 if updater.ExternalUIPath != "" { 647 updater.ExternalUIPath = C.Path.Resolve(updater.ExternalUIPath) 648 if _, err := os.Stat(updater.ExternalUIPath); os.IsNotExist(err) { 649 defaultUIpath := path.Join(C.Path.HomeDir(), "ui") 650 log.Warnln("external-ui: %s does not exist, creating folder in %s", updater.ExternalUIPath, defaultUIpath) 651 if err := os.MkdirAll(defaultUIpath, os.ModePerm); err != nil { 652 return nil, err 653 } 654 updater.ExternalUIPath = defaultUIpath 655 cfg.ExternalUI = defaultUIpath 656 } 657 } 658 // checkout UIpath/name exist 659 if cfg.ExternalUIName != "" { 660 updater.ExternalUIName = cfg.ExternalUIName 661 } else { 662 updater.ExternalUIFolder = updater.ExternalUIPath 663 } 664 if cfg.ExternalUIURL != "" { 665 updater.ExternalUIURL = cfg.ExternalUIURL 666 } 667 668 cfg.Tun.RedirectToTun = cfg.EBpf.RedirectToTun 669 return &General{ 670 Inbound: Inbound{ 671 Port: cfg.Port, 672 SocksPort: cfg.SocksPort, 673 RedirPort: cfg.RedirPort, 674 TProxyPort: cfg.TProxyPort, 675 MixedPort: cfg.MixedPort, 676 ShadowSocksConfig: cfg.ShadowSocksConfig, 677 VmessConfig: cfg.VmessConfig, 678 AllowLan: cfg.AllowLan, 679 SkipAuthPrefixes: cfg.SkipAuthPrefixes, 680 LanAllowedIPs: cfg.LanAllowedIPs, 681 LanDisAllowedIPs: cfg.LanDisAllowedIPs, 682 BindAddress: cfg.BindAddress, 683 InboundTfo: cfg.InboundTfo, 684 InboundMPTCP: cfg.InboundMPTCP, 685 }, 686 Controller: Controller{ 687 ExternalController: cfg.ExternalController, 688 ExternalUI: cfg.ExternalUI, 689 Secret: cfg.Secret, 690 ExternalControllerUnix: cfg.ExternalControllerUnix, 691 ExternalControllerTLS: cfg.ExternalControllerTLS, 692 }, 693 UnifiedDelay: cfg.UnifiedDelay, 694 Mode: cfg.Mode, 695 LogLevel: cfg.LogLevel, 696 IPv6: cfg.IPv6, 697 Interface: cfg.Interface, 698 RoutingMark: cfg.RoutingMark, 699 GeoXUrl: cfg.GeoXUrl, 700 GeoAutoUpdate: cfg.GeoAutoUpdate, 701 GeoUpdateInterval: cfg.GeoUpdateInterval, 702 GeodataMode: cfg.GeodataMode, 703 GeodataLoader: cfg.GeodataLoader, 704 TCPConcurrent: cfg.TCPConcurrent, 705 FindProcessMode: cfg.FindProcessMode, 706 EBpf: cfg.EBpf, 707 GlobalClientFingerprint: cfg.GlobalClientFingerprint, 708 GlobalUA: cfg.GlobalUA, 709 }, nil 710 } 711 712 func parseProxies(cfg *RawConfig) (proxies map[string]C.Proxy, providersMap map[string]providerTypes.ProxyProvider, err error) { 713 proxies = make(map[string]C.Proxy) 714 providersMap = make(map[string]providerTypes.ProxyProvider) 715 proxiesConfig := cfg.Proxy 716 groupsConfig := cfg.ProxyGroup 717 providersConfig := cfg.ProxyProvider 718 719 var proxyList []string 720 var AllProxies []string 721 proxiesList := list.New() 722 groupsList := list.New() 723 724 proxies["DIRECT"] = adapter.NewProxy(outbound.NewDirect()) 725 proxies["REJECT"] = adapter.NewProxy(outbound.NewReject()) 726 proxies["REJECT-DROP"] = adapter.NewProxy(outbound.NewRejectDrop()) 727 proxies["COMPATIBLE"] = adapter.NewProxy(outbound.NewCompatible()) 728 proxies["PASS"] = adapter.NewProxy(outbound.NewPass()) 729 proxyList = append(proxyList, "DIRECT", "REJECT") 730 731 // parse proxy 732 for idx, mapping := range proxiesConfig { 733 proxy, err := adapter.ParseProxy(mapping) 734 if err != nil { 735 return nil, nil, fmt.Errorf("proxy %d: %w", idx, err) 736 } 737 738 if _, exist := proxies[proxy.Name()]; exist { 739 return nil, nil, fmt.Errorf("proxy %s is the duplicate name", proxy.Name()) 740 } 741 proxies[proxy.Name()] = proxy 742 proxyList = append(proxyList, proxy.Name()) 743 AllProxies = append(AllProxies, proxy.Name()) 744 proxiesList.PushBack(mapping) 745 } 746 747 // keep the original order of ProxyGroups in config file 748 for idx, mapping := range groupsConfig { 749 groupName, existName := mapping["name"].(string) 750 if !existName { 751 return nil, nil, fmt.Errorf("proxy group %d: missing name", idx) 752 } 753 proxyList = append(proxyList, groupName) 754 groupsList.PushBack(mapping) 755 } 756 757 // check if any loop exists and sort the ProxyGroups 758 if err := proxyGroupsDagSort(groupsConfig); err != nil { 759 return nil, nil, err 760 } 761 762 var AllProviders []string 763 // parse and initial providers 764 for name, mapping := range providersConfig { 765 if name == provider.ReservedName { 766 return nil, nil, fmt.Errorf("can not defined a provider called `%s`", provider.ReservedName) 767 } 768 769 pd, err := provider.ParseProxyProvider(name, mapping) 770 if err != nil { 771 return nil, nil, fmt.Errorf("parse proxy provider %s error: %w", name, err) 772 } 773 774 providersMap[name] = pd 775 AllProviders = append(AllProviders, name) 776 } 777 778 // parse proxy group 779 for idx, mapping := range groupsConfig { 780 group, err := outboundgroup.ParseProxyGroup(mapping, proxies, providersMap, AllProxies, AllProviders) 781 if err != nil { 782 return nil, nil, fmt.Errorf("proxy group[%d]: %w", idx, err) 783 } 784 785 groupName := group.Name() 786 if _, exist := proxies[groupName]; exist { 787 return nil, nil, fmt.Errorf("proxy group %s: the duplicate name", groupName) 788 } 789 790 proxies[groupName] = adapter.NewProxy(group) 791 } 792 793 var ps []C.Proxy 794 for _, v := range proxyList { 795 if proxies[v].Type() == C.Pass { 796 continue 797 } 798 ps = append(ps, proxies[v]) 799 } 800 hc := provider.NewHealthCheck(ps, "", 5000, 0, true, nil) 801 pd, _ := provider.NewCompatibleProvider(provider.ReservedName, ps, hc) 802 providersMap[provider.ReservedName] = pd 803 804 global := outboundgroup.NewSelector( 805 &outboundgroup.GroupCommonOption{ 806 Name: "GLOBAL", 807 }, 808 []providerTypes.ProxyProvider{pd}, 809 ) 810 proxies["GLOBAL"] = adapter.NewProxy(global) 811 ProxiesList = proxiesList 812 GroupsList = groupsList 813 if ParsingProxiesCallback != nil { 814 // refresh tray menu 815 go ParsingProxiesCallback(GroupsList, ProxiesList) 816 } 817 return proxies, providersMap, nil 818 } 819 820 func parseListeners(cfg *RawConfig) (listeners map[string]C.InboundListener, err error) { 821 listeners = make(map[string]C.InboundListener) 822 for index, mapping := range cfg.Listeners { 823 listener, err := L.ParseListener(mapping) 824 if err != nil { 825 return nil, fmt.Errorf("proxy %d: %w", index, err) 826 } 827 828 if _, exist := mapping[listener.Name()]; exist { 829 return nil, fmt.Errorf("listener %s is the duplicate name", listener.Name()) 830 } 831 832 listeners[listener.Name()] = listener 833 834 } 835 return 836 } 837 838 func parseRuleProviders(cfg *RawConfig) (ruleProviders map[string]providerTypes.RuleProvider, err error) { 839 ruleProviders = map[string]providerTypes.RuleProvider{} 840 // parse rule provider 841 for name, mapping := range cfg.RuleProvider { 842 rp, err := RP.ParseRuleProvider(name, mapping, R.ParseRule) 843 if err != nil { 844 return nil, err 845 } 846 847 ruleProviders[name] = rp 848 RP.SetRuleProvider(rp) 849 } 850 return 851 } 852 853 func parseSubRules(cfg *RawConfig, proxies map[string]C.Proxy) (subRules map[string][]C.Rule, err error) { 854 subRules = map[string][]C.Rule{} 855 for name := range cfg.SubRules { 856 subRules[name] = make([]C.Rule, 0) 857 } 858 for name, rawRules := range cfg.SubRules { 859 if len(name) == 0 { 860 return nil, fmt.Errorf("sub-rule name is empty") 861 } 862 var rules []C.Rule 863 rules, err = parseRules(rawRules, proxies, subRules, fmt.Sprintf("sub-rules[%s]", name)) 864 if err != nil { 865 return nil, err 866 } 867 subRules[name] = rules 868 } 869 870 if err = verifySubRule(subRules); err != nil { 871 return nil, err 872 } 873 874 return 875 } 876 877 func verifySubRule(subRules map[string][]C.Rule) error { 878 for name := range subRules { 879 err := verifySubRuleCircularReferences(name, subRules, []string{}) 880 if err != nil { 881 return err 882 } 883 } 884 return nil 885 } 886 887 func verifySubRuleCircularReferences(n string, subRules map[string][]C.Rule, arr []string) error { 888 isInArray := func(v string, array []string) bool { 889 for _, c := range array { 890 if v == c { 891 return true 892 } 893 } 894 return false 895 } 896 897 arr = append(arr, n) 898 for i, rule := range subRules[n] { 899 if rule.RuleType() == C.SubRules { 900 if _, ok := subRules[rule.Adapter()]; !ok { 901 return fmt.Errorf("sub-rule[%d:%s] error: [%s] not found", i, n, rule.Adapter()) 902 } 903 if isInArray(rule.Adapter(), arr) { 904 arr = append(arr, rule.Adapter()) 905 return fmt.Errorf("sub-rule error: circular references [%s]", strings.Join(arr, "->")) 906 } 907 908 if err := verifySubRuleCircularReferences(rule.Adapter(), subRules, arr); err != nil { 909 return err 910 } 911 } 912 } 913 return nil 914 } 915 916 func parseRules(rulesConfig []string, proxies map[string]C.Proxy, subRules map[string][]C.Rule, format string) ([]C.Rule, error) { 917 var rules []C.Rule 918 919 // parse rules 920 for idx, line := range rulesConfig { 921 rule := trimArr(strings.Split(line, ",")) 922 var ( 923 payload string 924 target string 925 params []string 926 ruleName = strings.ToUpper(rule[0]) 927 ) 928 929 l := len(rule) 930 931 if ruleName == "NOT" || ruleName == "OR" || ruleName == "AND" || ruleName == "SUB-RULE" || ruleName == "DOMAIN-REGEX" || ruleName == "PROCESS-NAME-REGEX" || ruleName == "PROCESS-PATH-REGEX" { 932 target = rule[l-1] 933 payload = strings.Join(rule[1:l-1], ",") 934 } else { 935 if l < 2 { 936 return nil, fmt.Errorf("%s[%d] [%s] error: format invalid", format, idx, line) 937 } 938 if l < 4 { 939 rule = append(rule, make([]string, 4-l)...) 940 } 941 if ruleName == "MATCH" { 942 l = 2 943 } 944 if l >= 3 { 945 l = 3 946 payload = rule[1] 947 } 948 target = rule[l-1] 949 params = rule[l:] 950 } 951 if _, ok := proxies[target]; !ok { 952 if ruleName != "SUB-RULE" { 953 return nil, fmt.Errorf("%s[%d] [%s] error: proxy [%s] not found", format, idx, line, target) 954 } else if _, ok = subRules[target]; !ok { 955 return nil, fmt.Errorf("%s[%d] [%s] error: sub-rule [%s] not found", format, idx, line, target) 956 } 957 } 958 959 params = trimArr(params) 960 parsed, parseErr := R.ParseRule(ruleName, payload, target, params, subRules) 961 if parseErr != nil { 962 return nil, fmt.Errorf("%s[%d] [%s] error: %s", format, idx, line, parseErr.Error()) 963 } 964 965 rules = append(rules, parsed) 966 } 967 968 return rules, nil 969 } 970 971 func parseHosts(cfg *RawConfig) (*trie.DomainTrie[resolver.HostValue], error) { 972 tree := trie.New[resolver.HostValue]() 973 974 // add default hosts 975 hostValue, _ := resolver.NewHostValueByIPs( 976 []netip.Addr{netip.AddrFrom4([4]byte{127, 0, 0, 1})}) 977 if err := tree.Insert("localhost", hostValue); err != nil { 978 log.Errorln("insert localhost to host error: %s", err.Error()) 979 } 980 981 if len(cfg.Hosts) != 0 { 982 for domain, anyValue := range cfg.Hosts { 983 if str, ok := anyValue.(string); ok && str == "lan" { 984 if addrs, err := net.InterfaceAddrs(); err != nil { 985 log.Errorln("insert lan to host error: %s", err) 986 } else { 987 ips := make([]netip.Addr, 0) 988 for _, addr := range addrs { 989 if ipnet, ok := addr.(*net.IPNet); ok && !ipnet.IP.IsLoopback() && !ipnet.IP.IsLinkLocalUnicast() { 990 if ip, err := netip.ParseAddr(ipnet.IP.String()); err == nil { 991 ips = append(ips, ip) 992 } 993 } 994 } 995 anyValue = ips 996 } 997 } 998 value, err := resolver.NewHostValue(anyValue) 999 if err != nil { 1000 return nil, fmt.Errorf("%s is not a valid value", anyValue) 1001 } 1002 if value.IsDomain { 1003 node := tree.Search(value.Domain) 1004 for node != nil && node.Data().IsDomain { 1005 if node.Data().Domain == domain { 1006 return nil, fmt.Errorf("%s, there is a cycle in domain name mapping", domain) 1007 } 1008 node = tree.Search(node.Data().Domain) 1009 } 1010 } 1011 _ = tree.Insert(domain, value) 1012 } 1013 } 1014 tree.Optimize() 1015 1016 return tree, nil 1017 } 1018 1019 func hostWithDefaultPort(host string, defPort string) (string, error) { 1020 hostname, port, err := net.SplitHostPort(host) 1021 if err != nil { 1022 if !strings.Contains(err.Error(), "missing port in address") { 1023 return "", err 1024 } 1025 host = host + ":" + defPort 1026 if hostname, port, err = net.SplitHostPort(host); err != nil { 1027 return "", err 1028 } 1029 } 1030 1031 return net.JoinHostPort(hostname, port), nil 1032 } 1033 1034 func parseNameServer(servers []string, preferH3 bool) ([]dns.NameServer, error) { 1035 var nameservers []dns.NameServer 1036 1037 for idx, server := range servers { 1038 server = parsePureDNSServer(server) 1039 u, err := url.Parse(server) 1040 if err != nil { 1041 return nil, fmt.Errorf("DNS NameServer[%d] format error: %s", idx, err.Error()) 1042 } 1043 1044 proxyName := u.Fragment 1045 1046 var addr, dnsNetType string 1047 params := map[string]string{} 1048 switch u.Scheme { 1049 case "udp": 1050 addr, err = hostWithDefaultPort(u.Host, "53") 1051 dnsNetType = "" // UDP 1052 case "tcp": 1053 addr, err = hostWithDefaultPort(u.Host, "53") 1054 dnsNetType = "tcp" // TCP 1055 case "tls": 1056 addr, err = hostWithDefaultPort(u.Host, "853") 1057 dnsNetType = "tcp-tls" // DNS over TLS 1058 case "https": 1059 addr, err = hostWithDefaultPort(u.Host, "443") 1060 if err == nil { 1061 proxyName = "" 1062 clearURL := url.URL{Scheme: "https", Host: addr, Path: u.Path, User: u.User} 1063 addr = clearURL.String() 1064 dnsNetType = "https" // DNS over HTTPS 1065 if len(u.Fragment) != 0 { 1066 for _, s := range strings.Split(u.Fragment, "&") { 1067 arr := strings.Split(s, "=") 1068 if len(arr) == 0 { 1069 continue 1070 } else if len(arr) == 1 { 1071 proxyName = arr[0] 1072 } else if len(arr) == 2 { 1073 params[arr[0]] = arr[1] 1074 } else { 1075 params[arr[0]] = strings.Join(arr[1:], "=") 1076 } 1077 } 1078 } 1079 } 1080 case "dhcp": 1081 addr = u.Host 1082 dnsNetType = "dhcp" // UDP from DHCP 1083 case "quic": 1084 addr, err = hostWithDefaultPort(u.Host, "853") 1085 dnsNetType = "quic" // DNS over QUIC 1086 case "system": 1087 dnsNetType = "system" // System DNS 1088 case "rcode": 1089 dnsNetType = "rcode" 1090 addr = u.Host 1091 switch addr { 1092 case "success", 1093 "format_error", 1094 "server_failure", 1095 "name_error", 1096 "not_implemented", 1097 "refused": 1098 default: 1099 err = fmt.Errorf("unsupported RCode type: %s", addr) 1100 } 1101 default: 1102 return nil, fmt.Errorf("DNS NameServer[%d] unsupport scheme: %s", idx, u.Scheme) 1103 } 1104 1105 if err != nil { 1106 return nil, fmt.Errorf("DNS NameServer[%d] format error: %s", idx, err.Error()) 1107 } 1108 1109 nameservers = append( 1110 nameservers, 1111 dns.NameServer{ 1112 Net: dnsNetType, 1113 Addr: addr, 1114 ProxyName: proxyName, 1115 Params: params, 1116 PreferH3: preferH3, 1117 }, 1118 ) 1119 } 1120 return nameservers, nil 1121 } 1122 1123 func init() { 1124 dns.ParseNameServer = func(servers []string) ([]dns.NameServer, error) { // using by wireguard 1125 return parseNameServer(servers, false) 1126 } 1127 } 1128 1129 func parsePureDNSServer(server string) string { 1130 addPre := func(server string) string { 1131 return "udp://" + server 1132 } 1133 1134 if server == "system" { 1135 return "system://" 1136 } 1137 1138 if ip, err := netip.ParseAddr(server); err != nil { 1139 if strings.Contains(server, "://") { 1140 return server 1141 } 1142 return addPre(server) 1143 } else { 1144 if ip.Is4() { 1145 return addPre(server) 1146 } else { 1147 return addPre("[" + server + "]") 1148 } 1149 } 1150 } 1151 func parseNameServerPolicy(nsPolicy *orderedmap.OrderedMap[string, any], ruleProviders map[string]providerTypes.RuleProvider, preferH3 bool) (*orderedmap.OrderedMap[string, []dns.NameServer], error) { 1152 policy := orderedmap.New[string, []dns.NameServer]() 1153 updatedPolicy := orderedmap.New[string, any]() 1154 re := regexp.MustCompile(`[a-zA-Z0-9\-]+\.[a-zA-Z]{2,}(\.[a-zA-Z]{2,})?`) 1155 1156 for pair := nsPolicy.Oldest(); pair != nil; pair = pair.Next() { 1157 k, v := pair.Key, pair.Value 1158 if strings.Contains(strings.ToLower(k), ",") { 1159 if strings.Contains(k, "geosite:") { 1160 subkeys := strings.Split(k, ":") 1161 subkeys = subkeys[1:] 1162 subkeys = strings.Split(subkeys[0], ",") 1163 for _, subkey := range subkeys { 1164 newKey := "geosite:" + subkey 1165 updatedPolicy.Store(newKey, v) 1166 } 1167 } else if strings.Contains(strings.ToLower(k), "rule-set:") { 1168 subkeys := strings.Split(k, ":") 1169 subkeys = subkeys[1:] 1170 subkeys = strings.Split(subkeys[0], ",") 1171 for _, subkey := range subkeys { 1172 newKey := "rule-set:" + subkey 1173 updatedPolicy.Store(newKey, v) 1174 } 1175 } else if re.MatchString(k) { 1176 subkeys := strings.Split(k, ",") 1177 for _, subkey := range subkeys { 1178 updatedPolicy.Store(subkey, v) 1179 } 1180 } 1181 } else { 1182 if strings.Contains(strings.ToLower(k), "geosite:") { 1183 updatedPolicy.Store("geosite:"+k[8:], v) 1184 } else if strings.Contains(strings.ToLower(k), "rule-set:") { 1185 updatedPolicy.Store("rule-set:"+k[9:], v) 1186 } 1187 updatedPolicy.Store(k, v) 1188 } 1189 } 1190 1191 for pair := updatedPolicy.Oldest(); pair != nil; pair = pair.Next() { 1192 domain, server := pair.Key, pair.Value 1193 servers, err := utils.ToStringSlice(server) 1194 if err != nil { 1195 return nil, err 1196 } 1197 nameservers, err := parseNameServer(servers, preferH3) 1198 if err != nil { 1199 return nil, err 1200 } 1201 if _, valid := trie.ValidAndSplitDomain(domain); !valid { 1202 return nil, fmt.Errorf("DNS ResoverRule invalid domain: %s", domain) 1203 } 1204 if strings.HasPrefix(domain, "rule-set:") { 1205 domainSetName := domain[9:] 1206 if provider, ok := ruleProviders[domainSetName]; !ok { 1207 return nil, fmt.Errorf("not found rule-set: %s", domainSetName) 1208 } else { 1209 switch provider.Behavior() { 1210 case providerTypes.IPCIDR: 1211 return nil, fmt.Errorf("rule provider type error, except domain,actual %s", provider.Behavior()) 1212 case providerTypes.Classical: 1213 log.Warnln("%s provider is %s, only matching it contain domain rule", provider.Name(), provider.Behavior()) 1214 } 1215 } 1216 } 1217 policy.Store(domain, nameservers) 1218 } 1219 1220 return policy, nil 1221 } 1222 1223 func parseFallbackIPCIDR(ips []string) ([]netip.Prefix, error) { 1224 var ipNets []netip.Prefix 1225 1226 for idx, ip := range ips { 1227 ipnet, err := netip.ParsePrefix(ip) 1228 if err != nil { 1229 return nil, fmt.Errorf("DNS FallbackIP[%d] format error: %s", idx, err.Error()) 1230 } 1231 ipNets = append(ipNets, ipnet) 1232 } 1233 1234 return ipNets, nil 1235 } 1236 1237 func parseFallbackGeoSite(countries []string, rules []C.Rule) ([]router.DomainMatcher, error) { 1238 var sites []router.DomainMatcher 1239 if len(countries) > 0 { 1240 if err := geodata.InitGeoSite(); err != nil { 1241 return nil, fmt.Errorf("can't initial GeoSite: %s", err) 1242 } 1243 log.Warnln("replace fallback-filter.geosite with nameserver-policy, it will be removed in the future") 1244 } 1245 1246 for _, country := range countries { 1247 found := false 1248 for _, rule := range rules { 1249 if rule.RuleType() == C.GEOSITE { 1250 if strings.EqualFold(country, rule.Payload()) { 1251 found = true 1252 sites = append(sites, rule.(C.RuleGeoSite).GetDomainMatcher()) 1253 log.Infoln("Start initial GeoSite dns fallback filter from rule `%s`", country) 1254 } 1255 } 1256 } 1257 1258 if !found { 1259 matcher, recordsCount, err := geodata.LoadGeoSiteMatcher(country) 1260 if err != nil { 1261 return nil, err 1262 } 1263 1264 sites = append(sites, matcher) 1265 1266 log.Infoln("Start initial GeoSite dns fallback filter `%s`, records: %d", country, recordsCount) 1267 } 1268 } 1269 return sites, nil 1270 } 1271 1272 func paresNTP(rawCfg *RawConfig) *NTP { 1273 cfg := rawCfg.NTP 1274 ntpCfg := &NTP{ 1275 Enable: cfg.Enable, 1276 Server: cfg.Server, 1277 Port: cfg.ServerPort, 1278 Interval: cfg.Interval, 1279 DialerProxy: cfg.DialerProxy, 1280 WriteToSystem: cfg.WriteToSystem, 1281 } 1282 return ntpCfg 1283 } 1284 1285 func parseDNS(rawCfg *RawConfig, hosts *trie.DomainTrie[resolver.HostValue], rules []C.Rule, ruleProviders map[string]providerTypes.RuleProvider) (*DNS, error) { 1286 cfg := rawCfg.DNS 1287 if cfg.Enable && len(cfg.NameServer) == 0 { 1288 return nil, fmt.Errorf("if DNS configuration is turned on, NameServer cannot be empty") 1289 } 1290 1291 dnsCfg := &DNS{ 1292 Enable: cfg.Enable, 1293 Listen: cfg.Listen, 1294 PreferH3: cfg.PreferH3, 1295 IPv6Timeout: cfg.IPv6Timeout, 1296 IPv6: cfg.IPv6, 1297 UseSystemHosts: cfg.UseSystemHosts, 1298 EnhancedMode: cfg.EnhancedMode, 1299 FallbackFilter: FallbackFilter{ 1300 IPCIDR: []netip.Prefix{}, 1301 GeoSite: []router.DomainMatcher{}, 1302 }, 1303 } 1304 var err error 1305 if dnsCfg.NameServer, err = parseNameServer(cfg.NameServer, cfg.PreferH3); err != nil { 1306 return nil, err 1307 } 1308 1309 if dnsCfg.Fallback, err = parseNameServer(cfg.Fallback, cfg.PreferH3); err != nil { 1310 return nil, err 1311 } 1312 1313 if dnsCfg.NameServerPolicy, err = parseNameServerPolicy(cfg.NameServerPolicy, ruleProviders, cfg.PreferH3); err != nil { 1314 return nil, err 1315 } 1316 1317 if dnsCfg.ProxyServerNameserver, err = parseNameServer(cfg.ProxyServerNameserver, cfg.PreferH3); err != nil { 1318 return nil, err 1319 } 1320 1321 if len(cfg.DefaultNameserver) == 0 { 1322 return nil, errors.New("default nameserver should have at least one nameserver") 1323 } 1324 if dnsCfg.DefaultNameserver, err = parseNameServer(cfg.DefaultNameserver, cfg.PreferH3); err != nil { 1325 return nil, err 1326 } 1327 // check default nameserver is pure ip addr 1328 for _, ns := range dnsCfg.DefaultNameserver { 1329 if ns.Net == "system" { 1330 continue 1331 } 1332 host, _, err := net.SplitHostPort(ns.Addr) 1333 if err != nil || net.ParseIP(host) == nil { 1334 u, err := url.Parse(ns.Addr) 1335 if err == nil && net.ParseIP(u.Host) == nil { 1336 if ip, _, err := net.SplitHostPort(u.Host); err != nil || net.ParseIP(ip) == nil { 1337 return nil, errors.New("default nameserver should be pure IP") 1338 } 1339 } 1340 } 1341 } 1342 1343 fakeIPRange, err := netip.ParsePrefix(cfg.FakeIPRange) 1344 T.SetFakeIPRange(fakeIPRange) 1345 if cfg.EnhancedMode == C.DNSFakeIP { 1346 if err != nil { 1347 return nil, err 1348 } 1349 1350 var host *trie.DomainTrie[struct{}] 1351 // fake ip skip host filter 1352 if len(cfg.FakeIPFilter) != 0 { 1353 host = trie.New[struct{}]() 1354 for _, domain := range cfg.FakeIPFilter { 1355 _ = host.Insert(domain, struct{}{}) 1356 } 1357 host.Optimize() 1358 } 1359 1360 if len(dnsCfg.Fallback) != 0 { 1361 if host == nil { 1362 host = trie.New[struct{}]() 1363 } 1364 for _, fb := range dnsCfg.Fallback { 1365 if net.ParseIP(fb.Addr) != nil { 1366 continue 1367 } 1368 _ = host.Insert(fb.Addr, struct{}{}) 1369 } 1370 host.Optimize() 1371 } 1372 1373 pool, err := fakeip.New(fakeip.Options{ 1374 IPNet: fakeIPRange, 1375 Size: 1000, 1376 Host: host, 1377 Persistence: rawCfg.Profile.StoreFakeIP, 1378 }) 1379 if err != nil { 1380 return nil, err 1381 } 1382 1383 dnsCfg.FakeIPRange = pool 1384 } 1385 1386 if len(cfg.Fallback) != 0 { 1387 dnsCfg.FallbackFilter.GeoIP = cfg.FallbackFilter.GeoIP 1388 dnsCfg.FallbackFilter.GeoIPCode = cfg.FallbackFilter.GeoIPCode 1389 if fallbackip, err := parseFallbackIPCIDR(cfg.FallbackFilter.IPCIDR); err == nil { 1390 dnsCfg.FallbackFilter.IPCIDR = fallbackip 1391 } 1392 dnsCfg.FallbackFilter.Domain = cfg.FallbackFilter.Domain 1393 fallbackGeoSite, err := parseFallbackGeoSite(cfg.FallbackFilter.GeoSite, rules) 1394 if err != nil { 1395 return nil, fmt.Errorf("load GeoSite dns fallback filter error, %w", err) 1396 } 1397 dnsCfg.FallbackFilter.GeoSite = fallbackGeoSite 1398 } 1399 1400 if cfg.UseHosts { 1401 dnsCfg.Hosts = hosts 1402 } 1403 1404 if cfg.CacheAlgorithm == "" || cfg.CacheAlgorithm == "lru" { 1405 dnsCfg.CacheAlgorithm = "lru" 1406 } else { 1407 dnsCfg.CacheAlgorithm = "arc" 1408 } 1409 1410 return dnsCfg, nil 1411 } 1412 1413 func parseAuthentication(rawRecords []string) []auth.AuthUser { 1414 var users []auth.AuthUser 1415 for _, line := range rawRecords { 1416 if user, pass, found := strings.Cut(line, ":"); found { 1417 users = append(users, auth.AuthUser{User: user, Pass: pass}) 1418 } 1419 } 1420 return users 1421 } 1422 1423 func parseTun(rawTun RawTun, general *General) error { 1424 tunAddressPrefix := T.FakeIPRange() 1425 if !tunAddressPrefix.IsValid() { 1426 tunAddressPrefix = netip.MustParsePrefix("198.18.0.1/16") 1427 } 1428 tunAddressPrefix = netip.PrefixFrom(tunAddressPrefix.Addr(), 30) 1429 1430 if !general.IPv6 || !verifyIP6() { 1431 rawTun.Inet6Address = nil 1432 } 1433 1434 general.Tun = LC.Tun{ 1435 Enable: rawTun.Enable, 1436 Device: rawTun.Device, 1437 Stack: rawTun.Stack, 1438 DNSHijack: rawTun.DNSHijack, 1439 AutoRoute: rawTun.AutoRoute, 1440 AutoDetectInterface: rawTun.AutoDetectInterface, 1441 RedirectToTun: rawTun.RedirectToTun, 1442 1443 MTU: rawTun.MTU, 1444 GSO: rawTun.GSO, 1445 GSOMaxSize: rawTun.GSOMaxSize, 1446 Inet4Address: []netip.Prefix{tunAddressPrefix}, 1447 Inet6Address: rawTun.Inet6Address, 1448 StrictRoute: rawTun.StrictRoute, 1449 Inet4RouteAddress: rawTun.Inet4RouteAddress, 1450 Inet6RouteAddress: rawTun.Inet6RouteAddress, 1451 Inet4RouteExcludeAddress: rawTun.Inet4RouteExcludeAddress, 1452 Inet6RouteExcludeAddress: rawTun.Inet6RouteExcludeAddress, 1453 IncludeInterface: rawTun.IncludeInterface, 1454 ExcludeInterface: rawTun.ExcludeInterface, 1455 IncludeUID: rawTun.IncludeUID, 1456 IncludeUIDRange: rawTun.IncludeUIDRange, 1457 ExcludeUID: rawTun.ExcludeUID, 1458 ExcludeUIDRange: rawTun.ExcludeUIDRange, 1459 IncludeAndroidUser: rawTun.IncludeAndroidUser, 1460 IncludePackage: rawTun.IncludePackage, 1461 ExcludePackage: rawTun.ExcludePackage, 1462 EndpointIndependentNat: rawTun.EndpointIndependentNat, 1463 UDPTimeout: rawTun.UDPTimeout, 1464 FileDescriptor: rawTun.FileDescriptor, 1465 TableIndex: rawTun.TableIndex, 1466 } 1467 1468 return nil 1469 } 1470 1471 func parseTuicServer(rawTuic RawTuicServer, general *General) error { 1472 general.TuicServer = LC.TuicServer{ 1473 Enable: rawTuic.Enable, 1474 Listen: rawTuic.Listen, 1475 Token: rawTuic.Token, 1476 Users: rawTuic.Users, 1477 Certificate: rawTuic.Certificate, 1478 PrivateKey: rawTuic.PrivateKey, 1479 CongestionController: rawTuic.CongestionController, 1480 MaxIdleTime: rawTuic.MaxIdleTime, 1481 AuthenticationTimeout: rawTuic.AuthenticationTimeout, 1482 ALPN: rawTuic.ALPN, 1483 MaxUdpRelayPacketSize: rawTuic.MaxUdpRelayPacketSize, 1484 CWND: rawTuic.CWND, 1485 } 1486 return nil 1487 } 1488 1489 func parseSniffer(snifferRaw RawSniffer) (*Sniffer, error) { 1490 sniffer := &Sniffer{ 1491 Enable: snifferRaw.Enable, 1492 ForceDnsMapping: snifferRaw.ForceDnsMapping, 1493 ParsePureIp: snifferRaw.ParsePureIp, 1494 } 1495 loadSniffer := make(map[snifferTypes.Type]SNIFF.SnifferConfig) 1496 1497 if len(snifferRaw.Sniff) != 0 { 1498 for sniffType, sniffConfig := range snifferRaw.Sniff { 1499 find := false 1500 ports, err := utils.NewUnsignedRangesFromList[uint16](sniffConfig.Ports) 1501 if err != nil { 1502 return nil, err 1503 } 1504 overrideDest := snifferRaw.OverrideDest 1505 if sniffConfig.OverrideDest != nil { 1506 overrideDest = *sniffConfig.OverrideDest 1507 } 1508 for _, snifferType := range snifferTypes.List { 1509 if snifferType.String() == strings.ToUpper(sniffType) { 1510 find = true 1511 loadSniffer[snifferType] = SNIFF.SnifferConfig{ 1512 Ports: ports, 1513 OverrideDest: overrideDest, 1514 } 1515 } 1516 } 1517 1518 if !find { 1519 return nil, fmt.Errorf("not find the sniffer[%s]", sniffType) 1520 } 1521 } 1522 } else { 1523 if sniffer.Enable { 1524 // Deprecated: Use Sniff instead 1525 log.Warnln("Deprecated: Use Sniff instead") 1526 } 1527 globalPorts, err := utils.NewUnsignedRangesFromList[uint16](snifferRaw.Ports) 1528 if err != nil { 1529 return nil, err 1530 } 1531 1532 for _, snifferName := range snifferRaw.Sniffing { 1533 find := false 1534 for _, snifferType := range snifferTypes.List { 1535 if snifferType.String() == strings.ToUpper(snifferName) { 1536 find = true 1537 loadSniffer[snifferType] = SNIFF.SnifferConfig{ 1538 Ports: globalPorts, 1539 OverrideDest: snifferRaw.OverrideDest, 1540 } 1541 } 1542 } 1543 1544 if !find { 1545 return nil, fmt.Errorf("not find the sniffer[%s]", snifferName) 1546 } 1547 } 1548 } 1549 1550 sniffer.Sniffers = loadSniffer 1551 1552 forceDomainTrie := trie.New[struct{}]() 1553 for _, domain := range snifferRaw.ForceDomain { 1554 err := forceDomainTrie.Insert(domain, struct{}{}) 1555 if err != nil { 1556 return nil, fmt.Errorf("error domian[%s] in force-domain, error:%v", domain, err) 1557 } 1558 } 1559 sniffer.ForceDomain = forceDomainTrie.NewDomainSet() 1560 1561 skipDomainTrie := trie.New[struct{}]() 1562 for _, domain := range snifferRaw.SkipDomain { 1563 err := skipDomainTrie.Insert(domain, struct{}{}) 1564 if err != nil { 1565 return nil, fmt.Errorf("error domian[%s] in force-domain, error:%v", domain, err) 1566 } 1567 } 1568 sniffer.SkipDomain = skipDomainTrie.NewDomainSet() 1569 1570 return sniffer, nil 1571 }