小さなオフィスでも複数のサーバーがあるなら、「ipアドレス」ではなく「ホスト名」でアクセスしたいと思うでしょう。
以前このサイトでDockerコンテナを使ってDNSキャッシュサーバーを作りました。
これをグレードアップして、ネットワーク内のコンピュータを動的に登録します。
更新頻度が少ない場合は、DDNSにせず、ゾーンファイルを都度編集したほうが早いかもしれません。
しかしDDNSであれば、手元のPCからアップデートが可能ですし、間違うリスクが減ります。
注意が必要なのは、このDNSサーバーは、プライベートネットワークで便利に使うためのもので、決してインターネットに公開してはいけないものです。
グローバルネットワークに公開するDNSは、セキュリティーから考えなければいけないからです。
ゾーン名を決める
まず、事務所内や家庭内のネットワークの「ゾーン名(ドメイン名)」を決めます。
インターネットの公式のドメインをもっているなら、それを使ってもいいし、ローカル専用に新規作成してもいいでしょう。
「localnet」でもいいのですが、この単語はいろんなところに使われていて紛らわしいので止めておきます。
ここでは例としてゾーン名を「yellow.in.net」としました。
従って、これから設定するDNSサーバー「dns0」の正式なホスト名は「 dns0.yellow.in.net 」です。
ゾーンファイルを作る
「/etc/bind/」に「db.empty」という空のゾーンファイルがあるので、これをコピーして使います。
cp /etc/bind/db.empty /etc/bind/db.yellow.in.net
コピーした「db.yellow.in.net」を次のように編集します。
「;」より右側はコメントとして扱われます。
; BIND reverse data file for empty rfc1918 zone
;
; DO NOT EDIT THIS FILE - it is used for multiple zones.
; Instead, copy it, edit named.conf, and use that copy.
;
$TTL 86400
@ IN SOA dns0.yellow.in.net. fumi.yellow.in.net. (
1 ; Serial
604800 ; Refresh
86400 ; Retry
2419200 ; Expire
86400 ) ; Negative Cache TTL
;
@ IN NS dns0.yellow.in.net.
dns0 IN A 192.168.11.2
最初の「 $TTL 86400 」は、キャッシュサーバーがこのゾーンの検索結果を保持する期間です。
1度問い合わせたに答えたらキャッシュサーバーのほうでその情報を覚えておいて、86400秒、すなわち1日の間は再び問合せしないように要請します。
「db.empty」の「SOA」の行を、自分の環境に合わせて書き換えます。
「db.empty」の 「SOA」レコード:
@ IN SOA localhost. root.localhost. (
変更後の「SOA」レコード:
@ IN SOA dns0.yellow.in.net. fumi.yellow.in.net. (
この意味は次のようになります。
要素 | 意味 |
@ | ゾーン名、つまり「yellow.in.net」に置き換えられます。 |
IN | インターネットのことです。「IN」以外を使うことはありません。 |
SOA | 「Start Of Authority」の略で、権威を持つゾーンの始まりを意味します。 |
dns0.yellow.in.net. | このゾーンの情報を管理している権威サーバー名。 |
fumi.yellow.in.net. | 管理者のメールアドレス。 |
dns0.yellow.in.netではなく「 dns0.yellow.in.net. 」で最後の「.」を忘れないでください。
メールアドレスは「 fumi@yellow.in.net」と書かずに、最後の「.」もつけて「 fumi.yellow.in.net. 」と書きます。
続く「丸カッコ」に囲まれた5個の数字は次のような意味を持っています。
要素 | コメント | 期間 | 意味 | 誰に対するものか |
1 | Serial | ー | 数字が大きいほど新しい | セカンダリーサーバー |
604800 | Refresh | 7日 | セカンダリー サーバーが更新を確認する間隔 | セカンダリーサーバー |
86400 | Retry | 1日 | リフレッシュできなかった場合に、 再度更新を確認するまでの間隔 | セカンダリーサーバー |
2419200 | Expire | 28日 | 更新ができなかったときに現在の情報を 保持する期間 | セカンダリーサーバー |
86400 | Negative Cache TTL | 1日 | 問い合わせ先が存在しなかった場合、 「存在しない」ことを保持しておく期間 | キャッシュサーバー |
次に権威サーバーについての情報を2行記述します。
@ IN NS dns0.yellow.in.net.
dns0 IN A 192.168.11.2
この意味は以下の通りです。
意味 | ||
NS | NSレコード | ネームサーバー |
A | Aレコード | アドレス |
「@」はゾーン名(ドメイン名)に変換されます。
@ IN NS dns0.yellow.in.net.
ゾーン「yellow.in.net」のネームサーバーは「dns0.yellow.in.net」です。
dns0 IN A 192.168.11.2
「dns0.yellow.in.net」 のアドレスは「192.168.11.2」です。
サーバー名はゾーン名(ドメイン名)を省略して記述することができ「dns0」と書くことができます。
ゾーン名を省略しないで書くときは次のようになります。
dns0.yellow.in.net. IN A 192.168.11.2
ホスト名の最後の「.」を忘れて、次のようにしないでください。
dns0.yellow.in.net IN A 192.168.11.2
これは「dns0.yellow.in.net.yellow.in.net」 のアドレスは「192.168.11.2」の意味になります。
ゾーンファイルは以上です。
「SOA」の情報だけを設定しておけば、後は動的に登録できます。
allow-updateでDDNSに変身させる
ゾーンファイルができたので、ゾーンを有効にします。
BINDの設定ファイルは、「/etc/bind/named.conf」です。
Debianでは、 named.confから以下のファイルをインクルード(読み込む)するようになっています。
- /etc/bind/named.conf.options
- /etc/bind/named.conf.local
- /etc/bind/named.conf.default-zones
ゾーンの設定は「named.conf.local」に記述します。
root@dns0:/# vi /etc/bind/named.conf.local
//
// Do any local configuration here
//
// Consider adding the 1918 zones here, if they are not used in your
// organization
//include "/etc/bind/zones.rfc1918";
zone "yellow.in.net" {
check-names ignore;
type master;
file "/var/lib/bind/db.yellow.in.net";
allow-update {
192.168.11.0/24;
};
allow-transfer {
none;
};
};
「//」から始まる行はコメントです。
「zone」から始まって、ゾーン名に続く「{」と「}」で囲まれた部分がこのゾーン名についての設定です。
check-names ignore; | 既定ではホスト名にアンダーバー「_」を使えませんが、 プライベートネットワークなのでアンダーバーもOKにしています。 |
type master; | マスターサーバーであることを宣言します。 type slave;ならマスターのコピーサーバーになります。 |
file “/var/lib/bind/db.yellow.in.net”; | ゾーンファイルを指定します。 「/etc/bind/db.yellow.in.net」のリンクを指定しています。 ※下記で解説。 |
allow-update { 192.168.11.0/24; }; | アップデートを受け付けるネットワークの範囲やipアドレスを 設定します。 |
allow-transfer { none; }; | マスターだけなので、セカンダリー サーバーにゾーン転送はしません。 |
ゾーンファイルのリンクを「/var/lib/bind/」に作ります。
ln -s /etc/bind/db.yellow.in.net /var/lib/bind/db.yellow.in.net
ゾーンファイルのリンクを「/var/lib/bind/」に作る理由は次の通りです。
- BINDはユーザー「bind」で起動される。
- BINDはアップデート情報をゾーンファイルと同じ場所に保存する。
- BINDは「/etc/bind」ディレクトリーへの書き込み権限を持っていない。
- BINDが書き込み権限を持っているのは「/var/lib/bind」ディレクトリー。
なので「named.conf.local」に「ゾーンファイル本体ではなくリンクの場所」を設定します。
アップデート情報はジャーナル「/var/lib/bind/db.yellow.in.net.jnl」に保存されます。
「ジャーナル」とは「変更履歴」です。
ジャーナルはマスターからスレーブ(セカンダリー)にゾーンを転送する際に整合性をとる機能もあります。
設定は完了です。
BINDを再起動します。
root@dns0:/# /etc/init.d/bind9 restart
あるいは、コンテナを再起動します。
fumi@y3:~$ docker restart dns0
Linuxからアップデートする
BINDのアップデートは「nsupdate」コマンドで行います。
以下の設定をしたので、このネットワークからはどこからでもアップデートを受け付けます。
allow-update {
192.168.11.0/24;
};
nsupdateを使う
Debianでは「dnsutils」パッケージにコマンドが入っているので、インストールします。
root@dns0:/# apt -y install dnsutils
アップデートコマンド
コマンドの一連の流れです。
root@dns0:/# nsupdate -d
> server 127.0.0.1
> zone yellow.in.net
> update add pbx1 86400 IN A 192.168.11.12
> send
Sending update to 127.0.0.1#53
Outgoing update query:
;; ->>HEADER<<- opcode: UPDATE, status: NOERROR, id: 30272
;; flags:; ZONE: 1, PREREQ: 0, UPDATE: 1, ADDITIONAL: 0
;; ZONE SECTION:
;yellow.in.net. IN SOA
;; UPDATE SECTION:
pbx1. 86400 IN A 192.168.11.12
Reply from update query:
;; ->>HEADER<<- opcode: UPDATE, status: REFUSED, id: 30272
;; flags: qr; ZONE: 1, PREREQ: 0, UPDATE: 0, ADDITIONAL: 0
;; ZONE SECTION:
;yellow.in.net. IN SOA
> quit
root@dns0:/#
「-d」オプションを付けるとデバッグ情報を表示してくれます。
普通は「-d」オプションを付けておきます。
root@dns0:/# nsupdate -d
レコードを追加する
アップデートを送るサーバーを指定します。
> server 127.0.0.1
注意すべき点は、サーバーを指定しない場合、既定で「resolv.conf」に設定されているdnsサーバーをアップデートしようとします。
ところが、DockerではホストにDNSが立っており、コンテナ同士がお互いを解決できるようになっています。
Dockerコンテナは作成時に指定しなければ、DockerホストのDNSを参照します。
コンテナの「/etc/resolv.conf」は以下のようになっています。
nameserver 127.0.0.11
options ndots:0
「127.0.0.11」はDockerホストのDNSです。
従って、Dockerコンテナからnsupdateを使う場合は、「サーバーの指定は必須」です。
続いて「zone」を指定します。
> zone yellow.in.net
pbx1.yellow.in.netの「Aレコード」「192.168.11.12」を登録します。
> update add pbx1 86400 IN A 192.168.11.12
「zoneを指定していない場合」はzone情報も併せてアップデートすればOKです。
> update add pbx1.yellow.in.net 86400 IN A 192.168.11.12
最後にアップデートクエリをサーバーに送信します。
> send
送信結果が表示されます。
複数のアップデートがある場合には、「send」の前に、それらを入力することができます。
「send」の代わりに「空行にエンターキー」を押しても、アップデートが実行されます。
> ⏎
終了は「quit」です。
レコードの登録は「update add」で行います。
「update add」「ホスト名」「キャッシュ時間」「IN」「レコード」「ipアドレス」
1個以上のスペースかタブで区切って、この順番で並べます。
レコードを削除する
root@dns0:/# nsupdate -d
> server 127.0.0.1
> update delete pbx1.yellow.in.net
> ⏎
Reply from SOA query:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 28428
;; flags: qr aa rd ra; QUESTION: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 0
;; QUESTION SECTION:
;pbx1.yellow.in.net. IN SOA
;; AUTHORITY SECTION:
yellow.in.net. 86400 IN SOA dns0.yellow.in.net. fumi.yellow.in.net. 11 604800 86400 2419200 86400
Found zone name: yellow.in.net
The master is: dns0.yellow.in.net
Sending update to 192.168.11.2#53
Outgoing update query:
;; ->>HEADER<<- opcode: UPDATE, status: NOERROR, id: 56730
;; flags:; ZONE: 1, PREREQ: 0, UPDATE: 1, ADDITIONAL: 0
;; UPDATE SECTION:
pbx1.yellow.in.net. 0 ANY ANY
Reply from update query:
;; ->>HEADER<<- opcode: UPDATE, status: NOERROR, id: 56730
;; flags: qr; ZONE: 1, PREREQ: 0, UPDATE: 0, ADDITIONAL: 0
;; ZONE SECTION:
;yellow.in.net. IN SOA
> quit
登録の削除は「update delete」です。
そのホストについてのすべてのレコードを削除する場合は、ホスト名だけでOKです。
「update delete」 「ホスト名」
レコードを更新する
root@dns0:/# nsupdate -d
> server 127.0.0.1
> update delete pbx1.yellow.in.net
> update add pbx1.yellow.in.net 86400 IN A 192.168.11.13
> ⏎
Reply from SOA query:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 8624
;; flags: qr aa rd ra; QUESTION: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 0
;; QUESTION SECTION:
;pbx1.yellow.in.net. IN SOA
;; AUTHORITY SECTION:
yellow.in.net. 86400 IN SOA dns0.yellow.in.net. fumi.yellow.in.net. 13 604800 86400 2419200 86400
Found zone name: yellow.in.net
The master is: dns0.yellow.in.net
Sending update to 192.168.11.2#53
Outgoing update query:
;; ->>HEADER<<- opcode: UPDATE, status: NOERROR, id: 54513
;; flags:; ZONE: 1, PREREQ: 0, UPDATE: 2, ADDITIONAL: 0
;; UPDATE SECTION:
pbx1.yellow.in.net. 0 ANY ANY
pbx1.yellow.in.net. 86400 IN A 192.168.11.13
Reply from update query:
;; ->>HEADER<<- opcode: UPDATE, status: NOERROR, id: 54513
;; flags: qr; ZONE: 1, PREREQ: 0, UPDATE: 0, ADDITIONAL: 0
;; ZONE SECTION:
;yellow.in.net. IN SOA
> quit
root@dns0:/#
「update delete」して「update add」のあとに「⏎」です。
複数のアップデートを一度に行うと、「アップデート クエリ」が一度で済むので経済的です。
Windowsからアップデートする
Windows10に「Debianアプリ」をインストールして、「nsupdate」を使うこともできます。
ここでは、Windows用のBINDに含まれているnsupdate.exeを使う方法を解説します。
nsupdate.exeをインストールする
Microsoft Visual C++ をインストール
まず、nsupdate.exeを実行するために必要な「Microsoft Visual C++」をインストールします。
最新のサポートされる Visual C++ のダウンロードからダウンロードできます。
パソコンの環境に合わせてアーキテクチャを選んでダウンロードします。
「ライセンス条項および使用条件に同意する(A)」にチェックを入れて、インストールを開始します。
BINDを展開する
ISCのサイトからBINDをダウンロードします。
BINDをインストールするのではなく、パッケージに含まれている「nsupdate.exe」を使うことが目的なので、開発版でも安定板でもOKです。
ダウンロードしたファイルを「右クリック」して「すべて展開(T)…」をクリックします。
展開したフォルダの中に「nsupdate.exe」があります。
アップデートコマンド
nsupdate.exeはコマンドプロンプトで実行します。
パスが通っていないので、nsupdate.exeがあるフォルダに移動します。
C:\Users\yellow>cd Downloads\BIND9.16.20.x64
nsupdate.exeを「-d」オプションを付けて実行します。
C:\Users\yellow\Downloads\BIND9.16.20.x64>nsupdate.exe -d
ここでWindows Defenderのファイアウォールについての警告が出ることがあります。
プライベートネットワークでのアクセスを許可してください。
pbx1.yellow.in.net のAレコードを登録してみます。
C:\Users\yellow\Downloads\BIND9.16.20.x64>nsupdate.exe -d
> server 192.168.11.2
> zone yellow.in.net
> update add pbx1.yellow.in.net 86400 IN A 192.168.11.12
> ⏎
Sending update to 192.168.11.2#53
Outgoing update query:
;; ->>HEADER<<- opcode: UPDATE, status: NOERROR, id: 23152
;; flags:; ZONE: 1, PREREQ: 0, UPDATE: 1, ADDITIONAL: 0
;; ZONE SECTION:
;yellow.in.net. IN SOA
;; UPDATE SECTION:
pbx1.yellow.in.net. 86400 IN A 192.168.11.12
Reply from update query:
;; ->>HEADER<<- opcode: UPDATE, status: NOERROR, id: 23152
;; flags: qr; ZONE: 1, PREREQ: 0, UPDATE: 0, ADDITIONAL: 0
;; ZONE SECTION:
;yellow.in.net. IN SOA
> quit
C:\Users\yellow\Downloads\BIND9.16.20.x64>
DNSを便利に使う
プライベートネットワーク用のDynamicDNSを設定しました。
検索にこのDNSを設定すれば、ネットワーク内のホストにipアドレスではなくホスト名でアクセスできるようになります。
ところが、ホストの検索にはゾーン名(ドメイン名)も併せて指定しなければ検索結果に至りません。
同じネットワーク内にあるのに「pbx1.yellow.in.net」と入力するのは面倒です。
「pbx1」だけ入力すればOKにしたい。
解決方法は、ネットワーク内のコンピューターをゾーンに入れてしまえばいいのです。
DHCPでドメインを設定する
DHCPでドメイン名を配布するれば、Windows、Linux、その他のOSでもコンピューターが自動的にドメインを設定します。
WifiルーターもDHCPでドメイン名を配布することができます。
無線ルーター「WCR-1166DS」の場合、「LAN」→「LAN」の「DHCPサーバー設定 [拡張設定]」で拡張設定を表示して、「ドメイン名の通知」を設定します。
ヤマハのルーターなら次のように「dhcp scope option」を設定します。
dhcp scope option 1 dns=192.168.11.2 domain=yellow.in.net
固定 ipアドレスのコンピューターにドメインを設定する
固定でipアドレスを設定している場合はDHCPを使わないので、個別に設定する必要があります。
Windowsにドメインを設定する
Windowsでは、「ネットワーク アダプターのプロパティ」を表示し「インターネット プロトコル バージョン4(TCP/IPv4)のプロパティ」 で「詳細設定(V)…」ボタンをクリックして「TCP/IP 詳細設定」を表示します。
「DNS」タブを開き、「この接続のDNSサフィックス(S):」にドメイン名を設定します。
DNSサーバーがBINDなので「この接続のアドレスをDNSに登録する(R)」は機能しませんのでチェックを外しておきます。
Linuxにドメインを設定する
UNIX系のOSはresolv.confにドメインを設定します。
domain yellow.in.net
nameserver 192.168.11.2
これで、「pbx1」を入力すれば、dnsは「pbx1.yellow.in.net」のipアドレスを回答してくれます。
まとめ
Dockerでサーバーを複数作る場合は、ホストの検索が大変です。
ホスト名をDNSで解決する方法は、汎用性が高く、リソースの節約になります。
ゾーン名(ドメイン名)をDHCPサーバーに設定しておけば、ユーザーはドメイン名を省略してホストを検索できます。
DNSサーバーがネットワーク内にあると便利です。