Fail2Ban防SSH暴力破解:日志监控、阈值调优与排障实战

发布时间:2026/11/2 19:42:46
Fail2Ban防SSH暴力破解:日志监控、阈值调优与排障实战 1. 凌晨三点的登录日志比任何告警都诚实如果你维护过一台对公网开放的 SSH 服务器大概率见过这种场面早上打开终端lastb输出刷了满满几屏/var/log/auth.log里成片的Failed password for invalid user admin用户名从root、oracle、test一路猜到pi。这不是针对你扫描器是全互联网撒网的任何一台开放 22 端口的机器上线几小时内就会被打上标记。默认配置下密码登录开着、失败次数不限、日志没人看等于把门虚掩着然后祈祷没人拧把手。Fail2Ban 就是解决这个问题的老牌工具。它不是防火墙也不是入侵检测系统它的定位可以概括成一句话盯着日志看发现某个 IP 在短时间内反复出错就顺手把这个 IP 塞进防火墙黑名单里关一段时间。名字里的“Fail”指的是失败行为“Ban”指的是封禁动作。它擅长处理 SSH 暴力破解、Web 登录爆破、邮件认证失败这类“单 IP 高频重试”的场景配置门槛低资源占用小非常适合个人服务器、小团队项目机和内网跳板机。这篇内容适合三类人看刚接手一台云主机、只会ssh rootip的新手已经装了 Fail2Ban 但不确定参数是否合理、想知道为什么有时候封不住的中级运维以及准备把防爆破策略标准化、需要一套可复现配置模板的团队负责人。我会从“为什么光改端口不够”讲到参数怎么算、配置怎么写、怎么测、怎么排查最后给一份我自己在用的配置骨架你可以直接抄。2. 为什么只改端口、只换强密码依然不够2.1 暴力破解的真实成本已经低到可以忽略很多人对暴力破解的印象还停留在“一个个试密码很慢”的阶段实际上现在的扫描器根本不针对你。它们做的事情是全网批量探测开放 22 端口的地址拿到 banner 后用一份包含几万条的“用户名 弱口令”字典做低频并发尝试每个 IP 只试几次就换下一个目标。这种模式下单看某一个 IP 的请求频率并不高但累加起来一台无人值守的机器一天被尝试几千次是常态。我做过一个粗糙的统计某台业务机在开放密码登录的 24 小时内Failed password记录超过 8000 条涉及 300 多个不同来源地址尝试最多的用户名是root其次是各种常见服务名和默认账户名。这个量级下指望“密码足够复杂”就能高枕无忧是把安全性完全押在单一维度上。密码强度、登录方式、暴露面收敛、失败响应这几层应该是叠加的而不是互相替代。2.2 Fail2Ban 的工作模型日志是唯一的信息源理解 Fail2Ban关键是理解它其实是一个“日志正则匹配器 动作执行器”的组合。它内部有三样东西Filter过滤器一组正则表达式用来从日志行里抠出“攻击者 IP”和“这是一次失败尝试”这两个信息Jail监狱一个监控单元绑定“哪个过滤器 看哪个日志 阈值多少 封多久 用什么动作封”Action动作封禁时具体执行的命令通常是往防火墙里插一条规则也可以是发邮件、写日志、调外部接口。一次完整的判定流程是这样的日志新增一行 → 过滤器命中 → 提取 IP → 该 IP 在findtime窗口内的失败次数加一 → 达到maxretry→ 执行action封禁bantime时长 → 到期自动解封。这个模型的优点是通用性极强任何会写日志的服务都能被纳管缺点也同样明显日志里没写的东西它一概不知道。如果日志格式变了、日志路径错了、时区乱了、日志被轮转截断了Fail2Ban 就变成了一个安静运行但什么也不做的进程。后面排查章节里八成的问题根子都在这里。2.3 它和防火墙、密钥登录之间是补充关系不是替代关系这里必须把定位说清楚不然容易产生错误的安全感。防护手段解决的问题局限禁用密码登录、改用密钥从根上消除“猜密码”这条路径密钥管理不当、私钥泄露仍然有风险改默认端口减少被无差别扫描命中的概率属于降低噪音不是安全边界防火墙白名单只允许可信来源访问移动办公、动态 IP 场景下维护成本高Fail2Ban对高频失败来源做自动封禁压缩攻击窗口依赖日志质量对慢速分布式尝试基本无效所以正确的组合姿势是优先上密钥登录并把密码认证关掉这是收益最大的一步在此基础上升级 Fail2Ban 作为第二层用来处理“密钥尝试失败”“非法用户探测”“协议层异常”这些残留噪音同时把日志盯起来让你知道有人在敲门。指望靠 Fail2Ban 单独扛住暴力破解属于把补丁当承重墙。还有一点经常被忽略Fail2Ban 封的是新连接。当某个 IP 已经被封它已有的 TCP 会话并不会立刻收到断开通知而是后续数据包被拒绝表现出来是会话卡死、输入无响应、最后超时断开。这个细节在排查“为什么封了对方还在线”时非常有用。3. 动手之前环境确认与几个关键选型3.1 先搞清楚你的日志到底落在哪Fail2Ban 的第一大坑就在这里。不同发行版、不同初始化系统的日志落点完全不同传统 syslog 体系下SSH 认证日志通常在/var/log/auth.logDebian 系或/var/log/secureRHEL 系纯 journald 体系下可能根本没有上面这两个文件日志只存在于journalctl里部分精简系统同时开了 rsyslog 和 journald两份日志都有但要确认哪份是实时的。先跑两条命令确认ls -l /var/log/auth.log /var/log/secure 2/dev/null journalctl -u ssh --no-pager -n 5第一条看文件在不在第二条看 journal 里有没有 SSH 的认证记录。注意服务单元名Debian/Ubuntu 上通常是ssh.serviceRHEL 系是sshd.service这个差异后面会直接影响 journal 后端的匹配。确认完日志再确认版本因为 0.10 和 0.11 在配置项上差异不小fail2ban-client --version0.11 及以上支持bantime.increment、bantime -1永久封禁、nftables 原生动作这些在 0.10 上要么没有要么写法不同。心里有数后面抄配置才不会踩空。3.2 防火墙后端怎么选iptables、nftables 还是 firewalldFail2Ban 的封禁动作最终要落到某种防火墙机制上选错了会出现“日志显示已封禁但规则没生效”的诡异现象。判断方法很简单看你系统当前实际在用哪套# 看 nftables 有没有规则 nft list ruleset | head -20 # 看 iptables 有没有规则 iptables -S | head -20 # 看 firewalld 是否在跑 systemctl is-active firewalld选型建议按这个顺序系统已经在用firewalld常见于 RHEL 系就用banaction firewallcmd-ipset不要绕过它直接操作 iptables否则 firewalld reload 会把你加的规则清掉系统是nftables 原生新版 Debian、部分容器宿主用nftables-multiport或nftables-allports比 iptables 兼容层干净老系统或者不确定用默认的iptables-multiport最稳几乎所有发行版都能跑。如果封禁频率高比如每天上百次建议额外启用 ipset 版本的动作。原因是纯 iptables 方案每封一个 IP 就往链里插一条规则规则多了匹配开销线性增长ipset 把 IP 放进哈希集合匹配是常数级规则数量再多也不影响性能。这是个在被打得比较狠的时候才会体会到差别的优化。3.3 安装方式与最小依赖主流发行版的仓库里都有现成包直接装就行# Debian / Ubuntu apt update apt install -y fail2ban # RHEL 系 dnf install -y fail2ban fail2ban-firewalld装完先别急着改配置看一眼默认服务状态和自带配置文件结构systemctl enable --now fail2ban ls /etc/fail2ban/你会看到jail.conf、jail.d/、filter.d/、action.d/这几样。核心原则永远不要直接改jail.conf因为包升级会覆盖它你所有的自定义配置会在一夜之间蒸发。正确做法是新建jail.local或往jail.d/里丢.local文件加载顺序是jail.conf→jail.d/*.conf→jail.local→jail.d/*.local后面的覆盖前面的。我的习惯是全部写在/etc/fail2ban/jail.local一个文件里结构清晰、迁移方便换机器的时候复制一个文件就完事。4. 配置逐项拆解jail.local 里每一行到底在干什么4.1 全局段 [DEFAULT]三个时间参数怎么算才合理先给一份可以直接用的骨架然后逐项解释[DEFAULT] # 封禁时长首次 1 小时 bantime 1h # 统计窗口10 分钟 findtime 10m # 触发阈值窗口内失败 5 次 maxretry 5 # 白名单本机回环 管理出口 ignoreip 127.0.0.1/8 ::1 198.51.100.0/24 # 日志后端使用 systemd journal backend systemd这三个参数不是拍脑袋定的它们之间存在约束关系。核心逻辑是maxretry次失败必须能在findtime内被观察到否则永远不会触发。举个反例如果在findtime 60早期版本单位是秒的情况下把它理解成 60 分钟而bantime设成 10 分钟就会出现“封禁时间比统计窗口还短”的荒谬情况——攻击者刚被封窗口还没滑过去人已经解封了。我的经验取值是这样推的先统计自己正常登录时输错密码的概率。绝大多数人一次登录最多错 1 到 2 次所以maxretry 5留了足够余量不会误封自己同时 5 次对于字典攻击来说又足够触发因为扫描器通常是连续尝试几十上百次5 次的门槛它们一定会撞上。关于findtimeSSH 暴力破解的特点是短时间内密集尝试10 分钟的窗口能覆盖绝大多数扫描行为又不至于把“昨天下午输错两次、今天上午输错三次”这种跨天的偶发失败累加进去。关于bantime这里有个取舍。设短了比如 10 分钟攻击者等一会儿继续封禁形同虚设设长了比如永久万一误封了自己或者某个合作方出口 IP处理起来麻烦。我的建议是首次封禁 1 小时起步同时开启递增封禁让反复作案的 IP 自动升级惩罚[DEFAULT] bantime.increment true bantime.factor 2 bantime.maxtime 4w含义是同一个 IP 第二次被封禁时时长按倍数放大依次是 1h、2h、4h、8h……最长不超过 4 周。这样既保留了误封的自愈能力又让持续攻击者付出越来越高的代价。递增状态会记录在 Fail2Ban 的本地数据库里重启不会丢失。4.2 sshd 段过滤器模式和日志来源的匹配[sshd] enabled true port ssh filter sshd logpath %(sshd_log)s maxretry 3 bantime 24h这里有几个点值得展开。port ssh是引用/etc/services里 ssh 对应的端口号。如果你改过 SSH 端口这里必须写成具体数字多个端口用逗号分隔比如port 2222,22。写错了会导致封禁规则只对默认端口生效攻击者换个端口继续打而你以为已经防住了。filter sshd用的是内置过滤器。这个过滤器其实有多个模式通过方括号指定sshd[normal]是默认级别能覆盖最常见的失败密码、非法用户sshd[ddos]更激进会把连接层面的异常也算进去sshd[aggressive]命中范围最广包括“连接被关闭”“协议版本不匹配”这类行为适合把扫描器也一起清掉代价是误封概率略升。我在对外暴露的机器上一般用sshd[aggressive]因为在那台机器上任何非预期连接都值得记一笔。logpath %(sshd_log)s是引用变量实际值在paths-*.conf里定义。Debian 系是/var/log/auth.logRHEL 系是/var/log/secure。用变量的好处是配置跨发行版可移植不用手改路径。如果你的系统只有 journald没有日志文件就要靠backend systemd加journalmatch。这里有个非常容易翻车的细节内置sshd过滤器的journalmatch默认写的是_SYSTEMD_UNITsshd.service而 Debian/Ubuntu 上单元名是ssh.service两者对不上结果就是 Fail2Ban 运行正常、日志匹配零条、什么也不封。解决办法是在 jail 里显式覆盖[sshd] enabled true backend systemd journalmatch _SYSTEMD_UNITssh.service _COMMsshd这个坑我至少在有那么几台机器上撞过表现极具迷惑性systemctl status fail2ban一片绿色fail2ban-client status sshd显示Total failed: 0只有把journalmatch改对之后数字才开始跳。4.3 ignoreip 白名单写法比你想的讲究ignoreip支持单个 IP、CIDR 网段和 IPv6 地址多条之间用空格分隔。写成逗号在某些版本上会被当成一个非法字符串导致白名单整体失效——这是我在别人机器上见过最多的低级错误之一。白名单里应该放什么127.0.0.1/8和::1本机回环某些本地健康检查会走这里你的固定办公出口 IP或者跳板机的地址监控探针、备份任务、自动化部署节点的来源地址云平台的内网健康检查网段如果你不确定先别加观察日志再说。如果你的管理出口是动态 IP就别硬往白名单里塞了改用“管理入口单独走一个非标准端口 密钥认证 只允许特定用户”这种更可控的方式。白名单写得越宽等于防线的口子越大这一点要时刻清醒。4.4 封禁动作从“只封”到“封 告警 留痕”默认的action_是纯封禁不产生额外信息。如果你想知道“谁在打、从哪来、什么时间”可以换成带邮件或带 whois 的动作动作行为适用场景%(action_)s仅封禁默认最轻量%(action_mw)s封禁 whois 查询 邮件通知想有人盯着看的小规模环境%(action_mwl)s上面两项 附带相关日志需要事后复盘的场景%(action_allports)s封禁该 IP 的所有端口情节严重的重复攻击者这里有个实打实的坑要提前说带邮件的动作依赖本机 MTA。很多云主机没有装 sendmail 或 postfix动作执行时会在发信这一步卡住甚至超时表现出来是封禁延迟、日志里报错、严重时拖慢整个 Fail2Ban。我的建议是前期先用纯封禁动作把日志盯住确实需要告警走“Fail2Ban 写 syslog → 日志采集端做匹配告警”这条链路比在本机折腾 MTA 稳得多。5. 把误封和漏封同时压下去的策略调优5.1 先从日志里反推阈值而不是抄别人的数字参数没有普适最优解得看你机器实际承受的流量。动手配之前先做一次统计# 按小时统计失败次数找出攻击高峰 grep Failed password /var/log/auth.log \ | awk {print $1 $2 $3} \ | uniq -c | sort -rn | head -20# 统计攻击来源 IP 的分布 grep Failed password /var/log/auth.log \ | grep -oE ([0-9]{1,3}\.){3}[0-9]{1,3} \ | sort | uniq -c | sort -rn | head -20第一条命令告诉你攻击的时间分布如果集中在某几个时段、每次几分钟内几百条说明是典型的扫描器行为findtime 10m加maxretry 5完全够用。第二条告诉你来源集中度如果前 20 个 IP 占了总量的 80%说明封禁策略会非常有效如果 IP 极度分散、每个只试两三次那 Fail2Ban 基本抓不到这种情况下更该做的是关闭密码登录、上密钥、甚至只允许白名单访问。这个“先看数据再定参数”的习惯比任何配置模板都值钱。我见过太多人直接抄一份网上流传的配置maxretry设成 10、bantime设成 600 秒结果机器天天被打还以为是工具不好用。5.2 用 recidive 补上“屡教不改”的那一类递增封禁解决的是“同一个 IP 反复触发同一个 jail”的问题但有些攻击者会换着服务打——今天试 SSH明天试 Web 登录每个 jail 各自计数永远到不了长期封禁的门槛。这时候可以启用recidive它监控的是 Fail2Ban 自己的日志专门抓“在多个 jail 里被反复封禁”的 IP然后一次性封掉所有端口[recidive] enabled true logpath /var/log/fail2ban.log banaction %(banaction_allports)s bantime 1w findtime 1d maxretry 3含义是一天之内被任意 jail 封过 3 次的 IP直接全端口封一周。这个 jail 有个前置条件Fail2Ban 的日志必须写到文件里logtarget FILE这是默认值。如果你为了省磁盘把日志改成了SYSLOG或NONErecidive就会因为找不到日志文件而失效而且它不会明显报错只是安静地不工作。5.3 和密钥登录、端口收敛配合才是完整的组合拳调参调到极致也改变不了一个事实Fail2Ban 是被动响应攻击者总能先试几次。真正的防线应该是让“试”这件事本身失去意义。我的标准配置顺序是这样的生成密钥对把公钥部署到目标账户的authorized_keys编辑/etc/ssh/sshd_config设置PasswordAuthentication no、PermitRootLogin prohibit-password、PubkeyAuthentication yes改一个非默认端口这一步主要是降噪别当成安全措施sshd -t校验配置语法再systemctl reload ssh保留一个已登录的会话不要关另开窗口验证新配置能连上确认无误后再关旧会话最后上 Fail2Ban把残留的探测行为收掉。第 5 步是血泪教训。我早年改sshd_config的时候手快把PubkeyAuthentication拼错成PubkeyAuthentcationreload 之后所有连接被拒机器直接锁死最后靠控制台重置才救回来。从那以后我改 SSH 配置永远留一个活会话兜底这个习惯救过我至少三次。5.4 用一条命令看清当前到底封了谁日常巡检不需要开日志翻直接问 Fail2Banfail2ban-client status fail2ban-client status sshd第二条的输出大致长这样Status for the jail: sshd |- Filter | |- Currently failed: 3 | |- Total failed: 1247 | - File list: /var/log/auth.log - Actions |- Currently banned: 12 |- Total banned: 386 - Banned IP list: 203.0.113.45 198.51.100.77 ...这里几个数字的含义要分清Currently failed是当前窗口内还没达到阈值的累计Total failed是自启动以来的历史总数Currently banned是当下正在封禁中的数量Total banned是历史累计封禁次数。如果Total failed一直在涨但Total banned几乎不动说明阈值设得太高或者过滤器没匹配上如果Total banned涨得飞快但Currently banned很小说明封禁时长短于攻击间隔攻击者总能等到解封。6. 从零跑通一遍安装、测试、解封、持久化6.1 最小可用配置的完整落地过程假设是一台 Debian 系的新机器完整流程如下。第一步安装并写入配置apt update apt install -y fail2ban cat /etc/fail2ban/jail.local EOF [DEFAULT] bantime 1h findtime 10m maxretry 5 ignoreip 127.0.0.1/8 ::1 backend systemd bantime.increment true bantime.factor 2 bantime.maxtime 4w [sshd] enabled true port ssh filter sshd journalmatch _SYSTEMD_UNITssh.service _COMMsshd maxretry 3 bantime 24h EOF第二步校验配置语法。Fail2Ban 没有直接的configtest但可以用-d把解析后的完整配置 dump 出来任何语法错误都会在这一步暴露fail2ban-client -d /tmp/f2b-dump.txt 21 echo exit: $?如果 dump 出来的内容里能看到sshd段的maxretry是你写的 3说明配置被正确解析了。这一步能提前发现 90% 的配置问题比启动后再排查省事得多。第三步重启并确认状态systemctl restart fail2ban systemctl status fail2ban --no-pager fail2ban-client status sshd重点看输出里的File list或Journal matches是否指向你预期的位置Total failed是否在几秒后开始增长。这两项都对了才算真正跑通。6.2 手动触发一次封禁验证整条链路光看状态不够得实际验证“封禁动作真的写进防火墙了”。有两种验证方式。第一种是手动调用接口模拟一次封禁fail2ban-client set sshd banip 203.0.113.45然后立刻检查防火墙# iptables 后端 iptables -S | grep f2b # nftables 后端 nft list ruleset | grep -A3 f2b正常情况下能看到类似-A f2b-sshd -s 203.0.113.45/32 -j REJECT的规则。看到这条说明从“配置解析 → 动作执行 → 防火墙写入”整条链路是通的。第二种是真实触发。从另一台机器不要用本机本机 IP 在白名单里故意用错误密码连几次ssh -o PreferredAuthenticationspassword wronguser目标地址连续输错 4 次超过maxretry 3然后回目标机器看fail2ban-client status sshdBanned IP list里应该出现那台测试机的地址同时测试机再连就会超时或直接被拒。验证完记得解封不然测试机自己就被关在门外了fail2ban-client set sshd unbanip 203.0.113.456.3 解封、重载、重启三者行为不一样这几个命令经常被混用但效果差别很大值得单独说清楚命令作用是否保留封禁列表适用场景fail2ban-client reload重新加载配置保留改完参数后首选fail2ban-client restart重启服务进程保留数据库恢复配置大改或进程异常systemctl restart fail2ban同上走系统服务管理保留数据库恢复常规重启fail2ban-client set jail unbanip ip解封单个 IP只影响该 IP误封处理fail2ban-client unban --all清空所有封禁全部清空调试或误配后重置“保留”依赖的是/var/lib/fail2ban/fail2ban.sqlite3这个数据库。如果你手动删了这个文件或者目录权限不对导致写不进去重启后封禁列表就会清空——这在容器化部署里特别常见因为容器重建后这个路径往往是空的。所以容器方案要么把这个目录挂成持久卷要么接受“重启后封禁清零”这个事实并做额外加固。6.4 让规则在系统重启后依然生效Fail2Ban 本身设了开机自启就够了吗大多数情况下是的。但有两类情况需要额外确认一是防火墙服务启动顺序。如果系统同时启用了 firewalld 和 Fail2Ban而 Fail2Ban 先于 firewalld 启动它插入的规则可能被 firewalld 后续的初始化动作冲掉。确认方式很简单重启后跑一次iptables -S | grep f2b或nft list ruleset | grep f2b规则在就说明顺序没问题。不在的话给 Fail2Ban 的服务单元加个Afterfirewalld.service的依赖覆盖。二是云平台安全组与主机防火墙的叠加关系。云平台的安全组在主机外部生效Fail2Ban 操作的是主机内防火墙两者是串联的安全组先过滤放行的流量才轮到主机防火墙。这意味着你不能指望 Fail2Ban 去拦截那些被安全组已经挡掉的流量反过来安全组放行的来源如果被 Fail2Ban 封了照样连不进来。排查“为什么封了还能连”的时候先确认流量到底走到了哪一层。7. 排查实录那些日志看着正常但就是不封的时刻7.1 状态显示正常但 Total failed 永远是 0这是最高频的问题几乎全部指向“日志没读到”。按这个顺序排查第一步确认日志源。先手动确认日志里确实有失败记录且是实时的tail -f /var/log/auth.log # 或 journalctl -u ssh -f然后在另一个窗口故意输错一次密码看日志有没有跟着刷新。如果日志本身不刷新问题在 SSH 或日志服务不在 Fail2Ban。第二步用 fail2ban-regex 单独验证过滤器。这个工具能直接告诉你正则到底命中了多少行fail2ban-regex /var/log/auth.log /etc/filter.d/sshd.conf输出里的Lines和matched两个数字是关键。如果matched为 0说明日志格式和你用的过滤器对不上可能是 SSH 版本差异导致的措辞变化也可能是日志经过了某种格式化处理。如果matched有数字但Failregex部分全是 0说明命中了行但没提取出 IP通常是正则的捕获组问题。第三步检查 journalmatch。就是前面说的单元名不匹配问题。验证方法journalctl _SYSTEMD_UNITsshd.service -n 5 journalctl _SYSTEMD_UNITssh.service -n 5哪条有输出journalmatch就该写哪个。第四步检查 Fail2Ban 自身的日志。它的启动过程会打印每个 jail 的初始化结果包括读了多少行、有没有报错journalctl -u fail2ban -n 50 --no-pager grep -i error\|warning /var/log/fail2ban.log | tail -20常见的报错有日志文件权限不足Fail2Ban 以非 root 运行时、过滤器文件语法错误、action 脚本找不到对应命令。7.2 把自己封了怎么办先别慌也别急着重启服务器——重启很可能让事情更糟因为封禁列表是持久化的重启后照样封着。如果你还能通过其他途径进入系统控制台、VNC、云厂商的救援模式直接解封fail2ban-client set sshd unbanip 你的IP fail2ban-client unban --all如果进不去就看有没有其他已建立的会话还活着。前面说过封禁后已有连接会卡死但不会立刻断如果那个会话还能响应赶紧执行解封命令。预防措施比补救重要。我的做法是三层保险ignoreip里放固定出口 IP保留一个长期在线的管理通道跳板机或控制台不依赖单一入口阈值不要设得太激进maxretry低于 3 的时候正常人手滑两次就危险了。7.3 封禁规则在防火墙里看不到分两种情况。第一种是动作选错了后端。比如系统实际在用 nftables但你配了banaction iptables-multiportFail2Ban 会去操作 iptables 兼容层规则确实写进去了但nft list ruleset里看起来结构不一样容易误判成没生效。用fail2ban-client get sshd actions能看到当前 jail 实际使用的 action 名称对着系统实际情况核对一遍。第二种是规则被其他组件清掉了。典型场景是 firewalld reload、Docker 重启、某些安全加固脚本重置防火墙。判断方法是看封禁时间和规则消失时间是否吻合。如果是就改成与现有防火墙体系兼容的 action或者干脆用 ipset 方案把 IP 集合和防火墙规则解耦减少被覆盖的概率。7.4 容器环境里的特殊处理在容器里跑 Fail2Ban 有几个绕不开的点权限需要NET_ADMIN能力才能操作网络规则否则动作执行会失败日志来源容器里通常没有 SSH 日志要么把宿主机日志目录挂进来要么改用 journal 网关规则可见性容器内操作的是容器自己的网络命名空间如果用的是 host 网络模式才能影响宿主机用 bridge 模式时封禁只对容器内部生效对宿主机的 SSH 毫无作用持久化/var/lib/fail2ban/必须挂卷否则每次重建容器封禁记录全丢。坦白说容器里跑 Fail2Ban 的性价比不高除非你确实需要在容器边界做统一管控。更省心的做法是把 Fail2Ban 装在宿主机上让它直接看宿主机日志、操作宿主机防火墙。7.5 常见问题速查表现象最可能原因快速验证处理方式Total failed 恒为 0日志路径或 journalmatch 不对tail -f日志看是否刷新修正logpath或journalmatch日志有记录但 matched 为 0过滤器正则不匹配当前日志格式fail2ban-regex跑一遍换 filter 模式或自定义 filter显示已封禁但连不上的是自己白名单缺失fail2ban-client status sshd加ignoreip或临时 unban封禁规则重启后消失数据库路径不可写或未持久化检查/var/lib/fail2ban/权限修正权限或挂载持久卷封禁延迟很大动作里带邮件且无 MTA看 fail2ban.log 有无超时报错换纯封禁动作告警外置封了对方仍在尝试对方已建立会话或换了源 IPipset list或iptables -S核对属正常现象配合密钥登录加固每天封几百个但攻击不停IP 分散单点封禁收益低统计来源 IP 分布收敛暴露面关闭密码登录8. 我自己的配置习惯和几条不写在文档里的经验配置写到最后其实是在做取舍封得狠一点误封风险高一点封得松一点噪音多一点。我现在稳定用的一套是findtime 10m、maxretry 3、首封1h、递增到4w封顶、filter sshd[aggressive]、加recidive兜底、动作只用纯封禁不做邮件。这套参数在十几台机器上跑了两年多误封自己的次数是两次都是因为在咖啡厅用公共网络登录后来把常用出口加进白名单就再没出现过。有个小技巧值得分享把fail2ban-client status sshd的输出做成一个定时任务写到本地文件里每天扫一眼封禁数量的趋势。数量突然翻倍通常意味着有新的扫描波段来了或者你某个服务的暴露面变了。这个动作几乎零成本但比任何告警系统都更早让你察觉到异常。还有个容易忽略的点是日志清理。Fail2Ban 能正确跟随 logrotate 旋转前提是轮转后新日志文件的属主和权限没变。有些自建的清理脚本用rm删日志再用touch新建新建出来的文件属主是 root 且权限 644Fail2Ban 以非 root 身份读不到于是安静地停止工作。正确做法是用truncate -s 0原地清空或者干脆别手动清理交给 logrotate 管。最后说一句实话Fail2Ban 是个好东西但它解决的是“自动化响应噪音”这个问题不是“你的服务器安不安全”这个问题。真正的分水岭在于你有没有关掉密码登录、有没有收敛暴露端口、有没有人定期看日志。这三件事做到了Fail2Ban 是锦上添花做不到Fail2Ban 只是一个让你安心的心理安慰。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询