peer-term 1.2.6 → 1.2.8
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/README.md +4 -3
- package/package.json +1 -1
- package/src/index.js +25 -10
- package/src/ui.js +2 -0
package/README.md
CHANGED
|
@@ -14,7 +14,7 @@ This will start a terminal sharing session and give you a 6-digit code.
|
|
|
14
14
|
|
|
15
15
|
Share this code with your peer. They can view your terminal by going to https://peer-term-relay-production-9b7a.up.railway.app or https://peer-term-relay.onrender.com and entering the code.
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
If you started the session with `--secure`, both sides will show a short security fingerprint. Compare it over a trusted channel. If it matches, authorize the session in the host CLI:
|
|
18
18
|
|
|
19
19
|
```bash
|
|
20
20
|
a <code>
|
|
@@ -41,6 +41,7 @@ peer-term # starts at home directory
|
|
|
41
41
|
peer-term --path ~/projects # starts at ~/projects
|
|
42
42
|
peer-term --path . # starts in current directory
|
|
43
43
|
peer-term --readonly # view-only session
|
|
44
|
+
peer-term --secure # require fingerprint verification
|
|
44
45
|
peer-term --expiry 10m # custom expiry time
|
|
45
46
|
peer-term --relay wss://custom # use a custom relay server
|
|
46
47
|
peer-term --verbose # enable debug logging
|
|
@@ -49,7 +50,7 @@ peer-term --verbose # enable debug logging
|
|
|
49
50
|
## Features
|
|
50
51
|
|
|
51
52
|
- **No Config**: Works instantly. No port forwarding or firewall configuration needed.
|
|
52
|
-
- **End-to-End Encrypted**: Terminal data is encrypted locally using AES-256-GCM with ECDH P-256 key exchange
|
|
53
|
+
- **End-to-End Encrypted**: Terminal data is encrypted locally using AES-256-GCM with ECDH P-256 key exchange. The relay never sees plaintext. A `--secure` flag enables an out-of-band fingerprint check for strict MITM protection.
|
|
53
54
|
- **WebRTC P2P**: Creates a direct Peer-to-Peer connection on the same LAN for zero-latency, relay-free sessions.
|
|
54
55
|
- **Read-Only Mode**: Guests can view your terminal but cannot type commands.
|
|
55
56
|
- **Custom Start Path**: Set the starting directory with `--path`.
|
|
@@ -61,6 +62,6 @@ peer-term --verbose # enable debug logging
|
|
|
61
62
|
1. **Host** registers a session on the relay and gets a 6-digit code
|
|
62
63
|
2. **Client** opens the web UI and enters the code
|
|
63
64
|
3. Both sides perform an **ECDH key exchange** to derive a shared AES-256-GCM secret
|
|
64
|
-
4.
|
|
65
|
+
4. If `--secure` is used, both sides compare a short fingerprint, then the host authorizes the verified session with `a <code>`
|
|
65
66
|
5. All terminal I/O is encrypted end-to-end — the relay only forwards opaque blobs
|
|
66
67
|
6. If both peers are on the same LAN, a **WebRTC DataChannel** is established to bypass the relay entirely
|
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -61,7 +61,7 @@ try {
|
|
|
61
61
|
// ─── CLI Argument Parsing ────────────────────────────────────────────────────
|
|
62
62
|
|
|
63
63
|
const argv = minimist(process.argv.slice(2), {
|
|
64
|
-
boolean: ['readonly', 'verbose', 'help', 'version'],
|
|
64
|
+
boolean: ['readonly', 'verbose', 'help', 'version', 'secure'],
|
|
65
65
|
string: ['expiry', 'rejoin', 'relay', 'path'],
|
|
66
66
|
alias: { h: 'help', v: 'version', V: 'verbose' },
|
|
67
67
|
});
|
|
@@ -308,6 +308,7 @@ class Session {
|
|
|
308
308
|
this.readOnly = readOnly;
|
|
309
309
|
this.startPath = startPath;
|
|
310
310
|
this.onDestroy = onDestroy;
|
|
311
|
+
this.secureMode = argv.secure || false;
|
|
311
312
|
|
|
312
313
|
this.ws = null;
|
|
313
314
|
this.code = null;
|
|
@@ -357,7 +358,11 @@ class Session {
|
|
|
357
358
|
this.fingerprintAuthorized = false;
|
|
358
359
|
this.stopHeartbeat();
|
|
359
360
|
this._cleanupWebRTC();
|
|
360
|
-
this.ws.send(JSON.stringify({
|
|
361
|
+
this.ws.send(JSON.stringify({
|
|
362
|
+
type: 'key-exchange',
|
|
363
|
+
publicKey: this.hostPublicKeyBase64,
|
|
364
|
+
secureMode: this.secureMode
|
|
365
|
+
}));
|
|
361
366
|
}
|
|
362
367
|
|
|
363
368
|
async _completeKeyExchange(clientPublicKeyBase64) {
|
|
@@ -368,14 +373,19 @@ class Session {
|
|
|
368
373
|
|
|
369
374
|
const peerPublicKey = await importPublicKey(clientPublicKeyBase64);
|
|
370
375
|
this.sharedKey = await deriveSharedKey(this.keyPair.privateKey, peerPublicKey);
|
|
371
|
-
this.securityFingerprint = await fingerprintPublicKeys(
|
|
372
|
-
this.code,
|
|
373
|
-
this.hostPublicKeyBase64,
|
|
374
|
-
this.clientPublicKeyBase64
|
|
375
|
-
);
|
|
376
|
-
this.fingerprintAuthorized = false;
|
|
377
376
|
|
|
378
|
-
this.
|
|
377
|
+
if (this.secureMode) {
|
|
378
|
+
this.securityFingerprint = await fingerprintPublicKeys(
|
|
379
|
+
this.code,
|
|
380
|
+
this.hostPublicKeyBase64,
|
|
381
|
+
this.clientPublicKeyBase64
|
|
382
|
+
);
|
|
383
|
+
this.fingerprintAuthorized = false;
|
|
384
|
+
this._printFingerprintAuthorization();
|
|
385
|
+
} else {
|
|
386
|
+
this.fingerprintAuthorized = true;
|
|
387
|
+
await this._activateSecureSession();
|
|
388
|
+
}
|
|
379
389
|
}
|
|
380
390
|
|
|
381
391
|
_printFingerprintAuthorization() {
|
|
@@ -486,7 +496,7 @@ class Session {
|
|
|
486
496
|
code: this.code,
|
|
487
497
|
expiry: formatDuration(this.expiryMs),
|
|
488
498
|
rejoinWindow: formatDuration(this.rejoinMs),
|
|
489
|
-
mode: this.readOnly ? 'Read-Only' : 'Read-Write',
|
|
499
|
+
mode: (this.readOnly ? 'Read-Only' : 'Read-Write') + (this.secureMode ? ' (Secure)' : ''),
|
|
490
500
|
shell: this.shell,
|
|
491
501
|
startPath: this.startPath,
|
|
492
502
|
shareUrl: url.replace(/^wss:\/\//i, 'https://').replace(/^ws:\/\//i, 'http://')
|
|
@@ -505,6 +515,11 @@ class Session {
|
|
|
505
515
|
this.isClientConnected = true;
|
|
506
516
|
this.missedPings = 0;
|
|
507
517
|
|
|
518
|
+
if (this.useDataChannel && this.webrtc && this.webrtc.isActive()) {
|
|
519
|
+
this.startHeartbeat();
|
|
520
|
+
break;
|
|
521
|
+
}
|
|
522
|
+
|
|
508
523
|
await this._beginKeyExchange();
|
|
509
524
|
break;
|
|
510
525
|
}
|
package/src/ui.js
CHANGED
|
@@ -101,6 +101,7 @@ Options:
|
|
|
101
101
|
--expiry <time> Session expiry time (e.g. 5m, 30s, 1h) [default: 5m]
|
|
102
102
|
--rejoin <time> Reconnection window (e.g. 5m, 1h, 6h) [default: 2m]
|
|
103
103
|
--readonly Share in view-only mode
|
|
104
|
+
--secure Enable fingerprint verification for MITM protection
|
|
104
105
|
--path <dir> Starting directory for the terminal session [default: home]
|
|
105
106
|
--relay <url> Custom relay server URL
|
|
106
107
|
--verbose Enable debug logging
|
|
@@ -112,6 +113,7 @@ Examples:
|
|
|
112
113
|
peer-term --expiry 10m Custom expiry
|
|
113
114
|
peer-term --rejoin 30m Custom reconnection window
|
|
114
115
|
peer-term --readonly View-only session
|
|
116
|
+
peer-term --secure Require fingerprint verification
|
|
115
117
|
peer-term --path ~/projects Start in ~/projects
|
|
116
118
|
peer-term --verbose Debug logs
|
|
117
119
|
peer-term --relay wss://custom Use custom relay server
|