diff --git a/docs/configuration/outbound/hysteria2.md b/docs/configuration/outbound/hysteria2.md index a0274937..70c3c277 100644 --- a/docs/configuration/outbound/hysteria2.md +++ b/docs/configuration/outbound/hysteria2.md @@ -2,6 +2,7 @@ :material-plus: [hop_interval_max](#hop_interval_max) :material-plus: [bbr_profile](#bbr_profile) + :material-plus: [disable_chrome_parrot](#disable_chrome_parrot) :material-plus: [realm](#realm) :material-alert: [obfs](#obfstype) @@ -38,6 +39,7 @@ "bbr_profile": "", "brutal_debug": false, + "disable_chrome_parrot": false, "realm": { "server_url": "https://realm.example.com", "token": "", @@ -178,6 +180,25 @@ BBR congestion control algorithm profile, one of `conservative` `standard` `aggr Enable debug information logging for Hysteria Brutal CC. +#### disable_chrome_parrot + +!!! question "Since sing-box 1.14.0" + +Disable Chrome QUIC fingerprint parroting. + +If it is not disabled, the client's QUIC handshake is made to parrot Chrome's, so that Hysteria traffic +is harder to identify by handshake fingerprinting. + +To match Chrome, the client uses Chrome's own QUIC parameters, which override some settings: +`idle_timeout` is fixed at 30 seconds, `max_concurrent_streams` and `initial_packet_size` are replaced by +Chrome's values, and the receive windows start at Chrome's initial values before growing to the configured +maximums. + +!!! warning "" + + Chrome does not declare support for Ed25519, so a server using an Ed25519 certificate will fail the + handshake. Use an ECDSA or RSA certificate instead; certificates issued by ACME are unaffected. + #### realm !!! question "Since sing-box 1.14.0" diff --git a/docs/configuration/outbound/hysteria2.zh.md b/docs/configuration/outbound/hysteria2.zh.md index 0c24e2d9..042f5e75 100644 --- a/docs/configuration/outbound/hysteria2.zh.md +++ b/docs/configuration/outbound/hysteria2.zh.md @@ -2,6 +2,7 @@ :material-plus: [hop_interval_max](#hop_interval_max) :material-plus: [bbr_profile](#bbr_profile) + :material-plus: [disable_chrome_parrot](#disable_chrome_parrot) :material-plus: [realm](#realm) :material-alert: [obfs](#obfstype) @@ -38,6 +39,7 @@ "bbr_profile": "", "brutal_debug": false, + "disable_chrome_parrot": false, "realm": { "server_url": "https://realm.example.com", "token": "", @@ -176,6 +178,23 @@ BBR 拥塞控制算法配置,可选 `conservative` `standard` `aggressive`。 启用 Hysteria Brutal CC 的调试信息日志记录。 +#### disable_chrome_parrot + +!!! question "自 sing-box 1.14.0 起" + +禁用 Chrome QUIC 指纹模仿。 + +如果没有禁用,客户端的 QUIC 握手将被构造为模仿 Chrome,使 Hysteria 流量更难通过握手指纹识别。 + +为了与 Chrome 一致,客户端使用 Chrome 自己的 QUIC 参数,其覆盖部分设置: +`idle_timeout` 固定为 30 秒,`max_concurrent_streams` 与 `initial_packet_size` 被替换为 Chrome 的值, +接收窗口从 Chrome 的初始值开始,再增长到配置的最大值。 + +!!! warning "" + + Chrome 不声明支持 Ed25519,因此使用 Ed25519 证书的服务端将无法完成握手。 + 请改用 ECDSA 或 RSA 证书;由 ACME 签发的证书不受影响。 + #### realm !!! question "自 sing-box 1.14.0 起" diff --git a/docs/schema.json b/docs/schema.json index 70b82eba..21e60632 100644 --- a/docs/schema.json +++ b/docs/schema.json @@ -11612,6 +11612,9 @@ "brutal_debug": { "type": "boolean" }, + "disable_chrome_parrot": { + "type": "boolean" + }, "realm": { "$ref": "#/$defs/Hysteria2Realm" } diff --git a/go.mod b/go.mod index 753389ef..41cfb502 100644 --- a/go.mod +++ b/go.mod @@ -49,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.20260803041931-6c84c468bea2 + github.com/sagernet/sing-quic v0.6.4 github.com/sagernet/sing-shadowsocks v0.2.8 github.com/sagernet/sing-shadowsocks2 v0.2.1 github.com/sagernet/sing-shadowtls v0.2.1 diff --git a/go.sum b/go.sum index eed75a56..66e4fc7e 100644 --- a/go.sum +++ b/go.sum @@ -326,8 +326,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.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-quic v0.6.4 h1:BmGPebxcVICOkyBkn8a+fAfAB41zU9i83SMzObiu9bo= +github.com/sagernet/sing-quic v0.6.4/go.mod h1:+1lz5Rdw0+kAxRoJ9FW5RIott5OOAlS3QXKkwN6hR64= 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= diff --git a/option/hysteria2.go b/option/hysteria2.go index 3598c555..eead7c0f 100644 --- a/option/hysteria2.go +++ b/option/hysteria2.go @@ -212,9 +212,10 @@ type Hysteria2OutboundOptions struct { Network NetworkList `json:"network,omitempty"` OutboundTLSOptionsContainer QUICOptions - BBRProfile string `json:"bbr_profile,omitempty" enum:"standard,conservative,aggressive"` - BrutalDebug bool `json:"brutal_debug,omitempty"` - Realm *Hysteria2Realm `json:"realm,omitempty"` + BBRProfile string `json:"bbr_profile,omitempty" enum:"standard,conservative,aggressive"` + BrutalDebug bool `json:"brutal_debug,omitempty"` + DisableChromeParrot bool `json:"disable_chrome_parrot,omitempty"` + Realm *Hysteria2Realm `json:"realm,omitempty"` } type HysteriaRealmUser struct { diff --git a/protocol/hysteria2/outbound.go b/protocol/hysteria2/outbound.go index 742940ed..9bb7949a 100644 --- a/protocol/hysteria2/outbound.go +++ b/protocol/hysteria2/outbound.go @@ -150,6 +150,7 @@ func NewOutbound(ctx context.Context, router adapter.Router, logger log.ContextL }, UDPDisabled: !common.Contains(networkList, N.NetworkUDP), BBRProfile: options.BBRProfile, + ChromeParrot: !options.DisableChromeParrot, RealmOptions: realmOptions, }) if err != nil {