github.com/metacubex/mihomo@v1.18.5/listener/listener.go (about)

     1  package listener
     2  
     3  import (
     4  	"fmt"
     5  	"golang.org/x/exp/slices"
     6  	"net"
     7  	"sort"
     8  	"strconv"
     9  	"strings"
    10  	"sync"
    11  
    12  	"github.com/metacubex/mihomo/component/ebpf"
    13  	C "github.com/metacubex/mihomo/constant"
    14  	"github.com/metacubex/mihomo/listener/autoredir"
    15  	LC "github.com/metacubex/mihomo/listener/config"
    16  	"github.com/metacubex/mihomo/listener/http"
    17  	"github.com/metacubex/mihomo/listener/mixed"
    18  	"github.com/metacubex/mihomo/listener/redir"
    19  	embedSS "github.com/metacubex/mihomo/listener/shadowsocks"
    20  	"github.com/metacubex/mihomo/listener/sing_shadowsocks"
    21  	"github.com/metacubex/mihomo/listener/sing_tun"
    22  	"github.com/metacubex/mihomo/listener/sing_vmess"
    23  	"github.com/metacubex/mihomo/listener/socks"
    24  	"github.com/metacubex/mihomo/listener/tproxy"
    25  	"github.com/metacubex/mihomo/listener/tuic"
    26  	LT "github.com/metacubex/mihomo/listener/tunnel"
    27  	"github.com/metacubex/mihomo/log"
    28  
    29  	"github.com/samber/lo"
    30  )
    31  
    32  var (
    33  	allowLan    = false
    34  	bindAddress = "*"
    35  
    36  	socksListener       *socks.Listener
    37  	socksUDPListener    *socks.UDPListener
    38  	httpListener        *http.Listener
    39  	redirListener       *redir.Listener
    40  	redirUDPListener    *tproxy.UDPListener
    41  	tproxyListener      *tproxy.Listener
    42  	tproxyUDPListener   *tproxy.UDPListener
    43  	mixedListener       *mixed.Listener
    44  	mixedUDPLister      *socks.UDPListener
    45  	tunnelTCPListeners  = map[string]*LT.Listener{}
    46  	tunnelUDPListeners  = map[string]*LT.PacketConn{}
    47  	inboundListeners    = map[string]C.InboundListener{}
    48  	tunLister           *sing_tun.Listener
    49  	shadowSocksListener C.MultiAddrListener
    50  	vmessListener       *sing_vmess.Listener
    51  	tuicListener        *tuic.Listener
    52  	autoRedirListener   *autoredir.Listener
    53  	autoRedirProgram    *ebpf.TcEBpfProgram
    54  	tcProgram           *ebpf.TcEBpfProgram
    55  
    56  	// lock for recreate function
    57  	socksMux     sync.Mutex
    58  	httpMux      sync.Mutex
    59  	redirMux     sync.Mutex
    60  	tproxyMux    sync.Mutex
    61  	mixedMux     sync.Mutex
    62  	tunnelMux    sync.Mutex
    63  	inboundMux   sync.Mutex
    64  	tunMux       sync.Mutex
    65  	ssMux        sync.Mutex
    66  	vmessMux     sync.Mutex
    67  	tuicMux      sync.Mutex
    68  	autoRedirMux sync.Mutex
    69  	tcMux        sync.Mutex
    70  
    71  	LastTunConf  LC.Tun
    72  	LastTuicConf LC.TuicServer
    73  )
    74  
    75  type Ports struct {
    76  	Port              int    `json:"port"`
    77  	SocksPort         int    `json:"socks-port"`
    78  	RedirPort         int    `json:"redir-port"`
    79  	TProxyPort        int    `json:"tproxy-port"`
    80  	MixedPort         int    `json:"mixed-port"`
    81  	ShadowSocksConfig string `json:"ss-config"`
    82  	VmessConfig       string `json:"vmess-config"`
    83  }
    84  
    85  func GetTunConf() LC.Tun {
    86  	if tunLister == nil {
    87  		return LastTunConf
    88  	}
    89  	return tunLister.Config()
    90  }
    91  
    92  func GetTuicConf() LC.TuicServer {
    93  	if tuicListener == nil {
    94  		return LC.TuicServer{Enable: false}
    95  	}
    96  	return tuicListener.Config()
    97  }
    98  
    99  func AllowLan() bool {
   100  	return allowLan
   101  }
   102  
   103  func BindAddress() string {
   104  	return bindAddress
   105  }
   106  
   107  func SetAllowLan(al bool) {
   108  	allowLan = al
   109  }
   110  
   111  func SetBindAddress(host string) {
   112  	bindAddress = host
   113  }
   114  
   115  func ReCreateHTTP(port int, tunnel C.Tunnel) {
   116  	httpMux.Lock()
   117  	defer httpMux.Unlock()
   118  
   119  	var err error
   120  	defer func() {
   121  		if err != nil {
   122  			log.Errorln("Start HTTP server error: %s", err.Error())
   123  		}
   124  	}()
   125  
   126  	addr := genAddr(bindAddress, port, allowLan)
   127  
   128  	if httpListener != nil {
   129  		if httpListener.RawAddress() == addr {
   130  			return
   131  		}
   132  		httpListener.Close()
   133  		httpListener = nil
   134  	}
   135  
   136  	if portIsZero(addr) {
   137  		return
   138  	}
   139  
   140  	httpListener, err = http.New(addr, tunnel)
   141  	if err != nil {
   142  		log.Errorln("Start HTTP server error: %s", err.Error())
   143  		return
   144  	}
   145  
   146  	log.Infoln("HTTP proxy listening at: %s", httpListener.Address())
   147  }
   148  
   149  func ReCreateSocks(port int, tunnel C.Tunnel) {
   150  	socksMux.Lock()
   151  	defer socksMux.Unlock()
   152  
   153  	var err error
   154  	defer func() {
   155  		if err != nil {
   156  			log.Errorln("Start SOCKS server error: %s", err.Error())
   157  		}
   158  	}()
   159  
   160  	addr := genAddr(bindAddress, port, allowLan)
   161  
   162  	shouldTCPIgnore := false
   163  	shouldUDPIgnore := false
   164  
   165  	if socksListener != nil {
   166  		if socksListener.RawAddress() != addr {
   167  			socksListener.Close()
   168  			socksListener = nil
   169  		} else {
   170  			shouldTCPIgnore = true
   171  		}
   172  	}
   173  
   174  	if socksUDPListener != nil {
   175  		if socksUDPListener.RawAddress() != addr {
   176  			socksUDPListener.Close()
   177  			socksUDPListener = nil
   178  		} else {
   179  			shouldUDPIgnore = true
   180  		}
   181  	}
   182  
   183  	if shouldTCPIgnore && shouldUDPIgnore {
   184  		return
   185  	}
   186  
   187  	if portIsZero(addr) {
   188  		return
   189  	}
   190  
   191  	tcpListener, err := socks.New(addr, tunnel)
   192  	if err != nil {
   193  		return
   194  	}
   195  
   196  	udpListener, err := socks.NewUDP(addr, tunnel)
   197  	if err != nil {
   198  		tcpListener.Close()
   199  		return
   200  	}
   201  
   202  	socksListener = tcpListener
   203  	socksUDPListener = udpListener
   204  
   205  	log.Infoln("SOCKS proxy listening at: %s", socksListener.Address())
   206  }
   207  
   208  func ReCreateRedir(port int, tunnel C.Tunnel) {
   209  	redirMux.Lock()
   210  	defer redirMux.Unlock()
   211  
   212  	var err error
   213  	defer func() {
   214  		if err != nil {
   215  			log.Errorln("Start Redir server error: %s", err.Error())
   216  		}
   217  	}()
   218  
   219  	addr := genAddr(bindAddress, port, allowLan)
   220  
   221  	if redirListener != nil {
   222  		if redirListener.RawAddress() == addr {
   223  			return
   224  		}
   225  		redirListener.Close()
   226  		redirListener = nil
   227  	}
   228  
   229  	if redirUDPListener != nil {
   230  		if redirUDPListener.RawAddress() == addr {
   231  			return
   232  		}
   233  		redirUDPListener.Close()
   234  		redirUDPListener = nil
   235  	}
   236  
   237  	if portIsZero(addr) {
   238  		return
   239  	}
   240  
   241  	redirListener, err = redir.New(addr, tunnel)
   242  	if err != nil {
   243  		return
   244  	}
   245  
   246  	redirUDPListener, err = tproxy.NewUDP(addr, tunnel)
   247  	if err != nil {
   248  		log.Warnln("Failed to start Redir UDP Listener: %s", err)
   249  	}
   250  
   251  	log.Infoln("Redirect proxy listening at: %s", redirListener.Address())
   252  }
   253  
   254  func ReCreateShadowSocks(shadowSocksConfig string, tunnel C.Tunnel) {
   255  	ssMux.Lock()
   256  	defer ssMux.Unlock()
   257  
   258  	var err error
   259  	defer func() {
   260  		if err != nil {
   261  			log.Errorln("Start ShadowSocks server error: %s", err.Error())
   262  		}
   263  	}()
   264  
   265  	var ssConfig LC.ShadowsocksServer
   266  	if addr, cipher, password, err := embedSS.ParseSSURL(shadowSocksConfig); err == nil {
   267  		ssConfig = LC.ShadowsocksServer{
   268  			Enable:   len(shadowSocksConfig) > 0,
   269  			Listen:   addr,
   270  			Password: password,
   271  			Cipher:   cipher,
   272  			Udp:      true,
   273  		}
   274  	}
   275  
   276  	shouldIgnore := false
   277  
   278  	if shadowSocksListener != nil {
   279  		if shadowSocksListener.Config() != ssConfig.String() {
   280  			shadowSocksListener.Close()
   281  			shadowSocksListener = nil
   282  		} else {
   283  			shouldIgnore = true
   284  		}
   285  	}
   286  
   287  	if shouldIgnore {
   288  		return
   289  	}
   290  
   291  	if !ssConfig.Enable {
   292  		return
   293  	}
   294  
   295  	listener, err := sing_shadowsocks.New(ssConfig, tunnel)
   296  	if err != nil {
   297  		return
   298  	}
   299  
   300  	shadowSocksListener = listener
   301  
   302  	for _, addr := range shadowSocksListener.AddrList() {
   303  		log.Infoln("ShadowSocks proxy listening at: %s", addr.String())
   304  	}
   305  	return
   306  }
   307  
   308  func ReCreateVmess(vmessConfig string, tunnel C.Tunnel) {
   309  	vmessMux.Lock()
   310  	defer vmessMux.Unlock()
   311  
   312  	var err error
   313  	defer func() {
   314  		if err != nil {
   315  			log.Errorln("Start Vmess server error: %s", err.Error())
   316  		}
   317  	}()
   318  
   319  	var vsConfig LC.VmessServer
   320  	if addr, username, password, err := sing_vmess.ParseVmessURL(vmessConfig); err == nil {
   321  		vsConfig = LC.VmessServer{
   322  			Enable: len(vmessConfig) > 0,
   323  			Listen: addr,
   324  			Users:  []LC.VmessUser{{Username: username, UUID: password, AlterID: 1}},
   325  		}
   326  	}
   327  
   328  	shouldIgnore := false
   329  
   330  	if vmessListener != nil {
   331  		if vmessListener.Config() != vsConfig.String() {
   332  			vmessListener.Close()
   333  			vmessListener = nil
   334  		} else {
   335  			shouldIgnore = true
   336  		}
   337  	}
   338  
   339  	if shouldIgnore {
   340  		return
   341  	}
   342  
   343  	if !vsConfig.Enable {
   344  		return
   345  	}
   346  
   347  	listener, err := sing_vmess.New(vsConfig, tunnel)
   348  	if err != nil {
   349  		return
   350  	}
   351  
   352  	vmessListener = listener
   353  
   354  	for _, addr := range vmessListener.AddrList() {
   355  		log.Infoln("Vmess proxy listening at: %s", addr.String())
   356  	}
   357  	return
   358  }
   359  
   360  func ReCreateTuic(config LC.TuicServer, tunnel C.Tunnel) {
   361  	tuicMux.Lock()
   362  	defer func() {
   363  		LastTuicConf = config
   364  		tuicMux.Unlock()
   365  	}()
   366  	shouldIgnore := false
   367  
   368  	var err error
   369  	defer func() {
   370  		if err != nil {
   371  			log.Errorln("Start Tuic server error: %s", err.Error())
   372  		}
   373  	}()
   374  
   375  	if tuicListener != nil {
   376  		if tuicListener.Config().String() != config.String() {
   377  			tuicListener.Close()
   378  			tuicListener = nil
   379  		} else {
   380  			shouldIgnore = true
   381  		}
   382  	}
   383  
   384  	if shouldIgnore {
   385  		return
   386  	}
   387  
   388  	if !config.Enable {
   389  		return
   390  	}
   391  
   392  	listener, err := tuic.New(config, tunnel)
   393  	if err != nil {
   394  		return
   395  	}
   396  
   397  	tuicListener = listener
   398  
   399  	for _, addr := range tuicListener.AddrList() {
   400  		log.Infoln("Tuic proxy listening at: %s", addr.String())
   401  	}
   402  	return
   403  }
   404  
   405  func ReCreateTProxy(port int, tunnel C.Tunnel) {
   406  	tproxyMux.Lock()
   407  	defer tproxyMux.Unlock()
   408  
   409  	var err error
   410  	defer func() {
   411  		if err != nil {
   412  			log.Errorln("Start TProxy server error: %s", err.Error())
   413  		}
   414  	}()
   415  
   416  	addr := genAddr(bindAddress, port, allowLan)
   417  
   418  	if tproxyListener != nil {
   419  		if tproxyListener.RawAddress() == addr {
   420  			return
   421  		}
   422  		tproxyListener.Close()
   423  		tproxyListener = nil
   424  	}
   425  
   426  	if tproxyUDPListener != nil {
   427  		if tproxyUDPListener.RawAddress() == addr {
   428  			return
   429  		}
   430  		tproxyUDPListener.Close()
   431  		tproxyUDPListener = nil
   432  	}
   433  
   434  	if portIsZero(addr) {
   435  		return
   436  	}
   437  
   438  	tproxyListener, err = tproxy.New(addr, tunnel)
   439  	if err != nil {
   440  		return
   441  	}
   442  
   443  	tproxyUDPListener, err = tproxy.NewUDP(addr, tunnel)
   444  	if err != nil {
   445  		log.Warnln("Failed to start TProxy UDP Listener: %s", err)
   446  	}
   447  
   448  	log.Infoln("TProxy server listening at: %s", tproxyListener.Address())
   449  }
   450  
   451  func ReCreateMixed(port int, tunnel C.Tunnel) {
   452  	mixedMux.Lock()
   453  	defer mixedMux.Unlock()
   454  
   455  	var err error
   456  	defer func() {
   457  		if err != nil {
   458  			log.Errorln("Start Mixed(http+socks) server error: %s", err.Error())
   459  		}
   460  	}()
   461  
   462  	addr := genAddr(bindAddress, port, allowLan)
   463  
   464  	shouldTCPIgnore := false
   465  	shouldUDPIgnore := false
   466  
   467  	if mixedListener != nil {
   468  		if mixedListener.RawAddress() != addr {
   469  			mixedListener.Close()
   470  			mixedListener = nil
   471  		} else {
   472  			shouldTCPIgnore = true
   473  		}
   474  	}
   475  	if mixedUDPLister != nil {
   476  		if mixedUDPLister.RawAddress() != addr {
   477  			mixedUDPLister.Close()
   478  			mixedUDPLister = nil
   479  		} else {
   480  			shouldUDPIgnore = true
   481  		}
   482  	}
   483  
   484  	if shouldTCPIgnore && shouldUDPIgnore {
   485  		return
   486  	}
   487  
   488  	if portIsZero(addr) {
   489  		return
   490  	}
   491  
   492  	mixedListener, err = mixed.New(addr, tunnel)
   493  	if err != nil {
   494  		return
   495  	}
   496  
   497  	mixedUDPLister, err = socks.NewUDP(addr, tunnel)
   498  	if err != nil {
   499  		mixedListener.Close()
   500  		return
   501  	}
   502  
   503  	log.Infoln("Mixed(http+socks) proxy listening at: %s", mixedListener.Address())
   504  }
   505  
   506  func ReCreateTun(tunConf LC.Tun, tunnel C.Tunnel) {
   507  	tunMux.Lock()
   508  	defer func() {
   509  		LastTunConf = tunConf
   510  		tunMux.Unlock()
   511  	}()
   512  
   513  	var err error
   514  	defer func() {
   515  		if err != nil {
   516  			log.Errorln("Start TUN listening error: %s", err.Error())
   517  			tunConf.Enable = false
   518  		}
   519  	}()
   520  
   521  	if !hasTunConfigChange(&tunConf) {
   522  		if tunLister != nil {
   523  			tunLister.FlushDefaultInterface()
   524  		}
   525  		return
   526  	}
   527  
   528  	closeTunListener()
   529  
   530  	if !tunConf.Enable {
   531  		return
   532  	}
   533  
   534  	lister, err := sing_tun.New(tunConf, tunnel)
   535  	if err != nil {
   536  		return
   537  	}
   538  	tunLister = lister
   539  
   540  	log.Infoln("[TUN] Tun adapter listening at: %s", tunLister.Address())
   541  }
   542  
   543  func ReCreateRedirToTun(ifaceNames []string) {
   544  	tcMux.Lock()
   545  	defer tcMux.Unlock()
   546  
   547  	nicArr := ifaceNames
   548  	slices.Sort(nicArr)
   549  	nicArr = slices.Compact(nicArr)
   550  
   551  	if tcProgram != nil {
   552  		tcProgram.Close()
   553  		tcProgram = nil
   554  	}
   555  
   556  	if len(nicArr) == 0 {
   557  		return
   558  	}
   559  
   560  	tunConf := GetTunConf()
   561  
   562  	if !tunConf.Enable {
   563  		return
   564  	}
   565  
   566  	program, err := ebpf.NewTcEBpfProgram(nicArr, tunConf.Device)
   567  	if err != nil {
   568  		log.Errorln("Attached tc ebpf program error: %v", err)
   569  		return
   570  	}
   571  	tcProgram = program
   572  
   573  	log.Infoln("Attached tc ebpf program to interfaces %v", tcProgram.RawNICs())
   574  }
   575  
   576  func ReCreateAutoRedir(ifaceNames []string, tunnel C.Tunnel) {
   577  	autoRedirMux.Lock()
   578  	defer autoRedirMux.Unlock()
   579  
   580  	var err error
   581  	defer func() {
   582  		if err != nil {
   583  			if autoRedirListener != nil {
   584  				_ = autoRedirListener.Close()
   585  				autoRedirListener = nil
   586  			}
   587  			if autoRedirProgram != nil {
   588  				autoRedirProgram.Close()
   589  				autoRedirProgram = nil
   590  			}
   591  			log.Errorln("Start auto redirect server error: %s", err.Error())
   592  		}
   593  	}()
   594  
   595  	nicArr := ifaceNames
   596  	slices.Sort(nicArr)
   597  	nicArr = slices.Compact(nicArr)
   598  
   599  	if autoRedirListener != nil && autoRedirProgram != nil {
   600  		_ = autoRedirListener.Close()
   601  		autoRedirProgram.Close()
   602  		autoRedirListener = nil
   603  		autoRedirProgram = nil
   604  	}
   605  
   606  	if len(nicArr) == 0 {
   607  		return
   608  	}
   609  
   610  	defaultRouteInterfaceName, err := ebpf.GetAutoDetectInterface()
   611  	if err != nil {
   612  		return
   613  	}
   614  
   615  	addr := genAddr("*", C.TcpAutoRedirPort, true)
   616  
   617  	autoRedirListener, err = autoredir.New(addr, tunnel)
   618  	if err != nil {
   619  		return
   620  	}
   621  
   622  	autoRedirProgram, err = ebpf.NewRedirEBpfProgram(nicArr, autoRedirListener.TCPAddr().Port(), defaultRouteInterfaceName)
   623  	if err != nil {
   624  		return
   625  	}
   626  
   627  	autoRedirListener.SetLookupFunc(autoRedirProgram.Lookup)
   628  
   629  	log.Infoln("Auto redirect proxy listening at: %s, attached tc ebpf program to interfaces %v", autoRedirListener.Address(), autoRedirProgram.RawNICs())
   630  }
   631  
   632  func PatchTunnel(tunnels []LC.Tunnel, tunnel C.Tunnel) {
   633  	tunnelMux.Lock()
   634  	defer tunnelMux.Unlock()
   635  
   636  	type addrProxy struct {
   637  		network string
   638  		addr    string
   639  		target  string
   640  		proxy   string
   641  	}
   642  
   643  	tcpOld := lo.Map(
   644  		lo.Keys(tunnelTCPListeners),
   645  		func(key string, _ int) addrProxy {
   646  			parts := strings.Split(key, "/")
   647  			return addrProxy{
   648  				network: "tcp",
   649  				addr:    parts[0],
   650  				target:  parts[1],
   651  				proxy:   parts[2],
   652  			}
   653  		},
   654  	)
   655  	udpOld := lo.Map(
   656  		lo.Keys(tunnelUDPListeners),
   657  		func(key string, _ int) addrProxy {
   658  			parts := strings.Split(key, "/")
   659  			return addrProxy{
   660  				network: "udp",
   661  				addr:    parts[0],
   662  				target:  parts[1],
   663  				proxy:   parts[2],
   664  			}
   665  		},
   666  	)
   667  	oldElm := lo.Union(tcpOld, udpOld)
   668  
   669  	newElm := lo.FlatMap(
   670  		tunnels,
   671  		func(tunnel LC.Tunnel, _ int) []addrProxy {
   672  			return lo.Map(
   673  				tunnel.Network,
   674  				func(network string, _ int) addrProxy {
   675  					return addrProxy{
   676  						network: network,
   677  						addr:    tunnel.Address,
   678  						target:  tunnel.Target,
   679  						proxy:   tunnel.Proxy,
   680  					}
   681  				},
   682  			)
   683  		},
   684  	)
   685  
   686  	needClose, needCreate := lo.Difference(oldElm, newElm)
   687  
   688  	for _, elm := range needClose {
   689  		key := fmt.Sprintf("%s/%s/%s", elm.addr, elm.target, elm.proxy)
   690  		if elm.network == "tcp" {
   691  			tunnelTCPListeners[key].Close()
   692  			delete(tunnelTCPListeners, key)
   693  		} else {
   694  			tunnelUDPListeners[key].Close()
   695  			delete(tunnelUDPListeners, key)
   696  		}
   697  	}
   698  
   699  	for _, elm := range needCreate {
   700  		key := fmt.Sprintf("%s/%s/%s", elm.addr, elm.target, elm.proxy)
   701  		if elm.network == "tcp" {
   702  			l, err := LT.New(elm.addr, elm.target, elm.proxy, tunnel)
   703  			if err != nil {
   704  				log.Errorln("Start tunnel %s error: %s", elm.target, err.Error())
   705  				continue
   706  			}
   707  			tunnelTCPListeners[key] = l
   708  			log.Infoln("Tunnel(tcp/%s) proxy %s listening at: %s", elm.target, elm.proxy, tunnelTCPListeners[key].Address())
   709  		} else {
   710  			l, err := LT.NewUDP(elm.addr, elm.target, elm.proxy, tunnel)
   711  			if err != nil {
   712  				log.Errorln("Start tunnel %s error: %s", elm.target, err.Error())
   713  				continue
   714  			}
   715  			tunnelUDPListeners[key] = l
   716  			log.Infoln("Tunnel(udp/%s) proxy %s listening at: %s", elm.target, elm.proxy, tunnelUDPListeners[key].Address())
   717  		}
   718  	}
   719  }
   720  
   721  func PatchInboundListeners(newListenerMap map[string]C.InboundListener, tunnel C.Tunnel, dropOld bool) {
   722  	inboundMux.Lock()
   723  	defer inboundMux.Unlock()
   724  
   725  	for name, newListener := range newListenerMap {
   726  		if oldListener, ok := inboundListeners[name]; ok {
   727  			if !oldListener.Config().Equal(newListener.Config()) {
   728  				_ = oldListener.Close()
   729  			} else {
   730  				continue
   731  			}
   732  		}
   733  		if err := newListener.Listen(tunnel); err != nil {
   734  			log.Errorln("Listener %s listen err: %s", name, err.Error())
   735  			continue
   736  		}
   737  		inboundListeners[name] = newListener
   738  	}
   739  
   740  	if dropOld {
   741  		for name, oldListener := range inboundListeners {
   742  			if _, ok := newListenerMap[name]; !ok {
   743  				_ = oldListener.Close()
   744  				delete(inboundListeners, name)
   745  			}
   746  		}
   747  	}
   748  }
   749  
   750  // GetPorts return the ports of proxy servers
   751  func GetPorts() *Ports {
   752  	ports := &Ports{}
   753  
   754  	if httpListener != nil {
   755  		_, portStr, _ := net.SplitHostPort(httpListener.Address())
   756  		port, _ := strconv.Atoi(portStr)
   757  		ports.Port = port
   758  	}
   759  
   760  	if socksListener != nil {
   761  		_, portStr, _ := net.SplitHostPort(socksListener.Address())
   762  		port, _ := strconv.Atoi(portStr)
   763  		ports.SocksPort = port
   764  	}
   765  
   766  	if redirListener != nil {
   767  		_, portStr, _ := net.SplitHostPort(redirListener.Address())
   768  		port, _ := strconv.Atoi(portStr)
   769  		ports.RedirPort = port
   770  	}
   771  
   772  	if tproxyListener != nil {
   773  		_, portStr, _ := net.SplitHostPort(tproxyListener.Address())
   774  		port, _ := strconv.Atoi(portStr)
   775  		ports.TProxyPort = port
   776  	}
   777  
   778  	if mixedListener != nil {
   779  		_, portStr, _ := net.SplitHostPort(mixedListener.Address())
   780  		port, _ := strconv.Atoi(portStr)
   781  		ports.MixedPort = port
   782  	}
   783  
   784  	if shadowSocksListener != nil {
   785  		ports.ShadowSocksConfig = shadowSocksListener.Config()
   786  	}
   787  
   788  	if vmessListener != nil {
   789  		ports.VmessConfig = vmessListener.Config()
   790  	}
   791  
   792  	return ports
   793  }
   794  
   795  func portIsZero(addr string) bool {
   796  	_, port, err := net.SplitHostPort(addr)
   797  	if port == "0" || port == "" || err != nil {
   798  		return true
   799  	}
   800  	return false
   801  }
   802  
   803  func genAddr(host string, port int, allowLan bool) string {
   804  	if allowLan {
   805  		if host == "*" {
   806  			return fmt.Sprintf(":%d", port)
   807  		}
   808  		return fmt.Sprintf("%s:%d", host, port)
   809  	}
   810  
   811  	return fmt.Sprintf("127.0.0.1:%d", port)
   812  }
   813  
   814  func hasTunConfigChange(tunConf *LC.Tun) bool {
   815  	if LastTunConf.Enable != tunConf.Enable ||
   816  		LastTunConf.Device != tunConf.Device ||
   817  		LastTunConf.Stack != tunConf.Stack ||
   818  		LastTunConf.AutoRoute != tunConf.AutoRoute ||
   819  		LastTunConf.AutoDetectInterface != tunConf.AutoDetectInterface ||
   820  		LastTunConf.MTU != tunConf.MTU ||
   821  		LastTunConf.GSO != tunConf.GSO ||
   822  		LastTunConf.GSOMaxSize != tunConf.GSOMaxSize ||
   823  		LastTunConf.StrictRoute != tunConf.StrictRoute ||
   824  		LastTunConf.EndpointIndependentNat != tunConf.EndpointIndependentNat ||
   825  		LastTunConf.UDPTimeout != tunConf.UDPTimeout ||
   826  		LastTunConf.FileDescriptor != tunConf.FileDescriptor ||
   827  		LastTunConf.TableIndex != tunConf.TableIndex {
   828  		return true
   829  	}
   830  
   831  	if len(LastTunConf.DNSHijack) != len(tunConf.DNSHijack) {
   832  		return true
   833  	}
   834  
   835  	sort.Slice(tunConf.DNSHijack, func(i, j int) bool {
   836  		return tunConf.DNSHijack[i] < tunConf.DNSHijack[j]
   837  	})
   838  
   839  	sort.Slice(tunConf.Inet4Address, func(i, j int) bool {
   840  		return tunConf.Inet4Address[i].String() < tunConf.Inet4Address[j].String()
   841  	})
   842  
   843  	sort.Slice(tunConf.Inet6Address, func(i, j int) bool {
   844  		return tunConf.Inet6Address[i].String() < tunConf.Inet6Address[j].String()
   845  	})
   846  
   847  	sort.Slice(tunConf.Inet4RouteAddress, func(i, j int) bool {
   848  		return tunConf.Inet4RouteAddress[i].String() < tunConf.Inet4RouteAddress[j].String()
   849  	})
   850  
   851  	sort.Slice(tunConf.Inet6RouteAddress, func(i, j int) bool {
   852  		return tunConf.Inet6RouteAddress[i].String() < tunConf.Inet6RouteAddress[j].String()
   853  	})
   854  
   855  	sort.Slice(tunConf.Inet4RouteExcludeAddress, func(i, j int) bool {
   856  		return tunConf.Inet4RouteExcludeAddress[i].String() < tunConf.Inet4RouteExcludeAddress[j].String()
   857  	})
   858  
   859  	sort.Slice(tunConf.Inet6RouteExcludeAddress, func(i, j int) bool {
   860  		return tunConf.Inet6RouteExcludeAddress[i].String() < tunConf.Inet6RouteExcludeAddress[j].String()
   861  	})
   862  
   863  	sort.Slice(tunConf.IncludeInterface, func(i, j int) bool {
   864  		return tunConf.IncludeInterface[i] < tunConf.IncludeInterface[j]
   865  	})
   866  
   867  	sort.Slice(tunConf.ExcludeInterface, func(i, j int) bool {
   868  		return tunConf.ExcludeInterface[i] < tunConf.ExcludeInterface[j]
   869  	})
   870  
   871  	sort.Slice(tunConf.IncludeUID, func(i, j int) bool {
   872  		return tunConf.IncludeUID[i] < tunConf.IncludeUID[j]
   873  	})
   874  
   875  	sort.Slice(tunConf.IncludeUIDRange, func(i, j int) bool {
   876  		return tunConf.IncludeUIDRange[i] < tunConf.IncludeUIDRange[j]
   877  	})
   878  
   879  	sort.Slice(tunConf.ExcludeUID, func(i, j int) bool {
   880  		return tunConf.ExcludeUID[i] < tunConf.ExcludeUID[j]
   881  	})
   882  
   883  	sort.Slice(tunConf.ExcludeUIDRange, func(i, j int) bool {
   884  		return tunConf.ExcludeUIDRange[i] < tunConf.ExcludeUIDRange[j]
   885  	})
   886  
   887  	sort.Slice(tunConf.IncludeAndroidUser, func(i, j int) bool {
   888  		return tunConf.IncludeAndroidUser[i] < tunConf.IncludeAndroidUser[j]
   889  	})
   890  
   891  	sort.Slice(tunConf.IncludePackage, func(i, j int) bool {
   892  		return tunConf.IncludePackage[i] < tunConf.IncludePackage[j]
   893  	})
   894  
   895  	sort.Slice(tunConf.ExcludePackage, func(i, j int) bool {
   896  		return tunConf.ExcludePackage[i] < tunConf.ExcludePackage[j]
   897  	})
   898  
   899  	if !slices.Equal(tunConf.DNSHijack, LastTunConf.DNSHijack) ||
   900  		!slices.Equal(tunConf.Inet4Address, LastTunConf.Inet4Address) ||
   901  		!slices.Equal(tunConf.Inet6Address, LastTunConf.Inet6Address) ||
   902  		!slices.Equal(tunConf.Inet4RouteAddress, LastTunConf.Inet4RouteAddress) ||
   903  		!slices.Equal(tunConf.Inet6RouteAddress, LastTunConf.Inet6RouteAddress) ||
   904  		!slices.Equal(tunConf.Inet4RouteExcludeAddress, LastTunConf.Inet4RouteExcludeAddress) ||
   905  		!slices.Equal(tunConf.Inet6RouteExcludeAddress, LastTunConf.Inet6RouteExcludeAddress) ||
   906  		!slices.Equal(tunConf.IncludeInterface, LastTunConf.IncludeInterface) ||
   907  		!slices.Equal(tunConf.ExcludeInterface, LastTunConf.ExcludeInterface) ||
   908  		!slices.Equal(tunConf.IncludeUID, LastTunConf.IncludeUID) ||
   909  		!slices.Equal(tunConf.IncludeUIDRange, LastTunConf.IncludeUIDRange) ||
   910  		!slices.Equal(tunConf.ExcludeUID, LastTunConf.ExcludeUID) ||
   911  		!slices.Equal(tunConf.ExcludeUIDRange, LastTunConf.ExcludeUIDRange) ||
   912  		!slices.Equal(tunConf.IncludeAndroidUser, LastTunConf.IncludeAndroidUser) ||
   913  		!slices.Equal(tunConf.IncludePackage, LastTunConf.IncludePackage) ||
   914  		!slices.Equal(tunConf.ExcludePackage, LastTunConf.ExcludePackage) {
   915  		return true
   916  	}
   917  
   918  	return false
   919  }
   920  
   921  func closeTunListener() {
   922  	if tunLister != nil {
   923  		tunLister.Close()
   924  		tunLister = nil
   925  	}
   926  }
   927  
   928  func Cleanup() {
   929  	closeTunListener()
   930  }