Hyffer
发布于 2024-06-08 / 49 阅读 / 0 评论 / 0 点赞

通过代理加入Minecraft多人游戏

Minecraft不遵从代理设置

Minecraft多人游戏的网络流量并不遵循系统代理,即使手动设置JVM参数也不起作用,这是一个由来已久的有记载的bug,而且似乎并没有修复的计划[1]。Minecraft自版本1.7之后采用netty库实现多人游戏协议[1],虽然netty库早已支持客户端代理[2],但按照bug report,其影响范围覆盖从1.7到1.16的众多游戏版本[1],实测1.8和1.16.5均存在该问题。

受到StackExchange上回答的启发[3],尝试使用proxychains工具截获应用程序的流量,强制其通过网络代理。

[1][MC-38872] Minecraft ignores java proxy parameters - Jira

[2]Feature request: Client proxy support · Issue #1133 · netty/netty

[3]How can I play Minecraft through a proxy server? - Arqade

ProxyChains截获流量

proxychains hooks network-related libc functions in dynamically linked programs via a preloaded DLL and redirects the connections through SOCKS4a/5 or HTTP proxies.

ProxyChains通过动态链接库预装载,在C库层面截获应用程序的网络流量,进而重定向流量到网络代理。搭载Apple Silicon芯片的macOS可以通过Homebrew安装proxychains-ng,可执行文件是proxychains4

绕开macOS系统完整性保护

对于Linux系统,运行proxychains4 curl baidu.com 应当就可以在代理中看到有流量经过。然而对于macOS,由于存在系统完整性保护(SIP),curl (/usr/bin/curl) 作为系统组件,动态链接库并不会被预装载,proxychains于是"fail silently"[4][5]

[4]Proxychains, Torsocks, Torify on macOS? Guess Again! : r/TOR

[5]A Deep Dive into Penetration Testing of macOS Applications (Part 3):The purpose of DYLD_INSERT_LIBRARIES is to specify a dynamic library that should be loaded into a process at runtime. ... If System Integrity Protection (SIP) is enabled, this environment variable is ignored when executing binaries protected by SIP.

网络上有很多讲解如何关闭系统完整性保护的教程,但事实上我们不必这么做。Minecraft是用户软件,完全不被系统自身的保护机制约束。

可实际操作起来却不是那么容易,Minecraft依赖Java运行环境,macOS又有其独特的设计。找一台全新的macOS机器,在命令行中输入以下命令,会得到令人惊奇的输出:

$ which java
/usr/bin/java
$ java --version
The operation couldn’t be completed. Unable to locate a Java Runtime.
Please visit http://www.java.com for information on installing Java.

长话短说,/usr/bin/java 是系统的"java wrapper"[6],受到SIP保护,而真正的Java虚拟机是由用户安装的,比如通过Homebrew安装的JVM是/opt/homebrew/.../bin/java,不受SIP机制的限制。因此,只有直接运行用户安装的JVMproxychains4 /opt/homebrew/.../bin/java ... ,方可截获Java应用程序的网络流量。

[6]How does /usr/bin/java work on Mac? - Ask Different

最终的解决方案

HMCL为例,首先选择一个除/usr/bin/java之外的Java路径,之后在【游戏设置】>【高级设置】菜单中,将proxychains设为包装命令。这样,多人游戏的流量就会由proxychains截获并转发给网络代理。

Minecraft_java_version.pngMinecraft_multiplayer_proxy.png

再来看一眼proxychains的输出……

[proxychains] Strict chain  ...  127.0.0.1:9870  ...  mc.hypixel.net:25565  ...  OK
[proxychains] Strict chain  ...  127.0.0.1:9870  ...  127.0.0.1:9870  ...  OK

等等,这第二行是什么意思?经过几番尝试,不难发现,Minecraft多人游戏的身份验证请求是遵从系统代理的。为避免proxychains转发本就送往代理的身份验证流量,造成“身份验证目前正在停机维护”的异常,可以添加JVM参数取消Java虚拟机的网络代理,将所有网络请求都留给proxychains处理。或者,如果使用运行于本地的代理,也可以修改proxychains配置,关闭proxy_dns,并放行本地回环地址段(更多详细信息请参考proxychains的示例配置文件)。

好啦,现在再试着连接服务器,就可以看到多人游戏的流量从代理通过,身份验证也可以正常使用了。

补充说明

这篇文章写于2024年6月,系统环境和软件可能会在未来发生变化。如果你考古发现本文,那其中很多内容细节也许都已不再适用,请适当借鉴,切勿生搬硬套。

在编写此文时,使用的机器是搭载M系列芯片的MacBook,系统为macOS Sonoma 14.1.2 (23B92),proxychains-ng稳定发行版的版本是4.17。通过Homebrew安装的proxychains-ng可以直接使用,并不会出现网上很多人所说的架构不兼容的问题,也不需要按照网上给出的解决方案一步步编译安装,这些内容早已过时。

$ brew info proxychains-ng
==> proxychains-ng: stable 4.17 (bottled), HEAD
Hook preloader
https://github.com/rofl0r/proxychains-ng
/opt/homebrew/Cellar/proxychains-ng/4.17 (10 files, 211.4KB) *
  Poured from bottle using the formulae.brew.sh API on 2024-06-01 at 15:31:37
From: https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/p/proxychains-ng.rb
License: GPL-2.0-or-later
==> Options
--HEAD
	Install HEAD version
==> Analytics
install: 507 (30 days), 1,686 (90 days), 6,474 (365 days)
install-on-request: 507 (30 days), 1,683 (90 days), 6,469 (365 days)
build-error: 16 (30 days)
$ file $(which proxychains4)
/opt/homebrew/bin/proxychains4: Mach-O 64-bit executable arm64