Привет, Хабр!
Это снова я, тот, кто отвечает за IT-составляющую РосКомСвободы! Ты, наверное, меня помнишь по посту о самопроизвольной активации камеры при открытии страницы с embedded-youtube-видео.
На этот раз у меня история из личной жизни и, на мой взгляд, расследование немного поинтереснее.
Возможно, оно даже имеет запах теории заговора (между Ростелеком'ом (CC: Rostelecom ROSTELECOM-CENTER) и Mail.Ru Group).
Перед вступлением хотелось бы отметить, что на самом деле, этот пост больше месяца пролежал у меня в черновиках, потому что мы с darkk и ValdikSS всё ещё (актуально на 28.02.2020) собираем и анализируем данные об охвате этой проблемы, воспроизводимости, и прочие технические детали. И мы хотели сначала собрать полный набор данных, и только потом публиковать.
Но раз хайп уже пошёл, то, видимо, пришла пора выпустить этот пост наружу (а дополнять новыми данными уже будем по мере их накопления)...
Началась эта история с того, что пару лет назад провайдера, которым я пользовался уже больше 10 лет, купил Эр-Телеком (aka Dom.Ru).
После одной неприятной технической ситуации (здесь был рассказ со всеми деталями, но он занимал слишком много места и уводил статью в другое русло), кончилось всё тем, что, взвесив плюсы и минусы, я перешёл на Ростелеком (да и вариантов-то, в общем, и не было: всех провайдеров в городе купил либо первый, либо второй).
В общем, жил я себе половину января с интернетом от Ростелекома, пока не настал очередной интересный день...
Начался он с того, что по работе я отлаживал некоторые "плюшки" в self-hosted инсталляции Sentry, и мне оказалось необходимым проверить кое-что в Incognito-mode (т.е без всяких uBlock/uMatrix и прочих плюшек), да ещё и по http (в смысле, без SSL).
Представьте себе, насколько же я удивился, когда на странице ошибки Sentry я увидел рекламный баннер:
А открыв DOM-инспектор — обнаружил там такое:
Сначала я заподозрил аддоны, которым было разрешено загружаться в Incognito mode, и отключил их.
И, как мне сначала показалось — это даже помогло. Однако, на самом деле это оказалось хитростью MitM'а: после ещё пары перезагрузок страницы я опять увидел баннер.
Теперь я решил открыть исходный код страницы, (чтобы посмотреть на то, как он выглядит до того, как JS-скрипты его обработают и внесут изменения в DOM).
Там мой взгляд упал на вот такой блок:
Следующим шагом я пошёл искать этот ads.js
в коде Sentry и… таки обнаружил его.
Посмотрел я на всё это и, честно признаться, офигел...
Как раз вчера ночью я, мягко скажем, ругался на апстрим Sentry за вот это вот, и то, что из-за этого мне пришлось довольно ощутимо переделывать процесс деплоя Sentry.
Так что, из-за "подлитого" вчерашней обидой "масла в огонь", я решил, что "они там в Sentry" вообще оборзели уже и попутали берега, и собрался идти и ругаться...
Но по привычке покопал дальше и увидел, что по факту, данный скриптик сам по себе не делает ничего обидного (хотя его существование как таковое, и в частности определение адблока со стороны sentry уже само по себе вызывает вопросы о попутанных берегах, ну да ладно).
Как оказалось, он, как и написано в комментарии, просто выставляет переменную об обнаруженном адблоке в false
и не делает больше ничего.
Но откуда же взялся баннер?!?
Меня начинают одолевать смутные подозрения, что, учитывая тот факт, что Mail.Ru'шный рекламный блок в DOM появляется не всегда, а раз в N перезагрузок, значит, наверное, иногда вместо этого файла отдаётся другой.
На данный момент я всё ещё уверен, что делает это Sentry, и хочу найти какой именно файл оно отдаёт, чтобы пойти и потыкать в него носом разработчиков на гитхабе, что, мол, "некрасиво".
Открываю я, значит, вкладку со скриптом, перезагружаю её несколько раз...
И меня волшебным образом перебрасывает на домен r.analytic.press
, а в качестве параметров передаётся куча трекинговой информации, включая регион и оригинальную ссылку на файл (и все переданные параметры вшиваются в выдаваемый обфусцированный скрипт). Можно было бы разобрать скрипт (тем более, что к текущему моменту я его уже и в самом деле деобфусцировал), но, на самом деле, это опять уход от темы статьи, т.к. его вообще не должно было быть в моём трафике!
Ясное дело, что редиректа на такие подозрительные домены в коде Sentry обнаружено не было.
Кто у нас там следующий подозреваемый на очереди?..
Ага… трафик идёт по HTTP, происходит вторжение в трафик и подстановка "своего"… Уж очень напоминает модель действия Ростелекомовского DPI, который таким же образом всовывает заглушки о заблокированности ресурсов.
Итак, надо проверить, точно ли шкодит Ростелеком? А то, может, я теперь ещё и на него наговорю почём зря?.. Следующим-то, ведь, вариантом у нас среди подозреваемых остаётся только троян, но в это пока не хочется верить (flashforward: и не придётся), т.к. это бы означало либо что моя техническая компетенция слишком переоценена, либо что нашёлся кто-то "умнее" меня, раз смог незаметно подсунуть мне троян. А это был бы повод для другой статьи :).
Итак...
Для начала проверяю curl
'ом ссылку на скрипт и… редиректа не происходит, как я не пытаюсь…
Хорошо. Получается следующая вилка вариантов: либо протроянен браузер, либо MitM ещё более хитрый, нежели предполагалось (да).
Чтобы проверить второй вариант я иду обратно во вкладку, где я поймал редирект, и делаю вот так вот:
Проверяю в консоли, и, да, один раз из нескольких происходит 307 редирект на указанный домен.
Проверяю на другом девайсе (в домашней сети) — воспроизводится.
Ну что ж, значит, всё же, не троян. Или, по крайней мере, не у меня на компьютере.
Дальше встаёт вопрос: происходит ли это на CloudFlare, или, всё же, у провайдера (помните, я говорил про DPI?)?
Для начала пробую повторить запросы с серверов, расположенных за пределами квартиры (и не пользующихся ростелекомом).
Не воспроизводится.
А это значит, что шанс того, что дело именно в DPI Ростелекома возрастает. Но пока что — это лишь догадки...
И тут на помощь приходит прекрасная утилита, именуемая Wireshark
.
Открываю её, выбираю интерфейс для снятия дампа трафика, включаю фильтр (чтобы не разбирать лишний трафик), запускаю процесс снятия дампа трафика и воспроизвожу редирект.
После нескольких попыток — виднеется такая вот картина:
Особенно примечателен здесь практически моментальный ответ спустя 15мс (тот который TCP ZeroWindow), а так же то, что сразу же после него приходит реальный ответ от сервера (но cURL
его уже не принимает, т.к. для него это мусор, и шлёт в ответ TCP RST
).
Дальше, анализируя трафик, можно заметить, что у "фальшивого" ответа, с редиректом поле TTL имеет значение 59 (значит он находится в 64-59=5
"скачках" от меня, а настоящий ответ от CloudFlare имеет TTL=54 (в 10 скачках).
Ну что ж… Нужно потрейсить и посмотреть, кто же там у находится в этих 5 скачках...
А вот это уже интересно: сам маршрутизатор не представляется, но… оба "окружающих" его IP-адреса принадлежат Ростелекому (!!!):
Что крайне недвусмысленно намекает на то, что ответ приходит с оборудования, стоящего где-то на сети Ростелекома.
К счастью ли, или к сожалению, но знакомые из "tech-board" Роскомсвободы, которые помогали мне всё это дебажить, ValdikSS и darkk (за что им огромное спасибо) не смогли воспроизвести это на "своих" ростелекомовских линках, так что, судя по всему, это крайне регионозависимо.[1]
К слову, хоть это и зависимо от региона, но не зависимо от целевого сайта:
1) если обращаться не в CloudFlare'вским серверам, а, например, к серверу darkk, то редирект так же воспроизводится (хотя в оригинале его сервер отдаёт 404
), но MitM-DPI это не смущает, он всё равно подсовывает свою рекламу :) Кстати, интересный артефакт этой проблемы — darkk, собирая при тестах трафик со своей стороны, обратил внимание на то, что от меня приходили подтверждения получения пакетов, которые сервер не отправлял. Т.е. уровень, на котором происходит эта "подтасовка" трафика — просто до жути топорный…
2) на самом деле, я не единственный и у людей это воспроизводится на других сайтах:
ValdikSS нашёл вот эти вот случаи: раз и два(ч) (не открывайте, если рядом находятся дети, а то некоторые анонимусы запостили в тот тред эротику),
а darkk — вот эти: раз и два.
В общем,
Во-первых, это вызывает очень яркие воспоминания о похожем поведении у мобильных операторов, которые вставляют свою рекламу (которая ещё, порой, и подписки включает),
Во-вторых, вызывает вопрос к Rostelecom: вам что, клиенты (включая большинство государственных учреждений) приносят так мало денег, что без продажи юзерского трафика и аналитики "налево" (сторонним компаниям) никак не обойтись?
В то, что описанное выше — случайность, я не поверю ни за какие коврижки.
В то, что DPI неподконтролен вам и сам хулиганит — поверить готов, но, сами понимаете, к вам тогда встаёт другой вопрос.
В-третьих, как и было предсказано, технологии которые (якобы) направлены на "защиту" (опять же, "якобы"): фильтрацию трафика от "запрещённой информации", вполне себе используются для набивания чьих-то карманов деньгами…
В-четвёртых, мне кажется, что лучше бы уж наши доблестные депутаты вместо того чтобы изобретать "сувенирный" интернет и строить виртуальный Железный Занавес, лучше бы направили свою законотворческую деятельность в позитивное русло и запретили бы провайдерам (всем, и "проводным", и "мобильным") вмешиваться в трафик и вставлять туда что ни попадя (особенно — непрошенную рекламу).
Ну и, подводя итоги, мне хочется сказать, что, похоже, уже точно настал тот момент, когда больше нельзя ходить в интернет не через туннель, с endpoint'ом поднятым где-нибудь на "своём" (арендованном) VPS в стране, где сетевой нейтралитет закреплён на законодательном уровне.
Иначе твою "душу" (в смысле, "цифровой след") продавать будет не только какой-нибудь FaceBook или Google, но даже твой провайдер интернета.
[1] Те тезисы, которые используют сноску сюда уже немного устарели, т.к. та часть статьи была написана до того как мы с darkk и ValdikSS начали масштабное исследование этой проблемы (не просто всеросийское, но и всемирное, используя в т.ч. такие проекты, как RIPE Atlas). Но я решил, что имеет смысл оставить эту часть как есть, по крайней мере до того, как мы будем готовы выложить результаты исследования (или, может, отдельным постом?).