- PVSM.RU - https://www.pvsm.ru -
В этом посте я приведу небольшое исследование механизма блокировки сайтов Ростелекомом, а также покажу способы ее обхода без применения различных туннелей до сторонних хостов (прокси, vpn и пр.). Вероятно это применимо и к некоторым другим провайдерам.
HTTP-сайты РТ уже некоторое время блокирует по URL, а не по IP.
При блокировке в ответ приходит редирект вида 95.167.13.50/?st=0&dt=<IP>&rs=<URL> [1], где <IP> — IP, к которому подключался браузер, <URL> — 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 <!DOCTYPE HTML> <html lang="ru" xmlns:fb="http://www.facebook.com/2008/fbml"> <head> <meta charset="utf-8"> <title> Грани.Ру: Главное </title> ...
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 <!DOCTYPE HTML> <html lang="ru" xmlns:fb="http://www.facebook.com/2008/fbml"> <head> <meta charset="utf-8"> <title> Грани.Ру: Главное </title> ...
Т.е. найдя способ восстановить заголовки, можно обходить блокировку. Очевидно, это не самый доступный способ.
Очевидно, что блокировки сайтов у РТ на ручном контроле.
Не все сайты из реестра блокируются. Как минимум, есть несколько HTTPS-сайтов, которые никак не блокируются.
Обычно HTTPS-сайты блокируются по IP, иногда провайдер лезет и в HTTPS, подставляя свой сертификат, в таком случае происходит блокировка по URL.
Иногда HTTPS-сайт из реестра блокируется только по HTTP (соответственно по URL, а не по IP) и спокойно доступен по HTTPS.
В ходе ряда экспериментов были выявлены следующие принципы работы блокировки:
Проверка происходит только в первой строке, если в начало запроса вставить пустую строку, то запрос проходит.
Если URL равен "/", то ищется только название метода.
При добавлении лишнего пробела после названия метода запрос также проходит без проблем, если URL не равен "/".
По всей видимости считается, что URL закончился, когда встречаются символы пробел, "?" или "/". Если дописать к URL какой-то иной символ, то запрос проходит. В том числе, если дописать символ перевода строки, т.е. убрать " HTTP/1.1" из запроса.
Таким образом, приходим к следующим способам обхода:
Я выбрал реализацию на базе 3proxy. В его состав входит плагин, который позволяет модифицировать все передаваемые данные на основе регулярных выражений. При этом прокси довольно легкий и нетребовательный, возможна установка на обычный роутер.
В соответствии с вышеизложенным наиболее удобными вариантами на практике представляются добавление лишнего заголовка перед Host и модификация заголовка Host. Очевидно, модификация Host предпочтительнее, т.к. не увеличивает размер запроса. Я регулярно использую этот метод для того, чтобы самому решать какую информацию мне можно потреблять.
Но вообще оба варианта легко настраиваются:
pcre_rewrite cliheader dunno "Host:" "X-Something: 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000rnHost:"
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 [3] внес весьма интересное замечание:
Стоило вам присмотреться к трафику, который приходит на интерфейс от Ростелекома. Вероятно, 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, затем приходит пакет с нормальным ответом сайта.
Однако система не отбрасывает второй пакет, а своеобразно объединяет с первым.
Т.е. приходят пакеты1HTTP/1.1 302 Found Connection: close Location: http://95.167.13.50/?st=0&dt=192.237.142.117&rs=grani.ru/2HTTP/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 <!DOCTYPE HTML> ...А приложение видит это
так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 <!DOCTYPE HTML> ...Это наблюдается и в Windows и в Linux.
Но приведенное правило iptables действительно решает вопрос.
Так что +1 способ обхода.
Этот способ можно использовать и на шлюзе/роутере. Правило при этом конечно же нужно добавлять в цепочку FORWARD.
Автор: peter23
Источник [4]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/rostelekom/81364
Ссылки в тексте:
[1] 95.167.13.50/?st=0&dt=<IP>&rs=<URL>: http://95.167.13.50/?st=0&dt=<IP>&rs=<URL>
[2] здесь: http://habrahabr.ru/company/enterra/blog/241732/
[3] ValdikSS: http://habrahabr.ru/users/valdikss/
[4] Источник: http://habrahabr.ru/post/249433/
Нажмите здесь для печати.