MTUとMSSとは ― 違いとパケットが分割される仕組み
MTUは
MTUとMSSとは、1回で送れる大きさの上限
MTU(Maximum Transmission Unit)は、1回で送れるIPパケットの最大の大きさです。MSS(Maximum Segment Size)は、TCPが1つの送信単位(セグメント)に載せるデータの最大の大きさです。
イーサネットのMTUは1500バイトです。そこからIPヘッダとTCPヘッダを引いた1460バイトが、IPv4のTCPのMSSになります。
上限を超えたパケットは、分割されるか捨てられます。PPPoEやVPNの回線で一部のサイトだけ開けない不具合は、この上限の食い違いが原因で起きることがあります。2つの値の関係と分割の仕組み、上限が小さくなる理由と対策を順に説明します。
MTUとMSSの違い:1500と1460の関係
MTUとMSSの違いは、数える範囲です。MTUは、IPヘッダを含めたパケット全体の大きさです。MSSは、IPヘッダとTCPヘッダを除いた、TCPが運ぶデータだけの大きさです。
| 値 | 数える | 受け持つ層 | イーサネットでの |
|---|---|---|---|
| MTU | IPヘッダとデータ | 第2層(イーサネットなど) | 1500バイト |
| MSS | TCPのデータだけ | 第4層のTCP | IPv4は1460、IPv6は1440 |
IPv4のヘッダとTCPのヘッダは、オプションがなければどちらも20バイトです。そのため、MSSはMTUから40バイトを引いた値になります。IPv6ではIPヘッダが40バイトなので、1500から60を引いた1440バイトです。
MTUの1500バイトには、イーサネットのヘッダ14バイトと、末尾にある誤り検出用の欄4バイトは含まれません。これらを足したフレームは、最大1518バイトです。MTUはフレームの大きさではなく、フレームの中に入れられるIPパケットの大きさです。
MSSは3ウェイハンドシェイクのSYNで知らせる
TCPは、接続を始める手順である3ウェイハンドシェイクの最初のパケット(SYN)に、自分が受け取れるMSSを書いて相手に知らせます。MSSを書く欄は、SYNにだけ付けられます(RFC 9293)。相手からMSSが届かなかったときは、IPv4では536バイトとみなす決まりです。
実際に送るデータの大きさは、相手が知らせたMSSと、自分の側のMTUから求めた値の小さい方です。このため、通常のTCPの通信では、パケットがMTUを超えることはほとんどありません。
MTUを超えたとき:フラグメンテーションの仕組み
UDPなどで大きいデータを送ると、IPv4のパケットが途中の区間のMTUを超えることがあります。このとき、送信元か途中のルータが、パケットをいくつかに分けて送ります。この分割がフラグメンテーションで、分けた1つ1つを断片と呼びます。
IPヘッダには分割を禁じるDFビットがあり、これが立っていれば、ルータは分割せずにパケットを捨てます。この動きはカプセル化の記事のMTUの節で説明しています。ここでは、DFビットが立っていないときにパケットがどう分かれるかを説明します。
たとえば、データ部分が4000バイトのIPv4パケットを、MTU 1500の区間に送るとします。1つの断片にはIPヘッダ20バイトが付くので、運べるデータは最大1480バイトです。4000バイトは、1480バイト・1480バイト・1040バイトの3つに分かれます。
| 断片 | 元の | 全長 | オフセット | MF |
|---|---|---|---|---|
| 1つ目 | 0〜1479バイト目 | 1500バイト | 0 | 1 |
| 2つ目 | 1480〜2959バイト目 | 1500バイト | 185 | 1 |
| 3つ目 | 2960〜3999バイト目 | 1060バイト | 370 | 0 |
断片を元に戻すための3つの欄
どの断片にも、元のパケットのIPヘッダがコピーされます。その中の3つの欄が、元に戻すための手がかりになります。
- 識別子:元のパケットごとに付く番号です。同じ番号の断片を1つに集めます
- MF:後ろに続きの断片があることを示す印です。最後の断片だけ0になります
- フラグメントオフセット:その断片のデータが、元のデータの何番目から始まるかを示します
オフセットは、8バイトを1単位として数えます(RFC 791)。2つ目の断片は1480バイト目から始まるので、オフセットは1480 ÷ 8 = 185です。このため、最後以外の断片のデータは、8の倍数の大きさに切ります。
元に戻すのは宛先だけ
断片を1つのパケットに戻すのは、最終的な宛先のホストです。途中のルータは、断片を戻さずにそのまま転送します。断片が1つでも届かないと、宛先は時間切れで集めた断片を捨てます。
捨てたことは、通信の異常を知らせるICMPの時間超過(タイプ11)のコード1で、送信元に伝わることがあります。このコードの意味は、ICMPの記事のタイプの一覧にあります。
分割はできるだけ避ける
分割すると、断片ごとにIPヘッダが付く分のむだが生じます。また、TCPやUDPのポート番号は最初の断片にしか入っていません。RFC 8900によると、このためポート番号で判断するファイアウォールは、2つ目以降の断片を正しく扱えません。
こうした理由から、送信元は分割が起きない大きさで送るようにします。その大きさを調べる仕組みが、次に説明する経路MTU探索です。
経路MTU探索:分割せずに済む大きさを調べる
MTUは、宛先までの区間ごとに違うことがあります。その中でいちばん小さいMTUを送信元が調べる仕組みが、経路MTU探索です。IPv4での流れは次のとおりです。
- 送信元は、DFビットを立ててパケットを送ります
- MTUの小さい区間の手前のルータは、パケットを捨て、ICMPで次の区間のMTUを送信元に知らせます
- 送信元は、知らされたMTUに合わせて小さくして再送します
IPv6では途中のルータがパケットを分割しないので、送信元がこの探索で大きさを合わせます。途中でこのICMPを止めると起きる問題は、ICMPの記事の経路MTU探索の節に図で示しています。
MTUが小さくなる場面:PPPoEとVPNのトンネル
MTUが1500より小さくなるのは、パケットの外側にヘッダが増えるときです。イーサネットのフレームに入る大きさは1500バイトのままなので、増えた分だけIPパケットに使える大きさが減ります。次の図で回線やトンネルの種類を選ぶと、MTUとMSSの値と計算が切り替わります。
- 増える
ヘッダ - ありません。
- MTU
- 1500バイトです。
- MSS
- 1500 − 20 − 20 = 1460バイトです。
- 増える
ヘッダ - PPPoEヘッダ6バイトと、
PPPの 種類を 示す2バイトで、 合わせて 8バイトです。 - MTU
- 1500 − 8 = 1492バイトです。
- MSS
- 1492 − 20 − 20 = 1452バイトです。
- 増える
ヘッダ - 新しい
IPヘッダ20バイトと、 GREヘッダ4バイトで、 合わせて 24バイトです。 - MTU
- 1500 − 24 = 1476バイトです。
- MSS
- 1476 − 20 − 20 = 1436バイトです。
- 増える
ヘッダ - GREの
24バイトに、 IPsecの ESPの ヘッダと 末尾の 欄が 加わります。 ESPで 増える 量は、 暗号の 方式で 変わります。 - MTU
- Ciscoの
資料は、 よく ある 組み合わせに 収まる 値と して 1400バイトを 勧めています。 - MSS
- 1400から
計算すると、 1400 − 20 − 20 = 1360バイトです。
PPPoEでは1492バイト
PPPoEでつなぐと、フレームの中にPPPoEのヘッダ6バイトと、PPPの種類を示す2バイトが入ります。RFC 2516は、このためにPPPのMTUを1492バイト以下にすると定めています。PPPoEの仕組みそのものは、PPPoEとIPoEの記事で説明しています。
GREやIPsecのトンネルでは、さらに小さくなる
トンネルは、元のパケットを新しいIPパケットで包む技術です。GREトンネルでは、ヘッダが24バイト増えるのでMTUは1476バイトになります。
IPsecの暗号化方式ESPは、暗号化した中身の前後にヘッダと末尾の欄を付けます。増える量は、暗号の方式と、長さをそろえるために足す詰め物によって変わります。このため、GREとIPsecを組み合わせる場合、Ciscoの資料はトンネルのMTUを1400バイトにするよう勧めています。
pingでMTUを確かめる
分割を禁じたpingを送ると、経路を通せる大きさを確かめられます。Windowsでは、-f でDFビットを立て、-l で送るデータの大きさを指定します。
ping -f -l 1472 8.8.8.81472バイトは、1500からIPヘッダ20バイトとICMPのヘッダ8バイトを引いた値です。経路のMTUが1500より小さければ、応答の代わりに、分割が必要だという表示が出ます。Linuxでは、同じ確認を次のコマンドで行います。
ping -M do -s 1472 8.8.8.8経路でいちばん小さいMTUがPPPoEの1492バイトなら、1464バイトまでは応答が返ります。1464に28を足した1492が、その経路のMTUです。pingの基本の使い方は、ping・tracerouteの記事にまとめています。
MSSクランプとは:ルータがMSSを書き換える
PPPoEやトンネルの手前のルータは、通過するTCPのSYNに入ったMSSを書き換えることがあります。端末が1460と書いて送っても、ルータがトンネルに収まる値に小さくします。この手法をMSSクランプと呼びます。
MSSクランプを使うと、端末どうしは初めから小さいセグメントで通信するので、トンネルの区間で経路MTU探索のICMPに頼らずに済みます。Ciscoのルータでは、ip tcp adjust-mss という名前の設定です。
RFC 4459によると、この手法はPPPoEで最もよく使われています。ただし、書き換えられるのはTCPのMSSだけなので、MSSを持たないUDPの通信には効きません。
練習問題(全6問)
正解:1460バイト
MSSは、
正解:イーサネットの
PPPoEの
正解:185
1つ目の
正解:断片を
断片を
正解:途中の
MSSクランプでは、
正解:1500から
-l は、
選んでから「採点する」を押すと、解説つきで答え合わせができます。
参考にした資料
- RFC 791 Internet Protocol(識別子・MF・フラグメントオフセット、宛先での再構成)
- RFC 894(イーサネットのMTU 1500)
- RFC 9293 Transmission Control Protocol(MSSオプション、既定の536)
- RFC 2516 PPPoE(PPPoEのMTU 1492)
- RFC 8900 IP Fragmentation Considered Fragile(分割の問題点)
- RFC 4459(トンネルとMTU、MSSクランプ)
- Cisco Resolve IPv4 Fragmentation, MTU, MSS, and PMTUD Issues with GRE and IPsec(トンネルのMTUの設定値)
関連記事
おすすめの本 PR
ネットワークを初めて学ぶ人向けの入門書です。
![『[改訂新版]3分間ネットワーク基礎講座』の表紙](https://m.media-amazon.com/images/P/4774143731.09.MZZZZZZZ.jpg)
