#!/bin/bash

################################################################################
# 服务器自动化加固脚本 - 多发行版增强版
# 作者: Mercas
# 日期: 2025-11-09
# 版本: v4.2 Multi-Distro Enhanced (依赖检查版)
# 
# 支持的发行版:
# - Ubuntu/Debian (apt包管理器)
# - Arch Linux/Manjaro (pacman + AUR支持)
#
# 新增功能:
# - 防火墙: ufw / iptables / nftables 多选一
# - 入侵防护: fail2ban / sshguard / crowdsec 多选一
# - AUR助手: 自动安装yay或paru
# - SSH密钥: ED25519 (替代RSA 4096)
#
# 命令行参数:
# -y, --yes    跳过所有确认提示 (非交互模式)
# -h, --help   显示帮助信息
################################################################################

# ============================================================================
# 命令行参数解析
# ============================================================================

FORCE_YES=false

while [[ $# -gt 0 ]]; do
    case $1 in
        -y|--yes)
            FORCE_YES=true
            shift
            ;;
        -h|--help)
            echo "用法: $0 [选项]"
            echo "选项:"
            echo "  -y, --yes    跳过所有确认提示 (非交互模式)"
            echo "  -h, --help   显示此帮助信息"
            exit 0
            ;;
        *)
            echo "未知参数: $1"
            echo "使用 -h 查看帮助"
            exit 1
            ;;
    esac
done

# ============================================================================
# 全局配置
# ============================================================================

LOG_FILE="/var/log/server_hardening_$(date +%Y%m%d_%H%M%S).log"
BACKUP_DIR="/root/security_backup_$(date +%Y%m%d_%H%M%S)"
ROLLBACK_DIR="/root/security_rollback_$(date +%Y%m%d_%H%M%S)"
REPORT_FILE="/root/security_hardening_report_$(date +%Y%m%d_%H%M%S).txt"

# 错误级别
ERROR_CRITICAL=1
ERROR_SEVERE=2
ERROR_WARNING=3
ERROR_INFO=4

# ============================================================================
# 依赖检查
# ============================================================================

check_dependencies() {
    log_section "检查脚本依赖"
    
    local missing_deps=()
    local core_commands=("bash" "grep" "sed" "awk" "cat" "echo" "chmod" "chown" "cp" "mv" "rm" "mkdir" "date" "sleep" "tail" "head" "find")
    local distro_commands=()
    
    case $PACKAGE_MANAGER in
        apt)
            distro_commands=("apt" "dpkg" "systemctl")
            ;;
        pacman)
            distro_commands=("pacman" "systemctl")
            ;;
    esac
    
    # 检查核心命令
    log_info "检查核心命令..."
    for cmd in "${core_commands[@]}"; do
        if ! command -v "$cmd" &> /dev/null; then
            missing_deps+=("$cmd (core)")
            log_warning "缺少核心命令: $cmd"
        fi
    done
    
    # 检查发行版相关命令
    log_info "检查发行版相关命令..."
    for cmd in "${distro_commands[@]}"; do
        if ! command -v "$cmd" &> /dev/null; then
            missing_deps+=("$cmd (distro)")
            log_warning "缺少发行版命令: $cmd"
        fi
    done
    
    # 检查可选但重要的命令
    local optional_commands=("curl" "wget" "git" "sha256sum" "openssl")
    log_info "检查可选命令..."
    for cmd in "${optional_commands[@]}"; do
        if ! command -v "$cmd" &> /dev/null; then
            log_info "可选命令未安装: $cmd (某些功能可能受限)"
        fi
    done
    
    # 报告结果
    if [[ ${#missing_deps[@]} -gt 0 ]]; then
        log_error "缺少必要的依赖: ${missing_deps[*]}"
        log_info "尝试安装缺失的包..."
        
        case $PACKAGE_MANAGER in
            apt)
                apt update -y 2>&1 | tee -a "$LOG_FILE"
                apt install -y coreutils systemd 2>&1 | tee -a "$LOG_FILE" || true
                ;;
            pacman)
                pacman -Sy 2>&1 | tee -a "$LOG_FILE"
                pacman -S --needed coreutils systemd 2>&1 | tee -a "$LOG_FILE" || true
                ;;
        esac
        
        # 重新检查
        for cmd in "${core_commands[@]}" "${distro_commands[@]}"; do
            if ! command -v "$cmd" &> /dev/null; then
                handle_error $ERROR_SEVERE "命令 $cmd 仍然不可用，脚本无法继续执行" 1 $LINENO
            fi
        done
    fi
    
    # 检查网络工具
    if ! command -v ss &> /dev/null && ! command -v netstat &> /dev/null && ! command -v ip &> /dev/null; then
        log_warning "网络工具(ss/netstat/ip)都不可用，端口检查功能将受限"
    fi
    
    # 检查SSH
    if ! command -v sshd &> /dev/null && ! command -v ssh-keygen &> /dev/null; then
        log_warning "OpenSSH未安装，SSH加固功能将受限"
    fi
    
    log_success "依赖检查完成"
}

# ============================================================================
# 发行版检测
# ============================================================================

detect_distribution() {
    if [[ -f /etc/os-release ]]; then
        . /etc/os-release
        DISTRO_ID="${ID}"
        DISTRO_NAME="${NAME}"
        DISTRO_VERSION="${VERSION_ID}"
    elif [[ -f /etc/lsb-release ]]; then
        . /etc/lsb-release
        DISTRO_ID="${DISTRIB_ID}"
        DISTRO_NAME="${DISTRIB_DESCRIPTION}"
        DISTRO_VERSION="${DISTRIB_RELEASE}"
    else
        DISTRO_ID="unknown"
        DISTRO_NAME="Unknown Linux"
        DISTRO_VERSION="unknown"
    fi
    
    case "${DISTRO_ID}" in
        ubuntu)
            DISTRO_FAMILY="debian"
            PACKAGE_MANAGER="apt"
            ;;
        debian)
            DISTRO_FAMILY="debian"
            PACKAGE_MANAGER="apt"
            ;;
        arch|manjaro|antergos)
            DISTRO_FAMILY="arch"
            PACKAGE_MANAGER="pacman"
            ;;
        *)
            if command -v pacman &> /dev/null; then
                DISTRO_FAMILY="arch"
                PACKAGE_MANAGER="pacman"
            else
                DISTRO_FAMILY="debian"
                PACKAGE_MANAGER="apt"
            fi
            ;;
    esac
    
    echo "检测到发行版: $DISTRO_NAME ($DISTRO_FAMILY)"
}

# ============================================================================
# 颜色定义
# ============================================================================

setup_colors() {
    if command -v tput &> /dev/null && [[ -n "$TERM" ]]; then
        RED=$(tput setaf 1 2>/dev/null || echo '\033[0;31m')
        GREEN=$(tput setaf 2 2>/dev/null || echo '\033[0;32m')
        YELLOW=$(tput setaf 3 2>/dev/null || echo '\033[1;33m')
        BLUE=$(tput setaf 4 2>/dev/null || echo '\033[0;34m')
        CYAN=$(tput setaf 6 2>/dev/null || echo '\033[0;36m')
        NC=$(tput sgr0 2>/dev/null || echo '\033[0m')
    else
        RED='\033[0;31m'
        GREEN='\033[0;32m'
        YELLOW='\033[1;33m'
        BLUE='\033[0;34m'
        CYAN='\033[0;36m'
        NC='\033[0m'
    fi
}

# ============================================================================
# 日志函数
# ============================================================================

log() {
    echo -e "${GREEN}[$(date +'%Y-%m-%d %H:%M:%S')]${NC} $1" | tee -a "$LOG_FILE"
}

log_info() {
    echo -e "${BLUE}[INFO]${NC} $1" | tee -a "$LOG_FILE"
}

log_warning() {
    echo -e "${YELLOW}[WARNING]${NC} $1" | tee -a "$LOG_FILE"
}

log_error() {
    echo -e "${RED}[ERROR]${NC} $1" | tee -a "$LOG_FILE"
}

log_success() {
    echo -e "${GREEN}[SUCCESS]${NC} $1" | tee -a "$LOG_FILE"
}

log_section() {
    echo -e "\n${CYAN}========================================${NC}" | tee -a "$LOG_FILE"
    echo -e "${CYAN}$1${NC}" | tee -a "$LOG_FILE"
    echo -e "${CYAN}========================================${NC}\n" | tee -a "$LOG_FILE"
}

log_rollback() {
    echo -e "${YELLOW}[ROLLBACK]${NC} $1" | tee -a "$LOG_FILE"
}

# ============================================================================
# 核心工具函数
# ============================================================================

check_root() {
    if [[ $EUID -ne 0 ]]; then
        log_error "此脚本必须以root权限运行"
        exit 1
    fi
}

handle_error() {
    local error_level=$1
    local message=$2
    local exit_code=${3:-1}
    local lineno=${4:-0}
    
    case $error_level in
        $ERROR_CRITICAL)
            log_error "[致命错误] $message (行号: $lineno, 退出码: $exit_code)"
            exit $exit_code
            ;;
        $ERROR_SEVERE)
            log_error "[严重错误] $message (行号: $lineno, 退出码: $exit_code)"
            if confirm_action "发生严重错误，是否回滚所有更改并退出？"; then
                execute_rollback
                exit $exit_code
            fi
            ;;
        $ERROR_WARNING)
            log_warning "[警告] $message"
            ;;
        $ERROR_INFO)
            log_info "[信息] $message"
            ;;
    esac
}

backup_file() {
    local file=$1
    local description=${2:-"备份"}
    
    if [[ -f "$file" ]]; then
        mkdir -p "$BACKUP_DIR"
        local backup_path="$BACKUP_DIR/$(basename "$file").bak"
        local checksum_file="$backup_path.sha256"
        
        cp -p "$file" "$backup_path"
        
        if command -v sha256sum &> /dev/null; then
            sha256sum "$backup_path" > "$checksum_file"
            log_info "已备份: $(basename "$file") (SHA256: $(sha256sum --short "$backup_path"))"
        else
            log_info "已备份: $(basename "$file")"
        fi
        
        echo "$file:$backup_path:$(date +%s)" >> "$ROLLBACK_DIR/rollback_list.txt"
    fi
}

init_rollback() {
    mkdir -p "$ROLLBACK_DIR"
    touch "$ROLLBACK_DIR/rollback_list.txt"
    touch "$ROLLBACK_DIR/actions.log"
    log_info "回滚机制已初始化: $ROLLBACK_DIR"
}

execute_rollback() {
    log_rollback "开始执行回滚操作..."
    
    if [[ ! -f "$ROLLBACK_DIR/rollback_list.txt" ]]; then
        log_warning "没有回滚记录可执行"
        return 0
    fi
    
    while IFS=: read -r original backup timestamp; do
        if [[ -f "$backup" ]] && [[ -f "$original" ]]; then
            cp "$backup" "$original"
            log_rollback "已还原: $original"
        fi
    done < "$ROLLBACK_DIR/rollback_list.txt"
    
    log_success "回滚操作完成"
}

record_rollback_action() {
    local action_type=$1
    local target=$2
    local command=$3
    local timestamp=$(date +%s)
    echo "$timestamp:$action_type:$target:$command" >> "$ROLLBACK_DIR/actions.log"
}

# 安全获取主机名 (处理hostname命令不存在的情况)
get_hostname() {
    if command -v hostname &> /dev/null; then
        hostname
    elif [[ -f /etc/hostname ]]; then
        cat /etc/hostname
    elif [[ -f /proc/sys/kernel/hostname ]]; then
        cat /proc/sys/kernel/hostname
    else
        uname -n
    fi
}

# 安全获取IP地址
get_ip_address() {
    if command -v hostname &> /dev/null; then
        local ip=$(hostname -I 2>/dev/null | awk '{print $1}')
        if [[ -n "$ip" ]]; then
            echo "$ip"
        elif command -v ip &> /dev/null; then
            ip addr show 2>/dev/null | grep -oP 'inet \K[\d.]+' | head -1 || echo 'N/A'
        else
            echo 'N/A'
        fi
    elif command -v ip &> /dev/null; then
        ip addr show 2>/dev/null | grep -oP 'inet \K[\d.]+' | head -1 || echo 'N/A'
    elif [[ -f /proc/net/dev ]]; then
        grep -oP 'inet \K[\d.]+' /proc/net/fib_trie 2>/dev/null | head -1 || echo 'N/A'
    else
        echo 'N/A'
    fi
}

confirm_action() {
    local message=$1
    # 如果强制确认标志为真，直接返回成功
    if [[ "$FORCE_YES" == "true" ]]; then
        log_info "[自动确认] $message"
        return 0
    fi
    if [[ -t 0 ]]; then
        echo -e "${YELLOW}${message} [y/N]: ${NC}\c"
        read -n 1 -r
        echo
        if [[ ! $REPLY =~ ^[Yy]$ ]]; then
            return 1
        fi
        return 0
    else
        log_info "[非交互模式跳过] $message"
        return 1
    fi
}

check_port_available() {
    local port=$1
    local service_name=$2
    
    if ss -tunlp 2>/dev/null | grep -q ":$port "; then
        log_warning "端口 $port 已被占用"
        if ! confirm_action "是否继续使用端口 $port？"; then
            return 1
        fi
    fi
    return 0
}

# ============================================================================
# 包管理器抽象层
# ============================================================================

update_package_list() {
    case $PACKAGE_MANAGER in
        apt)
            apt update -y 2>&1 | tee -a "$LOG_FILE"
            ;;
        pacman)
            pacman -Sy 2>&1 | tee -a "$LOG_FILE"
            ;;
    esac
}

install_package() {
    local package=$1
    local description=${2:-"安装软件包"}
    
    log_info "安装: $package ($description)"
    
    case $PACKAGE_MANAGER in
        apt)
            if dpkg -l 2>/dev/null | grep -q "^ii  $package "; then
                log_info "$package 已安装"
                return 0
            fi
            apt install -y "$package" 2>&1 | tee -a "$LOG_FILE"
            return ${PIPESTATUS[0]}
            ;;
        pacman)
            if pacman -Qq "$package" &>/dev/null; then
                log_info "$package 已安装"
                return 0
            fi
            pacman -S --noconfirm "$package" 2>&1 | tee -a "$LOG_FILE"
            return ${PIPESTATUS[0]}
            ;;
    esac
}

is_package_installed() {
    local package=$1
    
    case $PACKAGE_MANAGER in
        apt)
            dpkg -l 2>/dev/null | grep -q "^ii  $package"
            ;;
        pacman)
            pacman -Qq "$package" &>/dev/null
            ;;
    esac
}

enable_service() {
    local service=$1
    
    if command -v systemctl &> /dev/null; then
        systemctl enable "$service" 2>&1 | tee -a "$LOG_FILE"
        systemctl start "$service" 2>&1 | tee -a "$LOG_FILE"
    fi
}

disable_service() {
    local service=$1
    
    if command -v systemctl &> /dev/null; then
        systemctl stop "$service" 2>&1 | tee -a "$LOG_FILE" || true
        systemctl disable "$service" 2>&1 | tee -a "$LOG_FILE" || true
    fi
}

# ============================================================================
# AUR助手安装
# ============================================================================

install_aur_helper() {
    log_section "安装AUR助手"
    
    if ! command -v git &> /dev/null; then
        log_info "安装git..."
        pacman -S --noconfirm git 2>&1 | tee -a "$LOG_FILE"
    fi
    
    if command -v yay &> /dev/null || command -v paru &> /dev/null; then
        log_info "AUR助手已安装"
        return 0
    fi
    
    echo -e "${YELLOW}请选择AUR助手:${NC}"
    echo "1) yay (更流行)"
    echo "2) paru (功能更丰富)"
    echo "3) 跳过安装"
    echo -e "${YELLOW}选择 [1-3]: ${NC}\c"
    read -p "" aur_choice
    
    local aur_helper=""
    local aur_repo=""
    
    case $aur_choice in
        1)
            aur_helper="yay"
            aur_repo="https://aur.archlinux.org/yay.git"
            ;;
        2)
            aur_helper="paru"
            aur_repo="https://aur.archlinux.org/paru.git"
            ;;
        3)
            log_info "跳过AUR助手安装"
            return 0
            ;;
        *)
            log_warning "无效选择"
            return 1
            ;;
    esac
    
    # 确保base-devel已安装
    log_info "安装构建依赖..."
    pacman -S --needed --noconfirm base-devel 2>&1 | tee -a "$LOG_FILE"
    
    # 克隆并安装AUR助手
    local temp_dir=$(mktemp -d)
    cd "$temp_dir"
    
    log_info "从AUR安装 $aur_helper..."
    git clone "$aur_repo" 2>&1 | tee -a "$LOG_FILE"
    cd "$aur_helper"
    
    if makepkg -si --noconfirm 2>&1 | tee -a "$LOG_FILE"; then
        log_success "$aur_helper 安装成功"
        
        # 记录回滚命令
        record_rollback_action "aur_helper" "$aur_helper" "pacman -Rns $aur_helper"
    else
        log_error "$aur_helper 安装失败"
        rm -rf "$temp_dir"
        return 1
    fi
    
    rm -rf "$temp_dir"
    
    # 验证安装
    if command -v $aur_helper &> /dev/null; then
        log_success "AUR助手 $aur_helper 已就绪"
    fi
}

install_aur_package() {
    local package=$1
    local description=${2:-"AUR包"}
    
    # 优先使用pacman
    if is_package_installed "$package"; then
        log_info "$package 已安装"
        return 0
    fi
    
    # 尝试pacman
    if pacman -S --noconfirm "$package" 2>&1 | tee -a "$LOG_FILE"; then
        return 0
    fi
    
    # 使用AUR助手
    if command -v yay &> /dev/null; then
        log_info "使用yay安装 $package..."
        yay -S --noconfirm "$package" 2>&1 | tee -a "$LOG_FILE"
    elif command -v paru &> /dev/null; then
        log_info "使用paru安装 $package..."
        paru -S --noconfirm "$package" 2>&1 | tee -a "$LOG_FILE"
    else
        log_warning "无AUR助手可用，跳过 $package 安装"
        return 1
    fi
}

# ============================================================================
# 密码策略配置
# ============================================================================

configure_password_policy() {
    log_info "配置密码策略..."
    
    case $PACKAGE_MANAGER in
        apt)
            if ! is_package_installed "libpam-pwquality"; then
                install_package "libpam-pwquality" "密码质量检查"
            fi
            
            local pwquality_file="/etc/security/pwquality.conf"
            backup_file "$pwquality_file"
            
            if ! grep -q "^minlen = 12" "$pwquality_file" 2>/dev/null; then
                cat >> "$pwquality_file" << 'EOF'

# 密码安全策略
minlen = 12
dcredit = -1
ucredit = -1
lcredit = -1
ocredit = -1
maxrepeat = 3
EOF
            fi
            ;;
        pacman)
            if ! is_package_installed "libpwquality"; then
                install_package "libpwquality" "密码质量检查库"
            fi
            
            local login_defs="/etc/login.defs"
            if [[ -f "$login_defs" ]]; then
                backup_file "$login_defs"
                sed -i 's/^PASS_MAX_DAYS.*/PASS_MAX_DAYS 90/' "$login_defs" 2>/dev/null || true
                sed -i 's/^PASS_MIN_DAYS.*/PASS_MIN_DAYS 1/' "$login_defs" 2>/dev/null || true
                sed -i 's/^PASS_WARN_AGE.*/PASS_WARN_AGE 14/' "$login_defs" 2>/dev/null || true
            fi
            ;;
    esac
    
    log_success "密码策略配置完成"
}

# ============================================================================
# 防火墙配置 (支持 ufw / iptables / nftables)
# ============================================================================

configure_firewall() {
    log_section "配置防火墙"
    
    local ssh_port=22
    
    # 检测SSH端口
    if [[ -f "/etc/ssh/sshd_config" ]]; then
        ssh_port=$(grep -E "^Port [0-9]+" /etc/ssh/sshd_config 2>/dev/null | awk '{print $2}' | head -1)
        ssh_port=${ssh_port:-22}
    fi
    
    echo -e "${YELLOW}请选择防火墙方案:${NC}"
    echo "1) UFW (简单防火墙) - 推荐Ubuntu/新手"
    echo "2) iptables (传统防火墙) - 通用选择"
    echo "3) nftables (下一代防火墙) - Arch推荐，更高效"
    echo "4) 跳过防火墙配置"
    echo -e "${YELLOW}选择 [1-4]: ${NC}\c"
    read -p "" firewall_choice
    
    case $firewall_choice in
        1)
            configure_ufw "$ssh_port"
            ;;
        2)
            configure_iptables "$ssh_port"
            ;;
        3)
            configure_nftables "$ssh_port"
            ;;
        4)
            log_info "跳过防火墙配置"
            ;;
        *)
            log_warning "无效选择，使用默认iptables"
            configure_iptables "$ssh_port"
            ;;
    esac
}

configure_ufw() {
    local ssh_port=$1
    
    log_info "配置UFW防火墙..."
    
    if ! is_package_installed "ufw"; then
        install_package "ufw" "简单防火墙"
    fi
    
    ufw default deny incoming 2>&1 | tee -a "$LOG_FILE"
    ufw default allow outgoing 2>&1 | tee -a "$LOG_FILE"
    
    if [[ -t 0 ]]; then
        echo -e "${YELLOW}SSH端口 (默认$ssh_port): ${NC}\c"
        read -p "" ssh_port_input
        ssh_port=${ssh_port_input:-$ssh_port}
    fi
    
    ufw allow "$ssh_port/tcp" comment 'SSH' 2>&1 | tee -a "$LOG_FILE"
    
    if confirm_action "是否开放HTTP(80)端口？"; then
        ufw allow 80/tcp comment 'HTTP' 2>&1 | tee -a "$LOG_FILE"
    fi
    
    if confirm_action "是否开放HTTPS(443)端口？"; then
        ufw allow 443/tcp comment 'HTTPS' 2>&1 | tee -a "$LOG_FILE"
    fi
    
    if [[ -t 0 ]]; then
        echo "y" | ufw enable 2>&1 | tee -a "$LOG_FILE"
    else
        ufw --force enable 2>&1 | tee -a "$LOG_FILE"
    fi
    
    ufw status numbered 2>/dev/null | tee -a "$LOG_FILE"
    
    record_rollback_action "firewall" "ufw" "ufw reset"
    log "UFW防火墙配置完成"
}

configure_iptables() {
    local ssh_port=$1
    
    log_info "配置iptables防火墙..."
    
    if ! command -v iptables &> /dev/null; then
        install_package "iptables" "防火墙工具"
    fi
    
    if command -v systemctl &> /dev/null; then
        systemctl enable iptables 2>/dev/null || true
        systemctl start iptables 2>/dev/null || true
    fi
    
    # 刷新现有规则
    iptables -F 2>&1 | tee -a "$LOG_FILE" || true
    iptables -X 2>&1 | tee -a "$LOG_FILE" || true
    
    # 设置默认策略
    iptables -P INPUT DROP 2>&1 | tee -a "$LOG_FILE"
    iptables -P FORWARD DROP 2>&1 | tee -a "$LOG_FILE"
    iptables -P OUTPUT ACCEPT 2>&1 | tee -a "$LOG_FILE"
    
    if [[ -t 0 ]]; then
        echo -e "${YELLOW}SSH端口 (默认$ssh_port): ${NC}\c"
        read -p "" ssh_port_input
        ssh_port=${ssh_port_input:-$ssh_port}
    fi
    
    # 允许SSH
    iptables -A INPUT -p tcp --dport "$ssh_port" -j ACCEPT 2>&1 | tee -a "$LOG_FILE"
    
    # 允许回环
    iptables -A INPUT -i lo -j ACCEPT 2>&1 | tee -a "$LOG_FILE"
    iptables -A OUTPUT -o lo -j ACCEPT 2>&1 | tee -a "$LOG_FILE"
    
    # 允许已建立的连接
    iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT 2>&1 | tee -a "$LOG_FILE"
    
    if confirm_action "是否开放HTTP(80)端口？"; then
        iptables -A INPUT -p tcp --dport 80 -j ACCEPT 2>&1 | tee -a "$LOG_FILE"
    fi
    
    if confirm_action "是否开放HTTPS(443)端口？"; then
        iptables -A INPUT -p tcp --dport 443 -j ACCEPT 2>&1 | tee -a "$LOG_FILE"
    fi
    
    # 保存规则
    mkdir -p /etc/iptables
    iptables-save > /etc/iptables/iptables.rules 2>&1 | tee -a "$LOG_FILE"
    
    iptables -L -n 2>/dev/null | tee -a "$LOG_FILE"
    
    record_rollback_action "firewall" "iptables" "iptables -F"
    log "iptables防火墙配置完成"
}

configure_nftables() {
    local ssh_port=$1
    
    log_info "配置nftables防火墙..."
    
    if ! command -v nft &> /dev/null; then
        install_package "nftables" "下一代防火墙"
    fi
    
    # 确保服务已启用
    if command -v systemctl &> /dev/null; then
        systemctl enable nftables 2>&1 | tee -a "$LOG_FILE"
        systemctl start nftables 2>&1 | tee -a "$LOG_FILE"
    fi
    
    # 备份现有配置
    if [[ -f /etc/nftables.conf ]]; then
        backup_file "/etc/nftables.conf"
    fi
    
    if [[ -t 0 ]]; then
        echo -e "${YELLOW}SSH端口 (默认$ssh_port): ${NC}\c"
        read -p "" ssh_port_input
        ssh_port=${ssh_port_input:-$ssh_port}
    fi
    
    # 创建nftables配置
    cat > /etc/nftables.conf << EOF
#!/usr/bin/nft -f

# 刷新所有规则
flush ruleset

# 定义表
table inet filter {
    # 链定义
    chain input {
        type filter hook input priority 0; policy drop;
        
        # 允许回环
        iif lo accept
        
        # 允许已建立的连接
        ct state established,related accept
        
        # SSH
        tcp dport $ssh_port accept
        
        # HTTP/HTTPS (可选)
        # tcp dport {80, 443} accept
        
        # 拒绝其他入站
        reject with icmpx type administratively-prohibited
    }
    
    chain forward {
        type filter hook forward priority 0; policy drop;
    }
    
    chain output {
        type filter hook output priority 0; policy accept;
    }
}
EOF
    
    log_info "SSH端口: $ssh_port"
    
    if confirm_action "是否开放HTTP(80)和HTTPS(443)端口？"; then
        sed -i 's|# tcp dport {80, 443} accept|tcp dport {80, 443} accept|' /etc/nftables.conf
        log_info "已添加HTTP/HTTPS规则"
    fi
    
    # 测试并加载配置
    nft -f /etc/nftables.conf 2>&1 | tee -a "$LOG_FILE"
    
    if [[ $? -eq 0 ]]; then
        log_success "nftables配置已应用"
    else
        log_error "nftables配置失败"
        return 1
    fi
    
    # 显示状态
    nft list ruleset 2>&1 | tee -a "$LOG_FILE"
    
    record_rollback_action "firewall" "nftables" "nft flush ruleset"
    log "nftables防火墙配置完成"
}

# ============================================================================
# 入侵防御系统 (支持 fail2ban / sshguard / crowdsec)
# ============================================================================

install_intrusion_prevention() {
    log_section "配置入侵防御系统"
    
    echo -e "${YELLOW}请选择入侵防御方案:${NC}"
    echo "1) Fail2ban (功能丰富，支持多服务)"
    echo "2) Sshguard (轻量级，专注SSH)"
    echo "3) Crowdsec (社区驱动，AI增强)"
    echo "4) 跳过安装"
    echo -e "${YELLOW}选择 [1-4]: ${NC}\c"
    read -p "" ips_choice
    
    case $ips_choice in
        1)
            install_fail2ban
            ;;
        2)
            install_sshguard
            ;;
        3)
            install_crowdsec
            ;;
        4)
            log_info "跳过入侵防御系统安装"
            ;;
        *)
            log_warning "无效选择"
            ;;
    esac
}

install_fail2ban() {
    log_info "安装Fail2ban..."
    
    case $PACKAGE_MANAGER in
        apt)
            install_package "fail2ban" "入侵防御"
            ;;
        pacman)
            install_package "fail2ban" "入侵防御"
            ;;
    esac
    
    if command -v fail2ban-client &> /dev/null; then
        configure_fail2ban
    fi
}

configure_fail2ban() {
    log_info "配置Fail2ban..."
    
    local jail_local="/etc/fail2ban/jail.local"
    backup_file "$jail_local" 2>/dev/null || true
    
    cat > "$jail_local" << 'EOF'
[DEFAULT]
bantime = 3600
findtime = 600
maxretry = 5

[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
bantime = 7200

[sshd-ddos]
enabled = true
port = ssh
filter = sshd-ddos
logpath = /var/log/auth.log
maxretry = 2
bantime = 7200
EOF
    
    enable_service "fail2ban"
    sleep 2
    
    if command -v fail2ban-client &> /dev/null; then
        fail2ban-client status 2>/dev/null | tee -a "$LOG_FILE"
    fi
    
    log_success "Fail2ban配置完成"
}

install_sshguard() {
    log_info "安装Sshguard..."
    
    case $PACKAGE_MANAGER in
        apt)
            install_package "sshguard" "SSH入侵防御"
            ;;
        pacman)
            install_package "sshguard" "SSH入侵防御"
            ;;
    esac
    
    if command -v sshguard &> /dev/null; then
        configure_sshguard
    fi
}

configure_sshguard() {
    log_info "配置Sshguard..."
    
    if command -v systemctl &> /dev/null; then
        systemctl enable sshguard 2>&1 | tee -a "$LOG_FILE"
        systemctl start sshguard 2>&1 | tee -a "$LOG_FILE"
    fi
    
    log_success "Sshguard已启动"
}

install_crowdsec() {
    log_section "安装Crowdsec"
    
    log_info "Crowdsec - 社区驱动的入侵防御系统"
    echo -e "${YELLOW}特点:${NC}"
    echo "• 社区威胁情报共享"
    echo "• 轻量级，高性能"
    echo "• 自动学习正常行为"
    echo "• 支持多种防火墙集成"
    
    if ! confirm_action "是否安装Crowdsec？"; then
        log_info "跳过Crowdsec安装"
        return 0
    fi
    
    case $PACKAGE_MANAGER in
        apt)
            # 使用官方安装脚本
            log_info "从官方源安装Crowdsec..."
            curl -s https://install.crowdsec.net | sh 2>&1 | tee -a "$LOG_FILE"
            ;;
        pacman)
            # 从AUR安装
            log_info "从AUR安装Crowdsec..."
            if ! is_package_installed "crowdsec"; then
                install_aur_package "crowdsec" "Crowdsec核心"
            fi
            if ! is_package_installed "crowdsec-firewall-bouncer"; then
                install_aur_package "crowdsec-firewall-bouncer" "防火墙联动"
            fi
            ;;
    esac
    
    if command -v cscli &> /dev/null; then
        configure_crowdsec
    fi
}

configure_crowdsec() {
    log_info "配置Crowdsec..."
    
    # 初始化
    cscli console enable 2>&1 | tee -a "$LOG_FILE"
    
    # 获取推荐场景
    log_info "安装推荐场景..."
    cscli scenarios list 2>&1 | tee -a "$LOG_FILE" | head -20
    
    # 安装SSH防护
    log_info "启用SSH防护..."
    cscli scenarios install crowdsecurity/ssh-bf 2>&1 | tee -a "$LOG_FILE"
    
    # 安装防火墙bouncer
    log_info "配置防火墙联动..."
    case $PACKAGE_MANAGER in
        apt)
            if is_package_installed "ufw"; then
                cscli bouncers add crowdsec-ufw-bouncer 2>&1 | tee -a "$LOG_FILE"
            elif command -v nft &> /dev/null; then
                cscli bouncers add crowdsec-nft-bouncer 2>&1 | tee -a "$LOG_FILE"
            fi
            ;;
        pacman)
            if command -v nft &> /dev/null; then
                cscli bouncers add crowdsec-nft-bouncer 2>&1 | tee -a "$LOG_FILE"
            fi
            ;;
    esac
    
    # 启动服务
    enable_service "crowdsec"
    
    sleep 2
    
    # 显示状态
    cscli metrics 2>&1 | tee -a "$LOG_FILE" | head -20
    
    log_success "Crowdsec配置完成"
    log_info "运行 'cscli dashboard setup' 可安装可视化面板"
}

# ============================================================================
# 自动安全更新
# ============================================================================

configure_auto_updates() {
    log_section "配置自动安全更新"
    
    case $PACKAGE_MANAGER in
        apt)
            if confirm_action "是否启用自动安全更新？"; then
                if ! is_package_installed "unattended-upgrades"; then
                    install_package "unattended-upgrades" "自动更新"
                fi
                echo unattended-upgrades unattended-upgrades/enable_auto_updates boolean true | debconf-set-selections 2>&1 | tee -a "$LOG_FILE"
                log "自动安全更新已启用"
            fi
            ;;
        pacman)
            log_warning "Arch Linux不推荐完全自动更新"
            if confirm_action "是否配置pacman更新通知？"; then
                local cron_file="/etc/cron.daily/check-updates"
                cat > "$cron_file" << 'EOF'
#!/bin/bash
pacman -Sy 2>/dev/null
echo "系统检查完成"
EOF
                chmod +x "$cron_file"
                log_info "已配置每日更新检查"
            fi
            ;;
    esac
}

# ============================================================================
# 安全审计工具
# ============================================================================

install_security_tools() {
    log_section "安装额外安全工具"
    
    if [[ "$PACKAGE_MANAGER" == "pacman" ]]; then
        # 确保AUR助手已安装
        if ! command -v yay &> /dev/null && ! command -v paru &> /dev/null; then
            if confirm_action "是否安装AUR助手以获取更多安全工具？"; then
                install_aur_helper
            fi
        fi
    fi
    
    local tools=()
    
    case $PACKAGE_MANAGER in
        apt)
            tools=("auditd")
            echo -e "${YELLOW}注意: aide和rkhunter可通过apt安装${NC}"
            ;;
        pacman)
            tools=("auditd")
            echo -e "${YELLOW}提示: aide和rkhunter可从AUR安装${NC}"
            ;;
    esac
    
    for tool in "${tools[@]}"; do
        if confirm_action "是否安装 $tool？"; then
            if is_package_installed "$tool"; then
                log_info "$tool 已安装"
                continue
            fi
            install_package "$tool" "安全工具"
            enable_service "$tool" 2>/dev/null || true
        fi
    done
    
    # 额外的AUR选项
    if [[ "$PACKAGE_MANAGER" == "pacman" ]]; then
        if confirm_action "是否从AUR安装 aide (文件完整性)？"; then
            install_aur_package "aide" "文件完整性检查"
        fi
        if confirm_action "是否从AUR安装 rkhunter (Rootkit检测)？"; then
            install_aur_package "rkhunter" "Rootkit检测"
        fi
    fi
}

# ============================================================================
# SSH密钥和用户管理 (使用ED25519)
# ============================================================================

verify_ssh_key_exists() {
    local username=$1
    
    if [[ -z "$username" ]]; then
        return 1
    fi
    
    local user_home=$(eval echo "~$username")
    local ssh_dir="$user_home/.ssh"
    local authorized_keys="$ssh_dir/authorized_keys"
    
    if [[ -f "$authorized_keys" ]] && [[ -s "$authorized_keys" ]]; then
        local key_count=$(grep -c "ssh-" "$authorized_keys" 2>/dev/null || echo 0)
        if [[ $key_count -gt 0 ]]; then
            log_success "用户 $username 已有 $key_count 个SSH公钥"
            return 0
        fi
    fi
    return 1
}

setup_ssh_key() {
    local username=$1
    local public_key=$2
    local user_home=$(eval echo "~$username")
    local ssh_dir="$user_home/.ssh"
    local authorized_keys="$ssh_dir/authorized_keys"
    
    mkdir -p "$ssh_dir"
    echo "$public_key" > "$authorized_keys"
    record_rollback_action "ssh_key" "$username" "rm -f $authorized_keys"
    log_success "SSH公钥已设置"
}

# 优化：使用ED25519替代RSA
setup_generate_key() {
    local username=$1
    local user_home=$(eval echo "~$username")
    local ssh_dir="$user_home/.ssh"
    local key_file="$ssh_dir/id_ed25519"
    
    mkdir -p "$ssh_dir"
    chown "$username:$username" "$ssh_dir"
    
    if [[ ! -f "$key_file" ]]; then
        log_info "生成ED25519 SSH密钥对..."
        log_info "ED25519: 比RSA更安全更快，256位即可达到4096位RSA的安全性"
        
        record_rollback_action "ssh_keygen" "$username" "rm -f $key_file $key_file.pub"
        
        # 使用ED25519生成密钥
        su - "$username" -c "ssh-keygen -t ed25519 -f '$key_file' -C '$username@$(get_hostname)'"
        
        if [[ -f "$key_file" ]]; then
            log_success "ED25519密钥对生成成功"
            log_info "私钥文件: $key_file"
            log_info "公钥文件: $key_file.pub"
            log_warning "请妥善保管私钥文件"
            
            echo -e "${YELLOW}公钥内容 (添加到authorized_keys):${NC}"
            cat "$key_file.pub"
            echo ""
        else
            log_error "SSH密钥生成失败，回退到RSA..."
            # 回退到RSA
            local rsa_key_file="$ssh_dir/id_rsa"
            su - "$username" -c "ssh-keygen -t rsa -b 4096 -f '$rsa_key_file' -N '' -C '$username@$(get_hostname)'"
            if [[ -f "$rsa_key_file" ]]; then
                log_success "RSA密钥对生成成功"
                log_info "密钥文件: $rsa_key_file"
            fi
            return 1
        fi
    else
        log_info "SSH密钥已存在 ($key_file)"
    fi
}

configure_sudo_settings() {
    local username=$1
    
    log_info "配置sudo权限..."
    
    echo -e "${YELLOW}请选择sudo权限级别:${NC}"
    echo "1) 完全无密码sudo"
    echo "2) 需要密码sudo (推荐)"
    echo "3) 仅特定命令无密码"
    echo "4) 不配置"
    echo -e "${YELLOW}选择 [1-4]: ${NC}\c"
    read -p "" sudo_option
    
    local sudoers_file="/etc/sudoers.d/$username"
    
    case $sudo_option in
        1)
            echo "$username ALL=(ALL) NOPASSWD:ALL" > "$sudoers_file"
            chmod 440 "$sudoers_file"
            record_rollback_action "sudoers" "$username" "rm -f $sudoers_file"
            log_warning "已配置无密码sudo (安全性较低)"
            ;;
        2)
            echo "$username ALL=(ALL) ALL" > "$sudoers_file"
            chmod 440 "$sudoers_file"
            record_rollback_action "sudoers" "$username" "rm -f $sudoers_file"
            log_success "已配置需要密码的sudo"
            ;;
        3)
            echo -e "${YELLOW}输入允许无密码执行的命令: ${NC}\c"
            read -p "" sudo_commands
            if [[ -n "$sudo_commands" ]]; then
                echo "$username ALL=(ALL) NOPASSWD: $sudo_commands" > "$sudoers_file"
                chmod 440 "$sudoers_file"
                record_rollback_action "sudoers" "$username" "rm -f $sudoers_file"
                log_success "已配置限制性sudo"
            fi
            ;;
        *)
            log_info "跳过sudo配置"
            ;;
    esac
}

manage_users() {
    log_section "创建管理用户和配置SSH密钥"
    
    if ! confirm_action "是否创建专用管理用户？"; then
        log_warning "跳过用户创建"
        return 0
    fi
    
    local username=""
    
    if [[ -t 0 ]]; then
        echo -e "${YELLOW}请输入新用户名: ${NC}\c"
        read -p "" username
    else
        username="admin"
    fi
    
    if [[ -z "$username" ]] || [[ ! "$username" =~ ^[a-z_][a-z0-9_-]*$ ]]; then
        handle_error $ERROR_SEVERE "无效的用户名: $username"
        return 1
    fi
    
    # 检查用户是否存在
    if id "$username" &>/dev/null 2>&1; then
        log_info "用户 $username 已存在"
    else
        log_info "创建用户: $username"
        useradd -m -s /bin/bash "$username" 2>&1 | tee -a "$LOG_FILE"
        
        if [[ -t 0 ]]; then
            echo -e "${YELLOW}为用户 $username 设置密码: ${NC}\c"
            passwd "$username"
        else
            local temp_password=$(openssl rand -base64 32)
            echo "$username:$temp_password" | chpasswd
            record_rollback_action "password" "$username" "passwd -d $username"
            log_warning "临时密码: $temp_password"
        fi
        
        case $PACKAGE_MANAGER in
            apt)
                usermod -aG sudo "$username" 2>&1 | tee -a "$LOG_FILE"
                record_rollback_action "usermod" "$username" "gpasswd -d $username sudo"
                ;;
            pacman)
                usermod -aG wheel "$username" 2>&1 | tee -a "$LOG_FILE"
                record_rollback_action "usermod" "$username" "gpasswd -d $username wheel"
                if [[ -f "/etc/sudoers" ]]; then
                    if ! grep -q "^%wheel ALL=" /etc/sudoers 2>/dev/null; then
                        backup_file "/etc/sudoers"
                        echo "%wheel ALL=(ALL) ALL" >> /etc/sudoers
                    fi
                fi
                ;;
        esac
    fi
    
    log_info "配置SSH密钥..."
    local key_configured=false
    
    if [[ -t 0 ]]; then
        echo -e "${YELLOW}选择密钥配置方式: ${NC}"
        echo "1) 现有公钥"
        echo "2) 生成ED25519密钥 (推荐)"
        echo "3) 跳过"
        echo -e "${YELLOW}选择 [1-3]: ${NC}\c"
        read -p "" key_option
    else
        key_option="3"
    fi
    
    case $key_option in
        1)
            echo -e "${YELLOW}输入SSH公钥: ${NC}\c"
            read -p "" public_key
            if [[ -n "$public_key" ]] && [[ "$public_key" =~ ^ssh- ]]; then
                setup_ssh_key "$username" "$public_key"
                key_configured=true
            fi
            ;;
        2)
            setup_generate_key "$username"
            key_configured=true
            ;;
        *)
            log_info "跳过密钥配置"
            ;;
    esac
    
    configure_sudo_settings "$username"
    
    local user_home=$(eval echo "~$username")
    local ssh_dir="$user_home/.ssh"
    
    if [[ -d "$ssh_dir" ]]; then
        chown -R "$username:$username" "$ssh_dir" 2>&1 | tee -a "$LOG_FILE"
        chmod 700 "$ssh_dir" 2>&1 | tee -a "$LOG_FILE"
        chmod 600 "$ssh_dir/authorized_keys" 2>&1 | tee -a "$LOG_FILE" || true
    fi
    
    if id "$username" &>/dev/null; then
        log_success "用户 $username 配置成功"
    fi
    
    if $key_configured; then
        return 0
    else
        return 1
    fi
}

# ============================================================================
# SSH安全加固
# ============================================================================

validate_ssh_config() {
    local ssh_config="/etc/ssh/sshd_config"
    
    if [[ ! -f "$ssh_config" ]]; then
        log_error "SSH配置文件不存在"
        return 1
    fi
    
    log_info "验证SSH配置语法..."
    
    if command -v sshd &> /dev/null; then
        if sshd -t 2>&1; then
            log_success "SSH配置语法验证通过"
            return 0
        else
            log_error "SSH配置语法验证失败"
            return 1
        fi
    fi
    return 0
}

harden_ssh() {
    log_section "SSH安全加固"
    
    local ssh_config="/etc/ssh/sshd_config"
    local ssh_port=22
    local key_configured=false
    
    if [[ ! -f "$ssh_config" ]]; then
        handle_error $ERROR_SEVERE "SSH配置文件不存在"
    fi
    
    backup_file "$ssh_config"
    
    ssh_port=$(grep -E "^Port [0-9]+" "$ssh_config" 2>/dev/null | awk '{print $2}' | head -1)
    ssh_port=${ssh_port:-22}
    
    log_info "步骤1/3: 配置用户和SSH密钥..."
    if manage_users; then
        key_configured=true
    fi
    
    log_info "步骤2/3: 配置安全参数..."
    
    if [[ -t 0 ]]; then
        echo -e "${YELLOW}修改SSH端口($ssh_port)? 输入新端口或留空: ${NC}\c"
        read -p "" new_port
        if [[ -n "$new_port" ]] && [[ "$new_port" =~ ^[0-9]+$ ]] && [[ "$new_port" -gt 1024 ]] && [[ "$new_port" -lt 65536 ]]; then
            if ! check_port_available "$new_port" "SSH"; then
                log_warning "端口检查未通过"
            else
                log_warning "请更新防火墙开放端口 $new_port"
                ssh_port=$new_port
            fi
        fi
    fi
    
    if confirm_action "是否禁用SSH root登录？"; then
        sed -i "s/^#*PermitRootLogin.*/PermitRootLogin no/" "$ssh_config"
        record_rollback_action "ssh_config" "PermitRootLogin" "sed -i 's/^PermitRootLogin.*/PermitRootLogin yes/' $ssh_config"
    fi
    
    if $key_configured; then
        if confirm_action "SSH密钥已配置，是否禁用密码认证？"; then
            sed -i "s/^#*PasswordAuthentication.*/PasswordAuthentication no/" "$ssh_config"
            record_rollback_action "ssh_config" "PasswordAuthentication" "sed -i 's/^PasswordAuthentication.*/PasswordAuthentication yes/' $ssh_config"
        fi
    else
        log_warning "SSH密钥未配置，跳过密码认证禁用"
    fi
    
    # 添加安全配置
    cat >> "$ssh_config" << EOF

# 安全加固配置
Protocol 2
MaxAuthTries 3
MaxSessions 2
LoginGraceTime 60
ClientAliveInterval 300
ClientAliveCountMax 2
PermitEmptyPasswords no
X11Forwarding no
UseDNS no
EOF
    
    log_info "步骤3/3: 验证并应用配置..."
    
    if ! validate_ssh_config; then
        handle_error $ERROR_SEVERE "SSH配置验证失败"
        execute_rollback
        return 1
    fi
    
    if systemctl restart sshd 2>&1 | tee -a "$LOG_FILE"; then
        log_success "SSH服务已重启 (端口: $ssh_port)"
    else
        handle_error $ERROR_SEVERE "SSH服务重启失败"
        return 1
    fi
    
    log "SSH加固完成"
}

# ============================================================================
# 系统加固
# ============================================================================

harden_users() {
    log_section "用户和权限加固"
    configure_password_policy
    
    log_info "锁定系统账户..."
    local system_users=("bin" "daemon" "adm" "lp" "sync" "shutdown" "halt" "mail" "news" "uucp" "operator" "games" "gopher" "ftp")
    
    for user in "${system_users[@]}"; do
        if id "$user" &>/dev/null 2>&1; then
            usermod -L -s /usr/sbin/nologin "$user" 2>/dev/null || true
        fi
    done
    
    log "用户加固完成"
}

disable_services() {
    log_section "禁用不必要的服务"
    local services_to_disable=("avahi-daemon" "cups" "bluetooth")
    
    for service in "${services_to_disable[@]}"; do
        if command -v systemctl &> /dev/null; then
            if systemctl is-enabled "$service" &>/dev/null 2>&1; then
                if confirm_action "是否禁用服务: $service？"; then
                    disable_service "$service"
                    record_rollback_action "service" "$service" "systemctl enable $service; systemctl start $service"
                    log_info "已禁用: $service"
                fi
            fi
        fi
    done
}

harden_kernel() {
    log_section "内核参数安全配置"
    local sysctl_conf="/etc/sysctl.d/99-security.conf"
    backup_file "$sysctl_conf" 2>/dev/null || true
    
    log_info "配置内核安全参数..."
    
    cat > "$sysctl_conf" << 'EOF'
# IP转发禁用
net.ipv4.ip_forward = 0
net.ipv6.conf.all.forwarding = 0

# SYN cookies保护
net.ipv4.tcp_syncookies = 1

# 忽略ICMP重定向
net.ipv4.conf.all.accept_redirects = 0
net.ipv6.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv6.conf.default.accept_redirects = 0

# 禁用源路由
net.ipv4.conf.all.accept_source_route = 0
net.ipv6.conf.all.accept_source_route = 0

# 记录可疑包
net.ipv4.conf.all.log_martians = 1
net.ipv4.conf.default.log_martians = 1

# 忽略ICMP ping请求
net.ipv4.icmp_echo_ignore_broadcasts = 1

# 反向路径过滤
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1

# SYN flood保护
net.ipv4.tcp_max_syn_backlog = 2048
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_syn_retries = 5
EOF
    
    if command -v sysctl &> /dev/null; then
        sysctl -p "$sysctl_conf" 2>&1 | tee -a "$LOG_FILE" || log_warning "应用内核参数失败"
    fi
    
    log "内核参数配置完成"
}

harden_filesystem() {
    log_section "文件系统权限加固"
    log_info "设置重要文件权限..."
    
    local files_to_protect=(
        "/etc/ssh/sshd_config:600"
        "/etc/passwd:644"
        "/etc/shadow:640"
        "/etc/group:644"
        "/etc/gshadow:600"
    )
    
    for file_perm in "${files_to_protect[@]}"; do
        local file="${file_perm%:*}"
        local perm="${file_perm#*:}"
        if [[ -f "$file" ]]; then
            chmod "$perm" "$file" 2>&1 | tee -a "$LOG_FILE"
            record_rollback_action "chmod" "$file" "chmod 644 $file"
        fi
    done
    
    log_info "SUID/SGID文件检查..."
    if command -v find &> /dev/null; then
        find / -perm /6000 -type f 2>/dev/null >> "$LOG_FILE" || true
    fi
}

collect_system_info() {
    log_section "收集系统信息"
    log_info "操作系统: $(cat /etc/os-release 2>/dev/null | grep PRETTY_NAME | cut -d= -f2 || echo "Unknown")"
    log_info "内核版本: $(uname -r)"
    log_info "主机名: $(get_hostname)"
    log_info "IP地址: $(get_ip_address)"
}

update_system() {
    log_section "系统更新"
    
    if confirm_action "是否执行系统更新？"; then
        case $PACKAGE_MANAGER in
            apt)
                apt update -y 2>&1 | tee -a "$LOG_FILE"
                apt upgrade -y 2>&1 | tee -a "$LOG_FILE"
                apt autoremove -y 2>&1 | tee -a "$LOG_FILE"
                ;;
            pacman)
                pacman -Syu --noconfirm 2>&1 | tee -a "$LOG_FILE"
                pacman -Rns $(pacman -Qdtq) --noconfirm 2>/dev/null || true
                ;;
        esac
        log "系统更新完成"
    else
        log_warning "跳过系统更新"
    fi
}

generate_report() {
    log_section "生成安全加固报告"
    
    local os_info=$(cat /etc/os-release 2>/dev/null | grep PRETTY_NAME | cut -d= -f2 || echo "Unknown")
    local kernel_info=$(uname -r)
    local hostname_info=$(get_hostname)
    
    cat > "$REPORT_FILE" << EOF
================================================================================
服务器安全加固报告
================================================================================
生成时间: $(date)
主机名: $hostname_info
操作系统: $os_info
内核版本: $kernel_info
包管理器: $PACKAGE_MANAGER

备份目录: $BACKUP_DIR
回滚目录: $ROLLBACK_DIR
日志文件: $LOG_FILE

--------------------------------------------------------------------------------
1. SSH配置
--------------------------------------------------------------------------------
$(grep -E "^(Port|PermitRootLogin|PasswordAuthentication)" /etc/ssh/sshd_config 2>/dev/null || echo "N/A")

--------------------------------------------------------------------------------
2. 防火墙状态
--------------------------------------------------------------------------------
$(case $PACKAGE_MANAGER in 
    apt) ufw status verbose 2>/dev/null ;; 
    pacman) 
        if command -v nft &> /dev/null; then nft list ruleset 2>/dev/null; 
        else iptables -L -n 2>/dev/null; fi 
    esac || echo "N/A")

--------------------------------------------------------------------------------
3. 入侵防御系统
--------------------------------------------------------------------------------
$(command -v fail2ban-client &> /dev/null && fail2ban-client status 2>/dev/null || echo "N/A")

--------------------------------------------------------------------------------
4. 已安装安全工具
--------------------------------------------------------------------------------
$(case $PACKAGE_MANAGER in 
    apt) dpkg -l 2>/dev/null | grep -E "fail2ban|ufw|auditd" | awk '{print $2 " " $3}' ;; 
    pacman) pacman -Q 2>/dev/null | grep -E "fail2ban|crowdsec|nftables|auditd" | head -10 ;; 
    esac || echo "N/A")

--------------------------------------------------------------------------------
5. AUR助手状态
--------------------------------------------------------------------------------
$(command -v yay &> /dev/null && echo "yay: 已安装" || echo "yay: 未安装")
$(command -v paru &> /dev/null && echo "paru: 已安装" || echo "paru: 未安装")

================================================================================
EOF
    
    if command -v sha256sum &> /dev/null; then
        sha256sum "$REPORT_FILE" > "${REPORT_FILE}.sha256"
    fi
    
    log_info "报告已生成: $REPORT_FILE"
}

# ============================================================================
# 主程序
# ============================================================================

main() {
    clear
    
    echo -e "${CYAN}"
    cat << "EOF"
╔══════════════════════════════════════════════════════════════╗
║       服务器安全加固脚本 (多发行版增强版)                     ║
║       v4.2 - 支持 Ubuntu + Arch Linux                        ║
║       • 多防火墙选择 (UFW/iptables/nftables)                 ║
║       • 多入侵防护 (Fail2ban/Sshguard/Crowdsec)              ║
║       • AUR助手自动安装 (yay/paru)                           ║
║       • ED25519 SSH密钥 (替代RSA)                            ║
║       • 支持 -y 参数用于非交互模式                           ║
║       • 依赖自动检查                                         ║
╚══════════════════════════════════════════════════════════════╝
EOF
    echo -e "${NC}"
    
    check_root
    detect_distribution
    check_dependencies
    setup_colors
    init_rollback
    
    log "开始服务器安全加固..."
    log_info "日志: $LOG_FILE | 备份: $BACKUP_DIR"
    
    echo -e "${YELLOW}警告: 此脚本将修改系统配置${NC}"
    
    if ! confirm_action "确认继续？"; then
        if [[ "$FORCE_YES" == "true" ]]; then
            log_info "自动模式: 继续执行加固操作"
        else
            log "用户取消"
            exit 0
        fi
    fi
    
    collect_system_info
    update_system
    harden_ssh
    configure_firewall
    install_intrusion_prevention
    harden_users
    disable_services
    harden_kernel
    harden_filesystem
    configure_auto_updates
    install_security_tools
    generate_report
    
    log_section "安全加固完成"
    
    echo -e "${GREEN}"
    cat << EOF
╔══════════════════════════════════════════════════════════════╗
║                  安全加固已完成！                            ║
╚══════════════════════════════════════════════════════════════╝

重要提醒:
• 备份: $BACKUP_DIR
• 回滚: $ROLLBACK_DIR
• 日志: $LOG_FILE
• 报告: $REPORT_FILE
• 建议重启服务器

下一步:
• 测试SSH登录
• 检查防火墙规则
• 配置入侵防御

EOF
    echo -e "${NC}"
    
    if confirm_action "是否重启服务器？"; then
        log "5秒后重启..."
        sleep 5
        reboot
    fi
}

main "$@"
