内网专用轻量级 SOCKS5 代理实现(nodejs )

安全警告
⚠️ 本实现专为内网测试场景设计,严禁直接用于公网环境。使用时必须注意:

强制配置IP白名单,防止未授权访问
生产环境应使用专业代理软件(如Squid、Dante)

协议交互流程(SOCKS5)

阶段
客户端行为
服务端响应

版本协商 (Handshake)
发送支持的认证方式列表
返回选择的认证方式

认证协商 (Auth)
根据认证方式发送凭证(本实现跳过)
返回认证结果(本实现始终无认证)

请求处理 (Request)
发送目标地址和端口
建立连接并转发数据

核心实现代码(Node.js)

支持白名单配置
严格的协议版本校验
完善的错误响应机制
完整支持 IPv4/IPv6/域名解析
符合 RFC 1928 规范的状态码返回

const net = require('net');
const dns = require('dns');

// 配置参数(建议改为环境变量)
const CONFIG = {
    PORT: 6532, // SOCKS5 代理端口
    ALLOWED_IPS: new Set(['127.0.0.1', '192.168.1.100']), // 允许访问的IP
    PROTOCOL_VERSION: 0x05
};

// SOCKS5 响应码生成器
const RESPONSE = {
    SUCCESS: Buffer.from([0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0, 0]),
    AUTH_FAIL: Buffer.from([0x05, 0xFF]),
    CONNECT_REFUSED: Buffer.from([0x05, 0x05, 0x00, 0x01, 0, 0, 0, 0, 0, 0]),
    HOST_UNREACHABLE: Buffer.from([0x05, 0x04, 0x00, 0x01, 0, 0, 0, 0, 0, 0])
};

const server = net.createServer((clientSocket) => {
    // 客户端IP验证(兼容IPv4/IPv6)
    const remoteAddress = clientSocket.remoteAddress.replace(/^::ffff:/, '');
    if (!CONFIG.ALLOWED_IPS.has(remoteAddress)) {
        console.warn(`[SECURITY] 非法访问尝试来自 ${remoteAddress}`);
        clientSocket.destroy();
        return;
    }

    // 连接目标服务器
    const connectTarget = (ip, port) => {
        const remoteSocket = net.connect(port, ip, () => {
            clientSocket.write(RESPONSE.SUCCESS);
            clientSocket.pipe(remoteSocket).pipe(clientSocket); // 双向数据转发
        });

        remoteSocket.on('error', () => clientSocket.end(RESPONSE.CONNECT_REFUSED));
    };

    // 协议握手处理
    clientSocket.once('data', data => {
        // 校验协议版本
        if (data[0] !== CONFIG.PROTOCOL_VERSION) {
            clientSocket.end();
            return;
        }

        // 认证方式协商(仅支持无认证)
        clientSocket.write(Buffer.from([0x05, 0x00]));

        // 请求处理
        clientSocket.once('data', req => {
            // 命令类型校验(仅支持CONNECT)
            if (req[0] !== 0x05 || req[1] !== 0x01) {
                clientSocket.end(RESPONSE.AUTH_FAIL);
                return;
            }

            // 地址类型解析
            const [atyp, offset] = [req[3], 4];
            try {
                let addr, port;
                switch (atyp) {
                    case 0x01: // IPv4
                        addr = req.slice(offset, offset + 4).join('.');
                        port = req.readUInt16BE(offset + 4);
                        break;
                    case 0x03: // 域名
                        const len = req[offset];
                        addr = req.slice(offset + 1, offset + 1 + len).toString();
                        port = req.readUInt16BE(offset + 1 + len);
                        dns.lookup(addr, (err, ip) => {
                            err ? clientSocket.end(RESPONSE.HOST_UNREACHABLE) : connectTarget(ip, port);
                        });
                        return;
                    case 0x04: // IPv6
                        addr = req.slice(offset, offset + 16);
                        port = req.readUInt16BE(offset + 16);
                        break;
                    default:
                        throw new Error('Unsupported address type');
                }
                connectTarget(addr, port);
            } catch (e) {
                clientSocket.end(RESPONSE.HOST_UNREACHABLE);
            }
        });
    });
});

server.listen(CONFIG.PORT, () => {
    console.log(`SOCKS5代理已启动,监听端口:${CONFIG.PORT}\n允许访问IP:${[...CONFIG.ALLOWED_IPS].join(', ')}`);
});

使用方法

node socks5.js