Split bind_address

This commit is contained in:
世界 2022-11-03 11:51:09 +08:00
parent 6adfea0a72
commit 7f84936050
No known key found for this signature in database
GPG key ID: CD109927C34A63C4
2 changed files with 52 additions and 22 deletions

View file

@ -3,7 +3,6 @@ package dialer
import ( import (
"context" "context"
"net" "net"
"net/netip"
"time" "time"
"github.com/sagernet/sing-box/adapter" "github.com/sagernet/sing-box/adapter"
@ -54,10 +53,13 @@ var warnTFOOnUnsupportedPlatform = warning.New(
) )
type DefaultDialer struct { type DefaultDialer struct {
dialer tfo.Dialer dialer4 tfo.Dialer
udpDialer net.Dialer dialer6 tfo.Dialer
udpDialer4 net.Dialer
udpDialer6 net.Dialer
udpListener net.ListenConfig udpListener net.ListenConfig
bindUDPAddr string udpAddr4 string
udpAddr6 string
} }
func NewDefault(router adapter.Router, options option.DialerOptions) *DefaultDialer { func NewDefault(router adapter.Router, options option.DialerOptions) *DefaultDialer {
@ -120,22 +122,37 @@ func NewDefault(router adapter.Router, options option.DialerOptions) *DefaultDia
dialer.Control = control.Append(dialer.Control, control.DisableUDPFragment()) dialer.Control = control.Append(dialer.Control, control.DisableUDPFragment())
listener.Control = control.Append(listener.Control, control.DisableUDPFragment()) listener.Control = control.Append(listener.Control, control.DisableUDPFragment())
} }
var bindUDPAddr string var (
udpDialer := dialer dialer4 = dialer
var bindAddress netip.Addr udpDialer4 = dialer
if options.BindAddress != nil { udpAddr4 string
bindAddress = options.BindAddress.Build() )
if options.Inet4BindAddress != nil {
bindAddr := options.Inet4BindAddress.Build()
dialer4.LocalAddr = &net.TCPAddr{IP: bindAddr.AsSlice()}
udpDialer4.LocalAddr = &net.UDPAddr{IP: bindAddr.AsSlice()}
udpAddr4 = M.SocksaddrFrom(bindAddr, 0).String()
} }
if bindAddress.IsValid() { var (
dialer.LocalAddr = &net.TCPAddr{ dialer6 = dialer
IP: bindAddress.AsSlice(), udpDialer6 = dialer
udpAddr6 string
)
if options.Inet6BindAddress != nil {
bindAddr := options.Inet6BindAddress.Build()
dialer6.LocalAddr = &net.TCPAddr{IP: bindAddr.AsSlice()}
udpDialer6.LocalAddr = &net.UDPAddr{IP: bindAddr.AsSlice()}
udpAddr6 = M.SocksaddrFrom(bindAddr, 0).String()
} }
udpDialer.LocalAddr = &net.UDPAddr{ return &DefaultDialer{
IP: bindAddress.AsSlice(), tfo.Dialer{Dialer: dialer4, DisableTFO: !options.TCPFastOpen},
tfo.Dialer{Dialer: dialer6, DisableTFO: !options.TCPFastOpen},
udpDialer4,
udpDialer6,
listener,
udpAddr4,
udpAddr6,
} }
bindUDPAddr = M.SocksaddrFrom(bindAddress, 0).String()
}
return &DefaultDialer{tfo.Dialer{Dialer: dialer, DisableTFO: !options.TCPFastOpen}, udpDialer, listener, bindUDPAddr}
} }
func (d *DefaultDialer) DialContext(ctx context.Context, network string, address M.Socksaddr) (net.Conn, error) { func (d *DefaultDialer) DialContext(ctx context.Context, network string, address M.Socksaddr) (net.Conn, error) {
@ -144,11 +161,23 @@ func (d *DefaultDialer) DialContext(ctx context.Context, network string, address
} }
switch N.NetworkName(network) { switch N.NetworkName(network) {
case N.NetworkUDP: case N.NetworkUDP:
return d.udpDialer.DialContext(ctx, network, address.String()) if !address.IsIPv6() {
return d.udpDialer4.DialContext(ctx, network, address.String())
} else {
return d.udpDialer6.DialContext(ctx, network, address.String())
}
}
if !address.IsIPv6() {
return DialSlowContext(&d.dialer4, ctx, network, address)
} else {
return DialSlowContext(&d.dialer6, ctx, network, address)
} }
return DialSlowContext(&d.dialer, ctx, network, address)
} }
func (d *DefaultDialer) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) { func (d *DefaultDialer) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
return d.udpListener.ListenPacket(ctx, N.NetworkUDP, d.bindUDPAddr) if !destination.IsIPv6() {
return d.udpListener.ListenPacket(ctx, N.NetworkUDP, d.udpAddr4)
} else {
return d.udpListener.ListenPacket(ctx, N.NetworkUDP, d.udpAddr6)
}
} }

View file

@ -122,7 +122,8 @@ func (h *Outbound) UnmarshalJSON(bytes []byte) error {
type DialerOptions struct { type DialerOptions struct {
Detour string `json:"detour,omitempty"` Detour string `json:"detour,omitempty"`
BindInterface string `json:"bind_interface,omitempty"` BindInterface string `json:"bind_interface,omitempty"`
BindAddress *ListenAddress `json:"bind_address,omitempty"` Inet4BindAddress *ListenAddress `json:"inet4_bind_address,omitempty"`
Inet6BindAddress *ListenAddress `json:"inet6_bind_address,omitempty"`
ProtectPath string `json:"protect_path,omitempty"` ProtectPath string `json:"protect_path,omitempty"`
RoutingMark int `json:"routing_mark,omitempty"` RoutingMark int `json:"routing_mark,omitempty"`
ReuseAddr bool `json:"reuse_addr,omitempty"` ReuseAddr bool `json:"reuse_addr,omitempty"`