«Отправляй большие загрузки в обход VPN, а маленькие ответы держи на нём» звучит как политика маршрутизации, но ею не является. Маршрутизатор решает по информации, доступной в этот момент: адреса, порты, протокол, метки firewall, идентифицированный поток. Итоговый размер ответа не входит в этот набор, потому что он ещё не пришёл, а к моменту, когда маршрутизатор смог бы измерить байты, он их уже передаёт. Если вы хотите управлять по задаче, решение должно перейти в точку, которая знает задачу, и контрольный список ниже показывает, есть ли такая точка в вашей архитектуре.

Почему маршрутизатор не может измерить ответ

В момент, когда пакету нужен маршрут, маршрутизатор видел не более первых нескольких пакетов потока. Он может сказать, кто с кем говорит, по какому протоколу, с какой меткой и сколько байт прошло к этому моменту. Прошедшие байты описывают прошлое. Размер ответа — свойство ещё не созданного ответа, а для фрагментированных или потоковых ответов он может вообще никогда не быть известен заранее.

Даже собственные метаданные протокола слабее, чем кажутся. HTTP допускает ответы, длина которых не объявляется до тела, а одно действие пользователя может породить множество запросов, совокупная стоимость которых не похожа ни на одно значение заголовка. Считать заголовок размером задачи — ошибка моделирования раньше, чем ошибка маршрутизации.

Проверка 1: есть ли точка решения, способная выбрать путь?

Назовите компонент, который будет делать выбор, а затем назовите, что он знает в момент выбора. Обновлятор, скачивающий из документированного набора хостов, знает свою цель до начала передачи. Служба загрузки, которая смотрит метаданные и затем открывает запрос, знает задачу до появления соединения. Взаимодействующий proxy может применять политику на уровне запроса или кешировать ответ, не притворяясь маршрутизатором.

Если ответ — «шлюз», контрольный список уже провален. Шлюз может классифицировать известные потоки по назначению, метке или сегменту клиента и отправлять их по заданному пути с первого пакета, что часто достаточно для одобренного обновлятора и никогда не достаточно для неизвестного размера ответа.

Проверка 2: что на самом деле говорят метаданные?

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

То, что метаданные приложения могут обосновать, — это решение о задаче: этот рабочий процесс — массовая синхронизация, этот интерактивный, этот — обновление ПО из известного источника. Это политика, написанная в терминах намерения, и она достаточно стабильна для проверки. «Этот ответ будет больше сорока мегабайт» — не такая политика.

Проверка 3: существует ли поток уже?

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

conntrack -L -p tcp --dport 443 | head -5
ip route get 203.0.113.10
ss -tn state established dst 203.0.113.10

Поэтому практическое правило таково: перенос посреди соединения с одного выхода на другой — это новые отношения, а не миграция. Если архитектура требует, чтобы то же соединение продолжалось, решение надо было принять до первого SYN, и никакое добавленное позже правило пакетов не восстановит его чисто.

Проверка 4: действительно ли нужно устранить задержку, а не выход?

Очень многие запросы «отправьте массовый трафик куда-нибудь ещё» на самом деле — жалобы на то, что большая передача делает интерактивную работу медленной. Это задача планирования, и у неё есть ответ из планирования: честная очередь или поддерживаемая политика полосы пропускания на существующем пути не даёт массовому потоку морить голодом сообщение в чате, не перемещая ни то, ни другое.

tc qdisc replace dev eth0 root cake bandwidth 100mbit

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

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

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

Похожие статьи