用 Fail2Ban 防范暴力破解 (SSH、vsftp、dovecot、sendmail)

Fail2Ban 可以用来防护 Linux Server 上的 SSH、vsftp、dovecot...等服务免于遭骇客使用暴力密码入侵。我以前曾写过即时封锁想要入侵 SSH 的程式,不过 Fail2Ban 厉害多了,也完全可以取代我写的程式。

安装 Fail2Ban

安装前可以先用下列指令来查看可安装的版本:

yum info fail2ban

像我的系统 (CentOS 5.x) 查出来有两个版本: 0.8.14 与 0.6.0,来自不同的套件库,但默认却安装 0.6.0,所以我必须要指定安装的版本为 0.8.14,以下的说明也是针对 0.8.*

安装 Fail2Ban:

yum install fail2ban

yum install fail2ban-版本

启动 Fail2Ban:

service fail2ban start
chkconfig fail2ban on

设定档

/etc/fail2ban/fail2ban.conf

搜寻:

logtarget = SYSLOG

改为:

logtarget = /var/log/fail2ban.log

(这是指定 fail2ban 的记录档位置,如果这个档案没有设定好,会在终端机跳出要记录的讯息)

/etc/fail2ban/jail.conf

这个设定档是 Fail2Ban 的重点,它是以 [名称] 的方式来定义每个 Profile,而 [DEFAULT] 这个 Profile 是代表所有 Profile 的默认值。

Fail2Ban 默认只启用 SSH 的防护,下面我们要将 vsftpd 与 dovecot 的防护也打开,并做一些修改。所有参数的名称都是通用的,你可以依照你的需求做修改。

[DEFAULT]
 ignoreip = 127.0.0.1/8 192.168.1.0/24 # 忽略 IP 的清单,以空白区隔不同 IP
 bantime  = 600 # 封锁的时间,单位:秒,600=10分钟,改为 -1 表示“永久”封锁
 findtime = 600 # 在多久的时间内,单位:秒,600=10分钟
 maxretry = 3 # 登入失败几次封锁
[ssh-iptables]
 enabled  = true # 启用 SSH
 filter   = sshd
 action   = iptables[name=SSH, port=ssh, protocol=tcp]
            sendmail-whois[name=SSH, dest=收件者 EMail, sender=显示的寄件者 EMail]
 logpath  = /var/log/secure # Log 档的位置
 maxretry = 10 # 登入失败几次封锁
 bantime  = 14400 # 封锁的时间,单位:秒,14400=4小时
[vsftpd-iptables]
 enabled  = true # 改为 true 以启用 vsftpd
 filter   = vsftpd
 action   = iptables[name=VSFTPD, port=ftp, protocol=tcp]
            sendmail-whois[name=VSFTPD, dest=收件者 EMail, sender=显示的寄件者 EMail]
 logpath  = /var/log/secure # Log 档的位置 (log 档的位置与 ssh 相同)
 maxretry = 10 # 登入失败几次封锁
 bantime  = 3600 # 封锁的时间,单位:秒,3600=1小时
[dovecot]
 enabled  = true # 改为 true 以启用 dovecot
 filter   = dovecot
 action   = iptables-multiport[name=dovecot, port="pop3,pop3s,imap,imaps,smtp,smtps,submission,sieve", protocol=tcp]
            sendmail-whois[name=dovecot, dest=收件者 EMail, sender=显示的寄件者 EMail]
 logpath  = /var/log/secure # Log 档的位置 (log 档的位置与 ssh 相同)
 maxretry = 10 # 登入失败几次封锁
 bantime  = 3600 # 封锁的时间,单位:秒,3600=1小时

dest=收件者 EMail 是指当有 IP 被封锁时所要通知的对象。可以改为“root”,或全部的 sendmail-whois 这一整行都删掉不做设定也可以,之后只要用 fail2ban-client 或 iptables 指令也可以查看封锁的结果。

请注意:“action =”后面“iptables”与“iptables-multiport”是有差别的,如果要同时封锁多个 port 就要写“iptables-multiport”。

Fail2Ban 相关指令

查看 Fail2Ban 的执行状态

$ fail2ban-client status
 Status
 |- Number of jail:  3
 `- Jail list:       ssh-iptables, vsftpd-iptables, dovecot

查看设定档的执行状态

$ fail2ban-client status ssh-iptables
 Status for the jail: ssh-iptables
 |- filter
 | |- File list:         /var/log/secure
 | |- Currently failed:  0
 | `- Total failed:      10
 `- action
    |- Currently banned: 1
    |  `- IP list:       43.229.53.63
    `- Total banned:     1
$ fail2ban-client status vsftpd-iptables
 Status for the jail: vsftpd-iptables
 |- filter
 | |- File list:         /var/log/secure
 | |- Currently failed:  1
 | `- Total failed:      6
 `- action
    |- Currently banned: 1
    |  `- IP list:       43.229.53.63
    `- Total banned:     1

查看防火墙的设定

$ iptables -n -L INPUT | grep fail2ban
 fail2ban-dovecot tcp -- 0.0.0.0/0  0.0.0.0/0  multiport dports 110,995,143,993,25,465,587,2000 
 fail2ban-SSH     tcp -- 0.0.0.0/0  0.0.0.0/0  tcp dpt:22 
 fail2ban-VSFTPD  tcp -- 0.0.0.0/0  0.0.0.0/0  tcp dpt:21

从防火墙查看有哪些 IP 被封锁

$ iptables --list
 ...
 Chain fail2ban-SSH (1 references)
 target     prot opt source        destination 
 REJECT     all  --  43.229.53.63  anywhere     reject-with icmp-port-unreachable
 RETURN     all  --  anywhere      anywhere

 Chain fail2ban-VSFTPD (1 references)
 target     prot opt source        destination
 REJECT     all  --  43.229.53.63  anywhere     reject-with icmp-port-unreachable
 RETURN     all  --  anywhere      anywhere

 Chain fail2ban-dovecot (1 references)
 target     prot opt source        destination
 RETURN     all  --  anywhere      anywhere

测试 Log 档

为什么要测试 Log 档呢? Log 档跟 jail.conf 里的 logpath 参数有关,由于 Linux 的发行版众多,你得确定你要让 Fail2Ban 扫描的 Log 档是正确的,不然就等于做了白工!!

你可以先用下列的指令来测试 Log 档:

fail2ban-regex log 档 筛选规则档

Log 档对应“logpath”参数,筛选规则档对应“filter”参数。

范例:

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

以 vsftpd 为例,Fail2Ban 默认 vsftpd 的 Log 档是 /var/log/xferlog,但实际测试之后,必须要用 /var/log/secure 才对:

$ fail2ban-regex /var/log/secure /etc/fail2ban/filter.d/vsftpd.conf
 Running tests
 =============
 Use regex file : /etc/fail2ban/filter.d/vsftpd.conf
 Use   log file : /var/log/secure
 Results
 =======
 ...
 Summary
 =======
 Addresses found:
 ...
 Date template hits:
 1150 hit(s): MONTH Day Hour:Minute:Second
 Success, the total number of match is 14
 However, look at the above section 'Running tests' which could contain important
 information.
$ fail2ban-regex /var/log/xferlog /etc/fail2ban/filter.d/vsftpd.conf
 Running tests
 =============
 Use regex file : /etc/fail2ban/filter.d/vsftpd.conf
 Use   log file : /var/log/xferlog
 Results
 =======
 Failregex:   0 total
 Ignoreregex: 0 total
 Summary
 =======
 Sorry, no match
 Look at the above section 'Running tests' which could contain important
 information.

sendmail

关于 sendmail 的防护,我试过 Fail2Ban 默认的两个规则档: sendmail-auth.conf 与 sendmail-reject.conf,如果以 fail2ban-regex 指令来检查 /var/log/maillog 或 /var/log/secure 的结果都是“no match”。最后是参考官方的 wiki 得到解决,解决方法如下:

1. 新增 /etc/fail2ban/filter.d/sendmail.conf,内容如下:

# Fail2Ban filter for sendmail authentication failures
#
# Source: http://www.the-art-of-web.com/system/fail2ban-sendmail/
# Contibutors: Gutza, the SASL regex
#
# $Revision: 0 $
#
[INCLUDES]

before = common.conf
[Definition]

_daemon = (?:sm-(mta|acceptingconnections))

failregex = \[<HOST>\] .*to MTA
# \[<HOST>\] \(may be forged\)
 \[<HOST>\], reject.*\.\.\. Relaying denied
 (User unknown)\n* \[<HOST>\]
 badlogin: .* \[<HOST>\] plaintext .* SASL

ignoreregex =

2. 测试看看:

$ fail2ban-regex /var/log/maillog /etc/fail2ban/filter.d/sendmail.conf
 Running tests
 =============
 Use regex file : /etc/fail2ban/filter.d/sendmail.conf
 Use   log file : /var/log/maillog
 Results
 =======
 ...
 Summary
 =======
 Addresses found:
 ...
 Date template hits:
 1135 hit(s): MONTH Day Hour:Minute:Second
 Success, the total number of match is 33
 However, look at the above section 'Running tests' which could contain important
 information.

3. 如果测试没问题就写入 jail.conf:

[sendmail]
 enabled  = true
 filter   = sendmail
 action   = iptables-multiport[name=sendmail, port="pop3,pop3s,imap,imaps,smtp,smtps,submission,sieve", protocol=tcp]
            sendmail-whois[name=sendmail, dest=收件者 EMail, sender=显示的寄件者 EMail]
 logpath  = /var/log/maillog # Log 档的位置
 maxretry = 10 # 登入失败几次封锁
 bantime  = 3600 # 封锁的时间,单位:秒,3600=1小时

这边可以看到,port 的定义跟原本 dovecot 的一样,都是跟邮件有关的 port。表示只要符合 sendmail 或 dovecot 的筛选器,就会封锁这些 port。

4. 重新启动 Fail2Ban:

service fail2ban restart

错误处理

查看 /var/log/fail2ban.log,如果发现类似这样的错误讯息:

ERROR   iptables -N fail2ban-sendmail
iptables -A fail2ban-sendmail -j RETURN
iptables -I INPUT -p tcp --dport submission,465,smtp -j fail2ban-sendmail returned 200

这表示你在 jail.conf 定义的 [sendmail] 里,它是要封锁多个 port,而参数必须是用“iptables-multiport”的地方你却只用了“iptables”,以致于该 Profile 在执行 iptables 指令时发生错误!!这个 Profile 的防火墙规则也不会正常启用。修正错误之后再重新启动 Fail2Ban 即可。

一开始我遇到这个错误没有太在意,以为是 Fail2Ban 的 Bug,我就干脆在每次启动 Fail2Ban 后新增一条规则:

$ iptables -I INPUT -p tcp --dport -j fail2ban-sendmail

这样倒也是可以正常执行,与 Fail2Ban 配合无误。不过最后知道问题了,我还是修正 jail.conf 错误。

另外,Fail2Ban 关于防火墙的指令是写在 /etc/fail2ban/action.d/iptables-allports.conf,有兴趣可以研究看看。

参考网页

    • @@
    • 12/06. 2015 3:23上午
    Using Mozilla Firefox Mozilla Firefox 42.0 on Windows Windows NT

    请问一下Fail2Ban 我设定mysql 好像不行
    网络上找了很多范例 都没办法
    开启/var/log/mysqld.log 里面 也没登入错误讯息

    版主可以帮我试试吗?

    • @@
    • 12/06. 2015 3:41上午
    Using Mozilla Firefox Mozilla Firefox 42.0 on Windows Windows NT

    我是这样设定还是不行

    打开Fail2Ban里面 mysqld-auth.conf 时候 文件里面说要在mysql设定档案 加入

    log-error=/var/log/fail2ban/mysqld.log
    log-warning = 2

    之后
    Fail2Ban设定如下

    [mysqld-iptables]

    enabled = true

    filter = mysqld-auth #对应/etc/fail2ban/filter.d/mysqld-auth.conf

    action = iptables[name=mysql, port=3306, protocol=tcp]

    sendmail-whois[name=MySQL, dest=你的电子邮件, sender=root]

    logpath = /var/log/mysqld.log

    maxretry = 5

    • Using Mozilla Firefox Mozilla Firefox 42.0 on Windows Windows NT

      我依照同样的方法测试也是不行,原因是 MySQL 5.x 并没有将登入失败的 log 写入 log-error 所指定的档案,即使将 log-warning 设为 2 也是一样!!
      这看起来是已知的 bug:
      * log_warnings doesn't seem to work for aborted connections in MySQL 5.1
      * dropped TCP connections not logged as errors but result in blocked host
      但似乎没有人要去解这 bug!!

      而正常状况下的我们希望的结果是这样:
      * Warning level in Error Log to see Aborted Connections

      或许你可以转换成 MariaDB 试试。

      另外,我如果在 my.cnf 里启用“通用 log”:

      log=/var/log/mysqld-access.log

      它有记录登入失败的 log,不过格式是:

      151206 12:32:46	     51 Connect     Access denied for user 'root'@'localhost' (using password: YES)

      如果你要使用此 log,必须自行改写 /etc/fail2ban/filter.d/mysqld-auth.conf 的比对规则。

      最后,如果你要查看你的 my.cnf 设定是否生效,可以在 MySQL 里下这个指令查询:

      SHOW GLOBAL VARIABLES LIKE '%log_%';
    • Using Mozilla Firefox Mozilla Firefox 42.0 on Windows Windows NT

      建议像 MySQL 这类的服务,没有必要的话最好不要对所有人开启。

      可以用白名单的方式指定只有某些特定 ip 可以存取,这样会比较安全。

    • @@
    • 12/09. 2015 12:48下午
    Using Mozilla Firefox Mozilla Firefox 42.0 on Windows Windows 7

    citypig 谢谢你

    因为我ip随时会变动

    对于webmin 跟ssh 都可以使用

    剩下mysql 不行

    虽然 fail2ban 帮我挡了很多事情 算是一个非常不错东西

    不过最好还是要把prot 改掉 防止机器人 一直换ip 暴力破解密码10000跟 22

    请问有line ? 可以交流一下

  1. 04/27. 2017
  2. 07/03. 2017
  3. 03/27. 2019

return top

%d 位部落客按了赞: