@qpjoy/tunnel-cli 0.1.7 → 0.1.9
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/dist/hdo.js +10 -5
- package/dist/index.js +12 -0
- package/package.json +3 -2
- package/resources/mihomo-client.sh +79 -5
- package/scripts/sync-mx-launcher-fallback.mjs +65 -0
package/dist/hdo.js
CHANGED
|
@@ -152,7 +152,9 @@ async function enrollCommand(args, refreshOnly) {
|
|
|
152
152
|
const manifest = await apiJson(serverUrl, auth.accessToken, `/api/v1/hdo/manifest/${encodeURIComponent(deviceId)}`, {
|
|
153
153
|
method: 'GET',
|
|
154
154
|
});
|
|
155
|
-
const runtime = hdoRuntimeFromManifest(manifest, registered, keys.privateKey
|
|
155
|
+
const runtime = hdoRuntimeFromManifest(manifest, registered, keys.privateKey, {
|
|
156
|
+
allowEndpointlessDirectPeers: direct.directListener,
|
|
157
|
+
});
|
|
156
158
|
writeWireGuardConfig(configPath, (0, electron_core_wireguard_1.renderHdoClientWireGuardConfig)({
|
|
157
159
|
privateKey: runtime.privateKey,
|
|
158
160
|
address: runtime.address,
|
|
@@ -537,7 +539,7 @@ function resolveDirectEndpoint(options, previous) {
|
|
|
537
539
|
endpoint: endpointHost && listenPort ? `${endpointHost}:${listenPort}` : undefined,
|
|
538
540
|
};
|
|
539
541
|
}
|
|
540
|
-
function directPeersFromManifest(wireGuard, ownOverlayIp) {
|
|
542
|
+
function directPeersFromManifest(wireGuard, ownOverlayIp, options = {}) {
|
|
541
543
|
const ownIp = ownOverlayIp.split('/')[0] || ownOverlayIp;
|
|
542
544
|
const rows = Array.isArray(wireGuard.directPeers) ? wireGuard.directPeers : [];
|
|
543
545
|
return rows.flatMap((item) => {
|
|
@@ -549,11 +551,14 @@ function directPeersFromManifest(wireGuard, ownOverlayIp) {
|
|
|
549
551
|
if (!publicKey || !overlayIp || overlayIp === ownIp)
|
|
550
552
|
return [];
|
|
551
553
|
const allowedIps = stringArray(row.allowedIps);
|
|
554
|
+
const endpoint = stringField(row.endpoint);
|
|
555
|
+
if (!endpoint && options.allowEndpointlessDirectPeers !== true)
|
|
556
|
+
return [];
|
|
552
557
|
const peer = {
|
|
553
558
|
name: `HDO Direct ${stringField(row.label) ?? stringField(row.id) ?? overlayIp}`,
|
|
554
559
|
publicKey,
|
|
555
560
|
allowedIps: allowedIps.length ? allowedIps : [`${overlayIp}/32`],
|
|
556
|
-
endpoint
|
|
561
|
+
endpoint,
|
|
557
562
|
persistentKeepalive: 25,
|
|
558
563
|
};
|
|
559
564
|
return [peer];
|
|
@@ -611,7 +616,7 @@ function writeWireGuardConfig(path, content) {
|
|
|
611
616
|
(0, node_fs_1.writeFileSync)(path, content, { mode: 0o600 });
|
|
612
617
|
chmodSyncSafe(path, 0o600);
|
|
613
618
|
}
|
|
614
|
-
function hdoRuntimeFromManifest(manifest, registered, privateKey) {
|
|
619
|
+
function hdoRuntimeFromManifest(manifest, registered, privateKey, options = {}) {
|
|
615
620
|
const root = requireRecord(manifest, 'manifest');
|
|
616
621
|
const license = requireRecord(root.license, 'manifest.license');
|
|
617
622
|
if (license.active !== true) {
|
|
@@ -645,7 +650,7 @@ function hdoRuntimeFromManifest(manifest, registered, privateKey) {
|
|
|
645
650
|
domesticPublicKey,
|
|
646
651
|
domesticEndpoint,
|
|
647
652
|
allowedIps,
|
|
648
|
-
directPeers: directPeersFromManifest(wireGuard, overlayIp),
|
|
653
|
+
directPeers: directPeersFromManifest(wireGuard, overlayIp, options),
|
|
649
654
|
generation: numberField(root.generation),
|
|
650
655
|
};
|
|
651
656
|
}
|
package/dist/index.js
CHANGED
|
@@ -24,14 +24,26 @@ const defaultNoProxyEntries = [
|
|
|
24
24
|
'docker.for.mac.host.internal',
|
|
25
25
|
'docker.for.win.localhost',
|
|
26
26
|
'kubernetes.docker.internal',
|
|
27
|
+
'kubernetes.default.svc',
|
|
28
|
+
'.cluster.local',
|
|
27
29
|
'10.0.0.0/8',
|
|
28
30
|
'172.16.0.0/12',
|
|
29
31
|
'192.168.0.0/16',
|
|
32
|
+
'169.254.0.0/16',
|
|
33
|
+
'169.254.169.254',
|
|
34
|
+
'169.254.169.254/32',
|
|
35
|
+
'100.100.100.200',
|
|
36
|
+
'100.100.100.200/32',
|
|
30
37
|
'100.64.0.0/10',
|
|
31
38
|
'100.88.0.0/16',
|
|
32
39
|
'100.89.0.0/16',
|
|
33
40
|
'100.90.0.0/16',
|
|
41
|
+
'10.88.0.0/16',
|
|
42
|
+
'10.89.0.0/16',
|
|
43
|
+
'10.90.0.0/16',
|
|
44
|
+
'10.91.0.0/16',
|
|
34
45
|
'.local',
|
|
46
|
+
'.lan',
|
|
35
47
|
];
|
|
36
48
|
const clientCommands = new Set([
|
|
37
49
|
'setup',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@qpjoy/tunnel-cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.9",
|
|
4
4
|
"description": "Global QPJoy Tunnel CLI for mihomo-client and cross-platform HDO mesh enrollment.",
|
|
5
5
|
"private": false,
|
|
6
6
|
"type": "commonjs",
|
|
@@ -22,13 +22,14 @@
|
|
|
22
22
|
"access": "public"
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@qpjoy/electron-core-wireguard": "^0.1.
|
|
25
|
+
"@qpjoy/electron-core-wireguard": "^0.1.28"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
28
|
"@types/node": "^22.10.7"
|
|
29
29
|
},
|
|
30
30
|
"scripts": {
|
|
31
31
|
"build": "tsc -p tsconfig.json",
|
|
32
|
+
"sync:mx-launcher-fallback": "node scripts/sync-mx-launcher-fallback.mjs",
|
|
32
33
|
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
33
34
|
"lint": "tsc -p tsconfig.json --noEmit"
|
|
34
35
|
}
|
|
@@ -16,7 +16,7 @@ MIHOMO_SERVICE_FILE="${MIHOMO_SERVICE_FILE:-/etc/systemd/system/$MIHOMO_SERVICE_
|
|
|
16
16
|
MIHOMO_PROFILE_PROXY_FILE="${MIHOMO_PROFILE_PROXY_FILE:-/etc/profile.d/mihomo-client-proxy.sh}"
|
|
17
17
|
MIHOMO_DAEMON_PROXY_SERVICES="${MIHOMO_DAEMON_PROXY_SERVICES:-docker.service containerd.service buildkit.service}"
|
|
18
18
|
MIHOMO_DAEMON_PROXY_DROPIN_NAME="${MIHOMO_DAEMON_PROXY_DROPIN_NAME:-mihomo-proxy.conf}"
|
|
19
|
-
MIHOMO_NO_PROXY="${MIHOMO_NO_PROXY:-localhost,127.0.0.1,::1,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,100.64.0.0/10,100.88.0.0/16,100.89.0.0/16,100.90.0.0/16,host.docker.internal,.local}"
|
|
19
|
+
MIHOMO_NO_PROXY="${MIHOMO_NO_PROXY:-localhost,127.0.0.1,::1,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,169.254.0.0/16,169.254.169.254,169.254.169.254/32,100.64.0.0/10,100.88.0.0/16,100.89.0.0/16,100.90.0.0/16,10.88.0.0/16,10.89.0.0/16,10.90.0.0/16,10.91.0.0/16,100.100.100.200,100.100.100.200/32,host.docker.internal,docker.for.mac.host.internal,docker.for.win.localhost,kubernetes.docker.internal,kubernetes.default.svc,.cluster.local,.local,.lan}"
|
|
20
20
|
MIHOMO_SSH_PROXY_HELPER="${MIHOMO_SSH_PROXY_HELPER:-/usr/local/bin/mihomo-ssh-proxy}"
|
|
21
21
|
MIHOMO_SSH_CONFIG_DIR="${MIHOMO_SSH_CONFIG_DIR:-/etc/ssh/ssh_config.d}"
|
|
22
22
|
MIHOMO_SSH_CONFIG_FILE="${MIHOMO_SSH_CONFIG_FILE:-$MIHOMO_SSH_CONFIG_DIR/99-mihomo-proxy.conf}"
|
|
@@ -49,7 +49,7 @@ Commands:
|
|
|
49
49
|
egress-off Alias for server-off
|
|
50
50
|
proxy-on Write /etc/profile.d proxy exports for login shells
|
|
51
51
|
proxy-off Remove /etc/profile.d proxy exports
|
|
52
|
-
tun-on Enable Mihomo TUN mode and
|
|
52
|
+
tun-on Enable persistent Mihomo TUN mode with cn-direct and local/private route bypasses
|
|
53
53
|
tun-off Disable Mihomo TUN mode and also turn proxy-on off
|
|
54
54
|
ssh-proxy-on Configure OpenSSH client to use local Mihomo SOCKS for common Git hosts
|
|
55
55
|
ssh-proxy-off Remove OpenSSH proxy override
|
|
@@ -399,8 +399,43 @@ ensure_subscription_source() {
|
|
|
399
399
|
[[ -f "$MIHOMO_SUBSCRIPTION_FILE" ]] || die "Subscription source not found. Please run install or update-subscription first."
|
|
400
400
|
}
|
|
401
401
|
|
|
402
|
+
detect_tun_proxy_group_name() {
|
|
403
|
+
local configured="${MIHOMO_TUN_PROXY_GROUP:-}"
|
|
404
|
+
local detected=""
|
|
405
|
+
if [[ -n "$configured" ]]; then
|
|
406
|
+
echo "$configured"
|
|
407
|
+
return
|
|
408
|
+
fi
|
|
409
|
+
if [[ -f "$MIHOMO_SUBSCRIPTION_FILE" ]]; then
|
|
410
|
+
detected="$(awk '
|
|
411
|
+
/^[[:space:]]*proxy-groups:[[:space:]]*$/ { in_groups=1; next }
|
|
412
|
+
in_groups && /^[^[:space:]-]/ { in_groups=0 }
|
|
413
|
+
in_groups && /^[[:space:]]*-[[:space:]]*name:[[:space:]]*/ {
|
|
414
|
+
line=$0
|
|
415
|
+
sub(/^[[:space:]]*-[[:space:]]*name:[[:space:]]*/, "", line)
|
|
416
|
+
gsub(/^[[:space:]"]+/, "", line)
|
|
417
|
+
gsub(/[[:space:]"]+$/, "", line)
|
|
418
|
+
print line
|
|
419
|
+
exit
|
|
420
|
+
}
|
|
421
|
+
in_groups && /^[[:space:]]*name:[[:space:]]*/ {
|
|
422
|
+
line=$0
|
|
423
|
+
sub(/^[[:space:]]*name:[[:space:]]*/, "", line)
|
|
424
|
+
gsub(/^[[:space:]"]+/, "", line)
|
|
425
|
+
gsub(/[[:space:]"]+$/, "", line)
|
|
426
|
+
print line
|
|
427
|
+
exit
|
|
428
|
+
}
|
|
429
|
+
' "$MIHOMO_SUBSCRIPTION_FILE" || true)"
|
|
430
|
+
fi
|
|
431
|
+
echo "${detected:-PROXY}"
|
|
432
|
+
}
|
|
433
|
+
|
|
402
434
|
write_tun_overlay() {
|
|
403
|
-
|
|
435
|
+
ensure_subscription_source
|
|
436
|
+
local proxy_group
|
|
437
|
+
proxy_group="$(detect_tun_proxy_group_name)"
|
|
438
|
+
cat > "$MIHOMO_TUN_OVERLAY_FILE" <<EOF
|
|
404
439
|
tun:
|
|
405
440
|
enable: true
|
|
406
441
|
stack: system
|
|
@@ -408,6 +443,17 @@ tun:
|
|
|
408
443
|
auto-redirect: true
|
|
409
444
|
auto-detect-interface: true
|
|
410
445
|
strict-route: true
|
|
446
|
+
route-exclude-address:
|
|
447
|
+
- 10.0.0.0/8
|
|
448
|
+
- 172.16.0.0/12
|
|
449
|
+
- 192.168.0.0/16
|
|
450
|
+
- 169.254.0.0/16
|
|
451
|
+
- 100.64.0.0/10
|
|
452
|
+
- 10.88.0.0/16
|
|
453
|
+
- 10.89.0.0/16
|
|
454
|
+
- 10.90.0.0/16
|
|
455
|
+
- 10.91.0.0/16
|
|
456
|
+
- 100.100.100.200/32
|
|
411
457
|
dns-hijack:
|
|
412
458
|
- any:53
|
|
413
459
|
- tcp://any:53
|
|
@@ -425,6 +471,7 @@ dns:
|
|
|
425
471
|
- 223.5.5.5
|
|
426
472
|
- 119.29.29.29
|
|
427
473
|
- 1.1.1.1
|
|
474
|
+
- 8.8.8.8
|
|
428
475
|
nameserver:
|
|
429
476
|
- https://dns.alidns.com/dns-query
|
|
430
477
|
- https://doh.pub/dns-query
|
|
@@ -436,6 +483,31 @@ dns:
|
|
|
436
483
|
geoip-code: CN
|
|
437
484
|
geosite:
|
|
438
485
|
- gfw
|
|
486
|
+
|
|
487
|
+
rules:
|
|
488
|
+
- DOMAIN-SUFFIX,local,DIRECT
|
|
489
|
+
- DOMAIN-SUFFIX,lan,DIRECT
|
|
490
|
+
- DOMAIN-SUFFIX,internal,DIRECT
|
|
491
|
+
- DOMAIN-SUFFIX,cluster.local,DIRECT
|
|
492
|
+
- DOMAIN,metadata.google.internal,DIRECT
|
|
493
|
+
- DOMAIN,kubernetes.default.svc,DIRECT
|
|
494
|
+
- IP-CIDR,127.0.0.0/8,DIRECT,no-resolve
|
|
495
|
+
- IP-CIDR,10.0.0.0/8,DIRECT,no-resolve
|
|
496
|
+
- IP-CIDR,172.16.0.0/12,DIRECT,no-resolve
|
|
497
|
+
- IP-CIDR,192.168.0.0/16,DIRECT,no-resolve
|
|
498
|
+
- IP-CIDR,169.254.0.0/16,DIRECT,no-resolve
|
|
499
|
+
- IP-CIDR,100.64.0.0/10,DIRECT,no-resolve
|
|
500
|
+
- IP-CIDR,10.88.0.0/16,DIRECT,no-resolve
|
|
501
|
+
- IP-CIDR,10.89.0.0/16,DIRECT,no-resolve
|
|
502
|
+
- IP-CIDR,10.90.0.0/16,DIRECT,no-resolve
|
|
503
|
+
- IP-CIDR,10.91.0.0/16,DIRECT,no-resolve
|
|
504
|
+
- IP-CIDR,100.100.100.200/32,DIRECT,no-resolve
|
|
505
|
+
- IP-CIDR6,::1/128,DIRECT,no-resolve
|
|
506
|
+
- IP-CIDR6,fc00::/7,DIRECT,no-resolve
|
|
507
|
+
- IP-CIDR6,fe80::/10,DIRECT,no-resolve
|
|
508
|
+
- GEOSITE,CN,DIRECT
|
|
509
|
+
- GEOIP,CN,DIRECT
|
|
510
|
+
- MATCH,$proxy_group
|
|
439
511
|
EOF
|
|
440
512
|
chmod 600 "$MIHOMO_TUN_OVERLAY_FILE"
|
|
441
513
|
}
|
|
@@ -759,10 +831,12 @@ tun_on_command() {
|
|
|
759
831
|
daemon_proxy_on_command
|
|
760
832
|
if service_is_active; then
|
|
761
833
|
systemctl restart "$MIHOMO_SERVICE_NAME"
|
|
762
|
-
|
|
834
|
+
systemctl enable "$MIHOMO_SERVICE_NAME" >/dev/null 2>&1 || true
|
|
835
|
+
echo "Mihomo TUN mode enabled, persisted, and service restarted."
|
|
763
836
|
else
|
|
764
837
|
systemctl start "$MIHOMO_SERVICE_NAME"
|
|
765
|
-
|
|
838
|
+
systemctl enable "$MIHOMO_SERVICE_NAME" >/dev/null 2>&1 || true
|
|
839
|
+
echo "Mihomo TUN mode enabled, persisted, and service started."
|
|
766
840
|
fi
|
|
767
841
|
}
|
|
768
842
|
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { execFileSync } from 'node:child_process';
|
|
4
|
+
import { existsSync, readdirSync, statSync } from 'node:fs';
|
|
5
|
+
import { dirname, join, resolve } from 'node:path';
|
|
6
|
+
import { fileURLToPath } from 'node:url';
|
|
7
|
+
|
|
8
|
+
const packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..');
|
|
9
|
+
const repoRoot = resolve(packageRoot, '../../..');
|
|
10
|
+
const mxLauncherRoot = resolve(repoRoot, 'electron-dock/mx-launcher');
|
|
11
|
+
const refreshScript = resolve(mxLauncherRoot, 'server/scripts/site-slot-refresh-tunnel-cli.mjs');
|
|
12
|
+
const args = process.argv.slice(2);
|
|
13
|
+
const tarball = optionValue('--from-tarball') || optionValue('--tarball') || latestPreviewTarball();
|
|
14
|
+
|
|
15
|
+
if (!tarball) {
|
|
16
|
+
die('Missing @qpjoy/tunnel-cli tarball. Pass --from-tarball FILE or run pnpm pack first.');
|
|
17
|
+
}
|
|
18
|
+
if (!existsSync(tarball)) {
|
|
19
|
+
die(`Tarball not found: ${tarball}`);
|
|
20
|
+
}
|
|
21
|
+
if (!existsSync(refreshScript)) {
|
|
22
|
+
die(`MX Launcher refresh script not found: ${refreshScript}`);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const passThrough = [];
|
|
26
|
+
for (const name of ['--target-dir', '--temp-dir']) {
|
|
27
|
+
const value = optionValue(name);
|
|
28
|
+
if (value) passThrough.push(name, value);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
execFileSync(process.execPath, [
|
|
32
|
+
refreshScript,
|
|
33
|
+
'--from-tarball',
|
|
34
|
+
tarball,
|
|
35
|
+
...passThrough
|
|
36
|
+
], {
|
|
37
|
+
cwd: mxLauncherRoot,
|
|
38
|
+
stdio: 'inherit'
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
function optionValue(name) {
|
|
42
|
+
const index = args.indexOf(name);
|
|
43
|
+
if (index < 0) return null;
|
|
44
|
+
const value = args[index + 1];
|
|
45
|
+
if (!value || value.startsWith('--')) die(`Missing value for ${name}`);
|
|
46
|
+
return resolve(value);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function latestPreviewTarball() {
|
|
50
|
+
const previewDir = '/tmp/qpjoy-publish-preview';
|
|
51
|
+
if (!existsSync(previewDir)) return null;
|
|
52
|
+
const tarballs = readdirSync(previewDir)
|
|
53
|
+
.filter((entry) => entry.endsWith('.tgz') && entry.includes('tunnel-cli'))
|
|
54
|
+
.map((entry) => {
|
|
55
|
+
const path = join(previewDir, entry);
|
|
56
|
+
return { path, mtimeMs: statSync(path).mtimeMs };
|
|
57
|
+
})
|
|
58
|
+
.sort((a, b) => b.mtimeMs - a.mtimeMs);
|
|
59
|
+
return tarballs[0]?.path ?? null;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function die(message) {
|
|
63
|
+
console.error(message);
|
|
64
|
+
process.exit(1);
|
|
65
|
+
}
|