柒、郵件地址改寫機制 vs 相關設定檔
當 cleanup 模組進行郵件過濾之前,會先依據各種設定檔呼叫 rewrite 模組,進行郵件地址改寫,這樣做的好處是可以減少標頭欄位的變化,使得過濾快取(請參考 duplicate_filter_limit 的說明)能更有效率的工作。
郵件地址改寫的順序如下:
alias、canonical、virtual 等設定檔是為了達成某些特殊功能而設計的,底下說明這些設定檔的功能以及如何啟用它們:
別名對應
alias 是 postfix 最被廣泛使用的一項功能,除了用來對應虛擬信箱外,也可以運用在郵遞清單或郵件討論群組上面。請在 main.cf 中加入這一行,以便啟用 alias:
alias_maps = hash:/etc/aliases
如果您的系統僅支援 dbm 格式的別名,或是透過 NIS 伺服器查詢別名,請使用底下的參數:
alias_maps = dbm:/etc/aliases, nis:mail.aliases
postfix 檢查信件的收信人欄位,當發現收信人的網域名稱為本機網域時就會開始進行分信,分信之前會先檢查上述設定中的 aliases 別名檔,看看是否有定義虛擬信箱,所謂虛擬信箱就是指不是給使用者使用的信箱,這些信箱多半是有特殊用途,例如:系統管理用的、郵寄群組用的 ...... 等等。 也有人把 aliases 別名檔拿來作使用者全名的對應,例如: Shane.Lee 對應成 shane ,雖然這也是一種應用的方式,但按照 postfix 設計的原意,應該是使用 canonical_maps 去做這件事比較正確,兩者不同的地方在於: canonical_maps 在進行收信人欄位改寫時就直接處理了,不會等到分信時才處理,而且按照 aliases 的設計必須要能載入 include 、呼叫執行 script ,並且允許使用遞迴別名,這都會降低處理效能,如果只是單純要作全名對應使用 aliases 比較不划算!
當安裝 postfix 時系統會自動幫我們產生 aliases 別名檔,同時會把系統上的服務帳號對應給 root ,這是因為服務帳號是給應用程式使用的,當應用程式執行過程中遇到某些突發狀況時,或網路上的其他管理人員需要聯絡該應用程式的管理人時,有時候會寫信給這些帳號,透過 aliases 別名檔的作用,這些信件就會分到 root 的個人信箱以免沒人處理。但在實際環境中,為了避免 root 密碼在網路上傳輸遭到駭客竊取,不管是透過 outlook express 或是透過 web 介面,我們都不該去收取 root 的信件,而應該在 aliases 別名檔中將 root 的信件分給實際管理該機器的使用者,而且為了避免駭客查出誰是真正的管理員,這個檔案的權限應該設成 600 。預設別名檔的內容節錄如下:
mailer-daemon: postmaster postmaster: root # General redirections for pseudo accounts. bin: root daemon: root ============ 中間省略 =================== # trap decode to catch security attacks decode: root # Person who should get root's mail #root: marc <== 請去掉 Remark 並改成自己的帳號 |
aliases 除了用來將虛擬信箱對應給真實的帳號外,還可以將信件儲存在備份檔案內,這樣做的目的是希望信件被收走後,能留一份在伺服器上備查,例如我們可以把上例解說過的那一行改為:
root: shane,/var/log/backup-mail
除此之外, aliases 也可以用來轉寄信件,例如下面的設定會將信件轉寄出去,以便確定 shane 一定收得到:
root: shane,shane@ms8.hinet.net,shane@tmtc.edu.tw,shane@tp.edu.tw
當要轉寄的信箱很多時,全部寫成一行還真是困難,譬如想寄同一封信給全校所有老師,但不想一個一個輸入收信人地址,透過 aliases 的幫助,我們只需要建立一個 teachers 虛擬信箱,接著準備一個空的純文字檔,把全校老師的信箱地址打進去,一個地址一行,最後得留一行空白行。檔案做好後,我們就可以將別名設定改成:
teachers: ":include:/etc/mail/all_teachers.txt"
利用這個方式,想同時寄信給一群人再容易不過了。但是,當郵寄群組很多而且成員相互重疊時,想要維護郵寄清單的正確性就會很痛苦,好比除了全校教師外,我們另外還有各學年教師、科任教師、行政人員、主任等多個清單,學期末老師退休或學期初新進同仁加入,這麼多清單要同時檢查修改不能遺漏,這工作可累了!還好 aliases 提供了遞迴參照的功能,讓我們可以將清單分批建立,並以參照方式建立聯集,工作就輕鬆多了,例如:
headship: lee (校長)
director: suelan,wang,............ (主任)
manager: maggy,young,.......... (組長)
grade1: jack,mary,helen,........ (一年級老師)
grade2: vicky,johnny,,,,,,,...... (二年級老師)
.......................................................... (省略)
course: sean,marc,................. (科任)
administer: headship,director,manager (行政人員)
teachers: administer,grade1,grade2,grade3,grade4,grade5,grade6,course (全校老師)
在更複雜的應用中, aliases 還可以結合外掛的程式提供更進階的服務,例如:郵件訂閱、自動回信系統( auto reply )、討論群組( mailing list ) ...... 等。例如:
check: "| perl /usr/libexec/subscribe.cgi"
如果您想建立討論群組但不想花精神維護它,建議您安裝 smart list ,這個套件雖然陽春但是非常簡易好用,它包含:信件訂閱、取消訂閱、討論文件索引備分、查詢討論清單與內容、自動清除遞送有問題之訂閱者 ...... 等等。如果您想讓使用者都能建立自己的討論群組, majordomo 是第一選擇,這個軟體不但使用者眾多,相關統計分析工具也已經開發得很完善,這些套件在 rpm 安裝時會自動修改 aliases 組態,需要手動修改的情況不多,因此不在此討論。
設定好 aliases 之後,必須以 postalias 指令來雜湊該檔案以利 postfix 讀取應用,由於 aliases 是隨用隨讀,因此並不需要重新啟動 sendmail 伺服器,它會立即生效。
全名對應
這個設定檔用來建立使用者全名與帳號的關係,例如:
shane@mail.syups.tp.edu.tw shane.lee@mail.syups.tp.edu.tw
如果網域名稱,已經設定在 $myorigin、$mydestination 或 $inet_interfaces 中就可以省略不寫,直接使用底下的語法:
shane shane.lee
此外這個設定檔還有一個用途,就是當網域遷移時,可以將信件對應到新的網域名稱,例如:
@mail.syups.tp.edu.tw @tp.edu.tw
當本機是 mail gateway 時,透過底下的設定可以得知哪些使用者是位於哪一台郵件主機上,分信時會分給該主機,而非分到本機的 /var/spool/mail 中:
shane @stu.syups.tp.edu.tw(帳號相同時)
shane s60101@stu.syups.tp.edu.tw(帳號不同時)
當設定檔輸入完成後,必須先將它雜湊成資料庫檔,以 btree 為例(與 sendmail 相容,但效能較差,建議改用 hash):
postmap btree:/etc/postfix/canonical (檔名可隨個人喜好更改)
接著在 main.cf 中加入底下這一行:
canonical_maps = btree:/etc/postfix/canonical
如果只想對應收信人欄位則將該行,取代成:
recipient_canonical_maps = hash:/etc/postfix/recipient_canonical
如果只想對應寄信人欄位則將該行,取代成:
sender_canonical_maps = hash:/etc/postfix/sender_canonical
虛擬對應
虛擬對應僅能作用在信封裡的收信人欄位,而不會去改寫郵件標頭,與全名對應相比較,虛擬對應的功能只能算是半套。虛擬對應一般應用在兩種場合:一、將收信人欄位中的全名改成帳號名稱,二、虛擬網域對應。 想啟用虛擬對應,請在 main.cf 中加入底下這一行:
virtual_maps = btree:/etc/postfix/virtual
至於虛擬對應的設定方式與全名對應相同,請自行參考前面小節的介紹。
使用者遷移
當使用者已經不再使用此信箱,而改用其它伺服器提供的信箱時,並無法通知所有的親朋好友,因此仍然會有不知情的寄信人寄信過來,這些郵件到底該如何處理呢?
首先使用者可以在自己的家目錄裡,建立 .forward 檔透過這個檔案將郵件轉寄到新的信箱,管理員也可以透過 alias別名對應幫該名使用者轉信。雖然這樣做很人性化,但也有兩個缺點:一、轉信會增加 postfix 處理郵件的負擔,導致效能降低,二、親朋好友並不知道要把信寄去哪裡才對,所以不斷地麻煩我們!
另一種處理的方法是不要替已經搬走的使用者轉信,而直接告訴對方該寄去哪裡才對,如果管理員也不清楚新的郵件地址,直接告訴對方不要再寄信過來也可以,使用這個功能請在 main.cf 加入:
relocated_maps = hash:/etc/postfix/relocated
/etc/postfix/relocated 的設定範例如下:
shane 使用者 shane 已經不再使用此信箱了,請將信寄到 tp.edu.tw 主機,新帳號是 sean!
在提示訊息中,我們不使用 @ 符號(sean@tp.edu.tw)是為了避免被信箱收集者賣給廣告商。
郵件繞送路由
transport_maps 允許我們直接將符合條件的郵件,透過特定的方式,傳送到特定的主機,而不需要依靠 DNS MX 紀錄,譬如前面已經介紹過的延遲傳送機制外(給撥接用戶使用的),要啟用 transport 功能,請在 main.cf 加入:
transport_maps = hash:/etc/postfix/transport
底下是 transport 設定檔的應用範例,意思是要將寄給 @syups.tp.edu.tw 網域的信件,傳送到 172.16.1.6 這台主機的 8025 port:
syups.tp.edu.tw smtp:[172.16.1.6]:8025
應用場合
優秀的管理員明白各種設定檔各有職司,就算功能可以互相取代,也不應該混合著用,例如:用全名對應機制作別名對應,用別名對應機制作虛擬對應......這樣作恐怕沒有人可以釐清其邏輯關係,將來要如何維護呢?
到底什麼情況下要用哪一種機制來實作呢?筆者給大家的建議是:
將寄信人帳號對應成全名 | sender_canonical_maps = hash:/etc/postfix/sender_fullname |
將收信人全名對應成帳號 | virtual_maps = hash:/etc/postfix/recipient_loginname |
網域名稱遷移 | canonical_maps = hash:/etc/postfix/domain_canonical |
使用者遷移 | relocated_maps = hash:/etc/postfix/relocated |
將寄給本機帳號的信件分到其它伺服器 | canonical_maps = hash:/etc/postfix/individual_user |
將寄給虛擬網域的郵件轉給真實存在的網域 | virtual_maps = hash:/etc/postfix/virtual_domain |
讓使用者登入後能改用虛擬信箱寄信 | smtpd_sender_login_maps = hash:/etc/postfix/unaliases |
將寄給虛擬信箱的郵件轉給真實存在的使用者 | alias_maps = hash:/etc/aliases |
將郵件導向某台郵件過濾或掃毒主機 | transport_maps = hash:/etc/postfix/transport |
捌、SpamAssassin
SpamAssassin 是一套用來協助過濾垃圾郵件的程式,它會針對信件中特定的比對樣式給予不同的分數,當分數超過指定的值後,該封郵件就會被當作垃圾郵件處理,處理方式依據設定的不同,會在信件標頭或郵件主旨欄位加入警告訊息。
SpamAssassin 必須結合 MTA 來使用,單獨執行並不能發揮其功效,由於該程式是使用 perl 語言開發,因此如果剛開始安裝 Linux作業系統時沒有一併安裝 perl,事後要補裝有一點小麻煩(非 Fedora 用戶可以先安裝 CPAN 程序以便透用它簡化安裝:perl -MCPAN -e shell、install Mail::SpamAssassin)Fedora 用戶請直接利用 yum 指令安裝:
yum install spamassassin
安裝好之後,請以下列指令啟動 spamd:
service spamassassin start
並將該服務設定為開機自動執行:
chkconfig --level 3,5 spamassassin on
請用底下指令,測試程式能否成功執行:
spamc -c < /var/mail/username
假設該使用者信箱已經有至少一封郵件,這時 spamc 程式會將該郵件傳送給 spamd(127.0.0.1:783)進行評分,如果執行成功應該會看到 SpamAssassin 的評分,例如:
3.5/5.0
讓 postfix 使用 SpamAssassin 過濾郵件
確定 SpamAssassin 可以正常執行之後,接著設定 /etc/postfix/master.cf,請修改 smtp deamon 服務的設定:
smtp inet ............中間五個欄位不用修改............. smtpd -o content_filter=spamfilter:這一行的意思是要求 smtpd 在進行完郵件過濾後,透過 spamfilter 服務進行郵件全文過濾,因此我們還得定義 spamfilter 這個服務(服務名稱可以自行修改):
spamfilter unix - n n - 100 pipe flags=Rq user=nobody argv=/usr/sbin/spamc.sh -f ${sender} -- ${recipient}
這裡定義 spamfilter 服務使用 unix socket 執行,最多同時進行 100 封信的過濾(如果記憶體不足請自行修改數量),過濾方式是透過pipe 模組以 nobody 身分啟動 /usr/sbin/spamc.sh ,並且將目前佇列中的郵件其資料結構中的 sender 和 recipient參數讀出來,連同 -f 參數傳遞給 spamc.sh 當作參數。旗號 R 表示要把信封中的寄信人地址,以 Return-Path: 標頭插入郵件中。旗號 q 表示參數中的特殊字元要用單引號括住,以避免被當成控制字元處理,在這個例子中用來避免郵件地址中的 @ 符號被當成控制字元。
接著我們還得自己寫一支小小的 shell script,底下就是 /usr/sbin/spamc.sh 的內容(這個檔案須自己建立,之所以放在 /usr/sbin/ 是因為這個資料夾的權限比較嚴格,也比較安全):
#!/bin/sh
/usr/bin/spamc -t 30 -e /usr/sbin/sendmail -i "$@"
不要忘記將該程式的檔案權限改成 755。pipe 模組傳遞參數給上面這支程式時,會將整封郵件的內容放在鍵盤的 input 佇列中,所以我們使用 sendmail -i 這道指令將郵件從 input 佇列讀進來,"$@" 會被 spamc.sh 的參數巨集取代,也就是說 "$@" 會變成
-f sender@sender.domain -- recipient@recipient.domain
這個字串將當成參數傳遞給 sendmail 程式,意思是要 sendmail 把參數傳遞進來的「寄信人地址 -- 收信人地址」寫在信封的寄信人欄位裡。 mail from: 與 rcpt to: 原始參數的取得,是由 smtpd於建立 SMTP 連線時,將該字串擷取出來放在郵件佇列的資料結構中,當 master 喚醒 spamfilter 服務時,透過 pipe 當白手套,把郵件資料結構中的字串傳遞給 spamc.sh 再傳遞給 sendmail。透過這些程式的接力表演,現在終於可以把這兩個參數當作過濾的鍵值。
附帶一提:如果本機沒有安裝 SpamAssassin,想要透過別台主機安裝好的 SpamAssassin,這時候可以修改 spamc.sh:
/usr/bin/spamc -d 172.16.1.6 -p 783 -t 30 -e /usr/sbin/sendmail -i "$@"
使用這個方法前,請先確認從本機到過濾主機之間的防火牆已經放行 783 port。
刪除可疑的垃圾郵件
SapmAssassin 發現垃圾郵件的可疑對象時,會加入一個郵件標頭,至於要不要把信刪除,則不關它的事。我們可以透過 header_checks機制(前參照第肆章 UCE 過濾的說明)把具有 SPAM 標頭的郵件刪除,然而這樣做是有風險的,萬一有些普通信件因為長得太像垃圾信而被標示為 SPAM,那就會一起被刪除!
如果你真的想刪除可疑郵件,請修改 main.cf 設置下列參數:
header_checks = pcre:/etc/postfix/header-checks
找到 /etc/postfix/header-checks 檔案,如果檔案不存在請自己建立,加入底下這一行:
/^X-Spam-Flag: Yes/ DISCARD垃圾郵件經驗學習法
SpamAssassin 判斷一個檔案是否為垃圾郵件,是透過郵件特徵比對 hits 比率(原理有點像 proxyserver),也就是說必須使用一段時間後,才能從經驗中學習到哪些郵件內容反覆不斷出現, 而要學會哪些郵件是垃圾郵件,最有效的方法是透過一個垃圾信箱來學習,首先我們建立一個沒人使用的信箱,接著以此信箱為名義在 news server 上發表測試文章。
等幾天後,很快的就有一大堆垃圾信湧入該信箱,現在我們只要把信餵給 SpamAssassin 就行了,底下是透過 alias 來餵信:
fakeuser: "| /usr/bin/spamassassin -r -w fakeuser"
上面這個範例中,指令參數 -r 的意思是要 SpamAssassin把所有郵件的寄信人信箱當成垃圾信的樣板,從此以後符合此樣板的郵件都會被認為是垃圾信。-w fakeuser 是一個非必要參數,SpamAssassin 將會以 fakeuser 信箱的名義寄警告信給對方,但是因為對方使用偽裝過的信箱,因此也沒有人會收到警告信,寄了也是白寄,建議不要使用此功能。
除了透過 alias 可以餵信給 SpamAssassin 外,我們也可以利用 .forward 來餵信,請在 fakeuser 的家目錄建立此檔案,檔案內容如下:
| /usr/bin/spamassassin -r -w fakeuser
決定 SPAM 過濾門檻
SpamAssassin 根據郵件比對的得分高低,來決定該郵件是否為垃圾信,預設值是 5 分,建議修改為 9 分。請修改 /etc/mail/spamassassin/local.cf:
required_hits 9.0
白名單與黑名單
SapmAssassin 維護一個郵件資料庫,該資料庫將透過自動學習機制來增減郵件的分數,分數高於門檻的稱之為黑名單,分數低於門檻的稱之為白名單,一旦某種特徵的郵件被評為黑名單,以後該信箱寄出的郵件都會被認為是垃圾郵件,雖然自動學習機制對於主動發現垃圾郵件很有用,但難免也有誤判的時候,這個時候我們可以透過以下命令來調整:
/usr/bin/spamassassin -W < message | 將該郵件加入白名單 |
/usr/bin/spamassassin --add-to-blacklist < message | 將該郵件加入黑名單 |
/usr/bin/spamassassin -R < message | 將該郵件移出白名單 |
/usr/bin/spamassassin --add-addr-to-whitelist=mailbox | 將該信箱加入白名單 |
/usr/bin/spamassassin --add-addr-to-blacklist=mailbox | 將該信箱加入黑名單 |
/usr/bin/spamassassin --remove-addr-from-whitelist=mailbox | 將該信箱移出白名單 |
當某個信箱被誤判為垃圾郵件,這時我們可以直接將該信箱加入白名單,例如:
/usr/bin/spamassassin --add-addr-to-whitelist=shane@mail.syups.tp.edu.tw
該信箱一旦加入白名單後,只能以手動方式移出或重新加入黑名單。如果要把具有某種特徵的郵件加入白名單(例如:校內郵件討論群組、校園電子報、網站更新通知......等,這類郵件經常被視為垃圾郵件),請先將該封郵件另存成純文字檔,接著將該信餵給 SapmAssassin 即可,請使用底下指令:
/usr/bin/spamassassin -W < myletter.eml
玖、amavisd-new + clamav
amavisd 用來將病毒過濾功能提供給郵件伺服器,和 SpamAssassin 一樣也是用 perl 開發的,而新版的 amavisd-new 更結合了SpamAssassin 和許多額外設定,透過 perl Net::Server 模組提供類似 Apache prefork 模式的效能,可以應付 ISP龐大的郵件處理量。也就是說,使用了 amavisd-new 就不需要再去作前一章提到的 SpamAssassin 相關設定,同時也可以根據自己的需求來制定執行緒的數量。
clamav 是一套免費的病毒過濾引擎,使用者不須註冊就可以透過病毒更新程式自動更新病毒碼,而且病毒碼的維護也很迅速,每天至少會更新一次。clamav主要用來應付硬碟檔案的掃毒工作,它可以因應硬碟 IO 動作即時監控掃毒,也可以排程進行資料夾掃描,但它卻無法與各種伺服器結合一起運作,這也就是為什麼我們需要 amavisd 的原因。更精確的說,amavisd 只是將現成的掃毒功能提供給郵件伺服器而已,它自己並不會掃毒。

設定 clamav
在這裡我們將只介紹 clamav 的安裝程序,並不打算詳細介紹 clamav 的各種功能和使用方法,有興趣的學員可以自行到 clamav 的官方網站
http://www.clamav.net/ 查看詳細的內容。使用底下指令進行安裝:
yum install clamav*
安裝完成後,可以使用 man clamd 來查看詳細介紹,請使用 ntsysv 或底下指令將 clamav 設定為開機時自動啟動:
chkconfig --level 3,5 clamd on
手動啟動 clamav 的方式和其它的服務一樣:
service clamd start
要更新病毒碼可以使用 freshclam 指令,如果要讓它自動更新,則可以加以下參數(意思是每天檢查更新兩次):
freshclam -d -c 2
freshclam 也是一個 deamon ,因此我們可以使用 ntsysv 或底下指令將它設定為開機時自動啟動:
chkconfig --level 3,5 freshclam on
在網路上可以找到 OpenAntiVirus 發展計畫,該計畫以GPL 精神來整合 Linux 平台上的各種掃毒引擎,clamav 只是其中之一,其它發展中的計畫還包括:mod_vscan(在 Apache上掃毒)、squid_vscan(在 Proxy 上掃毒)、amavisd(在 Mail 上掃毒)、pop3_vscan(在 iptables 防火牆上直接掃掉郵件病毒),有興趣的學員不妨去逛一逛。
安裝 amavisd-new
amavisd-new 的原始套件可以在 http://www.ijs.si/software/amavisd/ 取得。這個套件與 perl 模組的依存性很高,安裝異常複雜,但在 Fedora中可以利用 yum 來輕鬆安裝:
yum install amavisd-new
安裝完成後,amavisd 會自動被設定為開機啟動,你可以使用 ntsysv 或 chconfig 指令來修改啟動設定,也可以手動控制:service amavisd start
安裝外掛延伸套件
雖然在前面已經將 amavisd裝好,也可以運作了,但考量到掃毒成效,某些延伸套件也不得不安裝,舉例來說:有人把中毒的檔案壓縮後再寄出,假如沒有安裝解壓縮引擎,那豈不是掃不到病毒。要知道掃毒是透過病毒特徵的比對,一個被壓縮過的檔案,病毒特徵都消失了,當然就比對不出來!因此要讓 amavisd 發揮最大的掃毒效益,就必須安裝各種解壓縮軟體,底下是各種 Linux 版的解壓縮程式,請點選下列的超連結下載安裝:
外掛掃毒引擎
amavisd 支援 21 種掃毒軟體(包含前面介紹過的 clamav),其中大多數都是商業軟體,包括國內知名的趨勢科技和美國的賽門鐵克公司(當然得買 Linux 版,Windows 版的授權並不通用),因此在這裡我們就不介紹了!
修改 amavisd.conf
amavisd 的設定分為底下八個部分,說明如下:
Essential daemon and MTA settings | amavisd deamon 的基本設定以及指定使用何種 Mail server,需要手動修改的就是這個部分。 |
MTA specific | SMTP 通訊協定相關設定,使用預設值即可。 |
Logging | 系統日誌設定,使用預設值即可。 |
Notifications/DSN, BOUNCE/REJECT/DROP/PASS destiny, quarantine | 訂定郵件過濾政策,包括:郵件格式設定、警告訊息、中毒和垃圾郵件之處理......等等,請依需要修改,使用預設值也無妨(中毒時只警告不刪除)。 |
Per-recipient and per-sender handling, whitelisting, etc. | 訂定中毒及垃圾郵件黑、白名單管理政策,是否要透過資料庫存取、特定網域或信箱排外處理......等等,不是 ISP 應該用不到,所以我們不去理會它! |
Resource limits | 系統資源限制,請依據自己的硬體設備等級來調整,原則上盡量調高效能才會好!(但會影響其它服務的效能)。 |
External programs, virus scanners, SpamAssassin | 外掛套件的設定,由於程式會自動偵測,所以使用預設值就可以了! |
Debugging | 設定 debug 模式啟用時機,預設是不啟用。 |
在第一個部分一定得設定的有底下這些參數:
$MYHOME = '/var/amavis'; | 指定 amavis 服務帳號的家目錄,如果是使用筆者寫的 script 安裝的,這個部分不用修改。 |
$mydomain = 'syups.tp.edu.tw'; | 指定郵件伺服器網域。 |
$deamon_user = 'vscan'; | 指定 amavisd 服務帳號,如果是使用筆者寫的 script 安裝的,這個部分不用修改。 |
$deamon_group = 'sweep'; | 指定 amavisd 服務群組,如果是使用筆者寫的 script 安裝的,這個部分不用修改。 |
$forward_method = 'smtp:127.0.0.1:10025'; | 根據郵件伺服器的不同,須設定呼叫 amavisd 的方式,預設值是給 postfix 用的,如果您的郵件伺服器不是 postfix 請依文件說明修改。 |
$max_servers = 2; | 預設啟動幾個行程。 |
$max_requests = 10; | 預設每個子行程最多服務幾次要求,超過次數該子行程會重新啟動。 |
$child_timeout = 5*60; | 每次過濾郵件不可超過 5 分鐘,如果覺得病毒濾不乾淨,可以延長時間,預設是 8 分鐘。 |
在第四個部分底下這些參數,可依需要考量設定:
$hdr_encoding = 'iso-8859-1'; | 指定標頭使用的字元集,使用預設值即可。因為中文字和其它雙位元字都會編成 quoted-printable code 再寄出,因此沒有相容上的問題,除非是想要啟用 utf8 才須修改。 |
$bdy_encoding = 'iso-8859-1'; | 指定郵件內文使用的字元集,使用預設值即可。 |
$final_virus_destiny = D_BOUNCE; | 設定中毒郵件處理方式,預設值是發出警告信。 |
$final_banned_destiny = D_BOUNCE; | 當郵件夾帶禁止通行的檔案時(例如:exe、com、vbs、scr、pif....等等,稍後可自行修改)要如何處理,預設值是發出警告信。 |
$final_spam_destiny = D_REJECT; | 設定垃圾郵件的處理方式,預設值是拒收(郵件內容將遭到刪除)。 |
$final_bad_header_destiny = D_PASS; | 郵件標頭中含有非 ASCII 字元時,要如何處理?預設值是接受。這是垃圾信常用的招數,例如:收信人為「親愛的客戶@mail.syups.tp.edu.tw」之類的,雖然這些郵件仍然會由 postfix 再次過濾,但最好還是拒收。 |
當過濾政策設定為 D_PASS 時,可以利用底下參數來訂定要不要寄警告信,預設值是不要。 |
$warnvirussender = 1; | 中毒郵件要不要警告寄信者,其實這個功能還蠻實用,但是會增加伺服器負擔。 |
$warnspamsender = 1; | 垃圾郵件要不要警告寄信者,這個功能沒有用,不須設定。 |
$warnbannedsender = 1; | 郵件夾帶禁止通行的檔案時要不要通知寄信者,其實這個功能還蠻實用,但是會增加伺服器負擔。 |
$warnbadhsender = 1; | 郵件標頭含有非 ASCII 字元時要不要通知寄信者,這個功能沒有用,不須設定。 |
$warnvirusrecip = 1; | 要不要警告收信者他收到的信有毒,這個功能其實沒什麼用,因為不管有沒有收到警告信,outlook express 都會自動打開中毒郵件。 |
$warnbannedrecip = 1; | 要不要警告收信者他收到的附件檔案可能有危險,這個功能其實沒什麼用,理由同上。 |
$virus_admin = "virusalert\@$mydomain"; | 請將管理員信箱改成自己常用的信箱或是透過 alias 對應到常用信箱。當管理員信箱有設定時,管理員會同步收到所有的警告信。 |
$banned_filename_re = new_RE( qr'\.[a-zA-Z][a-zA-Z0-9]{0,3}\.(vbs|pif|scr|bat|com|exe|dll)$'i, # double extension # qr'.\.(exe|vbs|pif|scr|bat|com)$'i, # banned extension - basic # qr'.\.(ade|adp|bas|bat|chm|cmd|com|cpl|crt|exe|hlp|hta|inf|ins|isp|js| # jse|lnk|mdb|mde|msc|msi|msp|mst|pcd|pif|reg|scr|sct|shs|shb|vb| # vbe|vbs|wsc|wsf|wsh)$'ix, # banned extension - long # qr'^\.(exe|zip|lha|tnef)$'i, # banned file(1) types # qr'^application/x-msdownload$'i, # banned MIME types # qr'^message/partial$'i, qr'^message/external-body$'i, # rfc2046 ); |
上面是用來設定哪些檔案要禁止通行,採用 pcre 的格式來設定,如果你對 perl 程式設計有概念,可以自行修改內容! |
設定 postfix
首先在 master.cf 中先定義一個病毒過濾服務,服務名稱可以自己取:
amavis unix - - - - 2 smtp -o smtp_data_done_timeout=1200
這個服務將會執行 smtp client,配合稍後會作的 main.cf 的修改,該 smtp client 將會連往本機(127.0.0.1)的10024 埠,該埠號已經 binding 給 amavisd。限制行程數為 2 個,這是為了配合 amavisd.conf 中的設定,如果覺得不夠用想修改,不要忘記一併修改 amavisd.conf。
在啟動外掛過濾程式的做法上與前面介紹過的 SpamAssassin 略有不同,後者是透過 pipe 模組呼叫一個外部 client 端程式(spamc)來啟動。而 amavisd 則由於本身並未提供 client 端程式,所以需要由 postfix 的 smtp 模組來代勞。
接著請在 master.cf 加入底下幾行設定:
127.0.0.1:10025 inet n - - - - smtpd
-o content_filter=
-o local_recipient_maps=
-o relay_recipient_maps=
-o smtpd_restriction_classes=
-o smtpd_client_restrictions=
-o smtpd_helo_restrictions=
-o smtpd_sender_restrictions=
-o smtpd_recipient_restrictions=permit_mynetworks,reject
-o mynetworks=127.0.0.0/8
-o strict_rfc821_envelopes=yes
-o smtpd_error_sleep_time=0
-o smtpd_soft_error_limit=1001
-o smtpd_hard_error_limit=1000
這個設定用來啟動一個 smtp deamon,以便配合 amavisd 的過濾動作,郵件從 postfix 透過 smtp client 模組傳送給amavisd 進行病毒碼比對,比對有結果後 amavisd 會將郵件送往 10025 埠,而這個埠已經定義給 postfix smtp deamon模組,雖然該模組會讀取 main.cf 的設定,但上面所指定的參數將會取代 main.cf 的設定,仔細看其中 content_filter= 這個參數,就會發現 postfix 將不會再啟動其它的外掛過濾機制。
細心的學員應該會想到,一旦使用了 amavisd 就不會再進行 SapmAssassin 過濾!這也就是為何 amavisd-new 必須支援 SpamAssassin 的原因,當兩個過濾引擎結合為一體時,也就不必去煩惱如何整合的問題。
配合上述的修改,請將 main.cf 中的 content_filter 參數設定為:
content_filter = amavis:[127.0.0.1]:10024
上面這一行的服務名稱須與 master.cf 中的定義匹配,如果有改過服務名稱,不要忘記一併修改。另外埠號也是可以配合 amavisd.conf 來修改,在這裡就不討論了!
還記得在前一章設定 SpamAssassin 時,曾經修改過 master.cf 中的 smtp deamon 服務嗎?這個服務是 binding 在25 埠的主服務,不同於剛才加入的 10025 埠的 smtp deamon,當時在修改時有指定 content_filter 參數,這將會取代 main.cf 中的參數設定,導致 amavisd 過濾引擎不會被啟動,請將該參數移除:
smtp inet ............中間五個欄位不用修改............. smtpd -o content_filter=spamfilter:
改為:
smtp inet ............中間五個欄位不用修改............. smtpd
當然 spamfilter 服務也不再起作用了,可以一併刪除,不刪除也無所謂!
過濾測試
底下來測試 amavisd 的過濾功能是否有正常運作,測試時我們需要一個帶有病毒的測試檔案,這個檔案可以到 http://www.eicar.org/anti_virus_test_file.htm 取得,檔名就叫 eicar.com(這隻病毒不具有破壞能力),由於筆者的電腦有裝防毒軟體,所以無法下載這個檔案,但我們也可以直接使用病毒特徵來測試,eicar.com 的病毒特徵如下:
X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*
我們先來測試進行郵件濾後處理的 postfix smtp deamon 是否正常:
> $ telnet 127.0.0.1 10025
220 yourhost.example.com ESMTP Postfix
quit //已正常啟動並能接受指令
221 Bye
Connection closed by foreign host.
接著測試 amavisd 的過濾功能:
> $ telnet 127.0.0.1 10024
220 [127.0.0.1] ESMTP amavisd-new service ready
MAIL FROM:<test@example.com> //服務已經啟動,來寄信試試看
250 2.1.0 Sender test@example.com OK
RCPT TO:<postmaster>
250 2.1.5 Recipient postmaster OK
DATA
354 End data with <CR><LF>.<CR><LF>
Subject: test1
test1
.
*** 250 2.6.0 Ok, id=31859-01, from MTA: 250 Ok: queued as 90B7F16F //郵件已被接受,接著寄病毒信試試看
MAIL FROM:<test@example.com>
250 2.1.0 Sender test@example.com OK
RCPT TO:<postmaster>
250 2.1.5 Recipient postmaster OK
DATA
354 End data with <CR><LF>.<CR><LF>
Subject: test2 - virus test pattern //在標頭後面輸入病毒特徵
X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*
.
*** 550 5.7.1 Message content rejected, id=16968-01 - VIRUS: EICAR-AV-Test //發現病毒,郵件已被攔截
*** 250 2.5.0 Ok, but 1 BOUNCE //發送警告信通知寄信人
*** 250 2.7.1 Ok, discarded, id=16984-01 - VIRUS: EICAR-AV-Test //中斷收信動作
*** 250 2.6.0 Ok, id=17041-01, from MTA: 250 Ok: queued as 3F1841A5F5 //警告信已經排入佇列
QUIT
221 2.0.0 [127.0.0.1] (amavisd) closing transmission channel
Connection closed by foreign host.