基于Node.js搭建Minecraft代理服务器连接Hypixel失败求助
Minecraft代理服务器连接Hypixel失败的问题排查与解决思路
问题概述
自己搭建Node.js TCP代理服务器,可正常连接部分破解版Minecraft服务器,但连接Hypixel时仅传输少量数据就断开;尝试node-minecraft-proxy库无报错但连接超时;推测是客户端握手包携带localhost地址触发Hypixel安全验证;改用mineflayer bot实现代理后客户端仍超时,本地收到以0f 00 2f开头的数据包,但bot未收到,需确认该包类型并寻求解决方案。
核心原因分析
- Hypixel的服务器地址校验机制:握手包中的服务器地址字段必须匹配实际连接的
mc.hypixel.net,如果是localhost会被判定为异常请求直接断开连接。 - 关于
0f 00 2f开头的数据包:这是Minecraft协议中的状态查询包,属于客户端在状态阶段(比如刷新服务器列表)发送的请求,mineflayer bot默认跳过状态阶段直接进入登录流程,未处理这类数据包导致转发中断。
解决方法
1. 修改TCP代理的握手包内容
必须在TCP代理层拦截并修改客户端发送的握手包,将其中的服务器地址从localhost替换为mc.hypixel.net,再转发给Hypixel。核心逻辑示例:
// 实现VarInt编解码函数(Minecraft协议专用) function readVarInt(buffer, offset) { let value = 0; let position = 0; let byte; do { byte = buffer.readUInt8(offset + position); value |= (byte & 0x7F) << (position * 7); position++; if (position > 5) throw new Error('VarInt too long'); } while ((byte & 0x80) !== 0); return { value, length: position }; } function writeVarInt(value) { const buffer = []; do { let byte = value & 0x7F; value >>>= 7; if (value !== 0) byte |= 0x80; buffer.push(byte); } while (value !== 0); return Buffer.from(buffer); } // 拦截并修改握手包 clientSocket.on('data', (data) => { let offset = 0; const { value: packetLength, length: lenLength } = readVarInt(data, offset); offset += lenLength; const { value: packetId } = readVarInt(data, offset); // 仅处理握手包(包ID=0) if (packetId === 0) { offset += lenLength; // 解析协议版本 const { value: protocolVersion, length: protoLen } = readVarInt(data, offset); offset += protoLen; // 解析原服务器地址 const { value: addrLen, length: addrLenLength } = readVarInt(data, offset); offset += addrLenLength; const originalAddr = data.toString('utf8', offset, offset + addrLen); offset += addrLen; // 解析端口和后续状态 const port = data.readUInt16BE(offset); offset += 2; const { value: nextState } = readVarInt(data, offset); // 构造新的服务器地址数据 const newAddr = 'mc.hypixel.net'; const newAddrBuffer = Buffer.from(newAddr); const newAddrLen = writeVarInt(newAddrBuffer.length); // 重新组装握手包 const newPacketParts = [ writeVarInt(1 + protoLen + newAddrLen.length + newAddrBuffer.length + 2 + 1), // 新包长度 writeVarInt(0), // 握手包ID writeVarInt(protocolVersion), newAddrLen, newAddrBuffer, Buffer.from([(port >> 8) & 0xff, port & 0xff]), writeVarInt(nextState) ]; const modifiedPacket = Buffer.concat(newPacketParts); // 转发修改后的包,后续数据直接透传 serverSocket.write(modifiedPacket); clientSocket.on('data', d => serverSocket.write(d)); serverSocket.on('data', d => clientSocket.write(d)); } else { serverSocket.write(data); } });
2. 修复mineflayer bot代理的数据包转发
mineflayer默认跳过状态阶段,需手动处理状态与登录阶段的数据包转发:
- 监听客户端的
data事件,先解析握手包,根据后续状态(1=状态,2=登录)分阶段处理:- 状态阶段:将客户端的状态请求包转发给Hypixel,再把Hypixel返回的状态响应包转发给客户端;
- 登录阶段:初始化mineflayer bot连接Hypixel,将客户端的登录包转发给bot,同时监听bot的
packet事件,把服务器发来的游戏数据包转发给客户端。
- 确保bot的协议版本与客户端完全匹配,避免因版本不兼容导致数据包解析失败。
3. 适配Hypixel的额外验证
Hypixel可能有额外的反代理机制,需注意:
- 确保代理的IP与客户端IP一致,避免IP mismatch;
- 不要修改握手包外的其他协议字段,保持数据包结构的完整性;
- 若使用mineflayer,需禁用bot的自动重连、自动聊天等行为,仅做纯数据包转发。
关于0f 00 2f数据包的确认
这个数据包是客户端在状态阶段发送的服务器信息请求包:
0f是VarInt编码的包总长度(15字节);00是状态阶段的包ID(对应0x00状态请求);00 2f是后续的字符串数据(长度为0的字符串+"/",属于状态请求的附加路径)。
mineflayer bot未收到是因为它默认直接进入登录流程,未监听状态阶段的数据包,需在代理逻辑中单独处理该阶段的转发。
内容的提问来源于stack exchange,提问作者Nuro007
相关产品推荐
相关产品推荐

