Исследование механизма блокировки сайтов Ростелекомом и способы ее обхода02.02.2015 14:33
В этом посте я приведу небольшое исследование механизма блокировки сайтов Ростелекомом, а также покажу способы ее обхода без применения различных туннелей до сторонних хостов (прокси, vpn и пр.). Вероятно это применимо и к некоторым другим провайдерам.Результат работы блокировкиHTTP-сайты РТ уже некоторое время блокирует по URL, а не по IP.При блокировке в ответ приходит редирект вида 95.167.13.50/? st=0&dt=&rs=, где — IP, к которому подключался браузер, — URL, который он запрашивал. Если просмотреть передаваемый трафик, то становится видно, что перезаписывается лишь начало ответа сервера, остальное остается как есть.
Это выглядит примерно так
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 равен »/», то ищется только название метода.При добавлении лишнего пробела после названия метода запрос также проходит без проблем, если URL не равен »/».По всей видимости считается, что URL закончился, когда встречаются символы пробел,»?» или »/». Если дописать к URL какой-то иной символ, то запрос проходит. В том числе, если дописать символ перевода строки, т.е. убрать » HTTP/1.1» из запроса.
Кодирование URL (urlencode) не помогает преодолеть цензуру, в том числе в разных регистрах. Даже если закодировать начальный слэш (%2F), то запрос блокируется, хотя веб-сервер такого уже не понимает.
Далее ищется заголовок Host.Причем ищется в том же пакете.Причем ищется с обязательным соответствием виду «Host:
». Любой лишний символ или изменение регистра названия заголовка (host, HOST) позволяет запросу пройти.Изменение регистра символов самого домена однако не помогает, блокировка срабатывает.
Способы обхода
Таким образом, приходим к следующим способам обхода: Добавление пустой строки в начало запроса. Не все веб-серверы понимают, в частности 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
© Habrahabr.ru