みなさん IPv6 は使ってますか?僕の自宅は最近 IPv6 が使えるようになりました!そして、大学の僕の研究室でも IPv6 が使えます。
さて、その研究室の IPv6 ですが、何故だかなかなか表示されないウェブサイトがありました。今回は久々にその原因を探るというまじめな記事ですw
まずは今回の問題点です。 IPv6 に対応しているウェブサイトで、読み込みが完了しないところがある、ということです。いろいろなサイトがそうなっていたような気もしますが、一番記憶に残っているのが Wikipedia でした。ページの URL は ja.wikipedia.org ですが、ステータスバーを見る限りだと bits.wikimedia.org というサーバとの通信がうまくいっていないようでした。
まあこういうときは Wireshark とかでパケット見てみるのがいいのでとりあえず見てみました。
3-Way handshake には成功していますが、 HTTP の GET に対する応答が返ってきていないですね。いろいろ悩んだ末に、結局原因はパケットサイズだろうと考えました。研究室の IPv6 は IPIP トンネリング (IPv6 over IPv4) で接続されているらしく、その Maximum Transmission Unit (MTU) 以上の大きさのパケットが通っていないのではないかと思ったためです。だから、パケットの小さい 3-Way handshake は成功して、データは来ないというわけです。ググったところ、良い感じの解説が載っている素敵なページが見つかりました。
IPv6 ではルータでフラグメントしないので、大きすぎるパケットは破棄されてしまいます。そんなときのために Path MTU Discovery ってのがあるんですが、環境によってはそれがうまく働かないようです。ただし Path MTU Discovery が働かなくても TCP ならば MTU から IP ヘッダサイズを引いた値を MSS として相手に通知すれば、結果的に適切なパケットサイズで送ってもらえるというわけです。
上のリンク先では、 MSS の書き換えをルータが自動的に行ってくれるというものでしたが、今回はルータをいじれないので Windows の設定を変えました。 Windows は MTU を変えるとそれに併せて MSS も変えてくれるので、そうしました。しかも IPv4 と IPv6 で別々の MTU を設定出来るみたいです。以下のページを参考にさせて頂きました。
Windows7でMTU値を変更する:それ以上でもそれ以下でもあったりします:So-netブログ
まずコマンドプロンプトを管理者モードで起動して以下のコマンドを入力します。
netsh interface ipv6 show interface
表示されたリストの中から、自分が普段使っている NIC の Idx を覚えておきます。そして以下のコマンドを入力します。
netsh interface ipv6 set interface (Idx) mtu=(MTU)
ちなみに今回の MTU はデフォルトの 1500 バイトから IPv4 ヘッダの 20 バイトを引いた、 1480 バイトにします。これだけです。
この設定で Wikipedia を見てみるとちゃんと表示されました。
応答の Length が 1480 (MTU) + 14 (Ethernet Header) = 1494 になっていますので、適切なパケットサイズで相手からパケットが届いていることが分かります。こちらが SYN で投げている TCP のオプションを見ると MSS も 1420 バイトになっており問題なさそうです。というわけで、一応問題解決です。この作業したのは数週間前ですが、今も快適に使えています。
ただ、最初のリンク先にも書いてありますが、これ TCP でしか有効な対策じゃないんですね。例えば UDP だと MTU を通知するすべがないです。しかも、パソコンごとに設定しなければならないですし。
ちなみにちゃんと表示されるページはどうなっていたかというと、例えば Google 。
何もしてないのにパケットサイズが 1280 (Minimum IPv6 MTU) + 14 (Ethernet Header) = 1294 となっています。なるほど。
関連して良い資料を見つけました。こちらも IIJ さん!
なんかうまくまとまらなくて分かりにくくなってしまいましたが、とりあえず IPv6 で何故か通信出来ない、という方は是非パケットサイズを確認してみてください、ということでしたw