dan92 commited on
Commit
e080358
·
1 Parent(s): 45b8010

Upload 7 files

Browse files
Files changed (7) hide show
  1. .gitignore +35 -0
  2. Dockerfile +16 -0
  3. README.md +5 -0
  4. app.js +32 -0
  5. app_edtunnel.js +381 -0
  6. package-lock.json +72 -0
  7. package.json +14 -0
.gitignore ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2
+
3
+ # dependencies
4
+ /node_modules
5
+ /.pnp
6
+ .pnp.js
7
+
8
+ # testing
9
+ /coverage
10
+
11
+ # next.js
12
+ /.next/
13
+ /out/
14
+
15
+ # production
16
+ /build
17
+
18
+ # misc
19
+ .DS_Store
20
+ *.pem
21
+
22
+ # debug
23
+ npm-debug.log*
24
+ yarn-debug.log*
25
+ yarn-error.log*
26
+
27
+ # local env files
28
+ .env*.local
29
+
30
+ # vercel
31
+ .vercel
32
+
33
+ # typescript
34
+ *.tsbuildinfo
35
+ next-env.d.ts
Dockerfile ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # 使用官方 Node.js 镜像作为基础镜像
2
+ FROM node:lts-alpine3.18
3
+
4
+ # 设置工作目录
5
+ WORKDIR /app
6
+
7
+ # 将应用程序文件复制到容器中
8
+ COPY . .
9
+
10
+ # EXPOSE 3000
11
+
12
+ # 安装应用程序的依赖
13
+ RUN npm install
14
+
15
+ # 设置默认的命令,即启动应用程序
16
+ CMD ["npm", "start"]
README.md ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ 不能说的秘密
2
+
3
+ 代码全是chatgpt写的 我一个变量都看不懂
4
+
5
+ https://www.chunqiujinjing.com/2023/07/28/free-vps-free-domain/
app.js ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const net=require('net');
2
+ const {WebSocket,createWebSocketStream}=require('ws');
3
+ const { TextDecoder } = require('util');
4
+ const logcb= (...args)=>console.log.bind(this,...args);
5
+ const errcb= (...args)=>console.error.bind(this,...args);
6
+
7
+ const uuid= (process.env.UUID||'d342d11e-d424-4583-b36e-524ab1f0afa4').replace(/-/g, "");
8
+ const port= process.env.PORT||3000;
9
+
10
+ const wss=new WebSocket.Server({port},logcb('listen:', port));
11
+ wss.on('connection', ws=>{
12
+ console.log("on connection")
13
+ ws.once('message', msg=>{
14
+ const [VERSION]=msg;
15
+ const id=msg.slice(1, 17);
16
+ if(!id.every((v,i)=>v==parseInt(uuid.substr(i*2,2),16))) return;
17
+ let i = msg.slice(17, 18).readUInt8()+19;
18
+ const port = msg.slice(i, i+=2).readUInt16BE(0);
19
+ const ATYP = msg.slice(i, i+=1).readUInt8();
20
+ const host= ATYP==1? msg.slice(i,i+=4).join('.')://IPV4
21
+ (ATYP==2? new TextDecoder().decode(msg.slice(i+1, i+=1+msg.slice(i,i+1).readUInt8()))://domain
22
+ (ATYP==3? msg.slice(i,i+=16).reduce((s,b,i,a)=>(i%2?s.concat(a.slice(i-1,i+1)):s), []).map(b=>b.readUInt16BE(0).toString(16)).join(':'):''));//ipv6
23
+
24
+ logcb('conn:', host,port);
25
+ ws.send(new Uint8Array([VERSION, 0]));
26
+ const duplex=createWebSocketStream(ws);
27
+ net.connect({host,port}, function(){
28
+ this.write(msg.slice(i));
29
+ duplex.on('error',errcb('E1:')).pipe(this).on('error',errcb('E2:')).pipe(duplex);
30
+ }).on('error',errcb('Conn-Err:',{host,port}));
31
+ }).on('error',errcb('EE:'));
32
+ });
app_edtunnel.js ADDED
@@ -0,0 +1,381 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const WebSocket = require('ws');
2
+ const { Readable } = require('stream');
3
+ const net = require('net');
4
+
5
+ // 创建 WebSocket 服务器
6
+ const wss = new WebSocket.Server({ port: 443 });
7
+ let userID = 'd342d11e-d424-4583-b36e-524ab1f0afa4';
8
+ let proxyIP = "64.68.192." + Math.floor(Math.random() * 255);
9
+
10
+ let address = '';
11
+ let portWithRandomLog = '';
12
+ const log = (/** @type {string} */ info, /** @type {string | undefined} */ event) => {
13
+ console.log(`[${address}:${portWithRandomLog}] ${info}`, event || '');
14
+ };
15
+
16
+ // 监听连接事件
17
+ wss.on('connection', (ws) => {
18
+ console.log("ws connection")
19
+ // 在每个连接上设置消息处理逻辑
20
+ ws.once('message', (chunk) => {
21
+ console.log("on message")
22
+ let webSocket = ws;
23
+ let remoteSocketWapper = {
24
+ value: null,
25
+ };
26
+ let isDns = false;
27
+
28
+ const {
29
+ hasError,
30
+ message,
31
+ portRemote = 443,
32
+ addressRemote = '',
33
+ rawDataIndex,
34
+ vlessVersion = new Uint8Array([0, 0]),
35
+ isUDP,
36
+ } = processVlessHeader(chunk, userID);
37
+
38
+ address = addressRemote;
39
+ portWithRandomLog = `${portRemote}--${Math.random()} ${isUDP ? 'udp ' : 'tcp '
40
+ } `;
41
+ if (hasError) {
42
+ // controller.error(message);
43
+ // throw new Error(message); // cf seems has bug, controller.error will not end stream
44
+ // webSocket.close(1000, message);
45
+ console.log('hasError,Connection closed:'+message);
46
+ ws.close();
47
+ return;
48
+ }
49
+ // if UDP but port not DNS port, close it
50
+ if (isUDP) {
51
+ if (portRemote === 53) {
52
+ isDns = true;
53
+ } else {
54
+ // controller.error('UDP proxy only enable for DNS which is port 53');
55
+ throw new Error('UDP proxy only enable for DNS which is port 53'); // cf seems has bug, controller.error will not end stream
56
+ return;
57
+ }
58
+ }
59
+ // ["version", "附加信息长度 N"]
60
+ const vlessResponseHeader = new Uint8Array([vlessVersion[0], 0]);
61
+ const rawClientData = chunk.slice(rawDataIndex);
62
+
63
+ if (isDns) {
64
+ return handleDNSQuery(rawClientData, webSocket, vlessResponseHeader, log);
65
+ }
66
+ handleTCPOutBound(remoteSocketWapper, addressRemote, portRemote, rawClientData, webSocket, vlessResponseHeader, log);
67
+ });
68
+
69
+ // 监听连接断开事件
70
+ ws.on('close', () => {
71
+ console.log('Connection closed');
72
+ ws.close();
73
+ });
74
+ });
75
+
76
+
77
+ /**
78
+ * Handles outbound TCP connections.
79
+ *
80
+ * @param {any} remoteSocket
81
+ * @param {string} addressRemote The remote address to connect to.
82
+ * @param {number} portRemote The remote port to connect to.
83
+ * @param {Uint8Array} rawClientData The raw client data to write.
84
+ * @param {WebSocket} webSocket The WebSocket to pass the remote socket to.
85
+ * @param {Uint8Array} vlessResponseHeader The VLESS response header.
86
+ * @param {function} log The logging function.
87
+ * @returns {Promise<void>} The remote socket.
88
+ */
89
+ async function handleTCPOutBound(remoteSocket, addressRemote, portRemote, rawClientData, webSocket, vlessResponseHeader, log,) {
90
+ async function connectAndWrite(address, port) {
91
+ const options = {
92
+ host: address, // 服务器主机地址
93
+ port: port // 服务器监听的端口号
94
+ };
95
+
96
+ const tcpSocket = net.createConnection(options, () => {
97
+ console.log('已连接到服务器');
98
+ });
99
+
100
+ remoteSocket.value = tcpSocket;
101
+ log(`handleTCPOutBound connected to ${address}:${port}`);
102
+ // const writer = tcpSocket.writable.getWriter();
103
+ console.log("rawClientData:"+rawClientData)
104
+ tcpSocket.write(rawClientData); // first write, nomal is tls client hello
105
+ // writer.releaseLock();
106
+ return tcpSocket;
107
+ }
108
+
109
+ // if the cf connect tcp socket have no incoming data, we retry to redirect ip
110
+ async function retry() {
111
+ console.log("retry")
112
+ const tcpSocket = await connectAndWrite(proxyIP || addressRemote, portRemote)
113
+ // no matter retry success or not, close websocket
114
+ tcpSocket.closed.catch(error => {
115
+ console.log('retry tcpSocket closed error', error);
116
+ }).finally(() => {
117
+ safeCloseWebSocket(webSocket);
118
+ })
119
+ remoteSocketToWS(tcpSocket, webSocket, vlessResponseHeader, null, log);
120
+ }
121
+
122
+ const tcpSocket = await connectAndWrite(addressRemote, portRemote);
123
+
124
+ // when remoteSocket is ready, pass to websocket
125
+ // remote--> ws
126
+ remoteSocketToWS(tcpSocket, webSocket, vlessResponseHeader, retry, log);
127
+ }
128
+
129
+ /**
130
+ *
131
+ * @param {net.Socket} remoteSocket
132
+ * @param {WebSocket} webSocket
133
+ * @param {ArrayBuffer} vlessResponseHeader
134
+ * @param {(() => Promise<void>) | null} retry
135
+ * @param {*} log
136
+ */
137
+ async function remoteSocketToWS(remoteSocket, webSocket, vlessResponseHeader, retry, log) {
138
+ // remote--> ws
139
+ let remoteChunkCount = 0;
140
+ let chunks = [];
141
+ /** @type {ArrayBuffer | null} */
142
+ let vlessHeader = vlessResponseHeader;
143
+
144
+
145
+ // 监听 'data' 事件,将数据推送到可读流中
146
+ remoteSocket.on('data', (data) => {
147
+ // console.log("接收到data:"+data)
148
+ if (vlessHeader) {
149
+ new Blob([vlessHeader, data]).arrayBuffer()
150
+ .then(arrayBuffer => {
151
+ webSocket.send(arrayBuffer);
152
+ })
153
+ .catch(error => {
154
+ console.error('处理 ArrayBuffer 出错:', error);
155
+ });
156
+
157
+ vlessHeader = null;
158
+ } else {
159
+ webSocket.send(data);
160
+ }
161
+ });
162
+
163
+ // 监听 'end' 事件,标记流的结束
164
+ remoteSocket.on('end', () => {
165
+ console.log("remoteSocket on end end end")
166
+ webSocket.send(null);
167
+ });
168
+ let is_error = false;
169
+
170
+ // 监听 'error' 事件
171
+ remoteSocket.on('error', () => {
172
+ is_error = true;
173
+ });
174
+
175
+ if (is_error && retry) {
176
+ log(`retry`)
177
+ retry();
178
+ }
179
+ }
180
+
181
+
182
+ /**
183
+ * https://xtls.github.io/development/protocols/vless.html
184
+ * 1 字节 16 字节 1 字节 M 字节 1 字节 2 字节 1 字节 S 字节 X 字节
185
+ * 协议版本 等价 UUID 附加信息长度 M 附加信息ProtoBuf 指令 端口 地址类型 地址 请求数据
186
+ * @param { ArrayBuffer} vlessBuffer
187
+ * @param {string} userID
188
+ * @returns
189
+ */
190
+ function processVlessHeader(
191
+ vlessBuffer,
192
+ userID
193
+ ) {
194
+ if (vlessBuffer.byteLength < 24) {
195
+ return {
196
+ hasError: true,
197
+ message: 'invalid data',
198
+ };
199
+ }
200
+ const version = new Uint8Array(vlessBuffer.slice(0, 1));
201
+ let isValidUser = false;
202
+ let isUDP = false;
203
+ if (stringify(new Uint8Array(vlessBuffer.slice(1, 17))) === userID) {
204
+ console.log(stringify(new Uint8Array(vlessBuffer.slice(1, 17))))
205
+ console.log(userID)
206
+ isValidUser = true;
207
+ }
208
+ if (!isValidUser) {
209
+ console.log(stringify(new Uint8Array(vlessBuffer.slice(1, 17))))
210
+ console.log(userID)
211
+ return {
212
+ hasError: true,
213
+ message: 'invalid user',
214
+ };
215
+ }
216
+
217
+ const optLength = new Uint8Array(vlessBuffer.slice(17, 18))[0];
218
+ //skip opt for now
219
+
220
+ const command = new Uint8Array(
221
+ vlessBuffer.slice(18 + optLength, 18 + optLength + 1)
222
+ )[0];
223
+
224
+ // 0x01 TCP
225
+ // 0x02 UDP
226
+ // 0x03 MUX
227
+ if (command === 1) {
228
+ } else if (command === 2) {
229
+ isUDP = true;
230
+ } else {
231
+ return {
232
+ hasError: true,
233
+ message: `command ${command} is not support, command 01-tcp,02-udp,03-mux`,
234
+ };
235
+ }
236
+ const portIndex = 18 + optLength + 1;
237
+ const portBuffer = vlessBuffer.slice(portIndex, portIndex + 2);
238
+ // port is big-Endian in raw data etc 80 == 0x005d
239
+ const portRemote = portBuffer.readUInt16BE();
240
+
241
+ let addressIndex = portIndex + 2;
242
+ const addressBuffer = new Uint8Array(
243
+ vlessBuffer.slice(addressIndex, addressIndex + 1)
244
+ );
245
+
246
+ // 1--> ipv4 addressLength =4
247
+ // 2--> domain name addressLength=addressBuffer[1]
248
+ // 3--> ipv6 addressLength =16
249
+ const addressType = addressBuffer[0];
250
+ let addressLength = 0;
251
+ let addressValueIndex = addressIndex + 1;
252
+ let addressValue = '';
253
+ switch (addressType) {
254
+ case 1:
255
+ addressLength = 4;
256
+ addressValue = new Uint8Array(
257
+ vlessBuffer.slice(addressValueIndex, addressValueIndex + addressLength)
258
+ ).join('.');
259
+ break;
260
+ case 2:
261
+ addressLength = new Uint8Array(
262
+ vlessBuffer.slice(addressValueIndex, addressValueIndex + 1)
263
+ )[0];
264
+ addressValueIndex += 1;
265
+ addressValue = new TextDecoder().decode(
266
+ vlessBuffer.slice(addressValueIndex, addressValueIndex + addressLength)
267
+ );
268
+ break;
269
+ case 3:
270
+ addressLength = 16;
271
+ const dataView = new DataView(
272
+ vlessBuffer.slice(addressValueIndex, addressValueIndex + addressLength)
273
+ );
274
+ // 2001:0db8:85a3:0000:0000:8a2e:0370:7334
275
+ const ipv6 = [];
276
+ for (let i = 0; i < 8; i++) {
277
+ ipv6.push(dataView.getUint16(i * 2).toString(16));
278
+ }
279
+ addressValue = ipv6.join(':');
280
+ // seems no need add [] for ipv6
281
+ break;
282
+ default:
283
+ return {
284
+ hasError: true,
285
+ message: `invild addressType is ${addressType}`,
286
+ };
287
+ }
288
+ if (!addressValue) {
289
+ return {
290
+ hasError: true,
291
+ message: `addressValue is empty, addressType is ${addressType}`,
292
+ };
293
+ }
294
+
295
+ return {
296
+ hasError: false,
297
+ addressRemote: addressValue,
298
+ addressType,
299
+ portRemote,
300
+ rawDataIndex: addressValueIndex + addressLength,
301
+ vlessVersion: version,
302
+ isUDP,
303
+ };
304
+ }
305
+
306
+ const byteToHex = [];
307
+ for (let i = 0; i < 256; ++i) {
308
+ byteToHex.push((i + 256).toString(16).slice(1));
309
+ }
310
+
311
+ function unsafeStringify(arr, offset = 0) {
312
+ return (byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + "-" + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + "-" + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + "-" + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + "-" + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]).toLowerCase();
313
+ }
314
+ function stringify(arr, offset = 0) {
315
+ const uuid = unsafeStringify(arr, offset);
316
+ return uuid;
317
+ }
318
+
319
+ /**
320
+ *
321
+ * @param {ArrayBuffer} udpChunk
322
+ * @param {WebSocket} webSocket
323
+ * @param {Uint8Array} vlessResponseHeader
324
+ * @param {(string)=> void} log
325
+ */
326
+ async function handleDNSQuery(udpChunk, webSocket, vlessResponseHeader, log) {
327
+ // no matter which DNS server client send, we alwasy use hard code one.
328
+ // beacsue someof DNS server is not support DNS over TCP
329
+ try {
330
+ const dnsServer = '8.8.4.4'; // change to 1.1.1.1 after cf fix connect own ip bug
331
+ const dnsPort = 53;
332
+ /** @type {ArrayBuffer | null} */
333
+ let vlessHeader = vlessResponseHeader;
334
+
335
+ const options = {
336
+ host: dnsServer, // 服务器主机地址
337
+ port: dnsPort // 服务器监听的端口号
338
+ };
339
+ const tcpSocket = net.createConnection(options, () => {
340
+ console.log('handleDNSQuery 已连接到服务器');
341
+ });
342
+
343
+ log(`connected to ${dnsServer}:${dnsPort}`);
344
+ tcpSocket.write(udpChunk)
345
+
346
+ // 监听 'data' 事件,将数据推送到可读流中
347
+ tcpSocket.on('data', (data) => {
348
+ if (webSocket.readyState === WS_READY_STATE_OPEN) {
349
+ if (vlessHeader) {
350
+ new Blob([vlessHeader, data]).arrayBuffer()
351
+ .then(arrayBuffer => {
352
+ webSocket.send(arrayBuffer);
353
+ })
354
+ .catch(error => {
355
+ console.error('处理 ArrayBuffer 出错:', error);
356
+ });
357
+ vlessHeader = null;
358
+ } else {
359
+ webSocket.send(data);
360
+ }
361
+ }
362
+ });
363
+ } catch (error) {
364
+ console.error(
365
+ `handleDNSQuery have exception, error: ${error.message}`
366
+ );
367
+ }
368
+ }
369
+ /**
370
+ * Normally, WebSocket will not has exceptions when close.
371
+ * @param {import("@cloudflare/workers-types").WebSocket} socket
372
+ */
373
+ function safeCloseWebSocket(socket) {
374
+ try {
375
+ if (socket.readyState === WS_READY_STATE_OPEN || socket.readyState === WS_READY_STATE_CLOSING) {
376
+ socket.close();
377
+ }
378
+ } catch (error) {
379
+ console.error('safeCloseWebSocket error', error);
380
+ }
381
+ }
package-lock.json ADDED
@@ -0,0 +1,72 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "nodejs-proxy",
3
+ "version": "1.0.0",
4
+ "lockfileVersion": 3,
5
+ "requires": true,
6
+ "packages": {
7
+ "": {
8
+ "name": "nodejs-proxy",
9
+ "version": "1.0.0",
10
+ "dependencies": {
11
+ "http-proxy": "latest",
12
+ "ws": "^8.13.0"
13
+ }
14
+ },
15
+ "node_modules/eventemitter3": {
16
+ "version": "4.0.7",
17
+ "resolved": "https://registry.npmmirror.com/eventemitter3/-/eventemitter3-4.0.7.tgz",
18
+ "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw=="
19
+ },
20
+ "node_modules/follow-redirects": {
21
+ "version": "1.15.2",
22
+ "resolved": "https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.15.2.tgz",
23
+ "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==",
24
+ "engines": {
25
+ "node": ">=4.0"
26
+ },
27
+ "peerDependenciesMeta": {
28
+ "debug": {
29
+ "optional": true
30
+ }
31
+ }
32
+ },
33
+ "node_modules/http-proxy": {
34
+ "version": "1.18.1",
35
+ "resolved": "https://registry.npmmirror.com/http-proxy/-/http-proxy-1.18.1.tgz",
36
+ "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==",
37
+ "dependencies": {
38
+ "eventemitter3": "^4.0.0",
39
+ "follow-redirects": "^1.0.0",
40
+ "requires-port": "^1.0.0"
41
+ },
42
+ "engines": {
43
+ "node": ">=8.0.0"
44
+ }
45
+ },
46
+ "node_modules/requires-port": {
47
+ "version": "1.0.0",
48
+ "resolved": "https://registry.npmmirror.com/requires-port/-/requires-port-1.0.0.tgz",
49
+ "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ=="
50
+ },
51
+ "node_modules/ws": {
52
+ "version": "8.13.0",
53
+ "resolved": "https://registry.npmmirror.com/ws/-/ws-8.13.0.tgz",
54
+ "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==",
55
+ "engines": {
56
+ "node": ">=10.0.0"
57
+ },
58
+ "peerDependencies": {
59
+ "bufferutil": "^4.0.1",
60
+ "utf-8-validate": ">=5.0.2"
61
+ },
62
+ "peerDependenciesMeta": {
63
+ "bufferutil": {
64
+ "optional": true
65
+ },
66
+ "utf-8-validate": {
67
+ "optional": true
68
+ }
69
+ }
70
+ }
71
+ }
72
+ }
package.json ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "nodejs-proxy",
3
+ "version": "1.0.0",
4
+ "description": "",
5
+ "main": "app.js",
6
+ "scripts": {
7
+ "start": "node app.js",
8
+ "test": "echo \"Error: no test specified\" && exit 1"
9
+ },
10
+ "dependencies": {
11
+ "http-proxy": "latest",
12
+ "ws": "^8.13.0"
13
+ }
14
+ }