前回の続き
前回、MTUを計算して最適サイズの1374を設定したにもかかわらず自宅のIX2025からVPS側のOpenBSDへpingを飛ばしたが届かない。(応答なし)
shin@yui[7]%ping -M do -s 1346 10.0.0.3
PING 10.0.0.3 (10.0.0.3) 1346(1374) bytes of data.
^C
--- 10.0.0.3 ping statistics ---
4 packets transmitted, 0 received, 100% packet loss, time 3029ms
データサイズを減らしていったら1310byteで届いた。
shin@yui[8]%ping -M do -s 1310 10.0.0.3
PING 10.0.0.3 (10.0.0.3) 1310(1338) bytes of data.
1318 bytes from 10.0.0.3: icmp_seq=1 ttl=255 time=11.3 ms
1318 bytes from 10.0.0.3: icmp_seq=2 ttl=255 time=10.9 ms
1318 bytes from 10.0.0.3: icmp_seq=3 ttl=255 time=11.7 ms
1318 bytes from 10.0.0.3: icmp_seq=4 ttl=255 time=12.7 ms
^C
--- 10.0.0.3 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3004ms
rtt min/avg/max/mdev = 10.964/11.701/12.719/0.665 ms
したがって真のMTUは1338(=1310+28)となると推測した。
パケットはどうなっている?
データサイズガ1311byteの時、パケットはどうなっているのかwiresharekで確認してみたら、そもそも出力されていなかった。
トンネルインターフェースの設定を再度確認してみる。
interface Tunnel0.0
tunnel mode ether-ip ipsec
no ip address
ipsec policy tunnel ipsec-map pre-fragment out
bridge-group 1
no shutdown
IX2025のトンネル設定はpre-fragmentになっているのでIPsecカプセル化の前のデータサイズが出力インターフェースのMTUである1454を越えるとフラグメントされる。
ゆえに1311だと出力インターフェースのMTU(1454)を越えてしまってフラグメント禁止(ping -M do -s 1310 10.0.0.3)だとパケットが出なくなってしまったと考える。
36byteの謎
1374-1338=36byte。この36byteの差は何なのか?
ずっと悩んでいた時、ようやく思い出した。トンネルはIPSecの他にEtheripを使っていることを。
interface Tunnel0.0
tunnel mode ether-ip ipsec
no ip address
ipsec policy tunnel ipsec-map pre-fragment out
bridge-group 1
no shutdown
Etherip分のデータサイズが考慮されていなかった。orz
EtheripはIPヘッダ(20byte)+Etheripヘッダ(2byte)+Ethernetヘッダ(14byte)=36byteとなる。
全パケット構造は以下となる。(データ最大時)
これで計算が合った。バンザイ。
今回は暗号化にAESを使っているため暗号化部分のデータ長は16の倍数である必要がある。
IX2025の出力インターフェースのMTUは1454であるが最大1338byteのデータを送った場合、上記を満たす直近の数値は1440なので出力インターフェイスの実効的なペイロードは1440byteとなる。
データサイズを1310でpingを打った時、wiresharkでパケットを確認してみる。
1440byteになっており計算が合致していることが確認できた。
wiresharkを見るとパケット長は1454byteになっている。
これはEthernetヘッダーの14byte(識別子+MACアドレス)を含んでいるためだ。
ゆえにEthernetフレームのペイロードは1440(=1454-14)byteとなる。
ということでMTU値は1338でファイナルアンサー。
設定
MTUが確定したので各機器について設定をする。
VPS(OpenBSD)側
root#ifconfig tap1 mtu 1338
IX2025側
・OSPF対策
conoha-gateway(config)# interface BVI1
conoha-gateway(config-BVI1)# ip mtu 1338
・MSS設定
前編で述べたようにTunnnel設定でMTUを設定しても反映されないようだ。(1374のままだった)
MSSはMTUから自動設定されるので、このままだと不安なので手動でMSSを設定しておく。
conoha-gateway(config)#interface Tunnel0.0
conoha-gateway(config-Tunnel0.0)# ip tcp adjust-mss 1298
Fortigate50E側
# config system interface
(interface) # edit wan2
(wan2) # set mtu-override enable
(wan2) # set mtu 1338
(wan2) # next
(interface) # end
となる。
確認
データサイズ1311byteでpingを打つと
shin@yui[7]%ping -M do -s 1311 10.0.0.3
PING 10.0.0.3 (10.0.0.3) 1311(1339) bytes of data.
From 10.0.0.2 icmp_seq=1 Frag needed and DF set (mtu = 1338)
ping: local error: Message too long, mtu=1338
ping: local error: Message too long, mtu=1338
ping: local error: Message too long, mtu=1338
^C
--- 10.0.0.3 ping statistics ---
4 packets transmitted, 0 received, +4 errors, 100% packet loss, time 3010ms
今度は応答なしではなくエラーになる。
上記の場合、IPSecカプセル後のデータサイズは1456になる。出力インターフェイスのMTU(1454)を超えてしまいフラグメントが必要になる。したがってフラグメント禁止でpingを打つとエラーになってしまう。
(おまけ)prefragmentについて
本環境ではIX2025側のトンネルインターフェースはprefragmentを指定している。(デフォルトではpostfragmentである。)
prefragmentとはIPsecのカプセル前に出力インターフェースのMTUを超えるサイズのデータを送る時にフラグメントすることを意味する。
逆にpostfragmentではカプセル化後にフラグメントするためトンネルのMTUが1338あっても1311byte以上のpingパケットが疎通する。
これは、IPsecでカプセル化後も物理インターフェイスのMTUである1454byteまではフラグメントされないからである。
IXシリーズにおいてはNATトラバーサルを使う場合にはprefragmentが推奨されている。
postfragmentだとフラグメントされた2番目以降のパケットにはNATトラバーサルのヘッダが付加されない。一般的にNAT/NAPTルータはUDPやTCPのヘッダを参照して
アドレス変換を行っているため、NATトラバーサルのヘッダがつかないフラグメントパケットは正しく変換できない場合がある。
prefragmentだとすべてのパケットにNATトラバーサルのヘッダが付加されるため、NAT/NAPTルータで正しく変換することができる。
YAMAHAのルータはpostfragmentしか行わないようだけどNATトラバーサルがきちんと使える。このへんの仕組みは良くわからない。(知っている人おしえて)
NATトラバーサルは各社で実装の違があるらしいのでその違いかもとは思っている。
参考URI IX機能取説 NAT トラバーサル機能