diff --git a/adapter/outbound/hysteria2.go b/adapter/outbound/hysteria2.go index ddd5cceaff..47272ec806 100644 --- a/adapter/outbound/hysteria2.go +++ b/adapter/outbound/hysteria2.go @@ -50,6 +50,7 @@ type Hysteria2Option struct { CustomCA string `proxy:"ca,omitempty"` CustomCAString string `proxy:"ca-str,omitempty"` CWND int `proxy:"cwnd,omitempty"` + UdpMTU int `proxy:"udp-mtu,omitempty"` } func (h *Hysteria2) DialContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (_ C.Conn, err error) { @@ -117,6 +118,12 @@ func NewHysteria2(option Hysteria2Option) (*Hysteria2, error) { tlsConfig.NextProtos = option.ALPN } + if option.UdpMTU == 0 { + // "1200" from quic-go's MaxDatagramSize + // "-3" from quic-go's DatagramFrame.MaxDataLen + option.UdpMTU = 1200 - 3 + } + singDialer := proxydialer.NewByNameSingDialer(option.DialerProxy, dialer.NewDialer()) clientOptions := hysteria2.ClientOptions{ @@ -130,6 +137,7 @@ func NewHysteria2(option Hysteria2Option) (*Hysteria2, error) { TLSConfig: tlsConfig, UDPDisabled: false, CWND: option.CWND, + UdpMTU: option.UdpMTU, } client, err := hysteria2.NewClient(clientOptions) diff --git a/go.mod b/go.mod index 82f3ed07f2..a0d5c44728 100644 --- a/go.mod +++ b/go.mod @@ -21,7 +21,7 @@ require ( github.com/mdlayher/netlink v1.7.2 github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759 github.com/metacubex/quic-go v0.41.1-0.20240120014142-a02f4a533d4a - github.com/metacubex/sing-quic v0.0.0-20240120014430-9838ce4bbc41 + github.com/metacubex/sing-quic v0.0.0-20240122125415-d6eb83bc6ec4 github.com/metacubex/sing-shadowsocks v0.2.6 github.com/metacubex/sing-shadowsocks2 v0.2.0 github.com/metacubex/sing-tun v0.2.0 diff --git a/go.sum b/go.sum index 7137932e64..c30bcbd91a 100644 --- a/go.sum +++ b/go.sum @@ -110,8 +110,8 @@ github.com/metacubex/quic-go v0.41.1-0.20240120014142-a02f4a533d4a h1:IMr75VdMnD github.com/metacubex/quic-go v0.41.1-0.20240120014142-a02f4a533d4a/go.mod h1:F/t8VnA47xoia8ABlNA4InkZjssvFJ5p6E6jKdbkgAs= github.com/metacubex/sing v0.0.0-20240111014253-f1818b6a82b2 h1:upEO8dt9WDBavhgcgkXB3hRcwVNbkTbnd+xyzy6ZQZo= github.com/metacubex/sing v0.0.0-20240111014253-f1818b6a82b2/go.mod h1:9pfuAH6mZfgnz/YjP6xu5sxx882rfyjpcrTdUpd6w3g= -github.com/metacubex/sing-quic v0.0.0-20240120014430-9838ce4bbc41 h1:nBo+cgprEu5f6vfJ2lpNvoUh13QUWR3oq1Bul9iF9HY= -github.com/metacubex/sing-quic v0.0.0-20240120014430-9838ce4bbc41/go.mod h1:bdHqEysJclB9BzIa5jcKKSZ1qua+YEPjR8fOzzE3vZU= +github.com/metacubex/sing-quic v0.0.0-20240122125415-d6eb83bc6ec4 h1:4EukI/UdbuaXov7VDDZf4vaP0ZmkUu827DOeQqzVysw= +github.com/metacubex/sing-quic v0.0.0-20240122125415-d6eb83bc6ec4/go.mod h1:bdHqEysJclB9BzIa5jcKKSZ1qua+YEPjR8fOzzE3vZU= github.com/metacubex/sing-shadowsocks v0.2.6 h1:6oEB3QcsFYnNiFeoevcXrCwJ3sAablwVSgtE9R3QeFQ= github.com/metacubex/sing-shadowsocks v0.2.6/go.mod h1:zIkMeSnb8Mbf4hdqhw0pjzkn1d99YJ3JQm/VBg5WMTg= github.com/metacubex/sing-shadowsocks2 v0.2.0 h1:hqwT/AfI5d5UdPefIzR6onGHJfDXs5zgOM5QSgaM/9A= diff --git a/listener/config/hysteria2.go b/listener/config/hysteria2.go index 898204c617..3c9df5089e 100644 --- a/listener/config/hysteria2.go +++ b/listener/config/hysteria2.go @@ -21,6 +21,7 @@ type Hysteria2Server struct { IgnoreClientBandwidth bool `yaml:"ignore-client-bandwidth" json:"ignore-client-bandwidth,omitempty"` Masquerade string `yaml:"masquerade" json:"masquerade,omitempty"` CWND int `yaml:"cwnd" json:"cwnd,omitempty"` + UdpMTU int `yaml:"udp-mtu" json:"udp-mtu,omitempty"` MuxOption sing.MuxOption `yaml:"mux-option" json:"mux-option,omitempty"` } diff --git a/listener/inbound/hysteria2.go b/listener/inbound/hysteria2.go index acd5f9a852..31c2c4b8ab 100644 --- a/listener/inbound/hysteria2.go +++ b/listener/inbound/hysteria2.go @@ -21,6 +21,7 @@ type Hysteria2Option struct { IgnoreClientBandwidth bool `inbound:"ignore-client-bandwidth,omitempty"` Masquerade string `inbound:"masquerade,omitempty"` CWND int `inbound:"cwnd,omitempty"` + UdpMTU int `inbound:"udp-mtu,omitempty"` MuxOption MuxOption `inbound:"mux-option,omitempty"` } @@ -58,6 +59,7 @@ func NewHysteria2(options *Hysteria2Option) (*Hysteria2, error) { IgnoreClientBandwidth: options.IgnoreClientBandwidth, Masquerade: options.Masquerade, CWND: options.CWND, + UdpMTU: options.UdpMTU, MuxOption: options.MuxOption.Build(), }, }, nil diff --git a/listener/sing_hysteria2/server.go b/listener/sing_hysteria2/server.go index de4c95f593..77ad8efdeb 100644 --- a/listener/sing_hysteria2/server.go +++ b/listener/sing_hysteria2/server.go @@ -104,6 +104,12 @@ func New(config LC.Hysteria2Server, tunnel C.Tunnel, additions ...inbound.Additi } } + if config.UdpMTU == 0 { + // "1200" from quic-go's MaxDatagramSize + // "-3" from quic-go's DatagramFrame.MaxDataLen + config.UdpMTU = 1200 - 3 + } + service, err := hysteria2.NewService[string](hysteria2.ServiceOptions{ Context: context.Background(), Logger: log.SingLogger, @@ -115,6 +121,7 @@ func New(config LC.Hysteria2Server, tunnel C.Tunnel, additions ...inbound.Additi Handler: h, MasqueradeHandler: masqueradeHandler, CWND: config.CWND, + UdpMTU: config.UdpMTU, }) if err != nil { return nil, err diff --git a/transport/tuic/v5/frag.go b/transport/tuic/v5/frag.go index b0e1a17493..d680a5d01f 100644 --- a/transport/tuic/v5/frag.go +++ b/transport/tuic/v5/frag.go @@ -12,7 +12,9 @@ import ( // MaxFragSize is a safe udp relay packet size // because tuicv5 support udp fragment so we unneeded to do a magic modify for quic-go to increase MaxDatagramFrameSize // it may not work fine in some platform -var MaxFragSize = 1200 - PacketOverHead +// "1200" from quic-go's MaxDatagramSize +// "-3" from quic-go's DatagramFrame.MaxDataLen +var MaxFragSize = 1200 - PacketOverHead - 3 func fragWriteNative(quicConn quic.Connection, packet Packet, buf *bytes.Buffer, fragSize int) (err error) { fullPayload := packet.DATA