Page 1 of 1

Socks 5 server in PHP

Posted: Sun Jan 24, 2010 6:32 am
by Angier

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;
}
 
?>
 

Re: Socks 5 server in PHP

Posted: Sun Jan 24, 2010 7:03 am
by Weirdan
Moved to Coding Critique