Securing CloudPanel on Ubuntu 24.04 Part 9

20/11/2024 20/11/2024 security 5 mins read
Table Of Contents

Part 9: Comprehensive Security Auditing and Performance Monitoring #

Let’s create an integrated monitoring and auditing system:

Terminal window
# Create comprehensive monitoring script
sudo nano /usr/local/bin/cloudpanel-security-monitor.sh

#

#!/bin/bash
# Initialize paths and configuration
CP_HOME="/home/clp"
DB_PATH="${CP_HOME}/htdocs/app/data/db.sq3"
LOG_DIR="${CP_HOME}/logs/monitoring"
AUDIT_DIR="${CP_HOME}/logs/audit"
# Create necessary directories
mkdir -p "$LOG_DIR" "$AUDIT_DIR"
# Function to record system metrics in CloudPanel's database
record_system_metrics() {
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
# Record CPU usage
local cpu_usage=$(top -bn1 | grep "Cpu(s)" | awk '{print $2}')
sqlite3 "$DB_PATH" "
INSERT INTO instance_cpu (created_at, value)
VALUES ('$timestamp', $cpu_usage);"
# Record memory usage
local memory_usage=$(free | grep Mem | awk '{print ($3/$2 * 100)}')
sqlite3 "$DB_PATH" "
INSERT INTO instance_memory (created_at, value)
VALUES ('$timestamp', $memory_usage);"
# Record load averages
local load_1min=$(uptime | awk '{print $(NF-2)}' | tr -d ',')
local load_5min=$(uptime | awk '{print $(NF-1)}' | tr -d ',')
local load_15min=$(uptime | awk '{print $NF}')
sqlite3 "$DB_PATH" "
INSERT INTO instance_load_average (created_at, period, value)
VALUES
('$timestamp', 1, $load_1min),
('$timestamp', 5, $load_5min),
('$timestamp', 15, $load_15min);"
# Record disk usage for each mount point
df -P | grep '^/' | while read filesystem size used avail use mountpoint; do
sqlite3 "$DB_PATH" "
INSERT INTO instance_disk_usage (created_at, disk, value)
VALUES ('$timestamp', '$mountpoint', ${use%\%});"
done
}
# Function to analyze security events from CloudPanel's event table
analyze_security_events() {
echo "Analyzing security events..."
# Get recent security events
sqlite3 "$DB_PATH" "
SELECT
created_at,
user_name,
user_role,
event_name,
event_data,
source_ip_address,
user_agent
FROM event
WHERE created_at > datetime('now', '-1 hour')
ORDER BY created_at DESC;" | while IFS='|' read -r timestamp username role event_name data ip agent; do
# Analyze for suspicious patterns
case "$event_name" in
"login_failed")
check_brute_force_attempts "$username" "$ip"
;;
"file_modified")
verify_file_changes "$data"
;;
"config_changed")
audit_configuration_change "$username" "$data"
;;
esac
done
}
# Function to check for brute force attempts
check_brute_force_attempts() {
local username="$1"
local ip="$2"
# Count recent failed login attempts
local failed_attempts=$(sqlite3 "$DB_PATH" "
SELECT COUNT(*) FROM event
WHERE event_name = 'login_failed'
AND source_ip_address = '$ip'
AND created_at > datetime('now', '-1 hour');")
if [ "$failed_attempts" -gt 5 ]; then
# Log the security incident
log_security_incident "Possible brute force attack" \
"Multiple failed login attempts from IP: $ip targeting user: $username"
# Block the IP address through CloudPanel's firewall
sqlite3 "$DB_PATH" "
INSERT INTO blocked_ip (
site_id,
created_at,
updated_at,
ip
) VALUES (
NULL,
datetime('now'),
datetime('now'),
'$ip'
);"
fi
}
# Function to verify file changes
verify_file_changes() {
local file_data="$1"
# Extract file path from event data
local file_path=$(echo "$file_data" | jq -r '.path')
if [ -f "$file_path" ]; then
# Calculate current file hash
local current_hash=$(sha256sum "$file_path" | cut -d' ' -f1)
# Compare with expected hash if available
if [ -f "${file_path}.hash" ]; then
local expected_hash=$(cat "${file_path}.hash")
if [ "$current_hash" != "$expected_hash" ]; then
log_security_incident "Unexpected file modification" \
"File $file_path has been modified unexpectedly"
fi
else
# Store initial hash for future comparison
echo "$current_hash" > "${file_path}.hash"
fi
fi
}
# Function to audit configuration changes
audit_configuration_change() {
local username="$1"
local config_data="$2"
# Log the configuration change
echo "[$(date '+%Y-%m-%d %H:%M:%S')] User $username modified configuration: $config_data" >> "$AUDIT_DIR/config_changes.log"
# Store in CloudPanel's event system
sqlite3 "$DB_PATH" "
INSERT INTO event (
created_at,
user_name,
user_role,
event_name,
event_data
) VALUES (
datetime('now'),
'$username',
(SELECT role FROM user WHERE user_name = '$username'),
'config_audit',
'$config_data'
);"
}
# Function to generate security reports
generate_security_report() {
local report_file="$AUDIT_DIR/security_report_$(date +%Y%m%d).txt"
echo "CloudPanel Security Audit Report - $(date)" > "$report_file"
echo "==========================================" >> "$report_file"
# System Metrics Summary
echo "System Performance Metrics:" >> "$report_file"
sqlite3 "$DB_PATH" "
SELECT
avg(value) as avg_cpu,
max(value) as max_cpu
FROM instance_cpu
WHERE created_at > datetime('now', '-24 hours');" >> "$report_file"
# Security Events Summary
echo -e "\nSecurity Events Summary:" >> "$report_file"
sqlite3 "$DB_PATH" "
SELECT
event_name,
COUNT(*) as event_count
FROM event
WHERE created_at > datetime('now', '-24 hours')
GROUP BY event_name;" >> "$report_file"
# Failed Login Attempts
echo -e "\nFailed Login Attempts:" >> "$report_file"
sqlite3 "$DB_PATH" "
SELECT
source_ip_address,
COUNT(*) as attempt_count
FROM event
WHERE event_name = 'login_failed'
AND created_at > datetime('now', '-24 hours')
GROUP BY source_ip_address
HAVING attempt_count > 3;" >> "$report_file"
}
# Main execution loop
main() {
echo "Starting security monitoring system..."
while true; do
# Record system metrics
record_system_metrics
# Analyze security events
analyze_security_events
# Generate daily report at midnight
if [ "$(date +%H:%M)" = "00:00" ]; then
generate_security_report
fi
# Sleep for monitoring interval
sleep 300
done
}
main "$@"

This monitoring system provides:

  1. Comprehensive system metrics tracking using CloudPanel’s database structure
  2. Security event analysis and correlation
  3. Automated threat detection and response
  4. Configuration change auditing
  5. Daily security reports
  6. Integration with CloudPanel’s event logging system