你的位置:首页 > 互联网IT

NodeJS实现简单的Socks5代理服务,NodeJSSocks5代理搭建,NodeSocks5搭建,NodeSocks5代理,Socks5搭建,Socks5代理,s5代理,s5搭建

支持系统:Windows 64/32位系统/Linux系统

功能:NodeSocks5代理

软件:node

性能:一般

Windows/linux下载地址:NodeSocks5代理

windows node 下载地址:node-v12.14.0-x86.rar


项目地址:

https://gitee.com/baojuhua/node_simples/tree/master/node_simple_socks5_server


NodeSocks5代理


用法:

Socks5服务器端

修改Socks5.js:

最后一行:server.listen(11100);   //修改端口


Windows/linux启动:

服务端

node Socks5.js


Windows系统:

安装:node-v12.14.0-x86.msi

查看:node -v

返回版本信息,比喻:v0.10.48

同目录下运行cmd:

服务端

node Socks5.js或者启动Socks5.bat


后台隐藏运行:https://www.zhuguodong.com/?id=520


Linux系统:

第一种:nodejs安装

安装:yum -y install nodejs

查看:node -v

返回版本信息,比喻:v0.10.48

同目录下运行linux命令:

服务端

node Socks5.js


后台隐藏运行:https://www.zhuguodong.com/?id=498


1.升级node,下载 n管理包

npm install -g n

2.执行n 命令升级到v14.16.0

v14.16.0版本2021年2月23日

n 14.16.0 stable

v12.21.0版本2021年2月23日

n 12.21.0 stable

v10.23.3版本2021年2月9日

n 10.23.3 stable

3.重启centos7(必须).查看node版本,更新到14.16.0

reboot


第二种:nodejs安装

安装宝塔网站面板

软件商店:搜索node,安装

查看:node -v

返回版本信息,比喻:v0.10.48



Linux系统node安装:

参考文章:https://www.zhuguodong.com/?id=529


s5.js代码:最后一行:server.listen(11100);   //修改端口

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长度为 16return 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);


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);


参考文章:

https://gitee.com/baojuhua/node_simples/tree/master/node_simple_socks5_server

https://www.jianshu.com/p/b3b4941f7723



NodeJS实现简单的Socks5代理服务

简书:https://www.jianshu.com/p/b3b4941f7723

前言

最近在网上看到一篇文章《你也能写个 Shadowsocks》,于是处于好奇就了解到了SOCKS5协议。

这里我就根据SOCKS5协议,通过NodeJS实现一个最简单的,没有加密,不需要认证Socks5代理服务。

我相信大家都听过Socket,而Socks5协议是一种网络传输协议,常用过代理,之前很有名的shadow socks也是基于此协议实现的。这里大家单词可不要看错了。

编写TCP服务

我们使用NodeJSnet模块编写tcp服务。

使用socket.once('data',.....)来获取首次代理请求的数据

const net = require('net');let server = net.createServer(function (socket) {    socket.once('data', function (data) {        console.log(JSON.stringify(data));    });    socket.on('error', function (err) { console.error(`error:${err.message}`); });});server.listen(11100);
在浏览器中设置Socks5代理

NodeJS实现简单的Socks5代理服务,NodeJSSocks5代理搭建,NodeSocks5搭建,NodeSocks5代理,Socks5搭建,Socks5代理,s5代理,s5搭建 互联网IT 第1张测试效果:

NodeJS实现简单的Socks5代理服务,NodeJSSocks5代理搭建,NodeSocks5搭建,NodeSocks5代理,Socks5搭建,Socks5代理,s5代理,s5搭建 互联网IT 第2张

首次响应请求

上面我们获取到了首次请求的数据,根据SOCKS5协议我们可以知道其含义如下:

-VERSIONMETHODS_COUNTMETHODS...
data0x050x010x00
说明协议版本,目前固定0x05客户端支持的认证方法数量不需要认证

而我们在无需验证的情况下直接返回的结果如下:

-VERSIONMETHOD
data0x050x00
说明SOCKS协议版本,目前固定0x05本次连接所用的认证方法,上例中为无需认证

根据协议添加协议验证与响应:

//....let server = net.createServer(function (socket) {    socket.once('data', function (data) {        if (!data || data[0] !== 0x05) return socket.destroy();        socket.write(Buffer.from([5, 0]), function (err) {            if (err) socket.destroy();            socket.once('data', (data) => {                console.log(JSON.stringify(data));            });        });    });//....});//....
测试效果:

NodeJS实现简单的Socks5代理服务,NodeJSSocks5代理搭建,NodeSocks5搭建,NodeSocks5代理,Socks5搭建,Socks5代理,s5代理,s5搭建 互联网IT 第3张

实现请求解析

客户端在收到认证成功的消息后,会给代理服务器发送命令,其含义简介如下:

-VERSIONCOMMANDRSVADDRESS_TYPEDST.ADDRDST.PORT
长度1字节1字节1字节1字节1-255字节2字节
说明SOCKS协议版本,固定0x05命令(本文只实现CONNECT)保留字段目标服务器地址类型(本文仅实现IP V4与域名)目标地址端口

需要说的是在域名类型下,域名地址第1个字节为域名长度,剩下字节为域名名称字节数组

而服务端解析成功后,需要情况进行对应的响应:

-VERSIONRESPONSERSVADDRESS_TYPEBND.ADDRBND.PORT
长度1字节1字节1字节1字节1-255字节2字节
说明SOCKS协议版本,固定0x05响应命令保留字段代理服务器地址类型代理服务器地址代理服务器端口

RESPONSE 响应命令:

  • 0x00 代理服务器连接目标服务器成功

  • 0x01 代理服务器故障

  • 0x02 代理服务器规则集不允许连接

  • 0x03 网络无法访问

  • 0x04 目标服务器无法访问(主机名无效)

  • 0x05 连接目标服务器被拒绝

  • 0x06 TTL已过期

  • 0x07 不支持的命令

  • 0x08 不支持的目标服务器地址类型

  • 0x09 - 0xFF 未分配

我们响应的服务端地址默认是1,也就是ip v4,地址与端口可以直接就写0x00。

根据SOCKS5协议中命令部分,编写以下代码:

//...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地址            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");        }        console.log(`connecting : ${remoteAddr}:${remotePort}`);    } catch (e) {        console.error(e);    }});//...
测试效果:

NodeJS实现简单的Socks5代理服务,NodeJSSocks5代理搭建,NodeSocks5搭建,NodeSocks5代理,Socks5搭建,Socks5代理,s5代理,s5搭建 互联网IT 第4张

实现代理:

解析成功之后我们就可以实现正式的代理了,

代理部分很简单,创建一个TCP客户端请求,将请求信息转发给解析出来的IP与端口就行了。

//....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();});//....
效果测试

本人目前在杭州,在自己老家有一台香橙派作为自己平时的测试服务器,

这里我通过远程将服务部署在香橙派上作为测试。




  • 发表评论
  • 查看评论
【暂无评论!】

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。