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

     1  package sing_tun
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"net"
     7  	"net/netip"
     8  	"runtime"
     9  	"strconv"
    10  	"strings"
    11  
    12  	"github.com/metacubex/mihomo/adapter/inbound"
    13  	"github.com/metacubex/mihomo/component/dialer"
    14  	"github.com/metacubex/mihomo/component/iface"
    15  	"github.com/metacubex/mihomo/component/resolver"
    16  	C "github.com/metacubex/mihomo/constant"
    17  	LC "github.com/metacubex/mihomo/listener/config"
    18  	"github.com/metacubex/mihomo/listener/sing"
    19  	"github.com/metacubex/mihomo/log"
    20  
    21  	tun "github.com/metacubex/sing-tun"
    22  	"github.com/sagernet/sing/common"
    23  	"github.com/sagernet/sing/common/control"
    24  	E "github.com/sagernet/sing/common/exceptions"
    25  	F "github.com/sagernet/sing/common/format"
    26  	"github.com/sagernet/sing/common/ranges"
    27  )
    28  
    29  var InterfaceName = "Meta"
    30  var EnforceBindInterface = false
    31  
    32  type Listener struct {
    33  	closed  bool
    34  	options LC.Tun
    35  	handler *ListenerHandler
    36  	tunName string
    37  	addrStr string
    38  
    39  	tunIf    tun.Tun
    40  	tunStack tun.Stack
    41  
    42  	networkUpdateMonitor    tun.NetworkUpdateMonitor
    43  	defaultInterfaceMonitor tun.DefaultInterfaceMonitor
    44  	packageManager          tun.PackageManager
    45  
    46  	dnsServerIp []string
    47  }
    48  
    49  func CalculateInterfaceName(name string) (tunName string) {
    50  	if runtime.GOOS == "darwin" {
    51  		tunName = "utun"
    52  	} else if name != "" {
    53  		tunName = name
    54  		return
    55  	} else {
    56  		tunName = "tun"
    57  	}
    58  	interfaces, err := net.Interfaces()
    59  	if err != nil {
    60  		return
    61  	}
    62  	var tunIndex int
    63  	for _, netInterface := range interfaces {
    64  		if strings.HasPrefix(netInterface.Name, tunName) {
    65  			index, parseErr := strconv.ParseInt(netInterface.Name[len(tunName):], 10, 16)
    66  			if parseErr == nil {
    67  				tunIndex = int(index) + 1
    68  			}
    69  		}
    70  	}
    71  	tunName = F.ToString(tunName, tunIndex)
    72  	return
    73  }
    74  
    75  func checkTunName(tunName string) (ok bool) {
    76  	defer func() {
    77  		if !ok {
    78  			log.Warnln("[TUN] Unsupported tunName(%s) in %s, force regenerate by ourselves.", tunName, runtime.GOOS)
    79  		}
    80  	}()
    81  	if runtime.GOOS == "darwin" {
    82  		if len(tunName) <= 4 {
    83  			return false
    84  		}
    85  		if tunName[:4] != "utun" {
    86  			return false
    87  		}
    88  		if _, parseErr := strconv.ParseInt(tunName[4:], 10, 16); parseErr != nil {
    89  			return false
    90  		}
    91  	}
    92  	return true
    93  }
    94  
    95  func New(options LC.Tun, tunnel C.Tunnel, additions ...inbound.Addition) (l *Listener, err error) {
    96  	if len(additions) == 0 {
    97  		additions = []inbound.Addition{
    98  			inbound.WithInName("DEFAULT-TUN"),
    99  			inbound.WithSpecialRules(""),
   100  		}
   101  	}
   102  	if options.GSOMaxSize == 0 {
   103  		options.GSOMaxSize = 65536
   104  	}
   105  	tunName := options.Device
   106  	if tunName == "" || !checkTunName(tunName) {
   107  		tunName = CalculateInterfaceName(InterfaceName)
   108  		options.Device = tunName
   109  	}
   110  	tunMTU := options.MTU
   111  	if tunMTU == 0 {
   112  		tunMTU = 9000
   113  	}
   114  	var udpTimeout int64
   115  	if options.UDPTimeout != 0 {
   116  		udpTimeout = options.UDPTimeout
   117  	} else {
   118  		udpTimeout = int64(sing.UDPTimeout.Seconds())
   119  	}
   120  	tableIndex := options.TableIndex
   121  	if tableIndex == 0 {
   122  		tableIndex = 2022
   123  	}
   124  	includeUID := uidToRange(options.IncludeUID)
   125  	if len(options.IncludeUIDRange) > 0 {
   126  		var err error
   127  		includeUID, err = parseRange(includeUID, options.IncludeUIDRange)
   128  		if err != nil {
   129  			return nil, E.Cause(err, "parse include_uid_range")
   130  		}
   131  	}
   132  	excludeUID := uidToRange(options.ExcludeUID)
   133  	if len(options.ExcludeUIDRange) > 0 {
   134  		var err error
   135  		excludeUID, err = parseRange(excludeUID, options.ExcludeUIDRange)
   136  		if err != nil {
   137  			return nil, E.Cause(err, "parse exclude_uid_range")
   138  		}
   139  	}
   140  
   141  	var dnsAdds []netip.AddrPort
   142  
   143  	for _, d := range options.DNSHijack {
   144  		if _, after, ok := strings.Cut(d, "://"); ok {
   145  			d = after
   146  		}
   147  		d = strings.Replace(d, "any", "0.0.0.0", 1)
   148  		addrPort, err := netip.ParseAddrPort(d)
   149  		if err != nil {
   150  			return nil, fmt.Errorf("parse dns-hijack url error: %w", err)
   151  		}
   152  
   153  		dnsAdds = append(dnsAdds, addrPort)
   154  	}
   155  
   156  	var dnsServerIp []string
   157  	for _, a := range options.Inet4Address {
   158  		addrPort := netip.AddrPortFrom(a.Addr().Next(), 53)
   159  		dnsServerIp = append(dnsServerIp, a.Addr().Next().String())
   160  		dnsAdds = append(dnsAdds, addrPort)
   161  	}
   162  	for _, a := range options.Inet6Address {
   163  		addrPort := netip.AddrPortFrom(a.Addr().Next(), 53)
   164  		dnsServerIp = append(dnsServerIp, a.Addr().Next().String())
   165  		dnsAdds = append(dnsAdds, addrPort)
   166  	}
   167  
   168  	h, err := sing.NewListenerHandler(sing.ListenerConfig{
   169  		Tunnel:    tunnel,
   170  		Type:      C.TUN,
   171  		Additions: additions,
   172  	})
   173  	if err != nil {
   174  		return nil, err
   175  	}
   176  
   177  	handler := &ListenerHandler{
   178  		ListenerHandler: h,
   179  		DnsAdds:         dnsAdds,
   180  	}
   181  	l = &Listener{
   182  		closed:  false,
   183  		options: options,
   184  		handler: handler,
   185  		tunName: tunName,
   186  	}
   187  	defer func() {
   188  		if err != nil {
   189  			l.Close()
   190  			l = nil
   191  		}
   192  	}()
   193  
   194  	networkUpdateMonitor, err := tun.NewNetworkUpdateMonitor(log.SingLogger)
   195  	if err != nil {
   196  		err = E.Cause(err, "create NetworkUpdateMonitor")
   197  		return
   198  	}
   199  	l.networkUpdateMonitor = networkUpdateMonitor
   200  	err = networkUpdateMonitor.Start()
   201  	if err != nil {
   202  		err = E.Cause(err, "start NetworkUpdateMonitor")
   203  		return
   204  	}
   205  
   206  	defaultInterfaceMonitor, err := tun.NewDefaultInterfaceMonitor(networkUpdateMonitor, log.SingLogger, tun.DefaultInterfaceMonitorOptions{OverrideAndroidVPN: true})
   207  	if err != nil {
   208  		err = E.Cause(err, "create DefaultInterfaceMonitor")
   209  		return
   210  	}
   211  	l.defaultInterfaceMonitor = defaultInterfaceMonitor
   212  	defaultInterfaceMonitor.RegisterCallback(func(event int) {
   213  		l.FlushDefaultInterface()
   214  	})
   215  	err = defaultInterfaceMonitor.Start()
   216  	if err != nil {
   217  		err = E.Cause(err, "start DefaultInterfaceMonitor")
   218  		return
   219  	}
   220  
   221  	tunOptions := tun.Options{
   222  		Name:                     tunName,
   223  		MTU:                      tunMTU,
   224  		GSO:                      options.GSO,
   225  		Inet4Address:             options.Inet4Address,
   226  		Inet6Address:             options.Inet6Address,
   227  		AutoRoute:                options.AutoRoute,
   228  		StrictRoute:              options.StrictRoute,
   229  		Inet4RouteAddress:        options.Inet4RouteAddress,
   230  		Inet6RouteAddress:        options.Inet6RouteAddress,
   231  		Inet4RouteExcludeAddress: options.Inet4RouteExcludeAddress,
   232  		Inet6RouteExcludeAddress: options.Inet6RouteExcludeAddress,
   233  		IncludeInterface:         options.IncludeInterface,
   234  		ExcludeInterface:         options.ExcludeInterface,
   235  		IncludeUID:               includeUID,
   236  		ExcludeUID:               excludeUID,
   237  		IncludeAndroidUser:       options.IncludeAndroidUser,
   238  		IncludePackage:           options.IncludePackage,
   239  		ExcludePackage:           options.ExcludePackage,
   240  		FileDescriptor:           options.FileDescriptor,
   241  		InterfaceMonitor:         defaultInterfaceMonitor,
   242  		TableIndex:               tableIndex,
   243  	}
   244  
   245  	err = l.buildAndroidRules(&tunOptions)
   246  	if err != nil {
   247  		err = E.Cause(err, "build android rules")
   248  		return
   249  	}
   250  	tunIf, err := tunNew(tunOptions)
   251  	if err != nil {
   252  		err = E.Cause(err, "configure tun interface")
   253  		return
   254  	}
   255  
   256  	l.dnsServerIp = dnsServerIp
   257  	// after tun.New sing-tun has set DNS to TUN interface
   258  	resolver.AddSystemDnsBlacklist(dnsServerIp...)
   259  
   260  	stackOptions := tun.StackOptions{
   261  		Context:                context.TODO(),
   262  		Tun:                    tunIf,
   263  		TunOptions:             tunOptions,
   264  		EndpointIndependentNat: options.EndpointIndependentNat,
   265  		UDPTimeout:             udpTimeout,
   266  		Handler:                handler,
   267  		Logger:                 log.SingLogger,
   268  		InterfaceFinder:        control.DefaultInterfaceFinder(),
   269  		EnforceBindInterface:   EnforceBindInterface,
   270  	}
   271  
   272  	if options.FileDescriptor > 0 {
   273  		if tunName, err := getTunnelName(int32(options.FileDescriptor)); err != nil {
   274  			stackOptions.TunOptions.Name = tunName
   275  			stackOptions.ForwarderBindInterface = true
   276  		}
   277  	}
   278  	l.tunIf = tunIf
   279  
   280  	tunStack, err := tun.NewStack(strings.ToLower(options.Stack.String()), stackOptions)
   281  	if err != nil {
   282  		return
   283  	}
   284  
   285  	err = tunStack.Start()
   286  	if err != nil {
   287  		return
   288  	}
   289  	l.tunStack = tunStack
   290  
   291  	//l.openAndroidHotspot(tunOptions)
   292  
   293  	l.addrStr = fmt.Sprintf("%s(%s,%s), mtu: %d, auto route: %v, ip stack: %s",
   294  		tunName, tunOptions.Inet4Address, tunOptions.Inet6Address, tunMTU, options.AutoRoute, options.Stack)
   295  	return
   296  }
   297  
   298  func (l *Listener) FlushDefaultInterface() {
   299  	if l.options.AutoDetectInterface {
   300  		for _, destination := range []netip.Addr{netip.IPv4Unspecified(), netip.IPv6Unspecified(), netip.MustParseAddr("1.1.1.1")} {
   301  			autoDetectInterfaceName := l.defaultInterfaceMonitor.DefaultInterfaceName(destination)
   302  			if autoDetectInterfaceName == l.tunName {
   303  				log.Warnln("[TUN] Auto detect interface by %s get same name with tun", destination.String())
   304  			} else if autoDetectInterfaceName == "" || autoDetectInterfaceName == "<nil>" {
   305  				log.Warnln("[TUN] Auto detect interface by %s get empty name.", destination.String())
   306  			} else {
   307  				if old := dialer.DefaultInterface.Swap(autoDetectInterfaceName); old != autoDetectInterfaceName {
   308  					log.Warnln("[TUN] default interface changed by monitor, %s => %s", old, autoDetectInterfaceName)
   309  					iface.FlushCache()
   310  				}
   311  				return
   312  			}
   313  		}
   314  		if dialer.DefaultInterface.CompareAndSwap("", "<invalid>") {
   315  			log.Warnln("[TUN] Auto detect interface failed, set '<invalid>' to DefaultInterface to avoid lookback")
   316  		}
   317  	}
   318  }
   319  
   320  func uidToRange(uidList []uint32) []ranges.Range[uint32] {
   321  	return common.Map(uidList, func(uid uint32) ranges.Range[uint32] {
   322  		return ranges.NewSingle(uid)
   323  	})
   324  }
   325  
   326  func parseRange(uidRanges []ranges.Range[uint32], rangeList []string) ([]ranges.Range[uint32], error) {
   327  	for _, uidRange := range rangeList {
   328  		if !strings.Contains(uidRange, ":") {
   329  			return nil, E.New("missing ':' in range: ", uidRange)
   330  		}
   331  		subIndex := strings.Index(uidRange, ":")
   332  		if subIndex == 0 {
   333  			return nil, E.New("missing range start: ", uidRange)
   334  		} else if subIndex == len(uidRange)-1 {
   335  			return nil, E.New("missing range end: ", uidRange)
   336  		}
   337  		var start, end uint64
   338  		var err error
   339  		start, err = strconv.ParseUint(uidRange[:subIndex], 10, 32)
   340  		if err != nil {
   341  			return nil, E.Cause(err, "parse range start")
   342  		}
   343  		end, err = strconv.ParseUint(uidRange[subIndex+1:], 10, 32)
   344  		if err != nil {
   345  			return nil, E.Cause(err, "parse range end")
   346  		}
   347  		uidRanges = append(uidRanges, ranges.New(uint32(start), uint32(end)))
   348  	}
   349  	return uidRanges, nil
   350  }
   351  
   352  func (l *Listener) Close() error {
   353  	l.closed = true
   354  	resolver.RemoveSystemDnsBlacklist(l.dnsServerIp...)
   355  	return common.Close(
   356  		l.tunStack,
   357  		l.tunIf,
   358  		l.defaultInterfaceMonitor,
   359  		l.networkUpdateMonitor,
   360  		l.packageManager,
   361  	)
   362  }
   363  
   364  func (l *Listener) Config() LC.Tun {
   365  	return l.options
   366  }
   367  
   368  func (l *Listener) Address() string {
   369  	return l.addrStr
   370  }