Minecraft 实际上是如何连接到服务器的?
How does minecraft actually connect to a server?
出于我的迷你项目的目的,我需要在客户端和某些服务器之间使用代理服务器。此代码有效但无效。它开始连接,通过登录并停止加密,然后过了一会儿超时,我不知道为什么。我一直在重新阅读 minecraft 协议 (https://wiki.vg/Protocol#Handshake) 和握手,但我仍然无法弄清楚为什么它不起作用。 console.log() 用于调试,我从中推断出无论出于何种原因,服务器从未发送设置的压缩/登录成功数据包。
var net = require('net');
var mcip = "mc.hypixel.net";
var mcport = 25565;
var server = net.createServer((socket) =>{
var remoteAddress = socket.remoteAddress + ':' + socket.remotePort;
console.log('new client connection from %s' + remoteAddress);
socket.on('data', (d)=>{
var client = net.connect(mcport,mcip, ()=>{
console.log("connected to server");
client.on("data", (data)=>{
socket.write(data);
console.log(data);
console.log("S -> C");
client.end();
});
client.write(d);
console.log(d);
console.log("C -> S");
});
});
});
server.listen(25565);
这里的一个大问题是,每次客户端发送数据时,您都需要重新连接到 Hypixel!当您的客户端连接到您时,您需要重新安排它以仅连接到服务器一次。
socket.on('data', (d)=>{
var client = net.connect(mcport,mcip, ()=>{
console.log("connected to server");
client.on("data", (data)=>{
socket.write(data);
console.log(data);
console.log("S -> C");
client.end();
});
client.write(d);
console.log(d);
console.log("C -> S");
});
});
变成这样:
var client = net.connect(mcport,mcip, ()=>{
console.log("connected to server");
client.on("data", (data)=>{
socket.write(data);
console.log(data);
console.log("S -> C");
});
});
socket.on('data', (d)=>{
client.write(d);
console.log(d);
console.log("C -> S");
});
请注意,现在我们不会结束与 Hypixel 的连接,我们会保持连接打开并继续向客户端发送数据。 (您应该在客户端断开连接时在 socket.on('close', (hadError)=>{...})
处理程序中处理关闭连接)
通过此更改,代理开始工作,但 Hypixel 会立即踢你没有通过正确的地址连接。在握手数据包中,您的连接 minecraft 客户端会将服务器地址设置为您的代理服务器的地址,因为就其而言,这就是它所连接的地址。 Hypixel 发现这不是“mc.hypixel.net”并踢了客户端。
即使不是这种情况,一旦连接达到播放状态,您将无法看到任何有意义的数据(我怀疑您想要看到),因为它全部由 aes CFB 加密-8 流密码,密钥从 MC 客户端使用 RSA 传递到服务器(您无法切实获取它)。
不要让这让您气馁,虽然 minecraft c<->s 连接是有可能被 mitm 的。它涉及的内容更多 :p 如果您想进一步讨论该主题,请随时在 discord 中添加我 (Azurethi#0789)。
出于我的迷你项目的目的,我需要在客户端和某些服务器之间使用代理服务器。此代码有效但无效。它开始连接,通过登录并停止加密,然后过了一会儿超时,我不知道为什么。我一直在重新阅读 minecraft 协议 (https://wiki.vg/Protocol#Handshake) 和握手,但我仍然无法弄清楚为什么它不起作用。 console.log() 用于调试,我从中推断出无论出于何种原因,服务器从未发送设置的压缩/登录成功数据包。
var net = require('net');
var mcip = "mc.hypixel.net";
var mcport = 25565;
var server = net.createServer((socket) =>{
var remoteAddress = socket.remoteAddress + ':' + socket.remotePort;
console.log('new client connection from %s' + remoteAddress);
socket.on('data', (d)=>{
var client = net.connect(mcport,mcip, ()=>{
console.log("connected to server");
client.on("data", (data)=>{
socket.write(data);
console.log(data);
console.log("S -> C");
client.end();
});
client.write(d);
console.log(d);
console.log("C -> S");
});
});
});
server.listen(25565);
这里的一个大问题是,每次客户端发送数据时,您都需要重新连接到 Hypixel!当您的客户端连接到您时,您需要重新安排它以仅连接到服务器一次。
socket.on('data', (d)=>{
var client = net.connect(mcport,mcip, ()=>{
console.log("connected to server");
client.on("data", (data)=>{
socket.write(data);
console.log(data);
console.log("S -> C");
client.end();
});
client.write(d);
console.log(d);
console.log("C -> S");
});
});
变成这样:
var client = net.connect(mcport,mcip, ()=>{
console.log("connected to server");
client.on("data", (data)=>{
socket.write(data);
console.log(data);
console.log("S -> C");
});
});
socket.on('data', (d)=>{
client.write(d);
console.log(d);
console.log("C -> S");
});
请注意,现在我们不会结束与 Hypixel 的连接,我们会保持连接打开并继续向客户端发送数据。 (您应该在客户端断开连接时在 socket.on('close', (hadError)=>{...})
处理程序中处理关闭连接)
通过此更改,代理开始工作,但 Hypixel 会立即踢你没有通过正确的地址连接。在握手数据包中,您的连接 minecraft 客户端会将服务器地址设置为您的代理服务器的地址,因为就其而言,这就是它所连接的地址。 Hypixel 发现这不是“mc.hypixel.net”并踢了客户端。
即使不是这种情况,一旦连接达到播放状态,您将无法看到任何有意义的数据(我怀疑您想要看到),因为它全部由 aes CFB 加密-8 流密码,密钥从 MC 客户端使用 RSA 传递到服务器(您无法切实获取它)。
不要让这让您气馁,虽然 minecraft c<->s 连接是有可能被 mitm 的。它涉及的内容更多 :p 如果您想进一步讨论该主题,请随时在 discord 中添加我 (Azurethi#0789)。