结论是光看show status或show processlist无法有效识别内网暴力破解,必须结合连接行为、认证失败日志和账号活跃度三类指标交叉判断;mysql自身不记录“密码错误”详情,mysql_error_log默认也不写认证失败事件(除非开启log_warnings = 2),因此防暴力破解本质是“找异常模式”,而非“抓明文错误”。

直接说结论:光看 SHOW STATUS 或 SHOW PROCESSLIST 无法有效识别内网暴力破解,必须结合连接行为、认证失败日志和账号活跃度三类指标交叉判断。
MySQL 自身不记录“密码错误”详情,mysql_error_log 默认也不写认证失败事件(除非开启 log_warnings = 2),所以靠状态监控防暴力破解,本质是“找异常模式”,不是“抓明文错误”。
怎么查连接暴增但没实际查询的可疑会话
暴力破解常表现为大量短连接建立后立即断开,不执行任何业务 SQL。这类行为在SHOW PROCESSLIST 中体现为:
• 大量 Command 字段为 Connect 或 Quit,Time 值普遍小于 2 秒
• User 列出现多个不同账号(如 admin、root、test)轮询尝试,且都来自同一内网 IP(如 10.0.1.45)
• State 长期停留在 Connecting to master 或空值,而非 Executing / Sending data
建议用如下语句实时筛查(每 5 秒跑一次):SELECT host, user, COUNT(*) AS cnt FROM information_schema.processlist GROUP BY host, user HAVING cnt > 10;
若某内网 IP + 某非业务账号组合频繁出现,基本可判定为扫描行为。
为什么 Aborted_connects 计数器不可信
Aborted_connects 是 MySQL 状态变量,但它统计的是“连接建立失败”总数,包含网络超时、握手失败、协议错误等多种原因,并不单指密码错。
• 内网暴力破解中,很多工具(如 hydra -t 4 mysql://…)会复用 TCP 连接池,导致 Aborted_connects 增长缓慢甚至不增长
• 若攻击者使用合法账号(撞库)但密码错,MySQL 8.0+ 默认启用 caching_sha2_password 插件,首次失败会触发插件重试机制,Aborted_connects 可能只计 1 次,而实际已尝试 3–5 次
• 更关键的是:该变量不带时间戳、不记录源 IP、不区分账号——无法定位到具体哪台内网机器在扫
必须开启的两个底层日志配置
要真正捕获暴力破解痕迹,得动 MySQL 配置层:
• 开启 log_error_verbosity = 3(MySQL 8.0.14+),并确保 log_error 指向可读文件,这样认证失败会记入错误日志,形如:[Warning] [MY-010055] Access denied for user 'admin'@'10.0.1.45' (using password: YES)
• 启用 audit log(需企业版)或社区版替代方案:general_log = ON + general_log_file = '/var/log/mysql/general.log',但注意性能损耗;更推荐用 mysqlauditlogin 工具解析二进制日志中的 Login event(需开启 binlog_format = ROW)
别依赖 slow_query_log——暴力破解不产生慢查询。
内网场景下最容易被忽略的盲点
内网不像公网有 WAF 或云防火墙自动封 IP,管理员常误以为“反正不对外”,结果放任 skip-networking = OFF + bind_address = 0.0.0.0 的默认配置。
• MySQL 默认监听所有接口,内网任意机器都能连,只要知道端口(默认 3306)和账号名
• 很多内部运维脚本硬编码了 root 密码,一旦某台跳板机失陷,攻击者直接用该密码反向爆破其他数据库
• performance_schema 中的 events_waits_summary_global_by_event_name 表里,wait/io/socket/sql/client_connection 的等待次数突增,往往是批量连接建立的信号,但这个指标需要手动聚合,没人盯就等于没用
真正有效的预防,不是等暴力发生后再查日志,而是提前砍掉攻击面:关掉非必要账号的远程登录权限(UPDATE mysql.user SET host='127.0.0.1' WHERE user='root'; FLUSH PRIVILEGES;),对必须开放的内网账号强制启用 caching_sha2_password + password_history = 5,并把认证失败告警接入 SIEM(比如用 Filebeat 抓 log_error 中的 Access denied 关键字)。











