舫摘

知人者智 自知者明 胜人者有力 自胜者强

0%

CentOS 7下fail2ban安装配置

fail2ban可以监视你的系统日志,然后匹配日志的错误信息(正则式匹配)执行相应的屏蔽动作,一般情况下是调用防火墙iptables屏蔽,CentOS 7改由firewalld控制。

如:当有人在试探你的SSHSMTPFTP密码,只要达到你预设的次数,fail2ban就会调用防火墙屏蔽这个IP,而且可以发送e-mail通知系统管理员,是一款很实用、很强大的软件!

fail2banpython语言开发,基于logwatchgaminiptablestcp-wrappershorewall等。如果想要发送邮件通知道,那还需要安装postfixsendmail

安装fail2ban

添加源

1
2
wget http://epel.mirror.nucleus.be/7/x86_64/e/epel-release-7-5.noarch.rpm
rpm -i epel-release-7-5.noarch.rpm

安装fail2ban

CentOS 7已经将防火墙从iptables升级到firewalld,所以我们需要安装firewalld版本的fail2ban

1
yum install fail2ban-firewalld fail2ban-systemd

配置fail2ban

创建jail.local配置文件

1
2
3
4
5
6
7
8
# /etc/fail2ban/jail.local
[DEFAULT]
findtime = 5000 # 检查周期。

[sshd]
enabled = true # 启用规则
bantime = 86400 # 阻止时间,一天。单位秒。
maxretry = 3 # 重试次数

上面的代码创建了一个简单的监狱配置,包含了一个针对sshd的保护规则。

jail配置文件参数说明

名称默认值描述
enabled是否启用规则
filter过滤规则文件名字。更多过滤规则存放在/etc/fail2ban/filter.d/目录中
logpath/var/log/messages监控的日志路径
maxretry5匹配次数,达到次数的IP会被阻止访问
findtime600秒检测周期,阻止在检测周期内达到失败次数的IP访问服务
bantime600秒阻止时间,填负数会被永久阻止访问
banaction阻止IP时执行的动作。更多动作存放在/etc/fail2ban/action.d/

测试规则

执行

1
fail2ban-client -d

输出:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
['set', 'syslogsocket', 'auto']
['set', 'loglevel', 'INFO']
['set', 'logtarget', '/var/log/fail2ban.log']
['set', 'dbfile', '/var/lib/fail2ban/fail2ban.sqlite3']
['set', 'dbpurgeage', 86400]
['add', 'sshd', 'systemd']
['set', 'sshd', 'usedns', 'warn']
['set', 'sshd', 'maxretry', 3]
['set', 'sshd', 'addignoreip', '127.0.0.1/8']
['set', 'sshd', 'logencoding', 'auto']
['set', 'sshd', 'bantime', 86400]
['set', 'sshd', 'ignorecommand', '']
['set', 'sshd', 'findtime', 5000]
['set', 'sshd', 'maxlines', '10']
['set', 'sshd', 'addfailregex', '^\\s*(<[^.]+\\.[^.]+>)?\\s*(?:\\S+ )?(?:kernel: \\[ *\\d+\\.\\d+\\] )?(?:@vserver_\\S+ )?(?:(?:\\[\\d+\\])?:\\s+[\\[\\(]?sshd(?:\\(\\S+\\))?[\\]\\)]?:?|[\\[\\(]?sshd(?:\\(\\S+\\))?[\\]\\)]?:?(?:\\[\\d+\\])?:?)?\\s(?:\\[ID \\d+ \\S+\\])?\\s*(?:error: PAM: )?[aA]uthentication (?:failure|error) for .* from <HOST>( via \\S+)?\\s*$']
['set', 'sshd', 'addfailregex', '^\\s*(<[^.]+\\.[^.]+>)?\\s*(?:\\S+ )?(?:kernel: \\[ *\\d+\\.\\d+\\] )?(?:@vserver_\\S+ )?(?:(?:\\[\\d+\\])?:\\s+[\\[\\(]?sshd(?:\\(\\S+\\))?[\\]\\)]?:?|[\\[\\(]?sshd(?:\\(\\S+\\))?[\\]\\)]?:?(?:\\[\\d+\\])?:?)?\\s(?:\\[ID \\d+ \\S+\\])?\\s*(?:error: PAM: )?User not known to the underlying authentication module for .* from <HOST>\\s*$']
['set', 'sshd', 'addfailregex', '^\\s*(<[^.]+\\.[^.]+>)?\\s*(?:\\S+ )?(?:kernel: \\[ *\\d+\\.\\d+\\] )?(?:@vserver_\\S+ )?(?:(?:\\[\\d+\\])?:\\s+[\\[\\(]?sshd(?:\\(\\S+\\))?[\\]\\)]?:?|[\\[\\(]?sshd(?:\\(\\S+\\))?[\\]\\)]?:?(?:\\[\\d+\\])?:?)?\\s(?:\\[ID \\d+ \\S+\\])?\\s*Failed \\S+ for .*? from <HOST>(?: port \\d*)?(?: ssh\\d*)?(: (ruser .*|(\\S+ ID \\S+ \\(serial \\d+\\) CA )?\\S+ (?:[\\da-f]{2}:){15}[\\da-f]{2}(, client user ".*", client host ".*")?))?\\s*$']
['set', 'sshd', 'addfailregex', '^\\s*(<[^.]+\\.[^.]+>)?\\s*(?:\\S+ )?(?:kernel: \\[ *\\d+\\.\\d+\\] )?(?:@vserver_\\S+ )?(?:(?:\\[\\d+\\])?:\\s+[\\[\\(]?sshd(?:\\(\\S+\\))?[\\]\\)]?:?|[\\[\\(]?sshd(?:\\(\\S+\\))?[\\]\\)]?:?(?:\\[\\d+\\])?:?)?\\s(?:\\[ID \\d+ \\S+\\])?\\s*ROOT LOGIN REFUSED.* FROM <HOST>\\s*$']
['set', 'sshd', 'addfailregex', '^\\s*(<[^.]+\\.[^.]+>)?\\s*(?:\\S+ )?(?:kernel: \\[ *\\d+\\.\\d+\\] )?(?:@vserver_\\S+ )?(?:(?:\\[\\d+\\])?:\\s+[\\[\\(]?sshd(?:\\(\\S+\\))?[\\]\\)]?:?|[\\[\\(]?sshd(?:\\(\\S+\\))?[\\]\\)]?:?(?:\\[\\d+\\])?:?)?\\s(?:\\[ID \\d+ \\S+\\])?\\s*[iI](?:llegal|nvalid) user .* from <HOST>\\s*$']
['set', 'sshd', 'addfailregex', '^\\s*(<[^.]+\\.[^.]+>)?\\s*(?:\\S+ )?(?:kernel: \\[ *\\d+\\.\\d+\\] )?(?:@vserver_\\S+ )?(?:(?:\\[\\d+\\])?:\\s+[\\[\\(]?sshd(?:\\(\\S+\\))?[\\]\\)]?:?|[\\[\\(]?sshd(?:\\(\\S+\\))?[\\]\\)]?:?(?:\\[\\d+\\])?:?)?\\s(?:\\[ID \\d+ \\S+\\])?\\s*User .+ from <HOST> not allowed because not listed in AllowUsers\\s*$']
['set', 'sshd', 'addfailregex', '^\\s*(<[^.]+\\.[^.]+>)?\\s*(?:\\S+ )?(?:kernel: \\[ *\\d+\\.\\d+\\] )?(?:@vserver_\\S+ )?(?:(?:\\[\\d+\\])?:\\s+[\\[\\(]?sshd(?:\\(\\S+\\))?[\\]\\)]?:?|[\\[\\(]?sshd(?:\\(\\S+\\))?[\\]\\)]?:?(?:\\[\\d+\\])?:?)?\\s(?:\\[ID \\d+ \\S+\\])?\\s*User .+ from <HOST> not allowed because listed in DenyUsers\\s*$']
['set', 'sshd', 'addfailregex', '^\\s*(<[^.]+\\.[^.]+>)?\\s*(?:\\S+ )?(?:kernel: \\[ *\\d+\\.\\d+\\] )?(?:@vserver_\\S+ )?(?:(?:\\[\\d+\\])?:\\s+[\\[\\(]?sshd(?:\\(\\S+\\))?[\\]\\)]?:?|[\\[\\(]?sshd(?:\\(\\S+\\))?[\\]\\)]?:?(?:\\[\\d+\\])?:?)?\\s(?:\\[ID \\d+ \\S+\\])?\\s*User .+ from <HOST> not allowed because not in any group\\s*$']
['set', 'sshd', 'addfailregex', '^\\s*(<[^.]+\\.[^.]+>)?\\s*(?:\\S+ )?(?:kernel: \\[ *\\d+\\.\\d+\\] )?(?:@vserver_\\S+ )?(?:(?:\\[\\d+\\])?:\\s+[\\[\\(]?sshd(?:\\(\\S+\\))?[\\]\\)]?:?|[\\[\\(]?sshd(?:\\(\\S+\\))?[\\]\\)]?:?(?:\\[\\d+\\])?:?)?\\s(?:\\[ID \\d+ \\S+\\])?\\s*refused connect from \\S+ \\(<HOST>\\)\\s*$']
['set', 'sshd', 'addfailregex', '^\\s*(<[^.]+\\.[^.]+>)?\\s*(?:\\S+ )?(?:kernel: \\[ *\\d+\\.\\d+\\] )?(?:@vserver_\\S+ )?(?:(?:\\[\\d+\\])?:\\s+[\\[\\(]?sshd(?:\\(\\S+\\))?[\\]\\)]?:?|[\\[\\(]?sshd(?:\\(\\S+\\))?[\\]\\)]?:?(?:\\[\\d+\\])?:?)?\\s(?:\\[ID \\d+ \\S+\\])?\\s*Received disconnect from <HOST>: 3: \\S+: Auth fail$']
['set', 'sshd', 'addfailregex', '^\\s*(<[^.]+\\.[^.]+>)?\\s*(?:\\S+ )?(?:kernel: \\[ *\\d+\\.\\d+\\] )?(?:@vserver_\\S+ )?(?:(?:\\[\\d+\\])?:\\s+[\\[\\(]?sshd(?:\\(\\S+\\))?[\\]\\)]?:?|[\\[\\(]?sshd(?:\\(\\S+\\))?[\\]\\)]?:?(?:\\[\\d+\\])?:?)?\\s(?:\\[ID \\d+ \\S+\\])?\\s*User .+ from <HOST> not allowed because a group is listed in DenyGroups\\s*$']
['set', 'sshd', 'addfailregex', "^\\s*(<[^.]+\\.[^.]+>)?\\s*(?:\\S+ )?(?:kernel: \\[ *\\d+\\.\\d+\\] )?(?:@vserver_\\S+ )?(?:(?:\\[\\d+\\])?:\\s+[\\[\\(]?sshd(?:\\(\\S+\\))?[\\]\\)]?:?|[\\[\\(]?sshd(?:\\(\\S+\\))?[\\]\\)]?:?(?:\\[\\d+\\])?:?)?\\s(?:\\[ID \\d+ \\S+\\])?\\s*User .+ from <HOST> not allowed because none of user's groups are listed in AllowGroups\\s*$"]
['set', 'sshd', 'addfailregex', '^(?P<__prefix>\\s*(<[^.]+\\.[^.]+>)?\\s*(?:\\S+ )?(?:kernel: \\[ *\\d+\\.\\d+\\] )?(?:@vserver_\\S+ )?(?:(?:\\[\\d+\\])?:\\s+[\\[\\(]?sshd(?:\\(\\S+\\))?[\\]\\)]?:?|[\\[\\(]?sshd(?:\\(\\S+\\))?[\\]\\)]?:?(?:\\[\\d+\\])?:?)?\\s(?:\\[ID \\d+ \\S+\\])?\\s*)User .+ not allowed because account is locked<SKIPLINES>(?P=__prefix)(?:error: )?Received disconnect from <HOST>: 11: .+ \\[preauth\\]$']
['set', 'sshd', 'addfailregex', '^(?P<__prefix>\\s*(<[^.]+\\.[^.]+>)?\\s*(?:\\S+ )?(?:kernel: \\[ *\\d+\\.\\d+\\] )?(?:@vserver_\\S+ )?(?:(?:\\[\\d+\\])?:\\s+[\\[\\(]?sshd(?:\\(\\S+\\))?[\\]\\)]?:?|[\\[\\(]?sshd(?:\\(\\S+\\))?[\\]\\)]?:?(?:\\[\\d+\\])?:?)?\\s(?:\\[ID \\d+ \\S+\\])?\\s*)Disconnecting: Too many authentication failures for .+? \\[preauth\\]<SKIPLINES>(?P=__prefix)(?:error: )?Connection closed by <HOST> \\[preauth\\]$']
['set', 'sshd', 'addfailregex', '^(?P<__prefix>\\s*(<[^.]+\\.[^.]+>)?\\s*(?:\\S+ )?(?:kernel: \\[ *\\d+\\.\\d+\\] )?(?:@vserver_\\S+ )?(?:(?:\\[\\d+\\])?:\\s+[\\[\\(]?sshd(?:\\(\\S+\\))?[\\]\\)]?:?|[\\[\\(]?sshd(?:\\(\\S+\\))?[\\]\\)]?:?(?:\\[\\d+\\])?:?)?\\s(?:\\[ID \\d+ \\S+\\])?\\s*)Connection from <HOST> port \\d+(?: on \\S+ port \\d+)?<SKIPLINES>(?P=__prefix)Disconnecting: Too many authentication failures for .+? \\[preauth\\]$']
['set', 'sshd', 'addfailregex', '^\\s*(<[^.]+\\.[^.]+>)?\\s*(?:\\S+ )?(?:kernel: \\[ *\\d+\\.\\d+\\] )?(?:@vserver_\\S+ )?(?:(?:\\[\\d+\\])?:\\s+[\\[\\(]?sshd(?:\\(\\S+\\))?[\\]\\)]?:?|[\\[\\(]?sshd(?:\\(\\S+\\))?[\\]\\)]?:?(?:\\[\\d+\\])?:?)?\\s(?:\\[ID \\d+ \\S+\\])?\\s*pam_unix\\(sshd:auth\\):\\s+authentication failure;\\s*logname=\\S*\\s*uid=\\d*\\s*euid=\\d*\\s*tty=\\S*\\s*ruser=\\S*\\s*rhost=<HOST>\\s.*$']
['set', 'sshd', 'addjournalmatch', '_SYSTEMD_UNIT=sshd.service', '+', '_COMM=sshd']
['set', 'sshd', 'addaction', 'firewallcmd-ipset']
['set', 'sshd', 'action', 'firewallcmd-ipset', 'actionban', 'ipset add fail2ban-<name> <ip> timeout <bantime> -exist']
['set', 'sshd', 'action', 'firewallcmd-ipset', 'actionstop', 'firewall-cmd --direct --remove-rule ipv4 filter <chain> 0 -p <protocol> -m multiport --dports <port> -m set --match-set fail2ban-<name> src -j <blocktype>\nipset flush fail2ban-<name>\nipset destroy fail2ban-<name>']
['set', 'sshd', 'action', 'firewallcmd-ipset', 'actionstart', 'ipset create fail2ban-<name> hash:ip timeout <bantime>\nfirewall-cmd --direct --add-rule ipv4 filter <chain> 0 -p <protocol> -m multiport --dports <port> -m set --match-set fail2ban-<name> src -j <blocktype>']
['set', 'sshd', 'action', 'firewallcmd-ipset', 'actionunban', 'ipset del fail2ban-<name> <ip> -exist']
['set', 'sshd', 'action', 'firewallcmd-ipset', 'iptables', 'iptables <lockingopt>']
['set', 'sshd', 'action', 'firewallcmd-ipset', 'known/chain', 'INPUT']
['set', 'sshd', 'action', 'firewallcmd-ipset', 'known/lockingopt', '-w']
['set', 'sshd', 'action', 'firewallcmd-ipset', 'protocol', 'tcp']
['set', 'sshd', 'action', 'firewallcmd-ipset', 'name', 'sshd']
['set', 'sshd', 'action', 'firewallcmd-ipset', 'chain', 'INPUT']
['set', 'sshd', 'action', 'firewallcmd-ipset', 'known/__name__', 'Init']
['set', 'sshd', 'action', 'firewallcmd-ipset', 'known/protocol', 'tcp']
['set', 'sshd', 'action', 'firewallcmd-ipset', 'known/port', 'ssh']
['set', 'sshd', 'action', 'firewallcmd-ipset', 'known/returntype', 'RETURN']
['set', 'sshd', 'action', 'firewallcmd-ipset', 'known/iptables', 'iptables <lockingopt>']
['set', 'sshd', 'action', 'firewallcmd-ipset', 'lockingopt', '-w']
['set', 'sshd', 'action', 'firewallcmd-ipset', 'known/name', 'default']
['set', 'sshd', 'action', 'firewallcmd-ipset', 'known/blocktype', 'REJECT --reject-with icmp-port-unreachable']
['set', 'sshd', 'action', 'firewallcmd-ipset', 'returntype', 'RETURN']
['set', 'sshd', 'action', 'firewallcmd-ipset', 'blocktype', 'REJECT --reject-with icmp-port-unreachable']
['set', 'sshd', 'action', 'firewallcmd-ipset', 'port', 'ssh']
['set', 'sshd', 'action', 'firewallcmd-ipset', 'bantime', '86400']
['start', 'sshd']

可以看到我们前面的设置已经生效。

检测规则

执行

1
fail2ban-client status

输出:

1
2
3
Status
|- Number of jail: 1
`- Jail list: sshd

sshd规则已经启用。

添加fail2ban并启动

1
2
systemctl enable fail2ban
systemctl start fail2ban

检查被阻止的IP

执行:

1
tail -f /var/log/fail2ban.log

输出:

1
2
3
4
5
6
7
8
9
10
2015-12-10 11:54:40,693 fail2ban.actions        [12313]: NOTICE  [sshd] Ban 194.63.140.69
2015-12-10 11:54:40,702 fail2ban.actions [12313]: NOTICE [sshd] Ban 213.199.193.27
2015-12-10 11:54:40,712 fail2ban.actions [12313]: NOTICE [sshd] Ban 43.229.53.63
2015-12-10 11:54:40,745 fail2ban.actions [12313]: NOTICE [sshd] 113.195.134.231 already banned
2015-12-10 11:54:40,834 fail2ban.filter [12313]: INFO [sshd] Found 213.199.193.27
2015-12-10 11:54:40,847 fail2ban.filter [12313]: WARNING Determined IP using DNS Lookup: 213-199-193-27.tktelekom.pl = ['213.199.193.27']
2015-12-10 11:54:40,848 fail2ban.filter [12313]: INFO [sshd] Found 213.199.193.27
2015-12-10 11:54:41,746 fail2ban.actions [12313]: NOTICE [sshd] 213.199.193.27 already banned
2015-12-10 11:54:42,748 fail2ban.actions [12313]: NOTICE [sshd] 194.63.140.69 already banned
2015-12-10 11:54:42,778 fail2ban.filter [12313]: INFO [sshd] Found 213.199.193.27

坏蛋们都被关到监狱里面了~