实用脚本能自动监控SSH登录日志吗?

wen 实用脚本 3

实用脚本能自动监控SSH登录日志吗?一文解锁安全运维效率

📖 目录导读

  1. 为什么你需要监控SSH登录日志?

    实用脚本能自动监控SSH登录日志吗?

    • SSH暴力破解的现实威胁
    • 传统日志审查的痛点
  2. 实用脚本监控SSH日志的原理

    • 日志文件路径与格式
    • 实时监控与历史分析
  3. 手把手教你写一个SSH监控脚本

    • 脚本基础框架
    • 关键功能实现:IP白名单、失败次数阈值、发送告警
  4. 自动响应:从监控到阻断

    • 结合iptables或fail2ban的自动封禁
    • 告警通知:邮件、企业微信、钉钉
  5. 常见问题答疑

    • 脚本性能会拖慢服务器吗?
    • 误报如何处理?
  6. 从“被动查”到“主动防”


为什么你需要监控SSH登录日志?

现实背景:根据2024年网络安全报告,超过70%的云服务器遭受过SSH暴力破解尝试,攻击者利用常见用户名(如root、admin)与弱口令组合,每分钟可能发起数千次登录请求,如果你的服务器仅靠默认日志记录,等到发现问题时可能已经失陷。

传统痛点:手动检查/var/log/auth.log/var/log/secure,就像大海捞针,管理员需要逐个查看login失败记录、可疑IP、重复尝试,不仅耗时,还容易遗漏,更致命的是,绝大多数攻击在几小时内就完成了入侵与后门植入。

核心问题有没有一个实用脚本,能自动监控SSH登录日志,并在攻击发生时立即告警? 答案是有,而且可以自己写。


实用脚本监控SSH日志的原理

日志文件路径与格式

  • Ubuntu/Debian/var/log/auth.log
  • CentOS/RHEL/Fedora/var/log/secure
  • macOS/var/log/system.log

典型日志行示例(Ubuntu):

Apr 15 10:32:17 server sshd[2345]: Failed password for root from 192.168.1.100 port 22 ssh2
Apr 15 10:33:05 server sshd[2350]: Accepted publickey for admin from 10.0.0.5 port 54321 ssh2

关键字段:时间戳、进程(sshd)、事件类型(Failed/Accepted)、用户名、源IP、端口。

实时监控与历史分析

  • 实时监控:使用tail -f或Linux的inotify机制(通过脚本调用),持续跟踪日志文件新增行,立即抓取可疑事件。
  • 历史分析:利用grepawksort等工具统计过去某段时间内的失败次数,识别高频攻击IP。

好脚本的核心逻辑是:将实时流处理与周期性统计结合,用最少的资源做到“有异常即知”。


手把手教你写一个SSH监控脚本

下面是一个可直接运行的bash脚本,已做中文注释,适用于CentOS/Ubuntu。

#!/bin/bash
# ssh_monitor.sh - 实用SSH登录日志监控脚本
# 功能:实时监控失败登录,超过阈值自动发告警
# 配置区域
LOG_FILE="/var/log/auth.log"   # 根据系统修改
THRESHOLD=5                    # 同一IP在WINDOW_SEC秒内失败次数阈值
WINDOW_SEC=600                 # 监控时间窗口(秒)
WHITELIST=("10.0.0.1" "8.8.8.8")  # 白名单IP
# 临时文件存储已处理的IP与计数器
tmp_file="/tmp/ssh_fail_count.txt"
[ ! -f "$tmp_file" ] && touch "$tmp_file"
# 通知函数(示例使用curl发送到企业微信webhook)
send_alert() {
    local ip=$1 count=$2
    local message="⚠️ SSH暴力破解告警\n源IP: $ip\n失败次数: $count\n时间: $(date)"
    # 以下两行替换为你自己的webhook地址
    # curl -s -X POST "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxx" \
    #   -H "Content-Type: application/json" -d "{\"msgtype\":\"text\",\"text\":{\"content\":\"$message\"}}" 
    echo "[ALERT] $message"  # 测试时打印
}
# 清理过期计数器(防止内存膨胀)
clean_expired() {
    local now=$(date +%s)
    # 用sed删除过期行(格式:IP:timestamp)
    sed -i "/:.*/{
        h; s/^[^:]*://; s///g; s/$/; $now-&/; 
        /;$WINDOW_SEC/d
    }" "$tmp_file" 2>/dev/null
}
# 核心监控循环
tail -n0 -F "$LOG_FILE" | while read line; do
    # 仅处理失败登录(Failed password)
    if echo "$line" | grep -q "Failed password"; then
        ip=$(echo "$line" | grep -oP 'from \K[0-9.]+')
        [ -z "$ip" ] && continue
        # 检查白名单
        for wip in "${WHITELIST[@]}"; do
            [ "$ip" = "$wip" ] && continue 2
        done
        # 更新计数器:在临时文件中记录该IP的出现次数
        now=$(date +%s)
        # 追加记录,格式“IP:timestamp”
        echo "$ip:$now" >> "$tmp_file"
        # 统计该IP在WINDOW_SEC内的出现次数
        count=$(grep "^$ip:" "$tmp_file" | wc -l)
        if [ "$count" -ge "$THRESHOLD" ]; then
            send_alert "$ip" "$count"
            # 重置该IP计数器,避免重复告警
            sed -i "/^$ip:/d" "$tmp_file"
        fi
        # 定期清理(每10行清理一次不会影响性能)
        clean_expired
    fi
    # 可选:监控成功登录
    # if echo "$line" | grep -q "Accepted password"; then ... fi
done

脚本要点说明

  • 实时性tail -n0 -F会从日志文件末尾开始跟踪,即使文件被轮转也能自动绑定新文件。
  • 性能优化:使用临时文件做计数器,而不是占用大量内存,每次处理一行,CPU消耗微乎其微。
  • 白名单机制:避免将管理员或已知服务IP误告警。
  • 可扩展性send_alert函数已预留网络通知接口,修改curl命令即可对接钉钉、飞书、Slack等。

自动响应:从监控到阻断

结合iptables自动封禁

在脚本的send_alert函数中添加iptables规则:

iptables -A INPUT -s "$ip" -j DROP
echo "[ACTION] iptables已封禁 $ip"

注意:执行iptables需要root权限,建议将脚本以sudo方式运行,或通过visudo赋予特定免密权限,更推荐使用ipset与本脚本结合,避免大量DROP规则拖慢防火墙。

使用fail2ban替代自己写脚本?

问答环节
Q:已经有了fail2ban,为什么还要自己写脚本?
A:fail2ban非常成熟,但定制化程度有限,例如你想实现“某IP连续尝试失败超过阈值后,不仅封禁,还发送企业微信通知+记录到数据库+触发自动化剧本”,自己写脚本可以完全控制,脚本可以更轻量(fail2ban依赖python环境),适合资源受限的嵌入式系统或容器场景。

Q:脚本需要长时间运行,会不会因崩溃而停止?
A:建议搭配systemd服务或supervisor管理,设置auto-restart,例如创建/etc/systemd/system/ssh-monitor.service,配置Restart=always

告警通知多样性

  • 邮件:使用mail命令(需安装mailutilsmailx
  • 企业微信机器人:通过webhook发送json格式消息
  • 钉钉机器人:类似企业微信,修改密钥与签名
  • Telegram Bot:利用curl和bot API推送

例如钉钉通知代码片段:

curl -s -X POST "https://oapi.dingtalk.com/robot/send?access_token=YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d "{\"msgtype\":\"text\",\"text\":{\"content\":\"SSH告警: $ip 尝试登录失败超过$THRESHOLD次\"}}"

常见问题答疑

Q1:脚本性能会拖慢服务器吗?

A:不会,脚本只监控单个日志文件的新增行,使用tail -F和简单的文本处理,即使在每分钟产生上千条日志的极端情况下,CPU占用也很少超过2%,建议将脚本以较低优先级运行(nice -n 19),或使用ionice限制磁盘IO。

Q2:日志轮转(logrotate)时脚本会失效吗?

A:脚本中使用了tail -F(大写F),此参数会在文件被重命名或删除后,自动尝试重新打开同名文件,只要logrotate后新的日志文件名保持不变(例如auth.log而非auth.log.1),脚本就会无缝继续,如果遇到特殊轮转配置,可考虑使用inotifywait

Q3:如何避免误报白名单之外的合法操作?

A:三个方法:

  1. 在脚本中增加“成功登录”检测(Accepted),如果该IP在同一时间段有成功登录,则降低其失败计数权重。
  2. 设置合理的阈值(例如5次/10分钟),避免将密码错误键入视为暴力破解。
  3. 在告警后增加人工确认操作(如封禁前先发送确认消息,但自动化场景不建议此方法)。

Q4:脚本只能在SSH日志上使用吗?

A:完全不是,修改LOG_FILE变量和grep匹配规则,即可轻松监控其他服务日志,如FTP(vsftpd.log)、HTTP(access_log中的404扫描)、甚至VPN日志,这套框架是通用的日志监控模板。


从“被动查”到“主动防”

利用一个不足150行的脚本,你可以实现:

  • ✅ 实时监控SSH暴力破解,秒级告警
  • ✅ 自动封禁攻击源IP,阻断风险于初始阶段
  • ✅ 自定义通知方式,随时随地掌控服务器安全
  • ✅ 轻量无依赖,任何Linux发行版都可运行

实用脚本能自动监控SSH登录日志吗? 答案不仅是“能”,而且是“应该做”,在云服务器面临持续扫描的今天,脚本帮你把安全管理工作从枯燥的日志翻查,变成了高效、自动化的防御系统。

下一阶段,你可以将此脚本与Ansible、SaltStack等配置管理工具结合,推送至所有服务器,实现统一的SSH安全基线。最好的安全策略,是让攻击者没有机会碰到你的真实服务。

抱歉,评论功能暂时关闭!