import { NextRequest, NextResponse } from 'next/server' import { exec } from 'child_process' import { promisify } from 'util' import fs from 'fs/promises' const execAsync = promisify(exec) export async function GET(request: NextRequest) { const { searchParams } = new URL(request.url) const type = searchParams.get('type') const limit = parseInt(searchParams.get('limit') || '100') const since = searchParams.get('since') || undefined // timestamp try { switch (type) { case 'firewall': return await getFirewallLogs(limit, since) case 'lfd': return await getLfdLogs(limit, since) case 'system': return await getSystemLogs(limit, since) case 'blocked': return await getBlockedIPs(limit) case 'connections': return await getActiveConnections() default: return await getAllLogs(limit, since) } } catch (error: any) { console.error('Logs API error:', error) return NextResponse.json({ success: false, error: `Failed to retrieve logs: ${error.message}` }, { status: 500 }) } } async function getFirewallLogs(limit: number, since?: string) { try { // Get iptables logs from syslog let command = `grep "CSF\\|iptables" /var/log/syslog | tail -${limit}` if (since) { const sinceDate = new Date(since).toISOString().split('T')[0] command = `grep "CSF\\|iptables" /var/log/syslog | grep "${sinceDate}" | tail -${limit}` } const { stdout } = await execAsync(command) const logs = parseFirewallLogs(stdout) return NextResponse.json({ success: true, data: { logs, total: logs.length, type: 'firewall' } }) } catch (error: any) { return NextResponse.json({ success: false, error: `Failed to get firewall logs: ${error.message}` }, { status: 500 }) } } async function getLfdLogs(limit: number, since?: string) { try { let command = `grep "lfd" /var/log/lfd.log 2>/dev/null | tail -${limit} || echo ""` if (since) { const sinceDate = new Date(since).toISOString().split('T')[0] command = `grep "lfd" /var/log/lfd.log 2>/dev/null | grep "${sinceDate}" | tail -${limit} || echo ""` } const { stdout } = await execAsync(command) const logs = parseLfdLogs(stdout) return NextResponse.json({ success: true, data: { logs, total: logs.length, type: 'lfd' } }) } catch (error: any) { return NextResponse.json({ success: false, error: `Failed to get LFD logs: ${error.message}` }, { status: 500 }) } } async function getSystemLogs(limit: number, since?: string) { try { let command = `grep "kernel\\|iptables" /var/log/syslog | tail -${limit}` if (since) { const sinceDate = new Date(since).toISOString().split('T')[0] command = `grep "kernel\\|iptables" /var/log/syslog | grep "${sinceDate}" | tail -${limit}` } const { stdout } = await execAsync(command) const logs = parseSystemLogs(stdout) return NextResponse.json({ success: true, data: { logs, total: logs.length, type: 'system' } }) } catch (error: any) { return NextResponse.json({ success: false, error: `Failed to get system logs: ${error.message}` }, { status: 500 }) } } async function getBlockedIPs(limit: number) { try { // Get current blocked IPs from iptables const { stdout } = await execAsync('/usr/local/csf/bin/csf --status | grep DROP | head -' + limit) const blockedIPs = parseBlockedIPs(stdout) return NextResponse.json({ success: true, data: { blocked_ips: blockedIPs, total: blockedIPs.length, type: 'blocked' } }) } catch (error: any) { return NextResponse.json({ success: false, error: `Failed to get blocked IPs: ${error.message}` }, { status: 500 }) } } async function getActiveConnections() { try { // Get active network connections const { stdout } = await execAsync('netstat -tn | grep ESTABLISHED | wc -l') const activeConnections = parseInt(stdout.trim()) || 0 // Get connection details const { stdout: connections } = await execAsync('netstat -tn | grep ESTABLISHED | head -20') const connectionList = parseConnections(connections) return NextResponse.json({ success: true, data: { active_connections: activeConnections, connections: connectionList, type: 'connections' } }) } catch (error: any) { return NextResponse.json({ success: false, error: `Failed to get active connections: ${error.message}` }, { status: 500 }) } } async function getAllLogs(limit: number, since?: string) { try { const [firewallResult, lfdResult, systemResult] = await Promise.allSettled([ getFirewallLogs(Math.floor(limit / 3), since), getLfdLogs(Math.floor(limit / 3), since), getSystemLogs(Math.floor(limit / 3), since) ]) const allLogs = [] if (firewallResult.status === 'fulfilled') { const response = await firewallResult.value.json() if (response.success) allLogs.push(...response.data.logs) } if (lfdResult.status === 'fulfilled') { const response = await lfdResult.value.json() if (response.success) allLogs.push(...response.data.logs) } if (systemResult.status === 'fulfilled') { const response = await systemResult.value.json() if (response.success) allLogs.push(...response.data.logs) } // Sort by timestamp allLogs.sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime()) return NextResponse.json({ success: true, data: { logs: allLogs.slice(0, limit), total: allLogs.length, type: 'all' } }) } catch (error: any) { return NextResponse.json({ success: false, error: `Failed to get all logs: ${error.message}` }, { status: 500 }) } } // Parsing functions function parseFirewallLogs(output: string) { const logs = [] const lines = output.split('\\n').filter(line => line.trim()) for (let i = 0; i < lines.length; i++) { const line = lines[i] const logEntry = parseLogLine(line, 'firewall') if (logEntry) logs.push(logEntry) } return logs } function parseLfdLogs(output: string) { const logs = [] const lines = output.split('\\n').filter(line => line.trim()) for (let i = 0; i < lines.length; i++) { const line = lines[i] const logEntry = parseLogLine(line, 'lfd') if (logEntry) logs.push(logEntry) } return logs } function parseSystemLogs(output: string) { const logs = [] const lines = output.split('\\n').filter(line => line.trim()) for (let i = 0; i < lines.length; i++) { const line = lines[i] const logEntry = parseLogLine(line, 'system') if (logEntry) logs.push(logEntry) } return logs } function parseLogLine(line: string, type: string) { // Basic log parsing - adjust regex patterns based on actual log format const patterns = { timestamp: /^(\\w{3}\\s+\\d{1,2}\\s+\\d{2}:\\d{2}:\\d{2})/, ip: /(\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3})/, port: /DPT=(\\d+)/, protocol: /(TCP|UDP|ICMP)/i, action: /(BLOCK|DROP|ACCEPT|ALLOW|DENY)/i } const timestampMatch = line.match(patterns.timestamp) const ipMatch = line.match(patterns.ip) const portMatch = line.match(patterns.port) const protocolMatch = line.match(patterns.protocol) const actionMatch = line.match(patterns.action) if (!timestampMatch) return null const currentYear = new Date().getFullYear() const timestamp = new Date(`${currentYear} ${timestampMatch[1]}`).toISOString() return { id: `${type}-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`, timestamp, level: actionMatch && (actionMatch[1].toLowerCase() === 'block' || actionMatch[1].toLowerCase() === 'drop') ? 'block' : 'info', message: line, ip: ipMatch ? ipMatch[1] : undefined, port: portMatch ? portMatch[1] : undefined, protocol: protocolMatch ? protocolMatch[1].toUpperCase() : undefined, action: actionMatch ? actionMatch[1].toUpperCase() : undefined, type } } function parseBlockedIPs(output: string) { const blockedIPs = [] const lines = output.split('\\n').filter(line => line.trim()) for (const line of lines) { const ipMatch = line.match(/(\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3})/) if (ipMatch) { blockedIPs.push({ ip: ipMatch[1], reason: 'Firewall rule', timestamp: new Date().toISOString() }) } } return blockedIPs } function parseConnections(output: string) { const connections = [] const lines = output.split('\\n').filter(line => line.trim()) for (const line of lines) { const parts = line.trim().split(/\\s+/) if (parts.length >= 4) { const [protocol, , , localAddress, foreignAddress] = parts connections.push({ protocol, local_address: localAddress, foreign_address: foreignAddress, state: 'ESTABLISHED' }) } } return connections }