NodeJS搭建简单Socks5代理

user profile
Pandada 文章于 2023-10-19 发布
0

本代码是一个简单的 SOCKS5 代理服务器实现,使用 Node.js 的 net 模块。SOCKS5 代理服务器用于转发客户端的网络请求到目标服务器。它支持多种地址类型,包括 IPv4、IPv6 和域名地址。在本实现中,支持的操作是 CONNECT,即建立 TCP 连接。

代码功能详解

  • 引入模块:
    const net = require('net');
    引入 Node.js 的 net 模块,用于创建 TCP 服务器和客户端。
  • 创建服务器:
    let server = net.createServer(function (socket) {
        // 服务器逻辑
    });
    使用 net.createServer 方法创建一个 TCP 服务器。每当有新的客户端连接时,会执行回调函数,其中 socket 对象代表与客户端的连接。
  • 处理客户端数据:
    socket.once('data', function (data) {
                    // 处理客户端发送的数据
    });
    使用 socket.once 监听客户端发送的第一段数据。这通常是 SOCKS5 协议的握手请求。
  • 验证 SOCKS5 协议:
    if (!data || data[0] !== 0x05) return socket.destroy();
    验证客户端发送的数据是否符合 SOCKS5 协议。如果不是,则销毁该连接。
  • 发送响应:
    socket.write(Buffer.from([5, 0]), function (err) {
                    // 发送响应后的逻辑
    });
    向客户端发送响应,表示无需认证即可继续。
  • 处理连接请求:
    socket.once('data', (data) => {
                    // 解析目标地址和端口,并建立连接
    });
    再次监听客户端发送的数据,这次是连接请求。解析目标地址和端口,然后尝试建立到目标服务器的连接。
  • 建立连接到目标服务器:
    let remote = net.connect(remotePort, remoteAddr, function () {
                     // 连接成功后的逻辑
    });
    使用 net.connect 方法尝试连接到目标服务器。成功后,会执行回调函数。
  • 数据转发:
    remote.pipe(socket);
    socket.pipe(remote);
    使用 pipe 方法实现数据在客户端和目标服务器之间的双向转发。
  • 错误处理:
    remote.on('error', function (err) {
                    // 处理连接到目标服务器的错误
    });
    socket.on('error', function (err) {
        // 处理客户端连接的错误
    });
    监听错误事件,并在发生错误时销毁相应的连接。
  • 启动服务器:
    server.listen(11100);
    服务器监听端口 11100,等待客户端连接。
  • 完整代码

    const net = require('net');
                const net = require('net');
                let server = net.createServer(function (socket) {
                    socket.once('data', function (data) {
                        if (!data || data[0] !== 0x05) return socket.destroy();
                        let addrLen = 0, remoteAddr = null, remotePort = null;
                        socket.write(Buffer.from([5, 0]), function (err) {
                            if (err) socket.destroy();
                            socket.once('data', (data) => {
                                if (data.length < 7 || data[1] !== 0x01) return socket.destroy();  // 只支持 CONNECT 
                                try {
                                    addrtype = data[3];// ADDRESS_TYPE 目标服务器地址类型
                                    if (addrtype === 3) {  //0x03 域名地址(没有打错,就是没有0x02),
                                        addrLen = data[4];  //域名地址的第1个字节为域名长度,剩下字节为域名名称字节数组
                                    } else if (addrtype !== 1 && addrtype !== 4) {
                                        return socket.destroy();
                                    }
                                    remotePort = data.readUInt16BE(data.length - 2); //最后两位为端口值
                                    if (addrtype === 1) {  // 0x01 IP V4地址
                                        remoteAddr = data.slice(3, 7).join('.');
                                    } else if (addrtype === 4) {  //0x04 IP V6地址
                                        // remoteAddr = data.slice(3, 19);//IP V6长度为 16
                                        return socket.write(Buffer.from([0x05, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]));  //不支持IP V6
                                    } else {  //0x03 域名地址(没有打错,就是没有0x02),域名地址的第1个字节为域名长度,剩下字节为域名名称字节数组
                                        remoteAddr = data.slice(5, 5 + addrLen).toString("binary");
                                    }
                                    let remote = net.connect(remotePort, remoteAddr, function () {
                                        console.log(`connecting : ${remoteAddr}:${remotePort}`);
                                        socket.write(Buffer.from([0x05, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]), function (err) {
                                            if (err) {
                                                console.error(`error:${err.message}`);
                                                return socket.destroy();
                                            }
                                            remote.pipe(socket);
                                            socket.pipe(remote);
                                        });
                                    });
                                    remote.on('error', function (err) {
                                        console.error(`连接到远程服务器 ${remoteAddr}:${remoteAddr} 失败,失败信息:${err.message}`);
                                        remote.destroy();
                                        socket.destroy();
                                    });
                                } catch (e) {
                                    console.error(e);
                                }
                            });
                        });
                    });
                    socket.on('error', function (err) { console.error(`error:${err.message}`); });
                });
                server.listen(11100);
            
        

    使用方法

  • 将上述代码保存为 socks5.js
  • 在命令行中运行 node socks5.js 启动 SOCKS5 代理服务器。
  • 配置客户端使用 SOCKS5 代理,代理地址设置为服务器的 IP 和端口 11100
  • 注意事项

    • 本代码仅为简单实现,不包含认证等高级功能。
    • 在生产环境中使用时,需要考虑安全性和性能优化。
    • 如果需要支持更多 SOCKS5 协议的功能,需要进一步扩展代码。

    NodeJS搭建简单Socks5代理测评常见问答

    SOCKS5(Socket Secure 5)是一种网络传输协议,用于代理服务。它允许用户将其网络连接路由到代理服务器,以绕过地理位置限制或提高隐私性。与Shadowsocks等代理工具一样,SOCKS5代理可以用于保护用户的隐私和访问受限网站。

    您可以在浏览器的设置中配置代理服务器信息。在配置中,您需要指定SOCKS5代理服务器的IP地址和端口号。一旦配置完成,浏览器的所有网络请求将通过指定的代理服务器进行路由。
    上一篇 24款指纹浏览器(汇总) 浏览器指纹技术通常用于网站分析、广告定向、反欺诈检测和用户识...
    下一篇 代理IP的分类与用途详解 代理IP是跨境出海的重要工具,它为企业提供了许多途径,可以更...
    blog
    如何通过curl命令测试代理IP

    在进行网络开发或管理时,经常需要验证代理服务器的有效性和性能...

    blog
    NodeJS搭建简单Socks5代理

    本代码是一个简单的 SOCKS5 代理服务器实现,使用 No...

    blog
    如何解决代理IP速度慢的问题?

    在使用代理IP的过程中,速度慢是一个常见但令人头疼的问题。它...

    blog
    15+便宜且稳定Socks5代理IP商家...

    在我们的全面指南中发现最佳Socks5代理IP和HTTP代理...

    请直接通过电子邮件联系我们 pcb900817@gmail.com

    推荐商家