怎样部署fail2ban

2017年4月21日 | 分类: 【技术】

【介绍】

任何连接到互联网的机器都是恶意攻击的潜在目标。Fail2Ban 是一款入侵防御软件,可用来缓解服务器上的非法访问。Fail2Ban 能够降低错误认证尝试的速度,但是它不能消除弱认证带来的风险。 这只是服务器防止暴力攻击的安全手段之一。

fail2ban 可以监视系统日志,利用做filter和actor对匹配条件的错误信息(正则式匹配)执行相应的屏蔽动作。Fail2Ban 基于 auth 日志文件工作,默认情况下它会扫描所有 auth 日志文件,如 /var/log/auth.log 、 /var/log/apache/access.log 等,并禁止带有恶意标志的IP,比如密码失败太多,寻找漏洞等等标志。

Fail2Ban 用于更新防火墙规则,用于在指定的时间内拒绝 IP 地址。 它也会发送邮件通知。Fail2Ban 为各种服务提供了许多过滤器,如 ssh、apache、nginx、squid、named、mysql、nagios 等。

如果需要对IPv6地址进行匹配,Fail2ban的版本需要大于0.10。

Fail2Ban 用 Python 编程语言编写的。

官网:http://www.fail2ban.org/

CentOS 7已经自带Firewalld,并且使用Firewalld作为网络防火墙更加简单方便,以下是fail2ban + Firewalld使用方法。

参考:https://amon.org/firewalld

【环境】

检查Firewalld是否启用。

如果已经安装iptables建议先关闭:

service iptables stop

查看Firewalld状态:

firewall-cmd --state

启动firewalld:

systemctl start firewalld

设置firewalld开机启动:

systemctl enable firewalld.service

设置firewalld端口:

启用Firewalld后会禁止所有端口连接,因此请务必放行常用的端口,以免被阻挡在外。

firewall-cmd --zone=public --add-port=22/tcp --permanent
firewall-cmd --zone=public --add-port=80/tcp --permanent
firewall-cmd --zone=public --add-port=443/tcp --permanent

重载配置使之生效:

firewall-cmd --reload

查看已放行端口:

firewall-cmd --zone=public --list-ports

【安装(yum)】

yum -y install fail2ban

如果报错:

...
No package fail2ban available.
Error: Nothing to do

参考:https://www.atlantic.net/hipaa-compliant-cloud-storage/how-to-install-configure-fail2ban-centos/
参考:https://www.yeely.cn/fix-nopackage-available-on-linux.html

不如从源码编译。

查看版本:

fail2ban-client -V

设为开机自启:

systemctl enable fail2ban

【安装(源码编译)】

源码:https://github.com/fail2ban/fail2ban

git clone https://github.com/fail2ban/fail2ban.git && cd fail2ban && python setup.py install 

Fail2ban将安装到Python的库目录下,可执行脚本位于/usr/bin,配置文件位于/etc/fail2ban。

启动脚本:

复制源码路径files下相应的操作系统的启动脚本到/etc/init.d/下 :

参考:https://extremeshok.com/1759/centos-6-rhel-6-install-the-latest-fail2ban-from-source/

cp /root/fail2ban/files/redhat-initd /etc/init.d/fail2ban
chmod 755 /etc/init.d/fail2ban
chkconfig --add fail2ban && chkconfig fail2ban on

从源码升级:

cd /root/fail2ban && git pull -u && python setup.py install

查看版本:

fail2ban-client version

查看帮助:

fail2ban-client -h

【用法】

fail2ban-client 方式:

fail2ban-client status
fail2ban-client start
fail2ban-client stop
fail2ban-client restart

systemctl 方式:

systemctl status fail2ban
systemctl start fail2ban
systemctl stop fail2ban
systemctl restart fail2ban

service 方式:

service fail2ban status
service fail2ban start
service fail2ban stop
service fail2ban restart

查看被ban IP,其中sshd为名称,比如[wordpress]:

fail2ban-client status sshd

启用fail2ban日志:

sed -i "s|logtarget = SYSLOG|logtarget = /var/log/fail2ban.log|" /etc/fail2ban/fail2ban.conf

查看日志:

tail /var/log/fail2ban.log

避免你的IP和掩码被屏蔽:

sed -i "s|ignoreip = 127.0.0.1|ignoreip = 127.0.0.1 68.235.32.0/28|" /etc/fail2ban/fail2ban.conf

参考:https://www.xiaoz.me/archives/9831
参考:https://qiita.com/kskiwmt/items/f871f940fa9b64b4f396

【黑名单】

手工添加黑名单永久屏蔽(firewalld):

实证未遂。

参考:https://gist.github.com/utarn/fae9316a32e7db816741f7ec189e9f0b

创建一个黑名单文件:

/etc/fail2ban/ip.blacklist

备份 /etc/fail2ban/action.d/firewallcmd-multiport.conf ,然后编辑:

# Fail2Ban configuration file
#
# Author: Donald Yandt 
# Because of the --remove-rules in stop this action requires firewalld-0.3.8+

[INCLUDES]

before = firewallcmd-common.conf

[Definition]

actionstart = firewall-cmd --direct --add-chain <family> filter f2b-<name>
              firewall-cmd --direct --add-rule <family> filter f2b-<name> 1000 -j RETURN
              firewall-cmd --direct --add-rule <family> filter <chain> 0 -m conntrack --ctstate NEW -p <protocol> -m multiport --dports <port> -j f2b-<name>
	      cat /etc/fail2ban/ip.blacklist | awk '/^<family>-<name>/ {print $2}' | while read IP; do firewall-cmd --direct --add-rule <family> filter f2b-<name> 0 -s $IP -j <blocktype>; done

actionstop = firewall-cmd --direct --remove-rule <family> filter <chain> 0 -m conntrack --ctstate NEW -p <protocol> -m multiport --dports <port> -j f2b-<name>
             firewall-cmd --direct --remove-rules <family> filter f2b-<name>
             firewall-cmd --direct --remove-chain <family> filter f2b-<name>

# Example actioncheck: firewall-cmd --direct --get-chains ipv4 filter | sed -e 's, ,\n,g' | grep -q '^f2b-apache-modsecurity$'

actioncheck = firewall-cmd --direct --get-chains <family> filter | sed -e 's, ,\n,g' | grep -q '^f2b-<name>$'

actionban = firewall-cmd --direct --add-rule <family> filter f2b-<name> 0 -s <ip> -j <blocktype>
            echo "<family>-<name> <ip>" >> /etc/fail2ban/ip.blacklist

actionunban = firewall-cmd --direct --remove-rule <family> filter f2b-<name> 0 -s <ip> -j <blocktype>

手工添加黑名单永久屏蔽(iptables):

参考:https://zach.seifts.us/posts/2013/07/14/how-make-fail2ban-bans-persistent
参考:http://chang0206.blogspot.com/2016/12/fail2ban.html

创建一个黑名单文件:

/etc/fail2ban/ip.blacklist

备份 /etc/fail2ban/action.d/iptables-multiport.conf/etc/fail2ban/action.d/firewallcmd-multiport.conf ,然后编辑 actionstart 和 actionban 。

当 fail2ban 屏蔽一个不仅需要屏蔽,同时添加入黑名单的IP时:bans an IP we want to not only ban it, but we want to add the IP address to the ip.blacklist file.

actionban = iptables -I fail2ban-<name> 1 -s <ip> -j DROP
            echo <ip> >> /etc/fail2ban/ip.blacklist

我们需要确认当 fail2ban 启动时防火墙规则已被添加,需要在 actionstart 部分添加:

actionstart = iptables -N fail2ban-<name>
              iptables -A fail2ban-<name> -j RETURN
              iptables -I INPUT -p <protocol> -m multiport --dports <port> -j fail2ban-<name>
              cat /etc/fail2ban/ip.blacklist | while read IP; do iptables -I fail2ban-<name> 1 -s $IP -j DROP; done

这样当重启 fail2ban i时会自动屏蔽所有列入黑名单中的IP。

【配置】

默认情况下,Fail2Ban 将所有配置文件保存在 /etc/fail2ban/ 目录中。主配置文件是 jail.conf,它包含一组预定义的过滤器,但不要在它基础上修改配置。在同一目录下创建一个名为 jail.local 的新配置文件,并根据您的意愿进行修改。jail.local 将覆盖 jail.conf 的所有默认规则:

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

fail2ban已经内置很多匹配规则,位于filter.d目录下,包含了常见的SSH/FTP/Nginx/Apache等日志匹配。

默认情况下,大多数选项都已经配置的很完美了,如果要启用对任何特定 IP 的访问,则可以将 IP 地址添加到 ignoreip 区域,对于多个 IP 的情况,用空格隔开 IP 地址。

默认配置:

配置文件中的 DEFAULT 部分包含 Fail2Ban 遵循的基本规则集,您可以根据自己的意愿调整任何参数。

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

参数解释:
ignoreip:IP白名单,白名单中的IP不会屏蔽,可填写多个以(,)分隔
bantime:屏蔽时间,单位为秒(s)
findtime:时间范围
maxretry:主机被禁止之前的失败次数
banaction:屏蔽IP所使用的方法,上面使用firewalld屏蔽端口。必须用firewallcmd-ipset,这是fiewalll支持的关键,如果是用Iptables请不要这样填写。

防止SSH爆破:

如果您还在使用默认SSH端口(22),可能每天都会被扫描,强烈建议先参考《Linux服务器之登录安全》加强服务器防护,或者可以使用fail2ban将恶意IP屏蔽。

参考:https://www.xiaoz.me/archives/8223

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

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

参数解释:
[sshd]:自己定义。
enabled:确定服务是打开还是关闭。
filter:规则名称,必须填写位于filter.d目录里面的规则,sshd是fail2ban内置规则
port:指明特定的服务。如果使用默认端口,则服务名称可以放在这里。如果使用非传统端口,则应该是端口号。
action:采取的行动
logpath:需要监视的日志路径
backend:指定用于获取文件修改的后端。

上面的配置意思是如果同一个IP,在10分钟内,如果连续超过5次错误,则使用Firewalld将他IP ban了。

保存 jail.local 后,重新启用fail2ban:

systemctl restart fail2ban

测试效果:

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

fail2ban-client status sshd

输出:

Status for the jail: sshd
|- Filter
| |- Currently failed: 0
| |- Total failed: 0
| `- Journal matches:
`- Actions
 |- Currently banned: 0
 |- Total banned: 0
 `- Banned IP list:

WordPress防护配置:

分析日志会发现有大量机器人在扫描wordpress登录页面wp-login.php,虽然对方可能没成功,但是为了避免万一还是将他IP干掉为好。

新建一个日志匹配规则,/etc/fail2ban/filter.d/wordpress.conf

注意:所有新的规则都放置于 /etc/fail2ban/filter.d/ ,文件名与 jail.local 中的 [wordpress] 相对。

填写如下内容:

[Definition]
failregex = ^&lt;/host&gt;&lt;host&gt; -.* /wp-login.php.* HTTP/1\..&quot;
ignoreregex =

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

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

SendMail防护配置:

安装:

yum install sendmail

配置:

参考:http://www.fail2ban.org/wiki/index.php?title=sendmail&oldid=2965

如果报错:

My unqualified host name (Amon) unknown; sleeping for retry

参考:https://serverfault.com/questions/58363/my-unqualified-host-name-foo-bar-unknown-problem

127.0.0.1     localhost localhost.localdomain Amon

Sendmail looks for a fully qualified domain (FQDN) name and will use the localhost.localdomain in the single line version.

重启后,如果报错:

Job for fail2ban.service failed because the control process exited with error code. See "systemctl status fail2ban.service" and "journalctl -xe" for details.

输入:

systemctl status fail2ban.service

输出里发现:

ERROR   There is no directory /var/run/fail2ban to contain the socket file /var/run/fail2ban/fail2ban.sock.

那么创建这个目录:

mkdir /var/run/fail2ban

然后重启 fail2ban ,正常启动。

【排错】

报错: WARNING Wrong value for ‘findtime’ in ‘sshd’.

文件:jail.local

一般是因为时间格式引起的,统一用秒表示即可。

报错:WARNING Wrong value for ‘dbpurgeage’ in ‘Definition’

文件:fail2ban.conf

一般是因为时间格式引起的,统一用秒表示即可。

参考:https://www.cnblogs.com/miketwais/articles/fail2ban.html

# dbpurgeage = 1d
dbpurgeage = 86400

报错: fail2ban ERROR NOK: (“No ‘host’

参考:https://github.com/fail2ban/fail2ban/issues/1723

参考:https://www.centos.org/forums/viewtopic.php?t=49819

【应用】

参考:https://stackoverflow.com/questions/32652703/fail2ban-filter-error-no-host-found-in

failregex looks like this:

failregex = ^.*?&lt;HOST&gt; https?://.*?[Aa]dmin.*? ((301)|(404)).*$

参考:https://my.oschina.net/CandyMi/blog/500767
参考:https://my.oschina.net/yiyuanxi/blog/810988

【参考】

参考:https://zhuanlan.zhihu.com/p/33546122
参考:https://www.digitalocean.com/community/tutorials/how-to-set-up-a-firewall-using-firewalld-on-centos-7
参考:https://www.digitalocean.com/community/tutorials/how-to-protect-ssh-with-fail2ban-on-centos-7
参考:https://www.cnblogs.com/miketwais/articles/fail2ban.html
参考:http://www.cnblogs.com/canxuexiecheng/articles/3315021.html
参考:http://www.tutorials.makkugasho.com/2014/02/21/asterisk-11-5-fail2ban/
参考:http://blog.csdn.net/clebeg/article/details/37960425
参考:https://www.xiaoz.me/archives/9831
参考:https://www.ifshow.com/centos-7-install-fail2ban-with-firewalld-to-defend-brute-force-password/
参考:http://baike.baidu.com/item/Fail2ban
参考:https://my.oschina.net/monkeyzhu/blog/418592
参考:https://calvinpeak.herokuapp.com/2014/12/15/install-centos-7-in-linode/