Explicitly reject detour to empty direct outbounds

This commit is contained in:
世界
2025-03-20 20:48:23 +08:00
parent e257b19bb3
commit ef92ed6795
17 changed files with 106 additions and 29 deletions

View File

@@ -6,14 +6,20 @@ 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
directResolver bool
dialer N.Dialer
initOnce sync.Once
initErr error
@@ -23,9 +29,12 @@ func NewDetour(outboundManager adapter.OutboundManager, detour string) N.Dialer
return &DetourDialer{outboundManager: outboundManager, detour: detour}
}
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 +43,18 @@ 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 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) {