fail2ban优化配置+邮件预警 背景fail2ban配置生效后可以使用虽配置了邮件预警但是不能实时接收告警信息1、内网邮件系统内网STMP服务器DNS解析不到2、系统配置的mail用不了虽postfix可以配置relayhost(中继主机)它告诉 Postfix 不要做 DNS 查找MX 记录可以使用但是出现了新问题。3、问题外域邮箱地址且发送多个本地域名不存在的地址。思路Fail2ban 本身就原生支持在封禁/解封时发送包含 IP、规则名称等详细信息的邮件不需要额外写日志监控脚。用一个非常轻量级的 Python 脚本作为邮件发送工具完美绕过 Postfix 认证难题并让 Fail2ban 在特定动作时调用它。终极方案Fail2ban 原生 Action Python 轻量发信操作第一步创建 Python 邮件发送脚本vim /usr/local/bin/fail2ban_mail_alert.py注意点python3的路径[rootlocalhost bin]# which python3 /usr/local/bin/python3 [rootlocalhost bin]# python3 --version Python 3.12.7 [rootlocalhost bin]#chmod x /usr/local/bin/fail2ban_mail_alert.py#!/usr/local/bin/python3 import smtplib from email.mime.text import MIMEText import sys import socket import re # 配置 SMTP_HOST c**.******.cn SMTP_PORT 225 SENDER sy_*******.cn PASSWORD *********** # 替换为真实密码 RECEIVER e***w**.cn LOCAL_IP 192.168.16.129 #本机IP # # 格式化时间把秒转换为天/小时/分钟 def format_time(time_str): if not time_str or time_str N/A: return N/A # 如果已经是带字母的格式如 1d, 2h直接返回 if re.search(r[a-zA-Z], time_str): return time_str try: seconds int(time_str) if seconds 86400: return f{seconds // 86400}天 elif seconds 3600: return f{seconds // 3600}小时 elif seconds 60: return f{seconds // 60}分钟 else: return f{seconds}秒 except: return time_str # 接收 fail2ban 传过来的参数 action sys.argv[1] if len(sys.argv) 1 else unknown ip sys.argv[2] if len(sys.argv) 2 else N/A jail sys.argv[3] if len(sys.argv) 3 else N/A username sys.argv[4] if len(sys.argv) 4 else N/A bantime format_time(sys.argv[5]) if len(sys.argv) 5 else N/A findtime format_time(sys.argv[6]) if len(sys.argv) 6 else N/A maxretry sys.argv[7] if len(sys.argv) 7 else N/A # 构建邮件内容 subject f[Fail2ban告警] {action} - 规则: {jail} - 服务器: {LOCAL_IP} if action 封禁IP: body f Fail2ban 监控触发动作 ---------------------------------- 告警服务器 IP: {LOCAL_IP} 动作状态: {action} 触发规则: {jail} 来源 IP: {ip} 关联用户: {username} 触发条件: {findtime}内失败{maxretry}次 封禁时长: {bantime} ---------------------------------- else: body f Fail2ban 监控触发动作 ---------------------------------- 告警服务器 IP: {LOCAL_IP} 动作状态: {action} 触发规则: {jail} 来源 IP: {ip} 关联用户: {username} ---------------------------------- msg MIMEText(body, plain, utf-8) msg[Subject] subject msg[From] SENDER msg[To] RECEIVER try: with smtplib.SMTP(SMTP_HOST, SMTP_PORT) as server: server.login(SENDER, PASSWORD) server.sendmail(SENDER, RECEIVER, msg.as_string()) print(Mail sent successfully) except Exception as e: print(fFailed to send mail: {e}) sys.exit(1)第二步创建自定义 Action 文件Fail2ban 支持通过动作文件扩展功能不会导致配置字符串解析错误vim /etc/fail2ban/action.d/mail-alert.conf[Definition] # 服务启动通知 actionstart /usr/local/bin/fail2ban_mail_alert.py 服务启动 N/A name N/A # 服务停止通知 actionstop /usr/local/bin/fail2ban_mail_alert.py 服务停止 N/A name N/A # 封禁IP通知包含IP、规则名、用户名等 actionban /usr/local/bin/fail2ban_mail_alert.py 封禁IP ip name F-USER bantime findtime maxretry # 解封IP通知 actionunban /usr/local/bin/fail2ban_mail_alert.py 解封IP ip name N/A第三步配置 Fail2ban 动作和规则编辑jail.local或jail.d下的配置,本次配置就不做过多解释主要是action变化较大vim /etc/fail2ban/jail.localtime 600 findtime 600 maxretry 5 banaction iptables-allports action %(banaction)s[name%(__name__)s, bantime%(bantime)s, port%(port)s, protocol%(protocol)s] mail-alert[name%(__name__)s, bantime%(bantime)s, findtime%(findtime)s, maxretry%(maxretry)s] [sshd] enabled true port ssh backend auto logpath /var/log/secure第四步重启并测试服务重启systemctl restart fail2ban systemctl status fail2ban封禁IP到期自动解封IP:总结总体来说这种实现方式可控操作性更强推荐使用。1、注意python的路径2、注意/var/log/secure的日志格式有些匹配不到的需要调整