From d369f583b635fec048b735fc9eea4cc6c451b43d Mon Sep 17 00:00:00 2001 From: gitea Date: Wed, 8 Apr 2026 16:32:56 +0000 Subject: [PATCH] fix: grep nginx logs directly in /logs/:ip endpoint Records now works without running a scan first. If logs aren't cached in memory from a scan, the endpoint greps the nginx access logs directly for [Client IP] matches and returns the last 500 lines. Co-Authored-By: Claude Haiku 4.5 --- dashboard/server.js | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/dashboard/server.js b/dashboard/server.js index 19996e8..a05c532 100644 --- a/dashboard/server.js +++ b/dashboard/server.js @@ -490,12 +490,29 @@ app.get('/api/f2b/poll', (req, res) => { }); // ── Routes: Nginx log viewer ────────────────────────────────────────────────── -app.get('/logs/:ip', (req, res) => { +app.get('/logs/:ip', async (req, res) => { const ip = req.params.ip; - const logs = ipLogs.get(ip) || []; const hist = banHistory.get(ip); const esc = s => String(s).replace(/&/g,'&').replace(//g,'>'); + let logs = ipLogs.get(ip) || []; + + // If no logs in memory, grep nginx logs directly + if (logs.length === 0) { + try { + const files = fs.readdirSync(LOG_DIR) + .filter(f => f.startsWith('proxy-host-') && f.endsWith('_access.log')) + .map(f => path.join(LOG_DIR, f)); + + const ipEscaped = ip.replace(/\./g, '\\.'); + const grepCmd = `grep -h "\\[Client ${ipEscaped}\\]" ${files.join(' ')} 2>/dev/null || true`; + const output = await run(grepCmd); + logs = output.trim().split('\n').filter(l => l.trim()).slice(-500); // last 500 lines + } catch (e) { + logs = [`[Error reading logs: ${e.message}]`]; + } + } + let badge = ''; if (hist) badge = `
⚠ Previously banned ${hist.banCount}x — last ${new Date(hist.lastSeen).toLocaleString()}
`; @@ -508,8 +525,8 @@ app.get('/logs/:ip', (req, res) => {
// LOG ENTRIES
${badge} -

Entries in current scan window: ${logs.length}

-
${logs.map(esc).join('\n') || '(no entries — run a scan first)'}
+

Entries found: ${logs.length}

+
${logs.map(esc).join('\n') || '(no entries found)'}
_