Socks 5 server in PHP

Coding Critique is the place to post source code for peer review by other members of DevNetwork. Any kind of code can be posted. Code posted does not have to be limited to PHP. All members are invited to contribute constructive criticism with the goal of improving the code. Posted code should include some background information about it and what areas you specifically would like help with.

Popular code excerpts may be moved to "Code Snippets" by the moderators.

Moderator: General Moderators

Post Reply
Angier
Forum Newbie
Posts: 1
Joined: Sun Jan 24, 2010 6:29 am

Socks 5 server in PHP

Post 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;
}
 
?>
 
User avatar
Weirdan
Moderator
Posts: 5978
Joined: Mon Nov 03, 2003 6:13 pm
Location: Odessa, Ukraine

Re: Socks 5 server in PHP

Post by Weirdan »

Moved to Coding Critique
Post Reply