MTU/MSS値について
なんかおかしくない?
インターネットの記事を読んでいたら、MTUを表示してくれるサイトがあるというので何の気なしにアクセスしてみたらMTUが1374だと表示された。
「なんかおかしくない?(意訳)」とかブラウザに表示されていた。確かに。自分はルータにフレッツ光接続時に案内されたMTU値である1454を設定しているつもりだった。
再度ルータの設定を確認してみたけど確かに1454に設定されていた。なぜだろう、と考える前に、そもそもMTUについてよく理解していない事に気づき、あたらめて調べてみることにした。
Ethernetフレーム
まずLAN回線であるEthernetについて理解しておく必要があった。ネットワークスペシャリストの資格を取った時に覚えたはずだけどすっかり忘れてた。
Ethernetフレームは最大で1518バイト。それにプリアンブルという8バイトの物理ヘッダがつく。
1518バイトの内訳は、Ethernetヘッダが14バイト(宛先MAC:6、送信元MAC:6、タイプ:2)と4バイトのファイルチェックシーケンスがつき残りがデータ部。
データ部は最大1500バイトまでとなる。この中には上位の階層のヘッダも含まれる。例えばTCPで通信する際は、IPヘッダとTCPヘッダがともに20バイトあるので、実際のデータの最大値は1460バイトとなる。
現実世界ではPPPoEでデータをやり取りすることが多い。この場合はIPヘッダの前にさらにPPPoEヘッダが6バイト、PPPヘッダが2バイト入る。その分取り扱えるデータ量が減り1452バイトとなる。
ちなみに規格によりフレームサイズの最小値も決められており、それは64バイトとなっている。これに満たない場合は空のデータが挿入される。これはコリジョンを不都合なく検知するためらしい。
MTU/MSS
MTUやMSSの説明にPDUという言葉が含まれていることがあるので、先にPDUという言葉が意味する内容を確認する。PDUとはProtocol Data Unitの略でひとまとまりのデータを意味する。
OSIの階層によりPDUの呼称はおおむね決まっていて、EthernetやPPPが所属する第2階層ではフレーム、IPが所属する第3階層ではパケット、TCP/UDPが所属する第4階層ではセグメントと呼ぶ。
MTUは、Maximun Transmission Unitの略で、ネットワークにおいて1度の転送で送信できるデータの最大値のことをいう。(PDUの最大値となる)
MTU値は通信メディアやプロトコルによって違う。Ethernet環境でいえば1500(Ethenetのデータ部最大長)、PPPoE環境なら1492(Ehternetデータ最大長からさらにPPPoEヘッダを差し引いた分)となる。
MSSはMaximum Segment Sizeの略でTCPにおける1セグメントで転送可能なデータ最大サイズを指す。セグメントなので第4階層で考える。
例えば先のTCP通信におけるPPPoEフレームでは、1492のデータ部の中に20バイトのIPヘッダと20バイトのTCPヘッダがある。このデータが第4階層にまで到達した際、使えるデータ領域の最大サイズはIPとTCPヘッダ分をさし引いた1452バイトとなるので、MSSは1452となる。
MTUの制限を超えるとどうなるか
IPv4の世界ではフラグメンテーションと呼ばれる機構により、最大転送サイズを超えたパケットは分割される。これが発生するとデータ送信の効率は落ちる。
IPv6では通過できる経路を探す(最大転送サイズは経路により違うので)が、基本的にはフラグメンテーションを行わない。
フラグメンテーションが起きるとファイアウォールに引っかかってデータが正常に通信できないこともある。
MTUの自動調整
MTUはルータやOSに値を設定できるが、ICMPプロトコルの「Path MTU Discovery」によりMTUが自動決定されることもある。
Path MTU Discoveryプロトコルは経路上の最小MTUを検出して送信元へ送る。送信元はその情報を元にMTUを調整する。これはICMPプロトコルが稼働していないと機能しない。
OS上での確認と修正
MTUはネットワークインターフェース毎に設定されている。
Windowsでそれを確認する場合はコマンドプロンプトから次のコマンドを実行する。
変更する場合は、先のコマンドで表示されたインターフェスインデックスを指定して行う。例えば、インターフェースインデックスが10で、MTUを1444にしたいの場合は次のようにする。
linux(Debian)の場合は次の方法で確認できる。こちらはネットワークインタフェース名を指定して変更を行う。
例えば、インターフェース名enp1s0のmtuを1400にする場合は次のように指定する。
最適値の調べ方
Windowsの場合でもLinux(Debian)の場合でも、Pingにフラグメンテーションを禁止してどのサイズまで送信できるかを確認する。
ただし、それぞれの環境でオプションの指定が違う。Windowsでは、フラグメント禁止オプションが-f、サイズ指定オプションが-l。
...
ping -f -l 1455 www.google.co.jp
...
ping -f -l 1456 www.google.co.jp
...
Linux(Debian)ではフラグメント禁止オプションが-M do、サイズ指定オプションが-s。さらに-cオプションをつけることで試行回数を指定。
...
ping -s 1426 -M do -c 5 www.google.co.jp
...
ping -s 1427 -M do -c 5 www.google.co.jp
...
どちらの場合も、ICMPヘッダとIPヘッダ分を考慮する必要がある。実際にPingが通った最大サイズ+28(ICMPヘッダ8+IPヘッダ20)が最適MTU値となる。
途中でトンネルを通るとさらにMTUは小さくなる、例えばl2tpでは10バイトのヘッダがある。
異常の原因は?
上記の方法で調べてみたらpingでの通信はサイズを1454に固定した状態でgoogleにも、先のMTU測定再度にも接続可能だった。ということはhttpsの転送経路中にトンネリング等が発生しているのではないかと予想される。
参考にさせていただいたサイト