router.go 16 KB

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