464 lines
17 KiB
Bash
464 lines
17 KiB
Bash
#!/bin/bash
|
||
# ════════════════════════════════════════════════════════════════
|
||
# 🔍 TRIPZ FORTRESS v8.2 - Comprehensive System Check
|
||
# ════════════════════════════════════════════════════════════════
|
||
# استخدم هذا السكريبت لفحص حالة النظام الأمني بالكامل
|
||
# ════════════════════════════════════════════════════════════════
|
||
|
||
set -euo pipefail
|
||
|
||
# Colors
|
||
RED='\033[0;31m'
|
||
GREEN='\033[0;32m'
|
||
YELLOW='\033[1;33m'
|
||
BLUE='\033[0;34m'
|
||
CYAN='\033[0;36m'
|
||
NC='\033[0m'
|
||
|
||
# Counters
|
||
TOTAL_CHECKS=0
|
||
PASSED_CHECKS=0
|
||
FAILED_CHECKS=0
|
||
WARNING_CHECKS=0
|
||
|
||
# Functions
|
||
check_pass() {
|
||
echo -e "${GREEN}✅ $1${NC}"
|
||
((PASSED_CHECKS++))
|
||
((TOTAL_CHECKS++))
|
||
}
|
||
|
||
check_fail() {
|
||
echo -e "${RED}❌ $1${NC}"
|
||
((FAILED_CHECKS++))
|
||
((TOTAL_CHECKS++))
|
||
}
|
||
|
||
check_warn() {
|
||
echo -e "${YELLOW}⚠️ $1${NC}"
|
||
((WARNING_CHECKS++))
|
||
((TOTAL_CHECKS++))
|
||
}
|
||
|
||
info() {
|
||
echo -e "${CYAN}ℹ️ $1${NC}"
|
||
}
|
||
|
||
section() {
|
||
echo ""
|
||
echo -e "${BLUE}════════════════════════════════════════════════════════${NC}"
|
||
echo -e "${BLUE}$1${NC}"
|
||
echo -e "${BLUE}════════════════════════════════════════════════════════${NC}"
|
||
}
|
||
|
||
# Main
|
||
clear
|
||
|
||
cat <<'BANNER'
|
||
════════════════════════════════════════════════════════════════
|
||
🔍 TRIPZ FORTRESS v8.2 - System Health Check
|
||
════════════════════════════════════════════════════════════════
|
||
BANNER
|
||
|
||
echo ""
|
||
info "Starting comprehensive system check..."
|
||
info "Date: $(date '+%Y-%m-%d %H:%M:%S')"
|
||
info "Hostname: $(hostname)"
|
||
echo ""
|
||
|
||
# ════════════════════════════════════════════════════════════════
|
||
# 1. BASIC SYSTEM INFO
|
||
# ════════════════════════════════════════════════════════════════
|
||
|
||
section "1️⃣ BASIC SYSTEM INFORMATION"
|
||
|
||
# OS Info
|
||
if [ -f /etc/os-release ]; then
|
||
OS_NAME=$(grep PRETTY_NAME /etc/os-release | cut -d'"' -f2)
|
||
info "Operating System: $OS_NAME"
|
||
check_pass "OS detected"
|
||
else
|
||
check_fail "Cannot detect OS"
|
||
fi
|
||
|
||
# Kernel
|
||
KERNEL=$(uname -r)
|
||
info "Kernel: $KERNEL"
|
||
check_pass "Kernel detected"
|
||
|
||
# Uptime
|
||
UPTIME=$(uptime -p)
|
||
info "Uptime: $UPTIME"
|
||
|
||
# Resources
|
||
MEMORY_TOTAL=$(free -h | awk '/^Mem:/ {print $2}')
|
||
MEMORY_USED=$(free -h | awk '/^Mem:/ {print $3}')
|
||
MEMORY_PERCENT=$(free | awk '/^Mem:/ {printf "%.0f", $3/$2 * 100}')
|
||
|
||
info "Memory: $MEMORY_USED / $MEMORY_TOTAL (${MEMORY_PERCENT}%)"
|
||
|
||
if [ "$MEMORY_PERCENT" -lt 80 ]; then
|
||
check_pass "Memory usage OK"
|
||
elif [ "$MEMORY_PERCENT" -lt 90 ]; then
|
||
check_warn "Memory usage high: ${MEMORY_PERCENT}%"
|
||
else
|
||
check_fail "Memory usage critical: ${MEMORY_PERCENT}%"
|
||
fi
|
||
|
||
DISK_USAGE=$(df -h / | awk 'NR==2 {print $5}' | sed 's/%//')
|
||
DISK_USED=$(df -h / | awk 'NR==2 {print $3}')
|
||
DISK_TOTAL=$(df -h / | awk 'NR==2 {print $2}')
|
||
|
||
info "Disk: $DISK_USED / $DISK_TOTAL (${DISK_USAGE}%)"
|
||
|
||
if [ "$DISK_USAGE" -lt 80 ]; then
|
||
check_pass "Disk usage OK"
|
||
elif [ "$DISK_USAGE" -lt 90 ]; then
|
||
check_warn "Disk usage high: ${DISK_USAGE}%"
|
||
else
|
||
check_fail "Disk usage critical: ${DISK_USAGE}%"
|
||
fi
|
||
|
||
# ════════════════════════════════════════════════════════════════
|
||
# 2. NETWORK CONNECTIVITY
|
||
# ════════════════════════════════════════════════════════════════
|
||
|
||
section "2️⃣ NETWORK CONNECTIVITY"
|
||
|
||
# Internet
|
||
if ping -c 2 8.8.8.8 &>/dev/null; then
|
||
check_pass "Internet connectivity"
|
||
else
|
||
check_fail "No internet connection"
|
||
fi
|
||
|
||
# DNS
|
||
if ping -c 2 google.com &>/dev/null; then
|
||
check_pass "DNS resolution"
|
||
else
|
||
check_fail "DNS resolution failed"
|
||
fi
|
||
|
||
# External IP
|
||
EXTERNAL_IP=$(curl -s ifconfig.me 2>/dev/null || echo "unknown")
|
||
info "External IP: $EXTERNAL_IP"
|
||
|
||
# ════════════════════════════════════════════════════════════════
|
||
# 3. SECURITY SERVICES
|
||
# ════════════════════════════════════════════════════════════════
|
||
|
||
section "3️⃣ SECURITY SERVICES"
|
||
|
||
# SSH
|
||
if systemctl is-active --quiet sshd; then
|
||
check_pass "SSH (sshd) active"
|
||
|
||
# SSH Config
|
||
SSH_PORT=$(grep -E "^Port " /etc/ssh/sshd_config | awk '{print $2}' || echo "22")
|
||
info "SSH Port: $SSH_PORT"
|
||
|
||
if [ "$SSH_PORT" != "22" ]; then
|
||
check_pass "SSH port changed from default"
|
||
else
|
||
check_warn "SSH still on default port 22"
|
||
fi
|
||
|
||
# Password Authentication
|
||
if grep -q "^PasswordAuthentication no" /etc/ssh/sshd_config; then
|
||
check_pass "Password authentication disabled"
|
||
else
|
||
check_warn "Password authentication enabled"
|
||
fi
|
||
|
||
# Root Login
|
||
if grep -q "^PermitRootLogin no" /etc/ssh/sshd_config; then
|
||
check_pass "Root login disabled"
|
||
else
|
||
check_warn "Root login enabled"
|
||
fi
|
||
else
|
||
check_fail "SSH (sshd) not running"
|
||
fi
|
||
|
||
# UFW
|
||
if systemctl is-active --quiet ufw; then
|
||
check_pass "UFW firewall active"
|
||
|
||
UFW_STATUS=$(ufw status | head -1 | awk '{print $2}')
|
||
if [ "$UFW_STATUS" == "active" ]; then
|
||
check_pass "UFW enabled"
|
||
else
|
||
check_fail "UFW not enabled"
|
||
fi
|
||
else
|
||
check_fail "UFW not installed/running"
|
||
fi
|
||
|
||
# Fail2Ban
|
||
if systemctl is-active --quiet fail2ban 2>/dev/null; then
|
||
check_pass "Fail2Ban active"
|
||
|
||
# Banned IPs
|
||
if command -v fail2ban-client &>/dev/null; then
|
||
BANNED_COUNT=$(fail2ban-client status sshd 2>/dev/null | grep "Currently banned:" | awk '{print $4}' || echo "0")
|
||
info "Currently banned IPs: $BANNED_COUNT"
|
||
fi
|
||
else
|
||
check_warn "Fail2Ban not active (optional but recommended)"
|
||
fi
|
||
|
||
# Knockd (Port Knocking)
|
||
if systemctl is-active --quiet knockd 2>/dev/null; then
|
||
check_pass "Port Knocking (knockd) active"
|
||
|
||
if [ -f /etc/knockd.conf ]; then
|
||
KNOCK_SEQ=$(grep -A 1 "\[openSSH\]" /etc/knockd.conf | grep sequence | awk '{print $3}')
|
||
info "Knock sequence: $KNOCK_SEQ"
|
||
fi
|
||
else
|
||
check_warn "Port Knocking not active (optional)"
|
||
fi
|
||
|
||
# Endlessh (Honeypot)
|
||
if systemctl is-active --quiet endlessh 2>/dev/null; then
|
||
check_pass "Endlessh honeypot active"
|
||
else
|
||
check_warn "Endlessh honeypot not active (optional)"
|
||
fi
|
||
|
||
# Fake MySQL
|
||
if systemctl is-active --quiet fake-mysql 2>/dev/null; then
|
||
check_pass "Fake MySQL trap active"
|
||
else
|
||
check_warn "Fake MySQL trap not active (optional)"
|
||
fi
|
||
|
||
# ════════════════════════════════════════════════════════════════
|
||
# 4. SYSTEM HARDENING
|
||
# ════════════════════════════════════════════════════════════════
|
||
|
||
section "4️⃣ SYSTEM HARDENING"
|
||
|
||
# sysctl checks
|
||
if grep -q "net.ipv4.tcp_syncookies = 1" /etc/sysctl.conf; then
|
||
check_pass "SYN flood protection enabled"
|
||
else
|
||
check_warn "SYN flood protection not configured"
|
||
fi
|
||
|
||
if grep -q "net.ipv4.conf.all.rp_filter = 1" /etc/sysctl.conf; then
|
||
check_pass "Reverse path filtering enabled"
|
||
else
|
||
check_warn "Reverse path filtering not configured"
|
||
fi
|
||
|
||
if grep -q "kernel.kptr_restrict = 2" /etc/sysctl.conf; then
|
||
check_pass "Kernel pointer protection enabled"
|
||
else
|
||
check_warn "Kernel pointer protection not configured"
|
||
fi
|
||
|
||
# ════════════════════════════════════════════════════════════════
|
||
# 5. USERS & AUTHENTICATION
|
||
# ════════════════════════════════════════════════════════════════
|
||
|
||
section "5️⃣ USERS & AUTHENTICATION"
|
||
|
||
# Admin user
|
||
ADMIN_USER=$(grep -E "^AllowUsers" /etc/ssh/sshd_config | awk '{print $2}' || echo "unknown")
|
||
if [ "$ADMIN_USER" != "unknown" ]; then
|
||
info "Admin user: $ADMIN_USER"
|
||
check_pass "Admin user configured"
|
||
|
||
# Check sudo access
|
||
if [ -f "/etc/sudoers.d/$ADMIN_USER" ]; then
|
||
check_pass "Sudo access configured"
|
||
fi
|
||
else
|
||
check_warn "No specific admin user configured"
|
||
fi
|
||
|
||
# Check for users with UID 0 (root equivalents)
|
||
ROOT_USERS=$(awk -F: '$3 == 0 {print $1}' /etc/passwd | grep -v "^root$" | wc -l)
|
||
if [ "$ROOT_USERS" -eq 0 ]; then
|
||
check_pass "No additional UID 0 users"
|
||
else
|
||
check_warn "Found $ROOT_USERS additional UID 0 users"
|
||
fi
|
||
|
||
# ════════════════════════════════════════════════════════════════
|
||
# 6. BACKUPS
|
||
# ════════════════════════════════════════════════════════════════
|
||
|
||
section "6️⃣ BACKUP SYSTEM"
|
||
|
||
# Check backup directory
|
||
if [ -d "/backup/fortress" ]; then
|
||
check_pass "Backup directory exists"
|
||
|
||
# Count backups
|
||
BACKUP_COUNT=$(ls -1 /backup/fortress/*.enc 2>/dev/null | wc -l || echo "0")
|
||
info "Backup files: $BACKUP_COUNT"
|
||
|
||
if [ "$BACKUP_COUNT" -gt 0 ]; then
|
||
check_pass "Backups found"
|
||
|
||
# Last backup
|
||
LAST_BACKUP=$(ls -t /backup/fortress/*.enc 2>/dev/null | head -1)
|
||
if [ -n "$LAST_BACKUP" ]; then
|
||
LAST_BACKUP_DATE=$(stat -c %y "$LAST_BACKUP" | cut -d' ' -f1)
|
||
info "Last backup: $LAST_BACKUP_DATE"
|
||
|
||
# Check if recent (within 2 days)
|
||
DAYS_SINCE_BACKUP=$(( ($(date +%s) - $(stat -c %Y "$LAST_BACKUP")) / 86400 ))
|
||
if [ "$DAYS_SINCE_BACKUP" -le 2 ]; then
|
||
check_pass "Recent backup available"
|
||
else
|
||
check_warn "Last backup is $DAYS_SINCE_BACKUP days old"
|
||
fi
|
||
fi
|
||
else
|
||
check_warn "No backups found"
|
||
fi
|
||
else
|
||
check_warn "Backup directory not found"
|
||
fi
|
||
|
||
# Check cron job
|
||
if crontab -l 2>/dev/null | grep -q "fortress/backup.sh"; then
|
||
check_pass "Backup cron job configured"
|
||
else
|
||
check_warn "No backup cron job found"
|
||
fi
|
||
|
||
# ════════════════════════════════════════════════════════════════
|
||
# 7. MONITORING & LOGGING
|
||
# ════════════════════════════════════════════════════════════════
|
||
|
||
section "7️⃣ MONITORING & LOGGING"
|
||
|
||
# Log directory
|
||
if [ -d "/var/log/fortress" ]; then
|
||
check_pass "Fortress log directory exists"
|
||
|
||
LOG_SIZE=$(du -sh /var/log/fortress 2>/dev/null | awk '{print $1}')
|
||
info "Log directory size: $LOG_SIZE"
|
||
else
|
||
check_warn "Fortress log directory not found"
|
||
fi
|
||
|
||
# Check for large log files
|
||
LARGE_LOGS=$(find /var/log -type f -size +100M 2>/dev/null | wc -l)
|
||
if [ "$LARGE_LOGS" -gt 0 ]; then
|
||
check_warn "Found $LARGE_LOGS log files >100MB"
|
||
else
|
||
check_pass "No excessively large log files"
|
||
fi
|
||
|
||
# Telegram notifications
|
||
if [ -x "/usr/local/bin/fortress/telegram_notify.sh" ]; then
|
||
check_pass "Telegram notification script available"
|
||
else
|
||
check_warn "Telegram notifications not configured"
|
||
fi
|
||
|
||
# ════════════════════════════════════════════════════════════════
|
||
# 8. OPEN PORTS
|
||
# ════════════════════════════════════════════════════════════════
|
||
|
||
section "8️⃣ OPEN PORTS"
|
||
|
||
info "Listening ports:"
|
||
ss -tuln | grep LISTEN | awk '{print " " $5}' | sort -u
|
||
|
||
# Critical ports check
|
||
CRITICAL_PORTS=("22" "80" "443")
|
||
for port in "${CRITICAL_PORTS[@]}"; do
|
||
if ss -tuln | grep -q ":$port "; then
|
||
info "Port $port is listening"
|
||
fi
|
||
done
|
||
|
||
# ════════════════════════════════════════════════════════════════
|
||
# 9. SECURITY ADVISORIES
|
||
# ════════════════════════════════════════════════════════════════
|
||
|
||
section "9️⃣ SECURITY RECOMMENDATIONS"
|
||
|
||
RECOMMENDATIONS=()
|
||
|
||
# Check if running as root unnecessarily
|
||
if [ "$(id -u)" -eq 0 ]; then
|
||
RECOMMENDATIONS+=("⚠️ Don't run routine tasks as root - use sudo when needed")
|
||
fi
|
||
|
||
# Check SSH on default port
|
||
if ss -tuln | grep -q ":22 " && ! systemctl is-active --quiet endlessh; then
|
||
RECOMMENDATIONS+=("⚠️ SSH on port 22 without honeypot - consider using Port Knocking")
|
||
fi
|
||
|
||
# Check for pending updates
|
||
if command -v apt &>/dev/null; then
|
||
PENDING_UPDATES=$(apt list --upgradable 2>/dev/null | grep -c "upgradable" || echo "0")
|
||
if [ "$PENDING_UPDATES" -gt 0 ]; then
|
||
RECOMMENDATIONS+=("⚠️ $PENDING_UPDATES pending system updates - run: sudo apt update && sudo apt upgrade")
|
||
fi
|
||
fi
|
||
|
||
# Display recommendations
|
||
if [ ${#RECOMMENDATIONS[@]} -gt 0 ]; then
|
||
echo ""
|
||
for rec in "${RECOMMENDATIONS[@]}"; do
|
||
echo -e "${YELLOW}$rec${NC}"
|
||
done
|
||
else
|
||
check_pass "No critical recommendations"
|
||
fi
|
||
|
||
# ════════════════════════════════════════════════════════════════
|
||
# 10. FINAL SUMMARY
|
||
# ════════════════════════════════════════════════════════════════
|
||
|
||
section "📊 FINAL SUMMARY"
|
||
|
||
echo ""
|
||
echo -e "${CYAN}Total Checks: $TOTAL_CHECKS${NC}"
|
||
echo -e "${GREEN}Passed: $PASSED_CHECKS${NC}"
|
||
echo -e "${RED}Failed: $FAILED_CHECKS${NC}"
|
||
echo -e "${YELLOW}Warnings: $WARNING_CHECKS${NC}"
|
||
echo ""
|
||
|
||
# Calculate score
|
||
SCORE=$(( (PASSED_CHECKS * 100) / TOTAL_CHECKS ))
|
||
|
||
if [ "$SCORE" -ge 90 ]; then
|
||
echo -e "${GREEN}═══════════════════════════════════════════════════════${NC}"
|
||
echo -e "${GREEN}✅ EXCELLENT SECURITY POSTURE (Score: $SCORE%)${NC}"
|
||
echo -e "${GREEN}═══════════════════════════════════════════════════════${NC}"
|
||
elif [ "$SCORE" -ge 70 ]; then
|
||
echo -e "${YELLOW}═══════════════════════════════════════════════════════${NC}"
|
||
echo -e "${YELLOW}⚠️ GOOD SECURITY, SOME IMPROVEMENTS NEEDED (Score: $SCORE%)${NC}"
|
||
echo -e "${YELLOW}═══════════════════════════════════════════════════════${NC}"
|
||
else
|
||
echo -e "${RED}═══════════════════════════════════════════════════════${NC}"
|
||
echo -e "${RED}❌ SECURITY NEEDS ATTENTION (Score: $SCORE%)${NC}"
|
||
echo -e "${RED}═══════════════════════════════════════════════════════${NC}"
|
||
fi
|
||
|
||
echo ""
|
||
info "Check completed at: $(date '+%Y-%m-%d %H:%M:%S')"
|
||
info "For detailed logs, check: /var/log/fortress/"
|
||
echo ""
|
||
|
||
# ════════════════════════════════════════════════════════════════
|
||
# Exit with appropriate code
|
||
# ════════════════════════════════════════════════════════════════
|
||
|
||
if [ "$FAILED_CHECKS" -gt 0 ]; then
|
||
exit 1
|
||
elif [ "$WARNING_CHECKS" -gt 3 ]; then
|
||
exit 2
|
||
else
|
||
exit 0
|
||
fi
|