Conversation
|
@copilot 我是问你“现在 Xray 的 ECH 会加密哪些信息”,列举出来 |
现在 Xray 的 ECH 会加密以下信息(放在 inner ClientHello 中,外部不可见):
外部可观测到的 outer ClientHello 包含:
代码层面:
|
@copilot 这些也会被复制一份进 inner client hello 吗 |
不完全是"复制一份"。根据 uTLS fork 中 具体来说,当 使用 ECH 压缩引用(inner 不重复,引用 outer 的值,内外相同):
inner/outer 各自独立携带(值可以不同,这才是 ECH 真正隐藏的):
仅在 outer 中存在(inner 直接跳过):
所以 |
|
@copilot 所以带上隐藏 ALPN 后 |
关于带 ALPN vs 不带 ALPN 的长度区分:
paddingLen = 31 - ((len(h) + paddingLen - 1) % 32)ALPN 扩展(如 不过这并不是实际问题,因为:
关于与 GREASE 的区分: 可以区分。GREASE ECH 的 payload 长度是固定候选值: 此外,真正的 ECH 携带 实际上这也是浏览器的现状——Chrome 的 GREASE ECH 和真实 ECH 的 payload 长度不同,是已知的可区分点。 |
|
@copilot 你的意思是即使没有该 PR 的修改,
然而 X25519 公钥并不是纯随机数,此外详细解释 ECH 的加解密机制 |
是的。在 uTLS fork 的 if echInner && false { // 注意 && false,永远不会进入
echOuterExts = append(echOuterExts, extensionALPN)
}注释写的是 关于 X25519 和 ECH 加解密机制: 你说得对,X25519 公钥不是纯随机数。 ECH 加解密的完整机制(基于 HPKE,RFC 9180): 1. 密钥封装(客户端,
2. 密钥调度(
3. 加密 inner ClientHello(
4. 解密(服务端,
关于 GREASE ECH 的 |
|
@copilot 又在胡说,我看原代码 inner alpn 咋更像是压缩引用而并非你说的独立携带呢?也就是说密文长度可能会有变化 |
你说得对,我之前搞错了。 原始 upstream refraction-networking/utls 中,ALPN 确实是通过 // upstream 原版 handshake_messages.go:246
if echInner {
echOuterExts = append(echOuterExts, extensionALPN)
}inner ALPN = 引用 outer ALPN 的值,内外相同。 fangliding fork 把它改成了 // fork 修改后
if echInner && false { // 永远不进入,ALPN 不走压缩
echOuterExts = append(echOuterExts, extensionALPN)
}所以密文长度确实会变化:原本 inner 中 ALPN 只占 |
|
|
|
关于 inner payload 是否达不到 128: 对于 Xray(uTLS path,MaxNameLength=0):inner hello 包含 3 个 TLS 1.3 cipher suite + SNI + SCTs + ECH inner marker + ALPN(独立携带)+ 最短的 GREASE ECH payload( 对于 Chrome/BoringSSL:Chrome 的 inner hello 更大(15+ cipher suites、 总结:真 ECH ≥ 最短 GREASE,两者在 payload 长度上基本匹配。 |
|
@copilot 你看看你又在瞎说,Chrome TLSv1.3 哪有 15+ cipher suites,另外 uTLS 的任务之一就是模仿 Chrome client hello |
你说得对,Chrome 的 TLS 1.3 cipher suites 只有 3 个(AES_128_GCM、AES_256_GCM、CHACHA20_POLY1305),不是 15+。Chrome 的 outer ClientHello 总共 16 个 cipher suites(GREASE + 3 TLS 1.3 + 12 TLS 1.2),但 TLS 1.3 部分确实只有 3 个。 关于 uTLS 模仿 Chrome:uTLS 的 outer ClientHello 确实模仿 Chrome 指纹(16 cipher suites + 相同的扩展列表和顺序)。但 ECH 的 inner ClientHello 是通过 Go 的 |
When using uTLS+ECH with WebSocket/HTTPUpgrade, the real ALPN (
http/1.1) was exposed in the outer ClientHello, making it observable to network middleboxes. With this change, the outer ALPN presents as generich2, http/1.1while the actual ALPN is encrypted inside the inner ClientHello.tls.go—WebsocketHandshakeContext: Skip outer ALPN modification tohttp/1.1when ECH is active; the real ALPN stays encrypted in the inner ClientHellotls.go—copyConfig: PassNextProtosto uTLS config only when ECH is enabled, so the inner ClientHello carries the real ALPN values💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.