Last active
December 10, 2025 07:10
-
-
Save shibeta/f5287c29077e193ab3ff2544df74d42d to your computer and use it in GitHub Desktop.
Node.JS 编写的简易 SOCKS 代理服务器,用于检查流量是否通过代理
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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