Перейти к содержимому

 Друзья: Всё для вебмастера | [ Реклама на форуме ]


Rutor
Rutor


[ DDos Услуги. DDos атака. Заказать ДДос ]


PHP + socks5(авторизация по методу username/password)


  • Авторизуйтесь для ответа в теме
В этой теме нет ответов

#1
Jinn

Jinn

    Байт

  • Members
  • Pip
  • 77 сообщений
Название : PHP + socks5(авторизация по методу username/password)
   Автор : Jinn

%===| Введение |===%

Эта статья является продолжением темы взаимодействия php и socks5 сервера. Первую статью "Организация работы php скрипта через socks5 сервер" ты можешь найти на www.zaeb.us или на форуме www.root-access.ru. В ней рассматривалось взаимодействие php и сокса не обремененного аутентификацией. Но соксовые прокси без аутентификации чаще всего - публичные, а работать через них - сжигание своих нервных клеток, а не жировых, как думаю некоторые -). А свои кровные соксы, неважно, как добытые, очень часто, что не без основательно, устанавливаются с авторизацией. Единственным выходом является написание скриптов с поддержкой некоторых схем авторизации. Чем мы сейчас и займемся.
Для понимания данной статьи нужно обладать некоторыми знаниями(начальными), т.к подробно на этих моментам я останавливаться не буду. Желательно: знание протокола socks5(RFC1928 или знать содержание моей первой статьи), язык php.....
Для тестирования я использовал:
* Win XP SP2,
* Frenzy-lite 1.0 установленая на VMware 4.5.1 =)
* Opera 8.52
* Денвер
* оценочная версия какого-то снифера, подойдет любой, его не долго юзать:-)
Для организации socks5 сервера использовались:
  win : bouncer-1.0.rc6-win32, 3proxy-0.5.3i(ЗАРАЗА)
  frenzy : bouncer-1.0.rc6-freebsd-intel
Я писал и отлаживал скрипт на локалхосте, причем сначала на bouncer'е под виндой, потом под frenzy, и чтобы удостовериться в совместимости проверил на 3proxy. А когда код был готов, поднял сокс на удаленной FreeBSD :-)

%===| Кратко о протоколе |===%

Более подробно я описывал протокол в свой первой статье [1]. Сейчас же немного повтоюсь. Данные socks серверу передаются в бинарном виде.
Работа начинается с того, что клиент посылает пакет с данными о поддерживаемых им схемах авторизации, сокс отсылает клиенту ответ, в котором содержится выбраный метод авторизации, далее начинается сам процесс аутентификации.
Существует несколько методов:
	  *  00		аутентификация не требуется (описано в первой моей статье)
	  *  01		GSS-API (см.RFC1961)
	  *  02		USERNAME/PASSWORD (см. RFC1929), как я понял самый распространенный
	  *  03 до 7F  зарезервировано IANA
	  *  80 до FE  предназначено для частных методов
	  *  FF		нет применимых методов
Следующий шагом после аутентификации(если она успешна) является отправление пакета, где указан адрес и порт для коннекта(рассмотрим только его), после чего при успешном коннекте клиент может начинать отсылать данные, которые пройдут путь от сокса к конечному серверу. Данные должны быть представлены в формате задаваемом данной схемой авторизации, но это мы рассмотрим далее.

%===| Изучаем метод аутентификации |===%

Скажу сразу, что когда я начал изучать методы аутентификации у меня не было RFC, я получал данные снифанием трафика после чего анализировал их. Поэтому свой рассказ я буду строить так как изучал я (одновременно покажу методы изучения без документации). Конечно после все свои выводы я проверил по RFC1929....
Для тестов поднимаем пятый носок с аутентификацией по логину:jinn & пассу:jinn2, конечно 3proxy обладает большими возможностями, но для своих экспериментов я пользовался bouncer'ом - это личное дело каждого.
Нам нужно будет отснифать трафик передаваемый сокс серверу и посмотреть как формируются пакеты. Для этого я решил поработать через сокс с каким-либо шеллом :-)
Вот какие данные передаются в момент аутентификации при методе 02(username/password):
  Putty->bouncer
		 0x0000   01 04 6A 69 6E 6E 05 6A 69 6E 6E 32
  bouncer->Putty
		 0x0000   01 00

Т.е передаютя поля:
 *  ver			это как я понял постоянная переменная, т.к постоянно передается именно 01, после я глянул в RFC - так и есть:-)
 *  len username   длина логина
 *  Username	   логин
 *  len password   длина пароля
 *  Password	   пароль
Сервер сверяет полученные данные и отправляет пакет:
 *  ver	  01
 *  status 
	*  00	все в порядке,аутентификация прошла успешно :-)
	*  иное  связь должна быть разорвана

Метод аутентификации меня порадовал - очень прост :-) но эта схема аутентификации не требует особого формирования пакетов, т.е в ней не реализована проверка целостности/конфиденциальности данных. Поэтому после того как аутентификация прошла успешно, можно начинать посылать пакеты с connnect'ом, bind'ом - вообщем дальше все идет как будто аутентификации и не было :-)
Как выяснилось далее Bouncer поддерживает только метод username/password(рассмотренный выше). Это было выяснено методом научного тыка: сначала я слал пакеты с методами 00 и 02, bouncer выбирал 02, тогда когда на пакеты 00 01, 00 03 был ответ FF, т.е данный метод не поддерживается. Чтож проверим 3proxy, может быть сокс от ЗАРАЗЫ поддерживает другие методы?!
В файле конфигурации для сокса было выставлено auth strong, и вот как вел себя сервер. Точно также при предложенных ему методах 02 и 00 происходила авторизация по 02, далее отсылались пакеты на коннект, данные http-серверу - все было ok. Но когда я заменял 02 на что-либо иное(01,03), то сокс выбирал метод 00, т.е без авторизации, но на запрос Connect сокс-сервер отвечал ошибкой 04(хост недоступен). Тем самым недопускал трафик неавторизовавшихся, по его мнению, клиентов. Хотя может я что не так делал :-0. Вообщем мне не удалось найти сокс-сервер с поддержкой других методов. Напишем скрипт с поддержкой хотя бы этого метода.

%===| Практика |===%

Я решил, что за основу возьму код из моей первой статьи и добавлю туда поддержку метода username/password. В прошлой статье мы переводили даные в бинарный режим с помощью самописной ф-ции которая возвращала символ по его ascii коду, в этот раз мы воспользуемся ф-цией php pack(). В этот раз данные типа логина, пароля, доменного имени мы не будем переводить в hex, мы будем передавать их вообще не переводя, они ведь представлены в виде символов... Так же мы не будем использовать наши ф-ции len_test,hex. В предыдущей статье я хотел показать, что очень многие ф-ции php можно заменить своими, но в этот раз я покажу другой путь. Но все останется по прежнему в плане распаковки данных, мы будем использовать точно также  bin2hex(). Для постоянных экспериментов намного удобнеее сделать вебморду для скрипта, а результат выводить в textarea, но это будет не трудно любому человеку знающему php, но если что - стучи, договоримся :-) Т.к наши методы не требуют особого формирования пакетов, то мы вынесем авторизацию в отдельный блок. После того как она будет пройдена начнется взаимодействие с соксом, применимое в обоих случаях (когда схема 02 и когда 00).

Для того чтобы перевести длину в бинарный режим мы поступим вот как, сначала получим длину переменной с помощью strlen, а потом получим специфический символ с помощью chr. Это избавит нас от многих ненужных преобразований переменных.
Порт для подключения мы будем упаковывать с помощью pack("n"), а не как в тот раз самописной функцией.

Далее будет идти код с подробными коментариями:
<?
 error_reporting(0);
 $socks_ip	= "127.0.0.1"; // адрес scoks 5 прокси
 $socks_port  =  1080;	   // порт сокса
 $socks_login = "jinn";	  // логин для доступа к соксу
 $socks_pass  = "jinn2";	 // пароль
 
 $connect_host = "www.zaeb.us"; // доменное имя или ip сервера которому мы будем посылать данные через сокс-сервер =)
 $connect_port = 80;			  // порт
 $path = "/";					 // докумен который мы будем запрашивать у http-сервера,в нашем случае это главная страница
 
 $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($connect_host));
	  $h=pack("H*","05010003").$len_h.$connect_host.pack("n",$connect_port); //формируем запрос 
	  fwrite($socks_server,$h);
	  
	  $result=bin2hex(fread($socks_server,100)); // сичитываем ответ сокса переводим в hex
	  echo "<center>Ответ socks'а при попытке коннекта на хост ".$connect_host.":<b>".$result."</b></center><br>"; // выводим ответ сервера, иногда нужно при тестировании и  изучении протокола
	   // проверяем успешность подключения,выводи ошибки
		if($result{3} == 0)
		{
			$head  = "GET $path HTTP/1.0\r\n";
			$head .= "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; en) Opera 8.52\r\n";
			$head .= "Host: $connect_host\r\n";
			$head .= "Accept: text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1\r\n";
			$head .= "Accept-Language: ru,en;q=0.9\r\n";
			$head .= "Accept-Charset: windows-1252, utf-8, utf-16, iso-8859-1;q=0.6, *;q=0.1\r\n";
			$head .= "Proxy-Connection: close\r\n\r\n";
			fwrite($socks_server,$head);
			// считываем ответ HTTP-сервера через SOCKS-сервер  до конца  =)
			while(!feof($socks_server))
			{
			  echo fread($socks_server,1024);
			}
		}
		// определяем ошибку! данные коды ответа взяты из RFC
	   elseif ($result{3} == 1) {echo "<center><font color=red>Ошибка: вина SOCKS-сервера</font></center>";}
	   elseif ($result{3} == 2) {echo "<center><font color=red>Ошибка: соединение запрещено набором правил</font></center>";}
	   elseif ($result{3} == 3) {echo "<center><font color=red>Ошибка: сеть недоступна</font></center>";}
	   elseif ($result{3} == 4) {echo "<center><font color=red>Ошибка: хост недоступен</font></center>";}
	   elseif ($result{3} == 5) {echo "<center><font color=red>Ошибка: отказ в соединении</font></center>";}
	   elseif ($result{3} == 6) {echo "<center><font color=red>Ошибка: истечение TTL</font></center>";}
	   elseif ($result{3} == 7) {echo "<center><font color=red>Ошибка: команда не поддерживается</font></center>";}
	   elseif ($result{3} == 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://www.zaeb.us ] </font></td></tr></table>';

?>

Как и в первой статье на эту тему я ставил свой целью только показать основы взаимодействия с соксом, поэтому я не разделял ответ http-сервера на заголовок и контент. А в некоторых случаях даже нужно, чтобы все выводилось как получено, особенно при тестах и изучении проокола.

%===| Итог |===%

Конечно меня самого не устраивает поддержка только одной схемы авторизации, но писать поддержку других методов опираясь на RFC мне не улыбается :-( Хочется еще и практики...Может кто подскажет сокс-сервер с поддержкой других методов?
Еще много работы: нужно реализовать bind, udp associate:-)

%===| Материалы |===%
[1] Организация работы php скрипта через socks5 сервер, ]]>http://www.zaeb.us]]>
[2] RFC1928: SOCKS Protocol Version 5
[3] RFC1929: Username/Password Authentication for SOCKS V5

%-----|- Jinn | ZaeB.us | ]]>http://www.zaeb.us]]> -|-----%



--[ ZaeB.uS, ]]>http://zaeb.us]]> ]---
ICQ: 304227033
Jabber: jinn@jabber.prologic.ws
OCC: 82623


Количество пользователей, читающих эту тему: 0

0 пользователей, 0 гостей, 0 анонимных