polaris-vpn 1.1.1 → 1.1.2
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/CHANGELOG.md +10 -0
- package/package.json +1 -1
- package/src/commands/check.js +3 -2
- package/src/commands/dashboard.js +10 -5
- package/src/commands/deploy.js +2 -1
- package/src/commands/monitor.js +1 -1
- package/src/commands/start.js +1 -2
- package/src/commands/status.js +22 -9
- package/src/commands/tui.js +14 -4
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,16 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [1.1.2] - 2026-07-22
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- **Start Command**: Fixed `ReferenceError: config is not defined` crash when invoking `polaris start` without `--server` argument.
|
|
13
|
+
- **WireGuard & AmneziaWG Status**: Fixed `polaris status` and `polaris check` reporting false proxy failures for system-wide VPN interfaces.
|
|
14
|
+
- **AmneziaWG Bandwidth Monitoring**: Updated `polaris monitor`, `dashboard`, `status`, and TUI components to query `awg` interface statistics and accept `--mode amneziawg`.
|
|
15
|
+
- **Deploy Local Auto-Connect**: Updated `polaris deploy` to automatically trigger local connection passing correct server and mode arguments upon provisioning completion.
|
|
16
|
+
- **Status Table Formatting**: Replaced invalid SOCKS5 proxy port display (`socks5://127.0.0.1:0`) with clear `System-wide (All OS traffic)` label for WireGuard and AmneziaWG connections.
|
|
17
|
+
|
|
8
18
|
## [1.0.0] - 2026-07-15
|
|
9
19
|
|
|
10
20
|
### Added
|
package/package.json
CHANGED
package/src/commands/check.js
CHANGED
|
@@ -22,12 +22,13 @@ export default async (options) => {
|
|
|
22
22
|
if (spinner) spinner.text = 'Checking IP address...';
|
|
23
23
|
if (info) {
|
|
24
24
|
try {
|
|
25
|
-
const
|
|
25
|
+
const isSystemWide = info.mode === 'wireguard' || info.mode === 'amneziawg';
|
|
26
|
+
const tunnelIp = isSystemWide ? await getPublicIp() : await getProxiedIp(info.port);
|
|
26
27
|
results.ip = true;
|
|
27
28
|
details.ip = `Tunnel active (${(info.mode || 'ssh').toUpperCase()}): ${tunnelIp}`;
|
|
28
29
|
} catch (e) {
|
|
29
30
|
results.ip = false;
|
|
30
|
-
details.ip = `Tunnel
|
|
31
|
+
details.ip = `Tunnel active but IP check failed: ${e.message}`;
|
|
31
32
|
}
|
|
32
33
|
} else {
|
|
33
34
|
const pubIp = await getPublicIp();
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import blessed from 'blessed';
|
|
2
2
|
import contrib from 'blessed-contrib';
|
|
3
3
|
import { getActiveTunnel } from '../core/tunnel-service.js';
|
|
4
|
-
import { getProxiedIp } from '../net/ip-check.js';
|
|
4
|
+
import { getProxiedIp, getPublicIp } from '../net/ip-check.js';
|
|
5
5
|
import fetch from 'node-fetch';
|
|
6
6
|
import { spawnSync } from 'child_process';
|
|
7
7
|
import os from 'os';
|
|
@@ -67,8 +67,12 @@ const formatBytes = (bytes) => {
|
|
|
67
67
|
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
|
|
68
68
|
};
|
|
69
69
|
|
|
70
|
-
const getWgStats = () => {
|
|
71
|
-
const
|
|
70
|
+
const getWgStats = (isAwg = false) => {
|
|
71
|
+
const cmd = isAwg ? 'awg' : 'wg';
|
|
72
|
+
let dumpRes = spawnSync('sudo', [cmd, 'show', 'all', 'dump'], { encoding: 'utf-8' });
|
|
73
|
+
if (dumpRes.status !== 0 && isAwg) {
|
|
74
|
+
dumpRes = spawnSync('sudo', ['wg', 'show', 'all', 'dump'], { encoding: 'utf-8' });
|
|
75
|
+
}
|
|
72
76
|
if (dumpRes.status !== 0) return null;
|
|
73
77
|
const lines = dumpRes.stdout.trim().split('\n');
|
|
74
78
|
if (lines.length <= 1) return null;
|
|
@@ -201,7 +205,8 @@ export default async () => {
|
|
|
201
205
|
if (!geoFetched) {
|
|
202
206
|
geoFetched = true;
|
|
203
207
|
try {
|
|
204
|
-
|
|
208
|
+
const isSystemWide = info.mode === 'wireguard' || info.mode === 'amneziawg';
|
|
209
|
+
currentIp = isSystemWide ? await getPublicIp() : await getProxiedIp(info.port);
|
|
205
210
|
geoData = await getGeoIp(currentIp);
|
|
206
211
|
if (geoData) {
|
|
207
212
|
mapWidget.addMarker({ lat: geoData.lat, lon: geoData.lon, color: 'red', char: 'X' });
|
|
@@ -227,7 +232,7 @@ export default async () => {
|
|
|
227
232
|
|
|
228
233
|
// 4. Update WG Stats & Chart
|
|
229
234
|
if (info.mode === 'wireguard' || info.mode === 'amneziawg' || info.mode === 'auto') {
|
|
230
|
-
const stats = getWgStats();
|
|
235
|
+
const stats = getWgStats(info.mode === 'amneziawg');
|
|
231
236
|
if (stats) {
|
|
232
237
|
if (!hasInitWg) {
|
|
233
238
|
prevRx = stats.totalRx;
|
package/src/commands/deploy.js
CHANGED
|
@@ -36,7 +36,8 @@ export default async (options) => {
|
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
// Automatically trigger local connection
|
|
39
|
-
|
|
39
|
+
const mode = options.mode || 'wireguard';
|
|
40
|
+
await startCommand({ server, mode, json: isJson });
|
|
40
41
|
|
|
41
42
|
} catch (err) {
|
|
42
43
|
if (spinner) spinner.fail('Deployment failed');
|
package/src/commands/monitor.js
CHANGED
|
@@ -49,7 +49,7 @@ export default async (options) => {
|
|
|
49
49
|
const isJson = options.json;
|
|
50
50
|
const info = getActiveTunnel();
|
|
51
51
|
|
|
52
|
-
if (!info || info.mode !== 'wireguard') {
|
|
52
|
+
if (!info || (info.mode !== 'wireguard' && info.mode !== 'amneziawg')) {
|
|
53
53
|
if (isJson) {
|
|
54
54
|
console.log(JSON.stringify({ error: 'WireGuard tunnel is not active' }));
|
|
55
55
|
} else {
|
package/src/commands/start.js
CHANGED
|
@@ -51,8 +51,7 @@ export default async (options) => {
|
|
|
51
51
|
const requestedMode = options.mode || 'auto';
|
|
52
52
|
|
|
53
53
|
if (!server) {
|
|
54
|
-
const active =
|
|
55
|
-
const profiles = config.get('profiles') || {};
|
|
54
|
+
const { profiles, active } = getProfiles();
|
|
56
55
|
|
|
57
56
|
if (active && profiles[active]) {
|
|
58
57
|
server = profiles[active];
|
package/src/commands/status.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { getActiveTunnel } from '../core/tunnel-service.js';
|
|
2
|
-
import { getProxiedIp } from '../net/ip-check.js';
|
|
2
|
+
import { getProxiedIp, getPublicIp } from '../net/ip-check.js';
|
|
3
3
|
import { createTable, createSpinner, printError } from '../utils/display.js';
|
|
4
4
|
import chalk from 'chalk';
|
|
5
5
|
import fetch from 'node-fetch';
|
|
@@ -41,8 +41,12 @@ const formatBytes = (bytes) => {
|
|
|
41
41
|
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
|
|
42
42
|
};
|
|
43
43
|
|
|
44
|
-
const getWgStats = () => {
|
|
45
|
-
const
|
|
44
|
+
const getWgStats = (isAwg = false) => {
|
|
45
|
+
const cmd = isAwg ? 'awg' : 'wg';
|
|
46
|
+
let dumpRes = spawnSync('sudo', [cmd, 'show', 'all', 'dump'], { encoding: 'utf-8' });
|
|
47
|
+
if (dumpRes.status !== 0 && isAwg) {
|
|
48
|
+
dumpRes = spawnSync('sudo', ['wg', 'show', 'all', 'dump'], { encoding: 'utf-8' });
|
|
49
|
+
}
|
|
46
50
|
if (dumpRes.status !== 0) return null;
|
|
47
51
|
const lines = dumpRes.stdout.trim().split('\n');
|
|
48
52
|
if (lines.length <= 1) return null;
|
|
@@ -72,10 +76,11 @@ export default async (options) => {
|
|
|
72
76
|
}
|
|
73
77
|
|
|
74
78
|
let currentIp = 'Unknown';
|
|
75
|
-
const
|
|
79
|
+
const isSystemWide = info.mode === 'wireguard' || info.mode === 'amneziawg';
|
|
80
|
+
const spinner = isJson ? null : createSpinner(isSystemWide ? 'Checking public IP...' : 'Checking proxy status...').start();
|
|
76
81
|
|
|
77
82
|
try {
|
|
78
|
-
currentIp = await getProxiedIp(info.port);
|
|
83
|
+
currentIp = isSystemWide ? await getPublicIp() : await getProxiedIp(info.port);
|
|
79
84
|
if (spinner) spinner.stop();
|
|
80
85
|
|
|
81
86
|
let geo = 'N/A';
|
|
@@ -92,8 +97,8 @@ export default async (options) => {
|
|
|
92
97
|
latency = pingServer(serverIp);
|
|
93
98
|
geo = await getGeoIp(currentIp);
|
|
94
99
|
|
|
95
|
-
if (
|
|
96
|
-
const stats = getWgStats();
|
|
100
|
+
if (isSystemWide) {
|
|
101
|
+
const stats = getWgStats(info.mode === 'amneziawg');
|
|
97
102
|
if (stats) {
|
|
98
103
|
dataUsage = `${formatBytes(stats.totalRx)} / ${formatBytes(stats.totalTx)}`;
|
|
99
104
|
}
|
|
@@ -128,8 +133,16 @@ export default async (options) => {
|
|
|
128
133
|
table.push(
|
|
129
134
|
['Status', chalk.green('Connected')],
|
|
130
135
|
['Mode', (info.mode || 'ssh').toUpperCase()],
|
|
131
|
-
['Server', info.server]
|
|
132
|
-
|
|
136
|
+
['Server', info.server]
|
|
137
|
+
);
|
|
138
|
+
|
|
139
|
+
if (isSystemWide) {
|
|
140
|
+
table.push(['Connection', chalk.cyan('System-wide (All OS traffic)')]);
|
|
141
|
+
} else {
|
|
142
|
+
table.push(['Proxy', `socks5://127.0.0.1:${info.port}`]);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
table.push(
|
|
133
146
|
['Current IP', chalk.cyan(currentIp)],
|
|
134
147
|
['Uptime', `${uptimeMin} minutes`],
|
|
135
148
|
['PID', info.pid.toString()]
|
package/src/commands/tui.js
CHANGED
|
@@ -87,8 +87,12 @@ const fmtBytes = (n) => {
|
|
|
87
87
|
return `${(n / Math.pow(k, i)).toFixed(1)} ${s[i]}`;
|
|
88
88
|
};
|
|
89
89
|
|
|
90
|
-
const wgStats = () => {
|
|
91
|
-
const
|
|
90
|
+
const wgStats = (isAwg = false) => {
|
|
91
|
+
const cmd = isAwg ? 'awg' : 'wg';
|
|
92
|
+
let r = spawnSync('sudo', [cmd, 'show', 'all', 'dump'], { encoding: 'utf-8' });
|
|
93
|
+
if (r.status !== 0 && isAwg) {
|
|
94
|
+
r = spawnSync('sudo', ['wg', 'show', 'all', 'dump'], { encoding: 'utf-8' });
|
|
95
|
+
}
|
|
92
96
|
if (r.status !== 0) return null;
|
|
93
97
|
const lines = r.stdout.trim().split('\n');
|
|
94
98
|
if (lines.length <= 1) return null;
|
|
@@ -293,7 +297,7 @@ export default async () => {
|
|
|
293
297
|
if (info) {
|
|
294
298
|
const upMin = Math.floor((Date.now() - new Date(info.startTime).getTime()) / 60000);
|
|
295
299
|
const ping = pingServer(info.server.split('@').pop());
|
|
296
|
-
const wg = wgStats();
|
|
300
|
+
const wg = wgStats(info.mode === 'amneziawg');
|
|
297
301
|
L.push(`${t(D.accent, b('◈ Tunnel Status'))} ${t(D.success, '⬤ ACTIVE')}`);
|
|
298
302
|
L.push(hr()); L.push('');
|
|
299
303
|
L.push(` ${mu('Server ')} ${b(info.server)}`);
|
|
@@ -391,7 +395,13 @@ export default async () => {
|
|
|
391
395
|
const renderPeers = () => {
|
|
392
396
|
const L = [];
|
|
393
397
|
L.push(`${t(D.accent, b('≡ WireGuard Peers'))}`); L.push(hr()); L.push('');
|
|
394
|
-
const
|
|
398
|
+
const info = getActiveTunnel();
|
|
399
|
+
const isAwg = info && info.mode === 'amneziawg';
|
|
400
|
+
const cmd = isAwg ? 'awg' : 'wg';
|
|
401
|
+
let r = spawnSync('sudo', [cmd, 'show', 'all', 'dump'], { encoding: 'utf-8' });
|
|
402
|
+
if (r.status !== 0 && isAwg) {
|
|
403
|
+
r = spawnSync('sudo', ['wg', 'show', 'all', 'dump'], { encoding: 'utf-8' });
|
|
404
|
+
}
|
|
395
405
|
if (r.status !== 0 || !r.stdout.trim()) {
|
|
396
406
|
L.push(` ${t(D.warning, '⚠')} No WireGuard interface found.`);
|
|
397
407
|
L.push(` ${mu('Start a WireGuard tunnel first.')}`);
|