From 2024f4cbe0e489acd3af4815ade2378e6af08248 Mon Sep 17 00:00:00 2001 From: jenz Date: Thu, 2 Jul 2026 15:19:23 +0100 Subject: [PATCH] finally getting the ip to name relation properly --- client.html | 6 ++--- streaming-agent/signaling-server.js | 35 ++++++++++++++++++++++------- 2 files changed, 30 insertions(+), 11 deletions(-) diff --git a/client.html b/client.html index d8f2f99..36b35cf 100644 --- a/client.html +++ b/client.html @@ -408,10 +408,10 @@ setStatus('Connecting...'); sigWs = new WebSocket(SIG_URL); - sigWs.onopen = () => { + sigWs.onopen = async () => { setStatus('Connected — setting up stream...'); - initVisitorName(); - setupPeerConnection(); + await initVisitorName(); + await setupPeerConnection(); }; sigWs.onmessage = async e => { diff --git a/streaming-agent/signaling-server.js b/streaming-agent/signaling-server.js index 516ed57..1f28ec1 100644 --- a/streaming-agent/signaling-server.js +++ b/streaming-agent/signaling-server.js @@ -248,7 +248,14 @@ function stopPacat(browserSessId) { } // ── WebSocket handler ───────────────────────────────────────────────────────── -wss.on('connection', ws => { +wss.on('connection', (ws, req) => { + // Capture the real visitor IP at connection time from nginx headers. + // ws._socket.remoteAddress would be nginx's local IP for everyone. + const forwarded = req.headers['x-real-ip'] || + req.headers['x-forwarded-for'] || ''; + ws._realIp = forwarded.split(',')[0].trim() || + req.socket.remoteAddress.replace('::ffff:', ''); + let role = null; let agentSessionId = null; let browserSessId = null; @@ -280,7 +287,13 @@ wss.on('connection', ws => { } else if (msg.type === 'request_control') { - visitorName = msg.visitorName; + // Use the server-assigned name only — never trust the client-supplied one. + // If get_ip hasn't been called yet, reject the request. + if (!ws._assignedName) { + console.log('[sig] request_control rejected — no server-assigned name yet'); + return; + } + visitorName = ws._assignedName; if (containerRestarting) return; @@ -291,14 +304,17 @@ wss.on('connection', ws => { if (controlQueue.find(e => e.ws === ws)) return; + // Prevent someone with the same IP as the current controller from + // queuing behind themselves (duplicate tab or same-IP reconnect). + if (currentController && currentController.visitorName === visitorName) { + console.log(`[sig] ${visitorName} already controlling, ignoring duplicate request_control`); + return; + } + const entry = { ws, visitorName, browserSessId }; if (!currentController) { applyController(entry); - } else if (currentController.visitorName === visitorName) { - // Same identity already controlling (e.g. duplicate tab) — don't queue - // behind yourself. - return; } else { controlQueue.push(entry); console.log(`[sig] ${visitorName} joined queue position ${controlQueue.length}`); @@ -317,8 +333,11 @@ wss.on('connection', ws => { } else if (msg.type === 'get_ip') { - const ip = ws._socket.remoteAddress.replace('::ffff:', ''); - const name = ipToName(ip); + const name = ipToName(ws._realIp); + // Store server-assigned name on the socket so request_control can use + // it exclusively — the client-supplied visitorName is never trusted. + ws._assignedName = name; + visitorName = name; ws.send(JSON.stringify({ type: 'your_ip', ip: name })); }