Skip to content

Instantly share code, notes, and snippets.

@shibeta
Last active December 10, 2025 07:10
Show Gist options
  • Select an option

  • Save shibeta/f5287c29077e193ab3ff2544df74d42d to your computer and use it in GitHub Desktop.

Select an option

Save shibeta/f5287c29077e193ab3ff2544df74d42d to your computer and use it in GitHub Desktop.
Node.JS 编写的简易 SOCKS 代理服务器,用于检查流量是否通过代理
const net = require("net");
const PORT = 1080; // 监听端口
const server = net.createServer((socket) => {
let stage = 0; // 0: 握手, 1: 请求详情, 2: 转发中
socket.on("data", (data) => {
if (stage === 0) {
// SOCKS5 初始握手: [VER, NMETHODS, METHODS...]
if (data[0] === 0x05) {
// 回复: [VER, METHOD] -> 0x05, 0x00 (无需认证)
socket.write(Buffer.from([0x05, 0x00]));
stage = 1;
} else {
console.error("❌ 非 SOCKS5 协议");
socket.end();
}
} else if (stage === 1) {
// 连接请求: [VER, CMD, RSV, ATYP, DST.ADDR, DST.PORT]
const version = data[0];
const cmd = data[1]; // 0x01 = CONNECT
const atyp = data[3]; // 地址类型关键点
if (version !== 0x05 || cmd !== 0x01) {
console.error("❌ 不支持的命令或版本");
socket.end();
return;
}
let targetHost = "";
let targetPort = 0;
let addrLen = 0;
// 解析目标地址
if (atyp === 0x01) {
// IPv4 (4 bytes)
targetHost = data.slice(4, 8).join(".");
addrLen = 4;
console.log(
`[DNS 审计] ⚠️ 客户端发送的是 IP (本地 DNS): ${targetHost}`
);
} else if (atyp === 0x03) {
// Domain Name (1 byte len + domain)
const domainLen = data[4];
targetHost = data.slice(5, 5 + domainLen).toString();
addrLen = domainLen + 1;
console.log(
`[DNS 审计] ✅ 客户端发送的是域名 (远程 DNS): ${targetHost}`
);
} else if (atyp === 0x04) {
// IPv6 (16 bytes)
console.log(`[DNS 审计] ⚠️ 客户端发送的是 IPv6 (本地 DNS)`);
addrLen = 16;
// 简略处理 IPv6 解析...
}
// 解析端口 (最后2字节)
targetPort = data.readUInt16BE(4 + addrLen);
console.log(`[连接日志] 正在连接目标: ${targetHost}:${targetPort}`);
// 建立到目标的连接
const targetSocket = net.createConnection(
targetPort,
targetHost,
() => {
// SOCKS5 响应: 成功 (0x00)
// 构造一个虚假的绑定地址返回给客户端 (通常客户端不看这个)
const resp = Buffer.alloc(10);
resp[0] = 0x05;
resp[1] = 0x00; // Success
resp[3] = 0x01; // IPv4
socket.write(resp);
stage = 2; // 进入管道转发模式
// 管道连接
socket.pipe(targetSocket);
targetSocket.pipe(socket);
}
);
targetSocket.on("error", (err) => {
console.error(`[目标连接错误] ${err.message}`);
// 响应错误给客户端 (这里简略处理直接断开)
socket.end();
});
}
});
socket.on("error", (err) => {
// 忽略客户端重置连接的错误
});
});
server.listen(PORT, () => {
console.log(`SOCKS5 审计服务器已启动,端口: ${PORT}`);
console.log(
`请配置你的程序使用: socks5://127.0.0.1:${PORT} 或 socks5h://127.0.0.1:${PORT}`
);
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment