mirror of
https://github.com/SagerNet/sing-box.git
synced 2024-11-27 02:51:36 +00:00
refactor: Modular network manager
This commit is contained in:
parent
13e743412d
commit
d0f8ca034f
|
@ -52,13 +52,13 @@ func (m *Manager) Start(stage adapter.StartStage) error {
|
||||||
|
|
||||||
func (m *Manager) Close() error {
|
func (m *Manager) Close() error {
|
||||||
m.access.Lock()
|
m.access.Lock()
|
||||||
|
defer m.access.Unlock()
|
||||||
if !m.started {
|
if !m.started {
|
||||||
panic("not started")
|
return nil
|
||||||
}
|
}
|
||||||
m.started = false
|
m.started = false
|
||||||
inbounds := m.inbounds
|
inbounds := m.inbounds
|
||||||
m.inbounds = nil
|
m.inbounds = nil
|
||||||
m.access.Unlock()
|
|
||||||
monitor := taskmonitor.New(m.logger, C.StopTimeout)
|
monitor := taskmonitor.New(m.logger, C.StopTimeout)
|
||||||
var err error
|
var err error
|
||||||
for _, inbound := range inbounds {
|
for _, inbound := range inbounds {
|
||||||
|
|
23
adapter/network.go
Normal file
23
adapter/network.go
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
package adapter
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/sagernet/sing-tun"
|
||||||
|
"github.com/sagernet/sing/common/control"
|
||||||
|
)
|
||||||
|
|
||||||
|
type NetworkManager interface {
|
||||||
|
NewService
|
||||||
|
InterfaceFinder() control.InterfaceFinder
|
||||||
|
UpdateInterfaces() error
|
||||||
|
DefaultInterface() string
|
||||||
|
AutoDetectInterface() bool
|
||||||
|
AutoDetectInterfaceFunc() control.Func
|
||||||
|
DefaultMark() uint32
|
||||||
|
RegisterAutoRedirectOutputMark(mark uint32) error
|
||||||
|
AutoRedirectOutputMark() uint32
|
||||||
|
NetworkMonitor() tun.NetworkUpdateMonitor
|
||||||
|
InterfaceMonitor() tun.DefaultInterfaceMonitor
|
||||||
|
PackageManager() tun.PackageManager
|
||||||
|
WIFIState() WIFIState
|
||||||
|
ResetNetwork()
|
||||||
|
}
|
|
@ -48,16 +48,17 @@ func (m *Manager) Initialize(defaultOutboundFallback adapter.Outbound) {
|
||||||
|
|
||||||
func (m *Manager) Start(stage adapter.StartStage) error {
|
func (m *Manager) Start(stage adapter.StartStage) error {
|
||||||
m.access.Lock()
|
m.access.Lock()
|
||||||
defer m.access.Unlock()
|
|
||||||
if m.started && m.stage >= stage {
|
if m.started && m.stage >= stage {
|
||||||
panic("already started")
|
panic("already started")
|
||||||
}
|
}
|
||||||
m.started = true
|
m.started = true
|
||||||
m.stage = stage
|
m.stage = stage
|
||||||
|
outbounds := m.outbounds
|
||||||
|
m.access.Unlock()
|
||||||
if stage == adapter.StartStateStart {
|
if stage == adapter.StartStateStart {
|
||||||
m.startOutbounds()
|
return m.startOutbounds(outbounds)
|
||||||
} else {
|
} else {
|
||||||
for _, outbound := range m.outbounds {
|
for _, outbound := range outbounds {
|
||||||
err := adapter.LegacyStart(outbound, stage)
|
err := adapter.LegacyStart(outbound, stage)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return E.Cause(err, stage.Action(), " outbound/", outbound.Type(), "[", outbound.Tag(), "]")
|
return E.Cause(err, stage.Action(), " outbound/", outbound.Type(), "[", outbound.Tag(), "]")
|
||||||
|
@ -67,13 +68,13 @@ func (m *Manager) Start(stage adapter.StartStage) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Manager) startOutbounds() error {
|
func (m *Manager) startOutbounds(outbounds []adapter.Outbound) error {
|
||||||
monitor := taskmonitor.New(m.logger, C.StartTimeout)
|
monitor := taskmonitor.New(m.logger, C.StartTimeout)
|
||||||
started := make(map[string]bool)
|
started := make(map[string]bool)
|
||||||
for {
|
for {
|
||||||
canContinue := false
|
canContinue := false
|
||||||
startOne:
|
startOne:
|
||||||
for _, outboundToStart := range m.outbounds {
|
for _, outboundToStart := range outbounds {
|
||||||
outboundTag := outboundToStart.Tag()
|
outboundTag := outboundToStart.Tag()
|
||||||
if started[outboundTag] {
|
if started[outboundTag] {
|
||||||
continue
|
continue
|
||||||
|
@ -97,13 +98,13 @@ func (m *Manager) startOutbounds() error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(started) == len(m.outbounds) {
|
if len(started) == len(outbounds) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if canContinue {
|
if canContinue {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
currentOutbound := common.Find(m.outbounds, func(it adapter.Outbound) bool {
|
currentOutbound := common.Find(outbounds, func(it adapter.Outbound) bool {
|
||||||
return !started[it.Tag()]
|
return !started[it.Tag()]
|
||||||
})
|
})
|
||||||
var lintOutbound func(oTree []string, oCurrent adapter.Outbound) error
|
var lintOutbound func(oTree []string, oCurrent adapter.Outbound) error
|
||||||
|
@ -114,7 +115,9 @@ func (m *Manager) startOutbounds() error {
|
||||||
if common.Contains(oTree, problemOutboundTag) {
|
if common.Contains(oTree, problemOutboundTag) {
|
||||||
return E.New("circular outbound dependency: ", strings.Join(oTree, " -> "), " -> ", problemOutboundTag)
|
return E.New("circular outbound dependency: ", strings.Join(oTree, " -> "), " -> ", problemOutboundTag)
|
||||||
}
|
}
|
||||||
|
m.access.Lock()
|
||||||
problemOutbound := m.outboundByTag[problemOutboundTag]
|
problemOutbound := m.outboundByTag[problemOutboundTag]
|
||||||
|
m.access.Unlock()
|
||||||
if problemOutbound == nil {
|
if problemOutbound == nil {
|
||||||
return E.New("dependency[", problemOutboundTag, "] not found for outbound[", oCurrent.Tag(), "]")
|
return E.New("dependency[", problemOutboundTag, "] not found for outbound[", oCurrent.Tag(), "]")
|
||||||
}
|
}
|
||||||
|
@ -129,7 +132,8 @@ func (m *Manager) Close() error {
|
||||||
monitor := taskmonitor.New(m.logger, C.StopTimeout)
|
monitor := taskmonitor.New(m.logger, C.StopTimeout)
|
||||||
m.access.Lock()
|
m.access.Lock()
|
||||||
if !m.started {
|
if !m.started {
|
||||||
panic("not started")
|
m.access.Unlock()
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
m.started = false
|
m.started = false
|
||||||
outbounds := m.outbounds
|
outbounds := m.outbounds
|
||||||
|
|
|
@ -10,8 +10,6 @@ import (
|
||||||
"github.com/sagernet/sing-box/common/geoip"
|
"github.com/sagernet/sing-box/common/geoip"
|
||||||
C "github.com/sagernet/sing-box/constant"
|
C "github.com/sagernet/sing-box/constant"
|
||||||
"github.com/sagernet/sing-dns"
|
"github.com/sagernet/sing-dns"
|
||||||
"github.com/sagernet/sing-tun"
|
|
||||||
"github.com/sagernet/sing/common/control"
|
|
||||||
M "github.com/sagernet/sing/common/metadata"
|
M "github.com/sagernet/sing/common/metadata"
|
||||||
N "github.com/sagernet/sing/common/network"
|
N "github.com/sagernet/sing/common/network"
|
||||||
"github.com/sagernet/sing/common/x/list"
|
"github.com/sagernet/sing/common/x/list"
|
||||||
|
@ -31,28 +29,13 @@ type Router interface {
|
||||||
|
|
||||||
GeoIPReader() *geoip.Reader
|
GeoIPReader() *geoip.Reader
|
||||||
LoadGeosite(code string) (Rule, error)
|
LoadGeosite(code string) (Rule, error)
|
||||||
|
|
||||||
RuleSet(tag string) (RuleSet, bool)
|
RuleSet(tag string) (RuleSet, bool)
|
||||||
|
|
||||||
NeedWIFIState() bool
|
NeedWIFIState() bool
|
||||||
|
|
||||||
Exchange(ctx context.Context, message *mdns.Msg) (*mdns.Msg, error)
|
Exchange(ctx context.Context, message *mdns.Msg) (*mdns.Msg, error)
|
||||||
Lookup(ctx context.Context, domain string, strategy dns.DomainStrategy) ([]netip.Addr, error)
|
Lookup(ctx context.Context, domain string, strategy dns.DomainStrategy) ([]netip.Addr, error)
|
||||||
LookupDefault(ctx context.Context, domain string) ([]netip.Addr, error)
|
LookupDefault(ctx context.Context, domain string) ([]netip.Addr, error)
|
||||||
ClearDNSCache()
|
ClearDNSCache()
|
||||||
|
|
||||||
InterfaceFinder() control.InterfaceFinder
|
|
||||||
UpdateInterfaces() error
|
|
||||||
DefaultInterface() string
|
|
||||||
AutoDetectInterface() bool
|
|
||||||
AutoDetectInterfaceFunc() control.Func
|
|
||||||
DefaultMark() uint32
|
|
||||||
RegisterAutoRedirectOutputMark(mark uint32) error
|
|
||||||
AutoRedirectOutputMark() uint32
|
|
||||||
NetworkMonitor() tun.NetworkUpdateMonitor
|
|
||||||
InterfaceMonitor() tun.DefaultInterfaceMonitor
|
|
||||||
PackageManager() tun.PackageManager
|
|
||||||
WIFIState() WIFIState
|
|
||||||
Rules() []Rule
|
Rules() []Rule
|
||||||
|
|
||||||
ClashServer() ClashServer
|
ClashServer() ClashServer
|
||||||
|
@ -61,7 +44,7 @@ type Router interface {
|
||||||
V2RayServer() V2RayServer
|
V2RayServer() V2RayServer
|
||||||
SetV2RayServer(server V2RayServer)
|
SetV2RayServer(server V2RayServer)
|
||||||
|
|
||||||
ResetNetwork() error
|
ResetNetwork()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated: Use ConnectionRouterEx instead.
|
// Deprecated: Use ConnectionRouterEx instead.
|
||||||
|
|
56
box.go
56
box.go
|
@ -34,6 +34,7 @@ type Box struct {
|
||||||
router adapter.Router
|
router adapter.Router
|
||||||
inbound *inbound.Manager
|
inbound *inbound.Manager
|
||||||
outbound *outbound.Manager
|
outbound *outbound.Manager
|
||||||
|
network *route.NetworkManager
|
||||||
logFactory log.Factory
|
logFactory log.Factory
|
||||||
logger log.ContextLogger
|
logger log.ContextLogger
|
||||||
preServices1 map[string]adapter.Service
|
preServices1 map[string]adapter.Service
|
||||||
|
@ -109,20 +110,18 @@ func New(options Options) (*Box, error) {
|
||||||
return nil, E.Cause(err, "create log factory")
|
return nil, E.Cause(err, "create log factory")
|
||||||
}
|
}
|
||||||
routeOptions := common.PtrValueOrDefault(options.Route)
|
routeOptions := common.PtrValueOrDefault(options.Route)
|
||||||
inboundManager := inbound.NewManager(logFactory.NewLogger("inbound-manager"), inboundRegistry)
|
inboundManager := inbound.NewManager(logFactory.NewLogger("inbound"), inboundRegistry)
|
||||||
outboundManager := outbound.NewManager(logFactory.NewLogger("outbound-manager"), outboundRegistry, routeOptions.Final)
|
outboundManager := outbound.NewManager(logFactory.NewLogger("outbound"), outboundRegistry, routeOptions.Final)
|
||||||
ctx = service.ContextWith[adapter.InboundManager](ctx, inboundManager)
|
ctx = service.ContextWith[adapter.InboundManager](ctx, inboundManager)
|
||||||
ctx = service.ContextWith[adapter.OutboundManager](ctx, outboundManager)
|
ctx = service.ContextWith[adapter.OutboundManager](ctx, outboundManager)
|
||||||
router, err := route.NewRouter(
|
networkManager, err := route.NewNetworkManager(ctx, logFactory.NewLogger("network"), routeOptions)
|
||||||
ctx,
|
|
||||||
logFactory,
|
|
||||||
routeOptions,
|
|
||||||
common.PtrValueOrDefault(options.DNS),
|
|
||||||
common.PtrValueOrDefault(options.NTP),
|
|
||||||
options.Inbounds,
|
|
||||||
)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, E.Cause(err, "parse route options")
|
return nil, E.Cause(err, "initialize network manager")
|
||||||
|
}
|
||||||
|
ctx = service.ContextWith[adapter.NetworkManager](ctx, networkManager)
|
||||||
|
router, err := route.NewRouter(ctx, logFactory, routeOptions, common.PtrValueOrDefault(options.DNS), common.PtrValueOrDefault(options.NTP))
|
||||||
|
if err != nil {
|
||||||
|
return nil, E.Cause(err, "initialize router")
|
||||||
}
|
}
|
||||||
for i, inboundOptions := range options.Inbounds {
|
for i, inboundOptions := range options.Inbounds {
|
||||||
var tag string
|
var tag string
|
||||||
|
@ -177,11 +176,8 @@ func New(options Options) (*Box, error) {
|
||||||
option.DirectOutboundOptions{},
|
option.DirectOutboundOptions{},
|
||||||
),
|
),
|
||||||
))
|
))
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if platformInterface != nil {
|
if platformInterface != nil {
|
||||||
err = platformInterface.Initialize(ctx, router)
|
err = platformInterface.Initialize(networkManager)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, E.Cause(err, "initialize platform interface")
|
return nil, E.Cause(err, "initialize platform interface")
|
||||||
}
|
}
|
||||||
|
@ -219,6 +215,7 @@ func New(options Options) (*Box, error) {
|
||||||
router: router,
|
router: router,
|
||||||
inbound: inboundManager,
|
inbound: inboundManager,
|
||||||
outbound: outboundManager,
|
outbound: outboundManager,
|
||||||
|
network: networkManager,
|
||||||
createdAt: createdAt,
|
createdAt: createdAt,
|
||||||
logFactory: logFactory,
|
logFactory: logFactory,
|
||||||
logger: logFactory.Logger(),
|
logger: logFactory.Logger(),
|
||||||
|
@ -295,6 +292,10 @@ func (s *Box) preStart() error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
err = s.network.Start(adapter.StartStateInitialize)
|
||||||
|
if err != nil {
|
||||||
|
return E.Cause(err, "initialize network manager")
|
||||||
|
}
|
||||||
err = s.router.Start(adapter.StartStateInitialize)
|
err = s.router.Start(adapter.StartStateInitialize)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return E.Cause(err, "initialize router")
|
return E.Cause(err, "initialize router")
|
||||||
|
@ -303,6 +304,10 @@ func (s *Box) preStart() error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
err = s.network.Start(adapter.StartStateStart)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
return s.router.Start(adapter.StartStateStart)
|
return s.router.Start(adapter.StartStateStart)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -337,6 +342,10 @@ func (s *Box) start() error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
err = s.network.Start(adapter.StartStatePostStart)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
err = s.router.Start(adapter.StartStatePostStart)
|
err = s.router.Start(adapter.StartStatePostStart)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -345,6 +354,10 @@ func (s *Box) start() error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
err = s.network.Start(adapter.StartStateStarted)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
err = s.router.Start(adapter.StartStateStarted)
|
err = s.router.Start(adapter.StartStateStarted)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -378,13 +391,8 @@ func (s *Box) Close() error {
|
||||||
}
|
}
|
||||||
errors = E.Errors(errors, s.inbound.Close())
|
errors = E.Errors(errors, s.inbound.Close())
|
||||||
errors = E.Errors(errors, s.outbound.Close())
|
errors = E.Errors(errors, s.outbound.Close())
|
||||||
monitor.Start("close router")
|
errors = E.Errors(errors, s.network.Close())
|
||||||
if err := common.Close(s.router); err != nil {
|
errors = E.Errors(errors, s.router.Close())
|
||||||
errors = E.Append(errors, err, func(err error) error {
|
|
||||||
return E.Cause(err, "close router")
|
|
||||||
})
|
|
||||||
}
|
|
||||||
monitor.Finish()
|
|
||||||
for serviceName, service := range s.preServices1 {
|
for serviceName, service := range s.preServices1 {
|
||||||
monitor.Start("close ", serviceName)
|
monitor.Start("close ", serviceName)
|
||||||
errors = E.Append(errors, service.Close(), func(err error) error {
|
errors = E.Append(errors, service.Close(), func(err error) error {
|
||||||
|
@ -415,6 +423,10 @@ func (s *Box) Outbound() adapter.OutboundManager {
|
||||||
return s.outbound
|
return s.outbound
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Box) Network() adapter.NetworkManager {
|
||||||
|
return s.network
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Box) Router() adapter.Router {
|
func (s *Box) Router() adapter.Router {
|
||||||
return s.router
|
return s.router
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"context"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
@ -83,7 +84,7 @@ func ruleSetMatch(sourcePath string, domain string) error {
|
||||||
}
|
}
|
||||||
for i, ruleOptions := range plainRuleSet.Rules {
|
for i, ruleOptions := range plainRuleSet.Rules {
|
||||||
var currentRule adapter.HeadlessRule
|
var currentRule adapter.HeadlessRule
|
||||||
currentRule, err = rule.NewHeadlessRule(nil, ruleOptions)
|
currentRule, err = rule.NewHeadlessRule(context.Background(), ruleOptions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return E.Cause(err, "parse rule_set.rules.[", i, "]")
|
return E.Cause(err, "parse rule_set.rules.[", i, "]")
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,31 +29,31 @@ type DefaultDialer struct {
|
||||||
isWireGuardListener bool
|
isWireGuardListener bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDefault(router adapter.Router, options option.DialerOptions) (*DefaultDialer, error) {
|
func NewDefault(networkManager adapter.NetworkManager, options option.DialerOptions) (*DefaultDialer, error) {
|
||||||
var dialer net.Dialer
|
var dialer net.Dialer
|
||||||
var listener net.ListenConfig
|
var listener net.ListenConfig
|
||||||
if options.BindInterface != "" {
|
if options.BindInterface != "" {
|
||||||
var interfaceFinder control.InterfaceFinder
|
var interfaceFinder control.InterfaceFinder
|
||||||
if router != nil {
|
if networkManager != nil {
|
||||||
interfaceFinder = router.InterfaceFinder()
|
interfaceFinder = networkManager.InterfaceFinder()
|
||||||
} else {
|
} else {
|
||||||
interfaceFinder = control.NewDefaultInterfaceFinder()
|
interfaceFinder = control.NewDefaultInterfaceFinder()
|
||||||
}
|
}
|
||||||
bindFunc := control.BindToInterface(interfaceFinder, options.BindInterface, -1)
|
bindFunc := control.BindToInterface(interfaceFinder, options.BindInterface, -1)
|
||||||
dialer.Control = control.Append(dialer.Control, bindFunc)
|
dialer.Control = control.Append(dialer.Control, bindFunc)
|
||||||
listener.Control = control.Append(listener.Control, bindFunc)
|
listener.Control = control.Append(listener.Control, bindFunc)
|
||||||
} else if router != nil && router.AutoDetectInterface() {
|
} else if networkManager != nil && networkManager.AutoDetectInterface() {
|
||||||
bindFunc := router.AutoDetectInterfaceFunc()
|
bindFunc := networkManager.AutoDetectInterfaceFunc()
|
||||||
dialer.Control = control.Append(dialer.Control, bindFunc)
|
dialer.Control = control.Append(dialer.Control, bindFunc)
|
||||||
listener.Control = control.Append(listener.Control, bindFunc)
|
listener.Control = control.Append(listener.Control, bindFunc)
|
||||||
} else if router != nil && router.DefaultInterface() != "" {
|
} else if networkManager != nil && networkManager.DefaultInterface() != "" {
|
||||||
bindFunc := control.BindToInterface(router.InterfaceFinder(), router.DefaultInterface(), -1)
|
bindFunc := control.BindToInterface(networkManager.InterfaceFinder(), networkManager.DefaultInterface(), -1)
|
||||||
dialer.Control = control.Append(dialer.Control, bindFunc)
|
dialer.Control = control.Append(dialer.Control, bindFunc)
|
||||||
listener.Control = control.Append(listener.Control, bindFunc)
|
listener.Control = control.Append(listener.Control, bindFunc)
|
||||||
}
|
}
|
||||||
var autoRedirectOutputMark uint32
|
var autoRedirectOutputMark uint32
|
||||||
if router != nil {
|
if networkManager != nil {
|
||||||
autoRedirectOutputMark = router.AutoRedirectOutputMark()
|
autoRedirectOutputMark = networkManager.AutoRedirectOutputMark()
|
||||||
}
|
}
|
||||||
if autoRedirectOutputMark > 0 {
|
if autoRedirectOutputMark > 0 {
|
||||||
dialer.Control = control.Append(dialer.Control, control.RoutingMark(autoRedirectOutputMark))
|
dialer.Control = control.Append(dialer.Control, control.RoutingMark(autoRedirectOutputMark))
|
||||||
|
@ -65,9 +65,9 @@ func NewDefault(router adapter.Router, options option.DialerOptions) (*DefaultDi
|
||||||
if autoRedirectOutputMark > 0 {
|
if autoRedirectOutputMark > 0 {
|
||||||
return nil, E.New("`auto_redirect` with `route_[_exclude]_address_set is conflict with `routing_mark`")
|
return nil, E.New("`auto_redirect` with `route_[_exclude]_address_set is conflict with `routing_mark`")
|
||||||
}
|
}
|
||||||
} else if router != nil && router.DefaultMark() > 0 {
|
} else if networkManager != nil && networkManager.DefaultMark() > 0 {
|
||||||
dialer.Control = control.Append(dialer.Control, control.RoutingMark(router.DefaultMark()))
|
dialer.Control = control.Append(dialer.Control, control.RoutingMark(networkManager.DefaultMark()))
|
||||||
listener.Control = control.Append(listener.Control, control.RoutingMark(router.DefaultMark()))
|
listener.Control = control.Append(listener.Control, control.RoutingMark(networkManager.DefaultMark()))
|
||||||
if autoRedirectOutputMark > 0 {
|
if autoRedirectOutputMark > 0 {
|
||||||
return nil, E.New("`auto_redirect` with `route_[_exclude]_address_set is conflict with `default_mark`")
|
return nil, E.New("`auto_redirect` with `route_[_exclude]_address_set is conflict with `default_mark`")
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,16 +13,16 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func New(ctx context.Context, options option.DialerOptions) (N.Dialer, error) {
|
func New(ctx context.Context, options option.DialerOptions) (N.Dialer, error) {
|
||||||
router := service.FromContext[adapter.Router](ctx)
|
networkManager := service.FromContext[adapter.NetworkManager](ctx)
|
||||||
if options.IsWireGuardListener {
|
if options.IsWireGuardListener {
|
||||||
return NewDefault(router, options)
|
return NewDefault(networkManager, options)
|
||||||
}
|
}
|
||||||
var (
|
var (
|
||||||
dialer N.Dialer
|
dialer N.Dialer
|
||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
if options.Detour == "" {
|
if options.Detour == "" {
|
||||||
dialer, err = NewDefault(router, options)
|
dialer, err = NewDefault(networkManager, options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -33,16 +33,19 @@ func New(ctx context.Context, options option.DialerOptions) (N.Dialer, error) {
|
||||||
}
|
}
|
||||||
dialer = NewDetour(outboundManager, options.Detour)
|
dialer = NewDetour(outboundManager, options.Detour)
|
||||||
}
|
}
|
||||||
if router == nil {
|
if networkManager == nil {
|
||||||
return NewDefault(router, options)
|
return NewDefault(networkManager, options)
|
||||||
}
|
}
|
||||||
if options.Detour == "" {
|
if options.Detour == "" {
|
||||||
dialer = NewResolveDialer(
|
router := service.FromContext[adapter.Router](ctx)
|
||||||
router,
|
if router != nil {
|
||||||
dialer,
|
dialer = NewResolveDialer(
|
||||||
options.Detour == "" && !options.TCPFastOpen,
|
router,
|
||||||
dns.DomainStrategy(options.DomainStrategy),
|
dialer,
|
||||||
time.Duration(options.FallbackDelay))
|
options.Detour == "" && !options.TCPFastOpen,
|
||||||
|
dns.DomainStrategy(options.DomainStrategy),
|
||||||
|
time.Duration(options.FallbackDelay))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return dialer, nil
|
return dialer, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@ type DarwinSystemProxy struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSystemProxy(ctx context.Context, serverAddr M.Socksaddr, supportSOCKS bool) (*DarwinSystemProxy, error) {
|
func NewSystemProxy(ctx context.Context, serverAddr M.Socksaddr, supportSOCKS bool) (*DarwinSystemProxy, error) {
|
||||||
interfaceMonitor := service.FromContext[adapter.Router](ctx).InterfaceMonitor()
|
interfaceMonitor := service.FromContext[adapter.NetworkManager](ctx).InterfaceMonitor()
|
||||||
if interfaceMonitor == nil {
|
if interfaceMonitor == nil {
|
||||||
return nil, E.New("missing interface monitor")
|
return nil, E.New("missing interface monitor")
|
||||||
}
|
}
|
||||||
|
|
|
@ -109,7 +109,7 @@ func readGroups(reader io.Reader) (OutboundGroupIterator, error) {
|
||||||
func writeGroups(writer io.Writer, boxService *BoxService) error {
|
func writeGroups(writer io.Writer, boxService *BoxService) error {
|
||||||
historyStorage := service.PtrFromContext[urltest.HistoryStorage](boxService.ctx)
|
historyStorage := service.PtrFromContext[urltest.HistoryStorage](boxService.ctx)
|
||||||
cacheFile := service.FromContext[adapter.CacheFile](boxService.ctx)
|
cacheFile := service.FromContext[adapter.CacheFile](boxService.ctx)
|
||||||
outbounds := boxService.instance.Router().Outbounds()
|
outbounds := boxService.instance.Outbound().Outbounds()
|
||||||
var iGroups []adapter.OutboundGroup
|
var iGroups []adapter.OutboundGroup
|
||||||
for _, it := range outbounds {
|
for _, it := range outbounds {
|
||||||
if group, isGroup := it.(adapter.OutboundGroup); isGroup {
|
if group, isGroup := it.(adapter.OutboundGroup); isGroup {
|
||||||
|
@ -130,7 +130,7 @@ func writeGroups(writer io.Writer, boxService *BoxService) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, itemTag := range iGroup.All() {
|
for _, itemTag := range iGroup.All() {
|
||||||
itemOutbound, isLoaded := boxService.instance.Router().Outbound(itemTag)
|
itemOutbound, isLoaded := boxService.instance.Outbound().Outbound(itemTag)
|
||||||
if !isLoaded {
|
if !isLoaded {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,7 +43,7 @@ func (s *CommandServer) handleSelectOutbound(conn net.Conn) error {
|
||||||
if service == nil {
|
if service == nil {
|
||||||
return writeError(conn, E.New("service not ready"))
|
return writeError(conn, E.New("service not ready"))
|
||||||
}
|
}
|
||||||
outboundGroup, isLoaded := service.instance.Router().Outbound(groupTag)
|
outboundGroup, isLoaded := service.instance.Outbound().Outbound(groupTag)
|
||||||
if !isLoaded {
|
if !isLoaded {
|
||||||
return writeError(conn, E.New("selector not found: ", groupTag))
|
return writeError(conn, E.New("selector not found: ", groupTag))
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,7 +41,7 @@ func (s *CommandServer) handleURLTest(conn net.Conn) error {
|
||||||
if serviceNow == nil {
|
if serviceNow == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
abstractOutboundGroup, isLoaded := serviceNow.instance.Router().Outbound(groupTag)
|
abstractOutboundGroup, isLoaded := serviceNow.instance.Outbound().Outbound(groupTag)
|
||||||
if !isLoaded {
|
if !isLoaded {
|
||||||
return writeError(conn, E.New("outbound group not found: ", groupTag))
|
return writeError(conn, E.New("outbound group not found: ", groupTag))
|
||||||
}
|
}
|
||||||
|
@ -55,7 +55,7 @@ func (s *CommandServer) handleURLTest(conn net.Conn) error {
|
||||||
} else {
|
} else {
|
||||||
historyStorage := service.PtrFromContext[urltest.HistoryStorage](serviceNow.ctx)
|
historyStorage := service.PtrFromContext[urltest.HistoryStorage](serviceNow.ctx)
|
||||||
outbounds := common.Filter(common.Map(outboundGroup.All(), func(it string) adapter.Outbound {
|
outbounds := common.Filter(common.Map(outboundGroup.All(), func(it string) adapter.Outbound {
|
||||||
itOutbound, _ := serviceNow.instance.Router().Outbound(it)
|
itOutbound, _ := serviceNow.instance.Outbound().Outbound(it)
|
||||||
return itOutbound
|
return itOutbound
|
||||||
}), func(it adapter.Outbound) bool {
|
}), func(it adapter.Outbound) bool {
|
||||||
if it == nil {
|
if it == nil {
|
||||||
|
|
|
@ -50,7 +50,7 @@ func CheckConfig(configContent string) error {
|
||||||
|
|
||||||
type platformInterfaceStub struct{}
|
type platformInterfaceStub struct{}
|
||||||
|
|
||||||
func (s *platformInterfaceStub) Initialize(ctx context.Context, router adapter.Router) error {
|
func (s *platformInterfaceStub) Initialize(networkManager adapter.NetworkManager) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -115,7 +115,7 @@ func (m *platformDefaultInterfaceMonitor) UpdateDefaultInterface(interfaceName s
|
||||||
err = m.updateInterfaces()
|
err = m.updateInterfaces()
|
||||||
}
|
}
|
||||||
if err == nil {
|
if err == nil {
|
||||||
err = m.router.UpdateInterfaces()
|
err = m.networkManager.UpdateInterfaces()
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
m.logger.Error(E.Cause(err, "update interfaces"))
|
m.logger.Error(E.Cause(err, "update interfaces"))
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
package platform
|
package platform
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
|
|
||||||
"github.com/sagernet/sing-box/adapter"
|
"github.com/sagernet/sing-box/adapter"
|
||||||
"github.com/sagernet/sing-box/common/process"
|
"github.com/sagernet/sing-box/common/process"
|
||||||
"github.com/sagernet/sing-box/option"
|
"github.com/sagernet/sing-box/option"
|
||||||
|
@ -12,7 +10,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type Interface interface {
|
type Interface interface {
|
||||||
Initialize(ctx context.Context, router adapter.Router) error
|
Initialize(networkManager adapter.NetworkManager) error
|
||||||
UsePlatformAutoDetectInterfaceControl() bool
|
UsePlatformAutoDetectInterfaceControl() bool
|
||||||
AutoDetectInterfaceControl(fd int) error
|
AutoDetectInterfaceControl(fd int) error
|
||||||
OpenTun(options *tun.Options, platformOptions option.TunPlatformOptions) (tun.Tun, error)
|
OpenTun(options *tun.Options, platformOptions option.TunPlatformOptions) (tun.Tun, error)
|
||||||
|
|
|
@ -104,13 +104,13 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
type platformInterfaceWrapper struct {
|
type platformInterfaceWrapper struct {
|
||||||
iif PlatformInterface
|
iif PlatformInterface
|
||||||
useProcFS bool
|
useProcFS bool
|
||||||
router adapter.Router
|
networkManager adapter.NetworkManager
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *platformInterfaceWrapper) Initialize(ctx context.Context, router adapter.Router) error {
|
func (w *platformInterfaceWrapper) Initialize(networkManager adapter.NetworkManager) error {
|
||||||
w.router = router
|
w.networkManager = networkManager
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,5 +29,5 @@ func (s *BoxService) Wake() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *BoxService) ResetNetwork() {
|
func (s *BoxService) ResetNetwork() {
|
||||||
_ = s.instance.Router().ResetNetwork()
|
s.instance.Router().ResetNetwork()
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
experimental.RegisterClashServerConstructor(func(ctx context.Context, router adapter.Router, logFactory log.ObservableFactory, options option.ClashAPIOptions) (adapter.ClashServer, error) {
|
experimental.RegisterClashServerConstructor(func(ctx context.Context, logFactory log.ObservableFactory, options option.ClashAPIOptions) (adapter.ClashServer, error) {
|
||||||
return nil, E.New(`clash api is not included in this build, rebuild with -tags with_clash_api`)
|
return nil, E.New(`clash api is not included in this build, rebuild with -tags with_clash_api`)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,18 +11,18 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type loopBackDetector struct {
|
type loopBackDetector struct {
|
||||||
router adapter.Router
|
networkManager adapter.NetworkManager
|
||||||
connAccess sync.RWMutex
|
connAccess sync.RWMutex
|
||||||
packetConnAccess sync.RWMutex
|
packetConnAccess sync.RWMutex
|
||||||
connMap map[netip.AddrPort]netip.AddrPort
|
connMap map[netip.AddrPort]netip.AddrPort
|
||||||
packetConnMap map[uint16]uint16
|
packetConnMap map[uint16]uint16
|
||||||
}
|
}
|
||||||
|
|
||||||
func newLoopBackDetector(router adapter.Router) *loopBackDetector {
|
func newLoopBackDetector(networkManager adapter.NetworkManager) *loopBackDetector {
|
||||||
return &loopBackDetector{
|
return &loopBackDetector{
|
||||||
router: router,
|
networkManager: networkManager,
|
||||||
connMap: make(map[netip.AddrPort]netip.AddrPort),
|
connMap: make(map[netip.AddrPort]netip.AddrPort),
|
||||||
packetConnMap: make(map[uint16]uint16),
|
packetConnMap: make(map[uint16]uint16),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ func (l *loopBackDetector) NewConn(conn net.Conn) net.Conn {
|
||||||
}
|
}
|
||||||
if udpConn, isUDPConn := conn.(abstractUDPConn); isUDPConn {
|
if udpConn, isUDPConn := conn.(abstractUDPConn); isUDPConn {
|
||||||
if !source.Addr().IsLoopback() {
|
if !source.Addr().IsLoopback() {
|
||||||
_, err := l.router.InterfaceFinder().InterfaceByAddr(source.Addr())
|
_, err := l.networkManager.InterfaceFinder().InterfaceByAddr(source.Addr())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return conn
|
return conn
|
||||||
}
|
}
|
||||||
|
@ -59,7 +59,7 @@ func (l *loopBackDetector) NewPacketConn(conn N.NetPacketConn, destination M.Soc
|
||||||
return conn
|
return conn
|
||||||
}
|
}
|
||||||
if !source.Addr().IsLoopback() {
|
if !source.Addr().IsLoopback() {
|
||||||
_, err := l.router.InterfaceFinder().InterfaceByAddr(source.Addr())
|
_, err := l.networkManager.InterfaceFinder().InterfaceByAddr(source.Addr())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return conn
|
return conn
|
||||||
}
|
}
|
||||||
|
@ -82,7 +82,7 @@ func (l *loopBackDetector) CheckPacketConn(source netip.AddrPort, local netip.Ad
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if !source.Addr().IsLoopback() {
|
if !source.Addr().IsLoopback() {
|
||||||
_, err := l.router.InterfaceFinder().InterfaceByAddr(source.Addr())
|
_, err := l.networkManager.InterfaceFinder().InterfaceByAddr(source.Addr())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,10 +36,11 @@ func RegisterInbound(registry *inbound.Registry) {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Inbound struct {
|
type Inbound struct {
|
||||||
tag string
|
tag string
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
router adapter.Router
|
router adapter.Router
|
||||||
logger log.ContextLogger
|
networkManager adapter.NetworkManager
|
||||||
|
logger log.ContextLogger
|
||||||
// Deprecated
|
// Deprecated
|
||||||
inboundOptions option.InboundOptions
|
inboundOptions option.InboundOptions
|
||||||
tunOptions tun.Options
|
tunOptions tun.Options
|
||||||
|
@ -168,11 +169,12 @@ func NewInbound(ctx context.Context, router adapter.Router, logger log.ContextLo
|
||||||
if outputMark == 0 {
|
if outputMark == 0 {
|
||||||
outputMark = tun.DefaultAutoRedirectOutputMark
|
outputMark = tun.DefaultAutoRedirectOutputMark
|
||||||
}
|
}
|
||||||
|
networkManager := service.FromContext[adapter.NetworkManager](ctx)
|
||||||
inbound := &Inbound{
|
inbound := &Inbound{
|
||||||
tag: tag,
|
tag: tag,
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
router: router,
|
router: router,
|
||||||
|
networkManager: networkManager,
|
||||||
logger: logger,
|
logger: logger,
|
||||||
inboundOptions: options.InboundOptions,
|
inboundOptions: options.InboundOptions,
|
||||||
tunOptions: tun.Options{
|
tunOptions: tun.Options{
|
||||||
|
@ -198,7 +200,7 @@ func NewInbound(ctx context.Context, router adapter.Router, logger log.ContextLo
|
||||||
IncludeAndroidUser: options.IncludeAndroidUser,
|
IncludeAndroidUser: options.IncludeAndroidUser,
|
||||||
IncludePackage: options.IncludePackage,
|
IncludePackage: options.IncludePackage,
|
||||||
ExcludePackage: options.ExcludePackage,
|
ExcludePackage: options.ExcludePackage,
|
||||||
InterfaceMonitor: router.InterfaceMonitor(),
|
InterfaceMonitor: networkManager.InterfaceMonitor(),
|
||||||
},
|
},
|
||||||
endpointIndependentNat: options.EndpointIndependentNat,
|
endpointIndependentNat: options.EndpointIndependentNat,
|
||||||
udpTimeout: udpTimeout,
|
udpTimeout: udpTimeout,
|
||||||
|
@ -216,8 +218,8 @@ func NewInbound(ctx context.Context, router adapter.Router, logger log.ContextLo
|
||||||
Context: ctx,
|
Context: ctx,
|
||||||
Handler: (*autoRedirectHandler)(inbound),
|
Handler: (*autoRedirectHandler)(inbound),
|
||||||
Logger: logger,
|
Logger: logger,
|
||||||
NetworkMonitor: router.NetworkMonitor(),
|
NetworkMonitor: networkManager.NetworkMonitor(),
|
||||||
InterfaceFinder: router.InterfaceFinder(),
|
InterfaceFinder: networkManager.InterfaceFinder(),
|
||||||
TableName: "sing-box",
|
TableName: "sing-box",
|
||||||
DisableNFTables: dErr == nil && disableNFTables,
|
DisableNFTables: dErr == nil && disableNFTables,
|
||||||
RouteAddressSet: &inbound.routeAddressSet,
|
RouteAddressSet: &inbound.routeAddressSet,
|
||||||
|
@ -248,7 +250,7 @@ func NewInbound(ctx context.Context, router adapter.Router, logger log.ContextLo
|
||||||
}
|
}
|
||||||
if markMode {
|
if markMode {
|
||||||
inbound.tunOptions.AutoRedirectMarkMode = true
|
inbound.tunOptions.AutoRedirectMarkMode = true
|
||||||
err = router.RegisterAutoRedirectOutputMark(inbound.tunOptions.AutoRedirectOutputMark)
|
err = networkManager.RegisterAutoRedirectOutputMark(inbound.tunOptions.AutoRedirectOutputMark)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -300,7 +302,7 @@ func (t *Inbound) Tag() string {
|
||||||
|
|
||||||
func (t *Inbound) Start() error {
|
func (t *Inbound) Start() error {
|
||||||
if C.IsAndroid && t.platformInterface == nil {
|
if C.IsAndroid && t.platformInterface == nil {
|
||||||
t.tunOptions.BuildAndroidRules(t.router.PackageManager())
|
t.tunOptions.BuildAndroidRules(t.networkManager.PackageManager())
|
||||||
}
|
}
|
||||||
if t.tunOptions.Name == "" {
|
if t.tunOptions.Name == "" {
|
||||||
t.tunOptions.Name = tun.CalculateInterfaceName("")
|
t.tunOptions.Name = tun.CalculateInterfaceName("")
|
||||||
|
@ -338,7 +340,7 @@ func (t *Inbound) Start() error {
|
||||||
Handler: t,
|
Handler: t,
|
||||||
Logger: t.logger,
|
Logger: t.logger,
|
||||||
ForwarderBindInterface: forwarderBindInterface,
|
ForwarderBindInterface: forwarderBindInterface,
|
||||||
InterfaceFinder: t.router.InterfaceFinder(),
|
InterfaceFinder: t.networkManager.InterfaceFinder(),
|
||||||
IncludeAllNetworks: includeAllNetworks,
|
IncludeAllNetworks: includeAllNetworks,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -100,7 +100,7 @@ func NewOutbound(ctx context.Context, router adapter.Router, logger log.ContextL
|
||||||
if !options.SystemInterface && tun.WithGVisor {
|
if !options.SystemInterface && tun.WithGVisor {
|
||||||
wireTunDevice, err = wireguard.NewStackDevice(options.LocalAddress, mtu)
|
wireTunDevice, err = wireguard.NewStackDevice(options.LocalAddress, mtu)
|
||||||
} else {
|
} else {
|
||||||
wireTunDevice, err = wireguard.NewSystemDevice(router, options.InterfaceName, options.LocalAddress, mtu, options.GSO)
|
wireTunDevice, err = wireguard.NewSystemDevice(service.FromContext[adapter.NetworkManager](ctx), options.InterfaceName, options.LocalAddress, mtu, options.GSO)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, E.Cause(err, "create WireGuard device")
|
return nil, E.Cause(err, "create WireGuard device")
|
||||||
|
|
|
@ -33,7 +33,7 @@ func (r *Router) LoadGeosite(code string) (adapter.Rule, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
rule, err = R.NewDefaultRule(r.ctx, r, nil, geosite.Compile(items))
|
rule, err = R.NewDefaultRule(r.ctx, nil, geosite.Compile(items))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -145,13 +145,13 @@ func (r *Router) downloadGeoIPDatabase(savePath string) error {
|
||||||
r.logger.Info("downloading geoip database")
|
r.logger.Info("downloading geoip database")
|
||||||
var detour adapter.Outbound
|
var detour adapter.Outbound
|
||||||
if r.geoIPOptions.DownloadDetour != "" {
|
if r.geoIPOptions.DownloadDetour != "" {
|
||||||
outbound, loaded := r.Outbound(r.geoIPOptions.DownloadDetour)
|
outbound, loaded := r.outboundManager.Outbound(r.geoIPOptions.DownloadDetour)
|
||||||
if !loaded {
|
if !loaded {
|
||||||
return E.New("detour outbound not found: ", r.geoIPOptions.DownloadDetour)
|
return E.New("detour outbound not found: ", r.geoIPOptions.DownloadDetour)
|
||||||
}
|
}
|
||||||
detour = outbound
|
detour = outbound
|
||||||
} else {
|
} else {
|
||||||
detour = r.defaultOutboundForConnection
|
detour = r.outboundManager.Default()
|
||||||
}
|
}
|
||||||
|
|
||||||
if parentDir := filepath.Dir(savePath); parentDir != "" {
|
if parentDir := filepath.Dir(savePath); parentDir != "" {
|
||||||
|
@ -200,13 +200,13 @@ func (r *Router) downloadGeositeDatabase(savePath string) error {
|
||||||
r.logger.Info("downloading geosite database")
|
r.logger.Info("downloading geosite database")
|
||||||
var detour adapter.Outbound
|
var detour adapter.Outbound
|
||||||
if r.geositeOptions.DownloadDetour != "" {
|
if r.geositeOptions.DownloadDetour != "" {
|
||||||
outbound, loaded := r.Outbound(r.geositeOptions.DownloadDetour)
|
outbound, loaded := r.outboundManager.Outbound(r.geositeOptions.DownloadDetour)
|
||||||
if !loaded {
|
if !loaded {
|
||||||
return E.New("detour outbound not found: ", r.geositeOptions.DownloadDetour)
|
return E.New("detour outbound not found: ", r.geositeOptions.DownloadDetour)
|
||||||
}
|
}
|
||||||
detour = outbound
|
detour = outbound
|
||||||
} else {
|
} else {
|
||||||
detour = r.defaultOutboundForConnection
|
detour = r.outboundManager.Default()
|
||||||
}
|
}
|
||||||
|
|
||||||
if parentDir := filepath.Dir(savePath); parentDir != "" {
|
if parentDir := filepath.Dir(savePath); parentDir != "" {
|
||||||
|
|
337
route/network.go
Normal file
337
route/network.go
Normal file
|
@ -0,0 +1,337 @@
|
||||||
|
package route
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"net/netip"
|
||||||
|
"os"
|
||||||
|
"runtime"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
|
"github.com/sagernet/sing-box/adapter"
|
||||||
|
"github.com/sagernet/sing-box/common/conntrack"
|
||||||
|
"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/option"
|
||||||
|
"github.com/sagernet/sing-tun"
|
||||||
|
"github.com/sagernet/sing/common/control"
|
||||||
|
E "github.com/sagernet/sing/common/exceptions"
|
||||||
|
"github.com/sagernet/sing/common/logger"
|
||||||
|
M "github.com/sagernet/sing/common/metadata"
|
||||||
|
"github.com/sagernet/sing/common/winpowrprof"
|
||||||
|
"github.com/sagernet/sing/service"
|
||||||
|
"github.com/sagernet/sing/service/pause"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ adapter.NetworkManager = (*NetworkManager)(nil)
|
||||||
|
|
||||||
|
type NetworkManager struct {
|
||||||
|
logger logger.ContextLogger
|
||||||
|
interfaceFinder *control.DefaultInterfaceFinder
|
||||||
|
autoDetectInterface bool
|
||||||
|
defaultInterface string
|
||||||
|
defaultMark uint32
|
||||||
|
autoRedirectOutputMark uint32
|
||||||
|
networkMonitor tun.NetworkUpdateMonitor
|
||||||
|
interfaceMonitor tun.DefaultInterfaceMonitor
|
||||||
|
packageManager tun.PackageManager
|
||||||
|
powerListener winpowrprof.EventListener
|
||||||
|
pauseManager pause.Manager
|
||||||
|
platformInterface platform.Interface
|
||||||
|
outboundManager adapter.OutboundManager
|
||||||
|
wifiState adapter.WIFIState
|
||||||
|
started bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewNetworkManager(ctx context.Context, logger logger.ContextLogger, routeOptions option.RouteOptions) (*NetworkManager, error) {
|
||||||
|
nm := &NetworkManager{
|
||||||
|
logger: logger,
|
||||||
|
interfaceFinder: control.NewDefaultInterfaceFinder(),
|
||||||
|
autoDetectInterface: routeOptions.AutoDetectInterface,
|
||||||
|
defaultInterface: routeOptions.DefaultInterface,
|
||||||
|
defaultMark: routeOptions.DefaultMark,
|
||||||
|
pauseManager: service.FromContext[pause.Manager](ctx),
|
||||||
|
platformInterface: service.FromContext[platform.Interface](ctx),
|
||||||
|
outboundManager: service.FromContext[adapter.OutboundManager](ctx),
|
||||||
|
}
|
||||||
|
usePlatformDefaultInterfaceMonitor := nm.platformInterface != nil && nm.platformInterface.UsePlatformDefaultInterfaceMonitor()
|
||||||
|
enforceInterfaceMonitor := routeOptions.AutoDetectInterface
|
||||||
|
if !usePlatformDefaultInterfaceMonitor {
|
||||||
|
networkMonitor, err := tun.NewNetworkUpdateMonitor(logger)
|
||||||
|
if !((err != nil && !enforceInterfaceMonitor) || errors.Is(err, os.ErrInvalid)) {
|
||||||
|
if err != nil {
|
||||||
|
return nil, E.Cause(err, "create network monitor")
|
||||||
|
}
|
||||||
|
nm.networkMonitor = networkMonitor
|
||||||
|
networkMonitor.RegisterCallback(func() {
|
||||||
|
_ = nm.interfaceFinder.Update()
|
||||||
|
})
|
||||||
|
interfaceMonitor, err := tun.NewDefaultInterfaceMonitor(nm.networkMonitor, logger, tun.DefaultInterfaceMonitorOptions{
|
||||||
|
InterfaceFinder: nm.interfaceFinder,
|
||||||
|
OverrideAndroidVPN: routeOptions.OverrideAndroidVPN,
|
||||||
|
UnderNetworkExtension: nm.platformInterface != nil && nm.platformInterface.UnderNetworkExtension(),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, E.New("auto_detect_interface unsupported on current platform")
|
||||||
|
}
|
||||||
|
interfaceMonitor.RegisterCallback(nm.notifyNetworkUpdate)
|
||||||
|
nm.interfaceMonitor = interfaceMonitor
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
interfaceMonitor := nm.platformInterface.CreateDefaultInterfaceMonitor(logger)
|
||||||
|
interfaceMonitor.RegisterCallback(nm.notifyNetworkUpdate)
|
||||||
|
nm.interfaceMonitor = interfaceMonitor
|
||||||
|
}
|
||||||
|
return nm, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *NetworkManager) Start(stage adapter.StartStage) error {
|
||||||
|
monitor := taskmonitor.New(r.logger, C.StartTimeout)
|
||||||
|
switch stage {
|
||||||
|
case adapter.StartStateInitialize:
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case adapter.StartStateStart:
|
||||||
|
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")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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")
|
||||||
|
}
|
||||||
|
monitor.Start("start package manager")
|
||||||
|
err = packageManager.Start()
|
||||||
|
monitor.Finish()
|
||||||
|
if err != nil {
|
||||||
|
r.logger.Warn("initialize package manager: ", err)
|
||||||
|
} else {
|
||||||
|
r.packageManager = packageManager
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case adapter.StartStatePostStart:
|
||||||
|
r.started = true
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *NetworkManager) Close() error {
|
||||||
|
monitor := taskmonitor.New(r.logger, C.StopTimeout)
|
||||||
|
var err error
|
||||||
|
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()
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *NetworkManager) InterfaceFinder() control.InterfaceFinder {
|
||||||
|
return r.interfaceFinder
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *NetworkManager) 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 *NetworkManager) DefaultInterface() string {
|
||||||
|
return r.defaultInterface
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *NetworkManager) AutoDetectInterface() bool {
|
||||||
|
return r.autoDetectInterface
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *NetworkManager) AutoDetectInterfaceFunc() control.Func {
|
||||||
|
if r.platformInterface != nil && r.platformInterface.UsePlatformAutoDetectInterfaceControl() {
|
||||||
|
return func(network, address string, conn syscall.RawConn) error {
|
||||||
|
return control.Raw(conn, func(fd uintptr) error {
|
||||||
|
return r.platformInterface.AutoDetectInterfaceControl(int(fd))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} 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 *NetworkManager) DefaultMark() uint32 {
|
||||||
|
return r.defaultMark
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *NetworkManager) 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 *NetworkManager) AutoRedirectOutputMark() uint32 {
|
||||||
|
return r.autoRedirectOutputMark
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *NetworkManager) NetworkMonitor() tun.NetworkUpdateMonitor {
|
||||||
|
return r.networkMonitor
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *NetworkManager) InterfaceMonitor() tun.DefaultInterfaceMonitor {
|
||||||
|
return r.interfaceMonitor
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *NetworkManager) PackageManager() tun.PackageManager {
|
||||||
|
return r.packageManager
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *NetworkManager) WIFIState() adapter.WIFIState {
|
||||||
|
return r.wifiState
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *NetworkManager) ResetNetwork() {
|
||||||
|
conntrack.Close()
|
||||||
|
|
||||||
|
for _, outbound := range r.outboundManager.Outbounds() {
|
||||||
|
listener, isListener := outbound.(adapter.InterfaceUpdateListener)
|
||||||
|
if isListener {
|
||||||
|
listener.InterfaceUpdated()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *NetworkManager) 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.platformInterface != nil {
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !r.started {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
r.ResetNetwork()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *NetworkManager) 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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *NetworkManager) OnPackagesUpdated(packages int, sharedUsers int) {
|
||||||
|
r.logger.Info("updated packages list: ", packages, " packages, ", sharedUsers, " shared users")
|
||||||
|
}
|
|
@ -58,8 +58,8 @@ func (r *Router) routeConnection(ctx context.Context, conn net.Conn, metadata ad
|
||||||
if metadata.LastInbound == metadata.InboundDetour {
|
if metadata.LastInbound == metadata.InboundDetour {
|
||||||
return E.New("routing loop on detour: ", metadata.InboundDetour)
|
return E.New("routing loop on detour: ", metadata.InboundDetour)
|
||||||
}
|
}
|
||||||
detour := r.inboundByTag[metadata.InboundDetour]
|
detour, loaded := r.inboundManager.Get(metadata.InboundDetour)
|
||||||
if detour == nil {
|
if !loaded {
|
||||||
return E.New("inbound detour not found: ", metadata.InboundDetour)
|
return E.New("inbound detour not found: ", metadata.InboundDetour)
|
||||||
}
|
}
|
||||||
injectable, isInjectable := detour.(adapter.TCPInjectableInbound)
|
injectable, isInjectable := detour.(adapter.TCPInjectableInbound)
|
||||||
|
@ -100,7 +100,7 @@ func (r *Router) routeConnection(ctx context.Context, conn net.Conn, metadata ad
|
||||||
if selectedRule != nil {
|
if selectedRule != nil {
|
||||||
switch action := selectedRule.Action().(type) {
|
switch action := selectedRule.Action().(type) {
|
||||||
case *rule.RuleActionRoute:
|
case *rule.RuleActionRoute:
|
||||||
selectedOutbound, loaded := r.Outbound(action.Outbound)
|
selectedOutbound, loaded := r.outboundManager.Outbound(action.Outbound)
|
||||||
if !loaded {
|
if !loaded {
|
||||||
buf.ReleaseMulti(buffers)
|
buf.ReleaseMulti(buffers)
|
||||||
return E.New("outbound not found: ", action.Outbound)
|
return E.New("outbound not found: ", action.Outbound)
|
||||||
|
@ -128,13 +128,14 @@ func (r *Router) routeConnection(ctx context.Context, conn net.Conn, metadata ad
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if selectedRule == nil {
|
if selectedRule == nil {
|
||||||
if r.defaultOutboundForConnection == nil {
|
defaultOutbound := r.outboundManager.Default()
|
||||||
|
if !common.Contains(defaultOutbound.Network(), N.NetworkTCP) {
|
||||||
buf.ReleaseMulti(buffers)
|
buf.ReleaseMulti(buffers)
|
||||||
return E.New("missing default outbound with TCP support")
|
return E.New("TCP is not supported by default outbound: ", defaultOutbound.Tag())
|
||||||
}
|
}
|
||||||
selectedDialer = r.defaultOutboundForConnection
|
selectedDialer = defaultOutbound
|
||||||
selectedTag = r.defaultOutboundForConnection.Tag()
|
selectedTag = defaultOutbound.Tag()
|
||||||
selectedDescription = F.ToString("outbound/", r.defaultOutboundForConnection.Type(), "[", r.defaultOutboundForConnection.Tag(), "]")
|
selectedDescription = F.ToString("outbound/", defaultOutbound.Type(), "[", defaultOutbound.Tag(), "]")
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, buffer := range buffers {
|
for _, buffer := range buffers {
|
||||||
|
@ -217,8 +218,8 @@ func (r *Router) routePacketConnection(ctx context.Context, conn N.PacketConn, m
|
||||||
if metadata.LastInbound == metadata.InboundDetour {
|
if metadata.LastInbound == metadata.InboundDetour {
|
||||||
return E.New("routing loop on detour: ", metadata.InboundDetour)
|
return E.New("routing loop on detour: ", metadata.InboundDetour)
|
||||||
}
|
}
|
||||||
detour := r.inboundByTag[metadata.InboundDetour]
|
detour, loaded := r.inboundManager.Get(metadata.InboundDetour)
|
||||||
if detour == nil {
|
if !loaded {
|
||||||
return E.New("inbound detour not found: ", metadata.InboundDetour)
|
return E.New("inbound detour not found: ", metadata.InboundDetour)
|
||||||
}
|
}
|
||||||
injectable, isInjectable := detour.(adapter.UDPInjectableInbound)
|
injectable, isInjectable := detour.(adapter.UDPInjectableInbound)
|
||||||
|
@ -254,7 +255,7 @@ func (r *Router) routePacketConnection(ctx context.Context, conn N.PacketConn, m
|
||||||
if selectedRule != nil {
|
if selectedRule != nil {
|
||||||
switch action := selectedRule.Action().(type) {
|
switch action := selectedRule.Action().(type) {
|
||||||
case *rule.RuleActionRoute:
|
case *rule.RuleActionRoute:
|
||||||
selectedOutbound, loaded := r.Outbound(action.Outbound)
|
selectedOutbound, loaded := r.outboundManager.Outbound(action.Outbound)
|
||||||
if !loaded {
|
if !loaded {
|
||||||
N.ReleaseMultiPacketBuffer(packetBuffers)
|
N.ReleaseMultiPacketBuffer(packetBuffers)
|
||||||
return E.New("outbound not found: ", action.Outbound)
|
return E.New("outbound not found: ", action.Outbound)
|
||||||
|
@ -279,13 +280,14 @@ func (r *Router) routePacketConnection(ctx context.Context, conn N.PacketConn, m
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if selectedRule == nil || selectReturn {
|
if selectedRule == nil || selectReturn {
|
||||||
if r.defaultOutboundForPacketConnection == nil {
|
defaultOutbound := r.outboundManager.Default()
|
||||||
|
if !common.Contains(defaultOutbound.Network(), N.NetworkUDP) {
|
||||||
N.ReleaseMultiPacketBuffer(packetBuffers)
|
N.ReleaseMultiPacketBuffer(packetBuffers)
|
||||||
return E.New("missing default outbound with UDP support")
|
return E.New("UDP is not supported by outbound: ", defaultOutbound.Tag())
|
||||||
}
|
}
|
||||||
selectedDialer = r.defaultOutboundForPacketConnection
|
selectedDialer = defaultOutbound
|
||||||
selectedTag = r.defaultOutboundForPacketConnection.Tag()
|
selectedTag = defaultOutbound.Tag()
|
||||||
selectedDescription = F.ToString("outbound/", r.defaultOutboundForPacketConnection.Type(), "[", r.defaultOutboundForPacketConnection.Tag(), "]")
|
selectedDescription = F.ToString("outbound/", defaultOutbound.Type(), "[", defaultOutbound.Tag(), "]")
|
||||||
}
|
}
|
||||||
for _, buffer := range packetBuffers {
|
for _, buffer := range packetBuffers {
|
||||||
conn = bufio.NewCachedPacketConn(conn, buffer.Buffer, buffer.Destination)
|
conn = bufio.NewCachedPacketConn(conn, buffer.Buffer, buffer.Destination)
|
||||||
|
|
455
route/router.go
455
route/router.go
|
@ -2,17 +2,14 @@ package route
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
"net/netip"
|
"net/netip"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/sagernet/sing-box/adapter"
|
"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/dialer"
|
||||||
"github.com/sagernet/sing-box/common/geoip"
|
"github.com/sagernet/sing-box/common/geoip"
|
||||||
"github.com/sagernet/sing-box/common/geosite"
|
"github.com/sagernet/sing-box/common/geosite"
|
||||||
|
@ -25,16 +22,13 @@ import (
|
||||||
R "github.com/sagernet/sing-box/route/rule"
|
R "github.com/sagernet/sing-box/route/rule"
|
||||||
"github.com/sagernet/sing-box/transport/fakeip"
|
"github.com/sagernet/sing-box/transport/fakeip"
|
||||||
"github.com/sagernet/sing-dns"
|
"github.com/sagernet/sing-dns"
|
||||||
"github.com/sagernet/sing-tun"
|
|
||||||
"github.com/sagernet/sing/common"
|
"github.com/sagernet/sing/common"
|
||||||
"github.com/sagernet/sing/common/control"
|
|
||||||
E "github.com/sagernet/sing/common/exceptions"
|
E "github.com/sagernet/sing/common/exceptions"
|
||||||
F "github.com/sagernet/sing/common/format"
|
F "github.com/sagernet/sing/common/format"
|
||||||
M "github.com/sagernet/sing/common/metadata"
|
M "github.com/sagernet/sing/common/metadata"
|
||||||
N "github.com/sagernet/sing/common/network"
|
N "github.com/sagernet/sing/common/network"
|
||||||
"github.com/sagernet/sing/common/ntp"
|
"github.com/sagernet/sing/common/ntp"
|
||||||
"github.com/sagernet/sing/common/task"
|
"github.com/sagernet/sing/common/task"
|
||||||
"github.com/sagernet/sing/common/winpowrprof"
|
|
||||||
"github.com/sagernet/sing/service"
|
"github.com/sagernet/sing/service"
|
||||||
"github.com/sagernet/sing/service/pause"
|
"github.com/sagernet/sing/service/pause"
|
||||||
)
|
)
|
||||||
|
@ -42,69 +36,50 @@ import (
|
||||||
var _ adapter.Router = (*Router)(nil)
|
var _ adapter.Router = (*Router)(nil)
|
||||||
|
|
||||||
type Router struct {
|
type Router struct {
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
logger log.ContextLogger
|
logger log.ContextLogger
|
||||||
dnsLogger log.ContextLogger
|
dnsLogger log.ContextLogger
|
||||||
inboundByTag map[string]adapter.Inbound
|
inboundManager adapter.InboundManager
|
||||||
outbounds []adapter.Outbound
|
outboundManager adapter.OutboundManager
|
||||||
outboundByTag map[string]adapter.Outbound
|
networkManager adapter.NetworkManager
|
||||||
rules []adapter.Rule
|
rules []adapter.Rule
|
||||||
defaultDetour string
|
needGeoIPDatabase bool
|
||||||
defaultOutboundForConnection adapter.Outbound
|
needGeositeDatabase bool
|
||||||
defaultOutboundForPacketConnection adapter.Outbound
|
geoIPOptions option.GeoIPOptions
|
||||||
needGeoIPDatabase bool
|
geositeOptions option.GeositeOptions
|
||||||
needGeositeDatabase bool
|
geoIPReader *geoip.Reader
|
||||||
geoIPOptions option.GeoIPOptions
|
geositeReader *geosite.Reader
|
||||||
geositeOptions option.GeositeOptions
|
geositeCache map[string]adapter.Rule
|
||||||
geoIPReader *geoip.Reader
|
needFindProcess bool
|
||||||
geositeReader *geosite.Reader
|
dnsClient *dns.Client
|
||||||
geositeCache map[string]adapter.Rule
|
defaultDomainStrategy dns.DomainStrategy
|
||||||
needFindProcess bool
|
dnsRules []adapter.DNSRule
|
||||||
dnsClient *dns.Client
|
ruleSets []adapter.RuleSet
|
||||||
defaultDomainStrategy dns.DomainStrategy
|
ruleSetMap map[string]adapter.RuleSet
|
||||||
dnsRules []adapter.DNSRule
|
defaultTransport dns.Transport
|
||||||
ruleSets []adapter.RuleSet
|
transports []dns.Transport
|
||||||
ruleSetMap map[string]adapter.RuleSet
|
transportMap map[string]dns.Transport
|
||||||
defaultTransport dns.Transport
|
transportDomainStrategy map[dns.Transport]dns.DomainStrategy
|
||||||
transports []dns.Transport
|
dnsReverseMapping *DNSReverseMapping
|
||||||
transportMap map[string]dns.Transport
|
fakeIPStore adapter.FakeIPStore
|
||||||
transportDomainStrategy map[dns.Transport]dns.DomainStrategy
|
processSearcher process.Searcher
|
||||||
dnsReverseMapping *DNSReverseMapping
|
timeService *ntp.Service
|
||||||
fakeIPStore adapter.FakeIPStore
|
pauseManager pause.Manager
|
||||||
interfaceFinder *control.DefaultInterfaceFinder
|
clashServer adapter.ClashServer
|
||||||
autoDetectInterface bool
|
v2rayServer adapter.V2RayServer
|
||||||
defaultInterface string
|
platformInterface platform.Interface
|
||||||
defaultMark uint32
|
needWIFIState bool
|
||||||
autoRedirectOutputMark uint32
|
started bool
|
||||||
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
|
|
||||||
enforcePackageManager bool
|
|
||||||
wifiState adapter.WIFIState
|
|
||||||
started bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewRouter(
|
func NewRouter(ctx context.Context, logFactory log.Factory, options option.RouteOptions, dnsOptions option.DNSOptions, ntpOptions option.NTPOptions) (*Router, error) {
|
||||||
ctx context.Context,
|
|
||||||
logFactory log.Factory,
|
|
||||||
options option.RouteOptions,
|
|
||||||
dnsOptions option.DNSOptions,
|
|
||||||
ntpOptions option.NTPOptions,
|
|
||||||
inbounds []option.Inbound,
|
|
||||||
) (*Router, error) {
|
|
||||||
router := &Router{
|
router := &Router{
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
logger: logFactory.NewLogger("router"),
|
logger: logFactory.NewLogger("router"),
|
||||||
dnsLogger: logFactory.NewLogger("dns"),
|
dnsLogger: logFactory.NewLogger("dns"),
|
||||||
outboundByTag: make(map[string]adapter.Outbound),
|
inboundManager: service.FromContext[adapter.InboundManager](ctx),
|
||||||
|
outboundManager: service.FromContext[adapter.OutboundManager](ctx),
|
||||||
|
networkManager: service.FromContext[adapter.NetworkManager](ctx),
|
||||||
rules: make([]adapter.Rule, 0, len(options.Rules)),
|
rules: make([]adapter.Rule, 0, len(options.Rules)),
|
||||||
dnsRules: make([]adapter.DNSRule, 0, len(dnsOptions.Rules)),
|
dnsRules: make([]adapter.DNSRule, 0, len(dnsOptions.Rules)),
|
||||||
ruleSetMap: make(map[string]adapter.RuleSet),
|
ruleSetMap: make(map[string]adapter.RuleSet),
|
||||||
|
@ -114,22 +89,12 @@ func NewRouter(
|
||||||
geositeOptions: common.PtrValueOrDefault(options.Geosite),
|
geositeOptions: common.PtrValueOrDefault(options.Geosite),
|
||||||
geositeCache: make(map[string]adapter.Rule),
|
geositeCache: make(map[string]adapter.Rule),
|
||||||
needFindProcess: hasRule(options.Rules, isProcessRule) || hasDNSRule(dnsOptions.Rules, isProcessDNSRule) || options.FindProcess,
|
needFindProcess: hasRule(options.Rules, isProcessRule) || hasDNSRule(dnsOptions.Rules, isProcessDNSRule) || options.FindProcess,
|
||||||
defaultDetour: options.Final,
|
|
||||||
defaultDomainStrategy: dns.DomainStrategy(dnsOptions.Strategy),
|
defaultDomainStrategy: dns.DomainStrategy(dnsOptions.Strategy),
|
||||||
interfaceFinder: control.NewDefaultInterfaceFinder(),
|
|
||||||
autoDetectInterface: options.AutoDetectInterface,
|
|
||||||
defaultInterface: options.DefaultInterface,
|
|
||||||
defaultMark: options.DefaultMark,
|
|
||||||
pauseManager: service.FromContext[pause.Manager](ctx),
|
pauseManager: service.FromContext[pause.Manager](ctx),
|
||||||
platformInterface: service.FromContext[platform.Interface](ctx),
|
platformInterface: service.FromContext[platform.Interface](ctx),
|
||||||
needWIFIState: hasRule(options.Rules, isWIFIRule) || hasDNSRule(dnsOptions.Rules, isWIFIDNSRule),
|
needWIFIState: hasRule(options.Rules, isWIFIRule) || hasDNSRule(dnsOptions.Rules, isWIFIDNSRule),
|
||||||
enforcePackageManager: common.Any(inbounds, func(inbound option.Inbound) bool {
|
|
||||||
if tunOptions, isTUN := inbound.Options.(*option.TunInboundOptions); isTUN && tunOptions.AutoRoute {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}),
|
|
||||||
}
|
}
|
||||||
|
ctx = service.ContextWith[adapter.Router](ctx, router)
|
||||||
router.dnsClient = dns.NewClient(dns.ClientOptions{
|
router.dnsClient = dns.NewClient(dns.ClientOptions{
|
||||||
DisableCache: dnsOptions.DNSClientOptions.DisableCache,
|
DisableCache: dnsOptions.DNSClientOptions.DisableCache,
|
||||||
DisableExpire: dnsOptions.DNSClientOptions.DisableExpire,
|
DisableExpire: dnsOptions.DNSClientOptions.DisableExpire,
|
||||||
|
@ -147,14 +112,14 @@ func NewRouter(
|
||||||
Logger: router.dnsLogger,
|
Logger: router.dnsLogger,
|
||||||
})
|
})
|
||||||
for i, ruleOptions := range options.Rules {
|
for i, ruleOptions := range options.Rules {
|
||||||
routeRule, err := R.NewRule(ctx, router, router.logger, ruleOptions, true)
|
routeRule, err := R.NewRule(ctx, router.logger, ruleOptions, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, E.Cause(err, "parse rule[", i, "]")
|
return nil, E.Cause(err, "parse rule[", i, "]")
|
||||||
}
|
}
|
||||||
router.rules = append(router.rules, routeRule)
|
router.rules = append(router.rules, routeRule)
|
||||||
}
|
}
|
||||||
for i, dnsRuleOptions := range dnsOptions.Rules {
|
for i, dnsRuleOptions := range dnsOptions.Rules {
|
||||||
dnsRule, err := R.NewDNSRule(ctx, router, router.logger, dnsRuleOptions, true)
|
dnsRule, err := R.NewDNSRule(ctx, router.logger, dnsRuleOptions, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, E.Cause(err, "parse dns rule[", i, "]")
|
return nil, E.Cause(err, "parse dns rule[", i, "]")
|
||||||
}
|
}
|
||||||
|
@ -164,7 +129,7 @@ func NewRouter(
|
||||||
if _, exists := router.ruleSetMap[ruleSetOptions.Tag]; exists {
|
if _, exists := router.ruleSetMap[ruleSetOptions.Tag]; exists {
|
||||||
return nil, E.New("duplicate rule-set tag: ", ruleSetOptions.Tag)
|
return nil, E.New("duplicate rule-set tag: ", ruleSetOptions.Tag)
|
||||||
}
|
}
|
||||||
ruleSet, err := R.NewRuleSet(ctx, router, router.logger, ruleSetOptions)
|
ruleSet, err := R.NewRuleSet(ctx, router.logger, ruleSetOptions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, E.Cause(err, "parse rule-set[", i, "]")
|
return nil, E.Cause(err, "parse rule-set[", i, "]")
|
||||||
}
|
}
|
||||||
|
@ -191,7 +156,6 @@ func NewRouter(
|
||||||
transportTags[i] = tag
|
transportTags[i] = tag
|
||||||
transportTagMap[tag] = true
|
transportTagMap[tag] = true
|
||||||
}
|
}
|
||||||
ctx = service.ContextWith[adapter.Router](ctx, router)
|
|
||||||
outboundManager := service.FromContext[adapter.OutboundManager](ctx)
|
outboundManager := service.FromContext[adapter.OutboundManager](ctx)
|
||||||
for {
|
for {
|
||||||
lastLen := len(dummyTransportMap)
|
lastLen := len(dummyTransportMap)
|
||||||
|
@ -298,7 +262,7 @@ func NewRouter(
|
||||||
Context: ctx,
|
Context: ctx,
|
||||||
Name: "local",
|
Name: "local",
|
||||||
Address: "local",
|
Address: "local",
|
||||||
Dialer: common.Must1(dialer.NewDefault(router, option.DialerOptions{})),
|
Dialer: common.Must1(dialer.NewDefault(router.networkManager, option.DialerOptions{})),
|
||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
defaultTransport = transports[0]
|
defaultTransport = transports[0]
|
||||||
|
@ -327,44 +291,6 @@ func NewRouter(
|
||||||
router.fakeIPStore = fakeip.NewStore(ctx, router.logger, inet4Range, inet6Range)
|
router.fakeIPStore = fakeip.NewStore(ctx, router.logger, inet4Range, inet6Range)
|
||||||
}
|
}
|
||||||
|
|
||||||
usePlatformDefaultInterfaceMonitor := router.platformInterface != nil && router.platformInterface.UsePlatformDefaultInterfaceMonitor()
|
|
||||||
enforceInterfaceMonitor := options.AutoDetectInterface || common.Any(inbounds, func(inbound option.Inbound) bool {
|
|
||||||
if httpMixedOptions, isHTTPMixed := inbound.Options.(*option.HTTPMixedInboundOptions); isHTTPMixed && httpMixedOptions.SetSystemProxy {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if tunOptions, isTUN := inbound.Options.(*option.TunInboundOptions); isTUN && tunOptions.AutoRoute {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
})
|
|
||||||
|
|
||||||
if !usePlatformDefaultInterfaceMonitor {
|
|
||||||
networkMonitor, err := tun.NewNetworkUpdateMonitor(router.logger)
|
|
||||||
if !((err != nil && !enforceInterfaceMonitor) || 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{
|
|
||||||
InterfaceFinder: router.interfaceFinder,
|
|
||||||
OverrideAndroidVPN: options.OverrideAndroidVPN,
|
|
||||||
UnderNetworkExtension: router.platformInterface != nil && router.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 := router.platformInterface.CreateDefaultInterfaceMonitor(router.logger)
|
|
||||||
interfaceMonitor.RegisterCallback(router.notifyNetworkUpdate)
|
|
||||||
router.interfaceMonitor = interfaceMonitor
|
|
||||||
}
|
|
||||||
|
|
||||||
if ntpOptions.Enabled {
|
if ntpOptions.Enabled {
|
||||||
ntpDialer, err := dialer.New(ctx, ntpOptions.DialerOptions)
|
ntpDialer, err := dialer.New(ctx, ntpOptions.DialerOptions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -384,33 +310,10 @@ func NewRouter(
|
||||||
return router, nil
|
return router, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Router) Outbounds() []adapter.Outbound {
|
|
||||||
if !r.started {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return r.outbounds
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Router) Start(stage adapter.StartStage) error {
|
func (r *Router) Start(stage adapter.StartStage) error {
|
||||||
monitor := taskmonitor.New(r.logger, C.StartTimeout)
|
monitor := taskmonitor.New(r.logger, C.StartTimeout)
|
||||||
switch stage {
|
switch stage {
|
||||||
case adapter.StartStateInitialize:
|
case adapter.StartStateInitialize:
|
||||||
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 {
|
if r.fakeIPStore != nil {
|
||||||
monitor.Start("initialize fakeip store")
|
monitor.Start("initialize fakeip store")
|
||||||
err := r.fakeIPStore.Start()
|
err := r.fakeIPStore.Start()
|
||||||
|
@ -457,49 +360,10 @@ func (r *Router) Start(stage adapter.StartStage) error {
|
||||||
r.geositeReader = 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")
|
monitor.Start("initialize DNS client")
|
||||||
r.dnsClient.Start()
|
r.dnsClient.Start()
|
||||||
monitor.Finish()
|
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.enforcePackageManager {
|
|
||||||
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 {
|
for i, rule := range r.dnsRules {
|
||||||
monitor.Start("initialize DNS rule[", i, "]")
|
monitor.Start("initialize DNS rule[", i, "]")
|
||||||
err := rule.Start()
|
err := rule.Start()
|
||||||
|
@ -552,26 +416,13 @@ func (r *Router) Start(stage adapter.StartStage) error {
|
||||||
cacheContext.Close()
|
cacheContext.Close()
|
||||||
}
|
}
|
||||||
needFindProcess := r.needFindProcess
|
needFindProcess := r.needFindProcess
|
||||||
needWIFIState := r.needWIFIState
|
|
||||||
for _, ruleSet := range r.ruleSets {
|
for _, ruleSet := range r.ruleSets {
|
||||||
metadata := ruleSet.Metadata()
|
metadata := ruleSet.Metadata()
|
||||||
if metadata.ContainsProcessRule {
|
if metadata.ContainsProcessRule {
|
||||||
needFindProcess = true
|
needFindProcess = true
|
||||||
}
|
}
|
||||||
if metadata.ContainsWIFIRule {
|
if metadata.ContainsWIFIRule {
|
||||||
needWIFIState = true
|
r.needWIFIState = true
|
||||||
}
|
|
||||||
}
|
|
||||||
if C.IsAndroid && r.platformInterface == nil && !r.enforcePackageManager {
|
|
||||||
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 needFindProcess {
|
||||||
|
@ -581,7 +432,7 @@ func (r *Router) Start(stage adapter.StartStage) error {
|
||||||
monitor.Start("initialize process searcher")
|
monitor.Start("initialize process searcher")
|
||||||
searcher, err := process.NewSearcher(process.Config{
|
searcher, err := process.NewSearcher(process.Config{
|
||||||
Logger: r.logger,
|
Logger: r.logger,
|
||||||
PackageManager: r.packageManager,
|
PackageManager: r.networkManager.PackageManager(),
|
||||||
})
|
})
|
||||||
monitor.Finish()
|
monitor.Finish()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -593,15 +444,6 @@ func (r *Router) Start(stage adapter.StartStage) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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 {
|
for i, rule := range r.rules {
|
||||||
monitor.Start("initialize rule[", i, "]")
|
monitor.Start("initialize rule[", i, "]")
|
||||||
err := rule.Start()
|
err := rule.Start()
|
||||||
|
@ -660,34 +502,6 @@ func (r *Router) Close() error {
|
||||||
})
|
})
|
||||||
monitor.Finish()
|
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 {
|
if r.timeService != nil {
|
||||||
monitor.Start("close time service")
|
monitor.Start("close time service")
|
||||||
err = E.Append(err, r.timeService.Close(), func(err error) error {
|
err = E.Append(err, r.timeService.Close(), func(err error) error {
|
||||||
|
@ -705,25 +519,6 @@ func (r *Router) Close() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
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 {
|
func (r *Router) FakeIPStore() adapter.FakeIPStore {
|
||||||
return r.fakeIPStore
|
return r.fakeIPStore
|
||||||
}
|
}
|
||||||
|
@ -737,96 +532,10 @@ func (r *Router) NeedWIFIState() bool {
|
||||||
return r.needWIFIState
|
return r.needWIFIState
|
||||||
}
|
}
|
||||||
|
|
||||||
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 func(network, address string, conn syscall.RawConn) error {
|
|
||||||
return control.Raw(conn, func(fd uintptr) error {
|
|
||||||
return r.platformInterface.AutoDetectInterfaceControl(int(fd))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
} 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 {
|
func (r *Router) Rules() []adapter.Rule {
|
||||||
return r.rules
|
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 {
|
func (r *Router) ClashServer() adapter.ClashServer {
|
||||||
return r.clashServer
|
return r.clashServer
|
||||||
}
|
}
|
||||||
|
@ -843,10 +552,6 @@ func (r *Router) SetV2RayServer(server adapter.V2RayServer) {
|
||||||
r.v2rayServer = server
|
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) {
|
func (r *Router) NewError(ctx context.Context, err error) {
|
||||||
common.Close(err)
|
common.Close(err)
|
||||||
if E.IsClosedOrCanceled(err) {
|
if E.IsClosedOrCanceled(err) {
|
||||||
|
@ -856,75 +561,9 @@ func (r *Router) NewError(ctx context.Context, err error) {
|
||||||
r.logger.ErrorContext(ctx, err)
|
r.logger.ErrorContext(ctx, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Router) notifyNetworkUpdate(event int) {
|
func (r *Router) ResetNetwork() {
|
||||||
if event == tun.EventNoRoute {
|
r.networkManager.ResetNetwork()
|
||||||
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 {
|
for _, transport := range r.transports {
|
||||||
transport.Reset()
|
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()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,9 +9,10 @@ import (
|
||||||
"github.com/sagernet/sing-box/log"
|
"github.com/sagernet/sing-box/log"
|
||||||
"github.com/sagernet/sing-box/option"
|
"github.com/sagernet/sing-box/option"
|
||||||
E "github.com/sagernet/sing/common/exceptions"
|
E "github.com/sagernet/sing/common/exceptions"
|
||||||
|
"github.com/sagernet/sing/service"
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewRule(ctx context.Context, router adapter.Router, logger log.ContextLogger, options option.Rule, checkOutbound bool) (adapter.Rule, error) {
|
func NewRule(ctx context.Context, logger log.ContextLogger, options option.Rule, checkOutbound bool) (adapter.Rule, error) {
|
||||||
switch options.Type {
|
switch options.Type {
|
||||||
case "", C.RuleTypeDefault:
|
case "", C.RuleTypeDefault:
|
||||||
if !options.DefaultOptions.IsValid() {
|
if !options.DefaultOptions.IsValid() {
|
||||||
|
@ -23,7 +24,7 @@ func NewRule(ctx context.Context, router adapter.Router, logger log.ContextLogge
|
||||||
return nil, E.New("missing outbound field")
|
return nil, E.New("missing outbound field")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NewDefaultRule(ctx, router, logger, options.DefaultOptions)
|
return NewDefaultRule(ctx, logger, options.DefaultOptions)
|
||||||
case C.RuleTypeLogical:
|
case C.RuleTypeLogical:
|
||||||
if !options.LogicalOptions.IsValid() {
|
if !options.LogicalOptions.IsValid() {
|
||||||
return nil, E.New("missing conditions")
|
return nil, E.New("missing conditions")
|
||||||
|
@ -34,7 +35,7 @@ func NewRule(ctx context.Context, router adapter.Router, logger log.ContextLogge
|
||||||
return nil, E.New("missing outbound field")
|
return nil, E.New("missing outbound field")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NewLogicalRule(ctx, router, logger, options.LogicalOptions)
|
return NewLogicalRule(ctx, logger, options.LogicalOptions)
|
||||||
default:
|
default:
|
||||||
return nil, E.New("unknown rule type: ", options.Type)
|
return nil, E.New("unknown rule type: ", options.Type)
|
||||||
}
|
}
|
||||||
|
@ -51,7 +52,7 @@ type RuleItem interface {
|
||||||
String() string
|
String() string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDefaultRule(ctx context.Context, router adapter.Router, logger log.ContextLogger, options option.DefaultRule) (*DefaultRule, error) {
|
func NewDefaultRule(ctx context.Context, logger log.ContextLogger, options option.DefaultRule) (*DefaultRule, error) {
|
||||||
action, err := NewRuleAction(ctx, logger, options.RuleAction)
|
action, err := NewRuleAction(ctx, logger, options.RuleAction)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, E.Cause(err, "action")
|
return nil, E.Cause(err, "action")
|
||||||
|
@ -62,6 +63,8 @@ func NewDefaultRule(ctx context.Context, router adapter.Router, logger log.Conte
|
||||||
action: action,
|
action: action,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
router := service.FromContext[adapter.Router](ctx)
|
||||||
|
networkManager := service.FromContext[adapter.NetworkManager](ctx)
|
||||||
if len(options.Inbound) > 0 {
|
if len(options.Inbound) > 0 {
|
||||||
item := NewInboundRule(options.Inbound)
|
item := NewInboundRule(options.Inbound)
|
||||||
rule.items = append(rule.items, item)
|
rule.items = append(rule.items, item)
|
||||||
|
@ -221,12 +224,12 @@ func NewDefaultRule(ctx context.Context, router adapter.Router, logger log.Conte
|
||||||
rule.allItems = append(rule.allItems, item)
|
rule.allItems = append(rule.allItems, item)
|
||||||
}
|
}
|
||||||
if len(options.WIFISSID) > 0 {
|
if len(options.WIFISSID) > 0 {
|
||||||
item := NewWIFISSIDItem(router, options.WIFISSID)
|
item := NewWIFISSIDItem(networkManager, options.WIFISSID)
|
||||||
rule.items = append(rule.items, item)
|
rule.items = append(rule.items, item)
|
||||||
rule.allItems = append(rule.allItems, item)
|
rule.allItems = append(rule.allItems, item)
|
||||||
}
|
}
|
||||||
if len(options.WIFIBSSID) > 0 {
|
if len(options.WIFIBSSID) > 0 {
|
||||||
item := NewWIFIBSSIDItem(router, options.WIFIBSSID)
|
item := NewWIFIBSSIDItem(networkManager, options.WIFIBSSID)
|
||||||
rule.items = append(rule.items, item)
|
rule.items = append(rule.items, item)
|
||||||
rule.allItems = append(rule.allItems, item)
|
rule.allItems = append(rule.allItems, item)
|
||||||
}
|
}
|
||||||
|
@ -253,7 +256,7 @@ type LogicalRule struct {
|
||||||
abstractLogicalRule
|
abstractLogicalRule
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewLogicalRule(ctx context.Context, router adapter.Router, logger log.ContextLogger, options option.LogicalRule) (*LogicalRule, error) {
|
func NewLogicalRule(ctx context.Context, logger log.ContextLogger, options option.LogicalRule) (*LogicalRule, error) {
|
||||||
action, err := NewRuleAction(ctx, logger, options.RuleAction)
|
action, err := NewRuleAction(ctx, logger, options.RuleAction)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, E.Cause(err, "action")
|
return nil, E.Cause(err, "action")
|
||||||
|
@ -274,7 +277,7 @@ func NewLogicalRule(ctx context.Context, router adapter.Router, logger log.Conte
|
||||||
return nil, E.New("unknown logical mode: ", options.Mode)
|
return nil, E.New("unknown logical mode: ", options.Mode)
|
||||||
}
|
}
|
||||||
for i, subOptions := range options.Rules {
|
for i, subOptions := range options.Rules {
|
||||||
subRule, err := NewRule(ctx, router, logger, subOptions, false)
|
subRule, err := NewRule(ctx, logger, subOptions, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, E.Cause(err, "sub rule[", i, "]")
|
return nil, E.Cause(err, "sub rule[", i, "]")
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,9 +10,10 @@ import (
|
||||||
"github.com/sagernet/sing-box/option"
|
"github.com/sagernet/sing-box/option"
|
||||||
"github.com/sagernet/sing/common"
|
"github.com/sagernet/sing/common"
|
||||||
E "github.com/sagernet/sing/common/exceptions"
|
E "github.com/sagernet/sing/common/exceptions"
|
||||||
|
"github.com/sagernet/sing/service"
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewDNSRule(ctx context.Context, router adapter.Router, logger log.ContextLogger, options option.DNSRule, checkServer bool) (adapter.DNSRule, error) {
|
func NewDNSRule(ctx context.Context, logger log.ContextLogger, options option.DNSRule, checkServer bool) (adapter.DNSRule, error) {
|
||||||
switch options.Type {
|
switch options.Type {
|
||||||
case "", C.RuleTypeDefault:
|
case "", C.RuleTypeDefault:
|
||||||
if !options.DefaultOptions.IsValid() {
|
if !options.DefaultOptions.IsValid() {
|
||||||
|
@ -24,7 +25,7 @@ func NewDNSRule(ctx context.Context, router adapter.Router, logger log.ContextLo
|
||||||
return nil, E.New("missing server field")
|
return nil, E.New("missing server field")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NewDefaultDNSRule(ctx, router, logger, options.DefaultOptions)
|
return NewDefaultDNSRule(ctx, logger, options.DefaultOptions)
|
||||||
case C.RuleTypeLogical:
|
case C.RuleTypeLogical:
|
||||||
if !options.LogicalOptions.IsValid() {
|
if !options.LogicalOptions.IsValid() {
|
||||||
return nil, E.New("missing conditions")
|
return nil, E.New("missing conditions")
|
||||||
|
@ -35,7 +36,7 @@ func NewDNSRule(ctx context.Context, router adapter.Router, logger log.ContextLo
|
||||||
return nil, E.New("missing server field")
|
return nil, E.New("missing server field")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NewLogicalDNSRule(ctx, router, logger, options.LogicalOptions)
|
return NewLogicalDNSRule(ctx, logger, options.LogicalOptions)
|
||||||
default:
|
default:
|
||||||
return nil, E.New("unknown rule type: ", options.Type)
|
return nil, E.New("unknown rule type: ", options.Type)
|
||||||
}
|
}
|
||||||
|
@ -47,7 +48,7 @@ type DefaultDNSRule struct {
|
||||||
abstractDefaultRule
|
abstractDefaultRule
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDefaultDNSRule(ctx context.Context, router adapter.Router, logger log.ContextLogger, options option.DefaultDNSRule) (*DefaultDNSRule, error) {
|
func NewDefaultDNSRule(ctx context.Context, logger log.ContextLogger, options option.DefaultDNSRule) (*DefaultDNSRule, error) {
|
||||||
rule := &DefaultDNSRule{
|
rule := &DefaultDNSRule{
|
||||||
abstractDefaultRule: abstractDefaultRule{
|
abstractDefaultRule: abstractDefaultRule{
|
||||||
invert: options.Invert,
|
invert: options.Invert,
|
||||||
|
@ -59,6 +60,8 @@ func NewDefaultDNSRule(ctx context.Context, router adapter.Router, logger log.Co
|
||||||
rule.items = append(rule.items, item)
|
rule.items = append(rule.items, item)
|
||||||
rule.allItems = append(rule.allItems, item)
|
rule.allItems = append(rule.allItems, item)
|
||||||
}
|
}
|
||||||
|
router := service.FromContext[adapter.Router](ctx)
|
||||||
|
networkManager := service.FromContext[adapter.NetworkManager](ctx)
|
||||||
if options.IPVersion > 0 {
|
if options.IPVersion > 0 {
|
||||||
switch options.IPVersion {
|
switch options.IPVersion {
|
||||||
case 4, 6:
|
case 4, 6:
|
||||||
|
@ -218,12 +221,12 @@ func NewDefaultDNSRule(ctx context.Context, router adapter.Router, logger log.Co
|
||||||
rule.allItems = append(rule.allItems, item)
|
rule.allItems = append(rule.allItems, item)
|
||||||
}
|
}
|
||||||
if len(options.WIFISSID) > 0 {
|
if len(options.WIFISSID) > 0 {
|
||||||
item := NewWIFISSIDItem(router, options.WIFISSID)
|
item := NewWIFISSIDItem(networkManager, options.WIFISSID)
|
||||||
rule.items = append(rule.items, item)
|
rule.items = append(rule.items, item)
|
||||||
rule.allItems = append(rule.allItems, item)
|
rule.allItems = append(rule.allItems, item)
|
||||||
}
|
}
|
||||||
if len(options.WIFIBSSID) > 0 {
|
if len(options.WIFIBSSID) > 0 {
|
||||||
item := NewWIFIBSSIDItem(router, options.WIFIBSSID)
|
item := NewWIFIBSSIDItem(networkManager, options.WIFIBSSID)
|
||||||
rule.items = append(rule.items, item)
|
rule.items = append(rule.items, item)
|
||||||
rule.allItems = append(rule.allItems, item)
|
rule.allItems = append(rule.allItems, item)
|
||||||
}
|
}
|
||||||
|
@ -282,7 +285,7 @@ type LogicalDNSRule struct {
|
||||||
abstractLogicalRule
|
abstractLogicalRule
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewLogicalDNSRule(ctx context.Context, router adapter.Router, logger log.ContextLogger, options option.LogicalDNSRule) (*LogicalDNSRule, error) {
|
func NewLogicalDNSRule(ctx context.Context, logger log.ContextLogger, options option.LogicalDNSRule) (*LogicalDNSRule, error) {
|
||||||
r := &LogicalDNSRule{
|
r := &LogicalDNSRule{
|
||||||
abstractLogicalRule: abstractLogicalRule{
|
abstractLogicalRule: abstractLogicalRule{
|
||||||
rules: make([]adapter.HeadlessRule, len(options.Rules)),
|
rules: make([]adapter.HeadlessRule, len(options.Rules)),
|
||||||
|
@ -299,7 +302,7 @@ func NewLogicalDNSRule(ctx context.Context, router adapter.Router, logger log.Co
|
||||||
return nil, E.New("unknown logical mode: ", options.Mode)
|
return nil, E.New("unknown logical mode: ", options.Mode)
|
||||||
}
|
}
|
||||||
for i, subRule := range options.Rules {
|
for i, subRule := range options.Rules {
|
||||||
rule, err := NewDNSRule(ctx, router, logger, subRule, false)
|
rule, err := NewDNSRule(ctx, logger, subRule, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, E.Cause(err, "sub rule[", i, "]")
|
return nil, E.Cause(err, "sub rule[", i, "]")
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,24 +1,27 @@
|
||||||
package rule
|
package rule
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
"github.com/sagernet/sing-box/adapter"
|
"github.com/sagernet/sing-box/adapter"
|
||||||
C "github.com/sagernet/sing-box/constant"
|
C "github.com/sagernet/sing-box/constant"
|
||||||
"github.com/sagernet/sing-box/option"
|
"github.com/sagernet/sing-box/option"
|
||||||
E "github.com/sagernet/sing/common/exceptions"
|
E "github.com/sagernet/sing/common/exceptions"
|
||||||
|
"github.com/sagernet/sing/service"
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewHeadlessRule(router adapter.Router, options option.HeadlessRule) (adapter.HeadlessRule, error) {
|
func NewHeadlessRule(ctx context.Context, options option.HeadlessRule) (adapter.HeadlessRule, error) {
|
||||||
switch options.Type {
|
switch options.Type {
|
||||||
case "", C.RuleTypeDefault:
|
case "", C.RuleTypeDefault:
|
||||||
if !options.DefaultOptions.IsValid() {
|
if !options.DefaultOptions.IsValid() {
|
||||||
return nil, E.New("missing conditions")
|
return nil, E.New("missing conditions")
|
||||||
}
|
}
|
||||||
return NewDefaultHeadlessRule(router, options.DefaultOptions)
|
return NewDefaultHeadlessRule(ctx, options.DefaultOptions)
|
||||||
case C.RuleTypeLogical:
|
case C.RuleTypeLogical:
|
||||||
if !options.LogicalOptions.IsValid() {
|
if !options.LogicalOptions.IsValid() {
|
||||||
return nil, E.New("missing conditions")
|
return nil, E.New("missing conditions")
|
||||||
}
|
}
|
||||||
return NewLogicalHeadlessRule(router, options.LogicalOptions)
|
return NewLogicalHeadlessRule(ctx, options.LogicalOptions)
|
||||||
default:
|
default:
|
||||||
return nil, E.New("unknown rule type: ", options.Type)
|
return nil, E.New("unknown rule type: ", options.Type)
|
||||||
}
|
}
|
||||||
|
@ -30,7 +33,8 @@ type DefaultHeadlessRule struct {
|
||||||
abstractDefaultRule
|
abstractDefaultRule
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDefaultHeadlessRule(router adapter.Router, options option.DefaultHeadlessRule) (*DefaultHeadlessRule, error) {
|
func NewDefaultHeadlessRule(ctx context.Context, options option.DefaultHeadlessRule) (*DefaultHeadlessRule, error) {
|
||||||
|
networkManager := service.FromContext[adapter.NetworkManager](ctx)
|
||||||
rule := &DefaultHeadlessRule{
|
rule := &DefaultHeadlessRule{
|
||||||
abstractDefaultRule{
|
abstractDefaultRule{
|
||||||
invert: options.Invert,
|
invert: options.Invert,
|
||||||
|
@ -137,15 +141,15 @@ func NewDefaultHeadlessRule(router adapter.Router, options option.DefaultHeadles
|
||||||
rule.allItems = append(rule.allItems, item)
|
rule.allItems = append(rule.allItems, item)
|
||||||
}
|
}
|
||||||
if len(options.WIFISSID) > 0 {
|
if len(options.WIFISSID) > 0 {
|
||||||
if router != nil {
|
if networkManager != nil {
|
||||||
item := NewWIFISSIDItem(router, options.WIFISSID)
|
item := NewWIFISSIDItem(networkManager, options.WIFISSID)
|
||||||
rule.items = append(rule.items, item)
|
rule.items = append(rule.items, item)
|
||||||
rule.allItems = append(rule.allItems, item)
|
rule.allItems = append(rule.allItems, item)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(options.WIFIBSSID) > 0 {
|
if len(options.WIFIBSSID) > 0 {
|
||||||
if router != nil {
|
if networkManager != nil {
|
||||||
item := NewWIFIBSSIDItem(router, options.WIFIBSSID)
|
item := NewWIFIBSSIDItem(networkManager, options.WIFIBSSID)
|
||||||
rule.items = append(rule.items, item)
|
rule.items = append(rule.items, item)
|
||||||
rule.allItems = append(rule.allItems, item)
|
rule.allItems = append(rule.allItems, item)
|
||||||
}
|
}
|
||||||
|
@ -168,7 +172,7 @@ type LogicalHeadlessRule struct {
|
||||||
abstractLogicalRule
|
abstractLogicalRule
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewLogicalHeadlessRule(router adapter.Router, options option.LogicalHeadlessRule) (*LogicalHeadlessRule, error) {
|
func NewLogicalHeadlessRule(ctx context.Context, options option.LogicalHeadlessRule) (*LogicalHeadlessRule, error) {
|
||||||
r := &LogicalHeadlessRule{
|
r := &LogicalHeadlessRule{
|
||||||
abstractLogicalRule{
|
abstractLogicalRule{
|
||||||
rules: make([]adapter.HeadlessRule, len(options.Rules)),
|
rules: make([]adapter.HeadlessRule, len(options.Rules)),
|
||||||
|
@ -184,7 +188,7 @@ func NewLogicalHeadlessRule(router adapter.Router, options option.LogicalHeadles
|
||||||
return nil, E.New("unknown logical mode: ", options.Mode)
|
return nil, E.New("unknown logical mode: ", options.Mode)
|
||||||
}
|
}
|
||||||
for i, subRule := range options.Rules {
|
for i, subRule := range options.Rules {
|
||||||
rule, err := NewHeadlessRule(router, subRule)
|
rule, err := NewHeadlessRule(ctx, subRule)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, E.Cause(err, "sub rule[", i, "]")
|
return nil, E.Cause(err, "sub rule[", i, "]")
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,12 +10,12 @@ import (
|
||||||
var _ RuleItem = (*WIFIBSSIDItem)(nil)
|
var _ RuleItem = (*WIFIBSSIDItem)(nil)
|
||||||
|
|
||||||
type WIFIBSSIDItem struct {
|
type WIFIBSSIDItem struct {
|
||||||
bssidList []string
|
bssidList []string
|
||||||
bssidMap map[string]bool
|
bssidMap map[string]bool
|
||||||
router adapter.Router
|
networkManager adapter.NetworkManager
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewWIFIBSSIDItem(router adapter.Router, bssidList []string) *WIFIBSSIDItem {
|
func NewWIFIBSSIDItem(networkManager adapter.NetworkManager, bssidList []string) *WIFIBSSIDItem {
|
||||||
bssidMap := make(map[string]bool)
|
bssidMap := make(map[string]bool)
|
||||||
for _, bssid := range bssidList {
|
for _, bssid := range bssidList {
|
||||||
bssidMap[bssid] = true
|
bssidMap[bssid] = true
|
||||||
|
@ -23,12 +23,12 @@ func NewWIFIBSSIDItem(router adapter.Router, bssidList []string) *WIFIBSSIDItem
|
||||||
return &WIFIBSSIDItem{
|
return &WIFIBSSIDItem{
|
||||||
bssidList,
|
bssidList,
|
||||||
bssidMap,
|
bssidMap,
|
||||||
router,
|
networkManager,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *WIFIBSSIDItem) Match(metadata *adapter.InboundContext) bool {
|
func (r *WIFIBSSIDItem) Match(metadata *adapter.InboundContext) bool {
|
||||||
return r.bssidMap[r.router.WIFIState().BSSID]
|
return r.bssidMap[r.networkManager.WIFIState().BSSID]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *WIFIBSSIDItem) String() string {
|
func (r *WIFIBSSIDItem) String() string {
|
||||||
|
|
|
@ -10,12 +10,12 @@ import (
|
||||||
var _ RuleItem = (*WIFISSIDItem)(nil)
|
var _ RuleItem = (*WIFISSIDItem)(nil)
|
||||||
|
|
||||||
type WIFISSIDItem struct {
|
type WIFISSIDItem struct {
|
||||||
ssidList []string
|
ssidList []string
|
||||||
ssidMap map[string]bool
|
ssidMap map[string]bool
|
||||||
router adapter.Router
|
networkManager adapter.NetworkManager
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewWIFISSIDItem(router adapter.Router, ssidList []string) *WIFISSIDItem {
|
func NewWIFISSIDItem(networkManager adapter.NetworkManager, ssidList []string) *WIFISSIDItem {
|
||||||
ssidMap := make(map[string]bool)
|
ssidMap := make(map[string]bool)
|
||||||
for _, ssid := range ssidList {
|
for _, ssid := range ssidList {
|
||||||
ssidMap[ssid] = true
|
ssidMap[ssid] = true
|
||||||
|
@ -23,12 +23,12 @@ func NewWIFISSIDItem(router adapter.Router, ssidList []string) *WIFISSIDItem {
|
||||||
return &WIFISSIDItem{
|
return &WIFISSIDItem{
|
||||||
ssidList,
|
ssidList,
|
||||||
ssidMap,
|
ssidMap,
|
||||||
router,
|
networkManager,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *WIFISSIDItem) Match(metadata *adapter.InboundContext) bool {
|
func (r *WIFISSIDItem) Match(metadata *adapter.InboundContext) bool {
|
||||||
return r.ssidMap[r.router.WIFIState().SSID]
|
return r.ssidMap[r.networkManager.WIFIState().SSID]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *WIFISSIDItem) String() string {
|
func (r *WIFISSIDItem) String() string {
|
||||||
|
|
|
@ -13,12 +13,12 @@ import (
|
||||||
"go4.org/netipx"
|
"go4.org/netipx"
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewRuleSet(ctx context.Context, router adapter.Router, logger logger.ContextLogger, options option.RuleSet) (adapter.RuleSet, error) {
|
func NewRuleSet(ctx context.Context, logger logger.ContextLogger, options option.RuleSet) (adapter.RuleSet, error) {
|
||||||
switch options.Type {
|
switch options.Type {
|
||||||
case C.RuleSetTypeInline, C.RuleSetTypeLocal, "":
|
case C.RuleSetTypeInline, C.RuleSetTypeLocal, "":
|
||||||
return NewLocalRuleSet(ctx, router, logger, options)
|
return NewLocalRuleSet(ctx, logger, options)
|
||||||
case C.RuleSetTypeRemote:
|
case C.RuleSetTypeRemote:
|
||||||
return NewRemoteRuleSet(ctx, router, logger, options), nil
|
return NewRemoteRuleSet(ctx, logger, options), nil
|
||||||
default:
|
default:
|
||||||
return nil, E.New("unknown rule-set type: ", options.Type)
|
return nil, E.New("unknown rule-set type: ", options.Type)
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@ import (
|
||||||
var _ adapter.RuleSet = (*LocalRuleSet)(nil)
|
var _ adapter.RuleSet = (*LocalRuleSet)(nil)
|
||||||
|
|
||||||
type LocalRuleSet struct {
|
type LocalRuleSet struct {
|
||||||
router adapter.Router
|
ctx context.Context
|
||||||
logger logger.Logger
|
logger logger.Logger
|
||||||
tag string
|
tag string
|
||||||
rules []adapter.HeadlessRule
|
rules []adapter.HeadlessRule
|
||||||
|
@ -36,9 +36,9 @@ type LocalRuleSet struct {
|
||||||
refs atomic.Int32
|
refs atomic.Int32
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewLocalRuleSet(ctx context.Context, router adapter.Router, logger logger.Logger, options option.RuleSet) (*LocalRuleSet, error) {
|
func NewLocalRuleSet(ctx context.Context, logger logger.Logger, options option.RuleSet) (*LocalRuleSet, error) {
|
||||||
ruleSet := &LocalRuleSet{
|
ruleSet := &LocalRuleSet{
|
||||||
router: router,
|
ctx: ctx,
|
||||||
logger: logger,
|
logger: logger,
|
||||||
tag: options.Tag,
|
tag: options.Tag,
|
||||||
fileFormat: options.Format,
|
fileFormat: options.Format,
|
||||||
|
@ -130,7 +130,7 @@ func (s *LocalRuleSet) reloadRules(headlessRules []option.HeadlessRule) error {
|
||||||
rules := make([]adapter.HeadlessRule, len(headlessRules))
|
rules := make([]adapter.HeadlessRule, len(headlessRules))
|
||||||
var err error
|
var err error
|
||||||
for i, ruleOptions := range headlessRules {
|
for i, ruleOptions := range headlessRules {
|
||||||
rules[i], err = NewHeadlessRule(s.router, ruleOptions)
|
rules[i], err = NewHeadlessRule(s.ctx, ruleOptions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return E.Cause(err, "parse rule_set.rules.[", i, "]")
|
return E.Cause(err, "parse rule_set.rules.[", i, "]")
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,6 @@ var _ adapter.RuleSet = (*RemoteRuleSet)(nil)
|
||||||
type RemoteRuleSet struct {
|
type RemoteRuleSet struct {
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
cancel context.CancelFunc
|
cancel context.CancelFunc
|
||||||
router adapter.Router
|
|
||||||
outboundManager adapter.OutboundManager
|
outboundManager adapter.OutboundManager
|
||||||
logger logger.ContextLogger
|
logger logger.ContextLogger
|
||||||
options option.RuleSet
|
options option.RuleSet
|
||||||
|
@ -53,7 +52,7 @@ type RemoteRuleSet struct {
|
||||||
refs atomic.Int32
|
refs atomic.Int32
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewRemoteRuleSet(ctx context.Context, router adapter.Router, logger logger.ContextLogger, options option.RuleSet) *RemoteRuleSet {
|
func NewRemoteRuleSet(ctx context.Context, logger logger.ContextLogger, options option.RuleSet) *RemoteRuleSet {
|
||||||
ctx, cancel := context.WithCancel(ctx)
|
ctx, cancel := context.WithCancel(ctx)
|
||||||
var updateInterval time.Duration
|
var updateInterval time.Duration
|
||||||
if options.RemoteOptions.UpdateInterval > 0 {
|
if options.RemoteOptions.UpdateInterval > 0 {
|
||||||
|
@ -64,7 +63,6 @@ func NewRemoteRuleSet(ctx context.Context, router adapter.Router, logger logger.
|
||||||
return &RemoteRuleSet{
|
return &RemoteRuleSet{
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
cancel: cancel,
|
cancel: cancel,
|
||||||
router: router,
|
|
||||||
outboundManager: service.FromContext[adapter.OutboundManager](ctx),
|
outboundManager: service.FromContext[adapter.OutboundManager](ctx),
|
||||||
logger: logger,
|
logger: logger,
|
||||||
options: options,
|
options: options,
|
||||||
|
@ -180,7 +178,7 @@ func (s *RemoteRuleSet) loadBytes(content []byte) error {
|
||||||
}
|
}
|
||||||
rules := make([]adapter.HeadlessRule, len(plainRuleSet.Rules))
|
rules := make([]adapter.HeadlessRule, len(plainRuleSet.Rules))
|
||||||
for i, ruleOptions := range plainRuleSet.Rules {
|
for i, ruleOptions := range plainRuleSet.Rules {
|
||||||
rules[i], err = NewHeadlessRule(s.router, ruleOptions)
|
rules[i], err = NewHeadlessRule(s.ctx, ruleOptions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return E.Cause(err, "parse rule_set.rules.[", i, "]")
|
return E.Cause(err, "parse rule_set.rules.[", i, "]")
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,6 +38,7 @@ func init() {
|
||||||
type Transport struct {
|
type Transport struct {
|
||||||
options dns.TransportOptions
|
options dns.TransportOptions
|
||||||
router adapter.Router
|
router adapter.Router
|
||||||
|
networkManager adapter.NetworkManager
|
||||||
interfaceName string
|
interfaceName string
|
||||||
autoInterface bool
|
autoInterface bool
|
||||||
interfaceCallback *list.Element[tun.DefaultInterfaceUpdateCallback]
|
interfaceCallback *list.Element[tun.DefaultInterfaceUpdateCallback]
|
||||||
|
@ -54,15 +55,11 @@ func NewTransport(options dns.TransportOptions) (*Transport, error) {
|
||||||
if linkURL.Host == "" {
|
if linkURL.Host == "" {
|
||||||
return nil, E.New("missing interface name for DHCP")
|
return nil, E.New("missing interface name for DHCP")
|
||||||
}
|
}
|
||||||
router := service.FromContext[adapter.Router](options.Context)
|
|
||||||
if router == nil {
|
|
||||||
return nil, E.New("missing router in context")
|
|
||||||
}
|
|
||||||
transport := &Transport{
|
transport := &Transport{
|
||||||
options: options,
|
options: options,
|
||||||
router: router,
|
networkManager: service.FromContext[adapter.NetworkManager](options.Context),
|
||||||
interfaceName: linkURL.Host,
|
interfaceName: linkURL.Host,
|
||||||
autoInterface: linkURL.Host == "auto",
|
autoInterface: linkURL.Host == "auto",
|
||||||
}
|
}
|
||||||
return transport, nil
|
return transport, nil
|
||||||
}
|
}
|
||||||
|
@ -77,7 +74,7 @@ func (t *Transport) Start() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if t.autoInterface {
|
if t.autoInterface {
|
||||||
t.interfaceCallback = t.router.InterfaceMonitor().RegisterCallback(t.interfaceUpdated)
|
t.interfaceCallback = t.networkManager.InterfaceMonitor().RegisterCallback(t.interfaceUpdated)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -93,7 +90,7 @@ func (t *Transport) Close() error {
|
||||||
transport.Close()
|
transport.Close()
|
||||||
}
|
}
|
||||||
if t.interfaceCallback != nil {
|
if t.interfaceCallback != nil {
|
||||||
t.router.InterfaceMonitor().UnregisterCallback(t.interfaceCallback)
|
t.networkManager.InterfaceMonitor().UnregisterCallback(t.interfaceCallback)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -125,10 +122,10 @@ func (t *Transport) Exchange(ctx context.Context, message *mDNS.Msg) (*mDNS.Msg,
|
||||||
func (t *Transport) fetchInterface() (*net.Interface, error) {
|
func (t *Transport) fetchInterface() (*net.Interface, error) {
|
||||||
interfaceName := t.interfaceName
|
interfaceName := t.interfaceName
|
||||||
if t.autoInterface {
|
if t.autoInterface {
|
||||||
if t.router.InterfaceMonitor() == nil {
|
if t.networkManager.InterfaceMonitor() == nil {
|
||||||
return nil, E.New("missing monitor for auto DHCP, set route.auto_detect_interface")
|
return nil, E.New("missing monitor for auto DHCP, set route.auto_detect_interface")
|
||||||
}
|
}
|
||||||
interfaceName = t.router.InterfaceMonitor().DefaultInterfaceName(netip.Addr{})
|
interfaceName = t.networkManager.InterfaceMonitor().DefaultInterfaceName(netip.Addr{})
|
||||||
}
|
}
|
||||||
if interfaceName == "" {
|
if interfaceName == "" {
|
||||||
return nil, E.New("missing default interface")
|
return nil, E.New("missing default interface")
|
||||||
|
@ -177,7 +174,7 @@ func (t *Transport) interfaceUpdated(int) {
|
||||||
|
|
||||||
func (t *Transport) fetchServers0(ctx context.Context, iface *net.Interface) error {
|
func (t *Transport) fetchServers0(ctx context.Context, iface *net.Interface) error {
|
||||||
var listener net.ListenConfig
|
var listener net.ListenConfig
|
||||||
listener.Control = control.Append(listener.Control, control.BindToInterface(t.router.InterfaceFinder(), iface.Name, iface.Index))
|
listener.Control = control.Append(listener.Control, control.BindToInterface(t.networkManager.InterfaceFinder(), iface.Name, iface.Index))
|
||||||
listener.Control = control.Append(listener.Control, control.ReuseAddr())
|
listener.Control = control.Append(listener.Control, control.ReuseAddr())
|
||||||
listenAddr := "0.0.0.0:68"
|
listenAddr := "0.0.0.0:68"
|
||||||
if runtime.GOOS == "linux" || runtime.GOOS == "android" {
|
if runtime.GOOS == "linux" || runtime.GOOS == "android" {
|
||||||
|
@ -255,7 +252,7 @@ func (t *Transport) recreateServers(iface *net.Interface, serverAddrs []netip.Ad
|
||||||
return it.String()
|
return it.String()
|
||||||
}), ","), "]")
|
}), ","), "]")
|
||||||
}
|
}
|
||||||
serverDialer := common.Must1(dialer.NewDefault(t.router, option.DialerOptions{
|
serverDialer := common.Must1(dialer.NewDefault(t.networkManager, option.DialerOptions{
|
||||||
BindInterface: iface.Name,
|
BindInterface: iface.Name,
|
||||||
UDPFragmentDefault: true,
|
UDPFragmentDefault: true,
|
||||||
}))
|
}))
|
||||||
|
|
|
@ -34,7 +34,7 @@ type SystemDevice struct {
|
||||||
closeOnce sync.Once
|
closeOnce sync.Once
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSystemDevice(router adapter.Router, interfaceName string, localPrefixes []netip.Prefix, mtu uint32, gso bool) (*SystemDevice, error) {
|
func NewSystemDevice(networkManager adapter.NetworkManager, interfaceName string, localPrefixes []netip.Prefix, mtu uint32, gso bool) (*SystemDevice, error) {
|
||||||
var inet4Addresses []netip.Prefix
|
var inet4Addresses []netip.Prefix
|
||||||
var inet6Addresses []netip.Prefix
|
var inet6Addresses []netip.Prefix
|
||||||
for _, prefixes := range localPrefixes {
|
for _, prefixes := range localPrefixes {
|
||||||
|
@ -49,7 +49,7 @@ func NewSystemDevice(router adapter.Router, interfaceName string, localPrefixes
|
||||||
}
|
}
|
||||||
|
|
||||||
return &SystemDevice{
|
return &SystemDevice{
|
||||||
dialer: common.Must1(dialer.NewDefault(router, option.DialerOptions{
|
dialer: common.Must1(dialer.NewDefault(networkManager, option.DialerOptions{
|
||||||
BindInterface: interfaceName,
|
BindInterface: interfaceName,
|
||||||
})),
|
})),
|
||||||
name: interfaceName,
|
name: interfaceName,
|
||||||
|
|
Loading…
Reference in a new issue