Increase REALITY target TLS record buffer to 17 KiB - #33
Conversation
|
Update: changed the proposed bound from Reason: TLS plaintext records are commonly described as 16 KiB, but TLS 1.3 encrypted records can exceed 16 KiB slightly due to overhead (RFC allows TLSCiphertext length up to The original reproducer ( |
|
I met the same issue. LGTM👍 Nit: Please update the PR title accordingly to align with your change. |
|
Is this fix included in v26.7.11? As i remember it was promised to include it to next release... |
|
Really interested in merging this, otherwise clients (which I can't change) are broken for dest with big certs |
现象是 REALITY 客户端已经通过认证,然后在 VLESS 开始之前失败。根因在上游: 读取目标 TLS 记录的缓冲区小于 RFC 8446 给 TLSCiphertext 的上界, 8–17 KiB 的证书记录(链稍长就会到这个量级)读不完整。 这不是配置问题,所以没有绕过它的配置写法。XTLS/REALITY#33 修的就是这个。⚠️ 当前 replace 指向 fanyangCS/REALITY —— 一个第三方个人 fork。 上线前必须换掉:要么上游合并后回到 xtls/reality,要么把这个补丁拿进我们自己的 synexim fork。生产依赖握手路径上的陌生人仓库,是我们控制不住的风险。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
I hit this too, so I set out to confirm the 8273 number before adding another "please merge" to the pile. I came away with two things the thread has not covered, including a reason this patch has to be written exactly the way it is. Setup was Xray-core Reproducing the original reportUnpatched, with
With this patch applied and nothing else changed:
Why the patch has to change
|
| target | chain | chain bytes | OCSP | Certificate record | size=8192 | size=17408 |
|---|---|---|---|---|---|---|
www.microsoft.com |
3 | 5879 | 2341 | 8273 | REJECT, handshakeLen=8273 > 8192 |
PASS |
azure.microsoft.com |
3 | 5785 | 2341 | 8179 | REJECT, len(s2cSaved)=8539 > 8192 |
PASS |
www.entrust.com |
4 | 7741 | 599 | 7002 | PASS | PASS |
www.cisco.com |
3 | 4934 | 1493 | 6480 | PASS | PASS |
www.bbc.com |
3 | 4757 | 1429 | 6239 | PASS | PASS |
www.paypal.com |
2 | 4882 | 471 | 5401 | PASS | PASS |
www.yahoo.com |
2 | 4584 | 471 | 5103 | PASS | PASS |
www.bing.com |
3 | 3888 | 1081 | 5022 | PASS | PASS |
www.apple.com |
2 | 3231 | 1459 | 4738 | PASS | PASS |
gateway.icloud.com |
3 | 3195 | 0 | 3240 | PASS | PASS |
www.google.com |
3 | 2454 | 0 | 2821 | PASS | PASS |
www.cloudflare.com |
4 | 3426 | 0 | 2809 | PASS | PASS |
I ran 35 targets in total and these are the representative ones. OCSP stapling is what separates the two failures from the rest. Both pair a chain of roughly 5.8 KB with a 2341 byte stapled OCSP response, and nothing else I probed came close.
End to end
Real server and client, curl https://www.google.com/generate_204 through the SOCKS inbound.
| dest | unpatched | patched |
|---|---|---|
www.microsoft.com |
000 | 204 |
azure.microsoft.com |
000 | 204 |
www.apple.com |
204 | 204 |
gateway.icloud.com |
204 | 204 |
www.yahoo.com |
204 | 204 |
www.cisco.com |
204 | 204 |
Nothing that worked before regressed.
Why 17 KiB is the right constant
REALITY already defines the ceiling in common.go:66 and enforces it at conn.go:707.
maxCiphertextTLS13 = 16384 + 256 // 16640handshakeLen is recordHeaderLen + length, so the largest legal value is 5 + 16640 = 16645.
17 * 1024 is 17408, which covers that with 763 bytes to spare. The 16384 in the first revision of this PR falls 261 bytes short of it. Moving to 17 KiB was not caution, it was the difference between covering the protocol limit and missing it, so the revised constant is correct and about as tight as it can be.
The cost is small. empty grows once by 9216 bytes. Per connection the two handshake buffers go from 2x8192 to 2x17408, so 18 KiB more per connection, and only while the handshake goroutine is alive.
One thing that is not this bug
While probing I found that microsoft.com (the apex), www.office.com, teams.microsoft.com and login.microsoftonline.com answer a Chrome fingerprint ClientHello with a HelloRetryRequest. REALITY's parser rejects those whatever size is set to, so they are unusable as dest for a reason that predates this patch and is untouched by it. I left them out of the counts above. Flagging it only so it does not get folded into this report by mistake, and I can open a separate issue if that is useful.
Follow up
Every failure above reaches the operator as the same line.
REALITY: processed invalid connection from <addr>: handshake did not complete successfully
That opacity is most of why this one burned so much of people's time. Putting the offending length into failureReason, something like target handshake record too long: 8273 > 17408, would let the log diagnose itself. I would rather not add anything to this PR's diff while it is waiting to land. Happy to send it separately once this merges.
The patch looks right to me as written.
Fixes XTLS/Xray-core#6356.
Summary
Increase REALITY's target TLS record buffer from 8192 bytes to 16384 bytes.
This fixes a reproducible REALITY failure when the legitimate target server returns a TLS Certificate record slightly larger than 8192 bytes. In the linked Xray-core issue,
www.microsoft.comcan return a Certificate record with total record length 8273 bytes when OCSP/status is included:The current REALITY code rejects it because:
The resulting user-facing/server log error is only:
Validation
I reproduced the failure with Xray-core
v26.3.27using:dest:www.microsoft.com:443serverNames:www.microsoft.comchromeUnpatched Xray failed locally with:
After this patch, the same localhost REALITY server/client setup succeeds:
A production deployment using the patched binary was also verified by the reporter.
Notes
TLS records can be up to around 16 KiB, so 8192 is too tight for real-world OCSP-stapled Certificate records from some large sites/CDN edges. This patch keeps the change minimal and avoids changing protocol behavior beyond allowing larger legitimate target handshake records.