@nwct/demo 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,12 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <module type="WEB_MODULE" version="4">
3
+ <component name="NewModuleRootManager">
4
+ <content url="file://$MODULE_DIR$">
5
+ <excludeFolder url="file://$MODULE_DIR$/temp" />
6
+ <excludeFolder url="file://$MODULE_DIR$/.tmp" />
7
+ <excludeFolder url="file://$MODULE_DIR$/tmp" />
8
+ </content>
9
+ <orderEntry type="inheritedJdk" />
10
+ <orderEntry type="sourceFolder" forTests="false" />
11
+ </component>
12
+ </module>
@@ -0,0 +1,8 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="ProjectModuleManager">
4
+ <modules>
5
+ <module fileurl="file://$PROJECT_DIR$/.idea/mapping-net-main.iml" filepath="$PROJECT_DIR$/.idea/mapping-net-main.iml" />
6
+ </modules>
7
+ </component>
8
+ </project>
package/README.md ADDED
@@ -0,0 +1,113 @@
1
+ # nodejs 实现的 tcp 内网穿透、映射外网服务
2
+
3
+ ### 使用安装
4
+
5
+ - `npm i -g @mapping/net`,安装完成通过以下指令启动服务
6
+ - `mapping server --server_port 81 --token "helloServer"`
7
+
8
+
9
+ - `npm init mapping`,免安装可以直接使用以下指令
10
+ - 客户端:`npm init mapping client --server_addr 166.169.66.99 --server_port 81 --token "helloServer" --local_ip 127.0.0.1 --local_port 4000 --remote_port 80`
11
+ - 服务端:`npm init mapping server --server_port 81 --token "helloServer"`
12
+
13
+
14
+ - 通过`git`安装
15
+ - `git clone https://github.com/code-ba/mapping-net.git`
16
+ - `cd mapping-net && npm install`
17
+ - 通过指令启动,如`npm run client` or `npm run server`(启动多个服务需要配置)
18
+ - 配置`config.client.js`、`config.server.js`
19
+ - 通过指令启动单个服务:
20
+ - `node bin/index.js client --server_addr 166.169.66.99`
21
+ - `node bin/index.js server --server_port 81`
22
+
23
+
24
+ ---
25
+
26
+ ### 指令
27
+
28
+ - 客户端
29
+ ```c
30
+ $ mapping client --help
31
+ Usage: mapping client [options]
32
+ Options:
33
+ --server_addr <server_addr> 服务端地址(默认:0.0.0.0)
34
+ --server_port <server_port> 服务端端口(默认:10000)
35
+ --token <token> 连接令牌(默认:aksda@$@#kjsk)
36
+ --timeout <timeout> 请求超时时间(默认:3000)
37
+ --interval <interval> 连接令牌(默认:5000)
38
+ --binds <binds> 连接令牌(默认:ssh)
39
+ --local_ip <local_ip> 内网被转发的ip(默认:127.0.0.1)
40
+ --local_port <local_port> 内网被转发的端口(默认:80)
41
+ --remote_port <remote_port> 服务端映射的端口(默认:80)
42
+ -h, --help display help for command
43
+ ```
44
+
45
+ - 服务端
46
+ ```c
47
+ $ mapping server --help
48
+ Usage: mapping server [options]
49
+ Options:
50
+ --server_addr <server_addr> 服务端地址(默认:0.0.0.0)
51
+ --server_port <server_port> 服务端端口(默认:10000)
52
+ --token <token> 连接令牌(默认:aksda@$@#kjsk)
53
+ -h, --help display help for comman
54
+ ```
55
+
56
+ - 服务端后台启动方式
57
+ - `pm2 start -- run server`相当于`npm run server`(全局安装`pm2`可使用:`npm install -g pm2`)
58
+
59
+ ---
60
+
61
+ ### 客户端配置
62
+
63
+ ```js
64
+ // config.client.js
65
+ module.exports={
66
+ server_addr: "166.66.66.66",//服务端地址,纯IP,必须改
67
+ server_port: 10000,//服务端端口,客户端和服务端必须保持一致
68
+ token: "aksd()@$@#kjsk",//连接令牌,客户端和服务端必须保持一致
69
+ timeout: 3000,//请求超时时间
70
+ interval: 5000,//异常重试
71
+ binds: {//绑定内网应用
72
+ ssh: {
73
+ local_ip: "127.0.0.1",//当前内网被转发的ip
74
+ local_port: 80,//当前内网被转发的端口
75
+ remote_port: 10001,//服务端映射的端口
76
+ },
77
+ aria2: {
78
+ local_ip: "192.168.199.193",//当前内网被转发的ip
79
+ local_port: 6800,//当前内网被转发的端口
80
+ remote_port: 10002,//服务端映射的端口
81
+ },
82
+ aria2Ng: {
83
+ local_ip: "127.0.0.1",//当前内网被转发的ip
84
+ local_port: 80,//当前内网被转发的端口
85
+ remote_port: 10003,//服务端映射的端口
86
+ }
87
+ }
88
+ }
89
+ ```
90
+
91
+ ---
92
+
93
+ ### 服务端配置
94
+
95
+ ```js
96
+ // config.server.js
97
+ module.exports={
98
+ server_addr: "0.0.0.0",//服务端地址 一般是0.0.0.0或127.0.0.1,一般不需要改
99
+ server_port: 10000,//服务端端口,客户端和服务端必须保持一致
100
+ token: "aksd()@$@#kjsk",//连接令牌,客户端和服务端必须保持一致
101
+ }
102
+ ```
103
+
104
+ ---
105
+
106
+ ### 打赏
107
+
108
+ 您的支持是我持续更新的动力!
109
+
110
+ <img src="https://cdn.jsdelivr.net/gh/cxvh/static@main/img/20210218193037.png" width="200" height="200" alt="微信">
111
+ <img src="https://cdn.jsdelivr.net/gh/cxvh/static@main/img/20210218192738.jpg" width="200" height="200" alt="支付宝">
112
+
113
+ ---
package/bin/index.js ADDED
@@ -0,0 +1,7 @@
1
+ #! /usr/bin/env node
2
+ const importLocal=require('import-local')
3
+ if(importLocal(__filename)){
4
+ require('npmlog').info('正在使用本地版本')
5
+ }else{
6
+ require('../lib')(process.argv.slice(2))
7
+ }
@@ -0,0 +1,25 @@
1
+ module.exports={
2
+ server_addr: "8.141.174.71",//服务端地址,纯IP,必须改
3
+ server_port: 6001,//服务端端口,客户端和服务端必须保持一致
4
+ token: "aksda@$@#kjsk",//连接令牌,客户端和服务端必须保持一致
5
+ timeout: 3000,//请求超时时间
6
+ interval: 5000,//异常重试
7
+ binds: {//绑定内网应用
8
+ ssh: {
9
+ local_ip: "127.0.0.1",//当前内网被转发的ip
10
+ local_port: 80,//当前内网被转发的端口
11
+ remote_port: 8080,// 远程的端口
12
+ }
13
+ // ,
14
+ // aria2: {
15
+ // local_ip: "192.168.199.193",//当前内网被转发的ip
16
+ // local_port: 6800,//当前内网被转发的端口
17
+ // remote_port: 10002,//服务端映射的端口
18
+ // },
19
+ // aria2Ng: {
20
+ // local_ip: "127.0.0.1",//当前内网被转发的ip
21
+ // local_port: 90,//当前内网被转发的端口
22
+ // remote_port: 10003,//服务端映射的端口
23
+ // }
24
+ }
25
+ }
@@ -0,0 +1,5 @@
1
+ module.exports={
2
+ server_addr: "0.0.0.0",//服务端地址 一般是0.0.0.0或127.0.0.1,一般不需要改
3
+ server_port: 6001,//服务端端口,客户端和服务端必须保持一致
4
+ token: "aksda@$@#kjsk",//连接令牌,客户端和服务端必须保持一致,不支持空格
5
+ }
package/lib/client.js ADDED
@@ -0,0 +1,132 @@
1
+ const net = require('net');
2
+ const log=require('npmlog');
3
+ const envConfig=require('../config.client')
4
+ const defaultSsh={
5
+ local_ip: "127.0.0.1",//当前内网被转发的ip
6
+ local_port: 80,//当前内网被转发的端口
7
+ remote_port: 80,//服务端映射的端口
8
+ }
9
+ // 配置
10
+ const CONFIG = {
11
+ server_addr: "166.66.66.66",//服务端地址
12
+ server_port: 10000,//服务端端口
13
+ token: "aksda@$@#kjsk",//连接令牌
14
+ timeout: 3000,//请求超时时间
15
+ interval: 5000,//异常重试
16
+ binds: {//绑定内网应用
17
+ ssh: defaultSsh
18
+ },
19
+ ...envConfig
20
+ };
21
+ // 用于校验请求的code
22
+ let CODE;
23
+ let linkClient;
24
+ let runClient=false;
25
+ function listenClient(cmdObj) {
26
+ if(cmdObj){
27
+ CONFIG.server_addr=cmdObj.server_addr||CONFIG.server_addr;
28
+ CONFIG.server_port=cmdObj.server_port||CONFIG.server_port;
29
+ CONFIG.token=cmdObj.token||CONFIG.token;
30
+ CONFIG.timeout=cmdObj.timeout||CONFIG.timeout;
31
+ CONFIG.interval=cmdObj.interval||CONFIG.interval;
32
+ const binds=cmdObj.binds||'ssh';
33
+ var local_ip,local_port,remote_port
34
+ if(CONFIG.binds[binds]){
35
+ local_ip=cmdObj.local_ip||CONFIG.binds[binds].local_ip||defaultSsh.local_ip
36
+ local_port=cmdObj.local_port||CONFIG.binds[binds].local_port||defaultSsh.local_port
37
+ remote_port=cmdObj.remote_port||CONFIG.binds[binds].remote_port||defaultSsh.remote_port
38
+ }
39
+ CONFIG.binds[binds]={
40
+ local_ip,local_port,remote_port
41
+ }
42
+ }
43
+ log.info('客户端配置文件:',JSON.stringify(CONFIG,null,2))
44
+ if(runClient===false){
45
+ runClient=true;
46
+ tryError();
47
+ }
48
+ // 创建用于连接校验服务端的 客户端连接
49
+ linkClient = net.createConnection({ port: CONFIG.server_port, host: CONFIG.server_addr }, () => {
50
+ // 创建用于校验请求的code
51
+ CODE = (+new Date());
52
+ // 发送数据校验
53
+ linkClient.write(JSON.stringify({ token: CONFIG.token, code: CODE, type: 'register', binds: CONFIG.binds }));
54
+ console.log(`[${(new Date()).toLocaleString()}] 正在尝试连接...`);
55
+ });
56
+ linkClient.setTimeout(CONFIG.timeout);
57
+ linkClient.on('data', (data) => {
58
+ try {
59
+ data = JSON.parse(data);
60
+ // 校验请求
61
+ if (data.code == CODE) {
62
+ if (data.type == 'register') {
63
+ console.log(`[${(new Date()).toLocaleString()}] 已连接到服务器 ${CONFIG.server_addr}:${CONFIG.server_port}`);
64
+ } else {
65
+ // 请求标识
66
+ let key = data.key;
67
+ // 应用名称
68
+ let name = data.name;
69
+ // 本地的应用
70
+ let localApp = CONFIG.binds[name];
71
+ if (!localApp) linkClient.end();
72
+ // 创建服务端用的Socket
73
+ let serverClient = new net.Socket();
74
+ serverClient.setTimeout(CONFIG.timeout);
75
+ // 创建局域网内的Socket
76
+ let localClient = new net.Socket();
77
+ localClient.setTimeout(CONFIG.timeout);
78
+
79
+ // 连接服务端
80
+ serverClient.connect(CONFIG.server_port, CONFIG.server_addr, function () {
81
+ serverClient.write(JSON.stringify({ type: 'connect', key: key }));
82
+ // 连接本地服务器
83
+ localClient.connect(localApp.local_port, localApp.local_ip, function () {
84
+ console.log(`[${(new Date()).toLocaleString()}] [${name}] ${localApp.local_port}<===>${localApp.remote_port}`);
85
+ });
86
+ // 本地数据转发服务端
87
+ localClient.pipe(serverClient);
88
+ localClient.on('end', function (data) {
89
+ serverClient.end();
90
+ });
91
+ })
92
+ serverClient.on('error', function (err) {
93
+ console.error(`[${(new Date()).toLocaleString()}] 访问服务器异常,${err.message}`);
94
+ localClient.end();
95
+ })
96
+ localClient.on('error', function (err) {
97
+ console.error(`[${(new Date()).toLocaleString()}] 局域网访问异常,${err.message}`);
98
+ serverClient.end();
99
+ });
100
+ // 服务端数据转发本地
101
+ serverClient.pipe(localClient);
102
+ serverClient.on('end', function (data) {
103
+ localClient.end();
104
+ });
105
+ }
106
+ return;
107
+ }
108
+ } catch (error) {
109
+ // 异常
110
+ }
111
+ return linkClient.end();
112
+ });
113
+ linkClient.on('error', (err) => {
114
+ console.error(`[${(new Date()).toLocaleString()}] 异常:` + err.message);
115
+ });
116
+ linkClient.on('end', () => {
117
+ log.error(`[${(new Date()).toLocaleString()}] 已从服务器 ${CONFIG.server_port}:${CONFIG.server_port} 断开`)
118
+ });
119
+ }
120
+
121
+ //异常重试
122
+ function tryError(){
123
+ setInterval(() => {
124
+ if (linkClient.readyState == "closed") {
125
+ linkClient.end();
126
+ log.warn(`[${(new Date()).toLocaleString()}] 正在重新连接服务器...`)
127
+ listenClient();
128
+ }
129
+ }, CONFIG.interval);
130
+ }
131
+
132
+ module.exports=listenClient;
package/lib/index.js ADDED
@@ -0,0 +1,50 @@
1
+ module.exports = core;
2
+ const log=require('npmlog')
3
+ const colors=require('colors');
4
+ const commander=require('commander');
5
+ const program=new commander.Command();
6
+
7
+ const pkg=require('../package.json');
8
+ const client=require('./client')
9
+ const server=require('./server')
10
+
11
+ async function core() {
12
+ try{
13
+ // 命令注册
14
+ registerCommand()
15
+ }catch(e){
16
+ log.error(e.message);
17
+ if(program.debug){
18
+ console.log(e)
19
+ }
20
+ }
21
+ }
22
+ function registerCommand(){
23
+ program
24
+ .name(Object.keys(pkg.bin)[0])
25
+ .usage('<command> [options]')
26
+ .version(pkg.version)
27
+ // 命令注册
28
+ program
29
+ .command('client')
30
+ .option('--server_addr <server_addr>','服务端地址(默认:0.0.0.0)')
31
+ .option('--server_port <server_port>','服务端端口(默认:10000)')
32
+ .option('--local_port <local_port>','内网被转发的端口(默认:80)')
33
+ .action(client);
34
+ program
35
+ .command('server')
36
+ .action(server);
37
+ // 对未知命令进行监听
38
+ program.on('command:*',function(obj){
39
+ const availableCommands=program.commands.map(cmd=>cmd.name())
40
+ console.log(colors.red("未知命令:"+obj[0]));
41
+ if(availableCommands.length>0){
42
+ console.log(colors.red("可用命令:"+availableCommands.join(",")));
43
+ }
44
+ })
45
+ // 解析参数
46
+ program.parse(process.argv)
47
+ if(program.args&&program.args.length<1){
48
+ program.outputHelp()
49
+ }
50
+ }
package/lib/server.js ADDED
@@ -0,0 +1,128 @@
1
+ const net = require('net');
2
+ const log=require('npmlog');
3
+ const envConfig=require('../config.server')
4
+ // 配置
5
+ const CONFIG = {
6
+ server_addr: "0.0.0.0",//服务端地址 一般是0.0.0.0或127.0.0.1
7
+ server_port: 10000,//服务端端口
8
+ token: "aksda@$@#kjsk",//连接令牌
9
+ ...envConfig
10
+ };
11
+
12
+ // 客户端链接集
13
+ let linkClients = {};
14
+ // 客户端绑定的应用
15
+ let clientBings = {};
16
+ // 连接记录
17
+ let socketRecords = {};
18
+ // 删除相关信息
19
+ const removeInfo = function (id) {
20
+ if (linkClients[id]) {
21
+ linkClients[id] = null;
22
+ delete linkClients[id];
23
+ }
24
+ for (let k in clientBings) {
25
+ let d = clientBings[k];
26
+ if (id == d.linkId) {
27
+ d.forwardServer.close();
28
+ clientBings[k] = null;
29
+ delete clientBings[k];
30
+ }
31
+ }
32
+ };
33
+ // 端口转发服务 用于开放访问
34
+ function createForwardServer(conf) {
35
+ let forwardServer = net.createServer((socket) => {
36
+ // 判断客户是否在线
37
+ if (!linkClients[conf.linkId]) return socket.end();
38
+ let id = [socket.remoteAddress, socket.remoteFamily, socket.remotePort].join("_");
39
+ if (!socketRecords[id]) socketRecords[id] = { bind: socket };
40
+ // 发送需要数据 告诉客户端 开启新的连接用于访问
41
+ conf.linkSocket.write(JSON.stringify({ key: id, name: conf.name, code: conf.code }));
42
+ socket.on('error', () => {
43
+ socket.end();
44
+ });
45
+ socket.on('end', () => {
46
+ if (socketRecords[id]) {
47
+ if (socketRecords[id].bind) socketRecords[id].client.end();
48
+ if (socketRecords[id].client) socketRecords[id].bind.end();
49
+ delete socketRecords[id];
50
+ }
51
+ })
52
+ });
53
+ forwardServer.listen(conf.remote_port, () => {
54
+ console.log(`[${(new Date()).toLocaleString()}] [${conf.name}] 转发服务开启 ${conf.local_port}<===>${conf.remote_port}`);
55
+ });
56
+ return forwardServer;
57
+ }
58
+ // 远程监听访问 用于穿透
59
+ const listenServer = net.createServer((socket) => {
60
+ let id = [socket.remoteAddress, socket.remoteFamily, socket.remotePort].join("_");
61
+ console.log(`[${(new Date()).toLocaleString()}] ${socket.remoteAddress}:${socket.remotePort} 上线...`);
62
+ if (!linkClients[id]) {
63
+ // 保存连接
64
+ linkClients[id] = socket;
65
+ socket.on('data', (data) => {
66
+ try {
67
+ try {
68
+ data = JSON.parse(data);
69
+ } catch (error) {
70
+ return;
71
+ }
72
+ let [token, type, code, binds] = [data.token, data.type, data.code, data.binds];
73
+ if (token != token) return socket.end();
74
+ if (type == 'register') {// 客户端注册
75
+ for (let k in binds) {
76
+ let d = binds[k];
77
+ if (!clientBings[k]) {
78
+ [d.code, d.name, d.linkSocket, d.linkId] = [data.code, k, socket, id];
79
+ d.forwardServer = createForwardServer(d);//绑定客户端App对应服务端开放的端口服务
80
+ clientBings[k] = d;
81
+ }
82
+ }
83
+ return socket.write(JSON.stringify({ code: code, type: type, id: id }));
84
+ } else if (type == 'connect') {// 客户端连接
85
+ let id = data.key;
86
+ let socketRecord = socketRecords[id];
87
+ if (socketRecord && socketRecord.bind && !socketRecord.client) {
88
+ socket.firstConnection = false;
89
+ socketRecord.client = socket;//设置 客户端连接soket
90
+ // 数据转发
91
+ socket.pipe(socketRecord.bind);
92
+ socketRecord.bind.pipe(socket);
93
+ socketRecord.bind.on('end', () => {
94
+ socket.end();
95
+ });
96
+ socketRecord.bind.on('error', (err) => {
97
+ socket.end();
98
+ });
99
+ return;
100
+ }
101
+ }
102
+ } catch (error) {
103
+ //
104
+ removeInfo(id);
105
+ }
106
+ socket.end();
107
+ });
108
+ socket.on('error', (err) => {
109
+ //
110
+ removeInfo(id);
111
+ })
112
+ socket.on('end', (data) => {
113
+ removeInfo(id);
114
+ });
115
+ }
116
+ });
117
+ function listenServe(cmdObj){
118
+ if(cmdObj){
119
+ CONFIG.server_addr=cmdObj.server_addr||CONFIG.server_addr;
120
+ CONFIG.server_port=cmdObj.server_port||CONFIG.server_port;
121
+ CONFIG.token=cmdObj.token||CONFIG.token;
122
+ }
123
+ log.info('服务端配置文件:',JSON.stringify(CONFIG,null,2))
124
+ // 启动服务端监听
125
+ listenServer.listen(CONFIG.server_port, CONFIG.server_addr);
126
+ }
127
+
128
+ module.exports=listenServe;
package/package.json ADDED
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "@nwct/demo",
3
+ "version": "1.0.0",
4
+ "description": "Internal network penetration, mapping external network",
5
+ "main": "bin/index.js",
6
+ "bin": {
7
+ "demo": "bin/index.js"
8
+ },
9
+ "scripts": {
10
+ "test": "echo \"Error: no test specified\" && exit 1",
11
+ "start": "node bin/index.js client",
12
+ "client": "node bin/index.js client",
13
+ "server": "node bin/index.js server"
14
+ },
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "git+https://github.com/code-ba/mapping-net.git"
18
+ },
19
+ "keywords": [
20
+ "network",
21
+ "mapping"
22
+ ],
23
+ "author": "Baran",
24
+ "license": "ISC",
25
+ "bugs": {
26
+ "url": "https://github.com/code-ba/mapping-net/issues"
27
+ },
28
+ "homepage": "https://github.com/code-ba/mapping-net#readme",
29
+ "dependencies": {
30
+ "colors": "^1.4.0",
31
+ "commander": "^8.0.0",
32
+ "import-local": "^3.0.2",
33
+ "npmlog": "^4.1.2"
34
+ },
35
+ "publishConfig": {
36
+ "access": "public"
37
+ }
38
+ }