第13章 DNSサーバーの保護
LPIC-2 207.3 相当
第9章ではBINDの基本設定とゾーン管理を扱いました。ここでは、DNSサーバーを外部の脅威からどう保護するかを扱います。権威DNSサーバーは常時インターネットに露出しているため、稼働権限の制限やゾーン転送時の認証など、複数の防御層を組み合わせることが重要です。
chroot環境でのBIND運用
named(BIND)を一般ユーザー権限で、かつchroot環境(ファイルシステムの見える範囲を限定した環境)で動かすことで、万が一named自体に脆弱性があり乗っ取られた場合でも、被害をそのchroot環境の中に閉じ込められます。
Debian系でのchroot構成の例
$ sudo apt install bind9 # オプションによりchroot構成のパッケージも用意されている
/etc/default/named(またはsystemdのユニットファイル)で実行ユーザーとchrootパスを指定
OPTIONS="-u bind -t /var/lib/named"
-u bindでnamedプロセスの実行ユーザーを一般ユーザー(bind)に落とし、-tでchrootのルートパスを指定します。chroot環境内には、named自身が動作するために最低限必要な設定ファイル・ゾーンファイル・デバイスファイルのコピーを配置する必要があり、通常の/etc/named.confのパスも、chroot環境内での相対パスとして解釈される点に注意してください。
-uで非rootユーザーに切り替え、-tでchrootすることで、権限昇格や任意ファイルアクセスを狙う攻撃が成功した場合の被害範囲を大きく限定できます。
forwardersディレクティブによるsplit DNS
「split DNS」(あるいはsplit-horizon DNS)は、社内ネットワークからの問い合わせと、インターネットからの問い合わせに対して、同じドメイン名でも異なる回答を返す構成です。たとえば社内向けには内部IPアドレスを、外部向けにはグローバルIPアドレスを返す、といった使い分けができます。
/etc/bind/named.conf.local でのview定義によるsplit DNSの例(Debian系。RHEL系では/etc/named.conf内に同様に記述します)
view "internal" {
match-clients { 192.168.1.0/24; };
zone "example.com" {
type master;
file "/etc/bind/internal/example.com.zone";
};
};
view "external" {
match-clients { any; };
zone "example.com" {
type master;
file "/etc/bind/external/example.com.zone";
};
};
viewステートメントは、接続元(match-clients)ごとに異なるゾーン定義の集合を適用できる仕組みです。内部ネットワークからの問い合わせには社内専用のゾーンファイルを、それ以外(any)には外部公開用のゾーンファイルを返すことで、社内のプライベートな構成情報を外部に漏らさずに済みます。加えて、forwardersディレクティブを使うと、自分で再帰的な問い合わせを行わず、指定した上位のDNSサーバー(ISPが提供するキャッシュサーバーなど)に問い合わせを委任することもでき、外部への直接的な問い合わせを減らしてセキュリティと効率の両方を高められます。
TSIGによるゾーン転送の保護
プライマリ(マスター)DNSサーバーからセカンダリ(スレーブ)DNSサーバーへのゾーン転送は、標準では送信元IPアドレスによる制限しかかけられませんが、IPアドレスは詐称されうるため、より強固な保護策としてTSIG(Transaction Signature)が使われます。TSIGは共有鍵を使ってDNSメッセージに署名し、正当なサーバー間の通信であることを暗号学的に保証します。
$ tsig-keygen -a hmac-sha256 transfer-key # 共有鍵を生成
key "transfer-key" {
algorithm hmac-sha256;
secret "8k3jQm2vN9pXeR7wYbT5cZ4uH1sD6fG0aL+mK8nP3qU=";
};
この行のこの値に注目: tsig-keygenの出力は、named.confにそのまま貼り付けられるkey { ... }ブロックの形式で表示されます。secretの値はBase64エンコードされたランダムなバイト列で、プライマリ・セカンダリ両方の設定ファイルに同一の値を登録する必要があります。この鍵はパスワードと同等の機密情報なので、設定ファイルのパーミッションを適切に制限し、平文のまま第三者に渡さないようにします。
named.conf での鍵定義とゾーン転送への適用
key "transfer-key" {
algorithm hmac-sha256;
secret "生成された共有鍵の値";
};
zone "example.com" {
type master;
allow-transfer { key "transfer-key"; };
};
allow-transferにTSIGの鍵を指定することで、正しい鍵を持つセカンダリサーバーからのゾーン転送要求だけを受け付けるようになります。同じ鍵をセカンダリ側の設定にも登録しておく必要があります。
DNSSECの鍵運用
第9章でDNSSECの概要に触れましたが、ここでは実際の鍵運用コマンドを扱います。DNSSECは、ゾーンの応答に電子署名を付与することで、キャッシュポイズニングのような偽の応答を注入する攻撃から保護する仕組みです。
$ dnssec-keygen -a RSASHA256 -b 2048 example.com # ゾーン署名鍵(ZSK)のペアを生成
Generating key pair.
Kexample.com.+008+12345
$ ls Kexample.com.*
Kexample.com.+008+12345.key Kexample.com.+008+12345.private
$ dnssec-signzone -o example.com example.com.zone # ゾーンファイルに署名を付与
Fetching KSK/ZSK ... done
Verifying the zone using the following algorithms: RSASHA256.
Zone fully signed:
Algorithm: RSASHA256: KSKs: 0 active, 0 stand-by, 0 revoked
ZSKs: 1 active, 0 stand-by, 0 revoked
example.com.zone.signed
この行のこの値に注目: dnssec-keygenが出力するKexample.com.+008+12345という文字列は、生成された鍵ファイルのベース名で、008はアルゴリズム番号(RSASHA256)、12345は鍵タグ(鍵を一意に識別する番号)です。dnssec-signzoneのZone fully signed:以降は、実際に何個のZSK/KSKが有効な状態で署名に使われたかのサマリで、末尾に表示されるexample.com.zone.signedが署名済みゾーンファイルの実際のファイル名です。named.confのfileディレクティブは、この.signedファイルの方を指すように書き換える必要があります。
dnssec-keygenで公開鍵・秘密鍵のペアを生成し、dnssec-signzoneで実際にゾーンファイルへ署名を適用します。DNSSECには「ゾーン署名鍵(ZSK)」と、そのZSKを保証するための上位の「鍵署名鍵(KSK)」という2種類の鍵があり、定期的な鍵のロールオーバー(更新)運用も必要になる点が、単純な証明書運用とは異なる複雑さです。
DNSSECの信頼の連鎖(chain of trust)
DNSSECは、ルートゾーンから対象ドメインまで、親ゾーンが子ゾーンの鍵の正当性を保証していく「信頼の連鎖(chain of trust)」という考え方で成り立っています。子ゾーンのKSK(鍵署名鍵)のハッシュ値を、親ゾーンに「DS(Delegation Signer)レコード」として登録してもらうことで、この連鎖がつながります。
$ dnssec-dsfromkey Kexample.com.+008+12345.key # KSKからDSレコードを生成
example.com. IN DS 12345 8 2 A94B4A0193F8A5C9E8A1D4B3C2F1E0D9A8B7C6D5E4F3A2B1C0D9E8F7A6B5C4D3
# 生成したDSレコードの内容を、親ゾーン(この例では.comのレジストリ)に登録してもらう
この行のこの値に注目: 出力のDS 12345 8 2 ...のうち、12345は鍵タグ(鍵生成時のファイル名と一致)、8はアルゴリズム番号(RSASHA256)、2はダイジェストの種類(2はSHA-256)、末尾の16進数文字列がKSKのハッシュ値そのものです。この1行をそのまま、ドメインを取得したレジストラの管理画面のDSレコード登録欄に入力します。
この登録作業は自ゾーン内では完結せず、多くの場合、ドメインを取得したレジストラの管理画面からDSレコードを登録する手続きが必要です。DSレコードを登録し忘れると、DNSSEC自体は正しく設定されていても、信頼の連鎖がルートまでつながらず、検証に対応したリゾルバからは「未署名のドメイン」として扱われてしまいます。
DANEの概要
DANE(DNS-based Authentication of Named Entities)は、DNSSECで保護されたDNSレコード(TLSA レコード)を使って、TLS証明書の正当性を検証する仕組みです。従来のHTTPS証明書は商用CAの信頼に依存していますが、DANEを使うと、DNSSECによって保護されたDNS上で「このドメインが使うべき正しい証明書(またはその発行元CA)」を直接公開できます。LPIC-2の出題範囲としては、DANEが「DNSSECを基盤として証明書の正当性を検証する仕組みである」という位置づけを理解していれば十分です。