vpn-split 18.0.17 → 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.
@@ -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 index, portToPassthrough;
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 (_a) {
143
- switch (_a.label) {
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 80,443 to redirect to proper server domain/ip
144
+ //#region modify /etc/host to direct traffic appropriately
147
145
  saveHosts(this.hosts, { saveHostInUserFolder: saveHostInUserFolder });
148
- index = 0;
149
- _a.label = 1;
146
+ _g.label = 1;
150
147
  case 1:
151
- if (!(index < this.portsToPass.length)) return [3 /*break*/, 4];
152
- portToPassthrough = this.portsToPass[index];
153
- return [4 /*yield*/, this.serverPassthrough(portToPassthrough)];
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
- _a.sent();
156
- _a.label = 3;
152
+ if (!!_b.done) return [3 /*break*/, 5];
153
+ portToPassthrough = _b.value;
154
+ return [4 /*yield*/, this.serverPassthrough(portToPassthrough)];
157
155
  case 3:
158
- index++;
159
- return [3 /*break*/, 1];
156
+ _g.sent();
157
+ _g.label = 4;
160
158
  case 4:
161
- tnp_helpers_1.Helpers.info("Activated.");
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, e_1_1, originalHosts, cloned, _a, _b, portToPassthrough, e_2_1;
178
- var e_3, _c, e_1, _d, e_4, _e, e_2, _f;
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 (_g) {
181
- switch (_g.label) {
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 (e_3_1) { e_3 = { error: e_3_1 }; }
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 && (_c = vpnServerTargets_2.return)) _c.call(vpnServerTargets_2);
236
+ if (vpnServerTargets_2_1 && !vpnServerTargets_2_1.done && (_e = vpnServerTargets_2.return)) _e.call(vpnServerTargets_2);
196
237
  }
197
- finally { if (e_3) throw e_3.error; }
238
+ finally { if (e_6) throw e_6.error; }
198
239
  }
199
240
  this.createCertificateIfNotExists();
200
241
  hosts = [];
201
- _g.label = 1;
242
+ _k.label = 1;
202
243
  case 1:
203
- _g.trys.push([1, 6, 7, 8]);
244
+ _k.trys.push([1, 6, 7, 8]);
204
245
  vpnServerTargets_3 = tslib_1.__values(vpnServerTargets), vpnServerTargets_3_1 = vpnServerTargets_3.next();
205
- _g.label = 2;
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 = _g.sent();
252
+ newHosts = _k.sent();
212
253
  try {
213
- for (newHosts_1 = (e_4 = void 0, tslib_1.__values(newHosts)), newHosts_1_1 = newHosts_1.next(); !newHosts_1_1.done; newHosts_1_1 = newHosts_1.next()) {
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 (e_4_1) { e_4 = { error: e_4_1 }; }
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 && (_e = newHosts_1.return)) _e.call(newHosts_1);
264
+ if (newHosts_1_1 && !newHosts_1_1.done && (_g = newHosts_1.return)) _g.call(newHosts_1);
224
265
  }
225
- finally { if (e_4) throw e_4.error; }
266
+ finally { if (e_7) throw e_7.error; }
226
267
  }
227
- _g.label = 4;
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
- e_1_1 = _g.sent();
234
- e_1 = { error: e_1_1 };
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 && (_d = vpnServerTargets_3.return)) _d.call(vpnServerTargets_3);
279
+ if (vpnServerTargets_3_1 && !vpnServerTargets_3_1.done && (_f = vpnServerTargets_3.return)) _f.call(vpnServerTargets_3);
239
280
  }
240
- finally { if (e_1) throw e_1.error; }
281
+ finally { if (e_3) throw e_3.error; }
241
282
  return [7 /*endfinally*/];
242
283
  case 8:
243
284
  originalHosts = this.hostsArr;
244
- cloned = tnp_core_1._.values(tslib_1.__spreadArray(tslib_1.__spreadArray([], tslib_1.__read(originalHosts), false), tslib_1.__read(hosts.map(function (h) {
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(cloned, { saveHostInUserFolder: saveHostInUserFolder });
266
- _g.label = 9;
304
+ saveHosts(combinedHostsObj, { saveHostInUserFolder: saveHostInUserFolder });
305
+ _k.label = 9;
267
306
  case 9:
268
- _g.trys.push([9, 14, 15, 16]);
307
+ _k.trys.push([9, 14, 15, 16]);
269
308
  _a = tslib_1.__values(this.portsToPass), _b = _a.next();
270
- _g.label = 10;
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, cloned)];
313
+ return [4 /*yield*/, this.clientPassthrough(portToPassthrough, vpnServerTargets, combinedHostsObj)];
275
314
  case 11:
276
- _g.sent();
277
- _g.label = 12;
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
- e_2_1 = _g.sent();
284
- e_2 = { error: e_2_1 };
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 && (_f = _a.return)) _f.call(_a);
327
+ if (_b && !_b.done && (_h = _a.return)) _h.call(_a);
289
328
  }
290
- finally { if (e_2) throw e_2.error; }
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 = (_a.sent());
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, " maybe inactive...") +
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 certification for localhost... please follow instructions..");
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 / proxy passthrough
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(`[target] [${serverPassthrough ? 'server' : 'client'}] target="${target}", hostname="${hostname}",`
355
- // +` protocol="${req.protocol}", ip="${req.ip}", origin="${req.originalUrl}"`)
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 url that is not in proxy reach ".concat(type, "\n").concat(this.getGetRequestInfo(req, res, port, type), "\n ");
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.getMaybeChangeOriginTrueMs = function (req, res, port, type) {
384
- return "[vpn-split] maybe changeOrigin: true, in your porxy config ?\n".concat(this.getGetRequestInfo(req, res, port, type), "\n ");
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
- this.headersToRemove.forEach(function (headerName) {
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
- var httpPorts = [
407
- 443, 4443, 9443,
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 start server passthrough
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, h;
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
- return {
437
- ip: h.ip,
438
- alias: tnp_helpers_1.Helpers.arrays.from(h.aliases).join(' '),
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
- h = isHttps
454
- ? new tnp_core_1.https.Server({
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
- : new tnp_core_1.http.Server(app);
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
- h.listen(portToPassthrough, function () {
464
- console.log("Passthrough ".concat(isHttps ? 'SECURE' : 'UNSECURE', " server") +
465
- " listening on port: ".concat(portToPassthrough, "\n env: ").concat(app.settings.env, "\n "));
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 start client passthrough
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 hosts, vpnServerTargetsObj, isHttps, app, proxy, h;
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 (_a) {
494
- switch (_a.label) {
519
+ return tslib_1.__generator(this, function (_f) {
520
+ switch (_f.label) {
495
521
  case 0:
496
- hosts = hostsArr.reduce(function (a, b) {
497
- var e_5, _a;
498
- var aliasesObj = {};
499
- try {
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
- if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
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
- return tnp_core_1._.merge(a, aliasesObj);
513
- }, {});
514
- vpnServerTargetsObj = vpnServerTargets.reduce(function (a, b) {
515
- var _a;
516
- return tnp_core_1._.merge(a, (_a = {},
517
- _a[b.hostname] = b,
518
- _a));
519
- }, {});
520
- delete hosts['localhost'];
521
- delete hosts['broadcasthost'];
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
- var port = _this.getPortFromRequest(req);
531
- if (req.hostname === 'localhost') {
532
- if (_this.portsToPass.includes(port)) {
533
- var msg = _this.getNotFoundMsg(req, res, portToPassthrough, 'client');
534
- // log.d(msg)
535
- res.send(msg);
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
- else {
545
- proxy.web(req, res, _this.getProxyConfig({
546
- req: req,
547
- res: res,
548
- port: portToPassthrough,
549
- isHttps: isHttps,
550
- hostname: _this.resolveProperTarget(vpnServerTargetsObj, req, hosts).hostname,
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
- h = isHttps
555
- ? new tnp_core_1.https.Server({
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
- : new tnp_core_1.http.Server(app);
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
- _a.sent();
605
+ _f.sent();
563
606
  return [4 /*yield*/, new Promise(function (resolve, reject) {
564
- h.listen(portToPassthrough, function () {
565
- log.i("Passthrough ".concat(isHttps ? 'SECURE' : '', " client") +
566
- " listening on port: ".concat(portToPassthrough, "\n env: ").concat(app.settings.env, "\n "));
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
- _a.sent();
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
- port = hostParts[1];
655
+ return Number(hostParts[1]);
588
656
  }
589
657
  else {
590
- // Default ports based on protocol
591
- port = protocol === 'https' ? '443' : '80';
658
+ return protocol === 'https' ? 443 : 80;
592
659
  }
593
660
  }
594
- else {
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 (correct?) target server\n Example:\n vpn-server ".concat(currentLocalIp, " # or whatever ip of your machine with vpn\n\n # your local ip is: ").concat(currentLocalIp, "\n\n your args:\n ").concat(process.argv.slice(2).join(', '), "\n "), false, true);
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
- // Object.values(hosts).forEach( c => c )
631
- // console.log({ toSave })
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, options) {
642
- var saveHostInUserFolder = (options || {}).saveHostInUserFolder;
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
- return "".concat(v.disabled ? '#' : '').concat(v.ipOrDomain, " ").concat(v.aliases.join(' '));
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 ("".concat(v.disabled ? '#' : '').concat(v.ipOrDomain, " ").concat(v.aliases.join(' ')) +
656
- " # ".concat(v.name, " ").concat(GENERATED));
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 +