Дело о загадочном сбросе BGP-сессий из-за неправильного атрибута OTC
Qrator

Дело о загадочном сбросе BGP-сессий из-за неправильного атрибута OTC

Недавно мы столкнулись с интересной проблемой: необъяснимым сбросом BGP-сессий после получения роутерами маршрутов. Мы решили исследовать причины такого поведения — для этого мы проанализировали те сообщения BGP UPDATE, которые вызывали ошибку.

Довольно быстро выяснилось, что у всех этих маршрутов была одна общая деталь: они содержали некорректный атрибут OTC. При этом корень проблемы со сбросом сессий заключался в том, как именно роутеры обрабатывали неправильные маршруты. Поговорим об этом чуть ниже, а сперва обсудим матчасть.

Что такое OTC и как работает этот атрибут

OTC (BGP Only to Customer) — один из двух ключевых элементов системы BGP-ролей, описанной в стандарте RFC9234. Данная система была разработана при участии сотрудников Qrator и предназначена для обнаружения и предотвращения утечек маршрутов.

OTC — это опциональный атрибут сообщения BGP UPDATE, с установленной стандартом длиной 32 бита (4 октета). Его значением является номер автономной системы (ASN), которая выступает в качестве источника для нисходящей части маршрута.

Атрибут OTC работает в связке с BGP Role — механизмом, который задает роли и взаимоотношения автономных систем при установке между ними BGP-сессии (Provider–Customer, Peer–Peer, Customer–Provider).

Вот как это работает в случае входящих маршрутов: при получении маршрута автономная система сравнивает значение атрибута OTC с номером AS, от которой получен маршрут, принимая во внимание свои отношения с этой AS, заданные механизмом BGP Roles. Маршруты, полученные от клиентов или пиров, — за исключением случаев, когда OTC совпадает с ASN этого пира, — отклоняются, таким образом предотвращается утечка маршрута.

Аналогично в случае исходящих маршрутов: если в маршруте, который AS собирается отправить своим пирам или провайдерам (то есть не клиентам), есть установленный атрибут OTC, не совпадающий с номером данной AS, то этот маршрут отклоняется, чтобы предотвратить утечку маршрута.

 

Схема работы BGP Roles и атрибута OTC

Проще говоря, механизм BGP Roles и атрибут OTC позволяют поддерживающим их автономным системам удостоверяться в том, что маршруты распространяются только в правильном направлении и обнаруживать те случаи, когда это не так — то есть утечки маршрутов.

Также стандартом RFC9234 предусмотрено добавление атрибута OTC к легитимным маршрутам, в которых он не установлен — это может делать как отправляющая маршрут транзитная AS (при этом она записывает в качестве значения атрибута свой ASN), так и принимающая маршрут AS (в этом случае она записывает в атрибут ASN той системы, от которой маршрут получен).

Таким образом, данный механизм позволяет предотвращать утечки маршрутов даже в тех случаях, когда оригинальные отправители маршрутов не поддерживают стандарт RFC9234 — благодаря этому обеспечивается своего рода коллективный иммунитет.

Как выглядели сообщения об ошибках при сбросе BGP-сессий

Возвращаясь к исследуемому случаю, проблема заключалась в том, что некоторые AS рассылали сообщения BGP UPDATE с неверно заполненным полем Extended Length внутри атрибута OTC.

 

Некорректный размер атрибута OTC и последующий сброс BGP-сессии

Попробуем разобраться глубже и посмотрим в HEX-дамп одного из сообщений, которые вызвали сброс BGP-сессии. Определим часть дампа, в которой хранится информация об атрибуте с типом 35 (атрибут OTC). В данном случае это "f0fa 0423 0000 4cfe".

 

HEX-дамп одного из сообщений, которые вызвали сброс BGP-сессии

Скорее всего, OTC будет неизвестен большинству маршрутизаторов, так как это относительно новый атрибут, но роутеру в любом случае нужно его каким-то образом распарсить.

Распарсим и мы (не забывая про правило чтения байт в двубайтных словах — сначала правый, потом левый). Для парсинга нужно понять сколько места занимает атрибут в памяти и после этого извлечь содержимое атрибута.

  • 0xfa — часть предыдущего атрибута (Community), ее пропускаем.
  • 0xf0 (0b11110000) — флаги атрибута: Optional=1, Transitive=1, Partial=1, Extended Length=1.
  • 0x23 — 35 тип атрибута, соответствует OTC.
     

Размер атрибута описывается двумя полями:

  1. Флагом атрибута Extended Length (EL). Если значение EL=0, то размер атрибута занимает в памяти 1 байт, а если EL=1, то 2 байта.
  2. Самим значением размера атрибута.
     

Таким образом, если EL=1, то идущие следом два байта будут интерпретированы как размер.

  • 0x04 — 4, предполагаемая длина атрибута. Однако из-за неверного флага Extended Length к ней был добавлен соседний байт 0x00. Поэтому она была прочитана как 0x0400, то есть 1024 байта, что и вызвало проблему.
  • 0x00004cfe — 0xfe4c или 65100, значение атрибута (в данном случае это приватный ASN).
     

Похоже, в реализации относительно свежей функциональности была допущена ошибка.

Почему неправильный атрибут OTC вызывал сброс BGP-сессии

Эти сообщения начали передаваться между роутерами и автономными системами. При этом разные роутеры обрабатывали такие проблемные маршруты по-разному:

  • Вероятно, часть роутеров просто отбрасывала некорректный маршрут и продолжала работать как ни в чем ни бывало (почему «вероятно»: такие кейсы априори невозможно обнаружить, поскольку маршрут не передавался дальше).
  • Некоторые роутеры исправляли проблему, выставляя ожидаемый для данного атрибута флаг вместо оригинального значения.
  • Другие роутеры игнорировали ошибку и просто пересылали дальше маршрут с неправильным атрибутом.
  • В четвертом же случае роутеры при получении маршрута с поломанным атрибутом сбрасывали BGP-сессию.
     

Собственно, этот четвертый случай и был той проблемой, с которой мы столкнулись. Почему так происходило? На самом деле в стандарте RFC9234 в явном виде прописано, что следует делать при получении поломанного атрибута OTC:

«Атрибут OTC считается некорректно сформированным, если его значение длины не равно 4. Сообщение UPDATE с некорректно сформированным атрибутом OTC ДОЛЖНО обрабатываться согласно подходу "treat-as-withdraw" [RFC7606]».

Проще говоря, согласно стандарту при получении маршрутов с некорректным OTC такие маршруты следует отклонять. К сожалению, как мы видим, далеко не все роутеры следовали этому стандарту, вместо отклонения маршрута пересылая некорректное сообщение дальше или даже сбрасывая BGP-сессию.

Последняя ошибка, очевидно, была связана с тем, что роутеры действовали не по процедуре «treat-as-withdraw», прописанной в RFC7606, а по более старой, прописанной в базовой спецификации BGP:

«Согласно базовой спецификации BGP [RFC4271], BGP-узел, получивший сообщение UPDATE с некорректно сформированным атрибутом, обязан сбросить сессию, по которой был получен проблемный атрибут».

Выводы

При внедрении новых технологий и стандартов неизбежно возникают ошибки — конечно же, важно их обнаруживать и устранять в существующем ПО. Кейс с неправильным OTC-атрибутом показал, что даже при наличии четких требований в RFC поведение разных его реализаций может значительно отличаться. Это привело к непредсказуемым сетевым последствиям: от тихого распространения некорректных маршрутов до «необъяснимого» сброса BGP-сессий.

Правильный путь в таких ситуациях — единообразное следование стандартам, в данном случае явно указанному в RFC9234 механизму «treat-as-withdraw» из RFC7606. Чем быстрее вендоры и операторы внедрят корректную поддержку спецификации, тем выше будет устойчивость глобальной маршрутизируемой инфраструктуры.

Напомним, что поддержка BGP-ролей и атрибута OTC уже достаточно давно внедрена разработчиками в демоны маршрутизации FRR (FRRouting) и BIRD. А в сентябре 2025 поддержка RFC9234 появилась в роутерах Juniper, начиная с Junos OS Release 25.2R1.