vpn-split 18.0.18 → 18.0.19
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.
- package/assets/shared/shared_folder_info.txt +1 -1
- package/bin/vpn-split +11 -11
- package/bin/vpn-split-debug +11 -11
- package/browser/README.md +24 -24
- package/browser/esm2022/lib/models.mjs +19 -9
- package/browser/fesm2022/vpn-split.mjs +18 -8
- package/browser/fesm2022/vpn-split.mjs.map +1 -1
- package/browser/lib/models.d.ts +3 -1
- package/client/README.md +24 -24
- package/client/esm2022/lib/models.mjs +19 -9
- package/client/fesm2022/vpn-split.mjs +18 -8
- package/client/fesm2022/vpn-split.mjs.map +1 -1
- package/client/lib/models.d.ts +3 -1
- package/lib/models.d.ts +3 -1
- package/lib/models.js +22 -8
- package/lib/models.js.map +1 -1
- package/lib/vpn-split.backend.d.ts +18 -22
- package/lib/vpn-split.backend.js +292 -206
- package/lib/vpn-split.backend.js.map +1 -1
- package/package.json +3 -3
- package/taon.jsonc +33 -33
- package/tmp-environment.json +29 -29
- package/websql/README.md +24 -24
- package/websql/esm2022/lib/models.mjs +19 -9
- package/websql/fesm2022/vpn-split.mjs +18 -8
- package/websql/fesm2022/vpn-split.mjs.map +1 -1
- package/websql/lib/models.d.ts +3 -1
package/lib/vpn-split.backend.js
CHANGED
|
@@ -13,6 +13,7 @@ var models_1 = require("./models");
|
|
|
13
13
|
var axios_1 = require("axios");
|
|
14
14
|
var ng2_logger_1 = require("ng2-logger");
|
|
15
15
|
var crypto = require("crypto");
|
|
16
|
+
var dgram = require("dgram"); // <-- For UDP sockets
|
|
16
17
|
var log = ng2_logger_1.Log.create('vpn-split', ng2_logger_1.Level.INFO);
|
|
17
18
|
//#endregion
|
|
18
19
|
//#region consts
|
|
@@ -118,10 +119,6 @@ var VpnSplit = /** @class */ (function () {
|
|
|
118
119
|
switch (_g.label) {
|
|
119
120
|
case 0: return [4 /*yield*/, (0, tnp_core_1.isElevated)()];
|
|
120
121
|
case 1:
|
|
121
|
-
// console.log('ports', ports)
|
|
122
|
-
// console.log({
|
|
123
|
-
// allowNotSudo
|
|
124
|
-
// })
|
|
125
122
|
if (!(_g.sent()) && !allowNotSudo) {
|
|
126
123
|
tnp_helpers_1.Helpers.error("[vpn-split] Please run this program as sudo (or admin on windows)", false, true);
|
|
127
124
|
}
|
|
@@ -137,28 +134,68 @@ var VpnSplit = /** @class */ (function () {
|
|
|
137
134
|
//#region start server
|
|
138
135
|
VpnSplit.prototype.startServer = function () {
|
|
139
136
|
return tslib_1.__awaiter(this, arguments, void 0, function (saveHostInUserFolder) {
|
|
140
|
-
var
|
|
137
|
+
var _a, _b, portToPassthrough, e_1_1, _c, _d, portToPassthrough, e_2_1;
|
|
138
|
+
var e_1, _e, e_2, _f;
|
|
141
139
|
if (saveHostInUserFolder === void 0) { saveHostInUserFolder = false; }
|
|
142
|
-
return tslib_1.__generator(this, function (
|
|
143
|
-
switch (
|
|
140
|
+
return tslib_1.__generator(this, function (_g) {
|
|
141
|
+
switch (_g.label) {
|
|
144
142
|
case 0:
|
|
145
143
|
this.createCertificateIfNotExists();
|
|
146
|
-
//#region modify /etc/host
|
|
144
|
+
//#region modify /etc/host to direct traffic appropriately
|
|
147
145
|
saveHosts(this.hosts, { saveHostInUserFolder: saveHostInUserFolder });
|
|
148
|
-
|
|
149
|
-
_a.label = 1;
|
|
146
|
+
_g.label = 1;
|
|
150
147
|
case 1:
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
148
|
+
_g.trys.push([1, 6, 7, 8]);
|
|
149
|
+
_a = tslib_1.__values(this.portsToPass), _b = _a.next();
|
|
150
|
+
_g.label = 2;
|
|
154
151
|
case 2:
|
|
155
|
-
|
|
156
|
-
|
|
152
|
+
if (!!_b.done) return [3 /*break*/, 5];
|
|
153
|
+
portToPassthrough = _b.value;
|
|
154
|
+
return [4 /*yield*/, this.serverPassthrough(portToPassthrough)];
|
|
157
155
|
case 3:
|
|
158
|
-
|
|
159
|
-
|
|
156
|
+
_g.sent();
|
|
157
|
+
_g.label = 4;
|
|
160
158
|
case 4:
|
|
161
|
-
|
|
159
|
+
_b = _a.next();
|
|
160
|
+
return [3 /*break*/, 2];
|
|
161
|
+
case 5: return [3 /*break*/, 8];
|
|
162
|
+
case 6:
|
|
163
|
+
e_1_1 = _g.sent();
|
|
164
|
+
e_1 = { error: e_1_1 };
|
|
165
|
+
return [3 /*break*/, 8];
|
|
166
|
+
case 7:
|
|
167
|
+
try {
|
|
168
|
+
if (_b && !_b.done && (_e = _a.return)) _e.call(_a);
|
|
169
|
+
}
|
|
170
|
+
finally { if (e_1) throw e_1.error; }
|
|
171
|
+
return [7 /*endfinally*/];
|
|
172
|
+
case 8:
|
|
173
|
+
_g.trys.push([8, 13, 14, 15]);
|
|
174
|
+
_c = tslib_1.__values(this.portsToPass), _d = _c.next();
|
|
175
|
+
_g.label = 9;
|
|
176
|
+
case 9:
|
|
177
|
+
if (!!_d.done) return [3 /*break*/, 12];
|
|
178
|
+
portToPassthrough = _d.value;
|
|
179
|
+
return [4 /*yield*/, this.serverUdpPassthrough(portToPassthrough)];
|
|
180
|
+
case 10:
|
|
181
|
+
_g.sent();
|
|
182
|
+
_g.label = 11;
|
|
183
|
+
case 11:
|
|
184
|
+
_d = _c.next();
|
|
185
|
+
return [3 /*break*/, 9];
|
|
186
|
+
case 12: return [3 /*break*/, 15];
|
|
187
|
+
case 13:
|
|
188
|
+
e_2_1 = _g.sent();
|
|
189
|
+
e_2 = { error: e_2_1 };
|
|
190
|
+
return [3 /*break*/, 15];
|
|
191
|
+
case 14:
|
|
192
|
+
try {
|
|
193
|
+
if (_d && !_d.done && (_f = _c.return)) _f.call(_c);
|
|
194
|
+
}
|
|
195
|
+
finally { if (e_2) throw e_2.error; }
|
|
196
|
+
return [7 /*endfinally*/];
|
|
197
|
+
case 15:
|
|
198
|
+
tnp_helpers_1.Helpers.info("Activated (server).");
|
|
162
199
|
return [2 /*return*/];
|
|
163
200
|
}
|
|
164
201
|
});
|
|
@@ -170,15 +207,19 @@ var VpnSplit = /** @class */ (function () {
|
|
|
170
207
|
// console.log(hosts);
|
|
171
208
|
saveHosts(hosts);
|
|
172
209
|
};
|
|
210
|
+
VpnSplit.prototype.applyHostsLocal = function (hosts) {
|
|
211
|
+
// console.log(hosts);
|
|
212
|
+
saveHostsLocal(hosts);
|
|
213
|
+
};
|
|
173
214
|
//#endregion
|
|
174
215
|
//#region start client
|
|
175
216
|
VpnSplit.prototype.startClient = function (vpnServerTargets_1) {
|
|
176
217
|
return tslib_1.__awaiter(this, arguments, void 0, function (vpnServerTargets, saveHostInUserFolder) {
|
|
177
|
-
var vpnServerTargets_2, vpnServerTargets_2_1, vpnServerTarget, hosts, vpnServerTargets_3, vpnServerTargets_3_1, vpnServerTarget, newHosts, newHosts_1, newHosts_1_1, host,
|
|
178
|
-
var e_3,
|
|
218
|
+
var vpnServerTargets_2, vpnServerTargets_2_1, vpnServerTarget, hosts, vpnServerTargets_3, vpnServerTargets_3_1, vpnServerTarget, newHosts, newHosts_1, newHosts_1_1, host, e_3_1, originalHosts, combinedHostsObj, _a, _b, portToPassthrough, e_4_1, _c, _d, portToPassthrough, e_5_1;
|
|
219
|
+
var e_6, _e, e_3, _f, e_7, _g, e_4, _h, e_5, _j;
|
|
179
220
|
if (saveHostInUserFolder === void 0) { saveHostInUserFolder = false; }
|
|
180
|
-
return tslib_1.__generator(this, function (
|
|
181
|
-
switch (
|
|
221
|
+
return tslib_1.__generator(this, function (_k) {
|
|
222
|
+
switch (_k.label) {
|
|
182
223
|
case 0:
|
|
183
224
|
if (!Array.isArray(vpnServerTargets)) {
|
|
184
225
|
vpnServerTargets = [vpnServerTargets];
|
|
@@ -189,59 +230,59 @@ var VpnSplit = /** @class */ (function () {
|
|
|
189
230
|
this.preventBadTargetForClient(vpnServerTarget);
|
|
190
231
|
}
|
|
191
232
|
}
|
|
192
|
-
catch (
|
|
233
|
+
catch (e_6_1) { e_6 = { error: e_6_1 }; }
|
|
193
234
|
finally {
|
|
194
235
|
try {
|
|
195
|
-
if (vpnServerTargets_2_1 && !vpnServerTargets_2_1.done && (
|
|
236
|
+
if (vpnServerTargets_2_1 && !vpnServerTargets_2_1.done && (_e = vpnServerTargets_2.return)) _e.call(vpnServerTargets_2);
|
|
196
237
|
}
|
|
197
|
-
finally { if (
|
|
238
|
+
finally { if (e_6) throw e_6.error; }
|
|
198
239
|
}
|
|
199
240
|
this.createCertificateIfNotExists();
|
|
200
241
|
hosts = [];
|
|
201
|
-
|
|
242
|
+
_k.label = 1;
|
|
202
243
|
case 1:
|
|
203
|
-
|
|
244
|
+
_k.trys.push([1, 6, 7, 8]);
|
|
204
245
|
vpnServerTargets_3 = tslib_1.__values(vpnServerTargets), vpnServerTargets_3_1 = vpnServerTargets_3.next();
|
|
205
|
-
|
|
246
|
+
_k.label = 2;
|
|
206
247
|
case 2:
|
|
207
248
|
if (!!vpnServerTargets_3_1.done) return [3 /*break*/, 5];
|
|
208
249
|
vpnServerTarget = vpnServerTargets_3_1.value;
|
|
209
250
|
return [4 /*yield*/, this.getRemoteHosts(vpnServerTarget)];
|
|
210
251
|
case 3:
|
|
211
|
-
newHosts =
|
|
252
|
+
newHosts = _k.sent();
|
|
212
253
|
try {
|
|
213
|
-
for (newHosts_1 = (
|
|
254
|
+
for (newHosts_1 = (e_7 = void 0, tslib_1.__values(newHosts)), newHosts_1_1 = newHosts_1.next(); !newHosts_1_1.done; newHosts_1_1 = newHosts_1.next()) {
|
|
214
255
|
host = newHosts_1_1.value;
|
|
256
|
+
// Mark the original VPN server domain
|
|
215
257
|
host.originHostname = vpnServerTarget.hostname;
|
|
216
|
-
// console.log('host.originHostname' + host.originHostname)
|
|
217
258
|
hosts.push(host);
|
|
218
259
|
}
|
|
219
260
|
}
|
|
220
|
-
catch (
|
|
261
|
+
catch (e_7_1) { e_7 = { error: e_7_1 }; }
|
|
221
262
|
finally {
|
|
222
263
|
try {
|
|
223
|
-
if (newHosts_1_1 && !newHosts_1_1.done && (
|
|
264
|
+
if (newHosts_1_1 && !newHosts_1_1.done && (_g = newHosts_1.return)) _g.call(newHosts_1);
|
|
224
265
|
}
|
|
225
|
-
finally { if (
|
|
266
|
+
finally { if (e_7) throw e_7.error; }
|
|
226
267
|
}
|
|
227
|
-
|
|
268
|
+
_k.label = 4;
|
|
228
269
|
case 4:
|
|
229
270
|
vpnServerTargets_3_1 = vpnServerTargets_3.next();
|
|
230
271
|
return [3 /*break*/, 2];
|
|
231
272
|
case 5: return [3 /*break*/, 8];
|
|
232
273
|
case 6:
|
|
233
|
-
|
|
234
|
-
|
|
274
|
+
e_3_1 = _k.sent();
|
|
275
|
+
e_3 = { error: e_3_1 };
|
|
235
276
|
return [3 /*break*/, 8];
|
|
236
277
|
case 7:
|
|
237
278
|
try {
|
|
238
|
-
if (vpnServerTargets_3_1 && !vpnServerTargets_3_1.done && (
|
|
279
|
+
if (vpnServerTargets_3_1 && !vpnServerTargets_3_1.done && (_f = vpnServerTargets_3.return)) _f.call(vpnServerTargets_3);
|
|
239
280
|
}
|
|
240
|
-
finally { if (
|
|
281
|
+
finally { if (e_3) throw e_3.error; }
|
|
241
282
|
return [7 /*endfinally*/];
|
|
242
283
|
case 8:
|
|
243
284
|
originalHosts = this.hostsArr;
|
|
244
|
-
|
|
285
|
+
combinedHostsObj = tnp_core_1._.values(tslib_1.__spreadArray(tslib_1.__spreadArray([], tslib_1.__read(originalHosts), false), tslib_1.__read(hosts.map(function (h) {
|
|
245
286
|
return models_1.HostForServer.From({
|
|
246
287
|
aliases: h.alias,
|
|
247
288
|
ipOrDomain: h.ip,
|
|
@@ -252,8 +293,6 @@ var VpnSplit = /** @class */ (function () {
|
|
|
252
293
|
if (!copy.isDefault) {
|
|
253
294
|
copy.ip = "127.0.0.1";
|
|
254
295
|
}
|
|
255
|
-
// copy = HostForServer.From(copy);
|
|
256
|
-
// console.log('cloned host.originHostname' + copy.originHostname)
|
|
257
296
|
return copy;
|
|
258
297
|
})
|
|
259
298
|
.reduce(function (prev, curr) {
|
|
@@ -262,34 +301,59 @@ var VpnSplit = /** @class */ (function () {
|
|
|
262
301
|
_a[curr.aliases.join(' ')] = curr,
|
|
263
302
|
_a));
|
|
264
303
|
}, {}));
|
|
265
|
-
saveHosts(
|
|
266
|
-
|
|
304
|
+
saveHosts(combinedHostsObj, { saveHostInUserFolder: saveHostInUserFolder });
|
|
305
|
+
_k.label = 9;
|
|
267
306
|
case 9:
|
|
268
|
-
|
|
307
|
+
_k.trys.push([9, 14, 15, 16]);
|
|
269
308
|
_a = tslib_1.__values(this.portsToPass), _b = _a.next();
|
|
270
|
-
|
|
309
|
+
_k.label = 10;
|
|
271
310
|
case 10:
|
|
272
311
|
if (!!_b.done) return [3 /*break*/, 13];
|
|
273
312
|
portToPassthrough = _b.value;
|
|
274
|
-
return [4 /*yield*/, this.clientPassthrough(portToPassthrough, vpnServerTargets,
|
|
313
|
+
return [4 /*yield*/, this.clientPassthrough(portToPassthrough, vpnServerTargets, combinedHostsObj)];
|
|
275
314
|
case 11:
|
|
276
|
-
|
|
277
|
-
|
|
315
|
+
_k.sent();
|
|
316
|
+
_k.label = 12;
|
|
278
317
|
case 12:
|
|
279
318
|
_b = _a.next();
|
|
280
319
|
return [3 /*break*/, 10];
|
|
281
320
|
case 13: return [3 /*break*/, 16];
|
|
282
321
|
case 14:
|
|
283
|
-
|
|
284
|
-
|
|
322
|
+
e_4_1 = _k.sent();
|
|
323
|
+
e_4 = { error: e_4_1 };
|
|
285
324
|
return [3 /*break*/, 16];
|
|
286
325
|
case 15:
|
|
287
326
|
try {
|
|
288
|
-
if (_b && !_b.done && (
|
|
327
|
+
if (_b && !_b.done && (_h = _a.return)) _h.call(_a);
|
|
289
328
|
}
|
|
290
|
-
finally { if (
|
|
329
|
+
finally { if (e_4) throw e_4.error; }
|
|
291
330
|
return [7 /*endfinally*/];
|
|
292
331
|
case 16:
|
|
332
|
+
_k.trys.push([16, 21, 22, 23]);
|
|
333
|
+
_c = tslib_1.__values(this.portsToPass), _d = _c.next();
|
|
334
|
+
_k.label = 17;
|
|
335
|
+
case 17:
|
|
336
|
+
if (!!_d.done) return [3 /*break*/, 20];
|
|
337
|
+
portToPassthrough = _d.value;
|
|
338
|
+
return [4 /*yield*/, this.clientUdpPassthrough(portToPassthrough, vpnServerTargets, combinedHostsObj)];
|
|
339
|
+
case 18:
|
|
340
|
+
_k.sent();
|
|
341
|
+
_k.label = 19;
|
|
342
|
+
case 19:
|
|
343
|
+
_d = _c.next();
|
|
344
|
+
return [3 /*break*/, 17];
|
|
345
|
+
case 20: return [3 /*break*/, 23];
|
|
346
|
+
case 21:
|
|
347
|
+
e_5_1 = _k.sent();
|
|
348
|
+
e_5 = { error: e_5_1 };
|
|
349
|
+
return [3 /*break*/, 23];
|
|
350
|
+
case 22:
|
|
351
|
+
try {
|
|
352
|
+
if (_d && !_d.done && (_j = _c.return)) _j.call(_c);
|
|
353
|
+
}
|
|
354
|
+
finally { if (e_5) throw e_5.error; }
|
|
355
|
+
return [7 /*endfinally*/];
|
|
356
|
+
case 23:
|
|
293
357
|
tnp_helpers_1.Helpers.info("Client activated");
|
|
294
358
|
return [2 /*return*/];
|
|
295
359
|
}
|
|
@@ -306,17 +370,13 @@ var VpnSplit = /** @class */ (function () {
|
|
|
306
370
|
case 0:
|
|
307
371
|
_a.trys.push([0, 2, , 3]);
|
|
308
372
|
url = "http://".concat(vpnServerTarget.hostname).concat(SERVERS_PATH);
|
|
309
|
-
return [4 /*yield*/, (0, axios_1.default)({
|
|
310
|
-
url: url,
|
|
311
|
-
method: 'GET',
|
|
312
|
-
})];
|
|
373
|
+
return [4 /*yield*/, (0, axios_1.default)({ url: url, method: 'GET' })];
|
|
313
374
|
case 1:
|
|
314
|
-
response =
|
|
375
|
+
response = _a.sent();
|
|
315
376
|
return [2 /*return*/, response.data];
|
|
316
377
|
case 2:
|
|
317
378
|
err_1 = _a.sent();
|
|
318
|
-
tnp_helpers_1.Helpers.error("Remote server: ".concat(vpnServerTarget.hostname, "
|
|
319
|
-
" nothing to passthrought ", true, true);
|
|
379
|
+
tnp_helpers_1.Helpers.error("Remote server: ".concat(vpnServerTarget.hostname, " may be inactive..."), true, true);
|
|
320
380
|
return [2 /*return*/, []];
|
|
321
381
|
case 3: return [2 /*return*/];
|
|
322
382
|
}
|
|
@@ -328,18 +388,15 @@ var VpnSplit = /** @class */ (function () {
|
|
|
328
388
|
VpnSplit.prototype.createCertificateIfNotExists = function () {
|
|
329
389
|
if (!tnp_helpers_1.Helpers.exists(this.serveKeyPath) ||
|
|
330
390
|
!tnp_helpers_1.Helpers.exists(this.serveCertPath)) {
|
|
331
|
-
tnp_helpers_1.Helpers.info("[vpn-split] Generating new
|
|
391
|
+
tnp_helpers_1.Helpers.info("[vpn-split] Generating new self-signed certificate for localhost...");
|
|
332
392
|
var commandGen = "openssl req -nodes -new -x509 -keyout ".concat(this.serveKeyName, " -out ").concat(this.serveCertName);
|
|
333
393
|
tnp_helpers_1.Helpers.run(commandGen, { cwd: this.cwd, output: true }).sync();
|
|
334
|
-
// Helpers.run(`openssl verify -verbose -x509_strict -CAfile ${this.serveKeyName} ${this.serveCertChainName}`,
|
|
335
|
-
// { cwd: this.cwd, output: true }).sync()
|
|
336
394
|
}
|
|
337
395
|
};
|
|
338
396
|
//#endregion
|
|
339
|
-
//#region private methods /
|
|
397
|
+
//#region private methods / TCP & HTTPS passthrough
|
|
340
398
|
VpnSplit.prototype.getTarget = function (_a) {
|
|
341
399
|
var req = _a.req, res = _a.res, port = _a.port, hostname = _a.hostname;
|
|
342
|
-
// console.log(`protocol="${req.protocol}", hostname="${hostname}", port="${port}"`)
|
|
343
400
|
return "".concat(req.protocol, "://").concat(hostname, ":").concat(port);
|
|
344
401
|
};
|
|
345
402
|
VpnSplit.prototype.getProxyConfig = function (_a) {
|
|
@@ -351,8 +408,13 @@ var VpnSplit = /** @class */ (function () {
|
|
|
351
408
|
port: port,
|
|
352
409
|
hostname: serverPassthrough ? hostname : req.hostname,
|
|
353
410
|
});
|
|
354
|
-
// console.log(
|
|
355
|
-
//
|
|
411
|
+
// console.log({
|
|
412
|
+
// target,
|
|
413
|
+
// port,
|
|
414
|
+
// hostname,
|
|
415
|
+
// reqHostname: req.hostname,
|
|
416
|
+
// serverPassthrough,
|
|
417
|
+
// });
|
|
356
418
|
return isHttps
|
|
357
419
|
? {
|
|
358
420
|
target: target,
|
|
@@ -361,60 +423,38 @@ var VpnSplit = /** @class */ (function () {
|
|
|
361
423
|
cert: tnp_core_1.fse.readFileSync(this.serveCertPath),
|
|
362
424
|
},
|
|
363
425
|
agent: new tnp_core_1.https.Agent({
|
|
364
|
-
// for self signed you could also add
|
|
365
|
-
// rejectUnauthorized: false,
|
|
366
|
-
// allow legacy server
|
|
367
426
|
secureOptions: crypto.constants.SSL_OP_LEGACY_SERVER_CONNECT,
|
|
368
427
|
}),
|
|
369
428
|
secure: false,
|
|
370
|
-
// followRedirects: true,
|
|
371
|
-
// changeOrigin: true,
|
|
372
429
|
}
|
|
373
|
-
: {
|
|
374
|
-
target: target,
|
|
375
|
-
};
|
|
376
|
-
};
|
|
377
|
-
VpnSplit.prototype.getGetRequestInfo = function (req, res, port, type) {
|
|
378
|
-
return "server passthrough type: ".concat(type, "\nprotocol: ").concat(req.protocol, " <br>\nhostname: ").concat(req.hostname, " <br>\noriginalUrl: ").concat(req.originalUrl, " <br>\nreq.method ").concat(req.method, " <br>\nport: ").concat(port, " <br>\nSERVERS_PATH ").concat(SERVERS_PATH, " <br>");
|
|
430
|
+
: { target: target };
|
|
379
431
|
};
|
|
380
432
|
VpnSplit.prototype.getNotFoundMsg = function (req, res, port, type) {
|
|
381
|
-
return "[vpn-split] You are requesting
|
|
433
|
+
return "[vpn-split] You are requesting a URL that is not in proxy reach [".concat(type, "]\nProtocol: ").concat(req.protocol, "\nHostname: ").concat(req.hostname, "\nOriginalUrl: ").concat(req.originalUrl, "\nReq.method: ").concat(req.method, "\nPort: ").concat(port, "\nSERVERS_PATH: ").concat(SERVERS_PATH);
|
|
382
434
|
};
|
|
383
|
-
VpnSplit.prototype.
|
|
384
|
-
return "[vpn-split]
|
|
435
|
+
VpnSplit.prototype.getMaybeChangeOriginTrueMsg = function (req, res, port, type) {
|
|
436
|
+
return "[vpn-split] Possibly need changeOrigin: true in your proxy config\nProtocol: ".concat(req.protocol, "\nHostname: ").concat(req.hostname, "\nOriginalUrl: ").concat(req.originalUrl, "\nReq.method: ").concat(req.method, "\nPort: ").concat(port);
|
|
385
437
|
};
|
|
386
|
-
Object.defineProperty(VpnSplit.prototype, "headersToRemove", {
|
|
387
|
-
get: function () {
|
|
388
|
-
return [
|
|
389
|
-
// 'Strict-Transport-Security',
|
|
390
|
-
// 'upgrade-insecure-requests',
|
|
391
|
-
// 'Content-Security-Policy',
|
|
392
|
-
// 'Upgrade-Insecure-Requests',
|
|
393
|
-
// 'content-security-policy',
|
|
394
|
-
];
|
|
395
|
-
},
|
|
396
|
-
enumerable: false,
|
|
397
|
-
configurable: true
|
|
398
|
-
});
|
|
399
438
|
VpnSplit.prototype.filterHeaders = function (req, res) {
|
|
400
|
-
|
|
439
|
+
// If you have any headers to remove, do it here:
|
|
440
|
+
var headersToRemove = [
|
|
441
|
+
// 'Strict-Transport-Security',
|
|
442
|
+
// 'Content-Security-Policy',
|
|
443
|
+
// ...
|
|
444
|
+
];
|
|
445
|
+
headersToRemove.forEach(function (headerName) {
|
|
401
446
|
delete req.headers[headerName];
|
|
402
447
|
res.setHeader(headerName, '');
|
|
403
448
|
});
|
|
404
449
|
};
|
|
405
450
|
VpnSplit.prototype.isHttpsPort = function (port) {
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
// 2222,
|
|
409
|
-
// 22,
|
|
410
|
-
];
|
|
411
|
-
port = Number(port);
|
|
412
|
-
return httpPorts.includes(port);
|
|
451
|
+
// Decide your logic for “is HTTPS” here
|
|
452
|
+
return [443, 4443, 9443].includes(port);
|
|
413
453
|
};
|
|
414
|
-
//#region
|
|
454
|
+
//#region server passthrough (TCP/HTTPS)
|
|
415
455
|
VpnSplit.prototype.serverPassthrough = function (portToPassthrough) {
|
|
416
456
|
return tslib_1.__awaiter(this, void 0, void 0, function () {
|
|
417
|
-
var isHttps, app, proxy, currentLocalIps,
|
|
457
|
+
var isHttps, app, proxy, currentLocalIps, server;
|
|
418
458
|
var _this = this;
|
|
419
459
|
return tslib_1.__generator(this, function (_a) {
|
|
420
460
|
switch (_a.label) {
|
|
@@ -427,17 +467,14 @@ var VpnSplit = /** @class */ (function () {
|
|
|
427
467
|
'localhost',
|
|
428
468
|
'127.0.0.1'
|
|
429
469
|
], tslib_1.__read(tnp_helpers_1.Helpers.allLocalIpAddresses().map(function (a) { return a.hostname; })), false);
|
|
430
|
-
// console.log({ currentLocalIps });
|
|
431
470
|
app.use(function (req, res, next) {
|
|
432
471
|
_this.filterHeaders(req, res);
|
|
433
472
|
if (currentLocalIps.includes(req.hostname)) {
|
|
434
473
|
if (req.method === 'GET' && req.originalUrl === SERVERS_PATH) {
|
|
435
|
-
res.send(JSON.stringify(_this.hostsArrWithoutDefault.map(function (h) {
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
};
|
|
440
|
-
})));
|
|
474
|
+
res.send(JSON.stringify(_this.hostsArrWithoutDefault.map(function (h) { return ({
|
|
475
|
+
ip: h.ip,
|
|
476
|
+
alias: tnp_helpers_1.Helpers.arrays.from(h.aliases).join(' '),
|
|
477
|
+
}); })));
|
|
441
478
|
}
|
|
442
479
|
else {
|
|
443
480
|
var msg = _this.getNotFoundMsg(req, res, portToPassthrough, 'server');
|
|
@@ -450,21 +487,20 @@ var VpnSplit = /** @class */ (function () {
|
|
|
450
487
|
proxy.web(req, res, _this.getProxyConfig({ req: req, res: res, port: portToPassthrough, isHttps: isHttps }), next);
|
|
451
488
|
}
|
|
452
489
|
});
|
|
453
|
-
|
|
454
|
-
?
|
|
490
|
+
server = isHttps
|
|
491
|
+
? tnp_core_1.https.createServer({
|
|
455
492
|
key: tnp_core_1.fse.readFileSync(this.serveKeyPath),
|
|
456
493
|
cert: tnp_core_1.fse.readFileSync(this.serveCertPath),
|
|
457
494
|
}, app)
|
|
458
|
-
:
|
|
495
|
+
: tnp_core_1.http.createServer(app);
|
|
459
496
|
return [4 /*yield*/, tnp_helpers_1.Helpers.killProcessByPort(portToPassthrough, { silent: true })];
|
|
460
497
|
case 1:
|
|
461
498
|
_a.sent();
|
|
462
499
|
return [4 /*yield*/, new Promise(function (resolve, reject) {
|
|
463
|
-
|
|
464
|
-
console.log("
|
|
465
|
-
|
|
500
|
+
server.listen(portToPassthrough, function () {
|
|
501
|
+
console.log("TCP/HTTPS server listening on port ".concat(portToPassthrough, " (secure=").concat(isHttps, ")"));
|
|
502
|
+
resolve();
|
|
466
503
|
});
|
|
467
|
-
resolve(void 0);
|
|
468
504
|
})];
|
|
469
505
|
case 2:
|
|
470
506
|
_a.sent();
|
|
@@ -474,135 +510,165 @@ var VpnSplit = /** @class */ (function () {
|
|
|
474
510
|
});
|
|
475
511
|
};
|
|
476
512
|
//#endregion
|
|
477
|
-
//#region
|
|
478
|
-
VpnSplit.prototype.resolveProperTarget = function (vpnServerTargetsObj, req, hosts) {
|
|
479
|
-
/**
|
|
480
|
-
*
|
|
481
|
-
*/
|
|
482
|
-
var originHostname = hosts[req.hostname];
|
|
483
|
-
// console.log({
|
|
484
|
-
// 'req.hostname': req.hostname,
|
|
485
|
-
// 'originHostname': originHostname
|
|
486
|
-
// })
|
|
487
|
-
return vpnServerTargetsObj[originHostname];
|
|
488
|
-
};
|
|
513
|
+
//#region client passthrough (TCP/HTTPS)
|
|
489
514
|
VpnSplit.prototype.clientPassthrough = function (portToPassthrough, vpnServerTargets, hostsArr) {
|
|
490
515
|
return tslib_1.__awaiter(this, void 0, void 0, function () {
|
|
491
|
-
var
|
|
516
|
+
var aliasToOriginHostname, hostsArr_1, hostsArr_1_1, h, _a, _b, alias, originToUrlMap, vpnServerTargets_1, vpnServerTargets_1_1, url, isHttps, app, proxy, server;
|
|
517
|
+
var e_8, _c, e_9, _d, e_10, _e;
|
|
492
518
|
var _this = this;
|
|
493
|
-
return tslib_1.__generator(this, function (
|
|
494
|
-
switch (
|
|
519
|
+
return tslib_1.__generator(this, function (_f) {
|
|
520
|
+
switch (_f.label) {
|
|
495
521
|
case 0:
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
for (var _b = tslib_1.__values(b.aliases), _c = _b.next(); !_c.done; _c = _b.next()) {
|
|
501
|
-
var aliasDomain = _c.value;
|
|
502
|
-
aliasesObj[aliasDomain] = b.originHostname;
|
|
503
|
-
}
|
|
504
|
-
}
|
|
505
|
-
catch (e_5_1) { e_5 = { error: e_5_1 }; }
|
|
506
|
-
finally {
|
|
522
|
+
aliasToOriginHostname = {};
|
|
523
|
+
try {
|
|
524
|
+
for (hostsArr_1 = tslib_1.__values(hostsArr), hostsArr_1_1 = hostsArr_1.next(); !hostsArr_1_1.done; hostsArr_1_1 = hostsArr_1.next()) {
|
|
525
|
+
h = hostsArr_1_1.value;
|
|
507
526
|
try {
|
|
508
|
-
|
|
527
|
+
for (_a = (e_9 = void 0, tslib_1.__values(h.aliases)), _b = _a.next(); !_b.done; _b = _a.next()) {
|
|
528
|
+
alias = _b.value;
|
|
529
|
+
aliasToOriginHostname[alias] = h.originHostname;
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
catch (e_9_1) { e_9 = { error: e_9_1 }; }
|
|
533
|
+
finally {
|
|
534
|
+
try {
|
|
535
|
+
if (_b && !_b.done && (_d = _a.return)) _d.call(_a);
|
|
536
|
+
}
|
|
537
|
+
finally { if (e_9) throw e_9.error; }
|
|
509
538
|
}
|
|
510
|
-
finally { if (e_5) throw e_5.error; }
|
|
511
539
|
}
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
}
|
|
520
|
-
|
|
521
|
-
delete
|
|
540
|
+
}
|
|
541
|
+
catch (e_8_1) { e_8 = { error: e_8_1 }; }
|
|
542
|
+
finally {
|
|
543
|
+
try {
|
|
544
|
+
if (hostsArr_1_1 && !hostsArr_1_1.done && (_c = hostsArr_1.return)) _c.call(hostsArr_1);
|
|
545
|
+
}
|
|
546
|
+
finally { if (e_8) throw e_8.error; }
|
|
547
|
+
}
|
|
548
|
+
// Remove defaults from the map so we don't cause collisions
|
|
549
|
+
delete aliasToOriginHostname['localhost'];
|
|
550
|
+
delete aliasToOriginHostname['broadcasthost'];
|
|
551
|
+
originToUrlMap = {};
|
|
552
|
+
try {
|
|
553
|
+
for (vpnServerTargets_1 = tslib_1.__values(vpnServerTargets), vpnServerTargets_1_1 = vpnServerTargets_1.next(); !vpnServerTargets_1_1.done; vpnServerTargets_1_1 = vpnServerTargets_1.next()) {
|
|
554
|
+
url = vpnServerTargets_1_1.value;
|
|
555
|
+
originToUrlMap[url.hostname] = url;
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
catch (e_10_1) { e_10 = { error: e_10_1 }; }
|
|
559
|
+
finally {
|
|
560
|
+
try {
|
|
561
|
+
if (vpnServerTargets_1_1 && !vpnServerTargets_1_1.done && (_e = vpnServerTargets_1.return)) _e.call(vpnServerTargets_1);
|
|
562
|
+
}
|
|
563
|
+
finally { if (e_10) throw e_10.error; }
|
|
564
|
+
}
|
|
522
565
|
isHttps = this.isHttpsPort(portToPassthrough);
|
|
523
|
-
// if (isHttps) {
|
|
524
566
|
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
|
|
525
567
|
app = express();
|
|
526
568
|
proxy = httpProxy.createProxyServer({});
|
|
527
569
|
app.use(function (req, res, next) {
|
|
528
|
-
// console.log('req', req );
|
|
529
570
|
_this.filterHeaders(req, res);
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
}
|
|
537
|
-
else {
|
|
538
|
-
var msg = _this.getMaybeChangeOriginTrueMs(req, res, portToPassthrough, 'client');
|
|
539
|
-
// log.d(msg)
|
|
540
|
-
res.send(msg);
|
|
541
|
-
}
|
|
571
|
+
// Identify the real origin server based on alias
|
|
572
|
+
var originHostname = aliasToOriginHostname[req.hostname];
|
|
573
|
+
if (!originHostname) {
|
|
574
|
+
// Not one of our known aliases
|
|
575
|
+
var msg = _this.getMaybeChangeOriginTrueMsg(req, res, portToPassthrough, 'client');
|
|
576
|
+
res.send(msg);
|
|
542
577
|
next();
|
|
578
|
+
return;
|
|
543
579
|
}
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
}), next);
|
|
580
|
+
// Proxy onward to the real server domain at the same port
|
|
581
|
+
var targetUrlObj = originToUrlMap[originHostname];
|
|
582
|
+
if (!targetUrlObj) {
|
|
583
|
+
var notFoundMsg = _this.getNotFoundMsg(req, res, portToPassthrough, 'client');
|
|
584
|
+
res.send(notFoundMsg);
|
|
585
|
+
next();
|
|
586
|
+
return;
|
|
552
587
|
}
|
|
588
|
+
// Forward
|
|
589
|
+
proxy.web(req, res, _this.getProxyConfig({
|
|
590
|
+
req: req,
|
|
591
|
+
res: res,
|
|
592
|
+
port: portToPassthrough,
|
|
593
|
+
isHttps: isHttps,
|
|
594
|
+
hostname: targetUrlObj.hostname,
|
|
595
|
+
}), next);
|
|
553
596
|
});
|
|
554
|
-
|
|
555
|
-
?
|
|
597
|
+
server = isHttps
|
|
598
|
+
? tnp_core_1.https.createServer({
|
|
556
599
|
key: tnp_core_1.fse.readFileSync(this.serveKeyPath),
|
|
557
600
|
cert: tnp_core_1.fse.readFileSync(this.serveCertPath),
|
|
558
601
|
}, app)
|
|
559
|
-
:
|
|
602
|
+
: tnp_core_1.http.createServer(app);
|
|
560
603
|
return [4 /*yield*/, tnp_helpers_1.Helpers.killProcessByPort(portToPassthrough, { silent: true })];
|
|
561
604
|
case 1:
|
|
562
|
-
|
|
605
|
+
_f.sent();
|
|
563
606
|
return [4 /*yield*/, new Promise(function (resolve, reject) {
|
|
564
|
-
|
|
565
|
-
log.i("
|
|
566
|
-
|
|
607
|
+
server.listen(portToPassthrough, function () {
|
|
608
|
+
log.i("TCP/HTTPS client listening on port ".concat(portToPassthrough, " (secure=").concat(isHttps, ")"));
|
|
609
|
+
resolve();
|
|
567
610
|
});
|
|
568
|
-
resolve(void 0);
|
|
569
611
|
})];
|
|
570
612
|
case 2:
|
|
571
|
-
|
|
613
|
+
_f.sent();
|
|
572
614
|
return [2 /*return*/];
|
|
573
615
|
}
|
|
574
616
|
});
|
|
575
617
|
});
|
|
576
618
|
};
|
|
577
619
|
//#endregion
|
|
620
|
+
//#region UDP passthrough
|
|
621
|
+
/**
|
|
622
|
+
* Start a UDP socket for “server” mode on a given port.
|
|
623
|
+
* This example forwards inbound messages right back to the sender,
|
|
624
|
+
* or you can forward them to an external IP:port if desired.
|
|
625
|
+
*/
|
|
626
|
+
VpnSplit.prototype.serverUdpPassthrough = function (port) {
|
|
627
|
+
return tslib_1.__awaiter(this, void 0, void 0, function () {
|
|
628
|
+
var socket;
|
|
629
|
+
return tslib_1.__generator(this, function (_a) {
|
|
630
|
+
return [2 /*return*/];
|
|
631
|
+
});
|
|
632
|
+
});
|
|
633
|
+
};
|
|
634
|
+
/**
|
|
635
|
+
* Start a UDP socket for “client” mode on a given port.
|
|
636
|
+
* This example also just does a trivial pass-through or echo,
|
|
637
|
+
* but you can adapt to forward to a remote server.
|
|
638
|
+
*/
|
|
639
|
+
VpnSplit.prototype.clientUdpPassthrough = function (port, vpnServerTargets, hostsArr) {
|
|
640
|
+
return tslib_1.__awaiter(this, void 0, void 0, function () {
|
|
641
|
+
var socket, primaryTarget, targetHost, targetPort, clientMap;
|
|
642
|
+
return tslib_1.__generator(this, function (_a) {
|
|
643
|
+
return [2 /*return*/];
|
|
644
|
+
});
|
|
645
|
+
});
|
|
646
|
+
};
|
|
578
647
|
//#endregion
|
|
579
648
|
//#region private methods / get port from request
|
|
580
649
|
VpnSplit.prototype.getPortFromRequest = function (req) {
|
|
581
650
|
var host = req.headers.host;
|
|
582
651
|
var protocol = req.protocol;
|
|
583
|
-
var port;
|
|
584
652
|
if (host) {
|
|
585
653
|
var hostParts = host.split(':');
|
|
586
654
|
if (hostParts.length === 2) {
|
|
587
|
-
|
|
655
|
+
return Number(hostParts[1]);
|
|
588
656
|
}
|
|
589
657
|
else {
|
|
590
|
-
|
|
591
|
-
port = protocol === 'https' ? '443' : '80';
|
|
658
|
+
return protocol === 'https' ? 443 : 80;
|
|
592
659
|
}
|
|
593
660
|
}
|
|
594
|
-
|
|
595
|
-
// Default to port 80 if no host header is present (uncommon)
|
|
596
|
-
port = '80';
|
|
597
|
-
}
|
|
598
|
-
return Number(port);
|
|
661
|
+
return 80;
|
|
599
662
|
};
|
|
600
663
|
//#endregion
|
|
601
664
|
//#region private methods / prevent bad target for client
|
|
602
665
|
VpnSplit.prototype.preventBadTargetForClient = function (vpnServerTarget) {
|
|
603
666
|
if (!vpnServerTarget) {
|
|
604
667
|
var currentLocalIp = tnp_helpers_1.Helpers.localIpAddress();
|
|
605
|
-
tnp_helpers_1.Helpers.error("[vpn-server] Please provide
|
|
668
|
+
tnp_helpers_1.Helpers.error("[vpn-server] Please provide a correct target server.\n" +
|
|
669
|
+
"Example:\n" +
|
|
670
|
+
"vpn-server ".concat(currentLocalIp, "\n\n") +
|
|
671
|
+
"Your local IP is: ".concat(currentLocalIp), false, true);
|
|
606
672
|
}
|
|
607
673
|
};
|
|
608
674
|
//#endregion
|
|
@@ -616,7 +682,6 @@ var genMsg = "\n################################################\n## This file i
|
|
|
616
682
|
//#endregion
|
|
617
683
|
//#region helpers / save hosts
|
|
618
684
|
function saveHosts(hosts, options) {
|
|
619
|
-
// console.log({ hosts })
|
|
620
685
|
var saveHostInUserFolder = (options || {}).saveHostInUserFolder;
|
|
621
686
|
if (tnp_core_1._.isArray(hosts)) {
|
|
622
687
|
hosts = hosts.reduce(function (prev, curr) {
|
|
@@ -626,9 +691,25 @@ function saveHosts(hosts, options) {
|
|
|
626
691
|
_a));
|
|
627
692
|
}, {});
|
|
628
693
|
}
|
|
629
|
-
var toSave = parseHost(hosts, saveHostInUserFolder);
|
|
630
|
-
|
|
631
|
-
|
|
694
|
+
var toSave = parseHost(hosts, !!saveHostInUserFolder);
|
|
695
|
+
if (saveHostInUserFolder) {
|
|
696
|
+
tnp_helpers_1.Helpers.writeFile(HOST_FILE_PATHUSER, toSave);
|
|
697
|
+
}
|
|
698
|
+
else {
|
|
699
|
+
tnp_helpers_1.Helpers.writeFile(tnp_config_1.HOST_FILE_PATH, toSave);
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
function saveHostsLocal(hosts, options) {
|
|
703
|
+
var saveHostInUserFolder = (options || {}).saveHostInUserFolder;
|
|
704
|
+
if (tnp_core_1._.isArray(hosts)) {
|
|
705
|
+
hosts = hosts.reduce(function (prev, curr) {
|
|
706
|
+
var _a;
|
|
707
|
+
return tnp_core_1._.merge(prev, (_a = {},
|
|
708
|
+
_a[curr.name] = curr,
|
|
709
|
+
_a));
|
|
710
|
+
}, {});
|
|
711
|
+
}
|
|
712
|
+
var toSave = parseHost(hosts, !!saveHostInUserFolder, true);
|
|
632
713
|
if (saveHostInUserFolder) {
|
|
633
714
|
tnp_helpers_1.Helpers.writeFile(HOST_FILE_PATHUSER, toSave);
|
|
634
715
|
}
|
|
@@ -638,8 +719,8 @@ function saveHosts(hosts, options) {
|
|
|
638
719
|
}
|
|
639
720
|
//#endregion
|
|
640
721
|
//#region helpers / parse hosts
|
|
641
|
-
function parseHost(hosts,
|
|
642
|
-
|
|
722
|
+
function parseHost(hosts, saveHostInUserFolder, useLocal) {
|
|
723
|
+
if (useLocal === void 0) { useLocal = false; }
|
|
643
724
|
tnp_core_1._.keys(hosts).forEach(function (hostName) {
|
|
644
725
|
var v = hosts[hostName];
|
|
645
726
|
v.name = hostName;
|
|
@@ -649,11 +730,16 @@ function parseHost(hosts, options) {
|
|
|
649
730
|
tnp_core_1._.keys(hosts)
|
|
650
731
|
.map(function (hostName) {
|
|
651
732
|
var v = hosts[hostName];
|
|
733
|
+
var aliasesStr = v.aliases.join(' ');
|
|
652
734
|
if (saveHostInUserFolder) {
|
|
653
|
-
|
|
735
|
+
// For a user-specific hosts file:
|
|
736
|
+
return useLocal
|
|
737
|
+
? "127.0.0.1 ".concat(aliasesStr)
|
|
738
|
+
: "".concat(v.disabled ? '#' : '').concat(v.ipOrDomain, " ").concat(aliasesStr);
|
|
654
739
|
}
|
|
655
|
-
return
|
|
656
|
-
|
|
740
|
+
return useLocal
|
|
741
|
+
? "127.0.0.1 ".concat(aliasesStr)
|
|
742
|
+
: "".concat(v.disabled ? '#' : '').concat(v.ipOrDomain, " ").concat(aliasesStr, " # ").concat(v.name, " ").concat(GENERATED);
|
|
657
743
|
})
|
|
658
744
|
.join(EOL) +
|
|
659
745
|
EOL +
|