端口检测显示开放?为什么 Minecraft 玩家仍然进不去
一次成功的 TCP 连接只能证明一个套接字在某处被接受。登录、进入世界以及从内网到公网的路径,是三组不同的测试。
有人跑一次端口检测,看到开放二字,就把服务器当成已经解决。这个结果的实际含义很窄:从检测者所在的位置、在那一刻,发往该地址和端口的 TCP 连接被接受了。它既不能说明 Minecraft 协议握手,也不能说明账号认证,更不能说明服务器是否让玩家进入了世界。
这是四个不同的层面,其中任何一层出问题,玩家得到的都是同一句话:没成功。
探测只能测到它看得见的东西
TCP 连接在双方完成三次握手时建立,而这位于游戏所知的一切之下。探测报告的是:某个监听者存在,并从它所在的网络位置做出了回应。它无法告诉你监听者就是游戏本身,因为任何进程都能占用端口并接受连接。
位置和结果同样重要。公网上的检测器只测一条来自一个网络的路径。运营者从同一网络内部运行的检测器测的是完全另一条路径,那里的成功结果几乎说明不了远程玩家的体验。两个不同服务商的两个检测器,甚至可能因为与你的服务器毫无关系的原因而给出不同结论。
时间同样重要。探测结果描述的是它运行的那一刻;而动态地址或改动过转发规则的家庭宽带,可能在几分钟后就让真实答案改变。把公网地址、端口、地址族和时间与结论一起记录下来,否则这次观测无法复现。要从真正不同的网络重测,而不是用同一条宽带上的手机。
从套接字到玩家之间的四层
设想一个加入的客户端实际执行的顺序。它先解析地址,再向公布的端口打开 TCP 连接,然后用游戏自身的协议协商并认证,最后由服务器决定是否允许这个身份进入世界。每一层都有自己的失败特征,而端口检测只能看到第一层。
Java Edition 的默认端口是 25565,但运营者可以公布另一个外部端口并把它转发到内部,所以玩家输入的号码不一定是服务器看到的号码。检测器对着错误的外部端口时,会在服务器完全健康的情况下报告关闭,这是整个领域里最常见的误报。
名称在端口之上又加了一步。如果玩家输入主机名,解析必须返回公布的那个地址;而在网络内部的机器上,它可能返回私有地址。这不是防火墙故障,再怎么转发端口也改变不了。
为什么内网玩家走的是另一条路
同一局域网、或能到达该局域网的 VPN 里的玩家,会尝试从内部访问公网地址。请求发到路由器的外部地址,路由器必须把它翻译回内部,这种安排通常叫发夹回环或 NAT 反射。要让这条路走通,去程翻译和回程路径都得对上,而许多家用路由器根本没有实现。
所以外面的访客能进来,坐在服务器旁边的人反而不行。外部路径确实没问题;失败的是内部绕行,而且失败的方式在玩家屏幕上看起来像服务器故障。服务器自己的日志能判定到底是哪一种,因为从未被翻译的连接根本到不了它那里。
有两种诚实的修法和一种坏习惯。好办法是让内部玩家使用私有地址或内部解析到私有地址的 split-DNS 名称,或者在路由器支持且行为正常时启用反射。坏习惯是继续开更多端口或关掉主机防火墙,那对一个路由器从未执行过的翻译毫无作用。
Netgate 的NAT 反射文档更详细地描述了外部与内部的区别以及 split-DNS 这个替代方案。请把它当作机制说明来读,而不是当作某个 VPN 服务商或路由器支持所有 loopback 变体的承诺。
从每个视角收集证据
每次测试都要记下:谁执行的、从哪里、什么时间、针对哪个地址和端口,以及服务器记录了什么。服务器控制台里带有明确原因的游戏拒绝,和一次从未到达的连接是两种不同的发现,而两者导向相反的方向。
如果被允许的远程玩家能进、而某一个本地玩家进不去,那剩下的问题就是本地路径,值得单独排查:客户端用的是哪个地址、路由器对这次翻译做了什么、服务器到底有没有记录到连接尝试。把这三件事交给网络的所有者,而不是反复随机开端口。