仅支持socks5http

/**
 * node:net
 */
const net = require("net");

/**
 * 0x05 处理器
 * @param { net.Socket } socket
 * @param { Buffer } buffer
 */
const SOCKS5Handel = (socket, buffer) => {
    // 根据协议添加协议验证与响应
    socket.write(Buffer.from([5, 0]), (error) => {
        // 添加协议验证与响应失败
        if (error) {
            console.error("proxyServer:SOCKS5Handel.添加协议验证与响应失败:", error);
            socket.destroy();
            return;
        }

        let host, port, hostLen = 0;

        // 协议验证与响应
        socket.once("data", (data) => {
            // 只支持 CONNECT
            if (data.length < 7 || data[1] !== 0x01) {
                console.error("proxyServer:SOCKS5Handel.只支持CONNECT:", error);
                socket.destroy();
                return;
            }

            try {
                // ADDRESS_TYPE 目标服务器地址类型
                let addrtype = data[3];

                /**
                 * 0x03 域名地址(没有打错,就是没有0x02)
                 * 域名地址的第1个字节为域名长度,剩下字节为域名名称字节数组
                 */
                if (addrtype === 3) hostLen = data[4];
                else if (addrtype !== 1 && addrtype !== 4) return socket.destroy();

                // 最后两位为端口值
                port = data.readUInt16BE(data.length - 2);

                /**
                 * 0x01 IP V4地址
                 * 0x04 IP V6地址 remoteLink = data.slice(3, 19);//IP V6长度为 16 (不支持IP V6)
                 * 0x03 域名地址(没有打错,就是没有0x02),域名地址的第1个字节为域名长度,剩下字节为域名名称字节数组
                 */
                if (addrtype === 1) host = data.slice(3, 7).join(".");
                else if (addrtype === 4) return socket.write(Buffer.from([0x05, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]));
                else host = data.slice(5, 5 + hostLen).toString("binary");

                // 连接
                connectServer(socket, () => socket.write(Buffer.from([0x05, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])), { port, host, timeout: 30 * 60 * 1000, keepAlive: true });
            } catch (error) {
                console.error("proxyServer:SOCKS5Handel.解析期间发生异常:", error);
                socket.destroy();
            }
        });
    });
};
/**
 * HTTP 处理器
 * @param { net.Socket } socket
 * @param { Buffer } buffer
 */
const HTTPHandel = (socket, buffer) => {
    try {
        let connect = buffer.toString().match(/CONNECT (.+?) HTTP/);
        let host, port, callback;
        if (connect) {
            [host, port] = connect[1].split(":");
            callback = () => socket.write("HTTP/1.1 200 OK\r\n\r\n");
        } else {
            if (!!buffer.toString().match(/Host: (.*):(\d+)/i)) [, host, port] = buffer.toString().match(/Host: (.*):(\d+)/i);
            else if (!!buffer.toString().match(/Host: (.*)/i)) [, host] = buffer.toString().match(/Host: (.*)/i);
            if (!port) port = 80;
            callback = (server) => server.write(buffer);
        }

        // 连接
        connectServer(socket, callback, { port, host, timeout: 30 * 60 * 1000, keepAlive: true });
    } catch (error) {
        console.error("proxyServer:HTTPHandel.解析期间发生异常:", error);
        socket.destroy();
    }
};

/**
 * HTTP 处理器
 * @param { net.Socket } socket
 * @param { function } callback
 * @param { net.NetConnectOpts } options
 */
const connectServer = (socket, callback = (server = net.Socket) => { }, options) => {
    /**
     * 域名IP拦截
     */
    if (!proxySet.has(options.host)) {
        console.warn(`proxyServer.connectServer:白名单拦截<${options.host}:${options.port}>`);
        socket.destroy();
        return;
    }

    console.log(`proxyServer.connectServer<${options.host}:${options.port}>`);
    // 创建到目标服务器的连接
    let server = net.connect(options);
    // 连接回调
    callback(server);
    // 将数据从客户端转发到目标服务器
    socket.pipe(server);
    // 将数据从目标服务器转发回客户端
    server.pipe(socket);

    server.on("error", (error) => {
        console.error("proxyServer.connectServer.error:", options, error);
        socket.destroy();
        server.destroy();
    });
};

/**
 * 创建代理服务
 */
let proxyServer = net.createServer((socket) => {
    // 设置超时时间
    socket.setTimeout(30 * 60 * 1000);

    /**
     * 获取首次代理请求的数据
     */
    socket.once("data", (buffer) => {
        if (buffer[0] === 0x05) SOCKS5Handel(socket, buffer);
        else HTTPHandel(socket, buffer);
    });

    /**
     * 监听请求异常
     */
    socket.on("error", (error) => {
        console.error("proxyServer:socket.on.error:", error);
        socket.destroy();
    });
});

/**
 * 启动代理
 */
proxyServer.listen(3030, () => console.log(`Proxy run success: port is 3030.`));

文章作者: CaptainTwo
版权声明: 本站所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 CaptainTwo
NodeJs NodeJs
喜欢就支持一下吧