Windows Server 2016 高度なDNS設定の構成

AD DS環境では、多くのアプリケーションやサービスはDNSでの名前解決を利用するが故に、攻撃対象になりやすいです。
本記事では名前解決を行うDNSのオプションとして用意されている攻撃対策をご紹介します。

スポンサーリンク:

DNSセキュリティを向上させる3つの機能

DNSはアプリケーションを利用するための名前解決に使われる重要な役割であるが故に、それを利用した悪意のある攻撃があるのも事実です。
社内環境に構築するDNSであれば必要かと言われるとそんなことはありませんが、DNSに関連する一般的な知識として覚えておきましょう。

Windows Server DNSでは以下の3つのセキュリティオプション機能を使用することが出来ます。

  • DNSSEC
  • DNSソケットプール
  • DNSキャッシュロック

DNSSEC

DNSSECとは、公開鍵暗号方式と電子署名を応用して、DNSサーバーから応答されたレコードが本当に正しいかどうかをDNSリゾルバが検証するシステムです。

DNSSECでは、これらの暗号化技術を活用するため、まずそれぞれの概要について触れておきます。

公開鍵暗号方式

公開鍵暗号方式とは、対になる公開鍵と秘密鍵の二種類の鍵を作成して、インターネット上でも安全にやりとりができる暗号化技術です。
名前の通り、公開鍵は“公開される鍵”、秘密鍵は“公開されない鍵”として定められており、この二つの鍵を用いてデータの暗号化と復号化が実現されます。
公開鍵暗号方式

上の図では、AさんがBさんによって公開されている公開鍵で平文を暗号化し、Bさんに送信します。
Bさんは送られてきた暗号化文章を読むためには復号化が必要なので、Bさんだけが持っている秘密鍵を使って復号します。
公開鍵暗号方式では、公開鍵と秘密鍵は必ずペアとなりますので、Bさんの公開鍵で暗号化したモノは、Bさんの秘密鍵でしか復号化することは出来ません。
つまり、Bさん以外の悪意のある第三者にデータが盗聴されても、Bさんの秘密鍵を持っていなければ、データの中身を解読することは出来ません。

さて、先のフローでは公開鍵で暗号していましたが、逆に秘密鍵で暗号することによって、送信者の正当性を示すことが可能になります。

公開鍵暗号方式

上の図では、Aさんが自身の秘密鍵で暗号化をし、Bさんに送信します。
Bさんは受信したデータに対して、Aさんの公開鍵でデータを復号します。
この時、Bさんが受信したデータは秘密鍵の保持者であるAさんから送信されたものであるという検証が行えます。
なぜならば、Aさんの秘密鍵は、送信者であるAさんだけが保持していることが前提とされているためです。

この送信者が正当であるかどうかの検証を応用して、電子署名を実現することが出来ます。

電子署名

電子証明とは、送信するデータに対して一定のアルゴリズムでハッシュ値を求め、その値を秘密鍵で暗号化したデータを送信することで、受信者が送信者の正当性を検証することが出来るシステムです。
電子署名

Aさんが「Hello」メッセージをBさんに送信する前、「Hello」に対して、ハッシュ値を求め、さらにAさんの秘密鍵で暗号化します。暗号化されたデータを電子署名として、メッセージ+電子署名をBさんに送信します。
受信したBさんは、「Hello」を同じアルゴリズムで求めたハッシュ値③、電子署名をAさんの公開鍵で復号した値④を比較して、③と④で求められた値が一致していれば、Aさんから送信されたものであるということと、メッセージが改ざんされていないことが検証されます。

DNSSECのフロー

DNSSECでは、応答するレコードに電子署名を付与してDNSリゾルバに応答することで、DNSリゾルバが応答の正当性を検証することが可能になります。

例えば、デジタル署名されたcontoso.comゾーンを保持するDNSサーバーが、DNSリゾルバからクエリを受信すると、要求されたレコード+デジタル署名を返します。
レコードとデジタル署名を受け取ったDNSリゾルバは、応答してきたDNSサーバーがなりすましでないか、改ざんされていないかを検証することが出来ます。

DNSSEC

この時、DNSリゾルバはトラストアンカーからDNSSECの秘密鍵とペアになる公開鍵を取得し、応答されたレコードが改ざんされていないかどうかを検証します。

DNSSECの構築

DNSSECを構成するにあたって必要になるコンポーネントがトラストアンカーになります。
トラストアンカーとは、DNSSECのためのデジタル署名をDNSリゾルバが検証するにあたって必要になる公開鍵を格納する場所になります。

Windows ServerのDNSであれば、DNSSEC構成ウィザードでトランスアンカー配布ポイントを構成することが出来ます。
それでは、実際に構成ウィザードを走らせながらDNSSECを構築していきましょう。
本作業はActive Directory統合ゾーンで行っています。

DNS管理コンソールから、署名したゾーンを右クリックして[ゾーンの署名]をクリックします。
DNSSEC

[次へ]をクリックします。
DNSSEC

[次へ]をクリックします。
DNSSEC

[次へ]をクリックします。
DNSSEC

[次へ]をクリックします。
DNSSEC

KSK(Key Signing Key)とZSK(Zone Signing Key)のプロパティを設定していきましょう。
DNSSEC

DNSSEC

DNSSECでは署名に使われる秘密鍵がKSKとZSKの二種類が存在し、それぞれ役割が異なります。

ZSK=ゾーンに署名する秘密鍵
KSK=ZSKに署名する秘密鍵

ZSKはゾーンに署名する秘密鍵にであり、対になる公開鍵が後に登場するDNSKEYレコードとしてDNSリゾルバに公開されます。
一方、KSKの役割はZSKを署名するために存在し、こちらも後に登場するDS(Delegation Signer)として利用されます。

鍵を二種類用意するワケは、設定値にもあるロールオーバーが関係してきます。
ウィザードの規定値を確認すると、KSKは755日なのに対して、ZSKは90日と短い周期に設定されていますね。
こららはまとめてご説明した方が理解しやすいため、後ほど説明します。

NSEC3にチェックを付けて[次へ]をクリックします。
DNSSEC

NSEC(Next Secure)とは、クエリに対して該当するレコードをDNSサーバーが応答出来ない時の回答に署名するためのレコードになります。
NSECレコードでは、そのDNSサーバーがホストするゾーン情報を一通り返すため、DNSリゾルバは網羅的にゾーン情報を調べれてしまうというzoneenumeration問題があるため、悪意のあるユーザーに不正利用される恐れがあります。
そこで、登場したのがNSEC3というレコードです。NSEC3は従来のNSECとは異なり、応答に付け加えるゾーン情報を、あるアルゴリズムで算出されたハッシュ値で示すため、zoneenumeration問題を解決します。

トラストアンカーの構成をします。
DNSSEC
ウィザードを実行しているDNSサーバーがActiveDirectory統合ゾーンであるならば、[このゾーンに対するトラストアンカーの配布を有効にする]にチェックをつけると、フォレスト内で該当ゾーンをホストするActiveDirectory統合ゾーンのDNSサーバーでDNSSECが有効になります。
この設定はウィザード構成後にゾーンのプロパティから設定変更できるため、十分なテストを実施後、チェックをつけるようにしましょう。

[次へ]をクリックします。
DNSSEC

[次へ]をクリックします。
DNSSEC

[完了]をクリックすれば、構成完了です。
DNSSEC

構成完了後、DNS管理コンソールからDNSSEC設定を有効にしたゾーンを覗いてみると、大量のレコードが生成されています。(これをどうにかしておくれMSさん)

各レコードを表にまとめておきました。

DNSKEY ゾーンを署名する秘密鍵と対になる公開鍵
DS(Delegation Signer) 子ゾーンのDNSKEYをある一定のアルゴリズムから算出したハッシュ値
RRSIG 応答サーバーが正当であるかの検証をするために必要なレコードの電子署名

DNSリゾルバはDNSサーバーからレコードをRRSIGを受信し、DNSKEY(公開鍵)を使って、RRSIGを検証するフローになります。

DS(Delegation Signer)とは?

DSとは、DNSKEYレコードのハッシュ値になります。DSは親ゾーンが署名後、レコードとして登録してもらう委任レコードになります。

先ほど、DNSSECで使用する秘密鍵にはKSKとZSKの二種類があると書きましたが、そのうちのKSKのハッシュ値がDSになります。

そもそもDSは何の用途に使われるかと言いますと、DNSSECでの信頼の連鎖(chain of trust)を構成するため使われているレコードになります。

DNSSECでは、応答の正当性を検証できますが、それは公開鍵が応答したDNSサーバーのモノであるという前提条件のもと成り立っています。
そのため、単に公開鍵と電子署名を受け取っただけでは、信憑性がそこまで高くないことが言えます。
そこで考えられたのが、DSレコードによる信頼の連鎖です。

DNSは分散型サービスです。名前解決でも、www.microsoft.comのように、それぞれホストするゾーン情報にアクセスするため、複数のDNSサーバーにクエリを投げてIPアドレスを引きます。
参考:DNS 名前解決とは?

これらの複数のDNSサーバーには親子関係があり、www.microsoft.comであれば、”.(ルート)⇒com⇒microsoft.com”の順にDNSサーバーを照会していくため、各DNSサーバーでDSレコードと子ゾーンの公開鍵の検証を連鎖的に行いましょうって話です。

DSレコード

子ゾーンは自身のゾーンに対して親ゾーンとなるDNSサーバーに、DSレコード(公開鍵のハッシュ値)を送信します。
DSレコードを受け取った親ゾーンは子ゾーンからのDSレコードであること検証後、自身の秘密鍵で電子署名し、DNSリゾルバに対して公開します。

DNSリゾルバは、DNSサーバーからの応答に対して、親ゾーンから貰ったDSレコードを比較して検証を行います。
この時、全ての検証に成功する必要があり、どれか一つでも検証に失敗すると、DNSリゾルバはその応答に対して拒否します。

この連鎖的な検証を実装することで、いずれかのDNSサーバーの応答が偽装されていたとしても、上位DNSサーバーでそれを検知することが出来るため、より高度な信頼性を担保することが出来るんです。

さて、ここでまだ説明できていなところが、KSKとZSKの二分化のワケと、ロールオーバーの期間が異なる意味です。

KSK、ZSKとは?

KSKとZSKを分ける理由として、外部からの解析に対しての脅威を対抗するための処置です。

ゾーン署名鍵として使用されるZSKは、対となる公開鍵がDNSKEYとしてDNSリゾルバに公開されるため、一定のサイクルでロールオーバーしていかないと、悪意のあるユーザーに解析される恐れがあります。
一定のサイクルが短ければ短いほど、リスクは減少するのに対して、あまり頻繁にロールオーバーしてしまうと親ゾーンへのDSレコード登録回数が増るため、必然的に運用負荷が高くなるデメリットが出てきます。

そこでKSKというもう一つの署名鍵を用意することで、外部に公開するZSKのロールオーバーは短く、DSレコードに使用するKSKは短くという柔軟な運用体系を実現することが出来るわけです。

そのため、DNSSEC構成ウィザードでもロールオーバーの期間がZSKは90日、KSKは755日間とばらつきのある値が規定で設定されているわけです。

NRPT(名前解決ポリシーテーブル)

DNSSECの構成が完了しても、クライアント端末側でレコードの検証を実施するように設定しなければなりません。
WindowsではNRPT(名前解決ポリシーテーブル)という、クエリの送信~応答を処理するための動作を制御する規則が含まれています。

DNSSECを構成したいのであれば、特定のDNSサフィックスについて応答の妥当性をチェックするように要求します。
本設定はWindows Serverのグループポリシーによってクライアント展開することが出来ますので、お試しあれ。
名前解決ポリシー

DNSSEC検討ポイント

DNSSECを実装するにあたって、いくつか検討すべきポイントがあります。

パケットの増大

当然ですが、従来の名前解決フローとは異なり、レコード+電子署名が応答として帰ってきますので、パケットが増大します。
DNSはUDP/53を使用しますが、UDPは512Byteと制限があるため、EDNS0(Extension Mechanisms for DNS version 0)と呼ばれるDNSの拡張プロトコルを使うことで512Byteの壁をある程度緩和することが出来ます。
EDNS0

またEDNS0に対応していないDNSサーバーの場合、UDP⇒TCPにフォールバックすることで、制限のない通信が行えるのですが、名前解決は高速な通信を求められるものですから、3ウェイ・ハンドシェイクはあまり望ましくありません。

サーバーの負荷

こちらも当然ですが、DNSサーバー側で多くのレコードの生成や、レコードの検証が操作として増えるため、負荷が増えることになります。また、DSレコードの登録・検証も加わりますから、計画する必要があります。
現状、どれぐらいのクエリ数が来ていて、どれぐらいのリソースを喰っているのかを数値化した上で、考慮しましょう。

秘密鍵の保管

DNSに限らず、PKIによる暗号化技術の世界でも、秘密鍵こそが最重要機密に当たります。
秘密鍵が外部に漏えいしてしまいますと、悪意のあるユーザーから攻撃を受けてしまいますので、適切な管理方法と定期的な交換を心がけましょう。

そういえば、2017年9月19日にDNSのルートゾーンに更新が加わるようで、フルリゾルバを運用している方々にはヒヤリな記事が公開されました。
日本ネットワークインフォメーションセンターさんで詳しくまとめてありますので、ご参考下さい。
どうやら、KSKのロールオーバーとDNSKEYの応答サイズが一時的に大きくなるみたいですが、後者による影響が大きそうだな…

DNSソケットプール

DNSソケットプールとは、DNSサーバーがクエリを発行する時のソースポートをランダムに使用する技術です。

これは、DNSキャッシュポイズニングと呼ばれる、悪意のあるユーザーが偽のDNS応答を送り付け、正当なDNS応答の代わりにDNSサーバーにキャッシュさせる攻撃のリスク低減策として実装された技術です。

DNSソケットプールが有効だと、通信時の送信元ポートとして、予測可能なソースポートを使用する代わりにDNSソケットプールから選択したランダムなポートを使用します。
これにより、DNSキャッシュポイズニングを困難にすることで、リスク低減を実現することが出来ます。

DNSソケットプールは規定で有効になっており、規定サイズは2,500となっていますが、値としては0~10,000を下記コマンドで設定出来ます。

また、レジストリでも設定変更が可能です。
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\DNS\Parameters
値:SocketPoolSize
DNSソケットプール

値が大きければ大きいほど攻撃に対するセキュリティは高くなりますが、DNSサーバーが使用するポート数の割合が広くなるため、ネットワーク管理者への周知が必要になるかと思います。

DNSキャッシュロック

DNSサーバーでは処理の負荷を軽減させるために、他のDNSサーバーから返された応答を自身のローカルに一定期間キャッシュすることで、次以降のDNSクエリを受け取ると、キャッシュから応答するようになっています。

このキャッシュ期間に該当する設定値がレコードに設定されているTTLになります。

Time to live (時に TTL と省略される)は、コンピュータとコンピュータネットワーク技術において、1単位のデータ(例えば一つのパケット)が破棄される前に経過する可能性がある時間、もしくは繰り返し数すなわちトランスミッション数の上限(余命)である。
引用 – Wikipedia

TTLという言葉はよくネットワークのルーティングなどで目にしますが、DNSに関しては、レコードのキャッシュ期間を指します。
DNSキャッシュロック

しかし、キャッシュしたレコードが更新されていた場合、いつまでもキャッシュ情報をDNSリゾルバに返していては、接続エラーとなってしまいます。
そのため、DNSサーバーではTTL期間内でもレコードの更新情報を受信すると、キャッシュされたレコードを上書きする動作があります。

この特性を活かして、悪意のあるユーザーが偽のキャッシュ情報を通知させて、DNSサーバーに上書きさせるといった攻撃手法があります。
これを防ぐためにの手法が、DNSのキャッシュ内レコードを上書きさせない機能であるDNSキャッシュロックです。

Windows Server DNSではCacheLockingPercentという値で設定がされており、規定で100%となっています。
この値はキャッシュしたリソースレコードのTTLに対する割合を示しており、TTLの何%の時間が経過したら上書きを許可するかを決定します。
つまり、規定でキャッシュ内レコードは上書きさせない設定です。

本設定を変更するには下記コマンドで%値を変更します。

こちらの設定も同様にレジストリから設定変更が可能です。
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\DNS\Parameters
値:CacheLockingPercent
DNSキャッシュロック

規定の100%である場合、セキュリティ上は望ましい設定ですが、IPアドレスが更新された場合に、クライアントに古いIPアドレスを返すことになりますので、適切な値を設定しましょう。

おわりに

長々と記事を書いてしまいましたが、いかがでしたでしょうか?
DNSSECは結構耳にすると思いますので、各レコードがどんな役割を持つのかをしっかり理解しておくことをお勧めします。

Windows Serverでは本記事で紹介したセキュリティ設定以外にもラウンドロビンなども構成出来ますので、別記事にてご紹介できればと思います。

それでは、良いWindows Serverライフをっ♪

スポンサーリンク