HEARTBEATS

こんにちは、滝澤です。

メールとDNS関連の小ネタを書いてみます。

先日、ちょっと気が向いたのでメール関連のRFCの調査をしていたのですが、2015年6月に発行された RFC 7505 A "Null MX" No Service Resource Record for Domains That Accept No Mail というRFCが目にとまりました。

このRFCは、ドメイン名がメールを受け取らないことを明示する仕組みとして"Null MX"を定義しています。 今回はこの"Null MX"について調べてみたので紹介します。

DNSとメールについて詳しい人向けに1行で説明するとこれです。

example.com. 86400 IN MX 0 .

注記: 本記事で述べる「メールサーバ」はMTA(Message Transfer Agent)およびMSA(Message Submission Agent)のことです。最近はメールサーバを構築した経験がある技術者は少なく、MTAやMSAと言う言葉になじみがない人が増えていると感じているため、あえて「メールサーバ」と書きました。

MXレコードを登録していないドメイン名宛てにメールを送るとどうなるか

ウェブサイトやウェブサービス用にドメイン名を登録した場合に、そのドメイン名ではメールを使わないことはよくあります。 このときにはそのサービス用のドメイン名に対してMXレコードを初めから設定しないでしょう。 また、当初はそのドメイン名でのメールも使っていたけど、後でメールを使わなくなったため、MXレコードを削除したといったこともあるでしょう。

このとき、そのドメイン名宛てのメールを送るとどうなるでしょうか。そのドメイン名でのウェブサーバが存在するとします。

以降の説明では簡略化のため、IPv4アドレスの場合のみで説明します。

メールサーバありの場合

まず、比較のため、メールサーバがある場合を説明します。

次のような内容で考えてみましょう。

項目
ウェブサイトのドメイン名example.com
ウェブサイトのIPアドレス192.0.2.80
example.comのメールサーバのドメイン名mail.example.com
メールサーバのIPアドレス192.0.2.25

example.comゾーンには次の内容で登録されているものとします。

example.com.      86400 IN A  192.0.2.80
example.com.      86400 IN MX 10 mail.example.com.
mail.example.com. 86400 IN A  192.0.2.25

送信側メールサーバは次のような順番で処理を行います。

  1. 宛先メールアドレス"foo@example.com"のドメイン名"example.com."に対するMXレコードを問い合わせる。
  2. "example.com."に対する回答として1個のMXレコードを受け取る。その値は優先度が"10"で、メールエクスチェンジャが"mail.example.com."である。
  3. "mail.example.com."のAレコードを問い合わせる。
  4. "mail.example.com."に対する回答としてIPアドレス"192.0.2.25"を値とするAレコードを受け取る。
  5. IPアドレス"192.0.2.25"のSMTPポート(TCP 25)に接続を試みる。
  6. IPアドレス"192.0.2.25"のSMTPポート(TCP 25)に接続が成功して、SMTPによりメールを送信する。

以上のように、MXレコードに登録されたメールエクスチェンジャのホストに対してメールの送信を行います。

2において、MXレコードの問い合わせに対する回答として、そのドメイン名そのものが存在しないエラー("NXDOMAIN")を受け取った場合は、恒久的なエラーとして報告します。一時的に名前の解決ができない場合は、一時的なエラーとして配送キューに戻して、後で再送します。

ここら辺の仕組みはSMTPのRFCである RFC 5321 Simple Mail Transfer Protocol の"5.1. Locating the Target Host"に記述されていますので、ご興味がありましたらご覧ください。

メールサーバなしの場合

次に、メールサーバなしの場合を説明します。

次のような内容で考えてみましょう。

項目
ウェブサイトのドメイン名example.com
ウェブサイトのIPアドレス192.0.2.80
example.comのメールサーバのドメイン名なし
メールサーバのIPアドレスなし

example.comゾーンには次の内容で登録されているものとします。

example.com.      86400 IN A  192.0.2.80

送信側メールサーバは次のような順番で処理を行います。

  1. 宛先メールアドレス"foo@example.com"のドメイン名"example.com"に対するMXレコードを問い合わせる。
  2. "example.com"に対する回答として0個のMXレコードを受け取る。(MXレコードが登録されていないため。なお、"example.com"そのものは存在するため、回答のステータスとしては"NOERROR"である。)
  3. "example.com"に対するAレコードを問い合わせる。(MXレコードが存在しないときには、Aレコードにフォールバックするため)
  4. "example.com"に対する回答としてIPアドレス"192.0.2.80"を値とするAレコードを受け取る。
  5. IPアドレス"192.0.2.80"のSMTPポート(TCP 25)に接続を試みる。
  6. 接続がタイムアウトする。(IPアドレス"192.0.2.80"のウェブサーバはSMTPポートに対して応答しないため)
  7. メールサーバの配送キューの最大ライフタイムに達していなければ、配送キューに入り、しばらくしてから再送(1に戻る)を試みる。
  8. 送信元メールアドレスに配送不能としてバウンスメールを返す。

上記のようにウェブサーバではメールを受け取らないため、送信側メールサーバの配送キューの最大ライフタイム(たいてい数日間)までメールの再送を繰り返します。そして、数日経ってからバウンスメールを受け取ることになります。

MXレコードが存在しないときの動作の仕様

上述の「メールサーバなしの場合」の処理では、MXレコードが存在しないため、Aレコードにフォールバックして、メールを送信を試みています。

これはSMTPのRFCである RFC 5321 Simple Mail Transfer Protocol に従った動作です。"5.1. Locating the Target Host"に次のように記述されています。

If an empty list of MXs is returned, the address is treated as if it was associated with an implicit MX RR, with a preference of 0, pointing to that host.

邦訳: MXレコードの空のリストが返されたときには、そのアドレスは優先度が"0"でその(ドメイン名の)ホストを示す暗黙のMXレコードに関連づけられているように扱われます。

RFC 5321には明示されていませんが、理解のために暗黙のMXレコードの例を書いてみると次のようになります。

example.com.      86400 IN MX 0 example.com.
example.com.      86400 IN A  192.0.2.80

これは、"example.com."のMXレコードの値が優先度が"0"でメールエクスチェンジャが"example.com."ということです。 そのため、このメールエクスチェンジャのドメイン名"example.com."の名前の解決(Aレコードの問い合わせ)を行うことになります。

要するに「MXレコードを問い合わせる。存在しなかったら、Aレコード(あるいはAAAAレコード)の問い合わせにフォールバックする」ということです。

"Null MX"を登録してみる

あるドメイン名でのウェブサーバなどのホストが存在していて、メールサーバがない場合に、ドメイン名宛てのメールの送信が行われたら、メールの送信元メールサーバでは数日間ずっと再送を繰り返し、さらには数日経ってからバウンスメールが送り返されることを説明しました。

このような状況はあまり好ましくありません。

これを解消するRFCとして、RFC 7505 A "Null MX" No Service Resource Record for Domains That Accept No Mail が発行されました。

行うことは次の例のように優先度が"0"で、メールエクスチェンジャが"."のMXレコードを登録することです。

example.com. 86400 IN MX 0 .

ここで"."はラベルの長さ0のドメイン名で、メールエクスチェンジャが存在しないことを示します。 なお、"."はSRVレコードについてのRFCである RFC 2782 A DNS RR for specifying the location of services (DNS SRV) を由来として、サービスが利用できないことを示す偽ホスト名として用いられています。

RFC 7505に対応していないメールサーバでは"."はホスト名としては正しくないため、恒久的なエラーとして処理されます。 RFC 7505に対応しているメールサーバでは"Null MX"として判断し、恒久的なエラーとして処理されます。 どちらにしろ、恒久的なエラーとして処理されるため、再送は行われず、すぐに送信元メールアドレスにバウンスメールが送り返され、先に述べた問題が解消されます。

"Null MX"を登録したときには、送信側メールサーバは次のような順番に処理を行います。

  1. 宛先メールアドレス"foo@example.com"のドメイン名"example.com"に対するMXレコードを問い合わせる。
  2. "example.com"に対する回答として1個のMXレコードを受け取る。その値は優先度が"0"でメールエクスチェンジャが"."である。
  3. "."を恒久的なエラーとして処理し、配送不能としてバウンスメールを返す。
    • RFC 7505に対応していないメールサーバでは"."を不正なホスト名として処理する。(2016-12-15 注記: 一時的なエラーになり、配送キューに戻される実装もあるとのことです)
    • RFC 7505に対応しているメールサーバでは"Null MX"として処理する。

3の処理はメールサーバのソフトウェアにより動作はやや異なりますが、おおよそ同じような動きをすると思われます。仮にメールサーバのソフトウェアで"."を起因とする問題が発生しても、元々メールの送信先はないため、実質的には問題は無いでしょう。

実際に動きを確認するため、メールサーバのソフトウェアであるPostfixで確認しました。Postfix 3.0からRFC 7505に対応しています。

Postfix 2.10.1の場合は次のようななログ出力が行われ、バウンスメールが送られました。このときのエラーメッセージは"Name service error for name=example.com type=MX: Malformed or unexpected name server reply"です。

Dec 1 12:34:56 postfix210 postfix/smtp[15336]: 16CD322CFFA11: to=, relay=none, delay=0.22, delays=0.01/0/0.21/0, dsn=5.4.4, status=bounced (Name service error for name=example.com type=MX: Malformed or unexpected name server reply)

Postfix 3.1.0の場合は、RFC 7505に対応しているため、次のようななログ出力が行われ、バウンスメールが送られました。このときのエラーメッセージは"Domain example.com does not accept mail (nullMX)"です。

Dec 1 12:34:56 postfix31 postfix/smtp[3333]: 8A9C342533: to=, relay=none, delay=0.06, delays=0/0.01/0.05/0, dsn=5.1.0, status=bounced (Domain example.com does not accept mail (nullMX))

メール投稿時での適応

"Null MX"はメール投稿時にも適応することができます。

RCPT TOコマンドで入力された宛先メールアドレスのドメイン名が"Null MX"であるときには、RFC 7504 SMTP 521 and 556 Reply Codes で定義された応答コード"556"、拡張ステータスコード"5.1.10"(Permanent failure: Recipient address has null MX)のエラーとして拒否することができます。

実際にPostfix 3.1.0のメールサーバに対して接続を試みた結果を紹介します。ここで"example.com"に対してNull MXを登録しています。

なお、swaksというSMTPテストツールを使いました。

$ swaks -f bar@example.net -t foo@example.com -s localhost
=== Trying localhost:25...
=== Connected to localhost.
<-  220 localhost ESMTP Postfix (Ubuntu)
 -> EHLO localhost
<-  250-localhost
<-  250-PIPELINING
<-  250-SIZE 10240000
<-  250-VRFY
<-  250-ETRN
<-  250-STARTTLS
<-  250-ENHANCEDSTATUSCODES
<-  250-8BITMIME
<-  250 DSN
 -> MAIL FROM:
<-  250 2.1.0 Ok
 -> RCPT TO:
<** 556 5.1.10 : Recipient address rejected: Domain example.com does not accept mail (nullMX)
 -> QUIT
<-  221 2.0.0 Bye
=== Connection closed with remote host.

RCPT TOの後に、応答コード"556"、拡張ステータスコード"5.1.10"、エラーメッセージ" : Recipient address rejected: Domain example.com does not accept mail (nullMX)"で拒否されたのを確認できます。

※このテストを行ったときのPostfixの設定ファイルmail.cfの一部は下記のものです。

smtpd_relay_restrictions = reject_unknown_recipient_domain permit_mynetworks permit_sasl_authenticated defer_unauth_destination

Null MXを登録した場合の送信元メールアドレス

Null MXを登録した場合には、送信元メールアドレス(エンベロープFrom(RFC5321.MailFrom)およびヘッダFrom(RFC5322.From))にもそのドメイン名を使わないようにしてください。

メールの宛先で何か問題が発生した場合には、通常は送信元メールアドレス宛てにバウンスメールが送り返されます。しかし、Null MXが登録されているときには、バウンスメールの送り先のドメイン名はNull MXになるため、バウンスメールを送ることができません。こうなると問題が発生したことに気づくことができません。

なお、メールサーバの設定にもよりますが、メールの投稿時に送信元メールアドレスがNull MXであるときに、応答コード"550"、拡張ステータスコード"5.7.27"(Permanent failure: Sender address has null MX)として拒否されることもあります。

実際にPostfix 3.1.0のメールサーバに対して接続を試みた結果を紹介します。ここで"example.com"に対してNull MXを登録しています。

$ swaks -f foo@example.com -t bar@example.net -s localhost
=== Trying localhost:25...
=== Connected to localhost.
<-  220 localhost ESMTP Postfix (Ubuntu)
 -> EHLO localhost
<-  250-localhost
<-  250-PIPELINING
<-  250-SIZE 10240000
<-  250-VRFY
<-  250-ETRN
<-  250-STARTTLS
<-  250-ENHANCEDSTATUSCODES
<-  250-8BITMIME
<-  250 DSN
 -> MAIL FROM:
<** 550 5.7.27 : Sender address rejected: Domain example.com does not accept mail (nullMX)
 -> QUIT
<-  221 2.0.0 Bye
=== Connection closed with remote host.

MAIL FROMの後に、応答コード"550"、拡張ステータスコード"5.7.27"、エラーメッセージ": Sender address rejected: Domain example.com does not accept mail (nullMX)"で拒否されたのを確認できます。

※このテストを行ったときのPostfixの設定ファイルmail.cfの一部は下記のものです。

smtpd_delay_reject = no
smtpd_relay_restrictions = reject_unknown_recipient_domain permit_mynetworks permit_sasl_authenticated defer_unauth_destination
smtpd_sender_restrictions = reject_unknown_sender_domain

メールを扱わないドメイン名に対してメールが送信されることがあるのか

そもそも、メールを扱わないドメイン名に対してメールが送信されることがあるのかという話があります。

これについて考えてみると、元々メールを利用していたけど、後で使わなくなった場合が特に該当すると思います。 元々はそのメールアドレスは使われていたので、そのメールアドレスに対してメールが送信されることがあります。

また、メールを利用していなくても、迷惑メールに関してはユーザ名としてinfoとかsalesとかよくあるものを付けてメールアドレスを作成して、悲しくも踏み台として使われてしまったメールサーバ経由で、そのメールアドレス宛てに迷惑メールが送信されることがあります。 さらに、詐称された送信元メールアドレスとして使われることもあります。

そのドメイン名でメールを利用していなければこれらのメールを受け取ることはないですが、実は送信元メールサーバ内では本記事で説明したように送信できないメールが滞留している可能性があります。

このようなケースには"Null MX"を登録すると、他のメールサーバへの余計な負荷の削減になるため、利用する価値はあると思います。

さらに、そのドメイン名でメールを扱わない宣言として、SPF(Sender Policy Framework)の"-all"ポリシーと合わせて利用すると効果が高いでしょう。

まとめ

メールを扱わないドメイン名では"Null MX"を登録することにより他のメールサーバへの余計な負荷を減らします。

最後に

先日、ちょっと気が向いたのでメール関連のRFCの調査をしていたのですが、

冒頭のこれは個人的な趣味で作っているメールRFC系統図のことです。 メールのRFCに興味がありましたらご覧ください。

参考文献

株式会社ハートビーツの技術情報やイベント情報などをお届けする公式ブログです。



ハートビーツをフォロー

  • Twitter:HEARTBEATS
  • Facebook:HEARTBEATS
  • HATENA:HEARTBEATS
  • RSS:HEARTBEATS

殿堂入り記事