@@ -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(
|
||||
{
|
||||
const tokenPayload = {
|
||||
userId: user.id,
|
||||
username: user.username,
|
||||
role: user.role,
|
||||
permissions: user.permissions
|
||||
},
|
||||
JWT_SECRET,
|
||||
{ expiresIn: '24h' }
|
||||
)
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 {}
|
||||
|
||||
|
||||
@@ -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<CSFStats> {
|
||||
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<CSFStats> {
|
||||
// Función para obtener logs recientes
|
||||
async function getRecentLogs(limit: number = 50): Promise<LogEntry[]> {
|
||||
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())
|
||||
|
||||
Referencia en una nueva incidencia
Block a user