vpn-split 18.0.18 → 18.0.20

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.
Files changed (45) hide show
  1. package/assets/shared/shared_folder_info.txt +1 -1
  2. package/bin/vpn-split +11 -11
  3. package/bin/vpn-split-debug +11 -11
  4. package/browser/README.md +24 -24
  5. package/browser/esm2022/lib/models.mjs +19 -9
  6. package/browser/fesm2022/vpn-split.mjs +18 -8
  7. package/browser/fesm2022/vpn-split.mjs.map +1 -1
  8. package/browser/lib/models.d.ts +3 -1
  9. package/client/README.md +24 -24
  10. package/client/esm2022/lib/models.mjs +19 -9
  11. package/client/fesm2022/vpn-split.mjs +18 -8
  12. package/client/fesm2022/vpn-split.mjs.map +1 -1
  13. package/client/lib/models.d.ts +3 -1
  14. package/index.js +15 -2
  15. package/index.js.map +1 -1
  16. package/lib/build-info._auto-generated_.js.map +1 -1
  17. package/lib/hostile.backend.js +25 -31
  18. package/lib/hostile.backend.js.map +1 -1
  19. package/lib/index._auto-generated_.d.ts +1 -0
  20. package/lib/index._auto-generated_.js.map +1 -1
  21. package/lib/index.js +16 -3
  22. package/lib/index.js.map +1 -1
  23. package/lib/models.d.ts +3 -1
  24. package/lib/models.js +140 -193
  25. package/lib/models.js.map +1 -1
  26. package/lib/start.backend.d.ts +1 -0
  27. package/lib/start.backend.js.map +1 -1
  28. package/lib/vpn-split.backend.d.ts +18 -22
  29. package/lib/vpn-split.backend.js +469 -547
  30. package/lib/vpn-split.backend.js.map +1 -1
  31. package/migrations/index.js +15 -2
  32. package/migrations/index.js.map +1 -1
  33. package/migrations/migrations_index._auto-generated_.d.ts +1 -0
  34. package/migrations/migrations_index._auto-generated_.js.map +1 -1
  35. package/package.json +8 -44
  36. package/src.d.ts +1 -1
  37. package/taon.jsonc +33 -33
  38. package/tmp-environment.json +8 -375
  39. package/websql/README.md +24 -24
  40. package/websql/esm2022/lib/models.mjs +19 -9
  41. package/websql/fesm2022/vpn-split.mjs +18 -8
  42. package/websql/fesm2022/vpn-split.mjs.map +1 -1
  43. package/websql/lib/models.d.ts +3 -1
  44. package/browser/package.json +0 -25
  45. package/websql/package.json +0 -25
@@ -1,30 +1,31 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.VpnSplit = void 0;
4
- var tslib_1 = require("tslib");
5
4
  //#region imports
6
- var tnp_core_1 = require("tnp-core");
7
- var express = require("express");
8
- var httpProxy = require("http-proxy");
9
- var tnp_helpers_1 = require("tnp-helpers");
10
- var tnp_config_1 = require("tnp-config");
11
- var hostile_backend_1 = require("./hostile.backend");
12
- var models_1 = require("./models");
13
- var axios_1 = require("axios");
14
- var ng2_logger_1 = require("ng2-logger");
15
- var crypto = require("crypto");
16
- var log = ng2_logger_1.Log.create('vpn-split', ng2_logger_1.Level.INFO);
5
+ const tnp_core_1 = require("tnp-core");
6
+ const http = require("http");
7
+ const express = require("express");
8
+ const httpProxy = require("http-proxy");
9
+ const tnp_helpers_1 = require("tnp-helpers");
10
+ const tnp_config_1 = require("tnp-config");
11
+ const hostile_backend_1 = require("./hostile.backend");
12
+ const models_1 = require("./models");
13
+ const axios_1 = require("axios");
14
+ const ng2_logger_1 = require("ng2-logger");
15
+ const crypto = require("crypto");
16
+ const dgram = require("dgram"); // <-- For UDP sockets
17
+ const log = ng2_logger_1.Log.create('vpn-split', ng2_logger_1.Level.INFO);
17
18
  //#endregion
18
19
  //#region consts
19
- var GENERATED = '#GENERATED_BY_CLI#';
20
- var EOL = process.platform === 'win32' ? '\r\n' : '\n';
21
- var SERVERS_PATH = '/$$$$servers$$$$';
22
- var HOST_FILE_PATHUSER = (0, tnp_core_1.crossPlatformPath)([
20
+ const GENERATED = '#GENERATED_BY_CLI#';
21
+ const EOL = process.platform === 'win32' ? '\r\n' : '\n';
22
+ const SERVERS_PATH = '/$$$$servers$$$$';
23
+ const HOST_FILE_PATHUSER = (0, tnp_core_1.crossPlatformPath)([
23
24
  tnp_core_1.os.userInfo().homedir,
24
25
  'hosts-file__vpn-split',
25
26
  ]);
26
- var from = models_1.HostForServer.From;
27
- var defaultHosts = {
27
+ const from = models_1.HostForServer.From;
28
+ const defaultHosts = {
28
29
  'localhost alias': from({
29
30
  ipOrDomain: '127.0.0.1',
30
31
  aliases: 'localhost',
@@ -42,593 +43,510 @@ var defaultHosts = {
42
43
  }),
43
44
  };
44
45
  //#endregion
45
- var VpnSplit = /** @class */ (function () {
46
- function VpnSplit(portsToPass, hosts, cwd) {
46
+ class VpnSplit {
47
+ portsToPass;
48
+ hosts;
49
+ cwd;
50
+ //#region getters
51
+ get hostsArr() {
52
+ const hosts = this.hosts;
53
+ return tnp_core_1._.keys(hosts).map(hostName => {
54
+ const v = hosts[hostName];
55
+ v.name = hostName;
56
+ return v;
57
+ });
58
+ }
59
+ get hostsArrWithoutDefault() {
60
+ return this.hostsArr.filter(f => !f.isDefault);
61
+ }
62
+ get serveKeyName() {
63
+ return 'tmp-' + tnp_config_1.config.file.server_key;
64
+ }
65
+ get serveKeyPath() {
66
+ return tnp_core_1.path.join(this.cwd, this.serveKeyName);
67
+ }
68
+ get serveCertName() {
69
+ return 'tmp-' + tnp_config_1.config.file.server_cert;
70
+ }
71
+ get serveCertPath() {
72
+ return tnp_core_1.path.join(this.cwd, this.serveCertName);
73
+ }
74
+ get serveCertChainName() {
75
+ return 'tmp-' + tnp_config_1.config.file.server_chain_cert;
76
+ }
77
+ get serveCertChainPath() {
78
+ return tnp_core_1.path.join(this.cwd, this.serveCertChainName);
79
+ }
80
+ //#endregion
81
+ //#region fields
82
+ __hostile;
83
+ //#endregion
84
+ //#region singleton
85
+ static _instances = {};
86
+ constructor(portsToPass, hosts, cwd) {
47
87
  this.portsToPass = portsToPass;
48
88
  this.hosts = hosts;
49
89
  this.cwd = cwd;
50
90
  this.__hostile = new hostile_backend_1.Hostile();
51
91
  }
52
- Object.defineProperty(VpnSplit.prototype, "hostsArr", {
53
- //#region getters
54
- get: function () {
55
- var hosts = this.hosts;
56
- return tnp_core_1._.keys(hosts).map(function (hostName) {
57
- var v = hosts[hostName];
58
- v.name = hostName;
59
- return v;
60
- });
61
- },
62
- enumerable: false,
63
- configurable: true
64
- });
65
- Object.defineProperty(VpnSplit.prototype, "hostsArrWithoutDefault", {
66
- get: function () {
67
- return this.hostsArr.filter(function (f) { return !f.isDefault; });
68
- },
69
- enumerable: false,
70
- configurable: true
71
- });
72
- Object.defineProperty(VpnSplit.prototype, "serveKeyName", {
73
- get: function () {
74
- return 'tmp-' + tnp_config_1.config.file.server_key;
75
- },
76
- enumerable: false,
77
- configurable: true
78
- });
79
- Object.defineProperty(VpnSplit.prototype, "serveKeyPath", {
80
- get: function () {
81
- return tnp_core_1.path.join(this.cwd, this.serveKeyName);
82
- },
83
- enumerable: false,
84
- configurable: true
85
- });
86
- Object.defineProperty(VpnSplit.prototype, "serveCertName", {
87
- get: function () {
88
- return 'tmp-' + tnp_config_1.config.file.server_cert;
89
- },
90
- enumerable: false,
91
- configurable: true
92
- });
93
- Object.defineProperty(VpnSplit.prototype, "serveCertPath", {
94
- get: function () {
95
- return tnp_core_1.path.join(this.cwd, this.serveCertName);
96
- },
97
- enumerable: false,
98
- configurable: true
99
- });
100
- Object.defineProperty(VpnSplit.prototype, "serveCertChainName", {
101
- get: function () {
102
- return 'tmp-' + tnp_config_1.config.file.server_chain_cert;
103
- },
104
- enumerable: false,
105
- configurable: true
106
- });
107
- Object.defineProperty(VpnSplit.prototype, "serveCertChainPath", {
108
- get: function () {
109
- return tnp_core_1.path.join(this.cwd, this.serveCertChainName);
110
- },
111
- enumerable: false,
112
- configurable: true
113
- });
114
- VpnSplit.Instance = function () {
115
- return tslib_1.__awaiter(this, arguments, void 0, function (_a) {
116
- var _b = _a === void 0 ? {} : _a, _c = _b.ports, ports = _c === void 0 ? [80, 443, 4443, 22, 2222, 8180, 8080, 4407, 7999, 9443] : _c, _d = _b.additionalDefaultHosts, additionalDefaultHosts = _d === void 0 ? {} : _d, _e = _b.cwd, cwd = _e === void 0 ? process.cwd() : _e, _f = _b.allowNotSudo, allowNotSudo = _f === void 0 ? false : _f;
117
- return tslib_1.__generator(this, function (_g) {
118
- switch (_g.label) {
119
- case 0: return [4 /*yield*/, (0, tnp_core_1.isElevated)()];
120
- case 1:
121
- // console.log('ports', ports)
122
- // console.log({
123
- // allowNotSudo
124
- // })
125
- if (!(_g.sent()) && !allowNotSudo) {
126
- tnp_helpers_1.Helpers.error("[vpn-split] Please run this program as sudo (or admin on windows)", false, true);
127
- }
128
- if (!VpnSplit._instances[cwd]) {
129
- VpnSplit._instances[cwd] = new VpnSplit(ports, tnp_core_1._.merge(defaultHosts, additionalDefaultHosts), cwd);
130
- }
131
- return [2 /*return*/, VpnSplit._instances[cwd]];
132
- }
133
- });
134
- });
135
- };
92
+ static async Instance({ ports = [80, 443, 4443, 22, 2222, 8180, 8080, 4407, 7999, 9443], additionalDefaultHosts = {}, cwd = process.cwd(), allowNotSudo = false, } = {}) {
93
+ if (!(await (0, tnp_core_1.isElevated)()) && !allowNotSudo) {
94
+ tnp_helpers_1.Helpers.error(`[vpn-split] Please run this program as sudo (or admin on windows)`, false, true);
95
+ }
96
+ if (!VpnSplit._instances[cwd]) {
97
+ VpnSplit._instances[cwd] = new VpnSplit(ports, tnp_core_1._.merge(defaultHosts, additionalDefaultHosts), cwd);
98
+ }
99
+ return VpnSplit._instances[cwd];
100
+ }
136
101
  //#endregion
137
102
  //#region start server
138
- VpnSplit.prototype.startServer = function () {
139
- return tslib_1.__awaiter(this, arguments, void 0, function (saveHostInUserFolder) {
140
- var index, portToPassthrough;
141
- if (saveHostInUserFolder === void 0) { saveHostInUserFolder = false; }
142
- return tslib_1.__generator(this, function (_a) {
143
- switch (_a.label) {
144
- case 0:
145
- this.createCertificateIfNotExists();
146
- //#region modify /etc/host 80,443 to redirect to proper server domain/ip
147
- saveHosts(this.hosts, { saveHostInUserFolder: saveHostInUserFolder });
148
- index = 0;
149
- _a.label = 1;
150
- case 1:
151
- if (!(index < this.portsToPass.length)) return [3 /*break*/, 4];
152
- portToPassthrough = this.portsToPass[index];
153
- return [4 /*yield*/, this.serverPassthrough(portToPassthrough)];
154
- case 2:
155
- _a.sent();
156
- _a.label = 3;
157
- case 3:
158
- index++;
159
- return [3 /*break*/, 1];
160
- case 4:
161
- tnp_helpers_1.Helpers.info("Activated.");
162
- return [2 /*return*/];
163
- }
164
- });
165
- });
166
- };
103
+ async startServer(saveHostInUserFolder = false) {
104
+ this.createCertificateIfNotExists();
105
+ //#region modify /etc/host to direct traffic appropriately
106
+ saveHosts(this.hosts, { saveHostInUserFolder });
107
+ //#endregion
108
+ // Start TCP/HTTPS passthrough
109
+ for (const portToPassthrough of this.portsToPass) {
110
+ await this.serverPassthrough(portToPassthrough);
111
+ }
112
+ // Start UDP passthrough
113
+ for (const portToPassthrough of this.portsToPass) {
114
+ await this.serverUdpPassthrough(portToPassthrough);
115
+ }
116
+ tnp_helpers_1.Helpers.info(`Activated (server).`);
117
+ }
167
118
  //#endregion
168
119
  //#region apply hosts
169
- VpnSplit.prototype.applyHosts = function (hosts) {
120
+ applyHosts(hosts) {
170
121
  // console.log(hosts);
171
122
  saveHosts(hosts);
172
- };
123
+ }
124
+ applyHostsLocal(hosts) {
125
+ // console.log(hosts);
126
+ saveHostsLocal(hosts);
127
+ }
173
128
  //#endregion
174
129
  //#region start client
175
- VpnSplit.prototype.startClient = function (vpnServerTargets_1) {
176
- 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;
179
- if (saveHostInUserFolder === void 0) { saveHostInUserFolder = false; }
180
- return tslib_1.__generator(this, function (_g) {
181
- switch (_g.label) {
182
- case 0:
183
- if (!Array.isArray(vpnServerTargets)) {
184
- vpnServerTargets = [vpnServerTargets];
185
- }
186
- try {
187
- for (vpnServerTargets_2 = tslib_1.__values(vpnServerTargets), vpnServerTargets_2_1 = vpnServerTargets_2.next(); !vpnServerTargets_2_1.done; vpnServerTargets_2_1 = vpnServerTargets_2.next()) {
188
- vpnServerTarget = vpnServerTargets_2_1.value;
189
- this.preventBadTargetForClient(vpnServerTarget);
190
- }
191
- }
192
- catch (e_3_1) { e_3 = { error: e_3_1 }; }
193
- finally {
194
- try {
195
- if (vpnServerTargets_2_1 && !vpnServerTargets_2_1.done && (_c = vpnServerTargets_2.return)) _c.call(vpnServerTargets_2);
196
- }
197
- finally { if (e_3) throw e_3.error; }
198
- }
199
- this.createCertificateIfNotExists();
200
- hosts = [];
201
- _g.label = 1;
202
- case 1:
203
- _g.trys.push([1, 6, 7, 8]);
204
- vpnServerTargets_3 = tslib_1.__values(vpnServerTargets), vpnServerTargets_3_1 = vpnServerTargets_3.next();
205
- _g.label = 2;
206
- case 2:
207
- if (!!vpnServerTargets_3_1.done) return [3 /*break*/, 5];
208
- vpnServerTarget = vpnServerTargets_3_1.value;
209
- return [4 /*yield*/, this.getRemoteHosts(vpnServerTarget)];
210
- case 3:
211
- newHosts = _g.sent();
212
- 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()) {
214
- host = newHosts_1_1.value;
215
- host.originHostname = vpnServerTarget.hostname;
216
- // console.log('host.originHostname' + host.originHostname)
217
- hosts.push(host);
218
- }
219
- }
220
- catch (e_4_1) { e_4 = { error: e_4_1 }; }
221
- finally {
222
- try {
223
- if (newHosts_1_1 && !newHosts_1_1.done && (_e = newHosts_1.return)) _e.call(newHosts_1);
224
- }
225
- finally { if (e_4) throw e_4.error; }
226
- }
227
- _g.label = 4;
228
- case 4:
229
- vpnServerTargets_3_1 = vpnServerTargets_3.next();
230
- return [3 /*break*/, 2];
231
- case 5: return [3 /*break*/, 8];
232
- case 6:
233
- e_1_1 = _g.sent();
234
- e_1 = { error: e_1_1 };
235
- return [3 /*break*/, 8];
236
- case 7:
237
- try {
238
- if (vpnServerTargets_3_1 && !vpnServerTargets_3_1.done && (_d = vpnServerTargets_3.return)) _d.call(vpnServerTargets_3);
239
- }
240
- finally { if (e_1) throw e_1.error; }
241
- return [7 /*endfinally*/];
242
- case 8:
243
- 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) {
245
- return models_1.HostForServer.From({
246
- aliases: h.alias,
247
- ipOrDomain: h.ip,
248
- originHostname: h.originHostname,
249
- }, "external host ".concat(h.alias, " ").concat(h.ip));
250
- })), false).map(function (c) {
251
- var copy = c.clone();
252
- if (!copy.isDefault) {
253
- copy.ip = "127.0.0.1";
254
- }
255
- // copy = HostForServer.From(copy);
256
- // console.log('cloned host.originHostname' + copy.originHostname)
257
- return copy;
258
- })
259
- .reduce(function (prev, curr) {
260
- var _a;
261
- return tnp_core_1._.merge(prev, (_a = {},
262
- _a[curr.aliases.join(' ')] = curr,
263
- _a));
264
- }, {}));
265
- saveHosts(cloned, { saveHostInUserFolder: saveHostInUserFolder });
266
- _g.label = 9;
267
- case 9:
268
- _g.trys.push([9, 14, 15, 16]);
269
- _a = tslib_1.__values(this.portsToPass), _b = _a.next();
270
- _g.label = 10;
271
- case 10:
272
- if (!!_b.done) return [3 /*break*/, 13];
273
- portToPassthrough = _b.value;
274
- return [4 /*yield*/, this.clientPassthrough(portToPassthrough, vpnServerTargets, cloned)];
275
- case 11:
276
- _g.sent();
277
- _g.label = 12;
278
- case 12:
279
- _b = _a.next();
280
- return [3 /*break*/, 10];
281
- case 13: return [3 /*break*/, 16];
282
- case 14:
283
- e_2_1 = _g.sent();
284
- e_2 = { error: e_2_1 };
285
- return [3 /*break*/, 16];
286
- case 15:
287
- try {
288
- if (_b && !_b.done && (_f = _a.return)) _f.call(_a);
289
- }
290
- finally { if (e_2) throw e_2.error; }
291
- return [7 /*endfinally*/];
292
- case 16:
293
- tnp_helpers_1.Helpers.info("Client activated");
294
- return [2 /*return*/];
295
- }
130
+ async startClient(vpnServerTargets, saveHostInUserFolder = false) {
131
+ if (!Array.isArray(vpnServerTargets)) {
132
+ vpnServerTargets = [vpnServerTargets];
133
+ }
134
+ for (const vpnServerTarget of vpnServerTargets) {
135
+ this.preventBadTargetForClient(vpnServerTarget);
136
+ }
137
+ this.createCertificateIfNotExists();
138
+ // Get remote host definitions from remote server
139
+ const hosts = [];
140
+ for (const vpnServerTarget of vpnServerTargets) {
141
+ const newHosts = await this.getRemoteHosts(vpnServerTarget);
142
+ for (const host of newHosts) {
143
+ // Mark the original VPN server domain
144
+ host.originHostname = vpnServerTarget.hostname;
145
+ hosts.push(host);
146
+ }
147
+ }
148
+ // Merge with original, redirecting all non-default entries to 127.0.0.1
149
+ const originalHosts = this.hostsArr;
150
+ const combinedHostsObj = tnp_core_1._.values([
151
+ ...originalHosts,
152
+ ...hosts.map(h => models_1.HostForServer.From({
153
+ aliases: h.alias,
154
+ ipOrDomain: h.ip,
155
+ originHostname: h.originHostname,
156
+ }, `external host ${h.alias} ${h.ip}`)),
157
+ ]
158
+ .map(c => {
159
+ let copy = c.clone();
160
+ if (!copy.isDefault) {
161
+ copy.ip = `127.0.0.1`;
162
+ }
163
+ return copy;
164
+ })
165
+ .reduce((prev, curr) => {
166
+ return tnp_core_1._.merge(prev, {
167
+ [curr.aliases.join(' ')]: curr,
296
168
  });
297
- });
298
- };
169
+ }, {}));
170
+ saveHosts(combinedHostsObj, { saveHostInUserFolder });
171
+ // Start TCP/HTTPS passthrough
172
+ for (const portToPassthrough of this.portsToPass) {
173
+ await this.clientPassthrough(portToPassthrough, vpnServerTargets, combinedHostsObj);
174
+ }
175
+ // Start UDP passthrough
176
+ for (const portToPassthrough of this.portsToPass) {
177
+ await this.clientUdpPassthrough(portToPassthrough, vpnServerTargets, combinedHostsObj);
178
+ }
179
+ tnp_helpers_1.Helpers.info(`Client activated`);
180
+ }
299
181
  //#endregion
300
182
  //#region private methods / get remote hosts
301
- VpnSplit.prototype.getRemoteHosts = function (vpnServerTarget) {
302
- return tslib_1.__awaiter(this, void 0, void 0, function () {
303
- var url, response, err_1;
304
- return tslib_1.__generator(this, function (_a) {
305
- switch (_a.label) {
306
- case 0:
307
- _a.trys.push([0, 2, , 3]);
308
- url = "http://".concat(vpnServerTarget.hostname).concat(SERVERS_PATH);
309
- return [4 /*yield*/, (0, axios_1.default)({
310
- url: url,
311
- method: 'GET',
312
- })];
313
- case 1:
314
- response = (_a.sent());
315
- return [2 /*return*/, response.data];
316
- case 2:
317
- err_1 = _a.sent();
318
- tnp_helpers_1.Helpers.error("Remote server: ".concat(vpnServerTarget.hostname, " maybe inactive...") +
319
- " nothing to passthrought ", true, true);
320
- return [2 /*return*/, []];
321
- case 3: return [2 /*return*/];
322
- }
323
- });
324
- });
325
- };
183
+ async getRemoteHosts(vpnServerTarget) {
184
+ try {
185
+ const url = `http://${vpnServerTarget.hostname}${SERVERS_PATH}`;
186
+ const response = await (0, axios_1.default)({ url, method: 'GET' });
187
+ return response.data;
188
+ }
189
+ catch (err) {
190
+ tnp_helpers_1.Helpers.error(`Remote server: ${vpnServerTarget.hostname} may be inactive...`, true, true);
191
+ return [];
192
+ }
193
+ }
326
194
  //#endregion
327
195
  //#region private methods / create certificate
328
- VpnSplit.prototype.createCertificateIfNotExists = function () {
196
+ createCertificateIfNotExists() {
329
197
  if (!tnp_helpers_1.Helpers.exists(this.serveKeyPath) ||
330
198
  !tnp_helpers_1.Helpers.exists(this.serveCertPath)) {
331
- tnp_helpers_1.Helpers.info("[vpn-split] Generating new certification for localhost... please follow instructions..");
332
- var commandGen = "openssl req -nodes -new -x509 -keyout ".concat(this.serveKeyName, " -out ").concat(this.serveCertName);
199
+ tnp_helpers_1.Helpers.info(`[vpn-split] Generating new self-signed certificate for localhost...`);
200
+ const commandGen = `openssl req -nodes -new -x509 -keyout ${this.serveKeyName} -out ${this.serveCertName}`;
333
201
  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
202
  }
337
- };
203
+ }
338
204
  //#endregion
339
- //#region private methods / proxy passthrough
340
- VpnSplit.prototype.getTarget = function (_a) {
341
- var req = _a.req, res = _a.res, port = _a.port, hostname = _a.hostname;
342
- // console.log(`protocol="${req.protocol}", hostname="${hostname}", port="${port}"`)
343
- return "".concat(req.protocol, "://").concat(hostname, ":").concat(port);
344
- };
345
- VpnSplit.prototype.getProxyConfig = function (_a) {
346
- var req = _a.req, res = _a.res, port = _a.port, hostname = _a.hostname, isHttps = _a.isHttps;
347
- var serverPassthrough = !!hostname;
348
- var target = this.getTarget({
349
- req: req,
350
- res: res,
351
- port: port,
205
+ //#region private methods / TCP & HTTPS passthrough
206
+ getTarget({ req, res, port, hostname, }) {
207
+ return `${req.protocol}://${hostname}:${port}`;
208
+ }
209
+ getProxyConfig({ req, res, port, hostname, isHttps, }) {
210
+ const serverPassthrough = !!hostname;
211
+ const target = this.getTarget({
212
+ req,
213
+ res,
214
+ port,
352
215
  hostname: serverPassthrough ? hostname : req.hostname,
353
216
  });
354
- // console.log(`[target] [${serverPassthrough ? 'server' : 'client'}] target="${target}", hostname="${hostname}",`
355
- // +` protocol="${req.protocol}", ip="${req.ip}", origin="${req.originalUrl}"`)
217
+ // console.log({
218
+ // target,
219
+ // port,
220
+ // hostname,
221
+ // reqHostname: req.hostname,
222
+ // serverPassthrough,
223
+ // });
356
224
  return isHttps
357
225
  ? {
358
- target: target,
226
+ target,
359
227
  ssl: {
360
228
  key: tnp_core_1.fse.readFileSync(this.serveKeyPath),
361
229
  cert: tnp_core_1.fse.readFileSync(this.serveCertPath),
362
230
  },
363
231
  agent: new tnp_core_1.https.Agent({
364
- // for self signed you could also add
365
- // rejectUnauthorized: false,
366
- // allow legacy server
367
232
  secureOptions: crypto.constants.SSL_OP_LEGACY_SERVER_CONNECT,
368
233
  }),
369
234
  secure: false,
370
- // followRedirects: true,
371
- // changeOrigin: true,
372
235
  }
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>");
379
- };
380
- 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 ");
382
- };
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 ");
385
- };
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
- VpnSplit.prototype.filterHeaders = function (req, res) {
400
- this.headersToRemove.forEach(function (headerName) {
236
+ : { target };
237
+ }
238
+ getNotFoundMsg(req, res, port, type) {
239
+ return `[vpn-split] You are requesting a URL that is not in proxy reach [${type}]
240
+ Protocol: ${req.protocol}
241
+ Hostname: ${req.hostname}
242
+ OriginalUrl: ${req.originalUrl}
243
+ Req.method: ${req.method}
244
+ Port: ${port}
245
+ SERVERS_PATH: ${SERVERS_PATH}`;
246
+ }
247
+ getMaybeChangeOriginTrueMsg(req, res, port, type) {
248
+ return `[vpn-split] Possibly need changeOrigin: true in your proxy config
249
+ Protocol: ${req.protocol}
250
+ Hostname: ${req.hostname}
251
+ OriginalUrl: ${req.originalUrl}
252
+ Req.method: ${req.method}
253
+ Port: ${port}`;
254
+ }
255
+ filterHeaders(req, res) {
256
+ // If you have any headers to remove, do it here:
257
+ const headersToRemove = [
258
+ // 'Strict-Transport-Security',
259
+ // 'Content-Security-Policy',
260
+ // ...
261
+ ];
262
+ headersToRemove.forEach(headerName => {
401
263
  delete req.headers[headerName];
402
264
  res.setHeader(headerName, '');
403
265
  });
404
- };
405
- VpnSplit.prototype.isHttpsPort = function (port) {
406
- var httpPorts = [
407
- 443, 4443, 9443,
408
- // 2222,
409
- // 22,
266
+ }
267
+ isHttpsPort(port) {
268
+ // Decide your logic for “is HTTPS” here
269
+ return [443, 4443, 9443].includes(port);
270
+ }
271
+ //#region server passthrough (TCP/HTTPS)
272
+ async serverPassthrough(portToPassthrough) {
273
+ const isHttps = this.isHttpsPort(portToPassthrough);
274
+ process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
275
+ const app = express();
276
+ const proxy = httpProxy.createProxyServer({});
277
+ const currentLocalIps = [
278
+ 'localhost',
279
+ '127.0.0.1',
280
+ ...tnp_helpers_1.Helpers.allLocalIpAddresses().map(a => a.hostname),
410
281
  ];
411
- port = Number(port);
412
- return httpPorts.includes(port);
413
- };
414
- //#region start server passthrough
415
- VpnSplit.prototype.serverPassthrough = function (portToPassthrough) {
416
- return tslib_1.__awaiter(this, void 0, void 0, function () {
417
- var isHttps, app, proxy, currentLocalIps, h;
418
- var _this = this;
419
- return tslib_1.__generator(this, function (_a) {
420
- switch (_a.label) {
421
- case 0:
422
- isHttps = this.isHttpsPort(portToPassthrough);
423
- process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
424
- app = express();
425
- proxy = httpProxy.createProxyServer({});
426
- currentLocalIps = tslib_1.__spreadArray([
427
- 'localhost',
428
- '127.0.0.1'
429
- ], tslib_1.__read(tnp_helpers_1.Helpers.allLocalIpAddresses().map(function (a) { return a.hostname; })), false);
430
- // console.log({ currentLocalIps });
431
- app.use(function (req, res, next) {
432
- _this.filterHeaders(req, res);
433
- if (currentLocalIps.includes(req.hostname)) {
434
- 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
- })));
441
- }
442
- else {
443
- var msg = _this.getNotFoundMsg(req, res, portToPassthrough, 'server');
444
- log.d(msg);
445
- res.send(msg);
446
- }
447
- next();
448
- }
449
- else {
450
- proxy.web(req, res, _this.getProxyConfig({ req: req, res: res, port: portToPassthrough, isHttps: isHttps }), next);
451
- }
452
- });
453
- h = isHttps
454
- ? new tnp_core_1.https.Server({
455
- key: tnp_core_1.fse.readFileSync(this.serveKeyPath),
456
- cert: tnp_core_1.fse.readFileSync(this.serveCertPath),
457
- }, app)
458
- : new tnp_core_1.http.Server(app);
459
- return [4 /*yield*/, tnp_helpers_1.Helpers.killProcessByPort(portToPassthrough, { silent: true })];
460
- case 1:
461
- _a.sent();
462
- 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 "));
466
- });
467
- resolve(void 0);
468
- })];
469
- case 2:
470
- _a.sent();
471
- return [2 /*return*/];
282
+ app.use((req, res, next) => {
283
+ this.filterHeaders(req, res);
284
+ if (currentLocalIps.includes(req.hostname)) {
285
+ if (req.method === 'GET' && req.originalUrl === SERVERS_PATH) {
286
+ res.send(JSON.stringify(this.hostsArrWithoutDefault.map(h => ({
287
+ ip: h.ip,
288
+ alias: tnp_helpers_1.Helpers.arrays.from(h.aliases).join(' '),
289
+ }))));
290
+ }
291
+ else {
292
+ const msg = this.getNotFoundMsg(req, res, portToPassthrough, 'server');
293
+ log.d(msg);
294
+ res.send(msg);
472
295
  }
296
+ next();
297
+ }
298
+ else {
299
+ proxy.web(req, res, this.getProxyConfig({ req, res, port: portToPassthrough, isHttps }), next);
300
+ }
301
+ });
302
+ const server = isHttps
303
+ ? tnp_core_1.https.createServer({
304
+ key: tnp_core_1.fse.readFileSync(this.serveKeyPath),
305
+ cert: tnp_core_1.fse.readFileSync(this.serveCertPath),
306
+ }, app)
307
+ : http.createServer(app);
308
+ await tnp_helpers_1.Helpers.killProcessByPort(portToPassthrough, { silent: true });
309
+ await new Promise((resolve, reject) => {
310
+ server.listen(portToPassthrough, () => {
311
+ console.log(`TCP/HTTPS server listening on port ${portToPassthrough} (secure=${isHttps})`);
312
+ resolve();
473
313
  });
474
314
  });
475
- };
315
+ }
476
316
  //#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
- };
489
- VpnSplit.prototype.clientPassthrough = function (portToPassthrough, vpnServerTargets, hostsArr) {
490
- return tslib_1.__awaiter(this, void 0, void 0, function () {
491
- var hosts, vpnServerTargetsObj, isHttps, app, proxy, h;
492
- var _this = this;
493
- return tslib_1.__generator(this, function (_a) {
494
- switch (_a.label) {
495
- 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 {
507
- try {
508
- if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
509
- }
510
- finally { if (e_5) throw e_5.error; }
511
- }
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'];
522
- isHttps = this.isHttpsPort(portToPassthrough);
523
- // if (isHttps) {
524
- process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
525
- app = express();
526
- proxy = httpProxy.createProxyServer({});
527
- app.use(function (req, res, next) {
528
- // console.log('req', req );
529
- _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
- }
542
- next();
543
- }
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);
552
- }
553
- });
554
- h = isHttps
555
- ? new tnp_core_1.https.Server({
556
- key: tnp_core_1.fse.readFileSync(this.serveKeyPath),
557
- cert: tnp_core_1.fse.readFileSync(this.serveCertPath),
558
- }, app)
559
- : new tnp_core_1.http.Server(app);
560
- return [4 /*yield*/, tnp_helpers_1.Helpers.killProcessByPort(portToPassthrough, { silent: true })];
561
- case 1:
562
- _a.sent();
563
- 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 "));
567
- });
568
- resolve(void 0);
569
- })];
570
- case 2:
571
- _a.sent();
572
- return [2 /*return*/];
573
- }
317
+ //#region client passthrough (TCP/HTTPS)
318
+ async clientPassthrough(portToPassthrough, vpnServerTargets, hostsArr) {
319
+ // Map from an alias => the “real” origin hostname (the server domain)
320
+ const aliasToOriginHostname = {};
321
+ for (const h of hostsArr) {
322
+ for (const alias of h.aliases) {
323
+ aliasToOriginHostname[alias] = h.originHostname;
324
+ }
325
+ }
326
+ // Remove defaults from the map so we don't cause collisions
327
+ delete aliasToOriginHostname['localhost'];
328
+ delete aliasToOriginHostname['broadcasthost'];
329
+ // Build a dictionary from originHostname => URL (for quick lookup)
330
+ const originToUrlMap = {};
331
+ for (const url of vpnServerTargets) {
332
+ originToUrlMap[url.hostname] = url;
333
+ }
334
+ const isHttps = this.isHttpsPort(portToPassthrough);
335
+ process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
336
+ const app = express();
337
+ const proxy = httpProxy.createProxyServer({});
338
+ app.use((req, res, next) => {
339
+ this.filterHeaders(req, res);
340
+ // Identify the real origin server based on alias
341
+ const originHostname = aliasToOriginHostname[req.hostname];
342
+ if (!originHostname) {
343
+ // Not one of our known aliases
344
+ const msg = this.getMaybeChangeOriginTrueMsg(req, res, portToPassthrough, 'client');
345
+ res.send(msg);
346
+ next();
347
+ return;
348
+ }
349
+ // Proxy onward to the real server domain at the same port
350
+ const targetUrlObj = originToUrlMap[originHostname];
351
+ if (!targetUrlObj) {
352
+ const notFoundMsg = this.getNotFoundMsg(req, res, portToPassthrough, 'client');
353
+ res.send(notFoundMsg);
354
+ next();
355
+ return;
356
+ }
357
+ // Forward
358
+ proxy.web(req, res, this.getProxyConfig({
359
+ req,
360
+ res,
361
+ port: portToPassthrough,
362
+ isHttps,
363
+ hostname: targetUrlObj.hostname,
364
+ }), next);
365
+ });
366
+ const server = isHttps
367
+ ? tnp_core_1.https.createServer({
368
+ key: tnp_core_1.fse.readFileSync(this.serveKeyPath),
369
+ cert: tnp_core_1.fse.readFileSync(this.serveCertPath),
370
+ }, app)
371
+ : http.createServer(app);
372
+ await tnp_helpers_1.Helpers.killProcessByPort(portToPassthrough, { silent: true });
373
+ await new Promise((resolve, reject) => {
374
+ server.listen(portToPassthrough, () => {
375
+ log.i(`TCP/HTTPS client listening on port ${portToPassthrough} (secure=${isHttps})`);
376
+ resolve();
574
377
  });
575
378
  });
576
- };
379
+ }
577
380
  //#endregion
381
+ //#region UDP passthrough
382
+ /**
383
+ * Start a UDP socket for “server” mode on a given port.
384
+ * This example forwards inbound messages right back to the sender,
385
+ * or you can forward them to an external IP:port if desired.
386
+ */
387
+ async serverUdpPassthrough(port) {
388
+ return;
389
+ // Example of a simple “echo-style” server or forwarder
390
+ const socket = dgram.createSocket('udp4');
391
+ // (Optionally) kill existing processes on that port – though for UDP
392
+ // we might not have a direct “listener process.” Adjust as needed.
393
+ // await Helpers.killProcessByPort(port, { silent: true }).catch(() => {});
394
+ socket.on('message', (msg, rinfo) => {
395
+ // rinfo contains { address, port } of the sender
396
+ // In a typical “server” scenario, you might:
397
+ // 1. Inspect msg
398
+ // 2. Possibly forward to some real backend if needed
399
+ // 3. Or just echo it back
400
+ // For a real forward, do something like:
401
+ // const backendHost = 'some-other-host-or-ip';
402
+ // const backendPort = 9999;
403
+ // socket.send(msg, 0, msg.length, backendPort, backendHost);
404
+ // For a basic echo server:
405
+ socket.send(msg, 0, msg.length, rinfo.port, rinfo.address, err => {
406
+ if (err) {
407
+ log.er(`UDP server send error: ${err}`);
408
+ }
409
+ });
410
+ });
411
+ socket.on('listening', () => {
412
+ const address = socket.address();
413
+ log.i(`UDP server listening at ${address.address}:${address.port}`);
414
+ });
415
+ socket.bind(port);
416
+ }
417
+ /**
418
+ * Start a UDP socket for “client” mode on a given port.
419
+ * This example also just does a trivial pass-through or echo,
420
+ * but you can adapt to forward to a remote server.
421
+ */
422
+ async clientUdpPassthrough(port, vpnServerTargets, hostsArr) {
423
+ return;
424
+ // console.log(`Client UDP passthrough, port ${port}` );
425
+ // In client mode, we typically intercept local UDP traffic on “port”
426
+ // and forward it to the remote server. Then we forward the remote
427
+ // server's response back to the local client.
428
+ const socket = dgram.createSocket('udp4');
429
+ // await Helpers.killProcessByPort(port, { silent: true }).catch(() => {});
430
+ // For simplicity, pick the first server from the array
431
+ // Or add your own logic to choose among multiple.
432
+ const primaryTarget = vpnServerTargets[0];
433
+ const targetHost = primaryTarget.hostname;
434
+ // Choose the same port or a custom port
435
+ const targetPort = port;
436
+ // A map to remember who originally sent us a packet,
437
+ // so we can route the response back properly.
438
+ // Key could be “targetHost:targetPort => { address, port }”
439
+ // or “clientAddress:clientPort” => { remoteAddress, remotePort }.
440
+ // Adapt to your scenario.
441
+ const clientMap = new Map();
442
+ socket.on('message', (msg, rinfo) => {
443
+ //
444
+ // If the message is from a local client, forward to server.
445
+ // If the message is from the server, forward back to the correct client.
446
+ //
447
+ // Check if it’s from local or remote by address. This is simplistic:
448
+ const isFromLocal = !tnp_core_1._.includes(hostsArr.map(h => h.ipOrDomain), rinfo.address);
449
+ if (isFromLocal) {
450
+ // Received from local => forward to “server” (the VPN server)
451
+ // Keep track of who we got this from (the local client)
452
+ const key = `local-${rinfo.address}:${rinfo.port}`;
453
+ clientMap.set(key, rinfo);
454
+ // Forward to remote
455
+ socket.send(msg, 0, msg.length, targetPort, targetHost, err => {
456
+ if (err) {
457
+ log.er(`UDP client forward error: ${err}`);
458
+ }
459
+ });
460
+ }
461
+ else {
462
+ // Probably from remote => forward back to whichever local client sent it
463
+ // In a more advanced scenario, parse the payload or maintain a bigger table
464
+ // with NAT-like sessions.
465
+ //
466
+ // For now, we guess it’s from the “VPN server”
467
+ // We'll just route it back to the single local client that we stored
468
+ // or do multiple if we had a better NAT map.
469
+ // If you have multi-target or multi-client logic, adapt here.
470
+ // For example, search clientMap by something in the msg or a NAT key.
471
+ clientMap.forEach((localRinfo, key) => {
472
+ socket.send(msg, 0, msg.length, localRinfo.port, localRinfo.address, err => {
473
+ if (err) {
474
+ log.er(`UDP client re-send error: ${err}`);
475
+ }
476
+ });
477
+ });
478
+ }
479
+ });
480
+ socket.on('listening', () => {
481
+ const address = socket.address();
482
+ log.i(`UDP client listening at ${address.address}:${address.port}, forwarding to ${targetHost}:${targetPort}`);
483
+ });
484
+ socket.bind(port);
485
+ }
578
486
  //#endregion
579
487
  //#region private methods / get port from request
580
- VpnSplit.prototype.getPortFromRequest = function (req) {
581
- var host = req.headers.host;
582
- var protocol = req.protocol;
583
- var port;
488
+ getPortFromRequest(req) {
489
+ const host = req.headers.host;
490
+ const protocol = req.protocol;
584
491
  if (host) {
585
- var hostParts = host.split(':');
492
+ const hostParts = host.split(':');
586
493
  if (hostParts.length === 2) {
587
- port = hostParts[1];
494
+ return Number(hostParts[1]);
588
495
  }
589
496
  else {
590
- // Default ports based on protocol
591
- port = protocol === 'https' ? '443' : '80';
497
+ return protocol === 'https' ? 443 : 80;
592
498
  }
593
499
  }
594
- else {
595
- // Default to port 80 if no host header is present (uncommon)
596
- port = '80';
597
- }
598
- return Number(port);
599
- };
500
+ return 80;
501
+ }
600
502
  //#endregion
601
503
  //#region private methods / prevent bad target for client
602
- VpnSplit.prototype.preventBadTargetForClient = function (vpnServerTarget) {
504
+ preventBadTargetForClient(vpnServerTarget) {
603
505
  if (!vpnServerTarget) {
604
- 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);
506
+ const currentLocalIp = tnp_helpers_1.Helpers.localIpAddress();
507
+ tnp_helpers_1.Helpers.error(`[vpn-server] Please provide a correct target server.\n` +
508
+ `Example:\n` +
509
+ `vpn-server ${currentLocalIp}\n\n` +
510
+ `Your local IP is: ${currentLocalIp}`, false, true);
606
511
  }
607
- };
608
- //#endregion
609
- //#region singleton
610
- VpnSplit._instances = {};
611
- return VpnSplit;
612
- }());
512
+ }
513
+ }
613
514
  exports.VpnSplit = VpnSplit;
614
515
  //#region helper / gen msg
615
- var genMsg = "\n################################################\n## This file is generated #####################\n################################################\n".trim() + EOL;
516
+ const genMsg = `
517
+ ################################################
518
+ ## This file is generated #####################
519
+ ################################################
520
+ `.trim() + EOL;
616
521
  //#endregion
617
522
  //#region helpers / save hosts
618
523
  function saveHosts(hosts, options) {
619
- // console.log({ hosts })
620
- var saveHostInUserFolder = (options || {}).saveHostInUserFolder;
524
+ const { saveHostInUserFolder } = options || {};
525
+ if (tnp_core_1._.isArray(hosts)) {
526
+ hosts = hosts.reduce((prev, curr) => {
527
+ return tnp_core_1._.merge(prev, {
528
+ [curr.name]: curr,
529
+ });
530
+ }, {});
531
+ }
532
+ const toSave = parseHost(hosts, !!saveHostInUserFolder);
533
+ if (saveHostInUserFolder) {
534
+ tnp_helpers_1.Helpers.writeFile(HOST_FILE_PATHUSER, toSave);
535
+ }
536
+ else {
537
+ tnp_helpers_1.Helpers.writeFile(tnp_config_1.HOST_FILE_PATH, toSave);
538
+ }
539
+ }
540
+ function saveHostsLocal(hosts, options) {
541
+ const { saveHostInUserFolder } = options || {};
621
542
  if (tnp_core_1._.isArray(hosts)) {
622
- hosts = hosts.reduce(function (prev, curr) {
623
- var _a;
624
- return tnp_core_1._.merge(prev, (_a = {},
625
- _a[curr.name] = curr,
626
- _a));
543
+ hosts = hosts.reduce((prev, curr) => {
544
+ return tnp_core_1._.merge(prev, {
545
+ [curr.name]: curr,
546
+ });
627
547
  }, {});
628
548
  }
629
- var toSave = parseHost(hosts, saveHostInUserFolder);
630
- // Object.values(hosts).forEach( c => c )
631
- // console.log({ toSave })
549
+ const toSave = parseHost(hosts, !!saveHostInUserFolder, true);
632
550
  if (saveHostInUserFolder) {
633
551
  tnp_helpers_1.Helpers.writeFile(HOST_FILE_PATHUSER, toSave);
634
552
  }
@@ -638,22 +556,26 @@ function saveHosts(hosts, options) {
638
556
  }
639
557
  //#endregion
640
558
  //#region helpers / parse hosts
641
- function parseHost(hosts, options) {
642
- var saveHostInUserFolder = (options || {}).saveHostInUserFolder;
643
- tnp_core_1._.keys(hosts).forEach(function (hostName) {
644
- var v = hosts[hostName];
559
+ function parseHost(hosts, saveHostInUserFolder, useLocal = false) {
560
+ tnp_core_1._.keys(hosts).forEach(hostName => {
561
+ const v = hosts[hostName];
645
562
  v.name = hostName;
646
563
  });
647
564
  return (genMsg +
648
565
  EOL +
649
566
  tnp_core_1._.keys(hosts)
650
- .map(function (hostName) {
651
- var v = hosts[hostName];
567
+ .map(hostName => {
568
+ const v = hosts[hostName];
569
+ const aliasesStr = v.aliases.join(' ');
652
570
  if (saveHostInUserFolder) {
653
- return "".concat(v.disabled ? '#' : '').concat(v.ipOrDomain, " ").concat(v.aliases.join(' '));
571
+ // For a user-specific hosts file:
572
+ return useLocal
573
+ ? `127.0.0.1 ${aliasesStr}`
574
+ : `${v.disabled ? '#' : ''}${v.ipOrDomain} ${aliasesStr}`;
654
575
  }
655
- return ("".concat(v.disabled ? '#' : '').concat(v.ipOrDomain, " ").concat(v.aliases.join(' ')) +
656
- " # ".concat(v.name, " ").concat(GENERATED));
576
+ return useLocal
577
+ ? `127.0.0.1 ${aliasesStr}`
578
+ : `${v.disabled ? '#' : ''}${v.ipOrDomain} ${aliasesStr} # ${v.name} ${GENERATED}`;
657
579
  })
658
580
  .join(EOL) +
659
581
  EOL +