DNSとはおおまかに何?
詳しいことはあとで解説します。
DNSとはDomain Name Systemの略で、例えばhttps://yahoo.co.jp
がどのIPアドレスを指して、それを返すことで私たちはヤフーというサイトをみることができる。
そのようにIPアドレスという通信相手の特定のために使われうる機械に優しいように2進数で表されているものを、私たち人間が通信相手を直感的にすぐわかるようにドメイン名で対応づけするのがDNSの役割である。
yahoo.co.jpというドメイン名をDNSから対応するIPアドレスを取得することをDNSに問い合わせるという。また紐づくIPアドレスとドメイン名を取得することを名前解決という。
もちろんDockerをはじめとする仮想コンテナ同士の通信や、Kubernetesのコンテナオーケストラソフトウェアも同様の仕組みを持っている。
Kubernetesクラスタ内で問い合わせられる内部DNSが存在していて、例えばService FrontendからService backendはクラスタ内ではhttp://backendで問い合わせられたりする。
今回はこのDNSがどのように機能しているのか、どう設計したら良いのかを考える。
IPアドレスとは
IPアドレスとは、ビット列であり、101010100000101...
のようなものである。
しかし、私たちが開発しているときに見るとするIPアドレスは192.101....
のような形をしている。
これは先ほどのビット列を8ビット(256)区切りした、2進数に直している。このようにすることでIPアドレスを私たち人間が簡単に管理しやすくなる。
つまり、もっとも小さな0だけのビット列で構成されるIPアドレスは0.0.0.0
で、最大でも255.255.255.255
にしかIPアドレスは存在しないことになる。
余談になるが、電話番号のうんちく話があって、電話番号自体が10進数で多くても10桁なのは人間の記憶限界を調査した上で人間が覚えられるもっとも多い桁数らしい。
自分の今のIPアドレスは以下のように確認することができる。
$ ifconfig
IPアドレスの一意性
IPアドレスを知ることは通信相手を特定することと同値である。それは国民ナンバーも同様である。つまり、一意でなければならないのだ。
あるサイト、例えばhttp://futatu_ip_aru_site
を開こうとDNSに問い合わせてIPアドレス35.103.40.101
と34.293.203.2
が帰ってきたらだめである。
ポータルサイトを開こうとしたら、悪質なサイトを開いてしまうかもしれない。(実際にDNSを書き換えられるDNSキャッシュポイゾニングという手法がある)
その一意性を管理するためにもICANNという組織がある。
グローバルIPアドレスとプライベートIPアドレス
IPアドレスには大きく4つの種類がある。
名前 | 概要 |
---|---|
グローバルIPアドレス | 一意に定まるIPアドレス |
プライベートIPアドレス | ローカルなネットワーク(例えばLAN)などで有効なIPアドレス |
ループバックIPアドレス | 自分自身を指す特別なIPアドレスで127.0.0.1 でありlocalhost と言う名前です。 |
ブロードキャストIPアドレス | そのネットワークに所属するすべてのホスト全体を示すものである。ネットワーク全体に通信ができて、ホスト部がすべて1 であるもの。 |
注意点としてはプライベートIPアドレスからはインターネットに接続できないので、送信元にも受信元にもなることができない。なので、ゲートウェイなり何らかの処置をしなければいけなくなるが、大体はインターネットにアクセスする必要性はない。
またプライベートアドレスで使われるIPは以下の通りである。
10.xxx.xxx.xxx
172.xxx.xxx.xxx
192.168.xxx.xxx
この範囲のIPアドレスであればプライベートアドレスであることがわかる。
例えばKubernetesのPodのIPアドレスもプライベートIPアドレスであり、以下のように取得することができる。もちろん、このIPアドレスに外部からアクセスすることはできない。
PODIP=kubernetes get pod -o=jsonpath='{.status.podIP}' curl $PODIP curl: (7) Failed to connect to 10.28.1.77 port 80: Connection refused
サブネットマスクとCIDR記法
よくインフラ構築などをしているとサブネットマスクとCIDR記法に出くわすので知っておいた方がいいでしょう。
サブネットマスク
IPアドレスの先頭の何ビットをネットワークアドレスに使うかを定義する32ビットの数値である。
CIDR記法
ネットワークアドレスを任意に決められる仕組みです。
経路制御
IPアドレスを知ると通信ができる。と述べたが、ただやみくもに相手に届けようとするのではなくて、れっきとした通信経路をもつ。
例えば電話番号でいう+81
だろう。
IPアドレスにもネットワーク部とホスト部があり、ネットワーク部が電話番号でいう地理的な譲歩を持っていて、ホスト部でだれかを特定する。
インターネットとは、そもそもネットワークの集まりであり、それぞれはルーターによって接続されている。
それぞれのネットワークは主に企業がもっていて、ルータ内への通信を受け、ルータ内でないなら他へ転送する仕組みである。
つまり、ネットワーク部を見れば誰に接続すればいいのかがわかる。さらに、ホスト部はそのネットワーク部内の特定する仕組みなので、ホスト部を見れば通信相手が特定できるというわけである。
また、このような誰がどのIPアドレスを管理するのがIPテーブルというものである。
ドメイン名の構造
以下のようにドメイン名の構造は階層化されている。
もともとはフラットで階層がなく、すべてのIPアドレスを一つのシステムで管理していた。
しかし、インターネットが普及すると対応しきれずに.jpや.comのように管理をそれぞれの管理組織(レジストリ)に委任していった。
それぞれの.で区切ったものをラベルと呼び、右側から左側へいくほど階層が下位のものになっていく。
短縮URLって?
せっかくドメインについて学ぶなら特に身近なものを取り上げる。
特にTwitterをしていると短縮URLという、人間が読んでもわからない短かいリンクが貼っているのを目にした人がいるかもしれない。
ユースケースとしては例えばクエリパラメータが大量に付与されていたりするリンクは長いときである。これを短縮URL提供サービスに送信すると何らかの一意に短くできるアルコリズムで短縮URLを生成されて返される。
また、この生成元となったリンクと生成後を紐づけてデータベースで永続化をする。
リンクが開かれると元のURLを返すという仕組みである。
名前解決の仕組み
まず、スタブリゾルバというクライアント側のソフトウェアが、利用しているISPのキャッシュDNSに名前解決を要求する。
ここでISPとは、インターネットサービスプロバイダのことで、あなたをインターネットに接続してくれる役割を担っている人である。
キャッシュDNSは何をするかというと、それぞれの権威DNSサーバーに階層ごとに問い合わせしてIPアドレスを解決していく。
つまりまず権威DNSサーバーにアクセスして、ここにはそのIPアドレスはないが.jpのDNSサーバに聞いてくれとレスポンスが入る。
次に.jpのDNSサーバにアクセスするとここにはそのIPアドレスはないがexample.jp
のDNSサーバに聞いてくれとレスポンスが入る。
また、最後にexample.jpのDNSサーバにアクセスするとやっとIPアドレスが取得できスタブリゾルバが取得して、PCのアプリケーションに引き渡すっという感じである。
この仕組みによって、柔軟に、非常に大きなスケールでIPアドレスとドメインを対応させることができたのである。
また、名前解決にも二つの種類がある。
正引き
ドメイン名からIPアドレスを取得する方法である。
これはDNSクエリをすることができます。
$ host example.com => IPアドレスが返ってきます
ここでリソースレコードを取得したければ-t
オプションで-any
をつけると取得することができます。
逆引き
あまり使いませんが、IPアドレスからドメイン名を取得する方法です。
より深く知る
サブドメインとゾーン
例えばAPIサーバーなどはapi.hogehoge.com
のようにサブドメインであるapi.
がつけられていて、本体のWebアプリケーションはhogehoge.com
だったりする。
サブドメインというようにドメインよりも下位の概念であり、左にいけばいくほど下位の概念になるルールからもわかると思う。
しかし、注意点としてサブドメインで定義されるゾーンにも委任をするかしないかでゾーンとして成立する場合と成立しない場合の二つ種類がある。api.で委任されずにhogehoge.com
と同様に管理されていて同じゾーンであるケースや逆の場合もある。
ゾーンごとに権限が管理されているので、それを知る必要がある。
DNSの詳しいこと
動作原理
最初に大まかに動作を簡単に説明した。しかし、キャッシュっという言葉が名前解決をしてくれるサーバーについているようにキャッシュ機能を使っていることを理解するにはもう少し具体的に説明する必要がある。
- まずアプリケーションからクライアント側のスタブリゾルバにドメイン名が渡されて、名前解決が始まる。このときにhogehoge.comのIPアドレスをくれ!というリクエストをキャッシュDNSサーバーに送る。
- キャッシュDNSサーバーからは自身のキャッシュに「
hogehoge.com
がIPアドレス34.193.234.3
ですよ」などの情報をキャッシュしてなければ、権威DNSサーバに名前解決のために反復検索をするようになる。ここではヒントファイルといるルートサーバーの一覧があって、そのルートサーバーに問い合わせるようになる。
- ドメインの委任から.jpや.comのゾーンを管理しているDNSサーバーに問い合わせろとレスポンスが返る。
- これをどんどん下位のIPアドレスが特定できるまでのゾーンまで続ける。IPアドレスを渡す際に、そのサーバーは権限をもってIPアドレスを返す。
- スタブリゾルバがアプリケーションにIPアドレスを渡す。IPアドレスはキャッシュ用のデータベースにも記録される。キャッシュは有効期限が切れるまではスタブリゾルバに直接的にIPアドレスを返すために使われる。
以上のような流れになっている。厳密に書くと以下のようになります。
負荷分散
階層構造
私たちがIPアドレスに紐づくようなWebページ(すべてだが)にアクセスをすると、この問い合わせが始まる。
しかしYahooにもyahoo.com
やyahoo.co.jp
のようにルート自体がもっとも負荷のかかるようになっている。これは仕方ないが、逆に下位の.jp
などは負荷がかからないのである。
キャッシュを使う
また、先ほどの動作原理にもあったようにキャッシュという仕組みを使っているので一回問い合わせて名前解決をされた履歴があれば、一定期間ないなら反復解決をしなくてもIPアドレスを取得することができる。
ネガティブキャッシュ
次にネガティブキャッシュをいう仕組みを説明しておく。あるドメインに対して毎回IPアドレスを取得せずに保存しておくのがキャッシュであった。その反対に、IPアドレスが存在せずに名前解決できないものもキャッシュしておくのがネガティブキャッシュである。これは間違ったドメイン名を問い合わせているときに毎回名前解決のために反復検索をしなくて済むようしているのである。
TTL、DNS浸透期間とサービスダウンのリスクは
キャッシュの有効期限をTTL(Time to live)といい、どれだけ保持し、同じドメインに対してキャッシュを使うかを設定する。
逆をいうと、変更されてもキャッシュDNSサーバーに保持されているため、DNSのリソースレコードを設定してもすぐに反映されるわけではない。
この時に有効期限内ならば元のIPアドレスをキャッシュをしているので新しいIPアドレスを取得せずに返してしまう。 キャッシュの有効期限が切れると新しいIPアドレスにアクセスできるようになります。この期間をDNS浸透期間と言う。
このこれを設定することでいつまでも古いIPアドレスにアクセスしないようにすることができる。
しかし、これがリスクになったりします。例えばサーバーを移行して古いサーバーを削除した場合、キャッシュでは世の中にすでにないIPアドレスを持っていたりしていて、このときにアクセスすると404
が返ってくる。このような面でDNS浸透期間は早ければ早いほどいい(=すぐに新しいIPが反映される)状態は必ずしもいいわけではなく、運用という面ではリスクがある。
長いのとは反対に、TTLが短いとキャッシュをしなくなるので毎回権威DNSサーバーにアクセスをするのでキャッシュDNSサーバーのキャッシュをうまく使えず、負荷がかかってしまう。
つまりTTLはトレードオフになっていて、DNSサーバーへの負荷とリソースレコードの移行のしやすさを適切に選ばない。
ネームサーバーって
ネームサーバーとはDNSサーバーのことです。
ドメインを取得するとどのようなことが起きているのか?
大前提として、ドメインは各トップドメインごとにレジストリという管理団体が管理をしています。
あるドメインをとると、そのドメインのDNSサーバーを決定されます。つまり、DNSの設定を書き換えるには指定されたDNSサーバでなければならないので、他のDNSで設定しても期待する動作にはならないので注意が必要です。
まとめ
DNSを理解することは、ドメインとIPアドレスがどのように名前解決されるのかを知るには重要な概念です。
また、自分のドメインを取得して割り当てたりするにはこのような知識が必要です。
ドメインレジストラというドメインを買えたりするシステムがあるからこそ重要になってきます。