naoki86star

インターネットの片隅でなにかしら書いてみる

ICMP58 type2(Packet too big)

 ICMP58 Type2(code0)というのを目にした。ナンデスカこれってことで調べたら、IPv6は中継装置ではフラグメントしない代わりにこのままじゃ通せないよって通知するために仕様化されているらしい。この仕事していながら次々と色々無知無勉強であると感じる。

 ICMP58 Type2を鑑賞するモデルを作ってみる。まずパケット送受信の手始めにipv6のwebserverを動かしたいので、python3 http.serverでいいかと立ち上げた。0.0.0.0でなく::0にバインドする、ってことを初めてやったら起動しなかった。このQA、アンサー0,4はうまくいかなかった。立ち上がるけど、リクエスト受信時にコケる。6がイイ。*1ほんとに一時的なVMの上なので直接修正になんの抵抗もなし。


 本題・以下のような接続構成
f:id:naoki86star:20191120171225p:plain

  • L3アドレスはIPv6のみ
  • Linux2からLinuxの間には、1500より小さいMTUのルータを挟む。vMXのMTUを1400に設定。その他すべて1500であるのを確認。
  • Linux2/Linux3からLinuxにhttp要求し応答3000byteを返すようにする。(3001バイトになってしまった)
  • LinuxとMTUの小さいルータ(=vMX)の間に、別のルータを挟む。ここにはcumulusを使った*2

root@Linux2:~# curl http://[2001:db8:3::2]:8080/3000byte.html の、hubにおけるtcpdumpの結果

17:29:25.014646 IP6 2001:db8:2::2.43644 > 2001:db8:3::2.8080: Flags [S], seq 3351390758, win 28800, options [mss 1440,sackOK,TS val 585845039 ecr 0,nop,wscale 6], length 0
17:29:25.016678 IP6 2001:db8:3::2.8080 > 2001:db8:2::2.43644: Flags [S.], seq 404693454, ack 3351390759, win 26280, options [mss 1326,sackOK,TS val 1660746096 ecr 585845039,nop,wscale 6], length 0
17:29:25.016705 IP6 2001:db8:2::2.43644 > 2001:db8:3::2.8080: Flags [.], ack 1, win 450, options [nop,nop,TS val 585845042 ecr 1660746096], length 0
17:29:25.016717 IP6 2001:db8:2::2.43644 > 2001:db8:3::2.8080: Flags [P.], seq 1:98, ack 1, win 450, options [nop,nop,TS val 585845042 ecr 1660746096], length 97: HTTP: GET /3000byte.html HTTP/1.1
17:29:25.016720 IP6 2001:db8:3::2.8080 > 2001:db8:2::2.43644: Flags [.], ack 98, win 411, options [nop,nop,TS val 1660746098 ecr 585845042], length 0
17:29:25.020478 IP6 2001:db8:3::2.8080 > 2001:db8:2::2.43644: Flags [P.], seq 1:187, ack 98, win 411, options [nop,nop,TS val 1660746101 ecr 585845042], length 186: HTTP: HTTP/1.0 200 OK
17:29:25.020486 IP6 2001:db8:3::2.8080 > 2001:db8:2::2.43644: Flags [.], seq 187:2815, ack 98, win 411, options [nop,nop,TS val 1660746101 ecr 585845042], length 2628: HTTP
17:29:25.020488 IP6 2001:db8:3::2.8080 > 2001:db8:2::2.43644: Flags [FP.], seq 2815:3188, ack 98, win 411, options [nop,nop,TS val 1660746101 ecr 585845042], length 373: HTTP
17:29:25.020496 IP6 2001:db8:2::2.43644 > 2001:db8:3::2.8080: Flags [.], ack 187, win 467, options [nop,nop,TS val 585845046 ecr 1660746101], length 0
17:29:25.023259 IP6 2001:db8:2::2.43644 > 2001:db8:3::2.8080: Flags [.], ack 3189, win 561, options [nop,nop,TS val 585845046 ecr 1660746101], length 0
17:29:25.042205 IP6 2001:db8:2::2.43644 > 2001:db8:3::2.8080: Flags [F.], seq 98, ack 3189, win 561, options [nop,nop,TS val 585845068 ecr 1660746101], length 0
17:29:25.043915 IP6 2001:db8:3::2.8080 > 2001:db8:2::2.43644: Flags [.], ack 99, win 411, options [nop,nop,TS val 1660746124 ecr 585845068], length 0

む、ICMP58がでてこない。。だけどもcumulusでICMP58 type=2のACCEPTフィルタ書いてみるとカウンタはあがっている

root@cumulus:~# ip6tables -A FORWARD -p icmpv6 --icmpv6-type 2 -j ACCEPT
root@cumulus:~# ip6tables -L -n --line-number -v
Chain INPUT (policy ACCEPT 1 packets, 72 bytes)
num   pkts bytes target     prot opt in     out     source               destination

Chain FORWARD (policy ACCEPT 14 packets, 7176 bytes)
num   pkts bytes target     prot opt in     out     source               destination
1        2  2560 ACCEPT     icmpv6    *      *       ::/0                 ::/0                 ipv6-icmptype 2

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
num   pkts bytes target     prot opt in     out     source               destination


ここで、フィルタをDROPに変えてみる。

root@cumulus:~# ip6tables -F
root@cumulus:~# ip6tables -A FORWARD -p icmpv6 --icmpv6-type 2 -j DROP

するとLinux2からの要求は通らなくなる。今回期待した通りの結果。*3

root@Linux2:~# curl http://[2001:db8:3::2]:8080/3000byte.html の、hubにおけるtcpdumpの結果

16:52:40.707739 IP6 2001:db8:2::2.43634 > 2001:db8:3::2.8080: Flags [S], seq 4258666444, win 28800, options [mss 1440,sackOK,TS val 583640733 ecr 0,nop,wscale 6], length 0
16:52:40.714087 IP6 2001:db8:3::2.8080 > 2001:db8:2::2.43634: Flags [S.], seq 1159925414, ack 4258666445, win 28560, options [mss 1440,sackOK,TS val 1658541789 ecr 583640733,nop,wscale 6], length 0
16:52:40.714097 IP6 2001:db8:2::2.43634 > 2001:db8:3::2.8080: Flags [.], ack 1, win 450, options [nop,nop,TS val 583640735 ecr 1658541789], length 0
16:52:40.714103 IP6 2001:db8:2::2.43634 > 2001:db8:3::2.8080: Flags [P.], seq 1:98, ack 1, win 450, options [nop,nop,TS val 583640735 ecr 1658541789], length 97: HTTP: GET /3000byte.html HTTP/1.1
16:52:40.714107 IP6 2001:db8:3::2.8080 > 2001:db8:2::2.43634: Flags [.], ack 98, win 447, options [nop,nop,TS val 1658541791 ecr 583640735], length 0
16:52:40.714109 IP6 2001:db8:3::2.8080 > 2001:db8:2::2.43634: Flags [P.], seq 1:187, ack 98, win 447, options [nop,nop,TS val 1658541795 ecr 583640735], length 186: HTTP: HTTP/1.0 200 OK
16:52:40.714114 IP6 2001:db8:3::2.8080 > 2001:db8:2::2.43634: Flags [.], seq 187:3043, ack 98, win 447, options [nop,nop,TS val 1658541795 ecr 583640735], length 2856: HTTP
16:52:40.728706 IP6 2001:db8:1::1 > 2001:db8:3::2: ICMP6, packet too big, mtu 1386, length 1240
16:52:40.728709 IP6 2001:db8:3::2.8080 > 2001:db8:2::2.43634: Flags [.], seq 187:1615, ack 98, win 447, options [nop,nop,TS val 1658541809 ecr 583640740], length 1428: HTTP
16:52:40.935563 IP6 2001:db8:3::2.8080 > 2001:db8:2::2.43634: Flags [.], seq 187:1615, ack 98, win 447, options [nop,nop,TS val 1658542017 ecr 583640740], length 1428: HTTP
16:52:40.937059 IP6 2001:db8:1::1 > 2001:db8:3::2: ICMP6, packet too big, mtu 1386, length 1240
16:52:41.371556 IP6 2001:db8:3::2.8080 > 2001:db8:2::2.43634: Flags [.], seq 187:1615, ack 98, win 447, options [nop,nop,TS val 1658542453 ecr 583640740], length 1428: HTTP
16:52:41.373117 IP6 2001:db8:1::1 > 2001:db8:3::2: ICMP6, packet too big, mtu 1386, length 1240
16:52:42.203592 IP6 2001:db8:3::2.8080 > 2001:db8:2::2.43634: Flags [.], seq 187:1615, ack 98, win 447, options [nop,nop,TS val 1658543285 ecr 583640740], length 1428: HTTP
16:52:42.205236 IP6 2001:db8:1::1 > 2001:db8:3::2: ICMP6, packet too big, mtu 1386, length 1240
16:52:43.867505 IP6 2001:db8:3::2.8080 > 2001:db8:2::2.43634: Flags [.], seq 187:1615, ack 98, win 447, options [nop,nop,TS val 1658544949 ecr 583640740], length 1428: HTTP
16:52:43.869273 IP6 2001:db8:1::1 > 2001:db8:3::2: ICMP6, packet too big, mtu 1386, length 1240
16:52:47.355548 IP6 2001:db8:3::2.8080 > 2001:db8:2::2.43634: Flags [.], seq 187:1615, ack 98, win 447, options [nop,nop,TS val 1658548437 ecr 583640740], length 1428: HTTP
16:52:47.357099 IP6 2001:db8:1::1 > 2001:db8:3::2: ICMP6, packet too big, mtu 1386, length 1240
16:52:54.011515 IP6 2001:db8:3::2.8080 > 2001:db8:2::2.43634: Flags [.], seq 187:1615, ack 98, win 447, options [nop,nop,TS val 1658555093 ecr 583640740], length 1428: HTTP
16:52:54.013075 IP6 2001:db8:1::1 > 2001:db8:3::2: ICMP6, packet too big, mtu 1386, length 1240
16:53:07.323644 IP6 2001:db8:3::2.8080 > 2001:db8:2::2.43634: Flags [.], seq 187:1615, ack 98, win 447, options [nop,nop,TS val 1658568405 ecr 583640740], length 1428: HTTP
16:53:07.325538 IP6 2001:db8:1::1 > 2001:db8:3::2: ICMP6, packet too big, mtu 1386, length 1240
16:53:33.691745 IP6 2001:db8:3::2.8080 > 2001:db8:2::2.43634: Flags [.], seq 187:1615, ack 98, win 447, options [nop,nop,TS val 1658594773 ecr 583640740], length 1428: HTTP
16:53:33.693275 IP6 2001:db8:1::1 > 2001:db8:3::2: ICMP6, packet too big, mtu 1386, length 1240
16:53:41.549351 IP6 2001:db8:2::2.43634 > 2001:db8:3::2.8080: Flags [.], ack 187, win 484, options [nop,nop,TS val 583701575 ecr 1658541795,nop,nop,sack 1 {3043:3189}], length 0
16:53:41.551498 IP6 2001:db8:3::2.8080 > 2001:db8:2::2.43634: Flags [.], ack 98, win 447, options [nop,nop,TS val 1658602631 ecr 583640740], length 0


ICMP58 type2を落とすようなルータを通る経路を見つけた人は良からぬことをたくらむ、かもしれない。。

*1:python3.8ならノータッチでOKだそうな。

*2:...お手軽そうなもののなかからなんどなく

*3:インタフェース一度リセットかけてます