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)。