github.com/sagernet/sing-box@v1.2.7/inbound/tun.go (about) 1 package inbound 2 3 import ( 4 "context" 5 "net" 6 "strconv" 7 "strings" 8 9 "github.com/sagernet/sing-box/adapter" 10 C "github.com/sagernet/sing-box/constant" 11 "github.com/sagernet/sing-box/experimental/libbox/platform" 12 "github.com/sagernet/sing-box/log" 13 "github.com/sagernet/sing-box/option" 14 "github.com/sagernet/sing-tun" 15 "github.com/sagernet/sing/common" 16 E "github.com/sagernet/sing/common/exceptions" 17 M "github.com/sagernet/sing/common/metadata" 18 N "github.com/sagernet/sing/common/network" 19 "github.com/sagernet/sing/common/ranges" 20 ) 21 22 var _ adapter.Inbound = (*Tun)(nil) 23 24 type Tun struct { 25 tag string 26 ctx context.Context 27 router adapter.Router 28 logger log.ContextLogger 29 inboundOptions option.InboundOptions 30 tunOptions tun.Options 31 endpointIndependentNat bool 32 udpTimeout int64 33 stack string 34 tunIf tun.Tun 35 tunStack tun.Stack 36 platformInterface platform.Interface 37 platformOptions option.TunPlatformOptions 38 } 39 40 func NewTun(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.TunInboundOptions, platformInterface platform.Interface) (*Tun, error) { 41 tunName := options.InterfaceName 42 if tunName == "" { 43 tunName = tun.CalculateInterfaceName("") 44 } 45 tunMTU := options.MTU 46 if tunMTU == 0 { 47 tunMTU = 9000 48 } 49 var udpTimeout int64 50 if options.UDPTimeout != 0 { 51 udpTimeout = options.UDPTimeout 52 } else { 53 udpTimeout = int64(C.UDPTimeout.Seconds()) 54 } 55 includeUID := uidToRange(options.IncludeUID) 56 if len(options.IncludeUIDRange) > 0 { 57 var err error 58 includeUID, err = parseRange(includeUID, options.IncludeUIDRange) 59 if err != nil { 60 return nil, E.Cause(err, "parse include_uid_range") 61 } 62 } 63 excludeUID := uidToRange(options.ExcludeUID) 64 if len(options.ExcludeUIDRange) > 0 { 65 var err error 66 excludeUID, err = parseRange(excludeUID, options.ExcludeUIDRange) 67 if err != nil { 68 return nil, E.Cause(err, "parse exclude_uid_range") 69 } 70 } 71 return &Tun{ 72 tag: tag, 73 ctx: ctx, 74 router: router, 75 logger: logger, 76 inboundOptions: options.InboundOptions, 77 tunOptions: tun.Options{ 78 Name: tunName, 79 MTU: tunMTU, 80 Inet4Address: common.Map(options.Inet4Address, option.ListenPrefix.Build), 81 Inet6Address: common.Map(options.Inet6Address, option.ListenPrefix.Build), 82 AutoRoute: options.AutoRoute, 83 StrictRoute: options.StrictRoute, 84 Inet4RouteAddress: common.Map(options.Inet4RouteAddress, option.ListenPrefix.Build), 85 Inet6RouteAddress: common.Map(options.Inet6RouteAddress, option.ListenPrefix.Build), 86 IncludeUID: includeUID, 87 ExcludeUID: excludeUID, 88 IncludeAndroidUser: options.IncludeAndroidUser, 89 IncludePackage: options.IncludePackage, 90 ExcludePackage: options.ExcludePackage, 91 InterfaceMonitor: router.InterfaceMonitor(), 92 TableIndex: 2022, 93 }, 94 endpointIndependentNat: options.EndpointIndependentNat, 95 udpTimeout: udpTimeout, 96 stack: options.Stack, 97 platformInterface: platformInterface, 98 platformOptions: common.PtrValueOrDefault(options.Platform), 99 }, nil 100 } 101 102 func uidToRange(uidList option.Listable[uint32]) []ranges.Range[uint32] { 103 return common.Map(uidList, func(uid uint32) ranges.Range[uint32] { 104 return ranges.NewSingle(uid) 105 }) 106 } 107 108 func parseRange(uidRanges []ranges.Range[uint32], rangeList []string) ([]ranges.Range[uint32], error) { 109 for _, uidRange := range rangeList { 110 if !strings.Contains(uidRange, ":") { 111 return nil, E.New("missing ':' in range: ", uidRange) 112 } 113 subIndex := strings.Index(uidRange, ":") 114 if subIndex == 0 { 115 return nil, E.New("missing range start: ", uidRange) 116 } else if subIndex == len(uidRange)-1 { 117 return nil, E.New("missing range end: ", uidRange) 118 } 119 var start, end uint64 120 var err error 121 start, err = strconv.ParseUint(uidRange[:subIndex], 10, 32) 122 if err != nil { 123 return nil, E.Cause(err, "parse range start") 124 } 125 end, err = strconv.ParseUint(uidRange[subIndex+1:], 10, 32) 126 if err != nil { 127 return nil, E.Cause(err, "parse range end") 128 } 129 uidRanges = append(uidRanges, ranges.New(uint32(start), uint32(end))) 130 } 131 return uidRanges, nil 132 } 133 134 func (t *Tun) Type() string { 135 return C.TypeTun 136 } 137 138 func (t *Tun) Tag() string { 139 return t.tag 140 } 141 142 func (t *Tun) Start() error { 143 if C.IsAndroid && t.platformInterface == nil { 144 t.tunOptions.BuildAndroidRules(t.router.PackageManager(), t) 145 } 146 var ( 147 tunInterface tun.Tun 148 err error 149 ) 150 if t.platformInterface != nil { 151 tunInterface, err = t.platformInterface.OpenTun(&t.tunOptions, t.platformOptions) 152 } else { 153 tunInterface, err = tun.New(t.tunOptions) 154 } 155 if err != nil { 156 return E.Cause(err, "configure tun interface") 157 } 158 t.tunIf = tunInterface 159 t.tunStack, err = tun.NewStack(t.stack, tun.StackOptions{ 160 Context: t.ctx, 161 Tun: tunInterface, 162 MTU: t.tunOptions.MTU, 163 Name: t.tunOptions.Name, 164 Inet4Address: t.tunOptions.Inet4Address, 165 Inet6Address: t.tunOptions.Inet6Address, 166 EndpointIndependentNat: t.endpointIndependentNat, 167 UDPTimeout: t.udpTimeout, 168 Handler: t, 169 Logger: t.logger, 170 ForwarderBindInterface: t.platformInterface != nil, 171 }) 172 if err != nil { 173 return err 174 } 175 err = t.tunStack.Start() 176 if err != nil { 177 return err 178 } 179 t.logger.Info("started at ", t.tunOptions.Name) 180 return nil 181 } 182 183 func (t *Tun) Close() error { 184 return common.Close( 185 t.tunStack, 186 t.tunIf, 187 ) 188 } 189 190 func (t *Tun) NewConnection(ctx context.Context, conn net.Conn, upstreamMetadata M.Metadata) error { 191 ctx = log.ContextWithNewID(ctx) 192 var metadata adapter.InboundContext 193 metadata.Inbound = t.tag 194 metadata.InboundType = C.TypeTun 195 metadata.Source = upstreamMetadata.Source 196 metadata.Destination = upstreamMetadata.Destination 197 metadata.InboundOptions = t.inboundOptions 198 t.logger.InfoContext(ctx, "inbound connection from ", metadata.Source) 199 t.logger.InfoContext(ctx, "inbound connection to ", metadata.Destination) 200 err := t.router.RouteConnection(ctx, conn, metadata) 201 if err != nil { 202 t.NewError(ctx, err) 203 } 204 return nil 205 } 206 207 func (t *Tun) NewPacketConnection(ctx context.Context, conn N.PacketConn, upstreamMetadata M.Metadata) error { 208 ctx = log.ContextWithNewID(ctx) 209 var metadata adapter.InboundContext 210 metadata.Inbound = t.tag 211 metadata.InboundType = C.TypeTun 212 metadata.Source = upstreamMetadata.Source 213 metadata.Destination = upstreamMetadata.Destination 214 metadata.InboundOptions = t.inboundOptions 215 t.logger.InfoContext(ctx, "inbound packet connection from ", metadata.Source) 216 t.logger.InfoContext(ctx, "inbound packet connection to ", metadata.Destination) 217 err := t.router.RoutePacketConnection(ctx, conn, metadata) 218 if err != nil { 219 t.NewError(ctx, err) 220 } 221 return nil 222 } 223 224 func (t *Tun) NewError(ctx context.Context, err error) { 225 NewError(t.logger, ctx, err) 226 }