@nwct/demo 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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
+ }