tun.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447
  1. package inbound
  2. import (
  3. "context"
  4. "net"
  5. "net/netip"
  6. "os"
  7. "runtime"
  8. "strconv"
  9. "strings"
  10. "time"
  11. "github.com/sagernet/sing-box/adapter"
  12. "github.com/sagernet/sing-box/common/taskmonitor"
  13. C "github.com/sagernet/sing-box/constant"
  14. "github.com/sagernet/sing-box/experimental/deprecated"
  15. "github.com/sagernet/sing-box/experimental/libbox/platform"
  16. "github.com/sagernet/sing-box/log"
  17. "github.com/sagernet/sing-box/option"
  18. "github.com/sagernet/sing-tun"
  19. "github.com/sagernet/sing/common"
  20. E "github.com/sagernet/sing/common/exceptions"
  21. M "github.com/sagernet/sing/common/metadata"
  22. N "github.com/sagernet/sing/common/network"
  23. "github.com/sagernet/sing/common/ranges"
  24. "github.com/sagernet/sing/common/x/list"
  25. "go4.org/netipx"
  26. )
  27. var _ adapter.Inbound = (*Tun)(nil)
  28. type Tun struct {
  29. tag string
  30. ctx context.Context
  31. router adapter.Router
  32. logger log.ContextLogger
  33. inboundOptions option.InboundOptions
  34. tunOptions tun.Options
  35. endpointIndependentNat bool
  36. udpTimeout int64
  37. stack string
  38. tunIf tun.Tun
  39. tunStack tun.Stack
  40. platformInterface platform.Interface
  41. platformOptions option.TunPlatformOptions
  42. autoRedirect tun.AutoRedirect
  43. routeRuleSet []adapter.RuleSet
  44. routeRuleSetCallback []*list.Element[adapter.RuleSetUpdateCallback]
  45. routeExcludeRuleSet []adapter.RuleSet
  46. routeExcludeRuleSetCallback []*list.Element[adapter.RuleSetUpdateCallback]
  47. routeAddressSet []*netipx.IPSet
  48. routeExcludeAddressSet []*netipx.IPSet
  49. }
  50. func NewTun(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.TunInboundOptions, platformInterface platform.Interface) (*Tun, error) {
  51. address := options.Address
  52. var deprecatedAddressUsed bool
  53. //nolint:staticcheck
  54. //goland:noinspection GoDeprecation
  55. if len(options.Inet4Address) > 0 {
  56. address = append(address, options.Inet4Address...)
  57. deprecatedAddressUsed = true
  58. }
  59. //nolint:staticcheck
  60. //goland:noinspection GoDeprecation
  61. if len(options.Inet6Address) > 0 {
  62. address = append(address, options.Inet6Address...)
  63. deprecatedAddressUsed = true
  64. }
  65. inet4Address := common.Filter(address, func(it netip.Prefix) bool {
  66. return it.Addr().Is4()
  67. })
  68. inet6Address := common.Filter(address, func(it netip.Prefix) bool {
  69. return it.Addr().Is6()
  70. })
  71. routeAddress := options.RouteAddress
  72. //nolint:staticcheck
  73. //goland:noinspection GoDeprecation
  74. if len(options.Inet4RouteAddress) > 0 {
  75. routeAddress = append(routeAddress, options.Inet4RouteAddress...)
  76. deprecatedAddressUsed = true
  77. }
  78. //nolint:staticcheck
  79. //goland:noinspection GoDeprecation
  80. if len(options.Inet6RouteAddress) > 0 {
  81. routeAddress = append(routeAddress, options.Inet6RouteAddress...)
  82. deprecatedAddressUsed = true
  83. }
  84. inet4RouteAddress := common.Filter(routeAddress, func(it netip.Prefix) bool {
  85. return it.Addr().Is4()
  86. })
  87. inet6RouteAddress := common.Filter(routeAddress, func(it netip.Prefix) bool {
  88. return it.Addr().Is6()
  89. })
  90. routeExcludeAddress := options.RouteExcludeAddress
  91. //nolint:staticcheck
  92. //goland:noinspection GoDeprecation
  93. if len(options.Inet4RouteExcludeAddress) > 0 {
  94. routeExcludeAddress = append(routeExcludeAddress, options.Inet4RouteExcludeAddress...)
  95. deprecatedAddressUsed = true
  96. }
  97. //nolint:staticcheck
  98. //goland:noinspection GoDeprecation
  99. if len(options.Inet6RouteExcludeAddress) > 0 {
  100. routeExcludeAddress = append(routeExcludeAddress, options.Inet6RouteExcludeAddress...)
  101. deprecatedAddressUsed = true
  102. }
  103. inet4RouteExcludeAddress := common.Filter(routeExcludeAddress, func(it netip.Prefix) bool {
  104. return it.Addr().Is4()
  105. })
  106. inet6RouteExcludeAddress := common.Filter(routeExcludeAddress, func(it netip.Prefix) bool {
  107. return it.Addr().Is6()
  108. })
  109. if deprecatedAddressUsed {
  110. deprecated.Report(ctx, deprecated.OptionTUNAddressX)
  111. }
  112. tunMTU := options.MTU
  113. if tunMTU == 0 {
  114. tunMTU = 9000
  115. }
  116. var udpTimeout time.Duration
  117. if options.UDPTimeout != 0 {
  118. udpTimeout = time.Duration(options.UDPTimeout)
  119. } else {
  120. udpTimeout = C.UDPTimeout
  121. }
  122. var err error
  123. includeUID := uidToRange(options.IncludeUID)
  124. if len(options.IncludeUIDRange) > 0 {
  125. includeUID, err = parseRange(includeUID, options.IncludeUIDRange)
  126. if err != nil {
  127. return nil, E.Cause(err, "parse include_uid_range")
  128. }
  129. }
  130. excludeUID := uidToRange(options.ExcludeUID)
  131. if len(options.ExcludeUIDRange) > 0 {
  132. excludeUID, err = parseRange(excludeUID, options.ExcludeUIDRange)
  133. if err != nil {
  134. return nil, E.Cause(err, "parse exclude_uid_range")
  135. }
  136. }
  137. tableIndex := options.IPRoute2TableIndex
  138. if tableIndex == 0 {
  139. tableIndex = tun.DefaultIPRoute2TableIndex
  140. }
  141. ruleIndex := options.IPRoute2RuleIndex
  142. if ruleIndex == 0 {
  143. ruleIndex = tun.DefaultIPRoute2RuleIndex
  144. }
  145. inputMark := uint32(options.AutoRedirectInputMark)
  146. if inputMark == 0 {
  147. inputMark = tun.DefaultAutoRedirectInputMark
  148. }
  149. outputMark := uint32(options.AutoRedirectOutputMark)
  150. if outputMark == 0 {
  151. outputMark = tun.DefaultAutoRedirectOutputMark
  152. }
  153. inbound := &Tun{
  154. tag: tag,
  155. ctx: ctx,
  156. router: router,
  157. logger: logger,
  158. inboundOptions: options.InboundOptions,
  159. tunOptions: tun.Options{
  160. Name: options.InterfaceName,
  161. MTU: tunMTU,
  162. GSO: options.GSO,
  163. Inet4Address: inet4Address,
  164. Inet6Address: inet6Address,
  165. AutoRoute: options.AutoRoute,
  166. IPRoute2TableIndex: tableIndex,
  167. IPRoute2RuleIndex: ruleIndex,
  168. AutoRedirectInputMark: inputMark,
  169. AutoRedirectOutputMark: outputMark,
  170. StrictRoute: options.StrictRoute,
  171. IncludeInterface: options.IncludeInterface,
  172. ExcludeInterface: options.ExcludeInterface,
  173. Inet4RouteAddress: inet4RouteAddress,
  174. Inet6RouteAddress: inet6RouteAddress,
  175. Inet4RouteExcludeAddress: inet4RouteExcludeAddress,
  176. Inet6RouteExcludeAddress: inet6RouteExcludeAddress,
  177. IncludeUID: includeUID,
  178. ExcludeUID: excludeUID,
  179. IncludeAndroidUser: options.IncludeAndroidUser,
  180. IncludePackage: options.IncludePackage,
  181. ExcludePackage: options.ExcludePackage,
  182. InterfaceMonitor: router.InterfaceMonitor(),
  183. },
  184. endpointIndependentNat: options.EndpointIndependentNat,
  185. udpTimeout: int64(udpTimeout.Seconds()),
  186. stack: options.Stack,
  187. platformInterface: platformInterface,
  188. platformOptions: common.PtrValueOrDefault(options.Platform),
  189. }
  190. if options.AutoRedirect {
  191. if !options.AutoRoute {
  192. return nil, E.New("`auto_route` is required by `auto_redirect`")
  193. }
  194. disableNFTables, dErr := strconv.ParseBool(os.Getenv("DISABLE_NFTABLES"))
  195. inbound.autoRedirect, err = tun.NewAutoRedirect(tun.AutoRedirectOptions{
  196. TunOptions: &inbound.tunOptions,
  197. Context: ctx,
  198. Handler: inbound,
  199. Logger: logger,
  200. NetworkMonitor: router.NetworkMonitor(),
  201. InterfaceFinder: router.InterfaceFinder(),
  202. TableName: "sing-box",
  203. DisableNFTables: dErr == nil && disableNFTables,
  204. RouteAddressSet: &inbound.routeAddressSet,
  205. RouteExcludeAddressSet: &inbound.routeExcludeAddressSet,
  206. })
  207. if err != nil {
  208. return nil, E.Cause(err, "initialize auto-redirect")
  209. }
  210. if runtime.GOOS != "android" {
  211. var markMode bool
  212. for _, routeAddressSet := range options.RouteAddressSet {
  213. ruleSet, loaded := router.RuleSet(routeAddressSet)
  214. if !loaded {
  215. return nil, E.New("parse route_address_set: rule-set not found: ", routeAddressSet)
  216. }
  217. ruleSet.IncRef()
  218. inbound.routeRuleSet = append(inbound.routeRuleSet, ruleSet)
  219. markMode = true
  220. }
  221. for _, routeExcludeAddressSet := range options.RouteExcludeAddressSet {
  222. ruleSet, loaded := router.RuleSet(routeExcludeAddressSet)
  223. if !loaded {
  224. return nil, E.New("parse route_exclude_address_set: rule-set not found: ", routeExcludeAddressSet)
  225. }
  226. ruleSet.IncRef()
  227. inbound.routeExcludeRuleSet = append(inbound.routeExcludeRuleSet, ruleSet)
  228. markMode = true
  229. }
  230. if markMode {
  231. inbound.tunOptions.AutoRedirectMarkMode = true
  232. err = router.RegisterAutoRedirectOutputMark(inbound.tunOptions.AutoRedirectOutputMark)
  233. if err != nil {
  234. return nil, err
  235. }
  236. }
  237. }
  238. }
  239. return inbound, nil
  240. }
  241. func uidToRange(uidList option.Listable[uint32]) []ranges.Range[uint32] {
  242. return common.Map(uidList, func(uid uint32) ranges.Range[uint32] {
  243. return ranges.NewSingle(uid)
  244. })
  245. }
  246. func parseRange(uidRanges []ranges.Range[uint32], rangeList []string) ([]ranges.Range[uint32], error) {
  247. for _, uidRange := range rangeList {
  248. if !strings.Contains(uidRange, ":") {
  249. return nil, E.New("missing ':' in range: ", uidRange)
  250. }
  251. subIndex := strings.Index(uidRange, ":")
  252. if subIndex == 0 {
  253. return nil, E.New("missing range start: ", uidRange)
  254. } else if subIndex == len(uidRange)-1 {
  255. return nil, E.New("missing range end: ", uidRange)
  256. }
  257. var start, end uint64
  258. var err error
  259. start, err = strconv.ParseUint(uidRange[:subIndex], 0, 32)
  260. if err != nil {
  261. return nil, E.Cause(err, "parse range start")
  262. }
  263. end, err = strconv.ParseUint(uidRange[subIndex+1:], 0, 32)
  264. if err != nil {
  265. return nil, E.Cause(err, "parse range end")
  266. }
  267. uidRanges = append(uidRanges, ranges.New(uint32(start), uint32(end)))
  268. }
  269. return uidRanges, nil
  270. }
  271. func (t *Tun) Type() string {
  272. return C.TypeTun
  273. }
  274. func (t *Tun) Tag() string {
  275. return t.tag
  276. }
  277. func (t *Tun) Start() error {
  278. if C.IsAndroid && t.platformInterface == nil {
  279. t.tunOptions.BuildAndroidRules(t.router.PackageManager(), t)
  280. }
  281. if t.tunOptions.Name == "" {
  282. t.tunOptions.Name = tun.CalculateInterfaceName("")
  283. }
  284. var (
  285. tunInterface tun.Tun
  286. err error
  287. )
  288. monitor := taskmonitor.New(t.logger, C.StartTimeout)
  289. monitor.Start("open tun interface")
  290. if t.platformInterface != nil {
  291. tunInterface, err = t.platformInterface.OpenTun(&t.tunOptions, t.platformOptions)
  292. } else {
  293. tunInterface, err = tun.New(t.tunOptions)
  294. }
  295. monitor.Finish()
  296. if err != nil {
  297. return E.Cause(err, "configure tun interface")
  298. }
  299. t.logger.Trace("creating stack")
  300. t.tunIf = tunInterface
  301. var (
  302. forwarderBindInterface bool
  303. includeAllNetworks bool
  304. )
  305. if t.platformInterface != nil {
  306. forwarderBindInterface = true
  307. includeAllNetworks = t.platformInterface.IncludeAllNetworks()
  308. }
  309. tunStack, err := tun.NewStack(t.stack, tun.StackOptions{
  310. Context: t.ctx,
  311. Tun: tunInterface,
  312. TunOptions: t.tunOptions,
  313. EndpointIndependentNat: t.endpointIndependentNat,
  314. UDPTimeout: t.udpTimeout,
  315. Handler: t,
  316. Logger: t.logger,
  317. ForwarderBindInterface: forwarderBindInterface,
  318. InterfaceFinder: t.router.InterfaceFinder(),
  319. IncludeAllNetworks: includeAllNetworks,
  320. })
  321. if err != nil {
  322. return err
  323. }
  324. monitor.Start("initiating tun stack")
  325. err = tunStack.Start()
  326. monitor.Finish()
  327. t.tunStack = tunStack
  328. if err != nil {
  329. return err
  330. }
  331. t.logger.Info("started at ", t.tunOptions.Name)
  332. return nil
  333. }
  334. func (t *Tun) PostStart() error {
  335. monitor := taskmonitor.New(t.logger, C.StartTimeout)
  336. if t.autoRedirect != nil {
  337. t.routeAddressSet = common.FlatMap(t.routeRuleSet, adapter.RuleSet.ExtractIPSet)
  338. for _, routeRuleSet := range t.routeRuleSet {
  339. ipSets := routeRuleSet.ExtractIPSet()
  340. if len(ipSets) == 0 {
  341. t.logger.Warn("route_address_set: no destination IP CIDR rules found in rule-set: ", routeRuleSet.Name())
  342. }
  343. t.routeAddressSet = append(t.routeAddressSet, ipSets...)
  344. }
  345. t.routeExcludeAddressSet = common.FlatMap(t.routeExcludeRuleSet, adapter.RuleSet.ExtractIPSet)
  346. for _, routeExcludeRuleSet := range t.routeExcludeRuleSet {
  347. ipSets := routeExcludeRuleSet.ExtractIPSet()
  348. if len(ipSets) == 0 {
  349. t.logger.Warn("route_address_set: no destination IP CIDR rules found in rule-set: ", routeExcludeRuleSet.Name())
  350. }
  351. t.routeExcludeAddressSet = append(t.routeExcludeAddressSet, ipSets...)
  352. }
  353. monitor.Start("initialize auto-redirect")
  354. err := t.autoRedirect.Start()
  355. monitor.Finish()
  356. if err != nil {
  357. return E.Cause(err, "auto-redirect")
  358. }
  359. for _, routeRuleSet := range t.routeRuleSet {
  360. t.routeRuleSetCallback = append(t.routeRuleSetCallback, routeRuleSet.RegisterCallback(t.updateRouteAddressSet))
  361. routeRuleSet.DecRef()
  362. }
  363. for _, routeExcludeRuleSet := range t.routeExcludeRuleSet {
  364. t.routeExcludeRuleSetCallback = append(t.routeExcludeRuleSetCallback, routeExcludeRuleSet.RegisterCallback(t.updateRouteAddressSet))
  365. routeExcludeRuleSet.DecRef()
  366. }
  367. t.routeAddressSet = nil
  368. t.routeExcludeAddressSet = nil
  369. }
  370. return nil
  371. }
  372. func (t *Tun) updateRouteAddressSet(it adapter.RuleSet) {
  373. t.routeAddressSet = common.FlatMap(t.routeRuleSet, adapter.RuleSet.ExtractIPSet)
  374. t.routeExcludeAddressSet = common.FlatMap(t.routeExcludeRuleSet, adapter.RuleSet.ExtractIPSet)
  375. t.autoRedirect.UpdateRouteAddressSet()
  376. t.routeAddressSet = nil
  377. t.routeExcludeAddressSet = nil
  378. }
  379. func (t *Tun) Close() error {
  380. return common.Close(
  381. t.tunStack,
  382. t.tunIf,
  383. t.autoRedirect,
  384. )
  385. }
  386. func (t *Tun) NewConnection(ctx context.Context, conn net.Conn, upstreamMetadata M.Metadata) error {
  387. ctx = log.ContextWithNewID(ctx)
  388. var metadata adapter.InboundContext
  389. metadata.Inbound = t.tag
  390. metadata.InboundType = C.TypeTun
  391. metadata.Source = upstreamMetadata.Source
  392. metadata.Destination = upstreamMetadata.Destination
  393. metadata.InboundOptions = t.inboundOptions
  394. if upstreamMetadata.Protocol != "" {
  395. t.logger.InfoContext(ctx, "inbound ", upstreamMetadata.Protocol, " connection from ", metadata.Source)
  396. } else {
  397. t.logger.InfoContext(ctx, "inbound connection from ", metadata.Source)
  398. }
  399. t.logger.InfoContext(ctx, "inbound connection to ", metadata.Destination)
  400. err := t.router.RouteConnection(ctx, conn, metadata)
  401. if err != nil {
  402. t.NewError(ctx, err)
  403. }
  404. return nil
  405. }
  406. func (t *Tun) NewPacketConnection(ctx context.Context, conn N.PacketConn, upstreamMetadata M.Metadata) error {
  407. ctx = log.ContextWithNewID(ctx)
  408. var metadata adapter.InboundContext
  409. metadata.Inbound = t.tag
  410. metadata.InboundType = C.TypeTun
  411. metadata.Source = upstreamMetadata.Source
  412. metadata.Destination = upstreamMetadata.Destination
  413. metadata.InboundOptions = t.inboundOptions
  414. t.logger.InfoContext(ctx, "inbound packet connection from ", metadata.Source)
  415. t.logger.InfoContext(ctx, "inbound packet connection to ", metadata.Destination)
  416. err := t.router.RoutePacketConnection(ctx, conn, metadata)
  417. if err != nil {
  418. t.NewError(ctx, err)
  419. }
  420. return nil
  421. }
  422. func (t *Tun) NewError(ctx context.Context, err error) {
  423. NewError(t.logger, ctx, err)
  424. }