@miraj181/ipingyou 1.0.1 → 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 +4 -2
- package/src/server.js +0 -143
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@miraj181/ipingyou",
|
|
3
|
-
"version": "1.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,7 +8,9 @@
|
|
|
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
|
],
|
package/src/server.js
DELETED
|
@@ -1,143 +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 express from 'express';
|
|
13
|
-
|
|
14
|
-
const app = express();
|
|
15
|
-
app.use(express.json());
|
|
16
|
-
|
|
17
|
-
// ─── In-memory store — auto-expire after TTL ─────────────────
|
|
18
|
-
const TTL_MS = 60 * 60 * 1000; // 1 hour
|
|
19
|
-
const store = new Map(); // uid → { iv, ciphertext, createdAt }
|
|
20
|
-
|
|
21
|
-
function pruneExpired() {
|
|
22
|
-
const now = Date.now();
|
|
23
|
-
for (const [uid, entry] of store) {
|
|
24
|
-
if (now - entry.createdAt > TTL_MS) {
|
|
25
|
-
store.delete(uid);
|
|
26
|
-
console.log(`🗑️ Expired UID: ${uid}`);
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
// Run pruning every 5 minutes
|
|
32
|
-
setInterval(pruneExpired, 5 * 60 * 1000);
|
|
33
|
-
|
|
34
|
-
// ─── Routes ──────────────────────────────────────────────────
|
|
35
|
-
|
|
36
|
-
// Health
|
|
37
|
-
app.get('/health', (_req, res) => {
|
|
38
|
-
res.json({ status: 'ok', uptime: process.uptime(), activeUIDs: store.size });
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* POST /register
|
|
43
|
-
* Body: { uid: string, iv: string, ciphertext: string }
|
|
44
|
-
*
|
|
45
|
-
* The broker receives an ALREADY-ENCRYPTED blob from the host CLI.
|
|
46
|
-
* It never decrypts — just stores the { iv, ciphertext } pair.
|
|
47
|
-
*/
|
|
48
|
-
app.post('/register', (req, res) => {
|
|
49
|
-
try {
|
|
50
|
-
const { uid, iv, ciphertext } = req.body;
|
|
51
|
-
|
|
52
|
-
if (!uid || !iv || !ciphertext) {
|
|
53
|
-
return res.status(400).json({ error: 'Missing uid, iv, or ciphertext' });
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
if (typeof uid !== 'string' || uid.length < 6 || uid.length > 16) {
|
|
57
|
-
return res.status(400).json({ error: 'Invalid UID format (6-16 chars)' });
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// Validate IV format — must be 32 hex chars (16 bytes)
|
|
61
|
-
if (!/^[a-f0-9]{32}$/i.test(iv)) {
|
|
62
|
-
return res.status(400).json({ error: 'Invalid IV format (expected 32 hex chars)' });
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// Validate ciphertext is non-empty base64
|
|
66
|
-
if (typeof ciphertext !== 'string' || ciphertext.length === 0) {
|
|
67
|
-
return res.status(400).json({ error: 'Invalid ciphertext' });
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
// Store the encrypted blob as-is — broker NEVER decrypts
|
|
71
|
-
store.set(uid, {
|
|
72
|
-
iv,
|
|
73
|
-
ciphertext,
|
|
74
|
-
createdAt: Date.now(),
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
console.log(`✅ [${new Date().toLocaleTimeString()}] Registered UID: ${uid} (encrypted, ${ciphertext.length} bytes)`);
|
|
78
|
-
res.json({ status: 'registered', uid, expiresIn: '1 hour' });
|
|
79
|
-
} catch (err) {
|
|
80
|
-
console.error('❌ Register error:', err.message);
|
|
81
|
-
res.status(500).json({ error: 'Internal server error' });
|
|
82
|
-
}
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* GET /resolve/:uid
|
|
87
|
-
* Returns the ENCRYPTED blob { iv, ciphertext } for a given UID.
|
|
88
|
-
* The client CLI decrypts it locally — the broker never sees plaintext.
|
|
89
|
-
*/
|
|
90
|
-
app.get('/resolve/:uid', (req, res) => {
|
|
91
|
-
try {
|
|
92
|
-
const { uid } = req.params;
|
|
93
|
-
const entry = store.get(uid);
|
|
94
|
-
|
|
95
|
-
if (!entry) {
|
|
96
|
-
return res.status(404).json({ error: 'UID not found or expired' });
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
// Check TTL
|
|
100
|
-
if (Date.now() - entry.createdAt > TTL_MS) {
|
|
101
|
-
store.delete(uid);
|
|
102
|
-
return res.status(410).json({ error: 'UID expired' });
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
console.log(`🔍 [${new Date().toLocaleTimeString()}] Resolved UID: ${uid} (returning encrypted blob)`);
|
|
106
|
-
|
|
107
|
-
// Return encrypted blob — client decrypts
|
|
108
|
-
res.json({ uid, iv: entry.iv, ciphertext: entry.ciphertext });
|
|
109
|
-
} catch (err) {
|
|
110
|
-
console.error('❌ Resolve error:', err.message);
|
|
111
|
-
res.status(500).json({ error: 'Internal server error' });
|
|
112
|
-
}
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
/**
|
|
116
|
-
* DELETE /revoke/:uid
|
|
117
|
-
* Allows host to explicitly remove their UID before expiry.
|
|
118
|
-
*/
|
|
119
|
-
app.delete('/revoke/:uid', (req, res) => {
|
|
120
|
-
const { uid } = req.params;
|
|
121
|
-
const existed = store.delete(uid);
|
|
122
|
-
console.log(`🚫 [${new Date().toLocaleTimeString()}] Revoked UID: ${uid} (existed: ${existed})`);
|
|
123
|
-
res.json({ status: existed ? 'revoked' : 'not_found' });
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
// ─── Launch ──────────────────────────────────────────────────
|
|
127
|
-
// Render injects PORT; locally we use BROKER_PORT; fallback 4000
|
|
128
|
-
const PORT = process.env.PORT || process.env.BROKER_PORT || 4000;
|
|
129
|
-
const HOST = process.env.HOST || '0.0.0.0';
|
|
130
|
-
|
|
131
|
-
app.listen(PORT, HOST, () => {
|
|
132
|
-
console.log('');
|
|
133
|
-
console.log(' ╔══════════════════════════════════════════╗');
|
|
134
|
-
console.log(' ║ 🔗 SecureLink Broker — Active ║');
|
|
135
|
-
console.log(` ║ 📡 Port: ${String(PORT).padEnd(29)}║`);
|
|
136
|
-
console.log(' ║ 🔒 Zero-Knowledge Encrypted Store ║');
|
|
137
|
-
console.log(' ║ ⏱️ TTL: 1 hour per UID ║');
|
|
138
|
-
console.log(' ║ 🚫 Broker NEVER sees plaintext ║');
|
|
139
|
-
console.log(' ╚══════════════════════════════════════════╝');
|
|
140
|
-
console.log('');
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
export default app;
|