iT邦幫忙

2026 iThome 鐵人賽

DAY 15
0

https://ithelp.ithome.com.tw/upload/images/20260822/201812846lgzWmDSmU.png

郵件服務器 (mail server )
首先跟大家道歉一下,撥接所取得的固定ip,沒有辦法架設一個完全獨立自主的郵件服務器,因為他沒有反向解析。這不是說這樣,就沒辦法架設自己的服務器,只是要依賴第三方的服務,這跟我們要的自主掌控不符。用撥接取得的固定ip的朋友,請 google 或 AI 問:本機架設收信服務 + 透過第三方 SMTP Relay(中繼轉發)寄信

為什麼要自己的郵件服務器?

因為不管 gmail, outlook.com .... 用別人家的信箱,有三件事永遠不是自己決定的:
帳號哪天被鎖是別人決定的,
信被丟進垃圾桶是別人決定的,
寄件人能不能是自己的網域也是別人決定的(當然,付錢就可以)

我們要讓機房裡每一台機器都可以寄信 —— 備份報告、憑證到期、掃描結果,如果全部都依賴第三方的信箱,風險有點高。

動手之前先確認的兩件事

第一個:不是所有網路都能寄信。有些硬體路由器會封掉對外的 25 埠,所以叫 claude 檢查一下,你的網路有沒有封鎖 25。用自然語言,非常口語,問 claude code: 檢查這臺機器,對外25 Port 有沒有被封鎖

claude code 的回答:

srv80 (HQ) TCP/25 連通性檢查報告
檢查時間:2026-08-22 11:19:27 CST
受檢主機:srv80 / HQ,192.168.0.80(另有 docker bridge 172.17.0.1)
對外出口 IP:xxx.xxx.xxx.xx(PTR = xxx-xxx-xxx-xx.hinet-ip.hinet.net)
結論
25 port 沒有被擋,對外 SMTP 完全通。 ISP 未封鎖 TCP/25,本機防火牆也沒有相關規則。
檢查明細
檢查項目
結果
本機有無服務 listen 25
❌ 無(ss -tlnp 無 :25)****
本機 MTA 狀態
postfix / exim4 / sendmail / nullmailer 全 inactive
iptables OUTPUT 針對 dport 25
無相關規則
ufw
未安裝 / 不適用
出站 → gmail-smtp-in.l.google.com:25
✅ 220 mx.google.com ESMTP
出站 → aspmx.l.google.com:25
✅ 220 mx.google.com ESMTP
出站 → hotmail-com.olc.protection.outlook.com:25
✅ 220 ...outlook.com Microsoft ESMTP
出站 → 192.168.0.66:25(mailcow)
✅ 220 mail.candle.com.tw ESMTP Postcow

SMTP 握手實測(未送出信件內容)
流程為 EHLO → MAIL FROM → RCPT TO → RSET → QUIT,沒有進入 DATA 階段,未寄出任何信:

怎麼樣!這個同事夠專業吧!

第二個:位址反解是否設定好。
正向查詢是:人家查 mail.iron30.com,會指到 1.2.3.4,自己設定就好。
反向查詢是:人家查 1.2.3.4,會回什麼名字,必須要能回 : mail.iron30.com,這是要要跟電信商申請。
如果兩邊對不上,這信件直接被擋掉,而這是唯一一件「設定檔裡怎麼寫都沒用」的事。
如何申請?問 google, gemini。

機器規格與要開的Port:

新開一台虛擬機,4 vCPU、8GB 記憶體、60GB 磁碟再加 4GB 置換空間,Ubuntu 24.04,內網位址 192.168.0.34。信件本身不佔空間,佔空間的是紀錄檔與病毒特徵庫。線上那台跑到現在,磁碟用掉 16G。

收信 25、寄信 465 與 587、收信匣 993、老派的 995 與 110、還有讓客戶端設定過濾規則的 4190,加上網頁介面的 80 與 443。80 那個不能省:憑證是靠它驗證的,關掉了憑證就續不了,然後某一天早上所有人的信件軟體會同時跳出憑證錯誤。

開始安裝 mailcow 這套郵件服務器。

ssh 連到 hq,切換到 /opt/claude-working,執行 claude code:
告訴 claude code :

在 192.168.0.20 建一台 Ubuntu 虛擬機,IP:192.168.0.34,這台專門收信寄信。

一、規格:4 個虛擬核心、8 GB 記憶體,系統碟 60 GB,另外配 4 GB 置換空間。
    主機名稱設成 mail.iron30.com。
    ⚠️ 這個名字後面要跟反解對得起來,不要隨便取。

二、動工之前先驗兩件事,任何一件不過就停下來告訴我,不要往下裝:
    1. 從這台連得到外面的 25 埠嗎?
    2. 1.2.3.4 的反解是不是 mail.iron30.com?
    ⛔ 這兩件事等裝完才發現不行,前面全部白做。

三、用 mailcow 裝,不要一個元件一個元件自己接。

四、對外的埠分兩路,不要全部直接轉進來:
    1. 80 與 443 轉到反向代理 192.168.0.11,由它按網域轉進來。
    2. 25、465、587、993、995、110、4190 由路由器直接轉到這台。
    ⛔ 第二組不要交給反向代理轉,來源位址會全部變成代理,擋垃圾信就廢了。

五、憑證只能有一個申請人:把這台自己的自動續約關掉,改由反向代理那台申請,
    再把憑證同步進來、重啟收發信的服務。
    ⚠️ 驗的時候要把網域名稱一起送出去,不然你看到的不是客戶端拿到的那一份。

六、DNS 開這幾筆,開完自己查一次確認生效:
    - A    mail.iron30.com     → 1.2.3.4
    - MX   iron30.com          → 10 mail.iron30.com
    - TXT  iron30.com          → v=spf1 ip4:1.2.3.4 ~all
    - TXT  iron30._domainkey.iron30.com
                               → 裝完從管理介面把公鑰抄出來,
                                 ⛔ 不要自己編一組
    - TXT  _dmarc.iron30.com   → v=DMARC1; p=quarantine; pct=100;
                                 rua=mailto:bob@iron30.com;
                                 ruf=mailto:bob@iron30.com; fo=1
    ⚠️ 反解那一筆不在我的 DNS 上,那是要跟電信商申請的,你只要告訴我對不對得上。

七、對外能寄信的只有這一台。內網其他機器要寄信一律走它,而且要有帳號密碼。
    ⛔ 不要為了方便把整個內網放進信任名單,那叫開放轉發。

規則:
- 做完把這台寫進 machines.md 和 machines/mail.md,對外開了什麼寫進 exposure.md。
- ⛔ 管理介面的預設密碼裝完立刻改掉,改完告訴我,不要寫進任何檔案。

裝了哪些東西?

18 個容器:
收信與寄信的 postfix、放信與提供收信匣的 dovecot、評分擋垃圾信的 rspamd、掃病毒的 clamav、網頁信箱 sogo、自己的 DNS 查詢 unbound、自動封鎖的 netfilter、自動續憑證的 acme,還有資料庫、快取與前面那層 nginx。
這些東西一台一台自己裝、自己接起來,是好幾週的事;真正省下來的不是安裝時間,是「誰要跟誰講話」那張圖已經有人畫好了。

我自己覺得最有價值的是這一段 :

    - TXT  iron30.com          → v=spf1 ip4:1.2.3.4 ~all
    - TXT  iron30._domainkey.iron30.com
                               → 裝完從管理介面把公鑰抄出來,
                                 ⛔ 不要自己編一組
    - TXT  _dmarc.iron30.com   → v=DMARC1; p=quarantine; pct=100;
                                 rua=mailto:bob@iron30.com;
                                 ruf=mailto:bob@iron30.com; fo=1

為什麼這一段我覺得很有價值?因為我曾經花了非常多的時間,去學會如何設定它。
之前自己安裝 mail server,為了這3個設定,弄得雞飛狗跳,大概花了好幾個小時,google搜尋,找安裝指南,反覆測試...當然功力也增加不少。可是如今:AI 三行,3個段落,我沒有叫他做,他自己就弄好了。
這感覺很複雜....

第一次登入
從: mail.iron30,com/admin 進去。
預設帳號密碼是:admin/moohoo,請記住:登錄後請第一件事就是改掉密碼。

https://ithelp.ithome.com.tw/upload/images/20260822/20181284iy2zHAP8It.png

登入後檢查一下:

  1. 版本。管理介面第一頁就寫著版本與「系統已經是最新版本」,請務必保持最新版。
  2. 系統時間及時區:是否對。
  3. 要注意的是硬碟空間,一般不會有問題。

https://ithelp.ithome.com.tw/upload/images/20260822/20181284siDGGz7yFd.png

相關設定,已經自動填好了。底下再說明。

https://ithelp.ithome.com.tw/upload/images/20260822/20181284LwnylIPk62.png

這個我最喜歡,fail2ban,抓人用的。幫我抓一堆吃飽飯沒事幹,嘗試登入的 ip。
已經封鎖一大堆了.....

https://ithelp.ithome.com.tw/upload/images/20260822/20181284EFKGfpeXDV.png

https://ithelp.ithome.com.tw/upload/images/20260822/20181284iP8peZ215r.png

web mail 頁面。從 :mail.iron30.com/sogo 登入。

https://ithelp.ithome.com.tw/upload/images/20260822/20181284HXbIWrWRLa.png

科普一下,有關: SPF,DKIM,DMARC

SPF: - TXT:v=spf1 ip4:1.2.3.4 ~all。
v=spf1:
宣告此 TXT 記錄遵循 SPF 版本 1 規格(目前標準格式)。
ip4:1.2.3.4 :
明確授權 IPv4 地址為 1.2.3.4 的伺服器代表該網域寄信。收件端驗證時會回傳 Pass(通過)。
~all(SoftFail 軟性失敗):
規範未在記錄中列出的所有其他 IP:
意義:若郵件來自 1.2.3.4 以外的來源,標記為「軟性失敗」(SoftFail)。
常見處理:收件伺服器通常仍會接收該郵件,但會降低其信任度,可能將其標記為垃圾郵件(Spam)或放入垃圾信箱。
~all 與 -all 的常見差異:
~all SoftFail 容許接收,但通常直接歸類為垃圾郵件(適合過渡期或設定測試)。
-all HardFail 嚴格阻擋,收件端通常會直接退信(適合確認所有發信 IP 皆已列入後的正式環境)。

DKIM:- TXT iron30.domainkey.iron30.com
運作原理:
寄件端簽名:寄件伺服器使用保密的「私鑰(Private Key)」對信件內容與標頭運算產生數位簽章,並附加在郵件的 DKIM-Signature 標頭中。
收件端驗證:收件伺服器收到信件後,依據標頭指示向該網域的 DNS 查詢並取得「公鑰(Public Key)」,用來解密並驗證簽章是否相符。

各組成部分拆解
TXT:DNS 記錄類型,用來存放 DKIM 相關的公鑰或簽章宣告。
iron30(DKIM Selector / 選擇器):由發信系統指定的標識符(Selector)。一組網域可同時設定多個 DKIM 金鑰(例如用於不同郵件服務商或定期輪替金鑰),收件端會依據信件標頭中的 s=iron30 找到此特定記錄。
._domainkey.:
DKIM 標準規定的固定命名空間。所有 DKIM 公鑰記錄都必須掛在 _domainkey 子網域之下。
iron30.com:
寄件網域(Domain),對應信件標頭中的 d=iron30.com。

實際完整的 TXT 值範例:
此 DNS 節點的 TXT 內容通常會包含公鑰資訊:
Plaintext
v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC...

v=DKIM1:宣告使用 DKIM 版本 1。
k=rsa:指定金鑰演算法(通常為 RSA 或 Ed25519)。
p=...:公開金鑰(Public Key),收件伺服器會用此公鑰解開郵件 Header 上的數位簽章,確認信件是否在傳輸過程中遭到修改。

DMARC:- TXT _dmarc.iron30.com → v=DMARC1; p=quarantine; pct=100;
rua=mailto:bob@iron30.com;
ruf=mailto:bob@iron30.com; fo=1

DMARC是建立在 SPF 與 DKIM 之上的進階郵件安全防護協定。 (所以前面兩個一定要設好。)
SPF 只驗證信封發件人(Envelope From / Return-Path),惡意寄件者常在使用者看到的 From: 欄位偽造合法網域。DMARC 強制要求 From: 的網域必須與 SPF 或 DKIM 驗證通過的網域完全一致或子網域對齊。

各參數詳細拆解

dmarc.iron30.com:DMARC 記錄固定的 DNS 主機名稱,所有 DMARC TXT 記錄皆須建立在 dmarc. 底下。
v=DMARC1:宣告此記錄遵循 DMARC 版本 1(必填欄位,且必須放在第一位)。
p=quarantine(處置原則 / Policy):當郵件未通過 SPF 或 DKIM 的「對齊(Alignment)」驗證時,要求收件端採取的動作:
quarantine(隔離):將可疑郵件直接送入垃圾郵件資料夾(Spam/Junk)或進行隔離處理,而非直接退信。
(其他常見值:p=none 僅監控不動作、p=reject 直接拒收退信)。
pct=100(執行百分比 / Percentage)
此 DMARC 策略套用於 100% 的失敗郵件(即所有未通過驗證的信件都會執行 quarantine)。
rua=mailto:bob@iron30.com(彙總報告 / Aggregate Reports)
指定接收「每日彙總統計報告(XML)」的信箱。各大收件服務商(如 Gmail、Outlook)會定期寄送分析報告,說明來自該網域的寄信量、通過/失敗比例及來源 IP。
ruf=mailto:bob@iron30.com(鑑識報告 / Forensic Failure Reports)
指定接收「即時失敗詳情報告(Forensic Reports)」的信箱。每當有單封信件驗證失敗,收件伺服器會嘗試即時寄送一份詳細分析(包含信件標頭)。
fo=1(失敗回報選項 / Failure Option)
定義觸發 ruf 鑑識報告的條件:
fo=1:只要 SPF 或 DKIM 任一機制驗證失敗或未對齊,就產生並寄送報告。
(若為 fo=0,則需 SPF 與 DKIM 兩者「同時失敗」才回報)。*

DMARC 裡面 rua 那個信箱:從設好的那天起,全世界的大型郵件商每天會告訴你,有誰用你的網域名義在寄信、驗過了沒有、他們怎麼處置。這是唯一一個能從外面看自己網域的視角,而且免費。

https://ithelp.ithome.com.tw/upload/images/20260822/20181284dYzkvgW67M.png

驗收

驗收不是「有沒有收到信」,要檢查伺服器紀錄裡的三行:認證的帳號是誰、評分系統有沒有給「已認證」的加分、簽章有沒有蓋上去,最後對外投遞回來的那個 250。兩台機器一台一台送測試信、一台一台核對過,才算收工。

可以收發信了,來告訴系統:

把控制台的通知加寄信這條。

一、去 192.168.0.34 開一個只給控制台用的信箱,hq@iron30.com,只用來寄。
    ⛔ 不要拿我自己那個信箱的帳號密碼給它用,那是我在收信的。

二、密碼寫進控制台自己的設定檔,權限 600。
    ⛔ 不要寫進任何會進版控的檔案,也不要印在畫面上。

三、寄的方式是連 465,先登入再寄。
    ⛔ 不要圖方便直接丟 25 —— 沒認證的信不會被簽章,對方那邊一樣過不了。

四、連線寫網域名稱 mail.iron30.com,不要寫 192.168.0.34。
    憑證上寫的是名字,拿位址去連驗不過。
    ⚠️ 如果從控制台連不到那個名字,在控制台的 hosts 檔把它指到 192.168.0.34。

五、寄件人名稱:用 HQ維運中心 。
    ⚠️ 中文的顯示名稱要單獨編碼,位址留在外面 ——
       整欄一起編碼,對方會找不到位址而把信退回來。

六、收件人:fishbob123@gmail.com ,副本:admin@iron30.com,要真的送出去,不是只寫在表頭上。

七、每天早上七點半掃一次,八點把前一天的清單寄出來;
    掃到嚴重的問題當下另外寄一封,不要等到隔天早上。

規則:
- 密碼沒設的時候,畫面上要看得出來這條路是關的。⛔ 不要安靜地跳過。
- 做完寄一封測試信,去 192.168.0.34 的紀錄裡把三件事抄回來給我:
  認證的是哪個帳號、有沒有被算成已認證、簽章有沒有蓋上去。
  ⛔ 「我這邊顯示寄出了」不算驗收。

ok. 每天的報告完成。

https://ithelp.ithome.com.tw/upload/images/20260822/20181284bBrrTxkoDj.png

這信箱第一天送了個報告,說:那兩台虛擬化主機,每天寄備份報告,但是,驗證結果:沒有 SPF、簽章失敗,被丟進垃圾桶。

去機器上看,真相比報告更糟。報告說「丟進垃圾桶」,實際去那兩台機器上翻紀錄,是直接被退信,理由是這個位址沒有被授權直接寄信給他們。不是進垃圾桶,是根本沒收。換句話說,那些備份報告從來沒有被送到過。

最難發現的部分在這裡:機器本機的紀錄確實寫著寄送成功。那個成功只是「交給了本機的轉送程式」,不是「對方收下了」。一件事有沒有做成,不能問執行的那一步,要問結果的那一端。這條規矩在這座機房裡已經踩過不只一次。

講一下要注意的:

信譽

信譽不是設定檔裡的某個選項,是別人幫你記的一筆帳。它由這幾樣東西組成:這個位址過去寄過什麼、反解對不對得上、那三張紀錄齊不齊、退信率高不高、有多少人按了檢舉。一個全新的IP還沒有歷史,那不叫乾淨,叫沒有信用。所以第一天不要一次寄一千封,馬上被認定為垃圾信件。先慢慢跑,寄信給 gmail,outlook.com,來來回回一兩周,建立信譽。

實戰:

這台機器不對外宣傳,沒有網站連過去,信箱也只有幾個。最近 48 小時的連線紀錄:1248 次連入,來自 110 個不重複的位址。其中 329 次是還沒等到招呼語就先開口 —— 正常的信件伺服器會等,搶著講話的幾乎都是程式。491 次的來源當場就被送到在黑名單。同一段時間,真正寄出去的信是 41 封。自動封鎖的名單上現在有 482 個位址。

擋法是加權,不是一票否決。黑名單不是查到就退。每一張名單給不同的分數,累計到 6 分才動手,而且有幾張是負分 —— 那幾張是白名單,查到了要往回扣。單一名單一票否決很容易誤殺,而誤殺一封客戶的信,比放進來一封廣告貴得多。

評分的三個門檻:信收進來之後還有第二關:那是一套評分,7 分丟進灰名單、8 分在標頭上做記號、15 分直接退回。灰名單的意思是「第一次來的陌生人請先等一下再來一次」:真正的信件伺服器會照規矩重試,批次發垃圾的多半不會回頭。

掃描過 771 封:87.03% 直接放行、7.65% 判定是垃圾、4.15% 直接退回、5.32% 進灰名單。這個比例值得留著,因為它是判斷「今天是不是出事了」的基準線 —— 放行率如果突然掉下去,通常不是垃圾信變多了,是自己哪裡設壞了。

憑證

憑證從 8 月 9 日簽到 11 月 7 日,90 天一期,系統自己會續。

備份裡最貴的那一份

整台機器的應用層備份是 525MB,其中信件本體只佔一小部分。最貴的是裡面那 12KB 的加密金鑰:那一份掉了,信全部還在,但是一封都讀不出來。備份跑得動、檔案也在,不等於還原得回來 —— 這件事一定要注意。

現在這座機房會自己收信,也會自己寄信,每一封寄出去的信上面都有自己的簽名。而且第一次有人在外面替我盯著誰在冒用這個網域。明天來偵測,系統安不安全。


上一篇
Day14 你的機器還活著嗎
系列文
一個人的機房:用 Claude 建置 AI 機房15
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言