Path MTU Blackhole(2)
Path MTU Blackhole(2)
先週、こんなことがあったので、ふと自宅サーバの設定を「Path MTU Discovery (RFC1191) を利用しない」よう変更してみました1。そのまま一日が過ぎ、今日になってサーバのログを確認してみると、
Feb 26 16:46:42 tpx20 kernel: ICMP: xx.xx.xxx.xx: fragmentation needed and DF set.
なるログが山ほど出ていることを発見、いろいろ調べてみたところ、どうも一部クライアントからのアクセスに対して正常に返答できていないようです2。
そもそもこのメッセージはなんなのよ?と思い、kernel source をごそごそとあさってみたところ、net/ipv4/icmp.c の中に次のような箇所があり、どうもここで出力されているようでした。
case ICMP_FRAG_NEEDED:
if (ipv4_config.no_pmtu_disc) {
LIMIT_NETDEBUG(
printk(KERN_INFO "ICMP: %u.%u.%u.%u: "
"fragmentation needed "
"and DF set.\n",
NIPQUAD(iph->daddr)));
} else {
info = ip_rt_frag_needed(iph,
ntohs(icmph->un.frag.mtu));
if (!info)
goto out;
}
break;
…これってつまり、Linux の場合 Path MTU Discovery プロトコルが無効になっている状態 (/proc/sys/net/ipv4/ip_no_pmtu_desc が“1”の状態) では、経路途中の Router が ICMP Type=3、Code=4 (つまり「Destination Unreachable.」&「fragmentation needed and DF set.」) を返してきても、ログに出力するだけで何もしない、って事のように見えます。
確かに、この Linux サーバ的には、Path MTU Discovery プロトコルを無効にすると、送出されるパケットの DF (Don’t Fragment) フラグも 0 となり、つまり経路の Router がよろしく Fragment してくれさえすれば、ICMP Type=3、Code=4 のメッセージに答える必要は本来無いはずではあります。
しかしどうも巷にはそもそも DF フラグが立っていようがいまいが Fragment 出来ない Router が山ほど存在するらしく (とは SAK 氏談)、その場合その Router は (DF フラグの状態に関係なく) 上記 ICMP Type=3、Code=4 を送信元へ送り返すようなんですね (IPv4 には他に使えるメッセージがないのでしょうがないようです)。しかし上で見たように Linux kernel は Path MTU Discovery が有効になっていない場合単にそのパケットを破棄してしまいますから、結果的にその Router の先にいるクライアントへはパケットが届かないことになってしまうようです。
というわけで、こと Linux をサーバとして利用する場合、Path MTU Discovery は無効にしてはいけない (そもそも最近のトレンドでは常に on にしておくことが強く推奨されている模様)、また Blackhole を検知した場合も、サーバ側設定を変更するのではなく経路上で ICMP を破棄してしまっている Device の設定を変更しなくてはならない、というのが正解のようです。
ネットワーク屋さんにはきっと常識なのでしょうが (と、SAK 氏がうるさく連呼しているが)、いやはやいろいろ難しいですねぇ。