一、问题背景:VPN网关的“敲门”困境

不少做技术的朋友都碰到过这种糟心事:自己搭的VPN网关,明明只给几个靠谱的同事或者自己用,可后台日志里总是刷一堆陌生的IP尝试登录,有的甚至一分钟试几十次密码,跟个不知疲倦的“敲门贼”似的。这些暴力破解的请求不仅占着服务器的带宽、CPU资源,要是哪天密码设得不够强,还真可能被撞库撞进去,泄露数据不说,整个服务器都可能被搞成“肉鸡”。

之前很多人的应对办法是手动翻日志找恶意IP,再用防火墙命令把这些IP封掉,但问题是:人不可能24小时盯着日志,等发现的时候,对方可能已经试了几百次密码;而且手动封IP的速度根本赶不上对方换IP的速度,对方换个IP又能继续试,完全是“猫捉老鼠”的被动局面。这时候就需要一套能自动识别恶意请求、自动封IP的方案,而Fail2ban搭配iptables就是解决这个问题的低成本、高效率组合。

二、核心工具拆解:先搞懂两个工具的作用

在动手搭建之前,得先把两个核心工具的作用说清楚,不然配置的时候容易搞混逻辑。

2.1 iptables:服务器的“电子门”

很多人第一次接触iptables的时候,会觉得它是个复杂的防火墙工具,但其实可以把它理解成服务器的“电子门”——所有进出服务器的网络请求,都得经过这扇门的检查。你可以给这扇门定规则:比如允许某个IP的请求进来,拒绝另一个IP的请求,或者把符合某个条件的请求直接挡在门外。

举个简单的例子,如果你想临时封掉一个叫192.168.1.100的恶意IP,不让它访问服务器的任何服务,就可以用iptables的命令来实现。这个命令的逻辑是:给iptables的“输入链”(也就是所有要进入服务器的请求)加一条规则,只要请求的来源IP是192.168.1.100,就直接拒绝。

# 给iptables的输入链(INPUT)添加规则:拒绝来源IP为192.168.1.100的所有请求
iptables -A INPUT -s 192.168.1.100 -j DROP

这里的-A INPUT表示把规则加到输入链的末尾,-s指定来源IP,-j DROP表示直接丢弃这个请求,相当于这个IP的请求根本到不了服务器的任何服务。

不过iptables本身只是个“执行者”,它不会主动去判断哪个IP是恶意的,得有人告诉它该封哪个IP,而这个“判断者”就是Fail2ban。

2.2 Fail2ban:抓“敲门贼”的自动捕手

Fail2ban的作用,就是帮你自动监控服务器的日志文件,从中找出那些频繁尝试登录、符合暴力破解特征的请求,然后自动调用iptables的命令,把对应的恶意IP封掉。它的工作逻辑可以分成三步:

  1. 监控日志:比如你用的是OpenVPN服务,它会专门监控OpenVPN的登录日志,看看有没有重复的登录失败记录;
  2. 判断恶意:比如你可以设定“10分钟内登录失败超过5次”就算恶意请求;
  3. 自动处置:一旦发现恶意IP,就自动调用iptables的命令把它封掉,还能设定封禁时间,比如封1小时,到点自动解封,避免误封正常用户。

简单说,iptables是“门”,Fail2ban是“看门人”——看门人盯着日志找坏人,找到就把坏人关在门外。

三、实战配置:一步步搭建自动防护体系

接下来我们以OpenVPN服务为例,完整搭建一套从监控到自动封禁的体系,所有配置都用实际的例子,跟着做就能跑通。

3.1 准备工作:安装核心工具

首先得确保服务器上装了Fail2ban和iptables,不同的Linux发行版安装命令略有不同,这里以CentOS 7为例(如果是Ubuntu,把yum换成apt就行):

# 安装Fail2ban
yum install -y fail2ban
# 安装iptables(CentOS 7默认可能用firewalld,需要先停掉firewalld再装iptables)
systemctl stop firewalld
systemctl disable firewalld
yum install -y iptables-services
# 启动并设置开机自启
systemctl start iptables
systemctl enable iptables
systemctl start fail2ban
systemctl enable fail2ban

这里要注意:如果服务器之前用的是firewalld,一定要先停掉再装iptables,不然两个防火墙会冲突,导致配置失效。

3.2 配置Fail2ban:定义规则和动作

Fail2ban的配置文件主要在/etc/fail2ban/目录下,其中jail.conf是默认的配置模板,我们不要直接改这个文件,而是在jail.d/目录下新建一个自定义的配置文件,这样升级Fail2ban的时候不会覆盖我们的配置。

首先新建一个针对OpenVPN的配置文件:

# 新建自定义的Fail2ban配置文件
vim /etc/fail2ban/jail.d/openvpn.conf

然后把下面的配置粘贴进去,每一行都加了注释,方便理解:

# 针对OpenVPN服务的防护规则,名称可以自定义,这里叫openvpn
[openvpn]
# 启用这个规则,设为false就是关闭
enabled = true
# 监控的日志文件路径,OpenVPN的登录日志默认在/var/log/openvpn.log,根据自己的实际路径改
logpath = /var/log/openvpn.log
# 匹配日志的规则:这里是找“authentication failed”的行,也就是登录失败的记录
# 注意:如果你的OpenVPN日志里登录失败的关键词不一样,要改这里
filter = openvpn-auth-failed
# 10分钟(600秒)内登录失败的次数超过5次,就算恶意请求
findtime = 600
maxretry = 5
# 封禁时间:这里设为3600秒(1小时),如果想永久封禁,设为-1
bantime = 3600
# 调用iptables来执行封禁动作,这个是默认的动作模板
action = iptables[name=openvpn, port=1194, protocol=udp]

这里的action参数里的port=1194是OpenVPN默认的UDP端口,如果你的OpenVPN用的是TCP端口,要把protocol改成tcp,端口号改成你实际用的。

接下来要定义filter,也就是Fail2ban怎么从日志里找出登录失败的记录。新建一个filter文件:

vim /etc/fail2ban/filter.d/openvpn-auth-failed.conf

粘贴下面的配置:

# 定义匹配OpenVPN登录失败日志的规则
[Definition]
# 匹配日志中包含“authentication failed”的行,后面的.*表示任意字符,也就是只要有这个关键词就算匹配
failregex = authentication failed.*
# 忽略规则:这里可以加正常的登录失败记录,比如你自己测试的时候的失败,不过一般不用
ignoreregex =

这里的failregex是正则表达式,Fail2ban会用这个表达式去匹配日志里的每一行,如果匹配上,就算一次登录失败。如果你的OpenVPN日志里登录失败的关键词是“Auth failed”或者其他,要把failregex里的关键词改成对应的。

配置完之后,重启Fail2ban让配置生效:

systemctl restart fail2ban

3.3 验证效果:测试自动封禁

配置完之后,我们可以自己测试一下,看看Fail2ban是不是真的能自动封IP。比如你可以用另一台电脑,故意用错误的密码连接OpenVPN,连续试5次,然后回到服务器上,用下面的命令查看被封禁的IP:

# 查看Fail2ban的封禁状态
fail2ban-client status openvpn

如果看到类似下面的输出,说明配置成功了:

Status for the jail: openvpn
|- Filter
|  |- Currently failed: 0
|  |- Total failed: 5
|  `- File list:	/var/log/openvpn.log
`- Actions
   |- Currently banned: 1
   |- Total banned: 1
   `- Banned IP list:	192.168.1.100

这里的Banned IP list就是被封的恶意IP,比如192.168.1.100。你还可以用iptables的命令查看具体的规则:

# 查看iptables的所有规则
iptables -L -n

你会看到一条类似的规则:

DROP       udp  --  192.168.1.100         0.0.0.0/0            udp dpt:1194

这条规则就是Fail2ban自动加的,意思是拒绝192.168.1.100这个IP访问服务器的1194端口(OpenVPN的端口)。

如果想手动解封某个IP,可以用下面的命令:

# 手动解封192.168.1.100这个IP
fail2ban-client set openvpn unbanip 192.168.1.100

四、方案的细节分析:优缺点、应用场景和注意事项

4.1 应用场景

这套方案最适合的场景是:

  1. 个人或小团队搭建的OpenVPN(或其他需要登录的服务)网关,比如用来远程访问公司内部网络、或者自己家里的服务器;
  2. 服务器带宽有限,不想被暴力破解请求占用资源的情况;
  3. 没有预算买专业的WAF(Web应用防火墙)的中小团队或个人。

4.2 技术优缺点

优点

  1. 成本低:Fail2ban和iptables都是开源免费的,不需要额外花钱;
  2. 配置简单:跟着步骤走,不需要复杂的技术知识就能搭起来;
  3. 灵活:可以根据自己的需求调整规则,比如把maxretry改成3次、bantime改成永久封禁等;
  4. 效率高:自动监控、自动封禁,不需要人工干预,能快速应对暴力破解。

缺点

  1. 只能针对已知的暴力破解特征:比如如果对方用分布式暴力破解,每个IP只试1次,Fail2ban就识别不出来;
  2. 容易误封:如果你的规则设得太严,比如maxretry=3,正常用户输错3次密码就会被封;
  3. 依赖日志:如果服务的日志没有开启,或者日志路径不对,Fail2ban就监控不到;
  4. 不支持高级防护:比如不能识别SQL注入、XSS攻击等Web攻击,只能针对暴力破解这种有明显特征的攻击。

4.3 注意事项

  1. 日志路径一定要正确:不同的服务日志路径不一样,比如SSH的日志是/var/log/secure,OpenVPN的日志是/var/log/openvpn.log,一定要先确认自己的服务日志路径;
  2. 正则表达式要准确:如果failregex写得不对,Fail2ban就识别不到登录失败的记录,所以一定要先测试日志里的关键词;
  3. 规则要合理:maxretryfindtime的设定要平衡,太松容易被暴力破解,太严容易误封,比如一般设成“10分钟内失败5次”比较合理;
  4. 定期更新Fail2ban:新版本的Fail2ban会修复一些漏洞,所以要定期升级;
  5. 备份配置:在修改配置之前,一定要备份原来的配置文件,不然改坏了可以恢复。

五、方案的延伸:适配其他服务

其实Fail2ban不仅能防护OpenVPN,还能防护很多其他需要登录的服务,比如SSH、FTP、Web服务等,配置逻辑和OpenVPN的差不多,只是改一下logpathfilterfailregex就行。

比如防护SSH服务,只需要在/etc/fail2ban/jail.d/目录下新建一个ssh.conf的配置文件,内容大概是:

[ssh]
enabled = true
# SSH的日志路径,CentOS 7是/var/log/secure,Ubuntu是/var/log/auth.log
logpath = /var/log/secure
filter = sshd-auth-failed
findtime = 600
maxretry = 5
bantime = 3600
action = iptables[name=ssh, port=22, protocol=tcp]

然后新建/etc/fail2ban/filter.d/sshd-auth-failed.conf,内容是:

[Definition]
failregex = sshd.*authentication failed.*
ignoreregex =

重启Fail2ban之后,就能自动防护SSH的暴力破解了。

六、总结

这套用Fail2ban和iptables搭建的自动防护体系,本质上是把人工应对暴力破解的流程自动化:从监控日志到判断恶意请求,再到封禁IP,全程不需要人工干预,不仅能节省时间,还能大幅提高防护效率。对于个人和小团队来说,这是一套低成本、高效率的防护方案,能有效解决VPN网关的暴力破解问题。

不过要注意,这套方案只是第一道防线,不能替代其他安全措施,比如密码要设得足够复杂、定期更新服务版本、开启防火墙的其他规则等,只有多道防线配合,才能让服务器更安全。