你从社区帖子里复制了一个OpenVPN jail,重启了 fail2ban,却始终没有任何地址被封锁。原因几乎总是日志格式:Access Server 不写成品过滤器所期待的那些认证失败行。在动过滤器之前,先确认记录确实存在,因为模式无法匹配服务从未写入的内容。

以下是我在 Access Server 主机上遵循的流程:确认记录形态,写一条带锚点的表达式,用真实日志验证,然后按被攻击的界面拆分 jail,并确认封锁能落到防火墙上。

确认失败记录确实存在

Access Server 把自己结构化的行写入/var/log/openvpnas.log,客户端地址位于引号内的real_ip字段,而不是 syslog 行的开头。写任何模式之前,先搜一条你确知发生过的失败登录:

grep -i 'LOG ERR' /var/log/openvpnas.log | tail -20

如果什么都没有,下一个怀疑对象就是日志级别。Access Server 在/usr/local/openvpn_as/etc/as.conf里有一个日志数据库调试开关(DEBUG_LOGDB=1),改动之后必须重启服务。把这个开关当成诊断设置,模式定稿后要调回去,而不是当成永久配置。

既然已经在看这个文件,顺便记下哪些界面会往里写。客户端门户、管理界面和隧道认证的失败都落在同一个文件里,只是标记不同,而这个细节决定后面 jail 怎么拆。

以 real_ip 为锚点写一个过滤器

表达式要窄。一个宣称匹配任何含 IP 地址的行的过滤器,会因为普通断线就封人,而在繁忙的服务器上唯一的症状就是用户抱怨合上笔记本就被锁在外面。只宣称错误记录,并把引号里的地址捕获出来:

# /etc/fail2ban/filter.d/openvpnaccess.local
[Definition]
failregex = ^ .*LOG ERR.*"real_ip": "<HOST>".*
ignoreregex =

开头的空格不是装饰。Access Server 会给记录做缩进,锚在这个空格上能避免模式顺带匹配同一文件里其他无关服务写出的行。如果你的记录开头是时间戳,那就匹配那个前缀,但要锚在每一条你想宣称的记录都确实存在的东西上。

需要按界面精确匹配时,再要求同一行里出现界面标记(WEB_CLIENT、WEB_ADMIN或VPN)来收窄。一个带三条模式的过滤器,比三个只差一个词的过滤器更容易审查。

启用 jail 之前先测表达式

绝不要启用没有在生产日志上跑过的过滤器。文档给出的测试会把过滤器传两遍,一遍加载、一遍应用,而漏匹配行报告才是值得读的部分:

fail2ban-regex --print-all-missed /var/log/openvpnas.log \
  /etc/fail2ban/filter.d/openvpnaccess.local \
  /etc/fail2ban/filter.d/openvpnaccess.local > missed.txt

把匹配条数与第一步核实过的失败数对比。零匹配说明模式写错了;匹配到非认证失败的行说明模式太宽。把 missed.txt 读到你能解释每一条你选择不宣称的行为止。

日志很大时在副本上做这个测试,并在每次 Access Server 升级后重跑。日志格式就是你匹配的接口,而它并不是稳定的 API。

按界面而不是按守护进程拆 jail

一台 Access Server 提供多个认证界面:943/tcp 上的客户端和管理 Web 界面,以及多数部署中 1194/udp 或 443/tcp 上的隧道。一个 jail 覆盖全部,会让隧道上的猜测尝试封掉同样是你管理通道的地址,也掩盖了究竟哪个界面正在被打。给每个界面单独的 jail,各自带端口和阈值:

# /etc/fail2ban/jail.d/openvpnaccess.local
[openvpnas-web-client]
enabled  = true
port     = 943
protocol = tcp
filter   = openvpnaccess
logpath  = /var/log/openvpnas.log
maxretry = 3
findtime = 10m
bantime  = 1h
[openvpnas-tunnel]
enabled  = true
port     = 443
protocol = udp
filter   = openvpnaccess
logpath  = /var/log/openvpnas.log
maxretry = 5
findtime = 10m
bantime  = 1h

先用小计数和短封锁,观察一周真实流量后再调高。对共享办公地址给出宽松阈值,会连坐同一个 NAT 后面的所有人;对隧道界面下重手,会把凭证夜里过期的正常客户端一起断掉。

验证封锁、后端与连带影响

重启之后,状态输出是确认 jail 存在并在计数的最快方式:

fail2ban-client status
fail2ban-client status openvpnas-tunnel

接着确认封锁真的落到你在跑的那套防火墙上,因为给一个没人执行的后端配 jail 等于什么都没防。用 iptables 动作时地址出现在以 jail 命名的链里(f2b-openvpnas-tunnel);用 nftables 动作时它们进入 fail2ban 自己表里的一个集合。去查你的主机实际用哪一个,而不是想当然。

两项连带检查比封锁本身更重要。第一,确认real_ip是客户端地址,而不是负载均衡器或反向代理;在代理后面,每次封锁都落在代理上,会把整个服务一起拖下去。第二,把解封流程写下来,因为 02:00 撞上阈值的那个地址,通常属于值班工程师:fail2ban-client set openvpnas-tunnel unbanip 203.0.113.24。

调参时记住边界。Fail2ban 是单一认证界面上的限速器,不是访问控制层。它替代不了 MFA、按账号的权限限制,也替代不了把管理界面挡在公网之外;而 Access Server 有自己的 autoban 设置,在同一端口上叠两个限速器之前值得先看一眼。

相关文章