ICMP Redirectというものがあるらしい

目次

ICMP Type5(Redirect)というパケットを初めて知ったのでメモ

きっかけ

半年ほど前、nuroのHGWのバックドアが発見され、ユーザには開放されていなかった特権ユーザが使えるようになった。
参考: https://github.com/meh301/HG8045Q
(現在はファームウェアアップデートによりパスワードが変更されたため、ここに記載されている情報ではログインできない。)

この時、私が使用しているHGWはRIPv2が喋れることがわかったため、ここぞとばかりにRIPv2を有効化し、ほかのルータと経路交換して遊んでいた。その時のネットワーク構成が以下の通り。
ネットワーク図
HGWとL3SW間でRIPv2による経路交換を行っている。

しかし、この構成ではセグメント1のPCのデフォルトルートがHGWに向いているため、セグメント1のPCがセグメント2と通信する際には、図の赤線のようにHGW->L3SWと最適ではない経路を通ってしまう。
(このおかげで、ちゃんとHGWがL3SWから経路を受信していて、ルーティングしてくれていることがわかったので楽しかったわけだけど)

そして、こんな構成でしばらく使っていたところ、セグメント1のPC(Windows Server)のファイアウォールログにICMPのDROPログが出ていることに気が付いた。

2021-03-12 22:08:59 DROP ICMP [HGWのIP] [WinServのIP] - - 250 - - - - 5 1 - RECEIVE

調査

「これはなんだ?何かHGWがおかしなことをしてるのか?」と思い、調べてみたところ、これはICMPv4 Type 5 Code 1というパケットだった。
Type 5 = Redirect
Code 1 = Redirect Datagram for the Host
であるため、要はHGWが「その宛先ならもっと良い経路があるからこっち使いな!」というパケットらしい。

試しに、セグメント1のLinux PCでtcpdumpをしながらセグメント2宛にPingを投げたところ、以下のパケットが見え、確かにセグメント2の端末宛の通信で最適な経路を使うような内容になっていた。

13:01:55.640103 IP (tos 0xc0, ttl 64, id 3344, offset 0, flags [none], proto ICMP (1), length 112)
    _gateway > [セグメント1 PC]: ICMP redirect [セグメント2 PC] to host c3560cg.notr.app, length 92
        IP (tos 0x0, ttl 63, id 50290, offset 0, flags [DF], proto ICMP (1), length 84)
    [セグメント1 PC] > [セグメント2 PC]: ICMP echo request, id 1, seq 2, length 64

また、セグメント1のPCでip r show cacheなどを実行すると、以下のようになっていて、確かに経路が切り替わっていた。

suuei@mon:~$ ip r get [セグメント2 PC]
[セグメント2 PC] via [HGW] dev eth0 src [セグメント1 PC] uid 1000
    cache
suuei@mon:~$ ping [セグメント2 PC]
PING [セグメント2 PC] ([セグメント2 PC]) 56(84) バイトのデータ
64 バイト応答 送信元 [セグメント2 PC]: icmp_seq=1 ttl=255 時間=1.13ミリ秒
64 バイト応答 送信元 [セグメント2 PC]: icmp_seq=2 ttl=255 時間=1.05ミリ秒
送信元 [HGW] icmp_seq=2 ホストのリダイレクト(新しい次ホップ: [c3560cgのIPの逆表記])
64 バイト応答 送信元 [セグメント2 PC]: icmp_seq=3 ttl=255 時間=0.820ミリ秒
^C
--- [セグメント2 PC] ping 統計 ---
送信パケット数 3, 受信パケット数 3, +1 エラー, パケット損失 0%, 時間 2003ミリ秒
rtt 最小/平均/最大/mdev = 0.820/0.998/1.125/0.129ミリ秒
suuei@mon:~$ ip r get [セグメント2 PC]
[セグメント2 PC] via [c3560cg] dev eth0 src [セグメント1 PC] uid 1000
    cache <redirected> expires 296sec
suuei@mon:~$ ip r show cache
[セグメント2 PC] via [c3560cg] dev eth0
    cache <redirected> expires 290sec
suuei@mon:~$

有効時間はかなり短め(恐らく5分)だが、とても面白い。

調査2

しかし、Windows Serverではファイアウォールルールにより、初期設定ではこのパケットをDROPするため、この機能を使用するためにはファイアウォールルールを書く必要があった。
HGWからのICMPv4 リダイレクトを許可するルールを記述したところ、Windows Serverでも確かに経路が切り替わるようになった。

C:\Windows\System32\LogFiles\Firewall>ping -r 8 192.168.101.1 (c3560cgのセグメント2 IP)

192.168.101.1 に ping を送信しています 32 バイトのデータ:
192.168.101.1 からの応答: バイト数 =32 時間 =1ms TTL=255
    ルート: [HGW] ->
           [c3560cg] ->
           [c3560cg]
192.168.101.1 からの応答: バイト数 =32 時間 <1ms TTL=255
    ルート: [c3560cg] ->
           [c3560cg]
192.168.101.1 からの応答: バイト数 =32 時間 =1ms TTL=255
    ルート: [c3560cg] ->
           [c3560cg]
192.168.101.1 からの応答: バイト数 =32 時間 <1ms TTL=255
    ルート: [c3560cg] ->
           [c3560cg]

192.168.101.1 の ping 統計:
    パケット数: 送信 = 4、受信 = 4、損失 = 0 (0% の損失)、
ラウンド トリップの概算時間 (ミリ秒):
    最小 = 0ms、最大 = 1ms、平均 = 0ms

結論

このような最適でない経路を通るようなネットワーク設定を行った場合、機器が対応していれば、ICMPのRedirectにより最適な経路に切り替わる。
この経路は一時的なもので、Linuxの場合は5分で情報が破棄される。
Windows Serverでは初期設定でDROPするようになっているため、使用する場合にはファイアウォールルールの追加が必要。
ICMP Type 5のパケットを観測した際には、注意が必要。

これを受けてやりたいことのメモ

偽装してICMP Type5のパケットを送ると、通信を傍受できる?
偽装してICMP Type5のパケットを送ると、通信を一時的に遮断させられる?
-> 好きなICMPパケットを送れるようなプログラムを書いてみる。。。