调整fail2ban的mysql-auth.conf过滤器触发Python异常排查
问题根因与解答
第一次Python报错的原因
这个错误完全是配置写法错误导致,和本地Python环境无关。
fail2ban使用Python标准库的configparser模块解析配置文件,该模块默认将%(变量名)s格式的字符串识别为配置插值变量,会自动替换为对应配置项的值。你第一次写正则时开头加了^%(?:...),configparser看到%(就判定你要引用插值变量,但后续的:?不是合法的变量名格式,直接抛出InterpolationSyntaxError异常。
核心配置项说明
before = common.conf
这个配置不是强制必填项,作用是在加载当前过滤器配置前,先引入common.conf公共配置文件。该文件预定义了大量通用规则:包括<HOST>占位符的IP匹配正则、通用日志前缀匹配规则、常用日期匹配模板等,引入后可以直接复用这些公共规则减少重复代码。但如果你的服务日志格式和公共规则预设的格式不匹配,硬套公共规则反而会导致匹配失败。^%(__prefix_line)s
这是引用common.conf中预定义的__prefix_line正则片段的写法,该片段用来匹配传统类syslog日志的行首前缀(比如进程名、PID、日志级别标签等结构)。
你使用的是MySQL 8.0默认错误日志格式,时间戳之后的结构是「线程ID + 多个方括号包裹的日志标签」,和__prefix_line预设的前缀结构完全不匹配,把这段拼在正则开头相当于强制要求日志符合不相关的格式,自然会出现0命中的问题。
配置注意事项
- fail2ban处理日志时,会先通过内置/自定义的日期模板匹配并剥离行首的时间戳,剩余内容才会交给
failregex做匹配,你之前自己写的正则重复匹配时间戳部分,就算去掉__prefix_line也会因为匹配不到已经被剥离的时间戳导致命中失败。从你贴的测试结果也能看到,内置日期模板已经100%命中了你的MySQL日志时间格式,不需要自己写时间戳匹配规则。 - 正则中必须使用内置
<HOST>占位符标记恶意IP的位置,不要自己写IP匹配规则,fail2ban会自动把这个占位符替换成兼容IPv4/IPv6的匹配表达式,同时自动提取IP地址做封禁。 - 如果正则中需要使用字面量
%字符,必须写成%%做转义,避免触发configparser的插值语法报错。
可用配置示例
针对你的MySQL 8.0日志场景,/etc/fail2ban/filter.d/mysqld-auth.conf可按如下配置:
[Definition] before = common.conf failregex = ^\s*\d+ \[\w+\] \[[^\]]+\] \[Server\] Access denied for user '[^']+'@'<HOST>'(?: \(using password: (?:YES|NO)\))?\s*$ # 按需配置忽略规则,比如跳过本地回环、内网信任IP的匹配 ignoreregex =
配置完成后执行如下命令测试匹配效果:
fail2ban-regex /etc/mysql/error.log /etc/fail2ban/filter.d/mysqld-auth.conf
测试显示正常命中后,重启fail2ban服务即可生效。
补充提示:你当前安装的fail2ban 0.9.4版本较旧,Ubuntu 20.04官方软件源内置的fail2ban版本对MySQL 8.0日志的兼容性更好,如果后续遇到兼容问题,可以卸载手动安装的版本,改用
apt install fail2ban安装源内版本。
内容的提问来源于stack exchange,提问作者Peter Maurer
相关产品推荐
相关产品推荐

