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