diff --git a/src/app/api/auth/route.ts b/src/app/api/auth/route.ts index 85c922e..af435f3 100644 --- a/src/app/api/auth/route.ts +++ b/src/app/api/auth/route.ts @@ -2,13 +2,18 @@ import { NextRequest, NextResponse } from 'next/server' import { sign, verify } from 'jsonwebtoken' const JWT_SECRET = process.env.JWT_SECRET || 'csf-admin-secret-key-change-this-in-production' +const JWT_EXPIRES_IN = process.env.JWT_EXPIRES_IN || '24h' -// Simple user store - in production, use a database +// Get admin credentials from environment variables +const ADMIN_USERNAME = process.env.ADMIN_USERNAME || 'admin' +const ADMIN_PASSWORD = process.env.ADMIN_PASSWORD || 'admin123' + +// Simple user store - credentials from environment variables const ADMIN_USERS = [ { id: '1', - username: 'admin', - password: 'admin123', // In production, use hashed passwords + username: ADMIN_USERNAME, + password: ADMIN_PASSWORD, // In production, use hashed passwords role: 'admin', permissions: ['all'] } @@ -36,16 +41,16 @@ export async function POST(request: NextRequest) { } // Generate JWT token - const token = sign( - { - userId: user.id, - username: user.username, - role: user.role, - permissions: user.permissions - }, - JWT_SECRET, - { expiresIn: '24h' } - ) + const tokenPayload = { + userId: user.id, + username: user.username, + role: user.role, + permissions: user.permissions + } + + const token = sign(tokenPayload, JWT_SECRET, { + expiresIn: JWT_EXPIRES_IN as string + } as any) // Create response with token in httpOnly cookie const response = NextResponse.json({ @@ -60,11 +65,16 @@ export async function POST(request: NextRequest) { } }) + // Calculate maxAge based on JWT_EXPIRES_IN + const maxAge = JWT_EXPIRES_IN.includes('h') + ? parseInt(JWT_EXPIRES_IN.replace('h', '')) * 60 * 60 + : 24 * 60 * 60 // Default 24 hours + response.cookies.set('auth-token', token, { httpOnly: true, secure: process.env.NODE_ENV === 'production', sameSite: 'lax', - maxAge: 24 * 60 * 60 // 24 hours + maxAge }) return response diff --git a/src/app/api/config/route.ts b/src/app/api/config/route.ts index a3a90f8..d7d0185 100644 --- a/src/app/api/config/route.ts +++ b/src/app/api/config/route.ts @@ -1,9 +1,9 @@ import { NextRequest, NextResponse } from 'next/server' -import fs from 'fs/promises' -import path from 'path' +import { promises as fs } from 'fs' +import { join } from 'path' -const CSF_CONFIG_PATH = '/etc/csf' -const CSF_CONF_FILE = path.join(CSF_CONFIG_PATH, 'csf.conf') +const CSF_CONFIG_PATH = process.env.CSF_CONFIG_PATH || '/etc/csf' +const CSF_CONF_FILE = join(CSF_CONFIG_PATH, 'csf.conf') interface CSFConfigValue { key: string diff --git a/src/app/api/csf/route.ts b/src/app/api/csf/route.ts index 57acf0d..47b7584 100644 --- a/src/app/api/csf/route.ts +++ b/src/app/api/csf/route.ts @@ -1,12 +1,12 @@ import { NextRequest, NextResponse } from 'next/server' import { exec } from 'child_process' import { promisify } from 'util' +import path from 'path' const execAsync = promisify(exec) -// CSF command paths - adjust based on actual CSF installation -const CSF_PATH = '/usr/local/csf/bin/csf' -const CSF_CONFIG_PATH = '/etc/csf' +const CSF_PATH = process.env.CSF_BIN_PATH ? path.join(process.env.CSF_BIN_PATH, 'csf') : '/usr/local/csf/bin/csf' +const CSF_CONFIG_PATH = process.env.CSF_CONFIG_PATH || '/etc/csf' interface CSFCommandResult { success: boolean diff --git a/src/app/api/rules/route.ts b/src/app/api/rules/route.ts index e26b23e..1d8300f 100644 --- a/src/app/api/rules/route.ts +++ b/src/app/api/rules/route.ts @@ -7,7 +7,8 @@ import path from 'path' const execAsync = promisify(exec) // CSF configuration paths -const CSF_CONFIG_PATH = '/etc/csf' +const CSF_CONFIG_PATH = process.env.CSF_CONFIG_PATH || '/etc/csf' +const CSF_BIN_PATH = process.env.CSF_BIN_PATH || '/usr/local/csf/bin' const CSF_CONF_FILE = path.join(CSF_CONFIG_PATH, 'csf.conf') const CSF_ALLOW_FILE = path.join(CSF_CONFIG_PATH, 'csf.allow') const CSF_DENY_FILE = path.join(CSF_CONFIG_PATH, 'csf.deny') @@ -36,7 +37,7 @@ export async function GET(request: NextRequest) { case 'temp': // Get temporary bans from CSF - const { stdout } = await execAsync('/usr/local/csf/bin/csf --temp') + const { stdout } = await execAsync(`${CSF_BIN_PATH}/csf --temp`) const tempRules = parseTempRules(stdout) return NextResponse.json({ success: true, @@ -141,11 +142,11 @@ export async function POST(request: NextRequest) { } // Execute the CSF command - const fullCommand = `/usr/local/csf/bin/csf ${command} ${args.join(' ')}` + const fullCommand = `${CSF_BIN_PATH}/csf ${command} ${args.join(' ')}` const { stdout, stderr } = await execAsync(fullCommand, { timeout: 15000 }) // Restart CSF to apply changes - await execAsync('/usr/local/csf/bin/csf --restart', { timeout: 30000 }) + await execAsync(`${CSF_BIN_PATH}/csf --restart`, { timeout: 30000 }) return NextResponse.json({ success: true, @@ -179,12 +180,12 @@ export async function DELETE(request: NextRequest) { try { const command = type === 'allow' ? '--allowrm' : '--denyrm' - const fullCommand = `/usr/local/csf/bin/csf ${command} ${ip}` + const fullCommand = `${CSF_BIN_PATH}/csf ${command} ${ip}` const { stdout } = await execAsync(fullCommand, { timeout: 15000 }) // Restart CSF to apply changes - await execAsync('/usr/local/csf/bin/csf --restart', { timeout: 30000 }) + await execAsync(`${CSF_BIN_PATH}/csf --restart`, { timeout: 30000 }) return NextResponse.json({ success: true, diff --git a/src/app/api/stats/route.ts b/src/app/api/stats/route.ts index c616b3b..083b833 100644 --- a/src/app/api/stats/route.ts +++ b/src/app/api/stats/route.ts @@ -5,6 +5,10 @@ import fs from 'fs/promises' const execAsync = promisify(exec) +// CSF configuration from environment variables +const CSF_CONFIG_PATH = process.env.CSF_CONFIG_PATH || '/etc/csf' +const CSF_BIN_PATH = process.env.CSF_BIN_PATH || '/usr/local/csf/bin' + export async function GET() { try { // Get server statistics @@ -134,7 +138,7 @@ async function getCSFStats(): Promise<{ // Check CSF status let status = 'unknown' try { - await execAsync('/usr/local/csf/bin/csf --status >/dev/null 2>&1') + await execAsync(`${CSF_BIN_PATH}/csf --status >/dev/null 2>&1`) status = 'active' } catch { status = 'inactive' @@ -146,21 +150,21 @@ async function getCSFStats(): Promise<{ let tempBlocks = 0 try { - const denyContent = await fs.readFile('/etc/csf/csf.deny', 'utf-8') + const denyContent = await fs.readFile(`${CSF_CONFIG_PATH}/csf.deny`, 'utf-8') blockedIps = denyContent.split('\\n').filter(line => line.trim() && !line.trim().startsWith('#') ).length } catch {} try { - const allowContent = await fs.readFile('/etc/csf/csf.allow', 'utf-8') + const allowContent = await fs.readFile(`${CSF_CONFIG_PATH}/csf.allow`, 'utf-8') allowedIps = allowContent.split('\\n').filter(line => line.trim() && !line.trim().startsWith('#') ).length } catch {} try { - const { stdout } = await execAsync('/usr/local/csf/bin/csf --temp 2>/dev/null | grep -c "Temporary" || echo "0"') + const { stdout } = await execAsync(`${CSF_BIN_PATH}/csf --temp 2>/dev/null | grep -c "Temporary" || echo "0"`) tempBlocks = parseInt(stdout.trim()) || 0 } catch {} diff --git a/src/pages/api/socket.ts b/src/pages/api/socket.ts index 484c570..91771f4 100644 --- a/src/pages/api/socket.ts +++ b/src/pages/api/socket.ts @@ -7,6 +7,10 @@ import fs from 'fs/promises' const execAsync = promisify(exec) +// CSF configuration from environment variables +const CSF_CONFIG_PATH = process.env.CSF_CONFIG_PATH || '/etc/csf' +const CSF_LOG_PATH = process.env.CSF_LOG_PATH || '/var/log' + // Configuración del servidor Socket.IO let io: SocketIOServer | null = null @@ -74,14 +78,14 @@ async function getSystemStats(): Promise { let allowedIps = 0 try { - const denyContent = await fs.readFile('/etc/csf/csf.deny', 'utf-8') + const denyContent = await fs.readFile(`${CSF_CONFIG_PATH}/csf.deny`, 'utf-8') blockedIps = denyContent.split('\n').filter(line => line.trim() && !line.trim().startsWith('#') ).length } catch {} try { - const allowContent = await fs.readFile('/etc/csf/csf.allow', 'utf-8') + const allowContent = await fs.readFile(`${CSF_CONFIG_PATH}/csf.allow`, 'utf-8') allowedIps = allowContent.split('\n').filter(line => line.trim() && !line.trim().startsWith('#') ).length @@ -121,7 +125,7 @@ async function getSystemStats(): Promise { // Función para obtener logs recientes async function getRecentLogs(limit: number = 50): Promise { try { - const { stdout } = await execAsync(`tail -${limit} /var/log/syslog | grep -E "(CSF|iptables|lfd)" || echo ""`) + const { stdout } = await execAsync(`tail -${limit} ${CSF_LOG_PATH}/syslog | grep -E "(CSF|iptables|lfd)" || echo ""`) const logs: LogEntry[] = [] const lines = stdout.split('\n').filter(line => line.trim())