Добрый день! Меня зовут Александр Зубков, я работаю в Qrator Labs и сегодня я хочу поговорить о циклах маршрутизации.
Собственно, цикл маршрутизации это такая ситуация в Интернете, когда пакет, потенциально, бесконечно маршрутизируется по кругу. “Потенциально” потому что у нас есть защита от этого в IP-протоколе в форме TTL-поля, но даже при условии этого, если пакет с большим TTL’ем попадает в цикл - он может находится в нём достаточно долго, потому что максимальный TTL равен 225. И также возможны ситуации когда в пути TTL меняется и это может привести к реальным бесконечным циклам. Чтобы обнаружить цикл маршрутизации мы можем воспользоваться вот таким механизмом и если мы получаем на какой-то пакет ICMP ошибку о том что TTL иссяк, то это скорее всего одна из двух ситуаций: либо это длинный путь для которого нам не хватило TTL, либо это цикл маршрутизации в который попал пакет.
В Linux’е значение TTL по умолчанию равно 64, мы можем считать что этого хватает для Интернета и если у нас для довольно большого TTL вернулась ошибка, то мы можем считать что это почти гарантированно цикл, только если кто-то нас не обманывает специально.
Помимо того что таким образом мы можем обнаружить цикл, мы можем еще захотеть посмотреть на него - для этого можно воспользоваться утилитами вроде traceroute и mtr, знаете наверняка такие утилиты для того чтобы смотреть в Интернете красивые картинки.
Например, на ёлочку.
Или вот, ещё есть Звёздные Войны.
Или стихи про плохую лошадь.
К сожалению все остальные вы уже не посмотрите - это картинки из архивов. Плохая лошадь ещё осталась, но плохо работает и приходится ждать, пока стишок появится.
Естественно, можно наблюдать и цикл маршрутизации. В данном случае пакет сначала шёл нормально по цепочке маршрутизаторов, а потом в какой-то момент зациклился между двумя маршрутизаторами, один из которых не отвечает ошибками, а второй отвечает исправно. Видно, что пакет ходит между ними бесконечно. Кстати, данный конкретный пример это то, что сейчас можно увидеть вместо ёлочки показанной ранее. Так что ёлочка ушла, а хоровод остался.
Как можно получить цикл маршрутизации в Интернете? Один из вариантов - в результате работы протоколов динамической маршрутизации. Конечно, в них есть защита от циклов, но пока они сходятся существуют моменты в которые могут возникать циклы, пока состояние маршрутов в таблицах маршрутизаторов не согласовано. На примере BGP в Интернете, который может сходится несколько минут, мы можем довольно часто наблюдать циклы при изменении каких-то анонсов. Но такие циклы они кратковременные и обычно нас сильно не беспокоят.
Кроме этого, протоколы маршрутизации пишутся людьми, софт не идеальный и мы можем наблюдать такие случаи, когда у нас какие-то BGP-сессии залипают и это приводит к залипшим маршрутам, которые остаются в таблицах и никуда не деваются. То есть, таким образом тоже можно получить несогласованное состояние маршрутов и разные проблемы, в том числе циклы.
Также, проблема защиты от циклов в данных протоколах, она обычно делается для конкретного префикса, но если у нас есть пересекающиеся префиксы с разной маской, в результате агрегации, неполных таблиц маршрутизации и каких-то других вещей, таким образом мы тоже можем получить несогласованные маршруты, которые могут в том числе привести к циклам.
Эта конкретная проблема скорее относится ко второму классу циклов, которые я назвал “ошибки конфигурации”. И я считаю, что это наиболее популярный вариант, когда у нас есть какие-то неиспользуемые адреса или NAT-пулы используются, которые не терминируются нигде.
Простейший пример: провайдер маршрутизирует какой-то префикс в клиента, клиент использует только часть этих адресов и у него маршруты есть только на них, а на остальные адреса у него маршрутов нет и, соответственно, он по умолчанию эти маршруты маршрутизирует обратно в провайдера и таким образом возникает цикл.
Подобные циклы уже долговременные и до тех пор пока ошибка не будет устранена они будут приводить к проблемам.
Конкретно такую ошибку можно легко исправить на стороне клиента, если мы все адреса которые получаем от провайдера null-route’им. Таким образом этот маршрут у нас будет служить своеобразным fallback’ом. Причем такое делать лучше всегда, даже если вы используете все эти адреса. К примеру, есть оборудование, которое если у вас физический линк падает и это единственный линк относящийся к VLAN’у, то vlan тоже будет в состоянии down. Таким образом маршрут пропадет и вы получите цикл на этот промежуток времени, пока линк не восстановится. Поэтому лучше такой route добавить, с какой-нибудь большой метрикой в качестве fallback’а.
И на стороне провайдера, также, в некоторых случаях, если вы можете к клиенту применить политику антиспуфинга, например это одноногий (стаб-сеть) клиент, то такое лучше сделать в любом случае. И в данном случае это поможет вам разорвать цикл маршрутизации, потому что пакет который вернется от клиента уже будет с source’ом не из его сети, скорее всего.
Какие проблемы могут быть от циклов маршрутизации?
Самая очевидная проблема - это повышенная загрузка канала. Например, если у нас есть цикл длиной 2 и туда прилетает TTL 200, то он сто раз по этому циклу пройдет и мы получим стократное увеличение трафика на этом цикле. И такой цикл может быть целью атаки на отказ в обслуживании. Или если, например, это цикл между вами и вашим провайдером, то он может посчитать этот трафик и вы просто заплатите за него.
Есть менее очевидные проблемы. Например, циклы маршрутизации в совокупности с другими проблемами могут приводить к амплификации, которая посылает ответы на тот адрес с которого пришел пакет и такие циклы могут быть использованы как средство DDoS-атак на других лиц. И есть еще какие-то экзотические вещи, например в одной статье описывается возможность по циклам маршрутизации определять возможности спуфинга в вашей сети.
Я нашел несколько, как мне показалось, интересных статей по проблематике циклов. Первая статья (https://www.usenix.org/legacy/event/imc05/tech/full_papers/xia/xia_html/imc05-paper-128-final.html) как раз описывает возможность загрузки канала малым трафиком при наличии цикла. Второй материал (https://www.usenix.org/system/files/sec21fall-bock.pdf) не совсем про циклы - товарищи пытались использовать миддлбоксы, это обычно коробки, которые осуществляют какую-то фильтрацию или сбрасывают TCP-соединение, то есть отвечают на проходящие мимо пакеты, для организации отраженных атак. И такие коробки в сочетании с циклами в состоянии давать амплификацию, потому что пакет проходит несколько раз мимо такой коробки и она каждый раз что-то посылает в ответ. И в некоторых случаях они наткнулись в том числе на бесконечные циклы, то есть они описывают, что в одном случае они получали ответный трафик в течение шести дней после того как прекратили от себя посылать трафик, они предположили что пакет просто дропнулся и трафик перестал приходить.
И еще есть статья (https://mkorczynski.com/PAM17Lone.pdf) об обнаружении возможности спуфинга сети в случае наличия циклов. Дальше, довольно интересная статья вышедшая недавно (https://blog.benjojo.co.uk/post/bgp-stuck-routes-tcp-zero-window), в которой описывается механизм как BGP-сессия может залипнуть таким образом, что keep alive проверки не обнаружат этого и таким образом данная сессия может долго просуществовать в залипшем состоянии, с залипшими маршрутами. И в последней статье (https://toonk.io/the-risks-and-dangers-of-amplified-routing-loops/index.html) предлагается использовать совокупность обычной амплификации с циклом, то есть направлять трафик с амплификации в цикл, таким образом достигать кумулятивного эффекта и совсем малым трафиком осуществлять загрузку вашего канала.
Собственно, после этой статьи, комментарии к которой я читал и где был некоторый скепсис насчет того насколько реально использовать с этой целью циклы, я решил сделать этот доклад.
В том числе я вспомнил пример из собственной практики, больше четырех лет назад, с моим домашним провайдером. Я обнаружил цикл в их сети и написал им об этом, привел traceroute где явно видно цикл. В ответ мне, естественно, написали “иди отсюда глупый пользователь, ты ничего не понимаешь, это у нас такой NAT-пул и у тебя внешний адрес не должен работать, а если бы это был цикл маршрутизации, то наш мониторинг его бы заметил”. Ну я предположил, что если у них есть такой мониторинг, то он, наверное, сломан, раз он цикл не заметил - они мне ничего не ответили, я следом написал по контактам из RIPE, на что мне ответили достаточно интересную вещь, мол “техподдержка правильно написала, потому что это не цикл по определению (с их точки зрения), адреса из NAT-пула просто нигде не сконфигурированы, поэтому они отправляются по умолчанию. Это можно исправить, но проблема косметическая и не стоит усилий”.
Это 4 года назад было, цикл всё ещё там - я проверил перед докладом, ребят не сильно беспокоит.
Теория - теорией, я решил проверить на практике действительно ли циклы вызывают проблемы, так как это может быть не всем очевидно. Собрал некоторый сетап из двух свитчей и трёх серверов, между свитчами у меня был цикл. Линк между свитчами 40 гигабит, между серверами и свитчами по 10 гигабит. Один из серверов с nginx’ом, со второго сервера я подавал тестовую нагрузку, а с третьего запускал флуд.
Примерно такими командами тестил - утилитой ab, в сто потоков, 5 минут тестил запросы, и флуд hping’ом запускал с разным размером пакета, с разной скоростью и направлял в сервер напрямую, либо в цикл.
Здесь можно видеть полученный график загрузки каналов. Слева линейный график, справа логарифмическая шкала. Голубенькое это трафик флуда, а зелененькое это график загрузки канала между свитчами. С правой стороны, где я уже начал загружать канал в цикле, можно видеть что синенькое - где-то на два порядка меньше трафик и он вызывает полную загрузку канала в цикле, примерно в сто раз.
Можно посмотреть дальше - в табличке. Если я, к примеру, брал 450 мегабит флуда и направлял его в сервер напрямую, то это, естественно, не оказывало никакого значимого эффекта на работу сервера. А в случае с циклом это приводило к полной загрузке канала между свитчами и я получил замедление в 5 раз, чуть больше. В некотором смысле для меня было некоторым удивлением то, что когда я пытался загрузить цикл маленькими пакетами, то я обнаружил что это не оказывает влияния - там 30 гигабит, но маленькими пакетами это полностью загруженный канал. Скорее всего это связано с тем как в свитче реализована очередь между портами, она скорее всего какая-нибудь честная и наверняка выбирает пакеты по очереди. Так как пакеты в цикле и полезный трафик приходят с разных направлений, то проходит все без проблем.
Тем не менее, несмотря на это, в случае с большими пакетами, может быть заполняется буфер или что-то ещё, проблему удается воспроизвести. И в случае если у вас, к примеру, это будут не коммутаторы, а какие-нибудь честные маршрутизаторы или серверы, то там другие узкие места и вполне возможно что проблемы будут гораздо более существенные.
В Qrator Labs у нас есть проект Radar, где мы наблюдаем за разными проблемами в Интернете и коллеги мне предоставили историческую статистику по количеству наблюдаемых циклов в IPv4 сегменте. Я нанёс на график и видно что тренд нисходящий, что наверное хорошо, многообещающе. Надеюсь они не перемещаются постепенно в IPv6.
Кроме того я решил провести своё собственное исследование. Первый раз я просканировал все адреса в Интернете с помощью четырёх ICMP-проб с разными TTL’ами и когда я получал ошибку TTL exceeded, то я считал что наткнулся на цикл. Таких адресов я обнаружил более 28 миллионов - это больше 1% от всех активных адресов в Интернете.
Причём, это скорее всего нижняя оценка, потому что не все маршрутизаторы отвечают ошибками, также часто попадаешь в лимиты и возможны потери пакетов и так далее. Глядя на полученные результаты было видно, что есть соседние адреса с пробелами и когда я пытался посмотреть эти адреса, есть ли там цикл, то он там был - и он не попал в результат.
1% адресов это уже достаточно много, но если посмотреть на то, в каких автономных системах содержатся циклы, то мы получим ещё более страшную цифру в 25 000 автономных систем, содержащих такие адреса. Это больше трети всех автономных систем в интернете на момент исследования. Причем правило Парето сильно нарушается - двадцать самых крупных автономных систем по циклам, это меньше 0,1%, дают как минимум 17% циклов. Причем там можно встретить самые разные автономные системы, государственные учреждения, институты, хостеры, производители мобильных телефонов. И что самое неприятное с моей точки зрения - это наличие циклов в сетях операторов поставщиков услуг доступности, это операторы CDN и защиты от DDoS-атак.
Причем не только маленькие организации, но и крупные и широко известные компании.
На данном графике можно видеть топ-20 автономных систем с циклами. Видно, что существенными лидерами являются какая-то национальная Интернет сеть Индии, в которой почти 600 тысяч маршрутов с циклами, на втором месте Lumen, причем у Lumen на самом деле несколько автономных систем и из них две умудрились попасть в топ-20. Если их сложить, то в сумме получится даже больше 600 тысяч.
Как я уже упоминал, встречается такое явление, как амплификация. Причем, в моем случае я смотрел только на полученные ошибки (TTL exceeded), то есть это не та же самая ситуация, что описана товарищами с мидлбоксами. Даже только с ошибками встречается амплификация. Я посылал по 4 пробы - а в ответ я получил в среднем больше 4 ответов на один адрес, естественно из тех на которые я получил хоть какой-то ответ. В некоторых случаях у меня было больше ста тысяч ответов на одну пробу. Если посмотреть самый активный маршрутизатор, от которого я получал ответы, то он в ответе за более чем 6% полученных мною ответов, массивная доля. И он такой не один, просто самый активный, в результатах выделяется несколько очень активных маршрутизаторов.
Есть также разные варианты, иногда можно получить несколько ответов с одного адреса на одну пробу, можно получить несколько ответов с разных адресов на одну пробу. Иногда бывает ситуация, когда прилетает несколько ответов с пары адресов, после чего это заканчивается ответом ещё и с третьего адреса. И причем это повторяющийся паттерн, встречаются очень странные ситуации.
Я пытался посчитать еще и уникальные циклы, но с этим есть определенная проблема, потому что их нужно сопоставлять, из-за пропущенных ответов, из-за повторяющихся адресов. Какой-то маршрутизатор может повторяться несколько раз в одном цикле, то есть это не на разных витках цикла, а именно в одном цикле один адрес может повторяться несколько раз, в том числе подряд. Также, на одной и той же позиции цикла несколько маршрутизаторов могут отвечать, в том числе рандомно. Поэтому их трудно сопоставить, я попытался это сделать кое-как и даже если отбросить те циклы, которые мало раз повторяются, то все-равно остаются сотни тысяч циклов.
И если мы посмотрим какие маршрутизаторы отвечают, то более полумиллиона маршрутизаторов в этих циклах участвует, из 20 000 автономных систем.
Что касается характеристик циклов, то длина циклов которые я нашел - от одного до 34 хопов. И больше половины этих циклов составляют циклы длиной 2 хопа. По распределённости/распространённости циклов - можно найти циклы величиной до 7 автономных систем, или до 8 стран, естественно с поправкой на геолокацию, но примерно можно оценить. Если смотреть по времени, то самый длинный цикл который я видел занимал до 18 секунд, причем они были из одного хопа. Циклы из двух хопов - до 8 секунд. Такие циклы даже mtr’ом сложно посмотреть, потому что он больше 10 секунд не принимает ответы и не показывает - можно увидеть только первый виток цикла. Мне пришлось пользоваться tcpdump'ом, то есть я реально посылал ICMP-пробы с увеличивающимся TTL и с каждым увеличивающимся TTL я видел, что ответ начинает приходить на 18 секунд дольше. Где там блуждают пакеты все это время я даже не знаю.
Естественно, кроме этого было много трансконтинентальных циклов, с понятными временами вроде полсекунды, 300 миллисекунд.
Здесь я отобразил статистику по странам на карте мира и топ-10 стран. США абсолютный лидер, там содержится больше 6 миллионов циклов, у остальных уже существенно меньше. Из региона ENOG в десятку попала только РФ.
На этом слайде статистика по ENOG-региону, топ-10 стран. Россия естественно первая, дальше Украина с существенным отрывом, то же самое с Казахстаном, остальные уже идут группой.
Я еще посмотрел статистику по автономным системам - по операторам поискал у кого больше всех циклов содержится, после четырех мне надоело листать - там уже существенно меньше, но топ рейтинга выглядит вот так: Ростелеком, Киевстар, Kcell и Транстелеком. Это только ENOG-регион.
Далее, я хотел бы показать вам несколько обнаруженных мною вещей, как мне кажется, самых странных. Вот, например, ситуация о которой я говорил - я получаю ответы от двух роутеров, ошибки, и в конце завершается одной или несколькими ошибками от третьего роутера. Причем суммарно, в данном случае, я получаю порядка 500 ответов, в зависимости, несколько варьируется, в одном случае я получил больше 500. То есть тут тоже есть какая-то амплификация, и непонятно как оно там устроено внутри.
Или, например, в некоторых случаях я получал на один пинг ответ от 37 разных адресов. Может быть это один маршрутизатор, может быть разные. Это максимальная вариативность ответов, которые я получал.
Есть еще вот такие интересные циклы - состоит из 17 хопов, но 15 отсутствуют, просто не отвечают. Только два хопа отвечают.
Самое максимальное сколько я видел - это когда не отвечают 16 хопов в цикле из 33.
Это один из самых больших циклов, из 34 хопов, который я видел. И что интересно конкретно в этом цикле - все эти хопы находятся, судя по названиям, в сети одного оператора.
Еще встречаются всякие интересные вещи. Вот, например, похоже на то что принципы маршрутизации нарушаются в данном цикле - пакет проходит как будто бы туда и обратно по цепочке маршрутизаторов. Но это еще не самое странное.
Самый странный цикл, который мне удалось обнаружить, выглядит вот так. Цикл длины 14, предположительно задействованы 7 маршрутизаторов (7 адресов). И как минимум из трех автономных систем вот по такой странной траектории ходит этот цикл. Я даже не знаю что это, мне кажется случайно такое нельзя сделать, единственная идея которая мне пришла в голову, это что кто-то взял в рабство сетевого администратора и он тайное послание оставил, чтобы его нашли.
Если вас это всё взволновало и вы занервничали, решили проверить нет ли в вашей сети циклов - вы можете просто зарегистрироваться у нас в Радаре и не искать циклы самостоятельно. По своей автономной системе вы получите информацию не только по циклам, но и по амплификаторам, BGP-инцидентам и другим вещам.
Спасибо за внимание!
Видео презентации доступно по ссылке.