- Исследование механизма блокировки сайтов «Ростелекомом» и способы ее обхода
- Результат работы блокировки
- Что и как блокируется
- Исследуем глубже
- Способы обхода
- Практическая реализация
- Простой обход блокировки сайтов Ростелекомом на маршрутизаторе MikroTik
- Простой обход блокировки сайтов Ростелекомом на маршрутизаторе MikroTik : 8 комментариев
Исследование механизма блокировки сайтов «Ростелекомом» и способы ее обхода
В этом посте я приведу небольшое исследование механизма блокировки сайтов Ростелекомом, а также покажу способы ее обхода без применения различных туннелей до сторонних хостов (прокси, vpn и пр.). Вероятно это применимо и к некоторым другим провайдерам.
Результат работы блокировки
HTTP/1.1 302 Found Connection: close Location: http://95.167.13.50/?st=0&dt=192.237.142.117&rs=grani.ru/ f-8 Transfer-Encoding: chunked Connection: keep-alive 6d7 .
HTTP/1.1 200 OK Server: nginx/1.2.1 Date: Sun, 01 Feb 2015 17:34:03 GMT Content-Type: text/html; charset=utf-8 Transfer-Encoding: chunked Connection: keep-alive 6d7 .
Т.е. найдя способ восстановить заголовки, можно обходить блокировку. Очевидно, это не самый доступный способ.
Что и как блокируется
Очевидно, что блокировки сайтов у РТ на ручном контроле.
Не все сайты из реестра блокируются. Как минимум, есть несколько HTTPS-сайтов, которые никак не блокируются.
Обычно HTTPS-сайты блокируются по IP, иногда провайдер лезет и в HTTPS, подставляя свой сертификат, в таком случае происходит блокировка по URL.
Иногда HTTPS-сайт из реестра блокируется только по HTTP (соответственно по URL, а не по IP) и спокойно доступен по HTTPS.
Исследуем глубже
- В первой строке запроса ищется название HTTP-метода, пробел, URL, пробел или? или /.
Реагирует на методы GET, POST, HEAD, DELETE, OPTIONS, TRACE. Метод PUT, видимо, забыли, его пропускает. Прочие названия методов тоже пропускает. Названия методов с измененным регистром символов тоже пропускает.
Проверка происходит только в первой строке, если в начало запроса вставить пустую строку, то запрос проходит.
Если URL равен «/», то ищется только название метода.
Способы обхода
- Добавление пустой строки в начало запроса. Не все веб-серверы понимают, в частности nginx не понимает.
- Добавление пробела перед URL. Это понимают популярные веб-серверы. Однако могут быть проблемы в редких случаях (например как здесь)
- Добавление какого-то символа после URL. Очевидно, это должен быть какой-то символ, который проигнорирует веб-сервер, но цензурный агрегат решит, что это часть URL. Я не смог найти такого символа.
- Убрать название протокола и версию (» HTTP/1.1″). В таком случае запрос воспринимается веб-сервером как HTTP/1.0, а в этой версии протокола не было заголовка Host, поэтому со многими сайтами это работать не будет.
- Отправка URL и Host разными пакетами.
Можно просто сначала вызвать send для первой строки запроса (HTTP-метод и URL), а затем обычным образом отправлять остальную часть запроса.
Можно добавить какой-то достаточно большой заголовок (порядка 1530 байт, чтобы наверняка заполнить весь пакет) между этими строками.
Проблем с веб-серверами в таких случаях не выявлено. - Модификация заголовка Host.
Можно менять регистр, добавлять пробелы перед доменом и после него.
Проблем с веб-серверами в таких случаях не выявлено.
Практическая реализация
Я выбрал реализацию на базе 3proxy. В его состав входит плагин, который позволяет модифицировать все передаваемые данные на основе регулярных выражений. При этом прокси довольно легкий и нетребовательный, возможна установка на обычный роутер.
В соответствии с вышеизложенным наиболее удобными вариантами на практике представляются добавление лишнего заголовка перед Host и модификация заголовка Host. Очевидно, модификация Host предпочтительнее, т.к. не увеличивает размер запроса. Я регулярно использую этот метод для того, чтобы самому решать какую информацию мне можно потреблять.
Но вообще оба варианта легко настраиваются:
pcre_rewrite cliheader dunno "Host:" "X-Something: 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\r\nHost:"
pcre_rewrite cliheader dunno "Host:" "HOST:"
# dns-сервера nserver 77.88.8.8 nserver 8.8.8.8 # кэшируем dns nscache 65536 # работе в фоне daemon # подключение плагина, стоит указать полный путь plugin PCREPlugin.ld.so pcre_plugin # одно из правил описанных выше pcre_rewrite . # запуск прокси, опция -a позволяет избавиться от заголовков Forwarded-For и Via proxy -a -p8080
UPD:
@ValdikSS внес весьма интересное замечание:
Стоило вам присмотреться к трафику, который приходит на интерфейс от Ростелекома. Вероятно, DPI подключен параллельно, а не последовательно, и туда приходит только клиентский трафик. Т.к. DPI стоит явно ближе, чем вебсайт, пакет с Location от DPI приходит быстрее, чем реальный первый пакет от сайта, а пакет от сайта уже отбрасывается ядром ОС как ретрансмиссия, поэтому, если вы используете Linux, достаточно одной строки в iptables, чтобы обойти блокировку:
iptables -A INPUT -p tcp --sport 80 -m string --algo bm --string "http://95.167.13.50/?st" -j DROP
Действительно, есть ретрансмиссия. Я смотрел трафик, но очевидно недостаточно внимательно.
Сначала приходит пакет, в котором только HTTP 302 и Location, затем приходит пакет с нормальным ответом сайта.
Однако система не отбрасывает второй пакет, а своеобразно объединяет с первым.
Т.е. приходят пакеты
HTTP/1.1 302 Found Connection: close Location: http://95.167.13.50/?st=0&dt=192.237.142.117&rs=grani.ru/
HTTP/1.1 200 OK Server: nginx/1.2.1 Date: Sun, 01 Feb 2015 17:34:03 GMT Content-Type: text/html; charset=utf-8 Transfer-Encoding: chunked Connection: keep-alive 6d7 .
HTTP/1.1 302 Found Connection: close Location: http://95.167.13.50/?st=0&dt=192.237.142.117&rs=grani.ru/ f-8 Transfer-Encoding: chunked Connection: keep-alive 6d7 .
Это наблюдается и в Windows и в Linux.
Но приведенное правило iptables действительно решает вопрос.
Этот способ можно использовать и на шлюзе/роутере. Правило при этом конечно же нужно добавлять в цепочку FORWARD.
Простой обход блокировки сайтов Ростелекомом на маршрутизаторе MikroTik
Не будем вдаваться в политическую составляющую блокировок сайтов, но терпеть это становится всё сложнее, сайтов блокируют всё больше. Можно конечно ставить плагины для браузеров, но доверия им нет. Можно городить VPN, но устройств много, да и не всегда удобно это.
Стал изучать подробности работы механизма блокировки Ростелекомом неугодных сайтов, и wireshark на пару с гуглом подсказали, что механизм блокировки сайтов более чем примитивен — на неугодные запросы система блокировки у провайдера (DPI) возвращает от имени запрошенного сервера пакет с http переадресацией на страницу блокировки. Пакет же от самого сайта тоже приходит, но не обрабатывается по причине нарушения номера tcp последовательности (TCP-out-of-order) и по сути, являющегося для системы дублем уже принятого, не смотря на отличия в содержании.
Итак, всё что нам нужно для счастья — заблокировать файрволом эти самые ответы от DPI провайдера. Определить их можно по вхождению строки с переадресацией на страницу с информацией о запрете, на момент написания статьи все страницы с описанием запрета у Ростелекома начинаются с «http://95.167.13.50/?», а http-header переадресация пишет перед путём перенаправления «Location:», таким образом фильтровать будем по строке «Location: http://95.167.13.50/?». Полное правило для MikroTik будет выглядеть так:
/ip firewall filter add action=drop chain=forward content="Location: http://95.167.13.50/\?" in-interface=rt protocol=tcp src-port=80
Не забываем экранировать знак вопроса! Так же в примере для снижения нагрузки на процессор роутера указан входящий интерфейс для пакетов, в содержимом которых будем копаться, но это делать не обязательно.
Вот то же самое, но в картинках winbox:
После добавления данного правила в начало списка firewall, раздел filter все сайты стали открываться на всех домашних устройствах.
P.S. После создания этого правила данная страница перестанет полностью открываться по понятным причинам 😉
UPD: Ростелеком внёс небольшие изменения, подробнее в продолжении статьи по ссылке: Ростелеком обновил механизм блокировки сайтов — обходим снова
Простой обход блокировки сайтов Ростелекомом на маршрутизаторе MikroTik : 8 комментариев
1) Предложенный вами пример:
—-
/ip firewall filter add action=drop chain=forward content=»Location: http://95.167.13.50/\?» in-interface=rt protocol=tcp src-port=80
—-
по блокировки пакетов с контентом «Location: http://95.167.13.50» помогает, но лишь частично. На указанную заглушку Ростелекома — http://95.167.13.50 я уже не натыкаюсь. Но на некторые ресурсы зайти не могу, например http://kinozal.tv/ При попытке открыть сайт выскакивает заглушка Онлайм — 77.37.254.90:
http://77.37.254.90/zapret/?sa=104.24.106.53&da=xxx.xxx.xxx.xxx&url=http://kinozal.tv/ Попытки её обойти в виде указания на роутере
—-
/ip firewall filter add action=drop chain=forward content=»Location: http://77.37.254.90\?» in-interface=rt protocol=tcp src-port=80 # или
/ip firewall filter add action=drop chain=forward content=»Location: Location: http://77.37.254.90/zapret/?\?» in-interface=rt protocol=tcp src-port=80 # или даже полная блокировка пакетов с dst. address 77.37.254.90
—-
не помогают. Страница http://kinozal.tv/ просто не открывается вовсе. Предположу, что DPI у Онлайма в этом случае подключён последовательно. И пакеты от kinozal.tv не приходят вовсе. Но почему тогда открываются другие сайты? Если бы DPI был последовательный не открывались бы вообще никакие сайты. А значит я просто не правильно обрабатываю блокировку пакетов. Может как-то иначе? 2) Кстати, при условиии что работает предложенной вами правило «Location: http://95.167.13.50«, а в адрес kinozal.tv добавить точку в конце «http://kinozal.tv./» — сайт открывается. Я так понимаю Микротик добавлять точки в адреса (модифицировать заголовки) не умеет. Не нашёл такого функционала. Есть идеи? 3) Также пару раз наталкивался на заглушку ТТК (Транстелеком) — http://62.33.207.197/ Смоделировать ситуацию сейчас не могу. Потому не могу прокомментировать понять в каких случаях происходило подобное. Помню только то, что блокировка пакетов как и в случае с Онлайм, в этом случает также не срабатывала. Смотреть приходящие пакеты я не умею. Пробовал, но ничего толком не понял. Есть идеи?)
Добрый вечер!
Отвечу по пунктам —
1. Так а какой у вас провайдер то? Онлайм или Ростелеком? Описанная в статье система блокировки эффективна только если она стоит «близко» к клиенту и быстро отвечает, поэтому если блокировка идет у магистральных провайдеров, то вероятно иначе. А если трафик смотреть в wireshark то в первую очередь обратите внимание на пакеты ответа на запрос вашего браузера — нет ли ошибок TCP Dup как на скриншоте. Эта ошибка говорит о «дублях» пакетов. В случае как с DPI от ростелекома это по сути не дубль, а подделка (точнее дубль это как раз настоящий пакет, а первый был подделка)
2. Идея интересная, но проверить сейчас не могу ибо у меня и так всё открывается на базе правила, описанного в статье. А для модификации url можно попробовать использовать proxy в прозрачном режиме. С файрволом это не получится т.к. нарушатся контрольные суммы пакетов.
3. Да, я тоже встречался с такой заглушкой, но это таким образом не обойти и это уже не ростелеком — с аналогичными проблемами сталкиваются даже заграничные пользователи совсем других провайдеров если их трафик идет через ТТК. Сейчас у меня такая ошибка перестала вылезать — или поменялись маршруты или ТТК опомнился и убрал. Хотя трейс подсказывает, что маршрут идёт сейчас не через ТТК 🙂
4. Вы правы, SSL не позволяет промежуточным узлам узнать на какой URL будет запрос, поэтому тут решают иначе, скорее всего по IP.