Трассировка в MPLS L3VPN
Last updated
Last updated
Около года назад у меня была небольшая статейка с каверзными вопросами. Среди них был один очень для нас актуальный.
Пришло время разобрать его получше.
Если вдруг, вы не знали, как работает обычная трассировка, то стыд вам я вкратце расскажу.
Вы отправляете получателю пакеты с постепенно увеличивающимся значением TTL. Обычно это UDP, но может быть и ICMP и даже TCP.
Сначала это 1. Пакет доходит до непосредственно подключенного маршрутизатора, тот уменьшает TTL, видит, что теперь он равен нулю, формирует сообщение «time exceeded in transit» и посылает его вам обратно. Так по адресу отправителя вы знаете первый хоп.
Потом это 2. Пакет доходит до второго маршрутизатора. Происходит то же самое, так вы узнали следующий хоп.
…
Наконец TTL достигает N, узел назначения получает пакет, видит, что это к нему, формирует ответ (в соответствии с протоколом), по которому вы понимаете, что всё, кончено, и концы в консоль.
Кроме того, можно добавить, что на каждой итерации вы посылаете не один, а несколько пакетов (как правило, три).
В чём же особенность трассировки через L3VPN?
Пока пакет коммутируется по меткам значения каких-бы то ни было полей любых заголовков глубже MPLS не имеют никакого значения. В том числе и TTL. Маршрутизаторы ориентируются на TTL в заголовке MPLS.
И вот когда PE получает пакет от CE, есть два варианта:
Скопировать значение TTL из заголовка IP в MPLS (Это режим Uniform).
Записать в поле TTL заголовка MPLS 255 (Это режим Pipe или Short-Pipe).
В первом сценарии вы сможете увидеть каждый маршрутизатор на пути к получателю. Результат трассировки будет таким:
Механика же следующая:
На первом шаге ничего не меняется. TARS_1 отправляет ICMP-запрос с TTL=1. R1 его получает, уменьшает TTL до нуля и отправляет на TARS_1 «time exceeded in transit». Первый хоп (R1) готов.
TARS_1 отправляет ICMP-запрос с TTL=2.
R1 его получает, уменьшает до 1, навешивает сервисную метку, навешивает транспортную метку, записывает в поле TTL значение 1, отправляет пакет с метками на R2.
R2 его получает, уменьшает TTL до 0. Тут бы ему отправить обратно «time exceeded in transit». Но не по Сеньке шапка – нет у него ни сервисной метки для этого VPN, ни маршрута до отправителя – он же всего лишь ничем не примечательный P-маршрутизатор.
Таким образом он формирует новый пакет, содержащий «time exceeded in transit». В этом пакете адрес отправителя принадлежит R2, а адрес получателя – TARS_1.
Далее R2 навешивает на него ту же самую сервисную метку, что была и до этого, затем добавляет транспортную метку в сторону R3 и отправляет его на R3 (опять же можно сказать, что транспортную метку он не добавляет — PHP). То есть можно сказать, что он аккуратно вскрыл MPLS-мешок, выпотрошил IP-пакет, засунул на его место что-то новое и отправил дальше.
Пакет доходит до R3. Тот его раздевает, обнаруживает, что получатель – TARS_1, чья сеть известна где-то там за VPN'ом, за R1. Он упаковывает его в MPLS с сервисной и транспортной метками и шлёт назад.
TARS_1 отправляет ICMP-запрос с TTL=3. Он доходит до R3, который видит значение MPLS TTL, равное в данный момент 1, уменьшает его до 0 и возвращает «time exceeded in transit»
TARS_1 отправляет ICMP-запрос с TTL=4. R3 уменьшает MPLS TTL до 1, снимает метку, копирует значение MPLS TTL в IP TTL. А дальше пакет благополучно доходит до TARS_2, тот отправляет ответ об успешном завершении. Трассировка закончена.
А что, если у меня есть закономерное желание, чтобы клиенты не видели топологию моей сети своими трассировками? Надо запретить, скажете вы. Как отец двухгодовалой дочки, я вам говорю: не нужно запрещать. Можно и нужно поступить хитрее – я просто не буду внутри своей сети уменьшать TTL MPLS до нуля.
Для этого используется второй сценарий — установить TTL MPLS в 255. В этом случае при трассировке с TARS_1 вы увидите следующий путь: R1↔R3↔TARS_2.
TARS_1 отправляет ICMP-запрос с TTL=1. R1 его получает, уменьшает TTL до нуля и отправляет на TARS_1 «time exceeded in transit». Первый хоп (R1) готов.
TARS_1 отправляет ICMP-запрос с TTL=2.
R1 его получает, уменьшает до 1, навешивает сервисную метку, навешивает транспортную метку, записывает в поле TTL значение 255, отправляет пакет с метками на R2.
R2 его получает, уменьшает TTL до 254, меняет транспортную метку (или в данном случае снимает – POP Label) и отправляет на R3.
R3, сняв все метки, видит, что TTL истёк и отправляет «time exceeded in transit» обратно источнику (естественно, упаковывая в сервисную и транспортную метки)
TARS_1 отправляет ICMP-запрос с TTL=3. Он благополучно доходит до TARS_2, тот отправляет успешный ответ. Трассировка закончена.
И сколько бы ни было транзитных P-маршрутизаторов, TTL=3 будет достаточно всегда при трассировке с TARS_1 на TARS_2.
Поведение по умолчанию различается у вендоров. Циска считает, что инженер знает, что делает и чем ему грозит каждое действие, поэтому выбирает первый путь, а, например, Хуавэй предпочитает перестраховаться — лучше сначала запретить, дабы чего не вышло, а потом инженер разрешит при необходимости. Как бы то ни было, режим всегда можно поменять — в нашем случае в режиме глобальной конфигурации нужно для этого дать команду «no mpls ip propagate-ttl».
Замечательный пятидесятитрёхстраничный документ по трассировке на nano.org.
Кстати, для MPLS есть особенные утилиы пинга и трассировки.