mirror of
https://gitclone.com/github.com/MetaCubeX/Clash.Meta
synced 2025-04-24 20:28:11 +08:00
fix: sing_tun apply udpTimeout when using gvisor stack
This commit is contained in:
parent
5737fbc23c
commit
fd0580bfdd
4
go.mod
4
go.mod
@ -27,7 +27,7 @@ require (
|
|||||||
github.com/mroth/weightedrand/v2 v2.0.0
|
github.com/mroth/weightedrand/v2 v2.0.0
|
||||||
github.com/oschwald/geoip2-golang v1.8.0
|
github.com/oschwald/geoip2-golang v1.8.0
|
||||||
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97
|
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97
|
||||||
github.com/sagernet/sing v0.2.0
|
github.com/sagernet/sing v0.2.1-0.20230323055925-1c4c60c739ef
|
||||||
github.com/sagernet/sing-shadowtls v0.1.0
|
github.com/sagernet/sing-shadowtls v0.1.0
|
||||||
github.com/sagernet/sing-vmess v0.1.3
|
github.com/sagernet/sing-vmess v0.1.3
|
||||||
github.com/sagernet/tfo-go v0.0.0-20230303015439-ffcfd8c41cf9
|
github.com/sagernet/tfo-go v0.0.0-20230303015439-ffcfd8c41cf9
|
||||||
@ -42,7 +42,7 @@ require (
|
|||||||
go.uber.org/atomic v1.10.0
|
go.uber.org/atomic v1.10.0
|
||||||
go.uber.org/automaxprocs v1.5.1
|
go.uber.org/automaxprocs v1.5.1
|
||||||
golang.org/x/crypto v0.7.0
|
golang.org/x/crypto v0.7.0
|
||||||
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db
|
golang.org/x/exp v0.0.0-20230321023759-10a507213a29
|
||||||
golang.org/x/net v0.8.0
|
golang.org/x/net v0.8.0
|
||||||
golang.org/x/sync v0.1.0
|
golang.org/x/sync v0.1.0
|
||||||
golang.org/x/sys v0.6.0
|
golang.org/x/sys v0.6.0
|
||||||
|
8
go.sum
8
go.sum
@ -127,8 +127,8 @@ github.com/sagernet/go-tun2socks v1.16.12-0.20220818015926-16cb67876a61/go.mod h
|
|||||||
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 h1:iL5gZI3uFp0X6EslacyapiRz7LLSJyr4RajF/BhMVyE=
|
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 h1:iL5gZI3uFp0X6EslacyapiRz7LLSJyr4RajF/BhMVyE=
|
||||||
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97/go.mod h1:xLnfdiJbSp8rNqYEdIW/6eDO4mVoogml14Bh2hSiFpM=
|
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97/go.mod h1:xLnfdiJbSp8rNqYEdIW/6eDO4mVoogml14Bh2hSiFpM=
|
||||||
github.com/sagernet/sing v0.0.0-20220817130738-ce854cda8522/go.mod h1:QVsS5L/ZA2Q5UhQwLrn0Trw+msNd/NPGEhBKR/ioWiY=
|
github.com/sagernet/sing v0.0.0-20220817130738-ce854cda8522/go.mod h1:QVsS5L/ZA2Q5UhQwLrn0Trw+msNd/NPGEhBKR/ioWiY=
|
||||||
github.com/sagernet/sing v0.2.0 h1:iyc4TaeXG5XYXixl48zSDDTw46C9NOEAVFq6ZE0dA2k=
|
github.com/sagernet/sing v0.2.1-0.20230323055925-1c4c60c739ef h1:gCIUmEaAbTZnQU6DPcnJkqnD9D0W2f3mp/mx0HKiWI8=
|
||||||
github.com/sagernet/sing v0.2.0/go.mod h1:9uHswk2hITw8leDbiLS/xn0t9nzBcbePxzm9PJhwdlw=
|
github.com/sagernet/sing v0.2.1-0.20230323055925-1c4c60c739ef/go.mod h1:9uHswk2hITw8leDbiLS/xn0t9nzBcbePxzm9PJhwdlw=
|
||||||
github.com/sagernet/sing-shadowtls v0.1.0 h1:05MYce8aR5xfKIn+y7xRFsdKhKt44QZTSEQW+lG5IWQ=
|
github.com/sagernet/sing-shadowtls v0.1.0 h1:05MYce8aR5xfKIn+y7xRFsdKhKt44QZTSEQW+lG5IWQ=
|
||||||
github.com/sagernet/sing-shadowtls v0.1.0/go.mod h1:Kn1VUIprdkwCgkS6SXYaLmIpKzQbqBIKJBMY+RvBhYc=
|
github.com/sagernet/sing-shadowtls v0.1.0/go.mod h1:Kn1VUIprdkwCgkS6SXYaLmIpKzQbqBIKJBMY+RvBhYc=
|
||||||
github.com/sagernet/sing-vmess v0.1.3 h1:q/+tsF46dvvapL6CpQBgPHJ6nQrDUZqEtLHCbsjO7iM=
|
github.com/sagernet/sing-vmess v0.1.3 h1:q/+tsF46dvvapL6CpQBgPHJ6nQrDUZqEtLHCbsjO7iM=
|
||||||
@ -173,8 +173,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
|
|||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A=
|
golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A=
|
||||||
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
|
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
|
||||||
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db h1:D/cFflL63o2KSLJIwjlcIt8PR064j/xsmdEJL/YvY/o=
|
golang.org/x/exp v0.0.0-20230321023759-10a507213a29 h1:ooxPy7fPvB4kwsA2h+iBNHkAbp/4JxTSwCmvdjEYmug=
|
||||||
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
|
golang.org/x/exp v0.0.0-20230321023759-10a507213a29/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
|
||||||
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
|
@ -3,6 +3,7 @@ package sing
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
|
"go.uber.org/atomic"
|
||||||
"golang.org/x/exp/slices"
|
"golang.org/x/exp/slices"
|
||||||
"net"
|
"net"
|
||||||
"net/netip"
|
"net/netip"
|
||||||
@ -14,6 +15,7 @@ import (
|
|||||||
"github.com/Dreamacro/clash/log"
|
"github.com/Dreamacro/clash/log"
|
||||||
"github.com/Dreamacro/clash/transport/socks5"
|
"github.com/Dreamacro/clash/transport/socks5"
|
||||||
|
|
||||||
|
tun "github.com/metacubex/sing-tun"
|
||||||
vmess "github.com/sagernet/sing-vmess"
|
vmess "github.com/sagernet/sing-vmess"
|
||||||
"github.com/sagernet/sing/common/buf"
|
"github.com/sagernet/sing/common/buf"
|
||||||
E "github.com/sagernet/sing/common/exceptions"
|
E "github.com/sagernet/sing/common/exceptions"
|
||||||
@ -25,10 +27,11 @@ import (
|
|||||||
const UDPTimeout = 5 * time.Minute
|
const UDPTimeout = 5 * time.Minute
|
||||||
|
|
||||||
type ListenerHandler struct {
|
type ListenerHandler struct {
|
||||||
TcpIn chan<- C.ConnContext
|
TcpIn chan<- C.ConnContext
|
||||||
UdpIn chan<- C.PacketAdapter
|
UdpIn chan<- C.PacketAdapter
|
||||||
Type C.Type
|
Type C.Type
|
||||||
Additions []inbound.Addition
|
Additions []inbound.Addition
|
||||||
|
UDPTimeout time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
type waitCloseConn struct {
|
type waitCloseConn struct {
|
||||||
@ -96,11 +99,23 @@ func (h *ListenerHandler) NewPacketConnection(ctx context.Context, conn network.
|
|||||||
defer mutex.Unlock()
|
defer mutex.Unlock()
|
||||||
conn2 = nil
|
conn2 = nil
|
||||||
}()
|
}()
|
||||||
|
lastWrite := atomic.NewTime(time.Now())
|
||||||
|
needTimeout := tun.NeedTimeoutFromContext(ctx) // gvisor stack call NewPacketConnection() with ContextWithNeedTimeout()
|
||||||
|
udpTimeout := h.UDPTimeout
|
||||||
|
if udpTimeout == 0 {
|
||||||
|
udpTimeout = UDPTimeout
|
||||||
|
}
|
||||||
for {
|
for {
|
||||||
buff := buf.NewPacket() // do not use stack buffer
|
buff := buf.NewPacket() // do not use stack buffer
|
||||||
|
if needTimeout {
|
||||||
|
_ = conn.SetReadDeadline(time.Now().Add(udpTimeout))
|
||||||
|
}
|
||||||
dest, err := conn.ReadPacket(buff)
|
dest, err := conn.ReadPacket(buff)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
buff.Release()
|
buff.Release()
|
||||||
|
if needTimeout && E.IsTimeout(err) && time.Now().Sub(lastWrite.Load()) < udpTimeout {
|
||||||
|
continue // someone write successful in time, so we continue read instead of return error
|
||||||
|
}
|
||||||
if E.IsClosed(err) {
|
if E.IsClosed(err) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -108,11 +123,12 @@ func (h *ListenerHandler) NewPacketConnection(ctx context.Context, conn network.
|
|||||||
}
|
}
|
||||||
target := socks5.ParseAddr(dest.String())
|
target := socks5.ParseAddr(dest.String())
|
||||||
packet := &packet{
|
packet := &packet{
|
||||||
conn: &conn2,
|
conn: &conn2,
|
||||||
mutex: &mutex,
|
mutex: &mutex,
|
||||||
rAddr: metadata.Source.UDPAddr(),
|
rAddr: metadata.Source.UDPAddr(),
|
||||||
lAddr: conn.LocalAddr(),
|
lAddr: conn.LocalAddr(),
|
||||||
buff: buff,
|
buff: buff,
|
||||||
|
lastWrite: lastWrite,
|
||||||
}
|
}
|
||||||
select {
|
select {
|
||||||
case h.UdpIn <- inbound.NewPacket(target, packet, h.Type, additions...):
|
case h.UdpIn <- inbound.NewPacket(target, packet, h.Type, additions...):
|
||||||
@ -127,11 +143,12 @@ func (h *ListenerHandler) NewError(ctx context.Context, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type packet struct {
|
type packet struct {
|
||||||
conn *network.PacketConn
|
conn *network.PacketConn
|
||||||
mutex *sync.Mutex
|
mutex *sync.Mutex
|
||||||
rAddr net.Addr
|
rAddr net.Addr
|
||||||
lAddr net.Addr
|
lAddr net.Addr
|
||||||
buff *buf.Buffer
|
buff *buf.Buffer
|
||||||
|
lastWrite *atomic.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *packet) Data() []byte {
|
func (c *packet) Data() []byte {
|
||||||
@ -159,6 +176,10 @@ func (c *packet) WriteBack(b []byte, addr net.Addr) (n int, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
err = conn.WritePacket(buff, M.SocksaddrFromNet(addr))
|
err = conn.WritePacket(buff, M.SocksaddrFromNet(addr))
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.lastWrite.Store(time.Now())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@ import (
|
|||||||
"runtime"
|
"runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/Dreamacro/clash/adapter/inbound"
|
"github.com/Dreamacro/clash/adapter/inbound"
|
||||||
"github.com/Dreamacro/clash/component/dialer"
|
"github.com/Dreamacro/clash/component/dialer"
|
||||||
@ -151,10 +152,11 @@ func New(options LC.Tun, tcpIn chan<- C.ConnContext, udpIn chan<- C.PacketAdapte
|
|||||||
|
|
||||||
handler := &ListenerHandler{
|
handler := &ListenerHandler{
|
||||||
ListenerHandler: sing.ListenerHandler{
|
ListenerHandler: sing.ListenerHandler{
|
||||||
TcpIn: tcpIn,
|
TcpIn: tcpIn,
|
||||||
UdpIn: udpIn,
|
UdpIn: udpIn,
|
||||||
Type: C.TUN,
|
Type: C.TUN,
|
||||||
Additions: additions,
|
Additions: additions,
|
||||||
|
UDPTimeout: time.Second * time.Duration(udpTimeout),
|
||||||
},
|
},
|
||||||
DnsAdds: dnsAdds,
|
DnsAdds: dnsAdds,
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user