なぜ従来のDNSは攻撃に対して脆弱なのか?
取引先の部屋番号を電話の代表受付に問い合わせた場面を想像してみてください。悪意のある第三者が回線に割り込み、偽のオフィスの部屋番号を教えたとします。そのまま部屋に入れば、機密情報をすべて盗み取られてしまいます。従来のDNSプロトコルは、まさにこれと同じ仕組みで動作しています。
itfromzero.comを名前解決する際、クライアントは暗号化も本人確認も行わずにUDPポート53経由でパケットを送信します。同一LAN内や同じISPルーター上の攻撃者は、DNSキャッシュポイズニング(DNS Cache Poisoning)を実行することが可能です。攻撃者は、推測したトランザクションIDを用いて偽の応答パケットを社内DNSリゾルバーへ大量に送信します。本物のDNSサーバーよりもわずか数ミリ秒早く偽パケットが到達すると、リゾルバーはキャッシュに攻撃者のIPアドレスを上書き保存してしまいます。
その結果は非常に深刻です。社内のすべての端末がWebメール、ERP、決済ゲートウェイにアクセスしようとした際、自動的に偽装サーバーへと誘導されてしまいます。この脆弱性を根本から解決する仕組みがDNSSEC(DNS Security Extensions)です。
DNSSECはどのようにDNSレコードを保護するのか?
DNSSECは、DoH(DNS over HTTPS)やDoT(DNS over TLS)のように問い合わせデータ自体を隠蔽するわけではありません。その代わりに、各レコードに対して暗号化による電子署名(cryptographic signature)を付与します。応答を受け取ったリゾルバーは、「このレコードは本当に正当な管理者が発行したものか?」「伝送経路の途中で改ざんされていないか?」を自身で検証できるようになります。
DNSSECで導入される4つの新規レコード
- RRSIG (Resource Record Signature): レコードセット(A、TXT、MXなど)ごとに付与される電子署名です。リプレイ攻撃を防ぐため、有効期限が設定されています。
- DNSKEY: リゾルバーがRRSIG署名を検証するためにゾーン内に配置される公開鍵(Public Key)です。
- DS (Delegation Signer): DNSKEYのハッシュ値であり、上位のDNSサーバー(例:
.vnや.com)に登録されます。これにより、Root DNSからの途切れない「信頼の連鎖(Chain of Trust)」が形成されます。 - NSEC / NSEC3: 他のサブドメインの構成を外部に漏らすことなく、指定したサブドメインが存在しないことを証明するレコードです。
鍵の分離メカニズム:ZSKとKSK
セキュリティの維持と運用性を両立させるため、DNSSECでは署名処理を2層の鍵構造に分離しています。
- ZSK (Zone Signing Key): 各種レコード(A、CNAME、MXなど)の署名に定期的に使用される鍵です。通常、ECDSA P-256またはRSA 1024/2048-bitアルゴリズムが採用され、30〜90日程度の短い周期で更新(Key Rollover)されます。
- KSK (Key Signing Key): DNSKEYレコードへの署名のみに使用される上位の鍵です。KSKの有効期間はより長く(1〜2年程度)、KSKを変更する際にはドメインレジストラ(Registrar)側でDSレコードを再登録する必要があります。
BIND9でDNSSECを実装する手順
1. 内部リゾルバーでDNSSEC Validationを有効化する
社内ネットワーク向けの名前解決サーバーとして運用している場合は、インターネット上のDNSサーバーからの電子署名を検証する機能を有効化します。
/etc/bind/named.conf.optionsを開き、次のように設定します:
options {
directory "/var/cache/bind";
dnssec-validation auto;
auth-nxdomain no;
listen-on { 127.0.0.1; 192.168.1.10; }; # サーバーのIPアドレスに変更
listen-on-v6 { any; };
};
構文チェックを行い、BINDを再起動します:
sudo named-checkconf
sudo systemctl restart bind9
2. 権威サーバーで自動署名(Inline Signing)を設定する
BIND 9.16以降では、dnssec-policy機能により手動でcronジョブスクリプトを用意することなく、鍵のライフサイクル管理や自動ローテーションが行えます。
/etc/bind/named.conf.localにポリシーを記述します:
dnssec-policy "standard-policy" {
keys {
ksk key-directory lifetime unlimited algorithm ecdsap256sha256;
zsk key-directory lifetime 60d algorithm ecdsap256sha256;
};
};
zone "itfromzero.lab" {
type primary;
file "/var/lib/bind/db.itfromzero.lab";
key-directory "/etc/bind/keys";
dnssec-policy standard-policy;
inline-signing yes;
};
3. 鍵ディレクトリの作成とキーペアの生成
秘密鍵を格納するディレクトリを作成し、bindユーザーに対して厳格なアクセス権限を設定します:
sudo mkdir -p /etc/bind/keys
sudo chown -R bind:bind /etc/bind/keys
sudo chmod 750 /etc/bind/keys
dnssec-keygenを使用して手動で鍵を生成する場合は、以下のコマンドを実行します(署名サイズが小さく処理速度に優れたアルゴリズム13 – ECDSAP256SHA256を推奨):
cd /etc/bind/keys
# ZSKを生成
sudo dnssec-keygen -a ECDSAP256SHA256 -n ZONE itfromzero.lab
# -f KSKフラグを指定してKSKを生成
sudo dnssec-keygen -a ECDSAP256SHA256 -n ZONE -f KSK itfromzero.lab
# BINDに鍵ファイルの読み取り権限を付与
sudo chown bind:bind /etc/bind/keys/K*
ゾーン設定をリロードすると、BINDが自動的に署名を行い.signedファイルを出力します:
sudo rndc reload itfromzero.lab
sudo rndc signing -list itfromzero.lab
4. レジストラへDSレコードを登録する
信頼の連鎖を完成させるため、ドメイン事業者(Cloudflare、Namecheap、お名前.comなど)にDSレコードを登録します。
KSKの公開鍵ファイルからDSレコードのパラメータを抽出します:
dnssec-dsfromkey /etc/bind/keys/Kitfromzero.lab.+013+*.key
以下のような出力結果が得られます:
itfromzero.lab. IN DS 2371 13 2 A1B2C3D4E5F67890123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0
レジストラのDNSSEC管理画面で、対応する4つの項目を入力します:
- Key Tag:
2371 - Algorithm:
13(ECDSAP256SHA256) - Digest Type:
2(SHA-256) - Digest: 末尾に表示されている64文字の16進数ハッシュ文字列
5. 動作確認
digコマンドを実行し、応答にad(Authenticated Data)フラグとRRSIGレコードが含まれているか確認します:
dig @127.0.0.1 itfromzero.lab A +dnssec +multiline
正常に設定されている場合、ヘッダー部にflags: qr rd ra adが表示されます。また、Aレコードの直下に有効な電子署名を含むRRSIGブロックが出力されます。
DNSSEC運用時によくあるトラブルと注意点
DNSSECはなりすまし攻撃を強力に防御できる反面、設定ミスに対して非常にシビアです。以下はドメイン全体がSERVFAILとなってアクセス不能に陥る代表的な3大原因です:
- サーバーの時刻ズレ(NTP非同期): RRSIG署名には必ず有効開始日時と有効期限(Inception / Expiration)が設定されています。サーバーのクロックが世界標準時から5分以上ズレていると、世界中のリゾルバーが署名を無効と判定します。必ず
chronyやsystemd-timesyncdをセットアップしておきましょう。 - KSK更新時のDSレコード更新忘れ: サーバー上の古いKSKを削除したにもかかわらず、レジストラ側のDSレコード更新を怠ると信頼の連鎖が切断されます。これにより、インターネット上のリゾルバーは即座に対象ドメインへのアクセスをブロックします。
- 秘密鍵のアクセス権限喪失: バックアップやリストア作業を行った後は、
/etc/bind/keysディレクトリの所有権がbindユーザー(ディストリビューションによってはnamed)に正しく維持されていることを必ず確認してください。
最も安全な導入手順は、まずリゾルバー側でDNSSEC検証を有効にし、テスト用サブドメインで検証を行ってから本番環境へと段階的に展開することです。
