Bind9でDynamicDNSを構築

最終更新日:2019年11月02日
レベル:★★★★☆
IPアドレスが固定ではないサーバを運用する際などに有効な「ダイナミックDNS」の仕組みを構築する方法を紹介します。

非固定IPアドレスで運用されているサーバなどの場合、サーバに割当てられているFQDNとIPアドレスを対応付けるのに苦労します。
解決法の1つとして「ダイナミックDNS」を利用し、IPアドレスが変わったタイミングでDNSサーバへその旨を登録する仕組みを構築します。

なお、本内容はLinux OSとして「CentOS 7」を、DNSサーバとして「BIND 9」を使うことを前提とします。
CentOS 7のセットアップは「CentOS 7のインストール」を参照してください。

事前準備

サブドメインの作成

 以降の例では、ドメイン「testsite.com」のサブドメイン「sub.testsite.com」に対しダイナミックDNSが機能するように構成します。

そのためにはまず、ドメイン「testsite.com」のDNSの設定を変更し、サブドメイン「sub.testsite.com」を作成する必要があります。
ドメイン「testsite.com」のDNSのゾーン情報に次のようにNSレコードを追加します。
ここでは

  • サブドメイン名を「sub.testsite.com
  • サブドメインの情報を管理するネームサーバを「ns.testsite.com

とします。

  :
ns  sub ns.testsite.com. <------------ このデータを追加する
:
  • 上の例は「バリュードメイン」で管理されているドメインでの設定例です。
    サブドメインのネームサーバの情報の登録方法・書式は、それぞれの管理元DNSの書式に従ってください。

以降、サブドメイン「sub.testsite.com」を管理するネームサーバ「ns.testsite.com」を作成する手順となります。

BIND9によるDNSサーバの構築

BIND9のインストール

bind9の導入はyumにて下記のように行います。
今回はセキュリティを考慮して「bind-chroot」を利用します。

# yum install bind9 bind-chroot

 

BIND9の基本設定

/etc/named.conf の設定

bind9の設定ファイル「/etc/named.conf」を編集します。

# vi /etc/named.conf

次のように編集します。

下記の例ではドメイン「testsite.com」のサブドメイン「sub.testsite.com」をダイナミックDNSで更新できる設定とします。

  :
options {
        //listen-on port 53 { 127.0.0.1; }; <----------------------- ①
        listen-on port 53 { any; }; <------------------------------- ②
        listen-on-v6 port 53 { ::1; };
        directory       "/var/named";
        dump-file       "/var/named/data/cache_dump.db";
        statistics-file "/var/named/data/named_stats.txt";
        memstatistics-file "/var/named/data/named_mem_stats.txt";
        recursing-file  "/var/named/data/named.recursing";
        secroots-file   "/var/named/data/named.secroots";
        //allow-query     { localhost; }; <------------------------- ③
        allow-query     { any; }; <--------------------------------- ④
 :
zone "." IN {
        type hint;
        file "named.ca";
};
:
zone "sub.testsite.com" { <----------------------------------------- ⑤
        type master; <---------------------- ⑥
        file "sub.testsite.com.zone"; <---------------------- ⑦
        allow-query { any; }; <---------------------- ⑧
        allow-update { key sub-testsite.; }; <---------------------- ⑨
};
 :
  • ①:先頭に「//」をつけてコメントアウトします。
  • ②:①の行の「127.0.0.1」を「any」にします(53番ポートで全てに開放)。
  • ③:先頭に「//」をつけてコメントアウトします。
  • ④:③の行の「localhost」を「any」にします(全てに問い合わせを許可)。
  • ⑤:以降のドメイン「sub.testsite.com」の定義を追加します。
    • ⑥:typeは「master」
    • ⑦:ドメインの詳細定義はファイル「sub.testsite.com.zone」に記載する
    • ⑧:全てからの問い合わせを許可
    • ⑨:「sub-testsite.」の鍵を持つものからのドメイン情報更新を許可する
      →末尾の「.」を忘れないように

ゾーンファイルの作成

ゾーンファイル「sub.testsite.com.zone」を「/var/named」ディレクトリに作成します。

# vi /var/named/sub.testsite.com.zone

内容をつぎのようにします。
各値の詳細は専門書・サイトを参照してください。

$ORIGIN .
$TTL 60 ; 1 minute
sub.testsite.com IN SOA ns.testsite.com. hostmaster.testsite.com. ( <--- ①
2019010101 ; serial <------------ ②
60         ; refresh (1 minute) <------------ ③
60         ; retry (1 minute) <------------ ④
604800     ; expire (1 week) <------------ ⑤
3600       ; minimum (1 hour) <------------ ⑥
)
NS ns.testsite.com. <----------------------------- ⑦
$TTL 3600 ; 1 hour <----------------------------- ⑧
A 192.168.1.10 <----------------------------- ⑨
$ORIGIN sub.testsite.com. <----------------------------- ⑩
www A 192.168.1.20 <----------------------------- ⑪
  • ①:SOAレコード。ネームサーバ名と連絡先メールアドレスを記載します(どちらもメモ扱い)。
  • ②:ゾーンファイルのシリアル番号。かならず一意になるように
  • ③:ゾーン転送後に再度ゾーン情報を取得しようと試みるまでの時間
  • ④:③のrefreshでゾーン情報の取得失敗した場合に再度refreshを試みるまでの時間
  • ⑤:転送されたゾーンデータベースの有効期間
  • ⑥:各リソースレコードのTTLの最小値
  • ⑦:NSレコード。本ドメイン(sub.testsite.com)のネームサーバを指定します。
  • ⑧:後述の⑨以降のTTLを指定します。
  • ⑨:ホスト名なしで「sub.testsite.com」を指定されたときのIPアドレスを指定します。
  • ⑩:以降のAレコードのORIGINを指定します。ここでは「sub.testsite.com.」(末尾のピリオドを忘れずに)を指定します。
  • ⑪:Aレコード。「www.sub.testsite.com」のIPアドレスを指定します。

 

ファイル、ディレクトリのパーミッションを設定します。

# chown named:named /var/named/sub.testsite.com.zone
# chmod 600 /var/named/sub.testsite.com.zone
# chmod g+w /var/named

zoneファイルをチェックします

# cd /var/named
# named-checkzone sub.testsite.com sub.testsite.com.zone
zone sub.testsite.com/IN: loaded serial 〜
OK <------------------------------------------------------- これが出たらOK

rndc設定

BIND9操作コマンドである「rndc」を利用できるように設定します。
今回、ダイナミックDNSを設定するドメインのメンテナンスを手動で行う際にrndcコマンドを利用します。

鍵の作成を行います。
下記コマンドを実行すると結果を表示します。
これを/etc/named.confに記載するのですが、そのまま記載するのではありません。

# rndc-confgen -r /dev/urandom -b 256   <------------ 入力する
# Start of rndc.conf
key "rndc-key" {
algorithm hmac-sha256;
secret "+fVG〜";
};
 
options {
default-key "rndc-key";
default-server 127.0.0.1;
default-port 953;
};
# End of rndc.conf
 
# Use with the following in named.conf, adjusting the allow list as needed:
# key "rndc-key" { <-------------------------------------------------------- ①
#         algorithm hmac-sha256;
#         secret "+fVG〜";
# };
#
# controls {
#         inet 127.0.0.1 port 953
#                 allow { 127.0.0.1; } keys { "rndc-key"; };
# }; <---------------------------------------------------------------------- ①'
# End of named.conf

/etc/named.confに設定します。

# vi /etc/named.conf

上で表示された結果の①〜①'を/etc/named.confの先頭にこのように貼り付けます。

 :
// See the BIND Administrator's Reference Manual (ARM) for details about the
// configuration located in /usr/share/doc/bind-{version}/Bv9ARM.html
 
key "rndc-key" { <---------------------------------------------- ここから
        algorithm hmac-sha256;
        secret "+fVG〜";
};
 
controls {
        inet 127.0.0.1 port 953
        allow { 127.0.0.1; } keys { "rndc-key"; };
};<------------------------------------------------------------- ここまで
 
options {
        //listen-on port 53 { 127.0.0.1; };
        listen-on port 53 { any; };
 :

BIND9サービス起動

下記コマンドを実行してBIND9を起動します。

# systemctl start named-chroot

起動状態を確認します。

# systemctl status named-chroot
● named-chroot.service - Berkeley Internet Name Domain (DNS)
   Loaded: loaded (/usr/lib/systemd/system/named-chroot.service; disabled; vendor preset: disabled)
   Active: active (running) since 土 2018-06-30 13:41:25 JST; 29min ago
  Process: 11177 ExecStart=/usr/sbin/named -u named -c ${NAMEDCONF} -t /var/named/chroot $OPTIONS (code=exited, status=0/SUCCESS)
  Process: 11175 ExecStartPre=/bin/bash -c if [ ! "$DISABLE_ZONE_CHECKING" == "yes" ]; then /usr/sbin/named-checkconf -t /var/named/chroot -z "$NAMEDCONF"; else echo "Checking of zone files is disabled"; fi (code=exited, status=0/SUCCESS)
 Main PID: 11179 (named)
   CGroup: /system.slice/named-chroot.service
           └─11179 /usr/sbin/named -u named -c /etc/named.conf -t /var/named/...

問題ないようであれば、自動起動に設定します。

# systemctl enable named-chroot
Created symlink from /etc/systemd/system/multi-user.target.wants/named-chroot.service to /usr/lib/systemd/system/named-chroot.service.

firewalldの設定

/etc/firewalld/zones/public.xml」ファイルを編集し、DNSを外部に公開します。

# vi /etc/firewalld/zones/public.xml

以下のように編集します。

<?xml version="1.0" encoding="utf-8"?>
<zone>
  <short>Public</short>
  <description>For use in public areas. You do not trust the other computers on networks to not harm your computer. Only selected incoming connections are accepted.</description>
  <service name="ssh"/>
:
  <service name="dns"/> <------------- これを追加
</zone>

firewalldを再起動します。

# systemctl restart firewalld

 

動作確認

BIND9をインストールしたサーバからドメインを検索して動作を確認します。

# which nslookup
/usr/bin/nslookup  <-------- これがでてこなければ下記のようにインストールする
# yum install -y bind-utils

下記のようにnslookupコマンドを実行し、青字部分を入力します。

# nslookup
> server localhost
Default server: localhost
Address: ::1#53
Default server: localhost
Address: 127.0.0.1#53
> set type=any
> sub.testsite.com
Server:        localhost
Address:    ::1#53

sub.testsite.com <----------------------------- 以下が返ってくればOK
    origin = ns.testsite.com
    mail addr = hostmaster.testsite.com
    serial = 2019010101
    refresh = 60
    retry = 60
    expire = 604800
    minimum = 3600
sub.testsite.com    nameserver = ns.testsite.com.
Name:    sub.testsite.com
Address: 192.168.1.10
> exit

外部のマシンから同様にnslookupコマンドにて応答が返ってくることを確認します。

  • 外部からnslookupコマンドを実行する際には、上記「server」には「localhost」ではなくBIND9をインストールしたサーバのFQDNまたはIPアドレスを指定します。

DNSSECの設定

ダイナミックDNS機能で外部からIPアドレスなどのドメイン情報を更新する際に、DNSSECの仕組みを用いて鍵を持っているもののみドメイン情報の更新ができるように設定します。

鍵の作成

下記コマンドを実行し、DNSSEC用の鍵ペアを作成します。

  • dnssec-keygen コマンドの「HOST」の次にはnamed.conf の⑨で設定した値を指定すること。
# cd /root
# dnssec-keygen -r /dev/urandom -a HMAC-SHA256 -b 128 -n HOST sub-testsite
Ksub-testsite.+163+60945
# ls <----------------------------- 鍵ができたか確認
Ksub-testsite.+163+60945.key    Ksub-testsite.+163+60945.private

「K〜.key」「K〜.private」の2つのファイルが生成されます。
「K〜.private」ファイルの中身を確認し、以下で指定する部分を「/etc/named.conf」に設定します。

# cat Ksub-testsite.+163+60945.private
Private-key-format: v1.3
Algorithm: 163 (HMAC_SHA256)          <--- この値をnamed.confに設定
Key: Xxxxxxxxxxxxxxxxxxxxxx==    <--- この値をnamed.confに設定
Bits: AAA=
Created: 20180312065936
Publish: 20180312065936
Activate: 20180312065936

/etc/named.confの編集

「/etc/named.conf」を編集します。

# vi /etc/named.conf

次のように記載します。

  • rndcのキーと間違わないように(よくある間違いです)。
  :
key "rndc-key" {
        algorithm hmac-sha256;
        secret "+fVG〜";
};
 
controls {
        inet 127.0.0.1 port 953
        allow { 127.0.0.1; } keys { "rndc-key"; };
};
# End of rndc.conf

▼▼▼▼▼ ここの部分を記載します ▼▼▼▼▼
key "sub-testsite." {
        algorithm hmac-sha256;
        secret "Xxxxxxxxxxxxxxxxxxxxxx==";
};
▲▲▲▲▲ ここまで記載します ▲▲▲▲▲
options {
        //listen-on port 53 { 127.0.0.1; };
        listen-on port 53 { any; };
:

 手動で動作確認

設定したダイナミックDNSが正しく動作するかを確認してみます。
以下ではDNSサーバを構築したマシン以外から手動で「nsupdate」コマンドを実行し、正しくIPアドレスの更新ができることを確認してみます。

以降では、今回BIND9を使ってDNSサーバを構築したマシンを「DNSサーバ」、自分のグローバルIPアドレスを動的にDNSサーバに登録するマシンを「クライアント」と呼ぶことにします。

事前準備

dnssec鍵ペアの準備

「dnssec-keygen」で作成したdnssecの鍵ペアをクライアントに準備します
上の例では「Ksub-testsite.+163+60945.key」および「Ksub-testsite.+163+60945.private」として生成されています。
これをnsupdateコマンドを実行するクライアントの任意の場所に保存します。

nsupdateコマンドの準備

クライアントにて下記コマンドを実行し「nsupdate」コマンドがインストール済みかどうかを確認します。

# which nsupdate
/usr/bin/nsupdate <---------------- これが返ってくればOK

何も反応がなければインストールされていない可能性があるのでインストールします。
クライアントのOSがCentOS 7であれば「bind-utils」パッケージに、Ubuntu系であれば「dnsutils」パッケージに入っています。

IPアドレスの確認

クライアントのグローバルIPアドレスを確認します。
クライアントから自分のグローバルIPアドレスを表示してくれるWebサイトを参照するか、次のコマンドを実行して自分のグローバルIPアドレスを調べます。

$ curl http://v4.ipv6-test.com/api/myip.php
126.109.1.23 <--------------------------- 自分のグルーバルIPアドレスが表示される

 

手動でIPアドレス更新

nsupdateコマンドを使って手動でIPアドレスを更新してみます。
ここでは

  • dnssecのキーファイルの場所&ファイル名を「/home/user/Ksub-testsite.+163+60945.key」
  • DNSサーバのFQDNを「ns.testsite.com」
  • 動的に登録するドメインを「sub.testsite.com」
  • 動的に登録するIPアドレスを「126.109.1.23」(上で取得したもの)

とします。

$ nsupdate -k Ksub-testsite.+163+60945.key
> server ns.testsite.com
> update delete sub.testsite.com.
> update add sub.testsite.com. 3600 A 126.109.1.23
> send
> quit

nslookupで正常に登録されたかを確認します。

$ nslookup
> server ns.testsite.com
Default server: ns.testsite.com
Address: x.x.x.x#53
> set type=any
> sub.testsite.com
Server: ns.testsite.com
Address: x.x.x.x

sub.testsite.com
origin = testsite.com
mail addr = hostmaster.testsite.com
serial = 2019010101
:
Name: sub.testsite.com
Address: 126.109.1.23 <-------------------- 正しいIPアドレスが表示されること
> exit

実運用の話

IPアドレスが変わったらDNSを更新する仕組みの導入

手動でダイナミックDNSが動作することを確認できたら、この手順をスクリプト化する等を行い実運用に入ります。

例えば、

  • 1時間に1回等の頻度で自分のグローバルIPアドレスを確認(cron等を利用)
  • もしグローバルIPアドレスが変わったらnsupdateにて新しいIPアドレスにDNSを更新する

のような仕組みを作っておくと良いでしょう。

  • うまく仕組みを作れない場合、K'z StyleではダイナミックDNS導入支援も行っていますのでご相談ください。

ダイナミックDNSのゾーンファイルを手動で修正する

ダイナミックDNSに設定しているゾーンには、通常のゾーンファイルとは違い動的に登録された情報を持つジャーナルファイル(拡張子が「.jnl」のファイル)を持っています。
当該ゾーンファイルを手動で修正してしまうと、このジャーナルファイルとのデータの矛盾が生じてしまい思わぬトラブルを招く恐れがあります。

これを防ぐために次の手順で一旦ダイナミックDNSを無効にしてジャーナルファイルの内容をゾーンファイルに反映させた後に当該ゾーンファイルを修正します。
修正終了後には再びダイナミックDNSを有効に戻します。

# rndc freeze sub.testsite.com    <---------- ダイナミックDNSを停止
# vi /var/named/sub.testsite.com.zone <----- ゾーンファイルを修正
 
# rndc thaw sub.testsite.com <---------- ダイナミックDNSを再開
  • SELinuxを有効にしている場合、ジャーナルの反映ができない場合があります。
    この場合は一旦SELinuxを無効に(setenforce 0)してから「rndc freeze」を行い、ゾーンファイルを修正して「rndc thaw」をした後にSELinuxを有効に(setenforce 1)戻します。

よくある障害

rndcでエラーが出る時

# rndc freeze sub.testsite.com
rndc: connection to remote host closed
This may indicate that
* the remote server is using an older version of the command protocol,
* this host is not authorized to connect,
* the clocks are not synchronized,
* the key signing algorithm is incorrect, or
* the key is invalid.

rndcキーが違っている可能性があります。
「/etc/rndc.key」に記載されている値と「/etc/named.conf」に記載した値とが合っているかを確認してみてください。

rndc: 'thaw' failed: out of range

ダイナミックDNSを有効に戻す際に下記エラーを表示することがあります。

rndc: 'thaw' failed: out of range

ゾーンファイルの「serial」の値がおかしくなっている可能性があります。
「serial」を新たに振り直してみてください。

 

ー 以上 ー

 CMSを使ったホームページ制作
 VPS, AWS等クラウドシステム構築
等々のご依頼承っております