router.go 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519
  1. package route
  2. import (
  3. "context"
  4. "net/netip"
  5. "net/url"
  6. "os"
  7. "runtime"
  8. "strings"
  9. "time"
  10. "github.com/sagernet/sing-box/adapter"
  11. "github.com/sagernet/sing-box/common/conntrack"
  12. "github.com/sagernet/sing-box/common/dialer"
  13. "github.com/sagernet/sing-box/common/geoip"
  14. "github.com/sagernet/sing-box/common/geosite"
  15. "github.com/sagernet/sing-box/common/process"
  16. "github.com/sagernet/sing-box/common/taskmonitor"
  17. C "github.com/sagernet/sing-box/constant"
  18. "github.com/sagernet/sing-box/experimental/libbox/platform"
  19. "github.com/sagernet/sing-box/log"
  20. "github.com/sagernet/sing-box/option"
  21. R "github.com/sagernet/sing-box/route/rule"
  22. "github.com/sagernet/sing-box/transport/fakeip"
  23. "github.com/sagernet/sing-dns"
  24. "github.com/sagernet/sing/common"
  25. E "github.com/sagernet/sing/common/exceptions"
  26. F "github.com/sagernet/sing/common/format"
  27. M "github.com/sagernet/sing/common/metadata"
  28. N "github.com/sagernet/sing/common/network"
  29. "github.com/sagernet/sing/common/task"
  30. "github.com/sagernet/sing/service"
  31. "github.com/sagernet/sing/service/pause"
  32. )
  33. var _ adapter.Router = (*Router)(nil)
  34. type Router struct {
  35. ctx context.Context
  36. logger log.ContextLogger
  37. dnsLogger log.ContextLogger
  38. connTracker conntrack.Tracker
  39. inbound adapter.InboundManager
  40. outbound adapter.OutboundManager
  41. connection adapter.ConnectionManager
  42. network adapter.NetworkManager
  43. rules []adapter.Rule
  44. needGeoIPDatabase bool
  45. needGeositeDatabase bool
  46. geoIPOptions option.GeoIPOptions
  47. geositeOptions option.GeositeOptions
  48. geoIPReader *geoip.Reader
  49. geositeReader *geosite.Reader
  50. geositeCache map[string]adapter.Rule
  51. needFindProcess bool
  52. dnsClient *dns.Client
  53. defaultDomainStrategy dns.DomainStrategy
  54. dnsRules []adapter.DNSRule
  55. ruleSets []adapter.RuleSet
  56. ruleSetMap map[string]adapter.RuleSet
  57. defaultTransport dns.Transport
  58. transports []dns.Transport
  59. transportMap map[string]dns.Transport
  60. transportDomainStrategy map[dns.Transport]dns.DomainStrategy
  61. dnsReverseMapping *DNSReverseMapping
  62. fakeIPStore adapter.FakeIPStore
  63. processSearcher process.Searcher
  64. pauseManager pause.Manager
  65. tracker adapter.ConnectionTracker
  66. platformInterface platform.Interface
  67. needWIFIState bool
  68. started bool
  69. }
  70. func NewRouter(ctx context.Context, logFactory log.Factory, options option.RouteOptions, dnsOptions option.DNSOptions) (*Router, error) {
  71. router := &Router{
  72. ctx: ctx,
  73. logger: logFactory.NewLogger("router"),
  74. dnsLogger: logFactory.NewLogger("dns"),
  75. connTracker: service.FromContext[conntrack.Tracker](ctx),
  76. inbound: service.FromContext[adapter.InboundManager](ctx),
  77. outbound: service.FromContext[adapter.OutboundManager](ctx),
  78. connection: service.FromContext[adapter.ConnectionManager](ctx),
  79. network: service.FromContext[adapter.NetworkManager](ctx),
  80. rules: make([]adapter.Rule, 0, len(options.Rules)),
  81. dnsRules: make([]adapter.DNSRule, 0, len(dnsOptions.Rules)),
  82. ruleSetMap: make(map[string]adapter.RuleSet),
  83. needGeoIPDatabase: hasRule(options.Rules, isGeoIPRule) || hasDNSRule(dnsOptions.Rules, isGeoIPDNSRule),
  84. needGeositeDatabase: hasRule(options.Rules, isGeositeRule) || hasDNSRule(dnsOptions.Rules, isGeositeDNSRule),
  85. geoIPOptions: common.PtrValueOrDefault(options.GeoIP),
  86. geositeOptions: common.PtrValueOrDefault(options.Geosite),
  87. geositeCache: make(map[string]adapter.Rule),
  88. needFindProcess: hasRule(options.Rules, isProcessRule) || hasDNSRule(dnsOptions.Rules, isProcessDNSRule) || options.FindProcess,
  89. defaultDomainStrategy: dns.DomainStrategy(dnsOptions.Strategy),
  90. pauseManager: service.FromContext[pause.Manager](ctx),
  91. platformInterface: service.FromContext[platform.Interface](ctx),
  92. needWIFIState: hasRule(options.Rules, isWIFIRule) || hasDNSRule(dnsOptions.Rules, isWIFIDNSRule),
  93. }
  94. service.MustRegister[adapter.Router](ctx, router)
  95. router.dnsClient = dns.NewClient(dns.ClientOptions{
  96. DisableCache: dnsOptions.DNSClientOptions.DisableCache,
  97. DisableExpire: dnsOptions.DNSClientOptions.DisableExpire,
  98. IndependentCache: dnsOptions.DNSClientOptions.IndependentCache,
  99. CacheCapacity: dnsOptions.DNSClientOptions.CacheCapacity,
  100. RDRC: func() dns.RDRCStore {
  101. cacheFile := service.FromContext[adapter.CacheFile](ctx)
  102. if cacheFile == nil {
  103. return nil
  104. }
  105. if !cacheFile.StoreRDRC() {
  106. return nil
  107. }
  108. return cacheFile
  109. },
  110. Logger: router.dnsLogger,
  111. })
  112. for i, ruleOptions := range options.Rules {
  113. routeRule, err := R.NewRule(ctx, router.logger, ruleOptions, true)
  114. if err != nil {
  115. return nil, E.Cause(err, "parse rule[", i, "]")
  116. }
  117. router.rules = append(router.rules, routeRule)
  118. }
  119. for i, dnsRuleOptions := range dnsOptions.Rules {
  120. dnsRule, err := R.NewDNSRule(ctx, router.logger, dnsRuleOptions, true)
  121. if err != nil {
  122. return nil, E.Cause(err, "parse dns rule[", i, "]")
  123. }
  124. router.dnsRules = append(router.dnsRules, dnsRule)
  125. }
  126. for i, ruleSetOptions := range options.RuleSet {
  127. if _, exists := router.ruleSetMap[ruleSetOptions.Tag]; exists {
  128. return nil, E.New("duplicate rule-set tag: ", ruleSetOptions.Tag)
  129. }
  130. ruleSet, err := R.NewRuleSet(ctx, router.logger, ruleSetOptions)
  131. if err != nil {
  132. return nil, E.Cause(err, "parse rule-set[", i, "]")
  133. }
  134. router.ruleSets = append(router.ruleSets, ruleSet)
  135. router.ruleSetMap[ruleSetOptions.Tag] = ruleSet
  136. }
  137. transports := make([]dns.Transport, len(dnsOptions.Servers))
  138. dummyTransportMap := make(map[string]dns.Transport)
  139. transportMap := make(map[string]dns.Transport)
  140. transportTags := make([]string, len(dnsOptions.Servers))
  141. transportTagMap := make(map[string]bool)
  142. transportDomainStrategy := make(map[dns.Transport]dns.DomainStrategy)
  143. for i, server := range dnsOptions.Servers {
  144. var tag string
  145. if server.Tag != "" {
  146. tag = server.Tag
  147. } else {
  148. tag = F.ToString(i)
  149. }
  150. if transportTagMap[tag] {
  151. return nil, E.New("duplicate dns server tag: ", tag)
  152. }
  153. transportTags[i] = tag
  154. transportTagMap[tag] = true
  155. }
  156. outboundManager := service.FromContext[adapter.OutboundManager](ctx)
  157. for {
  158. lastLen := len(dummyTransportMap)
  159. for i, server := range dnsOptions.Servers {
  160. tag := transportTags[i]
  161. if _, exists := dummyTransportMap[tag]; exists {
  162. continue
  163. }
  164. var detour N.Dialer
  165. if server.Detour == "" {
  166. detour = dialer.NewDefaultOutbound(outboundManager)
  167. } else {
  168. detour = dialer.NewDetour(outboundManager, server.Detour)
  169. }
  170. var serverProtocol string
  171. switch server.Address {
  172. case "local":
  173. serverProtocol = "local"
  174. default:
  175. serverURL, _ := url.Parse(server.Address)
  176. var serverAddress string
  177. if serverURL != nil {
  178. if serverURL.Scheme == "" {
  179. serverProtocol = "udp"
  180. } else {
  181. serverProtocol = serverURL.Scheme
  182. }
  183. serverAddress = serverURL.Hostname()
  184. }
  185. if serverAddress == "" {
  186. serverAddress = server.Address
  187. }
  188. notIpAddress := !M.ParseSocksaddr(serverAddress).Addr.IsValid()
  189. if server.AddressResolver != "" {
  190. if !transportTagMap[server.AddressResolver] {
  191. return nil, E.New("parse dns server[", tag, "]: address resolver not found: ", server.AddressResolver)
  192. }
  193. if upstream, exists := dummyTransportMap[server.AddressResolver]; exists {
  194. detour = dns.NewDialerWrapper(detour, router.dnsClient, upstream, dns.DomainStrategy(server.AddressStrategy), time.Duration(server.AddressFallbackDelay))
  195. } else {
  196. continue
  197. }
  198. } else if notIpAddress && strings.Contains(server.Address, ".") {
  199. return nil, E.New("parse dns server[", tag, "]: missing address_resolver")
  200. }
  201. }
  202. var clientSubnet netip.Prefix
  203. if server.ClientSubnet != nil {
  204. clientSubnet = netip.Prefix(common.PtrValueOrDefault(server.ClientSubnet))
  205. } else if dnsOptions.ClientSubnet != nil {
  206. clientSubnet = netip.Prefix(common.PtrValueOrDefault(dnsOptions.ClientSubnet))
  207. }
  208. if serverProtocol == "" {
  209. serverProtocol = "transport"
  210. }
  211. transport, err := dns.CreateTransport(dns.TransportOptions{
  212. Context: ctx,
  213. Logger: logFactory.NewLogger(F.ToString("dns/", serverProtocol, "[", tag, "]")),
  214. Name: tag,
  215. Dialer: detour,
  216. Address: server.Address,
  217. ClientSubnet: clientSubnet,
  218. })
  219. if err != nil {
  220. return nil, E.Cause(err, "parse dns server[", tag, "]")
  221. }
  222. transports[i] = transport
  223. dummyTransportMap[tag] = transport
  224. if server.Tag != "" {
  225. transportMap[server.Tag] = transport
  226. }
  227. strategy := dns.DomainStrategy(server.Strategy)
  228. if strategy != dns.DomainStrategyAsIS {
  229. transportDomainStrategy[transport] = strategy
  230. }
  231. }
  232. if len(transports) == len(dummyTransportMap) {
  233. break
  234. }
  235. if lastLen != len(dummyTransportMap) {
  236. continue
  237. }
  238. unresolvedTags := common.MapIndexed(common.FilterIndexed(dnsOptions.Servers, func(index int, server option.DNSServerOptions) bool {
  239. _, exists := dummyTransportMap[transportTags[index]]
  240. return !exists
  241. }), func(index int, server option.DNSServerOptions) string {
  242. return transportTags[index]
  243. })
  244. if len(unresolvedTags) == 0 {
  245. panic(F.ToString("unexpected unresolved dns servers: ", len(transports), " ", len(dummyTransportMap), " ", len(transportMap)))
  246. }
  247. return nil, E.New("found circular reference in dns servers: ", strings.Join(unresolvedTags, " "))
  248. }
  249. var defaultTransport dns.Transport
  250. if dnsOptions.Final != "" {
  251. defaultTransport = dummyTransportMap[dnsOptions.Final]
  252. if defaultTransport == nil {
  253. return nil, E.New("default dns server not found: ", dnsOptions.Final)
  254. }
  255. }
  256. if defaultTransport == nil {
  257. if len(transports) == 0 {
  258. transports = append(transports, common.Must1(dns.CreateTransport(dns.TransportOptions{
  259. Context: ctx,
  260. Name: "local",
  261. Address: "local",
  262. Dialer: common.Must1(dialer.NewDefault(ctx, option.DialerOptions{})),
  263. })))
  264. }
  265. defaultTransport = transports[0]
  266. }
  267. if _, isFakeIP := defaultTransport.(adapter.FakeIPTransport); isFakeIP {
  268. return nil, E.New("default DNS server cannot be fakeip")
  269. }
  270. router.defaultTransport = defaultTransport
  271. router.transports = transports
  272. router.transportMap = transportMap
  273. router.transportDomainStrategy = transportDomainStrategy
  274. if dnsOptions.ReverseMapping {
  275. router.dnsReverseMapping = NewDNSReverseMapping()
  276. }
  277. if fakeIPOptions := dnsOptions.FakeIP; fakeIPOptions != nil && dnsOptions.FakeIP.Enabled {
  278. var inet4Range netip.Prefix
  279. var inet6Range netip.Prefix
  280. if fakeIPOptions.Inet4Range != nil {
  281. inet4Range = *fakeIPOptions.Inet4Range
  282. }
  283. if fakeIPOptions.Inet6Range != nil {
  284. inet6Range = *fakeIPOptions.Inet6Range
  285. }
  286. router.fakeIPStore = fakeip.NewStore(ctx, router.logger, inet4Range, inet6Range)
  287. }
  288. return router, nil
  289. }
  290. func (r *Router) Start(stage adapter.StartStage) error {
  291. monitor := taskmonitor.New(r.logger, C.StartTimeout)
  292. switch stage {
  293. case adapter.StartStateInitialize:
  294. if r.fakeIPStore != nil {
  295. monitor.Start("initialize fakeip store")
  296. err := r.fakeIPStore.Start()
  297. monitor.Finish()
  298. if err != nil {
  299. return err
  300. }
  301. }
  302. case adapter.StartStateStart:
  303. if r.needGeoIPDatabase {
  304. monitor.Start("initialize geoip database")
  305. err := r.prepareGeoIPDatabase()
  306. monitor.Finish()
  307. if err != nil {
  308. return err
  309. }
  310. }
  311. if r.needGeositeDatabase {
  312. monitor.Start("initialize geosite database")
  313. err := r.prepareGeositeDatabase()
  314. monitor.Finish()
  315. if err != nil {
  316. return err
  317. }
  318. }
  319. if r.needGeositeDatabase {
  320. for _, rule := range r.rules {
  321. err := rule.UpdateGeosite()
  322. if err != nil {
  323. r.logger.Error("failed to initialize geosite: ", err)
  324. }
  325. }
  326. for _, rule := range r.dnsRules {
  327. err := rule.UpdateGeosite()
  328. if err != nil {
  329. r.logger.Error("failed to initialize geosite: ", err)
  330. }
  331. }
  332. err := common.Close(r.geositeReader)
  333. if err != nil {
  334. return err
  335. }
  336. r.geositeCache = nil
  337. r.geositeReader = nil
  338. }
  339. monitor.Start("initialize DNS client")
  340. r.dnsClient.Start()
  341. monitor.Finish()
  342. for i, rule := range r.dnsRules {
  343. monitor.Start("initialize DNS rule[", i, "]")
  344. err := rule.Start()
  345. monitor.Finish()
  346. if err != nil {
  347. return E.Cause(err, "initialize DNS rule[", i, "]")
  348. }
  349. }
  350. for i, transport := range r.transports {
  351. monitor.Start("initialize DNS transport[", i, "]")
  352. err := transport.Start()
  353. monitor.Finish()
  354. if err != nil {
  355. return E.Cause(err, "initialize DNS server[", i, "]")
  356. }
  357. }
  358. var cacheContext *adapter.HTTPStartContext
  359. if len(r.ruleSets) > 0 {
  360. monitor.Start("initialize rule-set")
  361. cacheContext = adapter.NewHTTPStartContext()
  362. var ruleSetStartGroup task.Group
  363. for i, ruleSet := range r.ruleSets {
  364. ruleSetInPlace := ruleSet
  365. ruleSetStartGroup.Append0(func(ctx context.Context) error {
  366. err := ruleSetInPlace.StartContext(ctx, cacheContext)
  367. if err != nil {
  368. return E.Cause(err, "initialize rule-set[", i, "]")
  369. }
  370. return nil
  371. })
  372. }
  373. ruleSetStartGroup.Concurrency(5)
  374. ruleSetStartGroup.FastFail()
  375. err := ruleSetStartGroup.Run(r.ctx)
  376. monitor.Finish()
  377. if err != nil {
  378. return err
  379. }
  380. }
  381. if cacheContext != nil {
  382. cacheContext.Close()
  383. }
  384. needFindProcess := r.needFindProcess
  385. for _, ruleSet := range r.ruleSets {
  386. metadata := ruleSet.Metadata()
  387. if metadata.ContainsProcessRule {
  388. needFindProcess = true
  389. }
  390. if metadata.ContainsWIFIRule {
  391. r.needWIFIState = true
  392. }
  393. }
  394. if needFindProcess {
  395. if r.platformInterface != nil {
  396. r.processSearcher = r.platformInterface
  397. } else {
  398. monitor.Start("initialize process searcher")
  399. searcher, err := process.NewSearcher(process.Config{
  400. Logger: r.logger,
  401. PackageManager: r.network.PackageManager(),
  402. })
  403. monitor.Finish()
  404. if err != nil {
  405. if err != os.ErrInvalid {
  406. r.logger.Warn(E.Cause(err, "create process searcher"))
  407. }
  408. } else {
  409. r.processSearcher = searcher
  410. }
  411. }
  412. }
  413. case adapter.StartStatePostStart:
  414. for i, rule := range r.rules {
  415. monitor.Start("initialize rule[", i, "]")
  416. err := rule.Start()
  417. monitor.Finish()
  418. if err != nil {
  419. return E.Cause(err, "initialize rule[", i, "]")
  420. }
  421. }
  422. for _, ruleSet := range r.ruleSets {
  423. monitor.Start("post start rule_set[", ruleSet.Name(), "]")
  424. err := ruleSet.PostStart()
  425. monitor.Finish()
  426. if err != nil {
  427. return E.Cause(err, "post start rule_set[", ruleSet.Name(), "]")
  428. }
  429. }
  430. r.started = true
  431. return nil
  432. case adapter.StartStateStarted:
  433. for _, ruleSet := range r.ruleSetMap {
  434. ruleSet.Cleanup()
  435. }
  436. runtime.GC()
  437. }
  438. return nil
  439. }
  440. func (r *Router) Close() error {
  441. monitor := taskmonitor.New(r.logger, C.StopTimeout)
  442. var err error
  443. for i, rule := range r.rules {
  444. monitor.Start("close rule[", i, "]")
  445. err = E.Append(err, rule.Close(), func(err error) error {
  446. return E.Cause(err, "close rule[", i, "]")
  447. })
  448. monitor.Finish()
  449. }
  450. for i, rule := range r.dnsRules {
  451. monitor.Start("close dns rule[", i, "]")
  452. err = E.Append(err, rule.Close(), func(err error) error {
  453. return E.Cause(err, "close dns rule[", i, "]")
  454. })
  455. monitor.Finish()
  456. }
  457. for i, transport := range r.transports {
  458. monitor.Start("close dns transport[", i, "]")
  459. err = E.Append(err, transport.Close(), func(err error) error {
  460. return E.Cause(err, "close dns transport[", i, "]")
  461. })
  462. monitor.Finish()
  463. }
  464. if r.geoIPReader != nil {
  465. monitor.Start("close geoip reader")
  466. err = E.Append(err, r.geoIPReader.Close(), func(err error) error {
  467. return E.Cause(err, "close geoip reader")
  468. })
  469. monitor.Finish()
  470. }
  471. if r.fakeIPStore != nil {
  472. monitor.Start("close fakeip store")
  473. err = E.Append(err, r.fakeIPStore.Close(), func(err error) error {
  474. return E.Cause(err, "close fakeip store")
  475. })
  476. monitor.Finish()
  477. }
  478. return err
  479. }
  480. func (r *Router) FakeIPStore() adapter.FakeIPStore {
  481. return r.fakeIPStore
  482. }
  483. func (r *Router) RuleSet(tag string) (adapter.RuleSet, bool) {
  484. ruleSet, loaded := r.ruleSetMap[tag]
  485. return ruleSet, loaded
  486. }
  487. func (r *Router) NeedWIFIState() bool {
  488. return r.needWIFIState
  489. }
  490. func (r *Router) Rules() []adapter.Rule {
  491. return r.rules
  492. }
  493. func (r *Router) SetTracker(tracker adapter.ConnectionTracker) {
  494. r.tracker = tracker
  495. }
  496. func (r *Router) ResetNetwork() {
  497. r.network.ResetNetwork()
  498. for _, transport := range r.transports {
  499. transport.Reset()
  500. }
  501. }