├── LICENSE ├── README.md ├── client ├── config.js ├── package-lock.json ├── package.json └── tunnel-client.js ├── image.png └── server ├── config.js ├── core ├── authentication.js ├── decrypt.js ├── encrypt.js ├── socket.js ├── tcp-id.js ├── tcp.js └── tunneling.js ├── package-lock.json ├── package.json └── tunnel-server.js /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License with Attribution (MIT-CA) 2 | 3 | Copyright 2023 ABDI SYAHPUTRA HARAHAP 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | Attribution Requirement: 10 | 11 | If you use, modify, or distribute this software or any portion thereof, you must give appropriate attribution to ABDI SYAHPUTRA HARAHAP as the original creator of the software, and you must include the following information: 12 | 13 | - The name "ABDI SYAHPUTRA HARAHAP" must be prominently mentioned. 14 | 15 | This attribution requirement applies to any derivative works based on this software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS," WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 18 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # localhost-tunnel-websocket 2 | Exposing the localhost network to the public network through a WebSocket tunnel. TCP data exchange between the local server and the public server is routed through a WebSocket connection with additional AES 256 encryption. 3 | 4 | ![Image](image.png) 5 | 6 | This can be used to expose local networks such as SSH, RDP, web servers (HTTP), and other networks that use the TCP protocol. 7 | 8 | This script uses one of the following packages: 9 | - [Socket.io](https://www.npmjs.com/package/socket.io) 10 | - [express](https://www.npmjs.com/package/express) 11 | 12 | # How to Use: 13 | 14 | ## Server Tunnel Installation: 15 | 16 | 1. Clone the repository. 17 | 2. CD into the `server` directory. 18 | 3. Perform the installation: `npm install` 19 | 4. Open the `config.js` file. 20 | 5. Perform the configuration. 21 | - `port-tunnel`: The port used for the connection between the server tunnel and the client tunnel. 22 | - `port-tcp`: The port used to receive TCP connections on the server side. 23 | - `tcp-traffic-encryption`: Do you want to encrypt the flow of TCP data? `"key"` is the encryption key that will be used on the server tunnel and client. 24 | - `tunnel-authentication`: Used for authentication to the client. The `"token"` value between the server and client must be the same. 25 | 6. After that, run: `node tunnel-server.js` 26 | 27 | Make sure to follow the above steps correctly to successfully install and run the server tunnel. 28 | 29 | Note: 30 | - Ensure that you have installed Node.js and npm before running the `npm install` command. 31 | 32 | 33 | 34 | ## Client Tunnel Installation: 35 | 36 | 1. Please clone the repository. 37 | 2. CD into the `client` directory. 38 | 3. Perform the installation: `npm install` 39 | 4. Open the `config.js` file. 40 | 5. Perform the configuration. 41 | - `host-tunnel`: IP address of the tunnel server. 42 | - `port-tunnel`: The port used to establish a connection to the tunnel server. 43 | - `host-tcp`: IP address of the localhost or local server you want to expose to the public. 44 | - `port-tcp`: The port of the localhost. 45 | - `tcp-traffic-encryption-key`: The encryption key to be used in the server tunnel. 46 | - `tunnel-authentication`: Used for authentication to the server tunnel. The `"token"` value between the server and client must be the same. 47 | 6. After that, run: `node tunnel-client.js` 48 | 49 | Make sure to follow the above steps correctly to successfully install and run the client tunnel. 50 | 51 | Note: 52 | - Ensure that you have installed Node.js and npm before running the `npm install` command. 53 | -------------------------------------------------------------------------------- /client/config.js: -------------------------------------------------------------------------------- 1 | export default ({ 2 | "host-tunnel" : "123.123.123.123", 3 | "port-tunnel" : 80, 4 | "host-tcp" : "localhost", 5 | "port-tcp" : 80, 6 | "tcp-traffic-encryption-key":"pantek69", 7 | "tunnel-authentication":{ 8 | "token":"asedekontil66" 9 | } 10 | }); 11 | -------------------------------------------------------------------------------- /client/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tunnel-client", 3 | "version": "1.0.0", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "tunnel-client", 9 | "version": "1.0.0", 10 | "license": "ISC", 11 | "dependencies": { 12 | "crypto": "^1.0.1", 13 | "socket.io-client": "^4.7.2" 14 | } 15 | }, 16 | "node_modules/@socket.io/component-emitter": { 17 | "version": "3.1.0", 18 | "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz", 19 | "integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==" 20 | }, 21 | "node_modules/crypto": { 22 | "version": "1.0.1", 23 | "resolved": "https://registry.npmjs.org/crypto/-/crypto-1.0.1.tgz", 24 | "integrity": "sha512-VxBKmeNcqQdiUQUW2Tzq0t377b54N2bMtXO/qiLa+6eRRmmC4qT3D4OnTGoT/U6O9aklQ/jTwbOtRMTTY8G0Ig==", 25 | "deprecated": "This package is no longer supported. It's now a built-in Node module. If you've depended on crypto, you should switch to the one that's built-in." 26 | }, 27 | "node_modules/debug": { 28 | "version": "4.3.4", 29 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", 30 | "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", 31 | "dependencies": { 32 | "ms": "2.1.2" 33 | }, 34 | "engines": { 35 | "node": ">=6.0" 36 | }, 37 | "peerDependenciesMeta": { 38 | "supports-color": { 39 | "optional": true 40 | } 41 | } 42 | }, 43 | "node_modules/engine.io-client": { 44 | "version": "6.5.2", 45 | "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.5.2.tgz", 46 | "integrity": "sha512-CQZqbrpEYnrpGqC07a9dJDz4gePZUgTPMU3NKJPSeQOyw27Tst4Pl3FemKoFGAlHzgZmKjoRmiJvbWfhCXUlIg==", 47 | "dependencies": { 48 | "@socket.io/component-emitter": "~3.1.0", 49 | "debug": "~4.3.1", 50 | "engine.io-parser": "~5.2.1", 51 | "ws": "~8.11.0", 52 | "xmlhttprequest-ssl": "~2.0.0" 53 | } 54 | }, 55 | "node_modules/engine.io-parser": { 56 | "version": "5.2.1", 57 | "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.1.tgz", 58 | "integrity": "sha512-9JktcM3u18nU9N2Lz3bWeBgxVgOKpw7yhRaoxQA3FUDZzzw+9WlA6p4G4u0RixNkg14fH7EfEc/RhpurtiROTQ==", 59 | "engines": { 60 | "node": ">=10.0.0" 61 | } 62 | }, 63 | "node_modules/ms": { 64 | "version": "2.1.2", 65 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 66 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" 67 | }, 68 | "node_modules/socket.io-client": { 69 | "version": "4.7.2", 70 | "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.7.2.tgz", 71 | "integrity": "sha512-vtA0uD4ibrYD793SOIAwlo8cj6haOeMHrGvwPxJsxH7CeIksqJ+3Zc06RvWTIFgiSqx4A3sOnTXpfAEE2Zyz6w==", 72 | "dependencies": { 73 | "@socket.io/component-emitter": "~3.1.0", 74 | "debug": "~4.3.2", 75 | "engine.io-client": "~6.5.2", 76 | "socket.io-parser": "~4.2.4" 77 | }, 78 | "engines": { 79 | "node": ">=10.0.0" 80 | } 81 | }, 82 | "node_modules/socket.io-parser": { 83 | "version": "4.2.4", 84 | "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", 85 | "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", 86 | "dependencies": { 87 | "@socket.io/component-emitter": "~3.1.0", 88 | "debug": "~4.3.1" 89 | }, 90 | "engines": { 91 | "node": ">=10.0.0" 92 | } 93 | }, 94 | "node_modules/ws": { 95 | "version": "8.11.0", 96 | "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", 97 | "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", 98 | "engines": { 99 | "node": ">=10.0.0" 100 | }, 101 | "peerDependencies": { 102 | "bufferutil": "^4.0.1", 103 | "utf-8-validate": "^5.0.2" 104 | }, 105 | "peerDependenciesMeta": { 106 | "bufferutil": { 107 | "optional": true 108 | }, 109 | "utf-8-validate": { 110 | "optional": true 111 | } 112 | } 113 | }, 114 | "node_modules/xmlhttprequest-ssl": { 115 | "version": "2.0.0", 116 | "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz", 117 | "integrity": "sha512-QKxVRxiRACQcVuQEYFsI1hhkrMlrXHPegbbd1yn9UHOmRxY+si12nQYzri3vbzt8VdTTRviqcKxcyllFas5z2A==", 118 | "engines": { 119 | "node": ">=0.4.0" 120 | } 121 | } 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /client/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tunnel-client", 3 | "version": "1.0.0", 4 | "description": "Connects to the websocket tunnel server", 5 | "main": "client.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "Abdi Syahputra Harahap", 11 | "license": "ISC", 12 | "type": "module", 13 | "dependencies": { 14 | "crypto": "^1.0.1", 15 | "socket.io-client": "^4.7.2" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /client/tunnel-client.js: -------------------------------------------------------------------------------- 1 | import config from "./config.js"; 2 | import net from "net"; 3 | import { io } from "socket.io-client"; 4 | import crypto from "crypto"; 5 | const encryptionKeyText = config["tcp-traffic-encryption-key"]; 6 | const encryptionKey = Buffer.alloc(32); 7 | encryptionKey.write(encryptionKeyText, 'utf-8'); 8 | const socket = io("http://"+config["host-tunnel"]+":"+config["port-tunnel"], { 9 | reconnectionDelayMax: 10000, 10 | auth: { 11 | token: config["tunnel-authentication"].token 12 | } 13 | }); 14 | let channel_tcp = {}; 15 | socket.on("tcp-server-data",(obj)=>{ 16 | const id = obj.id; 17 | const data = obj.buff; 18 | if(channel_tcp[id]==undefined){ 19 | channel_tcp[id]=net.connect({ 20 | host: config["host-tcp"], 21 | port: config["port-tcp"] 22 | }, () => { 23 | console.log('Terhubung ke server!'); 24 | const iv = data.slice(0, 16); 25 | const encryptedContent = data.slice(16); 26 | const decipher = crypto.createDecipheriv('aes-256-cbc', encryptionKey, iv); 27 | const decryptedData = Buffer.concat([decipher.update(encryptedContent), decipher.final()]); 28 | channel_tcp[id].write(decryptedData); 29 | }).on('data', (dataTcp) => { 30 | const dataToEncrypt = Buffer.from(dataTcp); 31 | const iv = crypto.randomBytes(16); 32 | const cipher = crypto.createCipheriv('aes-256-cbc', encryptionKey, iv); 33 | const encryptedBuffer = Buffer.concat([iv, cipher.update(dataToEncrypt), cipher.final()]); 34 | socket.emit("tcp-client-data",id,encryptedBuffer); 35 | }).on('end', () => { 36 | socket.emit("tcp-client-end",id); 37 | }).on('error', (err) => { 38 | console.error('Kesalahan pada koneksi client:', err); 39 | socket.emit("tcp-client-error",id,err); 40 | channel_tcp[id].end(); 41 | channel_tcp[id].destroy(); 42 | }); 43 | }else{ 44 | const iv = data.slice(0, 16); 45 | const encryptedContent = data.slice(16); 46 | const decipher = crypto.createDecipheriv('aes-256-cbc', encryptionKey, iv); 47 | const decryptedData = Buffer.concat([decipher.update(encryptedContent), decipher.final()]); 48 | channel_tcp[id].write(decryptedData); 49 | }; 50 | }); 51 | socket.on("connect", () => { 52 | console.log("Tunnel Conected..."); 53 | }); 54 | socket.on("tcp-server-end",(id)=>{ 55 | // console.log("tcp-server-end",id); 56 | }); 57 | socket.on("tcp-server-close",(id)=>{ 58 | // console.log("tcp-server-close",id); 59 | }); 60 | socket.on("tcp-server-error",(id,err)=>{ 61 | // console.log("tcp-server-error",id,err); 62 | }); 63 | socket.on("connect_error", (err) => { 64 | console.log(err.message); 65 | }); 66 | -------------------------------------------------------------------------------- /image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maskodingku/localhost-tunnel-websocket/169cbf7a60d200bf1aea623000b7e843782ff0a0/image.png -------------------------------------------------------------------------------- /server/config.js: -------------------------------------------------------------------------------- 1 | export default ({ 2 | "port-tunnel" : 80, 3 | "port-tcp":8081, 4 | "tcp-traffic-encryption":{ 5 | "status":true, 6 | "key":"pantek69" 7 | }, 8 | "tunnel-authentication":{ 9 | "token":"asedekontil66" 10 | } 11 | }); 12 | -------------------------------------------------------------------------------- /server/core/authentication.js: -------------------------------------------------------------------------------- 1 | export default (socket, next, config)=>{ 2 | if(socket.handshake.auth && socket.handshake.auth.token){ 3 | if(socket.handshake.auth.token==config["tunnel-authentication"].token){ 4 | return next(); 5 | }else{ 6 | return next(new Error('Authentication error, Invalid Token !')); 7 | }; 8 | }else{ 9 | return next(new Error('Authentication error, Token Not Found!')); 10 | }; 11 | }; 12 | -------------------------------------------------------------------------------- /server/core/decrypt.js: -------------------------------------------------------------------------------- 1 | import crypto from "crypto"; 2 | export default (buff,key)=>{ 3 | const encryptionKey = Buffer.alloc(32); 4 | encryptionKey.write(key, 'utf-8'); 5 | const iv = buff.slice(0, 16); 6 | const decryptedContent = buff.slice(16); 7 | const decipher = crypto.createDecipheriv('aes-256-cbc', encryptionKey, iv); 8 | const decryptedData = Buffer.concat([decipher.update(decryptedContent), decipher.final()]); 9 | return decryptedData; 10 | }; 11 | -------------------------------------------------------------------------------- /server/core/encrypt.js: -------------------------------------------------------------------------------- 1 | import crypto from "crypto"; 2 | export default (buff,key)=>{ 3 | const encryptionKey = Buffer.alloc(32); 4 | encryptionKey.write(key, 'utf-8'); 5 | const dataToEncrypt = Buffer.from(buff); 6 | const iv = crypto.randomBytes(16); 7 | const cipher = crypto.createCipheriv('aes-256-cbc', encryptionKey, iv); 8 | const encryptedBuffer = Buffer.concat([iv, cipher.update(dataToEncrypt), cipher.final()]); 9 | return encryptedBuffer; 10 | }; 11 | -------------------------------------------------------------------------------- /server/core/socket.js: -------------------------------------------------------------------------------- 1 | import { Server } from 'socket.io'; 2 | import authentication from "./authentication.js"; 3 | export default { 4 | "init" : async (server_app,config) => { 5 | return new Promise((resolve)=>{ 6 | const port = config["port-tunnel"]; 7 | const tunnel = new Server(server_app,{ 8 | 'maxHttpBufferSize': 1000000 9 | }).use((socket, next)=>{ 10 | authentication(socket, next, config); 11 | }); 12 | server_app.listen(port, () => { 13 | console.log('Tunnel listening on port :',port); 14 | resolve(tunnel); 15 | }); 16 | }); 17 | } 18 | }; 19 | -------------------------------------------------------------------------------- /server/core/tcp-id.js: -------------------------------------------------------------------------------- 1 | const list_ID = {}; 2 | export default { 3 | "register" : (clientTcp)=>{ 4 | const cap = new Date().getTime(); 5 | list_ID[cap]=clientTcp; 6 | console.log("Total Koneksi :",Object.keys(list_ID).length) 7 | return cap; 8 | }, 9 | "sendData" : (id,data)=>{ 10 | if(list_ID[id]!=undefined){ 11 | // const bufferData = Buffer.from(data); 12 | // console.log('Data diterima dari tunnel local lalu diforwarding ke tcp server:\n',data+""); 13 | list_ID[id].write(data); 14 | }; 15 | return; 16 | }, 17 | "sendEnd" : (id)=>{ 18 | if(list_ID[id]!=undefined){ 19 | list_ID[id].destroy(); 20 | delete list_ID[id]; 21 | }; 22 | return; 23 | }, 24 | "sendError" : (id)=>{ 25 | if(list_ID[id]!=undefined){ 26 | list_ID[id].destroy(); 27 | delete list_ID[id]; 28 | }; 29 | return; 30 | }, 31 | "remove" : (id)=>{ 32 | if(list_ID[id]!=undefined){ 33 | delete list_ID[id]; 34 | }; 35 | return; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /server/core/tcp.js: -------------------------------------------------------------------------------- 1 | import net from "net"; 2 | export default { 3 | "init" : async (port,server_tunnel)=>{ 4 | return new Promise((resolve)=>{ 5 | const server = net.createServer().listen(port, () => { 6 | console.log('Server TCP listening on port :',port); 7 | resolve(server); 8 | }); 9 | }); 10 | } 11 | }; 12 | -------------------------------------------------------------------------------- /server/core/tunneling.js: -------------------------------------------------------------------------------- 1 | import tcpId from "./tcp-id.js"; 2 | import encrypt from "./encrypt.js"; 3 | import decrypt from "./decrypt.js"; 4 | export default (tcp,tunnel,config)=>{ 5 | let client_socket = null; 6 | tcp.on('connection', (clientTcp) => { 7 | console.log('New TCP Connected...'); 8 | const id = tcpId.register(clientTcp); 9 | if(client_socket!=null){ 10 | // client_socket.emit("register-channel-tcp",id); 11 | }else{ 12 | tcpId.remove(id); 13 | clientTcp.end(); 14 | clientTcp.destroy(); 15 | }; 16 | clientTcp.on('data', (data) => { 17 | if(client_socket!=null){ 18 | // Enkripsi data sebelum mengirimkannya. 19 | const dataEncrypt = encrypt(data,config["tcp-traffic-encryption"].key); 20 | client_socket.emit("tcp-server-data",{ 21 | "id":id, 22 | "buff":dataEncrypt 23 | }); 24 | }; 25 | }).on('end', () => { 26 | console.log('Koneksi Tcp klien ditutup'); 27 | if(client_socket!=null){ 28 | client_socket.emit("tcp-server-end",id); 29 | tcpId.remove(id); 30 | // clientTcp.end(); 31 | clientTcp.destroy(); 32 | }else{ 33 | // clientTcp.end(); 34 | clientTcp.destroy(); 35 | }; 36 | }).on('close', () => { 37 | console.log('Koneksi Tcp client telah ditutup sepenuhnya.'); 38 | if(client_socket!=null){ 39 | client_socket.emit("tcp-server-close",id); 40 | tcpId.remove(id); 41 | // clientTcp.end(); 42 | clientTcp.destroy(); 43 | }else{ 44 | // clientTcp.end(); 45 | clientTcp.destroy(); 46 | }; 47 | }).on('error', (err) => { 48 | console.error('Kesalahan pada koneksi client:', err); 49 | if(client_socket!=null){ 50 | client_socket.emit("tcp-server-error",id,err); 51 | // clientTcp.end(); 52 | clientTcp.destroy(); 53 | }else{ 54 | // clientTcp.end(); 55 | clientTcp.destroy(); 56 | }; 57 | }); 58 | }); 59 | tunnel.on('connection', (socket) => { 60 | console.log('a user connected'); 61 | client_socket = socket; 62 | socket.on("tcp-client-data",(id,data)=>{ 63 | // Mendekripsi data yang diterima. 64 | const dataDecrypt = decrypt(data,config["tcp-traffic-encryption"].key); 65 | tcpId.sendData(id,dataDecrypt); 66 | }); 67 | socket.on("tcp-client-end",(id)=>{ 68 | console.log("tcp-client-end",id); 69 | tcpId.sendEnd(id); 70 | }); 71 | socket.on("tcp-client-error",(id,err)=>{ 72 | console.log("tcp-client-error",id,err); 73 | tcpId.sendError(id); 74 | }); 75 | socket.on('disconnect', () => { 76 | console.log('user disconnected'); 77 | client_socket = null; 78 | }); 79 | }); 80 | }; 81 | -------------------------------------------------------------------------------- /server/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "server", 3 | "version": "1.0.0", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "server", 9 | "version": "1.0.0", 10 | "license": "ISC", 11 | "dependencies": { 12 | "crypto": "^1.0.1", 13 | "express": "^4.18.2", 14 | "socket.io": "^4.7.2" 15 | } 16 | }, 17 | "node_modules/@socket.io/component-emitter": { 18 | "version": "3.1.0", 19 | "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz", 20 | "integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==" 21 | }, 22 | "node_modules/@types/cookie": { 23 | "version": "0.4.1", 24 | "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", 25 | "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==" 26 | }, 27 | "node_modules/@types/cors": { 28 | "version": "2.8.13", 29 | "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.13.tgz", 30 | "integrity": "sha512-RG8AStHlUiV5ysZQKq97copd2UmVYw3/pRMLefISZ3S1hK104Cwm7iLQ3fTKx+lsUH2CE8FlLaYeEA2LSeqYUA==", 31 | "dependencies": { 32 | "@types/node": "*" 33 | } 34 | }, 35 | "node_modules/@types/node": { 36 | "version": "20.5.6", 37 | "resolved": "https://registry.npmjs.org/@types/node/-/node-20.5.6.tgz", 38 | "integrity": "sha512-Gi5wRGPbbyOTX+4Y2iULQ27oUPrefaB0PxGQJnfyWN3kvEDGM3mIB5M/gQLmitZf7A9FmLeaqxD3L1CXpm3VKQ==" 39 | }, 40 | "node_modules/accepts": { 41 | "version": "1.3.8", 42 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", 43 | "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", 44 | "dependencies": { 45 | "mime-types": "~2.1.34", 46 | "negotiator": "0.6.3" 47 | }, 48 | "engines": { 49 | "node": ">= 0.6" 50 | } 51 | }, 52 | "node_modules/array-flatten": { 53 | "version": "1.1.1", 54 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 55 | "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" 56 | }, 57 | "node_modules/base64id": { 58 | "version": "2.0.0", 59 | "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", 60 | "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", 61 | "engines": { 62 | "node": "^4.5.0 || >= 5.9" 63 | } 64 | }, 65 | "node_modules/body-parser": { 66 | "version": "1.20.1", 67 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", 68 | "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", 69 | "dependencies": { 70 | "bytes": "3.1.2", 71 | "content-type": "~1.0.4", 72 | "debug": "2.6.9", 73 | "depd": "2.0.0", 74 | "destroy": "1.2.0", 75 | "http-errors": "2.0.0", 76 | "iconv-lite": "0.4.24", 77 | "on-finished": "2.4.1", 78 | "qs": "6.11.0", 79 | "raw-body": "2.5.1", 80 | "type-is": "~1.6.18", 81 | "unpipe": "1.0.0" 82 | }, 83 | "engines": { 84 | "node": ">= 0.8", 85 | "npm": "1.2.8000 || >= 1.4.16" 86 | } 87 | }, 88 | "node_modules/body-parser/node_modules/debug": { 89 | "version": "2.6.9", 90 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 91 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 92 | "dependencies": { 93 | "ms": "2.0.0" 94 | } 95 | }, 96 | "node_modules/body-parser/node_modules/ms": { 97 | "version": "2.0.0", 98 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 99 | "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" 100 | }, 101 | "node_modules/bytes": { 102 | "version": "3.1.2", 103 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", 104 | "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", 105 | "engines": { 106 | "node": ">= 0.8" 107 | } 108 | }, 109 | "node_modules/call-bind": { 110 | "version": "1.0.2", 111 | "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", 112 | "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", 113 | "dependencies": { 114 | "function-bind": "^1.1.1", 115 | "get-intrinsic": "^1.0.2" 116 | }, 117 | "funding": { 118 | "url": "https://github.com/sponsors/ljharb" 119 | } 120 | }, 121 | "node_modules/content-disposition": { 122 | "version": "0.5.4", 123 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", 124 | "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", 125 | "dependencies": { 126 | "safe-buffer": "5.2.1" 127 | }, 128 | "engines": { 129 | "node": ">= 0.6" 130 | } 131 | }, 132 | "node_modules/content-type": { 133 | "version": "1.0.5", 134 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", 135 | "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", 136 | "engines": { 137 | "node": ">= 0.6" 138 | } 139 | }, 140 | "node_modules/cookie": { 141 | "version": "0.4.2", 142 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", 143 | "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", 144 | "engines": { 145 | "node": ">= 0.6" 146 | } 147 | }, 148 | "node_modules/cookie-signature": { 149 | "version": "1.0.6", 150 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 151 | "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" 152 | }, 153 | "node_modules/cors": { 154 | "version": "2.8.5", 155 | "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", 156 | "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", 157 | "dependencies": { 158 | "object-assign": "^4", 159 | "vary": "^1" 160 | }, 161 | "engines": { 162 | "node": ">= 0.10" 163 | } 164 | }, 165 | "node_modules/crypto": { 166 | "version": "1.0.1", 167 | "resolved": "https://registry.npmjs.org/crypto/-/crypto-1.0.1.tgz", 168 | "integrity": "sha512-VxBKmeNcqQdiUQUW2Tzq0t377b54N2bMtXO/qiLa+6eRRmmC4qT3D4OnTGoT/U6O9aklQ/jTwbOtRMTTY8G0Ig==", 169 | "deprecated": "This package is no longer supported. It's now a built-in Node module. If you've depended on crypto, you should switch to the one that's built-in." 170 | }, 171 | "node_modules/debug": { 172 | "version": "4.3.4", 173 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", 174 | "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", 175 | "dependencies": { 176 | "ms": "2.1.2" 177 | }, 178 | "engines": { 179 | "node": ">=6.0" 180 | }, 181 | "peerDependenciesMeta": { 182 | "supports-color": { 183 | "optional": true 184 | } 185 | } 186 | }, 187 | "node_modules/depd": { 188 | "version": "2.0.0", 189 | "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", 190 | "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", 191 | "engines": { 192 | "node": ">= 0.8" 193 | } 194 | }, 195 | "node_modules/destroy": { 196 | "version": "1.2.0", 197 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", 198 | "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", 199 | "engines": { 200 | "node": ">= 0.8", 201 | "npm": "1.2.8000 || >= 1.4.16" 202 | } 203 | }, 204 | "node_modules/ee-first": { 205 | "version": "1.1.1", 206 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 207 | "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" 208 | }, 209 | "node_modules/encodeurl": { 210 | "version": "1.0.2", 211 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 212 | "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", 213 | "engines": { 214 | "node": ">= 0.8" 215 | } 216 | }, 217 | "node_modules/engine.io": { 218 | "version": "6.5.2", 219 | "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.2.tgz", 220 | "integrity": "sha512-IXsMcGpw/xRfjra46sVZVHiSWo/nJ/3g1337q9KNXtS6YRzbW5yIzTCb9DjhrBe7r3GZQR0I4+nq+4ODk5g/cA==", 221 | "dependencies": { 222 | "@types/cookie": "^0.4.1", 223 | "@types/cors": "^2.8.12", 224 | "@types/node": ">=10.0.0", 225 | "accepts": "~1.3.4", 226 | "base64id": "2.0.0", 227 | "cookie": "~0.4.1", 228 | "cors": "~2.8.5", 229 | "debug": "~4.3.1", 230 | "engine.io-parser": "~5.2.1", 231 | "ws": "~8.11.0" 232 | }, 233 | "engines": { 234 | "node": ">=10.2.0" 235 | } 236 | }, 237 | "node_modules/engine.io-parser": { 238 | "version": "5.2.1", 239 | "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.1.tgz", 240 | "integrity": "sha512-9JktcM3u18nU9N2Lz3bWeBgxVgOKpw7yhRaoxQA3FUDZzzw+9WlA6p4G4u0RixNkg14fH7EfEc/RhpurtiROTQ==", 241 | "engines": { 242 | "node": ">=10.0.0" 243 | } 244 | }, 245 | "node_modules/escape-html": { 246 | "version": "1.0.3", 247 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 248 | "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" 249 | }, 250 | "node_modules/etag": { 251 | "version": "1.8.1", 252 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 253 | "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", 254 | "engines": { 255 | "node": ">= 0.6" 256 | } 257 | }, 258 | "node_modules/express": { 259 | "version": "4.18.2", 260 | "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", 261 | "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", 262 | "dependencies": { 263 | "accepts": "~1.3.8", 264 | "array-flatten": "1.1.1", 265 | "body-parser": "1.20.1", 266 | "content-disposition": "0.5.4", 267 | "content-type": "~1.0.4", 268 | "cookie": "0.5.0", 269 | "cookie-signature": "1.0.6", 270 | "debug": "2.6.9", 271 | "depd": "2.0.0", 272 | "encodeurl": "~1.0.2", 273 | "escape-html": "~1.0.3", 274 | "etag": "~1.8.1", 275 | "finalhandler": "1.2.0", 276 | "fresh": "0.5.2", 277 | "http-errors": "2.0.0", 278 | "merge-descriptors": "1.0.1", 279 | "methods": "~1.1.2", 280 | "on-finished": "2.4.1", 281 | "parseurl": "~1.3.3", 282 | "path-to-regexp": "0.1.7", 283 | "proxy-addr": "~2.0.7", 284 | "qs": "6.11.0", 285 | "range-parser": "~1.2.1", 286 | "safe-buffer": "5.2.1", 287 | "send": "0.18.0", 288 | "serve-static": "1.15.0", 289 | "setprototypeof": "1.2.0", 290 | "statuses": "2.0.1", 291 | "type-is": "~1.6.18", 292 | "utils-merge": "1.0.1", 293 | "vary": "~1.1.2" 294 | }, 295 | "engines": { 296 | "node": ">= 0.10.0" 297 | } 298 | }, 299 | "node_modules/express/node_modules/cookie": { 300 | "version": "0.5.0", 301 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", 302 | "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", 303 | "engines": { 304 | "node": ">= 0.6" 305 | } 306 | }, 307 | "node_modules/express/node_modules/debug": { 308 | "version": "2.6.9", 309 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 310 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 311 | "dependencies": { 312 | "ms": "2.0.0" 313 | } 314 | }, 315 | "node_modules/express/node_modules/ms": { 316 | "version": "2.0.0", 317 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 318 | "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" 319 | }, 320 | "node_modules/finalhandler": { 321 | "version": "1.2.0", 322 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", 323 | "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", 324 | "dependencies": { 325 | "debug": "2.6.9", 326 | "encodeurl": "~1.0.2", 327 | "escape-html": "~1.0.3", 328 | "on-finished": "2.4.1", 329 | "parseurl": "~1.3.3", 330 | "statuses": "2.0.1", 331 | "unpipe": "~1.0.0" 332 | }, 333 | "engines": { 334 | "node": ">= 0.8" 335 | } 336 | }, 337 | "node_modules/finalhandler/node_modules/debug": { 338 | "version": "2.6.9", 339 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 340 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 341 | "dependencies": { 342 | "ms": "2.0.0" 343 | } 344 | }, 345 | "node_modules/finalhandler/node_modules/ms": { 346 | "version": "2.0.0", 347 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 348 | "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" 349 | }, 350 | "node_modules/forwarded": { 351 | "version": "0.2.0", 352 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", 353 | "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", 354 | "engines": { 355 | "node": ">= 0.6" 356 | } 357 | }, 358 | "node_modules/fresh": { 359 | "version": "0.5.2", 360 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", 361 | "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", 362 | "engines": { 363 | "node": ">= 0.6" 364 | } 365 | }, 366 | "node_modules/function-bind": { 367 | "version": "1.1.1", 368 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 369 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" 370 | }, 371 | "node_modules/get-intrinsic": { 372 | "version": "1.2.1", 373 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", 374 | "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", 375 | "dependencies": { 376 | "function-bind": "^1.1.1", 377 | "has": "^1.0.3", 378 | "has-proto": "^1.0.1", 379 | "has-symbols": "^1.0.3" 380 | }, 381 | "funding": { 382 | "url": "https://github.com/sponsors/ljharb" 383 | } 384 | }, 385 | "node_modules/has": { 386 | "version": "1.0.3", 387 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", 388 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", 389 | "dependencies": { 390 | "function-bind": "^1.1.1" 391 | }, 392 | "engines": { 393 | "node": ">= 0.4.0" 394 | } 395 | }, 396 | "node_modules/has-proto": { 397 | "version": "1.0.1", 398 | "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", 399 | "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", 400 | "engines": { 401 | "node": ">= 0.4" 402 | }, 403 | "funding": { 404 | "url": "https://github.com/sponsors/ljharb" 405 | } 406 | }, 407 | "node_modules/has-symbols": { 408 | "version": "1.0.3", 409 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", 410 | "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", 411 | "engines": { 412 | "node": ">= 0.4" 413 | }, 414 | "funding": { 415 | "url": "https://github.com/sponsors/ljharb" 416 | } 417 | }, 418 | "node_modules/http-errors": { 419 | "version": "2.0.0", 420 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", 421 | "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", 422 | "dependencies": { 423 | "depd": "2.0.0", 424 | "inherits": "2.0.4", 425 | "setprototypeof": "1.2.0", 426 | "statuses": "2.0.1", 427 | "toidentifier": "1.0.1" 428 | }, 429 | "engines": { 430 | "node": ">= 0.8" 431 | } 432 | }, 433 | "node_modules/iconv-lite": { 434 | "version": "0.4.24", 435 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 436 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 437 | "dependencies": { 438 | "safer-buffer": ">= 2.1.2 < 3" 439 | }, 440 | "engines": { 441 | "node": ">=0.10.0" 442 | } 443 | }, 444 | "node_modules/inherits": { 445 | "version": "2.0.4", 446 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 447 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 448 | }, 449 | "node_modules/ipaddr.js": { 450 | "version": "1.9.1", 451 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", 452 | "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", 453 | "engines": { 454 | "node": ">= 0.10" 455 | } 456 | }, 457 | "node_modules/media-typer": { 458 | "version": "0.3.0", 459 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 460 | "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", 461 | "engines": { 462 | "node": ">= 0.6" 463 | } 464 | }, 465 | "node_modules/merge-descriptors": { 466 | "version": "1.0.1", 467 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", 468 | "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" 469 | }, 470 | "node_modules/methods": { 471 | "version": "1.1.2", 472 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 473 | "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", 474 | "engines": { 475 | "node": ">= 0.6" 476 | } 477 | }, 478 | "node_modules/mime": { 479 | "version": "1.6.0", 480 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 481 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", 482 | "bin": { 483 | "mime": "cli.js" 484 | }, 485 | "engines": { 486 | "node": ">=4" 487 | } 488 | }, 489 | "node_modules/mime-db": { 490 | "version": "1.52.0", 491 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", 492 | "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", 493 | "engines": { 494 | "node": ">= 0.6" 495 | } 496 | }, 497 | "node_modules/mime-types": { 498 | "version": "2.1.35", 499 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", 500 | "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", 501 | "dependencies": { 502 | "mime-db": "1.52.0" 503 | }, 504 | "engines": { 505 | "node": ">= 0.6" 506 | } 507 | }, 508 | "node_modules/ms": { 509 | "version": "2.1.2", 510 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 511 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" 512 | }, 513 | "node_modules/negotiator": { 514 | "version": "0.6.3", 515 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", 516 | "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", 517 | "engines": { 518 | "node": ">= 0.6" 519 | } 520 | }, 521 | "node_modules/object-assign": { 522 | "version": "4.1.1", 523 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 524 | "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", 525 | "engines": { 526 | "node": ">=0.10.0" 527 | } 528 | }, 529 | "node_modules/object-inspect": { 530 | "version": "1.12.3", 531 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", 532 | "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", 533 | "funding": { 534 | "url": "https://github.com/sponsors/ljharb" 535 | } 536 | }, 537 | "node_modules/on-finished": { 538 | "version": "2.4.1", 539 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", 540 | "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", 541 | "dependencies": { 542 | "ee-first": "1.1.1" 543 | }, 544 | "engines": { 545 | "node": ">= 0.8" 546 | } 547 | }, 548 | "node_modules/parseurl": { 549 | "version": "1.3.3", 550 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", 551 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", 552 | "engines": { 553 | "node": ">= 0.8" 554 | } 555 | }, 556 | "node_modules/path-to-regexp": { 557 | "version": "0.1.7", 558 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", 559 | "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" 560 | }, 561 | "node_modules/proxy-addr": { 562 | "version": "2.0.7", 563 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", 564 | "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", 565 | "dependencies": { 566 | "forwarded": "0.2.0", 567 | "ipaddr.js": "1.9.1" 568 | }, 569 | "engines": { 570 | "node": ">= 0.10" 571 | } 572 | }, 573 | "node_modules/qs": { 574 | "version": "6.11.0", 575 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", 576 | "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", 577 | "dependencies": { 578 | "side-channel": "^1.0.4" 579 | }, 580 | "engines": { 581 | "node": ">=0.6" 582 | }, 583 | "funding": { 584 | "url": "https://github.com/sponsors/ljharb" 585 | } 586 | }, 587 | "node_modules/range-parser": { 588 | "version": "1.2.1", 589 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", 590 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", 591 | "engines": { 592 | "node": ">= 0.6" 593 | } 594 | }, 595 | "node_modules/raw-body": { 596 | "version": "2.5.1", 597 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", 598 | "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", 599 | "dependencies": { 600 | "bytes": "3.1.2", 601 | "http-errors": "2.0.0", 602 | "iconv-lite": "0.4.24", 603 | "unpipe": "1.0.0" 604 | }, 605 | "engines": { 606 | "node": ">= 0.8" 607 | } 608 | }, 609 | "node_modules/safe-buffer": { 610 | "version": "5.2.1", 611 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 612 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", 613 | "funding": [ 614 | { 615 | "type": "github", 616 | "url": "https://github.com/sponsors/feross" 617 | }, 618 | { 619 | "type": "patreon", 620 | "url": "https://www.patreon.com/feross" 621 | }, 622 | { 623 | "type": "consulting", 624 | "url": "https://feross.org/support" 625 | } 626 | ] 627 | }, 628 | "node_modules/safer-buffer": { 629 | "version": "2.1.2", 630 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 631 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 632 | }, 633 | "node_modules/send": { 634 | "version": "0.18.0", 635 | "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", 636 | "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", 637 | "dependencies": { 638 | "debug": "2.6.9", 639 | "depd": "2.0.0", 640 | "destroy": "1.2.0", 641 | "encodeurl": "~1.0.2", 642 | "escape-html": "~1.0.3", 643 | "etag": "~1.8.1", 644 | "fresh": "0.5.2", 645 | "http-errors": "2.0.0", 646 | "mime": "1.6.0", 647 | "ms": "2.1.3", 648 | "on-finished": "2.4.1", 649 | "range-parser": "~1.2.1", 650 | "statuses": "2.0.1" 651 | }, 652 | "engines": { 653 | "node": ">= 0.8.0" 654 | } 655 | }, 656 | "node_modules/send/node_modules/debug": { 657 | "version": "2.6.9", 658 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 659 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 660 | "dependencies": { 661 | "ms": "2.0.0" 662 | } 663 | }, 664 | "node_modules/send/node_modules/debug/node_modules/ms": { 665 | "version": "2.0.0", 666 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 667 | "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" 668 | }, 669 | "node_modules/send/node_modules/ms": { 670 | "version": "2.1.3", 671 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 672 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" 673 | }, 674 | "node_modules/serve-static": { 675 | "version": "1.15.0", 676 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", 677 | "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", 678 | "dependencies": { 679 | "encodeurl": "~1.0.2", 680 | "escape-html": "~1.0.3", 681 | "parseurl": "~1.3.3", 682 | "send": "0.18.0" 683 | }, 684 | "engines": { 685 | "node": ">= 0.8.0" 686 | } 687 | }, 688 | "node_modules/setprototypeof": { 689 | "version": "1.2.0", 690 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", 691 | "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" 692 | }, 693 | "node_modules/side-channel": { 694 | "version": "1.0.4", 695 | "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", 696 | "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", 697 | "dependencies": { 698 | "call-bind": "^1.0.0", 699 | "get-intrinsic": "^1.0.2", 700 | "object-inspect": "^1.9.0" 701 | }, 702 | "funding": { 703 | "url": "https://github.com/sponsors/ljharb" 704 | } 705 | }, 706 | "node_modules/socket.io": { 707 | "version": "4.7.2", 708 | "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.7.2.tgz", 709 | "integrity": "sha512-bvKVS29/I5fl2FGLNHuXlQaUH/BlzX1IN6S+NKLNZpBsPZIDH+90eQmCs2Railn4YUiww4SzUedJ6+uzwFnKLw==", 710 | "dependencies": { 711 | "accepts": "~1.3.4", 712 | "base64id": "~2.0.0", 713 | "cors": "~2.8.5", 714 | "debug": "~4.3.2", 715 | "engine.io": "~6.5.2", 716 | "socket.io-adapter": "~2.5.2", 717 | "socket.io-parser": "~4.2.4" 718 | }, 719 | "engines": { 720 | "node": ">=10.2.0" 721 | } 722 | }, 723 | "node_modules/socket.io-adapter": { 724 | "version": "2.5.2", 725 | "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.2.tgz", 726 | "integrity": "sha512-87C3LO/NOMc+eMcpcxUBebGjkpMDkNBS9tf7KJqcDsmL936EChtVva71Dw2q4tQcuVC+hAUy4an2NO/sYXmwRA==", 727 | "dependencies": { 728 | "ws": "~8.11.0" 729 | } 730 | }, 731 | "node_modules/socket.io-parser": { 732 | "version": "4.2.4", 733 | "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", 734 | "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", 735 | "dependencies": { 736 | "@socket.io/component-emitter": "~3.1.0", 737 | "debug": "~4.3.1" 738 | }, 739 | "engines": { 740 | "node": ">=10.0.0" 741 | } 742 | }, 743 | "node_modules/statuses": { 744 | "version": "2.0.1", 745 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", 746 | "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", 747 | "engines": { 748 | "node": ">= 0.8" 749 | } 750 | }, 751 | "node_modules/toidentifier": { 752 | "version": "1.0.1", 753 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", 754 | "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", 755 | "engines": { 756 | "node": ">=0.6" 757 | } 758 | }, 759 | "node_modules/type-is": { 760 | "version": "1.6.18", 761 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", 762 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", 763 | "dependencies": { 764 | "media-typer": "0.3.0", 765 | "mime-types": "~2.1.24" 766 | }, 767 | "engines": { 768 | "node": ">= 0.6" 769 | } 770 | }, 771 | "node_modules/unpipe": { 772 | "version": "1.0.0", 773 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 774 | "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", 775 | "engines": { 776 | "node": ">= 0.8" 777 | } 778 | }, 779 | "node_modules/utils-merge": { 780 | "version": "1.0.1", 781 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 782 | "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", 783 | "engines": { 784 | "node": ">= 0.4.0" 785 | } 786 | }, 787 | "node_modules/vary": { 788 | "version": "1.1.2", 789 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 790 | "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", 791 | "engines": { 792 | "node": ">= 0.8" 793 | } 794 | }, 795 | "node_modules/ws": { 796 | "version": "8.11.0", 797 | "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", 798 | "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", 799 | "engines": { 800 | "node": ">=10.0.0" 801 | }, 802 | "peerDependencies": { 803 | "bufferutil": "^4.0.1", 804 | "utf-8-validate": "^5.0.2" 805 | }, 806 | "peerDependenciesMeta": { 807 | "bufferutil": { 808 | "optional": true 809 | }, 810 | "utf-8-validate": { 811 | "optional": true 812 | } 813 | } 814 | } 815 | } 816 | } 817 | -------------------------------------------------------------------------------- /server/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "server", 3 | "version": "1.0.0", 4 | "description": "Server tunnel WEBSOCKET", 5 | "main": "app.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "ABDI SYAHPUTRA HARAHAP", 11 | "license": "ISC", 12 | "type": "module", 13 | "dependencies": { 14 | "crypto": "^1.0.1", 15 | "express": "^4.18.2", 16 | "socket.io": "^4.7.2" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /server/tunnel-server.js: -------------------------------------------------------------------------------- 1 | // import module ---------------------------------------------------------------------- 2 | import http from 'http'; 3 | import express from 'express'; 4 | // import module costom --------------------------------------------------------------- 5 | import socket from "./core/socket.js"; 6 | import tcp from "./core/tcp.js"; 7 | import tunneling from "./core/tunneling.js"; 8 | //-- config --------------------------------------------------------------------------- 9 | import config from "./config.js"; 10 | //----- main -------------------------------------------------------------------------- 11 | const app = express(); 12 | (async ()=>{ 13 | const server_app = await http.createServer(app); 14 | const server_tcp = await tcp.init(config["port-tcp"]); 15 | const server_tunnel = await socket.init(server_app,config); 16 | tunneling(server_tcp,server_tunnel,config); 17 | })(); 18 | 19 | --------------------------------------------------------------------------------