mirror of
https://github.com/SagerNet/sing-box.git
synced 2024-11-22 08:31:30 +00:00
Add TCP MultiPath support
This commit is contained in:
parent
81b847faca
commit
1019ecfdcf
|
@ -26,7 +26,7 @@ type DefaultDialer struct {
|
||||||
udpAddr6 string
|
udpAddr6 string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDefault(router adapter.Router, options option.DialerOptions) *DefaultDialer {
|
func NewDefault(router adapter.Router, options option.DialerOptions) (*DefaultDialer, error) {
|
||||||
var dialer net.Dialer
|
var dialer net.Dialer
|
||||||
var listener net.ListenConfig
|
var listener net.ListenConfig
|
||||||
if options.BindInterface != "" {
|
if options.BindInterface != "" {
|
||||||
|
@ -93,6 +93,12 @@ func NewDefault(router adapter.Router, options option.DialerOptions) *DefaultDia
|
||||||
udpDialer6.LocalAddr = &net.UDPAddr{IP: bindAddr.AsSlice()}
|
udpDialer6.LocalAddr = &net.UDPAddr{IP: bindAddr.AsSlice()}
|
||||||
udpAddr6 = M.SocksaddrFrom(bindAddr, 0).String()
|
udpAddr6 = M.SocksaddrFrom(bindAddr, 0).String()
|
||||||
}
|
}
|
||||||
|
if options.TCPMultiPath {
|
||||||
|
if !multipathTCPAvailable {
|
||||||
|
return nil, E.New("MultiPath TCP requires go1.21, please recompile your binary.")
|
||||||
|
}
|
||||||
|
setMultiPathTCP(&dialer4)
|
||||||
|
}
|
||||||
return &DefaultDialer{
|
return &DefaultDialer{
|
||||||
tfo.Dialer{Dialer: dialer4, DisableTFO: !options.TCPFastOpen},
|
tfo.Dialer{Dialer: dialer4, DisableTFO: !options.TCPFastOpen},
|
||||||
tfo.Dialer{Dialer: dialer6, DisableTFO: !options.TCPFastOpen},
|
tfo.Dialer{Dialer: dialer6, DisableTFO: !options.TCPFastOpen},
|
||||||
|
@ -101,7 +107,7 @@ func NewDefault(router adapter.Router, options option.DialerOptions) *DefaultDia
|
||||||
listener,
|
listener,
|
||||||
udpAddr4,
|
udpAddr4,
|
||||||
udpAddr6,
|
udpAddr6,
|
||||||
}
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
||||||
|
|
11
common/dialer/default_go1.21.go
Normal file
11
common/dialer/default_go1.21.go
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
//go:build go1.21
|
||||||
|
|
||||||
|
package dialer
|
||||||
|
|
||||||
|
import "net"
|
||||||
|
|
||||||
|
const multipathTCPAvailable = true
|
||||||
|
|
||||||
|
func setMultiPathTCP(dialer *net.Dialer) {
|
||||||
|
dialer.SetMultipathTCP(true)
|
||||||
|
}
|
12
common/dialer/default_nongo1.21.go
Normal file
12
common/dialer/default_nongo1.21.go
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
//go:build !go1.21
|
||||||
|
|
||||||
|
package dialer
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
)
|
||||||
|
|
||||||
|
const multipathTCPAvailable = false
|
||||||
|
|
||||||
|
func setMultiPathTCP(dialer *net.Dialer) {
|
||||||
|
}
|
|
@ -6,13 +6,24 @@ import (
|
||||||
"github.com/sagernet/sing-box/adapter"
|
"github.com/sagernet/sing-box/adapter"
|
||||||
"github.com/sagernet/sing-box/option"
|
"github.com/sagernet/sing-box/option"
|
||||||
"github.com/sagernet/sing-dns"
|
"github.com/sagernet/sing-dns"
|
||||||
|
"github.com/sagernet/sing/common"
|
||||||
N "github.com/sagernet/sing/common/network"
|
N "github.com/sagernet/sing/common/network"
|
||||||
)
|
)
|
||||||
|
|
||||||
func New(router adapter.Router, options option.DialerOptions) N.Dialer {
|
func MustNew(router adapter.Router, options option.DialerOptions) N.Dialer {
|
||||||
var dialer N.Dialer
|
return common.Must1(New(router, options))
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(router adapter.Router, options option.DialerOptions) (N.Dialer, error) {
|
||||||
|
var (
|
||||||
|
dialer N.Dialer
|
||||||
|
err error
|
||||||
|
)
|
||||||
if options.Detour == "" {
|
if options.Detour == "" {
|
||||||
dialer = NewDefault(router, options)
|
dialer, err = NewDefault(router, options)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
dialer = NewDetour(router, options.Detour)
|
dialer = NewDetour(router, options.Detour)
|
||||||
}
|
}
|
||||||
|
@ -20,5 +31,5 @@ func New(router adapter.Router, options option.DialerOptions) N.Dialer {
|
||||||
if domainStrategy != dns.DomainStrategyAsIS || options.Detour == "" {
|
if domainStrategy != dns.DomainStrategyAsIS || options.Detour == "" {
|
||||||
dialer = NewResolveDialer(router, dialer, domainStrategy, time.Duration(options.FallbackDelay))
|
dialer = NewResolveDialer(router, dialer, domainStrategy, time.Duration(options.FallbackDelay))
|
||||||
}
|
}
|
||||||
return dialer
|
return dialer, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -101,7 +101,10 @@ func NewRealityServer(ctx context.Context, router adapter.Router, logger log.Log
|
||||||
tlsConfig.ShortIds[shortID] = true
|
tlsConfig.ShortIds[shortID] = true
|
||||||
}
|
}
|
||||||
|
|
||||||
handshakeDialer := dialer.New(router, options.Reality.Handshake.DialerOptions)
|
handshakeDialer, err := dialer.New(router, options.Reality.Handshake.DialerOptions)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
tlsConfig.DialContext = func(ctx context.Context, network, addr string) (net.Conn, error) {
|
tlsConfig.DialContext = func(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||||
return handshakeDialer.DialContext(ctx, network, M.ParseSocksaddr(addr))
|
return handshakeDialer.DialContext(ctx, network, M.ParseSocksaddr(addr))
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
"reuse_addr": false,
|
"reuse_addr": false,
|
||||||
"connect_timeout": "5s",
|
"connect_timeout": "5s",
|
||||||
"tcp_fast_open": false,
|
"tcp_fast_open": false,
|
||||||
|
"tcp_multi_path": false,
|
||||||
"udp_fragment": false,
|
"udp_fragment": false,
|
||||||
"domain_strategy": "prefer_ipv6",
|
"domain_strategy": "prefer_ipv6",
|
||||||
"fallback_delay": "300ms"
|
"fallback_delay": "300ms"
|
||||||
|
@ -19,8 +20,8 @@
|
||||||
### Fields
|
### Fields
|
||||||
|
|
||||||
| Field | Available Context |
|
| Field | Available Context |
|
||||||
|----------------------------------------------------------------------------------------------------------------------|-------------------|
|
|------------------------------------------------------------------------------------------------------------------------------------------|-------------------|
|
||||||
| `bind_interface` /`*bind_address` /`routing_mark` /`reuse_addr` / `tcp_fast_open`/ `udp_fragment` /`connect_timeout` | `detour` not set |
|
| `bind_interface` /`*bind_address` /`routing_mark` /`reuse_addr` / `tcp_fast_open` / `tcp_multi_path` / `udp_fragment` /`connect_timeout` | `detour` not set |
|
||||||
|
|
||||||
#### detour
|
#### detour
|
||||||
|
|
||||||
|
@ -54,6 +55,14 @@ Reuse listener address.
|
||||||
|
|
||||||
Enable TCP Fast Open.
|
Enable TCP Fast Open.
|
||||||
|
|
||||||
|
#### tcp_multi_path
|
||||||
|
|
||||||
|
!!! warning ""
|
||||||
|
|
||||||
|
Go 1.21 required.
|
||||||
|
|
||||||
|
Enable TCP Multi Path.
|
||||||
|
|
||||||
#### udp_fragment
|
#### udp_fragment
|
||||||
|
|
||||||
Enable UDP fragmentation.
|
Enable UDP fragmentation.
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
"reuse_addr": false,
|
"reuse_addr": false,
|
||||||
"connect_timeout": "5s",
|
"connect_timeout": "5s",
|
||||||
"tcp_fast_open": false,
|
"tcp_fast_open": false,
|
||||||
|
"tcp_multi_path": false,
|
||||||
"udp_fragment": false,
|
"udp_fragment": false,
|
||||||
"domain_strategy": "prefer_ipv6",
|
"domain_strategy": "prefer_ipv6",
|
||||||
"fallback_delay": "300ms"
|
"fallback_delay": "300ms"
|
||||||
|
@ -19,8 +20,8 @@
|
||||||
### 字段
|
### 字段
|
||||||
|
|
||||||
| 字段 | 可用上下文 |
|
| 字段 | 可用上下文 |
|
||||||
|----------------------------------------------------------------------------------------------------------------------|--------------|
|
|------------------------------------------------------------------------------------------------------------------------------------------|--------------|
|
||||||
| `bind_interface` /`*bind_address` /`routing_mark` /`reuse_addr` / `tcp_fast_open`/ `udp_fragment` /`connect_timeout` | `detour` 未设置 |
|
| `bind_interface` /`*bind_address` /`routing_mark` /`reuse_addr` / `tcp_fast_open` / `tcp_mutli_path` / `udp_fragment` /`connect_timeout` | `detour` 未设置 |
|
||||||
|
|
||||||
|
|
||||||
#### detour
|
#### detour
|
||||||
|
@ -57,6 +58,14 @@
|
||||||
|
|
||||||
启用 TCP Fast Open。
|
启用 TCP Fast Open。
|
||||||
|
|
||||||
|
#### tcp_multi_path
|
||||||
|
|
||||||
|
!!! warning ""
|
||||||
|
|
||||||
|
需要 Go 1.21。
|
||||||
|
|
||||||
|
启用 TCP Multi Path。
|
||||||
|
|
||||||
#### udp_fragment
|
#### udp_fragment
|
||||||
|
|
||||||
启用 UDP 分段。
|
启用 UDP 分段。
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
"listen": "::",
|
"listen": "::",
|
||||||
"listen_port": 5353,
|
"listen_port": 5353,
|
||||||
"tcp_fast_open": false,
|
"tcp_fast_open": false,
|
||||||
|
"tcp_multi_path": false,
|
||||||
"udp_fragment": false,
|
"udp_fragment": false,
|
||||||
"sniff": false,
|
"sniff": false,
|
||||||
"sniff_override_destination": false,
|
"sniff_override_destination": false,
|
||||||
|
@ -24,6 +25,7 @@
|
||||||
| `listen` | Needs to listen on TCP or UDP. |
|
| `listen` | Needs to listen on TCP or UDP. |
|
||||||
| `listen_port` | Needs to listen on TCP or UDP. |
|
| `listen_port` | Needs to listen on TCP or UDP. |
|
||||||
| `tcp_fast_open` | Needs to listen on TCP. |
|
| `tcp_fast_open` | Needs to listen on TCP. |
|
||||||
|
| `tcp_multi_path` | Needs to listen on TCP. |
|
||||||
| `udp_timeout` | Needs to assemble UDP connections, currently Tun and Shadowsocks. |
|
| `udp_timeout` | Needs to assemble UDP connections, currently Tun and Shadowsocks. |
|
||||||
| `proxy_protocol` | Needs to listen on TCP. |
|
| `proxy_protocol` | Needs to listen on TCP. |
|
||||||
| `proxy_protocol_accept_no_header` | When `proxy_protocol` enabled |
|
| `proxy_protocol_accept_no_header` | When `proxy_protocol` enabled |
|
||||||
|
@ -42,6 +44,14 @@ Listen port.
|
||||||
|
|
||||||
Enable TCP Fast Open.
|
Enable TCP Fast Open.
|
||||||
|
|
||||||
|
#### tcp_multi_path
|
||||||
|
|
||||||
|
!!! warning ""
|
||||||
|
|
||||||
|
Go 1.21 required.
|
||||||
|
|
||||||
|
Enable TCP Multi Path.
|
||||||
|
|
||||||
#### udp_fragment
|
#### udp_fragment
|
||||||
|
|
||||||
Enable UDP fragmentation.
|
Enable UDP fragmentation.
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
"listen": "::",
|
"listen": "::",
|
||||||
"listen_port": 5353,
|
"listen_port": 5353,
|
||||||
"tcp_fast_open": false,
|
"tcp_fast_open": false,
|
||||||
|
"tcp_multi_path": false,
|
||||||
"udp_fragment": false,
|
"udp_fragment": false,
|
||||||
"sniff": false,
|
"sniff": false,
|
||||||
"sniff_override_destination": false,
|
"sniff_override_destination": false,
|
||||||
|
@ -23,6 +24,7 @@
|
||||||
| `listen` | 需要监听 TCP 或 UDP。 |
|
| `listen` | 需要监听 TCP 或 UDP。 |
|
||||||
| `listen_port` | 需要监听 TCP 或 UDP。 |
|
| `listen_port` | 需要监听 TCP 或 UDP。 |
|
||||||
| `tcp_fast_open` | 需要监听 TCP。 |
|
| `tcp_fast_open` | 需要监听 TCP。 |
|
||||||
|
| `tcp_multi_path` | 需要监听 TCP。 |
|
||||||
| `udp_timeout` | 需要组装 UDP 连接, 当前为 Tun 和 Shadowsocks。 |
|
| `udp_timeout` | 需要组装 UDP 连接, 当前为 Tun 和 Shadowsocks。 |
|
||||||
| `proxy_protocol` | 需要监听 TCP。 |
|
| `proxy_protocol` | 需要监听 TCP。 |
|
||||||
| `proxy_protocol_accept_no_header` | `proxy_protocol` 启用时 |
|
| `proxy_protocol_accept_no_header` | `proxy_protocol` 启用时 |
|
||||||
|
@ -43,6 +45,14 @@
|
||||||
|
|
||||||
启用 TCP Fast Open。
|
启用 TCP Fast Open。
|
||||||
|
|
||||||
|
#### tcp_multi_path
|
||||||
|
|
||||||
|
!!! warning ""
|
||||||
|
|
||||||
|
需要 Go 1.21。
|
||||||
|
|
||||||
|
启用 TCP Multi Path。
|
||||||
|
|
||||||
#### udp_fragment
|
#### udp_fragment
|
||||||
|
|
||||||
启用 UDP 分段。
|
启用 UDP 分段。
|
||||||
|
|
|
@ -18,7 +18,14 @@ func (a *myInboundAdapter) ListenTCP() (net.Listener, error) {
|
||||||
bindAddr := M.SocksaddrFrom(a.listenOptions.Listen.Build(), a.listenOptions.ListenPort)
|
bindAddr := M.SocksaddrFrom(a.listenOptions.Listen.Build(), a.listenOptions.ListenPort)
|
||||||
var tcpListener net.Listener
|
var tcpListener net.Listener
|
||||||
if !a.listenOptions.TCPFastOpen {
|
if !a.listenOptions.TCPFastOpen {
|
||||||
tcpListener, err = net.ListenTCP(M.NetworkFromNetAddr(N.NetworkTCP, bindAddr.Addr), bindAddr.TCPAddr())
|
var listenConfig net.ListenConfig
|
||||||
|
if a.listenOptions.TCPMultiPath {
|
||||||
|
if !multipathTCPAvailable {
|
||||||
|
return nil, E.New("MultiPath TCP requires go1.21, please recompile your binary.")
|
||||||
|
}
|
||||||
|
setMultiPathTCP(&listenConfig)
|
||||||
|
}
|
||||||
|
tcpListener, err = listenConfig.Listen(a.ctx, M.NetworkFromNetAddr(N.NetworkTCP, bindAddr.Addr), bindAddr.String())
|
||||||
} else {
|
} else {
|
||||||
tcpListener, err = tfo.ListenTCP(M.NetworkFromNetAddr(N.NetworkTCP, bindAddr.Addr), bindAddr.TCPAddr())
|
tcpListener, err = tfo.ListenTCP(M.NetworkFromNetAddr(N.NetworkTCP, bindAddr.Addr), bindAddr.TCPAddr())
|
||||||
}
|
}
|
||||||
|
|
11
inbound/default_tcp_go1.21.go
Normal file
11
inbound/default_tcp_go1.21.go
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
//go:build go1.21
|
||||||
|
|
||||||
|
package inbound
|
||||||
|
|
||||||
|
import "net"
|
||||||
|
|
||||||
|
const multipathTCPAvailable = true
|
||||||
|
|
||||||
|
func setMultiPathTCP(listenConfig *net.ListenConfig) {
|
||||||
|
listenConfig.SetMultipathTCP(true)
|
||||||
|
}
|
10
inbound/default_tcp_nongo1.21.go
Normal file
10
inbound/default_tcp_nongo1.21.go
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
//go:build !go1.21
|
||||||
|
|
||||||
|
package inbound
|
||||||
|
|
||||||
|
import "net"
|
||||||
|
|
||||||
|
const multipathTCPAvailable = false
|
||||||
|
|
||||||
|
func setMultiPathTCP(listenConfig *net.ListenConfig) {
|
||||||
|
}
|
|
@ -40,12 +40,20 @@ func NewShadowTLS(ctx context.Context, router adapter.Router, logger log.Context
|
||||||
if options.Version > 1 {
|
if options.Version > 1 {
|
||||||
handshakeForServerName = make(map[string]shadowtls.HandshakeConfig)
|
handshakeForServerName = make(map[string]shadowtls.HandshakeConfig)
|
||||||
for serverName, serverOptions := range options.HandshakeForServerName {
|
for serverName, serverOptions := range options.HandshakeForServerName {
|
||||||
|
handshakeDialer, err := dialer.New(router, serverOptions.DialerOptions)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
handshakeForServerName[serverName] = shadowtls.HandshakeConfig{
|
handshakeForServerName[serverName] = shadowtls.HandshakeConfig{
|
||||||
Server: serverOptions.ServerOptions.Build(),
|
Server: serverOptions.ServerOptions.Build(),
|
||||||
Dialer: dialer.New(router, serverOptions.DialerOptions),
|
Dialer: handshakeDialer,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
handshakeDialer, err := dialer.New(router, options.Handshake.DialerOptions)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
service, err := shadowtls.NewService(shadowtls.ServiceConfig{
|
service, err := shadowtls.NewService(shadowtls.ServiceConfig{
|
||||||
Version: options.Version,
|
Version: options.Version,
|
||||||
Password: options.Password,
|
Password: options.Password,
|
||||||
|
@ -54,7 +62,7 @@ func NewShadowTLS(ctx context.Context, router adapter.Router, logger log.Context
|
||||||
}),
|
}),
|
||||||
Handshake: shadowtls.HandshakeConfig{
|
Handshake: shadowtls.HandshakeConfig{
|
||||||
Server: options.Handshake.ServerOptions.Build(),
|
Server: options.Handshake.ServerOptions.Build(),
|
||||||
Dialer: dialer.New(router, options.Handshake.DialerOptions),
|
Dialer: handshakeDialer,
|
||||||
},
|
},
|
||||||
HandshakeForServerName: handshakeForServerName,
|
HandshakeForServerName: handshakeForServerName,
|
||||||
StrictMode: options.StrictMode,
|
StrictMode: options.StrictMode,
|
||||||
|
|
|
@ -31,7 +31,7 @@ type Service struct {
|
||||||
clockOffset time.Duration
|
clockOffset time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewService(ctx context.Context, router adapter.Router, logger logger.Logger, options option.NTPOptions) *Service {
|
func NewService(ctx context.Context, router adapter.Router, logger logger.Logger, options option.NTPOptions) (*Service, error) {
|
||||||
ctx, cancel := common.ContextWithCancelCause(ctx)
|
ctx, cancel := common.ContextWithCancelCause(ctx)
|
||||||
server := options.ServerOptions.Build()
|
server := options.ServerOptions.Build()
|
||||||
if server.Port == 0 {
|
if server.Port == 0 {
|
||||||
|
@ -43,15 +43,19 @@ func NewService(ctx context.Context, router adapter.Router, logger logger.Logger
|
||||||
} else {
|
} else {
|
||||||
interval = 30 * time.Minute
|
interval = 30 * time.Minute
|
||||||
}
|
}
|
||||||
|
outboundDialer, err := dialer.New(router, options.DialerOptions)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
return &Service{
|
return &Service{
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
cancel: cancel,
|
cancel: cancel,
|
||||||
server: server,
|
server: server,
|
||||||
writeToSystem: options.WriteToSystem,
|
writeToSystem: options.WriteToSystem,
|
||||||
dialer: dialer.New(router, options.DialerOptions),
|
dialer: outboundDialer,
|
||||||
logger: logger,
|
logger: logger,
|
||||||
ticker: time.NewTicker(interval),
|
ticker: time.NewTicker(interval),
|
||||||
}
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) Start() error {
|
func (s *Service) Start() error {
|
||||||
|
|
|
@ -125,6 +125,7 @@ type ListenOptions struct {
|
||||||
Listen *ListenAddress `json:"listen,omitempty"`
|
Listen *ListenAddress `json:"listen,omitempty"`
|
||||||
ListenPort uint16 `json:"listen_port,omitempty"`
|
ListenPort uint16 `json:"listen_port,omitempty"`
|
||||||
TCPFastOpen bool `json:"tcp_fast_open,omitempty"`
|
TCPFastOpen bool `json:"tcp_fast_open,omitempty"`
|
||||||
|
TCPMultiPath bool `json:"tcp_multi_path,omitempty"`
|
||||||
UDPFragment *bool `json:"udp_fragment,omitempty"`
|
UDPFragment *bool `json:"udp_fragment,omitempty"`
|
||||||
UDPFragmentDefault bool `json:"-"`
|
UDPFragmentDefault bool `json:"-"`
|
||||||
UDPTimeout int64 `json:"udp_timeout,omitempty"`
|
UDPTimeout int64 `json:"udp_timeout,omitempty"`
|
||||||
|
|
|
@ -134,6 +134,7 @@ type DialerOptions struct {
|
||||||
ReuseAddr bool `json:"reuse_addr,omitempty"`
|
ReuseAddr bool `json:"reuse_addr,omitempty"`
|
||||||
ConnectTimeout Duration `json:"connect_timeout,omitempty"`
|
ConnectTimeout Duration `json:"connect_timeout,omitempty"`
|
||||||
TCPFastOpen bool `json:"tcp_fast_open,omitempty"`
|
TCPFastOpen bool `json:"tcp_fast_open,omitempty"`
|
||||||
|
TCPMultiPath bool `json:"tcp_multi_path,omitempty"`
|
||||||
UDPFragment *bool `json:"udp_fragment,omitempty"`
|
UDPFragment *bool `json:"udp_fragment,omitempty"`
|
||||||
UDPFragmentDefault bool `json:"-"`
|
UDPFragmentDefault bool `json:"-"`
|
||||||
DomainStrategy DomainStrategy `json:"domain_strategy,omitempty"`
|
DomainStrategy DomainStrategy `json:"domain_strategy,omitempty"`
|
||||||
|
|
|
@ -38,6 +38,10 @@ type Direct struct {
|
||||||
|
|
||||||
func NewDirect(router adapter.Router, logger log.ContextLogger, tag string, options option.DirectOutboundOptions) (*Direct, error) {
|
func NewDirect(router adapter.Router, logger log.ContextLogger, tag string, options option.DirectOutboundOptions) (*Direct, error) {
|
||||||
options.UDPFragmentDefault = true
|
options.UDPFragmentDefault = true
|
||||||
|
outboundDialer, err := dialer.New(router, options.DialerOptions)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
outbound := &Direct{
|
outbound := &Direct{
|
||||||
myOutboundAdapter: myOutboundAdapter{
|
myOutboundAdapter: myOutboundAdapter{
|
||||||
protocol: C.TypeDirect,
|
protocol: C.TypeDirect,
|
||||||
|
@ -49,7 +53,7 @@ func NewDirect(router adapter.Router, logger log.ContextLogger, tag string, opti
|
||||||
},
|
},
|
||||||
domainStrategy: dns.DomainStrategy(options.DomainStrategy),
|
domainStrategy: dns.DomainStrategy(options.DomainStrategy),
|
||||||
fallbackDelay: time.Duration(options.FallbackDelay),
|
fallbackDelay: time.Duration(options.FallbackDelay),
|
||||||
dialer: dialer.New(router, options.DialerOptions),
|
dialer: outboundDialer,
|
||||||
proxyProto: options.ProxyProtocol,
|
proxyProto: options.ProxyProtocol,
|
||||||
}
|
}
|
||||||
if options.ProxyProtocol > 2 {
|
if options.ProxyProtocol > 2 {
|
||||||
|
|
|
@ -26,7 +26,11 @@ type HTTP struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewHTTP(router adapter.Router, logger log.ContextLogger, tag string, options option.HTTPOutboundOptions) (*HTTP, error) {
|
func NewHTTP(router adapter.Router, logger log.ContextLogger, tag string, options option.HTTPOutboundOptions) (*HTTP, error) {
|
||||||
detour, err := tls.NewDialerFromOptions(router, dialer.New(router, options.DialerOptions), options.Server, common.PtrValueOrDefault(options.TLS))
|
outboundDialer, err := dialer.New(router, options.DialerOptions)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
detour, err := tls.NewDialerFromOptions(router, outboundDialer, options.Server, common.PtrValueOrDefault(options.TLS))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -117,6 +117,10 @@ func NewHysteria(ctx context.Context, router adapter.Router, logger log.ContextL
|
||||||
if down < hysteria.MinSpeedBPS {
|
if down < hysteria.MinSpeedBPS {
|
||||||
return nil, E.New("invalid down speed")
|
return nil, E.New("invalid down speed")
|
||||||
}
|
}
|
||||||
|
outboundDialer, err := dialer.New(router, options.DialerOptions)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
return &Hysteria{
|
return &Hysteria{
|
||||||
myOutboundAdapter: myOutboundAdapter{
|
myOutboundAdapter: myOutboundAdapter{
|
||||||
protocol: C.TypeHysteria,
|
protocol: C.TypeHysteria,
|
||||||
|
@ -127,7 +131,7 @@ func NewHysteria(ctx context.Context, router adapter.Router, logger log.ContextL
|
||||||
dependencies: withDialerDependency(options.DialerOptions),
|
dependencies: withDialerDependency(options.DialerOptions),
|
||||||
},
|
},
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
dialer: dialer.New(router, options.DialerOptions),
|
dialer: outboundDialer,
|
||||||
serverAddr: options.ServerOptions.Build(),
|
serverAddr: options.ServerOptions.Build(),
|
||||||
tlsConfig: tlsConfig,
|
tlsConfig: tlsConfig,
|
||||||
quicConfig: quicConfig,
|
quicConfig: quicConfig,
|
||||||
|
|
|
@ -39,6 +39,10 @@ func NewShadowsocks(ctx context.Context, router adapter.Router, logger log.Conte
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
outboundDialer, err := dialer.New(router, options.DialerOptions)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
outbound := &Shadowsocks{
|
outbound := &Shadowsocks{
|
||||||
myOutboundAdapter: myOutboundAdapter{
|
myOutboundAdapter: myOutboundAdapter{
|
||||||
protocol: C.TypeShadowsocks,
|
protocol: C.TypeShadowsocks,
|
||||||
|
@ -48,7 +52,7 @@ func NewShadowsocks(ctx context.Context, router adapter.Router, logger log.Conte
|
||||||
tag: tag,
|
tag: tag,
|
||||||
dependencies: withDialerDependency(options.DialerOptions),
|
dependencies: withDialerDependency(options.DialerOptions),
|
||||||
},
|
},
|
||||||
dialer: dialer.New(router, options.DialerOptions),
|
dialer: outboundDialer,
|
||||||
method: method,
|
method: method,
|
||||||
serverAddr: options.ServerOptions.Build(),
|
serverAddr: options.ServerOptions.Build(),
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,6 +37,10 @@ type ShadowsocksR struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewShadowsocksR(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.ShadowsocksROutboundOptions) (*ShadowsocksR, error) {
|
func NewShadowsocksR(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.ShadowsocksROutboundOptions) (*ShadowsocksR, error) {
|
||||||
|
outboundDialer, err := dialer.New(router, options.DialerOptions)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
outbound := &ShadowsocksR{
|
outbound := &ShadowsocksR{
|
||||||
myOutboundAdapter: myOutboundAdapter{
|
myOutboundAdapter: myOutboundAdapter{
|
||||||
protocol: C.TypeShadowsocksR,
|
protocol: C.TypeShadowsocksR,
|
||||||
|
@ -46,11 +50,10 @@ func NewShadowsocksR(ctx context.Context, router adapter.Router, logger log.Cont
|
||||||
tag: tag,
|
tag: tag,
|
||||||
dependencies: withDialerDependency(options.DialerOptions),
|
dependencies: withDialerDependency(options.DialerOptions),
|
||||||
},
|
},
|
||||||
dialer: dialer.New(router, options.DialerOptions),
|
dialer: outboundDialer,
|
||||||
serverAddr: options.ServerOptions.Build(),
|
serverAddr: options.ServerOptions.Build(),
|
||||||
}
|
}
|
||||||
var cipher string
|
var cipher string
|
||||||
var err error
|
|
||||||
switch options.Method {
|
switch options.Method {
|
||||||
case "none":
|
case "none":
|
||||||
cipher = "dummy"
|
cipher = "dummy"
|
||||||
|
|
|
@ -72,11 +72,15 @@ func NewShadowTLS(ctx context.Context, router adapter.Router, logger log.Context
|
||||||
tlsHandshakeFunc = shadowtls.DefaultTLSHandshakeFunc(options.Password, stdTLSConfig)
|
tlsHandshakeFunc = shadowtls.DefaultTLSHandshakeFunc(options.Password, stdTLSConfig)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
outboundDialer, err := dialer.New(router, options.DialerOptions)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
client, err := shadowtls.NewClient(shadowtls.ClientConfig{
|
client, err := shadowtls.NewClient(shadowtls.ClientConfig{
|
||||||
Version: options.Version,
|
Version: options.Version,
|
||||||
Password: options.Password,
|
Password: options.Password,
|
||||||
Server: options.ServerOptions.Build(),
|
Server: options.ServerOptions.Build(),
|
||||||
Dialer: dialer.New(router, options.DialerOptions),
|
Dialer: outboundDialer,
|
||||||
TLSHandshake: tlsHandshakeFunc,
|
TLSHandshake: tlsHandshakeFunc,
|
||||||
Logger: logger,
|
Logger: logger,
|
||||||
})
|
})
|
||||||
|
|
|
@ -37,6 +37,10 @@ func NewSocks(router adapter.Router, logger log.ContextLogger, tag string, optio
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
outboundDialer, err := dialer.New(router, options.DialerOptions)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
outbound := &Socks{
|
outbound := &Socks{
|
||||||
myOutboundAdapter: myOutboundAdapter{
|
myOutboundAdapter: myOutboundAdapter{
|
||||||
protocol: C.TypeSOCKS,
|
protocol: C.TypeSOCKS,
|
||||||
|
@ -46,7 +50,7 @@ func NewSocks(router adapter.Router, logger log.ContextLogger, tag string, optio
|
||||||
tag: tag,
|
tag: tag,
|
||||||
dependencies: withDialerDependency(options.DialerOptions),
|
dependencies: withDialerDependency(options.DialerOptions),
|
||||||
},
|
},
|
||||||
client: socks.NewClient(dialer.New(router, options.DialerOptions), options.ServerOptions.Build(), version, options.Username, options.Password),
|
client: socks.NewClient(outboundDialer, options.ServerOptions.Build(), version, options.Username, options.Password),
|
||||||
resolve: version == socks.Version4,
|
resolve: version == socks.Version4,
|
||||||
}
|
}
|
||||||
uotOptions := common.PtrValueOrDefault(options.UDPOverTCPOptions)
|
uotOptions := common.PtrValueOrDefault(options.UDPOverTCPOptions)
|
||||||
|
|
|
@ -44,6 +44,10 @@ type SSH struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSSH(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.SSHOutboundOptions) (*SSH, error) {
|
func NewSSH(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.SSHOutboundOptions) (*SSH, error) {
|
||||||
|
outboundDialer, err := dialer.New(router, options.DialerOptions)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
outbound := &SSH{
|
outbound := &SSH{
|
||||||
myOutboundAdapter: myOutboundAdapter{
|
myOutboundAdapter: myOutboundAdapter{
|
||||||
protocol: C.TypeSSH,
|
protocol: C.TypeSSH,
|
||||||
|
@ -54,7 +58,7 @@ func NewSSH(ctx context.Context, router adapter.Router, logger log.ContextLogger
|
||||||
dependencies: withDialerDependency(options.DialerOptions),
|
dependencies: withDialerDependency(options.DialerOptions),
|
||||||
},
|
},
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
dialer: dialer.New(router, options.DialerOptions),
|
dialer: outboundDialer,
|
||||||
serverAddr: options.ServerOptions.Build(),
|
serverAddr: options.ServerOptions.Build(),
|
||||||
user: options.User,
|
user: options.User,
|
||||||
hostKeyAlgorithms: options.HostKeyAlgorithms,
|
hostKeyAlgorithms: options.HostKeyAlgorithms,
|
||||||
|
|
|
@ -66,6 +66,10 @@ func NewTor(ctx context.Context, router adapter.Router, logger log.ContextLogger
|
||||||
}
|
}
|
||||||
startConf.TorrcFile = torrcFile
|
startConf.TorrcFile = torrcFile
|
||||||
}
|
}
|
||||||
|
outboundDialer, err := dialer.New(router, options.DialerOptions)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
return &Tor{
|
return &Tor{
|
||||||
myOutboundAdapter: myOutboundAdapter{
|
myOutboundAdapter: myOutboundAdapter{
|
||||||
protocol: C.TypeTor,
|
protocol: C.TypeTor,
|
||||||
|
@ -76,7 +80,7 @@ func NewTor(ctx context.Context, router adapter.Router, logger log.ContextLogger
|
||||||
dependencies: withDialerDependency(options.DialerOptions),
|
dependencies: withDialerDependency(options.DialerOptions),
|
||||||
},
|
},
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
proxy: NewProxyListener(ctx, logger, dialer.New(router, options.DialerOptions)),
|
proxy: NewProxyListener(ctx, logger, outboundDialer),
|
||||||
startConf: &startConf,
|
startConf: &startConf,
|
||||||
options: options.Options,
|
options: options.Options,
|
||||||
}, nil
|
}, nil
|
||||||
|
|
|
@ -33,6 +33,10 @@ type Trojan struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewTrojan(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.TrojanOutboundOptions) (*Trojan, error) {
|
func NewTrojan(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.TrojanOutboundOptions) (*Trojan, error) {
|
||||||
|
outboundDialer, err := dialer.New(router, options.DialerOptions)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
outbound := &Trojan{
|
outbound := &Trojan{
|
||||||
myOutboundAdapter: myOutboundAdapter{
|
myOutboundAdapter: myOutboundAdapter{
|
||||||
protocol: C.TypeTrojan,
|
protocol: C.TypeTrojan,
|
||||||
|
@ -42,11 +46,10 @@ func NewTrojan(ctx context.Context, router adapter.Router, logger log.ContextLog
|
||||||
tag: tag,
|
tag: tag,
|
||||||
dependencies: withDialerDependency(options.DialerOptions),
|
dependencies: withDialerDependency(options.DialerOptions),
|
||||||
},
|
},
|
||||||
dialer: dialer.New(router, options.DialerOptions),
|
dialer: outboundDialer,
|
||||||
serverAddr: options.ServerOptions.Build(),
|
serverAddr: options.ServerOptions.Build(),
|
||||||
key: trojan.Key(options.Password),
|
key: trojan.Key(options.Password),
|
||||||
}
|
}
|
||||||
var err error
|
|
||||||
if options.TLS != nil {
|
if options.TLS != nil {
|
||||||
outbound.tlsConfig, err = tls.NewClient(router, options.Server, common.PtrValueOrDefault(options.TLS))
|
outbound.tlsConfig, err = tls.NewClient(router, options.Server, common.PtrValueOrDefault(options.TLS))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -57,9 +57,13 @@ func NewTUIC(ctx context.Context, router adapter.Router, logger log.ContextLogge
|
||||||
case "quic":
|
case "quic":
|
||||||
udpStream = true
|
udpStream = true
|
||||||
}
|
}
|
||||||
|
outboundDialer, err := dialer.New(router, options.DialerOptions)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
client, err := tuic.NewClient(tuic.ClientOptions{
|
client, err := tuic.NewClient(tuic.ClientOptions{
|
||||||
Context: ctx,
|
Context: ctx,
|
||||||
Dialer: dialer.New(router, options.DialerOptions),
|
Dialer: outboundDialer,
|
||||||
ServerAddress: options.ServerOptions.Build(),
|
ServerAddress: options.ServerOptions.Build(),
|
||||||
TLSConfig: tlsConfig,
|
TLSConfig: tlsConfig,
|
||||||
UUID: userUUID,
|
UUID: userUUID,
|
||||||
|
|
|
@ -36,6 +36,10 @@ type VLESS struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewVLESS(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.VLESSOutboundOptions) (*VLESS, error) {
|
func NewVLESS(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.VLESSOutboundOptions) (*VLESS, error) {
|
||||||
|
outboundDialer, err := dialer.New(router, options.DialerOptions)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
outbound := &VLESS{
|
outbound := &VLESS{
|
||||||
myOutboundAdapter: myOutboundAdapter{
|
myOutboundAdapter: myOutboundAdapter{
|
||||||
protocol: C.TypeVLESS,
|
protocol: C.TypeVLESS,
|
||||||
|
@ -45,10 +49,9 @@ func NewVLESS(ctx context.Context, router adapter.Router, logger log.ContextLogg
|
||||||
tag: tag,
|
tag: tag,
|
||||||
dependencies: withDialerDependency(options.DialerOptions),
|
dependencies: withDialerDependency(options.DialerOptions),
|
||||||
},
|
},
|
||||||
dialer: dialer.New(router, options.DialerOptions),
|
dialer: outboundDialer,
|
||||||
serverAddr: options.ServerOptions.Build(),
|
serverAddr: options.ServerOptions.Build(),
|
||||||
}
|
}
|
||||||
var err error
|
|
||||||
if options.TLS != nil {
|
if options.TLS != nil {
|
||||||
outbound.tlsConfig, err = tls.NewClient(router, options.Server, common.PtrValueOrDefault(options.TLS))
|
outbound.tlsConfig, err = tls.NewClient(router, options.Server, common.PtrValueOrDefault(options.TLS))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -35,6 +35,10 @@ type VMess struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewVMess(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.VMessOutboundOptions) (*VMess, error) {
|
func NewVMess(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.VMessOutboundOptions) (*VMess, error) {
|
||||||
|
outboundDialer, err := dialer.New(router, options.DialerOptions)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
outbound := &VMess{
|
outbound := &VMess{
|
||||||
myOutboundAdapter: myOutboundAdapter{
|
myOutboundAdapter: myOutboundAdapter{
|
||||||
protocol: C.TypeVMess,
|
protocol: C.TypeVMess,
|
||||||
|
@ -44,10 +48,9 @@ func NewVMess(ctx context.Context, router adapter.Router, logger log.ContextLogg
|
||||||
tag: tag,
|
tag: tag,
|
||||||
dependencies: withDialerDependency(options.DialerOptions),
|
dependencies: withDialerDependency(options.DialerOptions),
|
||||||
},
|
},
|
||||||
dialer: dialer.New(router, options.DialerOptions),
|
dialer: outboundDialer,
|
||||||
serverAddr: options.ServerOptions.Build(),
|
serverAddr: options.ServerOptions.Build(),
|
||||||
}
|
}
|
||||||
var err error
|
|
||||||
if options.TLS != nil {
|
if options.TLS != nil {
|
||||||
outbound.tlsConfig, err = tls.NewClient(router, options.Server, common.PtrValueOrDefault(options.TLS))
|
outbound.tlsConfig, err = tls.NewClient(router, options.Server, common.PtrValueOrDefault(options.TLS))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -65,7 +65,11 @@ func NewWireGuard(ctx context.Context, router adapter.Router, logger log.Context
|
||||||
connectAddr = options.ServerOptions.Build()
|
connectAddr = options.ServerOptions.Build()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
outbound.bind = wireguard.NewClientBind(ctx, outbound, dialer.New(router, options.DialerOptions), isConnect, connectAddr, reserved)
|
outboundDialer, err := dialer.New(router, options.DialerOptions)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
outbound.bind = wireguard.NewClientBind(ctx, outbound, outboundDialer, isConnect, connectAddr, reserved)
|
||||||
localPrefixes := common.Map(options.LocalAddress, option.ListenPrefix.Build)
|
localPrefixes := common.Map(options.LocalAddress, option.ListenPrefix.Build)
|
||||||
if len(localPrefixes) == 0 {
|
if len(localPrefixes) == 0 {
|
||||||
return nil, E.New("missing local address")
|
return nil, E.New("missing local address")
|
||||||
|
@ -157,7 +161,6 @@ func NewWireGuard(ctx context.Context, router adapter.Router, logger log.Context
|
||||||
mtu = 1408
|
mtu = 1408
|
||||||
}
|
}
|
||||||
var wireTunDevice wireguard.Device
|
var wireTunDevice wireguard.Device
|
||||||
var err error
|
|
||||||
if !options.SystemInterface && tun.WithGVisor {
|
if !options.SystemInterface && tun.WithGVisor {
|
||||||
wireTunDevice, err = wireguard.NewStackDevice(localPrefixes, mtu)
|
wireTunDevice, err = wireguard.NewStackDevice(localPrefixes, mtu)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -38,7 +38,9 @@ import (
|
||||||
F "github.com/sagernet/sing/common/format"
|
F "github.com/sagernet/sing/common/format"
|
||||||
M "github.com/sagernet/sing/common/metadata"
|
M "github.com/sagernet/sing/common/metadata"
|
||||||
N "github.com/sagernet/sing/common/network"
|
N "github.com/sagernet/sing/common/network"
|
||||||
|
serviceNTP "github.com/sagernet/sing/common/ntp"
|
||||||
"github.com/sagernet/sing/common/uot"
|
"github.com/sagernet/sing/common/uot"
|
||||||
|
"github.com/sagernet/sing/service"
|
||||||
"github.com/sagernet/sing/service/pause"
|
"github.com/sagernet/sing/service/pause"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -319,7 +321,12 @@ func NewRouter(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ntpOptions.Enabled {
|
if ntpOptions.Enabled {
|
||||||
router.timeService = ntp.NewService(ctx, router, logFactory.NewLogger("ntp"), ntpOptions)
|
timeService, err := ntp.NewService(ctx, router, logFactory.NewLogger("ntp"), ntpOptions)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
service.ContextWith[serviceNTP.TimeService](ctx, timeService)
|
||||||
|
router.timeService = timeService
|
||||||
}
|
}
|
||||||
return router, nil
|
return router, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -248,10 +248,10 @@ func (t *Transport) recreateServers(iface *net.Interface, serverAddrs []netip.Ad
|
||||||
}), ","), "]")
|
}), ","), "]")
|
||||||
}
|
}
|
||||||
|
|
||||||
serverDialer := dialer.NewDefault(t.router, option.DialerOptions{
|
serverDialer := common.Must1(dialer.NewDefault(t.router, option.DialerOptions{
|
||||||
BindInterface: iface.Name,
|
BindInterface: iface.Name,
|
||||||
UDPFragmentDefault: true,
|
UDPFragmentDefault: true,
|
||||||
})
|
}))
|
||||||
var transports []dns.Transport
|
var transports []dns.Transport
|
||||||
for _, serverAddr := range serverAddrs {
|
for _, serverAddr := range serverAddrs {
|
||||||
serverTransport, err := dns.NewUDPTransport(t.name, t.ctx, serverDialer, M.Socksaddr{Addr: serverAddr, Port: 53})
|
serverTransport, err := dns.NewUDPTransport(t.name, t.ctx, serverDialer, M.Socksaddr{Addr: serverAddr, Port: 53})
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
"github.com/sagernet/sing-box/common/dialer"
|
"github.com/sagernet/sing-box/common/dialer"
|
||||||
"github.com/sagernet/sing-box/option"
|
"github.com/sagernet/sing-box/option"
|
||||||
"github.com/sagernet/sing-tun"
|
"github.com/sagernet/sing-tun"
|
||||||
|
"github.com/sagernet/sing/common"
|
||||||
M "github.com/sagernet/sing/common/metadata"
|
M "github.com/sagernet/sing/common/metadata"
|
||||||
N "github.com/sagernet/sing/common/network"
|
N "github.com/sagernet/sing/common/network"
|
||||||
wgTun "github.com/sagernet/wireguard-go/tun"
|
wgTun "github.com/sagernet/wireguard-go/tun"
|
||||||
|
@ -58,9 +59,9 @@ func NewSystemDevice(router adapter.Router, interfaceName string, localPrefixes
|
||||||
inet6Address = inet6Addresses[0].Addr()
|
inet6Address = inet6Addresses[0].Addr()
|
||||||
}
|
}
|
||||||
return &SystemDevice{
|
return &SystemDevice{
|
||||||
dialer: dialer.NewDefault(router, option.DialerOptions{
|
dialer: common.Must1(dialer.NewDefault(router, option.DialerOptions{
|
||||||
BindInterface: interfaceName,
|
BindInterface: interfaceName,
|
||||||
}),
|
})),
|
||||||
device: tunInterface,
|
device: tunInterface,
|
||||||
name: interfaceName,
|
name: interfaceName,
|
||||||
mtu: int(mtu),
|
mtu: int(mtu),
|
||||||
|
|
Loading…
Reference in a new issue