【図解】Path MTU Discoveryの仕組み~ルータやWindows/Linuxでの設定確認/変更方法~

Path MTU Discoveryとは

IPv4においては、パケットサイズがNW機器のインタフェースのMTU値を超えた場合、そのNW機器上でパケットを分割して MTU値以下にする"フラグメンテーション"という機能があります(PC等のパケットの送信元が分割するTCPセグメンテーションとは違います)。

しかしフラグメンテーションは効率が悪いです。というのも、ルータでパケットを分割する処理負荷、PC側でパケットを再構築する処理負荷がかかるからです。

上記の詳細はこちらをご参照下さい。

そのため、通信元と通信先の組合せ毎に、フラグメンテーションを必要としない最大のMSS値を把握できる(TCPにおいてはTCPセグメンテーションによる分割を行える)仕組みが考え出されました。 それがPath MTU Discoveryです。このPath MTU DiscoveryはICMPプロトコルをベースに構成されている仕組みであり、これ自体がプロトコルなわけではありません

なお、IPv6においてはこの考えに基づき、フラグメンテーションはしてはならないことになりました。

Path MTU Discoveryの動作

Path MTU Discoveryの基本的な動作としては以下の通りです。

まず、Path MTU DiscoveryをサポートしているOSはソケットAPIを通じて、通信する際にIPパケットにdfビット(don't fragment)を立てます。

データを送るPCは、PCのMSS値に従ってTCPセグメントサイズを決めます。このMSS値はインタフェースのMTU値に応じて適切な設定が入っており、通常はEthernetインタフェース(MTU=1500Byte)なので、MSS=1460となっています。

経路上の全てでPCのMTU値を超えない場合、そのまま通信が行なわれます。

経路上のどこかでこのMTU値を超えてしまう場合、dfビットが立っているため、フラグメントができないので、データが破棄されますが、 それと同時に、データの送信元のPCにICMPのタイプOx03/コードOx04 (Destination Unreachable/Fragmentation needed and Don't Fragment was set)が送られます。

このICMPのタイプOx03/コードOx04には、破棄される原因となったMTU値(Next-Hop MTU)が含まれています。この情報を元に、PCはMSS値を修正し、再度パケットを送ります。このような動作を通信が相手先に到達するまで繰り返します。

ブラックホール問題

Path MTU Discoveryの仕組みにおいて、ICMPが送信元に届かなかった場合、通信はずっと届かなくなってしまう。 これをブラックホール問題と言います。

具体的には、サーバがクライアントにデータを送ろうとしてパケットが破棄された場合を考えます。このとき、サーバは不要な通信を止める目的でICMPを全て止めてしまっていると、この問題が起きます。

そのため、DoS攻撃の心配は出てきますが、ICMPのDestination Unreachableだけは通信が届くようにしておくのがよい場合もあります。

NATポイントでのパケット破棄問題

特殊なケースとして、ソースNATの設定が入ったNW機器のインタフェースにおいてMTUサイズ越えが発生し、ICMPのタイプOx03/コードOx04が送信される場合にも問題が発生します。具体例として以下のケースが考えられます。

  1. クライアント200.200.200.200から50.50.50.50宛にhttp通信を開始する。
  2. NATルータが50.50.50.50を10.1.1.1にNAT変換する。
  3. 10.1.1.1が200.200.200.200に向けて1500Byteのパケットを送出する。
  4. NATルータにおいて10.1.1.1を50.50.50.50にNAT変換し、PPPoEインタフェースへルーティングする。
  5. PPPoEインタフェースにおいてMTU1454を超えるパケットが到着したため、NATルータの内部向けインタフェースからWebサーバへICMP Type3 Code4を送信。その際、NATにより宛先は50.50.50.50から10.1.1.1に変換されるが、ICMPメッセージ内に含まれるIPヘッダの情報はNAT変換されず、50.50.50.50のままになる。
  6. ICMPを受信したWebサーバは、到着したICMPにあるIPヘッダを確認するが、自分の送った内容と異なるので無視する。

この場合、Webサーバではメッセージを受け取っても、パケットを有効なものと見做さないため、MSS値を変えません。そのため、ブラックホール問題と同じで、いつまで経っても通信ができない状態になってしまいます。

don't fragment bitを設定変更する方法

方法は大きく分けて2つあります。

1. Windowsのレジストリを変更する

[Windowsキー + R]⇒『ファイル名を指定して実行する』のボックスで以下を入力しEnter

regedit

⇒レジストリ編集コンソールの以下パスを右クリック

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters

⇒『編集』の 『新規』をクリックし、『DWORD 値』をクリック

⇒入力ボックスに以下を記述し、Enter

EnablePMTUBHDetect

⇒『編集』メニューの『修正』をクリック

⇒『値のデータ』ボックスに "1" を入力し、『OK』をクリック

⇒再起動

2. ルータのPBRで変更する

ルータのPBR(Policy Based Routing)の機能には、ACLのルールに従ってネクストホップを変えるだけでなく、IPヘッダの変更もできます。

フラグメントが必要となる直前のルータで、インタフェースに入ったタイミングでIPヘッダの"df bit"を0に書き換えを行う方法です。

Ciscoの場合は以下の手順になります。

access-list 1 permit any
#
route-map DF-off permit 10
match ip address 1
set ip df 0
#
interface giga 0/1
ip address 10.1.1.1 255.255.255.0
ip policy route-map DF-off

これにより、giga 0/1に入力してきたパケットのdf bitをゼロにできます。

なお、ルータがルーティングするのではなく、ルータ自体がパケットを発生する場合は、パケットが入力してくるインタフェースが無いので、(config-if)# ip policyの代わりに以下のコマンドを使います。

(config)# ip local policy route-map DF-off

Windows/Linux で Path MTU Discovery 自体の設定を無効にする

Windows/Linux ではデフォルトで Path MTU Discovery が有効になっています。無効にしたい場合は以下のように設定します。

1. Windows の場合

[Windowsキー + R]⇒『ファイル名を指定して実行する』のボックスで以下を入力しEnter

regedit

⇒レジストリ編集コンソールの以下パスを右クリック

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters

⇒『編集』の 『新規』をクリックし、『DWORD 値』をクリック

⇒入力ボックスに以下を記述し、Enter

EnablePMTUDiscovery

⇒『値のデータ』ボックスが "0" になっていることを確認する

⇒再起動

2. Linux の場合

root でコマンドで以下のように設定

[root@localhost ~]# sysctl -a | grep pmtu
net.ipv4.ip_forward_use_pmtu = 0
net.ipv4.ip_no_pmtu_disc = 0
net.ipv4.route.min_pmtu = 552
[root@localhost ~]# echo "net.ipv4.ip_no_pmtu_disc = 1" >> /etc/sysctl.conf;grep net.ipv4.ip_no_pmtu_disc /etc/sysctl.conf
[root@localhost ~]# sysctl -p

シェアする

  • このエントリーをはてなブックマークに追加

フォローする