2007年10月25日 星期四

[postfix procmail spamassassin]搞定垃圾郵件過濾最終解決方案

搞了一個禮拜的東西,記一下,做個紀念!

遇到的問題:

  1. amavisd-new 在當時無法從套件庫安裝。 解決方法:考慮大量相依性問題 ( 可能還有缺少的很多套件 ) ,放棄使用。
  2. procmail 必需能搭配郵件目錄使用 Maildir/ 格式,而非 mbox 檔案格式。 解決方法:見前一篇「 [postfix procmail Maildir]procmail 與 Maildir 信箱格式的搭配」。
  3. 有人很少 ( 或根本 ) 不收信,家目錄的 quota 用完後,無法收信會讓 spamd / spamc 的執行環境錯亂無法過濾垃圾郵件。 本篇目的就是解決這個問題。

使用 procmail 替代直接遞送 mail box ,是造成上述問題的原因。如果是由 postfix 遞送郵件到收件人信箱,無法遞送時 ( 如我遇到的收件者信箱 quota exceeded 問題 ) 會由 postfix 退信。但是如果是由 promail 遞送到收件者信箱, postfix 把信交給 procmail 時,就算完工了,而 procmail 則是無法退信 ( 註1 ) ,於是送信到預設的 mbox 信箱去了。

我決定採用 Postfix After-Queue Content Filter 裡的 Simple content filter ,讓 procmail 做為 mail filter ( 註2 ) ,將郵件 pipe 給 spamc 過濾加標籤,再 pipe 給 sendmail ,讓郵件重回 postfix 的 mail queue ,讓 postfix 做最後的遞送到收件人信箱。如此,就可以解決收件人信箱 quota exceeded 的問題了。

以下是各項設定:

/etc/postfix/master.cf

# 修改這一行 ( 加入 content-filter ): smtp inet n - n - - smtpd -o content_filter=procmail:filter # 加入這一行: procmail unix - n n - - pipe flags=R user=filter argv=/usr/bin/procmail -t -m /etc/procmailrc ${sender} ${recipient}

/etc/postfix/main.cf

不用 mailbox_command 來使用 procmail 。 postconf -e mailbox_command=

/etc/procmailrc

# log 檔路徑 LOGFILE=/var/log/procmail.log SENDER=$1 SHIFT=1 # 將信件轉給 spmac 過濾並加標籤 :0 hbfw | /usr/local/bin/spamc # 將已過濾加標籤的信送回給 smtp :0 | /usr/sbin/sendmail -i -f "$SENDER" -- "$@"

建立使用者 filter

不允許登入,要有 shell 及家目錄,因為 spamassassin 會把設定與資料寫在 /home/filter/.spamassassin/ 裡。

useradd -d /home/filter -s /bin/sh filter

建立 log 檔, owner 為 filter ,procmail 才能寫入。

touch /var/log/procmail.log chown filter.filter /var/log/procmail.log

重新載入 postfix 設定,信件重新排入 mail queue 。

postsuper -r ALL postfix reload

順利的話,到這裡應該已經開始過濾垃圾信了。因為使用的是 Mandriva ,安全等級為 high ,所以還要再做一些後續設定。

/var/log/procmail.log 的 owner 問題:

Mandriva 的安全性程式 msec 會定時把 /var/log/procmail.log 的 owner 改為 root.root ,但是 procmail 是用 filter 帳號的身份執行,會造成無法寫入 log 檔。處理方法如下:

vi /etc/security/msec/perm.local /var/log/procmail.log filter.filter 0640

最後, /var/log/procmail.log 要定期維護,以免長太大佔用太多硬碟空間。這裡使用 logrotate 來維護 procmal.log 。

建立 /etc/logrotate.d/procmail /var/log/procmail.log { create 0640 filter filter weekly size=10M rotate 5 compress }

搞定!最近幾篇就是這一週來的紀念了。

註1: procmail 應該是可以 pipe 給 sendmail 做退信的動作,但是效率上應該差很多。

註2: 一般用 simple content filter 是建一個 filter.sh ,在 script 裡做 procmail + spamassassin ,再 sendmail 。我是搜尋到下面這兩篇,提供參考設定,直接使用 procmail 就行了。

3 則留言:

  1. Hello Less:
    可否指導一下,當我用這方式要把垃圾信直接在Server上刪除時,要如何做呢?感謝

    回覆刪除
  2. Less ?那是誰啊? XD

    要直接在 server 上刪除的話,可以在 procmailrc 裡面,加一條判斷,把加註 spam 記號的信直接丟掉,沒有加註的,則按原規則回傳給 smtpd 。怎麼寫?對不起,太久沒玩,請自己試試囉。

    如果你是網管的話,給你個良心的建議,千萬別這麼做。有些 spam 是 user 自己訂閱的,你把他刪了,他會來找你算帳。

    另外,雖然 spamassassin 過濾 spam 還算蠻準確,難保什麼時候會誤判。若是重要的信件被誤判,直接刪了,還是有人會找你算帳。

    幫 user 判斷 spam ,不要幫 user 刪 spam 。把權利還給 user 吧。

    回覆刪除
  3. Dear lss,
    現在我的 user mail 是放在 user home 底下,但退信會被「預設」退到 /var/mail
    這應該是同您所說的問題

    想請教的是,如果想解決此問題,是不是只需要將
    smtp inet n - n - - smtpd
    改成
    smtp inet n - n - - smtpd -o content_filter=procmail:filter
    並加入這一行
    procmail unix - n n - - pipe flags=R user=filter argv=/usr/bin/procmail -t -m /etc/procmailrc ${sender} ${recipient}
    就ok了?

    Best Regards,
    Jerry

    回覆刪除