私はよくドメイン名に関する問題に遭遇します。どうしてウェブサイトが動かないんだ? どうしてこんなくだらないのが上手くいかないんだ、何やってもダメだ。ただ動かしたいだけなのに! 質問をしてくる人はたいてい、DNSが何かを知らず、基本的な部分がどのように動くのかの理解にも乏しいです。より一般的には、みんなDNSが強くて複雑なものだと思っているのです。この記事では、その恐怖を和らげようと努力してみようと思います。一度基本的なコンセプトを理解してしまえば、DNSは簡単です。
DNSとは
まず大事なことから始めましょう。DNSは、Domain Name Systemの略です。基本的には、これはグローバルに分散されたキーバリューストアだと言えます。世界中のサーバーは、あなたが問い合わせたキーに対するバリューを返します。サーバーがそのキーを知らなければ、答えを出すために他のサーバーに尋ねます。
これだけです。どうってことはありません。あなた(あるいはあなたの使っているWebブラウザー)がキー(www.example.com
)に対する値を尋ねれば、 1.2.3.4
が返ってくるというわけです。
基本的な使い方と型
DNSが素晴らしいのは、完全にパブリックでオープンなので、あちこち見て回るのが簡単ということです。 web01.bugsplat.info
という名前のマシンにホストしているこのドメイン potekeen.net
から始めて、少々探検してみましょう。ここに出てくる例のすべてを、OS XあるいはLinuxのコマンドラインから試せます。
まず、シンプルにドメイン名からIPアドレスへのマッピングを見てみましょう。
$ dig web01.bugsplat.info
dig
コマンドはDNSへの問い合わせに関して本物のスイスアーミーナイフのように万能で、これはよく使うことになるでしょう。レスポンスの前半部分はこうなっています。
; <<>> DiG 9.7.6-P1 <<>> web01.bugsplat.info
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 51539
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
ひとつだけ興味深いところがあります。1レコードを問い合わせて、ぴったり1つの答えが返ってきています。これがその部分です。
;; QUESTION SECTION:
;web01.bugsplat.info. IN A
dig
はデフォルトで A
レコードを問い合わせます。 A
はaddressの意味で、DNSにおいて基本的なレコードの型のひとつです。 A
レコードはひとつの IPv4
アドレスを保持します。これに対応する IPv6
のアドレスは AAAA
になります。次に、DNSサーバからの回答を見てみましょう。
;; ANSWER SECTION:
web01.bugsplat.info. 300 IN A 192.241.250.244
これは、ホスト web01.bugsplat.info.
が、 A
アドレス 192.241.250.244
をひとつだけ持っているという意味です。 300
は TTL
値(time to live 有効期限)と呼ばれます。これは、このレコードがキャッシュされて次に確認される必要があるようになるまでの秒数です。 IN
コンポーネントは、 Internet
のことで、DNSが歴史的に責任を負ってきた色々なネットワークタイプでの曖昧さをなくすためにあります。これについては、IANAのDNSパラメータについてのドキュメントを読んでみるとよいでしょう(mcmatterson訂正どうもありがとう)。
レスポンスの残りの部分は、レスポンス自体について教えてくれます。
;; Query time: 20 msec
;; SERVER: 192.168.1.1#53(192.168.1.1)
;; WHEN: Fri Jul 19 20:01:16 2013
;; MSG SIZE rcvd: 56
具体的に言うと、サーバーがレスポンスを返すのにどのくらいかかったか、そのサーバーのIPアドレスが何か(192.168.1.1
)、 dig
が問い合わせたポートはどれか(53
、DNSのデフォルトのポート)、クエリーが完了した時刻はいつか、レスポンスが何バイトあったか、という情報が含まれています。
見ての通り、ひとつのDNSクエリーで大変な量の処理が行われます。Webページを開くたびに、ブラウザーはWebホスト、それも画像やスクリプトの置かれた外部ホストも含めたすべての名前解決をするために文字通り何ダースものクエリーを発行します。ひとつひとつのリソースは最低でもひとつのDNSクエリーに対応しており、DNSが大量にキャッシュするようなデザインになっていなければ、大変な量のトラフィックにつながります。
あなたは意識していないかもしれませんが、 web01.bugsplat.info
にマップされたアドレスが何かというシンプルな質問に答えるために、192.168.1.1
のDNSサーバーが、他の一連のサーバ全体と接続しているという動きがあります。なにもキャッシュされていない時に dig
がアクセスする全てのサーバを見るのにトレースをかけてみましょう。
$ dig +trace web01.bugsplat.info
; <<>> DiG 9.7.6-P1 <<>> +trace web01.bugsplat.info
;; global options: +cmd
. 137375 IN NS l.root-servers.net.
. 137375 IN NS m.root-servers.net.
. 137375 IN NS a.root-servers.net.
. 137375 IN NS b.root-servers.net.
. 137375 IN NS c.root-servers.net.
. 137375 IN NS d.root-servers.net.
. 137375 IN NS e.root-servers.net.
. 137375 IN NS f.root-servers.net.
. 137375 IN NS g.root-servers.net.
. 137375 IN NS h.root-servers.net.
. 137375 IN NS i.root-servers.net.
. 137375 IN NS j.root-servers.net.
. 137375 IN NS k.root-servers.net.
;; Received 512 bytes from 192.168.1.1#53(192.168.1.1) in 189 ms
info. 172800 IN NS c0.info.afilias-nst.info.
info. 172800 IN NS a2.info.afilias-nst.info.
info. 172800 IN NS d0.info.afilias-nst.org.
info. 172800 IN NS b2.info.afilias-nst.org.
info. 172800 IN NS b0.info.afilias-nst.org.
info. 172800 IN NS a0.info.afilias-nst.info.
;; Received 443 bytes from 192.5.5.241#53(192.5.5.241) in 1224 ms
bugsplat.info. 86400 IN NS ns-1356.awsdns-41.org.
bugsplat.info. 86400 IN NS ns-212.awsdns-26.com.
bugsplat.info. 86400 IN NS ns-1580.awsdns-05.co.uk.
bugsplat.info. 86400 IN NS ns-911.awsdns-49.net.
;; Received 180 bytes from 199.254.48.1#53(199.254.48.1) in 239 ms
web01.bugsplat.info. 300 IN A 192.241.250.244
bugsplat.info. 172800 IN NS ns-1356.awsdns-41.org.
bugsplat.info. 172800 IN NS ns-1580.awsdns-05.co.uk.
bugsplat.info. 172800 IN NS ns-212.awsdns-26.com.
bugsplat.info. 172800 IN NS ns-911.awsdns-49.net.
;; Received 196 bytes from 205.251.195.143#53(205.251.195.143) in 15 ms
DNSは階層構造に並べられています。前に尋ねたように、 dig
がどのようにホスト名 web01.bugsplat.info
の後に .
をひとつ追加するかを思い出してください。この .
はとても重要で、階層構造のルートであることを示しているのです。ルートDNSサーバーは世界中の色々な企業や政府が運用しています。元々は少数のサーバーしかなかったのですが、インターネットが成長するに従って追加され、見た目上は13台あるようになりました。これらのサーバーのそれぞれは、ひとつのIPアドレスの裏にたくさんの物理マシンが隠れた構造になっています。
というわけで、トレースの最初には NS
レコードによって表現されたルートサーバーがあるのがわかります。 NS
レコードはドメイン名をマップするもので、この場合はルートをDNSサーバーにマップしています。あなたがドメイン名をNamecheapやGodaddy(訳注 : どちらも有名なレジストラー)といったレジストラーに登録すると、レジストラーは NS
レコードを作ってくれます。
次のブロックでは、 dig
がルートサーバーのレスポンスの中の1つをランダムに選び、それに対して A
レコード web01.bugsplat.info
を尋ねているのがわかるでしょう。どのルートサーバーでしょうか?確認しましょう。
$ dig -x 192.5.5.241
; <<>> DiG 9.8.3-P1 <<>> -x 192.5.5.241
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 2862
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;241.5.5.192.in-addr.arpa. IN PTR
;; ANSWER SECTION:
241.5.5.192.in-addr.arpa. 3261 IN PTR f.root-servers.net.
-x
フラグは、与えられたIPアドレスに対する逆引きをさせるように dig
に指示します。DNSはIPをホスト名、この場合 f.root-servers.net
にマップする PTR
レコードを返します。
元のクエリーに戻って、 F
ルートサーバーは、別の NS
サーバーのセットを返しています。この場合は、 info
トップレベルドメインに責任を持つサーバーたちです。 dig
はこのサーバーたちに web01.bugsplat.info
に対する A
レコードを問い合わせ、また別の NS
サーバー群を受け取り、そのサーバ群の中の1台に web01.bugsplat.info
の A
レコードを聞き、やっと実際の答えを得るのです。
ふーっ!これがたくさんのトラフィックの理由です。ただし、これらのエントリーのほとんどがチェーン上の各サーバに長くキャッシュされないという前提の場合です。あなたのコンピューターもキャッシュしますし、ブラウザーもキャッシュします。サーバーのIPアドレスはほとんど変わらないので、DNS名前解決ではルートサーバーまでたどり着くのはまれです。 com
、 net
、 org
といったトップレベルドメインも通常は同じように十分にキャッシュされています。
その他の型
気に留めておくべき型が他にもいくつかあります。最初は MX
で、これはドメイン名をひとつあるいは複数のメールサーバーにマップするものです。メールは、独自のレコード型を持つインターネットの非常に重要な機能です。 petekeen.net
の MX
レコードは以下のようになっています。
$ dig petekeen.net mx
; <<>> DiG 9.7.6-P1 <<>> petekeen.net mx
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 18765
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;petekeen.net. IN MX
;; ANSWER SECTION:
petekeen.net. 86400 IN MX 60 web01.bugsplat.info.
;; Query time: 272 msec
;; SERVER: 192.168.1.1#53(192.168.1.1)
;; WHEN: Fri Jul 19 20:33:43 2013
;; MSG SIZE rcvd: 93
MX
レコードはIPアドレスではなく名前を指し示す点に注意しましょう。
知っておくべきもうひとつのレコード型は、 Canonical Name (正規名) の略の CNAME
です。これは、ある名前を他の名前にマップするものです。 CNAME
に対してのレスポンスを見てみましょう。
$ dig www.petekeen.net
; <<>> DiG 9.7.6-P1 <<>> www.petekeen.net
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 16785
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;www.petekeen.net. IN A
;; ANSWER SECTION:
www.petekeen.net. 86400 IN CNAME web01.bugsplat.info.
web01.bugsplat.info. 300 IN A 192.241.250.244
;; Query time: 63 msec
;; SERVER: 192.168.1.1#53(192.168.1.1)
;; WHEN: Fri Jul 19 20:36:58 2013
;; MSG SIZE rcvd: 86
最初に気づくのは、2つの返事が返ってきていることです。最初の1行は、 www.petekeen.net
が web01.bugsplat.info
にマップされていることを示しています。2行目は、そのサーバーの A
レコードです。 CNAME
のひとつの考え方として、他のドメイン名の エイリアス であると言えます。
CNAMEが混乱する理由
CNAME
は非常に便利ですが、ひとつ非常に重要な点があります。ある名前に対して CNAME
が存在している時、それはその名前に対して 唯一の レコードであるということです。 MX
も、 A
も、 NS
も同時に存在することはできません。これは、DNSが CNAME
のターゲットを CNAME
の値で代替してしまうので、各レコードは CNAME
に対して有効になってしまうのです。これが、 CNAME
を petekeen.net
のような (訳注 : サブドメインのないドメイン、Zone Apexという)ドメインに使えない理由でもあります。こういったドメインは、 MX
のような他のレコードで使われるのが一般的だからです。
他のサーバーに問い合わせる
DNS設定をぐちゃぐちゃにしてしまった時のことを話しましょう。問題は直したけれど、キャッシュの有効期限が切れるのを待ちたくないとします。 dig
を使うと、デフォルトサーバーに問い合わせる代わりにたくさんのパブリックDNSサーバーのうちの1台に問い合わせることができます。
$ dig www.petekeen.net @8.8.8.8
IPアドレスやホスト名の後に来る @
の文字は、 dig
にデフォルトのDNSポートを使ってそのサーバーに問いあわせるように伝えることを意味しています。私はGoogleのパブリックDNSサーバーや、 4.2.2.2
のようなレベル3のパブリックサーバーとみなしてよさそうなサーバーをよく使っています。
よくある問題
この最後のセクションでは、Web開発者がはまりがちなよくある問題について話します。
Zone apexをwwwにリダイレクトする
ほとんどどんな場合でも、 iskettlemanstillopen.com
のようなZone apexを www.iskettlemanstillopen.com
にリダイレクトしたくなるでしょう。NamecheapやDNSimpleのようなレジストラーはこれをURLリダイレクトと呼びます。NamecheapではURLリダイレクトを以下のように設定します。
@
はルートドメイン iskettlemanstillopen.com
を表しています。このドメインの A
レコードを見てみましょう。
$ dig iskettlemanstillopen.com
;; QUESTION SECTION:
;iskettlemanstillopen.com. IN A
;; ANSWER SECTION:
iskettlemanstillopen.com. 500 IN A 192.64.119.118
このIPはNamecheapが所有しており、HTTPレベルで http://www.iskettlemanstillopen.com
へとリダイレクトするだけの小さなWebサーバーが動いています。
$ curl -I iskettlemanstillopen.com
curl -I iskettlemanstillopen.com
HTTP/1.1 302 Moved Temporarily
Server: nginx
Date: Fri, 19 Jul 2013 23:53:21 GMT
Content-Type: text/html
Connection: keep-alive
Content-Length: 154
Location: http://www.iskettlemanstillopen.com/
HerokuやGitHubへのCNAME
上のスクリーンショットに、 CNAME
の定義が2行目に書かれていたのに気づいたでしょうか。この場合、 www.iskettlemanstillopen.com
はHerokuで動いているアプリケーションにマップされています。同じドメインマッピングでHerokuをセットアップする必要があります。
$ heroku domains
=== warm-journey-3906 Domain Names
warm-journey-3906.herokuapp.com
www.iskettlemanstillopen.com
ページのルートに置かれた CNAME
というファイルにマッピングを書くこと以外は、ドキュメントに書かれている通りGitHub (Pages)でも同じです。
ワイルドカード
多くのDNSサーバーでは、DNSワイルドカードを設定できます。例えば、 web01.bugsplat.info
にマップされた *.web01.bugsplat.info
に対するワイルドカード CNAME
を持っているとしましょう。この場合、 web01
上に任意のホストを作ることができ、いちいち新しいDNSレコードを作る必要がありません。
$ dig randomapp.web01.bugsplat.info
;; QUESTION SECTION:
;randomapp.web01.bugsplat.info. IN A
;; ANSWER SECTION:
randomapp.web01.bugsplat.info. 300 IN CNAME web01.bugsplat.info.
web01.bugsplat.info. 15 IN A 192.241.250.244
まとめ
この記事が、DNSが何者で、どう調べ始め、どのように設定が正しいか確認すればいいのかを理解するいい手がかりになれば嬉しいです。DNSに質問して、そしてその答えを得られるのだ、というのを思い出せばいいのです。インターネットの標準規格(RFC)はDNSを以下で定義しています。
- RFC 1034: Domain Names - Concepts and Facilities
- RFC 1035: Domain Names - Implementation and Specification
これ以外にも DNSSEC
について書かれた4034や、電子メールに関係してDNSについて書かれた5321 といったいくつかの興味深いRFCがあります。さらに詳しい情報を知りたいなら、これらは興味をそそる読み物でしょう。