Нашли три аномалии, у всех разное поведение.
Сообщение Что происходит с DNS в России? Ищем признаки цензуры. Разбор #26 появились сначала на Теплица социальных технологий.
В рубрике «Разбор Теплицы» мы в режиме реального времени разбираемся в определённой проблеме, новостях интернет-цензуры и рассказываем:
В России что-то происходит с DNS (системой получения информации о доменах) — и происходит давно.
Например, 8 сентября 2021 года Роскомнадзор заблокировал у нескольких крупных операторов, с помощью ТСПУ (техсредства «противодействия угрозам»), на час с 21:00 до 22:00 публичные DNS 1.1.1.1 и 8.8.8.8, это задокументировали независимые специалисты. Через несколько дней «Ростелеком» разослал внутреннее предложение закрепить эту блокировку на постоянной основе. В октябре 2024 года Cloudflare включил по умолчанию расширение TLS ECH, скрывающее домен назначения (SNI) при установке соединения; с 5 ноября 2024 года зафиксирована блокировка TLS-сессий с этой сигнатурой не через TCP RST, а через тихий дроп пакета после ее обнаружения, что вынуждает браузер откатываться на обычное, открытое соединение.
Мы решили самостоятельно проверить, как работают разные DNS в России на разных ресурсах и какую роль в их ограничении играет ТСПУ.
Что мы решили измерить? Узлы фильтрацииДля изоляции узлов фильтрации (ТСПУ) измерительная инфраструктура развернута на пяти независимых точках:
Сделали опрос резолверов по нескольким группам доменов.:
Различать два эти случая важно, так как для каждого нужны разные меры противодействия: VPN/обфускация трафика решает первое, но бессильна против второго — там нужна смена DNS.
Что мы нашлиСразу скажем: классической блокировки, сброса соединений или недоступности целых подсетей, на наших тестовых узлах мы не нашли. Зато мы обнаружили необъясненную подмену DNS-ответа у части резолверов для части доменов. Мы делали разбор этих адресов.
Тогда мы назвали эти адреса «заглушками РКН». Но при более подробной проверке оказалось, что это не совсем точное описание. По этим адресам отдается настоящий, рабочий контент Cloudflare, а не пустой отбойник, мы проверили это напрямую curl’ом с явным SNI на signal.org через адрес 8.47.69.6, причём не только с VPS, но и через обычный домашний интернет в России.
Как мы отличали «шум» от реальных аномалийПервый проход по логам показал: для части доменов ответ на российском узле отличался от ответа на всех проверенных зарубежных узлах. Прежде чем что-либо интерпретировать, эту выборку нужно было очистить от шума, иначе метод «повтор IP там, где его не должно быть» дает ложные срабатывания на любом anycast/CDN-сервисе
Важное методологическое наблюдение: стабильность, высокая повторяемость, сама по себе еще не признак вмешательства. Например, whatsapp.com и youtube.com дают воспроизводимые, узло-зависимые ответы со 100%-й повторяемостью и это ровно то, что можно объяснить штатной географической балансировкой нагрузки у самих провайдеров, а не подменой. Отличать «аномалию» от «шума» позволяет только сопоставление с контрольной группой: если то же самое происходит и с nvidia.com/microsoft.com, которые пока не блокируют и не собираются блокировать, дело может быть не в цензуре.
После вычитания «шума »в данных остается одно заметное семейство ответов: 8.47.69.N / 8.6.112.N, где N ∈ {0, 6, 8}. 8.6.112.0/24 по данным ARIN зарегистрирован за Cloudflare, Inc. (origin AS13335). При этом сеть не входит в публикуемый Cloudflare список IP Ranges, который предназначен для настройки allowlist на origin-серверах и не покрывает весь внутренний/продуктовый диапазон компании. Иными словами, обнаружение адреса вне публичного списка не означает, что адрес принадлежит кому-то другому.
Как мы нашли признаки подменыДля автоматического выявления подмены использовался простой принцип: если один и тот же IP-ответ повторяется у нескольких доменов, которые физически не связаны общей инфраструктурой (например, signal.org — собственные сервера Signal, meduza.io — за Cloudflare, te-st.org — за Cloudflare), это статистически аномально и указывает на общий источник подмены, а не на совпадение.
Метод не использует внешние базы данных о владельцах IP и не делает предположений о «правильных» адресах заранее — он просто ищет повторы там, где их не должно быть, что позволяет находить аномалии без необходимости заранее знать, что именно искать. Легитимность или нелегитимность каждого найденного совпадения мы проверяли дополнительно вручную. Домены за одним CDN-провайдером могут законно делить общий IP, такие случаи мы засчитывали как совпадение, а не подмену. Отличить одно от другого помогло то, какие конкретно домены оказались в одной группе.
Как мы исключили MITMПроверка TLS-сертификата показала, что соединение к 8.8.8.8/1.1.1.1 устанавливается с подлинной инфраструктурой Google/Cloudflare (сертификаты действительны, выпущены легитимными CA Google Trust Services и SSL.com соответственно), что исключает классический MITM-перехват с подменой сертификата на пути к самому резолверу. Трассировка подтверждает, что трафик из российских узлов действительно попадает в собственную сеть этих провайдеров (AS15169 для Google), а не перенаправляется на посторонний адрес.
Отсюда следует вывод: аномальный ответ по адресам 8.47.69.x/8.6.112.x не является результатом перехвата трафика на маршруте между клиентом и DNS Google/Cloudflare, соединение до самого резолвера подлинное. Если подмена и происходит, то она встроена в логику ответа на стороне резолвера (см. классификацию 2.4), либо является легитимным поведением инфраструктуры, которое имитирует подмену внешне.
Почему ответ похож на настоящий CloudflareСхема адресации Cloudflare для доменов под ее защитой, две A-записи в двух соседних /24 с одинаковым последним октетом:
signal.org 104.18.10.47 , 104.18.11.47 → октет 47
meduza.io 104.18.0.79 , 104.18.1.79 → октет 79
cdnjs.cloudflare.com 104.17.24.14 , 104.17.25.14 → октет 14
аномалия (класс B/C) 8.47.69.0 , 8.6.112.0 → октет 0
аномалия (класс A) 8.47.69.6 , 8.6.112.6 → октет 6
аномалия (AdGuard) 8.47.69.8 , 8.6.112.8 → октет 8
Аномальный ответ во всех трех вариантах воспроизводит внутреннее соглашение Cloudflare (парные /24 с общим последним октетом), а не выглядит как произвольная подстановка IP, типичная для инжектора на пути (ТСПУ в таких случаях обычно отдает один фиксированный IP-заглушку без такой структуры). Это аргумент в пользу происхождения ответа от инфраструктуры Cloudflare, а не от стороннего перехватчика, но это не окончательное доказательство.
Три разных сценария, которые мы нашли Класс A. Дифференциальный сигнал, только заблокированные домены, вне зависимости от протокола шифрования| резолвер | узлы | протоколы | ответ | заблокированных | контрольных задето |
| RU-msk, RU-spb, EU-vpn-SPB | udp_53, dot_853, doh_443 | 8.47.69.6, 8.6.112.6 | 4 | 0 | |
| AdGuard | RU-spb | udp_53, dot_853, doq_853, doh_443 | 8.47.69.8, 8.6.112.8 | 4 | 0 |
Повторяемость внутри класса A от 53.3% до 100%, у Google на RU-spb/doh_443 — 100%. Ключевая деталь: у Google этот ответ появляется на RU-Msk, RU-SPb и EU-vpn-SPb (VPN-выход через домашний ШПД в Санкт-Петербурге) и не появляется ни на одном из узлов без РФ-маршрута, то есть эффект зависит именно от маршрута, а не от DNS как такового. При этом cdnjs.cloudflare.com, включенный в ту же матрицу тестирования, ответ не меняет, задет только заблокированный набор. Это единственный класс, где дифференциальный тест (реакция только на заблокированные домены, при чистом контроле) пройден полностью.
Данные по DoT и DoH здесь важны отдельно: ответ 8.47.69.6 приходит и по каналам, где контент запроса зашифрован (DoT/DoH). Внутри TLS-сессии ТСПУ не может подменить DNS-ответ, не разрушив сессию (это привело бы к ошибке валидации на клиенте, а не к тихой подстановке IP), значит этот конкретный ответ сформирован на стороне, которая владеет приватным ключом сессии, то есть самим резолвером Google (или тем, кто отвечает ему как источник ответа для самого резолвера). Это сужает круг возможных причин появления аномалий класса A до действий Google/Cloudflare, реагирующей на маршрут запроса. Но зачем по такой логике исключать cdnjs.cloudflare.com — открытый вопрос.
Класс B. Resolver-side, ответ не зависит от узла-наблюдателя, но задевает контроль«Яндекс» и НСДИ отдают этот ответ 8.47.69.0, 8.6.112.0 со всех измерительных узлов. Затронуты 4 заблокированных домена и cdnjs.cloudflare.com, который не входит в блокировочные списки. Повторяемость от 53.3% до 100% (максимум у NSDI/FI-VPS — 100%).
Отсутствие зависимости от маршрута здесь ожидаемо и объяснимо инфраструктурно: «Яндекс» и НСДИ всегда обращаются к серверам из России, независимо от того, откуда вы сами их спрашиваете, поэтому «одинаковый ответ с любого узла» не отличает пока resolver-side цензуру от resolver-side не-цензурной особенности (например, ECS/anycast-роутинга самого вышестоящего сервера). Единственное, что не укладывается в нейтральную версию — участие cdnjs.cloudflare.com, домена, который не блокируется.
Гипотеза о «списке РКН» не подтверждается. Возможно, речь об инфраструктурной особенности ответа Cloudflare для upstream-запросов из РФ. Важное уточнение: мы пока не проверяли напрямую, ведет ли себя вышестоящий сервер «Яндекса»/НСДИ так же, как Cloudflare.
Класс C. РФ-специфично, зависимость от маршрута, но задевает тот же контрольCloudflare (RU-Msk, все протоколы включая DoH/DoT) и NextDNS (RU-Msk + RU-SPb, все 4 протокола) отдают тот же 8.47.69.0, 8.6.112.0 только с РФ-узлов, при этом cdnjs.cloudflare.com снова затронут. Повторяемость у Cloudflare/RU-Msk 100% по всем трем протоколам.
Формально класс C ближе к «признаку in-path перехвата» из методологии (результат меняется в зависимости от точки наблюдения), но структура ответа и участие DoH/DoT делают версию in-path-инжекции маловероятной по той же логике, что и в классе A. ТСПУ не может модифицировать шифрованный ответ незаметно для клиента. Более вероятное объяснение – то, что географическая маршрутизация запроса до вышестоящего сервера (edns-client-subnet или anycast-нода) приводит к тому же результату, что и у «Яндекса» и НСДИ, но проявляется только при РФ-адресе клиента, а не при РФ-адресе резолвера.
Что все это значитЧто в итоге? Есть ли блокировка?
Мы пока не знаем и продолжаем копать дальше. Три класса найденной аномалии объясняются по-разному, и общего объяснения для всех трех не нашлось: у Google эффект одинаково цепляет оба российских узла независимо от протокола шифрования; у Cloudflare как резолвера — только один из двух российских узлов, и смена заявленной подсети клиента ответ не меняет.
Содержимое по подставленному адресу оказалось настоящим и полным. При этом обычная загрузка той же страницы в браузере через то же домашнее подключение (без ручного указания IP) прошла медленно, с потерей части картинок и верстки, то есть что-то все же мешает работе сайта, но не полностью и не для всех запросов.
Похоже, часть запросов при обычной загрузке страницы не проходит, хотя основной адрес и основной документ загружаются полностью. Есть ли в этом признаки блокировки, мы не можем утверждать стопроцентно. Ранее мы уже писали о похожем поведении, блокировке уже настоящего адреса на уровне SNI (Разбор #20), увиденная нами аномалия подтверждает наш разбор.
За рамками этого исследования остались децентрализованные системы (OpenNIC, Namecoin, Emercoin, GNU Name System), альтернативные протоколы (DNSCrypt, ODoH) и малоизвестные региональные резолверы, они требуют другого инструментария и отдельной проверки.
Что можно сделать с этими аномалиями? Технические рекомендации Администраторам сайтов и разработчикам