准备工作

1、检查Firewalld是否启用

#如果您已经安装iptables建议先关闭
service iptables stop

#查看Firewalld状态
firewall-cmd --state

#启动firewalld
systemctl start firewalld

#设置开机启动
systemctl enable firewalld.service

启用Firewalld后会禁止所有端口连接,因此请务必放行常用的端口,以免被阻挡在外,以下是放行SSH端口(22)示例,供参考:

#放行22端口
firewall-cmd --zone=public --add-port=80/tcp --permanent
#重载配置
firewall-cmd --reload
#查看已放行端口
firewall-cmd --zone=public --list-ports

2、安装fail2ban

fail2ban可以监控系统日志,并且根据一定规则匹配异常IP后使用Firewalld将其屏蔽,尤其是针对一些爆破/扫描等非常有效。

#CentOS内置源并未包含fail2ban,需要先安装epel源
yum -y install epel-release

# 安装fial2ban
yum -y install fail2ban

# 如果需要支持电子邮件的话,需要安装Sendmail服务(Sendmail不需要使用Fail2Ban工具)
$ sudo yum install -y sendmail

# 启动并启用Fail2ban和Sendmail
$ sudo systemctl start fail2ban
$ sudo systemctl enable fail2ban
$ sudo systemctl start sendmail
$ sudo systemctl enable sendmail

# 如果遇到提示“没有目录/var/run/fail2ban”或者套接字文件
# “/var/run/fail2ban/fail2ban.sock”的错误,手动创建即可
$ sudo mkdir /var/run/fail2ban

3、配置

修改配置文件

安装成功后fail2ban配置文件位于/etc/fail2ban,其中jail.conf为主配置文件,它包含一组预定义的过滤器,所以尽量不要编辑该文件,除非你知道自己在干什么。而且只要有新的更新,该配置配置就会重置为默认值。而我们要做的就是,在同一目录下创建一个名为 jail.local 的新配置文件,并根据自己的意愿进行修改,即可。相关的匹配规则位于filter.d目录,其它 目录/文件 一般很少用到,如果需要详细了解可自行搜索。

虽然会优先读取jail.conf文件,但是jail.local文件会覆盖前者的配置

$ sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local

配置规则新建jail.local来覆盖fail2ban的一些默认规则:
默认 .local 会覆盖 .conf 的配置文件

#新建配置
vi /etc/fail2ban/jail.local
#默认配置
[DEFAULT]
ignoreip = 127.0.0.1/8
bantime  = 86400
findtime = 600
maxretry = 5
#这里banaction必须用firewallcmd-ipset,这是fiewalll支持的关键,如果是用Iptables请不要这样填写
banaction = firewallcmd-ipset
action = %(action_mwl)s

参数说明:
ignoreip:IP白名单,白名单中的IP不会屏蔽,可填写多个以(,)分隔
bantime:屏蔽时间,单位为秒(s)
findtime:时间范围
maxretry:最大次数
banaction:屏蔽IP所使用的方法,上面使用firewalld屏蔽端口

fail2ban.conf配置文件

shell > grep -v ^# /etc/fail2ban/fail2ban.conf

[Definition]
loglevel = 3                              ## 定义日志级别,默认
logtarget = /var/log/fail2ban.log         ## 定义 fail2ban 日志文件
socket = /var/run/fail2ban/fail2ban.sock  ## sock 文件存放位置,默认
pidfile = /var/run/fail2ban/fail2ban.pid  ## pid 文件存放位置,默认

jail.conf 防护配置

shell > grep -v ^# /etc/fail2ban/jail.conf

[DEFAULT]                         ## 全局设置,优先级最小
ignoreip = 127.0.0.1/8            ## 不受限制的 IP ,多组用空格分割
bantime = 600                     ## 非法 IP 被屏蔽时间(秒),-1 代表永远封锁
findtime = 600                    ## 设置多长时间(秒)内超过 maxretry 限制次数即被封锁
maxretry = 3                      ## 最大尝试次数
backend = auto                    ## 日志修改检测机制(gamin 、polling 、auto 三种)
usedns = warn
[ssh-iptables]                    ## 分类设置(基于 SSHD 服务的防护)
enabled = true                    ## 是否开启防护,false 为关闭
filter = sshd                     ## 过滤规则 filter 名称,对应 filter.d 目录下的 sshd.conf
action = iptables[name=SSH, port=ssh, protocol=tcp] ## 动作参数 
logpath = /var/log/secure         ## 检测系统登陆日志文件
maxretry = 5                      ## 最大尝试次数

如何删除fail2ban中已被禁用的黑名单IPfail2ban-配置

格式:
fail2ban-client set 服务规则 unbanip IP地址
例子:
fail2ban-client set nginx unbanip 8.8.8.8

CentOS7下如何验证fail2ban禁止的IP已经生效

第一个命令用来查看fail2ban配置的规则是否已经生效。
firewall-cmd --direct --get-all-rules

第二个命令用来查看在fail2ban黑名单里的IP是否已经加到了firewall中。
ipset list

测试自定义规则是否生效

fail2ban-regex /var/log/secure /etc/fail2ban/filter.d/sshd.conf

进程管理

如果你使用的是 CentOS 或 Fedora 的操作系统,则需要将 jail.local 配置文件中的 backend 选项从 auto 更改为 systemd。虽然在 Debian8+ 或 Ubuntu 16.04+ 上也都是使用了 systemd 来管理服务进程的,但这并不是必需的设置。默认情况下,在 CentOS7 中默认的配置文件是没有启用任何服务的,如果我们需要启动对应服务的话,需要手动修改配置文件,例如要启用 SSH 守护程序。

# /etc/fail2ban/jail.local

# "backend" specifies the backend used to get files modification.
# Available options are "pyinotify", "gamin", "polling", "systemd" and "auto".
# This option can be overridden in each jail as well.
backend = systemd

配置服务

Fail2Ban 自带有一组预定义的过滤器,用于各种服务,如 ssh、apache、nginx 等。我们不用对配置文件进行过多的更改,只需在对应服务区域中添加 enabled = true 启用该服务。禁用服务时将 true 改为 false 即可。

# /etc/fail2ban/jail.local
# enabled: 表明服务是要打开还是关闭
# port: 使用默认端口则填写服务名称;非传统端口则需要填写端口号
# logpath: 提供服务日志的位置
# backend: 指定用于获取文件修改的后端

[sshd]
enabled = true
port = ssh
filter = sshd
logpath = %(sshd_log)s
backend = %(sshd_backend)s
maxretry = 5

服务分离

如果需要监控的服务太多的话,放到一个配置文件里面,找起来还是又不方便的地方。所以,我们可以针对不同的服务配置创建不同的配置文件,每个配置文件立里面只配置对应服务的配置即可。将对应的配置放到 /etc/fail2ban/jail.d/ 目录下面,即可。

# /etc/fail2ban/jail.d/sshd.local

[sshd]
enabled   = true
filter    = sshd
banaction = iptables
backend   = systemd
maxretry  = 5
findtime  = 1d
bantime   = 2w
ignoreip  = 127.0.0.1/8

设置白名单

默认情况下,大多数选项都已经配置的很完美了,如果要启用忽略对某些特定 IP 的访问控制,则可以将 IP 地址添加到 ignoreip 区域即可。对于多个 IP 的情况,用空格隔开 IP 地址。配置文件中的 DEFAULT 部分包含 Fail2Ban 遵循的基本规则集,您可以根据自己的意愿调整任何参数。

# /etc/fail2ban/jail.local
# ignoreip: Fail2Ban不会禁止与列表中的地址匹配的主机;白名单
# bantime: 封禁时间秒,默认是10分钟
# findtime: 如果在最近findtime秒期间已经发生了maxretry次重试,则主机会被禁止
# maxretry: 最大重试次数,子项未设置时以此为准
# sendername: 发件人名称G
# sender: 用于发送告警邮件的邮箱地址
# destemail: 用于接收警报电子邮件的邮箱地址

[DEFAULT]
ignoreip = 127.0.0.1/8 192.168.1.100/24
bantime = 600
findtime = 600
maxretry = 3
sender = escapelife@gmail.com
destemail = escapelife@gmail.com

4、使用方式说明

工具服务启停操作

# 启动Fail2ban服务
$ sudo systemctl start fail2ban

# 停止Fail2ban服务
$ sudo systemctl stop fail2ban

# 开机自启动Fail2ban服务
$ sudo systemctl enable fail2ban

查看启用的服务监控列表

$ sudo fail2ban-client status
Status
|- Number of jail:  2
`- Jail list:   apache-auth, sshd

获取 SSH 服务禁止的 IP 地址

$ sudo fail2ban-client status ssh
Status for the jail: ssh
|- filter
| |- File list: /var/log/auth.log
| |- Currently failed: 1
| `- Total failed: 3
`- action
 |- Currently banned: 1
 | `- IP list: 192.168.1.115
 `- Total banned: 1

# 根据配置文件中的服务配置字段
$ sudo fail2ban-client status ssh-iptables

删除禁止的 IP 地址

# 根据配置文件中的服务配置字段
$ sudo fail2ban-client set ssh unbanip 192.168.1.115
$ sudo fail2ban-client set ssh-iptables unbanip 192.168.1.115

手动添加白名单

# 根据配置文件中的服务配置字段
$ sudo fail2ban-client set ssh addignoreip 192.168.1.115
$ sudo fail2ban-client set ssh-iptables addignoreip 192.168.1.115

示例演示说明

防止SSH爆破

如果您还在使用默认SSH端口(22),可能每天都会被扫描,我们可以修改端口尽量避免被扫,参考: https://www.moerats.com/archives/394/ ,或者可以使用fail2ban将恶意IP屏蔽。

继续修改jail.local这个配置文件,在后面追加如下内容:

[sshd]
enabled = true
filter  = sshd
port    = 22
action = %(action_mwl)s
logpath = /var/log/secure

参数说明:
[sshd]:名称,可以随便填写
filter:规则名称,必须填写位于filter.d目录里面的规则,sshd是fail2ban内置规则,对应 filter.d/sshd.conf
port:对应的端口
action:采取的行动
logpath:需要监视的日志路径

到这一步,我们jail.local的规则看起来可能像下面这样子:

[DEFAULT]
ignoreip = 127.0.0.1/8
bantime  = 86400
findtime = 600
maxretry = 5
banaction = firewallcmd-ipset
action = %(action_mwl)s

[sshd]
enabled = true
filter  = sshd
port    = 22
action = %(action_mwl)s
logpath = /var/log/secure

上面的配置意思是如果同一个IP,在10分钟内,如果连续超过5次错误,则使用Firewalld将他IP ban了。输入systemctl start fail2ban启动fail2ban来试试效果。

使用另一台服务器不断尝试连接SSH,并且不断的将密码输入错误,你会发现连续超过5次后直接连不上,说明IP被ban了,可以输入:fail2ban-client status sshd查看被ban的IP

使用 iptables 阻止IP访问

在不开启 firewalld 的情况下,可以使用 iptables 方式

vim jail.local 
[ssh-iptables]
enabled  = true
port     = 5258
filter   = sshd
action   = iptables[name=SSH, port=5258, protocol=tcp]
logpath  = /var/log/secure
maxretry = 5

自定义规则防止SSH暴力破解

查看 /var/log/secure 文件,有很多如下日志:

Jul  2 08:51:58 VM_0_8_centos sshd[22959]: Received disconnect from 119.29.191.40 port 54314:11: Bye Bye [preauth]
Jul  2 08:52:51 VM_0_8_centos sshd[23023]: Received disconnect from 104.37.189.106 port 52200:11: Bye Bye [preauth]
Jul  2 08:53:16 VM_0_8_centos sshd[23084]: Received disconnect from 119.29.191.40 port 48510:11: Bye Bye [preauth]
Jul  2 08:54:37 VM_0_8_centos sshd[23179]: Received disconnect from 119.29.191.40 port 42704:11: Bye Bye [preauth]
Jul  2 08:56:00 VM_0_8_centos sshd[23291]: Received disconnect from 119.29.191.40 port 36902:11: Bye Bye [preauth]
Jul  2 08:57:22 VM_0_8_centos sshd[23411]: Received disconnect from 119.29.191.40 port 59330:11: Bye Bye [preauth]
Jul  2 08:58:42 VM_0_8_centos sshd[23507]: Received disconnect from 119.29.191.40 port 53530:11: Bye Bye [preauth]
Jul  2 09:00:03 VM_0_8_centos sshd[23621]: Received disconnect from 119.29.191.40 port 47722:11: Bye Bye [preauth]
Jul  2 09:01:25 VM_0_8_centos sshd[23758]: Received disconnect from 119.29.191.40 port 41922:11: Bye Bye [preauth]
Jul  2 09:02:47 VM_0_8_centos sshd[23854]: Received disconnect from 119.29.191.40 port 36124:11: Bye Bye [preauth]
Jul  2 09:04:08 VM_0_8_centos sshd[23970]: Received disconnect from 119.29.191.40 port 58554:11: Bye Bye [preauth]
Jul  2 09:05:18 VM_0_8_centos sshd[24079]: Received disconnect from 104.37.189.106 port 46362:11: Bye Bye [preauth]
Jul  2 09:05:26 VM_0_8_centos sshd[24089]: Received disconnect from 119.29.191.40 port 52746:11: Bye Bye [preauth]
Jul  2 09:06:36 VM_0_8_centos sshd[24176]: Received disconnect from 62.231.7.220 port 55168:11: Bye Bye [preauth]
Jul  2 09:06:47 VM_0_8_centos sshd[24189]: Received disconnect from 119.29.191.40 port 46940:11: Bye Bye [preauth]
Jul  2 09:08:09 VM_0_8_centos sshd[24310]: Received disconnect from 119.29.191.40 port 41140:11: Bye Bye [preauth]
Jul  2 09:09:32 VM_0_8_centos sshd[24415]: Received disconnect from 119.29.191.40 port 35332:11: Bye Bye [preauth]
Jul  2 09:10:53 VM_0_8_centos sshd[24525]: Received disconnect from 119.29.191.40 port 57766:11: Bye Bye [preauth]
Jul  2 09:12:13 VM_0_8_centos sshd[24650]: Received disconnect from 119.29.191.40 port 51972:11: Bye Bye [preauth]
Jul  2 09:13:36 VM_0_8_centos sshd[24749]: Received disconnect from 119.29.191.40 port 46170:11: Bye Bye [preauth]
Jul  2 09:14:59 VM_0_8_centos sshd[24853]: Received disconnect from 119.29.191.40 port 40390:11: Bye Bye [preauth]
Jul  2 09:16:19 VM_0_8_centos sshd[24983]: Received disconnect from 119.29.191.40 port 34576:11: Bye Bye [preauth]
Jul  2 09:17:39 VM_0_8_centos sshd[25078]: Received disconnect from 119.29.191.40 port 57000:11: Bye Bye [preauth]
Jul  2 09:17:49 VM_0_8_centos sshd[25089]: Received disconnect from 104.37.189.106 port 40600:11: Bye Bye [preauth]

像这种日志,默认是不会被屏蔽的,需要手动添加规则

vim /etc/fail2ban/filter.d/sshd.conf

normal = ^%(__prefix_line_sl)s[aA]uthentication (?:failure|error|failed) for .* from <HOST>( via \S+)?\s*%(__suff)s$
         ^%(__prefix_line_sl)sUser not known to the underlying authentication module for .* from <HOST>\s*%(__suff)s$
        ...
        ...
         
        # 这里是添加的自定义规则
         ^%(__prefix_line)sReceived disconnect from <HOST> port \d*:\d*: Bye Bye \[preauth\]\s*$

重启服务并设置开机启动

systemctl restart fail2ban 
systemctl enable fail2ban 

防止CC攻击

这里仅以Nginx为例,使用fail2ban来监视nginx日志,匹配短时间内频繁请求的IP,并使用firewalld将其IP屏蔽,达到CC防护的作用。

#需要先新建一个nginx日志匹配规则
vi /etc/fail2ban/filter.d/nginx-cc.conf
#填写如下内容
[Definition]
failregex =  -.*- .*HTTP/1.* .* .*$
ignoreregex =

继续修改jail.local追加如下内容:

[nginx-cc]
enabled = true
port = http,https
filter = nginx-cc
action = %(action_mwl)s
maxretry = 20
findtime = 60
bantime = 3600
logpath = /usr/local/nginx/logs/access.log

上面的配置意思是如果在60s内,同一IP达到20次请求,则将其IP ban 1小时,上面只是为了测试,请根据自己的实际情况修改。logpath为nginx日志路径。

阻止恶意扫描

# 新增[nginx-dir-scan]模块
[nginx-dir-scan]
enabled = true
filter = nginx-dir-scan
action   = iptables[name=nginx-dir-scan, port=443, protocol=tcp]
logpath = /path/to/nginx/access.log
maxretry = 1
bantime = 172800
findtime  = 300

防止 vsftpd 攻击规则

[vsftpd-notification]
enabled = true
filter = vsftpd
action = sendmail-whois[name=VSFTPD, dest=you@example.com]
logpath = /var/log/vsftpd.log
maxretry = 5
bantime = 1800

[vsftpd-iptables]
enabled = true
filter = vsftpd
action = iptables[name=VSFTPD, port=ftp, protocol=tcp]
           sendmail-whois[name=VSFTPD, dest=you@example.com]
logpath = /var/log/vsftpd.log
maxretry = 5
bantime = 1800

总结

常用命令

启动
systemctl start fail2ban
#停止
systemctl stop fail2ban
#开机启动
systemctl enable fail2ban
#查看被ban IP,其中sshd为名称,比如上面的[wordpress]
fail2ban-client status sshd
#删除被ban IP
fail2ban-client set sshd delignoreip 192.168.111.111
#查看日志
tail /var/log/fail2ban.log

备注

每个.conf文件都会被名为 .local的文件覆盖。.conf首先被读取,其次是.local。新的配置会覆盖早先的。因此,.local 文件不必包含每个相应于.conf
中的选项,只是填写你想要覆盖的设置。

修改只会出现在.local文件中,而不是.conf中。这样可以避免升级时合并的问题。这些文件也是很好很详细的文档备注信息。

通用设置
fail2ban.conf文件中包含了fail2ban-server 守护进程的通用设置,诸如日志级别和目标。你也可以指定用于client和server端的通信的socket路径。