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  }