mirror of
https://github.com/SagerNet/sing-box.git
synced 2026-04-14 20:58:33 +10:00
Explicitly reject detour to empty direct outbounds
This commit is contained in:
@@ -6,26 +6,39 @@ import (
|
||||
"sync"
|
||||
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
"github.com/sagernet/sing/common"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
M "github.com/sagernet/sing/common/metadata"
|
||||
N "github.com/sagernet/sing/common/network"
|
||||
)
|
||||
|
||||
type DirectDialer interface {
|
||||
IsEmpty() bool
|
||||
}
|
||||
|
||||
type DetourDialer struct {
|
||||
outboundManager adapter.OutboundManager
|
||||
detour string
|
||||
legacyDNSDialer bool
|
||||
dialer N.Dialer
|
||||
initOnce sync.Once
|
||||
initErr error
|
||||
}
|
||||
|
||||
func NewDetour(outboundManager adapter.OutboundManager, detour string) N.Dialer {
|
||||
return &DetourDialer{outboundManager: outboundManager, detour: detour}
|
||||
func NewDetour(outboundManager adapter.OutboundManager, detour string, legacyDNSDialer bool) N.Dialer {
|
||||
return &DetourDialer{
|
||||
outboundManager: outboundManager,
|
||||
detour: detour,
|
||||
legacyDNSDialer: legacyDNSDialer,
|
||||
}
|
||||
}
|
||||
|
||||
func (d *DetourDialer) Start() error {
|
||||
_, err := d.Dialer()
|
||||
return err
|
||||
func InitializeDetour(dialer N.Dialer) error {
|
||||
detourDialer, isDetour := common.Cast[*DetourDialer](dialer)
|
||||
if !isDetour {
|
||||
return nil
|
||||
}
|
||||
return common.Error(detourDialer.Dialer())
|
||||
}
|
||||
|
||||
func (d *DetourDialer) Dialer() (N.Dialer, error) {
|
||||
@@ -34,11 +47,20 @@ func (d *DetourDialer) Dialer() (N.Dialer, error) {
|
||||
}
|
||||
|
||||
func (d *DetourDialer) init() {
|
||||
var loaded bool
|
||||
d.dialer, loaded = d.outboundManager.Outbound(d.detour)
|
||||
dialer, loaded := d.outboundManager.Outbound(d.detour)
|
||||
if !loaded {
|
||||
d.initErr = E.New("outbound detour not found: ", d.detour)
|
||||
return
|
||||
}
|
||||
if !d.legacyDNSDialer {
|
||||
if directDialer, isDirect := dialer.(DirectDialer); isDirect {
|
||||
if directDialer.IsEmpty() {
|
||||
d.initErr = E.New("detour to an empty direct outbound makes no sense")
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
d.dialer = dialer
|
||||
}
|
||||
|
||||
func (d *DetourDialer) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
|
||||
|
||||
@@ -23,6 +23,7 @@ type Options struct {
|
||||
DirectResolver bool
|
||||
ResolverOnDetour bool
|
||||
NewDialer bool
|
||||
LegacyDNSDialer bool
|
||||
}
|
||||
|
||||
// TODO: merge with NewWithOptions
|
||||
@@ -45,7 +46,7 @@ func NewWithOptions(options Options) (N.Dialer, error) {
|
||||
if outboundManager == nil {
|
||||
return nil, E.New("missing outbound manager")
|
||||
}
|
||||
dialer = NewDetour(outboundManager, dialOptions.Detour)
|
||||
dialer = NewDetour(outboundManager, dialOptions.Detour, options.LegacyDNSDialer)
|
||||
} else {
|
||||
dialer, err = NewDefault(options.Context, dialOptions)
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user