MTU計測ツール+αの話
Linuxにて、pingオプション”-M do”を付加すると、DF(Don't fragment)ビットがIPヘッダにセットされる。これを利用して、MTUを計測するツール(Script)を作成してみた+αの話。
早速Script
Script(ファイル名:calcMtu2)中にコメント記載。
calcMtu2
#!/bin/bash
function exit_func() { # 実行中に中断された時にCallされる関数
echo "Done by ctrl-c, etc."
exit 1
}
trap 'exit_func' 1 2 3 15 # ctrl-cなどのSIGNAL受信時に上記”exit_func”をCall
first_mtu=1420 # 最初にトライするPayloadの初期値
ip="8.8.8.8" # 宛先の初期値
arg1=$1 # 第1引数を格納
arg2=$2 # 第2引数を格納
if [ -n "$arg1" ]; then
first_mtu=$arg1 # 第1引数を最初にチェックするPayload値に設定
# Todo: Error Check # 入力エラーチェック未サポート
fi
if [ -n "$arg2" ]; then
ip=$arg2 # 第2引数を宛先に設定
# Todo: Error Check # 入力エラーチェック未サポート
fi
try_mtu=$first_mtu
ok_mtu=0
while true
do
echo ""
echo "<< Try payload size =" $try_mtu ">>"
ping -s $try_mtu -M do $ip -c 2 # DFビットをセットしてping実行
if [ $? -eq 1 ]; then # ping NG(シェル変数である直前コマンドの実行結果利用)
if [ $((ok_mtu)) -eq 0 ]; then # 最初のトライでNG
echo "### MTU is less than "$((try_mtu+28))". ###" # 最初のトライ値(+28(IPヘッダサイズ+ICMPヘッダサイズ))より小さいMTU値であることを表示
else
echo "### MTU =" $((ok_mtu+28)) "###" # MTU値を表示
fi
break
fi
ok_mtu=$((try_mtu)) # ping OK時にはトライしたPayload値を格納
try_mtu=$((try_mtu+1)) # 次にトライするPayload値(+1)をセット
done
検証
通常
本Scriptの実行状況を下記する。
$ bash calcMtu2 1420 1.1.1.1
<< Try payload size = 1420 >>
PING 1.1.1.1 (1.1.1.1) 1420(1448) bytes of data.
1428 bytes from 1.1.1.1: icmp_seq=1 ttl=57 time=12.7 ms
1428 bytes from 1.1.1.1: icmp_seq=2 ttl=57 time=8.96 ms
....
<< Try payload size = 1426 >>
PING 1.1.1.1 (1.1.1.1) 1426(1454) bytes of data.
1434 bytes from 1.1.1.1: icmp_seq=1 ttl=57 time=6.96 ms
1434 bytes from 1.1.1.1: icmp_seq=2 ttl=57 time=11.4 ms
--- 1.1.1.1 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1002ms
rtt min/avg/max/mdev = 6.957/9.189/11.421/2.232 ms
<< Try payload size = 1427 >>
PING 1.1.1.1 (1.1.1.1) 1427(1455) bytes of data.
ping: sendmsg: Message too long
ping: sendmsg: Message too long
--- 1.1.1.1 ping statistics ---
2 packets transmitted, 0 received, 100% packet loss, time 1001ms
### MTU = 1454 ###
pingのPayloadサイズ1420から開始。1427でエラーとなっている。なので、1454(=1426+28)がMTU値となる。
VPN経由だと
あるVPN経由で同様のことを実施してみる。
$ bash calcMtu2 1420 1.1.1.1
<< Try payload size = 1420 >>
PING 1.1.1.1 (1.1.1.1) 1420(1448) bytes of data.
ping: sendmsg: Message too long
ping: sendmsg: Message too long
--- 1.1.1.1 ping statistics ---
2 packets transmitted, 0 received, 100% packet loss, time 1001ms
### MTU is less than 1448. ###
同じく1420から開始しようとしたが、すぐにエラーとなった。なので、かなり小さい値1320を開始値として実行。
$ bash calcMtu2 1320 1.1.1.1
<< Try payload size = 1346 >>
PING 1.1.1.1 (1.1.1.1) 1346(1374) bytes of data.
1354 bytes from 1.1.1.1: icmp_seq=1 ttl=53 time=15.9 ms
1354 bytes from 1.1.1.1: icmp_seq=2 ttl=53 time=17.5 ms
--- 1.1.1.1 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1002ms
rtt min/avg/max/mdev = 15.885/16.715/17.545/0.830 ms
<< Try payload size = 1347 >>
PING 1.1.1.1 (1.1.1.1) 1347(1375) bytes of data.
--- 1.1.1.1 ping statistics ---
2 packets transmitted, 0 received, 100% packet loss, time 1001ms
### MTU = 1374 ###
MTU値は1374となった。VPNなし時の1454と比べて、トンネリングによるオーバーヘッドが相当存在することがわかる。
エラーも確認
pingのPayloadサイズを大きめに指定して、エラーが表示されることを確認。
$ bash calcMtu2 1450 1.1.1.1
<< Try payload size = 1450 >>
PING 1.1.1.1 (1.1.1.1) 1450(1478) bytes of data.
ping: sendmsg: Message too long
--- 1.1.1.1 ping statistics ---
2 packets transmitted, 0 received, 100% packet loss, time 1005ms
### MTU is less than 1478. ###
+α
DFビットをWiresharkで確認
”-M do”オプションなし時にはDFビットがない。
”-M do”オプションあり時にはDFビットがある。
ネットワークインターフェースのMTUを変更
変更前は1500となっており、まずは、この状態で、Payloadサイズ1400バイトを指定してpingを実行。
$ ip link
...
3: wlp2s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DORMANT group default qlen 1000
link/ether 6c:40:08:xx:yy:zz brd ff:ff:ff:ff:ff:ff
...
$ ping 192.168.10.1 -s 1400 -M do -c 1
PING 192.168.10.1 (192.168.10.1) 1400(1428) bytes of data.
1408 bytes from 192.168.10.1: icmp_seq=1 ttl=64 time=3.16 ms
次に、MTU値を1280に変更し、同じ条件でpingを実行。
$ sudo ip link set wlp2s0 mtu 1280
$ ip link
...
3: wlp2s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1280 qdisc fq_codel state UP mode DORMANT group default qlen 1000
link/ether 6c:40:08:xx:yy:zz brd ff:ff:ff:ff:ff:ff
...
$ ping 192.168.10.1 -s 1400 -M do -c 1
PING 192.168.10.1 (192.168.10.1) 1400(1428) bytes of data.
ping: local error: message too long, mtu=1280
Payloadサイズが大きすぎると、MTU値が表示されて、エラーとなる。
EOF