如何用脚本检测SSH暴力破解?

wen 实用脚本 4

如何用脚本检测SSH暴力破解?从日志分析到实时防御的完整指南

目录导读

  1. SSH暴力破解的威胁与现状
  2. 检测原理:日志、流量与行为模式
  3. 手写脚本:基于Python的SSH暴力破解检测器
  4. 实战部署:日志分析与告警触发
  5. 避免误报的优化策略
  6. 常见问题问答(FAQ)
  7. 总结与扩展建议

SSH暴力破解的威胁与现状

SSH(Secure Shell)是远程管理Linux/Unix服务器的核心协议,但也是攻击者的重点目标,根据安全机构统计,一台暴露在公网的SSH服务平均每天会遭遇数十次甚至数千次暴力破解尝试,攻击者通过字典或随机组合尝试用户名和密码,一旦成功即可获得服务器控制权,植入勒索软件、挖矿程序或作为跳板攻击内网。

如何用脚本检测SSH暴力破解?

典型特征

  • 短时间内大量失败的SSH登录尝试(如每分钟50次以上)。
  • 来自同一IP地址的多次尝试,且不同用户名反复切换。
  • 非正常时段(如凌晨3点)的突发登录活动。

传统方案如fail2ban虽然有效,但灵活性不足,本文将教你用自定义脚本精确检测SSH暴力破解,并支持二次开发集成到安全体系中。


检测原理:日志、流量与行为模式

要检测暴力破解,核心是解析SSH守护进程(sshd)的日志,Linux系统默认将SSH登录记录写入/var/log/auth.log(Debian/Ubuntu)或/var/log/secure(RHEL/CentOS),重点识别两类关键字:

  • 失败尝试Failed password for [user] from [ip] port [port] ssh2
  • 成功登录Accepted password for [user] from [ip] port [port] ssh2

关键阈值

  • 同一IP在特定时间窗口内(如5分钟) 失败超过N次(如10次) 即判定为暴力破解。
  • 同时关注可疑用户名(如root、admin、test等高频尝试对象)。

高级检测:结合logstash或GoAccess等工具可分析流量模式,但本文聚焦脚本实现。


手写脚本:基于Python的SSH暴力破解检测器

以下是一个轻量级Python脚本,持续监控日志文件,实时抓取暴力破解IP并输出告警,假设环境:Linux服务器 + Python3。

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# ssh_bruteforce_detector.py
import re
import time
from collections import defaultdict
from datetime import datetime, timedelta
LOG_FILE = "/var/log/auth.log"  # 根据系统调整路径
FAIL_THRESHOLD = 10             # 阈值:5分钟内失败次数
TIME_WINDOW = 300               # 时间窗口:秒
# 数据结构:{ip: [(timestamp1, failed_count), ...]}
failed_attempts = defaultdict(list)
def parse_log_line(line):
    """解析单行日志,返回(ip, username)或None"""
    pattern = r'Failed password for (\S+) from (\d+\.\d+\.\d+\.\d+) port'
    match = re.search(pattern, line)
    if match:
        username = match.group(1)
        ip = match.group(2)
        return ip, username
    return None
def detect_bruteforce(current_ip, current_time):
    """基于时间窗口检测"""
    # 移除过期记录(早于TIME_WINDOW的记录)
    failed_attempts[current_ip] = [
        (ts, count) for ts, count in failed_attempts[current_ip]
        if (current_time - ts).total_seconds() < TIME_WINDOW
    ]
    # 累加当前窗口内的失败次数
    total_failures = sum(count for _, count in failed_attempts[current_ip])
    return total_failures >= FAIL_THRESHOLD
def monitor_log():
    """主监控循环,类似tail -f"""
    with open(LOG_FILE, 'r') as f:
        f.seek(0, 2)  # 移动到文件末尾
        while True:
            line = f.readline()
            if line:
                result = parse_log_line(line)
                if result:
                    ip, username = result
                    current_time = datetime.now()
                    # 记录该IP的失败尝试(每次+1)
                    failed_attempts[ip].append((current_time, 1))
                    # 检测
                    if detect_bruteforce(ip, current_time):
                        print(f"[ALERT] 暴力破解检测!IP:{ip} 在{TIME_WINDOW//60}分钟内失败{FAIL_THRESHOLD}+次,用户名包含:{username}")
                        # 可在此加入封禁逻辑(调用iptables或fail2ban API)
            else:
                time.sleep(0.5)  # 等待新日志
if __name__ == "__main__":
    print(f"SSH暴力破解检测启动,监控日志:{LOG_FILE}")
    monitor_log()

运行方法:保存为.py文件,以root权限执行(因读取auth.log需要权限)。
输出例子

[ALERT] 暴力破解检测!IP:192.168.1.100 在5分钟内失败13次,用户名包含:root

实战部署:日志分析与告警触发

1 自动化封禁IP

在上方脚本的[ALERT]位置加入以下代码,通过iptables实时封禁IP(需root):

import subprocess
# 封禁IP(示例:屏蔽该IP 1小时)
subprocess.run(["iptables", "-A", "INPUT", "-s", ip, "-j", "DROP"])
# 或通过fail2ban客户端:
# subprocess.run(["fail2ban-client", "set", "sshd", "banip", ip])

2 集成到cron定时任务(非实时场景)

若不需实时监控,可写一个定时脚本,每5分钟分析过去5分钟的日志:

#!/bin/bash
# 提取5分钟内的日志
tail -n 5000 /var/log/auth.log | grep "Failed password" | awk '{print $11}' | sort | uniq -c | awk '$1>10{print "可疑IP:"$2,"次数:"$1}'

将上述命令加入/etc/crontab,每5分钟执行一次并发送邮件。

3 可视化与告警

  • 邮件/钉钉通知:在Python脚本中调用smtplib或钉钉Webhook,当检测到攻击时立即通知管理员。
  • 日志归档:将检测到的IP、时间和尝试次数写入CSV,用于事后审计。

避免误报的优化策略

暴力破解检测的难点在于分辨恶意扫描与合法操作(如管理员忘记密码、自动化脚本出错),以下优化建议:

  1. 排除特定IP:加上白名单列表,忽略内部管理网段(如0.0.0/8)。
  2. 多维度阈值
    • 低频攻击:同一IP 30分钟内失败超过20次才告警。
    • 高频攻击:同一IP 1分钟内失败超过5次立即告警。
  3. 用户名加权:如果尝试的是rootadmin等默认管理员名,降低阈值(如5次即报警)。
  4. 历史行为基线:通过机器学习(如ISOMAP)学习正常登录模式,但脚本实现时可简化为:记录过去24小时合法IP的平均登录间隔,偏差超过3倍标准差的视为异常。

常见问题问答(FAQ)

Q1:必须用Python吗?能用Shell脚本实现吗?
A:可以,Shell脚本grep配合uniq -c即可统计失败IP(参考第4节cron示例),但处理复杂逻辑(如时间窗口剔除、持久化状态)不如Python灵活,推荐使用Python以支持扩展。

Q2:检测到暴力破解后,直接封禁IP是否安全?
A:不建议永久封禁,攻击者可能伪造合法IP(如使用真实游客IP作为跳板),误封导致正常用户无法登录,推荐临时封禁(如5分钟),并通过fail2ban动态管理黑名单。

Q3:如果日志轮转(logrotate)导致脚本读取中断怎么办?
A:脚本应记录上次读取位置(如使用seek + 文件inode监测),或在monitor_log()中加入while循环检测文件是否被轮转,更简单的方法是配合journalctl使用(systemd系统)。

Q4:能否同时检测成功登录的异常行为?
A:可以,解析Accepted日志项,统计某IP成功登录后是否立即执行高危命令(如sudo),但这需要结合/var/log/btmp或auditd审计日志,复杂程度更高。

Q5:脚本检测和fail2ban有什么区别?
A:fail2ban是成熟工具,支持多种服务(SSH、Apache等)和多种封禁后端(iptables、firewalld),自定义脚本的优势在于:

  • 完全控制检测逻辑(如时间窗口粒度)。
  • 可集成到企业自有安全系统(如SIEM)。
  • 无冗余依赖,适合嵌入式设备。

总结与扩展建议

本文从原理到代码,详细拆解了如何用脚本检测SSH暴力破解,核心思想是:解析日志 → 统计频率 → 触发告警 → 动态防御,动手复制上方的Python脚本,5分钟内即可运行在你的服务器上。

进阶方向

  • 多维数据融合:结合netstat -ntu实时连接数,分析攻击IP的端口扫描行为。
  • 全球化威胁情报:调用AbuseIPDB或Shodan API,自动比对攻击IP的恶意记录。
  • 零信任架构:将SSH改为证书登录或跳板机,从根本上减少暴力破解风险。

脚本是工具,安全策略才是核心,建议将此脚本作为第一道防线,与系统更新、最小权限原则共同构成纵深防御体系。

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