Postfix郵件轉發詳解
到目前為止,我們主要的討論焦點,都是postfix于郵遞路徑末端所扮演的角色。也就
是說,抵達postfix服務器的郵件,主要是被投遞到本機系統。但是,postfix也常扮演
另一種角色--位于郵遞路徑中的中繼器。
備用交換器
在DNS的術語中,MX代表mail exchanger。一個MX記錄代表一個網域承接外來郵件的主
機,以及該主機的優先度。同一個網域可以同時有好幾個MX記錄,優先度最高的主機稱
為主交換器,其余主機稱為備用交換器。備用交換器的任務,是在主交換器離線時,承
接該網域的外來郵件;當優先度高于自己的其他備用交換器或主交換器恢復上線時,已
收下的郵件必須傳給主交換器來處理,備用交換器不能自己擅作主張,將收到的郵件直
接投遞到最終目的地。假設備用交換器時,不必特別設定如何傳信給主交換器,因為
postfix自己能從DNS查出如何轉信給主交換器。不過,前提是你必須讓postfix知道自
己是哪一個網域的備用交換器。你的 postfix系統是哪些網域的備用交換器,那些網域
的名稱就必須被列在relay_domains參數中。當寄信方的MTA發覺收信網域的主交換器離
線了,它會試著聯系優先度次高的交換器,直到有一個備用交換器能夠收下郵件地址為
止。如果你的postfix系統是某個網域的備用交換器,而且該網域被列在
relay_domains參數中,則postfix會收下該網域的郵件,并將其排入隊列。每隔一段時
間,postfix會掃描它的隊列,并檢查是否有優先度更高的郵件交換器恢復連接,如果有
,則交出先前代收的郵件。
如果不能交出郵件,postfix會持續嘗試,直到郵件在隊列里等待的時間超過
maximal_queue_lifetime所指定的時限為止。此參數的默認值為五天,如果郵件在等待
隊列里待的時間超過此上限,postfix會發出退信通知函給寄件人。如果你事先知道主交
換器停機的時間會超過五天,可以適度提高時限。
轉發列表
postfix可從relay_domains參數與DNS系統知道自己的備用交換器角色,但是它如何知
道轉發的網域中有哪些有效收件人?如果備用交換器無法事先知道主交換器有哪些合法
郵箱,它勢必被迫盲目收下所有郵件,等到主交換器恢復連接時,才會發現有哪些郵件
無法投遞并退信給原寄件人。因此,我們鄭重建議你在備用交換器設置一份列表,記錄
受理網域有哪些合法用戶,并定期與主交換器同步更新。
當備用交換器上的postfix server收到寄給relay_domains所列網域的郵件時,它會檢
查relay_recipient_maps參數所指定的查詢表,借此判斷是否應該收下郵件,如不應收
下則直接拒收。relay_recipient_maps參數的設定方式如下:
relay_recipient_maps = hash:/etc/postfix/relay_recipients
relay_recipients查詢表應該記錄所有合法收件人的郵件地址。postfix只需要此表的
索引鍵,所以對應值可以任意填寫(但不可不填)
對于人事變動頻繁的網域,我們建議你應該研制一個同步程序,利用rsync、ssh、
crond等工具,自動從主交換器下載最新列表。
如果備用交換器的postfix不過濾轉發網域的收件地址,會有什么后果?答案是備用交換
器會收到一大堆無法投遞的垃圾郵件,并產生一大堆寄不出去的退信通知函。因為捏造
收件人是垃圾郵件發送者常用的手段之一,他們事先不知道你的郵件交換器有哪些用戶
,于是以常用的人名來捏造收件地址,試圖蒙混過關。此外,垃圾郵件也不可能會提供
有效的回信地址。
假如備用交換器與主交換器位于同一個局域網,除了使用rsync、scp、ssh、crond等傳
統工具之外,還有更好的方法來進行列表的同步更新工作。比方說,將用戶賬號儲存在
某種數據庫中,像mysql、ldap等,讓postfix能夠進行實時查詢。
在你設定了relay_recipient_maps之后,還必須面對一個潛在的問題;你必須將所有轉
發網域的所有合法郵件地址都列入查詢表,因為 postfix將拒收任何收件地址沒出現在
查詢表的郵件。如果你不知道某些網域的合法郵件地址,你可以為該網域設置一個無限
別名地址;
快速清空
為許多網域承接郵件的網絡,時常會面臨無法立刻送出郵件的困境,因為他們的顧客的
服務器不見得永遠保持連接。在客戶離線的情況下,ISP只能將收到的郵件暫時存放在隊
列里,等到客戶的服務器恢復連接時,再使用SMTP的ETRN命令,一次清空隊列里的所有
郵件;
當一個網域的主交換器恢復連接并完成收信準備時,我們的隊列里已囤積了大量要傳給
該網域的郵件,讓postfix逐一檢查每一個隊列文件的收信網域為何,將會損耗許多時間
。為此,postfix提供了一種稱為“快速清空”(fast flush)的功能,可用來在隊列
中找出寄給特定網域的所有郵件。快速清空功能是由flush daemon控制管理的,對于
postfix所代理的每一個收信網域,flush各準備了一份列表,記錄該網域郵件在隊列里
的編號。如此,在發出ETRN 命令之后,postfix可以迅速找出所有要投遞到該網域的郵
件。
默認情況下,flush只管理relay_domains所列的網域。如果還有其他網域也需要快速清
空服務,你可以將它們的網域名稱在fast_flush_domains參數中,像這樣:
fast_flush_domains = $relay_domains, example.com
此例中,example.com是一個沒列在relay_domains的網域。
你可以使用postqueue -s命令來通知postfix,某各快速清空網域已經準備好接收先前
累積的郵件了:
postqueue -s example.com
傳輸表
當你想改變默認的郵遞流程時,可利用傳輸表(transport map)來達成愿望。也就是
說,如果你希望postfix以你指定的方式來處理特定網域的郵件,而不管DNS MX記錄是
怎么設定的,你可將相關網域與傳送方式寫在一二傳輸表中,然后將transport_maps參
數指向此傳輸表。
本節討論transport_maps參數的基本用法,后面幾章會陸續談到此參數在其他方面的應
用。transport_maps參數可指向一個或多個傳輸表,例如:
transport_maps = hash:/etc/postfix/transport
傳輸表的索引鍵可以是完整的郵件地址、網域名稱或子網域名稱。當收件地址或網域名
稱符合傳輸表某個記錄的索引鍵時,則以該記錄的對應值所指定的傳輸法來投遞該郵件
。
傳輸表內容
example.com smtp:[192.168.23.56]:20025
oreilly.com relay:[gateway.oreilly.com]
oreillynet.com smtp
ora.com maildrop
kdent@ora.com error:no mail accepted for kdent
傳輸表對應值的格式,隨傳輸方法而異,但大體上符合transport:nexthop這樣的格式
。某些傳輸方法的nexthop可表示成host:port形式,表示遞送路徑下一站的主機名與
通信端口。以下分別說明可組成對應值的三種元素:
transport
傳輸方法的名稱。此名稱必須是master.cf所定義的傳輸類型之一。如果你增加
了新的傳輸方法,則必須先在master.cf定義其名稱與傳輸類型。
host
收信主機或網域。host只能搭配inet傳輸類型(smtp或lmtp)。postfix按照一
般收信網域的處理流程host:先查詢mx記錄來決定郵件的去處,如果沒有mx記錄,則傳
到a記錄所指的ip地址。如果將主機名稱放在一對方括號內,則postfix會直接傳信到
host的a記錄所指的ip地址。但如果你直接使用ip地址,則一定要加方括號,例如
〔192.168.23.56〕
port
收信主機的通信端口。通常只有inet類型的傳輸服務才會指定通信端口。port
的格式可以是十進制數,也可以是/etc/services文件定義的服務名稱。
上例列出的傳輸表內容,暫時了transport:host:port的多種可能組合,分別解釋如
下:
example.com smtp:〔192.168.23.56〕:20025
收下所有寫給example.com的郵件,然后使用smtp MDA傳送到位于
192.168.23.56的主機,而且smtp MDA必須連接到該主機的port 20025,而非默認的
smtp port25。請注意,由于我們直接使用了ip地址,所以必須加上方括號。
oreilly.com relay:〔gateway.oreilly.com〕
收下所有要寄到oreilly.com的郵件,然后使用relay MDA轉寄給
gateway.oreilly.com主機。由于沒指定通信端口,所以relay使用默認的port25。由于
主機名稱被放在方括號內,所以郵件是直接傳到gateway.oreilly.com的A記錄所指的ip
地址,而非mx記錄所指的ip地址。
relay MDA是postfix2.0版以后才引進的,它修正了隊列調度算法可能引起的潛在效能
瓶頸。當你要將入站郵件送到內部系統時,應該直接通過relay MDA,以避免這類郵件與
出站郵件競爭資源。
oreillynet.com smtp
收下所有目的地為oreillynet.com網域的郵件,然后交給smtp MDA執行投遞操
作。由于沒指定host:port,所以smtp依照oreillynet.com網域的DNS MX或A記錄來決
定目的地,并使用port 25來聯系收信服務器。實際上這個例子實屬多余,因為只要將
oreillynet.com列在relay_hosts或relay_domains參數,就可以達到相同效果。
ora.com maildrop
收下所有寫給ora.com網域的郵件,然后交給maildrop處理。maildrop的運作方
式必須被明確定義在master.cf中。由于maildrop不需要inet socket,所以不必指定
host:port。
kdent@ora.com error:No mail accepted for kdent
error是一種特殊的傳輸服務,它唯一的作用是當場拒收郵件。冒號之后的字符
串是回復給傳送方的錯誤信息。
傳輸表不一定用來將郵件傳遞到外界,也可以用于將特定郵件交給本地系統,以便進行
特殊處理。比方說,過濾郵件內容、暫時扣留某個網域的所有郵件等。
#p#
延遲投遞時間
在某些情況下,你可能會希望postfix先收下郵件,但不立刻投遞出去。等到你下達
posqueue -f domain命令之后,或是postfix從支持快速清空功能的網域收到ETRN
SMTP命令之后,postfix才遞送出被暫扣留的郵件。
最常見的一種情況是ISP為客戶的網域代收郵件,但是客戶的網絡并不總是保持連接。
ISP必須先儲存郵件,直到客戶的網絡恢復連接,并且能收下郵件為止。類似的情況還有
客戶網絡上的用戶,應該要能夠通過本地的郵件網關來寄信,該網關必須能先暫存外寄
郵件,直到網絡恢復連接時才投遞出去。
暫緩轉發郵件
在以下的程序中,我們要先創建一種新型的傳輸法,稱為“ondemand”,然后設定傳輸
表,要求所有寄到example.com網域的郵件,一律先暫時扣留在隊列里。
1。 在master.cf設置一種新的傳輸法,并命名為ondemand。它的配置應該與smtp傳
輸法一樣
ondemand unix - - n - - smtp
2、要求postfix自動延緩任何通過ondemand遞送的郵件。只要將新設的ondemand傳輸法
列在main.cf的defer_transports參數中,就可以達到自動延緩的效果:
defer_transports = ondemand
3、 確定transport_maps參數指向我們的傳輸表:
transport_maps = hash:/etc/postfix/transport
4、編輯修改傳輸表,使得example.com網域的所有郵件都通過ondemand傳輸法來投遞:
example.com ondemand
5、運行postmap將傳輸表轉換成數據庫格式:
postmap /etc/postfix/transport
6、要求postfix重新讀取配置文件,使我們所做的改變開始生效:
postfix reload
現在,所有要寄到example.com網域的郵件都會被扣留在隊列里,直到你下達以下命令為
止:
postqueue -f example.com
暫緩投遞外地郵件
假設有一個小型辦公室網絡,他們與Internet之間沒有連接,而是由網管人員架設呢一
臺郵件服務器來接收內部員工寄到外界的郵件。網管人員希望能夠控制外地郵件的投遞
時間,讓postfix只有在有連接時才送出外地郵件。
1、 將smtp服務名稱列在main.cf的defer_transports參數中:
defer_transports = smtp
2、要求postfix重新加載配置文件,使我們的改變生效:
postfix reload
以后,每當辦公室網絡與Internet接通時,網管人員就可以使用postqueue -f命令來送
出所有外地郵件。
入站郵件網關
郵件網關是一種能收下郵件然后將其轉交給其他系統的郵件服務器系統。在在網絡術語
中,“網關"一詞的意義有兩個:一是物理上的含義,代表某個網絡到達另一個網絡的必
經通路;另一層含義是協議的轉換,將一種協議所傳達的信息以另一個協議傳到目標系
統。
郵件網關通常被設置在企業網絡與Internet之間,甚至與防火墻系統搭配在一起,以盡
可能減少需要直接訪問Internet的服務器數量。
假設有一個企業網絡,這家企業有多個部門,各部門都有自己的子網域,也有自己的內
部郵件服務器。網關系統gw.example.com負責收下企業網絡的所有郵件。假設人力資源
部門的郵件系統位于mail.example.com,此部門員工的郵件地址是
user@hr.example.com;業務部門的郵件系統位于mail2.example.com,他們的郵件地
址格式是user@sales.example.com。每個字網絡上的主機,應該分別從他們各自的內部
郵件服務器取信。郵件網關gw.example.com必須設置傳輸表,才能將收下的郵件交付給
正確的內部郵件服務器。
下列程序示范要如何設定gw.example.com,才能使它將郵件交給正確的內部服務器。
1、確定hr.example.com與sales.example.com的DNS mx記錄都指向gw.example.com網
關
2、編輯網關系統的main.cf配置文件,將兩個子網域列入relay_domains參數:
relay_domains = hr.example.com, sales.example.com
3、確定transport_maps參數指向正確的傳輸表“
transport_maps = hash:/etc/postfix/transport
4、編輯修改傳輸表內容,將各網域指向正確的內部服務器:
transport maps
hr.example.com relay:[mail.example.com]
sales.example.com relay:[mail2.example.com]
注意,內部郵件服務器的主機名是放在一對方括號內,這使得網關系統可跳過mx查詢,
而直接將郵件遞送到主機名稱所對應的ip地址。
5、重新加載配置文件,使改變生效:
postfix reload
鄭重建議你將mail與mail2的所有合法郵箱列表匯整成一個查詢表,放在gw系統上,并將
網關系統的relay_recipient_maps參數指向查詢表;否則,gw.example.com將會收下
許多垃圾郵件。
出站郵件網關
若郵件系統沒有足夠的信息或能力將郵件直接送達目的地,它可將郵件交給位于更有利
位置的其他系統,間接送到目的地。假設那兩個內部郵件系統不能直接訪問 Internet,
它們不能將字網絡上的用戶寄到外地的郵件直接遞送到目的地,但它們可以將所有外地
郵件都托付給網關系統,由網關代為遞送。下列步驟示范如何設定mail.example.com上
的postfix server,使它將收下的所有外地郵件都交給gw.example.com。
在開始設定內部郵件系統之前,請確定郵件網關已被設定成能接收內部郵件系統的轉發
要求。網關系統的mynetworks參數應該涵蓋內部郵件系統的所有 ip地址;此外,如果
網關系統使用了smtp ube過濾規則,請確定permit_mynetworks被列在過濾規則里。
1、在各部門的辦公室貼公告,告訴你的同事,要求他們設定MUA使用的內部郵件系統(mail1 mail2。。。)為smtp server
2、設定內部郵件系統(mail1與mail2)的mynetworks(或mynetworks_style)參數,確定子網絡上的全部客戶端系統都涵蓋在內。
3、編輯內部郵件系統的main.cf,將relayhost參數指向網關系統:
relayhost = 〔gw.example.com〕
4、重新加載postfix配置文件,使改變生效:
postfix reload
現在,所有送到mail.example.com的外地郵件,都會通過gw.example.com送到目的地。
UUCP、傳真以及其他投遞機制
postfix的在線文件描述了如何設定postfix使其將郵件交給傳真機系統以及如何使用postfix來架設UUCP網關。當你的postfix需要與任何特殊設備接軌時,這些例子提供了很好的參考。原則上,如果你需要在不同類型的系統或網絡之間架設網關,傳輸表提供了引導郵件到其他系統或設備的機制。
通過上面文章,我們可以清楚的知道Postfix郵件轉發的一些附屬知識,能更容易的掌握Postfix郵件轉發的功能。
【編輯推薦】