Skip to content

Fix occasional SSL protocol error in XTLS Vision direct copy mode#5520

Draft
Copilot wants to merge 3 commits intomainfrom
copilot/fix-issue-4878
Draft

Fix occasional SSL protocol error in XTLS Vision direct copy mode#5520
Copilot wants to merge 3 commits intomainfrom
copilot/fix-issue-4878

Conversation

Copy link
Contributor

Copilot AI commented Jan 11, 2026

Fixes occasional ERR_SSL_PROTOCOL_ERROR / ERR_SSL_BAD_RECORD_MAC_ALERT when using VLESS + XTLS Vision + Reality. The issue is more frequent with testpre (pre-connect) enabled.

Root Cause

When Vision switches to direct copy mode (bypassing outer TLS for splice), it was merging rawInput bytes into the output buffer. The rawInput buffer in Go's crypto/tls.Conn may contain encrypted bytes for partial TLS records not yet processed, corrupting the data stream.

Changes

  • Removed rawInput merging: Only merge input (decrypted application data) into the buffer
  • Defer switch when rawInput has pending data: If rawInput is not empty, return early and retry on next read cycle, allowing the TLS layer to process remaining encrypted bytes
  • Fix fast-path condition: Add w.input == nil check to ensure fast-path only triggers after switch is complete
// Before: merged encrypted rawInput bytes (incorrect)
if rawInputBuffer, err := buf.ReadFrom(w.rawInput); err == nil && !rawInputBuffer.IsEmpty() {
    buffer, _ = buf.MergeMulti(buffer, rawInputBuffer)
}

// After: defer switch if rawInput has pending encrypted data
if w.rawInput != nil && w.rawInput.Len() > 0 {
    return buffer, err  // retry on next ReadMultiBuffer call
}

Reference: #5169

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • go.googlesource.com
    • Triggering command: `/update-job-proxy /update-job-proxy golang.org/x/netadd mpile ux-amd64/pkg/too-v -o pkg/mod/gvisor.dev/gvisor@v0.0.0-20250428193742--p mpile rg/toolchain@v0.0.1-go1.25.0.linux-amd64/pkg/tool/linux_amd64/vet -p encoding/gob t rg/toolchain@v0.0.1-go1.25.0.linux-amd64/pkg/too-buildtags -o /tmp/go-build2556457102/b590/pkg.a by deferring direct copy when rawInput has pending data

Co-authored-by: RPRX <63339210+RPRX@us--wait 0.1-go1.25.0.linux-amd64/pkg/tool/linux_amd64/compile -p gvisor.dev/gviso-d t 0.1-go1.25.0.linux-amd64/pkg/too-buildtags` (dns block)

  • Triggering command: /update-job-proxy /update-job-proxy ACCEPT /home/REDACTED/.lo-l test -e SERTrust_RSA_Certification_Authority.pem git f origin refs/heads/main k test -e bfab552.0 git est origin 07a0dafa413d8656--wait k test (dns block)
  • go4.org
    • Triggering command: `/update-job-proxy /update-job-proxy golang.org/x/netadd mpile ux-amd64/pkg/too-v -o pkg/mod/gvisor.dev/gvisor@v0.0.0-20250428193742--p mpile rg/toolchain@v0.0.1-go1.25.0.linux-amd64/pkg/tool/linux_amd64/vet -p encoding/gob t rg/toolchain@v0.0.1-go1.25.0.linux-amd64/pkg/too-buildtags -o /tmp/go-build2556457102/b590/pkg.a by deferring direct copy when rawInput has pending data

Co-authored-by: RPRX <63339210+RPRX@us--wait 0.1-go1.25.0.linux-amd64/pkg/tool/linux_amd64/compile -p gvisor.dev/gviso-d t 0.1-go1.25.0.linux-amd64/pkg/too-buildtags` (dns block)

  • Triggering command: /update-job-proxy /update-job-proxy ACCEPT /home/REDACTED/.lo-l test -e SERTrust_RSA_Certification_Authority.pem git f origin refs/heads/main k test -e bfab552.0 git est origin 07a0dafa413d8656--wait k test (dns block)
  • golang.zx2c4.com
    • Triggering command: `/update-job-proxy /update-job-proxy golang.org/x/netadd mpile ux-amd64/pkg/too-v -o pkg/mod/gvisor.dev/gvisor@v0.0.0-20250428193742--p mpile rg/toolchain@v0.0.1-go1.25.0.linux-amd64/pkg/tool/linux_amd64/vet -p encoding/gob t rg/toolchain@v0.0.1-go1.25.0.linux-amd64/pkg/too-buildtags -o /tmp/go-build2556457102/b590/pkg.a by deferring direct copy when rawInput has pending data

Co-authored-by: RPRX <63339210+RPRX@us--wait 0.1-go1.25.0.linux-amd64/pkg/tool/linux_amd64/compile -p gvisor.dev/gviso-d t 0.1-go1.25.0.linux-amd64/pkg/too-buildtags` (dns block)

  • Triggering command: /update-job-proxy /update-job-proxy ACCEPT /home/REDACTED/.lo-l test -e SERTrust_RSA_Certification_Authority.pem git f origin refs/heads/main k test -e bfab552.0 git est origin 07a0dafa413d8656--wait k test (dns block)
  • google.golang.org
    • Triggering command: `/update-job-proxy /update-job-proxy golang.org/x/netadd mpile ux-amd64/pkg/too-v -o pkg/mod/gvisor.dev/gvisor@v0.0.0-20250428193742--p mpile rg/toolchain@v0.0.1-go1.25.0.linux-amd64/pkg/tool/linux_amd64/vet -p encoding/gob t rg/toolchain@v0.0.1-go1.25.0.linux-amd64/pkg/too-buildtags -o /tmp/go-build2556457102/b590/pkg.a by deferring direct copy when rawInput has pending data

Co-authored-by: RPRX <63339210+RPRX@us--wait 0.1-go1.25.0.linux-amd64/pkg/tool/linux_amd64/compile -p gvisor.dev/gviso-d t 0.1-go1.25.0.linux-amd64/pkg/too-buildtags` (dns block)

  • Triggering command: /update-job-proxy /update-job-proxy ACCEPT /home/REDACTED/.lo-l test -e SERTrust_RSA_Certification_Authority.pem git f origin refs/heads/main k test -e bfab552.0 git est origin 07a0dafa413d8656--wait k test (dns block)
  • gopkg.in
    • Triggering command: `/update-job-proxy /update-job-proxy golang.org/x/netadd mpile ux-amd64/pkg/too-v -o pkg/mod/gvisor.dev/gvisor@v0.0.0-20250428193742--p mpile rg/toolchain@v0.0.1-go1.25.0.linux-amd64/pkg/tool/linux_amd64/vet -p encoding/gob t rg/toolchain@v0.0.1-go1.25.0.linux-amd64/pkg/too-buildtags -o /tmp/go-build2556457102/b590/pkg.a by deferring direct copy when rawInput has pending data

Co-authored-by: RPRX <63339210+RPRX@us--wait 0.1-go1.25.0.linux-amd64/pkg/tool/linux_amd64/compile -p gvisor.dev/gviso-d t 0.1-go1.25.0.linux-amd64/pkg/too-buildtags` (dns block)

  • Triggering command: /update-job-proxy /update-job-proxy ACCEPT /home/REDACTED/.lo-l test -e SERTrust_RSA_Certification_Authority.pem git f origin refs/heads/main k test -e bfab552.0 git est origin 07a0dafa413d8656--wait k test (dns block)
  • gvisor.dev
    • Triggering command: `/update-job-proxy /update-job-proxy golang.org/x/netadd mpile ux-amd64/pkg/too-v -o pkg/mod/gvisor.dev/gvisor@v0.0.0-20250428193742--p mpile rg/toolchain@v0.0.1-go1.25.0.linux-amd64/pkg/tool/linux_amd64/vet -p encoding/gob t rg/toolchain@v0.0.1-go1.25.0.linux-amd64/pkg/too-buildtags -o /tmp/go-build2556457102/b590/pkg.a by deferring direct copy when rawInput has pending data

Co-authored-by: RPRX <63339210+RPRX@us--wait 0.1-go1.25.0.linux-amd64/pkg/tool/linux_amd64/compile -p gvisor.dev/gviso-d t 0.1-go1.25.0.linux-amd64/pkg/too-buildtags` (dns block)

  • Triggering command: /update-job-proxy /update-job-proxy ACCEPT /home/REDACTED/.lo-l test -e SERTrust_RSA_Certification_Authority.pem git f origin refs/heads/main k test -e bfab552.0 git est origin 07a0dafa413d8656--wait k test (dns block)
  • h12.io
    • Triggering command: `/update-job-proxy /update-job-proxy golang.org/x/netadd mpile ux-amd64/pkg/too-v -o pkg/mod/gvisor.dev/gvisor@v0.0.0-20250428193742--p mpile rg/toolchain@v0.0.1-go1.25.0.linux-amd64/pkg/tool/linux_amd64/vet -p encoding/gob t rg/toolchain@v0.0.1-go1.25.0.linux-amd64/pkg/too-buildtags -o /tmp/go-build2556457102/b590/pkg.a by deferring direct copy when rawInput has pending data

Co-authored-by: RPRX <63339210+RPRX@us--wait 0.1-go1.25.0.linux-amd64/pkg/tool/linux_amd64/compile -p gvisor.dev/gviso-d t 0.1-go1.25.0.linux-amd64/pkg/too-buildtags` (dns block)

  • Triggering command: /update-job-proxy /update-job-proxy ACCEPT /home/REDACTED/.lo-l test -e SERTrust_RSA_Certification_Authority.pem git f origin refs/heads/main k test -e bfab552.0 git est origin 07a0dafa413d8656--wait k test (dns block)
  • lukechampine.com
    • Triggering command: `/update-job-proxy /update-job-proxy golang.org/x/netadd mpile ux-amd64/pkg/too-v -o pkg/mod/gvisor.dev/gvisor@v0.0.0-20250428193742--p mpile rg/toolchain@v0.0.1-go1.25.0.linux-amd64/pkg/tool/linux_amd64/vet -p encoding/gob t rg/toolchain@v0.0.1-go1.25.0.linux-amd64/pkg/too-buildtags -o /tmp/go-build2556457102/b590/pkg.a by deferring direct copy when rawInput has pending data

Co-authored-by: RPRX <63339210+RPRX@us--wait 0.1-go1.25.0.linux-amd64/pkg/tool/linux_amd64/compile -p gvisor.dev/gviso-d t 0.1-go1.25.0.linux-amd64/pkg/too-buildtags` (dns block)

  • Triggering command: /update-job-proxy /update-job-proxy ACCEPT /home/REDACTED/.lo-l test -e SERTrust_RSA_Certification_Authority.pem git f origin refs/heads/main k test -e bfab552.0 git est origin 07a0dafa413d8656--wait k test (dns block)
  • www.google.com
    • Triggering command: /tmp/xray3150884112/xray.test /tmp/xray3150884112/xray.test -config=stdin: -format=pb l/linux_amd64/vet /tmp/go-build451471748/b330/vet.cfg 1.78.0/balancer/-errorsas ap ux-amd64/pkg/tool/linux_amd64/vet -p a20poly1305 l/linux_amd64/as-bool ux-amd64/pkg/too-buildtags --gd�� 1.78.0/reflectio-errorsas 6457102/b118/ ux-amd64/pkg/tool/linux_amd64/link /tmp/cc7EaCh5.s balancer/gracefu-atomic -c=4 ux-amd64/pkg/too-buildtags (dns block)
    • Triggering command: /tmp/xray4057186336/xray.test /tmp/xray4057186336/xray.test -config=stdin: -format=pb -tests /tmp/go-build451471748/b634/vet.cfg g_.a 0.1-go1.25.0.lin-ifaceassert ux-amd64/pkg/tool/linux_amd64/vet -import_runtime_bash 1305 6457102/b118/ ux-amd64/pkg/tool/linux_amd64/vet v_OQ�� internet/tcp/config.go internet/tcp/config.pb.go ux-amd64/pkg/tool/linux_amd64/vet abis oxyman =0 ux-amd64/pkg/too-buildtags (dns block)
    • Triggering command: /tmp/xray1609100268/xray.test /tmp/xray1609100268/xray.test -config=stdin: -format=pb l/linux_amd64/vet --gd�� config.pb.go dns.go ux-amd64/pkg/tool/linux_amd64/link /tmp/ccXEbpa7.s /utls/internal/b-atomic -importcfg ux-amd64/pkg/too-buildtags ortc�� apic.go decode.go ux-amd64/pkg/tool/linux_amd64/vet --gdwarf-5 /retry mpile ux-amd64/pkg/tool/linux_amd64/vet (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Original prompt

认真理解 XTLS Vision 的代码,找出 #4878 的问题所在并修复它


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

@RPRX
Copy link
Member

RPRX commented Jan 11, 2026

这个用的 Claude Opus 4.5 看看会不会有惊喜

Copilot AI and others added 2 commits January 11, 2026 10:33
…copy when rawInput has pending data

Co-authored-by: RPRX <63339210+RPRX@users.noreply.github.com>
Co-authored-by: RPRX <63339210+RPRX@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix issue identified in XTLS Vision code Fix occasional SSL protocol error in XTLS Vision direct copy mode Jan 11, 2026
Copilot AI requested a review from RPRX January 11, 2026 10:39
@RPRX
Copy link
Member

RPRX commented Jan 11, 2026

我发现似乎它还是没有理解 XTLS 是啥,不过貌似的确等内层 record 完整且 rawInput 没数据时再切换到 direct/splice 万无一失

@yuhan6665 @Fangliding 你们怎么看,该不会是 Go 的底层 TCP 还有缓存吧

@RPRX
Copy link
Member

RPRX commented Jan 11, 2026

等下,这个是 receiver 不太能决定是什么时候,等我温故一下 XTLS 的逻辑

@yuhan6665
Copy link
Member

疑难杂症 AI 解决不了
我觉得可能是 splice 的时机问题 就是说现在有个人工的 delay 不太优雅 如果能把 delay 换成明确的 code signal 可能好点

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants