把 DMARC 從 p=none 安全推到 p=reject 的實戰 playbook
本篇是「誰在冒用你的 Domain 寄信」系列的第 3 / 4 篇。你可以從系列總覽開始閱讀,也可以直接接著看本文。
p=none 的 DMARC 是很多公司的現狀:裝了,但等於沒鎖門——它只觀察、不擋任何冒名信。
但你不能直接把它改成 p=reject。因為一旦強制,所有「驗證沒對齊」的信都會被退回——包括你自己沒設好的那些合法寄件管道。員工信、電子報、客服回覆、系統通知……任何一個沒對齊的,使用者就收不到。
這篇是把 DMARC 從 p=none 安全推到 p=reject 的分階段 playbook。核心觀念是:前置步驟全部零風險,真正的風險集中在最後一步,而它被監控期擋著。
📎 這是「誰在冒用你的 Domain 寄信」系列的進階篇。不熟 SPF/DKIM/DMARC 先看 #2 白話入門;想看這套流程的真實案例,看系列起點 我如何重現一個資安評等的 F;這套 playbook 真的按下去那天的記錄在 #4 執行日的假訊號。
整條路長這樣——前面四格都不會擋掉任何一封信,只有最後一格會:
flowchart TD
subgraph ZERO["零風險區 · 只增不減,不會擋掉任何一封信"]
S0["階段 0<br/>DMARC 補上 rua<br/>政策維持 p=none"] --> S1["階段 1<br/>盤點每一條合法寄件管道"]
S1 --> S2["階段 2<br/>補 SPF include、每條管道開 DKIM<br/>SPF 結尾先留 ~all"]
S2 --> S3["階段 3<br/>讀 rua 報告 2–4 週"]
S3 --> Q{"每一條合法管道<br/>都 pass 而且對齊了嗎?"}
Q -->|"報告裡冒出沒授權過的寄件者"| S1
end
Q -->|"連續數週乾淨,沒有新面孔"| S4["階段 4 · 唯一會擋信的一步<br/>p=quarantine → p=reject<br/>最後 SPF 收成 -all"]
S4 --> OK["冒名信被退掉<br/>自家的信照樣送達"]
那個回頭的箭頭是整套流程的重點:報告一冒出沒見過的寄件者,就退回階段 1 重新盤點,而不是照日曆往下走。
先理解:為什麼會擋到自家信(alignment)
DMARC 不只看 SPF/DKIM 有沒有過,還看「通過的那個網域」和「From 顯示的網域」對不對得起來,這叫 alignment(對齊)。
用系列裡的掛號信比喻來說,對齊就是一條姓氏規則。信封上寫的寄件人是「陳家公司」,可是火漆印上蓋的卻是「陳家公司・第三分部」——因為交易信外包給自己的子網域 mg.yourdomain.com 在寄。這兩個名字算不算同一家?看你設的是哪一種規則:
- 寬鬆 relaxed(
adkim=r; aspf=r,預設):只看姓。mg.yourdomain.com和yourdomain.com同姓,算同一家 → 對齊。 - 嚴格 strict(
adkim=s; aspf=s):要一模一樣。差一個mg.就不算 → 不對齊。
幾乎所有公司的信,都是靠「只看姓」這條預設規則活著的。 用子網域幫你寄信的 SaaS(交易信、電子報、客服)一抓一大把,規則一改嚴格,它們全變成外人。
上面這張圖只畫了盤點時真的會用到的那一半。完整的比喻、以及「改成嚴格為什麼代價遠大於收益」的完整推導,在 #2 的〈對齊(alignment):姓氏規則〉;這裡只留執行時要記住的兩句:
- DMARC 是 OR 邏輯:SPF 對齊且通過,或 DKIM 對齊且通過,任一成立就算 pass。所以「改 strict 一定爆炸」是過度斷言——真正會整批掛掉的,是 DKIM 的
d=和 Return-Path 都掛在子網域上、而你又把兩個 tag 一起設成s的組合(真的長成這樣的一條管道在 #4)。 - 但改成嚴格,擋不掉一般的冒名信。 偽造信從來就不是任何一個「陳家」簽的,在寬鬆規則下本來就已經失敗;你多擋掉的幾乎都是自己的電子報、帳單和密碼重設信。(唯一的例外是子網域被接管的情況,見 #2。)
所以這套流程的預設就是:adkim=r; aspf=r 放著別動。
階段 0:先能「看見」(設 rua)
沒有報告,你不知道誰會被擋。第一步把 DMARC 加上 rua=mailto:...,維持 p=none。
原始 XML 人是看不了的,丟給 DMARC 分析服務解析(dmarcian、Postmark DMARC、Valimail 等;或自架開源解析器)。
這步零風險、零投遞影響,卻是整個流程的基礎。
階段 1:盤點所有合法寄件來源(最關鍵)
列出每一個會用 @yourdomain.com 寄信的東西,常見的有:
- 公司信箱(Google Workspace / Microsoft 365)
- 交易信 / 系統通知(Mailgun、SendGrid、SES、Postmark……通常走子網域如
mg.) - 行銷電子報(Mailchimp、HubSpot……)
- 客服系統(Zendesk、Intercom……)
- 最容易遺漏的:電子簽核、問卷、CRM、招募系統、發票系統
但只列出名字不算盤點完。清單上的每一條,都要走過同樣三個問題:
flowchart TD
P["清單上的一條寄件管道<br/>例:客服系統、發票系統"] --> Q1["先查:它實際上用哪個網域把信交出去?<br/>看 Return-Path 和 DKIM 的 d= 欄位"]
Q1 --> Q2{"① SPF 授權過<br/>這個來源了嗎?"}
Q2 -->|"沒有"| A1["補 include<br/>同時盯住 10 次 DNS 查詢上限"]
Q2 -->|"有"| Q3{"② 這條管道的 DKIM<br/>簽章開了、公鑰進 DNS 了嗎?"}
A1 --> Q3
Q3 -->|"沒有"| A2["去該服務後台開 DKIM<br/>把公鑰貼進自己的 DNS"]
A2 --> Q4
Q3 -->|"有"| Q4{"③ 通過的網域和 From<br/>對得起來嗎?<br/>就是上一節的姓氏規則"}
Q4 -->|"對不起來"| A3["改成用自己的子網域寄<br/>或請該服務改簽你的網域"]
A3 --> OK
Q4 -->|"對得起來"| OK["這條管道過關<br/>p=reject 之下照樣送達"]
三個問題全部答完,這條管道才算盤好。遺漏一條,它的信就會在 reject 時死掉。
真實案例:系列起點那篇裡,我盤點後發現高流量的交易信和電子報其實早就對齊了,缺口主要落在員工信和客服——爆炸半徑比想像中小。但盤點清單不會就此封閉:真正推上去那天,還是有一條電商管道的 DKIM 沒 provision 好(#4)。盤點讓你知道風險多大,監控期才是抓漏的那一關。
階段 2:鋪設(零風險)
- SPF:把所有合法來源補進去,結尾先用
~all(softfail,不會擋信)。注意 10-lookup 上限。 - DKIM:每個寄件管道都開簽章(Google Workspace 後台、各 SaaS 的 DKIM 設定)。
- DMARC:維持
p=none,但 rua 已經在收報告。
這些動作都是「多授權 / 加簽章」,只增不減,不會擋掉任何現有信件。
階段 3:監控(2–4 週)
- 讀 rua 報告,確認每一個合法來源都 pass 且對齊。
- 揪出階段 1 沒想到的寄件者(它們會在報告裡冒出來),補上授權。
- 這步是整個流程的安全閥——不要急,讓報告告訴你還有誰沒對齊。
階段 4:漸進強制
到這裡才第一次真的會擋信,所以一階一階來:
p=quarantine——驗不過的信進垃圾桶,還撈得回來。放個一到兩週,持續盯 rua。p=reject——驗不過的信直接被退。- 最後把 SPF 從
~all收緊成-all。
每一階之間都要回頭看報告有沒有誤殺合法信;有,就退回上一階,補完再上。
關於 pct:那是舊 RFC 的做法
早期的 playbook(包括我自己最早寫的版本)會教你用 pct=25 → pct=50 → pct=100,讓政策只對一部分驗不過的信生效、再慢慢放大。這個標籤已經不在標準裡了。
DMARC 現在的規範是 2026 年 5 月發布的 RFC 9989,它取代了原本的 RFC 7489 與 RFC 9091,並把 DMARC 從 Informational 升級成 Standards Track。pct 在附錄 A.6 被列為移除項目,registry 也已標成 historic。
實務上的意思是:某些收件方的舊實作可能還讀得懂 pct,但你不能把上線計畫建立在「有些人還吃這個標籤」上面——一部分人吃、一部分人不吃,你只會得到一個連自己都說不準生效範圍的政策。
那現在怎麼漸進?用政策階梯本身當節奏,而不是百分比:
none→quarantine→reject這三階,本來就是三個不同強度,一階一階爬。- 每階停留多久由 rua 報告決定,不是由日曆決定——報告連續乾淨才往上加一階。
- 想更保守,可以讓子網域先進強制:主網域維持
p=none,先設sp=quarantine只對子網域生效,觀察沒事再動主網域。
要注意的 side-effect
轉寄信與郵件群組(最常見的真實災情)
p=reject 之下最容易被退的,往往不是冒名信,而是被轉寄過的自家信。原因在 SPF 和 DKIM 的本質差別:SPF 只看「站在門口把信交出來的是誰」,信被轉寄一次,交信的就換成轉寄主機,SPF 當場斷掉;DKIM 的火漆印是壓在信上、跟著信走的,中間換幾手都還在。這條機制的完整對照圖在 #2 的〈信被轉寄一次〉。
對這份 playbook 來說,結論只有一句:把每一條管道的 DKIM 都簽好、簽對齊,轉寄斷掉的 SPF 就不會要你的命(OR 邏輯,DKIM 那邊過就算過)。大型收件方(Gmail、Microsoft 365)另外有 ARC 可以緩解,但那是對方的善意,不是你能控制的。至於會改標題、加尾註的郵件論壇,它連 DKIM 都會弄壞——那種只能個案處理。
其他幾個
- 遺漏的寄件者:最常見的翻車原因——監控期就是為了抓它們。
- relaxed 對齊別動:
adkim=r; aspf=r保留。改嚴格擋不掉一般的冒名信,卻會擋掉自己人(上面講過)。 - SPF 10-lookup:include 太多會
permerror讓 SPF 整個失效;用 SPF flattening 或精簡 include。 sp=/np=沒寫不代表沒設:sp=缺席時,子網域直接繼承p=;np=(不存在的子網域)缺席時繼承sp=。所以在p=reject後面補一句sp=reject; np=reject不會改變任何一封信的處置,只會讓彙整報告的policy_published長得比較清楚。要補可以,但那一行打錯一個字,整筆記錄可能被降級成p=none——辛苦推上來的強制瞬間歸零。純粹寫爽的改動,反而是風險。
一張表收尾
| 階段 | 動作 | 風險 |
|---|---|---|
| 0 | DMARC 加 rua | 零 |
| 1 | 盤點寄件來源 | 零 |
| 2 | 補 SPF/DKIM、~all | 零 |
| 3 | 監控報告 2–4 週 | 零 |
| 4 | quarantine→reject、-all | 有(被前面擋著) |
把風險留到最後、用監控期當安全閥——這就是為什麼一個 email 認證的「F」聽起來嚇人,實際動工卻可以很穩。
想看這套流程是怎麼從一個 F 開始的,回 系列起點:我如何重現一個資安評等的 F;想看它真的按下去那天發生什麼事、哪些嚇人的訊號其實是假警報,看 #4 執行日的假訊號。