你的位置:首页 > 互联网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长度为 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代理服务
前言
最近在网上看到一篇文章《你也能写个 Shadowsocks》,于是处于好奇就了解到了SOCKS5协议。
这里我就根据SOCKS5协议,通过NodeJS实现一个最简单的,没有加密,不需要认证Socks5代理服务。
我相信大家都听过Socket,而Socks5协议是一种网络传输协议,常用过代理,之前很有名的shadow socks也是基于此协议实现的。这里大家单词可不要看错了。
编写TCP服务
我们使用NodeJS的net
模块编写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代理
测试效果:
首次响应请求
上面我们获取到了首次请求的数据,根据SOCKS5协议我们可以知道其含义如下:
- | VERSION | METHODS_COUNT | METHODS... |
---|---|---|---|
data | 0x05 | 0x01 | 0x00 |
说明 | 协议版本,目前固定0x05 | 客户端支持的认证方法数量 | 不需要认证 |
而我们在无需验证的情况下直接返回的结果如下:
- | VERSION | METHOD |
---|---|---|
data | 0x05 | 0x00 |
说明 | 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)); }); }); });//....});//....
测试效果:
实现请求解析
客户端在收到认证成功的消息后,会给代理服务器发送命令,其含义简介如下:
- | VERSION | COMMAND | RSV | ADDRESS_TYPE | DST.ADDR | DST.PORT |
---|---|---|---|---|---|---|
长度 | 1字节 | 1字节 | 1字节 | 1字节 | 1-255字节 | 2字节 |
说明 | SOCKS协议版本,固定0x05 | 命令(本文只实现CONNECT) | 保留字段 | 目标服务器地址类型(本文仅实现IP V4与域名) | 目标地址 | 端口 |
需要说的是在域名类型下,域名地址第1个字节为域名长度,剩下字节为域名名称字节数组
而服务端解析成功后,需要情况进行对应的响应:
- | VERSION | RESPONSE | RSV | ADDRESS_TYPE | BND.ADDR | BND.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); }});//...
测试效果:
实现代理:
解析成功之后我们就可以实现正式的代理了,
代理部分很简单,创建一个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();});//....
效果测试
本人目前在杭州,在自己老家有一台香橙派作为自己平时的测试服务器,
这里我通过远程将服务部署在香橙派上作为测试。
发表评论: