github.com/yaling888/clash@v1.53.0/listener/listener.go (about)

     1  package listener
     2  
     3  import (
     4  	"fmt"
     5  	"net"
     6  	"reflect"
     7  	"strconv"
     8  	"strings"
     9  	"sync"
    10  
    11  	"github.com/phuslu/log"
    12  	"github.com/samber/lo"
    13  
    14  	"github.com/yaling888/clash/adapter/inbound"
    15  	"github.com/yaling888/clash/component/dialer"
    16  	"github.com/yaling888/clash/component/ebpf"
    17  	"github.com/yaling888/clash/component/iface"
    18  	"github.com/yaling888/clash/config"
    19  	C "github.com/yaling888/clash/constant"
    20  	A "github.com/yaling888/clash/listener/auth"
    21  	"github.com/yaling888/clash/listener/autoredir"
    22  	"github.com/yaling888/clash/listener/http"
    23  	"github.com/yaling888/clash/listener/mitm"
    24  	"github.com/yaling888/clash/listener/mixed"
    25  	"github.com/yaling888/clash/listener/redir"
    26  	"github.com/yaling888/clash/listener/socks"
    27  	"github.com/yaling888/clash/listener/tproxy"
    28  	"github.com/yaling888/clash/listener/tun"
    29  	"github.com/yaling888/clash/listener/tun/ipstack"
    30  	"github.com/yaling888/clash/listener/tun/ipstack/commons"
    31  	"github.com/yaling888/clash/listener/tunnel"
    32  	"github.com/yaling888/clash/tunnel/statistic"
    33  )
    34  
    35  var (
    36  	allowLan    = false
    37  	bindAddress = "*"
    38  
    39  	tcpInbounds  = map[string]C.Inbound{}
    40  	udpInbounds  = map[string]C.Inbound{}
    41  	tcpListeners = map[string]C.Listener{}
    42  	udpListeners = map[string]C.Listener{}
    43  
    44  	tunStackListener  ipstack.Stack
    45  	tcProgram         *ebpf.TcEBpfProgram
    46  	autoRedirListener *autoredir.Listener
    47  	autoRedirProgram  *ebpf.TcEBpfProgram
    48  
    49  	tunnelTCPListeners = map[string]*tunnel.Listener{}
    50  	tunnelUDPListeners = map[string]*tunnel.PacketConn{}
    51  
    52  	// lock for recreate function
    53  	inboundsMux  sync.Mutex
    54  	tunMux       sync.Mutex
    55  	tcMux        sync.Mutex
    56  	autoRedirMux sync.Mutex
    57  	tunnelMux    sync.Mutex
    58  )
    59  
    60  var tcpListenerCreators = map[C.InboundType]tcpListenerCreator{
    61  	C.InboundTypeHTTP:   http.New,
    62  	C.InboundTypeSocks:  socks.New,
    63  	C.InboundTypeSocks4: socks.New4,
    64  	C.InboundTypeSocks5: socks.New5,
    65  	C.InboundTypeRedir:  redir.New,
    66  	C.InboundTypeTproxy: tproxy.New,
    67  	C.InboundTypeMixed:  mixed.New,
    68  	C.InboundTypeMitm:   mitm.New,
    69  }
    70  
    71  var udpListenerCreators = map[C.InboundType]udpListenerCreator{
    72  	C.InboundTypeSocks:  socks.NewUDP,
    73  	C.InboundTypeSocks5: socks.NewUDP,
    74  	C.InboundTypeRedir:  tproxy.NewUDP,
    75  	C.InboundTypeTproxy: tproxy.NewUDP,
    76  	C.InboundTypeMixed:  socks.NewUDP,
    77  }
    78  
    79  type (
    80  	tcpListenerCreator func(addr string, tcpIn chan<- C.ConnContext) (C.Listener, error)
    81  	udpListenerCreator func(addr string, udpIn chan<- *inbound.PacketAdapter) (C.Listener, error)
    82  )
    83  
    84  type Ports struct {
    85  	Port       int `json:"port"`
    86  	SocksPort  int `json:"socks-port"`
    87  	RedirPort  int `json:"redir-port"`
    88  	TProxyPort int `json:"tproxy-port"`
    89  	MixedPort  int `json:"mixed-port"`
    90  	MitmPort   int `json:"mitm-port"`
    91  }
    92  
    93  func AllowLan() bool {
    94  	return allowLan
    95  }
    96  
    97  func BindAddress() string {
    98  	return bindAddress
    99  }
   100  
   101  func SetAllowLan(al bool) {
   102  	allowLan = al
   103  }
   104  
   105  func SetBindAddress(host string) {
   106  	bindAddress = host
   107  }
   108  
   109  func createListener(inbound C.Inbound, tcpIn chan<- C.ConnContext, udpIn chan<- *inbound.PacketAdapter) {
   110  	addr := inbound.BindAddress
   111  	if portIsZero(addr) {
   112  		log.Error().Str("addr", addr).Msgf("[Inbound] invalid %s address", inbound.Type)
   113  		return
   114  	}
   115  
   116  	inboundKey := inbound.Key()
   117  	tcpCreator := tcpListenerCreators[inbound.Type]
   118  	udpCreator := udpListenerCreators[inbound.Type]
   119  
   120  	if tcpCreator == nil && udpCreator == nil {
   121  		log.Error().Str("addr", addr).Msgf("[Inbound] server type %s is not supported", inbound.Type)
   122  		return
   123  	}
   124  
   125  	au := "none"
   126  	auLen := len(lo.FromPtr(inbound.Authentication))
   127  	if auLen != 0 {
   128  		au = "local"
   129  	} else if A.Authenticator() != nil {
   130  		au = "global"
   131  	}
   132  	if inbound.Type == C.InboundTypeRedir || inbound.Type == C.InboundTypeTproxy {
   133  		au = "none"
   134  	}
   135  
   136  	if tcpCreator != nil {
   137  		tcpListener, err := tcpCreator(addr, tcpIn)
   138  		if err != nil {
   139  			log.Error().Err(err).Str("addr", addr).Msgf("[Inbound] %s tcp server start failed", inbound.Type)
   140  			return
   141  		}
   142  
   143  		if !inbound.IsFromPortCfg && auLen != 0 {
   144  			if tl, ok := tcpListener.(C.AuthenticatorListener); ok {
   145  				authUsers := config.ParseAuthentication(*inbound.Authentication)
   146  				tl.SetAuthenticator(authUsers)
   147  			}
   148  		}
   149  
   150  		tcpInbounds[inboundKey] = inbound
   151  		tcpListeners[inboundKey] = tcpListener
   152  
   153  		log.Info().
   154  			Str("addr", addr).
   155  			Str("network", "tcp").
   156  			Str("auth", au).
   157  			Msgf("[Inbound] %s proxy listening", inbound.Type)
   158  	}
   159  
   160  	if udpCreator != nil {
   161  		udpListener, err := udpCreator(addr, udpIn)
   162  		if err != nil {
   163  			log.Error().Err(err).Str("addr", addr).Msgf("[Inbound] %s udp server start failed", inbound.Type)
   164  			return
   165  		}
   166  
   167  		udpInbounds[inboundKey] = inbound
   168  		udpListeners[inboundKey] = udpListener
   169  
   170  		log.Info().
   171  			Str("addr", addr).
   172  			Str("network", "udp").
   173  			Str("auth", au).
   174  			Msgf("[Inbound] %s proxy listening", inbound.Type)
   175  	}
   176  }
   177  
   178  func closeListener(inbound C.Inbound) {
   179  	inboundKey := inbound.Key()
   180  	listener := tcpListeners[inboundKey]
   181  	if listener != nil {
   182  		if err := listener.Close(); err != nil {
   183  			log.Error().Err(err).Msgf("[Inbound] close tcp server `%s` failed", inbound.ToAlias())
   184  		}
   185  		delete(tcpInbounds, inboundKey)
   186  		delete(tcpListeners, inboundKey)
   187  		log.Info().
   188  			Str("addr", inbound.BindAddress).
   189  			Str("network", "tcp").
   190  			Msgf("[Inbound] %s proxy is down", inbound.Type)
   191  	}
   192  	listener = udpListeners[inboundKey]
   193  	if listener != nil {
   194  		if err := listener.Close(); err != nil {
   195  			log.Error().Err(err).Msgf("[Inbound] close udp server `%s` failed", inbound.ToAlias())
   196  		}
   197  		delete(udpInbounds, inboundKey)
   198  		delete(udpListeners, inboundKey)
   199  		log.Info().
   200  			Str("addr", inbound.BindAddress).
   201  			Str("network", "udp").
   202  			Msgf("[Inbound] %s proxy is down", inbound.Type)
   203  	}
   204  }
   205  
   206  func getNeedCloseAndCreateInbound(originInbounds []C.Inbound, newInbounds []C.Inbound) ([]C.Inbound, []C.Inbound) {
   207  	var (
   208  		needClose    []C.Inbound
   209  		needCreate   []C.Inbound
   210  		needCloseMap = make(map[string]C.Inbound)
   211  	)
   212  	for _, m := range originInbounds {
   213  		needCloseMap[m.Key()] = m
   214  	}
   215  	for _, m := range newInbounds {
   216  		key := m.Key()
   217  		if c, ok := needCloseMap[key]; ok {
   218  			if !reflect.DeepEqual(m.Authentication, c.Authentication) {
   219  				needCreate = append(needCreate, m)
   220  			} else {
   221  				delete(needCloseMap, key)
   222  			}
   223  		} else {
   224  			needCreate = append(needCreate, m)
   225  		}
   226  	}
   227  	for _, m := range needCloseMap {
   228  		needClose = append(needClose, m)
   229  	}
   230  	return needClose, needCreate
   231  }
   232  
   233  // ReCreateListeners only recreate inbound config listener
   234  func ReCreateListeners(inbounds []C.Inbound, tcpIn chan<- C.ConnContext, udpIn chan<- *inbound.PacketAdapter) {
   235  	inboundsMux.Lock()
   236  	defer inboundsMux.Unlock()
   237  	newInbounds := append([]C.Inbound{}, inbounds...)
   238  	for _, m := range getInbounds() {
   239  		if m.IsFromPortCfg {
   240  			newInbounds = append(newInbounds, m)
   241  		}
   242  	}
   243  	reCreateListeners(newInbounds, tcpIn, udpIn)
   244  }
   245  
   246  // ReCreatePortsListeners only recreate ports config listener
   247  func ReCreatePortsListeners(ports Ports, tcpIn chan<- C.ConnContext, udpIn chan<- *inbound.PacketAdapter) {
   248  	inboundsMux.Lock()
   249  	defer inboundsMux.Unlock()
   250  	newInbounds := addPortInbound([]C.Inbound{}, C.InboundTypeHTTP, ports.Port)
   251  	newInbounds = addPortInbound(newInbounds, C.InboundTypeSocks, ports.SocksPort)
   252  	newInbounds = addPortInbound(newInbounds, C.InboundTypeRedir, ports.RedirPort)
   253  	newInbounds = addPortInbound(newInbounds, C.InboundTypeTproxy, ports.TProxyPort)
   254  	newInbounds = addPortInbound(newInbounds, C.InboundTypeMixed, ports.MixedPort)
   255  	newInbounds = addPortInbound(newInbounds, C.InboundTypeMitm, ports.MitmPort)
   256  	newInbounds = append(newInbounds, GetInbounds()...)
   257  	reCreateListeners(newInbounds, tcpIn, udpIn)
   258  }
   259  
   260  func addPortInbound(inbounds []C.Inbound, inboundType C.InboundType, port int) []C.Inbound {
   261  	if port != 0 {
   262  		inbounds = append(inbounds, C.Inbound{
   263  			Type:          inboundType,
   264  			BindAddress:   genAddr(bindAddress, port, allowLan),
   265  			IsFromPortCfg: true,
   266  		})
   267  	}
   268  	return inbounds
   269  }
   270  
   271  func reCreateListeners(inbounds []C.Inbound, tcpIn chan<- C.ConnContext, udpIn chan<- *inbound.PacketAdapter) {
   272  	needClose, needCreate := getNeedCloseAndCreateInbound(getInbounds(), inbounds)
   273  	for _, m := range needClose {
   274  		closeListener(m)
   275  	}
   276  	for _, m := range needCreate {
   277  		createListener(m, tcpIn, udpIn)
   278  	}
   279  	C.SetProxyInbound(tcpInbounds)
   280  }
   281  
   282  func ReCreateTun(tunConf *C.Tun, tcpIn chan<- C.ConnContext, udpIn chan<- *inbound.PacketAdapter) {
   283  	tunMux.Lock()
   284  	defer tunMux.Unlock()
   285  
   286  	if C.IsNoGVisor {
   287  		tunConf.Stack = C.TunSystem
   288  	}
   289  
   290  	tunConf.DNSHijack = lo.UniqBy(tunConf.DNSHijack, func(item C.DNSUrl) string {
   291  		return item.String()
   292  	})
   293  
   294  	if tunStackListener != nil {
   295  		if !hasTunConfigChange(tunConf) {
   296  			return
   297  		}
   298  
   299  		if tunConf.StopRouteListener && !tunConf.Enable {
   300  			commons.SetTunStatus(C.TunDisabled)
   301  		}
   302  
   303  		_ = tunStackListener.Close()
   304  		tunStackListener = nil
   305  	}
   306  
   307  	C.SetLastTunConf(tunConf)
   308  
   309  	if !tunConf.Enable {
   310  		return
   311  	}
   312  
   313  	callback := &tunChangeCallback{
   314  		tunConf: *tunConf,
   315  		tcpIn:   tcpIn,
   316  		udpIn:   udpIn,
   317  	}
   318  
   319  	if tunConf.AutoDetectInterface {
   320  		outboundInterface, err := commons.GetAutoDetectInterface()
   321  		if err != nil {
   322  			log.Info().Err(err).Msg("[Tun] auto detect interface failed")
   323  		}
   324  		if outboundInterface != "" && outboundInterface != dialer.DefaultInterface.Load() {
   325  			dialer.DefaultInterface.Store(outboundInterface)
   326  			iface.FlushCache()
   327  			commons.UpdateWireGuardBind()
   328  			log.Info().
   329  				Str("name", outboundInterface).
   330  				Msg("[TUN] default interface has overwrite by auto detect interface")
   331  		}
   332  	}
   333  
   334  	var err error
   335  	tunStackListener, err = tun.New(tunConf, tcpIn, udpIn, callback)
   336  	if err != nil {
   337  		log.Error().Err(err).Msg("[Inbound] tun server start failed")
   338  	}
   339  }
   340  
   341  func ReCreateRedirToTun(ifaceNames []string) {
   342  	tcMux.Lock()
   343  	defer tcMux.Unlock()
   344  
   345  	nicArr := lo.Uniq(ifaceNames)
   346  
   347  	if tcProgram != nil {
   348  		tcProgram.Close()
   349  		tcProgram = nil
   350  	}
   351  
   352  	if len(nicArr) == 0 {
   353  		return
   354  	}
   355  
   356  	lastTunConf := C.GetLastTunConf()
   357  	if lastTunConf == nil || !lastTunConf.Enable {
   358  		return
   359  	}
   360  
   361  	program, err := ebpf.NewTcEBpfProgram(nicArr, lastTunConf.Device)
   362  	if err != nil {
   363  		log.Error().Err(err).Msg("[Inbound] attach tc ebpf program failed")
   364  		return
   365  	}
   366  	tcProgram = program
   367  
   368  	log.Info().Strs("interfaces", tcProgram.RawNICs()).Msg("[Inbound] attached tc ebpf program")
   369  }
   370  
   371  func ReCreateAutoRedir(ifaceNames []string, defaultInterface string, tcpIn chan<- C.ConnContext, _ chan<- *inbound.PacketAdapter) {
   372  	autoRedirMux.Lock()
   373  	defer autoRedirMux.Unlock()
   374  
   375  	var err error
   376  	defer func(err error) {
   377  		if err != nil {
   378  			if autoRedirListener != nil {
   379  				_ = autoRedirListener.Close()
   380  				autoRedirListener = nil
   381  			}
   382  			if autoRedirProgram != nil {
   383  				autoRedirProgram.Close()
   384  				autoRedirProgram = nil
   385  			}
   386  			log.Error().Err(err).Msg("[Inbound] auto redirect server start failed")
   387  		}
   388  	}(err)
   389  
   390  	nicArr := lo.Uniq(ifaceNames)
   391  	defaultRouteInterfaceName := defaultInterface
   392  
   393  	if autoRedirListener != nil && autoRedirProgram != nil {
   394  		if defaultRouteInterfaceName == "" {
   395  			defaultRouteInterfaceName, _ = commons.GetAutoDetectInterface()
   396  		}
   397  		if autoRedirProgram.RawInterface() == defaultRouteInterfaceName &&
   398  			len(autoRedirProgram.RawNICs()) == len(nicArr) &&
   399  			lo.Every(autoRedirProgram.RawNICs(), nicArr) {
   400  			return
   401  		}
   402  		_ = autoRedirListener.Close()
   403  		autoRedirProgram.Close()
   404  		autoRedirListener = nil
   405  		autoRedirProgram = nil
   406  	}
   407  
   408  	if len(nicArr) == 0 {
   409  		return
   410  	}
   411  
   412  	if defaultRouteInterfaceName == "" {
   413  		defaultRouteInterfaceName, err = commons.GetAutoDetectInterface()
   414  		if err != nil {
   415  			return
   416  		}
   417  	}
   418  
   419  	addr := genAddr("*", C.TcpAutoRedirPort, true)
   420  
   421  	autoRedirListener, err = autoredir.New(addr, tcpIn)
   422  	if err != nil {
   423  		return
   424  	}
   425  
   426  	autoRedirProgram, err = ebpf.NewRedirEBpfProgram(nicArr, autoRedirListener.TCPAddr().Port(),
   427  		defaultRouteInterfaceName)
   428  	if err != nil {
   429  		return
   430  	}
   431  
   432  	autoRedirListener.SetLookupFunc(autoRedirProgram.Lookup)
   433  
   434  	log.Info().
   435  		Str("addr", autoRedirListener.Address()).
   436  		Strs("interfaces", autoRedirProgram.RawNICs()).
   437  		Msg("[Inbound] auto redirect proxy listening, attached tc ebpf program")
   438  }
   439  
   440  func PatchTunnel(tunnels []config.Tunnel, tcpIn chan<- C.ConnContext, udpIn chan<- *inbound.PacketAdapter) {
   441  	tunnelMux.Lock()
   442  	defer tunnelMux.Unlock()
   443  
   444  	type addrProxy struct {
   445  		network string
   446  		addr    string
   447  		target  string
   448  		proxy   string
   449  	}
   450  
   451  	tcpOld := lo.Map(
   452  		lo.Keys(tunnelTCPListeners),
   453  		func(key string, _ int) addrProxy {
   454  			parts := strings.Split(key, "/")
   455  			return addrProxy{
   456  				network: "tcp",
   457  				addr:    parts[0],
   458  				target:  parts[1],
   459  				proxy:   parts[2],
   460  			}
   461  		},
   462  	)
   463  	udpOld := lo.Map(
   464  		lo.Keys(tunnelUDPListeners),
   465  		func(key string, _ int) addrProxy {
   466  			parts := strings.Split(key, "/")
   467  			return addrProxy{
   468  				network: "udp",
   469  				addr:    parts[0],
   470  				target:  parts[1],
   471  				proxy:   parts[2],
   472  			}
   473  		},
   474  	)
   475  	oldElm := lo.Union(tcpOld, udpOld)
   476  
   477  	newElm := lo.FlatMap(
   478  		tunnels,
   479  		func(tunnel config.Tunnel, _ int) []addrProxy {
   480  			return lo.Map(
   481  				tunnel.Network,
   482  				func(network string, _ int) addrProxy {
   483  					return addrProxy{
   484  						network: network,
   485  						addr:    tunnel.Address,
   486  						target:  tunnel.Target,
   487  						proxy:   tunnel.Proxy,
   488  					}
   489  				},
   490  			)
   491  		},
   492  	)
   493  
   494  	needClose, needCreate := lo.Difference(oldElm, newElm)
   495  
   496  	for _, elm := range needClose {
   497  		key := fmt.Sprintf("%s/%s/%s", elm.addr, elm.target, elm.proxy)
   498  		if elm.network == "tcp" {
   499  			_ = tunnelTCPListeners[key].Close()
   500  			delete(tunnelTCPListeners, key)
   501  		} else {
   502  			_ = tunnelUDPListeners[key].Close()
   503  			delete(tunnelUDPListeners, key)
   504  		}
   505  	}
   506  
   507  	for _, elm := range needCreate {
   508  		key := fmt.Sprintf("%s/%s/%s", elm.addr, elm.target, elm.proxy)
   509  		if elm.network == "tcp" {
   510  			l, err := tunnel.New(elm.addr, elm.target, elm.proxy, tcpIn)
   511  			if err != nil {
   512  				log.Error().Err(err).Str("target", elm.target).Msg("[Inbound] tunnel server start failed")
   513  				continue
   514  			}
   515  			tunnelTCPListeners[key] = l
   516  			log.Info().
   517  				Str("addr", tunnelTCPListeners[key].Address()).
   518  				Str("network", elm.network).
   519  				Str("target", elm.target).
   520  				Str("proxy", elm.proxy).
   521  				Msg("[Inbound] tunnel proxy listening")
   522  		} else {
   523  			l, err := tunnel.NewUDP(elm.addr, elm.target, elm.proxy, udpIn)
   524  			if err != nil {
   525  				log.Error().Err(err).Str("target", elm.target).Msg("[Inbound] tunnel server start failed")
   526  				continue
   527  			}
   528  			tunnelUDPListeners[key] = l
   529  			log.Info().
   530  				Str("addr", tunnelUDPListeners[key].Address()).
   531  				Str("network", elm.network).
   532  				Str("target", elm.target).
   533  				Str("proxy", elm.proxy).
   534  				Msg("[Inbound] tunnel proxy listening")
   535  		}
   536  	}
   537  }
   538  
   539  func GetInbounds() []C.Inbound {
   540  	return lo.Filter(getInbounds(), func(inbound C.Inbound, _ int) bool {
   541  		return !inbound.IsFromPortCfg
   542  	})
   543  }
   544  
   545  // GetInbounds return inbounds of proxy servers
   546  func getInbounds() []C.Inbound {
   547  	var inbounds []C.Inbound
   548  	for _, tcp := range tcpInbounds {
   549  		inbounds = append(inbounds, tcp)
   550  	}
   551  	for _, udp := range udpInbounds {
   552  		if _, ok := tcpInbounds[udp.Key()]; !ok {
   553  			inbounds = append(inbounds, udp)
   554  		}
   555  	}
   556  	return inbounds
   557  }
   558  
   559  // GetPorts return the ports of proxy servers
   560  func GetPorts() *Ports {
   561  	ports := &Ports{}
   562  	for _, m := range getInbounds() {
   563  		fillPort(m, ports)
   564  	}
   565  	return ports
   566  }
   567  
   568  func fillPort(inbound C.Inbound, ports *Ports) {
   569  	if inbound.IsFromPortCfg {
   570  		port := getPort(inbound.BindAddress)
   571  		switch inbound.Type {
   572  		case C.InboundTypeHTTP:
   573  			ports.Port = port
   574  		case C.InboundTypeSocks:
   575  			ports.SocksPort = port
   576  		case C.InboundTypeTproxy:
   577  			ports.TProxyPort = port
   578  		case C.InboundTypeRedir:
   579  			ports.RedirPort = port
   580  		case C.InboundTypeMixed:
   581  			ports.MixedPort = port
   582  		case C.InboundTypeMitm:
   583  			ports.MitmPort = port
   584  		default:
   585  			// do nothing
   586  		}
   587  	}
   588  }
   589  
   590  func portIsZero(addr string) bool {
   591  	_, port, err := net.SplitHostPort(addr)
   592  	if port == "0" || port == "" || err != nil {
   593  		return true
   594  	}
   595  	return false
   596  }
   597  
   598  func genAddr(host string, port int, allowLan bool) string {
   599  	if allowLan {
   600  		if host == "*" {
   601  			return fmt.Sprintf(":%d", port)
   602  		}
   603  		return fmt.Sprintf("%s:%d", host, port)
   604  	}
   605  
   606  	return fmt.Sprintf("127.0.0.1:%d", port)
   607  }
   608  
   609  func getPort(addr string) int {
   610  	_, portStr, err := net.SplitHostPort(addr)
   611  	if err != nil {
   612  		return 0
   613  	}
   614  	port, err := strconv.ParseUint(portStr, 10, 16)
   615  	if err != nil {
   616  		return 0
   617  	}
   618  	return int(port)
   619  }
   620  
   621  func hasTunConfigChange(tunConf *C.Tun) bool {
   622  	lastTunConf := C.GetLastTunConf()
   623  	if lastTunConf == nil {
   624  		return true
   625  	}
   626  
   627  	if lastTunConf.Enable != tunConf.Enable ||
   628  		lastTunConf.Stack != tunConf.Stack ||
   629  		!lo.Every(lastTunConf.DNSHijack, tunConf.DNSHijack) ||
   630  		lastTunConf.AutoRoute != tunConf.AutoRoute ||
   631  		lastTunConf.AutoDetectInterface != tunConf.AutoDetectInterface ||
   632  		!reflect.DeepEqual(lastTunConf.TunAddressPrefix, tunConf.TunAddressPrefix) {
   633  		return true
   634  	}
   635  
   636  	return false
   637  }
   638  
   639  type tunChangeCallback struct {
   640  	tunConf C.Tun
   641  	tcpIn   chan<- C.ConnContext
   642  	udpIn   chan<- *inbound.PacketAdapter
   643  }
   644  
   645  func (t *tunChangeCallback) Pause() {
   646  	conf := t.tunConf
   647  	conf.Enable = false
   648  	conf.StopRouteListener = false
   649  	ReCreateTun(&conf, t.tcpIn, t.udpIn)
   650  	ReCreateRedirToTun([]string{})
   651  }
   652  
   653  func (t *tunChangeCallback) Resume() {
   654  	conf := t.tunConf
   655  	conf.Enable = true
   656  	conf.StopRouteListener = false
   657  	ReCreateTun(&conf, t.tcpIn, t.udpIn)
   658  	ReCreateRedirToTun(conf.RedirectToTun)
   659  	statistic.DefaultManager.Cleanup()
   660  }
   661  
   662  func Cleanup() {
   663  	if tcProgram != nil {
   664  		tcProgram.Close()
   665  	}
   666  	if autoRedirProgram != nil {
   667  		autoRedirProgram.Close()
   668  	}
   669  	if tunStackListener != nil {
   670  		commons.SetTunStatus(C.TunDisabled)
   671  		_ = tunStackListener.Close()
   672  	}
   673  }