DNSフラグメント攻撃についてはこちらを参照されたい。
ここで、権威サーバからの応答を強制的かつ攻撃者の任意の位置でフラグメントさせるために、攻撃者が偽のICMPv4 type 3 code 4 (destination Unreachable, fragmentation needed and DF set、以下簡単に ICMPv4 Packet TooBig) を権威サーバに投げつけることが攻撃成立の一つの要素となっている 。厳密にはそうでないケースもあるが、現時点で知られている限りほとんどのケースで必要である。
DNS権威サーバがLinuxの場合、デフォルト設定のIPv4 UDP ソケットはその偽ICMPv4 Packet TooBigメッセージを容易に受け入れ、送信するUDPパケット (DNS応答) をフラグメントして送信してしまう。
Linux Kernel 3.15 から、新しいソケットオプションIP_PMTUDISC_OMIT
が実装された。
このオプション有効にしたソケットは、ICMPv4 Packet TooBigメッセージを無視し、インタフェースMTU (ほとんどの場合、Ethenet MTUである 1500バイト) を超えた場合のみ送信時にフラグメントが行われる。すなわち、偽のICMPv4 Packet Toobigメッセージに騙されることがなくなり、これがフラグメント攻撃に対する緩和策となる。
このオプションが有効となるには、Linux カーネルのバージョンが 3.15以降であることの他、権威サーバソフトウェア側でも本オプションを IPv4 UDPソケットに対して有効にするコードが必要がある。有効化は簡単で、ソケットに対して setsockopt()するだけである。下記は、権威サーバ内で有効化するコードのイメージである。
#include <netinet/in.h>
#if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_OMIT)
int action_omit = IP_PMTUDISC_OMIT;
setsockopt(s, IPPROTO_IP, IP_MTU_DISCOVER, &action_omit, sizeof(action_omit));
#endif
- BIND 9.9.10 / 9.10.5 / 9.11.1 / 9.12.0 / 9.13.0 以降
- NSD 4.1.27, 4.2.0 以降
- Knot DNS 2.8.2 以降
- PowerDNS 4.2.0-rc2 以降
以上の権威サーバのバージョンを、
- Linux 3.15 以降
環境でビルドして動作させれば、自動的にフラグメント攻撃緩和策が有効となる。特別な設定やコンパイルオプションも不要である。
RHEL6 のカーネルは Linux 2.6.32ベース、RHEL7は3.10ベースと古く、カーネルのバージョンだけ見れば上記の権威サーバでも緩和策が有効にならないのだが、実は RHEL6/7に付属している Red Hat版Linuxカーネルには IP_PMTUDISC_OMIT
機能がバックポートされている(3.10.0-217.el7 / 2.6.32-525.el6)。
残念なことに、Red Hat は RHELのglibcヘッダに IP_PMTUDISC_OMIT
マクロをバックポートし忘れており、ごく最近までRHEL6,7で対応済権威サーバをコンパイルしても、本機能が有効とならなかった (上記のコードで IP_PMTUDISC_OMIT
マクロが定義されていないと setsockopt()できないことに注意)。
この glibc における IP_PMTUDISC_OMIT
未定義の問題は RHEL 7.7 (glibc-2.17-284.el7)で修正された。
したがって、RHEL 7.7 以降の環境で、上記権威サーバの新バージョン (BINDなら 9.9.10, 9.11.1, 9.12, 9.13 以降) をビルド・実行すれば緩和策が有効になる。特別なコンパイルオプションも不要である。
なお、RHEL 7に付属するパッケージの BIND9 は 9.9.4ベースであるため、本緩和策は無効である。有効となるバージョンをソースからビルドする必要がある。
なお、RHEL 7.7付属の BINDパッケージは 9.11.4 ベースに変更されたため (RHEL 7.6まではBIND 9.9.4ベース)、緩和策が有効となっている。
上記 glibcの問題で 緩和策が有効にならない RHEL のバージョンでも、
- RHEL 6.7 以降 (kernel 2.6.32-525.el6)
- RHEL 7.1 以降 (kernel 3.10.0-217.el7)
ならば、カーネル自体には本機能が入っているため、裏技的であるが緩和策を有効にすることができる。DNSサーバをビルドする際の ./configure
実行時に、Cコンパイラに対して強制的に IP_PMTUDISC_OMIT
マクロを定義させるようにする。
$ ./configure CFLAGS=-DIP_PMTUDISC_OMIT=5
IP_PMTUDISC_OMIT
はLinuxのソケットオプションであるが、ほかのOSではどうか。
FreeBSD の IPv4 UDPソケットは、デフォルトで Linux の IP_PMTUDISC_OMIT
相当の動作となっており、偽ICMPv4メッセージに騙されないため本緩和策が有効 (権威サーバ側の対応も不要) である。
Linux / FreeBSD以外のOSの状況は不明である。