Avoid nested direct outbound usage

This commit is contained in:
世界 2023-12-20 19:15:59 +08:00
parent 081c45b9d7
commit 6fe582fcd7
No known key found for this signature in database
GPG Key ID: CD109927C34A63C4
4 changed files with 27 additions and 11 deletions

View File

@ -6,21 +6,27 @@ import (
"sync"
"github.com/sagernet/sing-box/adapter"
C "github.com/sagernet/sing-box/constant"
E "github.com/sagernet/sing/common/exceptions"
M "github.com/sagernet/sing/common/metadata"
N "github.com/sagernet/sing/common/network"
)
type DetourDialer struct {
router adapter.Router
detour string
dialer N.Dialer
initOnce sync.Once
initErr error
router adapter.Router
detour string
allowNestedDirect bool
dialer N.Dialer
initOnce sync.Once
initErr error
}
func NewDetour(router adapter.Router, detour string) N.Dialer {
return &DetourDialer{router: router, detour: detour}
func NewDetour(router adapter.Router, detour string, allowNestedDirect bool) N.Dialer {
return &DetourDialer{
router: router,
detour: detour,
allowNestedDirect: allowNestedDirect,
}
}
func (d *DetourDialer) Start() error {
@ -30,10 +36,17 @@ func (d *DetourDialer) Start() error {
func (d *DetourDialer) Dialer() (N.Dialer, error) {
d.initOnce.Do(func() {
var loaded bool
d.dialer, loaded = d.router.Outbound(d.detour)
var (
dialer adapter.Outbound
loaded bool
)
dialer, loaded = d.router.Outbound(d.detour)
if !loaded {
d.initErr = E.New("outbound detour not found: ", d.detour)
} else if !d.allowNestedDirect && dialer.Type() == C.TypeDirect {
d.initErr = E.New("using a direct outbound as a detour is illegal")
} else {
d.dialer = dialer
}
})
return d.dialer, d.initErr

View File

@ -23,7 +23,7 @@ func New(router adapter.Router, options option.DialerOptions) (N.Dialer, error)
return nil, err
}
} else {
dialer = NewDetour(router, options.Detour)
dialer = NewDetour(router, options.Detour, false)
}
domainStrategy := dns.DomainStrategy(options.DomainStrategy)
if domainStrategy != dns.DomainStrategyAsIS || options.Detour == "" {

View File

@ -35,6 +35,9 @@ type Direct struct {
func NewDirect(router adapter.Router, logger log.ContextLogger, tag string, options option.DirectOutboundOptions) (*Direct, error) {
options.UDPFragmentDefault = true
if options.Detour != "" {
return nil, E.New("detour option for direct outbound is illegal")
}
outboundDialer, err := dialer.New(router, options.DialerOptions)
if err != nil {
return nil, err

View File

@ -195,7 +195,7 @@ func NewRouter(
if server.Detour == "" {
detour = dialer.NewRouter(router)
} else {
detour = dialer.NewDetour(router, server.Detour)
detour = dialer.NewDetour(router, server.Detour, true)
}
switch server.Address {
case "local":