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  }