Path MTU Discovery が原因の通信障害は分りづらい

普通、何らかの通信障害が発生すると、当然、通信の当事者に関する事を調べ出します。

サーバ側に何かログは出ていないか、パケットキャプチャをして相手からどんなパケットが届いているのか、Firewall 等で当該ホストに関するルールが引っかかっていないか....

ところが、Path MTU Discovery に起因する問題が発生すると、通信の当事者では、一見、相手が悪いように見えるし、実際、原因が当事者とは無関係のように見えるところにあります。

通信障害の最終手段として登場*1するパケットキャプチャをしても、単に、相手からのパケットが届かないだけに見えます。

そもそも、Path MTU Discovery とは?

まず、MTU

フレッツ網が出始めた頃、ネットワークスピードの改善方法として MTU のサイズを調整する話で有名になった MTU ですが、Maximum Transmission Unit の略で、1つのフレームで送信できる最大サイズの事を言います。

元々、MTU 自体は回線の種別によって決まるもので、一般的な Ethernet では 1500 バイトで、WAN 回線で使われる PPP の場合は可変ですが、Ethernet と同じ 1500 バイトになる事が多いようです。今はほとんど見かけない FDDI では 4352、IP over ATM で 9180 バイト、といった具合に、本来は様々な MTU を持つ回線があります。

フレッツ網が登場したときに MTU が話題になったのは、PPPoE というカプセル化技術を使ったためで、1500 バイトの Ethernet フレームの中に、ユーザ側の端末と契約先の ISP をつなぐ為の PPP を入れ、さらにその中に IP を入れる、という仕組みです。

そのため、通常の Ehternet に比べて PPP の分だけ、入れられる IP のサイズは小さくなります。

Path MTU とは

「Path」は「経路」を意味します。相手にパケットが届くまで、いくつものルータを渡っていきますが、その間の回線がどんな物が使われているか分りません。

ある相手と通信する時に、その経路全体での MTU が Path MTU です。

つまり、経路全体で、最も小さい MTU が Path MTU です。

Path MTU Discovery は、経路全体で最も小さい MTU をどうやったら分るか? という仕組みです。

ルータによるパケットの分割

ルータが受け取ったパケットを転送する際、転送先となる回線の MTU が受け取ったサイズより小さかった場合、パケットを分割して送ることがあります。

こうすれば、通信当事者は経路上の MTU など意識することなく、パケットを送信できますが、その代わり、ルータに取っては負担になります。

Path MTU Discovery の RFC 1191 が出されたのは 1990 年ですが、1990 年代に入ってから、ISP のルータのような、多くのネットワークとつながって、大量のパケットを裁くルータにかかる負荷が問題になっていました。

時期的に次期 IP(後の IPv6)の策定が行われていて、次期 IP のテーマの一つに、このルータの負荷問題もありました。

経路上の MTU が分ってしまえば、最初っからそれに合わせたサイズでパケットを送り出すことになるので、ルータでの分割は発生しません。

そのため、IPv6 では Path MTU Discovery が使われる事が前提になりました。

Path MTU Discovery の仕組み

もともと、IP パケットには DF(Don't Fragment)フラグというフラグがあり、このフラグがセットされているパケットは、ルータによる分割をしてはならない、ということになっています。

ルータがより小さい MTU を持つ回線を使ってパケットを転送しようとした時に、「分割できない」という事は、これ以上、パケットを転送する事ができない、という事を意味します。

こういった事態が発生していることを、パケットの送信元に伝えるために ICMP が使われます。

Type 3(Destination Unreachable Message)の Code 4(fragmentation needed and DF set)という ICMP がルータから送信元に送られ、この中に「○○○バイトだったら転送できるんだけど...」という情報が入っています。

送信元がこれを受け取ったら、そのサイズに合わせて IP パケットを再送します。

最終的に相手にパケットが届くまで、ICMP の情報に合わせて小さくしていけば、経路上の最小 MTU が見つかる、という仕組みです。

ICMP がフィルタされると Path MTU Discovery が成立しない

Path MTU Discovery は、パケットが分割できないときにルータが返す ICMP を利用して実現しています。ということは、もし ICMP がフィルタされている*2と、

  • ルータはこれ以上転送できないから、受け取ったパケットを捨てて ICMP を返す。
  • 送信元から見ると、送ったパケットに対して、相手から一切応答がない状態。

ということになります。

IPv6 では Path MTU Discovery が使われるので、ICMP をバッサリと Firewall 等で落としてしまうと、通信できない事態が発生する可能性があります。そのため、わざわざ RFC で、ICMPv6 のフィルタリングに関する文章が出されています。

RFC 4890: Recommendations for Filtering ICMPv6 Messages in Firewalls

考えなしにまるごとフィルタリングをしてはいけません。

実は IPv4 でも同じことが...

IPv6 の話だと思って、「そんなの使っていないし」と思っていると落とし穴があります。Path MTU Discovery 自体は IPv4 でも使える仕組みなので、原理的には同じことが発生しうることになります。

実は、割と以前から Linux では IPv4 でも Path MTU Discovery が有効になっていて、そのことに私が気がついたのは5年ほど前の CentOS Ver.6 系でした。CentOS 上で Squid を動かした HTTP Proxy を経由すると、繋がったり繋がらなかったり、みたいなことがあって、そのときにパケットキャプチャをして DF フラグが立っていることに気が付きました。

LinuxIPv4 の Path MTU Discovery が有効になっているかは sysctl コマンドで分ります。

$ sysctl net.ipv4.ip_no_pmtu_disc
net.ipv4.ip_no_pmtu_disc = 0

ちょっと分りづらいですが、ip_no_pmtu_disc なので、値が 0 なら有効です。

LinuxIPv4 の Path MTU Discovery が有効ということは...

今や Linux はサーバ以外にもいろいろなところで使われています。という事は、明確に「Linux」と認識していないものでも、Path MTU Discovery が有効になっている、ということになります。ネットワーク機器や IoT デバイスにも Linux は使われています。

私が実際に経験したのは、AWS のロードバランサである ELB です。

ELB に対する接続が VPN 経由だと NG、という事があったのですが、「ELB の実体って、Amazon Linuxインスタンスとかじゃないかなぁ」と思って、ICMP をブロックしていた Network ACL の設定を変更したら解消した、という事がありました。

IPv6 に限らず IPv4 に関しても、いたずらに「ICMP を丸ごとブロック」をするべきではありません。

Ping of Death*3Smurf 攻撃*4は、正直、過去の物です。ICMP に対して過大な恐怖心を持たず、フィルタするなら ICMP の「中身」も意識したいものです。

*1:個人的には、レイヤー 3 以下が原因になりそうな症状で、当事者が Linux だったら、最初っから tcpdump の登場させますが。

*2:Firewall 製品だと、意図的にブロックしない限り、許可している通信に対して発生した ICMP は適切に転送してくれる事が多いです。L3 スイッチの ACL のように、ステートレスにパケットを判断する場合、フィルタされてしまいがちです。

*3:Windows 95 が登場した頃、UNIX 系 OS がサイズの大きい ICMP Echo Request を送りつけられると、カーネルパニックに陥る欠陥があった。

*4:宛先がブロードキャストアドレスとなっている ICMP Echo Request に対して、該当するホストが応答する動作利用し、送信元アドレスを攻撃対象のアドレスに偽装してパケットを送りつけると、その何倍ものパケットが攻撃対象に向かう、という DDoS 攻撃の一種