tun.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457
  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. // Deprecated
  34. inboundOptions option.InboundOptions
  35. tunOptions tun.Options
  36. endpointIndependentNat bool
  37. udpTimeout time.Duration
  38. stack string
  39. tunIf tun.Tun
  40. tunStack tun.Stack
  41. platformInterface platform.Interface
  42. platformOptions option.TunPlatformOptions
  43. autoRedirect tun.AutoRedirect
  44. routeRuleSet []adapter.RuleSet
  45. routeRuleSetCallback []*list.Element[adapter.RuleSetUpdateCallback]
  46. routeExcludeRuleSet []adapter.RuleSet
  47. routeExcludeRuleSetCallback []*list.Element[adapter.RuleSetUpdateCallback]
  48. routeAddressSet []*netipx.IPSet
  49. routeExcludeAddressSet []*netipx.IPSet
  50. }
  51. func NewTun(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.TunInboundOptions, platformInterface platform.Interface) (*TUN, error) {
  52. address := options.Address
  53. var deprecatedAddressUsed bool
  54. //nolint:staticcheck
  55. //goland:noinspection GoDeprecation
  56. if len(options.Inet4Address) > 0 {
  57. address = append(address, options.Inet4Address...)
  58. deprecatedAddressUsed = true
  59. }
  60. //nolint:staticcheck
  61. //goland:noinspection GoDeprecation
  62. if len(options.Inet6Address) > 0 {
  63. address = append(address, options.Inet6Address...)
  64. deprecatedAddressUsed = true
  65. }
  66. inet4Address := common.Filter(address, func(it netip.Prefix) bool {
  67. return it.Addr().Is4()
  68. })
  69. inet6Address := common.Filter(address, func(it netip.Prefix) bool {
  70. return it.Addr().Is6()
  71. })
  72. routeAddress := options.RouteAddress
  73. //nolint:staticcheck
  74. //goland:noinspection GoDeprecation
  75. if len(options.Inet4RouteAddress) > 0 {
  76. routeAddress = append(routeAddress, options.Inet4RouteAddress...)
  77. deprecatedAddressUsed = true
  78. }
  79. //nolint:staticcheck
  80. //goland:noinspection GoDeprecation
  81. if len(options.Inet6RouteAddress) > 0 {
  82. routeAddress = append(routeAddress, options.Inet6RouteAddress...)
  83. deprecatedAddressUsed = true
  84. }
  85. inet4RouteAddress := common.Filter(routeAddress, func(it netip.Prefix) bool {
  86. return it.Addr().Is4()
  87. })
  88. inet6RouteAddress := common.Filter(routeAddress, func(it netip.Prefix) bool {
  89. return it.Addr().Is6()
  90. })
  91. routeExcludeAddress := options.RouteExcludeAddress
  92. //nolint:staticcheck
  93. //goland:noinspection GoDeprecation
  94. if len(options.Inet4RouteExcludeAddress) > 0 {
  95. routeExcludeAddress = append(routeExcludeAddress, options.Inet4RouteExcludeAddress...)
  96. deprecatedAddressUsed = true
  97. }
  98. //nolint:staticcheck
  99. //goland:noinspection GoDeprecation
  100. if len(options.Inet6RouteExcludeAddress) > 0 {
  101. routeExcludeAddress = append(routeExcludeAddress, options.Inet6RouteExcludeAddress...)
  102. deprecatedAddressUsed = true
  103. }
  104. inet4RouteExcludeAddress := common.Filter(routeExcludeAddress, func(it netip.Prefix) bool {
  105. return it.Addr().Is4()
  106. })
  107. inet6RouteExcludeAddress := common.Filter(routeExcludeAddress, func(it netip.Prefix) bool {
  108. return it.Addr().Is6()
  109. })
  110. if deprecatedAddressUsed {
  111. deprecated.Report(ctx, deprecated.OptionTUNAddressX)
  112. }
  113. tunMTU := options.MTU
  114. if tunMTU == 0 {
  115. tunMTU = 9000
  116. }
  117. var udpTimeout time.Duration
  118. if options.UDPTimeout != 0 {
  119. udpTimeout = time.Duration(options.UDPTimeout)
  120. } else {
  121. udpTimeout = C.UDPTimeout
  122. }
  123. var err error
  124. includeUID := uidToRange(options.IncludeUID)
  125. if len(options.IncludeUIDRange) > 0 {
  126. includeUID, err = parseRange(includeUID, options.IncludeUIDRange)
  127. if err != nil {
  128. return nil, E.Cause(err, "parse include_uid_range")
  129. }
  130. }
  131. excludeUID := uidToRange(options.ExcludeUID)
  132. if len(options.ExcludeUIDRange) > 0 {
  133. excludeUID, err = parseRange(excludeUID, options.ExcludeUIDRange)
  134. if err != nil {
  135. return nil, E.Cause(err, "parse exclude_uid_range")
  136. }
  137. }
  138. tableIndex := options.IPRoute2TableIndex
  139. if tableIndex == 0 {
  140. tableIndex = tun.DefaultIPRoute2TableIndex
  141. }
  142. ruleIndex := options.IPRoute2RuleIndex
  143. if ruleIndex == 0 {
  144. ruleIndex = tun.DefaultIPRoute2RuleIndex
  145. }
  146. inputMark := uint32(options.AutoRedirectInputMark)
  147. if inputMark == 0 {
  148. inputMark = tun.DefaultAutoRedirectInputMark
  149. }
  150. outputMark := uint32(options.AutoRedirectOutputMark)
  151. if outputMark == 0 {
  152. outputMark = tun.DefaultAutoRedirectOutputMark
  153. }
  154. inbound := &TUN{
  155. tag: tag,
  156. ctx: ctx,
  157. router: router,
  158. logger: logger,
  159. inboundOptions: options.InboundOptions,
  160. tunOptions: tun.Options{
  161. Name: options.InterfaceName,
  162. MTU: tunMTU,
  163. GSO: options.GSO,
  164. Inet4Address: inet4Address,
  165. Inet6Address: inet6Address,
  166. AutoRoute: options.AutoRoute,
  167. IPRoute2TableIndex: tableIndex,
  168. IPRoute2RuleIndex: ruleIndex,
  169. AutoRedirectInputMark: inputMark,
  170. AutoRedirectOutputMark: outputMark,
  171. StrictRoute: options.StrictRoute,
  172. IncludeInterface: options.IncludeInterface,
  173. ExcludeInterface: options.ExcludeInterface,
  174. Inet4RouteAddress: inet4RouteAddress,
  175. Inet6RouteAddress: inet6RouteAddress,
  176. Inet4RouteExcludeAddress: inet4RouteExcludeAddress,
  177. Inet6RouteExcludeAddress: inet6RouteExcludeAddress,
  178. IncludeUID: includeUID,
  179. ExcludeUID: excludeUID,
  180. IncludeAndroidUser: options.IncludeAndroidUser,
  181. IncludePackage: options.IncludePackage,
  182. ExcludePackage: options.ExcludePackage,
  183. InterfaceMonitor: router.InterfaceMonitor(),
  184. },
  185. endpointIndependentNat: options.EndpointIndependentNat,
  186. udpTimeout: udpTimeout,
  187. stack: options.Stack,
  188. platformInterface: platformInterface,
  189. platformOptions: common.PtrValueOrDefault(options.Platform),
  190. }
  191. if options.AutoRedirect {
  192. if !options.AutoRoute {
  193. return nil, E.New("`auto_route` is required by `auto_redirect`")
  194. }
  195. disableNFTables, dErr := strconv.ParseBool(os.Getenv("DISABLE_NFTABLES"))
  196. inbound.autoRedirect, err = tun.NewAutoRedirect(tun.AutoRedirectOptions{
  197. TunOptions: &inbound.tunOptions,
  198. Context: ctx,
  199. Handler: (*autoRedirectHandler)(inbound),
  200. Logger: logger,
  201. NetworkMonitor: router.NetworkMonitor(),
  202. InterfaceFinder: router.InterfaceFinder(),
  203. TableName: "sing-box",
  204. DisableNFTables: dErr == nil && disableNFTables,
  205. RouteAddressSet: &inbound.routeAddressSet,
  206. RouteExcludeAddressSet: &inbound.routeExcludeAddressSet,
  207. })
  208. if err != nil {
  209. return nil, E.Cause(err, "initialize auto-redirect")
  210. }
  211. if runtime.GOOS != "android" {
  212. var markMode bool
  213. for _, routeAddressSet := range options.RouteAddressSet {
  214. ruleSet, loaded := router.RuleSet(routeAddressSet)
  215. if !loaded {
  216. return nil, E.New("parse route_address_set: rule-set not found: ", routeAddressSet)
  217. }
  218. ruleSet.IncRef()
  219. inbound.routeRuleSet = append(inbound.routeRuleSet, ruleSet)
  220. markMode = true
  221. }
  222. for _, routeExcludeAddressSet := range options.RouteExcludeAddressSet {
  223. ruleSet, loaded := router.RuleSet(routeExcludeAddressSet)
  224. if !loaded {
  225. return nil, E.New("parse route_exclude_address_set: rule-set not found: ", routeExcludeAddressSet)
  226. }
  227. ruleSet.IncRef()
  228. inbound.routeExcludeRuleSet = append(inbound.routeExcludeRuleSet, ruleSet)
  229. markMode = true
  230. }
  231. if markMode {
  232. inbound.tunOptions.AutoRedirectMarkMode = true
  233. err = router.RegisterAutoRedirectOutputMark(inbound.tunOptions.AutoRedirectOutputMark)
  234. if err != nil {
  235. return nil, err
  236. }
  237. }
  238. }
  239. }
  240. return inbound, nil
  241. }
  242. func uidToRange(uidList option.Listable[uint32]) []ranges.Range[uint32] {
  243. return common.Map(uidList, func(uid uint32) ranges.Range[uint32] {
  244. return ranges.NewSingle(uid)
  245. })
  246. }
  247. func parseRange(uidRanges []ranges.Range[uint32], rangeList []string) ([]ranges.Range[uint32], error) {
  248. for _, uidRange := range rangeList {
  249. if !strings.Contains(uidRange, ":") {
  250. return nil, E.New("missing ':' in range: ", uidRange)
  251. }
  252. subIndex := strings.Index(uidRange, ":")
  253. if subIndex == 0 {
  254. return nil, E.New("missing range start: ", uidRange)
  255. } else if subIndex == len(uidRange)-1 {
  256. return nil, E.New("missing range end: ", uidRange)
  257. }
  258. var start, end uint64
  259. var err error
  260. start, err = strconv.ParseUint(uidRange[:subIndex], 0, 32)
  261. if err != nil {
  262. return nil, E.Cause(err, "parse range start")
  263. }
  264. end, err = strconv.ParseUint(uidRange[subIndex+1:], 0, 32)
  265. if err != nil {
  266. return nil, E.Cause(err, "parse range end")
  267. }
  268. uidRanges = append(uidRanges, ranges.New(uint32(start), uint32(end)))
  269. }
  270. return uidRanges, nil
  271. }
  272. func (t *TUN) Type() string {
  273. return C.TypeTun
  274. }
  275. func (t *TUN) Tag() string {
  276. return t.tag
  277. }
  278. func (t *TUN) Start() error {
  279. if C.IsAndroid && t.platformInterface == nil {
  280. t.tunOptions.BuildAndroidRules(t.router.PackageManager())
  281. }
  282. if t.tunOptions.Name == "" {
  283. t.tunOptions.Name = tun.CalculateInterfaceName("")
  284. }
  285. var (
  286. tunInterface tun.Tun
  287. err error
  288. )
  289. monitor := taskmonitor.New(t.logger, C.StartTimeout)
  290. monitor.Start("open tun interface")
  291. if t.platformInterface != nil {
  292. tunInterface, err = t.platformInterface.OpenTun(&t.tunOptions, t.platformOptions)
  293. } else {
  294. tunInterface, err = tun.New(t.tunOptions)
  295. }
  296. monitor.Finish()
  297. if err != nil {
  298. return E.Cause(err, "configure tun interface")
  299. }
  300. t.logger.Trace("creating stack")
  301. t.tunIf = tunInterface
  302. var (
  303. forwarderBindInterface bool
  304. includeAllNetworks bool
  305. )
  306. if t.platformInterface != nil {
  307. forwarderBindInterface = true
  308. includeAllNetworks = t.platformInterface.IncludeAllNetworks()
  309. }
  310. tunStack, err := tun.NewStack(t.stack, tun.StackOptions{
  311. Context: t.ctx,
  312. Tun: tunInterface,
  313. TunOptions: t.tunOptions,
  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) PrepareConnection(network string, source M.Socksaddr, destination M.Socksaddr) error {
  387. return t.router.PreMatch(adapter.InboundContext{
  388. Inbound: t.tag,
  389. InboundType: C.TypeTun,
  390. Network: network,
  391. Source: source,
  392. Destination: destination,
  393. InboundOptions: t.inboundOptions,
  394. })
  395. }
  396. func (t *TUN) NewConnectionEx(ctx context.Context, conn net.Conn, source M.Socksaddr, destination M.Socksaddr, onClose N.CloseHandlerFunc) {
  397. ctx = log.ContextWithNewID(ctx)
  398. var metadata adapter.InboundContext
  399. metadata.Inbound = t.tag
  400. metadata.InboundType = C.TypeTun
  401. metadata.Source = source
  402. metadata.Destination = destination
  403. metadata.InboundOptions = t.inboundOptions
  404. t.logger.InfoContext(ctx, "inbound connection from ", metadata.Source)
  405. t.logger.InfoContext(ctx, "inbound connection to ", metadata.Destination)
  406. t.router.RouteConnectionEx(ctx, conn, metadata, onClose)
  407. }
  408. func (t *TUN) NewPacketConnectionEx(ctx context.Context, conn N.PacketConn, source M.Socksaddr, destination M.Socksaddr, onClose N.CloseHandlerFunc) {
  409. ctx = log.ContextWithNewID(ctx)
  410. var metadata adapter.InboundContext
  411. metadata.Inbound = t.tag
  412. metadata.InboundType = C.TypeTun
  413. metadata.Source = source
  414. metadata.Destination = destination
  415. metadata.InboundOptions = t.inboundOptions
  416. t.logger.InfoContext(ctx, "inbound packet connection from ", metadata.Source)
  417. t.logger.InfoContext(ctx, "inbound packet connection to ", metadata.Destination)
  418. t.router.RoutePacketConnectionEx(ctx, conn, metadata, onClose)
  419. }
  420. type autoRedirectHandler TUN
  421. func (t *autoRedirectHandler) NewConnectionEx(ctx context.Context, conn net.Conn, source M.Socksaddr, destination M.Socksaddr, onClose N.CloseHandlerFunc) {
  422. ctx = log.ContextWithNewID(ctx)
  423. var metadata adapter.InboundContext
  424. metadata.Inbound = t.tag
  425. metadata.InboundType = C.TypeTun
  426. metadata.Source = source
  427. metadata.Destination = destination
  428. metadata.InboundOptions = t.inboundOptions
  429. t.logger.InfoContext(ctx, "inbound redirect connection from ", metadata.Source)
  430. t.logger.InfoContext(ctx, "inbound connection to ", metadata.Destination)
  431. t.router.RouteConnectionEx(ctx, conn, metadata, onClose)
  432. }