When fail2ban Won't Ban IPs: A 5-Minute Diagnostic Guide for Banned: 0
SSH logs are filling up with hundreds of Failed password lines, but fail2ban-client status sshd shows Banned: 0. "I installed it and enabled it—why isn't it blocking?" This is a 5-minute diagnostic manual for exactly that situation. In practice, fail2ban "not blocking" almost always collapses to one of the six causes below. Follow along by copy-pasting the commands as-is.
1. Run these three diagnostic commands first
Before you guess at the cause, find out where the chain broke. Run these three in order.
# ① 전체 jail 목록 — sshd가 보이는가?
sudo fail2ban-client status
# ② sshd jail의 핵심 수치
sudo fail2ban-client status sshd
# ③ 서비스 상태와 에러/Found 로그
sudo systemctl status fail2ban
sudo journalctl -u fail2ban -eIn the status sshd output, the two numbers that matter are Total failed and Banned. Interpret them as follows.
| Symptom | Interpretation | Likely cause |
|---|---|---|
| Total failed is climbing but Banned is 0 | Detection works, but the ban action isn't taking effect | banaction mismatch (④), ignoreip (⑤), thresholds (⑥) |
| Total failed stays at 0 | Stuck at log input or regex matching | logpath/backend (①), failregex (③) |
sshd is missing from status entirely | Jail is not enabled | jail.local not applied (②) |
Hold this branching in your head and the rest is fast. Jump to the matching section below.
2. Cause ①: Can't read the logs (logpath / systemd backend)
Symptom: Total failed stays at 0. journalctl -u fail2ban shows messages like Failed to access socket path or Found no accessible config files for 'logpath'.
This is the #1 most common cause. Especially on Ubuntu 22.04/24.04 and RHEL 9, journald is the default instead of rsyslog, so /var/log/auth.log is empty or missing entirely. If fail2ban is pointed at a file that doesn't exist, of course it reads nothing.
Diagnosis:
# fail2ban이 실제로 어떤 로그를 보는지
sudo fail2ban-client get sshd logpath
# 배포판별 인증 로그 경로 (둘 중 하나)
ls -l /var/log/auth.log # Debian/Ubuntu
ls -l /var/log/secure # RHEL/CentOS/Rocky
# journald에 SSH 로그가 있는지
sudo journalctl -u ssh -n 50 # Ubuntu (서비스명 ssh)
sudo journalctl -u sshd -n 50 # RHEL (서비스명 sshd)Fix: If the file log is empty and logs only exist in journald, switch the backend to systemd.
# /etc/fail2ban/jail.local
[sshd]
enabled = true
backend = systemdTo apply it globally, you can put backend = systemd in the [DEFAULT] block instead. After applying, verify the same way: check whether Total failed is climbing.
3. Cause ②: Jail isn't running (enabled=false / jail.local not applied)
Symptom: sshd is missing from the jail list in fail2ban-client status.
Diagnosis & fix: Never edit jail.conf directly. A package update will overwrite it. Put all custom settings in /etc/fail2ban/jail.local.
# /etc/fail2ban/jail.local
[sshd]
enabled = true# 설정 다시 읽기 (또는 재시작)
sudo fail2ban-client reload
# 안 먹으면
sudo systemctl restart fail2ban
# sshd가 목록에 떴는지 재확인
sudo fail2ban-client statusreload sometimes fails to pick up jail additions/removals. If you just turned enabled on and it still doesn't show up in the list, don't hesitate—just restart.
4. Cause ③: Detection isn't working (failregex mismatch)
Symptom: Logs are being read, but Total failed is 0. Cases have surged recently where OpenSSH 8.x → 9.x changed the log message format and older filters fail to match.
Diagnosis — Count matching lines yourself with fail2ban-regex.
# 파일 로그 백엔드일 때
sudo fail2ban-regex /var/log/auth.log /etc/fail2ban/filter.d/sshd.conf
# systemd 백엔드일 때
sudo fail2ban-regex "journalctl -u ssh -o short-iso" /etc/fail2ban/filter.d/sshd.confIf matched is 0 in the Lines: ... matched at the end of the output, the regex isn't matching.
Fix: Raise the filter mode to aggressive, or upgrade the fail2ban package itself (newer filters support the 9.x format).
# /etc/fail2ban/jail.local
[sshd]
enabled = true
mode = aggressive
backend = systemdsudo apt update && sudo apt install --only-upgrade fail2ban # Debian/Ubuntu
sudo dnf upgrade fail2ban # RHEL 계열5. Cause ④: Matching works, but bans don't (banaction mismatch)
Symptom: Total failed is climbing and Banned is climbing too, but the attacker keeps trying to connect. The firewall backend is mismatched. On systems where nftables is the default, using an iptables-based banaction puts rules in the wrong place and they have no effect.
Fix — Set the banaction that matches your environment in [DEFAULT].
# /etc/fail2ban/jail.local
[DEFAULT]
# firewalld 환경 (RHEL 9 등)
banaction = firewallcmd-rich-rules
# ufw 환경 (Ubuntu)
# banaction = ufw
# 순수 iptables
# banaction = iptables-multiport
# nftables 직접
# banaction = nftables-multiportVerify — Check whether the ban rules actually landed.
sudo iptables -L -n | grep f2b # iptables
sudo nft list ruleset | grep f2b # nftables
sudo firewall-cmd --list-all # firewalldIf the rules don't show up, the banaction is wrong.
6. Causes ⑤ and ⑥: The ignoreip trap and thresholds
Cause ⑤ ignoreip: While adding test IPs or internal ranges, if you put something as broad as 0.0.0.0/0, everything is effectively excluded from bans. Or you add your own public IP and then test from that IP, and mistakenly conclude that "it isn't blocking."
[DEFAULT]
ignoreip = 127.0.0.1/8 ::1 10.0.0.0/8 # 필요한 만큼만, 좁게Cause ⑥ thresholds: findtime = 10m, maxretry = 5 means "ban after 5 failures within 10 minutes." If the attack comes in slowly, it never hits the threshold and never gets banned.
[sshd]
findtime = 10m
maxretry = 5
bantime = 1hFor testing, lower them—e.g. maxretry = 2, bantime = 5m—so you can verify quickly.
Isolating the action — The best trick for separating detection from the ban action is a manual ban.
sudo fail2ban-client set sshd banip 1.2.3.4
sudo iptables -L -n | grep 1.2.3.4 # 또는 nft / firewall-cmdIf a manual banip works but automatic bans don't → it's a detection problem (①②③). If even the manual ban doesn't work → it's a banaction problem (④).
A practitioner's note: Whenever I set up a new server, I always verify the action first with
set sshd banip. Eighty percent of a 5-minute debug is just splitting "detection vs. ban"—and one manual banip line cuts that in half immediately. Two hours of wandering on Ubuntu 24.04 because I forgotbackend = systemdis what built this habit.
7. Complete jail.local example and diagnostic flowchart
Copy-paste this and uncomment the line that matches your environment.
# /etc/fail2ban/jail.local
[DEFAULT]
backend = systemd
ignoreip = 127.0.0.1/8 ::1
findtime = 10m
maxretry = 5
bantime = 1h
# 방화벽 환경에 맞춰 하나만 활성화
banaction = firewallcmd-rich-rules # firewalld
# banaction = ufw # ufw
# banaction = iptables-multiport # 순수 iptables
# banaction = nftables-multiport # nftables
[sshd]
enabled = true
mode = aggressive
backend = systemd
port = ssh6-cause diagnostic flowchart
fail2ban-client status sshd
├─ sshd missing from status? ─────────→ ② jail.local enabled=true + restart
├─ Total failed = 0 ?
│ ├─ get sshd logpath / journalctl empty? → ① backend=systemd
│ └─ fail2ban-regex matched=0 ? → ③ mode=aggressive / upgrade
└─ Total failed↑ but Banned=0 or still not blocked?
├─ set sshd banip 1.2.3.4 also not blocked? → ④ change banaction
├─ your IP / a broad range in ignoreip? → ⑤ clean up ignoreip
└─ threshold not reached? → ⑥ check findtime/maxretryPrevention checklist: ⬜ backend matches the environment (journald or not) ⬜ settings only in jail.local ⬜ banaction matches the firewall backend ⬜ ignoreip kept minimal ⬜ package is up to date ⬜ after changes, verify with fail2ban-regex and a manual banip
Frequently asked questions (FAQ)
Q. Total failed is climbing but Banned is 0.
A. Detection is fine; the ban action is misaligned. Check cause ④ (banaction), cause ⑤ (ignoreip), and the thresholds. Isolating the action with fail2ban-client set sshd banip is the fast path.
Q. I reloaded but the config didn't take effect.
A. reload sometimes doesn't pick up jail additions/removals. Do a full restart with sudo systemctl restart fail2ban and confirm with fail2ban-client status.
Q. It says it's banned, but SSH still connects.
A. Two things. Existing sessions stay up even after the firewall rule is added (only new connections are blocked). And if banaction doesn't match the actual firewall backend (nftables/firewalld/ufw), the rules are inert. Confirm the rules exist with iptables -L -n | grep f2b or equivalent.
Q. auth.log is empty on Ubuntu 22.04/24.04.
A. With journald as the default, /var/log/auth.log is empty or gone. Switch to backend = systemd and confirm logs exist with journalctl -u ssh.
Q. Bans disappear after a reboot.
A. That's close to expected behavior. Bans lift when bantime expires. If you need permanent bans, use bantime = -1 or incremental banning (bantime.increment = true).
Nodelog는 모든 콘텐츠의 내용과 출처를 공개 전에 검토합니다. 환경(OS·버전)에 따라 결과가 달라질 수 있는 기술 정보는 공식 문서와 함께 확인하며, 검토 기준과 정정 원칙은 편집 정책에서 안내합니다. 오류를 발견하시면 이메일로 제보해 주세요 — 확인 후 신속히 정정합니다.
Comments
Be the first to comment.