tun.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451
  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(source M.Socksaddr, destination M.Socksaddr) error {
  387. // TODO: implement rejects
  388. return nil
  389. }
  390. func (t *TUN) NewConnectionEx(ctx context.Context, conn net.Conn, source M.Socksaddr, destination M.Socksaddr, onClose N.CloseHandlerFunc) {
  391. ctx = log.ContextWithNewID(ctx)
  392. var metadata adapter.InboundContext
  393. metadata.Inbound = t.tag
  394. metadata.InboundType = C.TypeTun
  395. metadata.Source = source
  396. metadata.Destination = destination
  397. metadata.InboundOptions = t.inboundOptions
  398. t.logger.InfoContext(ctx, "inbound connection from ", metadata.Source)
  399. t.logger.InfoContext(ctx, "inbound connection to ", metadata.Destination)
  400. t.router.RouteConnectionEx(ctx, conn, metadata, onClose)
  401. }
  402. func (t *TUN) NewPacketConnectionEx(ctx context.Context, conn N.PacketConn, source M.Socksaddr, destination M.Socksaddr, onClose N.CloseHandlerFunc) {
  403. ctx = log.ContextWithNewID(ctx)
  404. var metadata adapter.InboundContext
  405. metadata.Inbound = t.tag
  406. metadata.InboundType = C.TypeTun
  407. metadata.Source = source
  408. metadata.Destination = destination
  409. metadata.InboundOptions = t.inboundOptions
  410. t.logger.InfoContext(ctx, "inbound packet connection from ", metadata.Source)
  411. t.logger.InfoContext(ctx, "inbound packet connection to ", metadata.Destination)
  412. t.router.RoutePacketConnectionEx(ctx, conn, metadata, onClose)
  413. }
  414. type autoRedirectHandler TUN
  415. func (t *autoRedirectHandler) NewConnectionEx(ctx context.Context, conn net.Conn, source M.Socksaddr, destination M.Socksaddr, onClose N.CloseHandlerFunc) {
  416. ctx = log.ContextWithNewID(ctx)
  417. var metadata adapter.InboundContext
  418. metadata.Inbound = t.tag
  419. metadata.InboundType = C.TypeTun
  420. metadata.Source = source
  421. metadata.Destination = destination
  422. metadata.InboundOptions = t.inboundOptions
  423. t.logger.InfoContext(ctx, "inbound redirect connection from ", metadata.Source)
  424. t.logger.InfoContext(ctx, "inbound connection to ", metadata.Destination)
  425. t.router.RouteConnectionEx(ctx, conn, metadata, onClose)
  426. }