1
0
世界 2 жил өмнө
parent
commit
c0bbb3849d

+ 3 - 3
go.mod

@@ -23,15 +23,15 @@ require (
 	github.com/sagernet/cloudflare-tls v0.0.0-20221031050923-d70792f4c3a0
 	github.com/sagernet/gomobile v0.0.0-20230728014906-3de089147f59
 	github.com/sagernet/gvisor v0.0.0-20230627031050-1ab0276e0dd2
-	github.com/sagernet/quic-go v0.0.0-20230811130919-d6f54a117913
+	github.com/sagernet/quic-go v0.0.0-20230821100820-d38697ecdbb0
 	github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691
-	github.com/sagernet/sing v0.2.10-0.20230820051732-fabfb87d9f29
+	github.com/sagernet/sing v0.2.10-0.20230821073500-620f3a3b882d
 	github.com/sagernet/sing-dns v0.1.9-0.20230731012726-ad50da89b659
 	github.com/sagernet/sing-mux v0.1.3-0.20230811111955-dc1639b5204c
 	github.com/sagernet/sing-shadowsocks v0.2.4
 	github.com/sagernet/sing-shadowsocks2 v0.1.3
 	github.com/sagernet/sing-shadowtls v0.1.4
-	github.com/sagernet/sing-tun v0.1.12-0.20230820091922-db70908d6125
+	github.com/sagernet/sing-tun v0.1.12-0.20230821065522-7545dc2d5641
 	github.com/sagernet/sing-vmess v0.1.7
 	github.com/sagernet/smux v0.0.0-20230312102458-337ec2a5af37
 	github.com/sagernet/tfo-go v0.0.0-20230816093905-5a5c285d44a6

+ 6 - 6
go.sum

@@ -107,14 +107,14 @@ github.com/sagernet/gvisor v0.0.0-20230627031050-1ab0276e0dd2 h1:dnkKrzapqtAwjTS
 github.com/sagernet/gvisor v0.0.0-20230627031050-1ab0276e0dd2/go.mod h1:1JUiV7nGuf++YFm9eWZ8q2lrwHmhcUGzptMl/vL1+LA=
 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/quic-go v0.0.0-20230811130919-d6f54a117913 h1:4dyzZWAEo9BNQN7yJsVSiN/Pm1hmUfkGJdEyWMkUnVE=
-github.com/sagernet/quic-go v0.0.0-20230811130919-d6f54a117913/go.mod h1:w+nln6f/ZtyPpGbFxmgd5iYFVMmgS+gpD5hu5GAqC1I=
+github.com/sagernet/quic-go v0.0.0-20230821100820-d38697ecdbb0 h1:NCda9SkbANuTWSxf6GVKNXHfYgOIV3byai5T5J9R0UU=
+github.com/sagernet/quic-go v0.0.0-20230821100820-d38697ecdbb0/go.mod h1:w+nln6f/ZtyPpGbFxmgd5iYFVMmgS+gpD5hu5GAqC1I=
 github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691 h1:5Th31OC6yj8byLGkEnIYp6grlXfo1QYUfiYFGjewIdc=
 github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691/go.mod h1:B8lp4WkQ1PwNnrVMM6KyuFR20pU8jYBD+A4EhJovEXU=
 github.com/sagernet/sing v0.0.0-20220817130738-ce854cda8522/go.mod h1:QVsS5L/ZA2Q5UhQwLrn0Trw+msNd/NPGEhBKR/ioWiY=
 github.com/sagernet/sing v0.1.8/go.mod h1:jt1w2u7lJQFFSGLiRrRIs5YWmx4kAPfWuOejuDW9qMk=
-github.com/sagernet/sing v0.2.10-0.20230820051732-fabfb87d9f29 h1:TGSiSJ5noRdmDW0vd1sc/WICJWoT2ulOhD/igXh8PJc=
-github.com/sagernet/sing v0.2.10-0.20230820051732-fabfb87d9f29/go.mod h1:9uOZwWkhT2Z2WldolLxX34s+1svAX4i4vvz5hy8u1MA=
+github.com/sagernet/sing v0.2.10-0.20230821073500-620f3a3b882d h1:4kgoOCE48CuQcBUcoRnE0QTPXkl8yM8i7Nipmzp/978=
+github.com/sagernet/sing v0.2.10-0.20230821073500-620f3a3b882d/go.mod h1:9uOZwWkhT2Z2WldolLxX34s+1svAX4i4vvz5hy8u1MA=
 github.com/sagernet/sing-dns v0.1.9-0.20230731012726-ad50da89b659 h1:1DAKccGNqTYJ8nsBR765FS0LVBVXfuFlFAHqKsGN3EI=
 github.com/sagernet/sing-dns v0.1.9-0.20230731012726-ad50da89b659/go.mod h1:W7GHTZFS8RkoLI3bA2LFY27/0E+uoQESWtMFLepO/JA=
 github.com/sagernet/sing-mux v0.1.3-0.20230811111955-dc1639b5204c h1:35/FowAvt3Z62mck0TXzVc4jS5R5CWq62qcV2P1cp0I=
@@ -125,8 +125,8 @@ github.com/sagernet/sing-shadowsocks2 v0.1.3 h1:WXoLvCFi5JTFBRYorf1YePGYIQyJ/zbs
 github.com/sagernet/sing-shadowsocks2 v0.1.3/go.mod h1:DOhJc/cLeqRv0wuePrQso+iUmDxOnWF4eT/oMcRzYFw=
 github.com/sagernet/sing-shadowtls v0.1.4 h1:aTgBSJEgnumzFenPvc+kbD9/W0PywzWevnVpEx6Tw3k=
 github.com/sagernet/sing-shadowtls v0.1.4/go.mod h1:F8NBgsY5YN2beQavdgdm1DPlhaKQlaL6lpDdcBglGK4=
-github.com/sagernet/sing-tun v0.1.12-0.20230820091922-db70908d6125 h1:ZqNuG9t4lAZbiqMSJN/nNv7ZtRRpm7h46KrmnkuhW9w=
-github.com/sagernet/sing-tun v0.1.12-0.20230820091922-db70908d6125/go.mod h1:+YImslQMLgMQcVgZZ9IK4ue1o/605VSU90amHUcp4hA=
+github.com/sagernet/sing-tun v0.1.12-0.20230821065522-7545dc2d5641 h1:a8lktNrCWZJisB+nPraW+qB73ZofgPtGmlfqNYcO79g=
+github.com/sagernet/sing-tun v0.1.12-0.20230821065522-7545dc2d5641/go.mod h1:+YImslQMLgMQcVgZZ9IK4ue1o/605VSU90amHUcp4hA=
 github.com/sagernet/sing-vmess v0.1.7 h1:TM8FFLsXmlXH9XT8/oDgc6PC5BOzrg6OzyEe01is2r4=
 github.com/sagernet/sing-vmess v0.1.7/go.mod h1:1qkC1L1T2sxnS/NuO6HU72S8TkltV+EXoKGR29m/Yss=
 github.com/sagernet/smux v0.0.0-20230312102458-337ec2a5af37 h1:HuE6xSwco/Xed8ajZ+coeYLmioq0Qp1/Z2zczFaV8as=

+ 6 - 0
inbound/tuic.go

@@ -99,6 +99,12 @@ func (h *TUIC) newPacketConnection(ctx context.Context, conn N.PacketConn, metad
 }
 
 func (h *TUIC) Start() error {
+	if h.tlsConfig != nil {
+		err := h.tlsConfig.Start()
+		if err != nil {
+			return err
+		}
+	}
 	packetConn, err := h.myInboundAdapter.ListenUDP()
 	if err != nil {
 		return err

+ 15 - 0
test/box_test.go

@@ -74,6 +74,21 @@ func testSuit(t *testing.T, clientPort uint16, testPort uint16) {
 	// require.NoError(t, testPacketConnTimeout(t, dialUDP))
 }
 
+func testSuitLargeUDP(t *testing.T, clientPort uint16, testPort uint16) {
+	dialer := socks.NewClient(N.SystemDialer, M.ParseSocksaddrHostPort("127.0.0.1", clientPort), socks.Version5, "", "")
+	dialTCP := func() (net.Conn, error) {
+		return dialer.DialContext(context.Background(), "tcp", M.ParseSocksaddrHostPort("127.0.0.1", testPort))
+	}
+	dialUDP := func() (net.PacketConn, error) {
+		return dialer.ListenPacket(context.Background(), M.ParseSocksaddrHostPort("127.0.0.1", testPort))
+	}
+	require.NoError(t, testPingPongWithConn(t, testPort, dialTCP))
+	require.NoError(t, testPingPongWithPacketConn(t, testPort, dialUDP))
+	require.NoError(t, testLargeDataWithConn(t, testPort, dialTCP))
+	require.NoError(t, testLargeDataWithPacketConn(t, testPort, dialUDP))
+	require.NoError(t, testLargeDataWithPacketConnSize(t, testPort, 1250, dialUDP))
+}
+
 func testTCP(t *testing.T, clientPort uint16, testPort uint16) {
 	dialer := socks.NewClient(N.SystemDialer, M.ParseSocksaddrHostPort("127.0.0.1", clientPort), socks.Version5, "", "")
 	dialTCP := func() (net.Conn, error) {

+ 8 - 5
test/clash_test.go

@@ -38,8 +38,8 @@ const (
 	ImageShadowsocksR          = "teddysun/shadowsocks-r:latest"
 	ImageXRayCore              = "teddysun/xray:latest"
 	ImageShadowsocksLegacy     = "mritd/shadowsocks:latest"
-	ImageTUICServer            = ""
-	ImageTUICClient            = ""
+	ImageTUICServer            = "kilvn/tuic-server:latest"
+	ImageTUICClient            = "kilvn/tuic-client:latest"
 )
 
 var allImages = []string{
@@ -55,8 +55,8 @@ var allImages = []string{
 	ImageShadowsocksR,
 	ImageXRayCore,
 	ImageShadowsocksLegacy,
-	// ImageTUICServer,
-	// ImageTUICClient,
+	ImageTUICServer,
+	ImageTUICClient,
 }
 
 var localIP = netip.MustParseAddr("127.0.0.1")
@@ -364,6 +364,10 @@ func testLargeDataWithConn(t *testing.T, port uint16, cc func() (net.Conn, error
 }
 
 func testLargeDataWithPacketConn(t *testing.T, port uint16, pcc func() (net.PacketConn, error)) error {
+	return testLargeDataWithPacketConnSize(t, port, 1024, pcc)
+}
+
+func testLargeDataWithPacketConnSize(t *testing.T, port uint16, chunkSize int, pcc func() (net.PacketConn, error)) error {
 	l, err := listenPacket("udp", ":"+F.ToString(port))
 	if err != nil {
 		return err
@@ -373,7 +377,6 @@ func testLargeDataWithPacketConn(t *testing.T, port uint16, pcc func() (net.Pack
 	rAddr := &net.UDPAddr{IP: localIP.AsSlice(), Port: int(port)}
 
 	times := 50
-	chunkSize := int64(1024)
 
 	pingCh, pongCh, test := newLargeDataPair()
 	writeRandData := func(pc net.PacketConn, addr net.Addr) (map[int][]byte, error) {

+ 2 - 1
test/config/tuic-client.json

@@ -1,6 +1,7 @@
 {
   "relay": {
-    "server": "127.0.0.1:10000",
+    "server": "example.org:10000",
+    "ip": "127.0.0.1",
     "uuid": "FE35D05B-8803-45C4-BAE6-723AD2CD5D3D",
     "password": "tuic",
     "certificates": [

+ 6 - 7
test/go.mod

@@ -7,15 +7,15 @@ require github.com/sagernet/sing-box v0.0.0
 replace github.com/sagernet/sing-box => ../
 
 require (
-	github.com/docker/docker v20.10.18+incompatible
+	github.com/docker/docker v24.0.5+incompatible
 	github.com/docker/go-connections v0.4.0
 	github.com/gofrs/uuid/v5 v5.0.0
-	github.com/sagernet/sing v0.2.10-0.20230820051732-fabfb87d9f29
+	github.com/sagernet/sing v0.2.10-0.20230821073500-620f3a3b882d
 	github.com/sagernet/sing-shadowsocks v0.2.4
 	github.com/sagernet/sing-shadowsocks2 v0.1.3
-	github.com/spyzhov/ajson v0.7.1
+	github.com/spyzhov/ajson v0.9.0
 	github.com/stretchr/testify v1.8.4
-	go.uber.org/goleak v1.2.0
+	go.uber.org/goleak v1.2.1
 	golang.org/x/net v0.14.0
 )
 
@@ -70,12 +70,12 @@ require (
 	github.com/sagernet/go-tun2socks v1.16.12-0.20220818015926-16cb67876a61 // indirect
 	github.com/sagernet/gvisor v0.0.0-20230627031050-1ab0276e0dd2 // indirect
 	github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 // indirect
-	github.com/sagernet/quic-go v0.0.0-20230811130919-d6f54a117913 // indirect
+	github.com/sagernet/quic-go v0.0.0-20230821100820-d38697ecdbb0 // indirect
 	github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691 // indirect
 	github.com/sagernet/sing-dns v0.1.9-0.20230731012726-ad50da89b659 // indirect
 	github.com/sagernet/sing-mux v0.1.3-0.20230811111955-dc1639b5204c // indirect
 	github.com/sagernet/sing-shadowtls v0.1.4 // indirect
-	github.com/sagernet/sing-tun v0.1.12-0.20230820091922-db70908d6125 // indirect
+	github.com/sagernet/sing-tun v0.1.12-0.20230821065522-7545dc2d5641 // indirect
 	github.com/sagernet/sing-vmess v0.1.7 // indirect
 	github.com/sagernet/smux v0.0.0-20230312102458-337ec2a5af37 // indirect
 	github.com/sagernet/tfo-go v0.0.0-20230816093905-5a5c285d44a6 // indirect
@@ -83,7 +83,6 @@ require (
 	github.com/sagernet/websocket v0.0.0-20220913015213-615516348b4e // indirect
 	github.com/sagernet/wireguard-go v0.0.0-20230807125731-5d4a7ef2dc5f // indirect
 	github.com/scjalliance/comshim v0.0.0-20230315213746-5e51f40bd3b9 // indirect
-	github.com/sirupsen/logrus v1.9.3 // indirect
 	github.com/u-root/uio v0.0.0-20230220225925-ffce2a382923 // indirect
 	github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 // indirect
 	github.com/zeebo/blake3 v0.2.3 // indirect

+ 12 - 16
test/go.sum

@@ -27,8 +27,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/docker/distribution v2.8.1+incompatible h1:Q50tZOPR6T/hjNsyc9g8/syEs6bk8XXApsHjKukMl68=
 github.com/docker/distribution v2.8.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
-github.com/docker/docker v20.10.18+incompatible h1:SN84VYXTBNGn92T/QwIRPlum9zfemfitN7pbsp26WSc=
-github.com/docker/docker v20.10.18+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
+github.com/docker/docker v24.0.5+incompatible h1:WmgcE4fxyI6EEXxBRxsHnZXrO1pQ3smi0k/jho4HLeY=
+github.com/docker/docker v24.0.5+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
 github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
 github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
 github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw=
@@ -123,14 +123,14 @@ github.com/sagernet/gvisor v0.0.0-20230627031050-1ab0276e0dd2 h1:dnkKrzapqtAwjTS
 github.com/sagernet/gvisor v0.0.0-20230627031050-1ab0276e0dd2/go.mod h1:1JUiV7nGuf++YFm9eWZ8q2lrwHmhcUGzptMl/vL1+LA=
 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/quic-go v0.0.0-20230811130919-d6f54a117913 h1:4dyzZWAEo9BNQN7yJsVSiN/Pm1hmUfkGJdEyWMkUnVE=
-github.com/sagernet/quic-go v0.0.0-20230811130919-d6f54a117913/go.mod h1:w+nln6f/ZtyPpGbFxmgd5iYFVMmgS+gpD5hu5GAqC1I=
+github.com/sagernet/quic-go v0.0.0-20230821100820-d38697ecdbb0 h1:NCda9SkbANuTWSxf6GVKNXHfYgOIV3byai5T5J9R0UU=
+github.com/sagernet/quic-go v0.0.0-20230821100820-d38697ecdbb0/go.mod h1:w+nln6f/ZtyPpGbFxmgd5iYFVMmgS+gpD5hu5GAqC1I=
 github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691 h1:5Th31OC6yj8byLGkEnIYp6grlXfo1QYUfiYFGjewIdc=
 github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691/go.mod h1:B8lp4WkQ1PwNnrVMM6KyuFR20pU8jYBD+A4EhJovEXU=
 github.com/sagernet/sing v0.0.0-20220817130738-ce854cda8522/go.mod h1:QVsS5L/ZA2Q5UhQwLrn0Trw+msNd/NPGEhBKR/ioWiY=
 github.com/sagernet/sing v0.1.8/go.mod h1:jt1w2u7lJQFFSGLiRrRIs5YWmx4kAPfWuOejuDW9qMk=
-github.com/sagernet/sing v0.2.10-0.20230820051732-fabfb87d9f29 h1:TGSiSJ5noRdmDW0vd1sc/WICJWoT2ulOhD/igXh8PJc=
-github.com/sagernet/sing v0.2.10-0.20230820051732-fabfb87d9f29/go.mod h1:9uOZwWkhT2Z2WldolLxX34s+1svAX4i4vvz5hy8u1MA=
+github.com/sagernet/sing v0.2.10-0.20230821073500-620f3a3b882d h1:4kgoOCE48CuQcBUcoRnE0QTPXkl8yM8i7Nipmzp/978=
+github.com/sagernet/sing v0.2.10-0.20230821073500-620f3a3b882d/go.mod h1:9uOZwWkhT2Z2WldolLxX34s+1svAX4i4vvz5hy8u1MA=
 github.com/sagernet/sing-dns v0.1.9-0.20230731012726-ad50da89b659 h1:1DAKccGNqTYJ8nsBR765FS0LVBVXfuFlFAHqKsGN3EI=
 github.com/sagernet/sing-dns v0.1.9-0.20230731012726-ad50da89b659/go.mod h1:W7GHTZFS8RkoLI3bA2LFY27/0E+uoQESWtMFLepO/JA=
 github.com/sagernet/sing-mux v0.1.3-0.20230811111955-dc1639b5204c h1:35/FowAvt3Z62mck0TXzVc4jS5R5CWq62qcV2P1cp0I=
@@ -141,8 +141,8 @@ github.com/sagernet/sing-shadowsocks2 v0.1.3 h1:WXoLvCFi5JTFBRYorf1YePGYIQyJ/zbs
 github.com/sagernet/sing-shadowsocks2 v0.1.3/go.mod h1:DOhJc/cLeqRv0wuePrQso+iUmDxOnWF4eT/oMcRzYFw=
 github.com/sagernet/sing-shadowtls v0.1.4 h1:aTgBSJEgnumzFenPvc+kbD9/W0PywzWevnVpEx6Tw3k=
 github.com/sagernet/sing-shadowtls v0.1.4/go.mod h1:F8NBgsY5YN2beQavdgdm1DPlhaKQlaL6lpDdcBglGK4=
-github.com/sagernet/sing-tun v0.1.12-0.20230820091922-db70908d6125 h1:ZqNuG9t4lAZbiqMSJN/nNv7ZtRRpm7h46KrmnkuhW9w=
-github.com/sagernet/sing-tun v0.1.12-0.20230820091922-db70908d6125/go.mod h1:+YImslQMLgMQcVgZZ9IK4ue1o/605VSU90amHUcp4hA=
+github.com/sagernet/sing-tun v0.1.12-0.20230821065522-7545dc2d5641 h1:a8lktNrCWZJisB+nPraW+qB73ZofgPtGmlfqNYcO79g=
+github.com/sagernet/sing-tun v0.1.12-0.20230821065522-7545dc2d5641/go.mod h1:+YImslQMLgMQcVgZZ9IK4ue1o/605VSU90amHUcp4hA=
 github.com/sagernet/sing-vmess v0.1.7 h1:TM8FFLsXmlXH9XT8/oDgc6PC5BOzrg6OzyEe01is2r4=
 github.com/sagernet/sing-vmess v0.1.7/go.mod h1:1qkC1L1T2sxnS/NuO6HU72S8TkltV+EXoKGR29m/Yss=
 github.com/sagernet/smux v0.0.0-20230312102458-337ec2a5af37 h1:HuE6xSwco/Xed8ajZ+coeYLmioq0Qp1/Z2zczFaV8as=
@@ -157,10 +157,8 @@ github.com/sagernet/wireguard-go v0.0.0-20230807125731-5d4a7ef2dc5f h1:Kvo8w8Y9l
 github.com/sagernet/wireguard-go v0.0.0-20230807125731-5d4a7ef2dc5f/go.mod h1:mySs0abhpc/gLlvhoq7HP1RzOaRmIXVeZGCh++zoApk=
 github.com/scjalliance/comshim v0.0.0-20230315213746-5e51f40bd3b9 h1:rc/CcqLH3lh8n+csdOuDfP+NuykE0U6AeYSJJHKDgSg=
 github.com/scjalliance/comshim v0.0.0-20230315213746-5e51f40bd3b9/go.mod h1:a/83NAfUXvEuLpmxDssAXxgUgrEy12MId3Wd7OTs76s=
-github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
-github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
-github.com/spyzhov/ajson v0.7.1 h1:1MDIlPc6x0zjNtpa7tDzRAyFAvRX+X8ZsvtYz5lZg6A=
-github.com/spyzhov/ajson v0.7.1/go.mod h1:63V+CGM6f1Bu/p4nLIN8885ojBdt88TbLoSFzyqMuVA=
+github.com/spyzhov/ajson v0.9.0 h1:tF46gJGOenYVj+k9K1U1XpCxVWhmiyY5PsVCAs1+OJ0=
+github.com/spyzhov/ajson v0.9.0/go.mod h1:a6oSw0MMb7Z5aD2tPoPO+jq11ETKgXUr2XktHdT8Wt8=
 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
 github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
@@ -182,8 +180,8 @@ github.com/zeebo/pcg v1.0.1 h1:lyqfGeWiv4ahac6ttHs+I5hwtH/+1mrhlCtVNQM2kHo=
 github.com/zeebo/pcg v1.0.1/go.mod h1:09F0S9iiKrwn9rlI5yjLkmrug154/YRW6KnnXVDM/l4=
 go.etcd.io/bbolt v1.3.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ=
 go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw=
-go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk=
-go.uber.org/goleak v1.2.0/go.mod h1:XJYK+MuIchqpmGmUSAzotztawfKvYLUIgg7guXrwVUo=
+go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A=
+go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4=
 go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
 go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
 go.uber.org/zap v1.25.0 h1:4Hvk6GtkucQ790dqmj7l1eEnRdKm3k3ZUrUMS2d5+5c=
@@ -199,7 +197,6 @@ golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk=
 golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
 golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df h1:UA2aFVmmsIlefxMk29Dp2juaUSth8Pyn3Tq5Y5mJGME=
 golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc=
-golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs=
 golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
@@ -231,7 +228,6 @@ golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220622161953-175b2fd9d664/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220731174439-a90be440212d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=

+ 3 - 2
test/tuic_test.go

@@ -94,7 +94,7 @@ func testTUICSelf(t *testing.T, udpStream bool, zeroRTTHandshake bool) {
 			},
 		},
 	})
-	testSuit(t, clientPort, testPort)
+	testSuitLargeUDP(t, clientPort, testPort)
 }
 
 func TestTUICInbound(t *testing.T) {
@@ -130,6 +130,7 @@ func TestTUICInbound(t *testing.T) {
 			caPem:              "/etc/tuic/ca.pem",
 		},
 	})
+	testSuitLargeUDP(t, clientPort, testPort)
 }
 
 func TestTUICOutbound(t *testing.T) {
@@ -174,5 +175,5 @@ func TestTUICOutbound(t *testing.T) {
 			},
 		},
 	})
-	testSuit(t, clientPort, testPort)
+	testSuitLargeUDP(t, clientPort, testPort)
 }

+ 39 - 22
transport/tuic/packet.go

@@ -41,7 +41,6 @@ type udpMessage struct {
 	fragmentTotal uint8
 	fragmentID    uint8
 	destination   M.Socksaddr
-	dataLength    uint16
 	data          *buf.Buffer
 }
 
@@ -72,7 +71,7 @@ func (m *udpMessage) pack() *buf.Buffer {
 }
 
 func (m *udpMessage) headerSize() int {
-	return 2 + 10 + addressSerializer.AddrPortLen(m.destination)
+	return 10 + addressSerializer.AddrPortLen(m.destination)
 }
 
 func fragUDPMessage(message *udpMessage, maxPacketSize int) []*udpMessage {
@@ -106,18 +105,19 @@ func fragUDPMessage(message *udpMessage, maxPacketSize int) []*udpMessage {
 }
 
 type udpPacketConn struct {
-	ctx       context.Context
-	cancel    common.ContextCancelCauseFunc
-	sessionID uint16
-	quicConn  quic.Connection
-	data      chan *udpMessage
-	udpStream bool
-	udpMTU    int
-	packetId  atomic.Uint32
-	closeOnce sync.Once
-	isServer  bool
-	defragger *udpDefragger
-	onDestroy func()
+	ctx        context.Context
+	cancel     common.ContextCancelCauseFunc
+	sessionID  uint16
+	quicConn   quic.Connection
+	data       chan *udpMessage
+	udpStream  bool
+	udpMTU     int
+	udpMTUTime time.Time
+	packetId   atomic.Uint32
+	closeOnce  sync.Once
+	isServer   bool
+	defragger  *udpDefragger
+	onDestroy  func()
 }
 
 func newUDPPacketConn(ctx context.Context, quicConn quic.Connection, udpStream bool, isServer bool, onDestroy func()) *udpPacketConn {
@@ -186,6 +186,15 @@ func (c *udpPacketConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
 	}
 }
 
+func (c *udpPacketConn) needFragment() bool {
+	nowTime := time.Now()
+	if c.udpMTU > 0 && nowTime.Sub(c.udpMTUTime) < 5*time.Second {
+		c.udpMTUTime = nowTime
+		return true
+	}
+	return false
+}
+
 func (c *udpPacketConn) WritePacket(buffer *buf.Buffer, destination M.Socksaddr) error {
 	defer buffer.Release()
 	select {
@@ -211,7 +220,7 @@ func (c *udpPacketConn) WritePacket(buffer *buf.Buffer, destination M.Socksaddr)
 	}
 	defer message.releaseMessage()
 	var err error
-	if !c.udpStream && c.udpMTU > 0 && buffer.Len() > c.udpMTU {
+	if !c.udpStream && c.needFragment() && buffer.Len() > c.udpMTU {
 		err = c.writePackets(fragUDPMessage(message, c.udpMTU))
 	} else {
 		err = c.writePacket(message)
@@ -224,6 +233,7 @@ func (c *udpPacketConn) WritePacket(buffer *buf.Buffer, destination M.Socksaddr)
 		return err
 	}
 	c.udpMTU = int(tooLargeErr)
+	c.udpMTUTime = time.Now()
 	return c.writePackets(fragUDPMessage(message, c.udpMTU))
 }
 
@@ -265,6 +275,7 @@ func (c *udpPacketConn) WriteTo(p []byte, addr net.Addr) (n int, err error) {
 		return
 	}
 	c.udpMTU = int(tooLargeErr)
+	c.udpMTUTime = time.Now()
 	err = c.writePackets(fragUDPMessage(message, c.udpMTU))
 	if err == nil {
 		return len(p), nil
@@ -414,10 +425,14 @@ func (d *udpDefragger) feed(m *udpMessage) *udpMessage {
 	}
 	newMessage := udpMessagePool.Get().(*udpMessage)
 	*newMessage = *item.messages[0]
-	if m.dataLength > 0 {
-		newMessage.data = buf.NewSize(int(m.dataLength))
+	var dataLength uint16
+	for _, message := range item.messages {
+		dataLength += uint16(message.data.Len())
+	}
+	if dataLength > 0 {
+		newMessage.data = buf.NewSize(int(dataLength))
 		for _, message := range item.messages {
-			newMessage.data.Write(message.data.Bytes())
+			common.Must1(newMessage.data.Write(message.data.Bytes()))
 			message.releaseMessage()
 		}
 		item.messages = nil
@@ -447,7 +462,8 @@ func readUDPMessage(message *udpMessage, reader io.Reader) error {
 	if err != nil {
 		return err
 	}
-	err = binary.Read(reader, binary.BigEndian, &message.dataLength)
+	var dataLength uint16
+	err = binary.Read(reader, binary.BigEndian, &dataLength)
 	if err != nil {
 		return err
 	}
@@ -455,7 +471,7 @@ func readUDPMessage(message *udpMessage, reader io.Reader) error {
 	if err != nil {
 		return err
 	}
-	message.data = buf.NewSize(int(message.dataLength))
+	message.data = buf.NewSize(int(dataLength))
 	_, err = message.data.ReadFullFrom(reader, message.data.FreeLen())
 	if err != nil {
 		return err
@@ -481,7 +497,8 @@ func decodeUDPMessage(message *udpMessage, data []byte) error {
 	if err != nil {
 		return err
 	}
-	err = binary.Read(reader, binary.BigEndian, &message.dataLength)
+	var dataLength uint16
+	err = binary.Read(reader, binary.BigEndian, &dataLength)
 	if err != nil {
 		return err
 	}
@@ -489,7 +506,7 @@ func decodeUDPMessage(message *udpMessage, data []byte) error {
 	if err != nil {
 		return err
 	}
-	if reader.Len() != int(message.dataLength) {
+	if reader.Len() != int(dataLength) {
 		return io.ErrUnexpectedEOF
 	}
 	message.data = buf.As(data[len(data)-reader.Len():])