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