話題の記事

DNSド素人がdigコマンドとRoute 53を使って、DNSについてあれこれ学んでみた

2018.02.05

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

「やだ、、、DNS、、、怖い・・・」

自分は今までDNS全般についてずーっと苦手意識が強かったんですが、弊社大瀧が、DNSの社内勉強会を開催したのをきっかけに、今一度、digコマンドとRoute 53を利用しながらDNSの基礎について学んでみたので、その過程をご報告します。

digコマンドは、DNSの動作を確認する時のデファクトスタンダードと言えるコマンドですが、残念ながらWindowsには標準実装されていません。が、今回はEC2を利用しているので、Windowsな方も大丈夫です。

この記事を読めば、digコマンドの基本的な使い方と、DNSの挙動の基本的なところが把握できるかと思います。

目次は、こんな感じ。

  1. 検証用の環境を構築
  2. digコマンドの基本的な利用方法を学ぶ
  3. EC2でdigコマンドをあれこれ試してみる
  4. Route 53のプライベートホストゾーンを作成し、DNSレコードを編集してみる

ほな、気軽にいってみましょ。

 __
(祭) ∧ ∧
 Y  ( ゚Д゚)
 Φ[_ソ__y_l〉     DNSダワッショイ
    |_|_|
    し'´J

検証用の環境を構築

以下の構成を作成します。フツーのVPCとEC2です。

作成手順の詳細は省略します。下記公式ドキュメントなどをご参照ください。

ざっくりとした手順はこちら。

  1. VPC(dns-test-vpc)を作成する
  2. VPCのDNS解決とDNSホスト名をTrueに設定する(重要)
  3. インターネットゲートウェイを作成し、VPC(dns-test-vpc)に割り当てる
  4. サブネット(subnet01)を作成する
  5. サブネット(subnet01)に割り当ててるルーティングテーブルに、「送信先:0.0.0.0/0」にインターネットゲートウェイを割り当てる
  6. EC2インスタンス、app01、app02を作成する

Route 53のプライベートホストゾーンの作成が必要ですが、そこは後ほど説明します。

これから記載する全てのコマンドは、VPC内のEC2から実行していますのでご注意ください。

digコマンドの基本的な利用方法を学ぶ

これからdigコマンドを利用して、DNSの挙動を確認していくわけですが、最初にdigコマンドの利用方法を確認します。

digコマンドの基本使用例

$dig @DNSサーバー example.com クエリタイプ
オプション名 必須(?) 解説
@DNSサーバー 任意 名前解決に利用するDNSサーバーを指定
example.com 必須 対象ドメイン名
クエリタイプ 任意 問い合わせるDNSのリソースレコードタイプを指定

クエリタイプに指定できるタイプの一覧(一部)

リソースレコードタイプ 役割
A ホストのアドレス
CNAME ホストの別名
MX ドメインのメール交換ホスト
NS ドメインのネームサーバ
TXT テキスト
ANY 全てのタイプの全てのレコードを返す

試しに、digコマンドを利用して、yahoo.co.jpに名前解決してみましょう。

$ dig yahoo.co.jp

; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.62.rc1.56.amzn1 <<>> yahoo.co.jp
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 57517
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;yahoo.co.jp.			IN	A

;; ANSWER SECTION:
yahoo.co.jp.		60	IN	A	182.22.59.229
yahoo.co.jp.		60	IN	A	183.79.135.206

;; Query time: 5 msec
;; SERVER: 10.0.0.2#53(10.0.0.2)
;; WHEN: Fri Feb  2 23:53:47 2018
;; MSG SIZE  rcvd: 61

なんや、わらわら出力されましたが、以降で各セクションの内容を解説していきます。

digコマンド結果の確認方法

HEADERセクション

; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.62.rc1.56.amzn1 <<>> yahoo.co.jp
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 57517
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 0

ここでは、statusに注目します。

  • NOERROR:正常にクエリが実行されている
  • NXDOMAIN:ドメインが存在しない
  • REFUSED:何らかの理由でクエリが拒否されている

NOERROR以外のstatusが返っている場合は、そのクエリは失敗しているので、注意しましょう。

QUESTIONセクション

;; QUESTION SECTION:
;yahoo.co.jp.			IN	A

DNSへの問い合わせ内容が表示されています。ここでは、yahoo.co.jpドメインのAレコードを問い合わせしています。INはインターネットの略で、クエリ全般これがついているので、とりあえず「そんなもんだ」と覚えておきましょう。

ANSWERセクション

;; ANSWER SECTION:
yahoo.co.jp.		60	IN	A	182.22.59.229
yahoo.co.jp.		60	IN	A	183.79.135.206

問い合わせ内容に対する返答です。ここでは、yahoo.co.jpのエイリアス(Aレコード)に、2つのIPアドレスがあることがわかります。また、ここの60はTTL(キャッシュの生存期間)を表します。

試しに、このIPアドレスにWebブラウザでアクセスしてみてください。yahooのトップページが表示されます。

締めのセクション

;; Query time: 5 msec
;; SERVER: 10.0.0.2#53(10.0.0.2)
;; WHEN: Fri Feb  2 23:53:47 2018
;; MSG SIZE  rcvd: 61

最後に、クエリにかかった時間や時刻が表示されます。ここで一番大事なのが、SERVER。ここに利用したDNSサーバーが表示されます。

digコマンドにおいて、DNSサーバーの指定は必須ではありません。そして、digコマンドを実行した環境により利用されるDNSサーバーは異なるので、「あっちとこっちで、結果が違うやん」という場合、大抵はこのクエリに利用したDNSサーバーが異なっていたというパターンが多いです。

ちなみに、サーバー名の後ろ「#53」は、DNSクエリに利用したポート番号53を表しています。Route 53の名前の由来ですね。

digコマンドの別のオプション

digコマンドには、他にも便利なオプションが存在するので、それらを紹介します。

結果をシンプルに表示したい

+shortオプションを利用すると、クエリ結果がシンプルに表示されます。

$ dig yahoo.co.jp +short
182.22.59.229
183.79.135.206

シェルスクリプトの中で使ったりするには、便利ですね。

ルートからDNSをたどる

+traceオプションを利用すると、強制的にルートサーバーから順番にたどることができます。

$ dig yahoo.co.jp +trace

再帰問い合わせをしない

+norecオプションを利用すると、再帰問い合わせをオフにして、名前解決を実行します。

$ dig yahoo.co.jp +norec

EC2でdigコマンドをあれこれ試してみる

ここから、EC2でdigコマンドをあれこれ試してみます。もう一度、yahoo.co.jpに対して、クエリを流します。

$ dig yahoo.co.jp

; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.62.rc1.56.amzn1 <<>> yahoo.co.jp
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 57517
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;yahoo.co.jp.			IN	A

;; ANSWER SECTION:
yahoo.co.jp.		60	IN	A	182.22.59.229
yahoo.co.jp.		60	IN	A	183.79.135.206

;; Query time: 5 msec
;; SERVER: 10.0.0.2#53(10.0.0.2)
;; WHEN: Fri Feb  2 23:53:47 2018
;; MSG SIZE  rcvd: 61

VPC内で利用するネームサーバ(DNS)のIPアドレスは?

ここでポイントなのが、DNSクエリを発行した時に利用されるDNSサーバ。digの結果を確認すると、下の方、;; SERVER: 10.0.0.2#53(10.0.0.2)で、DNSサーバとして、10.0.0.2のプライベートIPアドレスを利用しています。

これは、VPC内のサブネット内であらかじめAWS側でDNSサーバとして予約されているIPアドレスで、サブネット内IPアドレスの2つ目が、Amazonが提供するDNSサーバとして利用されます。

今回は、サブネットのCIDRが10.0.0.0/24なので、DNSサーバに10.0.0.2が割り当てられているということになります。

詳細は、公式ドキュメントの「VPC での DNS の使用 - Amazon Virtual Private Cloud」を参照ください。

ちなみにこのアドレスは、下記ファイルに記載されています。

$ cat /etc/resolv.conf
; generated by /sbin/dhclient-script
search ap-northeast-1.compute.internal
options timeout:2 attempts:5
nameserver 10.0.0.2

このファイルを編集すればデフォルトで利用するDNSサーバを変更できますが、恐らくはアンチパターンなので安易な変更はやめておきましょう。

Amazon提供のDNSサーバーをVPC内から利用すると、TTLが最大60秒?

上で説明したAmazon提供のDNSですが、あれこれ試してみた結果、VPC内から発行する全てのクエリのTTLが上限が60秒に設定されるようです。

yahoo.co.jpへのクエリで、DNSサーバーにAmazon提供DNSと、Googleが提供するグローバルDNS(8.8.8.8)を利用した時の差分がこちら。

$ dig @10.0.0.2 yahoo.co.jp > dns_amazon.txt
$ dig @8.8.8.8 yahoo.co.jp > dns_google.txt
$ diff dns_amazon.txt dns_google.txt
2c2
< ; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.62.rc1.56.amzn1 <<>> @10.0.0.2 yahoo.co.jp
---
> ; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.62.rc1.56.amzn1 <<>> @8.8.8.8 yahoo.co.jp
6c6
< ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 28002
---
> ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 94
13,14c13,14
< yahoo.co.jp.		60	IN	A	182.22.59.229
< yahoo.co.jp.		60	IN	A	183.79.135.206
---
> yahoo.co.jp.		211	IN	A	182.22.59.229
> yahoo.co.jp.		211	IN	A	183.79.135.206
16,18c16,18
< ;; Query time: 5 msec
< ;; SERVER: 10.0.0.2#53(10.0.0.2)
< ;; WHEN: Sat Feb  3 22:41:45 2018
---
> ;; Query time: 37 msec
> ;; SERVER: 8.8.8.8#53(8.8.8.8)
> ;; WHEN: Sat Feb  3 22:41:56 2018

ANSWERセクションのAレコード部分のTTLをみると、VPC内のAmazonDNSを利用した場合60、GoogleグローバルDNSを利用した時に211になっています。

逆に、TTLが5秒など60秒より短めに設定されているレコードの場合は、5秒で返却されます。

この挙動について公式ドキュメントが見当たらなかったのですが、VPC内からDNSを利用する場合は、TTLを長く設定する必要性がないので、最大60秒と短めに設定されていると推察されます。ただ、この仕様は将来的に変更される可能性もありますので、あくまで現時点での挙動として認識していただければと思います。

同一VPC内への名前解決を試してみた

試しに、パブリックリソースではなく、同一VPC内に作った別のEC2インスタンスのDNSホスト名に対して名前解決してみます。

$ dig ec2-176-32-88-158.ap-northeast-1.compute.amazonaws.com

; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.62.rc1.56.amzn1 <<>> ec2-176-32-88-158.ap-northeast-1.compute.amazonaws.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 33890
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;ec2-176-32-88-158.ap-northeast-1.compute.amazonaws.com.	IN A

;; ANSWER SECTION:
ec2-176-32-88-158.ap-northeast-1.compute.amazonaws.com.	20 IN A	10.0.0.145

;; Query time: 1 msec
;; SERVER: 10.0.0.2#53(10.0.0.2)
;; WHEN: Sat Feb  3 00:08:10 2018
;; MSG SIZE  rcvd: 88

同じように、10.0.0.2に問い合わせて、プライベートIPアドレスの10.0.0.145がかえってきました。まぁ当然の仕様ですね。

Route 53のプライベートホストゾーンを作成し、DNSレコードを編集してみる

AWSのRoute 53には、プライベートホストゾーンという、VPC内専用のDNSレコードを作成する機能があります。DNSサーバーの構築は素人にはなかなか敷居が高いですが、Route 53を利用して、お手軽にDNSレコードを編集してみましょう。

参考:プライベートホストゾーンの使用 - Amazon Route 53

AWSコンソールから[Route 53]を開き、[Create Hosted Zone]から設定します。VPC IDには、このプライベートホストゾーンを割り当てるVPCを設定します。

そうすると、NSレコードとSOAレコードがセットされたプライベートホストゾーンが自動的に作成されます。

試しに、VPC内のEC2からdigで確認してみると、先程作成したレコードが登録されているのがわかります。

$ dig ANY example.com

; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.62.rc1.56.amzn1 <<>> ANY example.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 2254
;; flags: qr rd ra; QUERY: 1, ANSWER: 5, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;example.com.			IN	ANY

;; ANSWER SECTION:
example.com.		60	IN	SOA	ns-1536.awsdns-00.co.uk. awsdns-hostmaster.amazon.com. 1 7200 900 1209600 86400
example.com.		60	IN	NS	ns-1536.awsdns-00.co.uk.
example.com.		60	IN	NS	ns-0.awsdns-00.com.
example.com.		60	IN	NS	ns-512.awsdns-00.net.
example.com.		60	IN	NS	ns-1024.awsdns-00.org.

;; Query time: 2 msec
;; SERVER: 10.0.0.2#53(10.0.0.2)
;; WHEN: Sat Feb  3 02:32:50 2018
;; MSG SIZE  rcvd: 225

Aレコードを設定し、独自ドメインでEC2に名前解決する

このゾーンに対して、EC2インスタンスプライベートIPアドレスへのAレコードを設定します。

結果を確認します。

$ dig app02.example.com

; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.62.rc1.56.amzn1 <<>> app02.example.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 62131
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;app02.example.com.		IN	A

;; ANSWER SECTION:
app02.example.com.	16	IN	A	10.0.0.145

;; Query time: 0 msec
;; SERVER: 10.0.0.2#53(10.0.0.2)
;; WHEN: Sat Feb  3 02:41:13 2018
;; MSG SIZE  rcvd: 51

無事、app02.example.comを利用して、プライベートIPアドレスへの名前解決ができるようになりました。

VPC内でEC2インスタンスやRDSに接続する時、IPアドレスやRDSのエンドポイントを直接指定せずに、プライベートホストゾーンで別名を指定してそれを利用する方法も有ります。そうすると、インスタンスやRDSの再作成時に、変更箇所をRoute 53の設定だけで済ますことができ、EC2内の設定を変更する必要がありません。

運用保守時には非常に便利な機能なので、適宜ご活用いただければと思います。

適当なTXTレコードを設定してみる

他のレコードも設定できます。TXTレコードの場合は、TypeにTXTを指定しましょう。

$ dig txt hamako9999.example.com

; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.62.rc1.56.amzn1 <<>> txt hamako9999.example.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 25113
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;hamako9999.example.com.		IN	TXT

;; ANSWER SECTION:
hamako9999.example.com.	60	IN	TXT	"dosukoi wassyoi"

;; Query time: 1 msec
;; SERVER: 10.0.0.2#53(10.0.0.2)
;; WHEN: Sat Feb  3 03:51:32 2018
;; MSG SIZE  rcvd: 68

無事、「dosukoi wassyoi」が返却されましたね。よござんす!!

digコマンドとRoute 53を使って、DNSについて理解を深めよう!

AWSのVPCにEC2を作成し、Amazon提供のDNSサーバーの挙動と、Route 53によるプライベートホストゾーンのレコード編集結果を、digコマンドでいろいろ試してみました。

digコマンドは機能が豊富で非常に便利なのですが、できることが多いがゆえに、その結果の見方が複雑であったり、動作がわかりにくい点もあるんじゃないでしょうか。正直自分も、最初は「ええ?これどないなってんねん?」となってしまいました。

今回の記事をきっかけに、digコマンドとDNSについて理解が深まれば幸いです。

それでは、今日はこのへんで。濱田(@hamako9999)でした。

おすすめ書籍

自分がDNSを勉強するにあたり、読んでいる本です。対話形式なので記述が冗長に感じるかもですが、丁寧に順を追って解説してくれるので、非常に分かりやすい。「DNS学ぶんだったら、最初はコレでええやろ」と自信をもってオススメします。

3分間DNS基礎講座
網野 衛二
技術評論社
販売価格 ¥2,462(2018年2月4日18時18分時点の価格)