2026年6月17日

2026年6月17日

DANE と EDNS0 を併用する設定|コンテナ・systemd-resolved・クラウド環境で送信 MTA に検証結果を届ける構成と点検

DANE を有効にした送信メールサーバーは、EDNS0 の DO ビットで署名つきの TLSA を要求し、リゾルバーが返す AD フラグ(検証済みの印)を見て DANE を適用します。この流れのどこかで EDNS0 や AD フラグが落ちると、エラーにはならず、DANE が黙って通常の暗号化(または平文)に戻ります。この記事では、Postfix をコンテナやクラウドの VM、systemd-resolved が動く Linux で動かすときに、EDNS0 と検証結果を MTA まで届ける構成の決め方と、設定が崩れていないかを定期的に点検する方法を説明します。

TLSA を公開する権威サーバー側の応答サイズや、Unbound と Postfix の基本設定そのものは扱いません。ここでは「MTA とリゾルバーの間に何が挟まっているか」に絞ります。

送信側で起きていること

Postfix で DANE を使う基本の設定は次の2行です。

# /etc/postfix/main.cf(例)
smtp_dns_support_level = dnssec
smtp_tls_security_level = dane

smtp_dns_support_level = dnssec にすると、Postfix は DNSSEC の情報を求める問い合わせ(EDNS0 の OPT レコードに DO ビットを立てたもの)を出します。Postfix 自身は署名を検証せず、リゾルバーの応答に AD フラグがあるかどうかだけを見ます。宛先の MX と TLSA が「検証済み」と判断できたときだけ DANE で証明書を照合し、そうでなければ may 相当の日和見 TLS で送ります。

つまり、途中で次のどれかが起きると、DANE は効かないのにメールは届き続けます。

  • リゾルバーが DNSSEC を検証していない(AD フラグを付けない)
  • リゾルバーと MTA の間で AD フラグが捨てられる
  • 大きな応答が途中で落ち、TCP への切り替えにも失敗する

送信できているから大丈夫、とは言えないのが DANE の難しいところです。以下、環境ごとに確認点を見ていきます。

構成の原則:検証するリゾルバーを MTA と同じホストに置く

Postfix のドキュメントは、DNSSEC を検証するリゾルバーを MTA と同じホスト(ループバックアドレス)で動かすことを勧めています。リゾルバーと MTA の間の通信は暗号化も署名もされていないため、ネットワークをまたぐと AD フラグを途中で書き換えられても気づけないからです。

この原則を、それぞれの環境に当てはめると次のようになります。

systemd-resolved が動いている Linux

Ubuntu などでは、/etc/resolv.conf が systemd-resolved のスタブ(127.0.0.53)を指していることが多くあります。スタブが生成する resolv.conf には options edns0 trust-ad が書かれていますが、AD フラグが付くのは systemd-resolved 自身が DNSSEC を検証したときだけです。systemd-resolved の DNSSEC 設定は、ディストリビューションの既定で無効または緩いモードになっていることが多く、そのままでは DANE の前提を満たしません。

MTA 用には、Unbound などの検証リゾルバーを 127.0.0.1 で動かし、resolv.conf をそこへ向けるのが分かりやすい構成です。systemd-resolved と 53 番ポートがぶつかる場合は、Unbound の待ち受けを 127.0.0.1 に限定し、systemd-resolved のスタブは 127.0.0.53 のまま残せます。

# /etc/resolv.conf(Unbound を 127.0.0.1 で動かす例)
nameserver 127.0.0.1
options edns0 trust-ad

trust-ad は glibc 2.31 以降で必要になった指定で、これが無いとライブラリが AD フラグを捨てます。また、resolv.conf は netplan、NetworkManager、cloud-init などに上書きされることがあります。OS の更新や再起動のあとに元へ戻っていないか、後述の点検で確かめます。

Docker などのコンテナ

ユーザー定義ネットワーク上のコンテナは、Docker の組み込み DNS(127.0.0.11)を使います。組み込み DNS はホスト側の設定に従って問い合わせを転送するため、コンテナ内の MTA から見た AD フラグの扱いは、Docker の版やホストのリゾルバー構成に左右されます。ここに依存するのは避けたほうが安全です。

確実性を上げるには、検証リゾルバーをコンテナとして並べ、MTA と同じネットワーク名前空間を共有させます。Docker Compose なら network_mode: "service:..." で、MTA のコンテナから 127.0.0.1 でリゾルバーに届くようにできます。

# docker-compose.yml(抜粋・例)
services:
  unbound:
    image: your-unbound-image   # 検証を有効にした Unbound のイメージ
  postfix:
    image: your-postfix-image
    network_mode: "service:unbound"   # unbound と同じネットワーク名前空間
    volumes:
      # 中身は「nameserver 127.0.0.1」と「options edns0 trust-ad」の2行
      - ./resolv.conf.mta:/etc/resolv.conf:ro

ネットワーク名前空間を共有するモードでは、Docker の dns や dns_opt の指定がネットワークモードと衝突してエラーになることがあるため、例では resolv.conf をファイルとして読み込ませています。network_mode を共有すると、公開ポートの指定はリゾルバー側のサービスに書く必要があるなど、構成の書き方が変わります。既存の構成を変える前に、ステージングで送受信を一通り確かめてください。

クラウドの VM

クラウドの VPC には事業者のリゾルバーがあり、DNSSEC の検証を有効にできるサービスもあります。ただし MTA から見るとネットワーク越しのリゾルバーで、先の原則からは外れます。ホスト上に Unbound を置き、上流をクラウドのリゾルバーにする形(転送)にしても、Unbound が自分で署名を検証するので原則を満たせます。外向きの 53 番が制限された環境では、この転送構成が現実的です。

# unbound.conf(上流へ転送しつつ、自分で検証する例)
server:
    interface: 127.0.0.1
    auto-trust-anchor-file: "/var/lib/unbound/root.key"
    edns-buffer-size: 1232

forward-zone:
    name: "."
    forward-addr: 169.254.169.253   # 例: クラウドのリゾルバー。環境に合わせて変更

転送先が DNSSEC の署名(RRSIG)を返さないと、Unbound の検証は失敗して SERVFAIL になります。転送先を決めたら、署名つきの応答が返るかを先に確かめます。

EDNS0 の通り道を確かめる

経路の途中では、セキュリティグループやファイアウォールが UDP の 53 番だけを許可し、TCP の 53 番を閉じていることがあります。DNSSEC の応答は大きくなりやすく、切り詰め(TC フラグ)からの TCP 再送が通らないと、特定の宛先だけ名前解決に失敗します。リゾルバーから外向きの UDP・TCP の両方を許可します。

MTA と同じ視点で確かめるには、MTA が動くホスト(コンテナならその名前空間)で、resolv.conf のリゾルバーに問い合わせます。

# 署名つきで TLSA を聞き、flags に ad が付くかを見る
dig +dnssec +bufsize=1232 _25._tcp.mail.example.net TLSA

# TCP でも同じ結果になるか
dig +dnssec +tcp _25._tcp.mail.example.net TLSA

# コンテナ内で確かめる例(イメージに dig が入っている場合)
docker compose exec postfix dig +dnssec _25._tcp.mail.example.net TLSA

flags: に ad が付けば、検証済みの結果が届いています。付かないときは、リゾルバーが検証していないか、途中で落とされています。例のドメイン名は、TLSA を公開していることが分かっている宛先に置き換えてください。

Postfix 付属の posttls-finger を使うと、DANE で照合できるかを MTA と同じ仕組みで試せます。

posttls-finger -c -l dane -L summary example.net

出力で TLSA の照合に成功したことが示されれば、DNS から証明書照合までの通り道がつながっています。

崩れていないかを定期的に点検する

DANE の設定は、作った時点では動いていても、OS の更新やコンテナの作り直しで静かに崩れます。次のような点検を定期的に行うと気づきやすくなります。

  • ログで検証の段階を数える:Postfix は TLS 接続のログに Verified、Trusted、Untrusted、Anonymous などの段階を記録します。DANE を公開している宛先への接続が Verified になっているかを見ます。以前は Verified だった宛先が Untrusted に変わったら、DNS 側の通り道を疑います。
  • Postfix の自己診断の警告を見る:Postfix 3.6 以降には、起動時などに DNSSEC 検証が使えるかを試す仕組み(dnssec_probe)があり、使えないと判断すると警告をログに残します。メッセージの文面は版で異なることがあるため、「DNSSEC」を含む warning を監視対象にしておくと拾いやすくなります。
  • resolv.conf の差分を見る:構成管理ツールや簡単なスクリプトで、nameserver 127.0.0.1 と trust-ad が残っているかを確かめます。
  • ルートのトラストアンカーを更新できる状態にしておく:ルートゾーンの KSK 更新が進む時期でもあります(2026年10月現在)。Unbound の auto-trust-anchor-file のように自動で更新される設定にしておき、固定のトラストアンカーを焼き込んだ古いイメージを使い続けないようにします。
# 直近のログで TLS 接続の段階を数える例
grep -oE '(Verified|Trusted|Untrusted|Anonymous) TLS connection' /var/log/mail.log | sort | uniq -c

変更するときの注意

resolv.conf やリゾルバーを入れ替えると、MTA だけでなく同じホストのすべての名前解決に影響します。WordPress と同じサーバーでメールを送っている場合、プラグインの更新確認や外部 API の呼び出しも止まる可能性があります。作業の前に設定ファイルを控え、コンソール接続など DNS が止まっても入れる経路を確保し、ステージングで試してから本番に反映してください。

まとめ

  • DANE は、EDNS0 の DO ビットで署名を要求し、リゾルバーの AD フラグを信用して動きます。どこかで落ちると、エラーにならず DANE が効かなくなります。
  • 検証リゾルバーは MTA と同じホスト(コンテナなら同じネットワーク名前空間)に置き、resolv.conf には trust-ad を入れます。
  • systemd-resolved のスタブ、Docker の組み込み DNS、クラウドのリゾルバーは、そのままでは前提を満たさないことがあります。Unbound を手元に置き、必要なら上流へ転送します。
  • TCP の 53 番を含めて通り道を確かめ、ログの Verified の比率や resolv.conf の差分を定期的に点検します。

お気軽にご相談ください

お見積りへ お問い合わせへ
▲