Показать сообщение отдельно

  #5  
Старый 16.08.2008, 12:14
Shadow_p1raT
Участник форума
Регистрация: 09.03.2008
Сообщений: 193
Провел на форуме:
2140897

Репутация: 267
Отправить сообщение для Shadow_p1raT с помощью ICQ
По умолчанию

--:[ Название : Socks5 изучение продолжается:BIND ]:--
--:[ Автор : Jinn, ZaeB.uS, _http://zaeb.us ]:--

o--:[ 1 | Введение ]:--o

Вот решил написать еще одну статью на тему соксов, некоторые личности скажут:"Вот понаписал статей, мог бы все в одной изложить!", объясню мою точку зрения на данную проблему: я считаю, что если бы весь этот материал(с первой статьи по текущую) содержался в одной статье, то статья бы получилась довольно большой и сложной для понимания! В этот раз рассмотрим метод не connect как в прошлых статьях, а bind. Если вы первый раз читаете про соксы и не знакомы с этим протоколом, то желательно прочитать мои статьи:"Организация работы php скрипта через socks5 сервер","PHP + socks5(авторизация по методу username/password)", либо RFC. Как и в прошлые разы перечислю на чем я все это гонял,ничего не изменилось=):
* Win XP SP2
* Opera 8.52
* Денвер
* 3proxy-0.5.3i(ЗАРАЗА)

o--:[ 2 | Общие принципы ]:--o

Для тех кто не знаком что это такое отправлю в гугл и коротко обьясню=) Bind используется для открытия порта, а по теме этой статьи видно что мы рассматриваем сокс => открывать порт будем на стороне socks5-сервера. А для чего это нужно? Это может использоваться в соединениях, которые требуют открытия порта на стороне клиента(мы ведь прячемся за сокс, т.е для удаленного сервера клиентом является сокс), хорошим примером требующим открытия порта на стороне клиента является ftp. Я думаю многие видели вопросы на форумах типа: "Ftp клиент не работает с http проксей", после долгой дискуссии выяснялось, что хлопчик пытается подключиться к фтп серверу через http проксю в активном режиме. И соответствующий ответ: "Юзай пассивный режим!". А что же это такое активный и пассивный режим? Если кто изучал ftp протокол те знаю, что в нем используется 2 вида соединения: клиент--->сервер по которому идут команды клиента и сервер--->клиент:альтернативный порт, который используется для передачи результата команды клиента(ls,get,put). Но вот проблема: с htpps проксями же такое не пройдет... Мы ведь не можем открыть порт на стороне https прокси, а для передачи данных его открыть нужно. Именно поэтому при использовании прокси сервера и активного режима вы не получите листинг директории,etc. Тогда приходиться юзать пассивный режим, там все открытия порта происходят на стороне ftp-сервера, а клиент из-за прокси просто к ним подключается и получает ответы на команды =) Но в соксах все по другому, тут есть механизм открытия порта на стороне сокс сервера и называется он bind. Т.е при использовании сокса не нужно переходить в пассивный режим(хотя возможно :-), но нужно тоже постараться чтобы открыть порт на соксе, а именно изучить данную небольшую статью =)

o--:[ 3 | Реализуем BIND ]:--o

Для чего это нужно разобрались, перейдем к практике и попробуем написать работающие приложение :-)
По RFC предполагается, что bind будет использован только как вторичное соединение, после первого первичного установленного с помощью метода CONNECT, но мы в наших экспериментах нарушим предписания RFC.
Пакеты для бинда порта мы должны слать такие же как и для коннекта, но метод должен быть не connect(01) а bind(02)=). Снова показывать структуру пакета я не буду, если ты ее не знаешь читай статьи [1],[2]. На connect сокс сервером возвращается один ответ, в котором указан статус(ok/error) подключения, с bind'ом все сложнее, соксом предоставляется 2 ответа: первый приходит сразу же после запроса, в нем так же указан статус успешности открытия порта для входящего соединения,а также ip и порт выделенные соксом для входящего соединения, эта информация, в случае надобности, может быть предоставлена серверу-приложению через первичное соединение как адрес для взаимодействия. Возможно что ip будет отличаться от ip сокс сервера, т.к иногда подобные сервера имеют несколько адресов. Второй пакет приходит после внешнего подключения к забинденому порту, там содержится ip и порт подключившегося хоста и статус подключения(коды те же, 0-ok,etc). Эти данные могут быть использованы для решения о дальнейшем взаимодействии(напрмиер ip подключившегося хоста содержится в черных списках, тогда соединение может быть разорвано....но это все на ваше усмотрение)
В принципе никакой сложности это вызывать не должно, после того как мы забиндим порт и получим первый ответ сокса, перед получением данных от подключившегося клиента мы должны будем получить второй пакет и проверять его статус, далее же, если все в порядке, мы сможем получать, отправлять данные как и прежде методами php(fread,fgets,fwrite,feof).
Теперь собственно обсудим что мы будем кодить. Мы не будем работать с ftp и вот почему: в php существуют ф-ции ftp_connect, ftp_put, etc. Но при подключении сначала к соксу а потом попытке передачи через данный сокет файла данными методами определенными для работы с ftp компилятор php верещит, что сокет не подходит => воспользоваться встроенными ф-циями работы с ftp сервером нам не удастся и придется изучать и писать свой класс для работы по протоколу ftp, а это не так то просто и не входит в мои планы....пока=) Но ведь наша цель просто открыть на соксе порт, и получить оттуда отправленные сервером данные, поэтому мы поступим вот как:
Код:
-- забиндим порт на соксе
-- получим ответ сокса, со статусом открытия порта, ip и порт выделенный для входящих подключений
   [ Мы за сервер ]
     -- теперь поработает за сервер и откроем подлючение не используя сокса(хм..хотя никто вам не мешает это сделать) с помощью fsockopen и выделенным адресом для входящего подключения
     -- отправим туда произвольные данные 
     -- закроем подключение
   [ сервер накрылся медным тазом ]
-- теперь мы получим пакет от сокса, в котором указаны ip и порт подключившегося хоста(т.е нашего)
-- опять получим данные, уже отправленные сервером(опять нами;-)
-- закроем подлючение к соксу
-- выведем все это пользователю
Этим примером мы проверим правильность понимания нами протокола, как мне кажется, данный пример полностью показывает все стороны bind'а, как клиентской стороны так и серверной :-)
Обсудим особенности нашего сегодняшнего кода.
Обычно сокс сервер формирует ответ с типом адреса 01, т.е ip адрес, а не так как мы 03 - доменное имя. Для перевода ip в привычный нам строковый вид, т.е с точками мы будем использовать функцию пхп long2ip, специального для этого предназначенную, но перед этим мы должны будем перевести адрес из hex'а в dec. Кстати существует функция ip2long, которая могла бы пригодиться нам в том случае если бы мы передавали соксу IPv4,но это просто на заметку :-)
Код изначально взят из моей статьи [2] и заточен именно для bind'а...
PHP код:
<?
error_reporting
(0);
$socks_ip    "127.0.0.1"// адрес scoks 5 прокси
$socks_port  =  1080;       // порт сокса
$socks_login "jinn";      // логин для доступа к соксу
$socks_pass  "jinn2";     // пароль

$bind_host "127.0.0.1";
$bind_port 3232;

$socks_server=fsockopen($socks_ip,$socks_port);   // соединяемся с соксом
if($socks_server)
{
   echo
'<meta http-equiv="Content-Language" content="ru"><meta http-equiv=Content-Type content="text/html; charset=windows-1251">';
   
$h=pack("H*",'05020002'); // привествие =)
   
fwrite($socks_server,$h);
   
$result=bin2hex(fread($socks_server,4)); // переводим в hex для дальнейшего сравнения
   
if($result == '0500'// авторизация отсутствует
   
{
      
$auth_ok=1;
   }
   elseif(
$result == '0502'// метод username/password
   
{
      
$len_login chr(strlen($socks_login)); //получаем спец символ соответсвующий ascii коду
      
$len_pass  chr(strlen($socks_pass));  // получаем спец символ соответсвующий ascii коду
  
      
$h=pack("H*","01").$len_login.$socks_login.$len_pass.$socks_pass// формируем пакет с помощью pack()
      
fwrite($socks_server,$h);
      
      
$result=bin2hex(fread($socks_server,4)); // переводим из бинарного режима в hex
      // далее сверяем если код ответа 0, то авторизация успешна,выставляем об этом переменую,в ином случа выводим сообщение об ошибке
       
if($result{3}!=0)
        {
           echo 
"<center><font color=red>Ошибка:аутентификация не прошла!</font></center>";
           
fclose($socks_server);
        }
        else
        {
           
$auth_ok=1;
        }
   }
   else
   {
     echo 
"<center><font color=red>Ошибка:возможно это не socks5 или он не поддерживает данные(00,02) методы аутентификации!</font></center>";
   }
    
   
$list="";
   
// проверяем если авторизация успешна , то начинаем взаимодействие с соксом
   
if($auth_ok==1)
   {
      
$len_h=chr(strlen($bind_host));
      
$h=pack("H*","05020003").$len_h.$bind_host.pack("n",$bind_port); //формируем запрос 
      
fwrite($socks_server,$h);
      
      
$result bin2hex(fread($socks_server,1024));
      
$ver    substr($result,0,2);
      
$status substr($result,2,2);
      
$in_ip     long2ip(hexdec(substr($result,8,8)));
      
$in_port   hexdec(substr($result,16,4));
      echo 
"Адрес для подключения:".$in_ip.":".$in_port."<br>";

       
// проверяем успешность подключения,выводи ошибки
        
if($status == '00')
        {
            
$head  "<br><br><center><font color='blue' size=4>HI!coded by ZaeB.uS</font></center>";
            
$in_socket=fsockopen($in_ip,$in_port);
            
fwrite($in_socket,$head);
            
fclose($in_socket);
            
            
$result bin2hex(fread($socks_server,1024));
            
$ver    substr($result,0,2);
            
$status substr($result,2,2); // тут статус входящего подключения
            
$con_ip     long2ip(hexdec(substr($result,8,8))); // а кто это к нам подключился?ип подключившегося хоста
            
$con_port   hexdec(substr($result,16,4)); // порт негодяя
            
            
echo "Подключившийся хост:".$con_ip.":".$con_port."<br>";
            echo 
"Полученные данные<br><br>";
            
// получаем данные
            
while(!feof($socks_server))
            {
              echo 
fread($socks_server,1024);
            }
        }
        
// определяем ошибку! данные коды ответа взяты из RFC
       
elseif ($status == 1) {echo "<center><font color=red>Ошибка: вина SOCKS-сервера</font></center>";}
       elseif (
$status == 2) {echo "<center><font color=red>Ошибка: соединение запрещено набором правил</font></center>";}
       elseif (
$status == 3) {echo "<center><font color=red>Ошибка: сеть недоступна</font></center>";}
       elseif (
$status == 4) {echo "<center><font color=red>Ошибка: хост недоступен</font></center>";}
       elseif (
$status == 5) {echo "<center><font color=red>Ошибка: отказ в соединении</font></center>";}
       elseif (
$status == 6) {echo "<center><font color=red>Ошибка: истечение TTL</font></center>";}
       elseif (
$status == 7) {echo "<center><font color=red>Ошибка: команда не поддерживается</font></center>";}
       elseif (
$status == 8) {echo "<center><font color=red>Ошибка: тип адреса не поддерживается</font></center>";}
       else {echo 
"<center><font color=red>Ошибка: не определено!RFC в панике! :-)</font></center>";}
    }
    
fclose($socks_server);
}
else
{
   echo 
"<center><font color=red>SOCKS сервер недоступен!</font></center>";
}
echo 
'<br><br><table border="0" cellspacing="1" width="100%" align="center" style="background-color:#000000;"><tr><td width="100%" align="center" style="background-color:#E8E8E8;"><font size=1 color="#292929" face="verdana">[ c0ded by <b>Jinn</b> | 304227033 | http://zaeb.us ] </font></td></tr></table>';

?>
o--:[ 4 | End ]:--o

Да, статья получилась не слишком большой, и возможно вы не узнали из нее ничего нового, но все же я думаю что знать данную инфу нужно, ведь понимание сетевых протоколов является основным=) По прежнему, если возникли предложения или вопросы стучи мне в асю или пиши на мыло, постараюсь дать ответ...

o--:[ 5 | Материалы ]:--o

1.... Организация работы php скрипта через socks5 сервер, Jinn, ZaeB.uS, _http://zaeb.us
2.... PHP + socks5(авторизация по методу username/password), Jinn, ZaeB.uS, _http://zaeb.us

o--:[ Jinn | ZaeB.uS | _http://zaeb.us ]:--o
 
Ответить с цитированием