< OS 有关 4 台 Ubuntu VPSs 正在被攻击:ssh > 记录、分析、防护的过程 配置 ufw Fail2Ban iptables 保护网络上的主机

环境:

主机名地区OS
BJN北京-京东云Ubuntu24
BJT北京-腾讯云Ubuntu24
JPT东京-腾讯云Ubuntu24
USW加州Ubuntu24

所有主机 SSH 连接使用 KEY 登录

被攻击现象:disabled SSH 服务

BJN:

BJT:

JPT 与 USW 的内容与 BJN 差不多, 我用文字表述一下: 造成 SSH 服务 disabled,如果我有重启主机, SSH 就不可再连接,结果是终端不能登录。

root@usw:/etc/ssh# sudo systemctl restart ssh sudo systemctl status ssh ● ssh.service - OpenBSD Secure Shell server Loaded: loaded (/usr/lib/systemd/system/ssh.service; disabled; preset: enab led) Active: active (running) since Thu 2025-06-26 12:16:28 PDT; 54ms ago TriggeredBy: ● ssh.socket Docs: man:sshd(8) man:sshd_config(5) Process: 1175 ExecStartPre=/usr/sbin/sshd -t (code=exited, status=0/SUCCESS) Main PID: 1177 (sshd) Tasks: 1 (limit: 1071) Memory: 1.2M (peak: 1.4M) CPU: 59ms CGroup: /system.slice/ssh.service └─1177 "sshd: /usr/sbin/sshd -D [listener] 0 of 10-100 startups" Jun 26 12:16:28 usw systemd[1]: Starting ssh.service - OpenBSD Secure Shell server... Jun 26 12:16:28 usw sshd[1177]: Server listening on :: port 9922. Jun 26 12:16:28 usw systemd[1]: Started ssh.service - OpenBSD Secure Shell server.

root@jpt:~# systemctl status ssh ● ssh.service - OpenBSD Secure Shell server Loaded: loaded (/usr/lib/systemd/system/ssh.service; disabled; preset: enabled) Active: active (running) since Mon 2025-06-23 21:54:29 CST; 3 days ago TriggeredBy: ● ssh.socket Docs: man:sshd(8) man:sshd_config(5) Main PID: 662224 (sshd) Tasks: 1 (limit: 1888) Memory: 3.9M (peak: 15.5M) CPU: 3min 29.833s CGroup: /system.slice/ssh.service └─662224 "sshd: /usr/sbin/sshd -D [listener] 0 of 10-100 startups" Jun 27 03:16:48 jpt sshd[729063]: Connection closed by invalid user jenkins 206.123.145.237 port 47252 [preauth] Jun 27 03:17:01 jpt sshd[729065]: Connection closed by authenticating user root 93.123.109.117 port 51774 [preauth] Jun 27 03:17:26 jpt sshd[729075]: Connection closed by authenticating user root 45.148.10.189 port 36270 [preauth] Jun 27 03:17:26 jpt sshd[729077]: Invalid user git from 206.123.145.237 port 34648 Jun 27 03:17:26 jpt sshd[729077]: Connection closed by invalid user git 206.123.145.237 port 34648 [preauth] Jun 27 03:18:04 jpt sshd[729086]: Connection closed by authenticating user root 206.123.145.237 port 37318 [preauth] Jun 27 03:18:41 jpt sshd[729088]: Accepted publickey for root from 12.75.157.1 port 16389 ssh2: ED25519 SHA256:jpUCXR/o4OM5+8TNsIYfpJyZWHLLxghIOe36RMVEx+0 Jun 27 03:18:41 jpt sshd[729088]: pam_unix(sshd:session): session opened for user root(uid=0) by root(uid=0) Jun 27 03:18:42 jpt sshd[729090]: Invalid user hadoop from 206.123.145.237 port 56434 Jun 27 03:18:42 jpt sshd[729090]: Connection closed by invalid user hadoop 206.123.145.237 port 56434 [preauth]

USW 在多个终端里尝试登录,10钟后,总算登录进入。

分析:

主机 JPT:仅使用运营商的防火墙

SSH 更换了默认端口
SSH 使用密钥登录
SSH 密钥有口令
  • 攻击频率: 每分钟20-50次尝试
  • 攻击持续时间: 48小时不间断
  • 攻击IP数量: 50+ 个不同IP地址
  • 尝试用户名: 1000+ 个不同用户名

有组织的 SSH 暴力破解
sudo journalctl -u ssh -n 1000 | grep Invalid

结果是:256

下面是:

systemctl status sshd

输出:

 System information as of Fri Jun 27 03:35:35 AM CST 2025

  System load:  0.0                Processes:             139
  Usage of /:   68.8% of 49.10GB   Users logged in:       0
  Memory usage: 39%                IPv4 address for eth0: 10.7.0.16
  Swap usage:   0%

 * Strictly confined Kubernetes makes edge and IoT secure. Learn how MicroK8s
   just raised the bar for easy, resilient and secure K8s cluster deployment.

   https://ubuntu.com/engage/secure-kubernetes-at-the-edge

*** System restart required ***
Last login: Fri Jun 27 03:18:43 2025 from 12.75.157.1
root@jpt:~# journalctl -u ssh -f
Jun 27 03:42:05 jpt sshd[729851]: Connection closed by authenticating user root 206.123.145.237 port 35220 [preauth]
Jun 27 03:42:43 jpt sshd[729853]: Invalid user teresa from 206.123.145.237 port 48576
Jun 27 03:42:43 jpt sshd[729853]: Connection closed by invalid user teresa 206.123.145.237 port 48576 [preauth]
Jun 27 03:42:49 jpt sshd[729855]: Connection closed by authenticating user root 93.123.109.118 port 32774 [preauth]
Jun 27 03:43:00 jpt sshd[729857]: Accepted publickey for root from 15.181.97.115 port 57992 ssh2: ED25519 SHA256:jpUCXR/o4OM5+8TNsIYfpJyZWHLLxghIOe36RMVEx+0
Jun 27 03:43:00 jpt sshd[729857]: pam_unix(sshd:session): session opened for user root(uid=0) by root(uid=0)
Jun 27 03:43:21 jpt sshd[729955]: Invalid user lionel from 206.123.145.237 port 41072
Jun 27 03:43:21 jpt sshd[729955]: Connection closed by invalid user lionel 206.123.145.237 port 41072 [preauth]
Jun 27 03:43:59 jpt sshd[729957]: Invalid user server11 from 206.123.145.237 port 48786
Jun 27 03:43:59 jpt sshd[729957]: Connection closed by invalid user server11 206.123.145.237 port 48786 [preauth]
Jun 27 03:44:37 jpt sshd[729966]: Connection closed by authenticating user root 206.123.145.237 port 50302 [preauth]
Jun 27 03:45:15 jpt sshd[729976]: Invalid user jgaona from 206.123.145.237 port 46572
Jun 27 03:45:15 jpt sshd[729976]: Connection closed by invalid user jgaona 206.123.145.237 port 46572 [preauth]
Jun 27 03:45:52 jpt sshd[729979]: Connection closed by authenticating user root 93.123.109.117 port 51514 [preauth]
Jun 27 03:45:53 jpt sshd[729981]: Connection closed by authenticating user messagebus 206.123.145.237 port 41498 [preauth]
Jun 27 03:46:16 jpt sshd[729988]: Accepted publickey for root from 15.181.97.115 port 58113 ssh2: ED25519 SHA256:jpUCXR/o4OM5+8TNsIYfpJyZWHLLxghIOe36RMVEx+0
Jun 27 03:46:16 jpt sshd[729988]: pam_unix(sshd:session): session opened for user root(uid=0) by root(uid=0)
Jun 27 03:46:30 jpt sshd[730084]: Invalid user colorado from 206.123.145.237 port 54534
Jun 27 03:46:31 jpt sshd[730084]: Connection closed by invalid user colorado 206.123.145.237 port 54534 [preauth]
Jun 27 03:47:08 jpt sshd[730095]: Invalid user dbird from 206.123.145.237 port 38548
Jun 27 03:47:09 jpt sshd[730095]: Connection closed by invalid user dbird 206.123.145.237 port 38548 [preauth]
Jun 27 03:47:46 jpt sshd[730099]: Invalid user 1p from 206.123.145.237 port 34708
Jun 27 03:47:46 jpt sshd[730099]: Connection closed by invalid user 1p 206.123.145.237 port 34708 [preauth]
Jun 27 03:48:05 jpt sshd[730106]: Connection closed by authenticating user root 45.148.10.189 port 55664 [preauth]
Jun 27 03:48:24 jpt sshd[730109]: Invalid user zhangxiaomei from 206.123.145.237 port 42700
Jun 27 03:48:25 jpt sshd[730109]: Connection closed by invalid user zhangxiaomei 206.123.145.237 port 42700 [preauth]
Jun 27 03:49:02 jpt sshd[730122]: Invalid user matt from 206.123.145.237 port 57886
Jun 27 03:49:02 jpt sshd[730120]: Connection closed by authenticating user root 93.123.109.127 port 58754 [preauth]
Jun 27 03:49:03 jpt sshd[730122]: Connection closed by invalid user matt 206.123.145.237 port 57886 [preauth]
Jun 27 03:49:40 jpt sshd[730125]: Invalid user tmax from 206.123.145.237 port 40428
Jun 27 03:49:40 jpt sshd[730125]: Connection closed by invalid user tmax 206.123.145.237 port 40428 [preauth]
Jun 27 03:50:18 jpt sshd[730133]: Invalid user krzysiek from 206.123.145.237 port 38650
Jun 27 03:50:19 jpt sshd[730133]: Connection closed by invalid user krzysiek 206.123.145.237 port 38650 [preauth]
Jun 27 03:50:56 jpt sshd[730136]: Invalid user oracle from 206.123.145.237 port 58568
Jun 27 03:50:56 jpt sshd[730136]: Connection closed by invalid user oracle 206.123.145.237 port 58568 [preauth]
Jun 27 03:51:34 jpt sshd[730173]: Invalid user marekg from 206.123.145.237 port 43232
Jun 27 03:51:35 jpt sshd[730173]: Connection closed by invalid user marekg 206.123.145.237 port 43232 [preauth]
Jun 27 03:52:12 jpt sshd[730190]: Invalid user jerry from 206.123.145.237 port 38580
Jun 27 03:52:12 jpt sshd[730190]: Connection closed by invalid user jerry 206.123.145.237 port 38580 [preauth]
Jun 27 03:52:40 jpt sshd[730193]: Connection closed by authenticating user root 93.123.109.128 port 51364 [preauth]
Jun 27 03:52:42 jpt sshd[730195]: Connection closed by authenticating user root 93.123.109.115 port 44990 [preauth]
Jun 27 03:52:46 jpt sshd[730197]: Connection closed by authenticating user root 45.148.10.179 port 58018 [preauth]
Jun 27 03:52:46 jpt sshd[730198]: Connection closed by authenticating user root 45.148.10.232 port 40528 [preauth]
Jun 27 03:52:51 jpt sshd[730201]: Connection closed by authenticating user mysql 206.123.145.237 port 38632 [preauth]
Jun 27 03:53:00 jpt sshd[730203]: Invalid user jenkins from 180.168.95.234 port 41486
Jun 27 03:53:00 jpt sshd[730203]: Received disconnect from 180.168.95.234 port 41486:11: Bye Bye [preauth]
Jun 27 03:53:00 jpt sshd[730203]: Disconnected from invalid user jenkins 180.168.95.234 port 41486 [preauth]
Jun 27 03:53:28 jpt sshd[730224]: Invalid user zhaoxh from 206.123.145.237 port 33774
Jun 27 03:53:29 jpt sshd[730224]: Connection closed by invalid user zhaoxh 206.123.145.237 port 33774 [preauth]

上面的引用,我加粗了前后的时间,可以看到这台主机,正在被攻击。 很显然,对方找到了我的 SSH 使用的端口号,在不断的测试。我想统计有多少,卡住了我也在等结果。

仅是 SSH 尝试登录,就有有 一百一十万次(1,103,255 次攻击)。这不是全部,其实是当前的日志,只是从:5月11日 开始记录,之前的已经打包。下面是日志截图(仅 SSH)

因为性能上没体现出下降,所以没有留意到被攻击这么久。

当前的基础保护
  • 在运营商(腾讯云)的主机 防火墙只保留最少端口
  • 使用 SSH + 密钥 登录
  • 因为用了 iptables 维护路由策略,所有没有使用 ufw
  • 没有安装 fail2ban
下载日志,进行分析

下载速度 400KB/s 够慢的,回头要找腾旭。

文件:

这么多内容,还是扔给 AI 就帮助。

1 解决方法:

1)安装 fail2ban
sudo apt update && sudo apt install fail2ban iptables-persistent -y

清除旧的配置(这台曾用 ufw + fail2ban ,但为了支持 tailscale 改用 iptables)

sudo rm -f /var/lib/fail2ban/fail2ban.sqlite3
sudo rm -f /etc/fail2ban/jail.local
2)创建 fail2ban 使用 iptables 后端工作配置
sudo tee /etc/fail2ban/jail.local << 'EOF'
[DEFAULT]
bantime = -1
findtime = 1800
maxretry = 3
backend = auto
banaction = iptables-multiport
banaction_allports = iptables-allports

[sshd]
enabled = true
port = 9922
filter = sshd
logpath = /var/log/auth.log
backend = auto
bantime = -1
findtime = 1800
maxretry = 3
action = iptables-multiport[name=SSH, port=9922, protocol=tcp]
EOF

注:

  • 不要全抄运行!
  • SSH 使用的是 9922 端口,以你的情况更改
  • 这台用的是 iptables,没有使用 ufw,现在是“使用 iptables 后端”
  •  -1 要永久封禁
  • 使用了 iptables链(Chain),不需要在 iptables drop ip 方法
3)查看生效(状态查看)
i. 服务状态
sudo systemctl status fail2ban
ii. 查看 ssh 状态
sudo fail2ban-client status sshd
iii. 查看所有已封禁的 IP
sudo fail2ban-client banned
iv. 查看 F2J 的配置信息
sudo fail2ban-client get sshd findtime
sudo fail2ban-client get sshd maxretry  
sudo fail2ban-client get sshd bantime
v. 实时监控 SSH 攻击
sudo tail -f /var/log/auth.log | grep "Invalid user"
vi. 查看防火墙 iptables 中的 Fail2Ban 规则
sudo iptables -L f2b-sshd -n -v
sudo iptables -L INPUT -n --line-numbers | grep f2b

4)推荐使用这个 fail2ban-Chain.sh 管理脚本
#!/bin/bash

# Fail2Ban 统一管理工具
# 集成监控、分析、封禁功能
# By Dave + Claude
# Version 0.1

# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
PURPLE='\033[0;35m'
CYAN='\033[0;36m'
BOLD='\033[1m'
NC='\033[0m' # No Color

# 全局变量
SCRIPT_NAME="Fail2Ban统一管理工具"
VERSION="1.0"
LOG_FILE="/tmp/f2b_tool_$(date +%Y%m%d).log"

# 分隔线函数
print_separator() {
    echo -e "${CYAN}==========================================================${NC}"
}

print_mini_separator() {
    echo -e "${CYAN}--------------------------------------------------${NC}"
}

# 打印标题函数
print_title() {
    echo -e "${BLUE}${BOLD}=== $1 ===${NC}"
}

# 记录日志函数
log_message() {
    echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" >> "$LOG_FILE"
}

# 检查命令是否存在
check_command() {
    if ! command -v $1 &> /dev/null; then
        echo -e "${RED}错误: $1 命令未找到${NC}"
        log_message "ERROR: $1 command not found"
        exit 1
    fi
}

# 检查权限
check_permissions() {
    if [ "$EUID" -ne 0 ]; then
        echo -e "${RED}错误: 请使用sudo运行此脚本${NC}"
        exit 1
    fi
}

# 显示主菜单
show_main_menu() {
    clear
    print_separator
    echo -e "${PURPLE}${BOLD}          $SCRIPT_NAME v$VERSION          ${NC}"
    echo -e "${PURPLE}${BOLD}              $(date '+%Y-%m-%d %H:%M:%S')              ${NC}"
    print_separator
    echo -e "${CYAN}${BOLD}主菜单:${NC}"
    echo -e "  ${GREEN}1)${NC} 系统状态监控"
    echo -e "  ${GREEN}2)${NC} 智能攻击分析"
    echo -e "  ${GREEN}3)${NC} 封禁管理"
    echo -e "  ${GREEN}4)${NC} 实时监控"
    echo -e "  ${GREEN}5)${NC} 配置管理"
    echo -e "  ${GREEN}6)${NC} 日志分析"
    echo -e "  ${GREEN}7)${NC} 系统维护"
    echo -e "  ${GREEN}8)${NC} 生成报告"
    echo -e "  ${YELLOW}h)${NC} 帮助信息"
    echo -e "  ${RED}0)${NC} 退出"
    print_mini_separator
}

# 1. 系统状态监控
system_status_monitor() {
    clear
    print_title "系统状态监控"
    log_message "Starting system status monitor"

    # 检查必要命令
    check_command "fail2ban-client"
    check_command "iptables"
    check_command "systemctl"

    # Fail2Ban服务状态
    print_title "Fail2Ban 服务状态"
    if systemctl is-active --quiet fail2ban; then
        echo -e "${GREEN}✓ Fail2Ban 服务正在运行${NC}"
        uptime=$(systemctl show fail2ban --property=ActiveEnterTimestamp --value)
        echo -e "启动时间: ${uptime}"

        # 内存使用
        memory=$(systemctl show fail2ban --property=MemoryCurrent --value)
        if [ "$memory" != "[not set]" ] && [ ! -z "$memory" ]; then
            memory_mb=$((memory / 1024 / 1024))
            echo -e "内存使用: ${memory_mb}MB"
        fi
    else
        echo -e "${RED}✗ Fail2Ban 服务未运行${NC}"
        echo -e "${YELLOW}建议执行: sudo systemctl start fail2ban${NC}"
    fi
    echo

    # 所有Jail总览
    print_title "Jail 总览"
    fail2ban_status=$(fail2ban-client status 2>/dev/null)
    if [ $? -eq 0 ]; then
        echo "$fail2ban_status"
    else
        echo -e "${RED}无法获取Fail2Ban状态${NC}"
    fi
    echo

    # SSH Jail详细状态
    print_title "SSH 防护详情"
    sshd_status=$(fail2ban-client status sshd 2>/dev/null)
    if [ $? -eq 0 ]; then
        echo "$sshd_status"

        # 提取关键信息
        currently_failed=$(echo "$sshd_status" | grep "Currently failed:" | awk '{print $4}')
        total_failed=$(echo "$sshd_status" | grep "Total failed:" | awk '{print $4}')
        banned_count=$(echo "$sshd_status" | grep "Currently banned:" | awk '{print $4}')
        total_banned=$(echo "$sshd_status" | grep "Total banned:" | awk '{print $4}')

        echo
        if [ "$banned_count" -gt 0 ]; then
            echo -e "${RED}⚠ 当前有 $banned_count 个IP被封禁${NC}"
        else
            echo -e "${GREEN}✓ 当前没有IP被封禁${NC}"
        fi
        echo -e "统计信息: 当前失败 $currently_failed | 总计失败 $total_failed | 累计封禁 $total_banned"
    else
        echo -e "${YELLOW}SSH jail 未配置或未启用${NC}"
    fi
    echo

    # 防火墙规则状态
    print_title "防火墙规则检查"

    # 检查f2b-sshd链
    if iptables -L f2b-sshd -n -v &>/dev/null; then
        echo -e "${GREEN}✓ f2b-sshd 链存在${NC}"
        chain_stats=$(iptables -L f2b-sshd -n -v | grep -v "Chain\|target")
        if [ ! -z "$chain_stats" ]; then
            echo "链统计信息:"
            echo "$chain_stats"

            # 统计通过的数据包
            total_packets=$(echo "$chain_stats" | awk '{sum += $1} END {print sum}')
            total_bytes=$(echo "$chain_stats" | awk '{sum += $2} END {print sum}')
            echo -e "总数据包: ${YELLOW}$total_packets${NC} 个, 总字节: ${YELLOW}$total_bytes${NC} 字节"
        fi
    else
        echo -e "${RED}✗ f2b-sshd 链不存在${NC}"
    fi

    # 检查INPUT链中的fail2ban规则
    f2b_rules=$(iptables -L INPUT -n --line-numbers | grep "f2b")
    if [ ! -z "$f2b_rules" ]; then
        echo -e "${GREEN}✓ INPUT链中的Fail2Ban规则:${NC}"
        echo "$f2b_rules"
    else
        echo -e "${YELLOW}⚠ INPUT链中未找到Fail2Ban规则${NC}"
    fi
    echo

    # 系统建议
    print_title "系统建议"

    # 检查配置
    if [ -f "/etc/fail2ban/jail.local" ]; then
        echo -e "${GREEN}✓ 自定义配置文件存在${NC}"
    else
        echo -e "${YELLOW}⚠ 建议创建 /etc/fail2ban/jail.local 配置文件${NC}"
    fi

    # 检查日志文件
    if [ -f "/var/log/fail2ban.log" ]; then
        log_size=$(du -h /var/log/fail2ban.log | cut -f1)
        echo -e "Fail2Ban日志大小: ${log_size}"
    fi

    # 检查SSH端口
    ssh_port=$(netstat -tlnp 2>/dev/null | grep sshd | awk '{print $4}' | cut -d: -f2 | head -1)
    if [ ! -z "$ssh_port" ] && [ "$ssh_port" != "22" ]; then
        echo -e "${GREEN}✓ SSH端口已修改为: $ssh_port${NC}"
    else
        echo -e "${YELLOW}⚠ 建议修改SSH默认端口22${NC}"
    fi

    log_message "System status monitor completed"
}

# 2. 智能攻击分析
intelligent_attack_analysis() {
    clear
    print_title "智能攻击分析"
    log_message "Starting intelligent attack analysis"

    # 检查Fail2Ban是否运行
    if ! systemctl is-active --quiet fail2ban; then
        echo -e "${RED}错误: Fail2Ban服务未运行${NC}"
        return 1
    fi

    # 分析时间范围选择
    echo -e "${CYAN}选择分析时间范围:${NC}"
    echo "1) 最近1小时"
    echo "2) 最近24小时"
    echo "3) 最近7天"
    echo "4) 自定义日期"
    read -p "请选择 [1-4]: " time_choice

    case $time_choice in
        1)
            time_filter="$(date +'%b %d %H')"
            echo -e "${YELLOW}分析最近1小时的攻击...${NC}"
            ;;
        2)
            time_filter="$(date +'%b %d')"
            echo -e "${YELLOW}分析最近24小时的攻击...${NC}"
            ;;
        3)
            echo -e "${YELLOW}分析最近7天的攻击...${NC}"
            time_filter=""
            ;;
        4)
            read -p "请输入日期 (格式: Jun 27): " custom_date
            time_filter="$custom_date"
            echo -e "${YELLOW}分析 $custom_date 的攻击...${NC}"
            ;;
        *)
            time_filter="$(date +'%b %d')"
            echo -e "${YELLOW}默认分析最近24小时的攻击...${NC}"
            ;;
    esac

    echo

    # 分析攻击者
    if [ -z "$time_filter" ]; then
        # 分析所有日志
        ATTACKERS=$(grep -E "Invalid user|Failed password" /var/log/auth.log | \
            grep -oE '([0-9]{1,3}\.){3}[0-9]{1,3}' | \
            sort | uniq -c | sort -nr)
    else
        # 分析指定时间的日志
        ATTACKERS=$(grep "$time_filter" /var/log/auth.log | \
            grep -E "Invalid user|Failed password" | \
            grep -oE '([0-9]{1,3}\.){3}[0-9]{1,3}' | \
            sort | uniq -c | sort -nr)
    fi

    if [ -z "$ATTACKERS" ]; then
        echo -e "${GREEN}✓ 指定时间范围内无攻击记录${NC}"
        return 0
    fi

    echo -e "${RED}发现以下攻击者IP (攻击次数):${NC}"
    echo "$ATTACKERS" | head -20  # 显示前20个

    total_attacks=$(echo "$ATTACKERS" | awk '{sum += $1} END {print sum}')
    unique_ips=$(echo "$ATTACKERS" | wc -l)
    echo
    echo -e "${YELLOW}统计: 共 $unique_ips 个唯一IP,总计 $total_attacks 次攻击${NC}"
    echo

    # 检查封禁状态
    print_title "封禁状态检查"

    # 获取当前已封禁的IP列表
    BANNED_IPS=$(fail2ban-client get sshd banip 2>/dev/null)

    # 检查每个攻击者IP
    NEW_ATTACKERS=""
    BANNED_COUNT=0
    UNBANNED_COUNT=0

    while read -r count ip; do
        if [ ! -z "$ip" ]; then
            if echo "$BANNED_IPS" | grep -q "$ip"; then
                echo -e "${GREEN}✓ $ip (已封禁, 攻击${count}次)${NC}"
                ((BANNED_COUNT++))
            else
                echo -e "${RED}✗ $ip (未封禁, 攻击${count}次)${NC}"
                NEW_ATTACKERS="$NEW_ATTACKERS $ip"
                ((UNBANNED_COUNT++))
            fi
        fi
    done <<< "$ATTACKERS"

    echo
    echo -e "${CYAN}封禁统计: 已封禁 $BANNED_COUNT 个, 未封禁 $UNBANNED_COUNT 个${NC}"

    # 网段分析
    print_title "网段分析"

    NETWORKS=$(echo "$ATTACKERS" | awk '{print $2}' | \
        sed 's/\.[0-9]*$/\.0\/24/' | sort | uniq -c | sort -nr)

    if [ ! -z "$NETWORKS" ]; then
        echo "可疑网段分布 (IP数量):"
        echo "$NETWORKS" | head -10
        echo

        # 高危网段警告
        echo -e "${YELLOW}高危网段 (超过5个攻击IP):${NC}"
        echo "$NETWORKS" | while read count network; do
            if [ "$count" -gt 5 ]; then
                echo -e "${RED}  $network - $count 个攻击IP${NC}"
            fi
        done
    fi

    # 地理位置分析(简单版本)
    print_title "攻击源分析"

    # 按IP段分析可能的地理位置
    echo -e "${CYAN}主要攻击源IP段:${NC}"
    echo "$ATTACKERS" | head -10 | while read count ip; do
        first_octet=$(echo $ip | cut -d. -f1)
        case $first_octet in
            1|2|3|4|5|6|7|8|9|10|11|12|13|14|15)
                region="美国/加拿大"
                ;;
            46|47|49|58|59|60|61|103|106|111|112|113|114|115|116|117|118|119|120|121|122|123|124|125)
                region="亚太地区"
                ;;
            80|81|82|83|84|85|86|87|88|89|90|91|92|93|94|95)
                region="欧洲"
                ;;
            200|201|202|203)
                region="亚太/南美"
                ;;
            *)
                region="其他地区"
                ;;
        esac
        echo -e "  $ip (${count}次) - ${region}"
    done

    # 询问是否封禁新攻击者
    if [ ! -z "$NEW_ATTACKERS" ]; then
        echo
        print_mini_separator
        echo -e "${YELLOW}发现 $UNBANNED_COUNT 个未封禁的攻击者${NC}"
        read -p "是否使用Fail2Ban封禁这些IP? [y/N]: " ban_choice

        if [[ $ban_choice =~ ^[Yy]$ ]]; then
            echo -e "${YELLOW}开始封禁新攻击者...${NC}"

            banned_success=0
            banned_failed=0

            for ip in $NEW_ATTACKERS; do
                echo -n "封禁 $ip ... "
                if fail2ban-client set sshd banip "$ip" 2>/dev/null; then
                    echo -e "${GREEN}成功${NC}"
                    ((banned_success++))
                    log_message "Successfully banned IP: $ip"
                else
                    echo -e "${RED}失败${NC}"
                    ((banned_failed++))
                    log_message "Failed to ban IP: $ip"
                fi
            done

            echo
            echo -e "${GREEN}封禁完成: 成功 $banned_success 个, 失败 $banned_failed 个${NC}"
        fi
    fi

    log_message "Intelligent attack analysis completed"
}

# 3. 封禁管理
ban_management() {
    clear
    print_title "封禁管理"

    while true; do
        echo -e "${CYAN}封禁管理选项:${NC}"
        echo "1) 查看封禁列表"
        echo "2) 手动封禁IP"
        echo "3) 解封IP"
        echo "4) 批量封禁"
        echo "5) 清空所有封禁"
        echo "6) 封禁网段"
        echo "0) 返回主菜单"
        echo
        read -p "请选择操作 [0-6]: " ban_choice

        case $ban_choice in
            1)
                echo -e "${BLUE}=== 当前封禁列表 ===${NC}"
                fail2ban-client status sshd
                echo
                banned_ips=$(fail2ban-client get sshd banip 2>/dev/null)
                if [ ! -z "$banned_ips" ]; then
                    echo -e "${CYAN}详细封禁IP:${NC}"
                    echo "$banned_ips" | tr ' ' '\n' | sort
                fi
                ;;
            2)
                read -p "请输入要封禁的IP地址: " ip
                if [[ $ip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
                    if fail2ban-client set sshd banip "$ip" 2>/dev/null; then
                        echo -e "${GREEN}IP $ip 已被封禁${NC}"
                        log_message "Manually banned IP: $ip"
                    else
                        echo -e "${RED}封禁失败${NC}"
                    fi
                else
                    echo -e "${RED}无效的IP地址格式${NC}"
                fi
                ;;
            3)
                current_bans=$(fail2ban-client get sshd banip 2>/dev/null)
                if [ -z "$current_bans" ]; then
                    echo -e "${YELLOW}当前没有被封禁的IP${NC}"
                else
                    echo -e "${CYAN}当前被封禁的IP:${NC}"
                    echo "$current_bans" | tr ' ' '\n' | nl
                    echo
                    read -p "请输入要解封的IP地址: " ip
                    if [[ $ip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
                        if fail2ban-client set sshd unbanip "$ip" 2>/dev/null; then
                            echo -e "${GREEN}IP $ip 已被解封${NC}"
                            log_message "Manually unbanned IP: $ip"
                        else
                            echo -e "${RED}解封失败(IP可能未被封禁)${NC}"
                        fi
                    else
                        echo -e "${RED}无效的IP地址格式${NC}"
                    fi
                fi
                ;;
            4)
                echo -e "${YELLOW}批量封禁模式${NC}"
                echo "请输入IP地址,每行一个,输入空行结束:"
                ips=()
                while read -r line; do
                    if [ -z "$line" ]; then
                        break
                    fi
                    if [[ $line =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
                        ips+=("$line")
                    else
                        echo -e "${RED}跳过无效IP: $line${NC}"
                    fi
                done

                if [ ${#ips[@]} -gt 0 ]; then
                    echo -e "${YELLOW}准备封禁 ${#ips[@]} 个IP...${NC}"
                    for ip in "${ips[@]}"; do
                        if fail2ban-client set sshd banip "$ip" 2>/dev/null; then
                            echo -e "${GREEN}✓ $ip${NC}"
                        else
                            echo -e "${RED}✗ $ip${NC}"
                        fi
                    done
                    log_message "Batch banned ${#ips[@]} IPs"
                fi
                ;;
            5)
                current_bans=$(fail2ban-client get sshd banip 2>/dev/null)
                if [ -z "$current_bans" ]; then
                    echo -e "${YELLOW}当前没有被封禁的IP${NC}"
                else
                    ban_count=$(echo "$current_bans" | wc -w)
                    echo -e "${RED}警告: 将解封所有 $ban_count 个IP${NC}"
                    read -p "确认清空所有封禁? [y/N]: " confirm
                    if [[ $confirm =~ ^[Yy]$ ]]; then
                        for ip in $current_bans; do
                            fail2ban-client set sshd unbanip "$ip" 2>/dev/null
                        done
                        echo -e "${GREEN}所有封禁已清空${NC}"
                        log_message "Cleared all bans"
                    fi
                fi
                ;;
            6)
                read -p "请输入要封禁的网段 (如: 192.168.1.0/24): " network
                if [[ $network =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}/[0-9]{1,2}$ ]]; then
                    echo -e "${YELLOW}注意: 网段封禁将直接添加到iptables规则${NC}"
                    read -p "确认封禁网段 $network? [y/N]: " confirm
                    if [[ $confirm =~ ^[Yy]$ ]]; then
                        if iptables -I INPUT -s "$network" -j DROP 2>/dev/null; then
                            echo -e "${GREEN}网段 $network 已被封禁${NC}"
                            log_message "Banned network: $network"
                        else
                            echo -e "${RED}封禁网段失败${NC}"
                        fi
                    fi
                else
                    echo -e "${RED}无效的网段格式${NC}"
                fi
                ;;
            0)
                return
                ;;
            *)
                echo -e "${RED}无效选择${NC}"
                ;;
        esac
        echo
        read -p "按回车键继续..."
        echo
    done
}

# 4. 实时监控
real_time_monitor() {
    clear
    print_title "实时监控"

    echo -e "${CYAN}实时监控选项:${NC}"
    echo "1) 监控SSH攻击"
    echo "2) 监控Fail2Ban日志"
    echo "3) 监控系统登录"
    echo "4) 综合监控面板"
    echo "0) 返回主菜单"
    echo
    read -p "请选择监控类型 [0-4]: " monitor_choice

    case $monitor_choice in
        1)
            echo -e "${YELLOW}开始监控SSH攻击 (按Ctrl+C停止)${NC}"
            echo -e "${CYAN}格式: 时间 | 攻击类型 | IP地址${NC}"
            print_mini_separator
            tail -f /var/log/auth.log | grep --line-buffered -E "Invalid user|Failed password" | \
                while read line; do
                    echo -e "${RED}$line${NC}"
                done
            ;;
        2)
            echo -e "${YELLOW}开始监控Fail2Ban日志 (按Ctrl+C停止)${NC}"
            print_mini_separator
            tail -f /var/log/fail2ban.log | \
                while read line; do
                    if echo "$line" | grep -q "Ban"; then
                        echo -e "${RED}$line${NC}"
                    elif echo "$line" | grep -q "Unban"; then
                        echo -e "${GREEN}$line${NC}"
                    else
                        echo -e "${CYYAN}$line${NC}"
                    fi
                done
            ;;
        3)
            echo -e "${YELLOW}开始监控系统登录 (按Ctrl+C停止)${NC}"
            print_mini_separator
            tail -f /var/log/auth.log | grep --line-buffered -E "Accepted|session opened" | \
                while read line; do
                    echo -e "${GREEN}$line${NC}"
                done
            ;;
        4)
            echo -e "${YELLOW}综合监控面板 (按Ctrl+C停止)${NC}"
            print_mini_separator

            # 创建临时文件用于监控数据
            temp_dir="/tmp/f2b_monitor_$$"
            mkdir -p "$temp_dir"

            # 后台监控进程
            tail -f /var/log/auth.log | grep --line-buffered "Invalid user" > "$temp_dir/attacks" &
            attack_pid=$!

            tail -f /var/log/fail2ban.log | grep --line-buffered "Ban" > "$temp_dir/bans" &
            ban_pid=$!

            # 监控循环
            trap "kill $attack_pid $ban_pid 2>/dev/null; rm -rf $temp_dir; exit" INT

            attack_count=0
            ban_count=0

            while true; do
                clear
                echo -e "${PURPLE}=== 综合监控面板 ($(date)) ===${NC}"
                echo

                # 当前状态
                current_status=$(fail2ban-client status sshd 2>/dev/null)
                if [ $? -eq 0 ]; then
                    echo "$current_status"
                fi
                echo

                # 实时计数
                if [ -f "$temp_dir/attacks" ]; then
                    new_attacks=$(wc -l < "$temp_dir/attacks" 2>/dev/null || echo 0)
                    if [ "$new_attacks" -gt "$attack_count" ]; then
                        echo -e "${RED}新攻击: $((new_attacks - attack_count)) 次${NC}"
                        attack_count=$new_attacks
                    fi
                fi

                if [ -f "$temp_dir/bans" ]; then
                    new_bans=$(wc -l < "$temp_dir/bans" 2>/dev/null || echo 0)
                    if [ "$new_bans" -gt "$ban_count" ]; then
                        echo -e "${GREEN}新封禁: $((new_bans - ban_count)) 个${NC}"
                        ban_count=$new_bans
                    fi
                fi

                echo -e "${CYAN}按Ctrl+C停止监控${NC}"
                sleep 5
            done
            ;;
        0)
            return
            ;;
        *)
            echo -e "${RED}无效选择${NC}"
            ;;
    esac
}

# 5. 配置管理
config_management() {
    clear
    print_title "配置管理"

    while true; do
        echo -e "${CYAN}配置管理选项:${NC}"
        echo "1) 查看当前配置"
        echo "2) 编辑jail配置"
        echo "3) 重载配置"
        echo "4) 备份配置"
        echo "5) 恢复配置"
        echo "6) 配置向导"
        echo "0) 返回主菜单"
        echo
        read -p "请选择操作 [0-6]: " config_choice

        case $config_choice in
            1)
                echo -e "${BLUE}=== 当前配置 ===${NC}"
                if [ -f "/etc/fail2ban/jail.local" ]; then
                    echo -e "${GREEN}jail.local 配置:${NC}"
                    cat /etc/fail2ban/jail.local
                else
                    echo -e "${YELLOW}未找到 jail.local 配置文件${NC}"
                fi
                echo
                echo -e "${CYAN}当前jail参数:${NC}"
                fail2ban-client get sshd findtime 2>/dev/null && echo
                fail2ban-client get sshd maxretry 2>/dev/null && echo
                fail2ban-client get sshd bantime 2>/dev/null && echo
                ;;
            2)
                if [ -f "/etc/fail2ban/jail.local" ]; then
                    echo -e "${YELLOW}即将编辑 jail.local 配置文件${NC}"
                    read -p "按回车键继续编辑..."
                    nano /etc/fail2ban/jail.local
                else
                    echo -e "${YELLOW}jail.local 不存在,是否创建? [y/N]: ${NC}"
                    read create_choice
                    if [[ $create_choice =~ ^[Yy]$ ]]; then
                        echo -e "${YELLOW}创建基础配置文件...${NC}"
                        cat > /etc/fail2ban/jail.local << 'EOF'
[DEFAULT]
bantime = -1
findtime = 600
maxretry = 1
backend = auto
banaction = iptables-multiport
banaction_allports = iptables-allports

[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
backend = auto
bantime = -1
findtime = 600
maxretry = 1
action = iptables-multiport[name=SSH, port=ssh, protocol=tcp]
EOF
                        echo -e "${GREEN}基础配置文件已创建${NC}"
                        read -p "是否现在编辑? [y/N]: " edit_choice
                        if [[ $edit_choice =~ ^[Yy]$ ]]; then
                            nano /etc/fail2ban/jail.local
                        fi
                    fi
                fi
                ;;
            3)
                echo -e "${YELLOW}重载Fail2Ban配置...${NC}"
                if fail2ban-client reload 2>/dev/null; then
                    echo -e "${GREEN}配置重载成功${NC}"
                    log_message "Configuration reloaded"
                else
                    echo -e "${RED}配置重载失败${NC}"
                fi
                ;;
            4)
                backup_dir="/root/fail2ban_backups"
                mkdir -p "$backup_dir"
                backup_file="$backup_dir/fail2ban_backup_$(date +%Y%m%d_%H%M%S).tar.gz"

                echo -e "${YELLOW}创建配置备份...${NC}"
                tar -czf "$backup_file" /etc/fail2ban/ 2>/dev/null
                if [ $? -eq 0 ]; then
                    echo -e "${GREEN}备份创建成功: $backup_file${NC}"
                    log_message "Configuration backup created: $backup_file"
                else
                    echo -e "${RED}备份创建失败${NC}"
                fi

                # 显示现有备份
                echo -e "${CYAN}现有备份文件:${NC}"
                ls -lh "$backup_dir"/*.tar.gz 2>/dev/null || echo "无备份文件"
                ;;
            5)
                backup_dir="/root/fail2ban_backups"
                if [ -d "$backup_dir" ]; then
                    backups=$(ls "$backup_dir"/*.tar.gz 2>/dev/null)
                    if [ ! -z "$backups" ]; then
                        echo -e "${CYAN}可用的备份文件:${NC}"
                        ls -1 "$backup_dir"/*.tar.gz | nl
                        echo
                        read -p "请输入要恢复的备份文件编号: " backup_num

                        backup_file=$(ls -1 "$backup_dir"/*.tar.gz | sed -n "${backup_num}p")
                        if [ ! -z "$backup_file" ]; then
                            echo -e "${RED}警告: 这将覆盖当前配置${NC}"
                            read -p "确认恢复备份? [y/N]: " confirm
                            if [[ $confirm =~ ^[Yy]$ ]]; then
                                echo -e "${YELLOW}恢复备份中...${NC}"
                                tar -xzf "$backup_file" -C / 2>/dev/null
                                if [ $? -eq 0 ]; then
                                    echo -e "${GREEN}备份恢复成功${NC}"
                                    echo -e "${YELLOW}重启Fail2Ban以应用恢复的配置...${NC}"
                                    systemctl restart fail2ban
                                    log_message "Configuration restored from: $backup_file"
                                else
                                    echo -e "${RED}备份恢复失败${NC}"
                                fi
                            fi
                        else
                            echo -e "${RED}无效的备份文件编号${NC}"
                        fi
                    else
                        echo -e "${YELLOW}没有找到备份文件${NC}"
                    fi
                else
                    echo -e "${YELLOW}备份目录不存在${NC}"
                fi
                ;;
            6)
                echo -e "${BLUE}=== Fail2Ban 配置向导 ===${NC}"
                echo

                # SSH端口检测
                ssh_port=$(netstat -tlnp 2>/dev/null | grep sshd | awk '{print $4}' | cut -d: -f2 | head -1)
                if [ -z "$ssh_port" ]; then
                    read -p "请输入SSH端口 [默认: 22]: " ssh_port
                    ssh_port=${ssh_port:-22}
                fi
                echo -e "检测到SSH端口: ${GREEN}$ssh_port${NC}"

                # 封禁时间配置
                echo
                echo -e "${CYAN}封禁时间配置:${NC}"
                echo "1) 永久封禁 (推荐)"
                echo "2) 1小时"
                echo "3) 24小时"
                echo "4) 7天"
                echo "5) 自定义"
                read -p "请选择封禁时间 [1-5]: " bantime_choice

                case $bantime_choice in
                    1) bantime="-1" ;;
                    2) bantime="3600" ;;
                    3) bantime="86400" ;;
                    4) bantime="604800" ;;
                    5)
                        read -p "请输入封禁时间(秒): " bantime
                        if ! [[ "$bantime" =~ ^[0-9]+$ ]]; then
                            bantime="-1"
                        fi
                        ;;
                    *) bantime="-1" ;;
                esac

                # 失败次数配置
                echo
                read -p "失败多少次后封禁 [默认: 1]: " maxretry
                maxretry=${maxretry:-1}

                # 时间窗口配置
                echo
                read -p "检测时间窗口(秒) [默认: 600]: " findtime
                findtime=${findtime:-600}

                # 生成配置
                echo
                echo -e "${YELLOW}生成配置文件...${NC}"

                cat > /etc/fail2ban/jail.local << EOF
[DEFAULT]
bantime = $bantime
findtime = $findtime
maxretry = $maxretry
backend = auto
banaction = iptables-multiport
banaction_allports = iptables-allports

[sshd]
enabled = true
port = $ssh_port
filter = sshd
logpath = /var/log/auth.log
backend = auto
bantime = $bantime
findtime = $findtime
maxretry = $maxretry
action = iptables-multiport[name=SSH, port=$ssh_port, protocol=tcp]
EOF

                echo -e "${GREEN}配置文件已生成${NC}"
                echo
                echo -e "${CYAN}配置摘要:${NC}"
                echo "SSH端口: $ssh_port"
                echo "封禁时间: $bantime 秒"
                echo "失败次数: $maxretry 次"
                echo "时间窗口: $findtime 秒"
                echo

                read -p "是否重启Fail2Ban应用新配置? [Y/n]: " restart_choice
                if [[ ! $restart_choice =~ ^[Nn]$ ]]; then
                    echo -e "${YELLOW}重启Fail2Ban...${NC}"
                    systemctl restart fail2ban
                    echo -e "${GREEN}Fail2Ban已重启${NC}"
                    log_message "Applied new configuration via wizard"
                fi
                ;;
            0)
                return
                ;;
            *)
                echo -e "${RED}无效选择${NC}"
                ;;
        esac
        echo
        read -p "按回车键继续..."
        echo
    done
}

# 6. 日志分析
log_analysis() {
    clear
    print_title "日志分析"

    while true; do
        echo -e "${CYAN}日志分析选项:${NC}"
        echo "1) 攻击趋势分析"
        echo "2) 顶级攻击者"
        echo "3) 攻击方式分析"
        echo "4) 时间段分析"
        echo "5) 地理分布分析"
        echo "6) 导出分析报告"
        echo "0) 返回主菜单"
        echo
        read -p "请选择分析类型 [0-6]: " analysis_choice

        case $analysis_choice in
            1)
                echo -e "${BLUE}=== 攻击趋势分析 ===${NC}"
                echo

                # 按天统计攻击
                echo -e "${CYAN}最近7天攻击统计:${NC}"
                for i in {6..0}; do
                    date_str=$(date -d "$i days ago" +'%b %d')
                    attack_count=$(grep "$date_str" /var/log/auth.log 2>/dev/null | \
                        grep -c -E "Invalid user|Failed password")
                    echo "$date_str: $attack_count 次攻击"
                done

                echo
                # 按小时统计今日攻击
                echo -e "${CYAN}今日每小时攻击统计:${NC}"
                today=$(date +'%b %d')
                for hour in {00..23}; do
                    attack_count=$(grep "$today $hour:" /var/log/auth.log 2>/dev/null | \
                        grep -c -E "Invalid user|Failed password")
                    if [ $attack_count -gt 0 ]; then
                        printf "%s %s:00 - %d 次攻击\n" "$today" "$hour" "$attack_count"
                    fi
                done
                ;;
            2)
                echo -e "${BLUE}=== 顶级攻击者分析 ===${NC}"
                echo

                # 最活跃的攻击IP
                echo -e "${CYAN}攻击次数最多的IP (前20):${NC}"
                grep -E "Invalid user|Failed password" /var/log/auth.log | \
                    grep -oE '([0-9]{1,3}\.){3}[0-9]{1,3}' | \
                    sort | uniq -c | sort -nr | head -20 | \
                    while read count ip; do
                        # 检查是否已被封禁
                        if fail2ban-client get sshd banip 2>/dev/null | grep -q "$ip"; then
                            status="${GREEN}(已封禁)${NC}"
                        else
                            status="${RED}(未封禁)${NC}"
                        fi
                        printf "%-6d %s %s\n" "$count" "$ip" "$status"
                    done

                echo
                # 最常被尝试的用户名
                echo -e "${CYAN}最常被尝试的用户名 (前15):${NC}"
                grep "Invalid user" /var/log/auth.log | \
                    sed 's/.*Invalid user \([^ ]*\) .*/\1/' | \
                    sort | uniq -c | sort -nr | head -15
                ;;
            3)
                echo -e "${BLUE}=== 攻击方式分析 ===${NC}"
                echo

                # 攻击类型统计
                invalid_user_count=$(grep -c "Invalid user" /var/log/auth.log 2>/dev/null)
                failed_password_count=$(grep -c "Failed password" /var/log/auth.log 2>/dev/null)

                echo -e "${CYAN}攻击类型分布:${NC}"
                echo "无效用户名攻击: $invalid_user_count 次"
                echo "密码错误攻击: $failed_password_count 次"

                total_attacks=$((invalid_user_count + failed_password_count))
                if [ $total_attacks -gt 0 ]; then
                    invalid_percent=$((invalid_user_count * 100 / total_attacks))
                    failed_percent=$((failed_password_count * 100 / total_attacks))
                    echo "无效用户名占比: ${invalid_percent}%"
                    echo "密码错误占比: ${failed_percent}%"
                fi

                echo
                # 常见攻击模式
                echo -e "${CYAN}常见攻击用户名模式:${NC}"
                grep "Invalid user" /var/log/auth.log | \
                    sed 's/.*Invalid user \([^ ]*\) .*/\1/' | \
                    grep -E '^(admin|root|user|test|guest|oracle|postgres|mysql|ftp|mail|www)' | \
                    sort | uniq -c | sort -nr | head -10
                ;;
            4)
                echo -e "${BLUE}=== 时间段分析 ===${NC}"
                echo

                read -p "请输入分析日期 (格式: Jun 27, 回车=今天): " analysis_date
                if [ -z "$analysis_date" ]; then
                    analysis_date=$(date +'%b %d')
                fi

                echo -e "${CYAN}$analysis_date 的攻击时间分布:${NC}"

                # 按2小时时段统计
                for start_hour in 00 02 04 06 08 10 12 14 16 18 20 22; do
                    end_hour=$(printf "%02d" $((10#$start_hour + 2)))
                    if [ $end_hour -gt 23 ]; then
                        end_hour="23"
                    fi

                    attack_count=$(grep "$analysis_date" /var/log/auth.log 2>/dev/null | \
                        awk -v start="$start_hour" -v end="$end_hour" '
                        {
                            time_part = $3
                            split(time_part, time_array, ":")
                            hour = time_array[1]
                            if (hour >= start && hour < end) count++
                        }
                        END {print count+0}')

                    if [ $attack_count -gt 0 ]; then
                        printf "%s:00-%s:59: %d 次攻击\n" "$start_hour" "$end_hour" "$attack_count"
                    fi
                done
                ;;
            5)
                echo -e "${BLUE}=== 地理分布分析 ===${NC}"
                echo

                # 简单的地理位置分析(基于IP段)
                echo -e "${CYAN}攻击源地区分布 (基于IP段):${NC}"

                grep -E "Invalid user|Failed password" /var/log/auth.log | \
                    grep -oE '([0-9]{1,3}\.){3}[0-9]{1,3}' | \
                    sort | uniq | \
                    while read ip; do
                        first_octet=$(echo $ip | cut -d. -f1)
                        case $first_octet in
                            1|2|3|4|5|6|7|8|9|10|11|12|13|14|15)
                                echo "北美"
                                ;;
                            46|47|49|58|59|60|61|103|106|111|112|113|114|115|116|117|118|119|120|121|122|123|124|125)
                                echo "亚太"
                                ;;
                            80|81|82|83|84|85|86|87|88|89|90|91|92|93|94|95)
                                echo "欧洲"
                                ;;
                            200|201|202|203)
                                echo "南美/亚太"
                                ;;
                            *)
                                echo "其他"
                                ;;
                        esac
                    done | sort | uniq -c | sort -nr

                echo
                echo -e "${CYAN}主要攻击国家/地区 (IP段分析):${NC}"
                grep -E "Invalid user|Failed password" /var/log/auth.log | \
                    grep -oE '([0-9]{1,3}\.){3}[0-9]{1,3}' | \
                    sort | uniq -c | sort -nr | head -10 | \
                    while read count ip; do
                        # 简单的国家判断
                        first_two=$(echo $ip | cut -d. -f1-2)
                        case $first_two in
                            "103.171"|"103.183"|"103.175")
                                country="可能来自东南亚"
                                ;;
                            "206.123"|"134.122")
                                country="可能来自北美"
                                ;;
                            "93.123"|"87.240"|"195.178")
                                country="可能来自欧洲"
                                ;;
                            "115.246"|"119.209"|"123.59")
                                country="可能来自中国"
                                ;;
                            *)
                                country="未知地区"
                                ;;
                        esac
                        printf "%-6d %s (%s)\n" "$count" "$ip" "$country"
                    done
                ;;
            6)
                echo -e "${BLUE}=== 导出分析报告 ===${NC}"

                report_file="/tmp/fail2ban_analysis_$(date +%Y%m%d_%H%M%S).txt"

                echo -e "${YELLOW}正在生成详细分析报告...${NC}"

                {
                    echo "Fail2Ban 安全分析报告"
                    echo "生成时间: $(date)"
                    echo "服务器: $(hostname)"
                    echo "========================================"
                    echo

                    echo "1. 系统状态"
                    echo "------------"
                    systemctl status fail2ban --no-pager -l
                    echo
                    fail2ban-client status sshd 2>/dev/null
                    echo

                    echo "2. 攻击统计"
                    echo "----------"
                    total_invalid=$(grep -c "Invalid user" /var/log/auth.log 2>/dev/null)
                    total_failed=$(grep -c "Failed password" /var/log/auth.log 2>/dev/null)
                    total_attacks=$((total_invalid + total_failed))

                    echo "总攻击次数: $total_attacks"
                    echo "无效用户名: $total_invalid"
                    echo "密码错误: $total_failed"
                    echo

                    echo "3. 顶级攻击者 (前20)"
                    echo "------------------"
                    grep -E "Invalid user|Failed password" /var/log/auth.log | \
                        grep -oE '([0-9]{1,3}\.){3}[0-9]{1,3}' | \
                        sort | uniq -c | sort -nr | head -20
                    echo

                    echo "4. 最近7天攻击趋势"
                    echo "----------------"
                    for i in {6..0}; do
                        date_str=$(date -d "$i days ago" +'%b %d')
                        attack_count=$(grep "$date_str" /var/log/auth.log 2>/dev/null | \
                            grep -c -E "Invalid user|Failed password")
                        echo "$date_str: $attack_count 次"
                    done
                    echo

                    echo "5. 常见攻击用户名"
                    echo "---------------"
                    grep "Invalid user" /var/log/auth.log | \
                        sed 's/.*Invalid user \([^ ]*\) .*/\1/' | \
                        sort | uniq -c | sort -nr | head -15
                    echo

                    echo "6. 当前封禁列表"
                    echo "-------------"
                    fail2ban-client get sshd banip 2>/dev/null | tr ' ' '\n' | sort
                    echo

                    echo "7. 防火墙规则"
                    echo "------------"
                    iptables -L INPUT -n --line-numbers | grep -E "f2b|fail2ban"
                    echo

                } > "$report_file"

                echo -e "${GREEN}报告已生成: $report_file${NC}"
                echo -e "${CYAN}报告大小: $(du -h "$report_file" | cut -f1)${NC}"

                read -p "是否查看报告? [y/N]: " view_choice
                if [[ $view_choice =~ ^[Yy]$ ]]; then
                    less "$report_file"
                fi

                log_message "Analysis report generated: $report_file"
                ;;
            0)
                return
                ;;
            *)
                echo -e "${RED}无效选择${NC}"
                ;;
        esac
        echo
        read -p "按回车键继续..."
        echo
    done
}

# 7. 系统维护
system_maintenance() {
    clear
    print_title "系统维护"

    while true; do
        echo -e "${CYAN}系统维护选项:${NC}"
        echo "1) 服务管理"
        echo "2) 日志清理"
        echo "3) 规则优化"
        echo "4) 性能检查"
        echo "5) 安全加固"
        echo "6) 系统健康检查"
        echo "0) 返回主菜单"
        echo
        read -p "请选择维护操作 [0-6]: " maintenance_choice

        case $maintenance_choice in
            1)
                echo -e "${BLUE}=== 服务管理 ===${NC}"
                echo
                echo "1) 启动Fail2Ban"
                echo "2) 停止Fail2Ban"
                echo "3) 重启Fail2Ban"
                echo "4) 重载配置"
                echo "5) 查看服务状态"
                echo "6) 启用开机自启"
                echo "7) 禁用开机自启"

                read -p "请选择操作: " service_choice

                case $service_choice in
                    1) systemctl start fail2ban; echo -e "${GREEN}Fail2Ban已启动${NC}" ;;
                    2) systemctl stop fail2ban; echo -e "${YELLOW}Fail2Ban已停止${NC}" ;;
                    3) systemctl restart fail2ban; echo -e "${GREEN}Fail2Ban已重启${NC}" ;;
                    4) fail2ban-client reload; echo -e "${GREEN}配置已重载${NC}" ;;
                    5) systemctl status fail2ban --no-pager -l ;;
                    6) systemctl enable fail2ban; echo -e "${GREEN}已启用开机自启${NC}" ;;
                    7) systemctl disable fail2ban; echo -e "${YELLOW}已禁用开机自启${NC}" ;;
                    *) echo -e "${RED}无效选择${NC}" ;;
                esac
                ;;
            2)
                echo -e "${BLUE}=== 日志清理 ===${NC}"
                echo

                # 显示日志大小
                if [ -f "/var/log/fail2ban.log" ]; then
                    f2b_size=$(du -h /var/log/fail2ban.log | cut -f1)
                    echo "Fail2Ban日志大小: $f2b_size"
                fi

                if [ -f "/var/log/auth.log" ]; then
                    auth_size=$(du -h /var/log/auth.log | cut -f1)
                    echo "认证日志大小: $auth_size"
                fi

                echo
                echo "清理选项:"
                echo "1) 清理Fail2Ban日志(保留最近1000行)"
                echo "2) 压缩旧日志文件"
                echo "3) 删除30天前的日志"
                echo "4) 清理临时文件"

                read -p "请选择清理操作: " clean_choice

                case $clean_choice in
                    1)
                        if [ -f "/var/log/fail2ban.log" ]; then
                            tail -1000 /var/log/fail2ban.log > /tmp/fail2ban.log.tmp
                            mv /tmp/fail2ban.log.tmp /var/log/fail2ban.log
                            echo -e "${GREEN}Fail2Ban日志已清理${NC}"
                        fi
                        ;;
                    2)
                        find /var/log -name "*.log.*" -not -name "*.gz" -exec gzip {} \;
                        echo -e "${GREEN}旧日志文件已压缩${NC}"
                        ;;
                    3)
                        find /var/log -name "*.log.*" -mtime +30 -delete
                        echo -e "${GREEN}30天前的日志已删除${NC}"
                        ;;
                    4)
                        rm -f /tmp/f2b_* /tmp/attack_report_* /tmp/fail2ban_analysis_*
                        echo -e "${GREEN}临时文件已清理${NC}"
                        ;;
                    *)
                        echo -e "${RED}无效选择${NC}"
                        ;;
                esac
                ;;
            3)
                echo -e "${BLUE}=== 规则优化 ===${NC}"
                echo

                echo "1) 检查重复规则"
                echo "2) 优化iptables规则顺序"
                echo "3) 清理无效封禁"
                echo "4) 合并相似网段"

                read -p "请选择优化操作: " optimize_choice

                case $optimize_choice in
                    1)
                        echo -e "${CYAN}检查iptables重复规则...${NC}"
                        iptables -L INPUT -n | sort | uniq -d
                        ;;
                    2)
                        echo -e "${CYAN}当前INPUT链规则顺序:${NC}"
                        iptables -L INPUT -n --line-numbers | head -20
                        echo -e "${YELLOW}建议将Fail2Ban规则放在前面以提高效率${NC}"
                        ;;
                    3)
                        echo -e "${CYAN}清理可能的无效封禁...${NC}"
                        # 这里可以添加检查IP是否仍然活跃的逻辑
                        banned_ips=$(fail2ban-client get sshd banip 2>/dev/null)
                        if [ ! -z "$banned_ips" ]; then
                            echo "当前封禁IP数量: $(echo $banned_ips | wc -w)"
                            echo "建议定期审查长期封禁的IP是否仍有必要"
                        fi
                        ;;
                    4)
                        echo -e "${CYAN}分析可合并的网段...${NC}"
                        banned_ips=$(fail2ban-client get sshd banip 2>/dev/null)
                        if [ ! -z "$banned_ips" ]; then
                            echo "$banned_ips" | tr ' ' '\n' | \
                                sed 's/\.[0-9]*$/\.0\/24/' | \
                                sort | uniq -c | \
                                awk '$1 > 3 {print "可考虑封禁整个网段: " $2 " (包含 " $1 " 个IP)"}'
                        fi
                        ;;
                    *)
                        echo -e "${RED}无效选择${NC}"
                        ;;
                esac
                ;;
            4)
                echo -e "${BLUE}=== 性能检查 ===${NC}"
                echo

                # CPU和内存使用
                echo -e "${CYAN}系统资源使用:${NC}"
                echo "CPU使用率: $(top -bn1 | grep "Cpu(s)" | awk '{print $2}' | cut -d'%' -f1)%"
                echo "内存使用: $(free | grep Mem | awk '{printf "%.1f%%", $3/$2 * 100.0}')"

                # Fail2Ban资源使用
                if pgrep -f fail2ban-server > /dev/null; then
                    f2b_pid=$(pgrep -f fail2ban-server)
                    f2b_cpu=$(ps -p $f2b_pid -o %cpu --no-headers 2>/dev/null | tr -d ' ')
                    f2b_mem=$(ps -p $f2b_pid -o %mem --no-headers 2>/dev/null | tr -d ' ')
                    echo "Fail2Ban CPU: ${f2b_cpu}%"
                    echo "Fail2Ban 内存: ${f2b_mem}%"
                fi

                # 日志处理性能
                echo
                echo -e "${CYAN}日志处理性能:${NC}"
                if [ -f "/var/log/auth.log" ]; then
                    auth_lines=$(wc -l < /var/log/auth.log)
                    echo "认证日志行数: $auth_lines"

                    # 检查日志增长速度
                    current_size=$(stat -c%s /var/log/auth.log 2>/dev/null || echo 0)
                    echo "当前日志大小: $(numfmt --to=iec $current_size)"
                fi

                # iptables规则数量
                rule_count=$(iptables -L INPUT -n | wc -l)
                echo "INPUT链规则数量: $rule_count"

                if [ $rule_count -gt 100 ]; then
                    echo -e "${YELLOW}警告: 规则数量较多,可能影响性能${NC}"
                fi
                ;;
            5)
                echo -e "${BLUE}=== 安全加固 ===${NC}"
                echo

                echo "1) 检查SSH配置安全性"
                echo "2) 设置更严格的Fail2Ban规则"
                echo "3) 启用额外的保护机制"
                echo "4) 检查系统安全状态"

                read -p "请选择加固操作: " security_choice

                case $security_choice in
                    1)
                        echo -e "${CYAN}SSH配置安全检查:${NC}"

                        # 检查SSH配置
                        if [ -f "/etc/ssh/sshd_config" ]; then
                            echo "检查SSH配置文件..."

                            # 检查关键配置项
                            port_config=$(grep "^Port " /etc/ssh/sshd_config 2>/dev/null)
                            if [ ! -z "$port_config" ]; then
                                echo -e "${GREEN}✓ SSH端口已修改: $port_config${NC}"
                            else
                                echo -e "${YELLOW}⚠ 建议修改SSH默认端口${NC}"
                            fi

                            root_login=$(grep "^PermitRootLogin " /etc/ssh/sshd_config 2>/dev/null)
                            if echo "$root_login" | grep -q "no"; then
                                echo -e "${GREEN}✓ 已禁用root直接登录${NC}"
                            else
                                echo -e "${YELLOW}⚠ 建议禁用root直接登录${NC}"
                            fi

                            password_auth=$(grep "^PasswordAuthentication " /etc/ssh/sshd_config 2>/dev/null)
                            if echo "$password_auth" | grep -q "no"; then
                                echo -e "${GREEN}✓ 已禁用密码认证${NC}"
                            else
                                echo -e "${YELLOW}⚠ 建议禁用密码认证,使用密钥认证${NC}"
                            fi
                        fi
                        ;;
                    2)
                        echo -e "${CYAN}设置更严格的Fail2Ban规则...${NC}"

                        cat > /etc/fail2ban/jail.local << 'EOF'
[DEFAULT]
# 更严格的配置
bantime = -1
findtime = 300
maxretry = 1
backend = auto
banaction = iptables-multiport
banaction_allports = iptables-allports
destemail = root@localhost
sendername = Fail2Ban

[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
backend = auto
bantime = -1
findtime = 300
maxretry = 1
action = iptables-multiport[name=SSH, port=ssh, protocol=tcp]
         sendmail-whois[name=SSH, dest=root, sender=fail2ban]

# 额外的保护
[sshd-ddos]
enabled = true
port = ssh
filter = sshd-ddos
logpath = /var/log/auth.log
bantime = 86400
findtime = 60
maxretry = 2

[apache-auth]
enabled = false
filter = apache-auth
action = iptables-multiport[name=apache-auth, port="http,https"]
logpath = /var/log/apache*/*error.log
maxretry = 6

[nginx-http-auth]
enabled = false
filter = nginx-http-auth
action = iptables-multiport[name=nginx-http-auth, port="http,https"]
logpath = /var/log/nginx/error.log
maxretry = 6
EOF

                        echo -e "${GREEN}严格配置已应用${NC}"
                        read -p "是否重启Fail2Ban应用新配置? [Y/n]: " restart_choice
                        if [[ ! $restart_choice =~ ^[Nn]$ ]]; then
                            systemctl restart fail2ban
                            echo -e "${GREEN}Fail2Ban已重启${NC}"
                        fi
                        ;;
                    3)
                        echo -e "${CYAN}启用额外保护机制...${NC}"

                        # 检查并安装psad (端口扫描检测)
                        if ! command -v psad &> /dev/null; then
                            echo "psad (端口扫描检测) 未安装"
                            read -p "是否安装psad? [y/N]: " install_psad
                            if [[ $install_psad =~ ^[Yy]$ ]]; then
                                apt update && apt install -y psad
                            fi
                        else
                            echo -e "${GREEN}✓ psad 已安装${NC}"
                        fi

                        # 设置更多的iptables规则
                        echo "添加额外的防护规则..."

                        # 限制连接频率
                        if ! iptables -L INPUT | grep -q "recent:"; then
                            iptables -I INPUT -p tcp --dport 22 -m state --state NEW -m recent --set
                            iptables -I INPUT -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 60 --hitcount 4 -j DROP
                            echo -e "${GREEN}✓ SSH连接频率限制已设置${NC}"
                        fi

                        # 保存规则
                        iptables-save > /etc/iptables/rules.v4 2>/dev/null
                        ;;
                    4)
                        echo -e "${CYAN}系统安全状态检查:${NC}"

                        # 检查开放端口
                        echo "开放的网络端口:"
                        netstat -tlnp | grep LISTEN | head -10

                        # 检查最近登录
                        echo -e "\n最近的登录记录:"
                        last | head -10

                        # 检查sudo使用
                        echo -e "\n最近的sudo使用:"
                        grep sudo /var/log/auth.log | tail -5 2>/dev/null || echo "无sudo记录"

                        # 检查系统用户
                        echo -e "\n系统用户账户:"
                        awk -F: '$3 >= 1000 {print $1 " (UID:" $3 ")"}' /etc/passwd

                        # 检查定时任务
                        echo -e "\n活跃的定时任务:"
                        crontab -l 2>/dev/null | grep -v "^#" | head -5 || echo "无定时任务"
                        ;;
                    *)
                        echo -e "${RED}无效选择${NC}"
                        ;;
                esac
                ;;
            6)
                echo -e "${BLUE}=== 系统健康检查 ===${NC}"
                echo

                health_score=0
                max_score=10

                # 1. Fail2Ban服务状态
                if systemctl is-active --quiet fail2ban; then
                    echo -e "${GREEN}✓ Fail2Ban服务运行正常${NC}"
                    ((health_score++))
                else
                    echo -e "${RED}✗ Fail2Ban服务未运行${NC}"
                fi

                # 2. 配置文件存在
                if [ -f "/etc/fail2ban/jail.local" ]; then
                    echo -e "${GREEN}✓ 自定义配置文件存在${NC}"
                    ((health_score++))
                else
                    echo -e "${YELLOW}⚠ 缺少自定义配置文件${NC}"
                fi

                # 3. SSH jail启用
                if fail2ban-client status sshd &>/dev/null; then
                    echo -e "${GREEN}✓ SSH jail正常工作${NC}"
                    ((health_score++))
                else
                    echo -e "${RED}✗ SSH jail未启用${NC}"
                fi

                # 4. 防火墙规则
                if iptables -L f2b-sshd &>/dev/null; then
                    echo -e "${GREEN}✓ 防火墙规则正常${NC}"
                    ((health_score++))
                else
                    echo -e "${YELLOW}⚠ 防火墙规则可能有问题${NC}"
                fi

                # 5. 日志文件可读
                if [ -r "/var/log/auth.log" ]; then
                    echo -e "${GREEN}✓ 日志文件可正常读取${NC}"
                    ((health_score++))
                else
                    echo -e "${RED}✗ 无法读取日志文件${NC}"
                fi

                # 6. 最近有防护活动
                recent_activity=$(grep "$(date +'%Y-%m-%d')" /var/log/fail2ban.log 2>/dev/null | wc -l)
                if [ $recent_activity -gt 0 ]; then
                    echo -e "${GREEN}✓ 今日有防护活动记录${NC}"
                    ((health_score++))
                else
                    echo -e "${YELLOW}⚠ 今日无防护活动${NC}"
                fi

                # 7. 内存使用正常
                mem_usage=$(free | grep Mem | awk '{printf "%.1f", $3/$2 * 100.0}')
                if [ "${mem_usage%.*}" -lt 90 ]; then
                    echo -e "${GREEN}✓ 内存使用正常 (${mem_usage}%)${NC}"
                    ((health_score++))
                else
                    echo -e "${YELLOW}⚠ 内存使用偏高 (${mem_usage}%)${NC}"
                fi

                # 8. 磁盘空间充足
                disk_usage=$(df / | tail -1 | awk '{print $5}' | sed 's/%//')
                if [ $disk_usage -lt 90 ]; then
                    echo -e "${GREEN}✓ 磁盘空间充足 (已使用${disk_usage}%)${NC}"
                    ((health_score++))
                else
                    echo -e "${YELLOW}⚠ 磁盘空间不足 (已使用${disk_usage}%)${NC}"
                fi

                # 9. SSH端口非默认
                ssh_port=$(netstat -tlnp 2>/dev/null | grep sshd | awk '{print $4}' | cut -d: -f2 | head -1)
                if [ "$ssh_port" != "22" ]; then
                    echo -e "${GREEN}✓ SSH端口已修改为非默认端口${NC}"
                    ((health_score++))
                else
                    echo -e "${YELLOW}⚠ 仍使用默认SSH端口22${NC}"
                fi

                # 10. 最近有封禁活动
                recent_bans=$(fail2ban-client status sshd 2>/dev/null | grep "Currently banned:" | awk '{print $4}')
                if [ "$recent_bans" -gt 0 ]; then
                    echo -e "${GREEN}✓ 系统正在积极防护 (${recent_bans}个IP被封禁)${NC}"
                    ((health_score++))
                else
                    echo -e "${YELLOW}⚠ 当前无IP被封禁${NC}"
                fi

                # 健康评分
                echo
                echo -e "${CYAN}=== 健康评分 ===${NC}"
                health_percent=$((health_score * 100 / max_score))

                if [ $health_percent -ge 80 ]; then
                    echo -e "${GREEN}系统健康状况: 优秀 (${health_score}/${max_score}, ${health_percent}%)${NC}"
                elif [ $health_percent -ge 60 ]; then
                    echo -e "${YELLOW}系统健康状况: 良好 (${health_score}/${max_score}, ${health_percent}%)${NC}"
                else
                    echo -e "${RED}系统健康状况: 需要改善 (${health_score}/${max_score}, ${health_percent}%)${NC}"
                fi

                # 建议改进措施
                if [ $health_score -lt $max_score ]; then
                    echo
                    echo -e "${CYAN}改进建议:${NC}"
                    if [ ! -f "/etc/fail2ban/jail.local" ]; then
                        echo "- 创建自定义配置文件"
                    fi
                    if [ "$ssh_port" = "22" ]; then
                        echo "- 修改SSH默认端口"
                    fi
                    if [ $recent_bans -eq 0 ]; then
                        echo "- 检查是否有攻击活动,系统可能过于安静"
                    fi
                fi
                ;;
            0)
                return
                ;;
            *)
                echo -e "${RED}无效选择${NC}"
                ;;
        esac
        echo
        read -p "按回车键继续..."
        echo
    done
}


# 8. 生成报告
generate_report() {
    clear
    print_title "生成报告"

    echo -e "${CYAN}报告类型选择:${NC}"
    echo "1) 快速状态报告"
    echo "2) 详细安全报告"
    echo "3) 攻击分析报告"
    echo "4) 性能报告"
    echo "5) 完整系统报告"
    echo "0) 返回主菜单"
    echo
    read -p "请选择报告类型 [0-5]: " report_choice

    case $report_choice in
        1)
            report_file="/tmp/f2b_quick_report_$(date +%Y%m%d_%H%M%S).txt"
            echo -e "${YELLOW}生成快速状态报告...${NC}"

            {
                echo "Fail2Ban 快速状态报告"
                echo "======================"
                echo "生成时间: $(date)"
                echo

                systemctl status fail2ban --no-pager -l
                echo
                fail2ban-client status sshd 2>/dev/null
                echo

                echo "防火墙规则:"
                iptables -L f2b-sshd -n -v 2>/dev/null

            } > "$report_file"
            ;;
        2)
            report_file="/tmp/f2b_security_report_$(date +%Y%m%d_%H%M%S).txt"
            echo -e "${YELLOW}生成详细安全报告...${NC}"

            {
                echo "Fail2Ban 详细安全报告"
                echo "===================="
                echo "生成时间: $(date)"
                echo "服务器: $(hostname)"
                echo "操作系统: $(uname -a)"
                echo

                echo "1. 服务状态"
                echo "----------"
                systemctl status fail2ban --no-pager -l
                echo

                echo "2. 配置信息"
                echo "----------"
                if [ -f "/etc/fail2ban/jail.local" ]; then
                    cat /etc/fail2ban/jail.local
                else
                    echo "未找到自定义配置文件"
                fi
                echo

                echo "3. 当前封禁状态"
                echo "-------------"
                fail2ban-client status sshd 2>/dev/null
                echo

                echo "4. 防火墙规则"
                echo "------------"
                iptables -L INPUT -n --line-numbers | grep -E "f2b|fail2ban"
                echo

                echo "5. SSH配置检查"
                echo "-------------"
                if [ -f "/etc/ssh/sshd_config" ]; then
                    grep -E "^(Port|PermitRootLogin|PasswordAuthentication)" /etc/ssh/sshd_config
                else
                    echo "SSH配置文件未找到"
                fi
                echo

                echo "6. 最近攻击活动"
                echo "-------------"
                grep "$(date +'%b %d')" /var/log/auth.log 2>/dev/null | \
                    grep -E "Invalid user|Failed password" | tail -10

            } > "$report_file"
            ;;
        3)
            report_file="/tmp/f2b_attack_analysis_$(date +%Y%m%d_%H%M%S).txt"
            echo -e "${YELLOW}生成攻击分析报告...${NC}"

            {
                echo "Fail2Ban 攻击分析报告"
                echo "===================="
                echo "生成时间: $(date)"
                echo

                echo "1. 攻击统计"
                echo "----------"
                total_invalid=$(grep -c "Invalid user" /var/log/auth.log 2>/dev/null)
                total_failed=$(grep -c "Failed password" /var/log/auth.log 2>/dev/null)
                total_attacks=$((total_invalid + total_failed))

                echo "总攻击次数: $total_attacks"
                echo "无效用户名攻击: $total_invalid"
                echo "密码错误攻击: $total_failed"
                echo

                echo "2. 顶级攻击者"
                echo "------------"
                grep -E "Invalid user|Failed password" /var/log/auth.log | \
                    grep -oE '([0-9]{1,3}\.){3}[0-9]{1,3}' | \
                    sort | uniq -c | sort -nr | head -20
                echo

                echo "3. 攻击趋势(最近7天)"
                echo "------------------"
                for i in {6..0}; do
                    date_str=$(date -d "$i days ago" +'%b %d')
                    attack_count=$(grep "$date_str" /var/log/auth.log 2>/dev/null | \
                        grep -c -E "Invalid user|Failed password")
                    echo "$date_str: $attack_count 次攻击"
                done
                echo

                echo "4. 常见攻击用户名"
                echo "---------------"
                grep "Invalid user" /var/log/auth.log | \
                    sed 's/.*Invalid user \([^ ]*\) .*/\1/' | \
                    sort | uniq -c | sort -nr | head -15
                echo

                echo "5. 网段分析"
                echo "----------"
                grep -E "Invalid user|Failed password" /var/log/auth.log | \
                    grep -oE '([0-9]{1,3}\.){3}[0-9]{1,3}' | \
                    sed 's/\.[0-9]*$/\.0\/24/' | sort | uniq -c | sort -nr | head -10

            } > "$report_file"
            ;;
        4)
            report_file="/tmp/f2b_performance_report_$(date +%Y%m%d_%H%M%S).txt"
            echo -e "${YELLOW}生成性能报告...${NC}"

            {
                echo "Fail2Ban 性能报告"
                echo "================="
                echo "生成时间: $(date)"
                echo

                echo "1. 系统资源使用"
                echo "-------------"
                echo "CPU使用率: $(top -bn1 | grep "Cpu(s)" | awk '{print $2}' | cut -d'%' -f1)%"
                echo "内存使用: $(free | grep Mem | awk '{printf "%.1f%%", $3/$2 * 100.0}')"
                echo "磁盘使用: $(df / | tail -1 | awk '{print $5}')"
                echo

                echo "2. Fail2Ban进程信息"
                echo "-----------------"
                if pgrep -f fail2ban-server > /dev/null; then
                    f2b_pid=$(pgrep -f fail2ban-server)
                    ps -p $f2b_pid -o pid,ppid,cmd,%cpu,%mem,time
                else
                    echo "Fail2Ban进程未运行"
                fi
                echo

                echo "3. 日志文件大小"
                echo "-------------"
                if [ -f "/var/log/fail2ban.log" ]; then
                    ls -lh /var/log/fail2ban.log
                fi
                if [ -f "/var/log/auth.log" ]; then
                    ls -lh /var/log/auth.log
                fi
                echo

                echo "4. iptables规则统计"
                echo "------------------"
                total_rules=$(iptables -L INPUT -n | wc -l)
                f2b_rules=$(iptables -L INPUT -n | grep -c "f2b")
                echo "总规则数: $total_rules"
                echo "Fail2Ban规则: $f2b_rules"
                echo

                echo "5. 网络连接统计"
                echo "-------------"
                netstat -an | awk '/^tcp/ {print $6}' | sort | uniq -c

            } > "$report_file"
            ;;
        5)
            report_file="/tmp/f2b_complete_report_$(date +%Y%m%d_%H%M%S).txt"
            echo -e "${YELLOW}生成完整系统报告...${NC}"

            {
                echo "Fail2Ban 完整系统报告"
                echo "===================="
                echo "生成时间: $(date)"
                echo "报告版本: $VERSION"
                echo "服务器信息: $(hostname) - $(uname -a)"
                echo

                # 包含所有其他报告的内容
                echo "================================"
                echo "第一部分: 系统状态"
                echo "================================"
                systemctl status fail2ban --no-pager -l
                echo
                fail2ban-client status
                echo

                echo "================================"
                echo "第二部分: 配置信息"
                echo "================================"
                if [ -f "/etc/fail2ban/jail.local" ]; then
                    cat /etc/fail2ban/jail.local
                else
                    echo "未找到自定义配置文件"
                fi
                echo

                echo "================================"
                echo "第三部分: 攻击分析"
                echo "================================"
                total_invalid=$(grep -c "Invalid user" /var/log/auth.log 2>/dev/null)
                total_failed=$(grep -c "Failed password" /var/log/auth.log 2>/dev/null)
                echo "攻击统计: 无效用户名 $total_invalid, 密码错误 $total_failed"
                echo
                echo "顶级攻击者:"
                grep -E "Invalid user|Failed password" /var/log/auth.log | \
                    grep -oE '([0-9]{1,3}\.){3}[0-9]{1,3}' | \
                    sort | uniq -c | sort -nr | head -15
                echo

                echo "================================"
                echo "第四部分: 防火墙状态"
                echo "================================"
                iptables -L INPUT -n --line-numbers
                echo

                echo "================================"
                echo "第五部分: 系统安全"
                echo "================================"
                if [ -f "/etc/ssh/sshd_config" ]; then
                    echo "SSH配置:"
                    grep -E "^(Port|PermitRootLogin|PasswordAuthentication)" /etc/ssh/sshd_config
                fi
                echo
                echo "开放端口:"
                netstat -tlnp | grep LISTEN
                echo

                echo "================================"
                echo "第六部分: 性能指标"
                echo "================================"
                echo "CPU: $(top -bn1 | grep "Cpu(s)" | awk '{print $2}' | cut -d'%' -f1)%"
                echo "内存: $(free | grep Mem | awk '{printf "%.1f%%", $3/$2 * 100.0}')"
                echo "磁盘: $(df / | tail -1 | awk '{print $5}')"
                echo

                echo "================================"
                echo "第七部分: 日志摘要"
                echo "================================"
                echo "最近的Fail2Ban活动:"
                tail -20 /var/log/fail2ban.log 2>/dev/null || echo "无Fail2Ban日志"
                echo
                echo "最近的攻击:"
                tail -10 /var/log/auth.log 2>/dev/null | grep -E "Invalid user|Failed password" || echo "无攻击记录"

            } > "$report_file"
            ;;
        0)
            return
            ;;
        *)
            echo -e "${RED}无效选择${NC}"
            return
            ;;
    esac

    if [ -f "$report_file" ]; then
        echo -e "${GREEN}报告生成成功: $report_file${NC}"
        echo -e "${CYAN}报告大小: $(du -h "$report_file" | cut -f1)${NC}"

        read -p "是否查看报告? [y/N]: " view_choice
        if [[ $view_choice =~ ^[Yy]$ ]]; then
            less "$report_file"
        fi

        read -p "是否发送报告到邮箱? [y/N]: " email_choice
        if [[ $email_choice =~ ^[Yy]$ ]]; then
            read -p "请输入邮箱地址: " email_addr
            if command -v mail &> /dev/null; then
                mail -s "Fail2Ban Report $(date)" "$email_addr" < "$report_file"
                echo -e "${GREEN}报告已发送到 $email_addr${NC}"
            else
                echo -e "${YELLOW}mail命令未安装,无法发送邮件${NC}"
            fi
        fi

        log_message "Report generated: $report_file"
    fi
}

# 显示帮助信息
show_help() {
    clear
    print_title "帮助信息"

    cat << EOF
${BOLD}Fail2Ban统一管理工具${NC} - 版本 $VERSION

${CYAN}功能模块说明:${NC}

${GREEN}1. 系统状态监控${NC}
   - 实时查看Fail2Ban服务状态
   - 监控SSH防护效果
   - 检查防火墙规则
   - 系统健康评估

${GREEN}2. 智能攻击分析${NC}
   - 自动分析攻击日志
   - 识别未封禁的攻击者
   - 网段攻击模式分析
   - 一键封禁新发现的攻击者

${GREEN}3. 封禁管理${NC}
   - 查看当前封禁列表
   - 手动封禁/解封IP
   - 批量操作支持
   - 网段封禁功能

${GREEN}4. 实时监控${NC}
   - SSH攻击实时监控
   - Fail2Ban日志监控
   - 系统登录监控
   - 综合监控面板

${GREEN}5. 配置管理${NC}
   - 配置文件编辑
   - 配置备份恢复
   - 配置向导
   - 参数优化建议

${GREEN}6. 日志分析${NC}
   - 攻击趋势分析
   - 攻击者排行
   - 时间段分析
   - 地理分布分析

${GREEN}7. 系统维护${NC}
   - 服务管理
   - 日志清理
   - 性能优化
   - 安全加固

${GREEN}8. 报告生成${NC}
   - 多种格式报告
   - 邮件发送支持
   - 自动化分析
   - 历史记录保存

${CYAN}使用建议:${NC}
1. 首次使用建议运行"配置向导"
2. 定期查看"系统健康检查"
3. 使用"智能攻击分析"主动发现威胁
4. 通过"实时监控"观察防护效果

${CYAN}常用快捷操作:${NC}
- 快速状态检查: 选择选项1
- 分析新攻击: 选择选项2
- 实时监控: 选择选项4
- 生成报告: 选择选项8

${YELLOW}注意事项:${NC}
- 所有操作都会记录在日志文件中
- 建议定期备份配置文件
- 修改配置后记得重启服务
- 重要操作前建议先生成报告

${CYAN}技术支持:${NC}
如有问题,请检查以下日志文件:
- Fail2Ban日志: /var/log/fail2ban.log
- 认证日志: /var/log/auth.log
- 工具日志: $LOG_FILE

EOF

    read -p "按回车键返回主菜单..."
}

# 主程序循环
main_loop() {
    # 检查权限
    check_permissions

    # 初始化日志
    log_message "Fail2Ban unified management tool started"

    while true; do
        show_main_menu
        read -p "请选择操作 [0-8,h]: " choice

        case $choice in
            1)
                system_status_monitor
                ;;
            2)
                intelligent_attack_analysis
                ;;
            3)
                ban_management
                ;;
            4)
                real_time_monitor # Now defined above main_loop
                ;;
            5)
                config_management # Now defined above main_loop
                ;;
            6)
                log_analysis # Now defined above main_loop
                ;;
            7)
                system_maintenance # Now defined above main_loop
                ;;
            8)
                generate_report
                ;;
            h|H)
                show_help
                ;;
            0)
                echo
                print_separator
                echo -e "${PURPLE}感谢使用 Fail2Ban 统一管理工具!${NC}"
                echo -e "${CYAN}工具日志已保存到: $LOG_FILE${NC}"
                print_separator
                log_message "Fail2Ban unified management tool exited"
                exit 0
                ;;
            *)
                echo -e "${RED}无效选择,请重新输入${NC}"
                ;;
        esac

        # 操作完成后暂停
        if [[ ! $choice =~ ^[0h]$ ]]; then
            echo
            read -p "按回车键返回主菜单..."
        fi
    done
}

# 脚本入口点
if [ "${BASH_SOURCE[0]}" == "${0}" ]; then
    main_loop
fi

2 介绍 iptables-chain ( iptables 链) 概念

链是iptables中的规则集合,数据包进入系统时会按顺序通过不同的链,每个链包含多条规则,会按顺序检查进入的数据包。

工作流程:

SSH连接请求到达服务器
        --> 进入INPUT链,按顺序交给 f2b-ssh-chain (rule 1)
                --> 在 f2b-sshd-chain (rule 5)中做:检查IP是否在封禁列表 (是:丢弃连接)
                        否 --> 返回主链继续
                                --> 经过其它规则检查
                                        --> 允许/拒绝

检测规则如配置文件中:

注:

  • 30 分钟内,失败 3 次就触发, 永久封禁。
  • 对于SSH 密钥+密码,如果密码输入错误,也会永久封禁。
  • f2b 是读取 /var/log/auth.log 内容

3 验证

正在修改 maxretry 时,IP 190.80.247.133 触发规则,被禁。

4 建议(可选)

在用户登录的启动文件加入“fail2ban-client status sshd” 方便没次登录可以看到 f2b 结果,如:

主机 USW:防火墙 UFW

这个主机与 JPT 不同,运营商的防火墙服务是收费的,所以自己使用 ufw 来保护主机

查看日志:(主机在本 16 号重装过)

上图,来自 92.118.39.56 在穷举登录
下图,来自203.91.184.180 与 103.163.21.28,短时间内大量连接尝,使用特殊断开消,在“预认证阶段断开”,使用不同端口号连接(说明它正在扫描这台主机)

1. 解决方法:

1)安装 fail2ban (f2b)
sudo apt update && sudo apt install fail2ban -y
2)创建 UFW 适配的配置文件
sudo tee /etc/fail2ban/jail.local << 'EOF'
[DEFAULT]
bantime = -1
findtime = 1800
maxretry = 3
backend = auto
banaction = ufw
banaction_allports = ufw
ignoreip = 127.0.0.1/8 ::1

[sshd]
enabled = true
port = 9922
filter = sshd
logpath = /var/log/auth.log
backend = auto
bantime = -1
findtime = 1800
maxretry = 3
action = ufw[name=SSH, port=9922, protocol=tcp]

[ssh-scanner]
enabled = true
port = 9922
filter = ssh-scanner
logpath = /var/log/auth.log
maxretry = 2
bantime = -1
findtime = 600
action = ufw[name=SSH-SCANNER, port=9922, protocol=tcp]
EOF
3)创建 UFW 动作配置文件
sudo tee /etc/fail2ban/action.d/ufw.conf << 'EOF'
[Definition]
actionstart =
actionstop =
actioncheck =
actionban = ufw insert 1 deny from <ip> to any port <port>
actionunban = ufw delete deny from <ip> to any port <port>

[Init]
name = default
port = ssh
protocol = tcp
EOF
4)创建扫描检测过滤器

专为 "Normal Shutdown, Thank you for playing" 这种扫描行为, 加入又遇到的字串

[INCLUDES]
before = common.conf

[Definition]
_daemon = sshd

failregex = ^%(__prefix_line)sConnection from <HOST> port \d+ on \S+ port \d+$
            ^%(__prefix_line)sConnection closed by <HOST> port \d+ \[preauth\]$
            ^%(__prefix_line)sConnection closed by authenticating user .* <HOST> port \d+ \[preauth\]$
            ^%(__prefix_line)sDisconnected from .* <HOST> port \d+ \[preauth\]$
            ^%(__prefix_line)sReceived disconnect from <HOST> port \d+:\d+: .* \[preauth\]$
            ^%(__prefix_line)sbanner exchange: Connection from <HOST> port \d+: invalid format$

ignoreregex =

5)启动和测试配置
# 测试配置文件语法
sudo fail2ban-client -t

# 重启 fail2ban 服务
sudo systemctl restart fail2ban

# 检查服务状态
sudo systemctl status fail2ban

# 查看 fail2ban 状态
sudo fail2ban-client status

# 查看 SSH 监狱状态
sudo fail2ban-client status sshd

# 查看 SSH Scanner 监狱状态
sudo fail2ban-client status ssh-scanner
6)测试:模拟扫描攻击行为

第一次攻击:(规则要2次才触发封禁)

sleep 5
sudo bash -c 'echo "$(date --iso-8601=seconds) usw sshd[9999]: Received disconnect from 1.2.3.4 port 12345:11: Normal Shutdown, Thank you for playing [preauth]" >> /var/log/auth.log'
sleep 5

查看 f2b 状态

sudo fail2ban-client status ssh-scanner
sudo ufw status | grep "1.2.3.4"

第二次攻击:(将出发封禁)

sleep 5
sudo bash -c 'echo "$(date --iso-8601=seconds) usw sshd[9998]: Received disconnect from 1.2.3.4 port 54321:11: Normal Shutdown, Thank you for playing [preauth]" >> /var/log/auth.log'
sleep 10

 查看 f2b 状态

sudo fail2ban-client status ssh-scanner
sudo ufw status | grep "1.2.3.4"

查看 ufw 是否添加了规则

sudo ufw status numbered | grep -A2 -B2 "1.2.3.4"

删除测试用的“封禁记录”

sudo fail2ban-client set ssh-scanner unbanip 1.2.3.4
6) 查看生效(状态查看)
i. 服务状态
sudo systemctl status fail2ban
ii. 查看 ssh scaner 状态
sudo fail2ban-client status sshd
sudo fail2ban-client status ssh-scanner
iii. 查看所有已封禁的 IP
sudo fail2ban-client banned
iv. 查看 F2J 的配置信息
sudo fail2ban-client get sshd findtime
sudo fail2ban-client get sshd maxretry  
sudo fail2ban-client get sshd bantime
v. 实时监控 SSH 攻击
sudo tail -f /var/log/auth.log | grep "Invalid user"

7)fail2ban-status.sh 报告脚本 

#!/bin/bash

# Fail2ban Status Display Script
# Shows banned IPs and attack statistics
# by Dave and Claude on 26Jun25

echo "================================================"
echo "🛡️  FAIL2BAN SECURITY STATUS REPORT"
echo "================================================"

# Check if fail2ban is running
if ! systemctl is-active --quiet fail2ban; then
    echo "❌ Fail2ban service is not running"
    exit 1
fi

# Get current time
echo "📅 Report Time: $(date '+%Y-%m-%d %H:%M:%S')"
echo ""

# Show overall status
echo "📊 Jail Overview:"
fail2ban-client status 2>/dev/null | sed 's/^/   /'
echo ""

# Get all jail list
jails=$(fail2ban-client status 2>/dev/null | grep "Jail list:" | cut -d: -f2 | tr ',' '\n' | xargs)

total_banned=0
total_failed=0

# Loop through each jail
for jail in $jails; do
    if [[ -n "$jail" ]]; then
        echo "🏢 Jail: $jail"
        echo "   ----------------------------------------"
        
        # Get jail status
        status_output=$(fail2ban-client status "$jail" 2>/dev/null)
        
        # Extract data
        currently_failed=$(echo "$status_output" | grep "Currently failed:" | awk '{print $NF}')
        total_failed_jail=$(echo "$status_output" | grep "Total failed:" | awk '{print $NF}')
        currently_banned=$(echo "$status_output" | grep "Currently banned:" | awk '{print $NF}')
        total_banned_jail=$(echo "$status_output" | grep "Total banned:" | awk '{print $NF}')
        banned_ips=$(echo "$status_output" | grep "Banned IP list:" | cut -d: -f2 | xargs)
        
        # Display statistics
        echo "   📈 Current Failed: $currently_failed"
        echo "   📊 Total Failed: $total_failed_jail"
        echo "   🚫 Currently Banned: $currently_banned"
        echo "   📋 Total Banned: $total_banned_jail"
        
        # Display banned IPs
        if [[ -n "$banned_ips" && "$banned_ips" != "" ]]; then
            echo "   🔴 Banned IPs:"
            for ip in $banned_ips; do
                # Try to get IP geolocation info (if whois command is available)
                if command -v whois >/dev/null 2>&1; then
                    country=$(whois "$ip" 2>/dev/null | grep -i country | head -1 | awk '{print $2}' 2>/dev/null)
                    if [[ -n "$country" ]]; then
                        echo "      🌍 $ip ($country)"
                    else
                        echo "      🌍 $ip"
                    fi
                else
                    echo "      🌍 $ip"
                fi
            done
        else
            echo "   ✅ No banned IPs currently"
        fi
        
        # Accumulate statistics
        total_banned=$((total_banned + currently_banned))
        total_failed=$((total_failed + total_failed_jail))
        
        echo ""
    fi
done

# Display totals
echo "================================================"
echo "📊 Overall Statistics:"
echo "   🚫 Total Banned IPs: $total_banned"
echo "   📈 Total Attack Attempts: $total_failed"
echo "================================================"

# Show recent attacks (if log file exists)
if [[ -f /var/log/fail2ban.log ]]; then
    echo ""
    echo "🕒 Recent Ban Activity:"
    echo "   ----------------------------------------"
    recent_bans=$(tail -50 /var/log/fail2ban.log 2>/dev/null | grep "Ban " | tail -5)
    if [[ -n "$recent_bans" ]]; then
        echo "$recent_bans" | while read line; do
            echo "   📅 $line"
        done
    else
        echo "   ✅ No recent ban activity"
    fi
fi

echo ""
echo "🛡️  Server security protection is running normally"
echo "================================================"

推荐加到 ~/.bashrc 

主机 BJN BJT: 运营商防火墙+ UFW + F2B

完全照上面的 USW 配置,即可实现 UFW会自动添加deny规则

附件:记录攻击的 IP 地址

主机 BJT:

主机 BJN

主机 JPT

主机 USW

Claude 分析:

提示:

脚本需要 fail2ban-status.sh 如果不展示国家名,需要安展 whois 包

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值