ミツカリ技術ブログ

株式会社ミツカリの開発チームのブログです

DNSに再入門: NS, AAAAレコードの必要性を整理する

こんにちは、ミツカリCTOの塚本こと、つかびー(@tsukaby0) です。

DNSは昨今のWebを支える技術です。

前回はDNSサーバーをRoute53からCloudflareに移行したという記事を書きました。

tech-blog.mitsucari.com

今回は移行中に生じた疑問をベースに、各種レコードの認識が甘い部分を整理してみました。

概要

  • 自ドメイン(自分のDNS)にもNSレコードは必要であり、権威を表明している
  • AAAAレコードは通信高速化のためには必要だが、必須ではない

解説しないレコード

以下のレコードは今回の対象範囲からは除外します。

  • Aレコード
    • ドメインとIPv4アドレスの対応
  • CNAMEレコード
    • エイリアス。別名
  • TXT
    • 一定のテキストを保存するためのもの。SPF/DKIM/DMARCなど、その他認証で利用
  • MX, CAA, PTR, ALIAS, etc

NSレコードは自分のゾーンにも必要なのか?

前回の記事では上位の権威DNSサーバーに自分のドメインのDNSサーバーの場所(NSレコード)が記録されているという話をしました。

Amazon Route53ではホステッドゾーンを作成すると自動でNSレコードが作成されます。設定値はRoute53のサーバーです。これは公式ドキュメントにもあるとおり、Route53の仕様です。

ここで1つ疑問が生まれます。例えば自身が持っている example.com ドメインのDNSサーバー(NS)を指すNSレコードは com の権威DNSサーバーに登録されます。これによってDNSクエリが投げられた時は example.com については指定のNSに問い合わせてね、という委任ができるようになるわけです。つまり、DNSクエリのフローだけを考えると自分のDNSサーバーにはNSレコードは登録しなくても良いのでは?と思います。

しかしどうしてRoute53ではNSレコードが自動で作られるのでしょうか。

また、CloudflareではRoute53とは異なりNSレコードは自動では作成されません。

これも疑問点の1つです。

どうしてこうなっているのか?NSレコードは必要なのか?を調査してみました。

CloudflareはUI上見えていないだけで、自動で登録されている

Cloudflareですが、これはGUI上でNSレコードが登録されていないように見えるだけで実際には裏で自動で登録されているようです。

dig @自ドメインのDNSサーバー foo.com NS というコマンドで結果が返ってくるので自動で登録されることが確認できます。

> dig @oswald.ns.cloudflare.com foo.com NS

(前略)

;; ANSWER SECTION:
foo.com.              86400   IN      NS      oswald.ns.cloudflare.com.
foo.com.              86400   IN      NS      treasure.ns.cloudflare.com.

(後略)

自ドメインのNSレコードは権威表明のために存在する

以下のJPRSの森下さん、堀さんのスライドが参考になりました。この情報の裏付けは取れてませんが、専門家なのでおそらく正しいでしょう。

https://jprs.jp/tech/material/iw2012-lunch-L3-01.pdf

まず、NSレコードはそもそも委任のためにあるものです。これがあるから (root) -> com -> foo.com というように辿れるわけですね。 .co.jp はjpのサブドメインだけど、そこは委任されていないというのは知りませんでした。確かに自分たちで tech-blog.foo.com などのサブドメインを作ることがありますが、NSを別に立てて委任するとは限りませんね。

親側(.com)のNSレコードは委任の表明であり、子側(foo.com)のNSレコードは権威の表明であることが書かれています。

自ドメインのネームサーバーを自ドメインのNSレコードとして登録するとループする

以下はRFC1034をJPRSが翻訳しているものですが、以下のような記述があります。

4.2.2. 管理に関する考慮点

ある組織が自身のドメインを管理したいと望む場合、その第一段階は、適切な親ゾーンを特定し、親ゾーンの所有者と管理の委任に関する合意を取り付けることである。管理を委任できるツリーの位置に関して技術面での具体的制約は何もないが、トップレベルの組織化に対応する管理上のグループ分けに関しては[RFC-1032]で議論されている。中間レベルのゾーンに関しては、独自のルールを自由に作成できる。例えば、ある大学は単一のゾーンの使用を選択するかもしれないし、別の大学は個々の学部または学科専用に設けられたサブゾーンによる構成を選択するかもしれない。[RFC-1033]は、利用可能なDNSソフトウェアと管理上の手続きを列挙している。

新しいサブゾーンの適切な名前が選択された時点で、新しい所有者は冗長なネームサーバーのサポートを実証することが要求されるべきである。ゾーンのサーバーが、そのドメインに属する名前のホストでなければならないという要件は存在しないことに注意せよ。多くの場合、ゾーンのサーバーは、ゾーン管理組織が管理する物理施設内にあるよりは、広域に分散配置した方が全体としてインターネットへのアクセス性はより向上するだろう。例えば現在のDNSでは、英国またはUKドメインのネームサーバーはアメリカ合衆国(US)にある。これにより、USのホストは大陸間を横断する限定された帯域を使用することなく、UKのデータを取得できるようになっている。

導入の最終段階として、委任を有効にするために必要な委任のNS RRとグルーRRが親ゾーンに追加されるべきである。両ゾーンの管理者は、カットの両側をマークするNSとグルーRRに一貫性があることを保証し、またそれを維持し続けるべきである。

引用: https://jprs.jp/tech/material/rfc/RFC1034-ja.txt

両ゾーンの管理者は、カットの両側をマークするNSとグルーRRに一貫性があることを保証し、またそれを維持し続けるべきである。

と言っています。まずRRはResource recordのことなので単純にレコードのことです。グルーRRというのは以下が参考になります。

jprs.jp

先ほどまでの私の例だとfoo.comのNSはoswald.ns.cloudflare.comなので、ドメインが異なります。その場合は問題がないのですが、同一ドメインにNSがある場合はループが発生してしまいます。

上記の記事と同じですが、例えばexample.jpのネームサーバーがns1.example.jpだとします。

  1. 「example.jpのIPアドレスは?」と問い合わせる
  2. 親(.jp)が「ns1.example.jpに聞いて」と答える
  3. 「ns1.example.jpのIPアドレスは?」と問い合わせる
  4. 「example.jpのネームサーバー(ns1.example.jp)に聞いて」(無限ループ)

というようになってしまいます。そこでAレコードを追加してns1.example.jpのIPアドレスを応答させることでループを回避できます。

また、

一貫性があることを保証し、またそれを維持し続けるべきである

という一文がありますが、おそらくはこれがあるから自ドメインのDNSサーバーにもNSレコードを登録して一貫性を保っている(権威を表明している)のでしょうね。作法なのかなと思いました。このあたりの経緯はもう少し深く調査しないと分かりません。RFCだからといって何でも分かるわけではなくやはり背景情報などは抜け落ちてしまいがちですね。

AAAAレコードも設定する必要があるか?

AレコードはIPv4アドレス用ですが、AAAAレコードはIPv6アドレス用です。

ただ単にそれだけなのですが、我々のような何らかのサービスを運営している事業者目線ではどうなるのでしょうか。AAAAは必要なのか気になります。

結論としては「無くても良いが、あった方がよい」という感じかなと思っています。

ISPなどからIPv6のアドレスを配られている端末からIPv4のサーバーにアクセスしようとした場合、NAT64でIPv6=>IPv4変換が行われます。変換があるということは当然余計なオーバーヘッドが発生するということです。サーバー側がIPv6も持っていたとしたら変換を回避することができます。つまり高速に接続できます。

そのため、我々のような事業者はIPv6対応した方が良いが、別になくてもサービス提供は可能である、というような結論になります。

勿論やったほうが良いのはそうなのですが、やった方が良いからやるというわけには行きません。開発に限らずあらゆる仕事は価値があることに集中すべきです。IPv6は本当に高速化に貢献するのでしょうか?(IPv4枯渇問題は置いといて、我々事業者にとって)価値があるのでしょうか?

そこで実験してみることにします。

IPv4経由とIPv6経由の速度比較

私の自宅環境はISPからIPv4とIPv6を配られています。この状況でIPv4を使ってとあるWebページに接続するケースとIPv6を使ってWebページに接続するケースで速度を比較してみます。

計測にはcurlを使います。curlには -4-6 というオプションがあり、これを使うとホスト名解決時にIPv4またはIPv6がそれぞれ使われます。ただし、curlは内部的にフォールバックする仕組みがあるので、仮に接続先がAAAAを提供していない状態で -6 を付けたとしてもcurlコマンドは成功します(IPv4にフォールバックします)。そこでcurlを実行する前に対象のサービス(私が持っているもの)が本当にIPv6経由で接続できるのかを確認します。

dig +short foo.com AAAA
2606:...
2606:...

(※実際にはfoo.comではなく別のドメインです)

この対象サービスはCloudflareで配信していますが、AAAAレコードが登録されておりIPv6に対応しています。もちろんAレコードも返ってきます。

この状態で以下のようなコマンドを実行してみます。

for i in {1..10}; do
  curl -4 -o /dev/null -s -w "%{time_total}\n" https://foo.com
done | awk '{sum += $1} END {if (NR>0) print sum/NR}'

-4-6 の2パターンで実行した結果が以下です。

  • -4 の場合: 0.0977467
  • -6 の場合: 0.110404

予想に反してIPv4の方が早いという結果が出ました。

私がプロバイダからIPv6しか配られていない場合はまた話が変わってきそうですが、新しい規格であるIPv6の方が通信が遅いのはなぜでしょうか。

そこでtraceroute, traceroute6の2つのコマンドを使ってみます。これらは通信経路を可視化するコマンドです。

> traceroute foo.com
traceroute: Warning: foo.com has multiple addresses; using 104.21.50.xxx
traceroute to foo.com (104.21.50.xxx), 64 hops max, 40 byte packets
 1  aterm.me (192.168.10.xxx)  18.907 ms  3.914 ms  4.069 ms
 2  *.kddnet.ad.jp (118.155.198.xxx)  9.643 ms  8.185 ms  9.284 ms
 3  27.86.120.xxx (27.86.120.xxx)  11.028 ms  9.657 ms  8.886 ms
 4  27.86.45.xxx (27.86.45.xxx)  9.923 ms
    27.85.137.xxx (27.85.137.xxx)  9.950 ms
    27.86.45.xxx (27.86.45.xxx)  9.977 ms
 5  * 27.85.134.xxx (27.85.134.xxx)  14.850 ms *
 6  103.22.201.xxx (103.22.201.xxx)  13.507 ms
    103.22.201.xxx (103.22.201.xxx)  10.323 ms
    103.22.201.xxx (103.22.201.xxx)  12.304 ms
 7  104.21.50.xxx (104.21.50.xxx)  10.801 ms  8.552 ms  8.065 ms

> traceroute6 foo.com
traceroute6: Warning: foo.com has multiple addresses; using 2606:4700:3031::ac43:****
traceroute6 to foo.com (2606:4700:3031::ac43:****) from 240b:10:3fc2:6100:****:****:****:****, 64 hops max, 28 byte packets
 1  aterm.me  6.277 ms  4.044 ms  4.212 ms
 2  240b:10:1f1f:ffff::****  9.566 ms  44.705 ms  11.520 ms
 3  * * *
 4  * * *
 5  2404:9200:225:7::****  10.346 ms  24.402 ms  20.898 ms
 6  * *
    2001:268:fa02:1b6::****  16.905 ms
 7  *
    2001:268:fa02:1d5::****  17.297 ms
    2001:268:fa02:173::****  12.623 ms
 8  2001:de8:8::1:3335:****  15.008 ms  15.001 ms  24.475 ms
 9  2400:cb00:382:3::****  24.064 ms
    2400:cb00:448:3::****  11.538 ms
    2400:cb00:382:3::****  15.904 ms
10  2400:cb00:448:1024::ac46:****  12.683 ms
    2400:cb00:763:1024::ac47:****  12.599 ms
    2400:cb00:1009:1024::ac40:****  9.903 ms

(※結果は一部マスクしています)

この結果からIPv6接続の場合は経由するネットワークノードが10個存在することが分かります(IPv4は7個)。

どうしてこうなっているのかは分かりませんが、おそらくこれが原因だと思います。私の通信環境においては(接続先にもよりますが)IPv6に対応しているサイトはあまり意味ないと言えそうです。

とはいえあくまでこれは私個人の話に限ります。国外であったり、国内でも別の通信網(私の場合はKDDIの様子)の場合はIPv4よりIPv6の通信網の方が高速化かつ最適化されている可能性はあります。実際、同僚にも同じ検証をしてもらったところ、同僚の環境ではIPv6のほうが早いという結果になりました。v4とv6どちらが早いかは環境次第と言えそうです。

これらの結果からIPv6対応(AAAAレコードの用意)は意味があることだとは思います。ただ、価値があるかは少し微妙なところです。

今回も前回に続いてDNSについて調べてみました。今後も気の向くままに気になったことを調べたり、実験したり、作っていきたいと思います。


現在、ミツカリではITエンジニアを募集しています。興味のある方はぜひお気軽にご連絡ください!

herp.careers