@miraj181/ipingyou 2.0.8 → 2.0.10
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/package.json +1 -1
- package/src/modes/client.js +1 -1
- package/src/modes/host.js +47 -0
- package/src/server.js +13 -1
package/package.json
CHANGED
package/src/modes/client.js
CHANGED
|
@@ -187,7 +187,7 @@ async function connectSSH(username, hostname, privateKeyPath) {
|
|
|
187
187
|
}
|
|
188
188
|
|
|
189
189
|
sshArgs.push(`${username}@${hostname}`);
|
|
190
|
-
sshArgs.push('-t', 'tmux new-session -A -s SecureLink_Session || exec $SHELL');
|
|
190
|
+
sshArgs.push('-t', 'tmux new-session -A -s SecureLink_Session 2>/dev/null || exec $SHELL -l');
|
|
191
191
|
|
|
192
192
|
const child = execa('ssh', sshArgs, {
|
|
193
193
|
stdio: 'inherit',
|
package/src/modes/host.js
CHANGED
|
@@ -18,6 +18,8 @@ import chalk from 'chalk';
|
|
|
18
18
|
import inquirer from 'inquirer';
|
|
19
19
|
import path from 'node:path';
|
|
20
20
|
import { fileURLToPath } from 'node:url';
|
|
21
|
+
import fs from 'node:fs';
|
|
22
|
+
import os from 'node:os';
|
|
21
23
|
import { generateUID } from '../lib/uid.js';
|
|
22
24
|
import { encrypt, decrypt } from '../lib/crypto.js';
|
|
23
25
|
import { trackPID, untrackPID, setRevokeOnExit, addCleanupHook } from '../lib/cleanup.js';
|
|
@@ -85,6 +87,50 @@ async function ensureSSHRunning() {
|
|
|
85
87
|
}
|
|
86
88
|
}
|
|
87
89
|
|
|
90
|
+
/**
|
|
91
|
+
* Ensure tmux is installed for terminal mirroring.
|
|
92
|
+
*/
|
|
93
|
+
async function ensureTmuxInstalled() {
|
|
94
|
+
const osInfo = detectOS();
|
|
95
|
+
if (osInfo.isWindows) return;
|
|
96
|
+
|
|
97
|
+
const spinner = createSpinner('Checking tmux installation...', networkSpinner).start();
|
|
98
|
+
try {
|
|
99
|
+
try {
|
|
100
|
+
await execaCommand('tmux -V', { reject: true });
|
|
101
|
+
spinner.succeed('tmux is installed (Terminal Mirroring available)');
|
|
102
|
+
} catch {
|
|
103
|
+
spinner.text = 'tmux not found. Attempting to install...';
|
|
104
|
+
if (osInfo.isLinux) {
|
|
105
|
+
if (fs.existsSync('/usr/bin/apt') || fs.existsSync('/usr/bin/apt-get')) {
|
|
106
|
+
await execaCommand('sudo apt-get update && sudo apt-get install -y tmux', { shell: true, stdio: 'inherit' });
|
|
107
|
+
} else if (fs.existsSync('/usr/bin/dnf')) {
|
|
108
|
+
await execaCommand('sudo dnf install -y tmux', { shell: true, stdio: 'inherit' });
|
|
109
|
+
} else if (fs.existsSync('/usr/bin/yum')) {
|
|
110
|
+
await execaCommand('sudo yum install -y tmux', { shell: true, stdio: 'inherit' });
|
|
111
|
+
} else if (fs.existsSync('/usr/bin/pacman')) {
|
|
112
|
+
await execaCommand('sudo pacman -S --noconfirm tmux', { shell: true, stdio: 'inherit' });
|
|
113
|
+
} else if (fs.existsSync('/sbin/apk')) {
|
|
114
|
+
await execaCommand('sudo apk add tmux', { shell: true, stdio: 'inherit' });
|
|
115
|
+
} else {
|
|
116
|
+
throw new Error('Unsupported Linux package manager');
|
|
117
|
+
}
|
|
118
|
+
spinner.succeed('tmux installed successfully (Terminal Mirroring available)');
|
|
119
|
+
} else if (osInfo.isMac) {
|
|
120
|
+
try {
|
|
121
|
+
await execaCommand('brew install tmux', { shell: true, stdio: 'inherit' });
|
|
122
|
+
spinner.succeed('tmux installed successfully (Terminal Mirroring available)');
|
|
123
|
+
} catch {
|
|
124
|
+
throw new Error('Homebrew is required to install tmux on macOS');
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
} catch (err) {
|
|
129
|
+
spinner.fail(`tmux check/install failed: ${err.message}`);
|
|
130
|
+
console.log(chalk.dim(' Terminal Mirroring feature will not be available.'));
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
88
134
|
/**
|
|
89
135
|
* Supervise cloudflared tunnel, restarting it if it crashes.
|
|
90
136
|
*/
|
|
@@ -565,6 +611,7 @@ export async function startHostMode() {
|
|
|
565
611
|
|
|
566
612
|
if (serviceType === 'ssh') {
|
|
567
613
|
await ensureSSHRunning();
|
|
614
|
+
await ensureTmuxInstalled();
|
|
568
615
|
console.log(chalk.dim(' 🔑 Generating ephemeral SSH key for passwordless entry...'));
|
|
569
616
|
try {
|
|
570
617
|
const ephemeralKey = await generateEphemeralKey();
|
package/src/server.js
CHANGED
|
@@ -79,8 +79,11 @@ function recordViolation(req) {
|
|
|
79
79
|
}
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
-
// ───
|
|
82
|
+
// ─── Constants & Limits ──────────────────────────────────────
|
|
83
83
|
const TTL_MS = 60 * 60 * 1000; // 1 hour
|
|
84
|
+
const MAX_UIDS = 50000; // Max concurrent tunnels (prevent memory leak)
|
|
85
|
+
const MAX_VIOLATIONS = 50000; // Max tracked malicious IPs before reset
|
|
86
|
+
|
|
84
87
|
const store = new Map(); // uid → { iv, ciphertext, salt, createdAt, clients: [] }
|
|
85
88
|
|
|
86
89
|
function pruneExpired() {
|
|
@@ -91,6 +94,10 @@ function pruneExpired() {
|
|
|
91
94
|
console.log(`🗑️ Expired UID: ${uid}`);
|
|
92
95
|
}
|
|
93
96
|
}
|
|
97
|
+
|
|
98
|
+
// Strict check to prevent malicious OOM overflow
|
|
99
|
+
if (ipViolations.size > MAX_VIOLATIONS) ipViolations.clear();
|
|
100
|
+
if (blacklistedIPs.size > MAX_VIOLATIONS) blacklistedIPs.clear();
|
|
94
101
|
}
|
|
95
102
|
|
|
96
103
|
// Run pruning every 5 minutes
|
|
@@ -136,6 +143,11 @@ app.post('/register', strictLimiter, (req, res) => {
|
|
|
136
143
|
return res.status(400).json({ error: 'Invalid ciphertext' });
|
|
137
144
|
}
|
|
138
145
|
|
|
146
|
+
// Prevent broker OOM
|
|
147
|
+
if (store.size >= MAX_UIDS && !store.has(uid)) {
|
|
148
|
+
return res.status(503).json({ error: 'Broker is at maximum capacity. Please try again later.' });
|
|
149
|
+
}
|
|
150
|
+
|
|
139
151
|
// Store the encrypted blob as-is — broker NEVER decrypts
|
|
140
152
|
store.set(uid, {
|
|
141
153
|
iv,
|