TCP поверх TCP – не такая уж плохая идея! Основные компоненты туннеля.

Процесс, в ходе которого создается защищенное логическое соединение между двумя конечными точками посредством инкапсуляции различных протоколов. Туннелирование представляет собой метод построения сетей, при котором один сетевой протокол инкапсулируется в другой. От обычных многоуровневых сетевых моделей (таких как OSI или TCP/IP) туннелирование отличается тем, что инкапсулируемый протокол относится к тому же или более низкому уровню, чем используемый в качестве тоннеля.

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

Типы протоколов

В процессе инкапсуляции (туннелирования) принимают участие следующие типы протоколов:

  1. транспортируемый протокол;
  2. несущий протокол;
  3. протокол инкапсуляции.

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

Согласование транспортных протоколов

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

Обычно туннелирование приводит к более простым и быстрым решениям по сравнению с трансляцией, так как решает более частную задачу, не обеспечивая взаимодействия с узлами транзитной сети.

Основные компоненты туннеля

Основными компонентами туннеля являются:

  • инициатор туннеля;
  • маршрутизируемая сеть;
  • туннельный коммутатор;
  • один или несколько туннельных терминаторов.

Инициатор туннеля встраивает (инкапсулирует) пакеты в новый пакет, содержащий наряду с исходными данными новый заголовок с информацией об отправителе и получателе. Несмотря на то, что все передаваемые по туннелю пакеты являются пакетами IP, инкапсулируемые пакеты могут принадлежать к протоколу любого типа, включая пакеты немаршрутизируемых протоколов. Маршрут между инициатором и терминатором туннеля определяет обычная маршрутизируемая сеть , которая может быть и сетью, отличной от Internet . Терминатор туннеля выполняет процесс, который является обратным инкапсуляции - он удаляет новые заголовки и направляет каждый исходный пакет в локальный стек протоколов или адресату в локальной сети. Инкапсуляция сама по себе никак не влияет на защищенность пакетов сообщений, передаваемых по туннелю VPN . Но инкапсуляция даёт возможность полной криптографической защиты инкапсулируемых пакетов. Конфиденциальность инкапсулируемых пакетов обеспечивается путем их криптографического закрытия, т. е. зашифровывания, а целостность и подлинность - путем формирования цифровой подписи . Так как существует множество методов криптозащиты данных, необходимо чтобы инициатор и терминатор туннеля использовали одни и те же методы и могли согласовывать друг с другом эту информацию. Более того, для возможности расшифровывания данных и проверки цифровой подписи при приеме инициатор и терминатор туннеля должны поддерживать функции безопасного обмена ключами. Чтобы туннели VPN создавались только между уполномоченными пользователями, конечные стороны взаимодействия требуется аутентифицировать.

Ссылки

  • Стратегии межсетевого взаимодействия: инкапсуляция (туннелирование) протоколов

Wikimedia Foundation . 2010 .

Смотреть что такое "Туннелирование (компьютерные сети)" в других словарях:

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

    Анонимные сети компьютерные сети, созданные для достижения анонимности в Интернете и работающие поверх глобальной сети. Специфика таких сетей заключается в том, что разработчики вынуждены идти на компромисс между степенью защиты и лёгкостью … Википедия

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

Рис. 1


Туннельные линки являются poin-to-point линками. Туннелирование состоит из следующих трех компонентов:
  • Протокол-"пассажир", который инкапсулируется в туннель, например AppleTalk, CLNS, IP, and IPX.
  • Протокол носитель - протокол, который выполняет инкапсуляцию, например GRE, IP-in-IP, L2TP, MPLS, STUN, и DLSw+.
  • Транспортный протокол, - протокол, используемый для переноса инкапсулированного протокола. Основной транспортный протокол - это IP.
Рассмотри для примера соединение двух сетей AppleTalk через IP-опорную сеть.


Рис 2. Обход ограничений роутингового протокола.


Большой траффик, создаваемый широковещательными анонсами роутингового протокола RTMP может существенно ухудшить работу опорной сети. Проблема может быть решена туннелированием AppleTalk через IP. Туннелирование инкапсулирует пакеты AppleTalk внутри IP-пакета, который пересылается по опорной сети непосредственно в точку назначения. Роутер в точке назначения "вынимает" пакет AppleTalk из капсулы и передает его в сеть AppleTalk обычным образом. Поскольку пакеты AppleTalk отправляются непосредственно в точку назначения, отсутствует расход полосы пропускания сети на широковещательные анонсы протокола AppleTalk.

Ограничения в реализации туннелирования

Нижеследующее нужно иметь в виду при планировании туннелей:
  • В ранних версиях IOS, инкапсуляция и декапсуляция пакетов в конечных точках туннеля производилось процессором (process-switching). Однако, начиная с версии 11.1 реализована обработка (fast-switching) для туннелей GRE. В сегодняшних версиях IOS используется CEF-коммутация для IPv6 и других туннелирующих протоколов.
  • Важно разрешать туннельному протоколу проходить через фаревол и через листы доступа
  • Роутинговые протоколы, в метрике которых содержится только число промежуточных узлов будут, как правило, предпочитать туннельные линки, так как с точки зрения такого протокола они выглядят существенно короче реальных. Это может оказаться нежелательным, поскольку туннель выглядит как один хоп и может проходить по более медленному каналу связи, чем по линку с промежуточными узлами.


Рис. 3

В топологии, показанной на рис.3 пакеты от Host1 до Host2 пойдут по пути w,q,z, вместо пути w,x,y,z. Потому что первый путь покажется короче.

Существенно худшие проблемы возникают, если информация о роутинге транспортной сети смешивается с информацией о роутинге туннелируемой сети. В этом случае "лучший" путь к точке окончания туннеля (для транспортного протокола) может оказаться через сам туннель! Это называется рекурсивным роутингом (recursive route) и в этом случае роутер временно выключает туннель. Чтобы избежать рекурсивного роутинга, принимайте меры к разделению роутинговой информации "пассажирской" и "транспортной" сетей:

  1. Используйте другой номер AS или маркер
  2. Используйте другой протокол роутинга
  3. Используйте явное указание статических путей (следите, чтобы не получалось петель роутинга)
Если роутер выдает нижеприведенное сообщение, то, скорее всего, имел место рекурсивный роутинг
%TUN-RECURDOWN Interface Tunnel 0 temporarily disabled due to recursive routing

Преимущества туннелирования

В следующих ситуациях полезно применения туннелей:
  • Для поддержки многопротокольных локальных сетей с помощью однопротокольной опорной сети
  • Для обхода ограничений ряда роутинговых протоколов (например: по числу промежуточных станций на пути пакета). См. Рис. 2
  • Для соединения разнесенных подсетей
  • Для организации виртуальных приватных сетей (VPN) поверх глобальных сетей (WAN)

Процесс конфигурирования GRE-туннеля

Обязательные действия:
  • Указание точки начала туннеля
  • Указание точки приемника туннеля
Необязательные действия:
  • Задание режима туннелирования
  • Задание режима контрольного суммирования
  • Задание ключа идентификации туннеля
  • Включение отбрасывания "заблудившихся" пакетов
Задание туннельного интерфейса
interface tunnel number
Указание точки начала туннеля
tunnel source {ip-address | type number}
Указание точки приемника туннеля
tunnel destination {hostname | ip-address}
Пример конфигурации роутеров изображенных на Рис 3

Конфигурация роутера A

interface Tunnel0
ip address 192.168.1.1 255.255.255.252
tunnel mode gre
tunnel source FastEthernet0/0
tunnel destination 172.16.15.34
!
interface FastEthernet0/0
ip address 10.0.145.13 255.255.255.0

Конфигурация роутера D

interface Tunnel0
ip address 192.168.1.2 255.255.255.252
tunnel mode gre
tunnel source FastEthernet1/0
tunnel destination 10.0.145.13
!
interface FastEthernet1/0
ip address 172.16.15.34 255.255.255.0 Режим туннелирования GRE всегда включен по умолчанию, поэтому команду tunnel mode gre можно опустить.

Я ищу программное обеспечение для туннелирования RDP или другого двоичного TCP-трафика через туннель HTTPS. Поскольку многие клиенты имеют только HTTP/S, разрешены (только порт 80 и 443 открыты в брандмауэре).

Но есть необходимость пересылать RDP (и другие протоколы) с машин в DMZ на клиентов.

Есть ли какое-либо программное обеспечение с открытым исходным кодом или корпоративное программное обеспечение для этой проблемы?

Плохие решения

Если бы было возможно, что клиент туннеля не будет выделенным сервером, а java-апптом флэш-памяти, запущенным в браузере клиентов, он будет соответствовать 100% моим потребностям.

3 ответов

Существует огромное количество проектов, которые туннелируют TCP через HTTP (S). Вам нужно будет немного поработать, чтобы выбрать тот, который наилучшим образом соответствует вашим потребностям (и, вероятно, немного измените его).

    Если вы находитесь в мире Windows, я настоятельно рекомендую взглянуть на службу SSTP VPN в Windows 2008/2008R2/2012. Он использует порт 443 и может быть совместно с IIS (на 443). Он работает как прелесть в Windows Vista/7/8. Я слышал о Mac OSX решениях, но еще нет.

    Однако есть хорошее старое решение SSH.

    Если на linux просто установите openssh-сервер. Если в окнах получить и установить сервер OpenSSH (например, copSSH из itefix https://www.itefix.no/). Измените порт, который будет использовать 443 вместо значения по умолчанию 22.

    На стороне клиента можно использовать Putty (

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

Исходной причиной для написания этой статьи стало наблюдение в последнее время огромного количества вирусов и троянов, которые применяют DNS-протокол в его нештатном режиме работы. Использование стандартных DNS-запросов в качестве транспорта, позволяет им эффективно преодолевать практически любые защитные системы, заботливо воздвигнутые администраторами на шлюзе в корпоративную сеть. В самом деле, DNS-трафик плохо (или почти никак) не анализируется стандартными IDS-системами, также как открыт для прохода в обе стороны практически на любом брандмауэре, что позволяет вражеской колонии из зловредов, находясь даже в глубоком тылу не терять связь со своей «большой родиной».

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

Общая теория

Несмотря на то, что многие узкоспециализированные программы такого рода (подробно обсуждаемые далее) работают по различным схемам — все они эксплуатируют одну центральную идею, применяемую для обхода стандартных средств сетевого контроля. Речь идёт об инкапсуляции своего служебного трафика в штатные DNS-запросы с последующей сборкой скрытно полученных TCP/IP-пакетов уже позади заградительного барьера на шлюзе.

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

  1. Регистрируем собственный домен, для управления его зонами и субдоменами настраиваем свой DNS-сервер, авторитативный для данного домена. Очевидно — этот конец цепочки находится под вашим полным контролем, это будет сторона, выполняющая роль управляющего сервера в создаваемом DNS-туннеле (далее Сервер);
  2. Специальное ПО совмещенное работающее согласовано с DNS-сервером, осуществляет в фоновом режиме непрерывный мониторинг всех входящих DNS-пакетов. В частности контролирует каждый входящий запрос на наличие идентифицирующих сигнатур. Уникальная комбинация флагов или значений в служебных полях DNS-запросов могут идентифицировать обращение клиента, после чего такой «особый пакет» распаковывается Сервером согласно заранее условленному алгоритму. После его обработки формируется ответ, точно также инкапсулированный в служебную часть отсылаемого DNS-пакета;
  3. С противоположной стороны, за множеством брандмауэров и сетевых фильтров находится тот, кто должен получать команды и как-то удаленно исполнять их, условно назовем его Клиент. Безотносительно к характеру предшествующей фильтрации стандартного TCP/IP-потока, такому клиенту достаточно иметь стандартную возможность резольвить (разрешать) DNS-имена, чтобы создать собственный скрытый и туннелированный канал соединения с заранее указанным и подготовленным Сервером из внешнего Интернета.

Несмотря на кажущуюся необычность схемы, всё довольно просто: метод напоминает идеи стеганографии, реализованные на базе DNS.

Перечислив этапы развертывания такой спецсвязи, кратко остановимся на некоторых деталях реализации метода туннелирования, а также на общей специфике службы имен, которые вместе делают возможным подобный транзит:

  1. Любой участвующий в туннеле DNS-пакет является полностью стандартным с точки зрения любого внешнего наблюдателя (строго выполняя соответствующую ему сетевую функцию согласно RFC 1034 и RFC 1035);
  2. В то же самое время он, как правило, в служебной части своего фрейма, несёт некую дополнительную зашифрованную информацию, которая является скрытой (или как минимум неявной) для любого постороннего наблюдателя, тем не менее, будучи неотъемлемой частью пакета, она, безусловно, доставляется по своему назначению. Наличие подобной «дополнительной начинки» никак не влияет на штатную работоспособность DNS;
  3. В инкапсулированной части пакета могут находиться, как собственные инструкции, так и специально упакованные команды других стандартных программ и сервисов (например, в Ozyman это реализация «проброса» сеанса обычного терминала SSH). В общем случае, возможна транспортировка «сквозь DNS-поток» с динамической сборкой на «обратной стороне» любых TCP/IP пакетов;
  4. В последнем варианте в силу технических особенностей устройства DNS-протокола, который существенно ограничивает размер инкапсулируемой информации за одно обращение, будет наблюдаться падение скорости «пробрасываемого» TCP/IP-потока в силу сильной фрагментации пакетов. Для хотя бы примерной оценки, могу привести собственные замеры: на канале в 1Мб скорость трансляции в DNS-туннеле держалась в диапазоне от 0,5 до 4 кбит/с. Что, как видно, потенциально позволяет вполне уверенно управлять зараженным компьютером-зомби, общаться в ICQ через полностью закрытый брандмауэр, или читать простые HTML-странички. К сожалению, хоть как-то увеличить скорость транслируемого извне трафика сверх указанного барьера в 2-4 кбит/с чрезвычайно проблематично;
  5. При реализации данной схемы не всегда обязательным является прямое обращение к DNS на обслуживаемом «магическом домене». Даже при рекурсивном режиме работы исходного DNS-провайдера, существуют техники «доставки посланий» до заданного «магического домена» транзитным способом через всю стандартную иерархию DNS-запросов.

Сфера применения

После ознакомления с формальной логикой работы механизма , предвижу вполне закономерный вопрос читателя: где может использоваться столь специфический и замысловатый способ связи?

Кроме уже упомянутых армии ботов и троянов, DNS-туннелинг активно используют для обхода как персональных, так и корпоративных средств защиты по всему миру. В частности, я лично был впечатлён случаем, когда наблюдал ситуацию применения такой технологии для проброса ICQ/Jabber, несмотря на практически полную блокировку входящего трафика в крупную государственную сеть.

Интересно, что в этом случае фильтрация и мониторинг сети осуществлялись как местным админом регионального филиала, так и московским специалистом из центрального офиса этой федеральной государственной структуры, где и обеспечивалось физическое подключение к интернету. Несмотря на использования разных технологических платформ на этих двух уровнях и принципиально различных методов фильтрации — механизм DNS-проброса на этом режимном объекте «с ограниченным уровнем доступа» работал очень надежно, хотя и относительно медленно (впрочем, на скорости достаточной, для сидения этого скучающего сотрудника в чате).

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

Моё выборочное тестирование нескольких местных провайдеров показывает, что все без исключения проверенные поставщики интернета (в том числе и один мобильный), дают возможность резолвить имена в этом гостевом режиме работы. И если даже в каких-то отдельных случаях брандмауэры или DNS настроены достаточно консервативно, например, делая невозможной передачу экзотических NULL-записей, у DNS-туннелинга есть достаточно хороший адаптационный потенциал, позволяющий переключаться на трансляцию через уж совсем обычные CNAME-запросы и так далее.

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

Dnscat

Эта небольшая популярная утилита является частью сервисного DNS-пакета , её развитие выделено в условно отдельный проект, поддерживаемый создателем Роном Бовисем . Как видно из названия, Dnscat пытается дублировать функциональность уже привычного всем базового сетевого инструмента netcat, за тем важным отличием, что здесь весь трафик транслируется посредством DNS-протокола. По большей части, все возможности Dnscat сводятся к двум моментам:

  • Это возможность установки соединения и передачи информации (текстовых сообщений или файлов) между двумя произвольными хостами интернета;
  • Возможность через уже установленное соединение, удаленно запускать команды системной оболочки (реализуется через опцию –e), а также перенаправлять при этом вывод запускаемых команд на инициирующий соединение хост.

Интересной особенностью этой утилиты является то, что она может быть достаточно всеядной. С одной стороны, она позволяет работать через обычные рекурсивные DNS (по умолчанию) с авторитативным сервером «магического домена», с другой — есть режим прямого подключения к DNS-серверу, в этом случае можно работать в стандартном режиме клиент-сервер (запуск через аргумент --dns). В последнем варианте понижается скрытность и универсальность работы утилиты, но в качестве приятного бонуса резко возрастает скорость и надежность соединения, кроме того, на принимающей соединение стороне уже не нужно иметь именно авторитативный сервер имен.

Утилита поставляется вместе с исходниками в составе пакета nbtool (сразу с клиентской и серверной частью), и может быть скомпилирована под Linux, FreeBSD и Windows.

NSTX

(NSTX) — одна из самых известных и фундаментальных реализаций идеи DNS-туннелинга. Данный комплекс создаёт двунаправленный IP-туннель для передачи данных на базе любого легитимного транзитного DNS-трафика.

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

Для разовой проверки почты или одного-двух твитов приобретать новую prepaid-карту чаще всего нецелесообразно, поэтому я выбрал иной путь. В таких ситуациях с помощью NSTX он пробрасывает IP-трафик к своему DNS-серверу (выполняющего роль принимающего прокси-сервера для выхода в большой Интернет). При этом, согласно его богатому международному опыту, в подобных сетях даже в гостевом режиме практически всегда доступен DNS-резольвинг. Собственно, именно для личных нужд и был разработан этот программный пакет.

В силу популярности именно этого варианта туннелирования, совсем немного остановлюсь на установке и настройке его клиента (на примере Debian). Для начала устанавливаем весь пакет NSTX:

# apt-get install nstx

После чего в файле-настройке /etc/default/nstx следует сначала добавить адрес принимающего DNS-сервера (параметр NSTX_DOMAIN), а затем включить работу этого демона путем присвоения обоим параметрам ifup_tun0 и start_nstxd значения «yes».

Дополнительно нужно сконфигурировать и новый системный интерфейс:

Iface tun0 inet static
address 10.0.0.1
netmask 255.0.0.0

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

Dns2tcp

Почти полный аналог NSTX, за тем исключением, что он пробрасывает лишь TCP-трафик. Автор Оливер Димбауэр постарался сделать максимально «легкую» реализацию идеи DNS-туннелинга: для запуска и инициализации соединения на стороне клиента не требуется установки никаких новых драйверов или интерфейсов, также как не нужны и права администратора.

Настройка Dns2tcp существенно проще в сравнении с NSTX, поэтому просто отмечу, что документация этого проекта . В силу простоты Dns2tcp в нём отсутствуют встроенные механизмы аутентификации и шифрования, именно поэтому он часто используется совместно с обёрткой из ssl-tunnel , вариант парной настройки которых и отражен в большинстве примеров официальной документации. Поставляется эта утилита в комплекте из сервера и клиента, доступных для самостоятельной компиляции в любой из Unix-систем.

Heyoka

На фоне аналогов инструментарий, который позволяет создавать двунаправленные TCP/IP туннели на основе использования всё того же DNS-трафика.

Исповедуя во многом похожие на своих предшественников идеи, отличается тем, что использует довольно интересный и самобытный алгоритм упаковки, который ощутимо ускоряет транзит трафика на фоне аналогичных инструментов. Так, Heyoka способен работать с практически неограниченным количеством принимающих трансляцию серверов. Это значит, что на стороне внешнего интернета можно создать сеть сразу из нескольких DNS-серверов, каждый из которых, принимая лишь часть данных, ретранслирует каждый полученный им пакет на некий центральный сервер, который и осуществляет сборку в «одно целое» всей этой «веерно транслируемой» информации (образуя собственную сеть из Серверов по топологии «звезда»).

Такой сложный на первый взгляд подход позволяет существенно затруднить отслеживание адресов серверов принимающих инкапсулированные пакеты.

Давайте немножко остановимся на этом важном моменте, принципиальном для понимания главной «фишки» Heyoka. Как можно увидеть на рис. сверху, там представлен обычный статистический анализ трафика входного для транзита DNS-сервера, где отчетливо виден аномальный всплеск объема транслируемой информации на один из внешних IP-адресов (это принимающий DNS-сервер), сразу позволяя выявить и заблокировать подобную нештатную ситуацию, сделав обычную схему работы DNS-туннелирования нерабочей для злоумышленника.

На рис. внизу показан аналогичный срез DNS-трафика транзитного интранет-сервера, но здесь используется Heyoka в режиме многоцелевой трансляции пакетов. Очевидно, что в последнем случае трафик более-менее равномерно распределен между большой группой IP-адресов, и администратор этой локальный сети, даже имея какие-то подозрения и зафильтровав выборочно какой-то один (или несколько) действующих в единой группе DNS-серверов, такую скрытую трансляцию прекратить всё равно не сможет. В этом худшем случае скорость «проброса» незначительно упадёт, а все пакеты теперь будут маршрутизироваться на оставшиеся доступными внешние серверы из общей цепочки.

Вторая особенность — Heyoka полностью ориентирован на ОС Windows. У этой утилиты нет конфиг-файлов, она полностью настраивается через консоль посредством аргументов командной строки. Один и тот же головной exe-файл может быть запущен как в режиме master (это сервер в нашей классификации, ключ –m), равно как и slave (клиент, ключ –s), позволяя пробрасывать любой трафик с локального на заданный удаленный порт. Ниже привожу пример запуска этой утилиты в режиме клиента:

Heyoka.exe -s -d mydomain.com -p 3389

Этот проект предоставляется в исходных кодах и распространяется по лицензии GPLv2.

Iodine

Как и все предыдущие инструменты, позволяет передавать IPv4 через DNS-трафик. Давайте перечислим основные отличия, которые без сомнения очень интересной реализацией:

  • Впервые используются экспериментальные NULL-пакеты (см. NULL RDATA format из RFC 1035), что позволяет существенно ускорить трансфер данных, доведя размер одного пакета до 1Кб полезных данных;
  • Iodine спроектирован очень универсально — он прекрасно работает как на Win32-системах, так и практически на всех Unix-системах. Таким образом, это даёт возможность запустить клиента, например, в среде Windows, а принимающий сервер настроить уже под любимой FreeBSD;
  • Пакет содержит достаточно хорошую встроенную систему безопасности. Например, он использует аутентификацию на базе MD5-хеша, а также принимает пакеты только с тех IP-адресов, которые сначала прошли аутентификацию, отбрасывая любые другие, какие бы команды они не содержали;
  • Iodine максимально автоматизирует и упрощает свою настройку. Например, он сам настраивает свой интерфейс во время инсталляции, сам тестирует и выбирает оптимальный по скорости режим передачи данных из множества доступных и так далее. Кстати говоря, здесь на одном сервере может «висеть» одновременно до 16 пользователей-клиентов;
  • Проект достаточно активно развивается, также доступны его полные исходные коды, есть репозитарий, прекрасно документированы спецификации всех используемых протоколов.

Хочу упомянуть, что кроме уже названных поддерживаемых платформ Linux/*BSD/Win32, также имеются рабочие клиенты под Android, Maemo, WinMobile, Mac OS X (дополнительно нужен драйвер tuntap), BeOS и Solaris. В заключение дам полезный совет: часто уменьшение на стороне клиента значения MTU (для интерфейса dns0 , например до 700) — существенно ускоряет обмен данными в таком туннеле.

OzymanDNS

От очень известного специалиста по безопасности Дэна Каминского (Dan Kaminsky), которого часто величают как «DNS guru». Главная особенность — это изначальная «заточенность» на проброс именно SSH-трафика. Автор утилиты призывает далее в зависимости от конкретной необходимости, туннелировать необходимый трафик (для примера, с Tor через туннель SSH/DNS).

Сам Дэн выполнил черновую реализацию и тестирование концепции «SSH через DNS» (proof-of-concept), а также открыл исходники своего проекта (кстати, полностью написанного на Perl). У OzymanDNS уже появились последователи — независимые сторонние доработки. В частности, я хотел бы порекомендовать этого инструмента, где автор реализовал иной алгоритм переупаковки трафика, который по его словам в среднем работает в два раза быстрее оригинального. Также совместного использования браузера и OzymanDNS, которые можно настроить работать через SSH-прокси и браузерные плагины со стороны клиента (такие как для Google Chrome или для Mozilla Firefox).

OzymanDNS написан на Perl, поэтому он может быть запущен во всех средах, где поддерживается этот интерпретатор (оригинальный набор скриптов был написан и протестирован в Linux). На Mac OS X можно использовать клиент в сочетании с заранее установленными Xcode и всеми необходимыми Perl-модулями (как минимум нужны MIME::Base32 и Net::DNS). Для клиента в Windows можно взять Cygwin (в котором самостоятельно скомпилировать и настроить всю рабочую среду) или проект Strawberry Perl. Кроме всего этого, для любой из клиентских сред должны быть установлены и настроены внешние сервера SOCKS 5 и SSH.

Бороться со злоупотреблениями технологией, описанной в этой статье вполне возможно. Среди множества подходов, самый простой — это настройка двух независимых DNS-серверов, один из которых специально предназначен для режима гостевого доступа и в принципе ничего не знает про «большой Интернет». Общая беда большинства уязвимых провайдеров и локальных сетей, прежде всего в том, что их администраторы часто не в курсе существования подобных методов обхода стандартной фильтрации, что и используется злоумышленниками в незаконных целях (отчасти эту проблему и решает эта статья).

В заключение напоминаю, что не надо забывать об аналогичных методиках, использующих, к примеру, (дополнительно и ) или , более тщательно продумывать правила фильтрации пакетов даже самых безобидных с первого взгляда протоколов, типа DHCP (об интересном способе использования которого, кстати, мы и поговорим в следующий раз в нашей рубрике «Безопасность»).

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

Использование TCP стало столь привычным, что большинство просто не задумывается о заложенных в этот протокол механизмах и во всех случаях полагается на «интеллект» системы. Одновременно с этим, если встречаются какие-то сведения, объясняющие что-то в его поведении, или теории, построенные на основе, так сказать, «упрощенных» представлений, то у многих просто недостает знаний правильно оценить полученную информацию. Что приводит к появлению технологических мифов. Один из которых, порожденный статьей Олафа Титца (Olaf Titz), здесь и попробуем опровергнуть. К сожалению, в России все, что написано на иностранном языке да еще размещено на зарубежном сайте, воспринимается как святое откровение. Хотя многие далее вынесенного в ее заголовок тезиса «Why TCP Over TCP Is A Bad Idea» и не читают. Чтобы уравнять шансы тех, кто имеет затруднения с английским языком, предложим дословный технический перевод упомянутого опуса . В переводе не использовались никакие литературные экстраполяции, чтобы максимально точно донести идеи автора и ни в коем случае не исправить на этапе перевода что-то из многочисленных его ошибок. Разберем текст этой статьи.

Суть проблемы

Итак, первое, что по мнению Олафа, мешает эффективной работе TCP в качестве туннеля, это повторные передачи. Если отбросить туманные рассуждения о насыщении канала (meltdown) из-за мифического фиксированного тайм-аута, которого нет в TCP, то в «сухом остатке» в первом разделе статьи лишь утверждение об экспоненциальном росте тайм-аута, если, цитирую, «сегмент задерживается сверх тайм-аута». Рассмотрим подробнее. Автор упорно не желает использовать общепринятую терминологию и предпочитает изъясняться как колдун-друид. Но так как в тексте упоминается RFC2001, то можно воспользоваться ссылкой и попытаться догадаться, на что намекает Олаф Титц. Единственный показатель, имеющий в RFC2001 экспоненциальный рост, – это CWND (congestion window). Но окно насыщения, или CWND, связано с пропускной способностью прямой зависимостью. Автор же намекает, что задержки растут по экспоненте и это якобы приводит к снижению темпа передачи. Задержки – это RTT (round trip time), или время обращения, на основании которых высчитывается RTO (retransmission time out), или таймер повтора. Об этом нет ничего в RFC2001. Но по другим документам можно узнать, как это происходит. Например, в RFC793 , упоминаемом также в статье, описан метод расчета RTO для каждого текущего пакета. Так вот, там используется показатель SRTT (smooted round trip time), или взвешенное время обращения. Подчеркиваю – взвешенное! Где тут Олаф «раскопал» экспоненту? Конечно, можно догадаться, что автор спутал расчет RTO при задержке с расчетом RTO при потере! Вот, если бы сегмент вообще пропал и от получателя нет никаких ответов, тогда алгоритм TCP на самом деле требует произвести повторы с экспоненциальным замедлением. Но, не смущаясь мелкими деталями, Олаф связывает увеличение периодов проверки на обрыв соединения с борьбой с насыщением, то есть с тем самым meltdown, который, как ружье со стены в известной пьесе, если упомянуто в первом акте, то далее обязательно «выстрелит». Таким образом, поскольку экспоненциального роста задержек передачи в TCP нет, то измышления первой части обсуждаемой статьи не имеют отношения к реализации TCP в нашей с вами Вселенной.

Рассуждения Олафа, где он считает, что трафик TCP в Интернете регулируется тайм-аутами, просто выкинем, как не соответствующие реальности и потому не актуальные. Конечно, можно было бы везде, где в тексте встречается «timeout», при переводе подставить «таймер», что сильно приблизит многие рассуждения к действительному положению дел, но тогда пришлось бы исправить и многое другое. Но, как уже было сказано выше, перевод сделан самым безжалостным способом.

Второе, что смутило Олафа Титца – это взаимодействие транспортного TCP и транспортируемого. Для ясности обратимся к схеме инкапсуляции, которая обсуждается в . Скопируем ее в переводном варианте и добавим немного комментариев.

Автор утверждает, что эти два потока TCP (см. рис. 1) могут иметь разные таймеры. Дословно: «может так случиться, что соединение нижнего уровня имеет медленные таймеры, возможно как остаток с периода медленного или ненадежного основного соединения». То есть автор предположил, что вложенное TCP успело разогнаться, а несущее тем не менее оставалось медленным. Это просто невозможно, так как противоречит законам сохранения, действующим в нашей Вселенной. Надо признать, что именно здесь Олафа «понесло». Он увлеченно живописует, как внутренний слой, такой быстрый и такой «несчастный», будет, не получая подтверждений, посылать пакет за пакетом и тем самым – вот оно, старое ружье выстрелило – создаст «внутренний meltdown-эффект». Здесь замечу, что термин «внутренний meltdown-эффект» изобретен просто «на ходу». Жаль разочаровывать Олафа, но после неподтверждения пакета и в отсутствие вообще всяких подтверждений TCP начинает процедуру медленного старта, в ходе которой поток TCP снова будет искать предельную передающую возможность среды, постепенно увеличивая скорость передачи, начиная с самых минимальных значений. Иначе говоря, TCP не снижает темп передачи, а вообще прекращает ее и затем возобновляет снова со стартовых значений. И это, кстати, дает гарантию, что внутренний TCP никогда не будет работать быстрее внешнего, того, что образует туннель. Так как, если параметры внутреннего TCP приведут к тому, что он разгонится быстрее туннельного, то после же столкновения он сбросится снова к состоянию медленного старта и снова начнет «догонять» туннельный TCP.

Давайте представим, что реально может случиться изза потерь сегментов (именно так и следует далее их называть, а не пакетами) в таком туннеле. Во-первых, просто обрыв связи будет обработан и тем и другим TCP соответственно и в пределах перечисленных RFC. А вот с повторами, и правда, могут возникнуть некоторые проблемы. Покажем на схеме (рис. 2), что будет происходить, если в пути потеряется сегмент с данными.

Предположим, что пропал сегмент D4. Тогда оба стека протоколов получат повторный ACK с последним принятым номером и согласно алгоритму Fast Retransmission, или быстрой повторной передачи, пропущенный пакет будет повторен. На рисунке изображена ситуация, когда оба стека имеют одинаковый RTT и, значит, близкие RTO. Тогда транспортный TCP сформирует повтор пропавшего сегмента T44 и точно так же добавит в поток сегмент T7-4, содержащий сегмент с данными D4, повторенный в транспортируемом TCP. Это самый худший вариант развития событий. Иначе говоря, если потери канала составляют 10%, то из полезной емкости канала будет изъято уже 20%. Но, как уже замечено, это предельно плохой вариант. Поскольку RTT туннеля и RTT транспортируемого TCP на практике не совпадают, то, скорее всего, реальные потери полосы будут гораздо меньше.

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

Для TCP нет разницы между потерянным сегментом и потерянным подтверждением, если и те и другие высылаются не так, как рассуждает Олаф, а сериями в пределах размера CWND. Но, с другой стороны, теперь уже для TCPтрафика происходит теоретическое учетверение потерь, то есть из полезной емкости канала будет изыматься уже 40%. Хотя это лишь «на бумаге», то есть снова здесь приведен самый плохой вариант.

Теперь, глядя на рис. 2, ответьте, в каком TCP надо запретить повторы? Олаф Титц делает вывод, что повторы надо запретить в верхнем транспортируемом TCP. На самом деле, повторы следует запретить в нижнем туннельном TCP.

Во-первых, потому что туннель это одно TCP-соединение, а вложенных может быть множество.

Вовторых, потому что туннель создается на специальном хосте, а внутренние потоки соединяют разные клиентские компьютеры со стандартным TCP-стеком. И, наконец, втретьих, кроме TCP есть еще много разных протоколов, сегменты c которыми все-таки очень не бесполезно восстановить при потере, а отличить их от TCP может только стек туннеля. Но такое расширение TCP-туннелей пока не реализовано. Здесь лишь рассматривается гипотетическая возможность. Но ничего не мешает в практической ситуации для пробы запретить повторы через параметры sysctl линуксового ядра на тех хостах, между которыми поднят туннель, и проверить действенность такой настройки.

Итак, и вторая часть рассуждений о проблемах TCP не выдерживает элементарной проверки. Быть может, в разделе «Практический опыт» нам откроется истина? Рассмотрим и его повнимательнее.

В практической части статьи содержится информация, которая может стать разгадкой всех проблем Олафа Титца. Оказывается, у автора этой статьи, цитирую, «использовалась волоконно-оптическая связь, которая страдала частыми потерями пакетов, иногда 1020%». Странная связь! Вероятно, на карманных фонариках. Последннее конечно шутка, но тем не менее это позволяет точно определить условия применения тезисов автора упомянутой статьи. Обратимся к RFC 2001 . Там однозначно установлено, что все алгоритмы TCP рассчитаны при допущении, что потери в канале составляют менее 1%. Вероятно, у Олафа были проблемы с кабельщиком. Быть может, суровому монтеру не понравилась его прическа и он решил таким путем выразить свое возмущение. Олаф утверждает, что, создав CIPE , смог решить проблемы и обеспечить надежную работу на канале с потерями до 20%. И если не проверить утверждения автора с помощью тестов с туннелем на подобном канале, то получится, что здесь предлагается рассуждения Олафа Титца заменить рассуждениями Алексея Барабанова. Лишь опыт позволит рассудить, на чьей стороне правда (или правдоподобность). Поскольку нет простой возможности создать искусственную линию связи с характеристиками, похожими на те, что создали так много проблем Олафу, то заменим реальные, обычно модулированные, помехи случайными. И дополнительно ограничим их 10-процентными. Думаю, что эта замена, не помешает понять суть происходящих процессов, так как на практике и 10% и 20% значительно больше указанного в RFC 1%, и отличаются лишь временем, затраченным на проведение эксперимента, поскольку чем больше потери, тем меньше скорость передачи.

Тестовая сеть

Проверку будем проводить путем передачи тестового массива псевдослучайных данных в одном направлении через TCP- и UDP-туннели. Это, конечно, примитивная модель взаимодействия, но только так можно в чистом виде попытаться определить зависимость характеристик канала и свойств полученного потока данных. Дополнительно в центре маршрута ограничим полосу, например до 10 Мбит, и внесем случайные потери в трафик. Конечно, 10 Мбит значительно выше типичной скорости канала, предоставленного ISP для подключения к Интернету. Но иначе придется уменьшить объем пересылаемых данных, чтобы в приемлемое время провести эксперимент. Перечислим элементы, которые нужны для организации таких проверок. Во-первых, хост-отправитель и хост-получатель трафика. Во-вторых, два хоста, между которыми проложен туннель. Поскольку «удаленный» конец туннеля может совпадать с хостом-получателем, то, кроме перечисленных трех хостов, нужен еще один, где будет эмулироваться «узкое место» в сети. Итого, достаточно будет 4 компьютера соединить последовательно. Строго говоря, хост-отправитель можно совместить с «ближним» концом туннеля. Но надо учесть, что вход в туннель тоже является своего рода ограничителем трафика, или шейпером, поэтому пусть будут в тестовой сети четыре компьютера, которые назовем wstovert, wsalekseybb, wskostja и server. Общий вид полученной сети представлен на рис. 3, и дальнейший комментарий будем вести согласно изображенной там схемы.

Все компьютеры включены в общую сеть 192.168.0.0/24, объединены общей кабельной системой с помощью коммутатора 1 Гбит и обмениваются данными по протоколу 1000BaseTX, то есть значительно выше проверяемых скоростей передачи, что позволит максимально снизить систематическую ошибку. На эту сеть наложены две виртуальные сети. Первая из них, с адресом 192.168.10.0/24 включает wstovert, wsalekseybb и server, а вторая – с адресом 192.168.11.0/24 – только server и wskostja. Практически все компьютеры могут резолвить адреса друг друга с помощью arp и обмениваться пакетами через общий коммутатор. Но нам ведь нам надо обеспечить передачу трафика между компьютерами так, будто они включены последовательно один за другим. Поэтому с помощью правил маршрутизации и преобразования адресов заставим трафик от wstovert проходить до wskostja через wsalekseybb и server так, как указывает стрелка на рис. 3. Для этого на каждом компьютере укажем статический маршрут до следующей по ходу движения стрелки на рис. 3 сети через соседний компьютер, а на том включим NAT так, чтобы заменять в таком маршруте адрес отправителя на собственный. Окончательно должно получиться так:

# traceroute 192.168.11.2

traceroute to 192.168.11.2 (192.168.11.2), 30 hops max, 40 byte packets

1 192.168.10.2 0.000 ms 0.000 ms 0.000 ms

2 192.168.10.1 0.566 ms 0.086 ms 0.088 ms

3 192.168.11.2 0.145 ms 0.170 ms 0.241 ms

Поскольку главный вопрос заключается в изучении поведения инкапсулированного трафика, то в тестовой сети настроим также и туннель. Воспользуемся программным обеспечением, которое позволит поднять туннель, как на основе UDP-транспорта, так и TCP. По этой причине CIPE не подходит. Выберем OpenVPN . Тем более что согласно сравнительной таблице этот проект рекордсмен в разделе Popularity. Туннельная сеть образует виртуальное соединение между wsalekseybb и wskostja, определенное как сеть 192.168.12.0/24. Для станции wsalekseybb настройки OpenVPN в режиме клиента TCP-туннеля будут производиться согласно следующему файлу конфигурации:

# cat /etc/openvpn/test.conf

proto tcp-client

tcp-queue-limit 1000

remote 192.168.11.2

dev tun

port 5000

tcqueuelen 1000

secret /etc/openvpn/static.key

ifconfig 192.168.12.1 192.168.12.2

route 192.168.12.0 255.255.255.0 192.168.12.1

Для станции wskostja все аналогично, меняются лишь адреса, протокол на tcp-server и удаляется строка remote, что переводит туннель в состояние прослушивания. В режиме UDP на обоих концах протокол просто переключается в udp и удаляется параметр tcp-queue-limit. И теперь путь между wstovert до wskostja проходит через туннель.

# traceroute 192.168.12.2

Таким образом, можно, отправляя трафик со станции wstovert до станции wskostja, осуществлять на промежуточном хосте server нужные манипуляции в соответствии с исследуемой моделью канала.

Для работы создадим на всех участвующих в экспериментах хостах специального пользователя tovert и разместим в его домашних директориях в файле.ssh/authorized_keys2 специально подготовленные ключи, чтобы можно было выполнять необходимые действия в автоматическом режиме с одной из станций. И для удобства разрешим через sudo выполнение пользователем tovert команд с привилегиями суперпользователя без ввода пароля.

На wstovert подготовим файл с данными, которые будут посылаться в тестовых сеансах:

# ssh tovert@wstovert "dd if=/dev/urandom of=~/100M.bin bs=1024 count=102400"

Симуляцию TCP-трафика будем создавать с помощью команды, отправляющей 100 Мб из файла на целевой хост. В качестве слушателя TCP используем sshd, который перешлет все принятые данные в /dev/null, чтобы не помешала буферизация. Причем для сокращения затрат на загрузку файла с диска каждую тестовую отправку будем предварять локальным копированием в /dev/null:

# dd if=/home/tovert/100M.bin bs=1024 count=102400 >>/dev/null

# dd if=/home/tovert/100M.bin bs=1024 count=102400 | ssh [email protected] "cat - >>/dev/null"

Симуляция UDP-трафика будет производить утилитой netcat, точно так же предварительно произведя локальное копирование:

# dd if=/home/tovert/100M.bin bs=1024 count=102400 >>/dev/null

# dd if=/home/tovert/100M.bin bs=1024 count=102400 | netcat -vu -w 1 192.168.12.2 22222

На приемной стороне UDP-трафик будет приниматься специальным слушателем и подсчитываться:

# netcat -vlnu -s 192.168.12.2 -w 15 -p 22222 | wc -c

В точке прохождения трафика через хост server включим ограничитель полосы типа HTB (Hierarchical Token Buckets) на 10 Мбит со следующей конфигурацией:

qdisc htb 1: r2q 10 default 0 direct_packets_stat 0

class htb 1:1 root rate 10Mbit ceil 10Mbit burst 14704b cburst 14704b

Sent 0 bytes 0 pkts (dropped 0, overlimits 0)

Tokens: 9191 ctokens: 9191

class htb 1:10 parent 1:1 prio 0 rate 10Mbit ceil 10Mbit burst 14704b cburst 14704b

Sent 0 bytes 0 pkts (dropped 0, overlimits 0)

Lended: 0 borrowed: 0 giants: 0

Tokens: 9191 ctokens: 9191

filter parent 1: protocol ip pref 1 fw

filter parent 1: protocol ip pref 1 fw handle 0xa classid 1:10

Так что фильтр будет направлять в шейпер только трафик, помеченный маркером 10 (0xa). Весь непомеченный трафик будет проходить в обход шейпера, так как в HTB не указан поток по умолчанию. Метиться будут лишь пакеты, направляемые на виртуальный адрес wskostja:

# traceroute 192.168.11.2

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

# iptables -n -L OUTPUT

Chain OUTPUT (policy ACCEPT)

target prot opt source destination

DROP all -- 192.168.12.2 0.0.0.0/0 random 10%

ACCEPT all -- 192.168.12.2 0.0.0.0/0

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

Теперь все окружение построено. Договоримся о точках, где будут сниматься данные. В условиях эксперимента будет тип трафика, тип туннеля, объем отправленных с wstovert данных. Скорость передачи нам сообщит команда dd на wstovert. Объем данных, поступивших в туннель, и число уничтоженных на входе пакетов узнаем через ifconfig tun0 на wsalekseybb. Статистика шейпера на server покажет, сколько данных и пакетов прошло через ограничитель трафика, сколько пакетов было уничтожено. На счетчиках iptables на wskostja узнаем, сколько данных добралось до назначения и сколько было уничтожено как имитация потерь в линии связи. И для UDP после отключения слушателя netcat получим объем реально полученных данных, подсчитанный командой wc.

С примерами некоторых скриптов, использованных для настроек, можно ознакомиться в архиве .

Передача TCP в туннелях

Сначала проверим самую главную версию, что трафик TCP внутри TCP-туннеля якобы плохо передается, а вот внутри туннеля UDP напротив очень хорошо. Для этого поднимем туннель OpenVPN сначала в режиме TCP, затем в режиме UDP, и в каждом состоянии проведем тестовую пересылку без потерь, с потерями 10% и с двухсторонними потерями. Полученные числа соберем в таблицу. К сожалению, так как используется высокоскоростная сеть, тестовый файл невелик, а время не позволяет делать сотни прогонов и затем производить сглаживание результатов, то в таблицу 1 будут занесены наиболее показательные данные из 23 прогонов на каждом условии и дополнительно указан возможный разброс.

Таблица 1. Передача TCP-трафика в туннелях

Протокол передачи данных

Режим туннеля

Передано в tun0, Мб

Скорость передачи, Мбайт/сек

Шейпер, передано Мб

Шейпер, передано пакетов

Шейпер, число задержек

Потери, %

Идеальный трафик шейпера / трафик шейпера

103.9

81218

100951

103.9

0.177 (до 0.188)

152585

5504

1.14

117.2

0.0736

157852

4318

10+10

1.16

103.9

144877

144581

103.9

0.18 (до 0.19)

161677

7995

1.11

117.1

0.0791

164227

6281

10+10

1.13

Колонка 5 не выявила никакого преимущества UDP-туннелей в скорости. Средний разброс показателей +/5%. То есть независимо от несущего протокола внутренний TCP рано или поздно подстраивался под условия передачи и находил примерно одинаковый максимум. А вот показатели колонки 6 имеют более интересную интерпретацию. Итак, в идеальных условиях на шейпере насчитано 112 Мб, как в TCP-туннеле, так и в туннеле UDP. Но, как только включаем уничтожение 10% трафика, туннель UDP ведет себя пропорционально потерям и добавляет уничтоженное повторной пересылкой дополнительных 10% объема 112*11=123,2, что примерно равно полученным 124 Мб на счетчике шейпера (все индексы в колонке 10). Туннель TCP реагирует на уничтожение трафика предсказанным способом – выполняет дублирование повторов, и трафик на шейпере возрастает, но, как это тоже было предсказано, не на полные 20%, а лишь на 14%. Как только включаем уничтожение обратного трафика, то потери еще выше, но опять не 40%, как при полных повторах, и не 20%, а всего лишь 16%! Если сопоставить показатели трафика через туннельный интерфейс (колонка 4) и через шейпер (колонка 6), то использование TCP-транспорта добавляет только 4% к переданному объему по сравнению с применением UDP-туннеля. То есть, 10% трафика «честно» пропадает в линии передачи, а погрешности двойного дублирования не превышают 4%. Замечу, туннель достаточно условен, сетка высокоскоростная, и расхождения RTT минимальны, что показала и утилита traceroute выше по тексту. И все равно не получается полного удвоения или учетверения. В условиях реального туннеля, где RTT будут различаться больше, скорости будут ниже, а потери, скорее всего, будут меньше, разница в условиях прохождения TCP-трафика через TCP- и UDP-туннель станет совсем незаметной.

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

Передача UDP в туннелях

Передача UDP-трафика – это весьма условное понятие. Фактически это более похоже на ветер. И поэтому понятие «скорость передачи» теряет всякий смысл. В тестовых проверках скорость случайным образом определялась в диапазоне от 13 до 29 Мбайт/сек. Но если на пути такого «ветра» встречается участок с меньшей полосой пропускания, недостаточной, чтобы передать все имитированные пакеты, то излишки просто уничтожаются. Как показали прогоны трафика через туннель OpenVPN вместе с шейпером, настроенным на большие предельные скорости, чем 10 Мбит/сек, сам туннель является скрытым ограничителем полосы. При настройках, согласно, указанным выше, туннель в режиме UDP ограничивает полосу скоростью 5,9 Мбайт/сек, а в режиме TCP даже еще ниже 2,9 Мбайт/сек. Вероятно, это связано с тем, что туннель организован как программа, работающая не в пространстве ядра, а в пользовательском пространстве. Но, так или иначе, потери UDP-трафика начнутся сразу же на входном интерфейсе туннеля, даже если в нем не настроен собственный шейпер. Второй барьер для UDP будет создавать ограничитель трафика, имитирующий «узкое место», взведенный в нашем случае после хоста server. Ну и, наконец, в тестах с потерей трафика дополнительную убыль пакетов UDP обеспечит фильтрация на входе wskostja. Обратный трафик «портить» не будем, так как это не скажется существенно на выводах. Результаты тестов сведены в таблице 2.

Таблица 2. Передача UDP-трафика в туннелях

Протокол передачи данных

Объем отправленных данных, Мб

Режим туннеля

Передано в tun0, Мб

Потеряно в tun0 пакетов

Шейпер, передано Мб

Шейпер, передано пакетов

Шейпер, уничтожено пакетов

Потери, %

Реально прибыло, Мб

Отправлено / прибыло

75375

1.94

1406

1.73

1.04

75195

2.29

1729

1.867

1.12

72744

4490

1611

3.125

1.69

70678

5.02

6441

2611

4.08

1.96

Судя по колонке 4, неявный шейпинг самого туннеля привел к тому, что в режиме TCP «пролетело» в интерфейс в два раза меньше пакетов, чем в режиме UDP. Ну и как следствие, окончательно попало в точку назначения (колонка 10) меньше в режиме TCP, чем в UDP. Поскольку туннель TCP, кроме всего прочего, может подстраиваться под реальную пропускную способность туннеля, то в TCP-режиме на шейпере после server нет потерь, а в UDP они присутствуют. Но самые интересные результаты дает расчет отношения трафика, реально отправленного через туннель, и того, что был получен в точке назначения. И в том и в другом режиме работы туннеля это соотношение подчиняется правилу, что трафик в проверке работы с потерями выше трафика в идеальном случае примерно на величину потерь. Например, для TCP 1,04*1,1=1,14 приблизительно равно 1,12, полученному в эксперименте. Или для UDP – 1,69*1,1=1,86 приблизительно равно 1,86, что показал тестовый прогон. Но вот само базовое соотношение пропорции доставки неутешительно для UDP. Получается, что в идеальном случае для TCP-туннеля доставляются практически все пакеты – коэффициент 1,04 , а вот в туннеле UDP лишь не более чем два из трех – коэффициент 1,69. Здесь еще раз видно, что полученные результаты могут носить лишь оценочный характер. Ясно же, что коэффициент передачи TCP-туннеля должен в идеальном случае равняться единице. Но реальные значения счетчиков интерфейсов интерпретируют по-разному пакеты, их заголовки и даже константы пересчета байт в килобайты. Однако общий смысл ясен: UDP-туннель совсем не способствует полноте доставки данных до получателя. Главная причина в том, что UDP-поток не может подстраиваться под фактическую ширину канала по маршруту роутинга. И именно этим объясняется присутствие специальной опции ограничения канала на входе туннеля OpenVPN. В настоящих настройках она не применялась, а в реальной жизни ее использование позволит сократить расходы на оплату трафика, который в противном случае будет «порезан» одним из маршрутизаторов уже после того как «провернутся» счетчики ISP. Обращаю внимание, в OpenVPN такая опция есть, а вот в CIPE отсутствует, что вообще не свидетельствует в пользу этого проекта.

Итак, трафик UDP тоже не приобретает ничего хорошего от завертывания его в туннель UDP. Быть может, никакого особого улучшения связи из-за применения CIPE и не происходило? Быть может, все это лишь проказы шаловливого кабельщика? Сейчас трудно разобраться, но безымянного кабельщика надо поблагодарить. Ведь именно из-за его работы Олаф Титц, как Колумб, «поплыл в Индию, а прибыл в Америку», то есть не важно, о чем он там думал, когда создавал CIPE, но, безусловно, что его инициатива подтолкнула многих других разработчиков сходных программных средств.

Практические выводы

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

Во-первых, современные сети являются в большей степени TCP-сетями. Они приспособлены для транспортировки именно такого трафика. Системы ограничения полос взаимодействуют с потоками TCP-трафика и путем накопления и торможения сегментов в очередях заставляют отправителей TCP замедлять трафик без потерь. Технология предотвращения перегрузки RED (Random early detection) работает только в отношении TCP-потоков. Разрабатываются дополнительные функциональные расширения, ориентированные на управление именно TCP-трафиком в первую очередь. Например, явное уведомление о перегрузке, или ECN, предложенное в RFC 3168 , реализовано как расширение формата TCP. И в том же RFC более половины его содержания посвящено проблеме, как транзитный маршрутизатор сможет управлять с помощью ECN трафиком, завернутым в IPsec. Отдельно там же сказаны и «добрые» слова в отношении других не-TCP-туннелей. Про UDP-туннели слов нет, поскольку UDP как достойный транспорт не рассматривается вообще. Конечно, если очень озаботиться, то в Интернете можно разыскать документ «A proposal for the use of ECN bits with UDP flows». Но предлагаю попробовать найти зарегистрированный RFC на эту же тему. Или попытаться его дождаться.

Во-вторых, если в вашей сети ситуация «не на высоте» и вопрос стоит не о соответствии последним технологическим новациям, а просто об удовлетворительном уровне работы, то и здесь следует предпочесть TCP-транспорт. Очень часто проблемы сетевого взаимодействия связаны с потерями UDP-пакетов. Например, замедленный резолвинг сетевых адресов может доставить много неприятностей. На ненадежных подключениях к Интернету браузеры могут или не открывать запрошенные ресурсы или делать это лишь со второго раза. И учитывая, что UDP-трафик самый «беззащитный», то даже на проводных сетях в условиях сильной загруженности будет происходить вытеснение UDP-пакетов в первую очередь. Завернув UDP-трафик в TCP-туннель, можно сделать его более надежным и предсказуемым. И часы у ваших компьютеров будут корректироваться чаще, и DNS будет работать стабильнее. А если в такой туннель завернуть ICMP, то и мониторинг внешних ресурсов также будет стабильнее.

Нет, решительно невозможно обнаружить никаких аргументов против туннелирования в TCP. Быть может, на дату написания статьи все обстояло иначе? Ну, разве что RFC 3168 было в стадии утверждения. А все остальные механизмы регулирования TCP были реализованы задолго до рождения столь оригинальной мысли о неприемлемости туннелирования трафика внутри TCP. Конечно, не стоит забывать о таком эффекте, как вытеснение TCP-потока (TCP-starvation/UDP-dominance) именно за счет его управляемости. То есть, если два типа трафика смешиваются в одной полосе регулирования, то TCP-трафик, поддающийся регулирующему воздействию, будет уступать полосу UDP. Быть может, это и послужило причиной того, что TCP-туннель у Олафа Титца не работал как надо. Но тогда, кроме признания известного недружелюбного кабельщика, надо согласиться с существованием нерадивого сотрудника ISP. Мне кажется, это уже слишком. http://mia.ece.uic.edu/~papers/volans/table.html .

  • Примеры скриптов – http://www.barabanov.ru/arts/tcp/tovert.tgz .
  • RFC 3168 –


  • Есть вопросы?

    Сообщить об опечатке

    Текст, который будет отправлен нашим редакторам: