需求:需要一部 SMTP 寄信主機可供論壇網站寄信,免費的 Gmail 或 ISP 提供的 SMTP 主機都會有寄送數量的限制,而其他提供可大量寄信的雲端服務商,例如 Mailchimp、Sendgrid 等收費都不便宜。
目的:使用 postfix 架設一部自有的 SMTP 寄信主機。
說明:
關鍵參數定義:
#> 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 憑證,必須先將 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 主機與發信電腦或發信系統加密連線。
在 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。
有了 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
TIP:
雖然系統會用 sasl 作郵件認証,不過 saslauthd 服務可以不用啟動。
mail.log 如服務正常運作,不應該出現錯誤訊息;用戶端在寄信後,這裡如果顯示 ... doesn't resolve to XXX.XXX.XXX.XXX 的錯誤,這是正常的,原因是主機所在的網路無法反查用戶端的 FQDN,這不會影響寄信功能。
關於 SPF、DKIM 與 DMARC 的運作原理,以及如何保護郵件被假冒或竄改,參閱下述連結
SPF 記錄的工作原理是,在「寄件者」郵件位址所在的網域設定裡,新增一筆 SMTP 主機 IP,用途是允許該 IP 使用這網域作為發信時的「寄件者」。
在 DNS Zone 新增一筆 TXT 記錄,內容為:
123.123.123.123 是 SMTP 主機位址
如果有多個 IP 位址,要用空格隔開,例如 ip4:123.123.123.123 ip4:111.111.111.111
關於 SPF 更多的說明,請參閱 Google: 使用 SPF 對電子郵件寄件者進行授權
採用 DomainKeys Identified Mail (DKIM) 標準有助於防止外寄電子郵件遭到假冒。
「假冒電子郵件」意指變更電子郵件內容,讓郵件顯示非真實寄件來源的寄件者或寄件地址。假冒是在未經授權的情況下使用電子郵件,這種情形十分常見,因此部分電子郵件伺服器會要求設定 DKIM,以免電子郵件遭到假冒。
DKIM 會在所有外寄郵件的標頭加上加密簽名,收到這些郵件的電子郵件伺服器則會使用 DKIM 來解密郵件標頭,並將它與 DNS 上的公鑰做匹配,以確認郵件寄出後並未遭人竄改。
DKIM 有一組配對的公、私鑰,私鑰設定在 SMTP 主機上,公鑰則設定在公開的 DNS Zone 上。
在 DNS Zone 新增一筆 TXT 記錄,內容為:
TIP:
Value 的值與 p=公鑰,內容都在建立金鑰步驟時產生的檔案 mail.txt 裡。
關於 DKIM 更多的說明,請參閱 Google: 使用 DKIM 驗證電子郵件
垃圾郵件發佈者可能會假造電子郵件的「寄件者」地址,讓人誤以為這些郵件是您網域中某位使用者所寄送。如果這類發佈者冒用您網域的名義傳送垃圾郵件,不僅會損害網域的聲譽,收件者也可能將假造郵件連同真正從您網域寄出的郵件一併標示為垃圾內容。
為了防堵這種濫發垃圾郵件的情形,許多郵件系統例如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 管理控制台新增完 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