每个暴露在外的服务都会收到同一条建议:装上 fail2ban。对 VPN 网关来说,这条建议既不算错,也不够用;把它当成加固清单上的一个勾选项,正是人们最后留下一个封不住任何有用东西的 jail 的原因。Fail2ban 读取你指定的失败记录,并请求执行后端封禁匹配的来源。它的全部价值取决于记录来自哪个认证面、记录里的地址是不是真正的客户端,以及该地址背后的其他人会怎样。

从机制上说,fail2ban 是什么

过滤器匹配日志中的行,jail 按来源统计匹配次数,动作通过防火墙后端施加封禁。三个可动部件,每一个都可能独立出错。

三者都不碰认证路径:fail2ban 只在事后对证据作出反应,从不自行校验凭证。因此 jail 可以运行得很干净,而它所指的那个面依旧和以前一样暴露。

隧道监听器不是登录表单

OpenVPN监听器如果用tls-auth或tls-crypt保护起来,就会在常规 TLS 处理开始之前丢弃缺少控制通道保护的报文。从未持有密钥的扫描器不会产生任何过滤器能统计的东西。证书认证又加了一道门,因为根本没有密码可猜。Fail2ban 项目记录了一种通用的日志驱动模型,而通用 VPN 过滤器不会把未认证报文变成有意义的失败事件。

如果网关只接受证书,你所防御的暴力破解故事在该端口上也许根本不存在。

那么,你保护的究竟是哪个面?

同一台主机常常暴露三样不同的东西:隧道监听器、客户端配置或自助服务门户,以及管理页面。门户和管理页面有密码表单,会产生过滤器能统计的日志行。隧道也许只会产生含义完全不同的握手错误。让 jail 对应这个面,而不是对应产品名。

盯着错误日志的 jail 比没有更糟,因为它制造了没有覆盖面的信心。把登录过滤器对准隧道的握手错误,计数器就会在从未持有密钥的扫描器上触发,而针对门户的密码攻击却不被统计。在相信 jail 的数字之前,先读一读过滤器匹配的那行日志。

来源归属是最薄弱的环节

封禁的好坏,取决于它瞄准的地址。当服务位于本地反向代理之后时,日志里的客户端地址可能是代理,封掉它就是封掉所有人。信任来自不可信来源的转发头,等于把封禁任意地址的能力交给攻击者。在 UDP 上源地址可以被伪造,因此统计它们比统计一次完整的 TCP 登录更需谨慎。

把来源归属方法写进 jail 的 README,因为来自不可信跳点的转发头会把封禁变成武器。

附带代价是其他人

同一个办公室 NAT 后面的多名员工共用一个地址,因此一个过期的已保存密码就可能在越过阈值后锁住整个站点。日志显示的是一个来源和一个账户失败,而不是全站故障。

短封禁和温和的阈值能减少这种情况,而一份写明的解封路径能在它仍然发生时降低支持负担。地址是一个粗糙的信号而非身份,提交工单的人描述的是故障,而不是阈值。

何时采用它,何时该去修别的东西

当你能控制的某个面上存在真实、可归属、反复出现的在线登录失败,并且执行后端确实覆盖了那个面时,才采用它。当问题出在薄弱的凭证策略、暴露在互联网上的管理页面,或一个因为已被攻陷而成功登录的账户时,该去修别的东西。封禁修不好其中任何一个,也无法吸收已经打满上行链路的流量。最后这个问题属于上游,属于那些能在报文到达你之前做过滤的人。

让每个 jail 只绑定一个面,复查误报,并衡量被避免的认证工作量,而不是被封禁的地址数量。

相关文章