Fail2Ban 是一个强大且灵活的工具,可以有效地保护服务器免受暴力破解等攻击。通过监控日志文件、设置规则和自动管理防火墙,Fail2Ban 为系统提供了一层额外的安全防护。
Nginx Proxy Manager(NPM)作为反向代理的 docker 容器可以通过网页界面简单地管理 SSL 证书和代理主机。所有它还是很受欢迎的。它还提供了一个名为 block common exploits
的简单功能,可阻止比较常见的攻击手段和漏洞。
本文主要已Ubuntu环境下的WordPress程序为例,WordPress 程序在访问 不存在(404)的页面时候,会导致服务器的CPU、内存等资源占用大增,通过Fail2ban与Cloudflare实现拦截404页面的功能。
Fail2Ban 的工作原理
- 日志监控:Fail2Ban 会不断监控指定的日志文件(如
/var/log/auth.log
或/var/log/apache2/error.log
),来检测是否有匹配特定攻击模式的记录。 - 触发规则:如果检测到某IP地址违反了预设的规则(如在一段时间内多次登录失败),Fail2Ban 就会执行特定的动作。
- 动作执行:默认情况下,Fail2Ban 会通过配置的防火墙(如
iptables
)阻止恶意IP地址。也可以自定义其他动作,如发送通知、修改特定服务的配置等。 - 解禁:Fail2Ban 也支持设置自动解禁时间,禁止的IP可以在一段时间后自动解除限制。
Fail2Ban 安装与配置
1.安装Fail2Ban
在大多数Linux发行版中,可以直接通过包管理工具来安装Fail2Ban。以下是一些常见的安装命令:
-
Debian/Ubuntu:
sudo apt update sudo apt install fail2ban
-
CentOS/RHEL:
sudo yum install epel-release sudo yum install fail2ban
2.Fail2Ban的基本配置
Fail2Ban 的主配置文件位于 /etc/fail2ban/jail.conf
,但是为了防止在升级时被覆盖,建议将其复制为 /etc/fail2ban/jail.local
,然后在 jail.local
文件中进行自定义配置。
可以参考以下步骤:
-
复制配置文件:
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
-
修改
/etc/fail2ban/jail.local
,自定义规则:- bantime: 设置禁止时间,单位是秒。默认是600秒(10分钟)。
- findtime: 指定在多长时间内累积触发失败尝试才会触发禁用。
- maxretry: 指定允许的最大失败尝试次数。
- ignoreip: 设置永不被禁止的IP列表(如你自己的服务器IP)。
示例配置:
[DEFAULT]
bantime = 3600 # 禁止时间设置为1小时
findtime = 600 # 检查过去10分钟内的失败尝试
maxretry = 5 # 允许最多5次失败尝试
ignoreip = 127.0.0.1 # 忽略本地回环地址
[sshd]
enabled = true # 启用对SSH的监控
port = ssh # 监控的端口,默认为22
logpath = /var/log/auth.log
maxretry = 3 # SSH登录最多允许3次失败尝试
3.启用Fail2Ban并启动服务
完成配置后,启用并启动Fail2Ban服务:
-
启动服务:
sudo systemctl start fail2ban
-
设置开机自启动:
sudo systemctl enable fail2ban
-
查看Fail2Ban的状态:
sudo fail2ban-client status
4.查看和管理被禁止的IP
可以使用Fail2Ban提供的命令行工具 fail2ban-client
来管理和查看状态。
-
查看某个监控规则(如SSH)的状态:
sudo fail2ban-client status sshd
-
查看所有被禁止的IP:
sudo fail2ban-client status
-
手动禁止一个IP:
sudo fail2ban-client set sshd banip 192.168.1.100
-
手动解除对某个IP的禁令:
sudo fail2ban-client set sshd unbanip 192.168.1.100
典型使用场景
- SSH防护:Fail2Ban最常用于保护SSH服务器,防止暴力破解攻击。
- Web服务器防护:通过监控Nginx、Apache等Web服务器的日志,检测和阻止对登录页面、管理页面的攻击。
- 邮件服务器防护:Fail2Ban也能用来防御针对邮件服务器(如 Postfix、Dovecot)的暴力破解。
Fail2Ban的自定义规则
如果默认的规则不够用,Fail2Ban允许自定义规则。你可以通过 filter.d
文件夹下的规则文件来定义新的日志匹配规则。例如,针对Apache的自定义规则可能如下:
-
创建一个新的过滤文件,例如
/etc/fail2ban/filter.d/apache-auth.conf
:[Definition] failregex = ^<HOST> - - \[.*\] "POST /wp-login.php HTTP/.*" 401
-
在
jail.local
文件中,添加对应的jail
规则:[apache-auth] enabled = true filter = apache-auth action = iptables-multiport[name=apache-auth, port="http,https"] logpath = /var/log/apache*/*access.log bantime = 3600 maxretry = 3
这段配置会监控Apache的访问日志,当某个IP尝试在 wp-login.php
页面多次失败登录时,将被暂时禁止。
关联Fail2ban、Npm与Cloudflare
上文中已介绍了在主机安装Fail2ban以及基础的配置方法,当然Fail2ban也有Docker版本,可以自行查询Docker 的应用,本文不做介绍,使用方法基本一致。现在开始做 fail2ban、Nginx Proxy Manager、Cloudflare 的配置。
前提条件
由于使用cloudflare 的cdn 功能,后端不能获取正确的ip地址,Cloudflare通常通过CF-Connecting-IP或X-Forwarded-For头传递真实的客户端IP。所有需要通过设置
real_ip_header CF-Connecting-IP;
来获取真实的客户端ip。添加这一主机头才能让NPM在网站访问日志中包含真实IP。 编辑 Nginx Proxy Manager 的代理主机,选择 Advanced
在Custom Nginx Configuration
中添加以下配置:
# Cloudflare IPv4 addresses
set_real_ip_from 103.21.244.0/22;
set_real_ip_from 103.22.200.0/22;
set_real_ip_from 103.31.4.0/22;
set_real_ip_from 104.16.0.0/13;
set_real_ip_from 104.24.0.0/14;
set_real_ip_from 108.162.192.0/18;
set_real_ip_from 131.0.72.0/22;
set_real_ip_from 141.101.64.0/18;
set_real_ip_from 162.158.0.0/15;
set_real_ip_from 172.64.0.0/13;
set_real_ip_from 173.245.48.0/20;
set_real_ip_from 188.114.96.0/20;
set_real_ip_from 190.93.240.0/20;
set_real_ip_from 197.234.240.0/22;
set_real_ip_from 198.41.128.0/17;
# Cloudflare IPv6 addresses
set_real_ip_from 2400:cb00::/32;
set_real_ip_from 2606:4700::/32;
set_real_ip_from 2803:f800::/32;
set_real_ip_from 2405:b500::/32;
set_real_ip_from 2405:8100::/32;
set_real_ip_from 2a06:98c0::/29;
set_real_ip_from 2c0f:f248::/32;
real_ip_header CF-Connecting-IP;
当然Cloudflare的cdn 地址会经常性更新,可以通过官网给的地址自行更新,或者自行写个shell 脚本自动更新。官网cdn 网段发布页:[https://www.cloudflare.com/zh-cn/ips/]() 。
还是一种写法就是直接允许任意网段访问,但这种写法就好导致安全性降低。
# Cloudflare IPv4 and IPv6 addresses
set_real_ip_from 0.0.0.0/0;
set_real_ip_from ::/0;
real_ip_header CF-Connecting-IP;
配置Fail2ban
配置jail
在 /etc/fail2ban/jail.local
中新增以下内容:
[npm-4xx]
enabled = true # 启用此 jail
filter = npm-4xx # 使用的过滤器名称
port = http,https # 监控的端口(HTTP 和 HTTPS)
action = cloudflare-4xx # 当检测到恶意行为时采取的动作
logpath = /opt/npm/data/logs/proxy-host-3_access.log # Nginx 访问日志的路径
maxretry = 3 # 在 findtime 时间段内允许的最大失败次数
bantime = 900 # 被禁止的持续时间(以秒为单位,15分钟)
findtime = 3600 # 检查失败尝试的时间段(以秒为单位,1小时)
ignoreip = 172.17.0.1/24 192.168.0.1/24 # 忽略的 IP 地址或子网,这些 IP 不会被禁止
关键配置项
- enabled: 设置为
true
表示启用该 jail。 - filter: 指定使用的过滤器名称,
nginx-4xx
过滤器需要在/etc/fail2ban/filter.d/
目录中定义。 - port: 指定要监控的端口,通常是 HTTP 和 HTTPS。
- action: 指定在检测到恶意行为后采取的动作,
cloudflare-4xx
应该是一个自定义的动作,通常用于通过 Cloudflare API 禁止 IP。 - logpath: 指定要监控的 Nginx 访问日志的路径,确保该路径正确且 Nginx 正在记录日志。
- maxretry: 在
findtime
时间段内允许的最大失败次数,超过这个次数后,IP 将被禁止。 - bantime: 被禁止的持续时间(以秒为单位),在这个配置中是 900 秒(15 分钟)。
- findtime: 检查失败尝试的时间段(以秒为单位),在这个配置中是 3600 秒(1 小时)。
- ignoreip: 指定要忽略的 IP 地址或子网,这些 IP 不会被禁止。
logpath
这一项为Npm日志路径,如果你要监控所有站点的话需要把 proxy-host-3_access.log
改为 proxy-host-*_access.log
改为*
号即可。
配置过滤器
在/etc/fail2ban/filter.d
目录下新增一个名为 npm-4xx.conf
的配置文件,内容为拦截规则,支持正则表达式。
通用拦截规则:
[Definition]
failregex = ^.* "(GET|POST|HEAD).*HTTP.*" ([45]\d\d) .*
ignoreregex =.*(robots.txt|favicon.ico|jpg|png)
Npm 使用规则:
配置cloudflare
在/etc/fail2ban/action.d
中新建一个名为cloudflare-4xx.conf
文件,(默认在此目录下也有一个cloudflare 的配置文件,以下配置改自此文件)内容如下:
[Definition]
actionstart =
actionstop =
actioncheck =
actionban = curl -s -o /dev/null -X POST <_cf_api_prms> \
-d '{"mode":"<mode>","configuration":{"target":"<cftarget>","value":"<ip>"},"notes":"Fail2Ban <name>"}' \
<_cf_api_url>
actionunban = id=$(curl -s -X GET <_cf_api_prms> \
"<_cf_api_url>?mode=<mode>&configuration_target=<cftarget>&configuration_value=<ip>&page=1&per_page=1¬es=Fail2Ban%%20<name>" \
| { jq -r '.result[0].id' 2>/dev/null || tr -d '\n' | sed -nE 's/^.*"result"\s*:\s*\[\s*\{\s*"id"\s*:\s*"([^"]+)".*$/\1/p'; })
if [ -z "$id" ]; then echo "<name>: id for <ip> cannot be found"; exit 0; fi;
curl -s -o /dev/null -X DELETE <_cf_api_prms> "<_cf_api_url>/$id"
_cf_api_url = https://api.cloudflare.com/client/v4/user/firewall/access_rules/rules
_cf_api_prms = -H 'X-Auth-Email: <cfuser>' -H 'X-Auth-Key: <cftoken>' -H 'Content-Type: application/json'
[Init]
cftoken = APIKEY00000ABC
cfuser = [email protected]
mode = block
cftarget = ip
[Init?family=inet6]
cftarget = ip6
以上配置中需要修改的的部分为 cftoken
、cfuser
和 mode
。
- cftoken 需要到cf后台右上角我的个人资料,选择左侧API令牌,获取Global API Key。https://dash.cloudflare.com/login
- cfuser 为你绑定Cloudflare 的邮箱账户。
- mode 为防火墙的动作,默认为
block
。支持四种模式,分别是"challenge"
(质询)、"block"
(阻止)、"whitelist"
(白名单)、"js_challenge"
(Javascript 质询)。
配置好cloudflare-4xx文件后,可以自行测试,然后在cf后台,站点-安全性-事件中查看拦截记录。
Block响应效果
参考链接
本文作者为Mr.Bai,转载请注明。