SASL + PAM 無法紀錄 rhost 以配合 fail2ban 的解法

如果cnetos5系統使用 saslauthd + PAM + sendmail 時, 當遠端使用 sasl 認證發生錯誤時相關紀錄檔並不會紀錄遠端的 ip 位址

/var/log/messages

Jan 26 07:14:12 fedora saslauthd[27264]: do_auth         : auth failure: [user=user1] [service=smtp] [realm=] [mech=pam] [reason=PAM auth error]
Jan 26 07:14:18 fedora saslauthd[27267]: do_auth         : auth failure: [user=user1] [service=smtp] [realm=] [mech=pam] [reason=PAM auth error]
Jan 26 07:14:22 fedora saslauthd[27262]: do_auth         : auth failure: [user=user1] [service=smtp] [realm=] [mech=pam] [reason=PAM auth error]
Jan 26 07:14:26 fedora saslauthd[27265]: do_auth         : auth failure: [user=user1] [service=smtp] [realm=] [mech=pam] [reason=PAM auth error]
Jan 26 07:14:32 fedora saslauthd[27267]: do_auth         : auth failure: [user=user1] [service=smtp] [realm=] [mech=pam] [reason=PAM auth error]

/var/log/maillog

Jan 26 07:14:13 fedora sendmail[29536]: s0PNE8Zh029536: [78.93.245.133] did not issue MAIL/EXPN/VRFY/ETRN during connection to MTA
Jan 26 07:14:18 fedora sendmail[29537]: s0PNED8R029537: [78.93.245.133] did not issue MAIL/EXPN/VRFY/ETRN during connection to MTA
Jan 26 07:14:23 fedora sendmail[29538]: s0PNEItR029538: [78.93.245.133] did not issue MAIL/EXPN/VRFY/ETRN during connection to MTA
Jan 26 07:14:28 fedora sendmail[29539]: s0PNENjN029539: [78.93.245.133] did not issue MAIL/EXPN/VRFY/ETRN during connection to MTA
Jan 26 07:14:32 fedora sendmail[29540]: s0PNESYI029540: [78.93.245.133] did not issue MAIL/EXPN/VRFY/ETRN during connection to MTA

/var/log/secure

Jan 26 07:14:10 fedora saslauthd[27264]: pam_unix(smtp:auth): check pass; user unknown
Jan 26 07:14:10 fedora saslauthd[27264]: pam_unix(smtp:auth): authentication failure; logname= uid=0 euid=0 tty= ruser= rhost=
Jan 26 07:14:10 fedora saslauthd[27264]: pam_succeed_if(smtp:auth): error retrieving information about user chi
Jan 26 07:14:15 fedora saslauthd[27267]: pam_unix(smtp:auth): check pass; user unknown
Jan 26 07:14:15 fedora saslauthd[27267]: pam_unix(smtp:auth): authentication failure; logname= uid=0 euid=0 tty= ruser= rhost=
Jan 26 07:14:15 fedora saslauthd[27267]: pam_succeed_if(smtp:auth): error retrieving information about user chi
Jan 26 07:14:21 fedora saslauthd[27262]: pam_unix(smtp:auth): check pass; user unknown
Jan 26 07:14:21 fedora saslauthd[27262]: pam_unix(smtp:auth): authentication failure; logname= uid=0 euid=0 tty= ruser= rhost=
Jan 26 07:14:21 fedora saslauthd[27262]: pam_succeed_if(smtp:auth): error retrieving information about user chi
Jan 26 07:14:25 fedora saslauthd[27265]: pam_unix(smtp:auth): check pass; user unknown
Jan 26 07:14:25 fedora saslauthd[27265]: pam_unix(smtp:auth): authentication failure; logname= uid=0 euid=0 tty= ruser= rhost=
Jan 26 07:14:25 fedora saslauthd[27265]: pam_succeed_if(smtp:auth): error retrieving information about user chi
Jan 26 07:14:30 fedora saslauthd[27267]: pam_unix(smtp:auth): check pass; user unknown
Jan 26 07:14:30 fedora saslauthd[27267]: pam_unix(smtp:auth): authentication failure; logname= uid=0 euid=0 tty= ruser= rhost=
Jan 26 07:14:30 fedora saslauthd[27267]: pam_succeed_if(smtp:auth): error retrieving information about user chi

主要原因是因為 cyrus-sasl 當初設計只紀錄四個欄位不包含遠端 ip , 網路上有 patch 可以增加 rhost 欄 , 但是因為它會影響其他軟體目前並未被納入正式的 package. 相關資訊可以參考以下討論串
https://bugzilla.cyrusimap.org/show_bug.cgi?id=3468
https://bugzilla.redhat.com/show_bug.cgi?id=683797

rhost 為空值的話 fail2ban 就無法阻擋 smtp-auth 密碼猜測的攻擊. 測試版的 fail2ban 0.9 增加了一樣令人興奮的功能 , 可以在過濾器裡進行多行比對!!如此一來只要增加 sendmail 的 log level (預設為 9) , 就可以看出遠端 ip 及認證錯誤的關聯性再利用 fail2ban 加以阻擋.

首先修改 sendmail.mc 檔, 變更以下行

dnl define(`confLOG_LEVEL’, `9′)dnl

改為

define(`confLOG_LEVEL’, `10‘)dnl

執行指令後並重新啟動 sendmail

[root@mailhost /]# m4 /etc/mail/senmail.mc > /etc/mail/sendmail.cf
[root@mailhost /]# service sendmail restart

此時檢視 /var/log/maillog 會發現 sasl 認證錯誤時訊息如下

Jan 26 19:30:01 fedora sendmail[2370]: NOQUEUE: connect from 223.59.18.218.broad.sz.gd.dynamic.163data.com.cn [218.18.59.223] (may be forged)
Jan 26 19:30:05 fedora sendmail[2370]: s0QBU1Ir002370: AUTH failure (LOGIN): authentication failure (-13) SASL(-13): authentication failure: checkpass failed
Jan 26 19:30:06 fedora sendmail[2370]: s0QBU1Ir002370: 223.59.18.218.broad.sz.gd.dynamic.163data.com.cn [218.18.59.223] (may be forged) did not issue MAIL/EXPN/VRFY/ETRN during connection to MTA

這時紀錄了 pid 及 mail ID 及驗證錯誤相關訊息 . 原來的 Log Level 只會紀錄最後一行, 但是該行錯誤在某些為了快速發信的軟體或者電子報等的不嚴謹的軟體連接伺服器時都可能發生, 因此光靠該行無法明確判斷是否為垃圾郵件. 現在在本例中我們可以確認它是在使用PLAIN TEXT驗證後才發生該錯誤 . 注意在繁忙的 server 中 ,該錯誤並不一定會連在一起, 因為server同時會處理其他服務如dovecot , 所以我們該使用 pid 或者 mail ID 來關聯這些錯誤.

接下來就是在 fail2ban 的 git 下載 0.9 版並安裝(略)
https://github.com/fail2ban/fail2ban/tarball/0.9

0.9版設定上有些差異 , 說明有提到盡量將各別設定或者自訂部份放在 /etc/fail2ban/jail.local 或者 /etc/fail2ban/jail.d 下

/etc/fail2ban/fail2ban.conf

[Definition]
loglevel = 3
logtarget = /var/log/fail2ban.log #個人比較喜歡紀錄在個別檔案中(預設值 SYSLOG)
socket = /var/run/fail2ban/fail2ban.sock
pidfile = /var/run/fail2ban/fail2ban.pid

/etc/fail2ban/jail.conf  這邊只列一些預設項目和重要設定, logpath部份注意一下, 當然也可以在jail.d下面覆蓋預設值.其他要新增的設定我們會加到/etc/fail2ban/jail.d/local.conf

[DEFAULT]
ignoreip = 127.0.0.1/8 10.0.18.0/24 10.160.8.0/23 #內部 ip 不阻擋
ignorecommand =
bantime  = 1200 #擋20分鐘
findtime  = 600
maxretry = 5 #出現五次紀錄即觸發
backend = auto
usedns = warn
logencoding = auto
enabled = false #預設不啟用任何服務 要啟用各別服務請在 jail.d下設定
filter = %(__name__)s
destemail = root@localhost
sender = root@localhost
mta = sendmail
protocol = tcp
chain = INPUT
port = 0:65535
banaction = iptables-multiport
action_ = %(banaction)s[name=%(__name__)s, port=”%(port)s”, protocol=”%(protocol)s”, chain=”%(chain)s”]
action_mw = %(banaction)s[name=%(__name__)s, port=”%(port)s”, protocol=”%(protocol)s”, chain=”%(chain)s”]
%(mta)s-whois[name=%(__name__)s, dest=”%(destemail)s”, protocol=”%(protocol)s”, chain=”%(chain)s”]
action_mwl = %(banaction)s[name=%(__name__)s, port=”%(port)s”, protocol=”%(protocol)s”, chain=”%(chain)s”]
%(mta)s-whois-lines[name=%(__name__)s, dest=”%(destemail)s”, logpath=%(logpath)s, chain=”%(chain)s”]
action_xarf = %(banaction)s[name=%(__name__)s, port=”%(port)s”, protocol=”%(protocol)s”, chain=”%(chain)s”]
xarf-login-attack[service=%(__name__)s, sender=”%(sender)s”, logpath=%(logpath)s, port=”%(port)s”]
action_blocklist_de  = blocklist_de[email=”%(sender)s”, service=%(filter)s, apikey=”%(blocklist_de_apikey)s”]
action = %(action_)s
[sshd]
port    = ssh
logpath = /var/log/secure
[sshd-ddos]
port    = ssh
logpath = /var/log/secure
[dovecot]
port    = pop3,pop3s,imap,imaps,submission,465,sieve
logpath = /var/log/maillog
[dovecot-auth]
filter  = dovecot
port    = pop3,pop3s,imap,imaps,submission,465,sieve
logpath = /var/log/secure

新增我們的過濾規則 /etc/fail2ban/filter.d/sendmail-sasl.conf

[Definition]
#比對規則 msgid 為多行比對中的關聯值 也就是mail ID
failregex = sendmail.*: (?P<msgid>[^:]+): AUTH failure.*\n(?:.*\n)*?.+ sendmail.*: (?P=msgid): .*\[<HOST>\] .*to MTA
ignoreregex =
[Init]
#設定LOG一次讀取到buffer的行數, 如果sever很忙碌導致符合的行中間插入很多其它的log , 你可以增加buffer行數值
maxlines = 10

啟用我們要檢查的服務 /etc/fail2ban/jail.d/local.conf

[DEFAULT]
[sshd]
enabled  = true
filter   = sshd
action   = iptables-allports[name=FTP, port=ftp, protocol=tcp]
logpath  = /var/log/secure
[vsftpd]
enabled  = true
filter   = vsftpd
action   = iptables-allports[name=FTP, port=ftp, protocol=tcp]
logpath  = /var/log/secure
[sendmail]
enabled  = true
filter   = sendmail
action   = iptables-allports[name=SENDMAIL, port=smtp, protocol=tcp]
logpath  = /var/log/maillog
[dovecot]
enabled  = true
filter   = dovecot
action   = iptables-allports[name=DOVECOT, port=”pop3,pop3s,imap,imaps”, protocol=tcp]
logpath  = /var/log/maillog
[dovecot-auth]
enabled  = true
filter  = dovecot
action   = iptables-allports[name=DOVECOT, port=”pop3,pop3s,imap,imaps”, protocol=tcp]
logpath = /var/log/secure
[sendmail-sasl]
enabled  = true
filter   = sendmail-sasl
action   = iptables-allports[name=SENDMAIL, port=smtp, protocol=tcp]
logpath  = /var/log/maillog

開始測試過濾規則 , 由於繁忙的server maillog 相當大 , 建議先複製小部份到測試用的檔案

[root@mailhost /]# fail2ban-regex /tmp/test.log .conf /etc/fail2ban/filter.d/sendmail-sasl.conf

若有符合的結果則顯示如下

Running tests
=============
Use   failregex file : sendmail-sasl.conf
Use         maxlines : 10
Use         log file : test.log
Use         encoding : UTF-8
Results
=======
Failregex: 21 total
|-  #) [# of hits] regular expression
|   1) [21] sendmail.*: (?P<msgid>[^:]+): AUTH failure.*\n(?:.*\n)*?.+ sendmail.*: (?P=msgid): .*\[<HOST>\] .*to MTA
`-
Ignoreregex: 0 total
Date template hits:
|- [# of hits] date format
|  [102] MON Day 24hour:Minute:Second
`-
Lines: 102 lines, 0 ignored, 42 matched, 60 missed
Missed line(s):: too many to print.  Use –print-all-missed to print all 60 lines

最後啟動 fail2ban 服務

[root@mailhost /]# service fail2ban start

接下來就是觀察/var/log/fail2ban.log , 看看是否有 BAN 掉惡意的 ip 來源囉