Протокол ICMP: типы диагностических сообщений, утилиты ping и traceroute, Path MTU Discovery.
Почему отсутствие ответа на ping не обязательно означает недоступность узла?
Как утилита traceroute строит трассу маршрута?
Почему ICMP не генерирует ошибку в ответ на ошибку?
Как работает Path MTU Discovery с использованием ICMP?
Какую роль играет ICMP в IPv4?
Что можно определить по выводу traceroute, помимо маршрута до цели?
Протокол ICMP: типы сообщений, ping, traceroute — одна тема в двух курсах
ICMPv6 — расширенная версия ICMP для IPv6, включающая NDP и автоконфигурацию
ICMPv6 в контексте ICND1: NDP, обнаружение соседей и замена ARP
Протокол ICMP (Internet Control Message Protocol) -- это служебный протокол, который работает поверх IP и выполняет диагностические функции. Когда с IP-пакетом что-то идет не так, именно ICMP сообщает отправителю о проблеме.
Вот типичные ситуации, когда ICMP вступает в дело:
У ICMP на самом деле достаточно много сервисных функций. Если посмотреть спецификацию, он умеет очень многое, плюс к нему есть дополнительные расширения для ещё большего объема полезной информации.
Среди часто используемых на практике:
Если вы отправили пакет и за 5 секунд не получили ответа -- значит, что-то не работает. Либо пакеты туда не проходят, либо обратно.
Можно отправлять много пакетов и мерить статистику по ответам:
Формат очень простой. Всё выровнено по границе 4 байт:
| Поле | Размер | Описание |
|---|---|---|
| Type | 1 байт (8 бит) | Тип сообщения |
| Code | 1 байт (8 бит) | Код сообщения |
| Checksum | 2 байта | Контрольная сумма |
| Data | переменный | Зависит от типа/кода |
В каждом сообщении есть два числа -- тип и код. Далее идёт контрольная сумма (checksum), которая нужна, чтобы убедиться, что пакет не побился по дороге.
В заголовке IP тоже есть checksum, но она считается только от самого заголовка. Данные при этом не закрываются. А checksum в ICMP закрывает и данные тоже.
Используется тот же самый механизм Internet Checksum, что и в протоколе IP:
0xFFFFВот некоторые популярные пары тип и код:
| Type | Code | Название | Описание |
|---|---|---|---|
| 8 | 0 | Echo Request | Запрос пинга |
| 0 | 0 | Echo Reply | Ответ на пинг |
| 3 | 0 | Network Unreachable | Нет маршрута в сеть назначения |
| 3 | 1 | Host Unreachable | Узел назначения недоступен |
| 3 | 3 | Port Unreachable | Порт недоступен (для UDP) |
| 3 | 4 | Fragmentation Needed | Нужна фрагментация, но стоит флаг DF |
| 3 | 13 | Administratively Filtered | Пакет заблокирован фильтром |
| 11 | 0 | TTL Expired in Transit | Пакет "протух" по дороге |
Type 3 (Destination Unreachable) -- все сообщения с этим типом означают, что пакет не удалось доставить по какой-либо причине. Там целая пачка кодов: Network Unreachable, Host Unreachable, слишком маленький MTU и т.д.
Host Unreachable (3, 1) -- это когда вы нашли маршрут connected в сеть назначения, но не можете получить канальный адрес соседа. Например, роутер нашёл, что получатель сидит с ним в одной канальной среде, нашёл connected-сеть, нашёл интерфейс. Дальше в эту сеть кричит ARP: "У кого из вас такой IP, скажите свой MAC?" А узел назначения выключен, никто не ответил. Роутер пакет прибивает и отправляет диагностику: "Сеть назначения есть, а вот узла нет".
TTL Expired in Transit (11, 0) -- пакет протух по дороге. С пакетом всё хорошо само по себе, сеть работает нормально, но TTL был выставлен слишком маленький.
Формат данных зависит от типа и кода сообщения. Например, в случае Echo Request/Echo Reply в поле данных будут:
По этим полям отправитель определяет, что ответ пришёл именно на конкретный запрос. Даже если ответы возвращаются не в том порядке, система сможет правильно сопоставить каждый ответ с соответствующим вопросом и корректно посчитать статистику.
Наиболее очевидный способ пощупать ICMP вживую -- это пинг соседа.
Термин ping пришел из словаря людей, работающих с радарами. Вы посылаете эхо-сигнал, он отражается и возвращается к вам -- это и есть пинг. Сама утилита расшифровывается как Packet Internet Groper.
Утилита посылает Echo Request и смотрит, когда на эти запросы приходит Echo Reply в ответ.
Пример: отправлено 4 пакета, получены ответы. По выводу можно сделать заключения о работе сети.
Время прохождения (RTT):
Размер пакетов:
TTL в ответах:
ping -t в Windows (бесконечная отправка) или просто ping в Linux и замерьте статистику хотя бы за минуту -- тогда среднее будет приближено к реальности.Утилита ping позволяет задать:
В Windows возможности ограничены, но в Linux утилита более продвинутая и предоставляет больше инструментов для диагностики.
Если узел пингается -- он живой, сеть позволяет до него добраться. Если ответы не приходят -- это ещё ни о чём не говорит:
Что касается Echo Request и Echo Reply, особых угроз для безопасности тут нет.
Внутри каждого Echo Request можно вложить произвольную полезную нагрузку. По умолчанию это случайные данные (32 байта, обычно буквы от A до Z), но никто не мешает вкладывать туда что-то полезное.
В своё время находились люди, которые написали реализацию транспортного протокола поверх ICMP. Они эксплуатировали тот факт, что некоторые провайдеры позволяют бесплатно отправлять пинги, но берут деньги за нормальный трафик. Путём скрытой инъекции полезных данных в пинги можно было бесплатно обмениваться данными с удалённым узлом.
Подобных скрытых техник много -- через DNS, через ICMP, через другие протоколы. Пропускная способность ICMP-туннеля невелика, но если надо скрыть передачу данных -- возможность имеется.
Всё это давно палится:
Но надо, чтобы кто-то озаботился установкой этих систем безопасности. Провайдеры редко проверяют трафик на аномалии.
Traceroute (tracert в Windows) -- утилита трассировки маршрутов. Вы указываете узел, и программа показывает список маршрутизаторов, через которые проходят пакеты.
Утилита не гарантирует, что трасса будет именно такой. Она лишь пытается построить трассу, похожую на правду.
На каждом шаге делается 3 попытки, и результаты заносятся в таблицу.
*) -- если какой-то один узел закрыл ICMP, вы увидите три звёздочки только для него, а остальные узлы будут нормально отвечатьСовет: в Windows используйте ключ -d (tracert -d), чтобы отключить DNS-резолвинг имён и получить результат быстрее.
Можно трассировать не только ICMP-запросами, но и "боевыми" данными -- UDP-датаграммами. На них тоже будут приходить TTL Expired in Transit.
Важное замечание: ICMP не будет отправлять сообщение об ошибке при доставке другого ICMP-пакета с ошибкой. То есть "сообщение об ошибке о том, что не удалось доставить сообщение об ошибке" -- посылаться не будет. Это сделано, чтобы не плодить лавину ошибок. Но на обычные Echo Request сообщения об ошибках генерируются нормально.
Имеем две Cisco-железки, связанные между собой. Роутер с IP 10.0.0.5 пингует узел 10.0.0.1.
Echo Request:
ABCD ABCD ABCD... (Cisco отправляет только ABCD, а Windows -- полный алфавит ABCDEFGH...)Echo Reply:
При отправке 5 пакетов видим: 5 восклицательных знаков (все успешно), Identifier остаётся тем же, а Sequence Number увеличивается с каждым пакетом.
Если запустить ping без параметров на Cisco, утилита начинает задавать вопросы:
В расширенном режиме можно:
0x01020304 вместо стандартного ABCD)Указываем минимальный размер (1400) и максимальный (1500), шаг 1 байт. Cisco отправляет пинги с нарастающим размером. До 1500 всё проходит (это общий размер IP-пакета, не размер вложения). При 1501 пакет уже не пролезает в канальную среду (обычный Ethernet без Jumbo Frames).
В Wireshark видно: последний успешный пакет содержит 1472 байта вложения (1500 - 20 байт IP-заголовок - 8 байт ICMP-заголовок).
Добавляем в топологию промежуточный маршрутизатор (multilayer switch) и выставляем на его интерфейсе MTU 1400.
Без флага DF: отправляем пакет 1500 байт. Он доходит до свитча, фрагментируется на два пакета, доставляется получателю. Получатель собирает фрагменты обратно (выполняет пересборку) и отправляет один ответ.
С флагом DF: отправляем пакет 1500 байт. Он доходит до свитча, но фрагментировать нельзя (стоит DF). Получаем ответ:
ICMP Destination Unreachable
Type: 3
Code: 4 (Fragmentation Needed and Don't Fragment was Set)
Next-Hop MTU: 1400
Внутри этого ICMP-сообщения содержится MTU интерфейса, через который пакет не смог пролезть. Это позволяет отправителю скорректировать размер пакетов.
Именно так работает Path MTU Discovery:
UDP тоже может отслеживать подобные вещи (стек UDP + IP делает это совместно). Если приложение попыталось отправить слишком крупную датаграмму, ICMP Fragmentation Needed подскажет правильный размер.
Когда приходит сообщение об ошибке, после заголовка ICMP (тип, код, checksum, неиспользуемые 2 байта, MTU) идёт вложение -- начало той датаграммы, которая вызвала проблему, включая IP-заголовок. По этим данным можно понять, какой именно пакет не удалось доставить (IP-адреса, порты TCP/UDP и т.д.).
Пытаемся установить Telnet-сессию (TCP, порт 23) на удалённый узел 192.168.0.1. Сразу получаем Connection Refused -- без таймаутов. В Wireshark видно: SYN-пакет ушёл, в ответ пришёл RST (Reset). TCP сам отработал отказ.
А вот в UDP никакого RST нет. Пробуем TFTP (copy startup-config tftp://192.168.0.1). Датаграмма на UDP-порт 69 уходит, а в ответ приходит:
ICMP Destination Unreachable
Type: 3
Code: 3 (Port Unreachable)
Пакет доставлен до получателя, но на транспортном уровне порт недоступен. Именно ICMP служит диагностическим помощником для UDP -- сообщает, что попытка отправки не удалась.
Настраиваем access-list на роутере, который разрешает трафик только от IP 1.1.1.1 (а всё остальное запрещено неявным deny в конце):
access-list 1 permit 1.1.1.1
interface GigabitEthernet0/0
ip access-group 1 in
Пингуем роутер -- на каждый пинг возвращается сообщение Communication Administratively Filtered:
ICMP Destination Unreachable
Type: 3
Code: 13 (Communication Administratively Filtered)
Это как HTTP 451 -- цензура не пропустила. Echo Request прошёл по проводу и воткнулся в роутер, а роутер сказал: "Эта датаграмма не от разрешённого IP, я её баню".
Если access-list висит на входе (in) и пакет не проходит -- ICMP-сообщение отправляется обратно отправителю.
Если access-list висит на выходе (out) и зарубает, например, Echo Reply -- то сообщение "я убил твой пакет" узнает только сам роутер (он сам пострадавшая сторона). По проводу мы его не увидим. Пакет убит до того, как покинул устройство.
Разница в том, расскажете ли вы отправителю о проблеме или просто молча прибьёте пакет.
Не все реализации Cisco одинаково хорошо дружат с access-list. Бывает, что вроде бы всё настроено правильно, а фильтрация не работает. Особенно это касается коммутируемых интерфейсов -- access-list нужно вешать на интерфейс VLAN, а не на физический порт.