优先查mysql错误日志中高频“access denied”记录,用grep+awk统计来源ip频次;结合general_log分析异常连接行为、netstat/ss查看连接堆积、max_connect_errors触发情况及系统日志交叉验证。

查错误日志里高频 Access denied 记录
MySQL 错误日志(路径由 log_error 变量决定)是第一手证据。暴力攻击最直接的表现就是短时间内大量失败登录,每条失败都会记一条 Access denied for user。别靠肉眼翻,用命令快速筛:
-
grep "Access denied" /var/log/mysql/error.log | tail -n 200 | awk '{print $13}' | sort | uniq -c | sort -nr | head -10—— 提取来源 IP 并统计频次 - 注意时间窗口:攻击常集中在几分钟内爆发,比如 5 分钟内同一 IP 出现 50+ 次拒绝,基本可判定为暴力尝试
- 如果日志里还夹杂
Host 'x.x.x.x' is blocked,说明 MySQL 自带的max_connect_errors触发了临时封禁,这是已发生攻击的铁证
看通用日志中异常连接行为
通用日志(general_log)记录所有连接和语句,但默认关闭。若已开启,它比错误日志更细粒度——能看见攻击者在试哪些用户名、是否连成功过、甚至有没有执行 SELECT USER() 这类探针语句。
- 先确认状态:
SHOW VARIABLES LIKE 'general_log%';,若general_log值为OFF,生产环境不建议临时开,会显著拖慢性能 - 若已启用,查最近 100 条连接:
SELECT * FROM mysql.general_log WHERE command_type = 'Connect' ORDER BY event_time DESC LIMIT 100; - 重点盯:相同 IP 在极短时间内反复连接不同用户(如
root、admin、test),或连接后立刻断开(无后续 SQL),属于典型字典扫描特征
用 netstat 和 ss 看连接堆积
暴力工具(如 hydra、medusa)常并发建连,MySQL 连接数会突增,且大量处于 SYN_RECV 或 TIME_WAIT 状态,这不是业务行为该有的样子。
- 查当前连接数:
mysql -e "SHOW STATUS LIKE 'Threads_connected';",对比日常基线(比如平时 20,突然跳到 200+) - 查可疑连接源:
ss -tnp | grep :3306 | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -nr | head -5 - 注意云环境干扰:某些云厂商的健康检查也会连 3306,需结合 IP 段过滤(如排除 VPC 内网段、云平台元数据地址)
核对 max_connect_errors 是否被频繁触发
MySQL 的 max_connect_errors 是内置防御机制,默认值 100。一旦某 IP 连续失败超限,该 IP 会被锁住,后续连接直接报 Host is blocked。这个变量本身不记录谁被锁,但它的变化就是攻击发生的刻度尺。
- 查当前值:
SHOW VARIABLES LIKE 'max_connect_errors'; - 查哪些账号被锁:
SELECT host, max_connect_errors, connect_errors FROM mysql.user WHERE connect_errors > 0;(MySQL 8.0+ 支持;5.7 及以前需依赖错误日志反推) - 重置单个 host 错误计数:
FLUSH HOSTS;,但别滥用——这会清掉所有被锁 IP,可能让攻击者继续扫 - 真正要改的是策略:把
max_connect_errors调低(如设为 10),并配合防火墙或 HSS 主机防护做 IP 封禁,否则光靠 MySQL 自身很难拦住高频暴破
真实攻击往往不会只留下单一痕迹。比如错误日志里看到某 IP 高频拒绝,ss 又发现它正维持 30+ 半开连接,mysql.user 里还看到它的 connect_errors 已满——这三者交叉印证,基本不用再怀疑。最容易被忽略的是:很多团队只盯着 MySQL 日志,却忘了同步查系统层的 /var/log/auth.log 或云平台的安全组访问日志,而攻击者扫完 MySQL 后,常会顺手扫 SSH,IP 行为是连贯的。











