如何在 Ubuntu 22.04 上使用 Fail2Ban 保护 SSH

前言

SSH,这玩意儿,简直是连接云服务器的标配。它不仅好用,还很灵活。新的加密技术出来,它也能跟着升级,保证核心协议的安全。但是,再牛的协议和软件,也都有可能被攻破。SSH 在网上用得这么广,就成了黑客们眼中的"肥肉",他们会想方设法来搞事情。

只要你的服务暴露在网络上,就可能被盯上。不信你看看那些高流量服务器的 SSH 日志,是不是经常看到有人在不停地尝试登录?这些家伙,要么是人,要么是机器人,都在用暴力破解的方式撞你的密码。虽然你可以通过一些设置,比如禁用密码登录,改用 SSH 密钥,把被攻破的几率降到最低,但这些尝试还是会给你带来一些麻烦。

对于那些对安全要求极高的生产环境,通常会在 SSH 服务前面加一层 VPN,比如 WireGuard。这样一来,除非有额外的"通行证",否则就没法直接从外网连到默认的 22 端口。VPN 确实很安全,但也会增加复杂性,有时候还会影响一些自动化脚本。

在搞 VPN 之前,或者作为 VPN 的补充,你可以试试 Fail2Ban 这个工具。Fail2Ban 可以自动修改你的防火墙设置,只要有人登录失败次数多了,就直接把他的 IP 给 ban 了。这样一来,你的服务器就能自己保护自己,不用你操心。

这篇教程,就是教你如何在 Ubuntu 22.04 服务器上安装和使用 Fail2Ban。

接下来,我一步一步带你搞定它!

准备工作

服务器准备

你需要:

  • 一颗好奇的心。
  • 一台 Linux 服务器(推荐腾讯云、阿里云或者雨云)。

我这里用 雨云 来给大家演示,教大家怎么创建自己的云服务器,方便学习这篇文章的内容。

注册链接: https://rainyun.ivwv.site

创建雨云服务器

下面的步骤只是个参考,你可以根据自己的需求来选择配置。

  • 打开 云产品云服务器立即购买
  • 选个离你近的区域,这样速度快。
  • 按照你的需求选配置,系统选 Ubuntu 22.04,看你需不需要预装 Docker。
  • 最后,按照提示买就行了。
  • 买完之后,等机器部署好,点开你刚买的服务器,进到管理面板,找到远程连接的信息。
  • 我们用 PowerShell 通过 SSH 远程连接服务器。Win+R 打开运行窗口,输入 powershell,然后点确定。
  • 输入 ssh root@你的服务器IP,比如 ssh root@154.9.227.239。第一次要输入 yes,然后回车,就能登录服务器了。
  • 到这里,你的云服务器就远程连上了。

第1步 - 安装 Fail2Ban

Fail2Ban 在 Ubuntu 的软件仓库里有。先用非 root 用户更新一下软件包列表,然后安装 Fail2Ban:

bash 复制代码
sudo apt update
sudo apt install fail2ban

装好之后,Fail2Ban 会自动启动一个后台服务。不过,默认情况下它是禁用的,因为有些默认设置可能会导致一些不希望出现的问题。你可以用 systemctl 命令来检查一下:

bash 复制代码
systemctl status fail2ban.service

你可以直接启用 Fail2Ban,但最好先了解一下它的功能。

第2步 - 配置 Fail2Ban

Fail2ban 的配置文件都放在 /etc/fail2ban 目录里。默认的配置文件是 jail.conf。我们先去这个目录,用 head -20 看看这个文件的前 20 行:

bash 复制代码
cd /etc/fail2ban
head -20 jail.conf

你会看到,文件的前几行都被注释掉了,就是以 # 开头的那些。这表示它们是说明文档,不是设置。注释里也说了,不要直接改这个文件。你有两个选择:要么在 jail.d/ 目录里为 Fail2Ban 创建单独的配置文件,要么在 jail.local 文件里设置你的本地配置。jail.conf 文件会随着 Fail2Ban 的更新而更新,它相当于一个默认设置的"源",如果你没有做任何覆盖,就会用这里的设置。

这篇教程里,我们用 jail.local。你可以复制 jail.conf 来创建它:

bash 复制代码
sudo cp jail.conf jail.local

现在你可以开始修改配置了。用 nano 或者你喜欢的文本编辑器打开这个文件:

bash 复制代码
sudo nano jail.local

当你浏览这个文件时,我会介绍一些你可能需要修改的选项。文件顶部的 [DEFAULT] 部分的设置会应用到 Fail2Ban 支持的所有服务。在文件的其他地方,比如 [sshd],是针对特定服务的设置,这些设置会覆盖默认设置。

/etc/fail2ban/jail.local

[DEFAULT]
. . .
bantime = 10m
. . .

bantime 参数设置了客户端被 ban 的时间,单位是秒。默认是 10 分钟。

/etc/fail2ban/jail.local

[DEFAULT]
. . .
findtime = 10m
maxretry = 5
. . .

接下来的两个参数是 findtimemaxretry。它们一起决定了什么情况下客户端会被认为是恶意用户,需要被 ban。

maxretry 变量设置了在 findtime 定义的时间窗口内,客户端尝试登录的最大次数。如果超过这个次数,就会被 ban。默认设置下,Fail2ban 会 ban 掉在 10 分钟内尝试登录失败 5 次的客户端。

/etc/fail2ban/jail.local

[DEFAULT]
. . .
destemail = root@localhost
sender = root@<fq-hostname>
mta = sendmail
. . .

如果你想在 Fail2Ban 有动作的时候收到邮件提醒,你需要设置 destemailsendernamemta 这几个参数。destemail 参数设置了接收 ban 消息的邮箱地址。sendername 设置了邮件中"From"字段的值。mta 参数配置了发送邮件的邮件服务。默认是 sendmail,你也可以用 Postfix 或者其他邮件服务。

/etc/fail2ban/jail.local

[DEFAULT]
. . .
action = $(action_)s
. . .

这个参数配置了 Fail2Ban 在需要 ban 的时候采取的动作。值 action_ 在这个参数前面不远的地方定义。默认的动作是更新你的防火墙配置,拒绝来自违规主机的流量,直到 ban 的时间结束。

默认情况下,还有其他 action_ 脚本,你可以用 $(action_) 替换上面的值:

...
# ban & send an e-mail with whois report to the destemail.
action_mw = %(action_)s
            %(mta)s-whois[sender="%(sender)s", dest="%(destemail)s", protocol="%(protocol)s", chain="%(chain)s"]

# ban & send an e-mail with whois report and relevant log lines
# to the destemail.
action_mwl = %(action_)s
             %(mta)s-whois-lines[sender="%(sender)s", dest="%(destemail)s", logpath="%(logpath)s", chain="%(chain)s"]

# See the IMPORTANT note in action.d/xarf-login-attack for when to use this action
#
# ban & send a xarf e-mail to abuse contact of IP address and include relevant log lines
# to the destemail.
action_xarf = %(action_)s
             xarf-login-attack[service=%(__name__)s, sender="%(sender)s", logpath="%(logpath)s", port="%(port)s"]

# ban IP on CloudFlare & send an e-mail with whois report and relevant log lines
# to the destemail.
action_cf_mwl = cloudflare[cfuser="%(cfemail)s", cftoken="%(cfapikey)s"]
                %(mta)s-whois-lines[sender="%(sender)s", dest="%(destemail)s", logpath="%(logpath)s", chain="%(chain)s"]
...

比如,action_mw 会 ban 掉 IP 并发送邮件,action_mwl 会 ban 掉 IP、发送邮件并包含日志记录,而 action_cf_mwl 除了以上所有操作,还会向你的 Cloudflare 账户发送更新,在那里 ban 掉违规者。

单独的监狱设置

接下来是配置文件中处理单独服务的部分。这些部分用 [sshd] 这样的标题来区分。

每个部分都需要通过在标题下添加 enabled = true 来单独启用,以及其他设置。

/etc/fail2ban/jail.local

bash 复制代码
[jail_to_enable]
. . .
enabled = true
. . .

默认情况下,SSH 服务是启用的,其他服务都是禁用的。

这里设置的其他一些设置是 filterlogpathfilter 用来决定日志中的一行是否表示登录失败,logpath 告诉 fail2ban 特定服务的日志在哪里。

filter 的值实际上是对 /etc/fail2ban/filter.d 目录中的文件的引用,只是去掉了 .conf 扩展名。这些文件包含正则表达式,用来判断日志中的一行是不是登录失败的尝试。我们这里就不深入研究这些文件了,因为它们比较复杂,而且预设的设置已经能很好地匹配相应的行了。

不过,你可以看看这个目录,了解一下有哪些可用的过滤器:

bash 复制代码
ls /etc/fail2ban/filter.d

如果你看到一个看起来和你正在使用的服务相关的文件,你应该用文本编辑器打开它。大多数文件都有很好的注释,你至少应该能知道这个脚本是用来防范哪种类型的攻击的。大多数过滤器在 jail.conf 文件中都有相应的(禁用)部分,如果需要,我们可以在 jail.local 文件中启用这些部分。

例如,假设你正在用 Nginx 为网站提供服务,并且发现网站中需要密码才能访问的部分正在被暴力破解。你可以告诉 fail2ban 用 nginx-http-auth.conf 文件来检查 /var/log/nginx/error.log 文件中是否有这种情况。

实际上,这已经在 /etc/fail2ban/jail.conf 文件中名为 [nginx-http-auth] 的部分设置好了。你只需要添加 enabled 参数:

/etc/fail2ban/jail.local

bash 复制代码
. . .
[nginx-http-auth]

enabled = true
. . .

改完之后,保存并关闭文件。现在,你可以启用 Fail2ban 服务,让它自动运行了。首先,运行 systemctl enable

bash 复制代码
sudo systemctl enable fail2ban

然后,用 systemctl start 手动启动它:

bash 复制代码
sudo systemctl start fail2ban

你可以用 systemctl status 验证它是否正在运行:

bash 复制代码
sudo systemctl status fail2ban
bash 复制代码
● fail2ban.service - Fail2Ban Service
     Loaded: loaded (/lib/systemd/system/fail2ban.service; enabled; vendor preset: enab>
     Active: active (running) since Tue 2022-06-28 19:29:15 UTC; 3s ago
       Docs: man:fail2ban(1)
   Main PID: 39396 (fail2ban-server)
      Tasks: 5 (limit: 1119)
     Memory: 12.9M
        CPU: 278ms
     CGroup: /system.slice/fail2ban.service
             └─39396 /usr/bin/python3 /usr/bin/fail2ban-server -xf start

Jun 28 19:29:15 fail2ban20 systemd[1]: Started Fail2Ban Service.
Jun 28 19:29:15 fail2ban20 fail2ban-server[39396]: Server ready

下一步,我们来演示一下 Fail2ban 是怎么工作的。

第 3 步 --- 测试禁止策略(可选)

你可以从另一台服务器(这台服务器以后不需要登录你的 Fail2ban 服务器)来测试规则,通过 ban 掉第二台服务器来测试。登录到第二台服务器后,尝试通过 SSH 访问 Fail2ban 服务器。你可以尝试用一个不存在的用户名来连接:

bash 复制代码
ssh blah@your_server

在密码提示中输入一些随机字符。重复几次。过一会儿,你收到的错误应该从 Permission denied 变成 Connection refused。这表示你的第二台服务器已经被 Fail2ban 服务器 ban 掉了。

在 Fail2ban 服务器上,你可以通过检查 iptables 的输出来查看新规则。iptables 是一个用来和服务器上的底层端口和防火墙规则交互的命令。如果你按照 DigitalOcean 的教程进行初始服务器设置,你会用 ufw 在更高层级管理防火墙规则。运行 iptables -S 会显示 ufw 创建的所有防火墙规则:

bash 复制代码
sudo iptables -S
Output
-P INPUT DROP
-P FORWARD DROP
-P OUTPUT ACCEPT
-N f2b-sshd
-N ufw-after-forward
-N ufw-after-input
-N ufw-after-logging-forward
-N ufw-after-logging-input
-N ufw-after-logging-output
-N ufw-after-output
-N ufw-before-forward
-N ufw-before-input
-N ufw-before-logging-forward
-N ufw-before-logging-input
-N ufw-before-logging-output
...

如果把 iptables -S 的输出通过管道传给 grep,搜索字符串 f2b,你就能看到 failed2ban 添加的规则:

bash 复制代码
sudo iptables -S | grep f2b
Output
-N f2b-sshd
-A INPUT -p tcp -m multiport --dports 22 -j f2b-sshd
-A f2b-sshd -s134.209.165.184/32 -j REJECT --reject-with icmp-port-unreachable
-A f2b-sshd -j RETURN

包含 REJECT --reject-with icmp-port-unreachable 的那一行就是 Fail2ban 添加的,应该会显示你的第二台服务器的 IP 地址。

结论

现在你应该可以为你的服务配置一些 ban 策略了。Fail2ban 是一个保护任何需要身份验证的服务的有效工具。

相关链接

雨云 - 新一代云服务提供商: https://rainyun.ivwv.site

我的博客:https://blog.ivwv.site

相关推荐
安科瑞刘鸿鹏7 分钟前
新能源汽车安全充电管理方案
大数据·运维·服务器·物联网·能源
网际探险者7 分钟前
企业数据文档加密软件产品选择_安全文档加密方案
服务器·网络·安全·web安全·网络安全
记录测试点滴11 分钟前
【自动化】requirements.txt
运维·自动化
CQU_JIAKE33 分钟前
12.4【java exp4][debug]
运维·服务器
苗雨旺42 分钟前
【linux】linux监控硬盘达到使用情况,进行邮箱通知
linux·运维·服务器
zym大哥大1 小时前
Linux进程控制
linux·运维·服务器
vvw&1 小时前
如何在 Rocky Linux 上安装 Docker Swarm 集群
linux·运维·服务器·docker·容器·集群·docker swarm
___波子 Pro Max.2 小时前
FreeBSD vs Linux:哪个开源操作系统更强大
linux·freebsd
凉忆-2 小时前
uniapp打包apk允许横屏竖屏内容翻转
android·服务器·uni-app