對這文章發表回應
發表限制: 非會員 可以發表
發表者: 冷日 發表時間: 2012/11/20 16:04:10
Postfix 反垃圾擋信機制
postfix的擋信機制
——— 《postfix權威指南》學習筆記 lxq007
不請自來的大宗郵件」(Unsolicited Bulk E-mail,UBE),或「不請自來的廣告郵件
」(Unsolicited Commercial E-mail,UCE),就是一般俗稱的「垃圾郵件」(spam),寄件人
沒有事先徵得收件人的同意,就擅自寄送大量(煩人的)郵件給一大群陌生的收件人,這樣的行為稱為
「濫發垃圾郵件」,而專門幹這種事的人,叫做「垃圾郵件發送者」(spammer)。垃圾郵件之所以存在,
是因為寄送成本便宜。郵遞量從幾百人增加到幾千人並不會增加太多成本,所以,來郵件發送者的目標
就是盡量收集多的郵件地址。
按照UBE的判別依據,postfix提供的檢查機制可分四大類:
客戶端判別規則
Postfix提供四種檢查客戶端身份的參數,每一種參數都可設定一系列決定如何響應客戶端的限
制條件(restriction)。如果條件成立,可能的響應動作包括OK(收下郵件)與reject(當場
拒收)。例如,你可以設定一條檢查規則。擋掉來自特定IP 地址的郵件。相對的,如果條件不成
立,則由後續條件繼續處理(這種結果 通常以DUNNO表示)。
語法檢查參數
Postfix內置一系列專用檢查語法的參數, 可用來核驗客戶端的smtp對話內容是否符合標準規
定。由於垃圾郵件發送者通常不遵守標準規定,則對於不符合規定的客戶端或郵件,你可以要求
postfix予以拒收。有些語法檢查參數也可作為客戶端判別規則。
內容檢查
你可以將一組描述垃圾郵件特徵的正則表達式(regular expression)寫在查詢表(稱為模式
表)中,要求Postfix依據樣式表來檢查郵件的標題與正文內容。
自定義過濾規則
你可將一系列內置的限制條件組織成新的過濾規則。
設定postfix的垃圾郵件標識參數時,你還必須指定如何處理被辨認出來的垃圾郵件。一般而言,
postfix可以當場拒收,或是收下郵件但是暫存在另一個隊列,或是交給外部過濾程序去處理。
一、客戶端判別規則
下列過濾規則可設定一系列對客戶端信息的限制條件:

上述的每一項參數,分別用於檢查smtp對話過程中的特定階段。在每一個階段,客戶端分別提供不同類型
的信息。potfix依據你給各規則設定的限制條件來檢查這些信息。
下圖為 SMTP對話過程及各階段對應的限制條件:
(描述了上述參數與SMTP對話過程各階段的對應關係,其中 header_checks與 body_checks
參數為「內容檢查」)

1 smtp對話過程(簡述)
首先,一個smtp client通過socket連接到postfix。由於是socket方式連接,所以postfix在建立連
接時就可以知道客戶端的ip地址。 smtpd client_restrictions讓你可依據客戶端的ip地址或主機名稱來
決定是接收還是拒收該信息。連接成功後,客戶端送出HELO命令來顯示自 己(送信方)的主機名稱.postfix
依據 smtpd_helo_restrictions的限制條件來檢查這個主機名稱,借此決定應該收下還是拒收郵件。
下一步,客戶端發出mail from命令來顯示寄件人的郵件地址,接著以一個rcpt to命令來表明收件人的
郵件地址。寄件人與收件人的郵件地址的限制條件,分別設定在 smtpd_sender_restrictions與 smtpd_
recipient_restrictions中。
如果到DATA命令為止之前的一切都可以接收,客戶端就可以開始傳送郵件的內容。郵件內容分成兩部分,
前半部是標題,由 header_check過濾;後 半部是正文(body),由check_body過濾。如果最後的標題與
正文檢查也過關,postfix就收下信息,並交給適當的MDA執行投遞操作。
註:很多垃圾郵件發送者在HELO步驟送出的是「收信方」的主機名稱,任何遵守規定的smtp client都不會
這樣做,所以你可以在 smtp_helo_restrictions設一個限制條件,禁止對方使用我們的主機名稱。
2 設定限制條件
任何限制條件都可以用於任何過濾規則。postfix的這種設計,主要是為了讓你可以更有靈活性的安排限制條件的順序。
表:
限制條件與對應的受檢信息
限制條件 客戶端提供的受檢信息
reject_rbl_client 客戶端的IP地址或主機名稱
reject_rhsbl_client
reject_unknown_client
check_client_access type:mapname HELO提供的主機名稱
permit_naked_ip_address
reject_invalid_hostname
reject_non_fqdn_hostname
reject_unknown_hostname
check_helo_access type:mapname MAIL FROM提供的寄件人郵件地址
reject_non_fqdn_sender
reject_rhsbl_sender
reject_unknown_sender_domain
check_sender_access type:mapname RCPT TO提供的收件人郵件地址
permit_auth_destination
permit_mx_backup
reject_non_fqdn_recipient
reject_unauth_destination
reject_unknown_recipient_domain
check_recipient_access type:mapname
reject_unauth_pipelining DATA命令
permit 無條件批准
reject 無條件拒絕
defer 無條件延遲
warn_if_reject 將原本的REJECT動作改成WARN
reject_unauth_pipelining 禁止非授權客戶端使用PIPELINING命令
拒絕在Postfix支持指令流水線前發送SMTP指
令流水線的客戶端連接。指令流水線是一些郵件
客戶端為了快速發送郵件所採用的技術
上邊所列的限制條件大致可分為3類。第一類是內置條件,它們的名稱以permit_和reject_開頭,不需
要額外自變量。第二類為自定義條件,它們的名稱類似check_*_access,需要一個type:mapname自變量,
其中mapname是訪問表(access table)的名稱。在技術上, 訪問表與一般的postfix查詢表沒兩樣,同樣
都是由一系列的key-value組合而成; 在用途上,訪問表供管理員定義自己的過濾規則;索引鍵描述客戶端的
匹配條件,對應值描述如何處理符合條件的客戶端。第三類為通用條件,它們沒有額外自變量,也不檢查任何信
息,用於直接改變郵件的處理流程,或是改變其他限制條件的作用。
2.1 內置限制條件的工作流程
每一種內置限制條件(reject_和permit_系列), 分別檢查不同的客戶端信息,Postfix依據
檢查結果決定如何處理郵件。處理方式包括:OK、 REJECT以及DUNNO. 當你在同一個過濾規則中列
出多個限制條件時, postfix依照它們的排列順序來進行檢查過程。 檢查過程中,如果某條件的檢
查結果為reject,則POSTFIX會立刻拒收郵件; 如果檢查結果為OK,則略過同一過濾規則中的其餘條件,繼續檢查下一個規則;到所有 規則都檢查完畢或是出現reject結果為止。
當過濾規則的檢查結果為reject時,postfix的默認行為並不是真的當場拒收,除非客戶端已經送出recp to命令。如果你想改變延遲reject時機的行為,讓 reject動作在第一時間發生,你可將main.cf的smtpd_delay_reject設成成no:
smtpd_delay_reject = no
2.2 測試限制條件:
當管理員修改了或增加了新的限制條件時,有些新條件的效果很難完全預測,為此,POSTFIX
提供了一個參數,讓你用來測試新限制條件
soft_bounce =yes #硬性拒絕碼(5xx)被改成軟性(4xx)
在sotf_bounce模式下,硬性拒絕碼(5xx)會被改成軟性拒絕碼(4xx)。對smtp client
而言, 5xx代表服務器端徹底拒絕請求,即使下次再嘗試寄出同一封郵件,服務器端也不會接受。所
有,收到5xx響應碼的客戶端不會繼續嘗試同樣的動作。另一方面,4xx代表服務器端只是暫時拒絕請
求,客戶端下次仍有機會成功寄出郵件, 所以smtp client會保留郵件以等待下次寄送時機。 利用
sotf_bounce模式來測試新條件,即使發生誤判,只要我們能實時更正,被誤判的smtp client就
有機會寄出它的信。
每增加一條你沒把握的新限制條件,都可以打開soft_bounce模式,然後觀察日誌文件,看看是
否發生誤判,並調整條件設計,等一切都妥當之後,再關掉sotf bounce模式。
另一個有用的條件測試工具是 warn_if_reject修飾符。將這個修飾符放在限制條件之前,該條件
原本的reject動作都被改成warn。也就是 說,smtp client不會被擋在門外,但是postfix會在
日誌文件裡留下一筆警告記錄, 表示該條件發生作用了。 如果你不確定新條件在實際環境下會造成什
麼後果, 但是又不喜歡 soft_bounce 模式那種全面性的影響,你可以用warn_if_reject。來測
試新條件,等到確定新條件的效果符合預期之 後,再拿掉warn_if_reject修飾符。舉例來說:
smtpd_recipient_restrictions =
permit_mynetworks
r eject_unauth_destination
warn_if_reject reject_invalid_hostname
reject_unknown_recipient_domain
reject_non_fqdn_recipient
在此例中,如果客戶端使用helo命令送出了一個無效的主機名稱,postfix仍然會容許對方送出郵件
(如果沒被其他條件擋掉的話),但是會在日誌文件留下一筆警告記錄。
2.3
實例
smtpd_recipient_restrictions = permit_mynetworks reject_unauth_destination reject_invalid_hostname reject_unknown_sender_domain |
permit_mynetworks返回OK, 整個smtpd_recipient_restrictions過濾規則也就跟
著結束。 若客戶端來自外界網絡,permit_mynetworks返回DUNNO。
若郵件的收件人不在Postfix所轄的網域(由mydestination定義), reject_unauth_
destination返回REJECT;否則返回DUNNO。
reject_invalid_hostname,若客戶端使用HELO命令提供的主機名稱是無效的,這項檢查
返回REJECT;有效則為DUNNO。
reject_unknown_sender_domain,如果客戶端在MAIL FROM提供的郵件地址的網域部分
是無效的(即用DNS查不出來),則檢查結果會是REJECT。
3 定義限制條件
依據檢查對象的不同,限制條件分為六大類型:
訪問表
check_*_access形式的,依據訪問表所列的IP地址、主機名稱或郵件地址而決定Postfix
應拒收還是接收。
客戶端參數
依據配置文件裡的一般信息而非訪問列表來檢查客戶端的資格。如permit_mynetwork條件
就是檢查客戶端是否來自mynetworks或mynetworks_style定義的網絡。
嚴格語法檢查
某些限制條件要求Postfix非常嚴格地貫徹SMTP標準。
DNS檢查
利用DNS系統提供的信息來審核客戶端是否誠實。
實時黑名單
RBL是一種依附在DNS系統下的網絡服務,供MTA實時查詢客戶端是否來自惡名昭彰的垃圾源。
通用限制條件
無條件拒絕reject或收下permit郵件,或是改變其他條件的行為(warn_if_reject)。
3.1 訪問表(access map)
訪問表也是Postfix查詢表的一種,由key-value組成,訪問表的索引鍵(key)是客戶端標識
信息(IP地址、郵件地址、主機名稱),而value是處理動作(OK或REJECT).
check_client_access maptype:mapname
check_client_access 指向一個含有IP地址、網絡地址、主機名稱、從屬網域名稱的訪問
表. 設定此限制條件時,Postfix先從DNS系統反查出客戶端IP地址的完整主機名稱( ptr記
錄),並自己分析出主機本名與從屬網域,然後以這些信息與訪問表中的每一個索引鍵比對,如
果發現相符的索引鍵,則採取對應值所指定的處理動作。
check_helo_access maptype:mapname
所指的訪問表含有主機名稱與從屬網域,用於比對客戶端在HELO 命令中顯示的主機名稱。如果
發現相符的索引鍵,則Postfix執行對應值所指定的處理動作。
check_recipient_access maptype:mapname
指向一個含有郵件地址、網域名稱、人名的訪問表,用於比對客戶端在RCPT TO命令中提供的收
件地址。如果發現相符的索引鍵,則Postfix執行對應值所指定的處理動作。
check_sender_access maptype:mapname
指向一個含有郵件地址、網域名稱、人名的訪問表,用於比對客戶端在 MAIL FROM命令中提供
的寄件人郵件地址。如果發現相符的索引鍵,則Postfix執行對應值所指定的處理動作。
索引鍵:
check_recipient_access 和 check_sender_access用來檢查客戶端提供的郵件地址,有
user@example.com、example.com、user@等格式。
check_client_access和 check_helo_access檢查的數據都是IP地址與主機名稱,如下寫法均
可192、192.168、 192.168.132、192.168.132.221
對應值:
OK 通過當前過濾規則的檢查, 繼續檢查下一個限制條件
REJECT
REJECT message-text
另外加一段簡短信息,說明拒絕服務的理由,這段信息會連同拒絕碼一起返回給客戶端,並且
被記錄在postfix的日誌文件裡。 access_map_reject_code定義所有check_*_access
限制條件的默認拒絕碼;maps_rbl_reject_code參數定義reject_maps_rbl的默認拒絕
碼;兩者均為554
DUNNO
未知,繼續檢查下一個限制條件
FILTER transport:nexthop
將郵件轉交給指定的內容過濾器。
HOLD
HOLD message-text
將郵件放在保留隊列
DISCARD
DISCARD message-text
要求postfix收下郵件後立刻丟棄,但是讓客戶端誤以為它已成功送出郵件。如果你加注一段
簡短信息, 則postfix會將這段信息記錄在日誌文件裡;否則只記錄一般信息.別輕易嘗試
discard動作,除非你已經謹慎考慮過可能的後果。暗自丟掉郵件的行為,有違郵件系統的設
計初衷.雖然丟掉垃圾郵件是 理所當然的動作,但萬一發生誤判,勢必無法挽回已經消息的合
法郵件,而且有損用於對於internet e-mail的信任。
4xx message-text
返回指定的拒絕碼與信息給客戶端,表示暫時拒收郵件。400-499範圍內的拒絕碼代表服務器
端暫時性問題,客戶端應該先保留郵件,下次再嘗試傳送。
5xx message-text
返回指定的拒絕碼與信息給客戶端,表示徹底拒收郵件。500-599範圍內的拒絕碼代表服務器
端不管怎樣都不會收下郵件,客戶端應該發出退信通知給原寄件人。
訪問表的索引鍵也可以是「正則表達式」。一般而言,使用正則表達式來描述訪問表是一種浪費,因
為postfix已經有分析郵件地址、網域名稱、ip地址的能力,所以正則表達式帶來的好處並不多。但
如果要檢查郵件的內容(標題或正文),正則表達式就非常好用。
範例:

/etc/postfix/client_access文件,其內容如下:
10.157 REJECT 192.168.132.221 REJECT example.com REJECT |
user@example.com REJECT test1@ REJECT example-test.com REJECT |
#postmap /etc/postfix/client_access
#postmap /etc/postfix/sender_access
3.2 客戶端條件設置
permit_auth_destination
如果收件地址位於Postfix的轄域,則批准請求。所謂"postfix的轄區「, 包括mydesti
nation、inet_interfaces、virtual_alias_maps或virtual_mailbox_maps及
relay_domain所列的網域及子網域。
permit_mynetworks
如果客戶端的IP地址位於mynetworks參數所列的任何地址範圍內,則批准請求。
reject_unauth_destination
如果收件地址不位於Postfix的轄域,批准請求.拒絕碼為relay_domains_reject_code參
數提供。
3.3嚴格語法條件
在內置限制條件,有部分是以「客戶端在smtp對話過程提供的信息是否符合標準「為判斷依據的。
這類條件可偵測出大量垃圾郵件,但是發生誤判的機會也很 高。你應該研究你收到的垃圾郵件與真
實郵件之間的差異(或共同處),才會知道哪些條件可以使用(或不可使用)。如果你事先知道哪些
寄件人可能被誤判,建議 你將他們列入白名單裡。
reject_invalid_hostname
客戶端在helo命令提供的主機名稱不是有效的主機名稱,返回invalid_hostname_reject
_code參數指定的拒絕碼(默認為501)
reject_non_fqdn_hostname
客戶端在HELO命令提供的主機名稱不是RFC要求的完整格式(FQDN),則返回non_fqdn_
reject_code參數指定的拒絕碼(默認504). 並非所有合法寄件人都會提供FQDN完整名稱
(尤其是Windows)。
reject_non_fqdn_recipient
客戶端在RCPT TO命令提供的收件地址的網域部分,不是RFC要求的完整格式(FQDN),則返
回non_fqdn_reject_code參數指定的拒絕碼(默認504)。
客戶端在mail from命令提供的寄件人地址的網域部分,不是RFC要求的完整格式(FQDN),則
返回non_fqdn_reject_code參數指定的拒絕碼(默認504)。
reject_unauth_pipelining
流水線操作(Pipelining)是一種加速處理大宗郵件的技術,其原理是容許客戶端一次送出多
個SMTP命令. 協議要求客戶端必須先檢查服務器端是否支持pipelining,才可開始流水線操
作,但有些MUA與MTA不遵守規定。此條件會拒絕不遵守規定的SMTP client。
3 .4 DNS限制 條件
DNS限制條件確定客戶端所在的網絡以及信封上的郵件地址,是否有可查驗的dns信息。如果郵件
管理員總是能取得有效的DNS信息,Internet E-mail系統的可用度將獲得普遍提升,因為垃圾郵
件發送者將難以遁形。不幸的, DNS系統是網管人員最常疏忽的一環,有許多合法用戶所在的網絡並
沒有可茲查驗的dns信息,因此,完全依賴dns來過濾垃圾郵件, 反而成了不切實際的想法。你應該
研究你所收到的垃圾郵件與真實郵件的本質,看看哪些限制條件既能夠阻擋最多的垃圾郵件,而誤判
機率又不令人擔心。如果你事先知道哪些寄件人可能被誤判,建議你將他們列入白名單裡,以免受到
dns限制條件的影響。
r eject_unknown_client
當SMTP client通過socket建立連接時,POSTFIX Server可從socket連接知道客戶端
的IP地址.先查詢客戶端IP地址的PTR記錄(改IP記錄在DNS系統登錄的主機名稱),如果查
不出,則會拒絕服務;如果能從DNS查出主機名稱,則POSTFIX還會使用該主機名再向DNS查
出其對應的IP地址,如查出的IP地址不符合socket連接提供的遠程IP地址,則會拒絕服務.
此拒絕碼定義在unknown_client_reject_code參數,其默認值為450(由於當前很多的
合法郵件均沒有PTR記錄,所以建議不使用這條規則)。
reject_unknown_hostname
如果HELO命令提供的主機名稱既沒有A記錄,也沒有MX記錄,則拒絕服務並返回unknown_
hostname_reject_code參數指定的拒絕碼(450)。這條規則建議不使用,因為許多客戶
端的HELO所提供的主機名稱不是完整形式,FOXMAIL中HELO所提供的主機名稱為客戶端系
統的計算機名稱。
reject_unknown_recipient_domain
如果RCPT to命令提供收件人地址,其網域部分查不出有效的DNS A或MX記錄,則以unknown
_address_reject_code參數定義的拒絕碼拒絕服務(450)。
reject_unknown_sender_domain
如果mail from命令提供寄件人地址, 其網域部分查不出有效的DNS A 或 MX記錄,則以
unknown_address_reject_code參數定義的拒絕碼拒絕服務(450).建議使用這條規則.
3.5 實時黑名單
實時黑名單(Real-Time Blacklist)是一種專為抵制垃圾郵件而設計的網絡服務。這種服務
依賴於DNS服務,所以也成為DNSBL。Postfix提供下列三種DNSBL的限制條件:
reject_rbl_client rblprovider.domain
將客戶端IP地址( 例如 192.168.1.3 )顛倒順序(成為3.1.168.192),搭配RBL管理
員的網 域名稱( 例如xpl.spamhaus.org ) 構成一個主機名稱( 成為
3.1.168.192.xpl.spamhaus.org) , 然後以此主機名稱向DNS 系統查詢,如果能查出
一 筆A 記錄,表示該地址已被列入黑名單,則會當場拒收郵件。
reject_rhsbl_client rblprovider.domain
如果客戶端的主機名在指定的rblprovdier.domain網域下有一筆A記錄,則拒絕服服務.
reject_rhsbl_sender rblprovider.domain
如果寄件人的郵件地址的網域部分,在指定的 rblprovdier.domain網域下有一筆A記錄,
則拒絕服務。
3.6通用限制條件
除了針對特定信息的檢查條件之外,postfix還提供了四個可用於任何過濾規則的限制條件,它
們適合放在過濾規則的最後,作為該組規則的默認處理政策。
permit
批准收下郵件。postfix不再繼續當前的過濾規則,但是會跳到下一組過濾規則
reject
無條件拒收。postfix不再繼續處理任何過濾規則。
defer
婉拒請求,客戶端被告知稍候再試。
二、SMTP語法規範參數
smtp是相當寬鬆的協議,有些smtp client/server的對話過程甚至比協議本身要求更寬鬆.
為此,postfix提供兩個參數,讓你自己決定是否要求嚴格遵守smtp協議的對話過程與語法。第一個
參數是smtp_helo_required,它決定是否要求smtp client以helo或ehlo動作為開場白。按照
smtp rfc的規定,smtp clients連接到server後的第一句話必須是helo或ehlo。
默認情況下,postfix對客戶端抱持寬容態度,容許客戶端不嚴格遵循smtp協議。但如果你設定
smtpd_helo_required = yes,而客戶端見面不打招呼,則postfix將拒絕服務。
smtp rfc也明確規範了信封地址的格式,正常情況下,postfix幾乎接受任何有意義的信封地
址,但是, 如果你設定了strict_rfc821_envelopes = yes,則沒有提供正確格式地址的客戶
端將被擋在門外。
實際上,要求對方必須提供helo/ehlo或許是個好主意,因為大部分的客戶端至少都會遵守smtp
協議的基本對話過程。但並非所有客戶端都提供符合標準格式的郵件地址,如果要求太嚴格,可能會錯
失一些合法郵件。
三、內容檢查
直接讓postfix將垃圾郵件過濾的最後機會,是檢查郵件內容本身。
Postfix提供了四個檢查郵件內容的參數:
headr_checks 檢查標題
mime_header_checks 檢查標題的MIME相關字段
nested_header_checks檢查夾帶附件的標題
body_checks檢查郵件的正文
內容檢查的影響是全面性的,即該階段已經沒有機會讓特定寄件人或收件人繞過檢查。
1 設定內容檢查參數
在默認情況下,如果你沒有設定mime_header_checks和nested_header_checks參數,它
們將與 header_checks共享同一個查詢表。如果你想將其區分開來,則必須分別提供不同的查詢
表給它們。設定檢查參數時,必須先註明正則表達式的語法格 式(regexp代表postfix的標準正
則表達式語法,pcre代表perl兼容的語法)以及模式表的完整路徑。例如:
header_checks = regexp:/etc/postfix/checks/header_checks mime_header_checks = regexp:/etc/postfix/checks/mime_header_checks body_checks = regexp:/etc/postfix/checks/body_checks |
模式表的索引鍵是描述比對特徵的正則表達式,此正則表達式本身必須放在一對分隔符(通常是/)
之間,例如: header_checks模式表如下:
/free mortgage quote/ reject /^Date:.* 200[0-7]/ REJECT Your email has a date from the past. /^Date:.*19[0-9][0-9]/ REJECT Fix your system clock and try again. /^Date:.* 2[0-9][1-9][0-9] / REJECT Your email has a error date. /^Date:.* 200[9] / REJECT Your email has a error date. |
2 內容檢查的響應動作
REJECT message-text
如果模式匹配成功,則拒絕郵件,並將message-text傳給客戶端。
WARN message-text
模擬拒收動作。
IGNORE
刪除符合模式的標題字段或整行文字。用來刪除某些敏感信息。
HOLD message-text
將郵件放在保留隊列。
DISCARD message
要求Postfix假裝接收郵件,但其實偷偷丟掉。能解決迂迴攻擊的問題。還有如果有無辜
用戶的郵件地址被用來當初垃圾郵件發信者地址,可用此沒收郵件,以免無辜受害者收到
退信通知。
FILTER transport:nexthop
將郵件轉交給指定的內容過濾器。
3 模式匹配
執行標題檢查時,標題裡的每一個字段都要依序與模式表裡的正則表達式匹配。如果字段內容跨越
多行,在比對之前,它們會先被合併成一行, postfix先從模式表裡的第一個正則表達式開始比
對 ,只要發現字段符合某正則表達式, 整個比對過程就立刻結束,並執行該正則表達式對應的動
作。只有在所有字段都不符合所有模式的請客下,整個標題才算通過檢查。
執行正文檢查時,body_checks指定的模式表裡的每一個正則表達式,依序與正文裡的每一文字
行比對,每次只比對一行。如果發現符合模式的字符串,整個比對過程立刻結束,執行此模式所對
應的動作。
如果要比對的文字行超過長度上限,postfix會將它們拆成符合長度限制的段落,分段檢查。文字
行的字符數上限由line_length_limit參數決定 ,其默認值為2048。如果標題的總長度超過
header_size_limit(默認值為100k)postfix也是以同樣原則分段處理。最後,如果正文
總長度超過body_checks_size_limit (默認值為50k),postfix不會檢查超過限制的部分.
這項限制相當有用,因為可避免postfix去掃瞄整個文件。
有些管理員運用header_checks來進行簡單的病毒過濾。例如,使用下列正則表達式可擋掉夾帶
危險文件的郵件:
/name ?="?.*\.{bat|scr|com|dll|exe|hta|pif|vbs}"?/ reject
如果你的postfix系統要服務許多windows系統的計算機,上述模式或許能幫你的用戶群減少不
少困擾,但同時也阻斷了「交流正常程序文件」的機會。請注意,這個模式的防毒效果有限,因為我
們還漏掉了一些擴展名, 不足以阻擋所有windows可執行文件,況且有許多pc客戶端不用擴展名
就可以直接運行文件。
下面是一個典型的body_checks模式文件的內容:
/increase your sales by/ reject
/in compliance (with|of) strict/ reject
/lowest rates.*\!/ reject
/[:alpha:]<!--.*-->[:alpha:]/ reject suspicious embedded htm comments
前兩個模式很簡單,不再解釋。第三個模式挑出任何含有「lowest rates」字樣且其後跟著任何
文字(.*)以及一個感歎號(!)的字符串,例如「we have our lowest rates in 40
years!」)。最後一個模式檢查是否有html註釋嵌在字句中間,例如「via<!--ooxx->gra「。
垃圾郵件發送者常用這種技巧試圖通過過濾程序,但是,這也成為垃圾郵件的絕佳特徵,因為一般
的正常郵件多半不包含html註釋,就算有,也不會刻意夾在字句中間。
使用postmap工具可以測試寫好的正則表達式.假設msg.txt是一個垃圾郵件樣本文件,我們可用
下列方式將它導入postmap:
postmap -q - regexp:/etc/postfix/body_checks < msg.txt
postfix會顯示出符合模式的字符串,以及對應該模式的動作。
每個站點面臨的垃圾郵件源都不太一樣,你應當研究收到的垃圾郵件,根據你自己的研究結果來寫
出適當的過濾模式.編寫正則表達式時一定要相當謹慎,如果設計不當,可能會嚴重降低服務器的效
率。另一個潛在的問題在於沒有任何郵件可以繞過內容檢查,即使郵件已通過所有smtpd_*_res
trictions過 濾規則的檢驗,甚至已被納入白名單,最後仍有可能被header_checks與body_
checks擋在門外。
在你設計判別垃圾郵件的過濾規則時,請留心用戶群之間需求與心態。有些人對垃圾郵件深惡痛絕,
甚至寧願承擔較高的誤判風險;有些人則寧可多收一些垃圾郵 件,也不願意錯失任何真實郵件。被你
擋掉的化妝品廣告郵件,有可能是某位女同事訂閱的電子報。如果無法兼顧所有人的要求,且必須分別
位不同用戶設定不同的過濾規則時, 則最好不要在mta做這件事, 應該考慮使用特殊的mda, 例如
procmail,maildrop,或任何能依用戶類別來選擇過濾規則的軟件。
倘若你真的希望在postfix解決不同用戶的爭議,則postfix提供了分級機制,可針對不同收件人
使用不同的過濾規則。
四、自定義過濾條件組合
為了滿足不同層次的觀眾,政府設計了電影分級制度;同樣的,為了滿足不同用戶的需求,postfix
也提供了分級制度,讓你可依據用戶的身份來選擇適當的 過濾條件組合。postfix的分級機制稱為「
規範等級」(restriction class),這是非常強大的工具,讓你能更靈活運用postfix的垃圾郵
件過濾條件。如果你的用戶需要不同鬆緊程度的過濾條件組合,或是有一兩位用戶 需要與眾不同的過
濾規則,投資時間研究如何設定規範等級決定是值得的。
具體做法如下:
1、 定義多組「規範等級」,每個等級都有自己的專屬名稱,不同的等級各由鬆緊不等的限制條件組
合而成。
2、製作一個訪問表,索引鍵是用戶的標識信息(通常是郵件地址),對應值是該用戶適用的限制等
級的名稱。
3、在一般的smtp_*_rrestrictions過濾規則中,加上一條檢查訪問表的條件。任何check_*
_access條件都可以用來檢查訪問表,換言之,你可以依據客戶端(check_client_access)、寄
件人(check_sender_access)或收件人(check_recipient_access)來執行分級過濾。
規範等級實例
為了舉例說明,假設我們有兩組用戶:一組是電信警察,以打擊垃圾郵件發送者為職責,研究垃圾郵件
是他們的專業;另一組人是八卦部隊,如果讓他們收到垃圾郵件,天下只會更亂而已。
很顯然,這兩組人不能共享相同的過濾規則,否則一定會出事。為了滿足這兩種極端的要求,我們擬定
了兩級規範,分別命名為「spamlover」與「spamhater」。所有規範等級的名稱都必須列在
smtpd_restriction_classes參數,像這樣:
smptd_restriction_classes = spamlover, spamhater
接下來, 我們當初怎樣設定一般的smtpd_*_restrictions過濾規則,現在就可以怎樣定義我們的
規範等級。以下是spamhater的定義,其限制條件相當嚴格:
spamhater =
reject_invalid_hostname
reject_non_fqdn_hostname
reject_unknown_sender_domain
reject_rbl_client nospam.example.com
下面是spamlover的定義,只有一個簡單的permit(無條件批准)
spamlover = permit
當然,現實環境中你應該視實際情況調整規範等級的定義,增加或減少某些限制條件。
現在,我們已經完成新規範等級的聲明與定義,下一步,我們要製作一個訪問表,讓postfix知道哪
些人適合哪些規範等級。由於我們的規範等級是針對不同用戶而設計的,所以訪問表的索引鍵是收件人
的郵件地址,而對應值是用戶適合的規範等級。假設這個訪問表的名稱是per_user_ube,它的內容看起來應該類似這樣:
#
#per_user_ube
#
a@example.com spamhater
b@example.com spamlover
最後,要求postfix在審核收件人限制時,檢查你指定的訪問表:
smtp_recipient_restrictions =
permit_mynetworks
reject_unauth_destination
check_recipient_access hash:/etc/postfix/per_user_ube
記得,postmap /etc/postfix/per_user_ube
一切就緒後,每當外界有人寫信給a@example.com,postfix先執行一遍正常的默認過濾規則,在
遇到check_recipient_access時,它會檢查指定的收件人訪問表,並查出a@example.com適用
的規範等級為spamhater,然後執行spamhater定義的限制條件。如果spamhater下的任何條件都
返回reject,postfix就拒收郵件;否則就將郵件交給適當的mda處理。外界寫給b@example.com
的郵件也是依照同樣的過程來處理,如果postfix所執行的規範等級為spamlover,會無條件收下任
何郵件。
反垃圾郵件實例
反垃圾郵件的main.cf配置文件樣本
smtpd_restriction_classes =
spamlover
spamhater
spamhater =
reject_invalid_hostname
reject_non_fqdn_hostname
reject_unknown_sender_domain
reject_rbl_client nospam.example.com
spamlover = permit
smtd_helo_required = yes
smtpd_client_restrictions =
check_client_access hash:/ect/postfix/client_access
smtpd_helo_restrictions =
reject_invalid_hostname
check_helo_access hash:/etc/postfix/helo_access
smtpd_sender_restrictions =
reject_non_fqdn_sender
reject_unknown_sender_domain
check_sender_access hash:/etc/postfix/sender_access
smtpd_recipient_restrictions =
permit_mynetworks
reject_unauth_destination
reject_non_fqdn_recipient
reject_unknown_recipient_domain
smtpd_data_restrictions =
reject_unauth_pipelining
header_checks = /etc/postfix/header_checks
body_checks = /etc/postfix/body_checks
這個例子需要好幾個訪問表,你應該分析實際收到的垃圾郵件,收集垃圾郵件發送者的ip或郵件地
址,創建你自己的訪問表。不過,就經驗來說,check_helo_access和check_sender_access
的效果有限, 阻擋不了太多的垃圾郵件。基本上,垃圾郵件發送者有無限多的郵件地址與主機名稱可
以使用,每次你更新了訪問表之後, 他們又從別的地方冒出來,讓你疲於奔命。況且,主機名稱與發
信者地址太容易捏造了,而且他們時常假冒來自擁有大群合法用戶的大型網站,使你防不勝防。
雖然擋不住精明的垃圾郵件發送者,但是阻擋垃圾郵件發送者的效果還挺不錯。有些傢伙不懂變化,
總是千篇一律的使用相同信息, 對付這種連幹壞事也沒有腦筋的垃圾郵件發送者,訪問表是最好的武器。
有些在線營銷服務發送信息真實的廣告信,而且也遵守規定的提供真實的選退機制,讓你決定是否願
意繼續收到廣告信。然而,如果你不相信那些聽都沒有聽過的公司的選退機制,你可用mail from或
helo的信息來阻擋他們的廣告信,而不要冒著讓他們有機會證實你的郵件地址的風險。當然,有些站點
惡名遠揚,你完全不想再見到他們,不管他們是否誠實、提供選退機制,你都可以直接擋掉它們的垃
圾郵件。
此外,有許多垃圾郵件假冒它們來自某些小國家。如果你確定不可能會收到來自馬爾代夫共和國的合法
郵件,你可以將該國的頂層網域名稱填入訪問表,一舉阻斷所有假冒來自該地址的垃圾郵件。然而,如
果你的郵件系統服務很多用戶,你或許不應該如此武斷,將你個人的獨斷意識強加在每位用戶身上。
焉知你的用戶沒有住在馬爾代夫的親戚?或是特別喜歡到該國出差?
原文出處:
Postfix 反垃圾挡信机制 - jsl99@mig的日志 - 网易博客