ANTICHAT.RU    VIDEO.ANTICHAT.RU    НОВЫЕ СООБЩЕНИЯ    ФОРУМ  

???????? RU ?????? ? RU ??????? ? ????? ???????. ? ??? ?????? ????!



ViKing – ?????? ????????? ??? ??????? ????????? ????? ?????????!

Вернуться   ????? ??????? > ???????????? ? ?????????? > ?????????
   
Ответ
 
Опции темы Поиск в этой теме Опции просмотра

pproxy - прокси на PHP
  #1  
Старый 24.11.2008, 20:54
Аватара для bons
bons
Участник форума
Регистрация: 20.12.2007
Сообщения: 295
Провел на форуме:
2 недели 6 дней

Репутация: 31 ±

Wink pproxy - прокси на PHP

Однажды мне понадобился прокси-сервер, работающий не как демон/служба а в контексте процесса веб-сервера. Подходящего не нашел поэтому написал свой, очень простой и достаточно юзабельный.

Описание

Состоит из двух частей. На удаленный веб-сервер заливается первая часть прокси, написанная на PHP - скрипт pproxy.php. На локалхосте запускается вторая часть прокси, реализованная на Perl (скрипт plocal.pl), которая прослушивает порт как HTTP-прокси. На этот локальный HTTP прокси настраивается, например, браузер.

Скрипты

pproxy.php - первая, удаленная часть прокси, на PHP:

PHP код:
<?php

//$secret = 'pproxypass';

if(isset($_POST['query']) && isset($_POST['host']))
{
    if(isset(
$secret) && ($_POST['secret'] != $secret))exit;
    
header('Content-type: application/octet-stream');
    @
set_time_limit(0);
    
$query base64_decode(str_replace(' ''+'$_POST['query']));
    list(
$host$port) = explode(':'base64_decode($_POST['host']));
    if(!
$port)$port 80;
    
$ip gethostbyname($host);
    if(
$fp = @fsockopen($ip$port$errno$errstr20))
    {
        
fwrite($fp$query);        
        while(!
feof($fp))
        {
            
$answer fread($fp1024);
            echo 
$answer;
        }
        
fclose($fp);
    }
    exit;
}
?>


plocal.pl - вторая, локальная часть прокси, на Perl:

Код:
use HTTP::Daemon;
use MIME::Base64 ();
use Getopt::Long;
use POSIX ":sys_wait_h";
use strict;

my $user_agent = 'Mozilla/5.0 (X11; U; Linux i686; ru; rv:1.9.0.4) Gecko/2008102920 Firefox/3.0.4';

my $errheader = "HTTP/1.1 200 OK\x0D\x0AContent-Type: text/plain\x0D\x0A\x0D\x0A";
my $errmsg1 = $errheader . 'Could not connect to server';
my $errmsg2 = $errheader . 'Could not connect to pproxy';

my ($pproxyhost, $pproxyport, $pproxyurl);
my ($tunnelhost, $tunnelport);
my ($pproxy, $bindport, $tunnel, $secret);
my ($destaddr, $destport, $desturl);

#Вывод справки
Usage() if @ARGV==0;

#Задание опций
GetOptions(
         "px=s"		=> \$pproxy,
         "bp=s" 	=> \$bindport,
         "tpx=s"	=> \$tunnel,
         "pwd=s"	=> \$secret
     );
die "need pproxy.php url" unless $pproxy;


#Получение параметров
$pproxy =~ /http:\/\/([\w\.\-]+)(:\d*)?\/(.+)/;
$pproxyhost = $1; $pproxyport = substr($2, 1); $pproxyurl = '/' . $3;

defined($pproxyport) || ($pproxyport = 80);
defined($bindport) || ($bindport = 8008);

if(defined($tunnel))
{
	$tunnel =~ /http:\/\/([\w\.\-]+):(\d*)?/;
	$tunnelhost = $1; $tunnelport = $2;

	$destaddr = $tunnelhost;
	$destport = $tunnelport;
	$desturl = $pproxy;

	print "# tunnelhost = $tunnelhost\n";
	print "# tunnelport = $tunnelport\n";
}else{
	$destaddr = $pproxyhost;
	$destport = $pproxyport;
	$desturl = $pproxyurl;
}

print "# pproxyhost = $pproxyhost\n";
print "# pproxyport = $pproxyport\n";
print "# pproxyurl = $pproxyurl\n";
print "# bindport = $bindport\n\n";

$|=1;
my %children;
my $slave;

#Прием подключений
my $master = HTTP::Daemon->new(	LocalPort => $bindport,
				LocalAddr => 'localhost', 
				Reuse=>1)
|| die "Can't start server ($@)";
&MainProc($slave) while $slave = $master->accept;

sub MainProc
{
		my $conn = shift;

		#Прием HTTP-запроса
		my $request = $conn->get_request();
		
		#Ответвление процесса(потока)
		my $pid = fork();
		unless(defined($pid))
		{
			print "# Erorr couldn't fork\n";
			close $conn;
			return;
		}

		if($pid)
		{
			close $conn;
			$children{$pid}++;
			foreach(keys %children )
			{
				my $kid = waitpid($_, &WNOHANG);
				delete $children{$_} if($kid == -1 || $kid == $_);
			}
			return;
		}

		#Преобразование HTTP заголовка
		$request -> remove_header('Proxy-Connection');
		$request -> remove_header('Keep-Alive');
		$request -> header(Connection=>'close');
		my $host = $request -> header('Host');
		my $http = $request -> as_string();
		my $head_end = index ($http, "\x0A\x0A") + 2;
		my $head = substr ($http, 0, $head_end);
		my $post = substr ($http, $head_end);
		$head =~ s/\x0A/\x0D\x0A/g;
		$http = $head . $post;
		$http =~ s/http:\/\/$host//;
		my $time_start = time;
		
		#Отправка запроса прокси и прием результата
		SendToPProxy(	MIME::Base64::encode($host),
				MIME::Base64::encode($http),
				$conn
					);

		my $time_end = time;
		
		#Лог
		print &TranslateTimeHour($time_end), "   ", $host,
			" (", &TranslateTime($time_end - $time_start),
			")\n";

		close $conn;
		exit;
}

sub SendToPProxy
{
	my $dest_host = shift;
	my $query_content = shift;
	my $clientsock = shift;
	
	my $proxysock = IO::Socket::INET->new(Proto=>'tcp',PeerAddr=>$destaddr,PeerPort=>$destport);
	unless($proxysock)
	{
		syswrite($clientsock, $errmsg2, length($errmsg2));
		return; 
	}
	
	my $post_query;
	$post_query = 'secret=' . $secret . '&' if defined($secret);
	$post_query .= 'host=' . $dest_host . '&query=' . $query_content;
	my $postlen = length($post_query);

	my $request = "POST $desturl HTTP/1.0\x0D\x0A".
			"Host: $pproxyhost:$pproxyport\x0D\x0A".
			"Accept: */*\x0D\x0A".
			"Content-Type: application/x-www-form-urlencoded\x0D\x0A".
			"Content-Length: $postlen\x0D\x0A".
			"User-Agent: $user_agent\x0D\x0A".
			"Connection: close\x0D\x0A\x0D\x0A" . $post_query;

	syswrite($proxysock, $request, length($request));
	my ($result, $buffer, $response);
	my $contentstart = -1;
	my $count = 0;
	while(1)
	{
		$result = sysread($proxysock, $buffer, 1024);
		last if !defined($result) || !$result;

		if($contentstart == -1)
		{
			$response .= $buffer;
			last if length($response)>65535;
			$contentstart = index($response,"\x0D\x0A\x0D\x0A");
			next if $contentstart == -1;
			$buffer = substr($response, $contentstart+4);
		}
		$count += length($buffer);
		syswrite($clientsock, $buffer, length($buffer));
	}
	syswrite($clientsock, $errmsg1, length($errmsg1)) if $count == 0;
	close $proxysock;
}

sub TranslateTime
{
	my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(shift);
	return sprintf "%02u:%02u", $min, $sec;
}

sub TranslateTimeHour
{
	my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(shift);
	return sprintf "%02u:%02u:%02u", $hour, $min, $sec;
}

sub Usage
{
	print "Usage: $0 -px proxy_url [-bp bindport] [-tpx tunnel_proxy] [-pwd secret]\n";
	print "Example: $0 -px http://site.com/proxy/proxy.php -bp 8080\n";
	print "         $0 -px http://site.com/proxy/proxy.php -pwd pproxypass\n";
	print "         $0 -px http://site.com/proxy/proxy.php -tpx http://localhost:8118\n";
	print "\nDefault bind port - 8008\n";
	exit;
}



Использование прокси

Допустим адрес pproxy.php будет http://site.com/proxy/pproxy.php
Тогда локальный скрипт запускается так:
Код:
perl plocal.pl -px http://site.com/proxy/pproxy.php

По умолчанию открывается порт 8008


Построение цепочки прокси

Для примера случай с двумя элементами цепочки.
Есть два веб-сервера с двумя скриптами pproxy:
http://site1.com/proxy/pproxy.php и
http://site2.com/proxy/pproxy.php

Локальный скрипт запускается два раза с такими параметрами:
Код:
perl plocal.pl -px http://site1.com/proxy/pproxy.php
perl plocal.pl -px http://site2.com/proxy/pproxy.php -tpx http://localhost:8008 -bp 8009

Браузер следует настроить на 8009 порт и трафик пойдет по такой цепочке:
localhost -> site1.com -> site2.com -> target

Думаю, несложно будет настроить и на более длинную цепочку.

Запуск через Tor

Если вы используете Tor вместе с Privoxy (по умолчанию на порту 8118)
тогда прокси запускается так:
Код:
perl plocal.pl -px http://site.com/proxy/pproxy.php -tpx http://localhost:8118

Соответственно http://site.com/proxy/pproxy.php - адрес PHP-прокси
К сожалению, через Tor некоторые сайты могут загружаться некорректно,
причины пока неизвестны.

Установка пароля

В pproxy.php раскомментировать строчку,
написать там свой пароль

PHP код:
 $secret 'pproxypass'


в параметрах запуска plocal.pl указать его же.
Код:
perl plocal.pl -px http://site.com/proxy/pproxy.php -pwd pproxypass


Примечания

1. Если вы хотите в качестве элемента цепочки узел SOCKS, то Privoxy поможет вам (см пример с Tor)
2. pproxy.php очень компактен и легко может быть внедрен в код сайта,
Возможно это немного повысит ваш уровень анонимности.
3. Не стоит забывать что веб-серверы ведут логи и восстановить истинный источник нетрудно даже по цепочке
4. Альтернативный клиент(Delphi/Pascal) с открытым исходным кодом доступен тут http://dump.ru/file/3320224

Спасибо за совет: b3, AkyHa_MaTaTa

Последний раз редактировалось bons, 29.08.2009 в 11:32. Причина: версия 0.5
 
Ответить с цитированием

  #2  
Старый 27.11.2008, 13:36
Аватара для DVD_RW
DVD_RW
Banned
Регистрация: 27.04.2008
Сообщения: 683
Провел на форуме:
1 месяц 1 неделю

Репутация: 21 ±



По умолчанию

эм...а прокси хттп\с или сокс?
 
Ответить с цитированием

  #3  
Старый 27.11.2008, 14:11
Аватара для nerezus
nerezus
Pagan Heart
Регистрация: 12.08.2004
Сообщения: 3,791
Провел на форуме:
2 месяца 2 недели 1 день

Репутация: 353 ±



Отправить сообщение для  nerezus с помощью ICQ
По умолчанию

http
Перенес в избранное. кстати.
__________________

You see me walking still sane!
But in the dark I feel
hell! (c) Illdisposed
 
Ответить с цитированием

  #4  
Старый 27.11.2008, 23:50
Аватара для KemSucks
KemSucks
Познающий
Регистрация: 06.01.2008
Сообщения: 76
Провел на форуме:
3 дня 17 часов 34 минуты

Репутация: 2 ±

Отправить сообщение для  KemSucks с помощью ICQ
По умолчанию

может как нить на https прикрутить можно?
 
Ответить с цитированием

  #5  
Старый 28.11.2008, 15:46
Аватара для bons
bons
Участник форума
Регистрация: 20.12.2007
Сообщения: 295
Провел на форуме:
2 недели 6 дней

Репутация: 31 ±

По умолчанию

нет, HTTPS тут реализовать почти невозможно. HTTPS прокси - он как и сокс основан на постоянном соединении и непрерывном обмене данными. А здесь, как видишь, обмен данными сводится к отсылке HTTP-запроса браузера и получению результата.

Последний раз редактировалось bons, 28.11.2008 в 16:15.
 
Ответить с цитированием

  #6  
Старый 28.11.2008, 22:57
Аватара для jumperby
jumperby
Новичок
Регистрация: 26.07.2007
Сообщения: 8
Провел на форуме:
3 часа 56 минут 9 секунд

Репутация: 0 ±

По умолчанию

А оградить это дело от чужих глаз можно как-то? логин:пасс какой-нибудь.
Связка ActivePerl + Opera 9.62 + Proxy, дает в результате тормоза, не в курсе как это можно исправить?
хттпс идет как я понял не через проксик, а через впн?

Последний раз редактировалось jumperby, 28.11.2008 в 23:54.
 
Ответить с цитированием

  #7  
Старый 29.11.2008, 05:32
Аватара для b3
b3
Постоянный
Регистрация: 05.12.2004
Сообщения: 647
Провел на форуме:
2 недели 5 дней

Репутация: 62 ±



Отправить сообщение для  b3 с помощью ICQ
По умолчанию

Цитата:
1. Понятно, что время соединения через такой прокси ограничено максимальным временем выполнения скрипта.
Обычно 30 секунд или 1 минута, это зависит от настроек в php.ini

допиши в начало кода РНР, строки:
Цитата:
set_time_limit(0);
ignore_user_abort();

Время выполнения - неограничено. Скрипт не останавливаеться после дисконекта клиента.
 
Ответить с цитированием

  #8  
Старый 29.11.2008, 16:10
Аватара для bons
bons
Участник форума
Регистрация: 20.12.2007
Сообщения: 295
Провел на форуме:
2 недели 6 дней

Репутация: 31 ±

По умолчанию

дописал set_time_limit(0);
добавил авторизацию в самом простом виде.
 
Ответить с цитированием

  #9  
Старый 30.11.2008, 01:26
Аватара для jumperby
jumperby
Новичок
Регистрация: 26.07.2007
Сообщения: 8
Провел на форуме:
3 часа 56 минут 9 секунд

Репутация: 0 ±

По умолчанию

Подскажите пожалуйста, почему ActivePerl 5.10 так жестко начинает жрать память через минуту юзания проксика, заодно начинает жрать и браузер (опера и файрфокс, ведут себя одинаково). Как это исправить?
п.с. выкиньте с фиксом версию (сет тайм лимит + авторизация)
 
Ответить с цитированием

  #10  
Старый 30.11.2008, 14:58
Аватара для bons
bons
Участник форума
Регистрация: 20.12.2007
Сообщения: 295
Провел на форуме:
2 недели 6 дней

Репутация: 31 ±

По умолчанию

да, память и процессорное время оно ест немилосердно, это расплата за небольшой размер скрипта.
Если слабая машина то могу предложить
1. Снизь приоритет выполнения процесса, это можно сделать в диспетчере задач. (процесс perl.exe)
2. Отключи многопоточность, тогда запросы будут выполняться последовательно и не так загружать процессор.

закомментируй эти строчки
Код:
...
		#my $pid = fork();
		#unless(defined($pid))
		#{
		#	print "# Erorr couldn't fork\n";
		#	close $conn;
		#	return;
		#}

		#if($pid)
		#{
		#	close $conn;
		#	$children{$pid}++;
		#	foreach(keys %children )
		#	{
		#		my $kid = waitpid($_, &WNOHANG);
		#		delete $children{$_} if($kid == -1 || $kid == $_);
		#	}
		#	return;
		#}
...


и еще команду exit:

Код:
...
		close $conn;
		#exit;
}
...

Последний раз редактировалось bons, 30.11.2008 в 15:11.
 
Ответить с цитированием
Ответ


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Books PHP FRAGNATIC PHP, PERL, MySQL, JavaScript 186 21.02.2010 02:41
Proxy FAQ foreva Чужие Статьи 12 04.01.2008 12:15
Что такое Php? PAPA212 Болталка 13 28.12.2007 20:44
Безопасность в Php, Часть Iii k00p3r Чужие Статьи 0 11.07.2005 20:02
Защищаем Php. Шаг за шагом. k00p3r Чужие Статьи 0 13.06.2005 12:31



Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра


Быстрый переход

plohihzagrusok.net


Powered by: vBulletin Version 3.0.x
Copyright ©2000 - 2019, Jelsoft Enterprises Ltd.

ANTICHAT.RU