Add TCP MultiPath support

This commit is contained in:
世界 2023-08-08 16:14:03 +08:00
parent 81b847faca
commit 1019ecfdcf
No known key found for this signature in database
GPG key ID: CD109927C34A63C4
33 changed files with 225 additions and 43 deletions

View file

@ -26,7 +26,7 @@ type DefaultDialer struct {
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 listener net.ListenConfig
if options.BindInterface != "" {
@ -93,6 +93,12 @@ func NewDefault(router adapter.Router, options option.DialerOptions) *DefaultDia
udpDialer6.LocalAddr = &net.UDPAddr{IP: bindAddr.AsSlice()}
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{
tfo.Dialer{Dialer: dialer4, DisableTFO: !options.TCPFastOpen},
tfo.Dialer{Dialer: dialer6, DisableTFO: !options.TCPFastOpen},
@ -101,7 +107,7 @@ func NewDefault(router adapter.Router, options option.DialerOptions) *DefaultDia
listener,
udpAddr4,
udpAddr6,
}
}, nil
}
func (d *DefaultDialer) DialContext(ctx context.Context, network string, address M.Socksaddr) (net.Conn, error) {

View file

@ -0,0 +1,11 @@
//go:build go1.21
package dialer
import "net"
const multipathTCPAvailable = true
func setMultiPathTCP(dialer *net.Dialer) {
dialer.SetMultipathTCP(true)
}

View file

@ -0,0 +1,12 @@
//go:build !go1.21
package dialer
import (
"net"
)
const multipathTCPAvailable = false
func setMultiPathTCP(dialer *net.Dialer) {
}

View file

@ -6,13 +6,24 @@ import (
"github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing-box/option"
"github.com/sagernet/sing-dns"
"github.com/sagernet/sing/common"
N "github.com/sagernet/sing/common/network"
)
func New(router adapter.Router, options option.DialerOptions) N.Dialer {
var dialer N.Dialer
func MustNew(router adapter.Router, options option.DialerOptions) 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 == "" {
dialer = NewDefault(router, options)
dialer, err = NewDefault(router, options)
if err != nil {
return nil, err
}
} else {
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 == "" {
dialer = NewResolveDialer(router, dialer, domainStrategy, time.Duration(options.FallbackDelay))
}
return dialer
return dialer, nil
}

View file

@ -101,7 +101,10 @@ func NewRealityServer(ctx context.Context, router adapter.Router, logger log.Log
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) {
return handshakeDialer.DialContext(ctx, network, M.ParseSocksaddr(addr))
}

View file

@ -10,6 +10,7 @@
"reuse_addr": false,
"connect_timeout": "5s",
"tcp_fast_open": false,
"tcp_multi_path": false,
"udp_fragment": false,
"domain_strategy": "prefer_ipv6",
"fallback_delay": "300ms"
@ -18,9 +19,9 @@
### Fields
| Field | Available Context |
|----------------------------------------------------------------------------------------------------------------------|-------------------|
| `bind_interface` /`*bind_address` /`routing_mark` /`reuse_addr` / `tcp_fast_open`/ `udp_fragment` /`connect_timeout` | `detour` not set |
| Field | Available Context |
|------------------------------------------------------------------------------------------------------------------------------------------|-------------------|
| `bind_interface` /`*bind_address` /`routing_mark` /`reuse_addr` / `tcp_fast_open` / `tcp_multi_path` / `udp_fragment` /`connect_timeout` | `detour` not set |
#### detour
@ -54,6 +55,14 @@ Reuse listener address.
Enable TCP Fast Open.
#### tcp_multi_path
!!! warning ""
Go 1.21 required.
Enable TCP Multi Path.
#### udp_fragment
Enable UDP fragmentation.

View file

@ -10,6 +10,7 @@
"reuse_addr": false,
"connect_timeout": "5s",
"tcp_fast_open": false,
"tcp_multi_path": false,
"udp_fragment": false,
"domain_strategy": "prefer_ipv6",
"fallback_delay": "300ms"
@ -18,9 +19,9 @@
### 字段
| 字段 | 可用上下文 |
|----------------------------------------------------------------------------------------------------------------------|--------------|
| `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
@ -57,6 +58,14 @@
启用 TCP Fast Open。
#### tcp_multi_path
!!! warning ""
需要 Go 1.21。
启用 TCP Multi Path。
#### udp_fragment
启用 UDP 分段。

View file

@ -5,6 +5,7 @@
"listen": "::",
"listen_port": 5353,
"tcp_fast_open": false,
"tcp_multi_path": false,
"udp_fragment": false,
"sniff": false,
"sniff_override_destination": false,
@ -24,6 +25,7 @@
| `listen` | 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_multi_path` | Needs to listen on TCP. |
| `udp_timeout` | Needs to assemble UDP connections, currently Tun and Shadowsocks. |
| `proxy_protocol` | Needs to listen on TCP. |
| `proxy_protocol_accept_no_header` | When `proxy_protocol` enabled |
@ -42,6 +44,14 @@ Listen port.
Enable TCP Fast Open.
#### tcp_multi_path
!!! warning ""
Go 1.21 required.
Enable TCP Multi Path.
#### udp_fragment
Enable UDP fragmentation.

View file

@ -5,6 +5,7 @@
"listen": "::",
"listen_port": 5353,
"tcp_fast_open": false,
"tcp_multi_path": false,
"udp_fragment": false,
"sniff": false,
"sniff_override_destination": false,
@ -23,6 +24,7 @@
| `listen` | 需要监听 TCP 或 UDP。 |
| `listen_port` | 需要监听 TCP 或 UDP。 |
| `tcp_fast_open` | 需要监听 TCP。 |
| `tcp_multi_path` | 需要监听 TCP。 |
| `udp_timeout` | 需要组装 UDP 连接, 当前为 Tun 和 Shadowsocks。 |
| `proxy_protocol` | 需要监听 TCP。 |
| `proxy_protocol_accept_no_header` | `proxy_protocol` 启用时 |
@ -43,6 +45,14 @@
启用 TCP Fast Open。
#### tcp_multi_path
!!! warning ""
需要 Go 1.21。
启用 TCP Multi Path。
#### udp_fragment
启用 UDP 分段。

View file

@ -18,7 +18,14 @@ func (a *myInboundAdapter) ListenTCP() (net.Listener, error) {
bindAddr := M.SocksaddrFrom(a.listenOptions.Listen.Build(), a.listenOptions.ListenPort)
var tcpListener net.Listener
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 {
tcpListener, err = tfo.ListenTCP(M.NetworkFromNetAddr(N.NetworkTCP, bindAddr.Addr), bindAddr.TCPAddr())
}

View file

@ -0,0 +1,11 @@
//go:build go1.21
package inbound
import "net"
const multipathTCPAvailable = true
func setMultiPathTCP(listenConfig *net.ListenConfig) {
listenConfig.SetMultipathTCP(true)
}

View file

@ -0,0 +1,10 @@
//go:build !go1.21
package inbound
import "net"
const multipathTCPAvailable = false
func setMultiPathTCP(listenConfig *net.ListenConfig) {
}

View file

@ -40,12 +40,20 @@ func NewShadowTLS(ctx context.Context, router adapter.Router, logger log.Context
if options.Version > 1 {
handshakeForServerName = make(map[string]shadowtls.HandshakeConfig)
for serverName, serverOptions := range options.HandshakeForServerName {
handshakeDialer, err := dialer.New(router, serverOptions.DialerOptions)
if err != nil {
return nil, err
}
handshakeForServerName[serverName] = shadowtls.HandshakeConfig{
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{
Version: options.Version,
Password: options.Password,
@ -54,7 +62,7 @@ func NewShadowTLS(ctx context.Context, router adapter.Router, logger log.Context
}),
Handshake: shadowtls.HandshakeConfig{
Server: options.Handshake.ServerOptions.Build(),
Dialer: dialer.New(router, options.Handshake.DialerOptions),
Dialer: handshakeDialer,
},
HandshakeForServerName: handshakeForServerName,
StrictMode: options.StrictMode,

View file

@ -31,7 +31,7 @@ type Service struct {
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)
server := options.ServerOptions.Build()
if server.Port == 0 {
@ -43,15 +43,19 @@ func NewService(ctx context.Context, router adapter.Router, logger logger.Logger
} else {
interval = 30 * time.Minute
}
outboundDialer, err := dialer.New(router, options.DialerOptions)
if err != nil {
return nil, err
}
return &Service{
ctx: ctx,
cancel: cancel,
server: server,
writeToSystem: options.WriteToSystem,
dialer: dialer.New(router, options.DialerOptions),
dialer: outboundDialer,
logger: logger,
ticker: time.NewTicker(interval),
}
}, nil
}
func (s *Service) Start() error {

View file

@ -125,6 +125,7 @@ type ListenOptions struct {
Listen *ListenAddress `json:"listen,omitempty"`
ListenPort uint16 `json:"listen_port,omitempty"`
TCPFastOpen bool `json:"tcp_fast_open,omitempty"`
TCPMultiPath bool `json:"tcp_multi_path,omitempty"`
UDPFragment *bool `json:"udp_fragment,omitempty"`
UDPFragmentDefault bool `json:"-"`
UDPTimeout int64 `json:"udp_timeout,omitempty"`

View file

@ -134,6 +134,7 @@ type DialerOptions struct {
ReuseAddr bool `json:"reuse_addr,omitempty"`
ConnectTimeout Duration `json:"connect_timeout,omitempty"`
TCPFastOpen bool `json:"tcp_fast_open,omitempty"`
TCPMultiPath bool `json:"tcp_multi_path,omitempty"`
UDPFragment *bool `json:"udp_fragment,omitempty"`
UDPFragmentDefault bool `json:"-"`
DomainStrategy DomainStrategy `json:"domain_strategy,omitempty"`

View file

@ -38,6 +38,10 @@ type Direct struct {
func NewDirect(router adapter.Router, logger log.ContextLogger, tag string, options option.DirectOutboundOptions) (*Direct, error) {
options.UDPFragmentDefault = true
outboundDialer, err := dialer.New(router, options.DialerOptions)
if err != nil {
return nil, err
}
outbound := &Direct{
myOutboundAdapter: myOutboundAdapter{
protocol: C.TypeDirect,
@ -49,7 +53,7 @@ func NewDirect(router adapter.Router, logger log.ContextLogger, tag string, opti
},
domainStrategy: dns.DomainStrategy(options.DomainStrategy),
fallbackDelay: time.Duration(options.FallbackDelay),
dialer: dialer.New(router, options.DialerOptions),
dialer: outboundDialer,
proxyProto: options.ProxyProtocol,
}
if options.ProxyProtocol > 2 {

View file

@ -26,7 +26,11 @@ type HTTP struct {
}
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 {
return nil, err
}

View file

@ -117,6 +117,10 @@ func NewHysteria(ctx context.Context, router adapter.Router, logger log.ContextL
if down < hysteria.MinSpeedBPS {
return nil, E.New("invalid down speed")
}
outboundDialer, err := dialer.New(router, options.DialerOptions)
if err != nil {
return nil, err
}
return &Hysteria{
myOutboundAdapter: myOutboundAdapter{
protocol: C.TypeHysteria,
@ -127,7 +131,7 @@ func NewHysteria(ctx context.Context, router adapter.Router, logger log.ContextL
dependencies: withDialerDependency(options.DialerOptions),
},
ctx: ctx,
dialer: dialer.New(router, options.DialerOptions),
dialer: outboundDialer,
serverAddr: options.ServerOptions.Build(),
tlsConfig: tlsConfig,
quicConfig: quicConfig,

View file

@ -39,6 +39,10 @@ func NewShadowsocks(ctx context.Context, router adapter.Router, logger log.Conte
if err != nil {
return nil, err
}
outboundDialer, err := dialer.New(router, options.DialerOptions)
if err != nil {
return nil, err
}
outbound := &Shadowsocks{
myOutboundAdapter: myOutboundAdapter{
protocol: C.TypeShadowsocks,
@ -48,7 +52,7 @@ func NewShadowsocks(ctx context.Context, router adapter.Router, logger log.Conte
tag: tag,
dependencies: withDialerDependency(options.DialerOptions),
},
dialer: dialer.New(router, options.DialerOptions),
dialer: outboundDialer,
method: method,
serverAddr: options.ServerOptions.Build(),
}

View file

@ -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) {
outboundDialer, err := dialer.New(router, options.DialerOptions)
if err != nil {
return nil, err
}
outbound := &ShadowsocksR{
myOutboundAdapter: myOutboundAdapter{
protocol: C.TypeShadowsocksR,
@ -46,11 +50,10 @@ func NewShadowsocksR(ctx context.Context, router adapter.Router, logger log.Cont
tag: tag,
dependencies: withDialerDependency(options.DialerOptions),
},
dialer: dialer.New(router, options.DialerOptions),
dialer: outboundDialer,
serverAddr: options.ServerOptions.Build(),
}
var cipher string
var err error
switch options.Method {
case "none":
cipher = "dummy"

View file

@ -72,11 +72,15 @@ func NewShadowTLS(ctx context.Context, router adapter.Router, logger log.Context
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{
Version: options.Version,
Password: options.Password,
Server: options.ServerOptions.Build(),
Dialer: dialer.New(router, options.DialerOptions),
Dialer: outboundDialer,
TLSHandshake: tlsHandshakeFunc,
Logger: logger,
})

View file

@ -37,6 +37,10 @@ func NewSocks(router adapter.Router, logger log.ContextLogger, tag string, optio
if err != nil {
return nil, err
}
outboundDialer, err := dialer.New(router, options.DialerOptions)
if err != nil {
return nil, err
}
outbound := &Socks{
myOutboundAdapter: myOutboundAdapter{
protocol: C.TypeSOCKS,
@ -46,7 +50,7 @@ func NewSocks(router adapter.Router, logger log.ContextLogger, tag string, optio
tag: tag,
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,
}
uotOptions := common.PtrValueOrDefault(options.UDPOverTCPOptions)

View file

@ -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) {
outboundDialer, err := dialer.New(router, options.DialerOptions)
if err != nil {
return nil, err
}
outbound := &SSH{
myOutboundAdapter: myOutboundAdapter{
protocol: C.TypeSSH,
@ -54,7 +58,7 @@ func NewSSH(ctx context.Context, router adapter.Router, logger log.ContextLogger
dependencies: withDialerDependency(options.DialerOptions),
},
ctx: ctx,
dialer: dialer.New(router, options.DialerOptions),
dialer: outboundDialer,
serverAddr: options.ServerOptions.Build(),
user: options.User,
hostKeyAlgorithms: options.HostKeyAlgorithms,

View file

@ -66,6 +66,10 @@ func NewTor(ctx context.Context, router adapter.Router, logger log.ContextLogger
}
startConf.TorrcFile = torrcFile
}
outboundDialer, err := dialer.New(router, options.DialerOptions)
if err != nil {
return nil, err
}
return &Tor{
myOutboundAdapter: myOutboundAdapter{
protocol: C.TypeTor,
@ -76,7 +80,7 @@ func NewTor(ctx context.Context, router adapter.Router, logger log.ContextLogger
dependencies: withDialerDependency(options.DialerOptions),
},
ctx: ctx,
proxy: NewProxyListener(ctx, logger, dialer.New(router, options.DialerOptions)),
proxy: NewProxyListener(ctx, logger, outboundDialer),
startConf: &startConf,
options: options.Options,
}, nil

View file

@ -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) {
outboundDialer, err := dialer.New(router, options.DialerOptions)
if err != nil {
return nil, err
}
outbound := &Trojan{
myOutboundAdapter: myOutboundAdapter{
protocol: C.TypeTrojan,
@ -42,11 +46,10 @@ func NewTrojan(ctx context.Context, router adapter.Router, logger log.ContextLog
tag: tag,
dependencies: withDialerDependency(options.DialerOptions),
},
dialer: dialer.New(router, options.DialerOptions),
dialer: outboundDialer,
serverAddr: options.ServerOptions.Build(),
key: trojan.Key(options.Password),
}
var err error
if options.TLS != nil {
outbound.tlsConfig, err = tls.NewClient(router, options.Server, common.PtrValueOrDefault(options.TLS))
if err != nil {

View file

@ -57,9 +57,13 @@ func NewTUIC(ctx context.Context, router adapter.Router, logger log.ContextLogge
case "quic":
udpStream = true
}
outboundDialer, err := dialer.New(router, options.DialerOptions)
if err != nil {
return nil, err
}
client, err := tuic.NewClient(tuic.ClientOptions{
Context: ctx,
Dialer: dialer.New(router, options.DialerOptions),
Dialer: outboundDialer,
ServerAddress: options.ServerOptions.Build(),
TLSConfig: tlsConfig,
UUID: userUUID,

View file

@ -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) {
outboundDialer, err := dialer.New(router, options.DialerOptions)
if err != nil {
return nil, err
}
outbound := &VLESS{
myOutboundAdapter: myOutboundAdapter{
protocol: C.TypeVLESS,
@ -45,10 +49,9 @@ func NewVLESS(ctx context.Context, router adapter.Router, logger log.ContextLogg
tag: tag,
dependencies: withDialerDependency(options.DialerOptions),
},
dialer: dialer.New(router, options.DialerOptions),
dialer: outboundDialer,
serverAddr: options.ServerOptions.Build(),
}
var err error
if options.TLS != nil {
outbound.tlsConfig, err = tls.NewClient(router, options.Server, common.PtrValueOrDefault(options.TLS))
if err != nil {

View file

@ -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) {
outboundDialer, err := dialer.New(router, options.DialerOptions)
if err != nil {
return nil, err
}
outbound := &VMess{
myOutboundAdapter: myOutboundAdapter{
protocol: C.TypeVMess,
@ -44,10 +48,9 @@ func NewVMess(ctx context.Context, router adapter.Router, logger log.ContextLogg
tag: tag,
dependencies: withDialerDependency(options.DialerOptions),
},
dialer: dialer.New(router, options.DialerOptions),
dialer: outboundDialer,
serverAddr: options.ServerOptions.Build(),
}
var err error
if options.TLS != nil {
outbound.tlsConfig, err = tls.NewClient(router, options.Server, common.PtrValueOrDefault(options.TLS))
if err != nil {

View file

@ -65,7 +65,11 @@ func NewWireGuard(ctx context.Context, router adapter.Router, logger log.Context
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)
if len(localPrefixes) == 0 {
return nil, E.New("missing local address")
@ -157,7 +161,6 @@ func NewWireGuard(ctx context.Context, router adapter.Router, logger log.Context
mtu = 1408
}
var wireTunDevice wireguard.Device
var err error
if !options.SystemInterface && tun.WithGVisor {
wireTunDevice, err = wireguard.NewStackDevice(localPrefixes, mtu)
} else {

View file

@ -38,7 +38,9 @@ import (
F "github.com/sagernet/sing/common/format"
M "github.com/sagernet/sing/common/metadata"
N "github.com/sagernet/sing/common/network"
serviceNTP "github.com/sagernet/sing/common/ntp"
"github.com/sagernet/sing/common/uot"
"github.com/sagernet/sing/service"
"github.com/sagernet/sing/service/pause"
)
@ -319,7 +321,12 @@ func NewRouter(
}
}
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
}

View file

@ -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,
UDPFragmentDefault: true,
})
}))
var transports []dns.Transport
for _, serverAddr := range serverAddrs {
serverTransport, err := dns.NewUDPTransport(t.name, t.ctx, serverDialer, M.Socksaddr{Addr: serverAddr, Port: 53})

View file

@ -10,6 +10,7 @@ import (
"github.com/sagernet/sing-box/common/dialer"
"github.com/sagernet/sing-box/option"
"github.com/sagernet/sing-tun"
"github.com/sagernet/sing/common"
M "github.com/sagernet/sing/common/metadata"
N "github.com/sagernet/sing/common/network"
wgTun "github.com/sagernet/wireguard-go/tun"
@ -58,9 +59,9 @@ func NewSystemDevice(router adapter.Router, interfaceName string, localPrefixes
inet6Address = inet6Addresses[0].Addr()
}
return &SystemDevice{
dialer: dialer.NewDefault(router, option.DialerOptions{
dialer: common.Must1(dialer.NewDefault(router, option.DialerOptions{
BindInterface: interfaceName,
}),
})),
device: tunInterface,
name: interfaceName,
mtu: int(mtu),