Кросспостинг, оригинальная статья

Как следует из названия статьи, сегодня мы займёмся некой функцией, которая включена по умолчанию на большинстве платформ Cisco IOS. Преследуемых целей две: встать на грабли, а потом выяснить их модель (производитель уже известен).

Топология лабы представлена ниже:

Все маршрутизаторы на схеме – это Cisco 7200 с прошивкой 15.2(4)M11. R3 выполняет роль конечного устройства (например, сервера), а R4 притворяется интернетом. Фильтр для соединения R1-Switch1 вносит дополнительную задержку для проходящего через него трафика. Актуальные выдержки из настроек маршрутизаторов:

R4(config)# interface Loopback0
R4(config-if)# ip address 4.4.4.4 255.255.255.255
R4(config)# interface FastEthernet1/0
R4(config-if)# ip address 192.168.14.4 255.255.255.0
R4(config)# router eigrp 1
R4(config-router)# network 0.0.0.0
R3(config)# interface FastEthernet0/0
R3(config-if)# ip address 192.168.0.3 255.255.255.0
R3(config)# ip route 0.0.0.0 0.0.0.0 192.168.0.1
R2(config)# interface FastEthernet0/0
R2(config-if)# ip address 192.168.0.2 255.255.255.0
R2(config)# interface FastEthernet0/1
R2(config-if)# ip address 192.168.12.2 255.255.255.0
R2(config)# router eigrp 1
R2(config-router)# network 0.0.0.0
R1(config)# interface FastEthernet0/0
R1(config-if)# ip address 192.168.0.1 255.255.255.0
R1(config)# interface FastEthernet0/1
R1(config-if)# ip address 192.168.12.1 255.255.255.0
R1(config)# interface FastEthernet1/0
R1(config-if)# ip address 192.168.14.1 255.255.255.0
R1(config)# router eigrp 1
R1(config-router)# network 0.0.0.0

В неопределённый момент в прошлом R2 был выключен, и сейчас его вернули снова в строй. Инженер наблюдает большой поток однонаправленного трафика из интернета в сторону R3, причём этот трафик чувствителен к задержкам. Канал между R1 и Switch1 оказывается перегружен, поэтому инженер принимает решение перенаправить проблемный поток через R2. Обратный трафик в сторону интернета незначителен, поэтому R1 остаётся на время единственным шлюзом по умолчанию.

Самый очевидный способ завернуть трафик для R3 в сторону R2 – статический маршрут на R1:

  1. R1 шлёт трафик для R3 через R2 согласно /32 маршруту;

  2. R2 использует локальный /24 маршрут, чтобы передать трафик R3.

Сказано – сделано:

R1(config)# ip route 192.168.0.3 255.255.255.255 192.168.12.2

Однако, как только инженер внёс необходимые изменения, R3 полностью пропал с радаров:

R3#ping 4.4.4.4
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 4.4.4.4, timeout is 2 seconds:
.....
Success rate is 0 percent (0/5)
R4#ping 192.168.0.3 source loopback 0
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 192.168.0.3, timeout is 2 seconds:
Packet sent with a source address of 4.4.4.4 
.....
Success rate is 0 percent (0/5)

Ближайшие 2 маршрутизатора, R1 и R2, также недоступны:

R3#ping 192.168.0.1
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 192.168.0.1, timeout is 2 seconds:
.....
Success rate is 0 percent (0/5)
R3#ping 192.168.0.2
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 192.168.0.2, timeout is 2 seconds:
.....
Success rate is 0 percent (0/5)

Никаких проблем на Switch1 не зафиксировано, CAM-таблица содержит в себе корректную информацию. Запустим traceroute на R3 и R4:

R3#traceroute 4.4.4.4 
Type escape sequence to abort.
Tracing the route to 4.4.4.4
VRF info: (vrf in name/id, vrf out name/id)
  1  *  *  * 
  2  *  *  * 
  3  *  *  * 
  <output trimmed>
R4#traceroute 192.168.0.3 source loopback 0
Type escape sequence to abort.
Tracing the route to 192.168.0.3
VRF info: (vrf in name/id, vrf out name/id)
  1 192.168.14.1 16 msec 12 msec 8 msec
  2 192.168.12.2 20 msec 20 msec 20 msec
  3 192.168.0.1 1388 msec 1300 msec 1296 msec
  4 192.168.12.2 1420 msec 1296 msec 1300 msec
  5 192.168.0.1 2696 msec 2604 msec 2696 msec
  6 192.168.12.2 2612 msec 2704 msec 2696 msec
<output trimmed>

Очевидно, что в сеть прокралась петля – R2 сошёл с ума и шлёт трафик обратно на R1. Каких-либо конкретных симптомов, впрочем, обнаружить не удаётся; IP адрес попадает в connected сеть, R2 выполняет ARP-запрос и обрабатывает последующий ARP-ответ:

R2#sho ip cef 192.168.0.3
192.168.0.3/32
  attached to FastEthernet0/0
R2#sho adjacency 192.168.0.3
Protocol Interface                 Address
IP       FastEthernet0/0           192.168.0.3(7)

Маршрутизация в полном порядке, поэтому займёмся последней милей:

R2#sho ip arp
Protocol  Address          Age (min)  Hardware Addr   Type   Interface
Internet  192.168.0.1            53   ca01.221b.0008  ARPA   FastEthernet0/0
Internet  192.168.0.2             -   ca02.224b.0008  ARPA   FastEthernet0/0
Internet  192.168.0.3            54   ca01.221b.0008  ARPA   FastEthernet0/0
Internet  192.168.12.1           55   ca01.221b.0006  ARPA   FastEthernet0/1
Internet  192.168.12.2            -   ca02.224b.0006  ARPA   FastEthernet0/1

Коллеги, видите ли вы что-то странное? Всё верно, 192.168.0.1 и 192.168.0.3 соответствуют одному и тому же MAC адресу, ca01.221b.0008, который принадлежит R1. Запахло жуками, поэтому попробуем очистить ARP-таблицу в надежде, что проблема исчерпает себя:

R2#clear arp 
R2#sho ip arp
Protocol  Address          Age (min)  Hardware Addr   Type   Interface
Internet  192.168.0.1             0   ca01.221b.0008  ARPA   FastEthernet0/0
Internet  192.168.0.2             -   ca02.224b.0008  ARPA   FastEthernet0/0
Internet  192.168.0.3             0   ca01.221b.0008  ARPA   FastEthernet0/0
Internet  192.168.12.1            0   ca01.221b.0006  ARPA   FastEthernet0/1
Internet  192.168.12.2            -   ca02.224b.0006  ARPA   FastEthernet0/1

Слишком настойчивый баг, не находите? Напоминание для тех, кто ожидал увидеть пустую таблицу, а не нулевой возраст записей: при очистке ARP-таблицы IOS шлёт unicast (да-да) ARP-запросы, чтобы обновить соответствующие записи. Выключение и включение интерфейса на R2, впрочем, даёт лучик надежды:

R4#ping 192.168.0.3 source loopback 0
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 192.168.0.3, timeout is 2 seconds:
Packet sent with a source address of 4.4.4.4 
...!.

Похоже, что изначально трафик ведёт себя так, как и было задумано; однако впоследствии что-то нарушает желаемый порядок вещей, переписывая на R2 ARP-запись для R3 на MAC адрес, принадлежащий R1.

Помните настройку по умолчанию, связанную с ARP, которую обычно рекомендуют отключать? Да, речь о Proxy ARP, который мог предоставить связность для устройств без шлюза по умолчанию или с некорректной настройкой маски подсети:

Since the router knows that the target address (172.16.20.200) is on another subnet and can reach Host D, it replies with its own MAC address to Host A.

Вольный перевод:

Поскольку маршрутизатор знает, что целевой адрес (172.16.20.200) находится в другой подсети, он отвечает собственным MAC адресом на запрос Host A.

Впрочем, это лишь первая половина загадки; вторая относится к тому, как положено обрабатывать ARP-пакеты. Согласно RFC826, сообщения ARP могут быть использованы для двух целей:

  1. обновление существующей ARP-записи;

  2. создание новой ARP-записи на том устройстве, которое послало ARP-запрос.

В нашем случае это означает, что ARP ответ R1 от лица R3 не может создать новую запись в ARP-таблице на R2; к сожалению, это также означает, что R1 может «обновить» соответствующую запись. Получается следующая последовательность событий:

  1. R2 получает пакет, предназначенный для R3, но не находит нужной ARP-записи;

  2. R2 посылает ARP-запрос и получает корректный ARP-ответ от R3, что проявляется в краткосрочной связности для R3;

  3. поскольку ARP-запрос является широковещательным, R1 также получает ARP-запрос от R2 после определённой задержки на канале R1-Switch1;

  4. в таблице маршрутизации на R1 присутствует 192.168.0.3/32, что активирует ARP-ответ в рамках Proxy ARP, т.к. R1 считает, что 192.168.0.3 находится в другой подсети;

  5. ARP-ответ от R1 достигает R2 позже, чем ARP-ответ от R3, благополучно переписывая ARP-запись на R2 для R3, используя MAC адрес R1;

  6. Петля маршрутизации, (не)приятно познакомиться.

Проверим, что дело действительно в Proxy ARP и его отключение решит проблему:

R1(config)#int f0/0
R1(config-if)#no ip proxy-arp
R2#clear arp
R4#ping 192.168.0.3 source loopback 0
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 192.168.0.3, timeout is 2 seconds:
Packet sent with a source address of 4.4.4.4 
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 116/120/124 ms
R2#sho ip arp
Protocol  Address          Age (min)  Hardware Addr   Type   Interface
Internet  192.168.0.1             1   ca01.221b.0008  ARPA   FastEthernet0/0
Internet  192.168.0.2             -   ca02.224b.0008  ARPA   FastEthernet0/0
Internet  192.168.0.3             1   ca03.225a.0008  ARPA   FastEthernet0/0
Internet  192.168.12.1            1   ca01.221b.0006  ARPA   FastEthernet0/1
Internet  192.168.12.2            -   ca02.224b.0006  ARPA   FastEthernet0/1

Наконец, решение в виде статического маршрута заработало. Может показаться, что причина такого некорректного поведения – неисправный канал R1-Switch1 и что в современной сети рассмотренная проблема невозможна. Однако если учесть длину L2 сегмента и задержки, вносимые оборудованием, становится очевидно, что ARP-ответ от Proxy ARP может случайным образом прийти позже корректного ARP-ответа, что приведёт к недоступности соответствующего хоста. Современные сети действительно построены без опоры на асимметричную маршрутизацию на шлюзе по умолчанию. Однако вряд ли даже в таких сетях кто-то сможет дать гарантию, что все возможные сценарии учтены и не придётся впоследствии вносить изменения, противоречащие, хотя бы и на непродолжительное время, общему духу симметричной маршрутизации. Вывод: стоит отключить Proxy ARP, если он не выполняет критических задач.

Статья вдохновлена книгой Routing TCP/IP, Volume 1, 2nd Edition, особенно разделом про отладку статических маршрутов.

Спасибо за рецензию: Анастасии Куралёвой, Максиму Климанову

Комментарии (2)


  1. ufoton
    10.09.2021 23:09

    no ip proxy-arp уже на уровне рефлексов должно быть.

    У меня так


  1. Gutt
    12.09.2021 16:50

    О, мой любимый ARP Proxy! После первого же случая завёл себе простынку с «настоящими дефолтными настройками IP-интерфейса», которая слегка длиннее того, что предлагается разработчиком ОС.