@miraj181/ipingyou 1.0.0 → 1.0.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@miraj181/ipingyou",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "SecureLink-CLI — Secure peer-to-peer remote access via SSH & Cloudflare Tunnels",
5
5
  "main": "src/cli.js",
6
6
  "bin": {
@@ -8,14 +8,14 @@
8
8
  "securelink": "src/cli.js"
9
9
  },
10
10
  "files": [
11
- "src/",
11
+ "src/cli.js",
12
+ "src/lib/",
13
+ "src/modes/",
12
14
  "README.md",
13
15
  "LICENSE"
14
16
  ],
15
17
  "scripts": {
16
18
  "start": "node src/cli.js",
17
- "broker": "node src/server.js",
18
- "dev:broker": "nodemon src/server.js",
19
19
  "dev:cli": "node src/cli.js",
20
20
  "prepublishOnly": "node -e \"require('fs').accessSync('LICENSE')\" && node src/cli.js --help"
21
21
  },
@@ -44,9 +44,7 @@
44
44
  "dependencies": {
45
45
  "chalk": "^5.3.0",
46
46
  "commander": "^12.1.0",
47
- "dotenv": "^16.4.5",
48
47
  "execa": "^9.5.2",
49
- "express": "^4.21.0",
50
48
  "inquirer": "^12.3.2",
51
49
  "nanoid": "^5.0.9",
52
50
  "ora": "^8.1.1",
package/src/cli.js CHANGED
@@ -11,7 +11,6 @@
11
11
  * npx ipingyou — Interactive mode
12
12
  * npx ipingyou host — Start as host directly
13
13
  * npx ipingyou connect — Start as client directly
14
- * npx ipingyou broker — Start the central broker
15
14
  *
16
15
  * Security:
17
16
  * All tunnel URLs are AES-256-CBC encrypted on the CLI side.
@@ -19,7 +18,6 @@
19
18
  * ============================================================
20
19
  */
21
20
 
22
- import 'dotenv/config';
23
21
  import { Command } from 'commander';
24
22
  import inquirer from 'inquirer';
25
23
  import chalk from 'chalk';
@@ -61,7 +59,6 @@ function showRichHelp() {
61
59
  console.log(` ${chalk.green('host')} : Generates a secure session UID and exposes your local machine.`);
62
60
  console.log(` ${chalk.blue('connect')} : Prompts for a UID to connect to a remote host.`);
63
61
  console.log(` ${chalk.dim('Supports Interactive SSH Shell & SCP File Transfers')}`);
64
- console.log(` ${chalk.yellow('broker')} : Start your own relay server (for self-hosting).`);
65
62
  console.log('');
66
63
 
67
64
  console.log(chalk.bold.white(' 🔒 Security Architecture:'));
@@ -74,7 +71,6 @@ function showRichHelp() {
74
71
  console.log(` $ npx ipingyou ${chalk.dim('# Interactive wizard (Recommended)')}`);
75
72
  console.log(` $ npx ipingyou host ${chalk.dim('# Quick start as Host')}`);
76
73
  console.log(` $ npx ipingyou connect ${chalk.dim('# Quick start as Client')}`);
77
- console.log(` $ npx ipingyou broker ${chalk.dim('# Start Relay')}`);
78
74
  console.log('');
79
75
  }
80
76
 
@@ -134,10 +130,6 @@ async function interactiveMode() {
134
130
  value: 'client',
135
131
  },
136
132
  new inquirer.Separator(),
137
- {
138
- name: `${chalk.yellow('📡 Start Broker Server')} ${chalk.dim('— Run the central relay (for self-hosting)')}`,
139
- value: 'broker',
140
- },
141
133
  {
142
134
  name: `${chalk.magenta('📖 Help / Information')} ${chalk.dim('— Learn how iPingYou works')}`,
143
135
  value: 'help',
@@ -153,23 +145,12 @@ async function interactiveMode() {
153
145
  case 'client':
154
146
  await startClientMode();
155
147
  break;
156
- case 'broker':
157
- await startBroker();
158
- break;
159
148
  case 'help':
160
149
  showRichHelp();
161
150
  break;
162
151
  }
163
152
  }
164
153
 
165
- // ─── Broker Start ────────────────────────────────────────────
166
- async function startBroker() {
167
- console.log(chalk.cyan(' Starting broker server...'));
168
- console.log('');
169
- // Dynamically import the server (it self-starts on import)
170
- await import('./server.js');
171
- }
172
-
173
154
  // ─── Commander Setup ─────────────────────────────────────────
174
155
  const program = new Command();
175
156
 
@@ -214,20 +195,6 @@ program
214
195
  }
215
196
  });
216
197
 
217
- program
218
- .command('broker')
219
- .description('Start the central broker server')
220
- .option('-p, --port <port>', 'Port to listen on', '4000')
221
- .action(async (opts) => {
222
- try {
223
- if (opts.port) process.env.BROKER_PORT = opts.port;
224
- showBanner();
225
- await startBroker();
226
- } catch (err) {
227
- fatal('broker', err);
228
- }
229
- });
230
-
231
198
  // ─── Default: interactive mode ──────────────────────────────
232
199
  program.action(async () => {
233
200
  try {
@@ -19,7 +19,7 @@ import { decrypt } from '../lib/crypto.js';
19
19
  import { trackPID, untrackPID } from '../lib/cleanup.js';
20
20
  import { createSpinner, sshSpinner, networkSpinner, fileTransferSpinner, showConnectionTrace, animatedSteps, simulateTransferProgress } from '../lib/animations.js';
21
21
 
22
- const BROKER_URL = process.env.BROKER_URL || 'http://localhost:4000';
22
+ const BROKER_URL = process.env.BROKER_URL || 'https://ipingyou.onrender.com';
23
23
 
24
24
  /**
25
25
  * Resolve a UID to a tunnel URL via the broker.
package/src/modes/host.js CHANGED
@@ -22,7 +22,7 @@ import { trackPID, untrackPID, setRevokeOnExit } from '../lib/cleanup.js';
22
22
  import { detectOS } from '../lib/platform.js';
23
23
  import { createSpinner, cryptoSpinner, tunnelSpinner, networkSpinner, typeText } from '../lib/animations.js';
24
24
 
25
- const BROKER_URL = process.env.BROKER_URL || 'http://localhost:4000';
25
+ const BROKER_URL = process.env.BROKER_URL || 'https://ipingyou.onrender.com';
26
26
 
27
27
  /**
28
28
  * Ensure the local SSH server is running.
@@ -307,7 +307,6 @@ export async function startHostMode() {
307
307
  const registered = await registerWithBroker(uid, tunnel.url);
308
308
  if (!registered) {
309
309
  console.error(chalk.red(`\n ❌ FATAL: Could not register with broker at ${BROKER_URL}`));
310
- console.log(chalk.dim(' Is the broker running? Try: npx ipingyou broker'));
311
310
  process.exit(1);
312
311
  }
313
312
 
package/src/server.js DELETED
@@ -1,144 +0,0 @@
1
- /**
2
- * ============================================================
3
- * SecureLink-CLI — Central Broker Server
4
- * ============================================================
5
- * A lightweight REST relay that pairs hosts and clients via
6
- * temporary UIDs. The broker is a DUMB PIPE — it stores and
7
- * returns encrypted blobs without ever seeing plaintext.
8
- * Encryption/decryption happens ONLY on the CLI side.
9
- * ============================================================
10
- */
11
-
12
- import 'dotenv/config';
13
- import express from 'express';
14
-
15
- const app = express();
16
- app.use(express.json());
17
-
18
- // ─── In-memory store — auto-expire after TTL ─────────────────
19
- const TTL_MS = 60 * 60 * 1000; // 1 hour
20
- const store = new Map(); // uid → { iv, ciphertext, createdAt }
21
-
22
- function pruneExpired() {
23
- const now = Date.now();
24
- for (const [uid, entry] of store) {
25
- if (now - entry.createdAt > TTL_MS) {
26
- store.delete(uid);
27
- console.log(`🗑️ Expired UID: ${uid}`);
28
- }
29
- }
30
- }
31
-
32
- // Run pruning every 5 minutes
33
- setInterval(pruneExpired, 5 * 60 * 1000);
34
-
35
- // ─── Routes ──────────────────────────────────────────────────
36
-
37
- // Health
38
- app.get('/health', (_req, res) => {
39
- res.json({ status: 'ok', uptime: process.uptime(), activeUIDs: store.size });
40
- });
41
-
42
- /**
43
- * POST /register
44
- * Body: { uid: string, iv: string, ciphertext: string }
45
- *
46
- * The broker receives an ALREADY-ENCRYPTED blob from the host CLI.
47
- * It never decrypts — just stores the { iv, ciphertext } pair.
48
- */
49
- app.post('/register', (req, res) => {
50
- try {
51
- const { uid, iv, ciphertext } = req.body;
52
-
53
- if (!uid || !iv || !ciphertext) {
54
- return res.status(400).json({ error: 'Missing uid, iv, or ciphertext' });
55
- }
56
-
57
- if (typeof uid !== 'string' || uid.length < 6 || uid.length > 16) {
58
- return res.status(400).json({ error: 'Invalid UID format (6-16 chars)' });
59
- }
60
-
61
- // Validate IV format — must be 32 hex chars (16 bytes)
62
- if (!/^[a-f0-9]{32}$/i.test(iv)) {
63
- return res.status(400).json({ error: 'Invalid IV format (expected 32 hex chars)' });
64
- }
65
-
66
- // Validate ciphertext is non-empty base64
67
- if (typeof ciphertext !== 'string' || ciphertext.length === 0) {
68
- return res.status(400).json({ error: 'Invalid ciphertext' });
69
- }
70
-
71
- // Store the encrypted blob as-is — broker NEVER decrypts
72
- store.set(uid, {
73
- iv,
74
- ciphertext,
75
- createdAt: Date.now(),
76
- });
77
-
78
- console.log(`✅ [${new Date().toLocaleTimeString()}] Registered UID: ${uid} (encrypted, ${ciphertext.length} bytes)`);
79
- res.json({ status: 'registered', uid, expiresIn: '1 hour' });
80
- } catch (err) {
81
- console.error('❌ Register error:', err.message);
82
- res.status(500).json({ error: 'Internal server error' });
83
- }
84
- });
85
-
86
- /**
87
- * GET /resolve/:uid
88
- * Returns the ENCRYPTED blob { iv, ciphertext } for a given UID.
89
- * The client CLI decrypts it locally — the broker never sees plaintext.
90
- */
91
- app.get('/resolve/:uid', (req, res) => {
92
- try {
93
- const { uid } = req.params;
94
- const entry = store.get(uid);
95
-
96
- if (!entry) {
97
- return res.status(404).json({ error: 'UID not found or expired' });
98
- }
99
-
100
- // Check TTL
101
- if (Date.now() - entry.createdAt > TTL_MS) {
102
- store.delete(uid);
103
- return res.status(410).json({ error: 'UID expired' });
104
- }
105
-
106
- console.log(`🔍 [${new Date().toLocaleTimeString()}] Resolved UID: ${uid} (returning encrypted blob)`);
107
-
108
- // Return encrypted blob — client decrypts
109
- res.json({ uid, iv: entry.iv, ciphertext: entry.ciphertext });
110
- } catch (err) {
111
- console.error('❌ Resolve error:', err.message);
112
- res.status(500).json({ error: 'Internal server error' });
113
- }
114
- });
115
-
116
- /**
117
- * DELETE /revoke/:uid
118
- * Allows host to explicitly remove their UID before expiry.
119
- */
120
- app.delete('/revoke/:uid', (req, res) => {
121
- const { uid } = req.params;
122
- const existed = store.delete(uid);
123
- console.log(`🚫 [${new Date().toLocaleTimeString()}] Revoked UID: ${uid} (existed: ${existed})`);
124
- res.json({ status: existed ? 'revoked' : 'not_found' });
125
- });
126
-
127
- // ─── Launch ──────────────────────────────────────────────────
128
- // Render injects PORT; locally we use BROKER_PORT; fallback 4000
129
- const PORT = process.env.PORT || process.env.BROKER_PORT || 4000;
130
- const HOST = process.env.HOST || '0.0.0.0';
131
-
132
- app.listen(PORT, HOST, () => {
133
- console.log('');
134
- console.log(' ╔══════════════════════════════════════════╗');
135
- console.log(' ║ 🔗 SecureLink Broker — Active ║');
136
- console.log(` ║ 📡 Port: ${String(PORT).padEnd(29)}║`);
137
- console.log(' ║ 🔒 Zero-Knowledge Encrypted Store ║');
138
- console.log(' ║ ⏱️ TTL: 1 hour per UID ║');
139
- console.log(' ║ 🚫 Broker NEVER sees plaintext ║');
140
- console.log(' ╚══════════════════════════════════════════╝');
141
- console.log('');
142
- });
143
-
144
- export default app;