diff --git a/.github/CRONET_GO_VERSION b/.github/CRONET_GO_VERSION index ea51fa11c..1b43b2668 100644 --- a/.github/CRONET_GO_VERSION +++ b/.github/CRONET_GO_VERSION @@ -1 +1 @@ -617d38f41f935b46a68f550d9add2e38abb3f168 +cfbca3ad7edb3f8c1bd78b4bcb7c4c1a1ae3d195 diff --git a/clients/android b/clients/android index 124a7c130..6ddd91f2b 160000 --- a/clients/android +++ b/clients/android @@ -1 +1 @@ -Subproject commit 124a7c13038fcc389e3efbe61504fe6ab14724d9 +Subproject commit 6ddd91f2b3bc0367f2343de1e0467eec191b7470 diff --git a/clients/apple b/clients/apple index afb1ac6fd..6a74d3b29 160000 --- a/clients/apple +++ b/clients/apple @@ -1 +1 @@ -Subproject commit afb1ac6fd63aeb4660f39b21bde4a3f52cdee9fa +Subproject commit 6a74d3b29bcc1dfb92379c3bdf748ad8e8783524 diff --git a/docs/changelog.md b/docs/changelog.md index 2bbb58e31..33bec2916 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -2,6 +2,33 @@ icon: material/alert-decagram --- +#### 1.14.0-beta.5 + +* Remove client metadata from AnyTLS requests by default **1** +* Update naiveproxy to v150.0.7871.63-1 +* Fixes and improvements + +**1**: + +We found that the AnyTLS client implementation uploads metadata that is +**not used by the open-source server**, and there are reports of vendors using +it to profile and discriminate against users. We now leave it empty by default +and allow you to customize it, see +[AnyTLS client metadata](/manual/misc/anytls-client-metadata/). + +#### 1.13.16 + +* Remove client metadata from AnyTLS requests by default **1** +* Fixes and improvements + +**1**: + +We found that the AnyTLS client implementation uploads metadata that is +**not used by the open-source server**, and there are reports of vendors using +it to profile and discriminate against users. We now leave it empty by default +and allow you to customize it, see +[AnyTLS client metadata](/manual/misc/anytls-client-metadata/). + #### 1.14.0-beta.4 * Fixes and improvements diff --git a/docs/configuration/outbound/anytls.md b/docs/configuration/outbound/anytls.md index 4b3e03716..af324891c 100644 --- a/docs/configuration/outbound/anytls.md +++ b/docs/configuration/outbound/anytls.md @@ -17,6 +17,7 @@ icon: material/new-box "idle_session_check_interval": "30s", "idle_session_timeout": "30s", "min_idle_session": 5, + "client_metadata": "", "tls": {}, ... // Dial Fields @@ -55,6 +56,12 @@ In the check, close sessions that have been idle for longer than this. Default: In the check, at least the first `n` idle sessions are kept open. Default value: `n`=0 +#### client_metadata + +!!! question "Since sing-box 1.13.16" + +Check [AnyTLS client metadata](/manual/misc/anytls-client-metadata/). + #### tls ==Required== diff --git a/docs/configuration/outbound/anytls.zh.md b/docs/configuration/outbound/anytls.zh.md index c1f8999e7..c3f7abaa6 100644 --- a/docs/configuration/outbound/anytls.zh.md +++ b/docs/configuration/outbound/anytls.zh.md @@ -17,6 +17,7 @@ icon: material/new-box "idle_session_check_interval": "30s", "idle_session_timeout": "30s", "min_idle_session": 5, + "client_metadata": "", "tls": {}, ... // 拨号字段 @@ -55,6 +56,12 @@ AnyTLS 密码。 在检查中,至少前 `n` 个空闲会话保持打开状态。默认值:`n`=0 +#### client_metadata + +!!! question "自 sing-box 1.13.16 起" + +参阅 [AnyTLS 客户端元数据](/zh/manual/misc/anytls-client-metadata/)。 + #### tls ==必填== diff --git a/docs/manual/misc/anytls-client-metadata.md b/docs/manual/misc/anytls-client-metadata.md new file mode 100644 index 000000000..f1a80e001 --- /dev/null +++ b/docs/manual/misc/anytls-client-metadata.md @@ -0,0 +1,67 @@ +--- +icon: material/incognito +--- + +# AnyTLS client metadata + +The AnyTLS protocol has a design flaw: its settings frame requires the client +to send its software name and version to the server, and the protocol +specification requires that clients not disguise this information. + +This field serves no protocol purpose — AnyTLS already has a separate version +field for compatibility negotiation, and the open-source server implementation +does not use client metadata. However, the field allows vendors to collect and track client types, and for +platform-specific clients, potentially infer private information such as the operating system type and version range — +something that should not, and is not expected by users to, appear in an +anti-censorship protocol. We have received reports that +commercial proxy providers use this information to identify and block +connections from the official library provided by AnyTLS for sing-box +integration, reportedly because abusive users connect to their servers with +sing-box or with clients using the same official library. This indicates that +client metadata is being collected and used for discrimination in practice. + +The protocol specification states that "disguising it has no value." We +disagree: the situation is analogous to browsers implementing TLS ECH GREASE — +without it, privacy-protecting clients can be fingerprinted and treated +differently. + +## Status + +### 2025-02-20 + +We merged the +[pull request adding this protocol](https://github.com/SagerNet/sing-box/pull/2615). +Since the metadata was fixed at `sing-anytls/` in the +implementation provided for our use, and we did not carefully review the +protocol specification and other implementations, we wrongly believed that it +was not private information. + +### 2025-04-05 + +The protocol document +[added](https://github.com/anytls/anytls-go/commit/8812aae7ab29dd88bb89067b9ca676e2e7e29171) +the requirement that third-party implementations fill in the real software +name and version, claiming that "disguising it has no value". + +### 2026-07-18 + +A [pull request submitted to sing-box](https://github.com/SagerNet/sing-box/pull/4311) +was found to additionally upload the `sing-box` name and the actual version; +the change was subsequently reverted and was never released. + +### 2026-08-03 + +sing-box 1.13.16 and 1.14.0-beta.5 have been released; the client metadata in +AnyTLS requests is now empty by default. For compatibility, the +[client_metadata](/configuration/outbound/anytls/#client_metadata) outbound +option allows users to set a custom value. + +Since the open-source server implementation does not use this information and +it has no legitimate use, this is not considered a breaking change. + +## Recommendations + +We recommend that the AnyTLS protocol remove the client metadata, or replace +it with an option that is not sent by default and can be customized by the +user; and that other client implementations also take action, to jointly stop +statistics collection and discrimination based on client metadata. diff --git a/docs/manual/misc/anytls-client-metadata.zh.md b/docs/manual/misc/anytls-client-metadata.zh.md new file mode 100644 index 000000000..2251339c2 --- /dev/null +++ b/docs/manual/misc/anytls-client-metadata.zh.md @@ -0,0 +1,35 @@ +--- +icon: material/incognito +--- + +# AnyTLS 客户端元数据 + +AnyTLS 协议具有设计缺陷:其 settings 帧要求客户端向服务器发送软件名称和版本,且协议规范要求客户端不得伪装此信息。 + +此字段不承担协议功能——AnyTLS 已有独立的版本字段用于兼容性协商,且开源服务端实现不使用客户端元数据。然而,此字段使得供应商可以收集并统计客户端类型,对于某些平台特定的客户端,还可能推断出操作系统类型与版本范围等隐私信息,而这不应该,也不是被用户预期的,在一个反审查协议中出现。我们收到报告,有商业代理提供商利用此信息识别和阻止来自 sing-box 使用的、由 AnyTLS 提供的用于 sing-box 集成的官方代码库的连接,据传原因是恶意用户使用 sing-box 或使用相同官方代码库的客户端连接到服务器,这表明客户端元数据在实践中已被用于收集和区别对待。 + +协议规范称「伪装它没有任何意义」。我们不同意:这类似于浏览器实现 TLS ECH GREASE——如果没有这一机制,保护隐私的客户端会被识别并受到差别对待。 + +## 状态 + +### 2025-02-20 + +我们合并了[添加此协议的 PR](https://github.com/SagerNet/sing-box/pull/2615)。由于在供我们使用的实现中,metadata 被固定在 `sing-anytls/`,且我们没有仔细审查协议规范和其他实现,我们错误地认为这不是隐私信息。 + +### 2025-04-05 + +协议文档[加入](https://github.com/anytls/anytls-go/commit/8812aae7ab29dd88bb89067b9ca676e2e7e29171)了要求第三方实现填写真实软件名称与版本号的条款,并声称「伪装它没有任何意义」。 + +### 2026-07-18 + +[向 sing-box 提出的 PR](https://github.com/SagerNet/sing-box/pull/4311) 被发现额外上传了 `sing-box` 和实际版本的字符串,随后此更改被回退,没有发布。 + +### 2026-08-03 + +发布了 sing-box 1.13.16 和 1.14.0-beta.5,现在 AnyTLS 请求中的客户端元数据默认为空。出于兼容性考虑,[client_metadata](/zh/configuration/outbound/anytls/#client_metadata) 出站选项允许用户自定义此值。 + +由于开源服务端实现不使用此信息,且它没有合理用途,这不被视为破坏性更改。 + +## 建议 + +我们建议 AnyTLS 协议移除客户端元数据,或将其替换为非默认提供、且用户可以自定义的选项;并建议其他客户端实现也采取行动,共同阻止基于客户端元数据的统计和区别对待。 diff --git a/docs/schema.json b/docs/schema.json index 50c1cadfb..b3f5b2977 100644 --- a/docs/schema.json +++ b/docs/schema.json @@ -10805,6 +10805,9 @@ }, "min_idle_session": { "type": "integer" + }, + "client_metadata": { + "type": "string" } }, "required": [ diff --git a/go.mod b/go.mod index cf7ab9137..654b2da90 100644 --- a/go.mod +++ b/go.mod @@ -12,6 +12,7 @@ require ( github.com/creack/pty v1.1.24 github.com/cretz/bine v0.2.0 github.com/database64128/tfo-go/v2 v2.3.2 + github.com/dblohm7/wingoes v0.0.0-20240119213807-a09d6be7affa github.com/go-chi/chi/v5 v5.2.5 github.com/go-chi/render v1.0.3 github.com/godbus/dbus/v5 v5.2.2 @@ -34,8 +35,8 @@ 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-20260712143338-d22f2ea3630e - github.com/sagernet/cronet-go/all v0.0.0-20260712143338-d22f2ea3630e + github.com/sagernet/cronet-go v0.0.0-20260731162621-4185d471b2e4 + github.com/sagernet/cronet-go/all v0.0.0-20260731162621-4185d471b2e4 github.com/sagernet/fswatch v0.1.2 github.com/sagernet/gliderssh v0.3.4-0.20260531100337-2194faca5648 github.com/sagernet/gomobile v0.1.12 @@ -48,7 +49,7 @@ require ( github.com/sagernet/sing-mux v0.3.5 github.com/sagernet/sing-openconnect v0.0.0-20260722140139-e0c977659ca2 github.com/sagernet/sing-openvpn v0.0.0-20260729104525-103eb5fe5eb6 - github.com/sagernet/sing-quic v0.6.4-0.20260727030926-0b32a5074a40 + github.com/sagernet/sing-quic v0.6.4-0.20260803041931-6c84c468bea2 github.com/sagernet/sing-shadowsocks v0.2.8 github.com/sagernet/sing-shadowsocks2 v0.2.1 github.com/sagernet/sing-shadowtls v0.2.1 @@ -57,7 +58,7 @@ require ( github.com/sagernet/sing-usbip v0.0.0-20260616101517-efb91521eddb github.com/sagernet/sing-vmess v0.2.8-0.20250909125414-3aed155119a1 github.com/sagernet/smux v1.5.50-sing-box-mod.1 - github.com/sagernet/tailscale v1.92.4-sing-box-1.13-mod.7.0.20260717155615-b353b93d194a + github.com/sagernet/tailscale v1.92.4-sing-box-1.13-mod.8.0.20260803091221-867c1f0012d9 github.com/sagernet/wireguard-go v0.0.5-0.20260717024847-6f5e8b1947ae github.com/sagernet/ws v0.0.0-20231204124109-acfe8907c854 github.com/spf13/cobra v1.10.2 @@ -94,7 +95,6 @@ require ( github.com/coreos/go-oidc/v3 v3.17.0 // indirect github.com/database64128/netx-go v0.1.1 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/dblohm7/wingoes v0.0.0-20240119213807-a09d6be7affa // indirect github.com/dgrijalva/jwt-go/v4 v4.0.0-preview1 // indirect github.com/dgryski/go-camellia v0.0.0-20191119043421-69a8a13fb23d // indirect github.com/ebitengine/purego v0.10.0 // indirect @@ -138,35 +138,35 @@ 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-20260712142643-1e5048bd5587 // indirect - github.com/sagernet/cronet-go/lib/android_amd64 v0.0.0-20260712142643-1e5048bd5587 // indirect - github.com/sagernet/cronet-go/lib/android_arm v0.0.0-20260712142643-1e5048bd5587 // indirect - github.com/sagernet/cronet-go/lib/android_arm64 v0.0.0-20260712142643-1e5048bd5587 // indirect - github.com/sagernet/cronet-go/lib/darwin_amd64 v0.0.0-20260712142643-1e5048bd5587 // indirect - github.com/sagernet/cronet-go/lib/darwin_arm64 v0.0.0-20260712142643-1e5048bd5587 // indirect - github.com/sagernet/cronet-go/lib/ios_amd64_simulator v0.0.0-20260712142643-1e5048bd5587 // indirect - github.com/sagernet/cronet-go/lib/ios_arm64 v0.0.0-20260712142643-1e5048bd5587 // indirect - github.com/sagernet/cronet-go/lib/ios_arm64_simulator v0.0.0-20260712142643-1e5048bd5587 // indirect - github.com/sagernet/cronet-go/lib/linux_386 v0.0.0-20260712142643-1e5048bd5587 // indirect - github.com/sagernet/cronet-go/lib/linux_386_musl v0.0.0-20260712142643-1e5048bd5587 // indirect - github.com/sagernet/cronet-go/lib/linux_amd64 v0.0.0-20260712142643-1e5048bd5587 // indirect - github.com/sagernet/cronet-go/lib/linux_amd64_musl v0.0.0-20260712142643-1e5048bd5587 // indirect - github.com/sagernet/cronet-go/lib/linux_arm v0.0.0-20260712142643-1e5048bd5587 // indirect - github.com/sagernet/cronet-go/lib/linux_arm64 v0.0.0-20260712142643-1e5048bd5587 // indirect - github.com/sagernet/cronet-go/lib/linux_arm64_musl v0.0.0-20260712142643-1e5048bd5587 // indirect - github.com/sagernet/cronet-go/lib/linux_arm_musl v0.0.0-20260712142643-1e5048bd5587 // indirect - github.com/sagernet/cronet-go/lib/linux_loong64 v0.0.0-20260712142643-1e5048bd5587 // indirect - github.com/sagernet/cronet-go/lib/linux_loong64_musl v0.0.0-20260712142643-1e5048bd5587 // indirect - github.com/sagernet/cronet-go/lib/linux_mips64le v0.0.0-20260712142643-1e5048bd5587 // indirect - github.com/sagernet/cronet-go/lib/linux_mipsle v0.0.0-20260712142643-1e5048bd5587 // indirect - github.com/sagernet/cronet-go/lib/linux_mipsle_musl v0.0.0-20260712142643-1e5048bd5587 // indirect - github.com/sagernet/cronet-go/lib/linux_riscv64 v0.0.0-20260712142643-1e5048bd5587 // indirect - github.com/sagernet/cronet-go/lib/linux_riscv64_musl v0.0.0-20260712142643-1e5048bd5587 // indirect - github.com/sagernet/cronet-go/lib/tvos_amd64_simulator v0.0.0-20260712142643-1e5048bd5587 // indirect - github.com/sagernet/cronet-go/lib/tvos_arm64 v0.0.0-20260712142643-1e5048bd5587 // indirect - github.com/sagernet/cronet-go/lib/tvos_arm64_simulator v0.0.0-20260712142643-1e5048bd5587 // indirect - github.com/sagernet/cronet-go/lib/windows_amd64 v0.0.0-20260712142643-1e5048bd5587 // indirect - github.com/sagernet/cronet-go/lib/windows_arm64 v0.0.0-20260712142643-1e5048bd5587 // indirect + github.com/sagernet/cronet-go/lib/android_386 v0.0.0-20260731161755-38229fb700f6 // indirect + github.com/sagernet/cronet-go/lib/android_amd64 v0.0.0-20260731161755-38229fb700f6 // indirect + github.com/sagernet/cronet-go/lib/android_arm v0.0.0-20260731161755-38229fb700f6 // indirect + github.com/sagernet/cronet-go/lib/android_arm64 v0.0.0-20260731161755-38229fb700f6 // indirect + github.com/sagernet/cronet-go/lib/darwin_amd64 v0.0.0-20260731161755-38229fb700f6 // indirect + github.com/sagernet/cronet-go/lib/darwin_arm64 v0.0.0-20260731161755-38229fb700f6 // indirect + github.com/sagernet/cronet-go/lib/ios_amd64_simulator v0.0.0-20260731161755-38229fb700f6 // indirect + github.com/sagernet/cronet-go/lib/ios_arm64 v0.0.0-20260731161755-38229fb700f6 // indirect + github.com/sagernet/cronet-go/lib/ios_arm64_simulator v0.0.0-20260731161755-38229fb700f6 // indirect + github.com/sagernet/cronet-go/lib/linux_386 v0.0.0-20260731161755-38229fb700f6 // indirect + github.com/sagernet/cronet-go/lib/linux_386_musl v0.0.0-20260731161755-38229fb700f6 // indirect + github.com/sagernet/cronet-go/lib/linux_amd64 v0.0.0-20260731161755-38229fb700f6 // indirect + github.com/sagernet/cronet-go/lib/linux_amd64_musl v0.0.0-20260731161755-38229fb700f6 // indirect + github.com/sagernet/cronet-go/lib/linux_arm v0.0.0-20260731161755-38229fb700f6 // indirect + github.com/sagernet/cronet-go/lib/linux_arm64 v0.0.0-20260731161755-38229fb700f6 // indirect + github.com/sagernet/cronet-go/lib/linux_arm64_musl v0.0.0-20260731161755-38229fb700f6 // indirect + github.com/sagernet/cronet-go/lib/linux_arm_musl v0.0.0-20260731161755-38229fb700f6 // indirect + github.com/sagernet/cronet-go/lib/linux_loong64 v0.0.0-20260731161755-38229fb700f6 // indirect + github.com/sagernet/cronet-go/lib/linux_loong64_musl v0.0.0-20260731161755-38229fb700f6 // indirect + github.com/sagernet/cronet-go/lib/linux_mips64le v0.0.0-20260731161755-38229fb700f6 // indirect + github.com/sagernet/cronet-go/lib/linux_mipsle v0.0.0-20260731161755-38229fb700f6 // indirect + github.com/sagernet/cronet-go/lib/linux_mipsle_musl v0.0.0-20260731161755-38229fb700f6 // indirect + github.com/sagernet/cronet-go/lib/linux_riscv64 v0.0.0-20260731161755-38229fb700f6 // indirect + github.com/sagernet/cronet-go/lib/linux_riscv64_musl v0.0.0-20260731161755-38229fb700f6 // indirect + github.com/sagernet/cronet-go/lib/tvos_amd64_simulator v0.0.0-20260731161755-38229fb700f6 // indirect + github.com/sagernet/cronet-go/lib/tvos_arm64 v0.0.0-20260731161755-38229fb700f6 // indirect + github.com/sagernet/cronet-go/lib/tvos_arm64_simulator v0.0.0-20260731161755-38229fb700f6 // indirect + github.com/sagernet/cronet-go/lib/windows_amd64 v0.0.0-20260731161755-38229fb700f6 // indirect + github.com/sagernet/cronet-go/lib/windows_arm64 v0.0.0-20260731161755-38229fb700f6 // indirect github.com/smallstep/pkcs7 v0.1.1 // indirect github.com/spf13/pflag v1.0.9 // indirect github.com/tailscale/certstore v0.1.1-0.20231202035212-d3fa0460f47e // indirect diff --git a/go.sum b/go.sum index 00c5d9d96..0870c4398 100644 --- a/go.sum +++ b/go.sum @@ -235,68 +235,68 @@ 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-20260712143338-d22f2ea3630e h1:Y5mhsZrYuZ9jraIqg7hg1fw4zoVreae81fWvmozbCsQ= -github.com/sagernet/cronet-go v0.0.0-20260712143338-d22f2ea3630e/go.mod h1:T/mwtrpC4JlWfScw73CmSBvHzIvc7BatQ1MhRr+cYNw= -github.com/sagernet/cronet-go/all v0.0.0-20260712143338-d22f2ea3630e h1:rdNlS1dRSi7jQe/ingFf7QmV9ZCUZMbxAfHnBrdVW7g= -github.com/sagernet/cronet-go/all v0.0.0-20260712143338-d22f2ea3630e/go.mod h1:WNl4xfTNuR+f7SObmuBtrk0p4MhlmvuuiWYoty3U52E= -github.com/sagernet/cronet-go/lib/android_386 v0.0.0-20260712142643-1e5048bd5587 h1:ENmDXbGH92/jsMwhjIxK2a0URkA8ILC3npjqmTGj0Yc= -github.com/sagernet/cronet-go/lib/android_386 v0.0.0-20260712142643-1e5048bd5587/go.mod h1:XXDwdjX/T8xftoeJxQmbBoYXZp8MAPFR2CwbFuTpEtw= -github.com/sagernet/cronet-go/lib/android_amd64 v0.0.0-20260712142643-1e5048bd5587 h1:5xn/EZOO5LriSEih91thvTuR+gxb59jNxNQiB/KQPEc= -github.com/sagernet/cronet-go/lib/android_amd64 v0.0.0-20260712142643-1e5048bd5587/go.mod h1:iNiUGoLtnr8/JTuVNj7XJbmpOAp2C6+B81KDrPxwaZM= -github.com/sagernet/cronet-go/lib/android_arm v0.0.0-20260712142643-1e5048bd5587 h1:2/UN0LvWnAM0Sc9B/zE2qWylGrX2hQXhknyQyTlvz4k= -github.com/sagernet/cronet-go/lib/android_arm v0.0.0-20260712142643-1e5048bd5587/go.mod h1:19ILNUOGIzRdOqa2mq+iY0JoHxuieB7/lnjYeaA2vEc= -github.com/sagernet/cronet-go/lib/android_arm64 v0.0.0-20260712142643-1e5048bd5587 h1:SDULc9o0HkneJD38H1G+HRLby69zfdtyQk5qaKtn/tU= -github.com/sagernet/cronet-go/lib/android_arm64 v0.0.0-20260712142643-1e5048bd5587/go.mod h1:JxzGyQf94Cr6sBShKqODGDyRUlESfJK/Njcz9Lz6qMQ= -github.com/sagernet/cronet-go/lib/darwin_amd64 v0.0.0-20260712142643-1e5048bd5587 h1:hfcM9YccWN4O2LENHN16Jgm4g1/1PRouV0RmvvrS1f0= -github.com/sagernet/cronet-go/lib/darwin_amd64 v0.0.0-20260712142643-1e5048bd5587/go.mod h1:KN+9T9TBycGOLzmKU4QdcHAJEj6Nlx48ifnlTvvHMvs= -github.com/sagernet/cronet-go/lib/darwin_arm64 v0.0.0-20260712142643-1e5048bd5587 h1:arY9CL3C7lwJfG2Cdz2ZLvHLzT1wnzCVyAomNER6CrY= -github.com/sagernet/cronet-go/lib/darwin_arm64 v0.0.0-20260712142643-1e5048bd5587/go.mod h1:kojvtUc29KKnk8hs2QIANynVR59921SnGWA9kXohHc0= -github.com/sagernet/cronet-go/lib/ios_amd64_simulator v0.0.0-20260712142643-1e5048bd5587 h1:HrtCf6KPJsW9KJ4L4T8HMW1vx+3xefLRLObpjZEtzF4= -github.com/sagernet/cronet-go/lib/ios_amd64_simulator v0.0.0-20260712142643-1e5048bd5587/go.mod h1:hkQzRE5GDbaH1/ioqYh0Taho4L6i0yLRCVEZ5xHz5M0= -github.com/sagernet/cronet-go/lib/ios_arm64 v0.0.0-20260712142643-1e5048bd5587 h1:Inzzp4hyvcC0lawhndaK8iwEN0vGLDJLCThbaKZpksg= -github.com/sagernet/cronet-go/lib/ios_arm64 v0.0.0-20260712142643-1e5048bd5587/go.mod h1:tzVJFTOm66UxLxy6K0ZN5Ic2PC79e+sKKnt+V9puEa4= -github.com/sagernet/cronet-go/lib/ios_arm64_simulator v0.0.0-20260712142643-1e5048bd5587 h1:qN6vqr9nFnZqjZXhLez+7tMcbm3FMfhaJRWNMlK3SLI= -github.com/sagernet/cronet-go/lib/ios_arm64_simulator v0.0.0-20260712142643-1e5048bd5587/go.mod h1:M/pN6m3j0HFU6/y83n0HU6GLYys3tYdr/xTE8hVEGMo= -github.com/sagernet/cronet-go/lib/linux_386 v0.0.0-20260712142643-1e5048bd5587 h1:Zwzpw6555p3rWw844JxNZ+5iRqli6ZBOEtMH3qq1c7s= -github.com/sagernet/cronet-go/lib/linux_386 v0.0.0-20260712142643-1e5048bd5587/go.mod h1:cGh5hO6eljCo6KMQ/Cel8Xgq4+etL0awZLRBDVG1EZQ= -github.com/sagernet/cronet-go/lib/linux_386_musl v0.0.0-20260712142643-1e5048bd5587 h1:CwsGHfo1HwvEhA2Wnh3O8WxazN3d4Un44LXhiuIvA/w= -github.com/sagernet/cronet-go/lib/linux_386_musl v0.0.0-20260712142643-1e5048bd5587/go.mod h1:JFE0/cxaKkx0wqPMZU7MgaplQlU0zudv82dROJjClKU= -github.com/sagernet/cronet-go/lib/linux_amd64 v0.0.0-20260712142643-1e5048bd5587 h1:Pn6vsVFOJkj9q/XKBOZosfuDLB6luNMLkqq6YLUPXEk= -github.com/sagernet/cronet-go/lib/linux_amd64 v0.0.0-20260712142643-1e5048bd5587/go.mod h1:vU8VftFeSt7fURCa3JXD6+k6ss1YAX+idQjPvHmJ2tI= -github.com/sagernet/cronet-go/lib/linux_amd64_musl v0.0.0-20260712142643-1e5048bd5587 h1:vgRWcEr2jlgICj28XwDMXPQcy8mTob1ZcO+tPdiZjes= -github.com/sagernet/cronet-go/lib/linux_amd64_musl v0.0.0-20260712142643-1e5048bd5587/go.mod h1:vCe4OUuL+XOUge9v3MyTD45BnuAXiH+DkjN9quDXJzQ= -github.com/sagernet/cronet-go/lib/linux_arm v0.0.0-20260712142643-1e5048bd5587 h1:uiO62HvSAdRJR3d1Jc4duxWig3kkdwHBSQ3TmUFqw48= -github.com/sagernet/cronet-go/lib/linux_arm v0.0.0-20260712142643-1e5048bd5587/go.mod h1:w9amBWrvjtohQzBGCKJ7LCh22LhTIJs4sE7cYaKQzM0= -github.com/sagernet/cronet-go/lib/linux_arm64 v0.0.0-20260712142643-1e5048bd5587 h1:mXioRdq9h2YlIr9XGM51kXgIkToywwVfnGmJiaz/uzM= -github.com/sagernet/cronet-go/lib/linux_arm64 v0.0.0-20260712142643-1e5048bd5587/go.mod h1:TqlsFtcYS/etTeck46kHBeT8Le0Igw1Q/AV88UnMS3s= -github.com/sagernet/cronet-go/lib/linux_arm64_musl v0.0.0-20260712142643-1e5048bd5587 h1:oOlfOL+sq0KNZRsk06+5KgvtKw2TEXl2EZnLakTx+WM= -github.com/sagernet/cronet-go/lib/linux_arm64_musl v0.0.0-20260712142643-1e5048bd5587/go.mod h1:B6Qd0vys8sv9OKVRN6J9RqDzYRGE938Fb2zrYdBDyTQ= -github.com/sagernet/cronet-go/lib/linux_arm_musl v0.0.0-20260712142643-1e5048bd5587 h1:UDCa0lYiSUXD4wbxA/G5pGPSXhJaesCQCh5IEiZKb3M= -github.com/sagernet/cronet-go/lib/linux_arm_musl v0.0.0-20260712142643-1e5048bd5587/go.mod h1:3tXMMFY7AHugOVBZ5Al7cL7JKsnFOe5bMVr0hZPk3ow= -github.com/sagernet/cronet-go/lib/linux_loong64 v0.0.0-20260712142643-1e5048bd5587 h1:Yg2Ut7mPs0GK4W6p9LDh8RrDOnhTe4YpvG/WeJyUqMo= -github.com/sagernet/cronet-go/lib/linux_loong64 v0.0.0-20260712142643-1e5048bd5587/go.mod h1:Wt5uFdU3tnmm8YzobYewwdF7Mt6SucRQg6xeTNWC3Tk= -github.com/sagernet/cronet-go/lib/linux_loong64_musl v0.0.0-20260712142643-1e5048bd5587 h1:NtagC/YHvucD0Azh86aVghOk4z5f7oOAAy25Uw4knXQ= -github.com/sagernet/cronet-go/lib/linux_loong64_musl v0.0.0-20260712142643-1e5048bd5587/go.mod h1:lyIF6wKBLwWa5ZXaAKbAoewewl+yCHo2iYev39Mbj4E= -github.com/sagernet/cronet-go/lib/linux_mips64le v0.0.0-20260712142643-1e5048bd5587 h1:INzfLHBKjgJxoUDBeCaiB9hYqjhn5yfudkMz2phYypA= -github.com/sagernet/cronet-go/lib/linux_mips64le v0.0.0-20260712142643-1e5048bd5587/go.mod h1:H46PnSTTZNcZokLLiDeMDaHiS1l14PH3tzWi0eykjD8= -github.com/sagernet/cronet-go/lib/linux_mipsle v0.0.0-20260712142643-1e5048bd5587 h1:IX5NCEV9nojHdjpOkxKVN4L5FUuA5nwawXlSTdFXjCE= -github.com/sagernet/cronet-go/lib/linux_mipsle v0.0.0-20260712142643-1e5048bd5587/go.mod h1:RBhSUDAKWq7fswtV4nQUQhuaTLcX3ettR7teA7/yf2w= -github.com/sagernet/cronet-go/lib/linux_mipsle_musl v0.0.0-20260712142643-1e5048bd5587 h1:pzgA94sR7kvrP+H86/to2oN3efYORQmh0Q3b6AyfRJQ= -github.com/sagernet/cronet-go/lib/linux_mipsle_musl v0.0.0-20260712142643-1e5048bd5587/go.mod h1:wRzoIOGG4xbpp3Gh3triLKwMwYriScXzFtunLYhY4w0= -github.com/sagernet/cronet-go/lib/linux_riscv64 v0.0.0-20260712142643-1e5048bd5587 h1:nkS6jhF90E24PW37Xemhs6+hUM0l2iRcQcZFhPJL8R8= -github.com/sagernet/cronet-go/lib/linux_riscv64 v0.0.0-20260712142643-1e5048bd5587/go.mod h1:LNiZXmWil1OPwKCheqQjtakZlJuKGFz+iv2eGF76Hhs= -github.com/sagernet/cronet-go/lib/linux_riscv64_musl v0.0.0-20260712142643-1e5048bd5587 h1:EbydHlp6vWdqhb8e8zBPVJv/F3HPob+FgO6rsSdNSr0= -github.com/sagernet/cronet-go/lib/linux_riscv64_musl v0.0.0-20260712142643-1e5048bd5587/go.mod h1:YFDGKTkpkJGc5+hnX/RYosZyTWg9h+68VB55fYRRLYc= -github.com/sagernet/cronet-go/lib/tvos_amd64_simulator v0.0.0-20260712142643-1e5048bd5587 h1:sSfVTswgqQZJqh9wTP0Acvvo5/qYARAoHegRYwZ+gyU= -github.com/sagernet/cronet-go/lib/tvos_amd64_simulator v0.0.0-20260712142643-1e5048bd5587/go.mod h1:aaX0YGl8nhGmfRWI8bc3BtDjY8Vzx6O0cS/e1uqxDq4= -github.com/sagernet/cronet-go/lib/tvos_arm64 v0.0.0-20260712142643-1e5048bd5587 h1:lHqqbALbKdJdq/1rcI4yyg3zvibHDw7wmhDYVbjy498= -github.com/sagernet/cronet-go/lib/tvos_arm64 v0.0.0-20260712142643-1e5048bd5587/go.mod h1:EdzMKA96xITc42QEI+ct4SwqX8Dn3ltKK8wzdkLWpSc= -github.com/sagernet/cronet-go/lib/tvos_arm64_simulator v0.0.0-20260712142643-1e5048bd5587 h1:23GyWjb58Nk9a7WXgRfFUiTrMD9kvYSRHx73AaBthYc= -github.com/sagernet/cronet-go/lib/tvos_arm64_simulator v0.0.0-20260712142643-1e5048bd5587/go.mod h1:qix4kv1TTAJ5tY4lJ9vjhe9EY4mM+B7H5giOhbxDVcc= -github.com/sagernet/cronet-go/lib/windows_amd64 v0.0.0-20260712142643-1e5048bd5587 h1:64EMjgVuZMD4TX5b7oWUfWRVp8aVl3hg4aWrriQKOWo= -github.com/sagernet/cronet-go/lib/windows_amd64 v0.0.0-20260712142643-1e5048bd5587/go.mod h1:lm9w/oCCRyBiUa3G8lDQTT8x/ONUvgVR2iV9fVzUZB8= -github.com/sagernet/cronet-go/lib/windows_arm64 v0.0.0-20260712142643-1e5048bd5587 h1:x8cvgMQUs0EgVwt3iT/isRQ9KImvXvPobLKO5bHTN4o= -github.com/sagernet/cronet-go/lib/windows_arm64 v0.0.0-20260712142643-1e5048bd5587/go.mod h1:n34YyLgapgjWdKa0IoeczjAFCwD3/dxbsH5sucKw0bw= +github.com/sagernet/cronet-go v0.0.0-20260731162621-4185d471b2e4 h1:9MNI/CIuC1BRz97axSF7+3buSGdVe76KCwE6TEOa4V0= +github.com/sagernet/cronet-go v0.0.0-20260731162621-4185d471b2e4/go.mod h1:T/mwtrpC4JlWfScw73CmSBvHzIvc7BatQ1MhRr+cYNw= +github.com/sagernet/cronet-go/all v0.0.0-20260731162621-4185d471b2e4 h1:ZXwAlX2AudQNacvqRTkkCzwMd+smaoAzIA7xElom3dM= +github.com/sagernet/cronet-go/all v0.0.0-20260731162621-4185d471b2e4/go.mod h1:xHx1MCtgdQSs2IfyK9hKcFTkeCbmEONT/vG9/OHYI1Q= +github.com/sagernet/cronet-go/lib/android_386 v0.0.0-20260731161755-38229fb700f6 h1:ut1EGiVVwxCzL7v+5asRXU0LOzyH1UgW30pnrcQ6qgY= +github.com/sagernet/cronet-go/lib/android_386 v0.0.0-20260731161755-38229fb700f6/go.mod h1:XXDwdjX/T8xftoeJxQmbBoYXZp8MAPFR2CwbFuTpEtw= +github.com/sagernet/cronet-go/lib/android_amd64 v0.0.0-20260731161755-38229fb700f6 h1:MRxEREvsFyZSBPQ7Eho+kG7YheJoq8Fji1Q/vzPoeLY= +github.com/sagernet/cronet-go/lib/android_amd64 v0.0.0-20260731161755-38229fb700f6/go.mod h1:iNiUGoLtnr8/JTuVNj7XJbmpOAp2C6+B81KDrPxwaZM= +github.com/sagernet/cronet-go/lib/android_arm v0.0.0-20260731161755-38229fb700f6 h1:58vxu5bItotDkhiGp1/1ztkrSg74bI8cPhMN+AC8Nv0= +github.com/sagernet/cronet-go/lib/android_arm v0.0.0-20260731161755-38229fb700f6/go.mod h1:19ILNUOGIzRdOqa2mq+iY0JoHxuieB7/lnjYeaA2vEc= +github.com/sagernet/cronet-go/lib/android_arm64 v0.0.0-20260731161755-38229fb700f6 h1:q2u1YyJwKt6xGmdKU2whP71Z3VWxNaNQMLojvOISsuo= +github.com/sagernet/cronet-go/lib/android_arm64 v0.0.0-20260731161755-38229fb700f6/go.mod h1:JxzGyQf94Cr6sBShKqODGDyRUlESfJK/Njcz9Lz6qMQ= +github.com/sagernet/cronet-go/lib/darwin_amd64 v0.0.0-20260731161755-38229fb700f6 h1:nOnI/SDp530zR+bBoa5dJjd0noTeW0k2WVjpxJCfLs4= +github.com/sagernet/cronet-go/lib/darwin_amd64 v0.0.0-20260731161755-38229fb700f6/go.mod h1:KN+9T9TBycGOLzmKU4QdcHAJEj6Nlx48ifnlTvvHMvs= +github.com/sagernet/cronet-go/lib/darwin_arm64 v0.0.0-20260731161755-38229fb700f6 h1:YPhPwiloXsx2VeP+kGQAqlsRcspr5YmrNYr2RaMhjCA= +github.com/sagernet/cronet-go/lib/darwin_arm64 v0.0.0-20260731161755-38229fb700f6/go.mod h1:kojvtUc29KKnk8hs2QIANynVR59921SnGWA9kXohHc0= +github.com/sagernet/cronet-go/lib/ios_amd64_simulator v0.0.0-20260731161755-38229fb700f6 h1:+vHJWV4vp2KQmttlCouelvp6szzUj7Xr02mcvzvLuoo= +github.com/sagernet/cronet-go/lib/ios_amd64_simulator v0.0.0-20260731161755-38229fb700f6/go.mod h1:hkQzRE5GDbaH1/ioqYh0Taho4L6i0yLRCVEZ5xHz5M0= +github.com/sagernet/cronet-go/lib/ios_arm64 v0.0.0-20260731161755-38229fb700f6 h1:rbBK8FOiM9qAfLm5G6KasDK8N91wqar49MmdDwB+9MQ= +github.com/sagernet/cronet-go/lib/ios_arm64 v0.0.0-20260731161755-38229fb700f6/go.mod h1:tzVJFTOm66UxLxy6K0ZN5Ic2PC79e+sKKnt+V9puEa4= +github.com/sagernet/cronet-go/lib/ios_arm64_simulator v0.0.0-20260731161755-38229fb700f6 h1:y7YiSgFhsNRvmbjoJsUtsq11H9is88wyEFqyE/B1M60= +github.com/sagernet/cronet-go/lib/ios_arm64_simulator v0.0.0-20260731161755-38229fb700f6/go.mod h1:M/pN6m3j0HFU6/y83n0HU6GLYys3tYdr/xTE8hVEGMo= +github.com/sagernet/cronet-go/lib/linux_386 v0.0.0-20260731161755-38229fb700f6 h1:qmVetdcSKFd5a1CkvIvTrjyOTbddiI6MLX0XcPUtC64= +github.com/sagernet/cronet-go/lib/linux_386 v0.0.0-20260731161755-38229fb700f6/go.mod h1:cGh5hO6eljCo6KMQ/Cel8Xgq4+etL0awZLRBDVG1EZQ= +github.com/sagernet/cronet-go/lib/linux_386_musl v0.0.0-20260731161755-38229fb700f6 h1:OvwnwFgCpuPtTIKre6jl+Or3lxOqYkDpD6z/un6J4RQ= +github.com/sagernet/cronet-go/lib/linux_386_musl v0.0.0-20260731161755-38229fb700f6/go.mod h1:JFE0/cxaKkx0wqPMZU7MgaplQlU0zudv82dROJjClKU= +github.com/sagernet/cronet-go/lib/linux_amd64 v0.0.0-20260731161755-38229fb700f6 h1:s4IQzyVKOgmxKGa67VPkgGA0qRDjAsME0OtGjAwuQKw= +github.com/sagernet/cronet-go/lib/linux_amd64 v0.0.0-20260731161755-38229fb700f6/go.mod h1:vU8VftFeSt7fURCa3JXD6+k6ss1YAX+idQjPvHmJ2tI= +github.com/sagernet/cronet-go/lib/linux_amd64_musl v0.0.0-20260731161755-38229fb700f6 h1:7H8NqdLCR5qPd+LqjY8z/iWeBjKaqTI3xwOtjE4PDr0= +github.com/sagernet/cronet-go/lib/linux_amd64_musl v0.0.0-20260731161755-38229fb700f6/go.mod h1:vCe4OUuL+XOUge9v3MyTD45BnuAXiH+DkjN9quDXJzQ= +github.com/sagernet/cronet-go/lib/linux_arm v0.0.0-20260731161755-38229fb700f6 h1:gt1VZJcGPWclQgDTaA/TG/zfQQ9FgzalAGMJavPekmg= +github.com/sagernet/cronet-go/lib/linux_arm v0.0.0-20260731161755-38229fb700f6/go.mod h1:w9amBWrvjtohQzBGCKJ7LCh22LhTIJs4sE7cYaKQzM0= +github.com/sagernet/cronet-go/lib/linux_arm64 v0.0.0-20260731161755-38229fb700f6 h1:JABuN/xojoGL2cVZHulRprReTKCT7pVfZBCRM+tuGF0= +github.com/sagernet/cronet-go/lib/linux_arm64 v0.0.0-20260731161755-38229fb700f6/go.mod h1:TqlsFtcYS/etTeck46kHBeT8Le0Igw1Q/AV88UnMS3s= +github.com/sagernet/cronet-go/lib/linux_arm64_musl v0.0.0-20260731161755-38229fb700f6 h1:eyjPPvtKLF4aRBzwvc6y6SscJu9VSgdgCmOrsRr6xKg= +github.com/sagernet/cronet-go/lib/linux_arm64_musl v0.0.0-20260731161755-38229fb700f6/go.mod h1:B6Qd0vys8sv9OKVRN6J9RqDzYRGE938Fb2zrYdBDyTQ= +github.com/sagernet/cronet-go/lib/linux_arm_musl v0.0.0-20260731161755-38229fb700f6 h1:BDpXb1eJrCNw8jreh2s4Cky3DVRJtb2t41D2169DoB4= +github.com/sagernet/cronet-go/lib/linux_arm_musl v0.0.0-20260731161755-38229fb700f6/go.mod h1:3tXMMFY7AHugOVBZ5Al7cL7JKsnFOe5bMVr0hZPk3ow= +github.com/sagernet/cronet-go/lib/linux_loong64 v0.0.0-20260731161755-38229fb700f6 h1:QI8w+BHowQizqziE6wPzLYUgnUKExPF/qyyt0BlZqKs= +github.com/sagernet/cronet-go/lib/linux_loong64 v0.0.0-20260731161755-38229fb700f6/go.mod h1:Wt5uFdU3tnmm8YzobYewwdF7Mt6SucRQg6xeTNWC3Tk= +github.com/sagernet/cronet-go/lib/linux_loong64_musl v0.0.0-20260731161755-38229fb700f6 h1:46SA6S7a+S8a+G7h8j08+A9eT1QTeq3vEoGl3aBSKjI= +github.com/sagernet/cronet-go/lib/linux_loong64_musl v0.0.0-20260731161755-38229fb700f6/go.mod h1:lyIF6wKBLwWa5ZXaAKbAoewewl+yCHo2iYev39Mbj4E= +github.com/sagernet/cronet-go/lib/linux_mips64le v0.0.0-20260731161755-38229fb700f6 h1:STb5YWVmvoXeQqCXt7Of9C0+xWg6tLv2/I/xq+58Lh8= +github.com/sagernet/cronet-go/lib/linux_mips64le v0.0.0-20260731161755-38229fb700f6/go.mod h1:H46PnSTTZNcZokLLiDeMDaHiS1l14PH3tzWi0eykjD8= +github.com/sagernet/cronet-go/lib/linux_mipsle v0.0.0-20260731161755-38229fb700f6 h1:mdSq5zL3DH9fuK5nIqK10IR0b1/sUj5KKtjsrlLe7xE= +github.com/sagernet/cronet-go/lib/linux_mipsle v0.0.0-20260731161755-38229fb700f6/go.mod h1:RBhSUDAKWq7fswtV4nQUQhuaTLcX3ettR7teA7/yf2w= +github.com/sagernet/cronet-go/lib/linux_mipsle_musl v0.0.0-20260731161755-38229fb700f6 h1:+/zbKV5TizxsmHurjjNWemcEpUbH+RKxpI913rxQ6og= +github.com/sagernet/cronet-go/lib/linux_mipsle_musl v0.0.0-20260731161755-38229fb700f6/go.mod h1:wRzoIOGG4xbpp3Gh3triLKwMwYriScXzFtunLYhY4w0= +github.com/sagernet/cronet-go/lib/linux_riscv64 v0.0.0-20260731161755-38229fb700f6 h1:VNpOg++d6OX/Ju0CfGqvIlvuMPFIN/uqHbA66Linm7s= +github.com/sagernet/cronet-go/lib/linux_riscv64 v0.0.0-20260731161755-38229fb700f6/go.mod h1:LNiZXmWil1OPwKCheqQjtakZlJuKGFz+iv2eGF76Hhs= +github.com/sagernet/cronet-go/lib/linux_riscv64_musl v0.0.0-20260731161755-38229fb700f6 h1:0cvUlRaOPApPFcfs1UcdxXy+s80x33NbZEk+1h8mzWI= +github.com/sagernet/cronet-go/lib/linux_riscv64_musl v0.0.0-20260731161755-38229fb700f6/go.mod h1:YFDGKTkpkJGc5+hnX/RYosZyTWg9h+68VB55fYRRLYc= +github.com/sagernet/cronet-go/lib/tvos_amd64_simulator v0.0.0-20260731161755-38229fb700f6 h1:TBACLPNcCYtQ5eyb3a8GSJSnkLCaRaPrlGI/9RABDQk= +github.com/sagernet/cronet-go/lib/tvos_amd64_simulator v0.0.0-20260731161755-38229fb700f6/go.mod h1:aaX0YGl8nhGmfRWI8bc3BtDjY8Vzx6O0cS/e1uqxDq4= +github.com/sagernet/cronet-go/lib/tvos_arm64 v0.0.0-20260731161755-38229fb700f6 h1:L+1d0+rHFWvp86wv5Zj1MBgl0xjtBmJjD4UXS2A2wwc= +github.com/sagernet/cronet-go/lib/tvos_arm64 v0.0.0-20260731161755-38229fb700f6/go.mod h1:EdzMKA96xITc42QEI+ct4SwqX8Dn3ltKK8wzdkLWpSc= +github.com/sagernet/cronet-go/lib/tvos_arm64_simulator v0.0.0-20260731161755-38229fb700f6 h1:Ef1wUbrCMNSVYsUzm9dvKucO4ERpDoIWoME1aydlwpc= +github.com/sagernet/cronet-go/lib/tvos_arm64_simulator v0.0.0-20260731161755-38229fb700f6/go.mod h1:qix4kv1TTAJ5tY4lJ9vjhe9EY4mM+B7H5giOhbxDVcc= +github.com/sagernet/cronet-go/lib/windows_amd64 v0.0.0-20260731161755-38229fb700f6 h1:oohlo6PpKUO1m7UPrqLH35k2oX9sVE7Zyeo71UF6hiw= +github.com/sagernet/cronet-go/lib/windows_amd64 v0.0.0-20260731161755-38229fb700f6/go.mod h1:lm9w/oCCRyBiUa3G8lDQTT8x/ONUvgVR2iV9fVzUZB8= +github.com/sagernet/cronet-go/lib/windows_arm64 v0.0.0-20260731161755-38229fb700f6 h1:gIiryH0Enkb2jqxcXYcEKAKUzNhwOZJwIMNc+3eKafI= +github.com/sagernet/cronet-go/lib/windows_arm64 v0.0.0-20260731161755-38229fb700f6/go.mod h1:n34YyLgapgjWdKa0IoeczjAFCwD3/dxbsH5sucKw0bw= github.com/sagernet/fswatch v0.1.2 h1:/TT7k4mkce1qFPxamLO842WjqBgbTBiXP2mlUjp9PFk= github.com/sagernet/fswatch v0.1.2/go.mod h1:5BpGmpUQVd3Mc5r313HRpvADHRg3/rKn5QbwFteB880= github.com/sagernet/gliderssh v0.3.4-0.20260531100337-2194faca5648 h1:IWVjKBARzVjdmH0VUaeTBOBli1qkwKmTG4XfbkpSS20= @@ -321,8 +321,8 @@ github.com/sagernet/sing-openconnect v0.0.0-20260722140139-e0c977659ca2 h1:IOzb7 github.com/sagernet/sing-openconnect v0.0.0-20260722140139-e0c977659ca2/go.mod h1:4AKZLVcvY3r54UaK2Gbnm7aN8pOwdLz+y4EP0QFZ5Eg= github.com/sagernet/sing-openvpn v0.0.0-20260729104525-103eb5fe5eb6 h1:ZAvhkor0prJ8KEX9EmTEH+gJ1WlA3ffjS8GZT6KKq9c= github.com/sagernet/sing-openvpn v0.0.0-20260729104525-103eb5fe5eb6/go.mod h1:PWX7WygD8jpwfqfaGNySXpJYTn0SOwjBI1BKHHC2+Bw= -github.com/sagernet/sing-quic v0.6.4-0.20260727030926-0b32a5074a40 h1:HSc3AkQYFsxafCSuq3+Jdg7UZc3cPG6JVm7VPyOjn0o= -github.com/sagernet/sing-quic v0.6.4-0.20260727030926-0b32a5074a40/go.mod h1:9k+dzGsWMttUGldBzq3dU792YHXzW6NgfbOGltnXq+0= +github.com/sagernet/sing-quic v0.6.4-0.20260803041931-6c84c468bea2 h1:XhJro6+Ou+WOPjfs22m14lY7Sh6sWPm/f0QiyFUgM60= +github.com/sagernet/sing-quic v0.6.4-0.20260803041931-6c84c468bea2/go.mod h1:9k+dzGsWMttUGldBzq3dU792YHXzW6NgfbOGltnXq+0= 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= @@ -339,8 +339,8 @@ github.com/sagernet/sing-vmess v0.2.8-0.20250909125414-3aed155119a1 h1:aSwUNYUkV github.com/sagernet/sing-vmess v0.2.8-0.20250909125414-3aed155119a1/go.mod h1:P11scgTxMxVVQ8dlM27yNm3Cro40mD0+gHbnqrNGDuY= github.com/sagernet/smux v1.5.50-sing-box-mod.1 h1:XkJcivBC9V4wBjiGXIXZ229aZCU1hzcbp6kSkkyQ478= github.com/sagernet/smux v1.5.50-sing-box-mod.1/go.mod h1:NjhsCEWedJm7eFLyhuBgIEzwfhRmytrUoiLluxs5Sk8= -github.com/sagernet/tailscale v1.92.4-sing-box-1.13-mod.7.0.20260717155615-b353b93d194a h1:mORXldIuzgU8Bk6n9KpOmLv1rV7Ta8us+lZ9JSv2eBw= -github.com/sagernet/tailscale v1.92.4-sing-box-1.13-mod.7.0.20260717155615-b353b93d194a/go.mod h1:p8Ms8FbGlwQJyHb862XmdShTS50fFJ8C71VdO6xvWyk= +github.com/sagernet/tailscale v1.92.4-sing-box-1.13-mod.8.0.20260803091221-867c1f0012d9 h1:ZfS2GktRvRMszD6DtGrvHHz4pZi49+DkyIeMEdWfjHk= +github.com/sagernet/tailscale v1.92.4-sing-box-1.13-mod.8.0.20260803091221-867c1f0012d9/go.mod h1:p8Ms8FbGlwQJyHb862XmdShTS50fFJ8C71VdO6xvWyk= github.com/sagernet/wireguard-go v0.0.5-0.20260717024847-6f5e8b1947ae h1:GmxlXWnRmeNfPE1tWXRZIFgKJd5BH5okoDHKZkkI5bw= github.com/sagernet/wireguard-go v0.0.5-0.20260717024847-6f5e8b1947ae/go.mod h1:hEqi4y5czEg6LYtX2Bpjg+lV0b/J1n+5rA885Z66Mx0= github.com/sagernet/ws v0.0.0-20231204124109-acfe8907c854 h1:6uUiZcDRnZSAegryaUGwPC/Fj13JSHwiTftrXhMmYOc= diff --git a/mkdocs.yml b/mkdocs.yml index 028e569c7..97fb276b6 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -78,6 +78,7 @@ nav: - Hysteria 2: manual/proxy-protocol/hysteria2.md - Misc: - TunnelVision: manual/misc/tunnelvision.md + - AnyTLS client metadata: manual/misc/anytls-client-metadata.md - Configuration: - configuration/index.md - JSON Schema: configuration/schema.md diff --git a/option/anytls.go b/option/anytls.go index 0f7852632..24efbfc6c 100644 --- a/option/anytls.go +++ b/option/anytls.go @@ -22,4 +22,5 @@ type AnyTLSOutboundOptions struct { IdleSessionCheckInterval badoption.Duration `json:"idle_session_check_interval,omitempty"` IdleSessionTimeout badoption.Duration `json:"idle_session_timeout,omitempty"` MinIdleSession int `json:"min_idle_session,omitempty"` + ClientMetadata string `json:"client_metadata,omitempty"` } diff --git a/protocol/anytls/client_metadata.go b/protocol/anytls/client_metadata.go new file mode 100644 index 000000000..09e21195d --- /dev/null +++ b/protocol/anytls/client_metadata.go @@ -0,0 +1,64 @@ +package anytls + +import ( + "encoding/binary" + "net" + "reflect" + "strings" + "sync" + "unsafe" + + "github.com/sagernet/sing/common" + + anytls "github.com/anytls/sing-anytls" + "github.com/anytls/sing-anytls/session" +) + +const ( + commandSettings = 4 + frameHeaderSize = 7 +) + +var ( + clientSessionField, _ = reflect.TypeFor[anytls.Client]().FieldByName("sessionClient") + streamSessionField, _ = reflect.TypeFor[session.Stream]().FieldByName("sess") + sessionConnLockField, _ = reflect.TypeFor[session.Session]().FieldByName("connLock") + sessionBufferField, _ = reflect.TypeFor[session.Session]().FieldByName("buffer") +) + +func sessionClientOf(client *anytls.Client) *session.Client { + return *(**session.Client)(unsafe.Add(unsafe.Pointer(client), clientSessionField.Offset)) +} + +func (h *Outbound) rewriteClientMetadata(conn net.Conn) { + sess := *(**session.Session)(unsafe.Add(unsafe.Pointer(conn.(*session.Stream)), streamSessionField.Offset)) + connLock := (*sync.Mutex)(unsafe.Add(unsafe.Pointer(sess), sessionConnLockField.Offset)) + bufferPointer := (*[]byte)(unsafe.Add(unsafe.Pointer(sess), sessionBufferField.Offset)) + connLock.Lock() + defer connLock.Unlock() + buffer := *bufferPointer + offset := 0 + for offset+frameHeaderSize <= len(buffer) { + dataLength := int(binary.BigEndian.Uint16(buffer[offset+5 : offset+7])) + frameEnd := offset + frameHeaderSize + dataLength + if frameEnd > len(buffer) { + return + } + if buffer[offset] == commandSettings { + data := []byte(strings.Join(common.Map(strings.Split(string(buffer[offset+frameHeaderSize:frameEnd]), "\n"), func(line string) string { + if strings.HasPrefix(line, "client=") { + return "client=" + h.clientMetadata + } + return line + }), "\n")) + newBuffer := make([]byte, 0, offset+frameHeaderSize+len(data)+len(buffer)-frameEnd) + newBuffer = append(newBuffer, buffer[:offset+5]...) + newBuffer = binary.BigEndian.AppendUint16(newBuffer, uint16(len(data))) + newBuffer = append(newBuffer, data...) + newBuffer = append(newBuffer, buffer[frameEnd:]...) + *bufferPointer = newBuffer + return + } + offset = frameEnd + } +} diff --git a/protocol/anytls/outbound.go b/protocol/anytls/outbound.go index 92fbbecd7..3d50b6416 100644 --- a/protocol/anytls/outbound.go +++ b/protocol/anytls/outbound.go @@ -19,22 +19,27 @@ import ( "github.com/sagernet/sing/common/uot" anytls "github.com/anytls/sing-anytls" + "github.com/anytls/sing-anytls/session" ) func RegisterOutbound(registry *outbound.Registry) { outbound.Register[option.AnyTLSOutboundOptions](registry, C.TypeAnyTLS, NewOutbound) } +var _ adapter.OutboundWithMultiplex = (*Outbound)(nil) + type Outbound struct { outbound.Adapter - ctx context.Context - dialer tls.Dialer - server M.Socksaddr - tlsConfig tls.Config - clientOptions anytls.ClientConfig - client *anytls.Client - uotClient *uot.Client - logger log.ContextLogger + ctx context.Context + dialer tls.Dialer + server M.Socksaddr + tlsConfig tls.Config + clientOptions anytls.ClientConfig + clientMetadata string + client *anytls.Client + sessionClient *session.Client + uotClient *uot.Client + logger log.ContextLogger } func NewOutbound(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.AnyTLSOutboundOptions) (adapter.Outbound, error) { @@ -80,6 +85,7 @@ func NewOutbound(ctx context.Context, router adapter.Router, logger log.ContextL DialOut: outbound.dialOut, Logger: logger, } + outbound.clientMetadata = options.ClientMetadata return outbound, nil } @@ -92,13 +98,28 @@ func (h *Outbound) Start(stage adapter.StartStage) error { return err } h.client = client + h.sessionClient = sessionClientOf(client) h.uotClient = &uot.Client{ - Dialer: (anytlsDialer)(client.CreateProxy), + Dialer: (anytlsDialer)(h.createProxy), Version: uot.Version, } return nil } +func (h *Outbound) createProxy(ctx context.Context, destination M.Socksaddr) (net.Conn, error) { + conn, err := h.sessionClient.CreateStream(ctx) + if err != nil { + return nil, err + } + h.rewriteClientMetadata(conn) + err = M.SocksaddrSerializer.WriteAddrPort(conn, destination) + if err != nil { + conn.Close() + return nil, err + } + return conn, nil +} + type anytlsDialer func(ctx context.Context, destination M.Socksaddr) (net.Conn, error) func (d anytlsDialer) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) { @@ -113,6 +134,10 @@ func (h *Outbound) dialOut(ctx context.Context) (net.Conn, error) { return h.dialer.DialTLSContext(ctx, h.server) } +func (h *Outbound) MultiplexEnabled() bool { + return true +} + func (h *Outbound) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) { ctx, metadata := adapter.ExtendContext(ctx) metadata.Outbound = h.Tag() @@ -120,7 +145,7 @@ func (h *Outbound) DialContext(ctx context.Context, network string, destination switch N.NetworkName(network) { case N.NetworkTCP: h.logger.InfoContext(ctx, "outbound connection to ", destination) - return h.client.CreateProxy(ctx, destination) + return h.createProxy(ctx, destination) case N.NetworkUDP: h.logger.InfoContext(ctx, "outbound UoT packet connection to ", destination) return h.uotClient.DialContext(ctx, network, destination) diff --git a/protocol/tailscale/endpoint.go b/protocol/tailscale/endpoint.go index c2d5ea564..af5bc425a 100644 --- a/protocol/tailscale/endpoint.go +++ b/protocol/tailscale/endpoint.go @@ -9,7 +9,6 @@ import ( "net" "net/http" "net/netip" - "net/url" "os" "path/filepath" "reflect" @@ -101,6 +100,7 @@ type Endpoint struct { sshReconfigHook wgengine.ReconfigListener cfg *wgcfg.Config + routerCfg *router.Config dnsCfg *tsDNS.Config routeDomains common.TypedValue[map[string]bool] routePrefixes atomic.Pointer[netipx.IPSet] @@ -171,21 +171,10 @@ func NewEndpoint(ctx context.Context, router adapter.Router, logger log.ContextL } else { udpTimeout = C.UDPTimeout } - var remoteIsDomain bool - if options.ControlURL != "" { - controlURL, err := url.Parse(options.ControlURL) - if err != nil { - return nil, E.Cause(err, "parse control URL") - } - remoteIsDomain = M.ParseSocksaddr(controlURL.Hostname()).IsDomain() - } else { - // controlplane.tailscale.com - remoteIsDomain = true - } outboundDialer, err := dialer.NewWithOptions(dialer.Options{ Context: ctx, Options: options.DialerOptions, - RemoteIsDomain: remoteIsDomain, + RemoteIsDomain: true, ResolverOnDetour: true, NewDialer: true, }) @@ -919,10 +908,13 @@ func (t *Endpoint) onReconfig(cfg *wgcfg.Config, routerCfg *router.Config, dnsCf if cfg == nil || dnsCfg == nil { return } - if (t.cfg != nil && reflect.DeepEqual(t.cfg, cfg)) && (t.dnsCfg != nil && reflect.DeepEqual(t.dnsCfg, dnsCfg)) { + if t.cfg != nil && reflect.DeepEqual(t.cfg, cfg) && + t.routerCfg != nil && reflect.DeepEqual(t.routerCfg, routerCfg) && + t.dnsCfg != nil && reflect.DeepEqual(t.dnsCfg, dnsCfg) { return } t.cfg = cfg + t.routerCfg = routerCfg t.dnsCfg = dnsCfg routeDomains := make(map[string]bool) diff --git a/protocol/tailscale/tun_device_windows.go b/protocol/tailscale/tun_device_windows.go index 8c9e87cee..37f813cb1 100644 --- a/protocol/tailscale/tun_device_windows.go +++ b/protocol/tailscale/tun_device_windows.go @@ -11,6 +11,9 @@ import ( singTun "github.com/sagernet/sing-tun" "github.com/sagernet/sing/common/logger" wgTun "github.com/sagernet/wireguard-go/tun" + + "github.com/dblohm7/wingoes/com" + "golang.org/x/sys/windows/svc" ) type tunDeviceAdapter struct { @@ -21,7 +24,23 @@ type tunDeviceAdapter struct { closeOnce sync.Once } -func newTunDeviceAdapter(tun singTun.Tun, mtu int, _ logger.ContextLogger) (wgTun.Device, error) { +var comRuntimeOnce sync.Once + +func newTunDeviceAdapter(tun singTun.Tun, mtu int, contextLogger logger.ContextLogger) (wgTun.Device, error) { + // wgengine/router/osrouter/ifconfig_windows.go setPrivateNetwork assumes COM + // is initialized process-wide, which upstream performs only in tailscaled's + // main package; library consumers must do it themselves. + comRuntimeOnce.Do(func() { + processType := com.ConsoleApp + isService, serviceErr := svc.IsWindowsService() + if serviceErr == nil && isService { + processType = com.Service + } + err := com.StartRuntime(processType) + if err != nil { + contextLogger.Warn("initialize COM runtime: ", err) + } + }) winTun, ok := tun.(singTun.WinTun) if !ok { return nil, errors.New("not a windows tun device")