@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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@miraj181/ipingyou",
3
- "version": "2.0.8",
3
+ "version": "2.0.10",
4
4
  "description": "SecureLink-CLI — Secure peer-to-peer remote access via SSH & Cloudflare Tunnels",
5
5
  "main": "src/cli.js",
6
6
  "bin": {
@@ -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
- // ─── In-memory store auto-expire after TTL ─────────────────
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,