tun.go 14 KB

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