@@ -2,13 +2,18 @@ import { NextRequest, NextResponse } from 'next/server'
|
|||||||
import { sign, verify } from 'jsonwebtoken'
|
import { sign, verify } from 'jsonwebtoken'
|
||||||
|
|
||||||
const JWT_SECRET = process.env.JWT_SECRET || 'csf-admin-secret-key-change-this-in-production'
|
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 = [
|
const ADMIN_USERS = [
|
||||||
{
|
{
|
||||||
id: '1',
|
id: '1',
|
||||||
username: 'admin',
|
username: ADMIN_USERNAME,
|
||||||
password: 'admin123', // In production, use hashed passwords
|
password: ADMIN_PASSWORD, // In production, use hashed passwords
|
||||||
role: 'admin',
|
role: 'admin',
|
||||||
permissions: ['all']
|
permissions: ['all']
|
||||||
}
|
}
|
||||||
@@ -36,16 +41,16 @@ export async function POST(request: NextRequest) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Generate JWT token
|
// Generate JWT token
|
||||||
const token = sign(
|
const tokenPayload = {
|
||||||
{
|
userId: user.id,
|
||||||
userId: user.id,
|
username: user.username,
|
||||||
username: user.username,
|
role: user.role,
|
||||||
role: user.role,
|
permissions: user.permissions
|
||||||
permissions: user.permissions
|
}
|
||||||
},
|
|
||||||
JWT_SECRET,
|
const token = sign(tokenPayload, JWT_SECRET, {
|
||||||
{ expiresIn: '24h' }
|
expiresIn: JWT_EXPIRES_IN as string
|
||||||
)
|
} as any)
|
||||||
|
|
||||||
// Create response with token in httpOnly cookie
|
// Create response with token in httpOnly cookie
|
||||||
const response = NextResponse.json({
|
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, {
|
response.cookies.set('auth-token', token, {
|
||||||
httpOnly: true,
|
httpOnly: true,
|
||||||
secure: process.env.NODE_ENV === 'production',
|
secure: process.env.NODE_ENV === 'production',
|
||||||
sameSite: 'lax',
|
sameSite: 'lax',
|
||||||
maxAge: 24 * 60 * 60 // 24 hours
|
maxAge
|
||||||
})
|
})
|
||||||
|
|
||||||
return response
|
return response
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import { NextRequest, NextResponse } from 'next/server'
|
import { NextRequest, NextResponse } from 'next/server'
|
||||||
import fs from 'fs/promises'
|
import { promises as fs } from 'fs'
|
||||||
import path from 'path'
|
import { join } from 'path'
|
||||||
|
|
||||||
const CSF_CONFIG_PATH = '/etc/csf'
|
const CSF_CONFIG_PATH = process.env.CSF_CONFIG_PATH || '/etc/csf'
|
||||||
const CSF_CONF_FILE = path.join(CSF_CONFIG_PATH, 'csf.conf')
|
const CSF_CONF_FILE = join(CSF_CONFIG_PATH, 'csf.conf')
|
||||||
|
|
||||||
interface CSFConfigValue {
|
interface CSFConfigValue {
|
||||||
key: string
|
key: string
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
import { NextRequest, NextResponse } from 'next/server'
|
import { NextRequest, NextResponse } from 'next/server'
|
||||||
import { exec } from 'child_process'
|
import { exec } from 'child_process'
|
||||||
import { promisify } from 'util'
|
import { promisify } from 'util'
|
||||||
|
import path from 'path'
|
||||||
|
|
||||||
const execAsync = promisify(exec)
|
const execAsync = promisify(exec)
|
||||||
|
|
||||||
// CSF command paths - adjust based on actual CSF installation
|
const CSF_PATH = process.env.CSF_BIN_PATH ? path.join(process.env.CSF_BIN_PATH, 'csf') : '/usr/local/csf/bin/csf'
|
||||||
const CSF_PATH = '/usr/local/csf/bin/csf'
|
const CSF_CONFIG_PATH = process.env.CSF_CONFIG_PATH || '/etc/csf'
|
||||||
const CSF_CONFIG_PATH = '/etc/csf'
|
|
||||||
|
|
||||||
interface CSFCommandResult {
|
interface CSFCommandResult {
|
||||||
success: boolean
|
success: boolean
|
||||||
|
|||||||
@@ -7,7 +7,8 @@ import path from 'path'
|
|||||||
const execAsync = promisify(exec)
|
const execAsync = promisify(exec)
|
||||||
|
|
||||||
// CSF configuration paths
|
// 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_CONF_FILE = path.join(CSF_CONFIG_PATH, 'csf.conf')
|
||||||
const CSF_ALLOW_FILE = path.join(CSF_CONFIG_PATH, 'csf.allow')
|
const CSF_ALLOW_FILE = path.join(CSF_CONFIG_PATH, 'csf.allow')
|
||||||
const CSF_DENY_FILE = path.join(CSF_CONFIG_PATH, 'csf.deny')
|
const CSF_DENY_FILE = path.join(CSF_CONFIG_PATH, 'csf.deny')
|
||||||
@@ -36,7 +37,7 @@ export async function GET(request: NextRequest) {
|
|||||||
|
|
||||||
case 'temp':
|
case 'temp':
|
||||||
// Get temporary bans from CSF
|
// 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)
|
const tempRules = parseTempRules(stdout)
|
||||||
return NextResponse.json({
|
return NextResponse.json({
|
||||||
success: true,
|
success: true,
|
||||||
@@ -141,11 +142,11 @@ export async function POST(request: NextRequest) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Execute the CSF command
|
// 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 })
|
const { stdout, stderr } = await execAsync(fullCommand, { timeout: 15000 })
|
||||||
|
|
||||||
// Restart CSF to apply changes
|
// 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({
|
return NextResponse.json({
|
||||||
success: true,
|
success: true,
|
||||||
@@ -179,12 +180,12 @@ export async function DELETE(request: NextRequest) {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const command = type === 'allow' ? '--allowrm' : '--denyrm'
|
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 })
|
const { stdout } = await execAsync(fullCommand, { timeout: 15000 })
|
||||||
|
|
||||||
// Restart CSF to apply changes
|
// 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({
|
return NextResponse.json({
|
||||||
success: true,
|
success: true,
|
||||||
|
|||||||
@@ -5,6 +5,10 @@ import fs from 'fs/promises'
|
|||||||
|
|
||||||
const execAsync = promisify(exec)
|
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() {
|
export async function GET() {
|
||||||
try {
|
try {
|
||||||
// Get server statistics
|
// Get server statistics
|
||||||
@@ -134,7 +138,7 @@ async function getCSFStats(): Promise<{
|
|||||||
// Check CSF status
|
// Check CSF status
|
||||||
let status = 'unknown'
|
let status = 'unknown'
|
||||||
try {
|
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'
|
status = 'active'
|
||||||
} catch {
|
} catch {
|
||||||
status = 'inactive'
|
status = 'inactive'
|
||||||
@@ -146,21 +150,21 @@ async function getCSFStats(): Promise<{
|
|||||||
let tempBlocks = 0
|
let tempBlocks = 0
|
||||||
|
|
||||||
try {
|
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 =>
|
blockedIps = denyContent.split('\\n').filter(line =>
|
||||||
line.trim() && !line.trim().startsWith('#')
|
line.trim() && !line.trim().startsWith('#')
|
||||||
).length
|
).length
|
||||||
} catch {}
|
} catch {}
|
||||||
|
|
||||||
try {
|
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 =>
|
allowedIps = allowContent.split('\\n').filter(line =>
|
||||||
line.trim() && !line.trim().startsWith('#')
|
line.trim() && !line.trim().startsWith('#')
|
||||||
).length
|
).length
|
||||||
} catch {}
|
} catch {}
|
||||||
|
|
||||||
try {
|
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
|
tempBlocks = parseInt(stdout.trim()) || 0
|
||||||
} catch {}
|
} catch {}
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,10 @@ import fs from 'fs/promises'
|
|||||||
|
|
||||||
const execAsync = promisify(exec)
|
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
|
// Configuración del servidor Socket.IO
|
||||||
let io: SocketIOServer | null = null
|
let io: SocketIOServer | null = null
|
||||||
|
|
||||||
@@ -74,14 +78,14 @@ async function getSystemStats(): Promise<CSFStats> {
|
|||||||
let allowedIps = 0
|
let allowedIps = 0
|
||||||
|
|
||||||
try {
|
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 =>
|
blockedIps = denyContent.split('\n').filter(line =>
|
||||||
line.trim() && !line.trim().startsWith('#')
|
line.trim() && !line.trim().startsWith('#')
|
||||||
).length
|
).length
|
||||||
} catch {}
|
} catch {}
|
||||||
|
|
||||||
try {
|
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 =>
|
allowedIps = allowContent.split('\n').filter(line =>
|
||||||
line.trim() && !line.trim().startsWith('#')
|
line.trim() && !line.trim().startsWith('#')
|
||||||
).length
|
).length
|
||||||
@@ -121,7 +125,7 @@ async function getSystemStats(): Promise<CSFStats> {
|
|||||||
// Función para obtener logs recientes
|
// Función para obtener logs recientes
|
||||||
async function getRecentLogs(limit: number = 50): Promise<LogEntry[]> {
|
async function getRecentLogs(limit: number = 50): Promise<LogEntry[]> {
|
||||||
try {
|
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 logs: LogEntry[] = []
|
||||||
const lines = stdout.split('\n').filter(line => line.trim())
|
const lines = stdout.split('\n').filter(line => line.trim())
|
||||||
|
|||||||
Referencia en una nueva incidencia
Block a user