任何时候你都可以开始做自己想做的事

搜索|
linux下 使用 fail2ban 监控nginx日志对异常访问IP进行封禁
发布时间:2026-04-07 22:50:33
Fail2ban 是一款强大的入侵防御软件,它通过监控系统日志,自动识别并封禁存在恶意行为(如暴力破解、高频扫描)的 IP 地址,是保护服务器安全的重要工具。

️ 核心概念与目录结构

Fail2ban 的工作原理是“监控-匹配-执行”:实时监控指定日志文件,使用正则表达式匹配失败或异常行为,一旦达到预设阈值,则调用防火墙(如 iptables)执行封禁动作。
  • /etc/fail2ban/: 主配置目录。

  • jail.conf: 默认配置文件,不建议直接修改,以免系统更新时被覆盖。

  • jail.local自定义配置文件,用于存放自定义的所有规则。安装jfail2ban后,手工复制jail.conf改名或者新建,Fail2ban 会优先读取此文件,它会覆盖 jail.conf 中的同名设置。

  • filter.d/: 过滤器规则目录,存放 .conf 文件,内部使用正则表达式定义如何从日志中识别恶意行为。

  • action.d/: 动作规则目录,定义触发封禁后执行的操作,默认通常是调用防火墙。


jail.local配置方式说明:


# =================================================================

# [DEFAULT] 全局默认配置

# =================================================================

# 此区块下的配置为全局默认值,会被下方具体的 [jail] 规则覆盖。

[DEFAULT]


# 白名单:永远不要封禁的 IP 地址。务必包含本机和管理员 IP。

ignoreip = 127.0.0.1/8


# 默认封禁时长:1 小时 (3600秒)。

# 这是一个平衡安全与便利的推荐值。

bantime = 3600


# 检测窗口:10 分钟 (600秒)。

# 在 10 分钟内统计失败次数。

findtime = 600


# 最大重试次数:5 次。

# 在 findtime 时间内,失败超过 5 次即触发封禁。

maxretry = 5


# 数据库清理周期:24 小时 (86400秒)。

# 【关键优化】此值必须 >= 所有 jail 规则中最大的 bantime。

# 它的作用是清理数据库中过期的封禁记录,防止内存和磁盘空间无限增长。

# 如果不设置,默认值就是 86400,通常无需修改。

# dbpurgeage = 86400



# =================================================================

# [sshd] SSH 服务防护

# =================================================================

# SSH 是服务器最重要的入口,防护策略应更严格。


[sshd]

enabled = true

port    = ssh

# CentOS 的安全日志路径是 /var/log/secure

logpath = /var/log/secure

maxretry = 3


# =================================================================

# [nginx-http-auth] Nginx HTTP 认证防护

# =================================================================

# 防护 Nginx 中启用了密码认证的目录(如 /admin)。

# fail2ban默认nginx防御规则

[nginx-http-auth]

enabled = true

port    = http,https

# 监控的日志路径

logpath = /usr/local/nginx/logs/error.log

# maxretry 未设置,继承全局的 5 次。



# =================================================================

# [nginx-botsearch] Nginx 恶意爬虫/扫描防护

# =================================================================

# 防护常见的恶意爬虫,它们会扫描敏感文件路径。

# fail2ban默认nginx防御规则

[nginx-botsearch]

enabled = true

port    = http,https

# 监控的日志路径

logpath = /usr/local/nginx/logs/access.log

# 策略更严格,2 次就封禁。

maxretry = 2



# =================================================================

# 自定义规则/扫描防护、爆破检测1

# =================================================================

# 监控nginx访问日志 (防 404 扫描) ---

[nginx-404-bomb]

enabled = true

port    = http,https

# 监控的日志路径

filter  = nginx-404-bomb

logpath = /usr/local/nginx/logs/access.log

maxretry = 5

findtime = 60

bantime   = 36000


--------------------------------------------------------------------------------------------------------------------------------------

对应的nginx-404-bomb规则(此规则文件放置在etc/fail2ban/filter.d/nginx-404-bomb.conf,规则名字对应文件名)

--------------------------------------------------------------------------------------------------------------------------------------


[Definition]

# 这个正则表达式解释:

# ^<HOST>  : 匹配行首的 IP 地址

# .*       : 忽略中间的内容

# "        : 找到请求开始的双引号

# (GET|POST|HEAD) : 匹配请求方法

# .*"      : 忽略请求路径,直到双引号结束

# 404      : 关键!匹配状态码 404

# .*       : 忽略后面的内容

failregex = ^<HOST> .*? "(GET|POST|HEAD) .*" 404

# failregex = ^<HOST> .*? "(GET|POST|HEAD) .*


# 我们不忽略任何内容,宁可错杀不可放过

ignoreregex =

--------------------------------------------------------------------------------------------------------------------------------------





# =================================================================

# 自定义规则/扫描防护、爆破检测2

# =================================================================


# 监控nginx访问日志(防爆破)

[attack]

enabled = true

监控nginx访问日志

filter = attack

logpath = /usr/local/nginx/logs/access.log

port = http,https

# 关键:只要命中上面任意一条规则,立刻封!

maxretry = 1      

findtime = 600

bantime = 86400


--------------------------------------------------------------------------------------------------------------------------------------

对应的attack规则(此规则文件放置在etc/fail2ban/filter.d/acctack.conf,规则名字对应文件名)

--------------------------------------------------------------------------------------------------------------------------------------

[Definition]


# 这里可以留一个总的描述,或者把注释放在文件最上面

# 1. 拦截恶意后缀(仅限 404 状态)

# 2. 拦截敏感路径(仅限 404 状态) 

# 3. 拦截对根目录 "/" 的 POST 请求

# 4. 拦截 User-Agent 为空的请求


failregex = ^<HOST> .*? "(GET|POST) .*?\.(php|asp|aspx|exe|bak|zip|rar|sql|jsp|cgi|inc|phtml|dll|cer|asa|shtml).*" 404 | ^

              ^<HOST> .*? "(GET|POST) /(.*?)(gponform|phpmyadmin|xmlrpc|wp-login|wp-admin|backup|shell|bash|mysql|dump|install|test|vendor).*" 404 | ^

              ^<HOST> .*? "POST / HTTP/1\.[01]" 403 | ^

              ^<HOST> .*? ".*" "-"$ 403 | ^

  ^<HOST> - .* "\\x[0-9A-F]{2}.*" 400


--------------------------------------------------------------------------------------------------------------------------------------




# =================================================================

# 常用的fail2ban 命令

# =================================================================


# fail2ban 关闭 启动 重新加载配置 

systemctl start fail2ban

systemctl stop fail2ban

systemctl reload fail2ban

systemctl status  fail2ban


# 查看各个规则的情况

fail2ban-client status (如后面这里加规则名,就会只查看该规则的,不加,会查看所有规则的状态)

--------------------------------------------------------------------------------------------------------------------------------------

[root@www ~]# fail2ban-client status nginx-404-bomb

Status for the jail: nginx-404-bomb

|- Filter

|  |- Currently failed: 3

|  |- Total failed:     23

|  `- File list:        /usr/local/nginx/logs/access.log

`- Actions

   |- Currently banned: 3

   |- Total banned:     3

   `- Banned IP list:   123.123.123.... (此规则封禁的IP)

   

--------------------------------------------------------------------------------------------------------------------------------------





# 解封指定IP

fail2ban-client set <jail名称> unbanip <IP地址>

# 解封所有ip

fail2ban-client unban --all


# 查看fail2ban 系统资占用

ps aux | grep python | grep fail2ban



# 查看各个规则封禁的IP 使用sudo

for jail in $(sudo fail2ban-client status | grep "Jail list:" | sed "s/ //g" | cut -d ":" -f2 | tr "," " "); do echo "=== 监狱: $jail ==="; sudo fail2ban-client status $jail | grep "Banned IP list:"; done


# 查看各个规则封禁的IP 无sudo

for jail in $(fail2ban-client status | grep "Jail list:" | sed "s/ //g" | cut -d ":" -f2 | tr "," " "); do echo "=== 监狱: $jail ==="; fail2ban-client status $jail | grep "Banned IP list:"; done