ВСЕ ЗАПИСИ

Статьи,заметки

SOCKS5 прокси на PHP через TOR

Бывают такие ситуации, когда нужно срочно зайти на какой-либо сайт, а этот сайт заблокирован Роскомнадзором. В таком случае можно зайти на сайт через Tor, либо через браузер, в котором включены плагины для обхода блокировок. Ну а если компьютера рядом нет, вы находитесь не дома и под рукой только смартфон? Может помочь влючение в настройках Хрома опции "сжимать трафик", но я заметил, что этот вариант не всегда срабатывает. Или можно поставить приложение Orbot, но не факт, что оно заработает на вашем смартфоне.

Для себя я выбрал другой способ обхода блокировок на смартфоне: у меня есть собственный домашний веб сервер, который всегда доступен онлайн, там работают много разных скриптов, выполняющих нужные мне задачи, почему бы не поставить туда ещё и скрипт прокси? Заодно было самому интересно написать свой прокси на PHP.

Прежде всего, на компьютер, где будет работать прокси, следует установить Tor Browser , или Vidalia-bundle, либо скачать Expert Bundle, - последняя ссылка, - это чистый Tor с необходимыми библиотеками, этого будет вполне достаточно для работы скрипта. Перед началом серфинга через прокси нужно будет запустить tor.exe, это приложение расположено в подкаталоге с соответствующим именем Tor, в каталоге основной программы, TorBrowser или Vidalia. Я запускаю его прямо из php скрипта, - скрипт запускает bat-файл с командной строкой для старта tor.exe, отключаю его также из скрипта, запустив батник, убивающий процесс tor. Никаких дополнительных настроек в самом tor'е можно не задавать, он запускается с дефолтными настройками, за 2-3 секунды, пока вы будете набирать в поле ввода адрес сайта, на который собираетесь зайти, тор уже будет готов к работе.

Вот собственно, часть кода для для получения страниц через Тор (используем curl)

$user_agent = "Mozilla/4.0 (compatible; MSIE 6.01; Windows NT 5.0)";
$timeout = 300;
$fn=$_SERVER['SCRIPT_FILENAME'];
$pn=basename($fn);
$fn=str_replace($pn,'',$fn);//расположение файла для записи куки,находится в том же каталоге, что и скрипт
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $u_rl);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
curl_setopt($ch, CURLOPT_USERAGENT, $user_agent);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_COOKIEJAR, $fn.'cookie.txt');
curl_setopt($ch, CURLOPT_COOKIEFILE, $fn.'cookie.txt');
curl_setopt($ch, CURLOPT_PROXY, '127.0.0.1:9050');//дефолтный адрес и порт TOR в Windows
curl_setopt($ch, CURLOPT_ENCODING, 'gzip,deflate');
curl_setopt($ch, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5);
curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL, TRUE);
$data = curl_exec($ch);
curl_close($ch);
echo $data;//выводим страницу в браузер

Далее, полученную страницу необходимо обработать, - заменить локальные ссылки в html-коде на абсолютные.
Вот например, абсолютная ссылка <a href="http://grani.ru/About/m. 13482.html">ссылка1</a>
а вот локальные: <a href="About/ m.3482.html" >ссылка2</a>,  <a href="../82.html">ссылка3</a> , которые надо привести к абсолютным, чтобы навигация по сайту была возможной. Также следует исправить пути к изображениям, css-стилям, подгружаемым java-скриптам.

Для преобразования ссылок я использовал функцию uri2absolute()

 показать

Чтобы всё работало, соответственно нужно сделать так, чтобы все ссылки заблокированного сайта открывались через прокси. Я сделал так, чтобы адреса, которые надо открыть передавались в скрипт через GET-запрос, поэтому активные ссылки в коде полученной страницы преобразуются к такому виду: http://url_скрипта?link=тут_url_ссылки

Вытаскиваем ur_ссылки из GET-запроса:
$u_rl=urldecode ($_SERVER['QUERY_STRING']);
$u_rl=str_replace('link=','',$u_rl);
$u_rl=trim($u_rl);
.....................................
curl_setopt($ch, CURLOPT_URL, $u_rl);

Для поиска ссылок в коде страницы был использован PHP Simple HTML DOM Parser

ПРИМЕРЫ

<php
include('simple_html_dom_mod.php');

/*вытаскиваем ссылки на файлы css-стилей
код html:
<link rel="stylesheet" href="css/style.css" type="text/css" media="screen" />
*/

$html = file_get_html('http://veterock.com');
foreach($html->find('link') as $element)
{echo $element->href . '<br>';}

/*вытаскиваем ссылки на файлы javascript
код html:
<script type="text/javascript" src="js/jquery.min.js"></script>
*/

foreach($html->find('script') as $element)
{echo $element->src . '<br>';}

//Получение url картинок на странице

$html = file_get_html('http://demotivators.to');
foreach($html->find('img') as $element)
{echo $element->src . '<br>';}

//Получение url внутри форм
//<form action="url_страницы">

$html = file_get_html('http://google.com');
foreach($html->find('form') as $element)
{echo $element->action . '<br>';}

//Получение ссылок на странице

$html = file_get_html('http://netz.ru');
foreach($html->find('a') as $element)
{echo $element->href . '<br>';}
?>

А теперь о кодировке. Страницы на кириллице, загруженные с помощью curl и обработанные PHP HTML DOM parser очень часто отображаются в браузере неправильно. Мой скрипт прокси использует кодировку windows-1251, и соответственно сайты в кодировке utf-8 показывают нечитаемый текст. Поэтому в скрипт был добавлен метод определения кодировки страниц и задействована принудительная перекодировка текста из utf-8 в windows-1251 таким способом: $html = iconv('utf-8','windows-1251//IGNORE',$html);
Надёжный метод определения кодировки удалось разработать не сразу,- в интернете часто встречается код, где с помощью PHP HTML DOM parser определяется заголовок meta http-equiv="Content-Type" и через регулярные выражения находится значение charset, но я убедился, что этот метод работает ненадёжно, вероятно из-за того, что значение кодировки может быть записано в коде по-разному: в одинарных кавычках, в двойных, или вообще без кавычек. Я использовал свой способ, - просто прочитать содержимое тега <head>, и если там не найдено значение "windows-1251", то страница конвертируется в utf-8, - это срабатывает на 100%
Готовый код:
$h=$html->find('head',0);
$pos1=stripos($h, 'windows-1251');
if ($pos1>0){} else
{$html = iconv('utf-8','windows-1251//IGNORE',$html);}

Но это ещё не всё, что касается кодировки. Несмотря ни на что, некоторые сайты всё-равно могут выдавать страницы неправильно, - местами в тексте попадаются куски в таком виде: болезни свиней, хотя большая часть текста отображается нормально. Было просмотрено множество тем на различных форумах, в основном там советуют использовать фукции iconv(), или mb_convert_encoding(). Но, как оказалось, это можно устранить только таким способом: заменить в файле simple_html_dom.php строку
$converted_text = iconv($sourceCharset, $targetCharset, $text);
на
$converted_text = $text;

В исходнике, ссылка на который приводится в конце статьи, уже сделаны необходимые исправления.

Также следует обратить внимание вот на эту строку в опциях curl:
curl_setopt($ch, CURLOPT_ENCODING, 'gzip,deflate');
включение распаковки страниц, в случае, если сервер отдаёт содержимое в сжатом виде, иначе текст будет отображаться в виде закорючек, точек, или вопросительных знаков.

Особенности работы скрипта

Этот скрипт в текущей реализации, конечно, не может полноценно заменить TorBrowser. Не всегда правильно подгружаются css-стили и изображеня с заблокированных сайтов, из-за того, что в скрипте не предусмотрена обработка запросов в формах, то на многих сайтах нельзя будет авторизоваться, и не будет работать поиск. Также невозможно зайти на сайты, которые находятся на облачном хостинге CloudFlare, - из-за срабатывания cloudflare DDOS protection.
Ещё следует учесть, что на некоторых сайтах, к примеру, http://rutracker.org может сломаться навигация по страницам.
Базовым url для него будет rutracker.org, но когда мы переходим на форум, видим, что ссылки там имеют такой вид: http://rutracker.org/forum/ viewforum.php?f=2285, функция uri2absolute() преобразует эту ссылку в http://rutracker.org/viewforum.php?f=2285, если по ней перейти, получим ответ "Страница не найдена". Поэтому для таких случаев придётся добавлять в скрипт дополнительную процедуру генерации base_url под конкретный сайт (можно посмотреть в моём исходнике, как это сделано в файле proxy.php).

В процессе тестирования скрипта был обнаружен ещё один неприятный баг, - при попытке открыть некоторые сайты, нарушалась работа сервера Apache, при этом появляется окно Прекращена работа Apache HTTP Server - искать решение проблемы в интернете, или закрыть программу, и работа сервера приостанавливается, пока это окно не будет закрыто. Возможно это связано с известной проблемой утечки памяти PHP HTML DOM parser.
Поэтому мною была написана программа, которая отслеживает состояние Apache, и принудительно закрывает окно при возникновении ошибки. У меня она запускается вместе с сервером, и постоянно висит в трее. Её можно взять тут в составе готовой сборки веб сервера, или скачать по прямой ссылке

Скачать скрипт прокси

Добавлено: март 2016

©Veterock




комментарии (0)



Имя

Сообщение

введите защитный код


Обновить

Powered by ©Veterock Studio 2013