介绍
fail2ban用于监视系统日志,通过正则表达式匹配错误错误信息,设置一定的条件触发相应的屏蔽动作。
在笔者的vps里,主要是用于ssh的保护,ssh登录错误的时候会记录到 /var/log/secure,fail2ban通过 gamin检测到新增日志,10min内同一ip连续登陆5次就会封禁30min。
当然,一个足够的强密码也是必须的!
官方主页:http://www.fail2ban.org/wiki/index.php/Main_Page
github:https://github.com/fail2ban/fail2ban
安装
这里有两种安装方式,使用yum安装或者通过rpm安装。笔者的系统版本是CentOS-6.7
1 2 3 4 5
| #首先安装epel源,如果已经安装可以跳过此步 yum install -y epel-release #然后安装fail2ban: yum install -y fail2ban
|
fail2ban依赖下面四个安装包:
ed: Linux 操作系统下最简单的文本编辑器,以行为单位对文件进行编辑
gamin-python: python调用gamin的一个模块,gamin实现了一套监控文件变化的机制
ipset: 管理 ip地址/端口/mac地址 的模块,一般用于辅助提高iptables的性能
python-inotify: python的一个模块,实现了文件变化通知机制
1 2 3 4 5 6 7 8 9 10 11
| #其中前三个都可以使用yum安装: yum -y install ed gamin-python ipset python-inotify #然后根据系统架构不同,使用不同的rpm包安装: #i386 rpm -Uvh ftp://rpmfind.net/linux/atrpms/el6-i386/atrpms/stable/python-inotify-0.9.1-1.1.el6.noarch.rpm rpm -Uvh ftp://rpmfind.net/linux/epel/testing/6/i386/fail2ban-0.9.3-1.el6.noarch.rpm #x86-64 rpm -Uvh ftp://rpmfind.net/linux/atrpms/el6-x86_64/atrpms/stable/python-inotify-0.9.1-1.1.el6.noarch.rpm rpm -Uvh ftp://rpmfind.net/linux/epel/testing/6/x86_64/fail2ban-0.9.3-1.el6.noarch.rpm
|
配置
目前的最新版本是0.9.3
1 2 3 4 5 6 7 8
| 配置文件位于: /etc/fail2ban/action.d/ //采取相对应措施的目录 /etc/fail2ban/fail2ban.conf //fail2ban的配置文件 /etc/fail2ban/fail2ban.d/ //fail2ban的配置文件目录 /etc/fail2ban/filter.d/ //具体过滤规则文件目录 /etc/fail2ban/jail.conf //阻挡设定文件 /etc/fail2ban/jail.d/ //阻挡设定文件的目录 /etc/fail2ban/paths-*.conf //不同linux发行版下路径的相关设置,在jail.conf的[INCLUDES]里指定
|
fail2ban.conf 是针对fail2ban程序运行本身的一些设置。
jail.conf 是fail2ban的业务功能设置,里面设置了需要监控那些服务以及如何保护等,里边已经针对常用的服务提供了监控方案,比如sshd、apache、3proxy等,笔者只启用了sshd的保护。
jail.conf里的注释十分丰富,简单介绍一些基本的设置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| #所有监控项的默认设置 [DEFAULT] #忽略的ip,这里表示本机ip将永不被封禁 ignoreip = 127.0.0.1/8 #封禁时间,单位为秒 bantime = 600 #监控周期,表示在600s内,失败次数达到maxretry的主机将会被封禁 findtime = 600 #最大重试次数,表示在findtime内,失败次数达到5次的主机将会被封禁 maxretry = 5 #默认关闭对所有服务的保护 enabled = false
|
启用sshd的保护很简单,在jail.conf的[sshd]中加上一行enabled = true就可以:
1 2 3 4 5 6 7 8
| # SSH servers # [sshd] port = ssh logpath = %(sshd_log)s enabled = true
|
最后就是设置服务自启动了
1 2
| chkconfig fail2ban on service fail2ban start
|
CentOS7的补充说明
在CentOS7下可能会出现类似错误
1 2 3 4 5 6 7 8 9 10 11 12
| 2017-04-19 10:19:30,335 fail2ban.action [526]: ERROR ipset create fail2ban-sshd hash:ip timeout 600 firewall-cmd --direct --add-rule ipv4 filter INPUT 0 -p tcp -m multiport --dports ssh -m set --match-set fail2ban-sshd src -j REJECT --reject-with icmp-port-unreachable -- stdout: '' 2017-04-19 10:19:30,335 fail2ban.action [526]: ERROR ipset create fail2ban-sshd hash:ip timeout 600 firewall-cmd --direct --add-rule ipv4 filter INPUT 0 -p tcp -m multiport --dports ssh -m set --match-set fail2ban-sshd src -j REJECT --reject-with icmp-port-unreachable -- stderr: 'ipset v6.19: Cannot open session to kernel.\n\x1b[91mFirewallD is not running\x1b[00m\n' 2017-04-19 10:19:30,336 fail2ban.action [526]: ERROR ipset create fail2ban-sshd hash:ip timeout 600 firewall-cmd --direct --add-rule ipv4 filter INPUT 0 -p tcp -m multiport --dports ssh -m set --match-set fail2ban-sshd src -j REJECT --reject-with icmp-port-unreachable -- killed with signal 124 (return code: 252) 2017-04-19 10:19:30,336 fail2ban.actions [526]: ERROR Failed to start jail 'sshd' action 'firewallcmd-ipset': Error starting action …… 2017-04-19 10:19:41,529 fail2ban.action [526]: ERROR ipset add fail2ban-sshd 116.31.116.14 timeout 600 -exist -- stdout: '' 2017-04-19 10:19:41,530 fail2ban.action [526]: ERROR ipset add fail2ban-sshd 116.31.116.14 timeout 600 -exist -- stderr: 'ipset v6.19: Cannot open session to kernel.\n' 2017-04-19 10:19:41,530 fail2ban.action [526]: ERROR ipset add fail2ban-sshd 116.31.116.14 timeout 600 -exist -- returned 1 2017-04-19 10:19:41,531 fail2ban.actions [526]: ERROR Failed to execute ban jail 'sshd' action 'firewallcmd-ipset' info 'CallingMap({'ipjailmatches': <function <lambda> at 0xb08578>, 'matches': '[……]', 'ip': '116.31.116.14', 'ipmatches': <function <lambda> at 0xb08410>, 'ipfailures': <function <lambda> at 0xb086e0>, 'time': 1492568381.402617, 'failures': 40, 'ipjailfailures': <function <lambda> at 0xb08500>})': Error banning 116.31.116.14
|
CentOS7使用了firewall作为默认防火墙,而fail2ban默认使用firewallcmd-ipset
作为封禁动作,但是在基于openvz的vps平台上是不能调用ipset的,所以需要做一些更改。
更改/etc/fail2ban/jail.d/00-firewalld.conf
文件,将其更改为使用firewallcmd-new
1 2 3
| [DEFAULT] #banaction = firewallcmd-ipset banaction = firewallcmd-new
|
FAQ
Q:日志中出现Error starting action错误
1 2 3 4 5 6
| fail2ban.server[2228]: INFO Jail sshd is not a JournalFilter instance fail2ban.jail[2228]: INFO Jail 'sshd' started fail2ban.action[2228]: ERROR iptables -w -N f2b-sshd#012iptables -w -A f2b-sshd -j RETURN#012iptables -w -I INPUT -p tcp -m multiport --dports ssh -j f2b-sshd -- stdout: '' fail2ban.action[2228]: ERROR iptables -w -N f2b-sshd#012iptables -w -A f2b-sshd -j RETURN#012iptables -w -I INPUT -p tcp -m multiport --dports ssh -j f2b-sshd -- stderr: '' fail2ban.action[2228]: ERROR iptables -w -N f2b-sshd#012iptables -w -A f2b-sshd -j RETURN#012iptables -w -I INPUT -p tcp -m multiport --dports ssh -j f2b-sshd -- returned 2 fail2ban.actions[2228]: ERROR Failed to start jail 'sshd' action 'iptables-multiport': Error starting action
|
A:fail2ban-0.9.3在执行iptable命令时,加上了-w参数用于防止冲突,但是iptables-1.4.20才有这个参数,而CentOS6.7下的是iptables-1.4.7,因此导致iptable的命令执行失败,Github有这个问题:
https://github.com/fail2ban/fail2ban/issues/1122
一个折中方案是,修改/etc/fail2ban/action.d/iptables-common.conf文件,去掉,也就是-w参数:
1 2 3 4 5
| # Option: iptables # Notes.: Actual command to be executed, including common to all calls options # Values: STRING #iptables = iptables <lockingopt> iptables = iptables
|
Q:日志中出现ERROR findFailure failed to parse timeText错误:
1 2 3 4
| Sep 21 09:57:51 12345 fail2ban.filter[1588]: ERROR findFailure failed to parse timeText: Sep 21 09:57:26 1234 #在fail2ban-0.9.2 是这样的错误 Sep 21 10:05:37 12345 fail2ban.filterpyinotify[1305]: ERROR Error in FilterPyinotify callback: mktime argument out of range
|
A:这个错误源于一个不算bug的bug,当用户的hostname前面为数字的时候就会触发
1 2
| [root@12345 ~]# hostname 12345.domain.com
|
在日志中,12345.domain.com前面的12345被当作是年份被解析了,笔者的vps很不幸,hostname就是数字开头的,而且当时的版本还是fail2ban-0.9.2,排错过程十分辛苦。
解决的方法有很多,比如最直接的修改hostname
1
| vi /etc/sysconfig/network
|
而笔者采用的方案是修改 rsyslog 的日志格式:
1 2 3 4 5 6
| vi /etc/rsyslog.conf # Use default timestamp format #$ActionFileDefaultTemplate RSYSLOG_TraditionalFileFormat $template FileFormat,"%TIMESTAMP:::date-rfc3339% %HOSTNAME% %syslogtag%%msg:::sp-if-no-1st-sp%%msg:::drop-last-lf%\n" $ActionFileDefaultTemplate FileFormat
|
重启 rsyslog 服务
关于rsyslog日志格式的说明:
http://www.rsyslog.com/doc/v8-stable/configuration/templates.html#reserved-template-names