というトラブルについて、原因として考えられる PMTU Black Hole という現象について解説するとともに、その回避方法を説明します。
(想定しているネットワークの構成図もあります。)
MTU (Maximum Transmission Unit) というのは、ネットワークの物理的な種類によって決まるパラメタで、1回に送信できるパケットの大きさを表します。
東京めたりっく通信の「Single」コースで使用する PPPoE では、MTU が 1454 バイトになっています。資料によるとフレッツ ADSL も同じ値です。一般のイーサネットや、アナログモデム・ISDN で使用する一般の PPP では、MTU は 1500 です。この 46 バイトの差が致命的なのです。
Windows であれ、FreeBSD であれ、PPPoE のクライアントが動作しているマシンでは、PPPoE の MTU が分かるので問題はありません。しかし、PPPoE がルータで動作している場合、実際にアプリケーション (WWW ブラウザなど) が動作しているマシンでは途中に PPPoE があることはわかりませんから、自分がつながっているイーサネットの MTU (1500) しか認識できません。サーバ側も同様で、途中に MTU の小さな部分があることはわかりません。
現代的な TCP/IP スタックは、この種の状況に対処するために Path MTU Discovery (経路 MTU 検出) という技術 (RFC 1191) を使用します。ところが、PMTU Black Hole という現象があり (RFC 2923)、PMTUD を実行することによって逆に、一部のインターネットサーバーと通信できなくなってしまうことがあります。PMTU Black Hole は、直接には PMTUD の実行に不可欠な「ICMP/Destination Unreachable/Fragmentation Needed」メッセージが IP データグラムの送信元に届かないことが原因で発生します。これは、具体的には、以下のような状況で起きます。
これにひっかかると、そのサーバとの間では、TCP コネクションが確立するのに、データは一切流れないという状態になってしまいます。これが Black Hole という名前の由来です。
[注] 実際は、一切流れないわけではありません (後述)。これが、また、問題の特定を難しくするのです。
[注] ここで、PPPoE を終端するルータとは、ローカル側ではなく電話局に設置されている ADSL プロバイダのルータのことです。また、IP フィルタとか NAT とかは、ローカル側で動いているものではなく、通信先のインターネットサーバ側で動いているもの (もしも動いていれば) です。
うまく通信できない、という現象が、Path MTU Black Hole なのかどうかを判断するのは、必ずしも易しくありません。Path MTU Black Hole には、次のような特徴があります。
netstat
で ESTABLISHED になる。)ポイントは、それまで問題ないように見えていたのに、大きなデータが送られるタイミングで急に黙る、という点です。また、これはコネクションごとです。つまり、あるTCP コネクションが黙ってしまっても、別の TCP コネクションを新たに確立することはできますし、1回の送信データ量が少なければ通信が継続します。
典型的なケースでは、PMTU Black Hole は、アプリケーションによって以下のような状況となってあらわれます。(様々な要因により、若干違うあらわれ方になることもあるようです。特に、サーバ側の混み方によって、同じことをやっても黙るタイミングが相当ズレるようです。)
cd
によってディレクトリを移動したり、モードを切り替えたり (binary
、prompt
、glob
などのコマンド) が問題なく行える。また、ファイルの数が少ないディレクトリではdir
(ls
) などのコマンドも問題なく行える。ファイルを put
することもできる。ところが get
すると、いきなり黙ってしまう。(そのファイルがとても小さいものでない限り。)/etc/motd
など) が長い場合、バナーが出るはずのタイミングで (又は最初の 1 〜 2 行が出た後で) 黙ってしまう。ログインバナーが短い場合は、シェルが動いて最初のうちはコマンドも実行できるが、ls -l
や more
など、たくさんの文字が一気に送られてくるようなことをやると黙ってしまう。また、PPPoE が原因で発生する PMTU Black Hole の特徴として、この現象が発生するサイトとの通信が、PPPoE を終端しているマシン (つまり、PPPoE を動かしている FreeBSD マシン) 上で動作するアプリケーションは影響を受けない、という点があります。例えば、ルータを介したローカルな LAN に繋がったマシン (*BSD 機であれ、Windows であれ) からあるサーバに FTP して上のような状況になるにもかかわらず、ルータ上から同じサーバに FTP すると問題なく動作したりします。
回避方法は 2 通りあります。最新の ppp に入れ換えて mss 調整機能を有効にする方法と、ローカル側のマシンでデフォルトの MTU を小さくする方法です。
TCP オプションに Maximum Segment Size (MSS) というものがあり、これを使って リモートシステムに MTU を通知することができます。(詳しく言うと、mss というのは MTU を通知するためのオプションではないのですが、ここはまぁ、大雑把な話です。) FreeBSD の最新の ppp コマンドには、この TCP の mss を NAT のようにして書き換えてリモートホストに PPPoE の MTU を通知する機能が追加されています。
ppp にこの機能が追加されたのは 2000 年 12 月です。このため、FreeBSD 4.2 RELEASE に含まれる ppp には間に合っていません。4.3 RELEASE には入る模様です。FreeBSD 4.2 以前の場合には、新しい ppp に入れ換えることにより、mss 調整機能を利用することができます。
現時点 (2001年2月) では、mss 調整機能に対応した新しい ppp のバイナリが、http://people.freebsd.org/~brian/ppp-010204-4.2-STABLE.bin.tar.gz にあります。これは、4.1 RELEASE 以降 (ひょっとすると、もう少し前の 4 STABLE でも?) で動くようです。
この新しい ppp では、mss を調整する機能 (enable tcpmssfixup
) は、デフォルトで有効になっています。新しいバイナリを入れ換えれば、すぐに、問題は解決するはずです。(もし万一、これで解決しなければ、残念ながら、あなたの問題は、PMTU Black Hole ではないことが確認されました。)
もしも、新しいバージョンの PPP に入れ換えることができなければ、とりあえずFAQ の対処方法に従って、LAN に接続したマシンの MTU を小さくしてみて下さい。たぶん、この FAQ の「すべて電話会社が悪い」という主張は間違っていると思いますが、対処方法は正確です。東京めたりっく通信やフレッツ ADSL の場合は、MTU は 1450 でも 1464 でもなく、1454 バイトです。余裕を見る必要はありません。