目次
- 経緯・確認したいこと
- 環境
- ネットワーク構成
- ディレクトリ(プロジェクト)
- Dockerfile
- Docker Compose
- BINDの設定
- 検証
- まとめ
- お片付け
経緯・確認したいこと
先日、参加しているオンラインコミュニティで 「どのような事象だったら代替DNSにクエリー(問い合わせ)されるのか?」 という質問をいただいた。
ケースとしては二つ考えられる。
- 優先DNSサーバが障害でDNS応答不可
- 優先DNSサーバ応答ありだけど名前解決不可
Dockerのコンテナを活用して動きを確認してみることにした。
環境
- OS: Windows 11 Pro 22H2 WSL2
- WSL2: Ubuntu 22.04.2 LTS
- Docker Engine:
- Client: 24.0.4
- Server: 24.0.4
ネットワーク構成
BINDでDNSサーバーを2台、Ubuntuのクライアントマシンを1台設置する。
Dockerfileでbind、Ubuntuのベースとなるコンテナイメージを作成し、Docker Composeでネットワークを明示的に指定する。
ディレクトリ(プロジェクト)
BINDとUbuntuごとにDockerfileを用意した。
project-bind
├── Dockerfile_bind
├── Dockerfile_ubuntu
└── docker-compose.yml
Dockerfile
FROM ubuntu/bind9:latest
RUN apt-get update -y
RUN apt-get install vim iputils-ping -y
BINDの設定ファイルを変更できるようにvim、ネットワーク疎通確認用にpingをインストールした。
FROM ubuntu:latest
RUN apt-get update -y
RUN apt-get install vim iputils-ping dnsutils -y
同様にvim、ping そして名前解決確認できるようにdigも追加インストールした。
Docker Compose
version: '3'
services:
# BIND build
bind-base:
build:
context: .
dockerfile: Dockerfile_bind
image: bind-base
profiles:
- extra
# Ubuntu build
ubuntu-base:
build:
context: .
dockerfile: Dockerfile_ubuntu
image: ubuntu-base
profiles:
- extra
# DNSServer1(bind)
bind01:
image: bind-base:latest
networks:
fixed_compose_network:
ipv4_address: 10.0.0.11
# DNSServer2(bind)
bind02:
image: bind-base:latest
networks:
fixed_compose_network:
ipv4_address: 10.0.0.12
# Client
Client01:
image: ubuntu-base:latest
tty: true
networks:
fixed_compose_network:
ipv4_address: 10.0.0.20
ベースイメージはビルドのみで使用したい。そのためdocker compose up -d
でコンテナ起動しないように profiles
を設定した。
build
ベースイメージをビルドするコマンド。
$ docker compose --profile extra build
イメージができていることを確認する。
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu-base latest f5752fc36de3 6 days ago 227MB
bind-base latest 0c7378c82095 7 days ago 237MB
コンテナ起動
コンテナを起動するコマンド。
$ docker compose up -d
[+] Running 4/4
✔ Network bind_fixed_compose_network Created 0.1s
✔ Container bind-bind01-1 Started 0.8s
✔ Container bind-Client01-1 Started 0.9s
✔ Container bind-bind02-1 Started
docker ps
で3つのコンテナが実行中であることを確認する。
BINDの設定
2つのBINDにゾーンファイルを作成していく。
bind01
まずは以下コマンドでBINDコンテナにアクセスする。
docker exec -it "bind01のコンテナID" /bin/bash
vimで named.conf.default-zones
を編集する。
このファイルに解決するドメインとゾーンファイルを登録する。
vim /etc/bind/named.conf.default-zones
zone "." {
type hint;
file "/usr/share/dns/root.hints";
};
// be authoritative for the localhost forward and reverse zones, and for
// broadcast zones as per RFC 1912
zone "localhost" {
type master;
file "/etc/bind/db.local";
};
zone "127.in-addr.arpa" {
type master;
file "/etc/bind/db.127";
};
zone "0.in-addr.arpa" {
type master;
file "/etc/bind/db.0";
};
zone "255.in-addr.arpa" {
type master;
file "/etc/bind/db.255";
};
// add test.pizza zone file
zone "test.pizza" {
type master;
file "/etc/bind/db.test.pizza";
};
登録したゾーンファイル db.test.pizza
を作成する。
デフォルトで存在する db.local
をコピーして作成する。
cp /etc/bind/db.local /etc/bind/db.test.pizza
コピー後はvimで編集する。
;
; BIND data file for local loopback interface
;
$TTL 604800
@ IN SOA ns1.test.pizza. postmaster.test.pizza. (
2 ; Serial
604800 ; Refresh
86400 ; Retry
2419200 ; Expire
604800 ) ; Negative Cache TTL
;
@ IN NS ns1.test.pizza.
ns1 IN A 10.0.0.11
www IN A 10.0.0.100
BINDの設定を反映させるには named デーモンを再起動させる必要がある。
Dockerだとshell上でnamedデーモンを再起動させるとコンテナが停止しまうため
ここではshellからexitでいったん抜けて、コンテナ自体を再起動(restart)させる。
docker restart "bind01のコンテナID"
実際にDNSサーバーにクエリーを投げて名前解決できるか確認する。
クライアントのコンテナのBashにアクセスする。
docker exec -it "Clinet01のコンテナID" /bin/bash
Ubuntuの問い合わせ先DNSサーバーを指定する時は "/etc/resolv.conf"を編集する。
vim /etc/resolv.conf
nameserver
に bind01のIPアドレスを指定する
nameserver 10.0.0.11
設定できたら、nslookup
で www.test.pizza を問い合わせをしてみる。
nslookup www.test.pizza
ゾーンファイルに登録したAレコードの結果(10.0.0.100)が表示されればクエリーの肯定応答となる。
nslookup www.test.pizza
Server: 10.0.0.11
Address: 10.0.0.11#53
Name: www.test.pizza
Address: 10.0.0.100
bind02
bind01同様に設定していく。
今回代替DNSの動きを確認するため、Aレコードは以下のようにbind01と異なるものを登録する。
;
; BIND data file for local loopback interface
;
$TTL 604800
@ IN SOA ns1.test.pizza. postmaster.test.pizza. (
2 ; Serial
604800 ; Refresh
86400 ; Retry
2419200 ; Expire
604800 ) ; Negative Cache TTL
;
@ IN NS ns2.test.pizza.
ns2 IN A 10.0.0.12
www IN A 10.0.0.100
www2 IN A 10.0.0.101
クライアントにセカンダリ(代替)DNSの指定先として bind02(IP:10.0.0.12)を指定する。
nameserver 10.0.0.11
nameserver 10.0.0.12
検証1: 優先DNSサーバが障害でDNS応答不可
優先DNSサーバー(bind01)の障害を見立てて、bind01コンテナを停止し、クライアントでwww.test.pizzaに問い合わせをしてみる。
bind01コンテナを停止するコマンド
docker stop "bind01のコンテナID"
クライアントで問い合わせた結果
root@client01:/# nslookup www.test.pizza
;; communications error to 10.0.0.11#53: timed out
;; communications error to 10.0.0.11#53: timed out
;; communications error to 10.0.0.11#53: timed out
Server: 10.0.0.12
Address: 10.0.0.12#53
Name: www.test.pizza
Address: 10.0.0.100
優先DNSサーバーと通信できないためタイムアウトが表示されるが、そのあと代替えDNSに問い合わせし、肯定応答が返ってきた。
よって、優先DNSサーバーと通信(TCP/UDP53)できないときは代替DNSサーバーに問い合わせする動きを確認できた。
検証2: 優先DNSサーバ応答ありだけど名前解決不可
今度は 代替DNSサーバーだけに登録している www2.test.pizza を問い合わせして検証してみる。
停止していた優先DNSサーバー(bind01)を起動させる。
docker start "bind01のコンテナID"
クライアントで問い合わせた結果
root@client01:/# nslookup www2.test.pizza
Server: 10.0.0.11
Address: 10.0.0.11#53
** server can't find www2.test.pizza: NXDOMAIN
優先DNSサーバーにはwww2.test.pizzaのレコードがないため否定応答が返ってきて、代替DNSサーバーに再度問い合わせすることはなかった。
まとめ
- 優先DNSサーバーが応答できない(通信できない)ときに代替DNSサーバーへ問い合わせする。
- 優先DNSサーバーが否定応答だからといって、次のDNSサーバに問い合わせたりはしない。
お片付け
Dockerでの動きを確認できたら、検証でつかったコンテナ、イメージは以下コマンドで削除できます。
docker compose down --rmi all