はじめに
Amazon SESを使ってシステムからメールを送信する際、SPF / DKIM / DMARCによる送信ドメイン認証は重要なセキュリティ対策です。
今回、次のような本番・STG環境を持つシステムで、メールのなりすまし対策を検討しました。
本番:sample.com
STG :stg.sample.com
本番とSTGはどちらもAmazon SESからメールを送信します。
一方で、
dummy.sample.com
test.sample.com
dummy.stg.sample.com
のような、メール送信に使用していないサブドメインをFromとして悪用された場合も拒否したいという要件がありました。
そこでDMARCを調べていくと、
p
sp
np
という3つのポリシーが出てきます。
特に分かりづらかったのが、
sp=rejectがあるならnp=rejectは何のため?
という点でした。
この記事では、実際の設計を例にしながら、DMARCの p / sp / np の違いと、サブドメインを含めたDMARC設計について整理します。
2026年5月、DMARCの新しい標準として RFC 9989 が公開され、従来のRFC 7489を置き換えました。
この記事ではRFC 9989を前提に整理しています。
今回の構成
今回想定する構成はこちらです。
要件は次のとおりです。
-
sample.comからSES経由でメールを送信する -
stg.sample.comからもSES経由でメールを送信する - 本番・STGとも、まずはDMARCを
p=noneで監視する - その他のサブドメインからのなりすましは原則拒否する
- 存在しない架空サブドメインも拒否する
この要件をDMARCでどのように表現するかを考えていきます。
そもそもDMARCとは
DMARC(Domain-based Message Authentication, Reporting, and Conformance)は、SPFやDKIMの認証結果と、メールのHeader Fromドメインとの整合性を確認する仕組みです。
ざっくり表すと次のようになります。
DMARCで重要なのは、単にSPFやDKIMが成功したかだけではなく、Header Fromで使われているドメインと認証されたドメインがAlignmentしているかという点です。
SPF / DKIM / Alignmentについては、第2回でAmazon SESの設定とあわせて詳しく整理します。
p / sp / np とは
本題です。
DMARCには次のポリシータグがあります。
| タグ | 主な対象 |
|---|---|
p |
DMARCレコードの対象ドメイン自身 |
sp |
Organizational Domain配下の存在するサブドメイン |
np |
Organizational Domain配下の存在しないサブドメイン |
例えば、
_dmarc.sample.com
TXT "v=DMARC1; p=none; sp=reject; np=reject;"
と設定した場合を考えます。
概念的には、
となります。
それぞれ詳しく見ていきます。
p:ドメイン自身のポリシー
p は基本となるDMARCポリシーです。
例えば、
v=DMARC1; p=none;
なら、DMARC認証に失敗したメールについて、
まずは配送を拒否せず監視する
というポリシーになります。
今回なら、
sample.com
→ p=none
です。
DMARC導入時にいきなり reject にすると、正規メールまで拒否される可能性があります。
そのため、まずは
p=none
でレポートを確認し、問題がないことを確認してから、
p=quarantine
や
p=reject
へ段階的に移行する方法があります。
sp:存在するサブドメインのポリシー
sp は Subdomain Policy です。
Organizational Domain配下の「存在するサブドメイン」に対するポリシーを指定します。
例えば、
api.sample.com
にAレコードがあり、DNS上実在しているとします。
しかし、
_dmarc.api.sample.com
には個別のDMARCレコードがない。
この場合、親側の
_dmarc.sample.com
に設定した、
sp=reject
が適用されます。
つまり、
sample.com
→ p=none
api.sample.com
→ sp=reject
という設計ができます。
これは、
親ドメインはメールを送るが、その他のサブドメインは原則メール送信元として使わせたくない
というケースで有効です。
np:存在しないサブドメインのポリシー
np は Non-existent Subdomain Policy です。
名前のとおり、DNS上存在しないサブドメインを対象にします。
例えば、
dummy.sample.com
という名前についてDNSを問い合わせても何も存在せず、
NXDOMAIN
となるケースです。
このような架空のサブドメインを攻撃者が、
From: attacker@dummy.sample.com
として使用するケースを想定できます。
そこで、
np=reject
を設定します。
すると、
dummy.sample.com
→ np=reject
というポリシーを明示できます。
ここでいう「存在しない」とは「メールを利用していない」という意味ではありません。
DNS上、そのドメイン名が存在しないことを意味します。
Web用途のサブドメインは「存在する」
例えば、
api.sample.com
がメールを一切使用していなくても、
api.sample.com A 192.0.2.10
というDNSレコードが存在すれば、DNS上は存在するサブドメインです。
そのため、
api.sample.com
→ sp
dummy.sample.com
→ np
となります。
整理すると、
sp
= DNS上存在するサブドメイン
np
= DNS上存在しないサブドメイン
と覚えると分かりやすいです。
sp と np はどちらか一方ではない
ここで最初に疑問になったのが、
架空サブドメインを防ぎたいなら、
spではなくnpを使えばいいのでは?
という点でした。
結論としては、sp と np はどちらか一方を選ぶものではありません。
守る対象が違います。
今回やりたいことは、
| 対象 | 方針 |
|---|---|
sample.com |
正規利用するため監視 |
| 実在するその他のサブドメイン | 原則拒否 |
| 存在しないサブドメイン | 原則拒否 |
です。
そのため、
v=DMARC1; p=none; sp=reject; np=reject;
とします。
これなら設定を見ただけでも、
親ドメイン自身は監視し、サブドメインは存在する・しないにかかわらず原則reject
という設計意図が分かります。
RFC 9989では、np が省略されている場合は sp、sp もなければ p が非存在サブドメインにも使用されます。
つまり、
p=none; sp=reject;
でも非存在サブドメインには結果的に reject が適用されます。
今回は「存在しないサブドメインも明示的に拒否する」という設計意図を分かりやすくするため、np=reject も明記しています。
では stg.sample.com もrejectされてしまう?
ここでもう一つ問題があります。
stg.sample.com
はDNS上存在するサブドメインです。
親側は、
_dmarc.sample.com
TXT "v=DMARC1; p=none; sp=reject; np=reject;"
なので、一見すると、
stg.sample.com
→ sp=reject
になりそうです。
しかし今回はSTG環境でもSESから正規メールを送信したい。
そこで、stg.sample.com 自身にDMARCレコードを設定します。
_dmarc.stg.sample.com
TXT "v=DMARC1; p=none;"
DMARCでは、まずAuthor Domain自身のDMARCレコードが確認されます。
そのため、
From: user@stg.sample.com
の場合、
_dmarc.stg.sample.com
が存在すれば、こちらの
p=none
が適用されます。
つまり、
原則
サブドメイン → reject
例外
stg.sample.com → 個別DMARCでnone
という設計が可能です。
これが今回やりたかった構成です。
sp は「絶対にサブドメインをrejectする設定」ではない
ここは重要です。
親側で、
sp=reject
としたからといって、すべてのサブドメインが無条件にrejectされるわけではありません。
対象のAuthor Domain自身にDMARCレコードがあれば、そちらが優先されます。
そのため、
sample.com
│
├─ api.sample.com
│ └─ 個別DMARCなし
│ → 親のsp=reject
│
├─ web.sample.com
│ └─ 個別DMARCなし
│ → 親のsp=reject
│
└─ stg.sample.com
└─ _dmarc.stg.sample.com
→ p=none
という管理ができます。
「原則拒否して、必要なドメインだけ明示的に許可・監視する」という考え方にしやすくなります。
RFC 9989で注意したい sp の扱い
ここは少し高度な内容ですが、今回調べていて重要だったポイントです。
sp は単純に、
このDMARCレコードより下の階層すべてに適用される設定
ではありません。
RFC 9989では、sp は Organizational Domainの既存サブドメインに対するポリシーとして定義されています。
さらに、Organizational Domainのサブドメイン上に公開されたDMARCレコードでは、sp が下位ドメインへ単純継承されるわけではありません。
そのため、
_dmarc.stg.sample.com
TXT "v=DMARC1; p=none; sp=reject;"
とすれば、
dummy.stg.sample.com
にも必ずその sp=reject が使われる、と単純に考えるのは避けた方がよいです。
p / sp / np を理解する際は、
「DNS階層に沿って単純に設定が継承される」
と考えるのではなく、DMARC Policy Discoveryによって、どのDMARCレコードが対象になるかが決まると理解した方が正確です。
今回の記事では、
sample.com
をOrganizational Domainとして、
_dmarc.sample.com
p=none; sp=reject; np=reject;
を基本ポリシーにします。
そして、
stg.sample.com
自身については、
_dmarc.stg.sample.com
p=none;
を設定する、という構成にしています。
今回のDMARC設計
ここまでを整理すると、今回の設定は次のようになります。
本番
Name:
_dmarc.sample.com
Type:
TXT
Value:
v=DMARC1; p=none; sp=reject; np=reject;
役割は、
sample.com
→ p=none
存在するサブドメイン
→ sp=reject
存在しないサブドメイン
→ np=reject
です。
STG
Name:
_dmarc.stg.sample.com
Type:
TXT
Value:
v=DMARC1; p=none;
これにより、
From: user@stg.sample.com
については、STG自身のDMARCポリシーで監視できます。
全体像
今回の設計思想を一言で表すなら、
メール送信に利用するドメインだけ明示的にDMARCを設定し、それ以外のサブドメインは原則rejectする
という形です。
よくある勘違い
sp と np はどちらか一方を設定する?
違います。
対象が異なります。
sp
→ 存在するサブドメイン
np
→ 存在しないサブドメイン
今回のように両方を拒否したいなら、
sp=reject; np=reject;
とします。
np の対象は「メールを使っていないドメイン」?
違います。
DNS上存在しないサブドメインです。
Webサーバー用のAレコードだけでも存在すれば、そのサブドメインは「存在する」側になります。
親に sp=reject を設定したらSTGもrejectされる?
STG自身にDMARCレコードがなければ、親のポリシーの対象になります。
しかし、
_dmarc.stg.sample.com
を設定すれば、stg.sample.com 自身についてはそのDMARCレコードの p が使われます。
p=none ならなりすまし対策にならない?
p=none は主に監視フェーズです。
本番メールの送信経路を把握せずに、いきなり、
p=reject
へ変更すると、正規メールを拒否する可能性があります。
まず none でDMARCレポートを確認し、
none
↓
quarantine
↓
reject
と段階的に強化する方法があります。
ここまでのポイント
今回特に押さえておきたいのは次の点です。
-
pは対象ドメイン自身のポリシー -
spはOrganizational Domain配下の存在するサブドメイン向け -
npは存在しないサブドメイン向け -
npはRFC 9989で定義されている -
spとnpはどちらか一方を選ぶものではない - 正規利用するサブドメインには個別DMARCを設定できる
- 親の
sp=rejectが個別DMARCを強制的に上書きするわけではない - DMARCポリシーは単純なDNS階層の継承として考えない
- 本番導入時はいきなり
rejectにせずnoneから監視する方法がある
最終的に今回は、
sample.com
→ p=none
→ sp=reject
→ np=reject
stg.sample.com
→ 個別DMARC
→ p=none
という構成にしました。
次回:Amazon SES側のSPF / DKIM / MAIL FROMを整理する
DMARCの設計はこれで整理できました。
しかし、ここで次の疑問が出てきます。
Amazon SESの場合、SPFは
sample.comに設定すればいいのか?
実はここで重要になるのが、
Header From
と、
MAIL FROM
の違いです。
例えば、
Header From:
user@sample.com
Custom MAIL FROM:
mail.sample.com
という構成の場合、SES用のSPFをどこへ設定するかを正しく理解する必要があります。
次回は、
「【AWS SES メール認証・なりすまし対策②】SPF・DKIM・Custom MAIL FROMを正しく理解する ~Header Fromとの違いを整理~」
として、
- SPF
- DKIM
- DMARC Alignment
- Header From
- MAIL FROM
- Custom MAIL FROM
- SESで必要になるMX / TXTレコード
の関係を整理します。
参考資料