TXT レコード
概要
TXT レコード は、DNS ゾーンに任意のテキスト文字列を格納するレコードタイプです。RFC 1035(1987年)で定義され、RFC 7208(SPF)や RFC 6376(DKIM)など後続の仕様でも情報公開の手段として広く採用されています。
もともとは人間が読むメモ用途として設計されましたが、現在は機械が読む構造化データの公開手段として使われています。メール認証(SPF・DKIM・DMARC)、ドメイン所有権の確認(Google Search Console、各種 SaaS)、BIMI など、TXT レコードに依存する仕様は多岐にわたります。
1 つのドメインに複数の TXT レコードを設定できますが、SPF は例外で、1 つのドメインに SPF レコードは 1 つだけ 設置する必要があります(RFC 7208 Section 3.2)。
仕組み
TXT レコードは 255 バイト単位の文字列で構成され、SPF・DKIM・DMARC をはじめとする多様な用途で利用されています。
レコードの構造
TXT レコードは 1 つ以上のテキスト文字列(character-string)で構成されます。RFC 1035 の制約で 1 文字列は 255 バイト以内 です。255 バイトを超える場合は、複数の文字列を並べて定義します。DNS リゾルバーは受信時にこれらを連結して 1 つのテキストとして扱います。
example.com. IN TXT "first string" "second string"
ゾーンファイル上のフィールド構成は次のとおりです。
| フィールド | 説明 |
|---|---|
| NAME | レコードを設定するドメイン名(example.com.、_dmarc.example.com. 等) |
| TTL | キャッシュの有効秒数 |
| CLASS | 通常は IN(Internet) |
| TYPE | TXT(レコードタイプ番号 16) |
| RDATA | 1 つ以上のテキスト文字列。各文字列はダブルクォートで囲む |
実際には SPF レコードが 512 バイトを超えることは少ないですが、DKIM の公開鍵(2048 ビット鍵)を TXT レコードに格納する場合は複数文字列に分割する必要があります。
主な用途
TXT レコードは多種多様な仕様で利用されています。代表的な用途を以下にまとめます。
| 用途 | 設定先ドメイン | 値の先頭 | 関連 RFC |
|---|---|---|---|
| SPF(送信元 IP の認証) | example.com | v=spf1 | RFC 7208 |
| DKIM(メール署名の公開鍵) | {selector}._domainkey.example.com | v=DKIM1 | RFC 6376 |
| DMARC(認証ポリシー) | _dmarc.example.com | v=DMARC1 | RFC 7489 |
| ドメイン所有権の確認 | example.com | サービス固有の文字列 | — |
| BIMI(ブランドロゴ表示) | default._bimi.example.com | v=BIMI1 | RFC 9495 |
TTL とキャッシュ
TXT レコードも他の DNS レコードと同様に TTL(Time to Live)を持ちます。SPF や DMARC の変更が反映されるまでには TTL に設定した秒数を待つ必要があります。緊急の変更を想定して TTL を短く(300〜600 秒)設定しておくと、変更後の伝搬が速くなります。
設定例
SPF、DKIM、DMARC、ドメイン所有権確認など、代表的な TXT レコードの記述方法を示します。
SPF
v=spf1 で始まる TXT レコードが SPF です。@example.com のメールを Google Workspace から送信する場合は次のようになります。
example.com. IN TXT "v=spf1 include:_spf.google.com ~all"
DKIM
{セレクター}._domainkey.{ドメイン} のサブドメインに設置する TXT レコードが DKIM の公開鍵です。
s1._domainkey.example.com. IN TXT "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQ..."
2048 ビット鍵の場合は 255 バイトを超えるため、次のように分割します。
s1._domainkey.example.com. IN TXT "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBA" "QUAA4GNADCBiQKBgQ..."
DMARC
_dmarc.{ドメイン} に設置します。
_dmarc.example.com. IN TXT "v=DMARC1; p=reject; rua=mailto:dmarc@example.com"
ドメイン所有権の確認
Google Search Console や各種 SaaS がドメイン所有権の確認に使う TXT レコードです。サービスごとに異なる文字列を設置します。
example.com. IN TXT "google-site-verification=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
確認方法
dig で TXT レコードを確認するには次のコマンドを使います。
dig TXT example.com
出力の ANSWER SECTION にテキスト文字列が表示されます。
;; ANSWER SECTION:
example.com. 3600 IN TXT "v=spf1 include:_spf.google.com ~all"
DMARC レコードを確認する場合は _dmarc サブドメインを指定します。
dig TXT _dmarc.example.com
;; ANSWER SECTION:
_dmarc.example.com. 3600 IN TXT "v=DMARC1; p=reject; rua=mailto:dmarc@example.com"
DKIM の公開鍵を確認する場合はセレクター付きの _domainkey サブドメインを指定します。
dig TXT s1._domainkey.example.com
;; ANSWER SECTION:
s1._domainkey.example.com. 3600 IN TXT "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQ..."
+short オプションを付けると値のみ表示されて読みやすくなります。
dig TXT example.com +short
"v=spf1 include:_spf.google.com ~all"
外部の視点からも確認したい場合は、Labee Dev Toolbox の DNS API を使うと、外部の視点から見た結果を取得できます。
curl "https://labee.dev/api/dns?domain=example.com&type=TXT"
レスポンスは次の形式で返ります。
{
"success": true,
"data": {
"domain": "example.com",
"records": {
"TXT": [
["v=spf1 include:_spf.google.com ~all"]
]
}
},
"error": null,
"meta": { "responseTime": 40 }
}
records.TXT は配列の配列として返ります。各要素が 1 つの TXT レコードに対応し、内側の配列にはテキスト文字列が格納されます。複数の TXT レコードがドメインに設定されている場合は、外側の配列に複数のエントリが含まれます。
外部の視点からも確認したい場合は、Labee Dev Toolbox の Mail Auth API を使うと、外部の視点から見た結果を取得できます。
curl "https://labee.dev/api/mail-auth?domain=example.com"
レスポンスは次の形式で返ります。
{
"success": true,
"data": {
"spf": {
"record": "v=spf1 include:_spf.google.com ~all",
"exists": true
},
"dkim": {
"record": "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQ...",
"exists": true,
"selector": "default"
},
"dmarc": {
"record": "v=DMARC1; p=reject; rua=mailto:dmarc@example.com",
"exists": true
},
"bimi": {
"record": null,
"exists": false
}
},
"error": null,
"meta": { "responseTime": 120 }
}
data.spf.record、data.dkim.record、data.dmarc.record のフィールドで各レコードの内容を確認できます。selector パラメーターを省略した場合、DKIM は default セレクターで検索されます。
よくある問題
TXT レコードの運用では、SPF の重複登録や DKIM 公開鍵の分割ミスが頻出します。
SPF レコードが複数存在する
1 つのドメインに v=spf1 で始まる TXT レコードが 2 つ以上あると、RFC 7208 の規定によりどちらも無効になります。複数の送信元を追加したい場合は include: メカニズムを 1 つのレコードにまとめます。
# 誤り: 2 つの SPF レコード
example.com. IN TXT "v=spf1 include:_spf.google.com ~all"
example.com. IN TXT "v=spf1 include:sendgrid.net ~all"
# 正しい: 1 つのレコードにまとめる
example.com. IN TXT "v=spf1 include:_spf.google.com include:sendgrid.net ~all"
DKIM の公開鍵が 255 バイトで切れる
DNS 管理パネルによっては 255 バイト以上の文字列を自動的に分割しないものがあります。2048 ビットの DKIM 公開鍵をそのまま貼り付けると、先頭 255 バイトで切れて無効な公開鍵になります。分割が必要な場合は手動でダブルクォートで区切ります。
TXT レコードが多すぎて DNS レスポンスが大きくなる
1 つのドメインに TXT レコードが増えると、DNS レスポンスサイズが UDP の 512 バイト制限を超えて TCP にフォールバックします。サービスが要求する所有権確認レコードが増え続けると問題になります。不要になった確認レコードは削除します。
変更後も古いレコードが返る
TXT レコードを変更してもキャッシュが残っているリゾルバーには TTL が切れるまで古い値が返ります。TTL が 3600 秒(1 時間)であれば、変更前の設定が最大 1 時間キャッシュされます。緊急の SPF・DMARC 変更を予定している場合は事前に TTL を短く(300 秒程度)設定しておきます。