Pull to refresh
22
0
Вячеслав Слинкин @slinkinone

Агент «Везде успеть»

Send message
  1. Sequence number выставляется tcp стеком на уровне ядра ОС. Два одинаковы сиквенса не могут быть при разном размере полезной нагрузки.

  2. Конечно ждем. В этом нет ничего критичного, так как нагрузка на систему около-нулевая. (За исключением аллоцированных 100-200 байт для потока) При этом у сетевого потока должен быть таймаут на стороне ТСПУ, чтобы избегать memory stagrantion.

  3. Соединение не пересобирается - собирается пакет. А если сказать еще точнее, то сообщение. В данном случае надо понимать что система планирует делать с собранным сообщением. Допустим DPI преимущественно дергает SNI, Host и authority header-ы, TLS сертификаты. В штатном случае, (исключая TLS сертификат), DPI классифицирует поток (сигнатурная классификация) по первым, допустим, 2048 байтам клиентских пакетов. Поэтому, если даже TCP окно выставлено на 10 мегабайт и пришел последний пакет, то DPI может просто игнорировать такой пакет, но когда пойдут пакеты у которых sequence в интервале от 0-2047 (relative) их уже начать буферизировать и анализировать.

  4. Тут уже должен работать анти-фрод. Это достаточно стандартный сценарий для ТСПУ - клиент открывает большое количество сессий за короткий интервал времени и допустим они все превышают среднее по больнице, то DPI может блокировать такого абонента. Также бывает и обратный случай фрода - когда абонент также открывает большое количество сессий, но после 3-5 пакетов сразу ее закрывает. Такое обычно бывает в странах где дорогая мобильная связь и люди создают решения чтобы скачивать файлы до того как ТСПУ успеет классифицировать (и как следствие тарифицировать) такой поток.

Я не спорю с тем, что собирать пакет по байту, да еще в реверсивном порядке, задача не быстрая и будет просадка по производительности)

Просто условно, если 1М сессий и 1к из них балуются сегментированием в 1 байт, то можно это детектировать и для таких потоков заряжать реассемблинг уже с увелеченным буфером. Такое поведение не должно сказаться на общий перфоманс системы, потому что это всего 0,0001% от всего трафика, который будет собираться побайтно. Вот если бы у всех пользователей TCP окно стало в 1 байт - был бы капец!

Не ляжет, а просто не распознает сервис в виду ограничения на количество пакетов для классификации. Пролечивается увеличением размера буфера для вырожденных случаев в виде TCP окна, условно, в интервале 1-8 байт.

Новый поток с реверсивным порядком байт - достаточно простой случай для сборки, потому что TCP handshake был отловлен и известен inital sequence number. А вот для потока, у которого DPI пропустил TCP handshake (допустим, переезд трафика на другой кластер), это уже сделать труднее, потому что тут возникает сразу несколько проблем - это невозможность определить начальный sequence из-за чего буфер нужно не только расширять, но еще и копировать буферизированные данные, т.к. DPI каждый раз получает TCP сегменты в реверсивном порядке, то приходится от начала копировать в конец. Также, если пропущен хотя-бы один байт полезной нагрузки, то определить финальный протокол станет крайне трудно.

Такой сценарий действительно выглядит реальным. Особенно если server_name extension размещен в конце секции extensions.

Буфер не может собираться вечно и будет сброшен. Получится что SNI не был выхвачен из первых N пакетов. Последующие пакеты либо просто будут заофложены как для неизвестного сервиса, либо в уже будут возникать трудности с диссекцией.

Итак столкнулись однажды с тем что при ДДОС-атаке легла ТСПУ

Это вполне реально=) Но складывается впечатление, что это вина не ТСПУ, а системы DDOS защиты. Потому что сам DPI обычно не определяет DDOS. DDOS должен отлавливаться на смежном сервисе, и не допускать флуд пакеты до анализатора.

Верно. Действительно это накладывает дополнительные издержки.

Но стоит учитывать что классификация происходит единожды и затем сетевой поток оффлоадится (offload), то есть, последующие пакеты больше не анализируются, а блокируются и/или шейпятся. Таким образом, достаточно лишь обработать от 1 (first packet classification), до примерно трех пакетов (при адекватной сегментации), чтобы определить сервис и затем освободить память.

От всего объема трафика, процент тех кто использует средства обхода крайне мал. То есть для системы (возьмем для примера один кластер), которая тянет допустим 10М потоков, 1к потоков мелко фрагментированного трафика не является значительным в плане перфоманса - это всего 0,0001% от общей нагрузки.

Было много спецификаций, предлагающих его зашифровать, но мэйнстримом оно не стало.

На мой взгляд, многие шифрованные штуки не вошли в постоянный обиход (IPv6, Encrypted SNI, DNS over TLS), по причине того, что это не выгодно с точки зрения бизнеса. Если убрать сигнатуры по которым можно определять сервис, то мобильные операторы не смогут разделать трафик, предлагать разные тарифы, "качественно" делать балансировку. Интернет принадлежит тем, кто его обслуживает.

Интернет провайдеры и мобильные операторы - это бизнес, который должен во-первых соблюдать законы государства, где он работает, а во-вторых, иметь возможность "гибко завлекать пользователей" и предоставлять конкурентноспособный уровень сервиса. Если убрать маркеры для классификации сервисов, то такой бизнес столкнется с большими трудностями. Есть ощущение что это работает плюс-минус одинаково во всех странах.

Вспомнить про то, что ТСПУ - это всё-таки очень высоконагруженная штука, которая вряд ли будет запоминать, что и когда мы там отправляли в сеть, и, соответственно, если мы просто разобьем наш запрос на два в середине SNI

Конечно будет. Это называется reassembling. После сборки сообщение и выдергивания из него нужных данных для классификации - буфер сборки просто очистится.

А какой у вас интернет провайдер, который не может из двух пакетов SNI собрать?)

Как разбивать? Есть два варианта

Еще есть фрагментация на уровне TLS, но она крайне редко встречается. Также есть фрагментация в DTLS протоколе, которая немного по другому работает. И

Верно. Решения вроде GoodbyeDPI используют corner cases для механизмов классификации. Программы чаще всего работают некорректно на граничных условиях. Например разные регистры для строковых значений, сегментация/фрагментация, порядок отправки, и так далее.

Но такие кейсы быстро всплывают и их фиксят. На них могут долгое время не обращать внимание и не исправлять допустим если процент таких обходов крайне мал по сравнению с общим объемом блокировок, или допустим когда случаи таких обходов не стали предметом широкой огласки.

В плюсах это действительно непросто, найти нужную либу. В идеале конечно, организацию программных библиотек надо воплощать в каком-нибудь пакетном менеджере вроде Conan.

@RoundRobinВ обоих случаях SNI передается в открытом виде. Здесь нет зависимости от транспорта (QUIC или TCP). Шифрованный SNI зависит от версии протокола TLS, который идет поверх QUIC/TCP. ClientHello (QUIC транспорт) можно всегда расшифровать.

Едва-ли фрагментированный SNI повлияет на скорости загрузки. При фрагментации, DPI просто будет собирать фрагменты и в конечном итоге соберет их, поймет что это youtube, и зарежет скорость.

Фрагментация может помочь, если реассемблинг в DPI Engine реализован некорректно. Но в таком случае, другие сервисы, которые запрещены тоже должны пролазить, и тревогу забили бы уже гораздо раньше.

QUIC потенциально может спасти когда допустим вы начали смотреть ютуб с впн, а потом впн отрубился. В протоколе реализован Connection migration mechanism, и при обрыве соединения, QUIC поможет восстановить соединение, без повторной отправки ClientHello и всего цикла инициализации сессии.

Могу предположить, что причина, почему на первых секундах сессии скорость может быть выше чем впоследствии - время на получение политик для абонента. То есть, когда DPI отловил youtube, и понял что сервис не для блокировки, то нужно запросить политики для этого сервиса у PCRF, DPI отправляет запрос и ждет пока придет ответ. И пока ответ не получен, он пропускает пакеты на максимально возможной для абонента скорости. Как только DPI получает ответ от PCRF и видит что скорость нужно урезать до 200 Kb/s, он начинает шейпить трафик и скорость youtube сессии падает.

Вряд ли. Я думаю что здесь несколько проще - просто будут шейпить ютуб трафик исключительно у абонентов интернет провайдеров. А мобильные пока этого делать не будут, или будут детектировать tethering и шейпить ютуб только для этих потоков.

SNI извлекается из TLS, а TLS "есть и в QUIC", потому что QUIC это транспорт для TLS. ClientHello диссектится на первом Initial пакете (ну или на втором, если сообщение фрагментировано на уровне QUIC).

Youtube уже давно работает по QUIC даже с десктопа. Протокол стандартизирован. Последние года полтора, регулярно проверяя исходящий трафик с ноутбука (причем под разными осями), ни разу не сталкивался с тем, чтобы использовался TCP или DTLS. Браузер - chrome.

Кайф! Очень интересная информация - спасибо за статью!

Сделал попытку переехать на мозилу буквально два месяца назад. Через месяц вернулся на хром. Нереально пользоваться после хрома.

Во-первых саму многолетнюю привычку трудно ломать, а тут ещё высыпаются косяки, о которых ты раньше даже не думал.

Например из последеног - бывает что кликаешь по веб элементам (конкретно запомнившийся пример - селф-хостед ютрак) и ничего не происходит и не понятно почему. Перезагружаешь страницу, вроде получается попользоваться какое-то время, потом что-то происходит и страница "отмирает". В хроме без нареканий работает.

Или PIA расширение. Иногда бывало что при включенном PIA и VPN (PIA или само развернутом), интернет страницы по какой-то причине переставали открываться. Опять же, открывая хром с соседнем окне и с теми же настройками всё работает.

Ну и хром побыстрее будет.

Приватность это конечно хорошо, но через день искать почему у тебя что-то отказывает в такой элементарной вещи (с точки зрения пользователя) как открытие страниц, для меня не приемлемо.

Несовсем понимаю вашу аргументы в пользу монорепы. Как разделение проектов по репозиториям влияет на врямя соборки?

Допустим есть продукт A и продукт B. A зависит от библиотеки CC, B также зависит от CC. И при этом A имеет еще одну библиотечную зависимость - DD.

Какой смысл держать A и B в одном репозитории если это разные продукты? Также зачем это делать для библиотеки вместе если они являются разными "сущностями" и подключаются под разные цели?

Когда библиотеки и продукты разделены по репозиториям, это грубо говоря добавляет "предохранитель" не сделать из кода трудно-интегриуемую мешанину.

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

Ещё, на мой взгляд странно, что когда сотрудник приходит условно в отдел по разработке антивируса, а ему надо тянуть гигабайты кода из репы и он сразу получает доступ ко всем остальным проектам.

Согласен что Я и ЛК это компании, которые являются предметом гордости и проф развития для тех специалистов.

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

На самом деле хорошо описано.

В умение писать код я бы добавил навык написания юнит тестов. Во-первых, этот навык позволяет писать "unitable" код, что делает его более масшатабируемым и надежным. А во-вторых, написанные тесты, являются отражением того, на сколько разработчик "осознаёт" написанный код - проверка базовых сценариев, сложных сценариев, сценариев с пограничными условиями, итд.

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

У меня есть сомнения что крупные сети сделают замену поврежденного устройства. Особенно в текущих реалиях, когда за возврат дают по шапке персоналу. А тут еще возврат поврежденного устройства, не просто по причине "не подошло".

Information

Rating
Does not participate
Location
Россия
Date of birth
Registered
Activity

Specialization

Software Developer, Software Architect
Linux
C
C++
Git
Docker
CI/CD
English
OOP