梯子实验室tizilab.net

梯子报EOF是什么意思:unexpected EOF的几种来源

简短回答

梯子报 EOF,意思是客户端还在等对方发数据,连接却已经被关掉了;unexpected EOF 更具体,指一段本该读完整的数据只读到一半就断了。常见的来源有四类,本机时间偏差太大、订阅里的密码或传输参数和服务端对不上、节点端主动断开,以及途中网络把连接重置。

背景:这个问题从哪来

多数人第一次看到 EOF,是在客户端的日志页或节点测速结果里。节点延迟能测出数字,打开网页却转圈,日志里一行接一行地刷出 EOF 或 unexpected EOF。也有人在 v2rayN、Clash Verge Rev 的连接列表里看到同样的字样。

mihomo、sing-box、Xray 这几个常用内核都用 Go 写成,EOF 和 unexpected EOF 正是 Go 标准库里两个错误值的原文。弄清这两个词在 Go 里的定义,再对照代理连接的几个阶段,就能大致判断是哪一段先把连接关掉的。

EOF 和 unexpected EOF 在字面上差什么

Go 的 io 包文档把 EOF 定义为读取时“没有更多输入可读”返回的错误。ErrUnexpectedEOF 则用于读一个固定长度的块或数据结构读到一半就碰上结尾的情况,它的错误文本就是 unexpected EOF。

放到梯子的场景里,这两句可以这样理解:

日志里的字样 字面含义 在代理连接里通常对应
EOF 对方已经关闭连接,后面没有数据了 握手刚开始或请求刚发出,对方就把连接关了
unexpected EOF 一段完整的数据只收到一部分 协议头、加密块读到一半,连接断了
connection reset by peer 收到了 TCP 的 RST 连接被强制中止,来源可能是服务器,也可能是途中设备

RFC 9293 里,FIN 表示“发送方没有更多数据”,属于正常收尾;RST 表示重置连接,收到的一方会中止连接并通知上层程序。前者在 Go 程序里多半表现为 EOF,后者多半表现为 reset。两种都说明 TCP 连接曾经建立过,这一点和超时不一样。

梯子报 EOF 的四类来源

下表按出现的位置排列。第三列写的是这一类通常会带来的现象,用来和自己的情况对照。

来源 为什么会导致 EOF 常见现象
本机时间偏差 VMess 靠时间做认证,V2Fly 文档要求系统的 UTC 时间误差在 90 秒以内,与时区无关 同一订阅里所有 VMess 节点一起报错,其他协议正常
协议或传输参数不匹配 密码、UUID、加密方式、传输层(ws、grpc 等)、TLS 开关和服务端不一致,服务端认不出这条请求 刚导入订阅或手动改过节点后出现,换节点也一样
节点端主动断开 服务器过载、重启,或者这个账户流量用完、到期后被拒绝 只有部分节点报错,或者某天起全部报错
中间网络重置 途中的防火墙、运营商设备或公司网关发出 RST 换网络(手机热点)后恢复,日志里 reset 较多

第二类里,Trojan 的情况比较特别。Trojan 协议文档写明,服务端收到密码不对或格式不对的请求时,会把连接交给一个预设的地址处理(文档给的默认值指向 127.0.0.1 的 80 端口,也就是本机的网页服务),让它看起来和普通网站一样。我们的判断是,这时客户端等来的是网页服务的回应或关闭,内核解析不出代理数据,日志里就可能出现 EOF。Shadowsocks 的 AEAD 文档只写了数据被篡改时解密会失败,没有规定服务端之后怎么处理,各实现的表现可能不同。

第三类里的“流量用完、套餐到期”,要登录机场面板核对,日志本身看不出来。机场面板打不开时,可以先到本站的机场在线检测看这家近期的状态。那个页面定时打开各家机场的用户面板,轮一圈大约半小时,确切间隔见页面顶部。面板打得开,并不代表节点能用,这一层检测看不到。

从日志里区分是哪一类

看日志之前,先把内核的日志级别调高。mihomo 文档列出的级别从 silent 到 debug 共五档,默认是 info,debug 会尽量输出运行中的全部信息。Clash Verge Rev 的日志页位置可以对照它的 Windows 图文教程。

拿到日志后,按下面的顺序看:

  1. 看报错的节点有什么共同点。 全部是 VMess、别的协议正常,先查时间;全部节点都报,查订阅和本机网络;只有几个报,查那几台服务器。
  2. 看报错出现的时间点。 刚更新订阅、刚换客户端就开始报,优先怀疑参数;用了几天突然报,优先怀疑节点端或账户状态。
  3. 看是 EOF 还是 reset。 集中出现 connection reset 时,换一个网络环境复测,能区分是不是途中设备在干预。
  4. 看延迟测试和实际访问是否一致。 延迟测试只证明入口端口能连上,认证能不能通过它不负责。延迟正常但访问报 EOF,恰好符合认证或参数出错的特征,细节见延迟数字怎么来的。

如果日志里根本没有 EOF,只有 timeout 或 i/o timeout,问题更可能出在连接建立之前,按全部节点超时的对照测试那一篇的步骤排查。

自己怎么验证

下面几项不依赖本站,每一项都能单独做,做完记下结果再改下一项:

  • 核对系统时间。 Windows 11 按 Microsoft 支持文档的路径进入时间和语言设置,把“自动设置时间”拨到开,然后点“同步时钟”一栏的按钮。手机在系统设置里打开自动时间。改完重新测 VMess 节点。
  • 重新导入订阅。 在客户端里删掉旧的配置,从机场面板重新复制订阅链接导入,排除手动改错参数的可能。想看懂一条节点里各个字段,可以对照拆分享链接的那篇指南。
  • 换一个网络。 电脑连手机热点,同一个节点再试一次。换网后恢复,说明问题在原来的网络环境里。
  • 换一台设备。 同一个订阅导入另一台设备的客户端。另一台正常,问题在本机,思路见手机能用电脑不能用。
  • 更新客户端。 从梯子下载页找到官方发布地址,换成新版本内核。旧内核不认识新的传输参数时,也会在握手阶段断开。

这篇没有覆盖的

本站没有在自己的设备上复现上面四类 EOF,表里的对应关系来自协议文档和 Go 标准库的定义,属于资料加推断。不同客户端给错误套的前缀不一样,同一个原因在 v2rayN 和 Clash Party 里的原文可能不同,本文没有逐个列出。

Hysteria2、TUIC 这类跑在 UDP 上的协议,出错时的表现和 TCP 协议有差别,本文没有展开。机场服务端的具体实现和限速策略本站也看不到,节点端主动断开的具体原因只能由机场给出答复。

本文引用的来源9 条 · 在新窗口打开

  1. Go 标准库文档:io 包(EOF 与 ErrUnexpectedEOF)pkg.go.dev
  2. RFC 9293:Transmission Control Protocol (TCP)rfc-editor.org
  3. V2Fly 文档:VMess 配置(系统时间要求)v2fly.org
  4. V2Fly 开发者文档:VMess 协议v2fly.org
  5. Trojan 文档:The Trojan Protocoltrojan-gfw.github.io
  6. Shadowsocks 文档:AEAD ciphersshadowsocks.org
  7. mihomo 文档:全局配置(log-level)wiki.metacubex.one
  8. mihomo 文档:VMess 代理字段wiki.metacubex.one
  9. Microsoft 支持:在 Windows 中设置时间、日期和时区support.microsoft.com

常见问题4 题

梯子报 EOF 和全部节点超时是一回事吗

两者出现的阶段不同。超时通常是连接根本没建立起来,客户端等到时限才放弃;EOF 说明连接已经建立,对方还在读写途中把它关了。所以 EOF 往往指向认证或参数问题,超时更多指向入口不通。

只有一个节点报 EOF,其他节点正常,要改本机设置吗

一般不用。本机时间或客户端版本出问题,同一订阅里用同一协议的节点通常会一起报错。只有个别节点报 EOF,更可能是那台服务器或它的线路出了状况,先换节点,再把节点名和时间记下来发给机场客服。

手机和电脑用同一个订阅,只有电脑报 EOF 怎么办

先对比两台设备的系统时间,再看两边客户端的内核版本。订阅一样时,差别多半出在本机这一侧。时间都准的话,把电脑客户端更新到官方发布页的新版本再试一次。

把日志级别调成 debug 会不会泄露订阅

debug 会写出更多连接细节,可能包含节点地址和访问的域名。日志只留在本机时影响不大,要截图发给别人前,先把服务器地址、端口、UUID 和密码打上码。

本文最后一次核对来源是 。软件界面、服务政策和法规会变,发现和现在不一致的地方,请按更正与反馈里的方法告诉我们。