用 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 ? 可以交流一下

return top

%d 位部落客按了讚: