設定 postfix 為寄信主機

情境說明

需求:需要一部 SMTP 寄信主機可供論壇網站寄信,免費的 Gmail 或 ISP 提供的 SMTP 主機都會有寄送數量的限制,而其他提供可大量寄信的雲端服務商,例如 Mailchimp、Sendgrid 等收費都不便宜。

目的:使用 postfix 架設一部自有的 SMTP 寄信主機。

說明:

關鍵參數定義:

安裝設定 container
git clone https://github.com/a-lang/docker-postfix-smtp.git 
docker pull alangtw/postfix-smtp:trusty

修改啟動參數

run.sh:

-e maildomain=mydomain.com -e smtp_user=alang@mydomain.com:thispassword \
建立 SSL 自我簽署憑證

為了要新增 SSL 憑證,必須先將 container 啟動。

注意:此時 container 雖然啟動,但缺少一些需要的憑證與金鑰檔,所以系統還無法正常運作。

啟動 container

chmod 0755 *.sh
./run.sh

建立 SSL 憑證檔
NOTE: 在 Host 執行以下指令

docker exec -it postfix openssl req -x509 -nodes -days 3650 -newkey rsa:2048 \
-keyout  /etc/postfix/certs/smtp-mydomain-com.key \
-out /etc/postfix/certs/smtp-mydomain-com.crt

Tip:

憑證檔 .crt 與 .key 會儲存在以下路徑:
- Host OS: data/certs
- Container OS: /etc/postfix/certs

SSL 憑證是用在 SMTP 主機與發信電腦或發信系統加密連線。

建立 DKIM 金鑰

在 Host 執行以下指令

docker exec -it postfix sh -c "cd /etc/opendkim/domainkeys && opendkim-genkey -t -s mail -d mydomain.com"

Tip:

私鑰檔 .private 與公鑰檔 .txt 會儲存在以下路徑:
- Host OS: data/domainkeys
- Container OS: /etc/postfix/domainkeys

.txt 內有公鑰字串,這要設定在 DNS Zone。

重啟 container

有了 SSL 憑證與 DKIM 金鑰,需重啟 container 以套用這些設定。

./stop.sh
./run.sh

到這裡,主機設定都已完成。

檢查幾個 container 的服務
postfix:

#> docker exec -it postfix ps -ef | grep postfix
root        54    51  0 07:11 ?        00:00:00 /bin/bash /opt/postfix.sh
root       125     1  0 07:11 ?        00:00:00 /usr/lib/postfix/master
postfix    127   125  0 07:11 ?        00:00:00 pickup -l -t unix -u
postfix    128   125  0 07:11 ?        00:00:00 qmgr -l -t unix -u

opendkim:

#> docker exec -it postfix ps -ef | grep opendkim
opendkim    55    51  0 07:11 ?        00:00:00 /usr/sbin/opendkim -f
opendkim    66    55  0 07:11 ?        00:00:00 /usr/sbin/opendkim -f

/var/log/mail.log:

#> docker exec -it postfix tail -20 /var/log/mail.log
Jan  2 07:11:14 a037fd779eaa opendkim[66]: OpenDKIM Filter v2.9.1 starting (args: -f)
Jan  2 07:11:15 a037fd779eaa postfix/master[125]: daemon started -- version 2.11.0, configuration /etc/postfix

雖然系統會用 sasl 作郵件認証,不過 saslauthd 服務可以不用啟動。

Tip: mail.log 如果服務正常運作,不應該出現錯誤訊息;用戶端在寄信後,這裡如果顯示 ... doesn't resolve to XXX.XXX.XXX.XXX 的錯誤,這是正常的,原因是主機所在的網路無法反查用戶端的FQDN,這不會影響寄信功能。

防止寄出信件成為垃圾信而遭阻擋

關於 SPF、DKIM 與 DMARC 的運作原理,以及如何保護郵件被假冒或竄改,參閱下述連結

新增 SPF 記錄

SPF 記錄的工作原理是,在「寄件者」郵件位址所在的網域設定裡,新增一筆 SMTP 主機 IP,用途是允許該 IP 使用這網域作為發信時的「寄件者」。

在 DNS Zone 新增一筆 TXT 記錄,內容為:

Tip:

123.123.123.123 是 SMTP 主機位址

如果有多個 IP 位址,要用空格隔開,例如 ip4:123.123.123.123 ip4:111.111.111.111

關於 SPF 更多的說明,請參閱 Google: 使用 SPF 對電子郵件寄件者進行授權

新增 DKIM 記錄

採用 DomainKeys Identified Mail (DKIM) 標準有助於防止外寄電子郵件遭到假冒。

「假冒電子郵件」意指變更電子郵件內容,讓郵件顯示非真實寄件來源的寄件者或寄件地址。假冒是在未經授權的情況下使用電子郵件,這種情形十分常見,因此部分電子郵件伺服器會要求設定 DKIM,以免電子郵件遭到假冒。

DKIM 會在所有外寄郵件的標頭加上加密簽名,收到這些郵件的電子郵件伺服器則會使用 DKIM 來解密郵件標頭,並將它與 DNS 上的公鑰做匹配,以確認郵件寄出後並未遭人竄改。

DKIM 有一組配對的公、私鑰,私鑰設定在 SMTP 主機上,公鑰則設定在公開的 DNS Zone 上。

在 DNS Zone 新增一筆 TXT 記錄,內容為:

Tip:

Value 的值與 p=公鑰,內容都在建立金鑰步驟時產生的檔案 mail.txt 裡。

關於 DKIM 更多的說明,請參閱 Google: 使用 DKIM 驗證電子郵件

新增 DMARC 記錄

垃圾郵件發佈者可能會假造電子郵件的「寄件者」地址,讓人誤以為這些郵件是您網域中某位使用者所寄送。如果這類發佈者冒用您網域的名義傳送垃圾郵件,不僅會損害網域的聲譽,收件者也可能將假造郵件連同真正從您網域寄出的郵件一併標示為垃圾內容。

為了防堵這種濫發垃圾郵件的情形,許多郵件系統例如Gmail 現在支援「網域型郵件驗證、報告與一致性」(DMARC) 機制。您可以使用 DMARC 定義政策,決定 Gmail 如何處理以您網域名義寄出的垃圾電子郵件。

注意:必須先完成 SPF 與 DKIM 設定,才能再設置 DMARC。

在 DNS Zone 新增一筆 TXT 記錄,內容為:

Tip:

p=none,對於可疑郵件,不採取任何處置
rua,回報 DMARC 的活動報告至該郵件位址

關於 DMARC 更多的說明,請參閱 Google: 使用 DMARC 管理可疑電子郵件

驗證與測試寄信

如何驗證寄信功能與每個安全協議是否生效,大概是文章中最困難以及最花時間的步驟。

驗證寄信功能

1. 用 openssl 測試 SMTP 帳號認證,將帳號密碼轉換成 base64 編碼

user: alang@mydomain.com
pass: yourpass

$> echo -ne '\000alang@mydomain.com\000yourpass' | openssl base64
AGFsYW5nQG15ZG9tYWluLmNvbQB5b3VycGFzcw==

# 另一個 perl 的方法
# 帳密如有包含 @ 字元,必須加上 \
$> perl -MMIME::Base64 -e \ 'print encode_base64("\0alang\@mydomain.com\0yourpass");' 
AGFsYW5nQG15ZG9tYWluLmNvbQB5b3VycGFzcw==

連線 smtp 主機

$> openssl s_client -quiet -starttls smtp -connect smtp.mydomain.com:587
depth=0 C = TW, ST = TY, L = TaoYuan, O = RAIDA, OU = Admin, CN = smtp.osslab.tw
verify error:num=18:self signed certificate
verify return:1
depth=0 C = TW, ST = TY, L = TaoYuan, O = RAIDA, OU = Admin, CN = smtp.osslab.tw
verify return:1
250 DSN

輸入帳號密碼的 base64編碼

AUTH PLAIN AGFsYW5nQG15ZG9tYWluLmNvbQB5b3VycGFzcw==

如果通過認証,會出現

235 2.7.0 Authentication successful

離開,輸入 quit。

2. 寄測試信到 Gmail 信箱

為何要用 Gmail 作測試信的收信位址?因為 Gmail 郵件系統已經整合了 SPF/DKIM/DMARC 郵件安全協議檢查,而且很容易得知檢查的結果。

Thunderbird SMTP 設定:

Tip:

連線安全性若使用 SSL/TLS,會無法成功連線主機。

如果連線成功,Thunderbird 會彈出密碼輸入的視窗,密碼必須與 container 啟動參數裡的相同。

因為使用 self-signed 憑證,所以必須檢驗憑證時,需要加入例外名單,參閱附圖 thunderbird-smtp.png 。

驗證 DNS 記錄

從 DNS 管理控制台新增完 TXT 記錄後,要驗證是否生效很簡單。

找一部可以上網的 Linux 桌機,分別執行

# SPF record
$> dig +short TXT mydomain.com

# DKIM key
$> dig +short TXT mail._domainkey.mydomain.com

# DMARC
$> dig +short TXT _dmarc.mydomain.com






Revision #8
Created 15 March 2021 02:01:42 by Admin
Updated 4 May 2023 10:24:44 by Admin