Postfix是一個非常優秀的MTA,她素以高效、安全的特點而著稱。Postfix是作者在UNIX上所見過的MTA中在反垃圾郵件(Anti-Spam或Anti-UCE)方面做得最好的一個,甚至有很多公司在Postfix代碼的基礎上進行二次開發而推出反垃圾郵件網關產品。 MTA的反垃圾郵件功能,實際上就是在MTA處理過程中對會話進行過濾。這個過濾不但過濾了發往自身的垃圾郵件,而且還防止了自身被惡意利用發送垃圾郵件。Postfix實現了目前所有主要的MTA過濾技術。關於郵件過濾技術可以參閱本站的相關文章
MTA過濾分為兩類:郵件數據發送前過濾和郵件數據發送後過濾。
一、數據前過濾
數據前過濾是指在SMTP會話中,DATA指令發送前進行的過濾。在這個階段,有四種不同子階段的過濾:SMTP連接時過濾、HELO/EHLO指令過濾、MAIL FROM指令過濾和RCPT TO指令過濾。根據這四個子階段接收到的信息的不同,它們也分別稱作SMTP客戶端限制、HELO/EHLO主機名限制、發送者地址限制和接收者地址限制。
過濾默認是在RCPT TO指令後生效的,這是因為一些Windows上的郵件客戶端不處理在RCPT TO指令前的過濾動作。可以通過將smtpd_delay_reject設置為no來使過濾動作立刻生效。這個參數還影響了在不同的指令上可以使用的過濾規則參數。
1、過濾規則
這四個子階段的過濾是分別通過四個配置語句來指定過濾規則的。它們都接收一系列的規則參數列表,參數間可以用空格或逗號分隔開。在默認狀態下smtpd_delay_reject的值是yes,它們可以接受所有支持的規則,不過需在RCPT TO指令後才能全部生效;如果把smtpd_delay_reject設置為no,它們只可以接受五個公共的規則參數、之前子階段的過濾規則參數和該子階段的規則參數。
它們接受的公共的規則參數如下:
- permit
允許該連接進行。該規則通常置於規則列表的最後面使規則更清晰。
defer
通知客戶端現在不能繼續會話,稍後再進行SMTP連接請求。這常用於服務器需要進行一些DNS檢查,但是(由於DNS查詢超時)沒有及時獲得結果時,通知客戶端稍後再進行連接。該規則通常置於規則列表的最後面使規則更清晰。 - reject
拒絕該連接請求。在這個階段就斷開了連接,有效的節約了垃圾郵件造成的帶寬和處理能力的浪費。該規則通常置於規則列表的最後面使規則更清晰。
拒絕動作默認不會在匹配了拒絕規則後就立刻斷開連接,而是在rcpt to指令處理完之後再斷開的,這是由於一些windows上有缺陷的郵件程序不處理在rcpt to指令前的發回的拒絕狀態碼。可以通過smtpd_delay_reject設置為no來立刻發送拒絕狀態碼斷開連接。
reject_code指定了拒絕的返回狀態碼(默認是554)。 - warn_if_reject
改變其後規則的拒絕動作為警告,即如果其後存在滿足拒絕的條件,並不實際拒絕,而是發出一條警告信息(reject_warning)到日誌文件中(通常是/var/log/maillog)。它常用於在實際運行的郵件服務器上測試郵件過濾規則。 - reject_unauth_pipelining
拒絕在Postfix支持指令流水線前發送SMTP指令流水線的客戶端連接。指令流水線是一些郵件客戶端為了快速發送郵件所採用的技術。
以下就四個子階段分別講述過濾規則
A、SMTP連接時過濾(SMTP客戶端限制)
Postfix可以在接受客戶端的SMTP連接請求時進行過濾檢查。
通過Postfix的smtpd_client_restrictions指令可以指定這個階段的過濾規則。這個階段可用的過濾規則除公共規則外還有:
- reject_unknown_client
拒絕客戶的地址沒有對應的DNS的A記錄或PTR記錄的連接。通常有些機器,尤其是個人撥號用戶的機器沒有對應的A記錄或PTR記錄,所以要注意漫遊用戶的使用(漫遊用戶是指不在$mynetworks中,比如在別的ISP撥號上網的用戶。通常用SMTP認證來解決這個問題)。
unknown_client_reject_code指定了拒絕的返回狀態碼(默認是450)。 - permit_mynetworks
允許來自其IP地址屬於$mynetworks所定義網絡的客戶端的連接。通常可用於ISP為自己的撥號用戶提供SMTP服務時,通過$mynetworks參數指定自己的網絡並允許自己的網絡內的機器發送郵件。
reject_rbl_client domain.tld和reject_rhsbl_client domain.tld
拒絕來自屬於RBL和RHSBL列表中的地址進行連接。通過檢查一個IP地址或域名是否存在於domain.tld的RBL或RHSBL中,可以判斷該客戶端是否被列入了domain.tld的實時黑名單,從而決定是否接受連接。有關實時黑名單可以參考本站的【 反垃圾郵件技術參考>> 實時黑名單技術】。
maps_rbl_reject_code指定了拒絕的返回狀態碼(默認是554)。 - check_client_access maptype:mapname
搜索名為mapname的maptype類型的訪問數據庫。可以根據客戶端的主機名、父域、IP地址或部分IP地址來匹配。關於訪問數據庫請參閱下面的
附錄。
例子:
smtpd_client_restrictions = hash:/etc/postfix/access,
reject_rbl_client relays.ordb.org,
reject_rhsbl_client dsn.rfc-ignorant.org,
permit_mynetworks,
reject_unknown_client
其中relays.ordb.org和dsn.rfs-ignorant.org都是國外比較權威的免費RBL和RHSBL服務器。
B、HELO/EHLO指令過濾(HELO/EHLO主機名限制)
在接受了SMTP連接後,可以對HELO或EHLO指令所發送的信息進行過濾檢查。
有些郵件客戶端在通訊時並不發送HELO/EHLO指令,可以通過smtpd_helo_required設置為yes強制要求發送HELO/EHLO指令(默認Postfix不要求發送HELO/EHLO)。
通過Postfix的smtpd_helo_restrictions指令可以指定這個階段的過濾規則。這個階段可用的過濾規則除公共規則和smtpd_client_restrictions的規則外還有:
- reject_invalid_hostname
拒絕無效格式的主機名的連接。
invalid_hostname_reject_code指定了拒絕的返回狀態碼(默認是501)。 - reject_unknown_hostname
拒絕未知的主機名的連接。所謂未知的主機名是指該主機沒有DNS的A記錄或MX記錄。由於很多撥號用戶的機器並沒有對應的A記錄或MX記錄,所以要注意漫遊用戶的使用。
unknown_hostname_reject_code指定了拒絕的返回狀態碼(默認是450)。 - reject_non_fqdn_hostname
拒絕主機名不是FQDN格式(完全限定域名格式,即用點分隔開的包括域名和主機名的主機全名)的連接。
non_fqdn_reject_code指定了拒絕的返回狀態碼(默認時504)。 - permit_naked_ip_address
允許直接使用IP地址的連接。通常在HELO/EHLO中使用主機名而不是IP地址。
check_client_access maptype:mapname
搜索名為mapname的maptype類型的訪問數據庫。可以根據HELO/EHLO發送的主機名、父域來匹配。關於訪問數據庫請參閱下面的 附錄。
C、MAIL FROM指令過濾(發送者地址限制)
在接受了SMTP連接,客戶端發送了HELO/EHLO指令後(該指令可選),應該通過MAIL FROM指令聲明發送者的身份。可以對發送者身份進行過濾檢查。
按照RFC規範,在MAIL FROM指令和下面的RCPT TO指令中應該使用RFC 821格式的郵件地址(例如:<user@domain.tld>),但是由於有許多的郵件客戶端的不規範,往往不使用標準的RFC 821格式。Postfix默認接受任何可以理解的郵件地址,如:丟失了地址裡的一對尖括號、可以包含RFC 822格式的註釋等。如果希望打開對RFC 821格式的限制,可以將strict_rfc821_envelopes設置為yes。
通過Postfix的smtpd_sender_restrictions指令可以指定這個階段的過濾規則。這個階段可用的過濾規則除了公共規則和smtpd_client_restrictions的規則和smtpd_helo_restrictions的規則外還有:
- reject_unknown_sender_domain
拒絕發送者郵件的域沒有DNS的A記錄或MX記錄的連接。
unknown_address_reject_code指定了拒絕的返回狀態碼(默認是450)。當進行DNS查詢出現臨時錯誤時(如查詢超時)也總是返回450。 - reject_rhsbl_sender domain.tld
拒絕發送者郵件的域屬於RHSBL黑名單的連接。通過檢查一個域名是否存在於domain.tld的RHSBL中,可以判斷該客戶端是否被列入了domain.tld的實時黑名單,從而決定是否接受連接。
maps_rbl_reject_code指定了拒絕的返回狀態碼(默認是554)。 - check_sender_access maptype:mapname
搜索名為mapname的maptype類型的訪問數據庫。可以根據發送者郵件的郵件地址、名字、域和父域來匹配。關於訪問數據庫請參閱下面的 附錄
。 - reject_non_fqdn_sender
拒絕發送者郵件的域不是FQDN格式的連接。
non_fqdn_reject_code指定了拒絕的返回狀態碼(默認時504)。 - reject_sender_login_mismatch
拒絕發送者在$smtpd_sender_owner_maps中所匹配的用戶名和SASL登錄名不一致的連接。
D、RCPT TO指令過濾(接收者地址限制)
在MAIL FROM指令後要通過RCPT TO指令指定郵件接收者。可以對接收者身份進行過濾檢查。
通過Postfix的smtpd_recipient_restrictions指令可以指定這個階段的過濾規則。同以上的檢查指令不同,為了避免開放轉發,這個指令有默認值:permit_mynetworks,reject_unauth_destination。這個階段可用的過濾規則除了公共規則和smtpd_client_restrictions的規則和smtpd_helo_restrictions的規則和smtpd_sender_restrictions的規則外還有:
以上的所有過濾規則如下表歸納:
子 階 段 | 規 則 名 | check_*_access | | X |
reject_unknown_* | | X | |
reject_non_fqdn_* | | X |
|
reject_rbl_*/reject_rhsbl_* | | X | |
permit_* | | X | |
other | X | |
公 共 規 則 | defer
| X | | |
| | |
reject
| X | | | | | |
warn_if_reject
| X | | | | |
|
reject_unauth_pipelining | X | | | | | |
permit | |
X | | | | |
連 接 過 濾 | permit_mynetworks | |
X | | | | |
reject_rbl_client | | | X
| | | |
reject_rhsbl_client | | | X | |
| |
reject_unknown_client | | | | | X | |
check_client_access | | | | | | X |
H E L O 過 濾
| reject_invalid_hostname | X | | | | | |
permit_naked_ip_address | | X | | | | |
reject_non_fqdn_hostname | |
| | X | | |
reject_unknown_hostname | | | | | X | |
check_helo_access | | | | | |
X |
發 送 者 過 濾 | reject_sender_login_mismatch | X | | | | |
|
reject_rhsbl_sender | | | X | | | |
reject_non_fqdn_sender | | | | X | | |
reject_unknown_sender_domain | | | | | X | |
check_sender_access | | | |
| | X |
接 收 者 過 濾 | reject_unauth_destination | X | | | | | |
check_recipient_maps | X | | | | |
|
permit_auth_destination | | X | | | | |
permit_mx_backup | | X | | | | |
permit_sasl_authenticated |
| X | | | | |
reject_rhsbl_recipient | | | X |
| | |
reject_non_fqdn_recipient | | | | X | |
|
reject_unknown_recipient_domain | | | | | X | |
check_recipient_access |
| | | | | X |