Socks 5 server in PHP
Posted: Sun Jan 24, 2010 6:32 am
Code: Select all
#!/usr/bin/php
<HEAD>
<META HTTP-EQUIV=Content-Type CONTENT="text/html;
CHARSET=windows-1250">
<TITLE>Serwer Socks 5 proxy dla PHP 4 >= 4.1.0</TITLE>
</HEAD>
<BODY BGCOLOR=#F0F0F0>
<FONT SIZE=3 COLOR="red">
<?php
define("SCRIPT_FILE_NAME", $_SERVER['PHP_SELF']);
/************ Parametry wewnetrzne skryptu *************/
define("HASLO", "runforest"); // opcjonalnie
define("CZAS_AUTORYZACJI", 5); // w sekundach
define("CZAS_BEZCZYNNOSCI_POL", 5); // w minutach
define("CZAS_WYSWIETLANIA_MONITU", 5); // w minutach
/*******************************************************/
/* parametry zewnetrzne skryptu */
$parametry = array('RCV_BUF_SIZE', 'SND_BUF_SIZE',
'CZAS_PRACY_SERWERA', 'PORT', 'IP_INTERFEJS',
'MAX_POLACZEN', 'HASLO_DOSTEPU');
$param_dod = array('HASLO_DOSTEPU', 'POKAZ_POLACZENIA');
/* przetwarzanie i definiowanie parametrow skryptu */
$a = $_POST;
for($i=0;$i<count($a);$i++) {
foreach($parametry as $param)
if((!strcasecmp($param, key($a)))&&(current($a)))
define($param, current($a));
foreach($param_dod as $param)
if(!strcasecmp($param, key($a)))
define($param, current($a));
next($a);
}
/* sprawdzanie czy wszystkie obowiazkowe
parametry skryptu sa podane */
for($i=0;$i<count($parametry);$i++)
if(!defined($parametry[$i]))
exit(MainPage());
/* kompatybilosc z wersja php 4.3.0 */
if(!function_exists("socket_set_option")) {
function socket_set_option($socket, $level, $optname, $optarg){
return socket_setopt( $socket, $level, $optname, $optarg);
}
}
/* ignorujemy przerwania pracy
skryptu przez uzytkownika */
//ignore_user_abort();
/* wlasna funkcja obslugi wyjscia */
register_shutdown_function(exit_program);
/* wylacz buforowanie danych wyjsciowych */
ob_implicit_flush();
/* bezustanny czas pracy skryptu */
ini_set("max_execution_time", 0);
/* ustawiamy pamiec dla skryptu */
if(!ini_set("memory_limit", "100M")) // 100MB
echo('OSTRZE?ENIE: Nie mo?na ustawi?
rozmiaru pami?ci dla skryptu!<BR>');
/* sprawdzamy kompatybilnosc wersji PHP ze skryptem */
list($wer, $major, $minor) = explode(".", phpversion());
if((($wer >= 4)&&($major < 1))||($wer < 4))
exit('Serwer nie dzia?a w wersji PHP < 4.1.0.
Aktualna wersja PHP to ' . phpversion());
/* sprawdzenie autentycznosci hasla */
if(HASLO && strncasecmp(HASLO, HASLO_DOSTEPU, 10))
exit('B??d: Z?e has?o!');
define("SEKUNDA", 1);
define("MINUTA", 60);
define("CZAS_PRACY_SERWERA_SECS",
CZAS_PRACY_SERWERA * MINUTA);
define("WYPISYWANIE_POL",
POKAZ_POLACZENIA=="checked"?true:false);
define("skAutoryzacja", 0);
define("skZapytanie", 1);
define("skBlad", 2);
define("skPolaczenie", 3);
define("skZniszcz", 4);
define("polTCP", "\x01");
define("polUDP", "\x03");
/* potrzebne w celu weryfikacji stanu polaczenia */
define("S_PONOW_PROBE", 11);
$KB_ODEBRANO = 0;
$KB_WYSLANO = 0;
/******** KLASA BAZOWA KLIENTA SOCKS5 PROXY *********/
class TS5Klient {
var $klient;
var $host;
var $UDPklient;
var $UDPaddr;
var $UDPport;
var $bufin;
var $bufout;
var $StanKlienta;
var $TypPol;
var $Timeout;
/* Konstruktor klasy TS5Klient */
function TS5Klient($local) {
$this->klient = $local;
$this->StanKlienta = skAutoryzacja;
$this->isntFree = false;
$this->bufin = "";
$this->bufout = "";
$this->Timeout = 0;
$this->TypPol = polTCP;
}
/* Destruktor klasy TS5Klient */
function Destroy() {
if(is_resource($this->klient))
socket_close($this->klient);
if(is_resource($this->UDPklient))
socket_close($this->UDPklient);
if(is_resource($this->host))
if($this->TypPol == polTCP){
fclose($this->host);
}
else
socket_close($this->host);
$this->StanKlienta = skZniszcz;
}
/* Glowna funkcja tunelujaca dane */
function WyslijOdbierzDane()
{
global $KB_WYSLANO;
global $KB_ODEBRANO;
if ($this->Timeout >= CZAS_BEZCZYNNOSCI_POL * MINUTA)
$this->StanKlienta = skBlad;
if (SND_BUF_SIZE - ($bufc = strlen($this->bufout)) > 1)
{
// socket_clear_error($this->klient);
$this->bufout.=@socket_read(
$this->klient,
SND_BUF_SIZE - strlen($this->bufout)
);
/* Sprawdzanie stanu polaczenia z klientem */
if ($bufc == strlen($this->bufout)) {
if (socket_last_error($this->klient) != S_PONOW_PROBE)
$this->StanKlienta = skBlad;
}
elseif($this->TypPol == polTCP)
$this->Timeout = 0;
}
if ($this->TypPol == polTCP)
{
if ($this->StanKlienta != skPolaczenie)
{
$this->Authorize();
if ($this->Timeout >= CZAS_AUTORYZACJI * SEKUNDA)
$this->StanKlienta = skBlad;
}
elseif (!feof($this->host))
{
$numw = fwrite($this->host, $this->bufout);
if ($numw) {
$this->bufout = substr(
$this->bufout,
$numw,
strlen($this->bufout)
);
$KB_WYSLANO += $numw;
}
$this->bufin .= fread(
$this->host,
RCV_BUF_SIZE - strlen($this->bufin)
);
$numw = @socket_write(
$this->klient,
$this->bufin
);
if ($numw) {
$this->Timeout = 0;
$this->bufin = substr(
$this->bufin,
$numw,
strlen($this->bufin)
);
$KB_ODEBRANO += $numw;
}
}
else
$this->StanKlienta = skBlad;
}
if ($this->TypPol == polUDP)
{
$this->bufout="";
if (@socket_recvfrom(
$this->UDPklient,
$this->bufout,
SND_BUF_SIZE,
0,
$src_addr,
$src_port))
{
if((!strcmp($this->UDPaddr, $src_addr))&&
(!strcmp($this->UDPport, $src_port))&&
(!strncmp($this->bufout, "\x00\x00\x00", 3)))
{
switch($this->bufout[3]) {
case "\x01":
$request_size = 10;
$dst_addr = ord($this->bufout[4]) . "." .
ord($this->bufout[5]) . "." .
ord($this->bufout[6]) . "." .
ord($this->bufout[7]);
break;
case "\x03":
$request_size = ord($this->bufout[4]) + 7;
$dst_addr = socket_gethostbyname(
substr($this->bufout, 5, ord($this->bufout[4]))
);
break;
default:
return 0;
}
$dst_port= ord($this->bufout[$request_size - 2]) * 256 +
ord($this->bufout[$request_size - 1]);
$KB_WYSLANO += @socket_sendto(
$this->host,
substr(
$this->bufout,
$request_size,
strlen($this->bufout)
),
SND_BUF_SIZE,
0,
$dst_addr,
$dst_port
);
$this->Timeout = 0;
}
}
if ((strcmp($this->UDPaddr, "0.0.0.0"))&&
($this->UDPport != 0)&&
(@socket_recvfrom(
$this->host,
$this->bufin,
RCV_BUF_SIZE,
0,
$src_addr,
$src_port)
))
{
$temp_addr = explode(".", $src_addr);
$KB_ODEBRANO+=strlen($this->bufin);
$this->bufin = "\x00\x00\x00\x01" .
chr($temp_addr[0]) . chr($temp_addr[1]) .
chr($temp_addr[2]) . chr($temp_addr[3]) .
chr($src_port / 256) . chr($src_port % 256) .
$this->bufin;
@socket_sendto(
$this->UDPklient,
$this->bufin,
strlen($this->bufin),
0,
$this->UDPaddr,
$this->UDPport
);
$this->Timeout = 0;
}
}
if ($this->StanKlienta == skBlad)
$this->Destroy();
}
/* Autoryzacja klienta Socks 5 */
function Authorize()
{
if ($bufc = strlen($this->bufout))
{
if($this->bufout[0] != "\x05")
$this->StanKlienta = skBlad;
if (($this->StanKlienta == skAutoryzacja)&&($bufc > 2))
if ($bufc == ord($this->bufout[1]) + 2) {
if (socket_write($this->klient, "\x05\x00"))
{
$this->bufout = "";
$this->StanKlienta = skZapytanie;
}
else
$this->StanKlienta = skBlad;
}
elseif($bufc > ord($this->bufout[1]))
$this->StanKlienta = skBlad;
if(($this->StanKlienta == skZapytanie)&&($bufc > 4))
{
switch($this->bufout[3]) {
case "\x01":
$request_size = 10;
break;
case "\x03":
$request_size = ord($this->bufout[4]) + 7;
break;
default:
$this->StanKlienta = skBlad;
}
if($bufc == $request_size)
{
$this->bufout[2] = chr("\x00");
if($this->bufout[3] == "\x01")
$dst_addr = ord($this->bufout[4]) . "." .
ord($this->bufout[5]) . "." .
ord($this->bufout[6]) . "." .
ord($this->bufout[7]);
if($this->bufout[3] == "\x03")
$dst_addr = socket_gethostbyname(
substr($this->bufout, 5, ord($this->bufout[4]))
);
$dst_port= ord($this->bufout[$request_size - 2]) * 256 +
ord($this->bufout[$request_size - 1]);
if(($this->bufout[1] == polTCP)||
($this->bufout[1] == polUDP))
{
$this->UDPaddr = $dst_addr;
$this->UDPport = $dst_port;
$this->TypPol = $this->bufout[1];
$this->bufout[1] = "\x00";
socket_getsockname($this->klient, $serwer_addr);
socket_getpeername($this->klient, $klient_addr);
switch($this->TypPol) {
case polTCP:
if($this->host = fsockopen(
$dst_addr,
$dst_port,
$errcode,
$errstr,
5)
)
{
socket_set_blocking($this->host, false);
}
else
$this->bufout[1] = chr($errcode);
break;
case polUDP:
if(($this->host = socket_create(
AF_INET,
SOCK_DGRAM,
0
)
)&&
(socket_bind(
$this->host,
"0.0.0.0",
rand(50000, 60000))
)&&
($this->UDPklient = socket_create(
AF_INET,
SOCK_DGRAM,
0)
)&&
(socket_bind(
$this->UDPklient,
IP_INTERFEJS,
$temp_port = rand(50000, 60000))
))
{
$this->UDPaddr = $klient_addr;
socket_set_nonblock($this->host);
socket_set_nonblock($this->UDPklient);
$request_size = 10;
$this->bufout[3] = "\x01";
$temp_addr = explode(".", $serwer_addr);
$this->bufout[4] = chr($temp_addr[0]);
$this->bufout[5] = chr($temp_addr[1]);
$this->bufout[6] = chr($temp_addr[2]);
$this->bufout[7] = chr($temp_addr[3]);
$this->bufout[8] = chr($temp_port / 256);
$this->bufout[9] = chr($temp_port % 256);
}else
$this->bufout[1] = "\x01";
break;
}
if(WYPISYWANIE_POL)
switch($this->TypPol) {
case polTCP:
echo('- TCP, od: ' . $klient_addr .
" do: ". $dst_addr . ":" .$dst_port);
break;
case polUDP:
echo('- UDP, od: ' . $klient_addr);
break;
}
switch($this->bufout[1]) {
case "\x00":
if(WYPISYWANIE_POL)
echo('<FONT COLOR="blue">' .' [POWODZENIE]' .
'</FONT><BR>');
$this->StanKlienta = skPolaczenie;
break;
default:
if(WYPISYWANIE_POL)
echo('<FONT COLOR="maroon"> [NIEPOWODZENIE] '.
$errstr . '</FONT><BR>');
$this->StanKlienta = skBlad;
}
}
else {
$this->bufout[1] = "\x07";
$this->StanKlienta = skBlad;
}
socket_write(
$this->klient,
$this->bufout,
$request_size
);
$this->bufout = "";
}
elseif($bufc > $request_size)
$this->StanKlienta == skBlad;
}
}
}
}
/****** KLASA BAZOWA SERWERA SOCKS5 PROXY *******/
class TS5Serwer {
var $clients;
var $server;
function run()
{
global $KB_WYSLANO;
global $KB_ODEBRANO;
echo('<HR><FONT SIZE=3 COLOR="darkblue">');
echo('[Serwer proxy Socks5 na porcie ' .
PORT . ' dzia?a. Mi?ej zabawy]<BR><P>');
echo('</FONT>');
if(WYPISYWANIE_POL)
echo('<U>Po??czenia:</U><BR>');
echo('<FONT SIZE=2>');
$czas_start = time();
$timer = 0;
/* Glowna petla serwera */
while(true)
{
/* Sprawdzanie czy nowy klient jest polaczony */
if($klient = @socket_accept($this->serwer))
if(count($this->clients) < MAX_POLACZEN) {
socket_set_nonblock($klient);
array_push($this->clients, new TS5Klient($klient));
}
else
socket_close($klient);
for($i=0;$i<count($this->clients);$i++)
{
$this->clients[$i]->WyslijOdbierzDane();
if($this->clients[$i]->StanKlienta == skZniszcz)
array_splice($this->clients, $i, 1);
}
$pomc = time() - $czas_start;
/* Blok uaktualniajacy czas dla wszystkich polaczen */
if($timer < $pomc) {
for($i=0;$i<count($this->clients);$i++)
$this->clients[$i]->Timeout+=$pomc - $timer;
$logc += $pomc - $timer;
$timer = $pomc;
if($logc >= (MINUTA * CZAS_WYSWIETLANIA_MONITU)) {
echo('Serwer pracuje ju? przez ' .
(integer)($timer / MINUTA) . ' minut<BR>');
echo('Ilo?? po??cze?: ' .
count($this->clients) . "<BR>");
echo('Wys?ano: ' . round($KB_WYSLANO / 1024) .
'KB, Odebrano: '. round($KB_ODEBRANO / 1024) .
'KB<BR>');
$logc = 0;
}
}
/* Sprawdzanie czasu dzialania serwera */
if((CZAS_PRACY_SERWERA)&&
($timer >= CZAS_PRACY_SERWERA_SECS))
{
for($i=0;$i<count($this->clients);$i++)
$this->clients[$i]->Destroy();
break;
}
usleep(1000);
}
socket_close($this->serwer);
echo('</FONT>');
echo('<U>Koniec pracy serwera...</U>');
}
function TS5Serwer($addr, $port, $wno = 5)
{
$this->clients = array();
if(!function_exists("socket_create"))
exit('B??d: Brak zainstalowanych funkcji sieciowych!');
if((!$localsrv = socket_create(AF_INET, SOCK_STREAM, 0))||
(!socket_set_option($localsrv, SOL_SOCKET, SO_REUSEADDR, 1))||
(!socket_bind($localsrv, $addr, $port))||
(!socket_listen($localsrv, $wno))||
(!socket_set_nonblock($localsrv))) {
exit('B??d: ' . socket_strerror(
socket_last_error($localsrv)));
}
else
$this->serwer = $localsrv;
}
}
function exit_program()
{
echo('<BR><BR><HR><FORM METHOD="POST" ACTION="' .
SCRIPT_FILE_NAME .
'"><INPUT TYPE="submit" VALUE=" Powrót "></FORM></BODY>');
}
/******************* GLOWNY PROGRAM ********************/
echo('</FONT>');
/* 256 spacji przed wypisywaniem czegokolwiek */
for($i=0;$i<256;$i++)
echo(' ');
$Socks5 = & new TS5Serwer(IP_INTERFEJS, PORT);
$Socks5->run();
/************ STRONA SERWERA SOCKS5 PROXY *************/
function MainPage()
{
return
<<<EOT
<FONT COLOR="darkblue" SIZE=5>
<HR SIZE=1>
<CENTER>
Serwer proxy Socks 5.
<HR SIZE=1>
<FORM METHOD="POST" ACTION="
EOT
. SCRIPT_FILE_NAME .
<<<EOT
">
<TABLE BORDER=1 BORDERCOLORLIGHT="yellow" CELLSPACING=0
BORDERCOLOR="darkblue" CELLPADDING=10 ALIGN="center" WIDTH=400>
<TR>
<TD COLSPAN=2><FONT COLOR="darkblue" SIZE=2>
Czas pracy serwera w minutach (0 - bez przerwy)<BR>
<INPUT TYPE="TEXT" NAME="CZAS_PRACY_SERWERA" VALUE="15">
</TD>
</TR>
<TR>
<TD><FONT COLOR="darkblue" SIZE=2>
Adres IP interfejsu (0.0.0.0 wszystkie)<BR>
<INPUT TYPE="TEXT" NAME="IP_INTERFEJS"
VALUE="0.0.0.0" MAXLENGTH=15>
</TD>
<TD><FONT COLOR="darkblue" SIZE=2>
Port serwera Socks 5<BR>
<INPUT TYPE="TEXT" NAME="PORT" VALUE="1080" MAXLENGTH=5>
</TD>
</TR>
<TR>
<TD><FONT COLOR="darkblue" SIZE=2>
Pozwól na wypisywanie po??cze?
<INPUT TYPE="checkbox" NAME="POKAZ_POLACZENIA" CHECKED
VALUE="checked"><BR><P>
Maksymalna liczba po??cze?<BR>
<INPUT TYPE="TEXT" NAME="MAX_POLACZEN" VALUE="15"
MAXLENGTH=2 SIZE=5></TD>
</TD>
<TD><FONT COLOR="darkblue" SIZE=2>
Bufor odbioru (w KB)<BR>
<INPUT TYPE="TEXT" NAME="RCV_BUF_SIZE" VALUE="8192"
SIZE=5 MAXLENGTH=5>
<BR><BR>
<FONT COLOR="darkblue" SIZE=2>
Bufor wysy?ania (w KB)<BR>
<INPUT TYPE="TEXT" NAME="SND_BUF_SIZE" VALUE="4096"
SIZE=5 MAXLENGTH=5>
</TD>
</TR>
EOT
.((HASLO)?
<<<EOT
<TR>
<TD COLSPAN=2><FONT COLOR="darkblue" SIZE=2>Has?o dost?pu<BR>
<INPUT TYPE="PASSWORD" NAME="HASLO_DOSTEPU" MAXLENGTH=10></TD>
</TR>
EOT
:NULL).
<<<EOT
<TR>
<TD COLSPAN=2 ALIGN="center">
<INPUT TYPE="SUBMIT" VALUE=" Aktywuj ">
<INPUT TYPE="RESET" VALUE= " Czy?? ">
</TD>
</TR>
</TABLE></FORM>
<HR COLOR="black" SIZE=1>
<FONT COLOR="black" SIZE=2>
</CENTER>
Autor skryptu: Krystian (Angier)
Uwagi oraz sugestie prosz? kierowa? na adres
<A HREF="mailto:myklata@inmail.pl?subject=S5 User">
</A>.<BR>
</BODY>
EOT;
}
?>