shell实现将登录失败次数超过5次ip拉入黑名单,以防暴力破解

柳三千

文章最后更新时间:2025年05月27日

前言

公网环境面临频繁的暴力破解攻击威胁。为防御此类攻击,本文将介绍如何编写脚本,实现以下功能:

  • 封禁登录失败超5次的IP地址
  • 通过邮件通知管理员异常访问行为

提示:以下为详细操作步骤及案例参考

一、服务器环境配置准备

  • 操作系统:CentOS 7
  • 防火墙策略:关闭firewalld,启用iptables
  • 辅助工具:配置邮箱服务用于告警通知

二、基础环境配置

1. 关闭 firewalld 防火墙

systemctl stop firewalld  # 停止服务  
systemctl disable firewalld  # 禁止开机自启  

2. 禁用 SELinux

# 临时关闭(立即生效)  
setenforce 0  
# 检查状态(应返回 Disabled)  
getenforce  
# 永久关闭(修改配置文件)  
cat /etc/selinux/config  
# 确保以下配置存在  
SELINUX=disabled  

3. 安装并启动 iptables

# 安装 iptables 服务  
yum install iptables-services -y  
# 启动服务  
systemctl start iptables  
# 设置开机自启  
systemctl enable iptables  

4. 配置邮件告警功能

(1)安装邮件客户端

yum install mailx -y  # 安装 mailx  

(2)配置邮箱账户

vim /etc/mail.rc  # 编辑配置文件  
# 添加以下内容(替换为实际邮箱信息)  
set bsdcompat  
set from=123456@qq.com       # 发件人邮箱  
set smtp=smtp.exmail.qq.com  # SMTP 服务器(以腾讯企业邮箱为例)  
set smtp-auth-user=123456@qq.com  # 邮箱账户  
set smtp-auth-password=xxx  # 邮箱密码/授权码  
set smtp-auth=login  

(3)发送测试邮件

echo "测试内容:服务器告警" | mail -s "【测试】服务器通知" 987654@qq.com  

三、防暴力破解脚本开发

1. 脚本设计逻辑

  1. 分析登录失败日志,提取IP并统计失败次数
  2. 对失败次数超过阈值(5次)的IP执行封禁
  3. 记录操作日志并发送邮件通知
  4. 自动备份和清理登录失败记录

2. 完整脚本代码

#!/bin/bash  
# 脚本功能:封禁登录失败超5次的IP,发送告警邮件并管理日志  

# 配置项  
TMP_DIR=$(mktemp -d)          # 临时目录(自动清理)  
LOG_FILE="$HOME/error_login.log"  # 日志文件  
BTMP_BACKUP_DIR="$HOME/btmp_backups"  # btmp日志备份目录  
MAX_BACKUPS=10                # 最大备份数  
THRESHOLD=5                   # 失败次数阈值  

# 创建备份目录(若不存在)  
mkdir -p "$BTMP_BACKUP_DIR"  

# 1. 提取并统计失败登录IP  
lastb | awk '{print $3}' | grep ^[0-9] | uniq -c | awk '{print $1"="$2}' > "$TMP_DIR/host"  

# 2. 遍历处理每个IP  
while IFS= read -r line; do  
    ip=$(echo "$line" | awk -F= '{print $2}')  
    num=$(echo "$line" | awk -F= '{print $1}')  

    # 检查是否超过失败阈值  
    if [[ $num -gt $THRESHOLD ]]; then  
        # 检查IP是否已被封禁  
        if iptables -L INPUT -n | grep -q "$ip"; then  
            echo "$(date +'%F %T') [INFO] IP $ip 已封禁,跳过" >> "$LOG_FILE"  
            continue  
        fi  

        # 查询IP归属信息(需联网)  
        ip_info=$(curl -s cip.cc/"$ip" | grep -E '地址|运营商' | tr -d '\n')  

        # 记录日志  
        echo "$(date +'%F %T') [ALERT] 检测到可疑IP: $ip(失败次数: $num) - $ip_info" >> "$LOG_FILE"  

        # 添加防火墙规则(使用绝对路径确保执行)  
        if /usr/sbin/iptables -I INPUT -s "$ip" -j DROP; then  
            echo "$(date +'%F %T') [SUCCESS] 已封禁IP: $ip - $ip_info" >> "$LOG_FILE"  
            # 发送告警邮件(取消注释以启用)  
            # echo "$ip 企图恶意登录(失败次数: $num) - $ip_info" | mail -s "【警告】暴力破解尝试" 123456@qq.com  
        else  
            echo "$(date +'%F %T') [ERROR] 封禁IP失败: $ip" >> "$LOG_FILE"  
        fi  
    fi  
done < "$TMP_DIR/host"  

# 3. 管理登录失败日志(btmp)  
if [[ -s /var/log/btmp ]]; then  
    # 备份当前btmp日志  
    backup_file="$BTMP_BACKUP_DIR/btmp_$(date +%Y%m%d_%H%M%S)"  
    cp /var/log/btmp "$backup_file"  
    echo "$(date +'%F %T') [INFO] 已备份btmp日志到: $backup_file" >> "$LOG_FILE"  

    # 清空btmp日志(避免重复统计)  
    cat /dev/null > /var/log/btmp  

    # 清理旧备份(保留最新$MAX_BACKUPS个)  
    find "$BTMP_BACKUP_DIR" -name "btmp_*" -type f | sort -r | tail -n +"$((MAX_BACKUPS + 1))" | xargs -r rm -f  
    echo "$(date +'%F %T') [INFO] 已清理过期btmp备份" >> "$LOG_FILE"  
fi  

# 自动清理临时目录  
rm -rf "$TMP_DIR"  

3. 脚本执行权限与测试

chmod +x unlogin.sh  # 赋予执行权限  
./unlogin.sh  # 手动测试执行  

4. 配置定时任务(Cron)

crontab -e  # 编辑定时任务  
# 添加以下内容(每5分钟执行一次)  
*/5 * * * * . /etc/profile && /bin/bash /root/unlogin.sh  

四、关键问题与解决方案

1. 定时任务执行失败

现象:脚本手动执行正常,但Cron中不生效
原因:Cron环境变量缺失
解决

  • 在脚本中使用命令绝对路径(如/usr/sbin/iptables
  • 在Cron任务中添加环境变量加载语句:
    */5 * * * * . /etc/profile && /bin/bash /path/to/script.sh  
    

2. IP归属查询功能

依赖:需服务器联网并允许访问cip.cc
作用:记录IP地理位置和运营商信息,辅助定位攻击来源

3. 日志管理

  • 日志文件$HOME/error_login.log 记录操作详情
  • 备份策略:自动保留最近10份btmp日志备份,避免日志过大

五、总结

本文通过结合iptables防火墙与Shell脚本,实现了自动化的暴力破解防御机制。关键要点包括:

  1. 环境一致性:确保脚本在Cron中的执行环境与手动执行一致
  2. 日志可追溯:详细记录封禁操作和IP信息,便于安全审计
  3. 弹性设计:通过临时目录和备份策略避免文件残留和日志膨胀

实际部署时,建议根据业务需求调整失败次数阈值(THRESHOLD)和定时任务频率。

文章版权声明:除非注明,否则均为柳三千运维录原创文章,转载或复制请以超链接形式并注明出处。

取消
微信二维码
微信二维码
支付宝二维码