github.com/kelleygo/clashcore@v1.0.2/tunnel/tunnel.go (about)

     1  package tunnel
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"fmt"
     7  	"net"
     8  	"net/netip"
     9  	"path/filepath"
    10  	"runtime"
    11  	"sync"
    12  	"time"
    13  
    14  	N "github.com/kelleygo/clashcore/common/net"
    15  	"github.com/kelleygo/clashcore/component/loopback"
    16  	"github.com/kelleygo/clashcore/component/nat"
    17  	P "github.com/kelleygo/clashcore/component/process"
    18  	"github.com/kelleygo/clashcore/component/resolver"
    19  	"github.com/kelleygo/clashcore/component/slowdown"
    20  	"github.com/kelleygo/clashcore/component/sniffer"
    21  	C "github.com/kelleygo/clashcore/constant"
    22  	"github.com/kelleygo/clashcore/constant/features"
    23  	"github.com/kelleygo/clashcore/constant/provider"
    24  	icontext "github.com/kelleygo/clashcore/context"
    25  	"github.com/kelleygo/clashcore/log"
    26  	"github.com/kelleygo/clashcore/tunnel/statistic"
    27  )
    28  
    29  var (
    30  	status         = newAtomicStatus(Suspend)
    31  	tcpQueue       = make(chan C.ConnContext, 200)
    32  	udpQueue       = make(chan C.PacketAdapter, 200)
    33  	natTable       = nat.New()
    34  	rules          []C.Rule
    35  	listeners      = make(map[string]C.InboundListener)
    36  	subRules       map[string][]C.Rule
    37  	proxies        = make(map[string]C.Proxy)
    38  	providers      map[string]provider.ProxyProvider
    39  	ruleProviders  map[string]provider.RuleProvider
    40  	sniffingEnable = false
    41  	configMux      sync.RWMutex
    42  
    43  	// Outbound Rule
    44  	mode = Rule
    45  
    46  	// default timeout for UDP session
    47  	udpTimeout = 60 * time.Second
    48  
    49  	findProcessMode P.FindProcessMode
    50  
    51  	fakeIPRange netip.Prefix
    52  )
    53  
    54  type tunnel struct{}
    55  
    56  var Tunnel C.Tunnel = tunnel{}
    57  
    58  func (t tunnel) HandleTCPConn(conn net.Conn, metadata *C.Metadata) {
    59  	connCtx := icontext.NewConnContext(conn, metadata)
    60  	handleTCPConn(connCtx)
    61  }
    62  
    63  func (t tunnel) HandleUDPPacket(packet C.UDPPacket, metadata *C.Metadata) {
    64  	packetAdapter := C.NewPacketAdapter(packet, metadata)
    65  	select {
    66  	case udpQueue <- packetAdapter:
    67  	default:
    68  	}
    69  }
    70  
    71  func (t tunnel) NatTable() C.NatTable {
    72  	return natTable
    73  }
    74  
    75  func OnSuspend() {
    76  	status.Store(Suspend)
    77  }
    78  
    79  func OnInnerLoading() {
    80  	status.Store(Inner)
    81  }
    82  
    83  func OnRunning() {
    84  	status.Store(Running)
    85  }
    86  
    87  func Status() TunnelStatus {
    88  	return status.Load()
    89  }
    90  
    91  func SetFakeIPRange(p netip.Prefix) {
    92  	fakeIPRange = p
    93  }
    94  
    95  func FakeIPRange() netip.Prefix {
    96  	return fakeIPRange
    97  }
    98  
    99  func SetSniffing(b bool) {
   100  	if sniffer.Dispatcher.Enable() {
   101  		configMux.Lock()
   102  		sniffingEnable = b
   103  		configMux.Unlock()
   104  	}
   105  }
   106  
   107  func IsSniffing() bool {
   108  	return sniffingEnable
   109  }
   110  
   111  func init() {
   112  	go process()
   113  }
   114  
   115  // TCPIn return fan-in queue
   116  // Deprecated: using Tunnel instead
   117  func TCPIn() chan<- C.ConnContext {
   118  	return tcpQueue
   119  }
   120  
   121  // UDPIn return fan-in udp queue
   122  // Deprecated: using Tunnel instead
   123  func UDPIn() chan<- C.PacketAdapter {
   124  	return udpQueue
   125  }
   126  
   127  // NatTable return nat table
   128  func NatTable() C.NatTable {
   129  	return natTable
   130  }
   131  
   132  // Rules return all rules
   133  func Rules() []C.Rule {
   134  	return rules
   135  }
   136  
   137  func Listeners() map[string]C.InboundListener {
   138  	return listeners
   139  }
   140  
   141  // UpdateRules handle update rules
   142  func UpdateRules(newRules []C.Rule, newSubRule map[string][]C.Rule, rp map[string]provider.RuleProvider) {
   143  	configMux.Lock()
   144  	rules = newRules
   145  	ruleProviders = rp
   146  	subRules = newSubRule
   147  	configMux.Unlock()
   148  }
   149  
   150  // Proxies return all proxies
   151  func Proxies() map[string]C.Proxy {
   152  	return proxies
   153  }
   154  
   155  func ProxiesWithProviders() map[string]C.Proxy {
   156  	allProxies := make(map[string]C.Proxy)
   157  	for name, proxy := range proxies {
   158  		allProxies[name] = proxy
   159  	}
   160  	for _, p := range providers {
   161  		for _, proxy := range p.Proxies() {
   162  			name := proxy.Name()
   163  			allProxies[name] = proxy
   164  		}
   165  	}
   166  	return allProxies
   167  }
   168  
   169  // Providers return all compatible providers
   170  func Providers() map[string]provider.ProxyProvider {
   171  	return providers
   172  }
   173  
   174  // RuleProviders return all loaded rule providers
   175  func RuleProviders() map[string]provider.RuleProvider {
   176  	return ruleProviders
   177  }
   178  
   179  // UpdateProxies handle update proxies
   180  func UpdateProxies(newProxies map[string]C.Proxy, newProviders map[string]provider.ProxyProvider) {
   181  	configMux.Lock()
   182  	proxies = newProxies
   183  	providers = newProviders
   184  	configMux.Unlock()
   185  }
   186  
   187  func UpdateListeners(newListeners map[string]C.InboundListener) {
   188  	configMux.Lock()
   189  	defer configMux.Unlock()
   190  	listeners = newListeners
   191  }
   192  
   193  func UpdateSniffer(dispatcher *sniffer.SnifferDispatcher) {
   194  	configMux.Lock()
   195  	sniffer.Dispatcher = dispatcher
   196  	sniffingEnable = dispatcher.Enable()
   197  	configMux.Unlock()
   198  }
   199  
   200  // Mode return current mode
   201  func Mode() TunnelMode {
   202  	return mode
   203  }
   204  
   205  // SetMode change the mode of tunnel
   206  func SetMode(m TunnelMode) {
   207  	mode = m
   208  }
   209  
   210  // SetFindProcessMode replace SetAlwaysFindProcess
   211  // always find process info if legacyAlways = true or mode.Always() = true, may be increase many memory
   212  func SetFindProcessMode(mode P.FindProcessMode) {
   213  	findProcessMode = mode
   214  }
   215  
   216  func isHandle(t C.Type) bool {
   217  	status := status.Load()
   218  	return status == Running || (status == Inner && t == C.INNER)
   219  }
   220  
   221  // processUDP starts a loop to handle udp packet
   222  func processUDP() {
   223  	queue := udpQueue
   224  	for conn := range queue {
   225  		handleUDPConn(conn)
   226  	}
   227  }
   228  
   229  func process() {
   230  	numUDPWorkers := 4
   231  	if num := runtime.GOMAXPROCS(0); num > numUDPWorkers {
   232  		numUDPWorkers = num
   233  	}
   234  	for i := 0; i < numUDPWorkers; i++ {
   235  		go processUDP()
   236  	}
   237  
   238  	queue := tcpQueue
   239  	for conn := range queue {
   240  		go handleTCPConn(conn)
   241  	}
   242  }
   243  
   244  func needLookupIP(metadata *C.Metadata) bool {
   245  	return resolver.MappingEnabled() && metadata.Host == "" && metadata.DstIP.IsValid()
   246  }
   247  
   248  func preHandleMetadata(metadata *C.Metadata) error {
   249  	// handle IP string on host
   250  	if ip, err := netip.ParseAddr(metadata.Host); err == nil {
   251  		metadata.DstIP = ip
   252  		metadata.Host = ""
   253  	}
   254  
   255  	// preprocess enhanced-mode metadata
   256  	if needLookupIP(metadata) {
   257  		host, exist := resolver.FindHostByIP(metadata.DstIP)
   258  		if exist {
   259  			metadata.Host = host
   260  			metadata.DNSMode = C.DNSMapping
   261  			if resolver.FakeIPEnabled() {
   262  				metadata.DstIP = netip.Addr{}
   263  				metadata.DNSMode = C.DNSFakeIP
   264  			} else if node, ok := resolver.DefaultHosts.Search(host, false); ok {
   265  				// redir-host should lookup the hosts
   266  				metadata.DstIP, _ = node.RandIP()
   267  			} else if node != nil && node.IsDomain {
   268  				metadata.Host = node.Domain
   269  			}
   270  		} else if resolver.IsFakeIP(metadata.DstIP) {
   271  			return fmt.Errorf("fake DNS record %s missing", metadata.DstIP)
   272  		}
   273  	} else if node, ok := resolver.DefaultHosts.Search(metadata.Host, true); ok {
   274  		// try use domain mapping
   275  		metadata.Host = node.Domain
   276  	}
   277  
   278  	return nil
   279  }
   280  
   281  func resolveMetadata(metadata *C.Metadata) (proxy C.Proxy, rule C.Rule, err error) {
   282  	if metadata.SpecialProxy != "" {
   283  		var exist bool
   284  		proxy, exist = proxies[metadata.SpecialProxy]
   285  		if !exist {
   286  			err = fmt.Errorf("proxy %s not found", metadata.SpecialProxy)
   287  		}
   288  		return
   289  	}
   290  
   291  	switch mode {
   292  	case Direct:
   293  		proxy = proxies["DIRECT"]
   294  	case Global:
   295  		proxy = proxies["GLOBAL"]
   296  	// Rule
   297  	default:
   298  		proxy, rule, err = match(metadata)
   299  	}
   300  	return
   301  }
   302  
   303  func handleUDPConn(packet C.PacketAdapter) {
   304  	if !isHandle(packet.Metadata().Type) {
   305  		packet.Drop()
   306  		return
   307  	}
   308  
   309  	metadata := packet.Metadata()
   310  	if !metadata.Valid() {
   311  		packet.Drop()
   312  		log.Warnln("[Metadata] not valid: %#v", metadata)
   313  		return
   314  	}
   315  
   316  	// make a fAddr if request ip is fakeip
   317  	var fAddr netip.Addr
   318  	if resolver.IsExistFakeIP(metadata.DstIP) {
   319  		fAddr = metadata.DstIP
   320  	}
   321  
   322  	if err := preHandleMetadata(metadata); err != nil {
   323  		packet.Drop()
   324  		log.Debugln("[Metadata PreHandle] error: %s", err)
   325  		return
   326  	}
   327  
   328  	if sniffer.Dispatcher.Enable() && sniffingEnable {
   329  		sniffer.Dispatcher.UDPSniff(packet)
   330  	}
   331  
   332  	// local resolve UDP dns
   333  	if !metadata.Resolved() {
   334  		ip, err := resolver.ResolveIP(context.Background(), metadata.Host)
   335  		if err != nil {
   336  			return
   337  		}
   338  		metadata.DstIP = ip
   339  	}
   340  
   341  	key := packet.LocalAddr().String()
   342  
   343  	handle := func() bool {
   344  		pc, proxy := natTable.Get(key)
   345  		if pc != nil {
   346  			if proxy != nil {
   347  				proxy.UpdateWriteBack(packet)
   348  			}
   349  			_ = handleUDPToRemote(packet, pc, metadata)
   350  			return true
   351  		}
   352  		return false
   353  	}
   354  
   355  	if handle() {
   356  		packet.Drop()
   357  		return
   358  	}
   359  
   360  	cond, loaded := natTable.GetOrCreateLock(key)
   361  
   362  	go func() {
   363  		defer packet.Drop()
   364  
   365  		if loaded {
   366  			cond.L.Lock()
   367  			cond.Wait()
   368  			handle()
   369  			cond.L.Unlock()
   370  			return
   371  		}
   372  
   373  		defer func() {
   374  			natTable.DeleteLock(key)
   375  			cond.Broadcast()
   376  		}()
   377  
   378  		proxy, rule, err := resolveMetadata(metadata)
   379  		if err != nil {
   380  			log.Warnln("[UDP] Parse metadata failed: %s", err.Error())
   381  			return
   382  		}
   383  
   384  		ctx, cancel := context.WithTimeout(context.Background(), C.DefaultUDPTimeout)
   385  		defer cancel()
   386  		rawPc, err := retry(ctx, func(ctx context.Context) (C.PacketConn, error) {
   387  			return proxy.ListenPacketContext(ctx, metadata.Pure())
   388  		}, func(err error) {
   389  			if rule == nil {
   390  				log.Warnln(
   391  					"[UDP] dial %s %s --> %s error: %s",
   392  					proxy.Name(),
   393  					metadata.SourceDetail(),
   394  					metadata.RemoteAddress(),
   395  					err.Error(),
   396  				)
   397  			} else {
   398  				log.Warnln("[UDP] dial %s (match %s/%s) %s --> %s error: %s", proxy.Name(), rule.RuleType().String(), rule.Payload(), metadata.SourceDetail(), metadata.RemoteAddress(), err.Error())
   399  			}
   400  		})
   401  		if err != nil {
   402  			return
   403  		}
   404  
   405  		pc := statistic.NewUDPTracker(rawPc, statistic.DefaultManager, metadata, rule, 0, 0, true)
   406  
   407  		switch true {
   408  		case metadata.SpecialProxy != "":
   409  			log.Infoln("[UDP] %s --> %s using %s", metadata.SourceDetail(), metadata.RemoteAddress(), metadata.SpecialProxy)
   410  		case rule != nil:
   411  			if rule.Payload() != "" {
   412  				log.Infoln("[UDP] %s --> %s match %s using %s", metadata.SourceDetail(), metadata.RemoteAddress(), fmt.Sprintf("%s(%s)", rule.RuleType().String(), rule.Payload()), rawPc.Chains().String())
   413  				if rawPc.Chains().Last() == "REJECT-DROP" {
   414  					pc.Close()
   415  					return
   416  				}
   417  			} else {
   418  				log.Infoln("[UDP] %s --> %s match %s using %s", metadata.SourceDetail(), metadata.RemoteAddress(), rule.Payload(), rawPc.Chains().String())
   419  			}
   420  		case mode == Global:
   421  			log.Infoln("[UDP] %s --> %s using GLOBAL", metadata.SourceDetail(), metadata.RemoteAddress())
   422  		case mode == Direct:
   423  			log.Infoln("[UDP] %s --> %s using DIRECT", metadata.SourceDetail(), metadata.RemoteAddress())
   424  		default:
   425  			log.Infoln("[UDP] %s --> %s doesn't match any rule using DIRECT", metadata.SourceDetail(), metadata.RemoteAddress())
   426  		}
   427  
   428  		oAddrPort := metadata.AddrPort()
   429  		writeBackProxy := nat.NewWriteBackProxy(packet)
   430  		natTable.Set(key, pc, writeBackProxy)
   431  
   432  		go handleUDPToLocal(writeBackProxy, pc, key, oAddrPort, fAddr)
   433  
   434  		handle()
   435  	}()
   436  }
   437  
   438  func handleTCPConn(connCtx C.ConnContext) {
   439  	if !isHandle(connCtx.Metadata().Type) {
   440  		_ = connCtx.Conn().Close()
   441  		return
   442  	}
   443  
   444  	defer func(conn net.Conn) {
   445  		_ = conn.Close()
   446  	}(connCtx.Conn())
   447  
   448  	metadata := connCtx.Metadata()
   449  	if !metadata.Valid() {
   450  		log.Warnln("[Metadata] not valid: %#v", metadata)
   451  		return
   452  	}
   453  
   454  	preHandleFailed := false
   455  	if err := preHandleMetadata(metadata); err != nil {
   456  		log.Debugln("[Metadata PreHandle] error: %s", err)
   457  		preHandleFailed = true
   458  	}
   459  
   460  	conn := connCtx.Conn()
   461  	conn.ResetPeeked() // reset before sniffer
   462  	if sniffer.Dispatcher.Enable() && sniffingEnable {
   463  		// Try to sniff a domain when `preHandleMetadata` failed, this is usually
   464  		// caused by a "Fake DNS record missing" error when enhanced-mode is fake-ip.
   465  		if sniffer.Dispatcher.TCPSniff(conn, metadata) {
   466  			// we now have a domain name
   467  			preHandleFailed = false
   468  		}
   469  	}
   470  
   471  	// If both trials have failed, we can do nothing but give up
   472  	if preHandleFailed {
   473  		log.Debugln("[Metadata PreHandle] failed to sniff a domain for connection %s --> %s, give up",
   474  			metadata.SourceDetail(), metadata.RemoteAddress())
   475  		return
   476  	}
   477  
   478  	peekMutex := sync.Mutex{}
   479  	if !conn.Peeked() {
   480  		peekMutex.Lock()
   481  		go func() {
   482  			defer peekMutex.Unlock()
   483  			_ = conn.SetReadDeadline(time.Now().Add(200 * time.Millisecond))
   484  			_, _ = conn.Peek(1)
   485  			_ = conn.SetReadDeadline(time.Time{})
   486  		}()
   487  	}
   488  
   489  	proxy, rule, err := resolveMetadata(metadata)
   490  	if err != nil {
   491  		log.Warnln("[Metadata] parse failed: %s", err.Error())
   492  		return
   493  	}
   494  
   495  	dialMetadata := metadata
   496  	if len(metadata.Host) > 0 {
   497  		if node, ok := resolver.DefaultHosts.Search(metadata.Host, false); ok {
   498  			if dstIp, _ := node.RandIP(); !FakeIPRange().Contains(dstIp) {
   499  				dialMetadata.DstIP = dstIp
   500  				dialMetadata.DNSMode = C.DNSHosts
   501  				dialMetadata = dialMetadata.Pure()
   502  			}
   503  		}
   504  	}
   505  
   506  	var peekBytes []byte
   507  	var peekLen int
   508  
   509  	ctx, cancel := context.WithTimeout(context.Background(), C.DefaultTCPTimeout)
   510  	defer cancel()
   511  	remoteConn, err := retry(ctx, func(ctx context.Context) (remoteConn C.Conn, err error) {
   512  		remoteConn, err = proxy.DialContext(ctx, dialMetadata)
   513  		if err != nil {
   514  			return
   515  		}
   516  
   517  		if N.NeedHandshake(remoteConn) {
   518  			defer func() {
   519  				for _, chain := range remoteConn.Chains() {
   520  					if chain == "REJECT" {
   521  						err = nil
   522  						return
   523  					}
   524  				}
   525  				if err != nil {
   526  					remoteConn = nil
   527  				}
   528  			}()
   529  			peekMutex.Lock()
   530  			defer peekMutex.Unlock()
   531  			peekBytes, _ = conn.Peek(conn.Buffered())
   532  			_, err = remoteConn.Write(peekBytes)
   533  			if err != nil {
   534  				return
   535  			}
   536  			if peekLen = len(peekBytes); peekLen > 0 {
   537  				_, _ = conn.Discard(peekLen)
   538  			}
   539  		}
   540  		return
   541  	}, func(err error) {
   542  		if rule == nil {
   543  			log.Warnln(
   544  				"[TCP] dial %s %s --> %s error: %s",
   545  				proxy.Name(),
   546  				metadata.SourceDetail(),
   547  				metadata.RemoteAddress(),
   548  				err.Error(),
   549  			)
   550  		} else {
   551  			log.Warnln("[TCP] dial %s (match %s/%s) %s --> %s error: %s", proxy.Name(), rule.RuleType().String(), rule.Payload(), metadata.SourceDetail(), metadata.RemoteAddress(), err.Error())
   552  		}
   553  	})
   554  	if err != nil {
   555  		return
   556  	}
   557  
   558  	remoteConn = statistic.NewTCPTracker(remoteConn, statistic.DefaultManager, metadata, rule, 0, int64(peekLen), true)
   559  	defer func(remoteConn C.Conn) {
   560  		_ = remoteConn.Close()
   561  	}(remoteConn)
   562  
   563  	switch true {
   564  	case metadata.SpecialProxy != "":
   565  		log.Infoln("[TCP] %s --> %s using %s", metadata.SourceDetail(), metadata.RemoteAddress(), metadata.SpecialProxy)
   566  	case rule != nil:
   567  		if rule.Payload() != "" {
   568  			log.Infoln("[TCP] %s --> %s match %s using %s", metadata.SourceDetail(), metadata.RemoteAddress(), fmt.Sprintf("%s(%s)", rule.RuleType().String(), rule.Payload()), remoteConn.Chains().String())
   569  		} else {
   570  			log.Infoln("[TCP] %s --> %s match %s using %s", metadata.SourceDetail(), metadata.RemoteAddress(), rule.RuleType().String(), remoteConn.Chains().String())
   571  		}
   572  	case mode == Global:
   573  		log.Infoln("[TCP] %s --> %s using GLOBAL", metadata.SourceDetail(), metadata.RemoteAddress())
   574  	case mode == Direct:
   575  		log.Infoln("[TCP] %s --> %s using DIRECT", metadata.SourceDetail(), metadata.RemoteAddress())
   576  	default:
   577  		log.Infoln(
   578  			"[TCP] %s --> %s doesn't match any rule using DIRECT",
   579  			metadata.SourceDetail(),
   580  			metadata.RemoteAddress(),
   581  		)
   582  	}
   583  
   584  	_ = conn.SetReadDeadline(time.Now()) // stop unfinished peek
   585  	peekMutex.Lock()
   586  	defer peekMutex.Unlock()
   587  	_ = conn.SetReadDeadline(time.Time{}) // reset
   588  	handleSocket(conn, remoteConn)
   589  }
   590  
   591  func shouldResolveIP(rule C.Rule, metadata *C.Metadata) bool {
   592  	return rule.ShouldResolveIP() && metadata.Host != "" && !metadata.DstIP.IsValid()
   593  }
   594  
   595  func match(metadata *C.Metadata) (C.Proxy, C.Rule, error) {
   596  	configMux.RLock()
   597  	defer configMux.RUnlock()
   598  	var (
   599  		resolved             bool
   600  		attemptProcessLookup = metadata.Type != C.INNER
   601  	)
   602  
   603  	if node, ok := resolver.DefaultHosts.Search(metadata.Host, false); ok {
   604  		metadata.DstIP, _ = node.RandIP()
   605  		resolved = true
   606  	}
   607  
   608  	for _, rule := range getRules(metadata) {
   609  		if !resolved && shouldResolveIP(rule, metadata) {
   610  			func() {
   611  				ctx, cancel := context.WithTimeout(context.Background(), resolver.DefaultDNSTimeout)
   612  				defer cancel()
   613  				ip, err := resolver.ResolveIP(ctx, metadata.Host)
   614  				if err != nil {
   615  					log.Debugln("[DNS] resolve %s error: %s", metadata.Host, err.Error())
   616  				} else {
   617  					log.Debugln("[DNS] %s --> %s", metadata.Host, ip.String())
   618  					metadata.DstIP = ip
   619  				}
   620  				resolved = true
   621  			}()
   622  		}
   623  
   624  		if attemptProcessLookup && !findProcessMode.Off() && (findProcessMode.Always() || rule.ShouldFindProcess()) {
   625  			attemptProcessLookup = false
   626  			if !features.CMFA {
   627  				// normal check for process
   628  				uid, path, err := P.FindProcessName(metadata.NetWork.String(), metadata.SrcIP, int(metadata.SrcPort))
   629  				if err != nil {
   630  					log.Debugln("[Process] find process %s error: %v", metadata.String(), err)
   631  				} else {
   632  					metadata.Process = filepath.Base(path)
   633  					metadata.ProcessPath = path
   634  					metadata.Uid = uid
   635  				}
   636  			} else {
   637  				// check package names
   638  				pkg, err := P.FindPackageName(metadata)
   639  				if err != nil {
   640  					log.Debugln("[Process] find process %s error: %v", metadata.String(), err)
   641  				} else {
   642  					metadata.Process = pkg
   643  				}
   644  			}
   645  		}
   646  
   647  		if matched, ada := rule.Match(metadata); matched {
   648  			adapter, ok := proxies[ada]
   649  			if !ok {
   650  				continue
   651  			}
   652  
   653  			// parse multi-layer nesting
   654  			passed := false
   655  			for adapter := adapter; adapter != nil; adapter = adapter.Unwrap(metadata, false) {
   656  				if adapter.Type() == C.Pass {
   657  					passed = true
   658  					break
   659  				}
   660  			}
   661  			if passed {
   662  				log.Debugln("%s match Pass rule", adapter.Name())
   663  				continue
   664  			}
   665  
   666  			if metadata.NetWork == C.UDP && !adapter.SupportUDP() {
   667  				log.Debugln("%s UDP is not supported", adapter.Name())
   668  				continue
   669  			}
   670  
   671  			return adapter, rule, nil
   672  		}
   673  	}
   674  
   675  	return proxies["DIRECT"], nil, nil
   676  }
   677  
   678  func getRules(metadata *C.Metadata) []C.Rule {
   679  	if sr, ok := subRules[metadata.SpecialRules]; ok {
   680  		log.Debugln("[Rule] use %s rules", metadata.SpecialRules)
   681  		return sr
   682  	} else {
   683  		log.Debugln("[Rule] use default rules")
   684  		return rules
   685  	}
   686  }
   687  
   688  func shouldStopRetry(err error) bool {
   689  	if errors.Is(err, resolver.ErrIPNotFound) {
   690  		return true
   691  	}
   692  	if errors.Is(err, resolver.ErrIPVersion) {
   693  		return true
   694  	}
   695  	if errors.Is(err, resolver.ErrIPv6Disabled) {
   696  		return true
   697  	}
   698  	if errors.Is(err, loopback.ErrReject) {
   699  		return true
   700  	}
   701  	return false
   702  }
   703  
   704  func retry[T any](ctx context.Context, ft func(context.Context) (T, error), fe func(err error)) (t T, err error) {
   705  	s := slowdown.New()
   706  	for i := 0; i < 10; i++ {
   707  		t, err = ft(ctx)
   708  		if err != nil {
   709  			if fe != nil {
   710  				fe(err)
   711  			}
   712  			if shouldStopRetry(err) {
   713  				return
   714  			}
   715  			if s.Wait(ctx) == nil {
   716  				continue
   717  			} else {
   718  				return
   719  			}
   720  		} else {
   721  			break
   722  		}
   723  	}
   724  	return
   725  }