Postfix 建置郵件伺服器 ─ main.cf 設定參數說明

本文轉自這裡-2003/03/21 作者李忠憲,因為是很久的文章了,怕不見備份於此。以下僅節錄main.cf的參數設定部分。

postfix 最被人稱道的地方在於設定檔的可讀性很高(當然是跟 sendmail 比),而在主要設定檔 main.cf 中,需要自行定義的東西並不多,而且這些參數就算不去定義,依照預設值也可以運作:

由本機寄出的郵件要使用哪個網域名稱

在 sendmail 中,這個功能稱為網域偽裝,也就是說可以和主機名稱不同,例如:本機名稱為 mail.spps.tp.edu.tw,而寄出的郵件其寄信人欄位則可以使用 spps.tp.edu.tw。(須配合 DNS MX 紀錄使用)

myorigin=spps.tp.edu.tw

不使用簡略名稱時,設定如下:

myorigin=mail.spps.tp.edu.tw

由於主機名稱與網域名稱會被反覆引用在不同設定值,為了簡化設定,通常是定義成變數:

myhostname = mail.spps.tp.edu.tw
mydomain = spps.tp.edu.tw

#myorigin=$mydomain
myorigin=$myhostname (省略時,視同此設定)

當然以上變數也可以省略不定義,這種情況下 postfix 將使用 gethostname( ) 函數取得系統設定。如果是將 myorigin 省略,則視同為設定 $myhostname。

另外,如果本機是某個網域的 mail gateway,也就是說網域內的所有郵件伺服器,都必須把它們的郵件送到本機來處理,這種情形可以使用 masquerade_domains 讓 postfix 自動缺省寄信人欄位中的郵件主機名稱,例如:

masquerade_domains = $mydomain

假設 $mydomain 是 spps.tp.edu.tw,則無論信件是來自 stu.spps.tp.edu.tw 或 mail.spps.tp.edu.tw 都將會被改寫成 spps.tp.edu.tw。

如果你有某些帳號不想要讓 mail gateway 改寫寄信人欄位,可以設定底下的參數(預設不啟用):

masquerade_exceptions = root

啟用 masquerade_domains 功能只會改寫郵件標頭與信封裡的寄信人欄位,如果想要將收信人欄位一併改寫,可以設置底下的參數:

masquerade_classes = envelope_sender, envelope_recipient, header_sender, header_recipient

注意:這樣做將使得 mail gateway 無法寄信給下屬郵件伺服器,因為收信人欄位 @ 後面的郵件網域名稱會被改寫成 mail gateway 自己。

要接收來自哪些網路介面的郵件

底下參數是用來定義要處理來自哪些網路介面的郵件,當未定義時,預設會處理本機所有網卡(可以使用 ifconfig 觀察),如果定義成 localhost ,則只有 loopback 介面會接受郵件,也就是說只接受主控台或 WEB 介面寄出的郵件,不接受 MUA(outlook express)遞交的郵件:

inet_interfaces = localhost

設定成 all ,表示接受所有網路介面的郵件,這是預設值:

#inet_interfaces = all

設定成 $myhostname ,表示要透過 DNS 反查 IP,當本機 IP 是由 DHCP 指派,而 DNS 又未被設定成 DDNS ,將會出現不可預期的錯誤!

#inet_interfaces = $myhostname

底下範例將會在有 DNS A 紀錄的 IP 以及 loopback 介面上提供服務,在這裡我們可以發現 main.cf 中有許多設定可以設定超過一個值,將它們用逗號區隔開來就行了!(底下的設定範例不適用於 postfix 本身兼 Proxy/NAT 的場合)

#inet_interfaces = $myhostname, localhost

哪些網域的郵件是給本機的

定義在這裡的網域將被視為是 local 網域,換句話說寄到這些網域的郵件,會被接收並分信給本機使用者,相當於 sendmail 中的 local-host-name,當不使用 DNS MX 紀錄時,設定如下:

mydestination = $myhostname localhost.$mydomain

如果有使用 DNS MX 紀錄,需修改為:

mydestination = $myhostname localhost.$mydomain $mydomian

假設該伺服器在 DNS 上有多筆 A 或 CNAME 紀錄,則須將這些紀錄也寫上去,例如:

mydestination = $myhostname localhost.$mydomain $mydomian www.$mydomain ftp.$mydomain

哪些郵件要進行 relay

在 postfix 中針對轉信網域作處理的參數有兩個,一是用來定義區域網路網段的 mynetworks,另一個是 relay_domains,未被定義在這些 參數裡的網域,系統將拒絕轉信!

首先說明區域網路網段設定,相關參數共有兩個:mynetworks_style 和 mynetworks,前者用來宣告區域網路類型,subnet 代表是子網路,這也是預設值,當未作設定時,postfix 將會自行根據 ifconfig 上登記的 IP 和 網路遮罩作運算,自動求出子網路的範圍;如果設定成 class,則是不理會遮罩,自動信任同一個 class 等級的電腦,如果該伺服器使用撥接上網,這樣設定將使得同一家 ISP 的撥接用戶,都可以利用本伺服器轉信,這是非常危險的(除非你是 ISP 公司);設定成 host 則僅該單機可以寄信。

#mynetworks_style = class
#mynetworks_style = subnet
#mynetworks_style = host

mynetworks 用來設定區域網路的 IP 範圍,剛才設定的 mynetworks_style 將會被此參數取代,如果省略不設定,則由 mynetworks_style 來決定要 binding 的網卡:

mynetworks = 168.100.189.0/25

mynetworks = 168.100.189.10

除了上面範例,設定成網段或單機外,也可以指定多個網段(多重 NAT 網域時),或是使用設定檔(條列式),或使用雜湊表(makemap hash 或 postmap hash:)。

#mynetworks = 168.100.189.0/28, 127.0.0.0/8
#mynetworks = $config_directory/mynetworks
#mynetworks = hash:/etc/postfix/network_table

有關轉信網域設定,以上兩個參數就已經足以應付各種需求,但為了與 sendmail 相容,仍然保留 relay_domains 設定,與 sendmail 不同的是,如果該 relay_domain 在 DNS 上有定義 MX 紀錄,將會被 postfix 故意忽略,而當成 mynetworks 來處理,這是為了避免被利用作為廣告信回信站台;relay domain 對 sendmail 而言是雙向的,但對 postfix 而言則是單向的,只能寄信,而且不代收回信,因此如果要將本機設定成 mail gateway,請使用 mydestination,而不要使用 relay_domains(注意:很多介紹 postfix 的文章都犯此錯誤!)建議不要設置此參數,使用預設值「不啟用」。

#relay_domains = $mydestination

當本機為某台 mail gateway 的下屬伺服器時,必須要將所有寄出的信件交給 mail gateway 代轉,這時可以設定 relayhost 為該 mail gateway 的 IP。預設不啟用。

#relayhost = $mydomain
#relayhost = mg.spps.tp.edu.tw
#relayhost = [172.16.1.7]

哪些情況須通知管理員

所謂管理員是指 postmaster 信箱,請修改 alias 設定將 postmaster 對應成管理人員真正使用的信箱,以免警告郵件沒人理會堆積在伺服器上。

notify_classes 參數用來決定哪些情形下須通知管理員,預設值如下:

notify_classes = resource, software

可以使用的參數包含:

bounce當一般郵件無法交遞時,產生警告信給管理員(會附上原始郵件的內文)。注意:郵件無法交遞時,本來就會寄警告信給發信人,管理員收到的不過是複製版本。
2bounce當寄給發信人的警告信無法交遞時, 產生警告信給管理員。
delay當對方站台忙碌要求延遲遞送時,產生警告信給管理員(不會附上原始郵件)。
policy對方寄信的要求因為不符合安全規範已經被回絕(被規則過濾掉),此時會產生警告信給管理員。
protocol通訊協定錯誤時產生警告信通知管理員,我們比較感興趣的是對方使用了哪些不合法的 SMTP 命令。
resource系統資源短缺導致信件無法寄出,例如:硬碟 I/O 錯誤,此時會產生警告信給管理員。
software軟體安裝不全或程式錯誤造成的問題,產生警告信給管理員。

 Proxy/NAT 地址

當郵件伺服器位於 proxy 或 NAT 防火牆的後方時,此參數用來設定真實 IP,以避免因為 MX 紀錄與本機 IP 不同,將該信誤判成需 relay 到其它 MX 的郵件;當本機所查詢的 DNS 其回覆 MX 紀錄為虛擬 IP 時,此種現象將不會發生,因此在 NAT 虛擬網域中,架設內部專用 DNS 是非常重要的,請參考網路名稱系統一文的解說。預設值為:

proxy_interfaces =

當本機被設定成其它網域的備份 MX 時,如果未設置此參數,郵件會成為伺服器間互踢的皮球(去詢問其它網域的 DNS 查詢 MX 紀錄時,查到的必然是真實 IP,即使有架設內部專用 DNS 也沒用)。設定如下:

proxy_interfaces = 163.21.166.7

 

肆、main.cf UCE(unsolicited commercial email)過濾

過去這類的郵件被稱為垃圾郵件,比較正式的稱呼是 SPAM 郵件,postfix 則稱此種郵件為 UCE,有那麼一點縮小打擊範圍的含意,因此使用 UCE 過濾並無法解決其它問題郵件(例如:匿跡郵件、病毒郵件、郵件炸彈)所帶來的困擾,請不要期望過高。

儘管如此,與 sendmail 使用 access 來進行存取控管相比較,postfix 的 UCE 過濾顯然要精細得多,彈性也比較好,以外掛方式讀取過濾規則使得管理員能隨時修改設定,並將它模組化,可以說是 postfix 最大的優點。

如前所述,postfix 並不使用複雜的巨集語言來進行規則運算,而是採用較為單純的查表法來控制,但各位可不要小看它,它所支援的查表方式可謂琳瑯滿目,諸如:欄位比對( 純文字檔,欄位以逗號或空格或定位點區隔)、DBM 檢索、HASH 雜湊、NIS 查詢、RBL 查詢.....等,比對規則也可以選擇採用正規表示法(regexp)或是 perl 改良過的正規表示法(pcre)。

郵件標頭過濾

標頭過濾所過濾的對象,除了郵件標頭外,更擴大範圍到附加檔案的 MIME 標頭,使得過濾可以更精確的進行,而不會因規則過於模糊,殃及無辜的郵件。用過 procmail 的使用者要特別注意:附加檔案檔名或檔案類型是在此過濾,而非在郵件內文過濾。設定方式如下:

header_checks = regexp:/etc/postfix/header_checks
header_checks = pcre:/etc/postfix/header_checks

在外掛設定檔 header_checks(可以改用其它檔名)中,當字串比對命中時,可以採取各種處理動作,包括:

REJECT拒收信件。
OK跳過符合條件的標頭不作後續檢查,在 sendmail 中一旦 OK 該信件就會被接受,但在 postfix 中,OK 僅用來跳過該標頭的後續比對,萬一有其它標頭被拒絕,該封郵件一樣會被拒絕。
IGNORE從郵件刪除該標頭。
WARN附加警告訊息。
HOLD放回佇列,等候處理。
DISCARD直接將郵件丟棄,不回應拒收訊息。
FILTER transport.nexthop呼叫外掛過濾程式,進行郵件內文剖析過濾。外掛過濾程式可以是任何一種可執行的檔案,例如:shell script。該程式必須先定義在 master.cf 中,模擬成一個 socket 來執行(由 master 模組負責伺服監聽),當需要呼叫它執行時,postfix 中的 clearup 模組會將整封郵件丟到指定的 port 號,master 模組監聽到訊息後會執行相對應的過濾程式。

header_checks 的範例如下:

/^Subject: Make Money Fast/ REJECT
/^To: friend@public.com/ REJECT

如果未設置此參數,則郵件標頭過濾功能將會關閉不啟用,這是系統預設值。

郵件內文過濾

這是用來過濾所有標頭過濾沒檢查到的郵件內容,設定方式與前面相同:

body_checks = regexp:/etc/postfix/body_checks
body_checks = pcre:/etc/postfix/body_checks

如果未設置此參數,則郵件標頭過濾功能將會關閉不啟用,這是系統預設值。

用戶端過濾

當用戶使用 SMTP 通訊協定連上伺服器提出寄信請求時,針對用戶端輸入的指令進行過濾。在 Linux 系管師進階班講義 中已經詳細論及在 SMTP 連線階段中出現的各種欺騙伺服器的手法, postfix 提供非常詳盡的設定可以針對這些問題加以預防。使用用戶端過濾時,必須將 smtpd_delay_reject = yes 設定上去,這是系統預設值。當設定成 no 時,雖然效率較高,但是這樣做將會使得 HELO 網域偽裝、送信人信箱偽裝、寄信人信箱偽裝 以外的其它過濾功能失效。

用戶端過濾能夠使用的過濾功能,包括:

reject_unknown_client用戶端之 IP 或 Domain name 無法從 DNS 查詢驗證時,拒絕連線。
permit_mynetworks符合 $mynetworks 定義的用戶端允許連線。
reject_rbl_client從 SPAM 資料庫站台驗證用戶端網域名稱,符合時拒絕連線,當這種情況發生時,postfix 將會依照 default_rbl_reply 的設定回覆相關訊息,也可以依照 rbl_reply_maps 的設定根據不同用戶端給予不同訊息,事實上我們根本不需要設置此兩個參數(除非想將訊息改成中文)。這個參數必須放在最後面,當成過濾政策。
reject_rhsbl_client同上,使用另一種 SPAM 資料庫站台。這個參數必須放在最後面,當成過濾政策。
check_client_access根據 access 設定過濾存取權限,與 sendmail 中的 access 資料庫相容。 可以省略參數名稱,直接寫檔名,例如:hash:/etc/postfix/access。
permit允許連線,設定在過濾規則的最後面,表示未被之前的規則拒絕的用戶端一律允許連線,也就是採用黑名單政策。
defer延遲連線,設定在過濾規則的最後面,表示未被之前的規則拒絕或接受的用戶端,必須在稍後重新接受檢驗,也就是採用拖延政策。
reject拒絕連線,設定在過濾規則的最後面,表示未被之前的規則接受的用戶端一律拒絕連線,也就是採用白名單政策。
warn_if_reject被拒絕時產生警告訊息,這是用來測試過濾規則用的。
reject_unauth_pipelining當用戶端持續一直傳送 SMTP 命令時,拒絕其連線,這可以防止某些軟體一次寄送大量郵件。

使用用戶端過濾跟稍後會介紹的各種 SMTP 過濾,可以把規則依照前後順序編排成一組規則鍊(寫成一行,中間用逗號隔開或從逗號後面分行),由於組合出來的過濾功能並非單獨運作的,因此順序非常重要!

smtpd_client_restrictions = reject_rbl_client dialup.ecenter.idv.tw(台灣免費的 SPAM 資料庫:擋撥接發廣告信)

smtpd_client_restrictions = reject_rbl_client relays.ordb.org(國外免費的 SPAM 資料庫 :擋開放轉信的伺服器)

smtpd_client_restrictions = reject_rbl_client spam.ecenter.idv.tw(台灣免費的 SPAM 資料庫:擋寄廣告信的信箱)

smtpd_client_restrictions = hash:/etc/postfix/access, reject(採用白名單政策)

smtpd_client_restrictions = permit_mynetworks,reject_unknown_client

smtpd_client_restrictions = permit_mynetworks,hash:/etc/postfix/client_checks,reject_unknown_client,reject_unauth_pipelining

取得石牌國小垃圾信阻擋清單(每日更新)

是否要求使用 HELO 命令

當啟用此功能時,將要求用戶端進行連線時須先傳送 HELO 字串,稍後我們可以根據 HELO 字串傳回來的網域名稱進行過濾,由於某些寄信程式不會傳送 HELO 命令,這樣做有可能會使得這些用戶端程式無法正常寄信。預設值是:

smtpd_helo_required = no

HELO 命令過濾

用來過濾 HELO 命令後面的網域名稱是否允許其連線,能夠使用的過濾功能,包括:

reject_invalid_hostname網域名稱字串不符合文法時,拒絕其連線。
reject_unknown_hostname網域名稱無法從 DNS 查到 A 或 MX 紀錄時,拒絕其連線。
reject_non_fqdn_hostname網域名稱不是完整 FQDN 格式時,拒絕其連線。
check_helo_access根據 access 設定過濾存取權限。
其它 permit、defer、reject、warn_if_reject、reject_unauth_pipelining 請參考前面的說明。

設定範例:

smtpd_helo_restrictions = permit_mynetworks, reject_invalid_hostname

信封標頭欄位過濾

此功能用來過濾郵件的信封標頭是否符合 RFC 821 之規定,預設是不啟用此過濾。因為目前最多人使用的 MUA 是 outlook express,它會使用許多額外的標頭來進行郵件控制,例如:大家熟知的要求回覆功能,如果啟用此參數將使得這些信件被拒絕無法寄出。

strict_rfc821_envelopes = yes

寄信人過濾

此功能並非過濾郵件標頭裡的寄信人欄位,而是過濾 mail from: 命令後面的字串,預設值是不過濾,但由於廣告信寄信程式為了能順利寄信,經常會偽造此字串,建議應該啟用。

可以使用的選項包括:

reject_unknown_sender_domain寄信人的網域名稱無法從 DNS 查詢驗證時,拒絕連線。
reject_rhsbl_sender寄信人信箱如果被紀錄在 SPAM 資料庫站台,就拒絕他連線。
check_sender_access根據 access 設定過濾存取權限。
reject_non_fqdn_sender寄信人的網域名稱不是完整 FQDN 格式時,拒絕其連線。
reject_sender_login_mismatch寄信人信箱與登入的帳號不吻合時,拒絕其連線。須配合 SASL 使用者認證機制使用(SMTP AUTH)。

配合 smtpd_sender_login_maps 指定的對應表,可以讓登入帳號與使用的信箱作對應,例如:shane 帳號可以用 webmaster 信箱寄信。

其它 permit、defer、reject、warn_if_reject、reject_unauth_pipelining 請參考前面的說明。

設定範例如下:

smtpd_sender_restrictions = reject_rhsbl_sender dsn.rfc-ignorant.org(國外免費的 SPAM 資料庫:擋寄廣告信的信箱)

smtpd_sender_restrictions = hash:/etc/postfix/access, reject_unknown_sender_domain

smtpd_sender_restrictions = permit_sasl_authenticated,reject_unknown_sender_domain,reject_non_fqdn_sender

收信人過濾

此功能並非過濾郵件標頭裡的收信人欄位,而是過濾 rcpt to: 命令後面的字串,預設值是不過濾,但由於廣告信寄信程式為了能順利寄信,經常會偽造此字串,建議應該啟用。

可以使用的選項包括:

permit_auth_destination收信人網域符合 $relay_domains、$mydestination、$inet_interfaces、$vitual_alias_domains、$virtual_mailbox_domains 的定義時,接受連線。
reject_unauth_destination收信人網域不符合上述設定時,拒絕連線。
permit_mx_backup當從 DNS 上查到本機為收信人網域的備份 MX 時,接受連線。使用此功能有安全漏洞,可以配合 permit_mx_backup_networks = 172.16.0.0/16 來檢查主要 MX 是否在該網段內,來加強過濾功能(避免被不信任的網域設定為轉信 MX)。
check_relay_domains允許代收要給 relay_domians 的信件。
check_recipient_access根據 access 設定過濾存取權限。
check_recipient_maps

當收信人網域不符合 permit_auth_destination 之要求,或是收信人信箱不符合 $local_recipient_maps、$virtual_alias_maps、$virtual_mailbox_maps、$relay_recipient_maps 的定義時,拒絕連線。此參數可以放在收信人過濾規則的最後面,當作過濾政策。

reject_unknown_recipient_domain收信人的網域名稱無法從 DNS 查詢驗證時,拒絕連線。
reject_rhsbl_recipient收信人信箱如果被紀錄在 SPAM 資料庫站台,就拒絕他連線。
reject_non_fqdn_recipient收信人的網域名稱不是完整 FQDN 格式時,拒絕其連線。
其它 permit、defer、reject、warn_if_reject、reject_unauth_pipelining 請參考前面的說明。

設定範例如下:

smtpd_recipient_restrictions = permit_mynetworks, reject_unauth_destination,reject_non_fqdn_recipient

ETRN 命令過濾

用來過濾哪些網域或哪些用戶端,可以使用 ETRN 命令。ETRN 命令用來一次處理大量郵件,當某個用戶端使用 ETRN 時,有時候會影響到其它用戶寄信的效能,通常只有撥接用戶、幫撥接用戶轉信的 mail gateway、郵件討論群組(mailing list)或電子報發行站台,需要使用此功能。postfix 的預設值是所有用戶端都可以使用 ETRN 命令。

能使用的特殊參數只有 check_etrn_access,其餘與用戶端過濾參數相同,請自行查閱前文。設定範例如下:

smtpd_etrn_restrictions = permit_mynetworks, hash:/etc/postfix/etrn_access, reject