1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330 |
- package route
- import (
- "context"
- "errors"
- "net"
- "net/netip"
- "net/url"
- "os"
- "os/user"
- "runtime"
- "strings"
- "time"
- "github.com/sagernet/sing-box/adapter"
- "github.com/sagernet/sing-box/common/conntrack"
- "github.com/sagernet/sing-box/common/dialer"
- "github.com/sagernet/sing-box/common/geoip"
- "github.com/sagernet/sing-box/common/geosite"
- "github.com/sagernet/sing-box/common/process"
- "github.com/sagernet/sing-box/common/sniff"
- "github.com/sagernet/sing-box/common/taskmonitor"
- C "github.com/sagernet/sing-box/constant"
- "github.com/sagernet/sing-box/experimental/libbox/platform"
- "github.com/sagernet/sing-box/log"
- "github.com/sagernet/sing-box/option"
- "github.com/sagernet/sing-box/outbound"
- "github.com/sagernet/sing-box/transport/fakeip"
- "github.com/sagernet/sing-dns"
- "github.com/sagernet/sing-mux"
- "github.com/sagernet/sing-tun"
- "github.com/sagernet/sing-vmess"
- "github.com/sagernet/sing/common"
- "github.com/sagernet/sing/common/buf"
- "github.com/sagernet/sing/common/bufio"
- "github.com/sagernet/sing/common/bufio/deadline"
- "github.com/sagernet/sing/common/control"
- E "github.com/sagernet/sing/common/exceptions"
- F "github.com/sagernet/sing/common/format"
- M "github.com/sagernet/sing/common/metadata"
- N "github.com/sagernet/sing/common/network"
- "github.com/sagernet/sing/common/ntp"
- "github.com/sagernet/sing/common/task"
- "github.com/sagernet/sing/common/uot"
- "github.com/sagernet/sing/common/winpowrprof"
- "github.com/sagernet/sing/service"
- "github.com/sagernet/sing/service/pause"
- )
- var _ adapter.Router = (*Router)(nil)
- type Router struct {
- ctx context.Context
- logger log.ContextLogger
- dnsLogger log.ContextLogger
- inboundByTag map[string]adapter.Inbound
- outbounds []adapter.Outbound
- outboundByTag map[string]adapter.Outbound
- rules []adapter.Rule
- defaultDetour string
- defaultOutboundForConnection adapter.Outbound
- defaultOutboundForPacketConnection adapter.Outbound
- needGeoIPDatabase bool
- needGeositeDatabase bool
- geoIPOptions option.GeoIPOptions
- geositeOptions option.GeositeOptions
- geoIPReader *geoip.Reader
- geositeReader *geosite.Reader
- geositeCache map[string]adapter.Rule
- needFindProcess bool
- dnsClient *dns.Client
- defaultDomainStrategy dns.DomainStrategy
- dnsRules []adapter.DNSRule
- ruleSets []adapter.RuleSet
- ruleSetMap map[string]adapter.RuleSet
- defaultTransport dns.Transport
- transports []dns.Transport
- transportMap map[string]dns.Transport
- transportDomainStrategy map[dns.Transport]dns.DomainStrategy
- dnsReverseMapping *DNSReverseMapping
- fakeIPStore adapter.FakeIPStore
- interfaceFinder *control.DefaultInterfaceFinder
- autoDetectInterface bool
- defaultInterface string
- defaultMark uint32
- autoRedirectOutputMark uint32
- networkMonitor tun.NetworkUpdateMonitor
- interfaceMonitor tun.DefaultInterfaceMonitor
- packageManager tun.PackageManager
- powerListener winpowrprof.EventListener
- processSearcher process.Searcher
- timeService *ntp.Service
- pauseManager pause.Manager
- clashServer adapter.ClashServer
- v2rayServer adapter.V2RayServer
- platformInterface platform.Interface
- needWIFIState bool
- needPackageManager bool
- wifiState adapter.WIFIState
- started bool
- }
- func NewRouter(
- ctx context.Context,
- logFactory log.Factory,
- options option.RouteOptions,
- dnsOptions option.DNSOptions,
- ntpOptions option.NTPOptions,
- inbounds []option.Inbound,
- platformInterface platform.Interface,
- ) (*Router, error) {
- router := &Router{
- ctx: ctx,
- logger: logFactory.NewLogger("router"),
- dnsLogger: logFactory.NewLogger("dns"),
- outboundByTag: make(map[string]adapter.Outbound),
- rules: make([]adapter.Rule, 0, len(options.Rules)),
- dnsRules: make([]adapter.DNSRule, 0, len(dnsOptions.Rules)),
- ruleSetMap: make(map[string]adapter.RuleSet),
- needGeoIPDatabase: hasRule(options.Rules, isGeoIPRule) || hasDNSRule(dnsOptions.Rules, isGeoIPDNSRule),
- needGeositeDatabase: hasRule(options.Rules, isGeositeRule) || hasDNSRule(dnsOptions.Rules, isGeositeDNSRule),
- geoIPOptions: common.PtrValueOrDefault(options.GeoIP),
- geositeOptions: common.PtrValueOrDefault(options.Geosite),
- geositeCache: make(map[string]adapter.Rule),
- needFindProcess: hasRule(options.Rules, isProcessRule) || hasDNSRule(dnsOptions.Rules, isProcessDNSRule) || options.FindProcess,
- defaultDetour: options.Final,
- defaultDomainStrategy: dns.DomainStrategy(dnsOptions.Strategy),
- interfaceFinder: control.NewDefaultInterfaceFinder(),
- autoDetectInterface: options.AutoDetectInterface,
- defaultInterface: options.DefaultInterface,
- defaultMark: options.DefaultMark,
- pauseManager: service.FromContext[pause.Manager](ctx),
- platformInterface: platformInterface,
- needWIFIState: hasRule(options.Rules, isWIFIRule) || hasDNSRule(dnsOptions.Rules, isWIFIDNSRule),
- needPackageManager: common.Any(inbounds, func(inbound option.Inbound) bool {
- return len(inbound.TunOptions.IncludePackage) > 0 || len(inbound.TunOptions.ExcludePackage) > 0
- }),
- }
- router.dnsClient = dns.NewClient(dns.ClientOptions{
- DisableCache: dnsOptions.DNSClientOptions.DisableCache,
- DisableExpire: dnsOptions.DNSClientOptions.DisableExpire,
- IndependentCache: dnsOptions.DNSClientOptions.IndependentCache,
- RDRC: func() dns.RDRCStore {
- cacheFile := service.FromContext[adapter.CacheFile](ctx)
- if cacheFile == nil {
- return nil
- }
- if !cacheFile.StoreRDRC() {
- return nil
- }
- return cacheFile
- },
- Logger: router.dnsLogger,
- })
- for i, ruleOptions := range options.Rules {
- routeRule, err := NewRule(router, router.logger, ruleOptions, true)
- if err != nil {
- return nil, E.Cause(err, "parse rule[", i, "]")
- }
- router.rules = append(router.rules, routeRule)
- }
- for i, dnsRuleOptions := range dnsOptions.Rules {
- dnsRule, err := NewDNSRule(router, router.logger, dnsRuleOptions, true)
- if err != nil {
- return nil, E.Cause(err, "parse dns rule[", i, "]")
- }
- router.dnsRules = append(router.dnsRules, dnsRule)
- }
- for i, ruleSetOptions := range options.RuleSet {
- if _, exists := router.ruleSetMap[ruleSetOptions.Tag]; exists {
- return nil, E.New("duplicate rule-set tag: ", ruleSetOptions.Tag)
- }
- ruleSet, err := NewRuleSet(ctx, router, router.logger, ruleSetOptions)
- if err != nil {
- return nil, E.Cause(err, "parse rule-set[", i, "]")
- }
- router.ruleSets = append(router.ruleSets, ruleSet)
- router.ruleSetMap[ruleSetOptions.Tag] = ruleSet
- }
- transports := make([]dns.Transport, len(dnsOptions.Servers))
- dummyTransportMap := make(map[string]dns.Transport)
- transportMap := make(map[string]dns.Transport)
- transportTags := make([]string, len(dnsOptions.Servers))
- transportTagMap := make(map[string]bool)
- transportDomainStrategy := make(map[dns.Transport]dns.DomainStrategy)
- for i, server := range dnsOptions.Servers {
- var tag string
- if server.Tag != "" {
- tag = server.Tag
- } else {
- tag = F.ToString(i)
- }
- if transportTagMap[tag] {
- return nil, E.New("duplicate dns server tag: ", tag)
- }
- transportTags[i] = tag
- transportTagMap[tag] = true
- }
- ctx = adapter.ContextWithRouter(ctx, router)
- for {
- lastLen := len(dummyTransportMap)
- for i, server := range dnsOptions.Servers {
- tag := transportTags[i]
- if _, exists := dummyTransportMap[tag]; exists {
- continue
- }
- var detour N.Dialer
- if server.Detour == "" {
- detour = dialer.NewRouter(router)
- } else {
- detour = dialer.NewDetour(router, server.Detour)
- }
- switch server.Address {
- case "local":
- default:
- serverURL, _ := url.Parse(server.Address)
- var serverAddress string
- if serverURL != nil {
- serverAddress = serverURL.Hostname()
- }
- if serverAddress == "" {
- serverAddress = server.Address
- }
- notIpAddress := !M.ParseSocksaddr(serverAddress).Addr.IsValid()
- if server.AddressResolver != "" {
- if !transportTagMap[server.AddressResolver] {
- return nil, E.New("parse dns server[", tag, "]: address resolver not found: ", server.AddressResolver)
- }
- if upstream, exists := dummyTransportMap[server.AddressResolver]; exists {
- detour = dns.NewDialerWrapper(detour, router.dnsClient, upstream, dns.DomainStrategy(server.AddressStrategy), time.Duration(server.AddressFallbackDelay))
- } else {
- continue
- }
- } else if notIpAddress && strings.Contains(server.Address, ".") {
- return nil, E.New("parse dns server[", tag, "]: missing address_resolver")
- }
- }
- var clientSubnet netip.Prefix
- if server.ClientSubnet != nil {
- clientSubnet = server.ClientSubnet.Build()
- } else if dnsOptions.ClientSubnet != nil {
- clientSubnet = dnsOptions.ClientSubnet.Build()
- }
- transport, err := dns.CreateTransport(dns.TransportOptions{
- Context: ctx,
- Logger: logFactory.NewLogger(F.ToString("dns/transport[", tag, "]")),
- Name: tag,
- Dialer: detour,
- Address: server.Address,
- ClientSubnet: clientSubnet,
- })
- if err != nil {
- return nil, E.Cause(err, "parse dns server[", tag, "]")
- }
- transports[i] = transport
- dummyTransportMap[tag] = transport
- if server.Tag != "" {
- transportMap[server.Tag] = transport
- }
- strategy := dns.DomainStrategy(server.Strategy)
- if strategy != dns.DomainStrategyAsIS {
- transportDomainStrategy[transport] = strategy
- }
- }
- if len(transports) == len(dummyTransportMap) {
- break
- }
- if lastLen != len(dummyTransportMap) {
- continue
- }
- unresolvedTags := common.MapIndexed(common.FilterIndexed(dnsOptions.Servers, func(index int, server option.DNSServerOptions) bool {
- _, exists := dummyTransportMap[transportTags[index]]
- return !exists
- }), func(index int, server option.DNSServerOptions) string {
- return transportTags[index]
- })
- if len(unresolvedTags) == 0 {
- panic(F.ToString("unexpected unresolved dns servers: ", len(transports), " ", len(dummyTransportMap), " ", len(transportMap)))
- }
- return nil, E.New("found circular reference in dns servers: ", strings.Join(unresolvedTags, " "))
- }
- var defaultTransport dns.Transport
- if dnsOptions.Final != "" {
- defaultTransport = dummyTransportMap[dnsOptions.Final]
- if defaultTransport == nil {
- return nil, E.New("default dns server not found: ", dnsOptions.Final)
- }
- }
- if defaultTransport == nil {
- if len(transports) == 0 {
- transports = append(transports, common.Must1(dns.CreateTransport(dns.TransportOptions{
- Context: ctx,
- Name: "local",
- Address: "local",
- Dialer: common.Must1(dialer.NewDefault(router, option.DialerOptions{})),
- })))
- }
- defaultTransport = transports[0]
- }
- if _, isFakeIP := defaultTransport.(adapter.FakeIPTransport); isFakeIP {
- return nil, E.New("default DNS server cannot be fakeip")
- }
- router.defaultTransport = defaultTransport
- router.transports = transports
- router.transportMap = transportMap
- router.transportDomainStrategy = transportDomainStrategy
- if dnsOptions.ReverseMapping {
- router.dnsReverseMapping = NewDNSReverseMapping()
- }
- if fakeIPOptions := dnsOptions.FakeIP; fakeIPOptions != nil && dnsOptions.FakeIP.Enabled {
- var inet4Range netip.Prefix
- var inet6Range netip.Prefix
- if fakeIPOptions.Inet4Range != nil {
- inet4Range = *fakeIPOptions.Inet4Range
- }
- if fakeIPOptions.Inet6Range != nil {
- inet6Range = *fakeIPOptions.Inet6Range
- }
- router.fakeIPStore = fakeip.NewStore(ctx, router.logger, inet4Range, inet6Range)
- }
- usePlatformDefaultInterfaceMonitor := platformInterface != nil && platformInterface.UsePlatformDefaultInterfaceMonitor()
- needInterfaceMonitor := options.AutoDetectInterface || common.Any(inbounds, func(inbound option.Inbound) bool {
- return inbound.HTTPOptions.SetSystemProxy || inbound.MixedOptions.SetSystemProxy || inbound.TunOptions.AutoRoute
- })
- if !usePlatformDefaultInterfaceMonitor {
- networkMonitor, err := tun.NewNetworkUpdateMonitor(router.logger)
- if !((err != nil && !needInterfaceMonitor) || errors.Is(err, os.ErrInvalid)) {
- if err != nil {
- return nil, err
- }
- router.networkMonitor = networkMonitor
- networkMonitor.RegisterCallback(func() {
- _ = router.interfaceFinder.Update()
- })
- interfaceMonitor, err := tun.NewDefaultInterfaceMonitor(router.networkMonitor, router.logger, tun.DefaultInterfaceMonitorOptions{
- OverrideAndroidVPN: options.OverrideAndroidVPN,
- UnderNetworkExtension: platformInterface != nil && platformInterface.UnderNetworkExtension(),
- })
- if err != nil {
- return nil, E.New("auto_detect_interface unsupported on current platform")
- }
- interfaceMonitor.RegisterCallback(router.notifyNetworkUpdate)
- router.interfaceMonitor = interfaceMonitor
- }
- } else {
- interfaceMonitor := platformInterface.CreateDefaultInterfaceMonitor(router.logger)
- interfaceMonitor.RegisterCallback(router.notifyNetworkUpdate)
- router.interfaceMonitor = interfaceMonitor
- }
- if ntpOptions.Enabled {
- ntpDialer, err := dialer.New(router, ntpOptions.DialerOptions)
- if err != nil {
- return nil, E.Cause(err, "create NTP service")
- }
- timeService := ntp.NewService(ntp.Options{
- Context: ctx,
- Dialer: ntpDialer,
- Logger: logFactory.NewLogger("ntp"),
- Server: ntpOptions.ServerOptions.Build(),
- Interval: time.Duration(ntpOptions.Interval),
- WriteToSystem: ntpOptions.WriteToSystem,
- })
- service.MustRegister[ntp.TimeService](ctx, timeService)
- router.timeService = timeService
- }
- return router, nil
- }
- func (r *Router) Initialize(inbounds []adapter.Inbound, outbounds []adapter.Outbound, defaultOutbound func() adapter.Outbound) error {
- inboundByTag := make(map[string]adapter.Inbound)
- for _, inbound := range inbounds {
- inboundByTag[inbound.Tag()] = inbound
- }
- outboundByTag := make(map[string]adapter.Outbound)
- for _, detour := range outbounds {
- outboundByTag[detour.Tag()] = detour
- }
- var defaultOutboundForConnection adapter.Outbound
- var defaultOutboundForPacketConnection adapter.Outbound
- if r.defaultDetour != "" {
- detour, loaded := outboundByTag[r.defaultDetour]
- if !loaded {
- return E.New("default detour not found: ", r.defaultDetour)
- }
- if common.Contains(detour.Network(), N.NetworkTCP) {
- defaultOutboundForConnection = detour
- }
- if common.Contains(detour.Network(), N.NetworkUDP) {
- defaultOutboundForPacketConnection = detour
- }
- }
- if defaultOutboundForConnection == nil {
- for _, detour := range outbounds {
- if common.Contains(detour.Network(), N.NetworkTCP) {
- defaultOutboundForConnection = detour
- break
- }
- }
- }
- if defaultOutboundForPacketConnection == nil {
- for _, detour := range outbounds {
- if common.Contains(detour.Network(), N.NetworkUDP) {
- defaultOutboundForPacketConnection = detour
- break
- }
- }
- }
- if defaultOutboundForConnection == nil || defaultOutboundForPacketConnection == nil {
- detour := defaultOutbound()
- if defaultOutboundForConnection == nil {
- defaultOutboundForConnection = detour
- }
- if defaultOutboundForPacketConnection == nil {
- defaultOutboundForPacketConnection = detour
- }
- outbounds = append(outbounds, detour)
- outboundByTag[detour.Tag()] = detour
- }
- r.inboundByTag = inboundByTag
- r.outbounds = outbounds
- r.defaultOutboundForConnection = defaultOutboundForConnection
- r.defaultOutboundForPacketConnection = defaultOutboundForPacketConnection
- r.outboundByTag = outboundByTag
- for i, rule := range r.rules {
- if _, loaded := outboundByTag[rule.Outbound()]; !loaded {
- return E.New("outbound not found for rule[", i, "]: ", rule.Outbound())
- }
- }
- return nil
- }
- func (r *Router) Outbounds() []adapter.Outbound {
- if !r.started {
- return nil
- }
- return r.outbounds
- }
- func (r *Router) PreStart() error {
- monitor := taskmonitor.New(r.logger, C.StartTimeout)
- if r.interfaceMonitor != nil {
- monitor.Start("initialize interface monitor")
- err := r.interfaceMonitor.Start()
- monitor.Finish()
- if err != nil {
- return err
- }
- }
- if r.networkMonitor != nil {
- monitor.Start("initialize network monitor")
- err := r.networkMonitor.Start()
- monitor.Finish()
- if err != nil {
- return err
- }
- }
- if r.fakeIPStore != nil {
- monitor.Start("initialize fakeip store")
- err := r.fakeIPStore.Start()
- monitor.Finish()
- if err != nil {
- return err
- }
- }
- return nil
- }
- func (r *Router) Start() error {
- monitor := taskmonitor.New(r.logger, C.StartTimeout)
- if r.needGeoIPDatabase {
- monitor.Start("initialize geoip database")
- err := r.prepareGeoIPDatabase()
- monitor.Finish()
- if err != nil {
- return err
- }
- }
- if r.needGeositeDatabase {
- monitor.Start("initialize geosite database")
- err := r.prepareGeositeDatabase()
- monitor.Finish()
- if err != nil {
- return err
- }
- }
- if r.needGeositeDatabase {
- for _, rule := range r.rules {
- err := rule.UpdateGeosite()
- if err != nil {
- r.logger.Error("failed to initialize geosite: ", err)
- }
- }
- for _, rule := range r.dnsRules {
- err := rule.UpdateGeosite()
- if err != nil {
- r.logger.Error("failed to initialize geosite: ", err)
- }
- }
- err := common.Close(r.geositeReader)
- if err != nil {
- return err
- }
- r.geositeCache = nil
- r.geositeReader = nil
- }
- if runtime.GOOS == "windows" {
- powerListener, err := winpowrprof.NewEventListener(r.notifyWindowsPowerEvent)
- if err == nil {
- r.powerListener = powerListener
- } else {
- r.logger.Warn("initialize power listener: ", err)
- }
- }
- if r.powerListener != nil {
- monitor.Start("start power listener")
- err := r.powerListener.Start()
- monitor.Finish()
- if err != nil {
- return E.Cause(err, "start power listener")
- }
- }
- monitor.Start("initialize DNS client")
- r.dnsClient.Start()
- monitor.Finish()
- if C.IsAndroid && r.platformInterface == nil {
- monitor.Start("initialize package manager")
- packageManager, err := tun.NewPackageManager(tun.PackageManagerOptions{
- Callback: r,
- Logger: r.logger,
- })
- monitor.Finish()
- if err != nil {
- return E.Cause(err, "create package manager")
- }
- if r.needPackageManager {
- monitor.Start("start package manager")
- err = packageManager.Start()
- monitor.Finish()
- if err != nil {
- return E.Cause(err, "start package manager")
- }
- }
- r.packageManager = packageManager
- }
- for i, rule := range r.dnsRules {
- monitor.Start("initialize DNS rule[", i, "]")
- err := rule.Start()
- monitor.Finish()
- if err != nil {
- return E.Cause(err, "initialize DNS rule[", i, "]")
- }
- }
- for i, transport := range r.transports {
- monitor.Start("initialize DNS transport[", i, "]")
- err := transport.Start()
- monitor.Finish()
- if err != nil {
- return E.Cause(err, "initialize DNS server[", i, "]")
- }
- }
- if r.timeService != nil {
- monitor.Start("initialize time service")
- err := r.timeService.Start()
- monitor.Finish()
- if err != nil {
- return E.Cause(err, "initialize time service")
- }
- }
- return nil
- }
- func (r *Router) Close() error {
- monitor := taskmonitor.New(r.logger, C.StopTimeout)
- var err error
- for i, rule := range r.rules {
- monitor.Start("close rule[", i, "]")
- err = E.Append(err, rule.Close(), func(err error) error {
- return E.Cause(err, "close rule[", i, "]")
- })
- monitor.Finish()
- }
- for i, rule := range r.dnsRules {
- monitor.Start("close dns rule[", i, "]")
- err = E.Append(err, rule.Close(), func(err error) error {
- return E.Cause(err, "close dns rule[", i, "]")
- })
- monitor.Finish()
- }
- for i, transport := range r.transports {
- monitor.Start("close dns transport[", i, "]")
- err = E.Append(err, transport.Close(), func(err error) error {
- return E.Cause(err, "close dns transport[", i, "]")
- })
- monitor.Finish()
- }
- if r.geoIPReader != nil {
- monitor.Start("close geoip reader")
- err = E.Append(err, r.geoIPReader.Close(), func(err error) error {
- return E.Cause(err, "close geoip reader")
- })
- monitor.Finish()
- }
- if r.interfaceMonitor != nil {
- monitor.Start("close interface monitor")
- err = E.Append(err, r.interfaceMonitor.Close(), func(err error) error {
- return E.Cause(err, "close interface monitor")
- })
- monitor.Finish()
- }
- if r.networkMonitor != nil {
- monitor.Start("close network monitor")
- err = E.Append(err, r.networkMonitor.Close(), func(err error) error {
- return E.Cause(err, "close network monitor")
- })
- monitor.Finish()
- }
- if r.packageManager != nil {
- monitor.Start("close package manager")
- err = E.Append(err, r.packageManager.Close(), func(err error) error {
- return E.Cause(err, "close package manager")
- })
- monitor.Finish()
- }
- if r.powerListener != nil {
- monitor.Start("close power listener")
- err = E.Append(err, r.powerListener.Close(), func(err error) error {
- return E.Cause(err, "close power listener")
- })
- monitor.Finish()
- }
- if r.timeService != nil {
- monitor.Start("close time service")
- err = E.Append(err, r.timeService.Close(), func(err error) error {
- return E.Cause(err, "close time service")
- })
- monitor.Finish()
- }
- if r.fakeIPStore != nil {
- monitor.Start("close fakeip store")
- err = E.Append(err, r.fakeIPStore.Close(), func(err error) error {
- return E.Cause(err, "close fakeip store")
- })
- monitor.Finish()
- }
- return err
- }
- func (r *Router) PostStart() error {
- monitor := taskmonitor.New(r.logger, C.StopTimeout)
- if len(r.ruleSets) > 0 {
- monitor.Start("initialize rule-set")
- ruleSetStartContext := NewRuleSetStartContext()
- var ruleSetStartGroup task.Group
- for i, ruleSet := range r.ruleSets {
- ruleSetInPlace := ruleSet
- ruleSetStartGroup.Append0(func(ctx context.Context) error {
- err := ruleSetInPlace.StartContext(ctx, ruleSetStartContext)
- if err != nil {
- return E.Cause(err, "initialize rule-set[", i, "]")
- }
- return nil
- })
- }
- ruleSetStartGroup.Concurrency(5)
- ruleSetStartGroup.FastFail()
- err := ruleSetStartGroup.Run(r.ctx)
- monitor.Finish()
- if err != nil {
- return err
- }
- ruleSetStartContext.Close()
- }
- needFindProcess := r.needFindProcess
- needWIFIState := r.needWIFIState
- for _, ruleSet := range r.ruleSets {
- metadata := ruleSet.Metadata()
- if metadata.ContainsProcessRule {
- needFindProcess = true
- }
- if metadata.ContainsWIFIRule {
- needWIFIState = true
- }
- }
- if C.IsAndroid && r.platformInterface == nil && !r.needPackageManager {
- if needFindProcess {
- monitor.Start("start package manager")
- err := r.packageManager.Start()
- monitor.Finish()
- if err != nil {
- return E.Cause(err, "start package manager")
- }
- } else {
- r.packageManager = nil
- }
- }
- if needFindProcess {
- if r.platformInterface != nil {
- r.processSearcher = r.platformInterface
- } else {
- monitor.Start("initialize process searcher")
- searcher, err := process.NewSearcher(process.Config{
- Logger: r.logger,
- PackageManager: r.packageManager,
- })
- monitor.Finish()
- if err != nil {
- if err != os.ErrInvalid {
- r.logger.Warn(E.Cause(err, "create process searcher"))
- }
- } else {
- r.processSearcher = searcher
- }
- }
- }
- if needWIFIState && r.platformInterface != nil {
- monitor.Start("initialize WIFI state")
- r.needWIFIState = true
- r.interfaceMonitor.RegisterCallback(func(_ int) {
- r.updateWIFIState()
- })
- r.updateWIFIState()
- monitor.Finish()
- }
- for i, rule := range r.rules {
- monitor.Start("initialize rule[", i, "]")
- err := rule.Start()
- monitor.Finish()
- if err != nil {
- return E.Cause(err, "initialize rule[", i, "]")
- }
- }
- for _, ruleSet := range r.ruleSets {
- monitor.Start("post start rule_set[", ruleSet.Name(), "]")
- err := ruleSet.PostStart()
- monitor.Finish()
- if err != nil {
- return E.Cause(err, "post start rule_set[", ruleSet.Name(), "]")
- }
- }
- r.started = true
- return nil
- }
- func (r *Router) Cleanup() error {
- for _, ruleSet := range r.ruleSetMap {
- ruleSet.Cleanup()
- }
- runtime.GC()
- return nil
- }
- func (r *Router) Outbound(tag string) (adapter.Outbound, bool) {
- outbound, loaded := r.outboundByTag[tag]
- return outbound, loaded
- }
- func (r *Router) DefaultOutbound(network string) (adapter.Outbound, error) {
- if network == N.NetworkTCP {
- if r.defaultOutboundForConnection == nil {
- return nil, E.New("missing default outbound for TCP connections")
- }
- return r.defaultOutboundForConnection, nil
- } else {
- if r.defaultOutboundForPacketConnection == nil {
- return nil, E.New("missing default outbound for UDP connections")
- }
- return r.defaultOutboundForPacketConnection, nil
- }
- }
- func (r *Router) FakeIPStore() adapter.FakeIPStore {
- return r.fakeIPStore
- }
- func (r *Router) RuleSet(tag string) (adapter.RuleSet, bool) {
- ruleSet, loaded := r.ruleSetMap[tag]
- return ruleSet, loaded
- }
- func (r *Router) NeedWIFIState() bool {
- return r.needWIFIState
- }
- func (r *Router) RouteConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error {
- if r.pauseManager.IsDevicePaused() {
- return E.New("reject connection to ", metadata.Destination, " while device paused")
- }
- if metadata.InboundDetour != "" {
- if metadata.LastInbound == metadata.InboundDetour {
- return E.New("routing loop on detour: ", metadata.InboundDetour)
- }
- detour := r.inboundByTag[metadata.InboundDetour]
- if detour == nil {
- return E.New("inbound detour not found: ", metadata.InboundDetour)
- }
- injectable, isInjectable := detour.(adapter.InjectableInbound)
- if !isInjectable {
- return E.New("inbound detour is not injectable: ", metadata.InboundDetour)
- }
- if !common.Contains(injectable.Network(), N.NetworkTCP) {
- return E.New("inject: TCP unsupported")
- }
- metadata.LastInbound = metadata.Inbound
- metadata.Inbound = metadata.InboundDetour
- metadata.InboundDetour = ""
- err := injectable.NewConnection(ctx, conn, metadata)
- if err != nil {
- return E.Cause(err, "inject ", detour.Tag())
- }
- return nil
- }
- conntrack.KillerCheck()
- metadata.Network = N.NetworkTCP
- switch metadata.Destination.Fqdn {
- case mux.Destination.Fqdn:
- return E.New("global multiplex is deprecated since sing-box v1.7.0, enable multiplex in inbound options instead.")
- case vmess.MuxDestination.Fqdn:
- return E.New("global multiplex (v2ray legacy) not supported since sing-box v1.7.0.")
- case uot.MagicAddress:
- return E.New("global UoT not supported since sing-box v1.7.0.")
- case uot.LegacyMagicAddress:
- return E.New("global UoT (legacy) not supported since sing-box v1.7.0.")
- }
- if r.fakeIPStore != nil && r.fakeIPStore.Contains(metadata.Destination.Addr) {
- domain, loaded := r.fakeIPStore.Lookup(metadata.Destination.Addr)
- if !loaded {
- return E.New("missing fakeip context")
- }
- metadata.OriginDestination = metadata.Destination
- metadata.Destination = M.Socksaddr{
- Fqdn: domain,
- Port: metadata.Destination.Port,
- }
- metadata.FakeIP = true
- r.logger.DebugContext(ctx, "found fakeip domain: ", domain)
- }
- if deadline.NeedAdditionalReadDeadline(conn) {
- conn = deadline.NewConn(conn)
- }
- if metadata.InboundOptions.SniffEnabled && !sniff.Skip(metadata) {
- buffer := buf.NewPacket()
- sniffMetadata, err := sniff.PeekStream(
- ctx,
- conn,
- buffer,
- time.Duration(metadata.InboundOptions.SniffTimeout),
- sniff.StreamDomainNameQuery,
- sniff.TLSClientHello,
- sniff.HTTPHost,
- sniff.BitTorrent,
- )
- if sniffMetadata != nil {
- metadata.Protocol = sniffMetadata.Protocol
- metadata.Domain = sniffMetadata.Domain
- if metadata.InboundOptions.SniffOverrideDestination && M.IsDomainName(metadata.Domain) {
- metadata.Destination = M.Socksaddr{
- Fqdn: metadata.Domain,
- Port: metadata.Destination.Port,
- }
- }
- if metadata.Domain != "" {
- r.logger.DebugContext(ctx, "sniffed protocol: ", metadata.Protocol, ", domain: ", metadata.Domain)
- } else {
- r.logger.DebugContext(ctx, "sniffed protocol: ", metadata.Protocol)
- }
- } else if err != nil {
- r.logger.TraceContext(ctx, "sniffed no protocol: ", err)
- }
- if !buffer.IsEmpty() {
- conn = bufio.NewCachedConn(conn, buffer)
- } else {
- buffer.Release()
- }
- }
- if r.dnsReverseMapping != nil && metadata.Domain == "" {
- domain, loaded := r.dnsReverseMapping.Query(metadata.Destination.Addr)
- if loaded {
- metadata.Domain = domain
- r.logger.DebugContext(ctx, "found reserve mapped domain: ", metadata.Domain)
- }
- }
- if metadata.Destination.IsFqdn() && dns.DomainStrategy(metadata.InboundOptions.DomainStrategy) != dns.DomainStrategyAsIS {
- addresses, err := r.Lookup(adapter.WithContext(ctx, &metadata), metadata.Destination.Fqdn, dns.DomainStrategy(metadata.InboundOptions.DomainStrategy))
- if err != nil {
- return err
- }
- metadata.DestinationAddresses = addresses
- r.dnsLogger.DebugContext(ctx, "resolved [", strings.Join(F.MapToString(metadata.DestinationAddresses), " "), "]")
- }
- if metadata.Destination.IsIPv4() {
- metadata.IPVersion = 4
- } else if metadata.Destination.IsIPv6() {
- metadata.IPVersion = 6
- }
- ctx, matchedRule, detour, err := r.match(ctx, &metadata, r.defaultOutboundForConnection)
- if err != nil {
- return err
- }
- if !common.Contains(detour.Network(), N.NetworkTCP) {
- return E.New("missing supported outbound, closing connection")
- }
- if r.clashServer != nil {
- trackerConn, tracker := r.clashServer.RoutedConnection(ctx, conn, metadata, matchedRule)
- defer tracker.Leave()
- conn = trackerConn
- }
- if r.v2rayServer != nil {
- if statsService := r.v2rayServer.StatsService(); statsService != nil {
- conn = statsService.RoutedConnection(metadata.Inbound, detour.Tag(), metadata.User, conn)
- }
- }
- return detour.NewConnection(ctx, conn, metadata)
- }
- func (r *Router) RoutePacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error {
- if r.pauseManager.IsDevicePaused() {
- return E.New("reject packet connection to ", metadata.Destination, " while device paused")
- }
- if metadata.InboundDetour != "" {
- if metadata.LastInbound == metadata.InboundDetour {
- return E.New("routing loop on detour: ", metadata.InboundDetour)
- }
- detour := r.inboundByTag[metadata.InboundDetour]
- if detour == nil {
- return E.New("inbound detour not found: ", metadata.InboundDetour)
- }
- injectable, isInjectable := detour.(adapter.InjectableInbound)
- if !isInjectable {
- return E.New("inbound detour is not injectable: ", metadata.InboundDetour)
- }
- if !common.Contains(injectable.Network(), N.NetworkUDP) {
- return E.New("inject: UDP unsupported")
- }
- metadata.LastInbound = metadata.Inbound
- metadata.Inbound = metadata.InboundDetour
- metadata.InboundDetour = ""
- err := injectable.NewPacketConnection(ctx, conn, metadata)
- if err != nil {
- return E.Cause(err, "inject ", detour.Tag())
- }
- return nil
- }
- conntrack.KillerCheck()
- metadata.Network = N.NetworkUDP
- if r.fakeIPStore != nil && r.fakeIPStore.Contains(metadata.Destination.Addr) {
- domain, loaded := r.fakeIPStore.Lookup(metadata.Destination.Addr)
- if !loaded {
- return E.New("missing fakeip context")
- }
- metadata.OriginDestination = metadata.Destination
- metadata.Destination = M.Socksaddr{
- Fqdn: domain,
- Port: metadata.Destination.Port,
- }
- metadata.FakeIP = true
- r.logger.DebugContext(ctx, "found fakeip domain: ", domain)
- }
- // Currently we don't have deadline usages for UDP connections
- /*if deadline.NeedAdditionalReadDeadline(conn) {
- conn = deadline.NewPacketConn(bufio.NewNetPacketConn(conn))
- }*/
- if metadata.InboundOptions.SniffEnabled || metadata.Destination.Addr.IsUnspecified() {
- var (
- buffer = buf.NewPacket()
- destination M.Socksaddr
- done = make(chan struct{})
- err error
- )
- go func() {
- sniffTimeout := C.ReadPayloadTimeout
- if metadata.InboundOptions.SniffTimeout > 0 {
- sniffTimeout = time.Duration(metadata.InboundOptions.SniffTimeout)
- }
- conn.SetReadDeadline(time.Now().Add(sniffTimeout))
- destination, err = conn.ReadPacket(buffer)
- conn.SetReadDeadline(time.Time{})
- close(done)
- }()
- select {
- case <-done:
- case <-ctx.Done():
- conn.Close()
- return ctx.Err()
- }
- if err != nil {
- buffer.Release()
- if !errors.Is(err, os.ErrDeadlineExceeded) {
- return err
- }
- } else {
- if metadata.Destination.Addr.IsUnspecified() {
- metadata.Destination = destination
- }
- if metadata.InboundOptions.SniffEnabled {
- sniffMetadata, _ := sniff.PeekPacket(
- ctx,
- buffer.Bytes(),
- sniff.DomainNameQuery,
- sniff.QUICClientHello,
- sniff.STUNMessage,
- sniff.UTP,
- sniff.UDPTracker,
- sniff.DTLSRecord,
- )
- if sniffMetadata != nil {
- metadata.Protocol = sniffMetadata.Protocol
- metadata.Domain = sniffMetadata.Domain
- if metadata.InboundOptions.SniffOverrideDestination && M.IsDomainName(metadata.Domain) {
- metadata.Destination = M.Socksaddr{
- Fqdn: metadata.Domain,
- Port: metadata.Destination.Port,
- }
- }
- if metadata.Domain != "" {
- r.logger.DebugContext(ctx, "sniffed packet protocol: ", metadata.Protocol, ", domain: ", metadata.Domain)
- } else {
- r.logger.DebugContext(ctx, "sniffed packet protocol: ", metadata.Protocol)
- }
- }
- }
- conn = bufio.NewCachedPacketConn(conn, buffer, destination)
- }
- }
- if r.dnsReverseMapping != nil && metadata.Domain == "" {
- domain, loaded := r.dnsReverseMapping.Query(metadata.Destination.Addr)
- if loaded {
- metadata.Domain = domain
- r.logger.DebugContext(ctx, "found reserve mapped domain: ", metadata.Domain)
- }
- }
- if metadata.Destination.IsFqdn() && dns.DomainStrategy(metadata.InboundOptions.DomainStrategy) != dns.DomainStrategyAsIS {
- addresses, err := r.Lookup(adapter.WithContext(ctx, &metadata), metadata.Destination.Fqdn, dns.DomainStrategy(metadata.InboundOptions.DomainStrategy))
- if err != nil {
- return err
- }
- metadata.DestinationAddresses = addresses
- r.dnsLogger.DebugContext(ctx, "resolved [", strings.Join(F.MapToString(metadata.DestinationAddresses), " "), "]")
- }
- if metadata.Destination.IsIPv4() {
- metadata.IPVersion = 4
- } else if metadata.Destination.IsIPv6() {
- metadata.IPVersion = 6
- }
- ctx, matchedRule, detour, err := r.match(ctx, &metadata, r.defaultOutboundForPacketConnection)
- if err != nil {
- return err
- }
- if !common.Contains(detour.Network(), N.NetworkUDP) {
- return E.New("missing supported outbound, closing packet connection")
- }
- if r.clashServer != nil {
- trackerConn, tracker := r.clashServer.RoutedPacketConnection(ctx, conn, metadata, matchedRule)
- defer tracker.Leave()
- conn = trackerConn
- }
- if r.v2rayServer != nil {
- if statsService := r.v2rayServer.StatsService(); statsService != nil {
- conn = statsService.RoutedPacketConnection(metadata.Inbound, detour.Tag(), metadata.User, conn)
- }
- }
- if metadata.FakeIP {
- conn = bufio.NewNATPacketConn(bufio.NewNetPacketConn(conn), metadata.OriginDestination, metadata.Destination)
- }
- return detour.NewPacketConnection(ctx, conn, metadata)
- }
- func (r *Router) match(ctx context.Context, metadata *adapter.InboundContext, defaultOutbound adapter.Outbound) (context.Context, adapter.Rule, adapter.Outbound, error) {
- matchRule, matchOutbound := r.match0(ctx, metadata, defaultOutbound)
- if contextOutbound, loaded := outbound.TagFromContext(ctx); loaded {
- if contextOutbound == matchOutbound.Tag() {
- return nil, nil, nil, E.New("connection loopback in outbound/", matchOutbound.Type(), "[", matchOutbound.Tag(), "]")
- }
- }
- ctx = outbound.ContextWithTag(ctx, matchOutbound.Tag())
- return ctx, matchRule, matchOutbound, nil
- }
- func (r *Router) match0(ctx context.Context, metadata *adapter.InboundContext, defaultOutbound adapter.Outbound) (adapter.Rule, adapter.Outbound) {
- if r.processSearcher != nil {
- var originDestination netip.AddrPort
- if metadata.OriginDestination.IsValid() {
- originDestination = metadata.OriginDestination.AddrPort()
- } else if metadata.Destination.IsIP() {
- originDestination = metadata.Destination.AddrPort()
- }
- processInfo, err := process.FindProcessInfo(r.processSearcher, ctx, metadata.Network, metadata.Source.AddrPort(), originDestination)
- if err != nil {
- r.logger.InfoContext(ctx, "failed to search process: ", err)
- } else {
- if processInfo.ProcessPath != "" {
- r.logger.InfoContext(ctx, "found process path: ", processInfo.ProcessPath)
- } else if processInfo.PackageName != "" {
- r.logger.InfoContext(ctx, "found package name: ", processInfo.PackageName)
- } else if processInfo.UserId != -1 {
- if /*needUserName &&*/ true {
- osUser, _ := user.LookupId(F.ToString(processInfo.UserId))
- if osUser != nil {
- processInfo.User = osUser.Username
- }
- }
- if processInfo.User != "" {
- r.logger.InfoContext(ctx, "found user: ", processInfo.User)
- } else {
- r.logger.InfoContext(ctx, "found user id: ", processInfo.UserId)
- }
- }
- metadata.ProcessInfo = processInfo
- }
- }
- for i, rule := range r.rules {
- metadata.ResetRuleCache()
- if rule.Match(metadata) {
- detour := rule.Outbound()
- r.logger.DebugContext(ctx, "match[", i, "] ", rule.String(), " => ", detour)
- if outbound, loaded := r.Outbound(detour); loaded {
- return rule, outbound
- }
- r.logger.ErrorContext(ctx, "outbound not found: ", detour)
- }
- }
- return nil, defaultOutbound
- }
- func (r *Router) InterfaceFinder() control.InterfaceFinder {
- return r.interfaceFinder
- }
- func (r *Router) UpdateInterfaces() error {
- if r.platformInterface == nil || !r.platformInterface.UsePlatformInterfaceGetter() {
- return r.interfaceFinder.Update()
- } else {
- interfaces, err := r.platformInterface.Interfaces()
- if err != nil {
- return err
- }
- r.interfaceFinder.UpdateInterfaces(interfaces)
- return nil
- }
- }
- func (r *Router) AutoDetectInterface() bool {
- return r.autoDetectInterface
- }
- func (r *Router) AutoDetectInterfaceFunc() control.Func {
- if r.platformInterface != nil && r.platformInterface.UsePlatformAutoDetectInterfaceControl() {
- return r.platformInterface.AutoDetectInterfaceControl()
- } else {
- if r.interfaceMonitor == nil {
- return nil
- }
- return control.BindToInterfaceFunc(r.InterfaceFinder(), func(network string, address string) (interfaceName string, interfaceIndex int, err error) {
- remoteAddr := M.ParseSocksaddr(address).Addr
- if C.IsLinux {
- interfaceName, interfaceIndex = r.InterfaceMonitor().DefaultInterface(remoteAddr)
- if interfaceIndex == -1 {
- err = tun.ErrNoRoute
- }
- } else {
- interfaceIndex = r.InterfaceMonitor().DefaultInterfaceIndex(remoteAddr)
- if interfaceIndex == -1 {
- err = tun.ErrNoRoute
- }
- }
- return
- })
- }
- }
- func (r *Router) RegisterAutoRedirectOutputMark(mark uint32) error {
- if r.autoRedirectOutputMark > 0 {
- return E.New("only one auto-redirect can be configured")
- }
- r.autoRedirectOutputMark = mark
- return nil
- }
- func (r *Router) AutoRedirectOutputMark() uint32 {
- return r.autoRedirectOutputMark
- }
- func (r *Router) DefaultInterface() string {
- return r.defaultInterface
- }
- func (r *Router) DefaultMark() uint32 {
- return r.defaultMark
- }
- func (r *Router) Rules() []adapter.Rule {
- return r.rules
- }
- func (r *Router) WIFIState() adapter.WIFIState {
- return r.wifiState
- }
- func (r *Router) NetworkMonitor() tun.NetworkUpdateMonitor {
- return r.networkMonitor
- }
- func (r *Router) InterfaceMonitor() tun.DefaultInterfaceMonitor {
- return r.interfaceMonitor
- }
- func (r *Router) PackageManager() tun.PackageManager {
- return r.packageManager
- }
- func (r *Router) ClashServer() adapter.ClashServer {
- return r.clashServer
- }
- func (r *Router) SetClashServer(server adapter.ClashServer) {
- r.clashServer = server
- }
- func (r *Router) V2RayServer() adapter.V2RayServer {
- return r.v2rayServer
- }
- func (r *Router) SetV2RayServer(server adapter.V2RayServer) {
- r.v2rayServer = server
- }
- func (r *Router) OnPackagesUpdated(packages int, sharedUsers int) {
- r.logger.Info("updated packages list: ", packages, " packages, ", sharedUsers, " shared users")
- }
- func (r *Router) NewError(ctx context.Context, err error) {
- common.Close(err)
- if E.IsClosedOrCanceled(err) {
- r.logger.DebugContext(ctx, "connection closed: ", err)
- return
- }
- r.logger.ErrorContext(ctx, err)
- }
- func (r *Router) notifyNetworkUpdate(event int) {
- if event == tun.EventNoRoute {
- r.pauseManager.NetworkPause()
- r.logger.Error("missing default interface")
- } else {
- r.pauseManager.NetworkWake()
- if C.IsAndroid && r.platformInterface == nil {
- var vpnStatus string
- if r.interfaceMonitor.AndroidVPNEnabled() {
- vpnStatus = "enabled"
- } else {
- vpnStatus = "disabled"
- }
- r.logger.Info("updated default interface ", r.interfaceMonitor.DefaultInterfaceName(netip.IPv4Unspecified()), ", index ", r.interfaceMonitor.DefaultInterfaceIndex(netip.IPv4Unspecified()), ", vpn ", vpnStatus)
- } else {
- r.logger.Info("updated default interface ", r.interfaceMonitor.DefaultInterfaceName(netip.IPv4Unspecified()), ", index ", r.interfaceMonitor.DefaultInterfaceIndex(netip.IPv4Unspecified()))
- }
- }
- if !r.started {
- return
- }
- _ = r.ResetNetwork()
- }
- func (r *Router) ResetNetwork() error {
- conntrack.Close()
- for _, outbound := range r.outbounds {
- listener, isListener := outbound.(adapter.InterfaceUpdateListener)
- if isListener {
- listener.InterfaceUpdated()
- }
- }
- for _, transport := range r.transports {
- transport.Reset()
- }
- return nil
- }
- func (r *Router) updateWIFIState() {
- if r.platformInterface == nil {
- return
- }
- state := r.platformInterface.ReadWIFIState()
- if state != r.wifiState {
- r.wifiState = state
- if state.SSID == "" && state.BSSID == "" {
- r.logger.Info("updated WIFI state: disconnected")
- } else {
- r.logger.Info("updated WIFI state: SSID=", state.SSID, ", BSSID=", state.BSSID)
- }
- }
- }
- func (r *Router) notifyWindowsPowerEvent(event int) {
- switch event {
- case winpowrprof.EVENT_SUSPEND:
- r.pauseManager.DevicePause()
- _ = r.ResetNetwork()
- case winpowrprof.EVENT_RESUME:
- if !r.pauseManager.IsDevicePaused() {
- return
- }
- fallthrough
- case winpowrprof.EVENT_RESUME_AUTOMATIC:
- r.pauseManager.DeviceWake()
- _ = r.ResetNetwork()
- }
- }
|