github.com/MerlinKodo/sing-tun@v0.1.15/tun_rules.go (about)

     1  package tun
     2  
     3  import (
     4  	"context"
     5  	"net/netip"
     6  	"os"
     7  	"runtime"
     8  	"sort"
     9  	"strconv"
    10  
    11  	"github.com/sagernet/sing/common"
    12  	E "github.com/sagernet/sing/common/exceptions"
    13  	"github.com/sagernet/sing/common/ranges"
    14  
    15  	"go4.org/netipx"
    16  )
    17  
    18  const (
    19  	androidUserRange        = 100000
    20  	userEnd          uint32 = 0xFFFFFFFF - 1
    21  )
    22  
    23  func (o *Options) BuildAndroidRules(packageManager PackageManager, errorHandler E.Handler) {
    24  	var includeUser []uint32
    25  	if len(o.IncludeAndroidUser) > 0 {
    26  		o.IncludeAndroidUser = common.Uniq(o.IncludeAndroidUser)
    27  		sort.Ints(o.IncludeAndroidUser)
    28  		var userExcludeRange []ranges.Range[uint32]
    29  		for _, androidUser := range o.IncludeAndroidUser {
    30  			includeUser = append(includeUser, uint32(androidUser))
    31  			userExcludeRange = append(userExcludeRange, ranges.New[uint32](uint32(androidUser)*androidUserRange, uint32(androidUser+1)*androidUserRange-1))
    32  		}
    33  		userExcludeRange = ranges.Revert(0, userEnd, userExcludeRange)
    34  		o.ExcludeUID = append(o.ExcludeUID, userExcludeRange...)
    35  	}
    36  	if len(includeUser) == 0 {
    37  		userDirs, err := os.ReadDir("/data/user")
    38  		if err == nil {
    39  			var userId uint64
    40  			for _, userDir := range userDirs {
    41  				userId, err = strconv.ParseUint(userDir.Name(), 10, 32)
    42  				if err != nil {
    43  					continue
    44  				}
    45  				includeUser = append(includeUser, uint32(userId))
    46  			}
    47  		}
    48  	}
    49  	if len(includeUser) == 0 {
    50  		includeUser = []uint32{0}
    51  	}
    52  	if len(o.IncludePackage) > 0 {
    53  		o.IncludePackage = common.Uniq(o.IncludePackage)
    54  		for _, packageName := range o.IncludePackage {
    55  			if sharedId, loaded := packageManager.IDBySharedPackage(packageName); loaded {
    56  				for _, androidUser := range includeUser {
    57  					o.IncludeUID = append(o.IncludeUID, ranges.NewSingle(sharedId+androidUser*androidUserRange))
    58  				}
    59  				continue
    60  			}
    61  			if userId, loaded := packageManager.IDByPackage(packageName); loaded {
    62  				for _, androidUser := range includeUser {
    63  					o.IncludeUID = append(o.IncludeUID, ranges.NewSingle(userId+androidUser*androidUserRange))
    64  				}
    65  				continue
    66  			}
    67  			errorHandler.NewError(context.Background(), E.New("package to include not found: ", packageName))
    68  		}
    69  	}
    70  	if len(o.ExcludePackage) > 0 {
    71  		o.ExcludePackage = common.Uniq(o.ExcludePackage)
    72  		for _, packageName := range o.ExcludePackage {
    73  			if sharedId, loaded := packageManager.IDBySharedPackage(packageName); loaded {
    74  				for _, androidUser := range includeUser {
    75  					o.ExcludeUID = append(o.ExcludeUID, ranges.NewSingle(sharedId+androidUser*androidUserRange))
    76  				}
    77  			}
    78  			if userId, loaded := packageManager.IDByPackage(packageName); loaded {
    79  				for _, androidUser := range includeUser {
    80  					o.ExcludeUID = append(o.ExcludeUID, ranges.NewSingle(userId+androidUser*androidUserRange))
    81  				}
    82  				continue
    83  			}
    84  			errorHandler.NewError(context.Background(), E.New("package to exclude not found: ", packageName))
    85  		}
    86  	}
    87  }
    88  
    89  func (o *Options) ExcludedRanges() (uidRanges []ranges.Range[uint32]) {
    90  	return buildExcludedRanges(o.IncludeUID, o.ExcludeUID)
    91  }
    92  
    93  func buildExcludedRanges(includeRanges []ranges.Range[uint32], excludeRanges []ranges.Range[uint32]) (uidRanges []ranges.Range[uint32]) {
    94  	uidRanges = includeRanges
    95  	if len(uidRanges) > 0 {
    96  		uidRanges = ranges.Exclude(uidRanges, excludeRanges)
    97  		uidRanges = ranges.Revert(0, userEnd, uidRanges)
    98  	} else {
    99  		uidRanges = excludeRanges
   100  	}
   101  	return ranges.Merge(uidRanges)
   102  }
   103  
   104  const autoRouteUseSubRanges = runtime.GOOS == "darwin"
   105  
   106  func (o *Options) BuildAutoRouteRanges() ([]netip.Prefix, error) {
   107  	var routeRanges []netip.Prefix
   108  	if len(o.Inet4Address) > 0 {
   109  		var inet4Ranges []netip.Prefix
   110  		if len(o.Inet4RouteAddress) > 0 {
   111  			inet4Ranges = o.Inet4RouteAddress
   112  		} else if autoRouteUseSubRanges {
   113  			inet4Ranges = []netip.Prefix{
   114  				netip.PrefixFrom(netip.AddrFrom4([4]byte{1, 0, 0, 0}), 8),
   115  				netip.PrefixFrom(netip.AddrFrom4([4]byte{2, 0, 0, 0}), 7),
   116  				netip.PrefixFrom(netip.AddrFrom4([4]byte{4, 0, 0, 0}), 6),
   117  				netip.PrefixFrom(netip.AddrFrom4([4]byte{8, 0, 0, 0}), 5),
   118  				netip.PrefixFrom(netip.AddrFrom4([4]byte{16, 0, 0, 0}), 4),
   119  				netip.PrefixFrom(netip.AddrFrom4([4]byte{32, 0, 0, 0}), 3),
   120  				netip.PrefixFrom(netip.AddrFrom4([4]byte{64, 0, 0, 0}), 2),
   121  				netip.PrefixFrom(netip.AddrFrom4([4]byte{128, 0, 0, 0}), 1),
   122  			}
   123  		} else {
   124  			inet4Ranges = []netip.Prefix{netip.PrefixFrom(netip.IPv4Unspecified(), 0)}
   125  		}
   126  		if len(o.Inet4RouteExcludeAddress) == 0 {
   127  			routeRanges = append(routeRanges, inet4Ranges...)
   128  		} else {
   129  			var builder netipx.IPSetBuilder
   130  			for _, inet4Range := range inet4Ranges {
   131  				builder.AddPrefix(inet4Range)
   132  			}
   133  			for _, prefix := range o.Inet4RouteExcludeAddress {
   134  				builder.RemovePrefix(prefix)
   135  			}
   136  			resultSet, err := builder.IPSet()
   137  			if err != nil {
   138  				return nil, E.Cause(err, "build IPv4 route address")
   139  			}
   140  			routeRanges = append(routeRanges, resultSet.Prefixes()...)
   141  		}
   142  	}
   143  	if len(o.Inet6Address) > 0 {
   144  		var inet6Ranges []netip.Prefix
   145  		if len(o.Inet6RouteAddress) > 0 {
   146  			inet6Ranges = o.Inet6RouteAddress
   147  		} else if autoRouteUseSubRanges {
   148  			inet6Ranges = []netip.Prefix{
   149  				netip.PrefixFrom(netip.IPv6Unspecified(), 1),
   150  				netip.PrefixFrom(netip.AddrFrom16([16]byte{0: 128}), 1),
   151  			}
   152  		} else {
   153  			inet6Ranges = []netip.Prefix{netip.PrefixFrom(netip.IPv6Unspecified(), 0)}
   154  		}
   155  		if len(o.Inet6RouteExcludeAddress) == 0 {
   156  			routeRanges = append(routeRanges, inet6Ranges...)
   157  		} else {
   158  			var builder netipx.IPSetBuilder
   159  			for _, inet6Range := range inet6Ranges {
   160  				builder.AddPrefix(inet6Range)
   161  			}
   162  			for _, prefix := range o.Inet6RouteExcludeAddress {
   163  				builder.RemovePrefix(prefix)
   164  			}
   165  			resultSet, err := builder.IPSet()
   166  			if err != nil {
   167  				return nil, E.Cause(err, "build IPv6 route address")
   168  			}
   169  			routeRanges = append(routeRanges, resultSet.Prefixes()...)
   170  		}
   171  	}
   172  	return routeRanges, nil
   173  }