记录一次 zerotier 不通的问题
记录一次 zerotier 不通的问题
此内容年代久远,谨慎参考

§前言

这几天与好友联机尝试联机 minecraft,玩一个闯关冒险地图,由于地图本身限制不能用服务器架设,只能用客户端开服 P2P 联机。一开始想的就是直接使用 zerotier 联机,但是却发现我开设的服务端,好友连不进来。之前玩的其它联机游戏却可以正常通过 zerotier 进行 P2P 联机。

经过多处资料收集,现记录如下内容。

§在这之前,先要提一下 steam 的联机方式

steam 在游戏调用其 steamframework 后提供一个基于应用层的虚拟网络,只有这个游戏进程主动使用此能力才能进行 P2P 通信,而不影响系统中其它进程。

游戏从原有的

textudp_listen()
udp_receive()
udp_send()

等方法替换为

textsteam_udp_listen()
steam_udp_receive()
steam_udp_send()

等方法进行数据交换

由于集成了 steamframework 的盗版游戏本身没有特别标识,所以可以通过 spacewar 或其它申请了能力的免费游戏进行盗版联机。如游侠对战平台等盗版联机平台也是基于此原理,但从框架支持改为了 hook 实现。后来还发展出了游戏盾这种特殊用处的产品。

§在没有公网的情况下联机游戏遇到的问题

红警 2 的时代,个人计算机设备并未普及,大多数人只能选择去网吧,而网吧就有一个较大的局域网环境,诸如帝国时代、流星蝴蝶剑、红警、反恐精英等都是常在显示器上看到的画面。

而在互联网发达的北美地区,由于当时公网资源富裕,都是通过 IP 直连联机,去 YouTube 上找较老的 CS 联机视频,就会发现 connect aaa.bbb.ccc.ddd 这样的公网 IP 直连操作。

但这一天终于到来,IP 地址数量不足,网民们不但失去了相对固定的 IP 地址,甚至还被迫用上了 NAT,某个 IP 甚至并不代表这个 IP。

不但联机游戏如此,网络游戏也遇到了一样的问题。

网络游戏除了基本的游戏逻辑数据传输以外,还有一部分数据是通过 P2P 传输的,最常见的有内置语言聊天,区域文本聊天,甚至有的游戏连其它玩家的坐标数据也是通过 P2P 同步,各种瞬移早期玩网游的都应该见过。

比如 CSGO 这个游戏,时至今日,外挂问题如此严重,都只在服务器做最基本的运算,其它运算一律丢给客户端,透视(全局下发坐标),自瞄(全局下发坐标、不可见渲染),早期还有魔法子弹(客户端运算优先级高于服务端)。除了引擎本身的原因(参考泰坦陨落2),还有个问题就是公网带宽占用,与其将所有数据都通过服务端中转,不如直接让客户端们互相链接,不但更快而且省带宽。由于 CSGO 的 tick 较高,网络带宽占用其实挺大的,以一局经典的 16:9 竞技来说,需要大约 1.5G 的流量和不低于 2.1MBPS 的带宽,这仅仅只是必须与服务端交互的部分。

§P2P 组网和 NAT 打洞

由于 NAT 的日益猖狂,P2P 已经越来越难,emule 开始没落,BT 开始崛起(因为有 tracker 用于交换节点信息),国内也出现过 PP 点点通 这类用 BT 思想做互联的操作。

联机环境日益恶劣,但联机游戏用户群体却在日益增加,就有人想到了利用虚拟局域网进行联机的方案,最常见的例子就是传统意义上的 VPN。

说起来也有意思,谁能想到居然有一天提起 VPN 的想到的居然不是私有数据交换而是访问海外网络。

由于虚拟局域网为上层应用提供了相对固定的 IP 地址和简单的网络环境,立刻就受到了大量使用,包括但不限于联机游戏,远程办公,私密数据传输。

早期基于 VPN 的虚拟专网技术有较大的局限性,首先是默认路由表会将所有数据接管并转发到网关,其次是维护路由表对于个人用户而且困难且繁琐。这时就出现了诸如 hamachi 等软件提供的一键式专网,个人用户只用启动软件,取得 IP 地址,与他人交换并链接即可。可以说此类软件为个人用户的 P2P 联机起到了极大的帮助,光是国内在清网以前就能搜到大量 minecraft 与 hamachi 的内容。

但基于 VPN 的组网方式,需要一个或多个中心服务器做网关,而这很明显不能一直是免费的服务,于是有人研究出了利用 UDP 在 NAT 打洞的操作,相当于在免去中心服务器的情况下直接使用用户的浮动对外公网地址进行联机,同时又提供一个固定专网地址。

并不存在完全不需要中心服务器的组网,这里忽略现阶段中心服务器的作用,有兴趣的可以自行搜索

来到 P2P 组网的时代,涌现了如 zerotier 、N2N、nebula 等优秀的组网套件。此类套件对用户提供一个简单的人机界面,让用户实现一键式组网,而且费用低廉甚至免费。

§闲话说完了,下面是正题

zerotier 的实现方式是安装一个 tap 设备,或者说虚拟网卡。对外暴露 9993/udp 端口,经过中心服务器(亦称网络控制器)辅助的情况下进行 P2P 组网,对上层暴露一个具有固定地址的网卡适配器。用户与用户之间就可以通过固定的地址以局域网的方式直接进行联机,简单快捷。

我首先检查了防火墙,是直接通过指定应用程序可执行文件路径的方式添加的规则,经过测试可以联通。

又测试了互相 ping 的操作,也没问题。

正当我纳闷的时候,突然发现防火墙里面并没有 javaw.exe 的例外,当我添加例外后,就可以正常联机了。

结束游戏后,我又来研究这个问题,发现本质上是因为 zerotier 的网卡适配器的地址没有做例外。

在默认情况下,zerotier 创建的虚拟网卡设备的 IP 地址,与物理网卡的地址处于同样受限。在没有对网卡地址进行例外的情况下,是游戏本身自动(或手动)添加了对公用、专用、域的例外,而要实现完全联通的 zerotier 专网,应该将 zerotier 的地址加入例外,而不是依赖游戏本身添加例外。

举个例子,如果有如下链接界面

链接列表
链接列表

则应当在防火墙添加如下例外

防火墙例外
防火墙例外
防火墙例外
防火墙例外
防火墙例外
防火墙例外

如此配置后,通过 lan1 适配器的任何链接都将得到直接放行,不用去再去单独配置防火墙规则,远程桌面也好,联机游戏也好,只管用即可。另外就是务必将链接选择为专网,这样将得到更低的优先级,避免影响公用网络。

但类型为 PUBLIC 的网络建议不要这样搞,由于是自动授权入网的,有一定的危险。

§广告

ae4555e832a39f55 为我创建的无限设备数量的公开网络,详情点此

作者
ragnaroks
发布时间
2021-08-09
创作协议