|
|
@@ -3,7 +3,6 @@ package dialer
|
|
|
import (
|
|
|
"context"
|
|
|
"net"
|
|
|
- "net/netip"
|
|
|
"time"
|
|
|
|
|
|
"github.com/sagernet/sing-box/adapter"
|
|
|
@@ -54,10 +53,13 @@ var warnTFOOnUnsupportedPlatform = warning.New(
|
|
|
)
|
|
|
|
|
|
type DefaultDialer struct {
|
|
|
- dialer tfo.Dialer
|
|
|
- udpDialer net.Dialer
|
|
|
+ dialer4 tfo.Dialer
|
|
|
+ dialer6 tfo.Dialer
|
|
|
+ udpDialer4 net.Dialer
|
|
|
+ udpDialer6 net.Dialer
|
|
|
udpListener net.ListenConfig
|
|
|
- bindUDPAddr string
|
|
|
+ udpAddr4 string
|
|
|
+ udpAddr6 string
|
|
|
}
|
|
|
|
|
|
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())
|
|
|
listener.Control = control.Append(listener.Control, control.DisableUDPFragment())
|
|
|
}
|
|
|
- var bindUDPAddr string
|
|
|
- udpDialer := dialer
|
|
|
- var bindAddress netip.Addr
|
|
|
- if options.BindAddress != nil {
|
|
|
- bindAddress = options.BindAddress.Build()
|
|
|
+ var (
|
|
|
+ dialer4 = dialer
|
|
|
+ udpDialer4 = dialer
|
|
|
+ udpAddr4 string
|
|
|
+ )
|
|
|
+ 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() {
|
|
|
- dialer.LocalAddr = &net.TCPAddr{
|
|
|
- IP: bindAddress.AsSlice(),
|
|
|
- }
|
|
|
- udpDialer.LocalAddr = &net.UDPAddr{
|
|
|
- IP: bindAddress.AsSlice(),
|
|
|
- }
|
|
|
- bindUDPAddr = M.SocksaddrFrom(bindAddress, 0).String()
|
|
|
+ var (
|
|
|
+ dialer6 = dialer
|
|
|
+ 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()
|
|
|
+ }
|
|
|
+ return &DefaultDialer{
|
|
|
+ tfo.Dialer{Dialer: dialer4, DisableTFO: !options.TCPFastOpen},
|
|
|
+ tfo.Dialer{Dialer: dialer6, DisableTFO: !options.TCPFastOpen},
|
|
|
+ udpDialer4,
|
|
|
+ udpDialer6,
|
|
|
+ listener,
|
|
|
+ udpAddr4,
|
|
|
+ udpAddr6,
|
|
|
}
|
|
|
- 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) {
|
|
|
@@ -144,11 +161,23 @@ func (d *DefaultDialer) DialContext(ctx context.Context, network string, address
|
|
|
}
|
|
|
switch N.NetworkName(network) {
|
|
|
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) {
|
|
|
- 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)
|
|
|
+ }
|
|
|
}
|