vpn-split 21.0.22 → 21.0.24
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/bin/vpn-split +10 -10
- package/bin/vpn-split-debug +10 -10
- package/browser/README.md +24 -24
- package/browser/fesm2022/vpn-split-browser.mjs.map +1 -1
- package/browser/package.json +1 -1
- package/browser-prod/README.md +24 -24
- package/browser-prod/fesm2022/vpn-split-browser.mjs.map +1 -1
- package/browser-prod/package.json +1 -1
- package/lib/build-info._auto-generated_.d.ts +1 -1
- package/lib/build-info._auto-generated_.js +1 -1
- package/lib/package.json +1 -1
- package/lib-prod/build-info._auto-generated_.d.ts +1 -1
- package/lib-prod/build-info._auto-generated_.js +6 -9
- package/lib-prod/build-info._auto-generated_.js.map +1 -1
- package/lib-prod/env/env.angular-node-app.js +64 -68
- package/lib-prod/env/env.angular-node-app.js.map +1 -1
- package/lib-prod/env/env.docs-webapp.js +64 -68
- package/lib-prod/env/env.docs-webapp.js.map +1 -1
- package/lib-prod/env/env.electron-app.js +64 -68
- package/lib-prod/env/env.electron-app.js.map +1 -1
- package/lib-prod/env/env.mobile-app.js +64 -68
- package/lib-prod/env/env.mobile-app.js.map +1 -1
- package/lib-prod/env/env.npm-lib-and-cli-tool.js +64 -68
- package/lib-prod/env/env.npm-lib-and-cli-tool.js.map +1 -1
- package/lib-prod/env/env.vscode-plugin.js +64 -68
- package/lib-prod/env/env.vscode-plugin.js.map +1 -1
- package/lib-prod/env/index.js +6 -22
- package/lib-prod/env/index.js.map +1 -1
- package/lib-prod/hostile.backend.js +10 -14
- package/lib-prod/hostile.backend.js.map +1 -1
- package/lib-prod/index.js +2 -18
- package/lib-prod/index.js.map +1 -1
- package/lib-prod/migrations/index.js +1 -17
- package/lib-prod/migrations/index.js.map +1 -1
- package/lib-prod/models.js +23 -27
- package/lib-prod/models.js.map +1 -1
- package/lib-prod/package.json +1 -1
- package/lib-prod/vpn-split.backend.js +95 -99
- package/lib-prod/vpn-split.backend.js.map +1 -1
- package/package.json +1 -1
- package/websql/README.md +24 -24
- package/websql/fesm2022/vpn-split-websql.mjs.map +1 -1
- package/websql/package.json +1 -1
- package/websql-prod/README.md +24 -24
- package/websql-prod/fesm2022/vpn-split-websql.mjs.map +1 -1
- package/websql-prod/package.json +1 -1
package/lib-prod/models.js
CHANGED
|
@@ -1,10 +1,7 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.HostForServer = void 0;
|
|
4
1
|
//#region imports
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
class HostForServer {
|
|
2
|
+
import { chalk, ___NS__cloneDeep, ___NS__first, ___NS__isArray, ___NS__isBoolean, ___NS__isObject, ___NS__isString, ___NS__kebabCase, UtilsNetwork__NS__isValidIp, UtilsNetwork__NS__urlParse } from 'tnp-core/lib-prod';
|
|
3
|
+
import { HelpersTaon__NS__strings__NS__splitIfNeed } from 'tnp-helpers/lib-prod';
|
|
4
|
+
export class HostForServer {
|
|
8
5
|
_data;
|
|
9
6
|
clone() {
|
|
10
7
|
return HostForServer.From(this);
|
|
@@ -13,24 +10,24 @@ class HostForServer {
|
|
|
13
10
|
if (!ipOrDomain) {
|
|
14
11
|
return void 0;
|
|
15
12
|
}
|
|
16
|
-
if (
|
|
17
|
-
const dataClone =
|
|
13
|
+
if (___NS__isObject(ipOrDomain) && ipOrDomain instanceof HostForServer) {
|
|
14
|
+
const dataClone = ___NS__cloneDeep(ipOrDomain._data);
|
|
18
15
|
dataClone.name = name && name.trim() !== '' ? name : dataClone.name;
|
|
19
|
-
if (!
|
|
16
|
+
if (!___NS__isBoolean(dataClone.disabled)) {
|
|
20
17
|
dataClone.disabled = disabled;
|
|
21
18
|
}
|
|
22
19
|
return new HostForServer(dataClone);
|
|
23
20
|
}
|
|
24
|
-
if (
|
|
21
|
+
if (___NS__isString(ipOrDomain)) {
|
|
25
22
|
// @ts-ignore
|
|
26
|
-
const parsed =
|
|
23
|
+
const parsed = UtilsNetwork__NS__urlParse(ipOrDomain);
|
|
27
24
|
if (parsed) {
|
|
28
25
|
ipOrDomain = parsed;
|
|
29
26
|
}
|
|
30
27
|
}
|
|
31
|
-
if (
|
|
28
|
+
if (___NS__isObject(ipOrDomain) && ipOrDomain instanceof URL) {
|
|
32
29
|
ipOrDomain = ipOrDomain;
|
|
33
|
-
if (
|
|
30
|
+
if (UtilsNetwork__NS__isValidIp(ipOrDomain?.host)) {
|
|
34
31
|
return new HostForServer({ ip: ipOrDomain.origin, name, disabled });
|
|
35
32
|
}
|
|
36
33
|
else {
|
|
@@ -38,7 +35,7 @@ class HostForServer {
|
|
|
38
35
|
}
|
|
39
36
|
}
|
|
40
37
|
else {
|
|
41
|
-
if (
|
|
38
|
+
if (___NS__isString(ipOrDomain)) {
|
|
42
39
|
return new HostForServer({ ipOrDomain, name, disabled });
|
|
43
40
|
}
|
|
44
41
|
else {
|
|
@@ -46,7 +43,7 @@ class HostForServer {
|
|
|
46
43
|
name && name.trim() !== ''
|
|
47
44
|
? name
|
|
48
45
|
: ipOrDomain.name;
|
|
49
|
-
if (!
|
|
46
|
+
if (!___NS__isBoolean(ipOrDomain.disabled)) {
|
|
50
47
|
ipOrDomain.disabled = disabled;
|
|
51
48
|
}
|
|
52
49
|
return new HostForServer(ipOrDomain);
|
|
@@ -55,7 +52,7 @@ class HostForServer {
|
|
|
55
52
|
}
|
|
56
53
|
constructor(data) {
|
|
57
54
|
if (data?.ipOrDomain) {
|
|
58
|
-
if (
|
|
55
|
+
if (UtilsNetwork__NS__isValidIp(data.ipOrDomain)) {
|
|
59
56
|
data.ip = data.ipOrDomain;
|
|
60
57
|
}
|
|
61
58
|
else {
|
|
@@ -71,8 +68,8 @@ class HostForServer {
|
|
|
71
68
|
if (!data) {
|
|
72
69
|
data = {};
|
|
73
70
|
}
|
|
74
|
-
if (
|
|
75
|
-
data.aliases =
|
|
71
|
+
if (___NS__isString(data?.aliases)) {
|
|
72
|
+
data.aliases = HelpersTaon__NS__strings__NS__splitIfNeed(data.aliases);
|
|
76
73
|
}
|
|
77
74
|
this._data = data;
|
|
78
75
|
}
|
|
@@ -95,16 +92,16 @@ class HostForServer {
|
|
|
95
92
|
if (this.disabled) {
|
|
96
93
|
return [];
|
|
97
94
|
}
|
|
98
|
-
if (
|
|
95
|
+
if (___NS__isString(this._data.aliases)) {
|
|
99
96
|
return this._data.aliases.split(' ');
|
|
100
97
|
}
|
|
101
|
-
if (!
|
|
98
|
+
if (!___NS__isArray(this._data.aliases)) {
|
|
102
99
|
return [];
|
|
103
100
|
}
|
|
104
101
|
return this._data.aliases;
|
|
105
102
|
}
|
|
106
103
|
get firstAlias() {
|
|
107
|
-
return
|
|
104
|
+
return ___NS__first(this.aliases);
|
|
108
105
|
}
|
|
109
106
|
get name() {
|
|
110
107
|
return this._data.name;
|
|
@@ -125,7 +122,7 @@ class HostForServer {
|
|
|
125
122
|
return this._data.isDefault;
|
|
126
123
|
}
|
|
127
124
|
get identifier() {
|
|
128
|
-
return
|
|
125
|
+
return ___NS__kebabCase(this._data.name);
|
|
129
126
|
}
|
|
130
127
|
set disabled(v) {
|
|
131
128
|
this._data.disabled = v;
|
|
@@ -157,25 +154,24 @@ class HostForServer {
|
|
|
157
154
|
}
|
|
158
155
|
get hostname() {
|
|
159
156
|
// @ts-ignore
|
|
160
|
-
const h =
|
|
157
|
+
const h = UtilsNetwork__NS__urlParse(this.ipOrFirstAlias, { forceDomain: true });
|
|
161
158
|
return h ? h.hostname : void 0;
|
|
162
159
|
}
|
|
163
160
|
get hostnameFirstAlias() {
|
|
164
161
|
// @ts-ignore
|
|
165
|
-
const h =
|
|
162
|
+
const h = UtilsNetwork__NS__urlParse(this.firstAlias, { forceDomain: true });
|
|
166
163
|
return h ? h.hostname : void 0;
|
|
167
164
|
}
|
|
168
165
|
get hostnameIp() {
|
|
169
166
|
// @ts-ignore
|
|
170
|
-
const h =
|
|
167
|
+
const h = UtilsNetwork__NS__urlParse(this.ip);
|
|
171
168
|
return h ? h.hostname : void 0;
|
|
172
169
|
}
|
|
173
170
|
get nameWithIpOrDomain() {
|
|
174
|
-
return
|
|
171
|
+
return chalk.underline(`${this.name} ${this.ipOrDomain}`);
|
|
175
172
|
}
|
|
176
173
|
toString = () => {
|
|
177
174
|
return `[string version] ${this.nameWithIpOrDomain}`;
|
|
178
175
|
};
|
|
179
176
|
}
|
|
180
|
-
exports.HostForServer = HostForServer;
|
|
181
177
|
//# sourceMappingURL=models.js.map
|
package/lib-prod/models.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"models.js","sourceRoot":"","sources":[""],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"models.js","sourceRoot":"","sources":[""],"names":[],"mappings":"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"}
|
package/lib-prod/package.json
CHANGED
|
@@ -1,33 +1,30 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.VpnSplit = void 0;
|
|
4
1
|
//#region imports
|
|
5
|
-
|
|
2
|
+
import { execSync } from 'child_process';
|
|
6
3
|
// TODO I am using TCP ugrade not UDP!
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
const HOST_FILE_PATH =
|
|
20
|
-
const log =
|
|
4
|
+
import * as dgram from 'dgram'; // <-- For UDP sockets
|
|
5
|
+
import * as http from 'http';
|
|
6
|
+
import axios from 'axios';
|
|
7
|
+
import * as express from 'express';
|
|
8
|
+
import * as httpProxy from 'http-proxy';
|
|
9
|
+
import { Log, Level } from 'ng2-logger/lib-prod';
|
|
10
|
+
import { config } from 'tnp-core/lib-prod';
|
|
11
|
+
import { path, fse, https, isElevated, crossPlatformPath, ___NS__includes, ___NS__isArray, ___NS__keys, ___NS__merge, ___NS__values, UtilsNetwork__NS__getEtcHostsPath, UtilsNetwork__NS__getFirstIpV4LocalActiveIpAddress, UtilsNetwork__NS__getLocalIpAddresses, UtilsOs__NS__commandExistsSync, UtilsOs__NS__getRealHomeDir, UtilsOs__NS__isRunningInWindowsPowerShell } from 'tnp-core/lib-prod';
|
|
12
|
+
import { CoreModels__NS__localhostDomain, CoreModels__NS__localhostIp127 } from 'tnp-core/lib-prod';
|
|
13
|
+
import { Helpers__NS__error, Helpers__NS__exists, Helpers__NS__info, Helpers__NS__killProcessByPort, Helpers__NS__run, Helpers__NS__writeFile, HelpersTaon__NS__arrays__NS__from } from 'tnp-helpers/lib-prod';
|
|
14
|
+
import { Hostile } from './hostile.backend';
|
|
15
|
+
import { HostForServer } from './models';
|
|
16
|
+
const HOST_FILE_PATH = UtilsNetwork__NS__getEtcHostsPath();
|
|
17
|
+
const log = Log.create('vpn-split', Level.INFO);
|
|
21
18
|
//#endregion
|
|
22
19
|
//#region consts
|
|
23
20
|
const GENERATED = '#GENERATED_BY_CLI#';
|
|
24
21
|
const EOL = process.platform === 'win32' ? '\r\n' : '\n';
|
|
25
22
|
const SERVERS_PATH = '/$$$$servers$$$$';
|
|
26
|
-
const HOST_FILE_PATHUSER =
|
|
27
|
-
|
|
23
|
+
const HOST_FILE_PATHUSER = crossPlatformPath([
|
|
24
|
+
UtilsOs__NS__getRealHomeDir(),
|
|
28
25
|
'hosts-file__vpn-split',
|
|
29
26
|
]);
|
|
30
|
-
const from =
|
|
27
|
+
const from = HostForServer.From;
|
|
31
28
|
const DefaultEtcHosts = {
|
|
32
29
|
'localhost alias': from({
|
|
33
30
|
ipOrDomain: '127.0.0.1',
|
|
@@ -46,14 +43,14 @@ const DefaultEtcHosts = {
|
|
|
46
43
|
}),
|
|
47
44
|
};
|
|
48
45
|
//#endregion
|
|
49
|
-
class VpnSplit {
|
|
46
|
+
export class VpnSplit {
|
|
50
47
|
portsToPass;
|
|
51
48
|
hosts;
|
|
52
49
|
cwd;
|
|
53
50
|
//#region getters
|
|
54
51
|
get hostsArr() {
|
|
55
52
|
const hosts = this.hosts;
|
|
56
|
-
return
|
|
53
|
+
return ___NS__keys(hosts).map(hostName => {
|
|
57
54
|
const v = hosts[hostName];
|
|
58
55
|
v.name = hostName;
|
|
59
56
|
return v;
|
|
@@ -63,22 +60,22 @@ class VpnSplit {
|
|
|
63
60
|
return this.hostsArr.filter(f => !f.isDefault);
|
|
64
61
|
}
|
|
65
62
|
get serveKeyName() {
|
|
66
|
-
return 'tmp-' +
|
|
63
|
+
return 'tmp-' + config.file.server_key;
|
|
67
64
|
}
|
|
68
65
|
get serveKeyPath() {
|
|
69
|
-
return
|
|
66
|
+
return path.join(this.cwd, this.serveKeyName);
|
|
70
67
|
}
|
|
71
68
|
get serveCertName() {
|
|
72
|
-
return 'tmp-' +
|
|
69
|
+
return 'tmp-' + config.file.server_cert;
|
|
73
70
|
}
|
|
74
71
|
get serveCertPath() {
|
|
75
|
-
return
|
|
72
|
+
return path.join(this.cwd, this.serveCertName);
|
|
76
73
|
}
|
|
77
74
|
get serveCertChainName() {
|
|
78
|
-
return 'tmp-' +
|
|
75
|
+
return 'tmp-' + config.file.server_chain_cert;
|
|
79
76
|
}
|
|
80
77
|
get serveCertChainPath() {
|
|
81
|
-
return
|
|
78
|
+
return path.join(this.cwd, this.serveCertChainName);
|
|
82
79
|
}
|
|
83
80
|
//#endregion
|
|
84
81
|
//#region fields
|
|
@@ -90,14 +87,14 @@ class VpnSplit {
|
|
|
90
87
|
this.portsToPass = portsToPass;
|
|
91
88
|
this.hosts = hosts;
|
|
92
89
|
this.cwd = cwd;
|
|
93
|
-
this.__hostile = new
|
|
90
|
+
this.__hostile = new Hostile();
|
|
94
91
|
}
|
|
95
92
|
static async Instance({ ports = [80, 443, 4443, 22, 2222, 8180, 8080, 4407, 7999, 9443], additionalDefaultHosts = {}, cwd = process.cwd(), allowNotSudo = false, } = {}) {
|
|
96
|
-
if (!(await
|
|
97
|
-
|
|
93
|
+
if (!(await isElevated()) && !allowNotSudo) {
|
|
94
|
+
Helpers__NS__error(`[vpn-split] Please run this program as sudo (or admin on windows)`, false, true);
|
|
98
95
|
}
|
|
99
96
|
if (!VpnSplit._instances[cwd]) {
|
|
100
|
-
VpnSplit._instances[cwd] = new VpnSplit(ports,
|
|
97
|
+
VpnSplit._instances[cwd] = new VpnSplit(ports, ___NS__merge(DefaultEtcHosts, additionalDefaultHosts), cwd);
|
|
101
98
|
}
|
|
102
99
|
return VpnSplit._instances[cwd];
|
|
103
100
|
}
|
|
@@ -129,7 +126,7 @@ class VpnSplit {
|
|
|
129
126
|
for (const portToPassthrough of this.portsToPass) {
|
|
130
127
|
await this.serverUdpPassthrough(portToPassthrough);
|
|
131
128
|
}
|
|
132
|
-
|
|
129
|
+
Helpers__NS__info(`Activated (server).`);
|
|
133
130
|
}
|
|
134
131
|
//#endregion
|
|
135
132
|
//#region apply hosts
|
|
@@ -165,9 +162,9 @@ class VpnSplit {
|
|
|
165
162
|
}
|
|
166
163
|
// Merge with original, redirecting all non-default entries to 127.0.0.1
|
|
167
164
|
const originalHosts = this.hostsArr;
|
|
168
|
-
const combinedHostsObj =
|
|
165
|
+
const combinedHostsObj = ___NS__values([
|
|
169
166
|
...originalHosts,
|
|
170
|
-
...hosts.map(h =>
|
|
167
|
+
...hosts.map(h => HostForServer.From({
|
|
171
168
|
aliases: h.alias,
|
|
172
169
|
ipOrDomain: h.ip,
|
|
173
170
|
originHostname: h.originHostname,
|
|
@@ -181,7 +178,7 @@ class VpnSplit {
|
|
|
181
178
|
return copy;
|
|
182
179
|
})
|
|
183
180
|
.reduce((prev, curr) => {
|
|
184
|
-
return
|
|
181
|
+
return ___NS__merge(prev, {
|
|
185
182
|
[curr.aliases.join(' ')]: curr,
|
|
186
183
|
});
|
|
187
184
|
}, {}));
|
|
@@ -209,31 +206,31 @@ class VpnSplit {
|
|
|
209
206
|
for (const portToPassthrough of this.portsToPass) {
|
|
210
207
|
await this.clientUdpPassthrough(portToPassthrough, vpnServerTargets, combinedHostsObj);
|
|
211
208
|
}
|
|
212
|
-
|
|
209
|
+
Helpers__NS__info(`Client activated`);
|
|
213
210
|
}
|
|
214
211
|
//#endregion
|
|
215
212
|
//#region private methods / get remote hosts
|
|
216
213
|
async getRemoteHosts(vpnServerTarget) {
|
|
217
214
|
try {
|
|
218
215
|
const url = `http://${vpnServerTarget.hostname}${SERVERS_PATH}`;
|
|
219
|
-
const response = await (
|
|
216
|
+
const response = await axios({ url, method: 'GET' });
|
|
220
217
|
return response.data;
|
|
221
218
|
}
|
|
222
219
|
catch (err) {
|
|
223
|
-
|
|
220
|
+
Helpers__NS__error(`Remote server: ${vpnServerTarget.hostname} may be inactive...`, true, true);
|
|
224
221
|
return [];
|
|
225
222
|
}
|
|
226
223
|
}
|
|
227
224
|
//#endregion
|
|
228
225
|
//#region private methods / create certificate
|
|
229
226
|
createCertificateIfNotExists() {
|
|
230
|
-
if (!
|
|
231
|
-
!
|
|
232
|
-
|
|
233
|
-
const commandGen =
|
|
227
|
+
if (!Helpers__NS__exists(this.serveKeyPath) ||
|
|
228
|
+
!Helpers__NS__exists(this.serveCertPath)) {
|
|
229
|
+
Helpers__NS__info(`[vpn-split] Generating new self-signed certificate for localhost...`);
|
|
230
|
+
const commandGen = UtilsOs__NS__isRunningInWindowsPowerShell()
|
|
234
231
|
? `powershell -Command "& 'C:\\Program Files\\Git\\usr\\bin\\openssl.exe' req -nodes -new -x509 -keyout ${this.serveKeyName} -out ${this.serveCertName}"`
|
|
235
232
|
: `openssl req -nodes -new -x509 -keyout ${this.serveKeyName} -out ${this.serveCertName}`;
|
|
236
|
-
|
|
233
|
+
Helpers__NS__run(commandGen, { cwd: this.cwd, output: true }).sync();
|
|
237
234
|
}
|
|
238
235
|
}
|
|
239
236
|
//#endregion
|
|
@@ -260,8 +257,8 @@ class VpnSplit {
|
|
|
260
257
|
? {
|
|
261
258
|
target,
|
|
262
259
|
ssl: {
|
|
263
|
-
key:
|
|
264
|
-
cert:
|
|
260
|
+
key: fse.readFileSync(this.serveKeyPath),
|
|
261
|
+
cert: fse.readFileSync(this.serveCertPath),
|
|
265
262
|
},
|
|
266
263
|
// agent: new https.Agent({
|
|
267
264
|
// secureOptions: crypto.constants.SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION,
|
|
@@ -310,10 +307,10 @@ Port: ${port}`;
|
|
|
310
307
|
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
|
|
311
308
|
const app = express();
|
|
312
309
|
const proxy = httpProxy.createProxyServer({});
|
|
313
|
-
const localIp = await
|
|
310
|
+
const localIp = await UtilsNetwork__NS__getLocalIpAddresses();
|
|
314
311
|
const currentLocalIps = [
|
|
315
|
-
|
|
316
|
-
|
|
312
|
+
CoreModels__NS__localhostDomain,
|
|
313
|
+
CoreModels__NS__localhostIp127,
|
|
317
314
|
...localIp.map(a => a.address),
|
|
318
315
|
];
|
|
319
316
|
app.use((req, res, next) => {
|
|
@@ -322,7 +319,7 @@ Port: ${port}`;
|
|
|
322
319
|
if (req.method === 'GET' && req.originalUrl === SERVERS_PATH) {
|
|
323
320
|
res.send(JSON.stringify(this.hostsArrWithoutDefault.map(h => ({
|
|
324
321
|
ip: h.ip,
|
|
325
|
-
alias:
|
|
322
|
+
alias: HelpersTaon__NS__arrays__NS__from(h.aliases).join(' '),
|
|
326
323
|
}))));
|
|
327
324
|
}
|
|
328
325
|
else {
|
|
@@ -337,12 +334,12 @@ Port: ${port}`;
|
|
|
337
334
|
}
|
|
338
335
|
});
|
|
339
336
|
const server = isHttps
|
|
340
|
-
?
|
|
341
|
-
key:
|
|
342
|
-
cert:
|
|
337
|
+
? https.createServer({
|
|
338
|
+
key: fse.readFileSync(this.serveKeyPath),
|
|
339
|
+
cert: fse.readFileSync(this.serveCertPath),
|
|
343
340
|
}, app)
|
|
344
341
|
: http.createServer(app);
|
|
345
|
-
await
|
|
342
|
+
await Helpers__NS__killProcessByPort(portToPassthrough, { silent: true });
|
|
346
343
|
await new Promise((resolve, reject) => {
|
|
347
344
|
server.listen(portToPassthrough, () => {
|
|
348
345
|
console.log(`TCP/HTTPS server listening on port ${portToPassthrough} (secure=${isHttps})`);
|
|
@@ -401,12 +398,12 @@ Port: ${port}`;
|
|
|
401
398
|
}), next);
|
|
402
399
|
});
|
|
403
400
|
const server = isHttps
|
|
404
|
-
?
|
|
405
|
-
key:
|
|
406
|
-
cert:
|
|
401
|
+
? https.createServer({
|
|
402
|
+
key: fse.readFileSync(this.serveKeyPath),
|
|
403
|
+
cert: fse.readFileSync(this.serveCertPath),
|
|
407
404
|
}, app)
|
|
408
405
|
: http.createServer(app);
|
|
409
|
-
await
|
|
406
|
+
await Helpers__NS__killProcessByPort(portToPassthrough, { silent: true });
|
|
410
407
|
await new Promise((resolve, reject) => {
|
|
411
408
|
server.listen(portToPassthrough, () => {
|
|
412
409
|
log.i(`TCP/HTTPS client listening on port ${portToPassthrough} (secure=${isHttps})`);
|
|
@@ -482,7 +479,7 @@ Port: ${port}`;
|
|
|
482
479
|
// If the message is from the server, forward back to the correct client.
|
|
483
480
|
//
|
|
484
481
|
// Check if it’s from local or remote by address. This is simplistic:
|
|
485
|
-
const isFromLocal = !
|
|
482
|
+
const isFromLocal = !___NS__includes(hostsArr.map(h => h.ipOrDomain), rinfo.address);
|
|
486
483
|
if (isFromLocal) {
|
|
487
484
|
// Received from local => forward to “server” (the VPN server)
|
|
488
485
|
// Keep track of who we got this from (the local client)
|
|
@@ -542,8 +539,8 @@ Port: ${port}`;
|
|
|
542
539
|
//#region @backendFunc
|
|
543
540
|
// console.log('Domains for cert:', domains);
|
|
544
541
|
// Helpers__NS__error(``,false,true);
|
|
545
|
-
if (!
|
|
546
|
-
|
|
542
|
+
if (!UtilsOs__NS__commandExistsSync('mkcert')) {
|
|
543
|
+
Helpers__NS__error('[vpn-split] mkcert is not installed.', false, true);
|
|
547
544
|
}
|
|
548
545
|
const certPath = this.serveCertPath; // e.g. .../tmp-server_cert
|
|
549
546
|
const keyPath = this.serveKeyPath; // e.g. .../tmp-server_key
|
|
@@ -560,12 +557,12 @@ Port: ${port}`;
|
|
|
560
557
|
// Helper: run mkcert and capture output
|
|
561
558
|
const runMkcert = (args) => {
|
|
562
559
|
try {
|
|
563
|
-
return
|
|
560
|
+
return execSync(`mkcert ${args}`, { stdio: 'pipe' }).toString().trim();
|
|
564
561
|
}
|
|
565
562
|
catch (err) {
|
|
566
563
|
const stderr = err.stderr?.toString() || '';
|
|
567
564
|
if (stderr.includes('command not found')) {
|
|
568
|
-
|
|
565
|
+
Helpers__NS__error('[vpn-split] mkcert is not installed. Install it first: https://github.com/FiloSottile/mkcert', false, true);
|
|
569
566
|
}
|
|
570
567
|
throw err;
|
|
571
568
|
}
|
|
@@ -575,28 +572,28 @@ Port: ${port}`;
|
|
|
575
572
|
try {
|
|
576
573
|
const output = runMkcert('-CAROOT');
|
|
577
574
|
// If -CAROOT succeeds and the root files exist → CA is installed
|
|
578
|
-
const rootDir =
|
|
575
|
+
const rootDir = crossPlatformPath(output.trim());
|
|
579
576
|
if (rootDir &&
|
|
580
|
-
|
|
581
|
-
|
|
577
|
+
fse.pathExistsSync(crossPlatformPath([rootDir, 'rootCA.pem']))) {
|
|
578
|
+
Helpers__NS__info('[vpn-split] mkcert local CA is already installed');
|
|
582
579
|
caInstalled = true;
|
|
583
580
|
}
|
|
584
581
|
else {
|
|
585
|
-
|
|
582
|
+
Helpers__NS__info('[vpn-split] mkcert local CA is NOT installed');
|
|
586
583
|
}
|
|
587
584
|
}
|
|
588
585
|
catch {
|
|
589
|
-
|
|
586
|
+
Helpers__NS__info('[vpn-split] mkcert error checking local CA installation');
|
|
590
587
|
}
|
|
591
588
|
// 2. Install the local CA if needed (requires sudo once)
|
|
592
589
|
if (!caInstalled) {
|
|
593
|
-
|
|
590
|
+
Helpers__NS__info('[vpn-split] Installing mkcert local CA (requires sudo once)...');
|
|
594
591
|
try {
|
|
595
|
-
|
|
596
|
-
|
|
592
|
+
execSync('mkcert -install', { stdio: 'inherit' });
|
|
593
|
+
Helpers__NS__info('[vpn-split] Local CA installed and trusted system-wide');
|
|
597
594
|
}
|
|
598
595
|
catch (err) {
|
|
599
|
-
|
|
596
|
+
Helpers__NS__error('[vpn-split] Failed to run "mkcert -install". Run it manually with sudo.', false, true);
|
|
600
597
|
}
|
|
601
598
|
}
|
|
602
599
|
const isWindows = process.platform === 'win32';
|
|
@@ -607,59 +604,58 @@ Port: ${port}`;
|
|
|
607
604
|
// Small list or non-Windows: one shot
|
|
608
605
|
const namesArg = allNames.map(d => `"${d}"`).join(' ');
|
|
609
606
|
const mkcertCmd = `-key-file "${keyPath}" -cert-file "${certPath}" ${namesArg}`;
|
|
610
|
-
|
|
607
|
+
fse.ensureDirSync(path.dirname(certPath));
|
|
611
608
|
runMkcert(mkcertCmd);
|
|
612
609
|
}
|
|
613
610
|
else {
|
|
614
611
|
// Big list on Windows: Batch into chunks of ~20 domains
|
|
615
612
|
const chunkSize = 20;
|
|
616
|
-
|
|
613
|
+
fse.ensureDirSync(path.dirname(certPath));
|
|
617
614
|
for (let i = 0; i < allNames.length; i += chunkSize) {
|
|
618
615
|
const chunk = allNames.slice(i, i + chunkSize);
|
|
619
616
|
const tempCert = `${certPath}.${i}.pem`;
|
|
620
617
|
const tempKey = `${keyPath}.${i}.pem`;
|
|
621
618
|
const namesArg = chunk.map(d => `"${d}"`).join(' ');
|
|
622
619
|
const mkcertCmd = `-key-file "${tempKey}" -cert-file "${tempCert}" ${namesArg}`;
|
|
623
|
-
|
|
620
|
+
Helpers__NS__info(`[vpn-split] Generating batch ${Math.floor(i / chunkSize) + 1}/${Math.ceil(allNames.length / chunkSize)}...`);
|
|
624
621
|
runMkcert(mkcertCmd);
|
|
625
622
|
tempCertFiles.push(tempCert);
|
|
626
623
|
tempKeyFiles.push(tempKey);
|
|
627
624
|
}
|
|
628
625
|
// 3. Merge all temp certs into one (cert chain + leaves) and pick first key
|
|
629
|
-
|
|
626
|
+
Helpers__NS__info('[vpn-split] Merging batches into final cert...');
|
|
630
627
|
const firstKey = tempKeyFiles[0];
|
|
631
|
-
|
|
628
|
+
fse.copySync(firstKey, keyPath); // Use the first key (all are identical)
|
|
632
629
|
// Concat all certs (mkcert output is already PEM-formatted)
|
|
633
630
|
const mergedCertContent = tempCertFiles
|
|
634
|
-
.map(f =>
|
|
631
|
+
.map(f => fse.readFileSync(f, 'utf8'))
|
|
635
632
|
.join('\n'); // PEM certs stack nicely
|
|
636
|
-
|
|
633
|
+
fse.writeFileSync(certPath, mergedCertContent);
|
|
637
634
|
// Clean up temps
|
|
638
|
-
tempCertFiles.forEach(f =>
|
|
639
|
-
tempKeyFiles.slice(1).forEach(f =>
|
|
640
|
-
|
|
635
|
+
tempCertFiles.forEach(f => fse.removeSync(f));
|
|
636
|
+
tempKeyFiles.slice(1).forEach(f => fse.removeSync(f)); // Keep first key as backup if needed
|
|
637
|
+
Helpers__NS__info('[vpn-split] Merged cert ready!');
|
|
641
638
|
}
|
|
642
639
|
// Verify
|
|
643
|
-
if (!
|
|
644
|
-
|
|
640
|
+
if (!fse.existsSync(certPath) || !fse.existsSync(keyPath)) {
|
|
641
|
+
Helpers__NS__error('[vpn-split] Files missing after generation!', false, true);
|
|
645
642
|
}
|
|
646
643
|
else {
|
|
647
|
-
|
|
644
|
+
Helpers__NS__info(`[vpn-split] Trusted cert ready: ${allNames.length} hostnames covered`);
|
|
648
645
|
}
|
|
649
646
|
//#endregion
|
|
650
647
|
}
|
|
651
648
|
//#region private methods / prevent bad target for client
|
|
652
649
|
async preventBadTargetForClient(vpnServerTarget) {
|
|
653
650
|
if (!vpnServerTarget) {
|
|
654
|
-
const currentLocalIp = await
|
|
655
|
-
|
|
651
|
+
const currentLocalIp = await UtilsNetwork__NS__getFirstIpV4LocalActiveIpAddress();
|
|
652
|
+
Helpers__NS__error(`[vpn-server] Please provide a correct target server.\n` +
|
|
656
653
|
`Example:\n` +
|
|
657
654
|
`vpn-server ${currentLocalIp}\n\n` +
|
|
658
655
|
`Your local IP is: ${currentLocalIp}`, false, true);
|
|
659
656
|
}
|
|
660
657
|
}
|
|
661
658
|
}
|
|
662
|
-
exports.VpnSplit = VpnSplit;
|
|
663
659
|
//#region helper / gen msg
|
|
664
660
|
const genMsg = `
|
|
665
661
|
################################################
|
|
@@ -670,36 +666,36 @@ const genMsg = `
|
|
|
670
666
|
//#region helpers / save hosts
|
|
671
667
|
function saveHosts(hosts, options) {
|
|
672
668
|
const { saveHostInUserFolder } = options || {};
|
|
673
|
-
if (
|
|
669
|
+
if (___NS__isArray(hosts)) {
|
|
674
670
|
hosts = hosts.reduce((prev, curr) => {
|
|
675
|
-
return
|
|
671
|
+
return ___NS__merge(prev, {
|
|
676
672
|
[curr.name]: curr,
|
|
677
673
|
});
|
|
678
674
|
}, {});
|
|
679
675
|
}
|
|
680
676
|
const toSave = parseHost(hosts, !!saveHostInUserFolder);
|
|
681
677
|
if (saveHostInUserFolder) {
|
|
682
|
-
|
|
678
|
+
Helpers__NS__writeFile(HOST_FILE_PATHUSER, toSave);
|
|
683
679
|
}
|
|
684
680
|
else {
|
|
685
|
-
|
|
681
|
+
Helpers__NS__writeFile(HOST_FILE_PATH, toSave);
|
|
686
682
|
}
|
|
687
683
|
}
|
|
688
684
|
function saveHostsLocal(hosts, options) {
|
|
689
685
|
const { saveHostInUserFolder } = options || {};
|
|
690
|
-
if (
|
|
686
|
+
if (___NS__isArray(hosts)) {
|
|
691
687
|
hosts = hosts.reduce((prev, curr) => {
|
|
692
|
-
return
|
|
688
|
+
return ___NS__merge(prev, {
|
|
693
689
|
[curr.name]: curr,
|
|
694
690
|
});
|
|
695
691
|
}, {});
|
|
696
692
|
}
|
|
697
693
|
const toSave = parseHost(hosts, !!saveHostInUserFolder, true);
|
|
698
694
|
if (saveHostInUserFolder) {
|
|
699
|
-
|
|
695
|
+
Helpers__NS__writeFile(HOST_FILE_PATHUSER, toSave);
|
|
700
696
|
}
|
|
701
697
|
else {
|
|
702
|
-
|
|
698
|
+
Helpers__NS__writeFile(HOST_FILE_PATH, toSave);
|
|
703
699
|
}
|
|
704
700
|
}
|
|
705
701
|
//#endregion
|
|
@@ -710,13 +706,13 @@ function parseHost(hosts, saveHostInUserFolder, useLocal = false) {
|
|
|
710
706
|
...DefaultEtcHosts,
|
|
711
707
|
...hosts,
|
|
712
708
|
};
|
|
713
|
-
|
|
709
|
+
___NS__keys(hosts).forEach(hostName => {
|
|
714
710
|
const v = hosts[hostName];
|
|
715
711
|
v.name = hostName;
|
|
716
712
|
});
|
|
717
713
|
return (genMsg +
|
|
718
714
|
EOL +
|
|
719
|
-
|
|
715
|
+
___NS__keys(hosts)
|
|
720
716
|
.map(hostName => {
|
|
721
717
|
const v = hosts[hostName];
|
|
722
718
|
if (v.skipUpdateOfServerEtcHosts) {
|