Browse Source

Add QUIC support for naiveproxy

世界 3 weeks ago
parent
commit
e5efd5189a

+ 1 - 1
.github/CRONET_GO_VERSION

@@ -1 +1 @@
-4f12714a37cc546cbd171765e44988a348ba77fa
+446096b34fb07e86541d927be26f8e5c42d41b4a

+ 29 - 13
docs/configuration/inbound/naive.md

@@ -2,19 +2,20 @@
 
 ```json
 {
-  "type": "naive",
-  "tag": "naive-in",
-  "network": "udp",
-
-  ... // Listen Fields
-
-  "users": [
-    {
-      "username": "sekai",
-      "password": "password"
-    }
-  ],
-  "tls": {}
+"type": "naive",
+"tag": "naive-in",
+"network": "udp",
+...
+// Listen Fields
+
+"users": [
+{
+"username": "sekai",
+"password": "password"
+}
+],
+"quic_congestion_control": "",
+"tls": {}
 }
 ```
 
@@ -36,6 +37,21 @@ Both if empty.
 
 Naive users.
 
+#### quic_congestion_control
+
+QUIC congestion control algorithm.
+
+| Algorithm      | Description                     |
+|----------------|---------------------------------|
+| `bbr`          | BBR                             |
+| `bbr_standard` | BBR (Standard version)         |
+| `bbr2`         | BBRv2                           |
+| `bbr2_variant` | BBRv2 (An experimental variant) |
+| `cubic`        | CUBIC                           |
+| `reno`         | New Reno                        |
+
+`bbr` is used by default (the default of QUICHE, used by Chromium which NaiveProxy is based on).
+
 #### tls
 
 TLS configuration, see [TLS](/configuration/shared/tls/#inbound).

+ 29 - 13
docs/configuration/inbound/naive.zh.md

@@ -2,19 +2,20 @@
 
 ```json
 {
-  "type": "naive",
-  "tag": "naive-in",
-  "network": "udp",
-
-  ... // 监听字段
-
-  "users": [
-    {
-      "username": "sekai",
-      "password": "password"
-    }
-  ],
-  "tls": {}
+"type": "naive",
+"tag": "naive-in",
+"network": "udp",
+
+... // 监听字段
+
+"users": [
+{
+"username": "sekai",
+"password": "password"
+}
+],
+"quic_congestion_control": "",
+"tls": {}
 }
 ```
 
@@ -36,6 +37,21 @@
 
 Naive 用户。
 
+#### quic_congestion_control
+
+QUIC 拥塞控制算法。
+
+| 算法             | 描述                 |
+|----------------|--------------------|
+| `bbr`          | BBR                |
+| `bbr_standard` | BBR (标准版) |
+| `bbr2`         | BBRv2              |
+| `bbr2_variant` | BBRv2 (一种试验变体)     |
+| `cubic`        | CUBIC              |
+| `reno`         | New Reno           |
+
+默认使用 `bbr`(NaiveProxy 基于的 Chromium 使用的 QUICHE 的默认值)。
+
 #### tls
 
 TLS 配置, 参阅 [TLS](/zh/configuration/shared/tls/#inbound)。

+ 19 - 0
docs/configuration/outbound/naive.md

@@ -18,6 +18,8 @@ icon: material/new-box
   "insecure_concurrency": 0,
   "extra_headers": {},
   "udp_over_tcp": false | {},
+  "quic": false,
+  "quic_congestion_control": "",
   "tls": {},
 
   ... // Dial Fields
@@ -80,6 +82,23 @@ UDP over TCP protocol settings.
 
 See [UDP Over TCP](/configuration/shared/udp-over-tcp/) for details.
 
+#### quic
+
+Use QUIC instead of HTTP/2.
+
+#### quic_congestion_control
+
+QUIC congestion control algorithm.
+
+| Algorithm | Description |
+|-----------|-------------|
+| `bbr` | BBR |
+| `bbr2` | BBRv2 |
+| `cubic` | CUBIC |
+| `reno` | New Reno |
+
+`bbr` is used by default (the default of QUICHE, used by Chromium which NaiveProxy is based on).
+
 #### tls
 
 ==Required==

+ 19 - 0
docs/configuration/outbound/naive.zh.md

@@ -18,6 +18,8 @@ icon: material/new-box
   "insecure_concurrency": 0,
   "extra_headers": {},
   "udp_over_tcp": false | {},
+  "quic": false,
+  "quic_congestion_control": "",
   "tls": {},
 
   ... // 拨号字段
@@ -80,6 +82,23 @@ UDP over TCP 配置。
 
 参阅 [UDP Over TCP](/zh/configuration/shared/udp-over-tcp/)。
 
+#### quic
+
+使用 QUIC 代替 HTTP/2。
+
+#### quic_congestion_control
+
+QUIC 拥塞控制算法。
+
+| 算法 | 描述 |
+|------|------|
+| `bbr` | BBR |
+| `bbr2` | BBRv2 |
+| `cubic` | CUBIC |
+| `reno` | New Reno |
+
+默认使用 `bbr`(NaiveProxy 基于的 Chromium 使用的 QUICHE 的默认值)。
+
 #### tls
 
 ==必填==

+ 26 - 26
go.mod

@@ -26,15 +26,15 @@ require (
 	github.com/sagernet/asc-go v0.0.0-20241217030726-d563060fe4e1
 	github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a
 	github.com/sagernet/cors v1.2.1
-	github.com/sagernet/cronet-go v0.0.0-20251217133746-1955399f1585
-	github.com/sagernet/cronet-go/all v0.0.0-20251217133746-1955399f1585
+	github.com/sagernet/cronet-go v0.0.0-20251218041957-eeb28f1dba2f
+	github.com/sagernet/cronet-go/all v0.0.0-20251218041957-eeb28f1dba2f
 	github.com/sagernet/fswatch v0.1.1
 	github.com/sagernet/gomobile v0.1.10
 	github.com/sagernet/gvisor v0.0.0-20250811.0-sing-box-mod.1
-	github.com/sagernet/quic-go v0.57.1-sing-box-mod.1
+	github.com/sagernet/quic-go v0.57.1-sing-box-mod.3
 	github.com/sagernet/sing v0.8.0-beta.6.0.20251207063731-56fd482ce1c6
 	github.com/sagernet/sing-mux v0.3.3
-	github.com/sagernet/sing-quic v0.6.0-beta.5
+	github.com/sagernet/sing-quic v0.6.0-beta.5.0.20251218085114-6968f531a8c0
 	github.com/sagernet/sing-shadowsocks v0.2.8
 	github.com/sagernet/sing-shadowsocks2 v0.2.1
 	github.com/sagernet/sing-shadowtls v0.2.1-0.20250503051639-fcd445d33c11
@@ -108,28 +108,28 @@ require (
 	github.com/prometheus-community/pro-bing v0.4.0 // indirect
 	github.com/quic-go/qpack v0.6.0 // indirect
 	github.com/safchain/ethtool v0.3.0 // indirect
-	github.com/sagernet/cronet-go/lib/android_386 v0.0.0-20251217133247-ea405ec61e5f // indirect
-	github.com/sagernet/cronet-go/lib/android_amd64 v0.0.0-20251217133247-ea405ec61e5f // indirect
-	github.com/sagernet/cronet-go/lib/android_arm v0.0.0-20251217133247-ea405ec61e5f // indirect
-	github.com/sagernet/cronet-go/lib/android_arm64 v0.0.0-20251217133247-ea405ec61e5f // indirect
-	github.com/sagernet/cronet-go/lib/darwin_amd64 v0.0.0-20251217133247-ea405ec61e5f // indirect
-	github.com/sagernet/cronet-go/lib/darwin_arm64 v0.0.0-20251217133247-ea405ec61e5f // indirect
-	github.com/sagernet/cronet-go/lib/ios_amd64_simulator v0.0.0-20251217133247-ea405ec61e5f // indirect
-	github.com/sagernet/cronet-go/lib/ios_arm64 v0.0.0-20251217133247-ea405ec61e5f // indirect
-	github.com/sagernet/cronet-go/lib/ios_arm64_simulator v0.0.0-20251217133247-ea405ec61e5f // indirect
-	github.com/sagernet/cronet-go/lib/linux_386 v0.0.0-20251217133247-ea405ec61e5f // indirect
-	github.com/sagernet/cronet-go/lib/linux_386_musl v0.0.0-20251217133247-ea405ec61e5f // indirect
-	github.com/sagernet/cronet-go/lib/linux_amd64 v0.0.0-20251217133247-ea405ec61e5f // indirect
-	github.com/sagernet/cronet-go/lib/linux_amd64_musl v0.0.0-20251217133247-ea405ec61e5f // indirect
-	github.com/sagernet/cronet-go/lib/linux_arm v0.0.0-20251217133247-ea405ec61e5f // indirect
-	github.com/sagernet/cronet-go/lib/linux_arm64 v0.0.0-20251217133247-ea405ec61e5f // indirect
-	github.com/sagernet/cronet-go/lib/linux_arm64_musl v0.0.0-20251217133247-ea405ec61e5f // indirect
-	github.com/sagernet/cronet-go/lib/linux_arm_musl v0.0.0-20251217133247-ea405ec61e5f // indirect
-	github.com/sagernet/cronet-go/lib/tvos_amd64_simulator v0.0.0-20251217133247-ea405ec61e5f // indirect
-	github.com/sagernet/cronet-go/lib/tvos_arm64 v0.0.0-20251217133247-ea405ec61e5f // indirect
-	github.com/sagernet/cronet-go/lib/tvos_arm64_simulator v0.0.0-20251217133247-ea405ec61e5f // indirect
-	github.com/sagernet/cronet-go/lib/windows_amd64 v0.0.0-20251217133247-ea405ec61e5f // indirect
-	github.com/sagernet/cronet-go/lib/windows_arm64 v0.0.0-20251217133247-ea405ec61e5f // indirect
+	github.com/sagernet/cronet-go/lib/android_386 v0.0.0-20251218041530-c2a431c5f1f7 // indirect
+	github.com/sagernet/cronet-go/lib/android_amd64 v0.0.0-20251218041530-c2a431c5f1f7 // indirect
+	github.com/sagernet/cronet-go/lib/android_arm v0.0.0-20251218041530-c2a431c5f1f7 // indirect
+	github.com/sagernet/cronet-go/lib/android_arm64 v0.0.0-20251218041530-c2a431c5f1f7 // indirect
+	github.com/sagernet/cronet-go/lib/darwin_amd64 v0.0.0-20251218041530-c2a431c5f1f7 // indirect
+	github.com/sagernet/cronet-go/lib/darwin_arm64 v0.0.0-20251218041530-c2a431c5f1f7 // indirect
+	github.com/sagernet/cronet-go/lib/ios_amd64_simulator v0.0.0-20251218041530-c2a431c5f1f7 // indirect
+	github.com/sagernet/cronet-go/lib/ios_arm64 v0.0.0-20251218041530-c2a431c5f1f7 // indirect
+	github.com/sagernet/cronet-go/lib/ios_arm64_simulator v0.0.0-20251218041530-c2a431c5f1f7 // indirect
+	github.com/sagernet/cronet-go/lib/linux_386 v0.0.0-20251218041530-c2a431c5f1f7 // indirect
+	github.com/sagernet/cronet-go/lib/linux_386_musl v0.0.0-20251218041530-c2a431c5f1f7 // indirect
+	github.com/sagernet/cronet-go/lib/linux_amd64 v0.0.0-20251218041530-c2a431c5f1f7 // indirect
+	github.com/sagernet/cronet-go/lib/linux_amd64_musl v0.0.0-20251218041530-c2a431c5f1f7 // indirect
+	github.com/sagernet/cronet-go/lib/linux_arm v0.0.0-20251218041530-c2a431c5f1f7 // indirect
+	github.com/sagernet/cronet-go/lib/linux_arm64 v0.0.0-20251218041530-c2a431c5f1f7 // indirect
+	github.com/sagernet/cronet-go/lib/linux_arm64_musl v0.0.0-20251218041530-c2a431c5f1f7 // indirect
+	github.com/sagernet/cronet-go/lib/linux_arm_musl v0.0.0-20251218041530-c2a431c5f1f7 // indirect
+	github.com/sagernet/cronet-go/lib/tvos_amd64_simulator v0.0.0-20251218041530-c2a431c5f1f7 // indirect
+	github.com/sagernet/cronet-go/lib/tvos_arm64 v0.0.0-20251218041530-c2a431c5f1f7 // indirect
+	github.com/sagernet/cronet-go/lib/tvos_arm64_simulator v0.0.0-20251218041530-c2a431c5f1f7 // indirect
+	github.com/sagernet/cronet-go/lib/windows_amd64 v0.0.0-20251218041530-c2a431c5f1f7 // indirect
+	github.com/sagernet/cronet-go/lib/windows_arm64 v0.0.0-20251218041530-c2a431c5f1f7 // indirect
 	github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a // indirect
 	github.com/sagernet/nftables v0.3.0-beta.4 // indirect
 	github.com/spf13/pflag v1.0.6 // indirect

+ 52 - 52
go.sum

@@ -154,54 +154,54 @@ github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a h1:+NkI2670SQpQWvkk
 github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a/go.mod h1:63s7jpZqcDAIpj8oI/1v4Izok+npJOHACFCU6+huCkM=
 github.com/sagernet/cors v1.2.1 h1:Cv5Z8y9YSD6Gm+qSpNrL3LO4lD3eQVvbFYJSG7JCMHQ=
 github.com/sagernet/cors v1.2.1/go.mod h1:O64VyOjjhrkLmQIjF4KGRrJO/5dVXFdpEmCW/eISRAI=
-github.com/sagernet/cronet-go v0.0.0-20251217133746-1955399f1585 h1:fu/J7Z+umFy5JwIxo2/7ixvuMRouJx93VU0RUXQx8aI=
-github.com/sagernet/cronet-go v0.0.0-20251217133746-1955399f1585/go.mod h1:hwFHBEjjthyEquDULbr4c4ucMedp8Drb6Jvm2kt/0Bw=
-github.com/sagernet/cronet-go/all v0.0.0-20251217133746-1955399f1585 h1:QN3WvGKiBg9N5vrSVKJzNTmK/BfEVMJNbRZDOlOfUpo=
-github.com/sagernet/cronet-go/all v0.0.0-20251217133746-1955399f1585/go.mod h1:JTqmHTkUqWDX5Hz+jnx8kdDKJ07U80QS1hN0Wfe7CTI=
-github.com/sagernet/cronet-go/lib/android_386 v0.0.0-20251217133247-ea405ec61e5f h1:hjyZ7QZWWxYEW13lBT3+yAk7yENgKBuqhiw5rl/oxng=
-github.com/sagernet/cronet-go/lib/android_386 v0.0.0-20251217133247-ea405ec61e5f/go.mod h1:XXDwdjX/T8xftoeJxQmbBoYXZp8MAPFR2CwbFuTpEtw=
-github.com/sagernet/cronet-go/lib/android_amd64 v0.0.0-20251217133247-ea405ec61e5f h1:RHPD2Opa4kGqlTtHyhtMWhzvr3F1PZsT6GW+IMBaMYs=
-github.com/sagernet/cronet-go/lib/android_amd64 v0.0.0-20251217133247-ea405ec61e5f/go.mod h1:iNiUGoLtnr8/JTuVNj7XJbmpOAp2C6+B81KDrPxwaZM=
-github.com/sagernet/cronet-go/lib/android_arm v0.0.0-20251217133247-ea405ec61e5f h1:wPrD+ADgFZC7AFFqUDWaKdcElqGODX10WrNpmUywX00=
-github.com/sagernet/cronet-go/lib/android_arm v0.0.0-20251217133247-ea405ec61e5f/go.mod h1:19ILNUOGIzRdOqa2mq+iY0JoHxuieB7/lnjYeaA2vEc=
-github.com/sagernet/cronet-go/lib/android_arm64 v0.0.0-20251217133247-ea405ec61e5f h1:MC0T2f2SXwai6hdmTkkulE7PlHA11lHp1re7alZCQLo=
-github.com/sagernet/cronet-go/lib/android_arm64 v0.0.0-20251217133247-ea405ec61e5f/go.mod h1:JxzGyQf94Cr6sBShKqODGDyRUlESfJK/Njcz9Lz6qMQ=
-github.com/sagernet/cronet-go/lib/darwin_amd64 v0.0.0-20251217133247-ea405ec61e5f h1:X3RxBK5D5P3fcb+j8HqiEwhXEGMZkCg9ecmGYHo2qpg=
-github.com/sagernet/cronet-go/lib/darwin_amd64 v0.0.0-20251217133247-ea405ec61e5f/go.mod h1:KN+9T9TBycGOLzmKU4QdcHAJEj6Nlx48ifnlTvvHMvs=
-github.com/sagernet/cronet-go/lib/darwin_arm64 v0.0.0-20251217133247-ea405ec61e5f h1:K/CJaXL1djRbHyoVHGNx9nacncZPKE0QkEoO12nWL4s=
-github.com/sagernet/cronet-go/lib/darwin_arm64 v0.0.0-20251217133247-ea405ec61e5f/go.mod h1:kojvtUc29KKnk8hs2QIANynVR59921SnGWA9kXohHc0=
-github.com/sagernet/cronet-go/lib/ios_amd64_simulator v0.0.0-20251217133247-ea405ec61e5f h1:uN/ay0BtmWWPdaoAsK5yu+bbQfr6iujEUTo7zZhF3a4=
-github.com/sagernet/cronet-go/lib/ios_amd64_simulator v0.0.0-20251217133247-ea405ec61e5f/go.mod h1:hkQzRE5GDbaH1/ioqYh0Taho4L6i0yLRCVEZ5xHz5M0=
-github.com/sagernet/cronet-go/lib/ios_arm64 v0.0.0-20251217133247-ea405ec61e5f h1:vdDIjy2y8DQEu1tVkpS/WOx0fEbK4yjMQv7X1e7MbFU=
-github.com/sagernet/cronet-go/lib/ios_arm64 v0.0.0-20251217133247-ea405ec61e5f/go.mod h1:tzVJFTOm66UxLxy6K0ZN5Ic2PC79e+sKKnt+V9puEa4=
-github.com/sagernet/cronet-go/lib/ios_arm64_simulator v0.0.0-20251217133247-ea405ec61e5f h1:BElLblhAfW8Yd5ehlI9xk1FhlsGnKIX6oVak3C8cCnc=
-github.com/sagernet/cronet-go/lib/ios_arm64_simulator v0.0.0-20251217133247-ea405ec61e5f/go.mod h1:M/pN6m3j0HFU6/y83n0HU6GLYys3tYdr/xTE8hVEGMo=
-github.com/sagernet/cronet-go/lib/linux_386 v0.0.0-20251217133247-ea405ec61e5f h1:vALFH1gx8nLLiAqkTy7tgrT9uLWCPC4e+Ir1UvEQkRw=
-github.com/sagernet/cronet-go/lib/linux_386 v0.0.0-20251217133247-ea405ec61e5f/go.mod h1:cGh5hO6eljCo6KMQ/Cel8Xgq4+etL0awZLRBDVG1EZQ=
-github.com/sagernet/cronet-go/lib/linux_386_musl v0.0.0-20251217133247-ea405ec61e5f h1:vQ99pp3CGklVoUGO2x//xne3BkfzSmNKDOzB5V9BoaU=
-github.com/sagernet/cronet-go/lib/linux_386_musl v0.0.0-20251217133247-ea405ec61e5f/go.mod h1:JFE0/cxaKkx0wqPMZU7MgaplQlU0zudv82dROJjClKU=
-github.com/sagernet/cronet-go/lib/linux_amd64 v0.0.0-20251217133247-ea405ec61e5f h1:MqINoyziFNrN8t5d/XCu1z+BZs2CkRLLKKOdx0g6bJ4=
-github.com/sagernet/cronet-go/lib/linux_amd64 v0.0.0-20251217133247-ea405ec61e5f/go.mod h1:vU8VftFeSt7fURCa3JXD6+k6ss1YAX+idQjPvHmJ2tI=
-github.com/sagernet/cronet-go/lib/linux_amd64_musl v0.0.0-20251217133247-ea405ec61e5f h1:L7HQmTsLFI7nAzyi2RIkmkuraSY7LRivBYoflIjQcxk=
-github.com/sagernet/cronet-go/lib/linux_amd64_musl v0.0.0-20251217133247-ea405ec61e5f/go.mod h1:vCe4OUuL+XOUge9v3MyTD45BnuAXiH+DkjN9quDXJzQ=
-github.com/sagernet/cronet-go/lib/linux_arm v0.0.0-20251217133247-ea405ec61e5f h1:DAswotlvnP6zYlP2KleGfMUy4dIBNNYGg3sh1reS53I=
-github.com/sagernet/cronet-go/lib/linux_arm v0.0.0-20251217133247-ea405ec61e5f/go.mod h1:w9amBWrvjtohQzBGCKJ7LCh22LhTIJs4sE7cYaKQzM0=
-github.com/sagernet/cronet-go/lib/linux_arm64 v0.0.0-20251217133247-ea405ec61e5f h1:b2OhFosX8oUEdOpYkDS4fkbotbEe9WRMCpYGAWWq4VI=
-github.com/sagernet/cronet-go/lib/linux_arm64 v0.0.0-20251217133247-ea405ec61e5f/go.mod h1:TqlsFtcYS/etTeck46kHBeT8Le0Igw1Q/AV88UnMS3s=
-github.com/sagernet/cronet-go/lib/linux_arm64_musl v0.0.0-20251217133247-ea405ec61e5f h1:H+GUhGCYe/4wHi+XRw96AgFxETSE3yCDhyAH7G6GbQc=
-github.com/sagernet/cronet-go/lib/linux_arm64_musl v0.0.0-20251217133247-ea405ec61e5f/go.mod h1:B6Qd0vys8sv9OKVRN6J9RqDzYRGE938Fb2zrYdBDyTQ=
-github.com/sagernet/cronet-go/lib/linux_arm_musl v0.0.0-20251217133247-ea405ec61e5f h1:ziXSJVeboo4ZiCulyMbbEgG9ArfP98hqN1pALA15XeM=
-github.com/sagernet/cronet-go/lib/linux_arm_musl v0.0.0-20251217133247-ea405ec61e5f/go.mod h1:3tXMMFY7AHugOVBZ5Al7cL7JKsnFOe5bMVr0hZPk3ow=
-github.com/sagernet/cronet-go/lib/tvos_amd64_simulator v0.0.0-20251217133247-ea405ec61e5f h1:X9FaZ28M35Hj23agNDRDCklSrR0zb8PZz4K4EBalILE=
-github.com/sagernet/cronet-go/lib/tvos_amd64_simulator v0.0.0-20251217133247-ea405ec61e5f/go.mod h1:aaX0YGl8nhGmfRWI8bc3BtDjY8Vzx6O0cS/e1uqxDq4=
-github.com/sagernet/cronet-go/lib/tvos_arm64 v0.0.0-20251217133247-ea405ec61e5f h1:qKlncyWLNJ3YtJrF3hK5YPd2Tb66ZF1iQXjq1mEADhE=
-github.com/sagernet/cronet-go/lib/tvos_arm64 v0.0.0-20251217133247-ea405ec61e5f/go.mod h1:EdzMKA96xITc42QEI+ct4SwqX8Dn3ltKK8wzdkLWpSc=
-github.com/sagernet/cronet-go/lib/tvos_arm64_simulator v0.0.0-20251217133247-ea405ec61e5f h1:qpBg3PtrVx4Tgv+AwwoRgPqYsfEZeZ3Jn+zHfqr7Z1A=
-github.com/sagernet/cronet-go/lib/tvos_arm64_simulator v0.0.0-20251217133247-ea405ec61e5f/go.mod h1:qix4kv1TTAJ5tY4lJ9vjhe9EY4mM+B7H5giOhbxDVcc=
-github.com/sagernet/cronet-go/lib/windows_amd64 v0.0.0-20251217133247-ea405ec61e5f h1:PvjxP4e6qosQrhkPrpW2ZnRm2OKZsvEXIADV29fKWeY=
-github.com/sagernet/cronet-go/lib/windows_amd64 v0.0.0-20251217133247-ea405ec61e5f/go.mod h1:lm9w/oCCRyBiUa3G8lDQTT8x/ONUvgVR2iV9fVzUZB8=
-github.com/sagernet/cronet-go/lib/windows_arm64 v0.0.0-20251217133247-ea405ec61e5f h1:l3+QN68ENC0KHCxHa0iUO0vMGiG00TJlHgH8+jVrDNU=
-github.com/sagernet/cronet-go/lib/windows_arm64 v0.0.0-20251217133247-ea405ec61e5f/go.mod h1:n34YyLgapgjWdKa0IoeczjAFCwD3/dxbsH5sucKw0bw=
+github.com/sagernet/cronet-go v0.0.0-20251218041957-eeb28f1dba2f h1:WTHyVtd9nNZ4VB20aja31e0ZXXGrVlssAanJJBMc5BU=
+github.com/sagernet/cronet-go v0.0.0-20251218041957-eeb28f1dba2f/go.mod h1:hwFHBEjjthyEquDULbr4c4ucMedp8Drb6Jvm2kt/0Bw=
+github.com/sagernet/cronet-go/all v0.0.0-20251218041957-eeb28f1dba2f h1:qupezSQEMraq2yajI4HrWf9h9rY7RESUYbYHRRd49FY=
+github.com/sagernet/cronet-go/all v0.0.0-20251218041957-eeb28f1dba2f/go.mod h1:onaFo5hJh1KsvuxkYTFLokh0Yx2oBh9J3yvFTnFB1Fc=
+github.com/sagernet/cronet-go/lib/android_386 v0.0.0-20251218041530-c2a431c5f1f7 h1:jmDdDxVFN/W+pX/QRHYR6jFu5gosRPNSSPemGmchHpM=
+github.com/sagernet/cronet-go/lib/android_386 v0.0.0-20251218041530-c2a431c5f1f7/go.mod h1:XXDwdjX/T8xftoeJxQmbBoYXZp8MAPFR2CwbFuTpEtw=
+github.com/sagernet/cronet-go/lib/android_amd64 v0.0.0-20251218041530-c2a431c5f1f7 h1:zQeDQJg2YZSlmR5+mYV4KyqIWwe+SH5hnxTO4EalDwA=
+github.com/sagernet/cronet-go/lib/android_amd64 v0.0.0-20251218041530-c2a431c5f1f7/go.mod h1:iNiUGoLtnr8/JTuVNj7XJbmpOAp2C6+B81KDrPxwaZM=
+github.com/sagernet/cronet-go/lib/android_arm v0.0.0-20251218041530-c2a431c5f1f7 h1:85ck9+7Ftj+J3RO1uusn1Y3EXRLX9Dy0WIK/ZjRlQok=
+github.com/sagernet/cronet-go/lib/android_arm v0.0.0-20251218041530-c2a431c5f1f7/go.mod h1:19ILNUOGIzRdOqa2mq+iY0JoHxuieB7/lnjYeaA2vEc=
+github.com/sagernet/cronet-go/lib/android_arm64 v0.0.0-20251218041530-c2a431c5f1f7 h1:D//nc8RxHp7tTKcIYYQZ80wQBwxlCJv6HpkrCkqIVRo=
+github.com/sagernet/cronet-go/lib/android_arm64 v0.0.0-20251218041530-c2a431c5f1f7/go.mod h1:JxzGyQf94Cr6sBShKqODGDyRUlESfJK/Njcz9Lz6qMQ=
+github.com/sagernet/cronet-go/lib/darwin_amd64 v0.0.0-20251218041530-c2a431c5f1f7 h1:wwrQCcrwnHSY/Y4cy8JCiZLzuWXM8tENphhJtFplh0c=
+github.com/sagernet/cronet-go/lib/darwin_amd64 v0.0.0-20251218041530-c2a431c5f1f7/go.mod h1:KN+9T9TBycGOLzmKU4QdcHAJEj6Nlx48ifnlTvvHMvs=
+github.com/sagernet/cronet-go/lib/darwin_arm64 v0.0.0-20251218041530-c2a431c5f1f7 h1:Q52ojQVXk9f6Z+EWHWv+SJajNF56bVvgMyQP/7WV2TI=
+github.com/sagernet/cronet-go/lib/darwin_arm64 v0.0.0-20251218041530-c2a431c5f1f7/go.mod h1:kojvtUc29KKnk8hs2QIANynVR59921SnGWA9kXohHc0=
+github.com/sagernet/cronet-go/lib/ios_amd64_simulator v0.0.0-20251218041530-c2a431c5f1f7 h1:UzXQ09sZQZDlsZvWd4SAhtaF0RMxAVg4TEYsRNMutjU=
+github.com/sagernet/cronet-go/lib/ios_amd64_simulator v0.0.0-20251218041530-c2a431c5f1f7/go.mod h1:hkQzRE5GDbaH1/ioqYh0Taho4L6i0yLRCVEZ5xHz5M0=
+github.com/sagernet/cronet-go/lib/ios_arm64 v0.0.0-20251218041530-c2a431c5f1f7 h1:sjSknfRi3fMJqwHW4pNL64SGq7Y5XIm4pz5Ds21hvKw=
+github.com/sagernet/cronet-go/lib/ios_arm64 v0.0.0-20251218041530-c2a431c5f1f7/go.mod h1:tzVJFTOm66UxLxy6K0ZN5Ic2PC79e+sKKnt+V9puEa4=
+github.com/sagernet/cronet-go/lib/ios_arm64_simulator v0.0.0-20251218041530-c2a431c5f1f7 h1:uxb8pqzB4KH7ai6MocOWQPu3/+BAYISSIMPHWs0wtrQ=
+github.com/sagernet/cronet-go/lib/ios_arm64_simulator v0.0.0-20251218041530-c2a431c5f1f7/go.mod h1:M/pN6m3j0HFU6/y83n0HU6GLYys3tYdr/xTE8hVEGMo=
+github.com/sagernet/cronet-go/lib/linux_386 v0.0.0-20251218041530-c2a431c5f1f7 h1:uV78fIQ2XdVQUzowiafKP2fs+rGlkI+9u7l1cBMlQlc=
+github.com/sagernet/cronet-go/lib/linux_386 v0.0.0-20251218041530-c2a431c5f1f7/go.mod h1:cGh5hO6eljCo6KMQ/Cel8Xgq4+etL0awZLRBDVG1EZQ=
+github.com/sagernet/cronet-go/lib/linux_386_musl v0.0.0-20251218041530-c2a431c5f1f7 h1:6d87Pvio5dpWakic3SNBVTwTlt8ZnvL1GWPPeY2xSLs=
+github.com/sagernet/cronet-go/lib/linux_386_musl v0.0.0-20251218041530-c2a431c5f1f7/go.mod h1:JFE0/cxaKkx0wqPMZU7MgaplQlU0zudv82dROJjClKU=
+github.com/sagernet/cronet-go/lib/linux_amd64 v0.0.0-20251218041530-c2a431c5f1f7 h1:tc3GdN9pAfZqdfb55DmtUSXEuKuecWNYSD/+4jclXmo=
+github.com/sagernet/cronet-go/lib/linux_amd64 v0.0.0-20251218041530-c2a431c5f1f7/go.mod h1:vU8VftFeSt7fURCa3JXD6+k6ss1YAX+idQjPvHmJ2tI=
+github.com/sagernet/cronet-go/lib/linux_amd64_musl v0.0.0-20251218041530-c2a431c5f1f7 h1:W5fN1B1wYgnh7Y5Nw+MgcDjsvdPvEPAGe27iemq2LJs=
+github.com/sagernet/cronet-go/lib/linux_amd64_musl v0.0.0-20251218041530-c2a431c5f1f7/go.mod h1:vCe4OUuL+XOUge9v3MyTD45BnuAXiH+DkjN9quDXJzQ=
+github.com/sagernet/cronet-go/lib/linux_arm v0.0.0-20251218041530-c2a431c5f1f7 h1:xfNH8CO8p2W8rtVFgyv8kiAkzoSArW6+h2s/p5ZNvP8=
+github.com/sagernet/cronet-go/lib/linux_arm v0.0.0-20251218041530-c2a431c5f1f7/go.mod h1:w9amBWrvjtohQzBGCKJ7LCh22LhTIJs4sE7cYaKQzM0=
+github.com/sagernet/cronet-go/lib/linux_arm64 v0.0.0-20251218041530-c2a431c5f1f7 h1:1mkhgxLOh1pPjBLgC/GK3Rhhinz0254OjGJRrivVhQ8=
+github.com/sagernet/cronet-go/lib/linux_arm64 v0.0.0-20251218041530-c2a431c5f1f7/go.mod h1:TqlsFtcYS/etTeck46kHBeT8Le0Igw1Q/AV88UnMS3s=
+github.com/sagernet/cronet-go/lib/linux_arm64_musl v0.0.0-20251218041530-c2a431c5f1f7 h1:zf252WwVhJYduTDBXvkBKdwSU+Ce0OToQzvy5SwPS3c=
+github.com/sagernet/cronet-go/lib/linux_arm64_musl v0.0.0-20251218041530-c2a431c5f1f7/go.mod h1:B6Qd0vys8sv9OKVRN6J9RqDzYRGE938Fb2zrYdBDyTQ=
+github.com/sagernet/cronet-go/lib/linux_arm_musl v0.0.0-20251218041530-c2a431c5f1f7 h1:Nhkn2M2UsGe0hr6qOgNKvGKgAbo6EfWQto+YjlNWGqg=
+github.com/sagernet/cronet-go/lib/linux_arm_musl v0.0.0-20251218041530-c2a431c5f1f7/go.mod h1:3tXMMFY7AHugOVBZ5Al7cL7JKsnFOe5bMVr0hZPk3ow=
+github.com/sagernet/cronet-go/lib/tvos_amd64_simulator v0.0.0-20251218041530-c2a431c5f1f7 h1:HSvWFyBDLC7grFuSwBSIaxLI/MVpe/w4qJJAWAZsBxc=
+github.com/sagernet/cronet-go/lib/tvos_amd64_simulator v0.0.0-20251218041530-c2a431c5f1f7/go.mod h1:aaX0YGl8nhGmfRWI8bc3BtDjY8Vzx6O0cS/e1uqxDq4=
+github.com/sagernet/cronet-go/lib/tvos_arm64 v0.0.0-20251218041530-c2a431c5f1f7 h1:PJa1fhmbXWXCYk07DZhqzjP2u9rM/cnS0A1aaPU56pY=
+github.com/sagernet/cronet-go/lib/tvos_arm64 v0.0.0-20251218041530-c2a431c5f1f7/go.mod h1:EdzMKA96xITc42QEI+ct4SwqX8Dn3ltKK8wzdkLWpSc=
+github.com/sagernet/cronet-go/lib/tvos_arm64_simulator v0.0.0-20251218041530-c2a431c5f1f7 h1:Tpskq8p8boYHkBya18ythhgWTMv8gFsseGk55MFW+/k=
+github.com/sagernet/cronet-go/lib/tvos_arm64_simulator v0.0.0-20251218041530-c2a431c5f1f7/go.mod h1:qix4kv1TTAJ5tY4lJ9vjhe9EY4mM+B7H5giOhbxDVcc=
+github.com/sagernet/cronet-go/lib/windows_amd64 v0.0.0-20251218041530-c2a431c5f1f7 h1:qjB64lzTP0ROuk9GCCwsNQ9ca37nIr75iOyc2vuGFQg=
+github.com/sagernet/cronet-go/lib/windows_amd64 v0.0.0-20251218041530-c2a431c5f1f7/go.mod h1:lm9w/oCCRyBiUa3G8lDQTT8x/ONUvgVR2iV9fVzUZB8=
+github.com/sagernet/cronet-go/lib/windows_arm64 v0.0.0-20251218041530-c2a431c5f1f7 h1:GDJjygR/HLWOzwAs0RjhvqN6d1rUm7WiDAmHNe8gRAM=
+github.com/sagernet/cronet-go/lib/windows_arm64 v0.0.0-20251218041530-c2a431c5f1f7/go.mod h1:n34YyLgapgjWdKa0IoeczjAFCwD3/dxbsH5sucKw0bw=
 github.com/sagernet/fswatch v0.1.1 h1:YqID+93B7VRfqIH3PArW/XpJv5H4OLEVWDfProGoRQs=
 github.com/sagernet/fswatch v0.1.1/go.mod h1:nz85laH0mkQqJfaOrqPpkwtU1znMFNVTpT/5oRsVz/o=
 github.com/sagernet/gomobile v0.1.10 h1:ElqZ0OVDvyQlU91MU0C9cfU0FrILBbc65+NOKzZ1t0c=
@@ -212,15 +212,15 @@ github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a h1:ObwtHN2VpqE0ZN
 github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a/go.mod h1:xLnfdiJbSp8rNqYEdIW/6eDO4mVoogml14Bh2hSiFpM=
 github.com/sagernet/nftables v0.3.0-beta.4 h1:kbULlAwAC3jvdGAC1P5Fa3GSxVwQJibNenDW2zaXr8I=
 github.com/sagernet/nftables v0.3.0-beta.4/go.mod h1:OQXAjvjNGGFxaTgVCSTRIhYB5/llyVDeapVoENYBDS8=
-github.com/sagernet/quic-go v0.57.1-sing-box-mod.1 h1:6fhKbfA0b7L1CVekayV1g87uJFtMXFE0rFXR48SRrWI=
-github.com/sagernet/quic-go v0.57.1-sing-box-mod.1/go.mod h1:OqILvS182CyOol5zNNo6bguvOGgXzV459+chpRaUC+4=
+github.com/sagernet/quic-go v0.57.1-sing-box-mod.3 h1:Rah/tDukrowqlznHQgXD4E9/yEsVsEMIxBZzS2NorGc=
+github.com/sagernet/quic-go v0.57.1-sing-box-mod.3/go.mod h1:OqILvS182CyOol5zNNo6bguvOGgXzV459+chpRaUC+4=
 github.com/sagernet/sing v0.6.9/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak=
 github.com/sagernet/sing v0.8.0-beta.6.0.20251207063731-56fd482ce1c6 h1:EYaDzllFzNYnzQ9xH/ieSAXct4wQ8pD45kgNMo7RPZc=
 github.com/sagernet/sing v0.8.0-beta.6.0.20251207063731-56fd482ce1c6/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak=
 github.com/sagernet/sing-mux v0.3.3 h1:YFgt9plMWzH994BMZLmyKL37PdIVaIilwP0Jg+EcLfw=
 github.com/sagernet/sing-mux v0.3.3/go.mod h1:pht8iFY4c9Xltj7rhVd208npkNaeCxzyXCgulDPLUDA=
-github.com/sagernet/sing-quic v0.6.0-beta.5 h1:kZfRLmsPxAgl0usZUgomDurLn7ZZ26lJWIpGow9ZWR4=
-github.com/sagernet/sing-quic v0.6.0-beta.5/go.mod h1:9D9GANrK33NjWCe1VkU5L5+8MxU39WrduBSmHuHz8GA=
+github.com/sagernet/sing-quic v0.6.0-beta.5.0.20251218085114-6968f531a8c0 h1:YNXy008FFkVwfNjCR8GlVTlHbBXPwv8Y4ytDnSFUSDo=
+github.com/sagernet/sing-quic v0.6.0-beta.5.0.20251218085114-6968f531a8c0/go.mod h1:Y3YVjPutLHLQvYjGtUFH+w8YmM4MTd19NDzxLZGNGIs=
 github.com/sagernet/sing-shadowsocks v0.2.8 h1:PURj5PRoAkqeHh2ZW205RWzN9E9RtKCVCzByXruQWfE=
 github.com/sagernet/sing-shadowsocks v0.2.8/go.mod h1:lo7TWEMDcN5/h5B8S0ew+r78ZODn6SwVaFhvB6H+PTI=
 github.com/sagernet/sing-shadowsocks2 v0.2.1 h1:dWV9OXCeFPuYGHb6IRqlSptVnSzOelnqqs2gQ2/Qioo=

+ 1 - 1
include/quic_stub.go

@@ -44,7 +44,7 @@ func registerQUICInbounds(registry *inbound.Registry) {
 	inbound.Register[option.Hysteria2InboundOptions](registry, C.TypeHysteria2, func(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.Hysteria2InboundOptions) (adapter.Inbound, error) {
 		return nil, C.ErrQUICNotIncluded
 	})
-	naive.ConfigureHTTP3ListenerFunc = func(listener *listener.Listener, handler http.Handler, tlsConfig tls.ServerConfig, logger logger.Logger) (io.Closer, error) {
+	naive.ConfigureHTTP3ListenerFunc = func(ctx context.Context, logger logger.Logger, listener *listener.Listener, handler http.Handler, tlsConfig tls.ServerConfig, options option.NaiveInboundOptions) (io.Closer, error) {
 		return nil, C.ErrQUICNotIncluded
 	}
 }

+ 20 - 7
option/naive.go

@@ -5,20 +5,33 @@ import (
 	"github.com/sagernet/sing/common/json/badoption"
 )
 
+type QuicheCongestionControl string
+
+const (
+	QuicheCongestionControlDefault QuicheCongestionControl = ""
+	QuicheCongestionControlBBR     QuicheCongestionControl = "TBBR"
+	QuicheCongestionControlBBRv2   QuicheCongestionControl = "B2ON"
+	QuicheCongestionControlCubic   QuicheCongestionControl = "QBIC"
+	QuicheCongestionControlReno    QuicheCongestionControl = "RENO"
+)
+
 type NaiveInboundOptions struct {
 	ListenOptions
-	Users   []auth.User `json:"users,omitempty"`
-	Network NetworkList `json:"network,omitempty"`
+	Users                 []auth.User `json:"users,omitempty"`
+	Network               NetworkList `json:"network,omitempty"`
+	QUICCongestionControl string      `json:"quic_congestion_control,omitempty"`
 	InboundTLSOptionsContainer
 }
 
 type NaiveOutboundOptions struct {
 	DialerOptions
 	ServerOptions
-	Username            string               `json:"username,omitempty"`
-	Password            string               `json:"password,omitempty"`
-	InsecureConcurrency int                  `json:"insecure_concurrency,omitempty"`
-	ExtraHeaders        badoption.HTTPHeader `json:"extra_headers,omitempty"`
-	UDPOverTCP          *UDPOverTCPOptions   `json:"udp_over_tcp,omitempty"`
+	Username              string               `json:"username,omitempty"`
+	Password              string               `json:"password,omitempty"`
+	InsecureConcurrency   int                  `json:"insecure_concurrency,omitempty"`
+	ExtraHeaders          badoption.HTTPHeader `json:"extra_headers,omitempty"`
+	UDPOverTCP            *UDPOverTCPOptions   `json:"udp_over_tcp,omitempty"`
+	QUIC                  bool                 `json:"quic,omitempty"`
+	QUICCongestionControl string               `json:"quic_congestion_control,omitempty"`
 	OutboundTLSOptionsContainer
 }

+ 3 - 2
protocol/naive/inbound.go

@@ -29,7 +29,7 @@ import (
 	"golang.org/x/net/http2/h2c"
 )
 
-var ConfigureHTTP3ListenerFunc func(listener *listener.Listener, handler http.Handler, tlsConfig tls.ServerConfig, logger logger.Logger) (io.Closer, error)
+var ConfigureHTTP3ListenerFunc func(ctx context.Context, logger logger.Logger, listener *listener.Listener, handler http.Handler, tlsConfig tls.ServerConfig, options option.NaiveInboundOptions) (io.Closer, error)
 
 func RegisterInbound(registry *inbound.Registry) {
 	inbound.Register[option.NaiveInboundOptions](registry, C.TypeNaive, NewInbound)
@@ -40,6 +40,7 @@ type Inbound struct {
 	ctx              context.Context
 	router           adapter.ConnectionRouterEx
 	logger           logger.ContextLogger
+	options          option.NaiveInboundOptions
 	listener         *listener.Listener
 	network          []string
 	networkIsDefault bool
@@ -121,7 +122,7 @@ func (n *Inbound) Start(stage adapter.StartStage) error {
 	}
 
 	if common.Contains(n.network, N.NetworkUDP) {
-		http3Server, err := ConfigureHTTP3ListenerFunc(n.listener, n, n.tlsConfig, n.logger)
+		http3Server, err := ConfigureHTTP3ListenerFunc(n.ctx, n.logger, n.listener, n, n.tlsConfig, n.options)
 		if err == nil {
 			n.h3Server = http3Server
 		} else if len(n.network) > 1 {

+ 17 - 2
protocol/naive/outbound.go

@@ -160,7 +160,21 @@ func NewOutbound(ctx context.Context, router adapter.Router, logger log.ContextL
 			echConfigList = block.Bytes
 		}
 	}
-
+	var quicCongestionControl cronet.QUICCongestionControl
+	switch options.QUICCongestionControl {
+	case "":
+		quicCongestionControl = cronet.QUICCongestionControlDefault
+	case "bbr":
+		quicCongestionControl = cronet.QUICCongestionControlBBR
+	case "bbr2":
+		quicCongestionControl = cronet.QUICCongestionControlBBRv2
+	case "cubic":
+		quicCongestionControl = cronet.QUICCongestionControlCubic
+	case "reno":
+		quicCongestionControl = cronet.QUICCongestionControlReno
+	default:
+		return nil, E.New("unknown quic congestion control: ", options.QUICCongestionControl)
+	}
 	client, err := cronet.NewNaiveClient(cronet.NaiveClientConfig{
 		Context:                           ctx,
 		ServerAddress:                     serverAddress,
@@ -176,11 +190,12 @@ func NewOutbound(ctx context.Context, router adapter.Router, logger log.ContextL
 		ECHEnabled:                        echEnabled,
 		ECHConfigList:                     echConfigList,
 		ECHQueryServerName:                echQueryServerName,
+		QUIC:                              options.QUIC,
+		QUICCongestionControl:             quicCongestionControl,
 	})
 	if err != nil {
 		return nil, err
 	}
-
 	var uotClient *uot.Client
 	uotOptions := common.PtrValueOrDefault(options.UDPOverTCP)
 	if uotOptions.Enabled {

+ 69 - 3
protocol/naive/quic/inbound_init.go

@@ -1,21 +1,29 @@
 package quic
 
 import (
+	"context"
 	"io"
 	"net/http"
 
 	"github.com/sagernet/quic-go"
+	"github.com/sagernet/quic-go/congestion"
 	"github.com/sagernet/quic-go/http3"
 	"github.com/sagernet/sing-box/common/listener"
 	"github.com/sagernet/sing-box/common/tls"
+	"github.com/sagernet/sing-box/option"
 	"github.com/sagernet/sing-box/protocol/naive"
 	"github.com/sagernet/sing-quic"
+	"github.com/sagernet/sing-quic/congestion_bbr1"
+	"github.com/sagernet/sing-quic/congestion_bbr2"
+	congestion_meta1 "github.com/sagernet/sing-quic/congestion_meta1"
+	congestion_meta2 "github.com/sagernet/sing-quic/congestion_meta2"
 	E "github.com/sagernet/sing/common/exceptions"
 	"github.com/sagernet/sing/common/logger"
+	"github.com/sagernet/sing/common/ntp"
 )
 
 func init() {
-	naive.ConfigureHTTP3ListenerFunc = func(listener *listener.Listener, handler http.Handler, tlsConfig tls.ServerConfig, logger logger.Logger) (io.Closer, error) {
+	naive.ConfigureHTTP3ListenerFunc = func(ctx context.Context, logger logger.Logger, listener *listener.Listener, handler http.Handler, tlsConfig tls.ServerConfig, options option.NaiveInboundOptions) (io.Closer, error) {
 		err := qtls.ConfigureHTTP3(tlsConfig)
 		if err != nil {
 			return nil, err
@@ -26,9 +34,67 @@ func init() {
 			return nil, err
 		}
 
+		var congestionControl func(conn *quic.Conn) congestion.CongestionControl
+		switch options.QUICCongestionControl {
+		case "", "bbr":
+			congestionControl = func(conn *quic.Conn) congestion.CongestionControl {
+				return congestion_meta2.NewBbrSender(
+					congestion_meta2.DefaultClock{TimeFunc: ntp.TimeFuncFromContext(ctx)},
+					congestion.ByteCount(conn.Config().InitialPacketSize),
+					congestion.ByteCount(congestion_meta1.InitialCongestionWindow),
+				)
+			}
+		case "bbr_standard":
+			congestionControl = func(conn *quic.Conn) congestion.CongestionControl {
+				return congestion_bbr1.NewBbrSender(
+					congestion_bbr1.DefaultClock{TimeFunc: ntp.TimeFuncFromContext(ctx)},
+					congestion.ByteCount(conn.Config().InitialPacketSize),
+					congestion_bbr1.InitialCongestionWindowPackets,
+					congestion_bbr1.MaxCongestionWindowPackets,
+				)
+			}
+		case "bbr2":
+			congestionControl = func(conn *quic.Conn) congestion.CongestionControl {
+				return congestion_bbr2.NewBBR2Sender(
+					congestion_bbr2.DefaultClock{TimeFunc: ntp.TimeFuncFromContext(ctx)},
+					congestion.ByteCount(conn.Config().InitialPacketSize),
+					0,
+					false,
+				)
+			}
+		case "bbr2_variant":
+			congestionControl = func(conn *quic.Conn) congestion.CongestionControl {
+				return congestion_bbr2.NewBBR2Sender(
+					congestion_bbr2.DefaultClock{TimeFunc: ntp.TimeFuncFromContext(ctx)},
+					congestion.ByteCount(conn.Config().InitialPacketSize),
+					32*congestion.ByteCount(conn.Config().InitialPacketSize),
+					true,
+				)
+			}
+		case "cubic":
+			congestionControl = func(conn *quic.Conn) congestion.CongestionControl {
+				return congestion_meta1.NewCubicSender(
+					congestion_meta1.DefaultClock{TimeFunc: ntp.TimeFuncFromContext(ctx)},
+					congestion.ByteCount(conn.Config().InitialPacketSize),
+					false,
+				)
+			}
+		case "reno":
+			congestionControl = func(conn *quic.Conn) congestion.CongestionControl {
+				return congestion_meta1.NewCubicSender(
+					congestion_meta1.DefaultClock{TimeFunc: ntp.TimeFuncFromContext(ctx)},
+					congestion.ByteCount(conn.Config().InitialPacketSize),
+					true,
+				)
+			}
+		default:
+			return nil, E.New("unknown quic congestion control: ", options.QUICCongestionControl)
+		}
+
 		quicListener, err := qtls.ListenEarly(udpConn, tlsConfig, &quic.Config{
-			MaxIncomingStreams: 1 << 60,
-			Allow0RTT:          true,
+			MaxIncomingStreams:   1 << 60,
+			Allow0RTT:            true,
+			GetCongestionControl: congestionControl,
 		})
 		if err != nil {
 			udpConn.Close()

+ 26 - 27
test/go.mod

@@ -10,9 +10,9 @@ require (
 	github.com/docker/docker v27.3.1+incompatible
 	github.com/docker/go-connections v0.5.0
 	github.com/gofrs/uuid/v5 v5.3.2
-	github.com/sagernet/quic-go v0.57.1-sing-box-mod.1
+	github.com/sagernet/quic-go v0.57.1-sing-box-mod.3
 	github.com/sagernet/sing v0.8.0-beta.6.0.20251207063731-56fd482ce1c6
-	github.com/sagernet/sing-quic v0.6.0-beta.5
+	github.com/sagernet/sing-quic v0.6.0-beta.5.0.20251218085114-6968f531a8c0
 	github.com/sagernet/sing-shadowsocks v0.2.8
 	github.com/sagernet/sing-shadowsocks2 v0.2.1
 	github.com/spyzhov/ajson v0.9.4
@@ -97,31 +97,30 @@ require (
 	github.com/safchain/ethtool v0.3.0 // indirect
 	github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a // indirect
 	github.com/sagernet/cors v1.2.1 // indirect
-	github.com/sagernet/cronet-go v0.0.1-140.0.7339.123-1 // indirect
-	github.com/sagernet/cronet-go/all v0.0.0-20251217073804-0aadbdd7485f // indirect
-	github.com/sagernet/cronet-go/lib/android_386 v0.0.0-20251217073321-98bf559282b1 // indirect
-	github.com/sagernet/cronet-go/lib/android_amd64 v0.0.0-20251217073321-98bf559282b1 // indirect
-	github.com/sagernet/cronet-go/lib/android_arm v0.0.0-20251217073321-98bf559282b1 // indirect
-	github.com/sagernet/cronet-go/lib/android_arm64 v0.0.0-20251217073321-98bf559282b1 // indirect
-	github.com/sagernet/cronet-go/lib/darwin_amd64 v0.0.0-20251217073321-98bf559282b1 // indirect
-	github.com/sagernet/cronet-go/lib/darwin_arm64 v0.0.0-20251217073321-98bf559282b1 // indirect
-	github.com/sagernet/cronet-go/lib/ios_amd64_simulator v0.0.0-20251217073321-98bf559282b1 // indirect
-	github.com/sagernet/cronet-go/lib/ios_arm64 v0.0.0-20251217073321-98bf559282b1 // indirect
-	github.com/sagernet/cronet-go/lib/ios_arm64_simulator v0.0.0-20251217073321-98bf559282b1 // indirect
-	github.com/sagernet/cronet-go/lib/linux_386 v0.0.0-20251217073321-98bf559282b1 // indirect
-	github.com/sagernet/cronet-go/lib/linux_386_musl v0.0.0-20251217073321-98bf559282b1 // indirect
-	github.com/sagernet/cronet-go/lib/linux_amd64 v0.0.0-20251217073321-98bf559282b1 // indirect
-	github.com/sagernet/cronet-go/lib/linux_amd64_musl v0.0.0-20251217073321-98bf559282b1 // indirect
-	github.com/sagernet/cronet-go/lib/linux_arm v0.0.0-20251217073321-98bf559282b1 // indirect
-	github.com/sagernet/cronet-go/lib/linux_arm64 v0.0.0-20251217073321-98bf559282b1 // indirect
-	github.com/sagernet/cronet-go/lib/linux_arm64_musl v0.0.0-20251217073321-98bf559282b1 // indirect
-	github.com/sagernet/cronet-go/lib/linux_arm_musl v0.0.0-20251217073321-98bf559282b1 // indirect
-	github.com/sagernet/cronet-go/lib/tvos_amd64_simulator v0.0.0-20251217073321-98bf559282b1 // indirect
-	github.com/sagernet/cronet-go/lib/tvos_arm64 v0.0.0-20251217073321-98bf559282b1 // indirect
-	github.com/sagernet/cronet-go/lib/tvos_arm64_simulator v0.0.0-20251217073321-98bf559282b1 // indirect
-	github.com/sagernet/cronet-go/lib/windows_386 v0.0.0-20251217073321-98bf559282b1 // indirect
-	github.com/sagernet/cronet-go/lib/windows_amd64 v0.0.0-20251217073321-98bf559282b1 // indirect
-	github.com/sagernet/cronet-go/lib/windows_arm64 v0.0.0-20251217073321-98bf559282b1 // indirect
+	github.com/sagernet/cronet-go v0.0.0-20251218041957-eeb28f1dba2f // indirect
+	github.com/sagernet/cronet-go/all v0.0.0-20251218041957-eeb28f1dba2f // indirect
+	github.com/sagernet/cronet-go/lib/android_386 v0.0.0-20251218041530-c2a431c5f1f7 // indirect
+	github.com/sagernet/cronet-go/lib/android_amd64 v0.0.0-20251218041530-c2a431c5f1f7 // indirect
+	github.com/sagernet/cronet-go/lib/android_arm v0.0.0-20251218041530-c2a431c5f1f7 // indirect
+	github.com/sagernet/cronet-go/lib/android_arm64 v0.0.0-20251218041530-c2a431c5f1f7 // indirect
+	github.com/sagernet/cronet-go/lib/darwin_amd64 v0.0.0-20251218041530-c2a431c5f1f7 // indirect
+	github.com/sagernet/cronet-go/lib/darwin_arm64 v0.0.0-20251218041530-c2a431c5f1f7 // indirect
+	github.com/sagernet/cronet-go/lib/ios_amd64_simulator v0.0.0-20251218041530-c2a431c5f1f7 // indirect
+	github.com/sagernet/cronet-go/lib/ios_arm64 v0.0.0-20251218041530-c2a431c5f1f7 // indirect
+	github.com/sagernet/cronet-go/lib/ios_arm64_simulator v0.0.0-20251218041530-c2a431c5f1f7 // indirect
+	github.com/sagernet/cronet-go/lib/linux_386 v0.0.0-20251218041530-c2a431c5f1f7 // indirect
+	github.com/sagernet/cronet-go/lib/linux_386_musl v0.0.0-20251218041530-c2a431c5f1f7 // indirect
+	github.com/sagernet/cronet-go/lib/linux_amd64 v0.0.0-20251218041530-c2a431c5f1f7 // indirect
+	github.com/sagernet/cronet-go/lib/linux_amd64_musl v0.0.0-20251218041530-c2a431c5f1f7 // indirect
+	github.com/sagernet/cronet-go/lib/linux_arm v0.0.0-20251218041530-c2a431c5f1f7 // indirect
+	github.com/sagernet/cronet-go/lib/linux_arm64 v0.0.0-20251218041530-c2a431c5f1f7 // indirect
+	github.com/sagernet/cronet-go/lib/linux_arm64_musl v0.0.0-20251218041530-c2a431c5f1f7 // indirect
+	github.com/sagernet/cronet-go/lib/linux_arm_musl v0.0.0-20251218041530-c2a431c5f1f7 // indirect
+	github.com/sagernet/cronet-go/lib/tvos_amd64_simulator v0.0.0-20251218041530-c2a431c5f1f7 // indirect
+	github.com/sagernet/cronet-go/lib/tvos_arm64 v0.0.0-20251218041530-c2a431c5f1f7 // indirect
+	github.com/sagernet/cronet-go/lib/tvos_arm64_simulator v0.0.0-20251218041530-c2a431c5f1f7 // indirect
+	github.com/sagernet/cronet-go/lib/windows_amd64 v0.0.0-20251218041530-c2a431c5f1f7 // indirect
+	github.com/sagernet/cronet-go/lib/windows_arm64 v0.0.0-20251218041530-c2a431c5f1f7 // indirect
 	github.com/sagernet/fswatch v0.1.1 // indirect
 	github.com/sagernet/gvisor v0.0.0-20250822052253-5558536cf237 // indirect
 	github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a // indirect

+ 52 - 54
test/go.sum

@@ -181,56 +181,54 @@ github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a h1:+NkI2670SQpQWvkk
 github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a/go.mod h1:63s7jpZqcDAIpj8oI/1v4Izok+npJOHACFCU6+huCkM=
 github.com/sagernet/cors v1.2.1 h1:Cv5Z8y9YSD6Gm+qSpNrL3LO4lD3eQVvbFYJSG7JCMHQ=
 github.com/sagernet/cors v1.2.1/go.mod h1:O64VyOjjhrkLmQIjF4KGRrJO/5dVXFdpEmCW/eISRAI=
-github.com/sagernet/cronet-go v0.0.1-140.0.7339.123-1 h1:ql2eCQp1sIinoSwNcJW+tBGToRoxm0rsU8uqRJA9Vao=
-github.com/sagernet/cronet-go v0.0.1-140.0.7339.123-1/go.mod h1:DzcRxPQdpy5y2bbabpFXotAzPfY2P4HKZ8rQj3dSClo=
-github.com/sagernet/cronet-go/all v0.0.0-20251217073804-0aadbdd7485f h1:eZcIuGEbGT9Ldh4QP14UxVzWOeMpwltU8lWCthefaGw=
-github.com/sagernet/cronet-go/all v0.0.0-20251217073804-0aadbdd7485f/go.mod h1:qt0I3+OORnNmYDKKg3sN2/JguaNNl3ckgdoYEMeMGSA=
-github.com/sagernet/cronet-go/lib/android_386 v0.0.0-20251217073321-98bf559282b1 h1:JPrpsOAMZL7WpRfRymdazS/LTguAJVTqTPgIM1hRGSk=
-github.com/sagernet/cronet-go/lib/android_386 v0.0.0-20251217073321-98bf559282b1/go.mod h1:XXDwdjX/T8xftoeJxQmbBoYXZp8MAPFR2CwbFuTpEtw=
-github.com/sagernet/cronet-go/lib/android_amd64 v0.0.0-20251217073321-98bf559282b1 h1:yKOa/aPDWyB8+Vw2bze3lczwA0T+Jp014F82bb04RZg=
-github.com/sagernet/cronet-go/lib/android_amd64 v0.0.0-20251217073321-98bf559282b1/go.mod h1:iNiUGoLtnr8/JTuVNj7XJbmpOAp2C6+B81KDrPxwaZM=
-github.com/sagernet/cronet-go/lib/android_arm v0.0.0-20251217073321-98bf559282b1 h1:bFWOKRv1gadjBtcCj5eSMVITdM/nFAM9WRvHGrFkW2M=
-github.com/sagernet/cronet-go/lib/android_arm v0.0.0-20251217073321-98bf559282b1/go.mod h1:19ILNUOGIzRdOqa2mq+iY0JoHxuieB7/lnjYeaA2vEc=
-github.com/sagernet/cronet-go/lib/android_arm64 v0.0.0-20251217073321-98bf559282b1 h1:rwk5kw6tggldlnYkufttjrLgNZ4m2oDj8VPVbUkMIj8=
-github.com/sagernet/cronet-go/lib/android_arm64 v0.0.0-20251217073321-98bf559282b1/go.mod h1:JxzGyQf94Cr6sBShKqODGDyRUlESfJK/Njcz9Lz6qMQ=
-github.com/sagernet/cronet-go/lib/darwin_amd64 v0.0.0-20251217073321-98bf559282b1 h1:Kz7898MkdKck/F3KhpQ3iSbDvuMcBKgcIT9kblbEAag=
-github.com/sagernet/cronet-go/lib/darwin_amd64 v0.0.0-20251217073321-98bf559282b1/go.mod h1:KN+9T9TBycGOLzmKU4QdcHAJEj6Nlx48ifnlTvvHMvs=
-github.com/sagernet/cronet-go/lib/darwin_arm64 v0.0.0-20251217073321-98bf559282b1 h1:Csm66Pf4aFnrKW9SQ7/QAD+ODxrXM1y/1tOsMeWJt2Q=
-github.com/sagernet/cronet-go/lib/darwin_arm64 v0.0.0-20251217073321-98bf559282b1/go.mod h1:kojvtUc29KKnk8hs2QIANynVR59921SnGWA9kXohHc0=
-github.com/sagernet/cronet-go/lib/ios_amd64_simulator v0.0.0-20251217073321-98bf559282b1 h1:xYt0vGrcBe5E/4S1AhZrXZKqzfyMVv2EJzms+hkyMwE=
-github.com/sagernet/cronet-go/lib/ios_amd64_simulator v0.0.0-20251217073321-98bf559282b1/go.mod h1:hkQzRE5GDbaH1/ioqYh0Taho4L6i0yLRCVEZ5xHz5M0=
-github.com/sagernet/cronet-go/lib/ios_arm64 v0.0.0-20251217073321-98bf559282b1 h1:HUIwo+G+gp5xJO7oFLXE8wUBuAMSlZCff7x8BkGwrV8=
-github.com/sagernet/cronet-go/lib/ios_arm64 v0.0.0-20251217073321-98bf559282b1/go.mod h1:tzVJFTOm66UxLxy6K0ZN5Ic2PC79e+sKKnt+V9puEa4=
-github.com/sagernet/cronet-go/lib/ios_arm64_simulator v0.0.0-20251217073321-98bf559282b1 h1:aM0ZlZyaMsj+ckqffWuwQ/LvlEocp4+8jf0CS3Y7C08=
-github.com/sagernet/cronet-go/lib/ios_arm64_simulator v0.0.0-20251217073321-98bf559282b1/go.mod h1:M/pN6m3j0HFU6/y83n0HU6GLYys3tYdr/xTE8hVEGMo=
-github.com/sagernet/cronet-go/lib/linux_386 v0.0.0-20251217073321-98bf559282b1 h1:vAFYo+d3JZauxyW2fL8Kqqzjx2CoMSNYwS3mj2O3vig=
-github.com/sagernet/cronet-go/lib/linux_386 v0.0.0-20251217073321-98bf559282b1/go.mod h1:cGh5hO6eljCo6KMQ/Cel8Xgq4+etL0awZLRBDVG1EZQ=
-github.com/sagernet/cronet-go/lib/linux_386_musl v0.0.0-20251217073321-98bf559282b1 h1:vitvkHM3isRtAt6J/hJbi1YEkkmoJQYxCWFyWBzetK0=
-github.com/sagernet/cronet-go/lib/linux_386_musl v0.0.0-20251217073321-98bf559282b1/go.mod h1:JFE0/cxaKkx0wqPMZU7MgaplQlU0zudv82dROJjClKU=
-github.com/sagernet/cronet-go/lib/linux_amd64 v0.0.0-20251217073321-98bf559282b1 h1:Y5OW7wtkGkAICo1c4TjsSVsRe0YY0rGXBZS3W4kWEMM=
-github.com/sagernet/cronet-go/lib/linux_amd64 v0.0.0-20251217073321-98bf559282b1/go.mod h1:vU8VftFeSt7fURCa3JXD6+k6ss1YAX+idQjPvHmJ2tI=
-github.com/sagernet/cronet-go/lib/linux_amd64_musl v0.0.0-20251217073321-98bf559282b1 h1:U4fj5bK6Bp/Fc3OaQT2+pXioRTC4NkWXD8M+kcJIXx0=
-github.com/sagernet/cronet-go/lib/linux_amd64_musl v0.0.0-20251217073321-98bf559282b1/go.mod h1:vCe4OUuL+XOUge9v3MyTD45BnuAXiH+DkjN9quDXJzQ=
-github.com/sagernet/cronet-go/lib/linux_arm v0.0.0-20251217073321-98bf559282b1 h1:6aMDLdA+GF0J6CPBAXh6yn8wCJHhmREIU8I/uCVl16w=
-github.com/sagernet/cronet-go/lib/linux_arm v0.0.0-20251217073321-98bf559282b1/go.mod h1:w9amBWrvjtohQzBGCKJ7LCh22LhTIJs4sE7cYaKQzM0=
-github.com/sagernet/cronet-go/lib/linux_arm64 v0.0.0-20251217073321-98bf559282b1 h1:OvZQkFRfs5fhN1ZNEjBRj1foZfwP9EdYhLFzrF23TO4=
-github.com/sagernet/cronet-go/lib/linux_arm64 v0.0.0-20251217073321-98bf559282b1/go.mod h1:TqlsFtcYS/etTeck46kHBeT8Le0Igw1Q/AV88UnMS3s=
-github.com/sagernet/cronet-go/lib/linux_arm64_musl v0.0.0-20251217073321-98bf559282b1 h1:HJYoVGlafnfo7qwsNgocIwqg/ScCWH3MwC7oqD4Hj3I=
-github.com/sagernet/cronet-go/lib/linux_arm64_musl v0.0.0-20251217073321-98bf559282b1/go.mod h1:B6Qd0vys8sv9OKVRN6J9RqDzYRGE938Fb2zrYdBDyTQ=
-github.com/sagernet/cronet-go/lib/linux_arm_musl v0.0.0-20251217073321-98bf559282b1 h1:U/eE0HxhS6iJxBhvt2mmkxvAuwjGQ6SfGz0IZc0NWQE=
-github.com/sagernet/cronet-go/lib/linux_arm_musl v0.0.0-20251217073321-98bf559282b1/go.mod h1:3tXMMFY7AHugOVBZ5Al7cL7JKsnFOe5bMVr0hZPk3ow=
-github.com/sagernet/cronet-go/lib/tvos_amd64_simulator v0.0.0-20251217073321-98bf559282b1 h1:V8mKJHu2iMoHjXH2deNQAY+Itcn9mlTeLDqhrFXkwcY=
-github.com/sagernet/cronet-go/lib/tvos_amd64_simulator v0.0.0-20251217073321-98bf559282b1/go.mod h1:aaX0YGl8nhGmfRWI8bc3BtDjY8Vzx6O0cS/e1uqxDq4=
-github.com/sagernet/cronet-go/lib/tvos_arm64 v0.0.0-20251217073321-98bf559282b1 h1:uHy+Un5hEvONSH5+nWHLWisvfhPIAE0EWq8cLjJpAuU=
-github.com/sagernet/cronet-go/lib/tvos_arm64 v0.0.0-20251217073321-98bf559282b1/go.mod h1:EdzMKA96xITc42QEI+ct4SwqX8Dn3ltKK8wzdkLWpSc=
-github.com/sagernet/cronet-go/lib/tvos_arm64_simulator v0.0.0-20251217073321-98bf559282b1 h1:IXNOyK596srcY+OtnrCrUdclKVL5lakKcO30H85Kryc=
-github.com/sagernet/cronet-go/lib/tvos_arm64_simulator v0.0.0-20251217073321-98bf559282b1/go.mod h1:qix4kv1TTAJ5tY4lJ9vjhe9EY4mM+B7H5giOhbxDVcc=
-github.com/sagernet/cronet-go/lib/windows_386 v0.0.0-20251217073321-98bf559282b1 h1:aPMCg3h46G8Mx5WIiYyPTr/1EQ8j4wgCI/HUPGm/occ=
-github.com/sagernet/cronet-go/lib/windows_386 v0.0.0-20251217073321-98bf559282b1/go.mod h1:rnS7D+ULJX2PrP0Cy+05GS0mRZ2PP6+gVSroZKt8fjk=
-github.com/sagernet/cronet-go/lib/windows_amd64 v0.0.0-20251217073321-98bf559282b1 h1:snfESeRYtwkOlfQyoxfHKVNj4N0cpIpxMfsM+y52rw4=
-github.com/sagernet/cronet-go/lib/windows_amd64 v0.0.0-20251217073321-98bf559282b1/go.mod h1:lm9w/oCCRyBiUa3G8lDQTT8x/ONUvgVR2iV9fVzUZB8=
-github.com/sagernet/cronet-go/lib/windows_arm64 v0.0.0-20251217073321-98bf559282b1 h1:weCViGxMO6iajrI1EjHH4hMT/cXwGc+HhXH24xUrVGE=
-github.com/sagernet/cronet-go/lib/windows_arm64 v0.0.0-20251217073321-98bf559282b1/go.mod h1:n34YyLgapgjWdKa0IoeczjAFCwD3/dxbsH5sucKw0bw=
+github.com/sagernet/cronet-go v0.0.0-20251218041957-eeb28f1dba2f h1:WTHyVtd9nNZ4VB20aja31e0ZXXGrVlssAanJJBMc5BU=
+github.com/sagernet/cronet-go v0.0.0-20251218041957-eeb28f1dba2f/go.mod h1:hwFHBEjjthyEquDULbr4c4ucMedp8Drb6Jvm2kt/0Bw=
+github.com/sagernet/cronet-go/all v0.0.0-20251218041957-eeb28f1dba2f h1:qupezSQEMraq2yajI4HrWf9h9rY7RESUYbYHRRd49FY=
+github.com/sagernet/cronet-go/all v0.0.0-20251218041957-eeb28f1dba2f/go.mod h1:onaFo5hJh1KsvuxkYTFLokh0Yx2oBh9J3yvFTnFB1Fc=
+github.com/sagernet/cronet-go/lib/android_386 v0.0.0-20251218041530-c2a431c5f1f7 h1:jmDdDxVFN/W+pX/QRHYR6jFu5gosRPNSSPemGmchHpM=
+github.com/sagernet/cronet-go/lib/android_386 v0.0.0-20251218041530-c2a431c5f1f7/go.mod h1:XXDwdjX/T8xftoeJxQmbBoYXZp8MAPFR2CwbFuTpEtw=
+github.com/sagernet/cronet-go/lib/android_amd64 v0.0.0-20251218041530-c2a431c5f1f7 h1:zQeDQJg2YZSlmR5+mYV4KyqIWwe+SH5hnxTO4EalDwA=
+github.com/sagernet/cronet-go/lib/android_amd64 v0.0.0-20251218041530-c2a431c5f1f7/go.mod h1:iNiUGoLtnr8/JTuVNj7XJbmpOAp2C6+B81KDrPxwaZM=
+github.com/sagernet/cronet-go/lib/android_arm v0.0.0-20251218041530-c2a431c5f1f7 h1:85ck9+7Ftj+J3RO1uusn1Y3EXRLX9Dy0WIK/ZjRlQok=
+github.com/sagernet/cronet-go/lib/android_arm v0.0.0-20251218041530-c2a431c5f1f7/go.mod h1:19ILNUOGIzRdOqa2mq+iY0JoHxuieB7/lnjYeaA2vEc=
+github.com/sagernet/cronet-go/lib/android_arm64 v0.0.0-20251218041530-c2a431c5f1f7 h1:D//nc8RxHp7tTKcIYYQZ80wQBwxlCJv6HpkrCkqIVRo=
+github.com/sagernet/cronet-go/lib/android_arm64 v0.0.0-20251218041530-c2a431c5f1f7/go.mod h1:JxzGyQf94Cr6sBShKqODGDyRUlESfJK/Njcz9Lz6qMQ=
+github.com/sagernet/cronet-go/lib/darwin_amd64 v0.0.0-20251218041530-c2a431c5f1f7 h1:wwrQCcrwnHSY/Y4cy8JCiZLzuWXM8tENphhJtFplh0c=
+github.com/sagernet/cronet-go/lib/darwin_amd64 v0.0.0-20251218041530-c2a431c5f1f7/go.mod h1:KN+9T9TBycGOLzmKU4QdcHAJEj6Nlx48ifnlTvvHMvs=
+github.com/sagernet/cronet-go/lib/darwin_arm64 v0.0.0-20251218041530-c2a431c5f1f7 h1:Q52ojQVXk9f6Z+EWHWv+SJajNF56bVvgMyQP/7WV2TI=
+github.com/sagernet/cronet-go/lib/darwin_arm64 v0.0.0-20251218041530-c2a431c5f1f7/go.mod h1:kojvtUc29KKnk8hs2QIANynVR59921SnGWA9kXohHc0=
+github.com/sagernet/cronet-go/lib/ios_amd64_simulator v0.0.0-20251218041530-c2a431c5f1f7 h1:UzXQ09sZQZDlsZvWd4SAhtaF0RMxAVg4TEYsRNMutjU=
+github.com/sagernet/cronet-go/lib/ios_amd64_simulator v0.0.0-20251218041530-c2a431c5f1f7/go.mod h1:hkQzRE5GDbaH1/ioqYh0Taho4L6i0yLRCVEZ5xHz5M0=
+github.com/sagernet/cronet-go/lib/ios_arm64 v0.0.0-20251218041530-c2a431c5f1f7 h1:sjSknfRi3fMJqwHW4pNL64SGq7Y5XIm4pz5Ds21hvKw=
+github.com/sagernet/cronet-go/lib/ios_arm64 v0.0.0-20251218041530-c2a431c5f1f7/go.mod h1:tzVJFTOm66UxLxy6K0ZN5Ic2PC79e+sKKnt+V9puEa4=
+github.com/sagernet/cronet-go/lib/ios_arm64_simulator v0.0.0-20251218041530-c2a431c5f1f7 h1:uxb8pqzB4KH7ai6MocOWQPu3/+BAYISSIMPHWs0wtrQ=
+github.com/sagernet/cronet-go/lib/ios_arm64_simulator v0.0.0-20251218041530-c2a431c5f1f7/go.mod h1:M/pN6m3j0HFU6/y83n0HU6GLYys3tYdr/xTE8hVEGMo=
+github.com/sagernet/cronet-go/lib/linux_386 v0.0.0-20251218041530-c2a431c5f1f7 h1:uV78fIQ2XdVQUzowiafKP2fs+rGlkI+9u7l1cBMlQlc=
+github.com/sagernet/cronet-go/lib/linux_386 v0.0.0-20251218041530-c2a431c5f1f7/go.mod h1:cGh5hO6eljCo6KMQ/Cel8Xgq4+etL0awZLRBDVG1EZQ=
+github.com/sagernet/cronet-go/lib/linux_386_musl v0.0.0-20251218041530-c2a431c5f1f7 h1:6d87Pvio5dpWakic3SNBVTwTlt8ZnvL1GWPPeY2xSLs=
+github.com/sagernet/cronet-go/lib/linux_386_musl v0.0.0-20251218041530-c2a431c5f1f7/go.mod h1:JFE0/cxaKkx0wqPMZU7MgaplQlU0zudv82dROJjClKU=
+github.com/sagernet/cronet-go/lib/linux_amd64 v0.0.0-20251218041530-c2a431c5f1f7 h1:tc3GdN9pAfZqdfb55DmtUSXEuKuecWNYSD/+4jclXmo=
+github.com/sagernet/cronet-go/lib/linux_amd64 v0.0.0-20251218041530-c2a431c5f1f7/go.mod h1:vU8VftFeSt7fURCa3JXD6+k6ss1YAX+idQjPvHmJ2tI=
+github.com/sagernet/cronet-go/lib/linux_amd64_musl v0.0.0-20251218041530-c2a431c5f1f7 h1:W5fN1B1wYgnh7Y5Nw+MgcDjsvdPvEPAGe27iemq2LJs=
+github.com/sagernet/cronet-go/lib/linux_amd64_musl v0.0.0-20251218041530-c2a431c5f1f7/go.mod h1:vCe4OUuL+XOUge9v3MyTD45BnuAXiH+DkjN9quDXJzQ=
+github.com/sagernet/cronet-go/lib/linux_arm v0.0.0-20251218041530-c2a431c5f1f7 h1:xfNH8CO8p2W8rtVFgyv8kiAkzoSArW6+h2s/p5ZNvP8=
+github.com/sagernet/cronet-go/lib/linux_arm v0.0.0-20251218041530-c2a431c5f1f7/go.mod h1:w9amBWrvjtohQzBGCKJ7LCh22LhTIJs4sE7cYaKQzM0=
+github.com/sagernet/cronet-go/lib/linux_arm64 v0.0.0-20251218041530-c2a431c5f1f7 h1:1mkhgxLOh1pPjBLgC/GK3Rhhinz0254OjGJRrivVhQ8=
+github.com/sagernet/cronet-go/lib/linux_arm64 v0.0.0-20251218041530-c2a431c5f1f7/go.mod h1:TqlsFtcYS/etTeck46kHBeT8Le0Igw1Q/AV88UnMS3s=
+github.com/sagernet/cronet-go/lib/linux_arm64_musl v0.0.0-20251218041530-c2a431c5f1f7 h1:zf252WwVhJYduTDBXvkBKdwSU+Ce0OToQzvy5SwPS3c=
+github.com/sagernet/cronet-go/lib/linux_arm64_musl v0.0.0-20251218041530-c2a431c5f1f7/go.mod h1:B6Qd0vys8sv9OKVRN6J9RqDzYRGE938Fb2zrYdBDyTQ=
+github.com/sagernet/cronet-go/lib/linux_arm_musl v0.0.0-20251218041530-c2a431c5f1f7 h1:Nhkn2M2UsGe0hr6qOgNKvGKgAbo6EfWQto+YjlNWGqg=
+github.com/sagernet/cronet-go/lib/linux_arm_musl v0.0.0-20251218041530-c2a431c5f1f7/go.mod h1:3tXMMFY7AHugOVBZ5Al7cL7JKsnFOe5bMVr0hZPk3ow=
+github.com/sagernet/cronet-go/lib/tvos_amd64_simulator v0.0.0-20251218041530-c2a431c5f1f7 h1:HSvWFyBDLC7grFuSwBSIaxLI/MVpe/w4qJJAWAZsBxc=
+github.com/sagernet/cronet-go/lib/tvos_amd64_simulator v0.0.0-20251218041530-c2a431c5f1f7/go.mod h1:aaX0YGl8nhGmfRWI8bc3BtDjY8Vzx6O0cS/e1uqxDq4=
+github.com/sagernet/cronet-go/lib/tvos_arm64 v0.0.0-20251218041530-c2a431c5f1f7 h1:PJa1fhmbXWXCYk07DZhqzjP2u9rM/cnS0A1aaPU56pY=
+github.com/sagernet/cronet-go/lib/tvos_arm64 v0.0.0-20251218041530-c2a431c5f1f7/go.mod h1:EdzMKA96xITc42QEI+ct4SwqX8Dn3ltKK8wzdkLWpSc=
+github.com/sagernet/cronet-go/lib/tvos_arm64_simulator v0.0.0-20251218041530-c2a431c5f1f7 h1:Tpskq8p8boYHkBya18ythhgWTMv8gFsseGk55MFW+/k=
+github.com/sagernet/cronet-go/lib/tvos_arm64_simulator v0.0.0-20251218041530-c2a431c5f1f7/go.mod h1:qix4kv1TTAJ5tY4lJ9vjhe9EY4mM+B7H5giOhbxDVcc=
+github.com/sagernet/cronet-go/lib/windows_amd64 v0.0.0-20251218041530-c2a431c5f1f7 h1:qjB64lzTP0ROuk9GCCwsNQ9ca37nIr75iOyc2vuGFQg=
+github.com/sagernet/cronet-go/lib/windows_amd64 v0.0.0-20251218041530-c2a431c5f1f7/go.mod h1:lm9w/oCCRyBiUa3G8lDQTT8x/ONUvgVR2iV9fVzUZB8=
+github.com/sagernet/cronet-go/lib/windows_arm64 v0.0.0-20251218041530-c2a431c5f1f7 h1:GDJjygR/HLWOzwAs0RjhvqN6d1rUm7WiDAmHNe8gRAM=
+github.com/sagernet/cronet-go/lib/windows_arm64 v0.0.0-20251218041530-c2a431c5f1f7/go.mod h1:n34YyLgapgjWdKa0IoeczjAFCwD3/dxbsH5sucKw0bw=
 github.com/sagernet/fswatch v0.1.1 h1:YqID+93B7VRfqIH3PArW/XpJv5H4OLEVWDfProGoRQs=
 github.com/sagernet/fswatch v0.1.1/go.mod h1:nz85laH0mkQqJfaOrqPpkwtU1znMFNVTpT/5oRsVz/o=
 github.com/sagernet/gvisor v0.0.0-20250822052253-5558536cf237 h1:SUPFNB+vSP4RBPrSEgNII+HkfqC8hKMpYLodom4o4EU=
@@ -239,15 +237,15 @@ github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a h1:ObwtHN2VpqE0ZN
 github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a/go.mod h1:xLnfdiJbSp8rNqYEdIW/6eDO4mVoogml14Bh2hSiFpM=
 github.com/sagernet/nftables v0.3.0-beta.4 h1:kbULlAwAC3jvdGAC1P5Fa3GSxVwQJibNenDW2zaXr8I=
 github.com/sagernet/nftables v0.3.0-beta.4/go.mod h1:OQXAjvjNGGFxaTgVCSTRIhYB5/llyVDeapVoENYBDS8=
-github.com/sagernet/quic-go v0.57.1-sing-box-mod.1 h1:6fhKbfA0b7L1CVekayV1g87uJFtMXFE0rFXR48SRrWI=
-github.com/sagernet/quic-go v0.57.1-sing-box-mod.1/go.mod h1:OqILvS182CyOol5zNNo6bguvOGgXzV459+chpRaUC+4=
+github.com/sagernet/quic-go v0.57.1-sing-box-mod.3 h1:Rah/tDukrowqlznHQgXD4E9/yEsVsEMIxBZzS2NorGc=
+github.com/sagernet/quic-go v0.57.1-sing-box-mod.3/go.mod h1:OqILvS182CyOol5zNNo6bguvOGgXzV459+chpRaUC+4=
 github.com/sagernet/sing v0.6.9/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak=
 github.com/sagernet/sing v0.8.0-beta.6.0.20251207063731-56fd482ce1c6 h1:EYaDzllFzNYnzQ9xH/ieSAXct4wQ8pD45kgNMo7RPZc=
 github.com/sagernet/sing v0.8.0-beta.6.0.20251207063731-56fd482ce1c6/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak=
 github.com/sagernet/sing-mux v0.3.3 h1:YFgt9plMWzH994BMZLmyKL37PdIVaIilwP0Jg+EcLfw=
 github.com/sagernet/sing-mux v0.3.3/go.mod h1:pht8iFY4c9Xltj7rhVd208npkNaeCxzyXCgulDPLUDA=
-github.com/sagernet/sing-quic v0.6.0-beta.5 h1:kZfRLmsPxAgl0usZUgomDurLn7ZZ26lJWIpGow9ZWR4=
-github.com/sagernet/sing-quic v0.6.0-beta.5/go.mod h1:9D9GANrK33NjWCe1VkU5L5+8MxU39WrduBSmHuHz8GA=
+github.com/sagernet/sing-quic v0.6.0-beta.5.0.20251218085114-6968f531a8c0 h1:YNXy008FFkVwfNjCR8GlVTlHbBXPwv8Y4ytDnSFUSDo=
+github.com/sagernet/sing-quic v0.6.0-beta.5.0.20251218085114-6968f531a8c0/go.mod h1:Y3YVjPutLHLQvYjGtUFH+w8YmM4MTd19NDzxLZGNGIs=
 github.com/sagernet/sing-shadowsocks v0.2.8 h1:PURj5PRoAkqeHh2ZW205RWzN9E9RtKCVCzByXruQWfE=
 github.com/sagernet/sing-shadowsocks v0.2.8/go.mod h1:lo7TWEMDcN5/h5B8S0ew+r78ZODn6SwVaFhvB6H+PTI=
 github.com/sagernet/sing-shadowsocks2 v0.2.1 h1:dWV9OXCeFPuYGHb6IRqlSptVnSzOelnqqs2gQ2/Qioo=

+ 193 - 1
test/naive_self_test.go

@@ -210,7 +210,6 @@ func TestNaiveSelfPublicKeySHA256(t *testing.T) {
 }
 
 func TestNaiveSelfECH(t *testing.T) {
-	t.Skip("TODO: ECH is not currently supported on naive outbound")
 	caPem, certPem, keyPem := createSelfSignedCertificate(t, "example.org")
 	caPemContent, err := os.ReadFile(caPem)
 	require.NoError(t, err)
@@ -440,3 +439,196 @@ func TestNaiveSelfInsecureConcurrency(t *testing.T) {
 	require.GreaterOrEqual(t, sessionCount, 3,
 		"Expected at least 3 HTTP/2 sessions with insecure_concurrency=3. NetLog: %s", netLogPath)
 }
+
+func TestNaiveSelfQUIC(t *testing.T) {
+	caPem, certPem, keyPem := createSelfSignedCertificate(t, "example.org")
+	caPemContent, err := os.ReadFile(caPem)
+	require.NoError(t, err)
+	startInstance(t, option.Options{
+		Inbounds: []option.Inbound{
+			{
+				Type: C.TypeMixed,
+				Tag:  "mixed-in",
+				Options: &option.HTTPMixedInboundOptions{
+					ListenOptions: option.ListenOptions{
+						Listen:     common.Ptr(badoption.Addr(netip.IPv4Unspecified())),
+						ListenPort: clientPort,
+					},
+				},
+			},
+			{
+				Type: C.TypeNaive,
+				Tag:  "naive-in",
+				Options: &option.NaiveInboundOptions{
+					ListenOptions: option.ListenOptions{
+						Listen:     common.Ptr(badoption.Addr(netip.IPv4Unspecified())),
+						ListenPort: serverPort,
+					},
+					Users: []auth.User{
+						{
+							Username: "sekai",
+							Password: "password",
+						},
+					},
+					Network: network.NetworkUDP,
+					InboundTLSOptionsContainer: option.InboundTLSOptionsContainer{
+						TLS: &option.InboundTLSOptions{
+							Enabled:         true,
+							ServerName:      "example.org",
+							CertificatePath: certPem,
+							KeyPath:         keyPem,
+						},
+					},
+				},
+			},
+		},
+		Outbounds: []option.Outbound{
+			{
+				Type: C.TypeDirect,
+			},
+			{
+				Type: C.TypeNaive,
+				Tag:  "naive-out",
+				Options: &option.NaiveOutboundOptions{
+					ServerOptions: option.ServerOptions{
+						Server:     "127.0.0.1",
+						ServerPort: serverPort,
+					},
+					Username: "sekai",
+					Password: "password",
+					QUIC:     true,
+					OutboundTLSOptionsContainer: option.OutboundTLSOptionsContainer{
+						TLS: &option.OutboundTLSOptions{
+							Enabled:     true,
+							ServerName:  "example.org",
+							Certificate: []string{string(caPemContent)},
+						},
+					},
+				},
+			},
+		},
+		Route: &option.RouteOptions{
+			Rules: []option.Rule{
+				{
+					Type: C.RuleTypeDefault,
+					DefaultOptions: option.DefaultRule{
+						RawDefaultRule: option.RawDefaultRule{
+							Inbound: []string{"mixed-in"},
+						},
+						RuleAction: option.RuleAction{
+							Action: C.RuleActionTypeRoute,
+							RouteOptions: option.RouteActionOptions{
+								Outbound: "naive-out",
+							},
+						},
+					},
+				},
+			},
+		},
+	})
+	testTCP(t, clientPort, testPort)
+}
+
+func TestNaiveSelfQUICCongestionControl(t *testing.T) {
+	testCases := []struct {
+		name              string
+		congestionControl string
+	}{
+		{"BBR", "bbr"},
+		{"BBR2", "bbr2"},
+		{"Cubic", "cubic"},
+		{"Reno", "reno"},
+	}
+	for _, tc := range testCases {
+		t.Run(tc.name, func(t *testing.T) {
+			caPem, certPem, keyPem := createSelfSignedCertificate(t, "example.org")
+			caPemContent, err := os.ReadFile(caPem)
+			require.NoError(t, err)
+			startInstance(t, option.Options{
+				Inbounds: []option.Inbound{
+					{
+						Type: C.TypeMixed,
+						Tag:  "mixed-in",
+						Options: &option.HTTPMixedInboundOptions{
+							ListenOptions: option.ListenOptions{
+								Listen:     common.Ptr(badoption.Addr(netip.IPv4Unspecified())),
+								ListenPort: clientPort,
+							},
+						},
+					},
+					{
+						Type: C.TypeNaive,
+						Tag:  "naive-in",
+						Options: &option.NaiveInboundOptions{
+							ListenOptions: option.ListenOptions{
+								Listen:     common.Ptr(badoption.Addr(netip.IPv4Unspecified())),
+								ListenPort: serverPort,
+							},
+							Users: []auth.User{
+								{
+									Username: "sekai",
+									Password: "password",
+								},
+							},
+							Network:               network.NetworkUDP,
+							QUICCongestionControl: tc.congestionControl,
+							InboundTLSOptionsContainer: option.InboundTLSOptionsContainer{
+								TLS: &option.InboundTLSOptions{
+									Enabled:         true,
+									ServerName:      "example.org",
+									CertificatePath: certPem,
+									KeyPath:         keyPem,
+								},
+							},
+						},
+					},
+				},
+				Outbounds: []option.Outbound{
+					{
+						Type: C.TypeDirect,
+					},
+					{
+						Type: C.TypeNaive,
+						Tag:  "naive-out",
+						Options: &option.NaiveOutboundOptions{
+							ServerOptions: option.ServerOptions{
+								Server:     "127.0.0.1",
+								ServerPort: serverPort,
+							},
+							Username:              "sekai",
+							Password:              "password",
+							QUIC:                  true,
+							QUICCongestionControl: tc.congestionControl,
+							OutboundTLSOptionsContainer: option.OutboundTLSOptionsContainer{
+								TLS: &option.OutboundTLSOptions{
+									Enabled:     true,
+									ServerName:  "example.org",
+									Certificate: []string{string(caPemContent)},
+								},
+							},
+						},
+					},
+				},
+				Route: &option.RouteOptions{
+					Rules: []option.Rule{
+						{
+							Type: C.RuleTypeDefault,
+							DefaultOptions: option.DefaultRule{
+								RawDefaultRule: option.RawDefaultRule{
+									Inbound: []string{"mixed-in"},
+								},
+								RuleAction: option.RuleAction{
+									Action: C.RuleActionTypeRoute,
+									RouteOptions: option.RouteActionOptions{
+										Outbound: "naive-out",
+									},
+								},
+							},
+						},
+					},
+				},
+			})
+			testTCP(t, clientPort, testPort)
+		})
+	}
+}