Протокол ICMP: служебные сообщения IP-уровня для диагностики и управления сетью, механизм работы traceroute.
Какое значение поля Protocol в IP-заголовке соответствует ICMP?
Какой тип ICMP-сообщения использует traceroute для определения маршрута?
Что означает ICMP Destination Unreachable с кодом 3 (Port Unreachable)?
Что такое ICMP Fragmentation Needed и когда оно отправляется?
Как traceroute последовательно определяет маршрутизаторы на пути?
Еще один служебный протокол, необходимый для работы IP. В отличие от ARP и DHCP, которые сегодня являются стандартом де-факто, эти два протокола изначально не были частью протокола IP. А ICMP, тот протокол, который мы сейчас будем изучать, как раз изначально являлся частью протокола IP. Это дополнительный служебный протокол, необходимый для корректной работы протокола IP. Он был придуман одновременно с IP. Не то чтобы совсем уж неотъемлемая часть IP, как здесь написано, но это действительно протокол, без которого IP становится очень грустно. Некоторые вещи, которые в IP есть, рассчитаны на то, что у вас есть этот служебный сервисный протокол, который будет решать служебные задачи, необходимые для передачи данных. Сам по себе данные он не передает, но вспомогательные задачи обеспечивает — те, что необходимы для того, чтобы IP мог передавать полезные пользовательские данные.
RFC 792 очень тесно связан с RFC 791, который описывает поведение протокола IP. 791 — это IP, 792 — это ICMP. Они рядышком друг с другом очень хорошо сосуществуют. ICMP вкладывается напрямую в IP, код вложения — единичка, и дальше идет заголовок самого ICMP. Первые 4 байта у каждого ICMP-сообщения предсказуемы, дальше будет зависеть от конкретного сообщения. Они бывают разных типов, и то, что после первых 4 байтов будет идти, зависит уже от конкретного типа сообщения. Типы будут следующие. Однобайтовое значение «тип» — это про что это сообщение глобально. Допустим, тройка в поле «тип» означает, что какие-то данные не удалось передать. Мы отправили какие-то данные, они бежали, бежали по сети, и в какой-то момент не смогли дойти до получателя.
Дальше, для того чтобы специфицировать, почему именно эти данные не дошли до получателя, у нас есть второе поле, которое обозначает код конкретного сообщения. Если мы видим там 3.0, это будет Network Unreachable. На каком-то транзитном маршрутизаторе или даже на самом отправителе — гипотетически тоже такое может быть — не оказалось маршрута до сети назначения. Пришел IP-пакет, у него написан какой-то IP получателя, и нам непонятно, куда его девать — маршрута нет. В этом случае пакет уничтожается, а в сторону отправителя отправляется служебное сообщение Network Unreachable с типом 3 и кодом 0. Может быть такое, что у нас есть маршрут в сети назначения, и там написано, что нужно посылать пакеты куда-то конкретно — либо в какой-то интерфейс напрямую получателю, либо к какому-то транзитному узлу. Но мы пытаемся распознать канальный адрес получателя, и у нас не удается это сделать.
В этом случае, если мы ARP-ом не смогли достучаться напрямую до получателя, либо ARP-ом не смогли достучаться до транзитного узла, на который у нас есть маршрут, мы отправляем сообщение «Я уничтожил твой пакет, потому что следующий хоп недоступен». Мы знаем, кто он должен быть, но мы не можем до него добраться. Это Host Unreachable. Есть еще 3.2 — Protocol Unreachable, когда мы отправляем IP-пакет напрямую получателю, а он говорит: «Я не знаю, что с ним делать, потому что ты указал в качестве вложения в IP что-то совершенно непонятное». Обычно, допустим, единица — это ICMP, шестерка — TCP, 17 — UDP. А ты указал какой-то 219, который не соответствует ничему из того, что мы могли бы обработать. И есть еще Port Unreachable. Это, например, мы отправили UDP-вложение. Мы смогли разобраться с тем, что написано в заголовке IP в поле «протокол». Мы отправили содержимое на обработчик конкретного протокола, а он не смог разобраться, что там внутри.
Например, мы в UDP отправили на какой-то порт, на котором ни одно приложение не слушает. В этом случае будет 3.3 — Port Unreachable. 3.4 — это Packet Too Big. Как раз ситуация, когда мы отправили пакет, и он где-то не пролез в канал, а в пакете мы запретили фрагментацию. Если вдруг вы отправите пакет и у него протухнет TTL по дороге — каждый раз, проходя через транзитный роутер, мы вычитаем либо количество секунд, либо единичку, и рано или поздно получится число, которое равно или меньше нуля. В этом случае пакет опять же уничтожается, и отправляется встречное сообщение «Твой пакет протух по дороге».
Это сообщение с типом 11, кодом 0. Если вы отправляете обычные пинги, то для ICMP Echo Request будет тип 8, код 0, а для ICMP Echo Reply — тип 0, код 0. Обычные пинги — это, наверное, самый распространенный способ использования протокола ICMP в диагностических целях. Смысл утилиты заключается в следующем. Мы отправляем пакеты с указанием: «Как только ты получишь такой пакет, срочно отправь мне встречный пакет». Мы отправляем Echo Request туда, и нам возвращается Echo Reply в обратную сторону. Такие служебные пакеты позволяют проверить, работает ли двусторонняя связность между двумя узлами, и если работает, то с какими характеристиками. В нашем случае мы отправили на узел Google.com, допустим, четыре сообщения «Как только ты это увидишь, срочно ответь», и к нам пришло четыре ответа. Из этих четырех ответов нам понятно, во-первых, от кого они пришли,
во-вторых, понятно, за какое время они прошли туда-сюда по сети, потому что мы замеряем время, прошедшее с момента отправки до момента получения ответа, и здесь показывается количество миллисекунд. В-третьих, в ответах показан TTL, и это тоже информация, из которой мы можем сделать полезные выводы. И в-четвертых, показывается статистика — усредненное значение по времени и по доставке пакетов. В нашем случае мы отправили четыре пакета, получили четыре, потеря у нас ноль, и ноль от четырех — это примерно 0%. Это первая характеристика — количество потерь. И вторая — усредненное время прохождения пакета туда-обратно. Минимум 22, максимум 156 миллисекунд, а среднее — 68. Среднее время прохождения пакетов по сети — это тоже довольно важная характеристика,
она тоже сильно будет влиять. Что здесь можно заметить? Во-первых, если вы видите, что время прохождения пакетов туда-обратно большое, то вы можете сделать вывод, что голосовые соединения с удаленным узлом могут работать не совсем хорошо. Задержка 156 миллисекунд, если она постоянно такая, уже дает немного некомфортное звучание IP-телефонии. Если вы видите значение сильно больше 150, например 500, то голос будет работать совсем плохо. Если вы видите большой разброс во времени прохождения пакетов, то тоже ничего хорошего для голоса это не дает. Среднее — 68 миллисекунд. Сколько здесь отклонения от среднего? Порядка 46 миллисекунд. Сколько здесь отклонения? Порядка 21 миллисекунда. Сколько здесь? Порядка 20 миллисекунд. И сколько здесь? Порядка 90 миллисекунд.
У нас расхождение во времени прохождения пакета по сети довольно большое получается в этом примере. И мы можем сделать вывод, что голосовые соединения при таком джиттере будут, возможно, весьма проблемно работать. Если вы видите, что время прохождения пакетов по сети плюс-минус одинаково до одного и того же узла, это означает, что с некоторой вероятностью голос будет бегать хорошо. Дальше — количество потерь. С ним все понятно. Много потерь — плохо, мало потерь — хорошо, ноль потерь — прекрасно. И что здесь еще можно заметить? TTL, который вы здесь видите — это TTL, который приходит в обратных пакетах. То, как вы отправляете пакеты, и то, как вам отправляются пакеты — это абсолютно разные пакеты между собой, никак не связанные. Поэтому значение TTL, которое приходит к вам — это никоим образом не то значение TTL, которое вы отправляли или которое получил получатель. Когда отправлялись ответы в вашу сторону,
отправитель некоторый TTL поставил. И гипотетически он поставил, скорее всего, какой-то красивый TTL. Ближайшее красивое число, которое близко к 47 — это 64. С некоторой ненулевой вероятностью мы можем сделать вывод, что, скорее всего, это было 64 на момент отправки пакета нам. После того как пакет прошел через цепочку роутеров, он каждый раз терял единичку в поле TTL. Когда он дошел до нас, он стал 47. Поэтому мы можем сделать вывод, что таких роутеров в цепочке было 17 штук. Между нами и Google.com — 17 прыжков между роутерами. Не совсем точное утверждение, но по крайней мере на основании TTL равного 47 мы можем сделать такое предположение. Не точное, но достаточно близкое к реальности. Что еще можно заметить?
Количество байт, которое вы здесь видите — это количество байт, которое отправил вам другой конец. Когда вы отправляете свои пакеты, вы отправляете с определенным размером. Если хотите, можете указать размер ключиком -l в Windows, допустим, 1480 — что вы отправляете пакеты длиной 1480 байт, тогда здесь будет 1480. И ответы, которые вы будете получать, никак не связаны с тем, что вы отправляете. Может быть, отправитель вам проставит столько же, сколько вы отправляли. Может быть, он проставит 32 или 64. Напрямую на это повлиять вы не можете. Пинг — он такой. Если пингается — хорошо. Если не пингается — плохо. Еще одна штука, которая активно использует ICMP — это утилита трассировки. В Windows она называется tracert, в Linux и Cisco она называется traceroute.
Работает она следующим образом. Она отправляет IP-пакеты с некоторым содержимым и указывает для этих пакетов разные TTL, начиная с единички и заканчивая некоторым значением. Она смотрит и выводит на экран, кто прислал вам сообщение TTL Expired in Transit — пакет протух по дороге. Зачем она это делает? С помощью такого механизма вы можете посмотреть, кто конкретно убивает ваши пакеты с разным TTL, и фактически — кто находится в транзите между вами и удаленной сетью. Когда вы указываете traceroute или tracert Google.com, что делает система? Она отправляет сначала три пакета с TTL равным единице. Такие пакеты доходят до ближайшего роутера к вашему узлу. Дальше этот роутер вычитает единичку из поля TTL, обнаруживает там ноль и говорит: «Я уничтожу такой пакет, потому что он протух по дороге». Вы отправляете три пакета, получаете три ответа «Я убил твой пакет, потому что он протух»,
и видите, кто вам эти три ответных пакета прислал. IP-адрес того, кто прислал, здесь показан. Время прохождения ответов — три значения. Это ближайший роутер к вам. Дальше, после того как вы три ответа получили, вы отправляете три пакета с TTL равным двойке. Опять же измеряете время и смотрите, кто присылает сообщение «Я уничтожил твой пакет, потому что он протух по дороге». И так вы делаете до тех пор, пока не получаете что-то отличное от «Я уничтожил твой пакет, потому что он протух по дороге». Например, если вы получаете сообщение Port Unreachable, значит, вы дошли до конечной точки — никто уже не уничтожает пакеты, которые протухают по дороге. Пакеты не протухают, они доходят до конечного узла, и он говорит: «Я не знаю, что ты хочешь от меня». В этом случае трассировка останавливается — вы отправили пакеты с TTL равным 7 и получили результаты. Три времени и указание,
кто прислал вам ответ, отличный от «пакет протух по дороге». Далее. Что здесь еще можно заметить? На эти времена надо смотреть с очень большой осторожностью. Они не означают, что время, которое требуется пакету для того, чтобы дойти до данного участка — это ровно то время, которое отображается. Обратите внимание: допустим, шестой узел отчитался о том, что убил ваш пакет спустя 46 и 38 миллисекунд, а еще один ответ он просто потерял. Тем не менее видно, что среднее значение здесь порядка 40–42 миллисекунд. За 45 миллисекунд он точно вам ответил. Если посмотреть на пятый пункт, видно, что пятый роутер отвечает с большей задержкой: 75, 87 и 98 миллисекунд. Это не означает, что до пятого роутера пакеты доходят с большей задержкой,
чем до шестого. Как вы понимаете, это бессмысленно — не может быть такого, что до пятого за 75 миллисекунд, а до шестого за 46. Это всего лишь означает, что каждый из этих роутеров немного загружен. У него есть другие дела, кроме того, как отвечать на ваши трассировки. Ответы на трассировки он генерирует в самую последнюю очередь, по остаточному принципу. И время, которое требуется на генерацию ответа, может быть достаточно значительным. Может быть такое, что до самого этого роутера пакет дошел за 20 миллисекунд. Дальше, для того чтобы сформировать вам ответ на трассировку, роутер подумал-подумал, и ему 55 миллисекунд потребовалось. Поэтому в итоге вы видите, что результат до вас дошел через 75 миллисекунд. Здесь он еще дольше думал — 67 миллисекунд. А здесь вообще под 80. Время, которое требуется роутеру для генерации ответа,
может быть очень большим и сильно больше, чем время, которое потребовалось пакету для того, чтобы дойти до этого роутера. Поэтому на эти времена ориентироваться нельзя. Они чисто индикативные. Понятное дело, что если вы видите, что у вас были значения 2, 2, 2, 2, 2, 2, 2, и начиная с какой-то ступеньки начинается 100, и все роутеры дальше показывают 101 — здесь были маленькие значения, а дальше большие — вы можете сделать вывод, что в этом канале у вас начинают расти задержки. Но опять же, вывод надо делать очень аккуратно. Это никоим образом не гарантировано. И надо сто раз перепроверить, прежде чем, допустим, звонить провайдеру и говорить, что у него в каком-то канале задержки. Это индикативный инструмент, но никоим образом не доказательство. Вот это два основных механизма, которые можно задействовать в ICMP.
Вы можете использовать их как в Windows и Linux, так и в Cisco. Продолжение следует...