chore: tuic add max_udp_relay_packet_size

This commit is contained in:
wwqgtxx 2022-11-25 12:43:23 +08:00
parent a13dedb6e4
commit f542351404
4 changed files with 60 additions and 30 deletions

View file

@ -243,6 +243,7 @@ proxies:
# request_timeout: 8000 # request_timeout: 8000
udp_relay_mode: native # Available: "native", "quic". Default: "native" udp_relay_mode: native # Available: "native", "quic". Default: "native"
# congestion_controller: bbr # Available: "cubic", "new_reno", "bbr". Default: "cubic" # congestion_controller: bbr # Available: "cubic", "new_reno", "bbr". Default: "cubic"
# max_udp_relay_packet_size: 1500
# skip-cert-verify: true # skip-cert-verify: true
``` ```

View file

@ -41,6 +41,7 @@ type TuicOption struct {
UdpRelayMode string `proxy:"udp_relay_mode,omitempty"` UdpRelayMode string `proxy:"udp_relay_mode,omitempty"`
CongestionController string `proxy:"congestion_controller,omitempty"` CongestionController string `proxy:"congestion_controller,omitempty"`
DisableSni bool `proxy:"disable_sni,omitempty"` DisableSni bool `proxy:"disable_sni,omitempty"`
MaxUdpRelayPacketSize int `proxy:"max_udp_relay_packet_size,omitempty"`
SkipCertVerify bool `proxy:"skip-cert-verify,omitempty"` SkipCertVerify bool `proxy:"skip-cert-verify,omitempty"`
Fingerprint string `proxy:"fingerprint,omitempty"` Fingerprint string `proxy:"fingerprint,omitempty"`
@ -152,6 +153,10 @@ func NewTuic(option TuicOption) (*Tuic, error) {
option.UdpRelayMode = "native" option.UdpRelayMode = "native"
} }
if option.MaxUdpRelayPacketSize == 0 {
option.MaxUdpRelayPacketSize = 1500
}
quicConfig := &quic.Config{ quicConfig := &quic.Config{
InitialStreamReceiveWindow: uint64(option.ReceiveWindowConn), InitialStreamReceiveWindow: uint64(option.ReceiveWindowConn),
MaxStreamReceiveWindow: uint64(option.ReceiveWindowConn), MaxStreamReceiveWindow: uint64(option.ReceiveWindowConn),
@ -186,9 +191,21 @@ func NewTuic(option TuicOption) (*Tuic, error) {
clientMapMutex.Lock() clientMapMutex.Lock()
defer clientMapMutex.Unlock() defer clientMapMutex.Unlock()
if client, ok := clientMap[o]; ok && client != nil { for key := range clientMap {
client := clientMap[key]
if client == nil {
delete(clientMap, key) // It is safe in Golang
continue
}
if key == o {
client.LastVisited = time.Now()
return client return client
} }
if time.Now().Sub(client.LastVisited) > 30*time.Minute {
delete(clientMap, key)
continue
}
}
client := &tuic.Client{ client := &tuic.Client{
TlsConfig: tlsConfig, TlsConfig: tlsConfig,
QuicConfig: quicConfig, QuicConfig: quicConfig,
@ -198,6 +215,8 @@ func NewTuic(option TuicOption) (*Tuic, error) {
CongestionController: option.CongestionController, CongestionController: option.CongestionController,
ReduceRtt: option.ReduceRtt, ReduceRtt: option.ReduceRtt,
RequestTimeout: option.RequestTimeout, RequestTimeout: option.RequestTimeout,
MaxUdpRelayPacketSize: option.MaxUdpRelayPacketSize,
LastVisited: time.Now(),
} }
clientMap[o] = client clientMap[o] = client
runtime.SetFinalizer(client, closeTuicClient) runtime.SetFinalizer(client, closeTuicClient)

View file

@ -471,6 +471,7 @@ proxies:
# request_timeout: 8000 # request_timeout: 8000
udp_relay_mode: native # Available: "native", "quic". Default: "native" udp_relay_mode: native # Available: "native", "quic". Default: "native"
# congestion_controller: bbr # Available: "cubic", "new_reno", "bbr". Default: "cubic" # congestion_controller: bbr # Available: "cubic", "new_reno", "bbr". Default: "cubic"
# max_udp_relay_packet_size: 1500
# skip-cert-verify: true # skip-cert-verify: true
# ShadowsocksR # ShadowsocksR

View file

@ -6,6 +6,7 @@ import (
"context" "context"
"crypto/tls" "crypto/tls"
"errors" "errors"
"fmt"
"math/rand" "math/rand"
"net" "net"
"net/netip" "net/netip"
@ -28,6 +29,9 @@ type Client struct {
CongestionController string CongestionController string
ReduceRtt bool ReduceRtt bool
RequestTimeout int RequestTimeout int
MaxUdpRelayPacketSize int
LastVisited time.Time
quicConn quic.Connection quicConn quic.Connection
connMutex sync.Mutex connMutex sync.Mutex
@ -237,6 +241,7 @@ func (t *Client) DialContext(ctx context.Context, metadata *C.Metadata, dialFn f
} }
_, err = buf.WriteTo(stream) _, err = buf.WriteTo(stream)
if err != nil { if err != nil {
_ = stream.Close()
return nil, err return nil, err
} }
return stream, err return stream, err
@ -379,6 +384,9 @@ func (q *quicStreamPacketConn) ReadFrom(p []byte) (n int, addr net.Addr, err err
} }
func (q *quicStreamPacketConn) WriteTo(p []byte, addr net.Addr) (n int, err error) { func (q *quicStreamPacketConn) WriteTo(p []byte, addr net.Addr) (n int, err error) {
if len(p) > q.client.MaxUdpRelayPacketSize {
return 0, fmt.Errorf("udp packet too large(%d > %d)", len(p), q.client.MaxUdpRelayPacketSize)
}
defer func() { defer func() {
q.client.deferQuicConn(q.quicConn, err) q.client.deferQuicConn(q.quicConn, err)
}() }()
@ -401,6 +409,7 @@ func (q *quicStreamPacketConn) WriteTo(p []byte, addr net.Addr) (n int, err erro
} }
_, err = buf.WriteTo(stream) _, err = buf.WriteTo(stream)
if err != nil { if err != nil {
_ = stream.Close()
return return
} }
err = stream.Close() err = stream.Close()