Ubuntu 下 UFW + Nginx + Fail2ban 封禁IP实操(避坑完整版)

前言:作为运维新手,在部署Ubuntu服务器、搭建Nginx站点后,最头疼的就是恶意IP扫描、暴力破解、爬虫攻击等问题。试过单独用UFW封禁、Nginx拉黑,但手动操作太繁琐,还容易遗漏。经过多次踩坑,终于调试出一套「UFW兜底 + Nginx拦截 + Fail2ban自动封禁」的组合方案,全程实操可复制,新手也能轻松上手,今天就把完整经验分享给大家,避开所有我踩过的坑!

查看Fail2ban封禁Ip记录

一、整体防护逻辑(新手必懂)

这套组合的核心是「三层防护」,层层递进,既高效又省心,不用手动盯着日志封IP:

  1. Nginx 应用层拦截:优先拦截恶意请求,返回403,不占用服务器连接资源;
  2. Fail2ban 自动监控:盯着Nginx日志,识别恶意行为(高频扫描、暴力试错),自动触发封禁;
  3. UFW 系统层兜底:彻底拉黑恶意IP,让其无法连接服务器,防护最彻底。

适用环境:Ubuntu 20.04/22.04(亲测可用)、Nginx 1.18+、Fail2ban 0.11.2(系统默认版本),其他Ubuntu版本可参考,核心步骤一致。

二、前期准备(必做,避免后续报错)

先确认服务器已安装 Nginx、UFW、Fail2ban,若未安装,执行以下命令一键安装:

# 更新软件源
sudo apt update
# 安装 Nginx + UFW + Fail2ban
sudo apt install nginx ufw fail2ban -y

三、 step1:配置UFW基础规则(兜底防护)

UFW是Ubuntu自带的防火墙,先配置基础规则,放行必要端口,拒绝所有不必要的入站请求,避免服务器暴露过多端口。防火墙配置很容易出错,防自己剔出外面。允许的情况下,自己找台机器测试好再上线。

# 重置UFW默认策略(安全基线,新手直接执行)
sudo ufw default deny incoming
sudo ufw default allow outgoing

# 放行必要端口(SSH、HTTP、HTTPS,缺一不可)
sudo ufw allow 22/tcp  # SSH连接,远程管理必备
sudo ufw allow 80/tcp  # HTTP站点
sudo ufw allow 443/tcp # HTTPS站点

# 启用UFW,生效规则
sudo ufw enable

执行后会提示:
Command may disrupt existing ssh connections. Proceed with operation (y|n)?
输入 y 回车即可,不会断开你当前的 SSH。


# 查看UFW状态,确认规则生效
sudo ufw status

正常状态会显示「active」,并列出放行的端口,此时UFW基础防护已生效。

常用小命令

# 查看详细状态
sudo ufw status verbose

# 禁止某个IP
sudo ufw deny from 1.2.3.4

# 删除规则
sudo ufw status numbered
sudo ufw delete 序号

四、 配置Fail2ban自动封禁(核心,不用手动盯日志)

这是最关键的一步!Fail2ban会自动监控Nginx日志,识别恶意行为,达到阈值后自动调用UFW封禁IP,彻底解放双手。重点避坑:不同版本的Fail2ban,自带的过滤器(filter)名称不同,本文适配Fail2ban 0.11.2(Ubuntu默认版本)。

1. 查看系统自带的Nginx过滤器(避免用错名称报错)

先确认自己系统有哪些可用的Nginx过滤器,避免像我之前一样,用了不存在的过滤器导致报错:

ls /etc/fail2ban/filter.d/nginx-*

正常输出(Fail2ban 0.11.2 自带):

/etc/fail2ban/filter.d/nginx-404.conf
/etc/fail2ban/filter.d/nginx-http-auth.conf
/etc/fail2ban/filter.d/nginx-botsearch.conf
/etc/fail2ban/filter.d/nginx-limit-req.conf

这4个过滤器是系统自带的,100%可用,其他名称(如nginx-badbots、nginx-noscript)在该版本中不存在,用了必报错!

2. 配置Fail2ban规则(核心配置)

编辑Fail2ban的规则文件,直接复制以下内容,覆盖原有配置,避免冲突:

sudo nano /etc/fail2ban/jail.d/defaults-debian.conf

全量替换为以下内容(适配Fail2ban 0.11.2,不报错):

# SSH暴力破解防护(默认启用)
[sshd]
enabled = true

# 1. 防Nginx密码暴力破解(监控错误日志)
[nginx-http-auth]
enabled = true
filter = nginx-http-auth
logpath = /var/log/nginx/error.log
bantime = 3600        # 封禁1小时

# 2. 防Nginx恶意扫描、爬虫、爆404(监控访问日志)
[nginx-botsearch]
enabled = true
filter = nginx-botsearch
logpath = /var/log/nginx/access.log
bantime = 3600       # 封禁24小时

# 3. 防Nginx高并发请求(CC攻击,监控错误日志)
[nginx-limit-req]
enabled = true
filter = nginx-limit-req
logpath = /var/log/nginx/error.log
bantime = 3600        # 封禁1小时

为了确保配置文件格式有没有错,可以执行命令测试一下。

sudo fail2ban-client -t

# 没问题再启动
sudo systemctl start fail2ban
sudo systemctl status fail2ban

六、Fail2ban识别的黑名单,同步给Nginx拉黑(自动实现)

核心逻辑:通过Fail2ban的「action动作」,将识别到的恶意IP自动写入Nginx黑名单文件,无需手动复制,实现“Fail2ban识别→Nginx拦截”的全自动联动,比单纯UFW封禁更灵活(可针对单个站点拦截)。

实现步骤(基于本文现有配置,直接添加配置即可):

1、创建 nginx-block action

sudo tee /etc/fail2ban/action.d/nginx-block.conf << 'EOF'
[Definition]
actionstart = 
actionstop = 
actioncheck = 
actionban = echo "deny <ip>;" >> /etc/nginx/blockips.conf
              /usr/bin/systemctl reload nginx
actionunban = sed -i '/^deny <ip>;/d' /etc/nginx/blockips.conf
              /usr/bin/systemctl reload nginx
EOF

2、 确保 nginx 黑名单文件存在

sudo touch /etc/nginx/blockips.conf    #保存位置个人看着改

3、在 http {} 最顶部加入以下内容,让黑名单全局生效:

http {
    # 引入IP黑名单
    include /etc/nginx/blockips.conf;
    
    # 其他Nginx配置(保留原有内容,不要删除)
    ...
}

4、 编辑Fail2ban规则文件(继续使用当前配置文件)

sudo vim /etc/fail2ban/jail.d/defaults-debian.conf

在文件最顶部([sshd]上方),添加以下「全局action配置」,指定联动Nginx的动作,ubuntu系统使用ufw:

[DEFAULT]
banaction = ufw
action = %(action_mw)s
         nginx-block

bantime = 3600
findtime = 600
maxretry = 5
  • banaction = ufw 会让 fail2ban 通过 ufw deny from <ip> 来封禁
  • 确认 fail2ban 的 ufw action 存在
ls /etc/fail2ban/action.d/ufw*
#正常是有文件存在的

七、UFW封禁IP的详细原理+实现细节

UFW(Ubuntu防火墙)是系统层防火墙,Fail2ban调用UFW封禁IP的本质,是自动给UFW添加“拒绝该IP所有入站请求”的规则,从根源上阻止恶意IP连接服务器,比Nginx拦截更彻底(Nginx拦截是应用层,UFW拦截是系统层,恶意IP连服务器端口都无法访问)。

1. UFW封禁IP的核心原理

UFW基于iptables(Linux底层防火墙)封装,简化了iptables的复杂配置,Fail2ban通过调用UFW的命令,给iptables添加“DROP(拒绝)”规则,当恶意IP发起请求时,服务器会直接拒绝响应,不建立任何连接,相当于“直接拉黑该IP的所有访问权限”。

简单来说:Fail2ban是“监控者”,识别恶意IP;UFW是“执行者”,彻底阻断恶意IP的连接,二者通过系统命令联动,无需手动操作,这也是我们这套防护方案的核心优势之一。

2. UFW封禁IP的实操细节(Fail2ban自动执行,也可手动操作)

本文配置中,Fail2ban默认调用UFW封禁IP,无需额外配置,以下是详细细节(帮你理解“UFW到底在做什么”):

# (1)Fail2ban自动封禁IP时,后台执行的UFW命令(无需手动输入)
sudo ufw insert 1 deny from 恶意IP to any
# 说明:insert 1 表示将该规则插入到UFW规则的第1位,优先执行;deny from 恶意IP to any 表示拒绝该IP的所有入站请求

# (2)查看UFW中Fail2ban添加的封禁规则(验证是否封禁成功)
sudo ufw status numbered
# 输出中会显示类似内容:
#  1    DENY IN    1.2.3.4(恶意IP)

# (3)手动通过UFW封禁IP(应急使用,如发现恶意IP未被自动封禁)
sudo ufw deny from 1.2.3.4 to any
# 手动封禁后,该IP无法访问服务器的任何端口(22、80、443等)

# (4)手动通过UFW解封IP(误封时使用)
sudo ufw delete deny from 1.2.3.4 to any
# 也可结合Fail2ban的解封命令,双重解封(更稳妥):
sudo fail2ban-client unban 1.2.3.4
sudo ufw delete deny from 1.2.3.4 to any

3. 关键注意点(避免UFW封禁失效)

  • 必须确保UFW处于启用状态(sudo ufw enable),否则Fail2ban调用UFW封禁会失败;
  • UFW的封禁规则是临时的,服务器重启后会失效,但本文中我们设置了Fail2ban开机自启(sudo systemctl enable fail2ban),重启后Fail2ban会重新加载规则,自动重新封禁未到期的IP;

八、联动逻辑总结(一句话看懂)

1. 恶意IP发起攻击(扫描、暴力破解等)→ 2. Nginx日志记录该行为 → 3. Fail2ban监控日志,识别恶意IP(达到maxretry阈值)→ 4. Fail2ban自动执行两个动作:① 调用UFW封禁IP(系统层,彻底阻断连接);② 写入Nginx黑名单(应用层,快速拦截请求)→ 5. 封禁时间到期后,Fail2ban自动解封,同时删除Nginx和UFW中的对应规则,全程自动化,无需手动干预。

这样的联动的方式,既兼顾了Nginx的灵活拦截(可针对站点),又兼顾了UFW的彻底防护(系统层兜底),完美解决“单一防护不彻底”的问题,也是生产环境中最常用的防护组合方式之一。

保存退出。

2. 重启Fail2ban,生效规则

# 重启Fail2ban,加载新配置
sudo systemctl restart fail2ban

# 设置开机自启,避免服务器重启后失效
sudo systemctl enable fail2ban

# 查看Fail2ban状态,确认无报错
sudo fail2ban-client status

正常状态会列出所有启用的规则(sshd、nginx-http-auth等),无任何报错。

九、 常用操作命令(收藏备用,新手必备)

配置完成后,日常管理只需要记住以下几条命令,轻松查看、封禁、解封IP:

# 1. 查看所有被封禁的IP(最常用)
sudo fail2ban-client banned

# 2. 查看某个规则的详细状态(如nginx-botsearch)
sudo fail2ban-client status nginx-botsearch

# 3. 手动封禁某个IP(应急用,如1.2.3.4)
sudo fail2ban-client set nginx-botsearch banip 1.2.3.4

# 4. 手动解封某个IP(误封时用)
sudo fail2ban-client unban 1.2.3.4

# 5. 实时查看Fail2ban日志(看谁在被攻击、被封禁)
sudo tail -f /var/log/fail2ban.log

# 6. 查看Nginx访问日志,找出恶意IP(高频访问)
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -nr | head -20

十、 常见报错及解决方法(避坑重点)

分享我踩过的3个高频报错,新手遇到直接对照解决,不用浪费时间排查:

1. 报错:Permission denied to socket(必须用sudo)

错误命令:fail2ban-client status nginx-botsearch

解决:所有fail2ban命令必须加sudo(管理员权限),正确命令:

sudo fail2ban-client status nginx-botsearch

2. 报错:Sorry but the jail ‘xxx’ does not exist(规则不存在)

原因:用了系统没有的过滤器名称(如nginx-badbots、nginx-noscript),或配置文件未加载。

解决:只用系统自带的过滤器(nginx-http-auth、nginx-botsearch、nginx-limit-req),修改配置后重启Fail2ban。

3. 配置后Fail2ban不生效(无封禁记录)

原因:日志路径错误,或maxretry(触发阈值)设置过高。

解决:确认logpath是/var/log/nginx/access.log(访问日志)或error.log(错误日志),适当降低maxretry(如10-20次)。

十一、 总结

这套「UFW + Nginx + Fail2ban」的组合方案,是Ubuntu服务器防护的最优解之一,新手也能轻松部署:

  • 无需手动盯日志,Fail2ban自动识别、自动封禁;
  • 三层防护,从应用层到系统层,防护彻底;
  • 适配Ubuntu默认版本,无报错,可直接复制执行。

配置完成后,服务器就能自动抵御恶意扫描、暴力破解、爬虫攻击,再也不用手动封禁IP。如果你的服务器版本不同,或遇到其他报错,欢迎在评论区留言,一起交流解决~

本文首发于 58Linux技术博客,专注Ubuntu桌面使用、Linux服务器运维与网站搭建实战。
       本系列的一部分

Linux服务器

Post 24 of 24

发表评论

粤ICP备10052831号 | © 2026 58Linux 技术笔记. All Rights Reserved. | 联系我们 | 关于本站
本站内容开放共享,仅供学习交流 | 专注 Ubuntu & Linux 实战教程
Built with GeneratePress