Ubuntu/DebianでBind9を使ったDNSサーバー構築ガイド

Network tutorial - IT technology blog
Network tutorial - IT technology blog

ISPのデフォルトDNS — 使えるが制御できない

私は50人規模のオフィスと小規模なデータセンターのネットワークを管理しています。最初の数年は8.8.8.8と1.1.1.1に任せきりでした。RouterがDHCPでIPを割り当て、クライアントはISPのDNSを使う——「みんなそうしてるんだから問題ない」という感じで。しかし徐々に問題が積み重なってきました:

  • 内部ホスト名が名前解決できない — サーバーにSSHするたびに、server1.office.localの代わりにIPアドレスを入力する必要がある
  • すべてのDNSクエリがインターネットに出て行き、平均30〜40msかかる。ローカルキャッシュなら1ms以下なのに
  • split-DNSができない — 内部と外部で同じIPを返すしかない
  • ログがない。ネットワークに問題が発生したとき、どこから調査すればいいか分からない

そこでBind9を導入することにしました。世界中のプロダクションサーバーで20年以上稼働してきた実績があり、現在も活発にメンテナンスされている最も歴史あるDNSソフトウェアです——プロダクション環境で信頼して使うには十分な理由があります。

インストール前に:押さえておくべき基本概念

Bind9にはさまざまな役割があります:authoritative server(ドメインの権威サーバー)、recursive resolver(クライアントに代わって問い合わせる)、またはその両方。この記事ではauthoritative + forwarderモードのみ使用します——オフィスネットワークには十分で、それ以上複雑にする必要はありません。

押さえておくべき基本用語

  • Zone:DNS管理の単位。例:office.localexample.com
  • A record:ホスト名をIPv4アドレスに対応付ける。例:server1.office.local → 192.168.1.10
  • PTR record:逆引きDNS——IPアドレスをホスト名に対応付ける。A recordの逆方向
  • NS record:ゾーンのネームサーバーを宣言する
  • SOA record:ゾーンのメタデータ——serial、refresh、retry、expire
  • Forwarder:Bind9が回答できない場合、クエリを別のDNS(例:8.8.8.8)に転送する

今回は192.168.1.0/24のネットワーク向けに、office.localドメインの内部DNSを構築します。全体の流れを最初から最後まで実演するのに十分な環境です。

Bind9のインストールと設定

ステップ1:Bind9のインストール

Ubuntu/Debianの場合:

sudo apt update
sudo apt install -y bind9 bind9utils bind9-doc dnsutils

インストール後、namedサービスが自動起動します。素早く確認:

sudo systemctl status named

ステップ2:named.conf.optionsの設定

ファイル/etc/bind/named.conf.options——フォワーダーとアクセスコントロールを定義する場所:

sudo nano /etc/bind/named.conf.options
acl "trusted" {
    192.168.1.0/24;   // 内部ネットワーク
    localhost;
    localnets;
};

options {
    directory "/var/cache/bind";

    // 信頼できるネットワークからのクエリのみ許可
    allow-query { trusted; };
    allow-recursion { trusted; };

    // フォワーダー — 不明な場合はCloudflareへ転送
    forwarders {
        1.1.1.1;
        8.8.8.8;
    };
    forward only;

    dnssec-validation auto;
    listen-on { any; };
    listen-on-v6 { any; };
};

forward onlyの行が重要です:Bind9は自分で外部に再帰問い合わせせず、すべてフォワーダーに委ねます。オフィスネットワークではこの方法が高速でシンプルです。Bind9に8.8.8.8に依存せず完全に自己解決させたい場合は、この行を削除してください。

ステップ3:named.conf.localでのゾーン宣言

sudo nano /etc/bind/named.conf.local
// フォワードゾーン
zone "office.local" {
    type master;
    file "/etc/bind/zones/db.office.local";
};

// 192.168.1.0/24の逆引きゾーン
zone "1.168.192.in-addr.arpa" {
    type master;
    file "/etc/bind/zones/db.192.168.1";
};

ステップ4:フォワードゾーンファイルの作成

sudo mkdir /etc/bind/zones
sudo nano /etc/bind/zones/db.office.local
;
; office.localのフォワードゾーンファイル
;
$TTL    604800
@       IN      SOA     ns1.office.local. admin.office.local. (
                        2026022801  ; シリアル番号 (形式: YYYYMMDDNN)
                        604800      ; リフレッシュ間隔 (7日)
                        86400       ; リトライ間隔 (1日)
                        2419200     ; 有効期限 (28日)
                        604800      ; ネガティブキャッシュTTL
                        )

; ネームサーバー
@       IN      NS      ns1.office.local.

; Aレコード
ns1     IN      A       192.168.1.1
gateway IN      A       192.168.1.1
server1 IN      A       192.168.1.10
server2 IN      A       192.168.1.11
nas     IN      A       192.168.1.20
printer IN      A       192.168.1.30

シリアル番号はYYYYMMDDNN形式:今日の日付+その日の連番です。今日は2026年2月28日で、最初の修正なら2026022801となります。ゾーンを修正するたびに必ずシリアルを増やしてください——これを忘れると、スレーブDNSがエラーを出さずに静かにアップデートを無視します。この件で午前中まるごとデバッグに費やしたことがあります。

ステップ5:逆引きゾーンファイルの作成

sudo nano /etc/bind/zones/db.192.168.1
;
; 192.168.1.0/24の逆引きゾーンファイル
;
$TTL    604800
@       IN      SOA     ns1.office.local. admin.office.local. (
                        2026022801
                        604800
                        86400
                        2419200
                        604800
                        )

@       IN      NS      ns1.office.local.

; PTRレコード(ホスト部分のみ記載、フルIPは不要)
1       IN      PTR     ns1.office.local.
10      IN      PTR     server1.office.local.
11      IN      PTR     server2.office.local.
20      IN      PTR     nas.office.local.
30      IN      PTR     printer.office.local.

ステップ6:再起動前の設定検証

このステップは絶対に省略しないでください。以前、確認せずにnamedを再起動したことがあり、ゾーンファイルのタイポでオフィス全体のDNSが約10分間停止しました:

# named.confを検証する
sudo named-checkconf

# 各ゾーンファイルを検証する
sudo named-checkzone office.local /etc/bind/zones/db.office.local
sudo named-checkzone 1.168.192.in-addr.arpa /etc/bind/zones/db.192.168.1

OKと表示されたら再起動:

sudo systemctl restart named
sudo systemctl enable named

ステップ7:クライアントからのテスト

192.168.1.0/24のネットワーク内のマシンから、DNSを192.168.1.1に向けてテストします:

# 正引き
dig @192.168.1.1 server1.office.local
nslookup server1.office.local 192.168.1.1

# 逆引き
dig @192.168.1.1 -x 192.168.1.10

# フォワーダーのテスト — 外部ドメインへのクエリ
dig @192.168.1.1 google.com

正引きが成功すると次のように返ってきます:

;; ANSWER SECTION:
server1.office.local.   604800  IN  A   192.168.1.10

内部ホスト名のクエリタイムは、一度キャッシュされると通常1ms未満です。8.8.8.8に直接クエリした場合の30〜40msと比べると大きな差があります。

よくあるトラブルシューティング

  • SERVFAIL:ゾーンファイルの構文エラー — named-checkzoneを再実行する
  • REFUSED:クライアントのIPがACL trustedに含まれていない — allow-queryを確認する
  • Timeout:ファイアウォールがポート53のUDP/TCPをブロックしている — ufw allow 53
  • スレーブが新しいゾーンを受け取らない:シリアルが増えていない — 最も多いミスで、エラーも表示されない
# デバッグ時のリアルタイムログ確認
sudo tail -f /var/log/syslog | grep named

まとめ

Bind9のセットアップ全体で約30分かかります。実際の成果:内部ホスト名が解決できるようになり、クエリタイムが30〜40msから1ms未満に短縮され、ネットワーク障害時に使えるまともなログを初めて手に入れました。

次のステップはsplit-DNSです——server1.example.comが内部からのクエリにはプライベートIP、外部からのクエリにはパブリックIPを返すように設定します。これについては次の記事で書く予定です。

10人以上のチームのネットワークを管理しているなら、問題が起きてから対応するのではなく、今すぐ設定することをお勧めします。内部DNSは一度構築すれば永続的に恩恵を受けられます——文字通りの意味で。

Share: