Yakstは、海外の役立つブログ記事などを人力で翻訳して公開するプロジェクトです。
約1年前投稿 修正あり

DNSの仕組み

DNSの仕組みと一般的な使い方について、DNSに関する作業をする時によく使うコマンドや、具体的な例を交えてまとめた入門的記事。

原文
DNS: The Good Parts | Pete Keen (English)
翻訳依頼者
D98ee74ffe0fafbdc83b23907dda3665
翻訳者
D98ee74ffe0fafbdc83b23907dda3665 doublemarket
翻訳レビュアー
B5aa4f809000b9147289650532e83932 taka-h
原著者への翻訳報告
未報告


私はよくドメイン名に関する問題に遭遇します。どうしてウェブサイトが動かないんだ? どうしてこんなくだらないのが上手くいかないんだ、何やってもダメだ。ただ動かしたいだけなのに! 質問をしてくる人はたいてい、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 レコードを問い合わせます。 Aaddressの意味で、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 をひとつだけ持っているという意味です。 300TTL 値(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.infoA レコードを聞き、やっと実際の答えを得るのです。

ふーっ!これがたくさんのトラフィックの理由です。ただし、これらのエントリーのほとんどがチェーン上の各サーバに長くキャッシュされないという前提の場合です。あなたのコンピューターもキャッシュしますし、ブラウザーもキャッシュします。サーバーのIPアドレスはほとんど変わらないので、DNS名前解決ではルートサーバーまでたどり着くのはまれです。 comnetorg といったトップレベルドメインも通常は同じように十分にキャッシュされています。

その他の型

気に留めておくべき型が他にもいくつかあります。最初は MX で、これはドメイン名をひとつあるいは複数のメールサーバーにマップするものです。メールは、独自のレコード型を持つインターネットの非常に重要な機能です。 petekeen.netMX レコードは以下のようになっています。

$ 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.netweb01.bugsplat.info にマップされていることを示しています。2行目は、そのサーバーの A レコードです。 CNAME のひとつの考え方として、他のドメイン名の エイリアス であると言えます。

CNAMEが混乱する理由

CNAME は非常に便利ですが、ひとつ非常に重要な点があります。ある名前に対して CNAME が存在している時、それはその名前に対して 唯一の レコードであるということです。 MX も、 A も、 NS も同時に存在することはできません。これは、DNSが CNAME のターゲットを CNAME の値で代替してしまうので、各レコードは CNAME に対して有効になってしまうのです。これが、 CNAMEpetekeen.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リダイレクトを以下のように設定します。

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を以下で定義しています。

これ以外にも DNSSEC について書かれた4034や、電子メールに関係してDNSについて書かれた5321 といったいくつかの興味深いRFCがあります。さらに詳しい情報を知りたいなら、これらは興味をそそる読み物でしょう。

次の記事
InfluxDB 1.0 GAリリース : 振り返りとこれから
前の記事
git diffコマンドで比較する時のダブルドット(..)とトリプルドット(...)の違いとは?

Feed small 記事フィード