众所周知,某些容器管理服务只让放一个端口,还有某些免费的NAT VPS也只给你放一个空闲端口,这个就直接导致了我现在SSH VNC 还有一个 Terraria 服务端根本就不够开… 好了前面都是废话,代码又不是我写的,直接贴:
// safe-app.js - 完全透明首包缓存代理
const net = require('net');
const LISTEN_PORT = 5911;
const ROUTES = [
{
name: 'SSH',
port: 22,
detect: buf => buf.toString().startsWith('SSH-'),
},
{
name: 'VNC',
port: 5912,
detect: buf => false,
},
{
name: 'Terraria',
port: 7777,
detect: buf => true,
}
];
const server = net.createServer(clientSocket => {
console.log(`[+] 新连接来自 ${clientSocket.remoteAddress}`);
let resolved = false;
let buffer = Buffer.alloc(0);
const timer = setTimeout(() => {
if (!resolved) {
console.log('[~] 未收到数据,默认转发 VNC');
forward(ROUTES[1].port);
}
}, 1000);
clientSocket.on('data', chunk => {
if (resolved) return;
buffer = Buffer.concat([buffer, chunk]);
for (const route of ROUTES) {
if (route.detect(buffer)) {
clearTimeout(timer);
forward(route.port);
return;
}
}
// 超出长度仍未判断成功,转默认
if (buffer.length > 12) {
clearTimeout(timer);
forward(ROUTES[2].port); // Terraria fallback
}
});
function forward(targetPort) {
resolved = true;
console.log(`[→] 正在转发到端口 ${targetPort}`);
const target = net.connect(targetPort, '127.0.0.1', () => {
if (buffer.length > 0) target.write(buffer);
clientSocket.pipe(target);
target.pipe(clientSocket);
});
target.on('error', err => {
console.error(`[×] 转发端口 ${targetPort} 出错: ${err.message}`);
clientSocket.destroy();
});
clientSocket.on('error', () => {
target.destroy();
});
}
});
server.listen(LISTEN_PORT, () => {
console.log(`[✔] 多协议智能代理监听于端口 ${LISTEN_PORT}`);
});
因为我是Docker容器去映射端口到主机,所以地址都指定了127.0.0.1。这里我的情况是客户端没响应发给VNC,然后SSH自己报名的就发给SSH。如果VNC给超时了或者客户端发的也不是SSH的就全部转给Terraria,就这些功能,水一篇帖子。如果有人有成熟的项目的话欢迎推荐!