DNS обычно объясняют так: пользователь вводит адрес сайта, DNS возвращает IP-адрес, браузер открывает страницу. Удобная школьная схема, почти безболезненная для менеджеров и начинающих админов. Проблема начинается там, где схема заканчивается. DNS не просто подсказывает, где лежит сайт. DNS переносит данные. Небольшими кусками, с ограничениями, через странные поля, но переносит.
DNS-туннелирование как раз использует эту особенность. Данные прячут внутрь DNS-запросов и DNS-ответов, а сам DNS превращают в транспорт. Не в «интернет через браузер», не в нормальный прикладной протокол, а в узкую технологическую щель, через которую можно протащить команды, небольшие файлы, маркеры заражения или фрагменты украденной информации.
Метафора с телефонной книгой тут ломается. Представьте, что человек не просто ищет номер по фамилии, а начинает передавать секретное сообщение через сами фамилии, индексы и пометки на полях. Формально книга всё ещё выглядит как книга. По факту книгу уже используют как почтового голубя, только менее романтичного и более удобного для SOC-аналитика, если аналитик не спит.
Исторический нерв у темы хороший. В 2004 году Дэн Камински показал OzymanDNS, инструмент для SSH-туннеля и передачи файлов поверх DNS. Демонстрация стала важной не потому, что DNS внезапно превратился в модем из подвала. Камински наглядно показал старую инженерную истину: любой разрешённый канал можно нагрузить чужим смыслом. Протоколы не имеют морали. DNS не знает, помогает ли открыть сайт, передать файл или поддержать канал управления вредоносной программы.
С тех пор прошло больше двадцати лет, но идея не состарилась. Компании построили новые периметры, добавили EDR, прокси, песочницы, SIEM, повесили на стены плакаты про Zero Trust, а DNS часто оставили в роли «служебного шума». Мол, пусть ходит, без DNS всё развалится. Вот в этой фразе и живёт проблема.
Как DNS-туннель работает на практике
Для туннеля атакующему или исследователю нужен домен и авторитетный DNS-сервер, который контролирует принимающая сторона. Клиент внутри сети берёт данные, кодирует, режет на маленькие фрагменты и вставляет фрагменты в поддомены. Корпоративный резолвер видит обычный DNS-запрос и отправляет его дальше. Авторитетный сервер получает запрос, вытаскивает фрагмент из имени и собирает исходные данные обратно.
Примерно так может выглядеть логика запроса: длинная строка перед доменом уже не является осмысленным именем хоста. Строка несёт кусок полезной нагрузки. Серия таких запросов превращается в поток данных. Ответная сторона может возвращать информацию через DNS-ответы, чаще через TXT или NULL-записи, иногда через A, AAAA, MX и другие типы. CNAME тоже встречается в отдельных реализациях, но CNAME неудобен для произвольных данных и не стоит воспринимать его как основной вариант.
DNS накладывает жёсткие ограничения. Одна метка доменного имени, то есть часть между точками, не должна превышать 63 октета. Полное DNS-имя в проводном формате ограничено 255 октетами, а в привычной записи с точками обычно говорят о 253 символах. Поэтому туннель вынужден дробить данные и постоянно плодить новые имена. Быстрого автобана не получается. Скорее выходит контрабандная тропинка через лес.
Кодирование тоже не произвольное. В поддоменах часто используют base32, потому что DNS-имена регистронезависимы и не любят символы, которые спокойно живут в обычном base64. Чистый base64 содержит плюсы, слеши и знаки равенства, а такие символы в нормальном DNS-имени не проходят. Поэтому встречается либо base32, либо модифицированный base64 без проблемных символов.
Кеширование создаёт отдельный парадокс. DNS умеет кешировать ответы, и для обычного интернета это полезно. Для туннеля кеш может стать помехой: повторный запрос может не дойти до авторитетного сервера, если резолвер уже знает ответ. Поэтому туннели часто генерируют уникальные поддомены, меняют идентификаторы в каждом запросе и стараются обойти кеш. В логах это выглядит как лавина почти неповторяющихся имён внутри одной зоны.
EDNS(0) добавляет современную деталь. Классический DNS по UDP долго жил с лимитом 512 байт на сообщение. EDNS(0) позволяет согласовывать больший размер UDP-пакета, часто до нескольких килобайт. Для нормального DNS это нужно, например, DNSSEC и крупным ответам. Для туннеля это тоже полезно: больше полезной нагрузки можно уместить в один ответ. Защитнику стоит смотреть не только на имя, но и на размер DNS-ответов, частоту запросов, переход на TCP/53 и странное поведение вокруг фрагментации.
Почему история с OzymanDNS до сих пор важна
OzymanDNS часто вспоминают как ранний символ DNS-туннелирования. Инструмент написали на Perl, а основной сценарий описывали как SSH через DNS и передачу файлов. В поздних пересказах рядом с этой историей иногда всплывают аудио и видео, но для аккуратного текста лучше держаться подтверждённого ядра: SSH, файлы, DNS как транспорт.
Смысл не в конкретном инструменте. OzymanDNS показал, что DNS обладает свойствами, которые удобно использовать против владельца сети. DNS проходит почти везде. DNS поддерживает делегирование зон. DNS часто работает даже там, где остальной доступ ещё не выдали, например в сетях с captive portal в отелях, аэропортах и кафе. DNS воспринимают как инфраструктуру, а не как пользовательский трафик. Именно поэтому DNS иногда выпускают наружу почти без вопросов.
В старой модели безопасности периметр делил мир на «внутри» и «снаружи». Всё опасное будто бы жило снаружи, всё служебное внутри считали почти природным явлением. DNS плохо вписывается в такую картину. Каждая рабочая станция постоянно спрашивает внешнюю систему, где лежат чужие домены. Вопросы уходят изнутри наружу. Ответы возвращаются обратно. Такой канал нельзя назвать безвредным только потому, что на схеме рядом с ним написали «инфраструктура».
DNS-туннелирование эксплуатирует не одну уязвимость, а привычку доверять служебному протоколу. Поэтому тема переживает поколения защитных продуктов. Сигнатуры меняются, инструменты меняются, домены меняются, но базовый принцип остаётся тем же: спрятать обмен там, где сеть ждёт увидеть скучные запросы имён.
Для чего используют DNS-туннелирование
В легальной среде DNS-туннели применяют в лабораториях, на учениях, при проверке сетевой политики и в демонстрациях. Команда безопасности может поднять свой домен, свой авторитетный сервер, свой тестовый клиент и проверить, видят ли средства защиты такой канал. Такой тест полезен, если согласован заранее и проходит в контролируемой среде.
В атакующей среде картина другая. DNS-туннель помогает вредоносной программе получить команды от управляющего сервера, отправить небольшие фрагменты данных, проверить связь с оператором или обойти плохо настроенный фильтр. Для кражи многогигабайтного архива DNS подходит плохо. Для токенов, конфигураций, списков файлов, учётных данных, небольших документов или команд управления скорости может хватить.
Ещё один сценарий связан с обходом ограничений в публичных сетях. Иногда Wi-Fi в гостинице или аэропорту закрывает веб-доступ до авторизации, но DNS-запросы пропускает. Технически через такую дыру можно организовать туннель. Юридически и организационно это уже не «находчивость», а обход чужой политики доступа. Для компании разницы между «я просто проверял» и «я вывел данные» может не быть, если пользователь сделал всё без разрешения.
Популярные инструменты вроде iodine и dnscat2 полезно знать не для того, чтобы запускать их в чужих сетях, а чтобы понимать следы. Названия появляются в отчётах, лабораторных стендах и правилах детектирования. Защитник должен узнавать характерный профиль: длинные случайные поддомены, необычные типы записей, резкий рост запросов к одной зоне, большие DNS-ответы, постоянные обращения от одного хоста.
Какие признаки выдают DNS-туннель
Один странный DNS-запрос ещё не доказывает атаку. Современный интернет сам по себе выглядит как мусорный контейнер из длинных идентификаторов, CDN-имён, рекламных трекеров и облачных служебных зон. Если резать всё длинное и некрасивое, первым пострадает бизнес, а не злоумышленник. Детектирование DNS-туннелей строится не на эстетике имени, а на поведении.
Подозрение вызывают длинные и случайные поддомены. Особенно если один внутренний хост за короткое время генерирует сотни или тысячи уникальных имён внутри одной зоны. Поддомены могут выглядеть как base32: много однотипных букв и цифр, мало естественных слов, высокая энтропия. Иногда встречается модифицированный base64, но чистый base64 в DNS-именах использовать неудобно.
Отдельно смотрят на типы записей. TXT-запросы сами по себе нормальны: SPF, DKIM, DMARC, проверки владения доменом, служебные записи. Но рабочая станция, которая внезапно начинает часто спрашивать TXT у странной зоны, уже выглядит иначе. NULL-записи встречаются редко в легитимном клиентском трафике, поэтому всплеск NULL почти всегда заслуживает внимания. A и AAAA тоже нельзя игнорировать, потому что туннели могут маскироваться под самые обычные запросы адресов.
Размер ответов тоже важен. Крупные DNS-ответы, ответы почти под старый UDP-лимит 512 байт, использование EDNS(0), переходы на TCP/53 и признаки фрагментации помогают отличить обычный резолвинг от попытки тащить полезную нагрузку. Для сетевого уровня подойдут IDS/IPS, Zeek, Suricata и DNS-логи с нормальной разбивкой по полям, а не просто строка «что-то спросили у кого-то».
Для SOC полезнее смотреть на связку признаков:
- один хост создаёт много запросов к одному домену или поддоменной зоне;
- имена длинные, случайные и почти не повторяются;
- часто встречаются TXT, NULL или редкие типы записей;
- DNS-ответы заметно крупнее обычных ответов для рабочих станций;
- запросы идут с равномерным интервалом, похожим на маяк;
- клиент пытается обращаться к внешним DNS-серверам напрямую, минуя корпоративный резолвер;
- подозрительные DNS-запросы инициирует неизвестный процесс на конечной машине.
Последний пункт часто важнее красивых графиков. Если браузер и системный резолвер создают ожидаемый шум, вопросов меньше. Если неизвестный файл из пользовательского профиля начинает генерировать длинные DNS-запросы к свежему домену, разговор с владельцем устройства будет коротким. Желательно без театра, но с изоляцией машины.
Как защищаться без топора и суеверий
Самый плохой способ борьбы с DNS-туннелями выглядит соблазнительно: запретить всё длинное, всё TXT, всё редкое, всё некрасивое. Через час после такого решения начнут ломаться почта, облака, проверки владения доменами, контейнерные платформы, CDN, телеметрия и очередной внутренний сервис, который «никто не трогал с 2018 года, но он критичен». DNS нельзя чистить топором. DNS надо контролировать.
Первый слой защиты простой: рабочие станции не должны отправлять DNS-запросы куда захотят. Клиенты должны ходить только к корпоративным резолверам. Прямой исходящий DNS на внешние адреса стоит блокировать, если конкретному серверу такая свобода не нужна по архитектуре. Иначе часть трафика сразу уйдёт мимо логирования, фильтрации и расследования.
Второй слой — нормальные DNS-логи. Нужно хранить имя, тип записи, источник, время, ответ, размер, код ответа, резолвер и связь с пользователем или устройством. Лог без контекста превращается в цифровой песок. Лог с контекстом помогает понять, какой процесс создал запрос, какой пользователь сидел за машиной, какие сетевые соединения шли рядом и что ещё делал хост.
Третий слой — поведенческие правила. Сигнатуры известных инструментов помогают, но не закрывают тему. Туннель можно переписать, домен сменить, кодирование изменить. Зато поведение обмануть сложнее. Большой объём уникальных поддоменов, высокая энтропия, редкие типы записей, крупные ответы и регулярность запросов дают хороший профиль риска.
Четвёртый слой — контроль DoH и DoT. Зашифрованный DNS полезен пользователю в недоверенной сети, но в корпоративной среде бесконтрольный DoH ослепляет классический анализ на межсетевом экране. Когда браузер отправляет DNS-запросы внешнему провайдеру поверх HTTPS, старый контроль UDP/53 уже не видит содержимое. Выход зависит от политики компании: централизованный корпоративный DoH, контроль приложений, прокси с расшифровкой там, где это законно и оправдано, плюс мониторинг на уровне конечных устройств через EDR.
Практический минимум для сети выглядит так:
- разрешить исходящий DNS только корпоративным резолверам;
- заблокировать прямые обращения клиентов к внешним DNS-серверам;
- вести подробные DNS-логи и передавать их в SIEM;
- строить правила по длине имён, энтропии, числу уникальных поддоменов и редким типам записей;
- следить за TXT, NULL, крупными ответами, EDNS(0), TCP/53 и фрагментацией;
- использовать Zeek или Suricata для разбора DNS на сетевом уровне;
- связывать DNS-события с EDR, пользователями, процессами и сетевыми соединениями;
- добавить защитный DNS-фильтр, RPZ или аналогичный механизм блокировки известных вредоносных доменов;
- описать политику DoH и DoT, чтобы приложения не уводили резолвинг в тёмную зону.
Как проверять защиту легально
DNS-туннелирование не нужно превращать в запретную легенду. Защитнику надо понимать механику, иначе расследование будет похоже на гадание по логам. Но проверять туннели надо в своей инфраструктуре, на своём домене, с согласованным сценарием и понятной целью. Лаборатория решает задачу без попыток лезть в чужие сети и потом объяснять охране, что «исследовательский интерес» случайно совпал с обходом правил доступа.
Хороший тест строят вокруг вопросов, а не вокруг желания запустить модный инструмент. Видит ли резолвер длинные уникальные поддомены? Срабатывают ли правила на TXT и NULL? Попадает ли событие в SIEM? Связывается ли DNS-запрос с процессом на рабочей станции? Замечает ли IDS крупные ответы и переход на TCP/53? Понимает ли SOC, какой домен контролирует тестовая сторона и почему поток запросов не похож на нормальный DNS?
Если после теста команда получает только красивый отчёт с зелёными галочками, пользы мало. Нужны конкретные изменения: новое правило, новый дашборд, новая блокировка прямого DNS, корректная политика DoH, понятный порядок изоляции хоста. Без таких изменений тест превращается в корпоративный ритуал. Ритуалы безопасность не усиливают, зато хорошо смотрятся в презентациях.
Почему DNS-туннели не исчезают
DNS-туннели живут не из-за гениальности злоумышленников. Они живут из-за архитектурной привычки считать DNS фоном. Сеть постоянно спрашивает имена, резолверы постоянно отвечают, администраторы постоянно боятся сломать доступ. На этом фоне маленький скрытый канал чувствует себя неплохо.
DNS нельзя просто отключить. DNS нельзя полностью заменить одним фильтром. DNS нельзя считать безопасным только потому, что протокол родился в инфраструктурной зоне и не похож на пользовательский чат. Каждое DNS-имя является объектом сети, а не декоративной строкой. Имя уходит наружу, ответ возвращается внутрь, между ними появляется смысл. Иногда нормальный, иногда вредоносный.
Урок OzymanDNS и всех последующих туннелей простой: служебный трафик тоже остаётся трафиком. Если компания не смотрит в DNS, компания добровольно теряет один из самых информативных слоёв сетевой телеметрии. DNS-запросы показывают, куда смотрят приложения, какие домены ищут пользователи, какие процессы пытаются связаться с внешним миром и где вредоносный код проверяет канал управления.
Хорошая безопасность редко выглядит эффектно. Запрет прямого DNS, нормальные логи, корреляция с EDR, правила по энтропии, контроль DoH, аккуратные исключения для бизнес-сервисов. Никакого кино, зато меньше шансов узнать об утечке из чужого отчёта. В кибербезопасности это уже почти роскошь.
FAQ
DNS-туннелирование всегда означает атаку?
Нет. DNS-туннелирование используют в лабораториях, на учениях и при проверке сетевой защиты. Проблема начинается, когда туннель запускают без разрешения, применяют для обхода политики доступа, управления вредоносным кодом или вывода данных из сети.
Почему DNS-туннель трудно заметить?
DNS-трафика в сети много, а сам протокол почти всегда разрешён. Один длинный запрос может оказаться легитимным шумом от облачного сервиса. Надёжнее смотреть на поведение: количество уникальных поддоменов, длину имён, энтропию, типы записей, размер ответов и процесс, который создаёт запросы.
Какие типы DNS-записей чаще используют для туннелей?
Часто встречаются TXT и NULL. Также туннели могут использовать A, AAAA, MX и другие типы записей, если инструмент так устроен. CNAME возможен в отдельных случаях, но неудобен для произвольной полезной нагрузки и не является главным вариантом.
Почему в поддоменах чаще используют base32, а не обычный base64?
DNS-имена регистронезависимы и ограничены по допустимым символам. Обычный base64 содержит символы вроде +, / и =, которые плохо подходят для DNS-имён. Поэтому туннели чаще используют base32 или модифицированный base64 без проблемных символов.
Зачем упоминать лимиты 63 и 253 символа?
Лимиты объясняют, почему DNS-туннели медленные и шумные. Одна метка доменного имени ограничена 63 октетами, а привычная человекочитаемая запись полного имени обычно упирается примерно в 253 символа. Данные приходится дробить на маленькие части и передавать серией запросов.
DoH защищает от DNS-туннелей или мешает защите?
Для пользователя в недоверенной сети DoH может повысить приватность DNS-запросов. В корпоративной сети бесконтрольный DoH мешает классическому анализу DNS на межсетевом экране, потому что запросы уходят поверх HTTPS. Поэтому компаниям нужна отдельная политика DoH и мониторинг на конечных устройствах.
Можно ли просто запретить TXT-запросы?
Полный запрет TXT быстро сломает легитимные сценарии: SPF, DKIM, DMARC, проверки владения доменом и часть облачных сервисов. Лучше строить правила по поведению: кто спрашивает TXT, как часто, у каких зон, с какой длиной имён и какими ответами.
Какие инструменты помогают искать DNS-туннели?
На сетевом уровне полезны Zeek, Suricata, DNS-логи резолверов и правила в SIEM. На конечных устройствах помогает EDR, потому что EDR показывает процесс, который создал подозрительный DNS-запрос. Для лабораторных проверок часто вспоминают iodine и dnscat2, но тестировать такие инструменты нужно только в согласованной среде.