mirror of
https://github.com/SagerNet/sing-box.git
synced 2024-11-22 08:31:30 +00:00
Improve udp timeout
This commit is contained in:
parent
5491895a60
commit
816d7b734c
48
common/canceler/instance.go
Normal file
48
common/canceler/instance.go
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
package canceler
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Instance struct {
|
||||||
|
ctx context.Context
|
||||||
|
cancelFunc context.CancelFunc
|
||||||
|
timer *time.Timer
|
||||||
|
timeout time.Duration
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(ctx context.Context, cancelFunc context.CancelFunc, timeout time.Duration) *Instance {
|
||||||
|
instance := &Instance{
|
||||||
|
ctx,
|
||||||
|
cancelFunc,
|
||||||
|
time.NewTimer(timeout),
|
||||||
|
timeout,
|
||||||
|
}
|
||||||
|
go instance.wait()
|
||||||
|
return instance
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *Instance) Update() bool {
|
||||||
|
if !i.timer.Stop() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if !i.timer.Reset(i.timeout) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *Instance) wait() {
|
||||||
|
select {
|
||||||
|
case <-i.timer.C:
|
||||||
|
case <-i.ctx.Done():
|
||||||
|
}
|
||||||
|
i.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *Instance) Close() error {
|
||||||
|
i.timer.Stop()
|
||||||
|
i.cancelFunc()
|
||||||
|
return nil
|
||||||
|
}
|
41
common/canceler/packet.go
Normal file
41
common/canceler/packet.go
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
package canceler
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/sagernet/sing/common/buf"
|
||||||
|
M "github.com/sagernet/sing/common/metadata"
|
||||||
|
N "github.com/sagernet/sing/common/network"
|
||||||
|
)
|
||||||
|
|
||||||
|
type PacketConn struct {
|
||||||
|
N.PacketConn
|
||||||
|
instance *Instance
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewPacketConn(ctx context.Context, conn N.PacketConn, timeout time.Duration) (context.Context, N.PacketConn) {
|
||||||
|
ctx, cancel := context.WithCancel(ctx)
|
||||||
|
instance := New(ctx, cancel, timeout)
|
||||||
|
return ctx, &PacketConn{conn, instance}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *PacketConn) ReadPacket(buffer *buf.Buffer) (destination M.Socksaddr, err error) {
|
||||||
|
destination, err = c.PacketConn.ReadPacket(buffer)
|
||||||
|
if err == nil {
|
||||||
|
c.instance.Update()
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *PacketConn) WritePacket(buffer *buf.Buffer, destination M.Socksaddr) error {
|
||||||
|
err := c.PacketConn.WritePacket(buffer, destination)
|
||||||
|
if err == nil {
|
||||||
|
c.instance.Update()
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *PacketConn) Upstream() any {
|
||||||
|
return c.PacketConn
|
||||||
|
}
|
|
@ -103,7 +103,7 @@ func NewDefault(router adapter.Router, options option.DialerOptions) *DefaultDia
|
||||||
if options.ConnectTimeout != 0 {
|
if options.ConnectTimeout != 0 {
|
||||||
dialer.Timeout = time.Duration(options.ConnectTimeout)
|
dialer.Timeout = time.Duration(options.ConnectTimeout)
|
||||||
} else {
|
} else {
|
||||||
dialer.Timeout = C.DefaultTCPTimeout
|
dialer.Timeout = C.TCPTimeout
|
||||||
}
|
}
|
||||||
if options.TCPFastOpen {
|
if options.TCPFastOpen {
|
||||||
warnTFOOnUnsupportedPlatform.Check()
|
warnTFOOnUnsupportedPlatform.Check()
|
||||||
|
@ -118,7 +118,7 @@ func (d *DefaultDialer) DialContext(ctx context.Context, network string, address
|
||||||
}
|
}
|
||||||
if tcpConn, isTCP := common.Cast[*net.TCPConn](conn); isTCP {
|
if tcpConn, isTCP := common.Cast[*net.TCPConn](conn); isTCP {
|
||||||
tcpConn.SetKeepAlive(true)
|
tcpConn.SetKeepAlive(true)
|
||||||
tcpConn.SetKeepAlivePeriod(C.DefaultTCPKeepAlivePeriod)
|
tcpConn.SetKeepAlivePeriod(C.TCPKeepAlivePeriod)
|
||||||
}
|
}
|
||||||
return conn, nil
|
return conn, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -129,7 +129,7 @@ func (d *TLSDialer) DialContext(ctx context.Context, network string, destination
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
tlsConn := tls.Client(conn, d.config)
|
tlsConn := tls.Client(conn, d.config)
|
||||||
ctx, cancel := context.WithTimeout(ctx, C.DefaultTCPTimeout)
|
ctx, cancel := context.WithTimeout(ctx, C.TCPTimeout)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
err = tlsConn.HandshakeContext(ctx)
|
err = tlsConn.HandshakeContext(ctx)
|
||||||
return tlsConn, err
|
return tlsConn, err
|
||||||
|
|
|
@ -3,9 +3,12 @@ package constant
|
||||||
import "time"
|
import "time"
|
||||||
|
|
||||||
const (
|
const (
|
||||||
DefaultTCPTimeout = 5 * time.Second
|
TCPTimeout = 5 * time.Second
|
||||||
DefaultTCPKeepAlivePeriod = 20 * time.Second
|
TCPKeepAlivePeriod = 20 * time.Second
|
||||||
ReadPayloadTimeout = 300 * time.Millisecond
|
ReadPayloadTimeout = 300 * time.Millisecond
|
||||||
URLTestTimeout = DefaultTCPTimeout
|
URLTestTimeout = TCPTimeout
|
||||||
DefaultURLTestInterval = 1 * time.Minute
|
DefaultURLTestInterval = 1 * time.Minute
|
||||||
|
DNSTimeout = 10 * time.Second
|
||||||
|
QUICTimeout = 30 * time.Second
|
||||||
|
STUNTimeout = 15 * time.Second
|
||||||
)
|
)
|
||||||
|
|
2
go.mod
2
go.mod
|
@ -12,7 +12,7 @@ require (
|
||||||
github.com/gorilla/websocket v1.5.0
|
github.com/gorilla/websocket v1.5.0
|
||||||
github.com/logrusorgru/aurora v2.0.3+incompatible
|
github.com/logrusorgru/aurora v2.0.3+incompatible
|
||||||
github.com/oschwald/maxminddb-golang v1.9.0
|
github.com/oschwald/maxminddb-golang v1.9.0
|
||||||
github.com/sagernet/sing v0.0.0-20220725031620-096223b346f3
|
github.com/sagernet/sing v0.0.0-20220725141316-c15de13f4f68
|
||||||
github.com/sagernet/sing-dns v0.0.0-20220724053927-eb8d0d542175
|
github.com/sagernet/sing-dns v0.0.0-20220724053927-eb8d0d542175
|
||||||
github.com/sagernet/sing-shadowsocks v0.0.0-20220717063942-45a2ad9cd41f
|
github.com/sagernet/sing-shadowsocks v0.0.0-20220717063942-45a2ad9cd41f
|
||||||
github.com/sagernet/sing-tun v0.0.0-20220720051454-d35c334b46c9
|
github.com/sagernet/sing-tun v0.0.0-20220720051454-d35c334b46c9
|
||||||
|
|
4
go.sum
4
go.sum
|
@ -37,8 +37,8 @@ github.com/oschwald/maxminddb-golang v1.9.0/go.mod h1:TK+s/Z2oZq0rSl4PSeAEoP0bgm
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
github.com/sagernet/sing v0.0.0-20220725031620-096223b346f3 h1:Qm57CtqzaZ6Cq0ZDz1dX4vSNUoTYKn7qfXnpleKE0z0=
|
github.com/sagernet/sing v0.0.0-20220725141316-c15de13f4f68 h1:EQ80ogJM1Xk4zgYI5lioDc15SCFeP0vdM5DMlmAOqnc=
|
||||||
github.com/sagernet/sing v0.0.0-20220725031620-096223b346f3/go.mod h1:GbtQfZSpmtD3cXeD1qX2LCMwY8dH+bnnInDTqd92IsM=
|
github.com/sagernet/sing v0.0.0-20220725141316-c15de13f4f68/go.mod h1:GbtQfZSpmtD3cXeD1qX2LCMwY8dH+bnnInDTqd92IsM=
|
||||||
github.com/sagernet/sing-dns v0.0.0-20220724053927-eb8d0d542175 h1:YpacS9+rDFcLG8lSkmwU21capz2gewk4LQfCE/x73U0=
|
github.com/sagernet/sing-dns v0.0.0-20220724053927-eb8d0d542175 h1:YpacS9+rDFcLG8lSkmwU21capz2gewk4LQfCE/x73U0=
|
||||||
github.com/sagernet/sing-dns v0.0.0-20220724053927-eb8d0d542175/go.mod h1:2A34p89do4H4E9Ke046cJCMTdVqmvsXGWXzRwgeO2TQ=
|
github.com/sagernet/sing-dns v0.0.0-20220724053927-eb8d0d542175/go.mod h1:2A34p89do4H4E9Ke046cJCMTdVqmvsXGWXzRwgeO2TQ=
|
||||||
github.com/sagernet/sing-shadowsocks v0.0.0-20220717063942-45a2ad9cd41f h1:F6yiuKbBoXgWiuoP7R0YA14pDEl3emxA1mL7M16Q7gc=
|
github.com/sagernet/sing-shadowsocks v0.0.0-20220717063942-45a2ad9cd41f h1:F6yiuKbBoXgWiuoP7R0YA14pDEl3emxA1mL7M16Q7gc=
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/sagernet/sing-box/adapter"
|
"github.com/sagernet/sing-box/adapter"
|
||||||
|
"github.com/sagernet/sing-box/common/canceler"
|
||||||
C "github.com/sagernet/sing-box/constant"
|
C "github.com/sagernet/sing-box/constant"
|
||||||
"github.com/sagernet/sing-box/log"
|
"github.com/sagernet/sing-box/log"
|
||||||
"github.com/sagernet/sing/common"
|
"github.com/sagernet/sing/common"
|
||||||
|
@ -78,6 +79,16 @@ func NewPacketConnection(ctx context.Context, this N.Dialer, conn N.PacketConn,
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if metadata.Protocol != "" {
|
||||||
|
switch metadata.Protocol {
|
||||||
|
case C.ProtocolQUIC:
|
||||||
|
ctx, conn = canceler.NewPacketConn(ctx, conn, C.QUICTimeout)
|
||||||
|
case C.ProtocolDNS:
|
||||||
|
ctx, conn = canceler.NewPacketConn(ctx, conn, C.DNSTimeout)
|
||||||
|
case C.ProtocolSTUN:
|
||||||
|
ctx, conn = canceler.NewPacketConn(ctx, conn, C.STUNTimeout)
|
||||||
|
}
|
||||||
|
}
|
||||||
return bufio.CopyPacketConn(ctx, conn, bufio.NewPacketConn(outConn))
|
return bufio.CopyPacketConn(ctx, conn, bufio.NewPacketConn(outConn))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,10 +6,9 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"sync"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/sagernet/sing-box/adapter"
|
"github.com/sagernet/sing-box/adapter"
|
||||||
|
"github.com/sagernet/sing-box/common/canceler"
|
||||||
C "github.com/sagernet/sing-box/constant"
|
C "github.com/sagernet/sing-box/constant"
|
||||||
"github.com/sagernet/sing-box/log"
|
"github.com/sagernet/sing-box/log"
|
||||||
"github.com/sagernet/sing/common"
|
"github.com/sagernet/sing/common"
|
||||||
|
@ -103,14 +102,14 @@ func (d *DNS) NewConnection(ctx context.Context, conn net.Conn, metadata adapter
|
||||||
func (d *DNS) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error {
|
func (d *DNS) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error {
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
ctx = adapter.WithContext(ctx, &metadata)
|
ctx = adapter.WithContext(ctx, &metadata)
|
||||||
_buffer := buf.StackNewSize(1024)
|
|
||||||
defer common.KeepAlive(_buffer)
|
|
||||||
buffer := common.Dup(_buffer)
|
|
||||||
defer buffer.Release()
|
|
||||||
var wg sync.WaitGroup
|
|
||||||
fastClose, cancel := context.WithCancel(ctx)
|
fastClose, cancel := context.WithCancel(ctx)
|
||||||
err := task.Run(fastClose, func() error {
|
timeout := canceler.New(fastClose, cancel, C.DNSTimeout)
|
||||||
var count int
|
return task.Run(fastClose, func() error {
|
||||||
|
defer cancel()
|
||||||
|
_buffer := buf.StackNewSize(1024)
|
||||||
|
defer common.KeepAlive(_buffer)
|
||||||
|
buffer := common.Dup(_buffer)
|
||||||
|
defer buffer.Release()
|
||||||
for {
|
for {
|
||||||
buffer.FullReset()
|
buffer.FullReset()
|
||||||
destination, err := conn.ReadPacket(buffer)
|
destination, err := conn.ReadPacket(buffer)
|
||||||
|
@ -127,13 +126,13 @@ func (d *DNS) NewPacketConnection(ctx context.Context, conn N.PacketConn, metada
|
||||||
metadata.Domain = string(question.Name.Data[:question.Name.Length-1])
|
metadata.Domain = string(question.Name.Data[:question.Name.Length-1])
|
||||||
d.logger.DebugContext(ctx, "inbound dns query ", formatDNSQuestion(question), " from ", metadata.Source)
|
d.logger.DebugContext(ctx, "inbound dns query ", formatDNSQuestion(question), " from ", metadata.Source)
|
||||||
}
|
}
|
||||||
wg.Add(1)
|
timeout.Update()
|
||||||
go func() error {
|
go func() error {
|
||||||
defer wg.Done()
|
|
||||||
response, err := d.router.Exchange(ctx, &message)
|
response, err := d.router.Exchange(ctx, &message)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
timeout.Update()
|
||||||
_responseBuffer := buf.StackNewSize(1024)
|
_responseBuffer := buf.StackNewSize(1024)
|
||||||
defer common.KeepAlive(_responseBuffer)
|
defer common.KeepAlive(_responseBuffer)
|
||||||
responseBuffer := common.Dup(_responseBuffer)
|
responseBuffer := common.Dup(_responseBuffer)
|
||||||
|
@ -146,24 +145,8 @@ func (d *DNS) NewPacketConnection(ctx context.Context, conn N.PacketConn, metada
|
||||||
err = conn.WritePacket(responseBuffer, destination)
|
err = conn.WritePacket(responseBuffer, destination)
|
||||||
return err
|
return err
|
||||||
}()
|
}()
|
||||||
count++
|
|
||||||
if count == 2 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
cancel()
|
|
||||||
return nil
|
|
||||||
}, func() error {
|
|
||||||
timer := time.NewTimer(5 * time.Second)
|
|
||||||
select {
|
|
||||||
case <-timer.C:
|
|
||||||
cancel()
|
|
||||||
case <-fastClose.Done():
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
})
|
||||||
wg.Wait()
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func formatDNSQuestion(question dnsmessage.Question) string {
|
func formatDNSQuestion(question dnsmessage.Question) string {
|
||||||
|
|
|
@ -3,6 +3,7 @@ package outbound
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"net"
|
"net"
|
||||||
|
"sort"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/sagernet/sing-box/adapter"
|
"github.com/sagernet/sing-box/adapter"
|
||||||
|
@ -167,6 +168,29 @@ func (g *URLTestGroup) Select() adapter.Outbound {
|
||||||
return minOutbound
|
return minOutbound
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (g *URLTestGroup) Fallback(used adapter.Outbound) []adapter.Outbound {
|
||||||
|
outbounds := make([]adapter.Outbound, 0, len(g.outbounds)-1)
|
||||||
|
for _, detour := range g.outbounds {
|
||||||
|
if detour != used {
|
||||||
|
outbounds = append(outbounds, detour)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sort.Slice(outbounds, func(i, j int) bool {
|
||||||
|
oi := outbounds[i]
|
||||||
|
oj := outbounds[j]
|
||||||
|
hi := g.router.URLTestHistoryStorage(false).LoadURLTestHistory(RealTag(oi))
|
||||||
|
if hi == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
hj := g.router.URLTestHistoryStorage(false).LoadURLTestHistory(RealTag(oj))
|
||||||
|
if hj == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return hi.Delay < hj.Delay
|
||||||
|
})
|
||||||
|
return outbounds
|
||||||
|
}
|
||||||
|
|
||||||
func (g *URLTestGroup) loopCheck() {
|
func (g *URLTestGroup) loopCheck() {
|
||||||
go g.checkOutbounds()
|
go g.checkOutbounds()
|
||||||
for {
|
for {
|
||||||
|
|
|
@ -576,16 +576,22 @@ func (r *Router) RoutePacketConnection(ctx context.Context, conn N.PacketConn, m
|
||||||
|
|
||||||
func (r *Router) Exchange(ctx context.Context, message *dnsmessage.Message) (*dnsmessage.Message, error) {
|
func (r *Router) Exchange(ctx context.Context, message *dnsmessage.Message) (*dnsmessage.Message, error) {
|
||||||
ctx, transport := r.matchDNS(ctx)
|
ctx, transport := r.matchDNS(ctx)
|
||||||
|
ctx, cancel := context.WithTimeout(ctx, C.DNSTimeout)
|
||||||
|
defer cancel()
|
||||||
return r.dnsClient.Exchange(ctx, transport, message)
|
return r.dnsClient.Exchange(ctx, transport, message)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Router) Lookup(ctx context.Context, domain string, strategy dns.DomainStrategy) ([]netip.Addr, error) {
|
func (r *Router) Lookup(ctx context.Context, domain string, strategy dns.DomainStrategy) ([]netip.Addr, error) {
|
||||||
ctx, transport := r.matchDNS(ctx)
|
ctx, transport := r.matchDNS(ctx)
|
||||||
|
ctx, cancel := context.WithTimeout(ctx, C.DNSTimeout)
|
||||||
|
defer cancel()
|
||||||
return r.dnsClient.Lookup(ctx, transport, domain, strategy)
|
return r.dnsClient.Lookup(ctx, transport, domain, strategy)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Router) LookupDefault(ctx context.Context, domain string) ([]netip.Addr, error) {
|
func (r *Router) LookupDefault(ctx context.Context, domain string) ([]netip.Addr, error) {
|
||||||
ctx, transport := r.matchDNS(ctx)
|
ctx, transport := r.matchDNS(ctx)
|
||||||
|
ctx, cancel := context.WithTimeout(ctx, C.DNSTimeout)
|
||||||
|
defer cancel()
|
||||||
return r.dnsClient.Lookup(ctx, transport, domain, r.defaultDomainStrategy)
|
return r.dnsClient.Lookup(ctx, transport, domain, r.defaultDomainStrategy)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ require (
|
||||||
github.com/docker/docker v20.10.17+incompatible
|
github.com/docker/docker v20.10.17+incompatible
|
||||||
github.com/docker/go-connections v0.4.0
|
github.com/docker/go-connections v0.4.0
|
||||||
github.com/gofrs/uuid v4.2.0+incompatible
|
github.com/gofrs/uuid v4.2.0+incompatible
|
||||||
github.com/sagernet/sing v0.0.0-20220725031620-096223b346f3
|
github.com/sagernet/sing v0.0.0-20220725141316-c15de13f4f68
|
||||||
github.com/spyzhov/ajson v0.7.1
|
github.com/spyzhov/ajson v0.7.1
|
||||||
github.com/stretchr/testify v1.8.0
|
github.com/stretchr/testify v1.8.0
|
||||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b
|
golang.org/x/net v0.0.0-20220722155237-a158d28d115b
|
||||||
|
|
|
@ -64,8 +64,8 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/sagernet/sing v0.0.0-20220725031620-096223b346f3 h1:Qm57CtqzaZ6Cq0ZDz1dX4vSNUoTYKn7qfXnpleKE0z0=
|
github.com/sagernet/sing v0.0.0-20220725141316-c15de13f4f68 h1:EQ80ogJM1Xk4zgYI5lioDc15SCFeP0vdM5DMlmAOqnc=
|
||||||
github.com/sagernet/sing v0.0.0-20220725031620-096223b346f3/go.mod h1:GbtQfZSpmtD3cXeD1qX2LCMwY8dH+bnnInDTqd92IsM=
|
github.com/sagernet/sing v0.0.0-20220725141316-c15de13f4f68/go.mod h1:GbtQfZSpmtD3cXeD1qX2LCMwY8dH+bnnInDTqd92IsM=
|
||||||
github.com/sagernet/sing-dns v0.0.0-20220724053927-eb8d0d542175 h1:YpacS9+rDFcLG8lSkmwU21capz2gewk4LQfCE/x73U0=
|
github.com/sagernet/sing-dns v0.0.0-20220724053927-eb8d0d542175 h1:YpacS9+rDFcLG8lSkmwU21capz2gewk4LQfCE/x73U0=
|
||||||
github.com/sagernet/sing-dns v0.0.0-20220724053927-eb8d0d542175/go.mod h1:2A34p89do4H4E9Ke046cJCMTdVqmvsXGWXzRwgeO2TQ=
|
github.com/sagernet/sing-dns v0.0.0-20220724053927-eb8d0d542175/go.mod h1:2A34p89do4H4E9Ke046cJCMTdVqmvsXGWXzRwgeO2TQ=
|
||||||
github.com/sagernet/sing-shadowsocks v0.0.0-20220717063942-45a2ad9cd41f h1:F6yiuKbBoXgWiuoP7R0YA14pDEl3emxA1mL7M16Q7gc=
|
github.com/sagernet/sing-shadowsocks v0.0.0-20220717063942-45a2ad9cd41f h1:F6yiuKbBoXgWiuoP7R0YA14pDEl3emxA1mL7M16Q7gc=
|
||||||
|
|
Loading…
Reference in a new issue