4001, 'AUTH' => 0, 'STOPFILE' => 'stop.txt', // create this file // to stop the server 'LOGIN' => 'someshit', // if AUTH == 1 'PASSWORD' => '666', // if AUTH == 1 'MAX_CONNECTIONS' => 5, 'LOG_FILE' => -1, // if -1 - no logs 'AUTH_TIMEOUT' => 60, // sec 'CONNECT_TIMEOUT' => 5, // Timeout for connection // to remote server (sec) ); // Remote hosts, which are not supported for working with $blocked_hosts = array('81.177.6.78', '88.212.221.34', ); // Client hosts, which are not supported for working with (banned) $blocked_users = array('127.0.0.2' ); /*-------------------------------------------------------------------------------------*/ set_time_limit(0) OR DIE('set_time_limit(0) failed'); error_reporting(0); /*-------------------------------------------------------------------------------------*\ | D E F I N I T I O N S | \*-------------------------------------------------------------------------------------*/ DEFINE('VER', "\x05"); DEFINE('CONNECT', "\x01"); DEFINE('AUTH_METHOD', "\x02"); DEFINE('AUTH_NOT_REQ', "\x00"); DEFINE('WRONG_AUTH_METHODS', "\xFF"); DEFINE('REP_SUCCESS', "\x00"); DEFINE('REP_WRONG_COMMAND', "\x07"); DEFINE('REP_SOCKS_ERROR', "\x01"); DEFINE('REP_BLOCKED_HOST', "\x02"); DEFINE('REP_BAD_HOST', "\x04"); DEFINE('IPv4', "\x01"); DEFINE('DOMAIN', "\x03"); DEFINE('CLOSED_SOCKET', -12); DEFINE('NO_DATA', -11); DEFINE('NOT_ALL_DATA', -10); DEFINE('STATUS_RECVSTARTREQ', -9); DEFINE('STATUS_RECVAUTHREQ', -8); DEFINE('STATUS_REQUESTRECV', -7); DEFINE('STATUS_CONNECTING', -6); DEFINE('STATUS_WORKING', -5); /*-------------------------------------------------------------------------------------*/ $clientsockets = array(); $serversockets = array(); $recvdata = array(); $sockets_status = array(); $timeout = array(); $reqmessage = array(); $ipport = array(); /*-------------------------------------------------------------------------------------*\ | F U N C T I O N S | \*-------------------------------------------------------------------------------------*/ function getstring(&$s, $len = 1){ if(@($message = socket_recv($s, &$com, $len, 0)) === 0) return CLOSED_SOCKET; elseif($message === FALSE) return NO_DATA; else return $com; } function sendstring(&$s, $mess){ return socket_write($s, $mess, strlen($mess)); } function BridgeEstablish2($id){ global $serversockets, $clientsockets, $sockets_status, $settings, $reqmessage, $timeout, $ipport; sendstring($clientsockets[$id], VER.REP_SUCCESS."\x00\x01".$ipport[$id]); $sockets_status[$id] = STATUS_WORKING; } function BridgeEstablish1($id){ global $serversockets, $clientsockets, $sockets_status, $settings, $reqmessage, $timeout, $blocked_hosts, $ipport; $message = ''; if(($message = getstring($clientsockets[$id], 100)) === CLOSED_SOCKET){ close($id); return CLOSED_SOCKET; } elseif($message === NO_DATA) return NOT_ALL_DATA; @$reqmessage[$id] .= $message; // Checking the packet if($reqmessage[$id][0] !== VER){ close($id); return CLOSED_SOCKET; } if(!isset($reqmessage[$id][1])) return NOT_ALL_DATA; if($reqmessage[$id][1] !== CONNECT) { socket_getsockname ($clientsockets[$id], $addr, $port); $addr = explode('.', $addr); for($i = 0; $i < 4; $i++) $addr[$i] = chr($addr[$i]); $addr = implode('', $addr); sendstring($clientsockets[$id], VER.REP_WRONG_COMMAND."\x00\x01\x00". "\x00\x00\x00\x00\x00"); close($id); return CLOSED_SOCKET; } if(!isset($reqmessage[$id][2])) return NOT_ALL_DATA; if($reqmessage[$id][2] !== "\x00") { close($id); return CLOSED_SOCKET; } if(!isset($reqmessage[$id][3])) return NOT_ALL_DATA; if($reqmessage[$id][3] !== DOMAIN && $reqmessage[$id][3] !== IPv4) { close($id); return CLOSED_SOCKET; } if(!isset($reqmessage[$id][4])) return NOT_ALL_DATA; if($reqmessage[$id][3] === DOMAIN){ $reqlen = ord($reqmessage[$id][4])+1; if(!isset($reqmessage[$id][3+$reqlen])) return NOT_ALL_DATA; $host = substr($reqmessage[$id], 5, $reqlen-1); } else{ // IP v4 $reqlen = 4; if(!isset($reqmessage[$id][3+$reqlen])) return NOT_ALL_DATA; $host = base_convert(bin2hex($reqmessage[$id][4]), 16, 10).'.'. base_convert(bin2hex($reqmessage[$id][5]), 16, 10).'.'. base_convert(bin2hex($reqmessage[$id][6]), 16, 10).'.'. base_convert(bin2hex($reqmessage[$id][7]), 16, 10); } if(!isset($reqmessage[$id][3+$reqlen+2])) return NOT_ALL_DATA; socket_getsockname ($clientsockets[$id], $self_addr, $self_port); $self_addr = explode('.', $self_addr); for($i = 0; $i < 4; $i++) $self_addr[$i] = chr($self_addr[$i]); $self_add = implode('', $self_addr); $self_port = pack('n', $self_port); $ipport[$id] = $self_add.$self_port; if(in_array($host, $blocked_hosts)){ sendstring($clientsockets[$id], VER.REP_BLOCKED_HOST."\x00\x01".$ipport[$id]); close($id); return CLOSED_SOCKET; } $port = base_convert(bin2hex(substr($reqmessage[$id], 3+$reqlen+1, 2)), 16, 10); // Connection to remote host $serversockets[$id] = socket_create(AF_INET, SOCK_STREAM, 6 /* TCP*/); if($serversockets[$id] === FALSE){ sendstring($clientsockets[$id], VER.REP_SOCKS_ERROR."\x00\x01".$ipport[$id]); close($id); return CLOSED_SOCKET; } socket_set_nonblock($serversockets[$id]); //echo $host.':'.$port; socket_connect($serversockets[$id], $host, $port); unset($reqmessage[$id]); $sockets_status[$id] = STATUS_CONNECTING; } function Authorization($id){ global $serversockets, $clientsockets, $sockets_status, $settings, $reqmessage, $timeout; $message = ''; if(($message = getstring($clientsockets[$id], 100)) === CLOSED_SOCKET){ close($id); return CLOSED_SOCKET; } elseif($message === NO_DATA) return NOT_ALL_DATA; @$reqmessage[$id] .= $message; if($reqmessage[$id][0] != "\x01"){ close($id); return CLOSED_SOCKET; } if(!isset($reqmessage[$id][1])) return NOT_ALL_DATA; $pos = ord($reqmessage[$id][1])+2; if(!isset($reqmessage[$id][$pos])) return NOT_ALL_DATA; if(!isset($reqmessage[$id][$pos+ord($reqmessage[$id][$pos])])) return NOT_ALL_DATA; // Authorization if($settings['LOGIN'] === substr($reqmessage[$id], 2, ord($reqmessage[$id][1])) && $settings['PASSWORD'] === substr($reqmessage[$id], $pos+1, ord($reqmessage[$id][$pos]))) { $timeout[$id] = time(); unset($reqmessage[$id]); $sockets_status[$id] = STATUS_REQUESTRECV; sendstring($clientsockets[$id], "\x01\x00"); } else{ sendstring($clientsockets[$id], "\x01\x01"); close($id); } } function close($id){ global $serversockets, $clientsockets, $sockets_status, $settings, $reqmessage, $timeout, $ipport; socket_getpeername($clientsockets[$id], $ip); @socket_close($clientsockets[$id]); unset($clientsockets[$id]); @socket_close($serversockets[$id]); unset($serversockets[$id]); unset($sockets_status[$id]); unset($timeout[$id]); unset($ipport[$id]); makelog($ip.' disconnected.'); } function Start($id){ global $serversockets, $clientsockets, $sockets_status, $settings, $reqmessage, $timeout; $message = ''; if(($message = getstring($clientsockets[$id], 10)) === CLOSED_SOCKET){ close($id); return CLOSED_SOCKET; } elseif($message === NO_DATA) return NOT_ALL_DATA; @$reqmessage[$id] .= $message; // Checking the packet if($reqmessage[$id][0] !== VER){ close($id); return CLOSED_SOCKET; } if(!isset($reqmessage[$id][1])) return NOT_ALL_DATA; if(ord($reqmessage[$id][1]) > strlen($reqmessage[$id]) - 2) return NOT_ALL_DATA; elseif(ord($reqmessage[$id][1]) === strlen($reqmessage[$id]) - 2){ if($settings['AUTH'] !== 1){ sendstring($clientsockets[$id], VER.AUTH_NOT_REQ); unset($reqmessage[$id]); $sockets_status[$id] = STATUS_REQUESTRECV; $timeout[$id] = time(); return 0; } if(strstr(substr($reqmessage[$id], 2, ord($reqmessage[$id][1])), AUTH_METHOD)) { $timeout[$id] = time(); $sockets_status[$id] = STATUS_RECVAUTHREQ; sendstring($clientsockets[$id], VER.AUTH_METHOD); unset($reqmessage[$id]); return 0; } else{ sendstring($clientsockets[$id], VER.WRONG_AUTH_METHODS); return 0; close($id); return CLOSED_SOCKET; } $sockets_status[$id] = STATUS_REQUEST; return 0; } else{ close($id); return CLOSED_SOCKET; } } function one_array($f, $s){ $new_array = array(); foreach($f as $elt) if(!in_array($elt, $s)) array_push($new_array, $elt); return array_merge_recursive($new_array, $s); } function makelog($string){ global $settings; if($settings['LOG_FILE'] == -1) return FALSE; $fp = fopen($settings['LOG_FILE'], 'a'); fputs($fp, date("d.m.Y. H:i:s").' '.$string."\r\n". "---------------------------------------------------------\r\n"); fclose($fp); } function stop(){ global $serversockets, $clientsockets, $sockets_status, $settings, $reqmessage, $timeout; for($i = 0; $i < sizeof($clientsockets); $i++) close($i); makelog('Finish!: '.$string); DIE(); } function error($string){ makelog('<>: '.$string); stop(); DIE(); } /*-------------------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------------------*\ | P R O G R A M M | \*-------------------------------------------------------------------------------------*/ $sock = socket_create(AF_INET, SOCK_STREAM, 6 /* TCP*/) OR DIE(socket_strerror(socket_last_error())); if(!socket_bind($sock, "0.0.0.0", $settings['PORT'])) error(socket_strerror(socket_last_error($sock))); if(!socket_listen ($sock)) error(socket_strerror(socket_last_error($sock))); socket_set_nonblock($sock); $maxcount = $settings['MAX_CONNECTIONS'] + 1; $sock = array($sock); while(TRUE){ $readed = $wr = array_merge($sock, $clientsockets); if(socket_select($readed, $wr, $exc = NULL, 7) < 1){ if(file_exists($settings['STOPFILE'])) stop(); continue; } if (in_array($sock[0], $readed)){ $clientsockets[] = ($cl_sock = socket_accept($sock[0])); socket_getpeername($cl_sock, $ip); makelog($ip.' connected to server.'); $id = array_search($cl_sock, $clientsockets); if(count($clientsockets) >= $maxcount){ socket_close($cl_sock); unset($clientsockets[$id]); makelog('Connection with '.$ip.' has been aborted by server. '. 'Reason: too many connections.'); } elseif(in_array($ip, $blocked_users)){ socket_close($newsock); unset($clientsockets[$id]); makelog('Connection with '.$ip.' has been aborted by server. '. 'Reason: banned user.'); } else{ socket_set_nonblock($cl_sock); $sockets_status[$id] = STATUS_RECVSTARTREQ; } $key = array_search($sock[0], $readed); unset($readed[$key]); } $array_status = one_array($readed, $wr); foreach($array_status as $socket){ $id = array_search($socket, $clientsockets); if($id === FALSE) $id = array_search($socket, $serversockets); if($id === FALSE) continue; switch ($sockets_status[$id]){ case STATUS_RECVAUTHREQ: if(time() - $timeout[$id] > $settings['AUTH_TIMEOUT']) { //echo 'aaaaa'; close($id); break; } Authorization($id); break; case STATUS_REQUESTRECV: BridgeEstablish1($id); break; case STATUS_RECVSTARTREQ: Start($id); break; case STATUS_CONNECTING: if(time() - $timeout[$id] > $settings['CONNECT_TIMEOUT']) { sendstring($clientsockets[$id], VER.REP_BAD_HOST. "\x00\x01".$ipport[$id]); close($id); break; } // checkin remote host $exr = $ewr = array($serversockets[$id]); if(socket_select($exr, $ewr, $exc = NULL, 0) > 0) BridgeEstablish2($id); break; default: // STATUS_WORKING $mes= getstring($clientsockets[$id], 8024); if($mes === CLOSED_SOCKET){ close($id); break; } if($mes !== NO_DATA) if(sendstring($serversockets[$id], $mes) === FALSE){ close($id); break; } $mes = getstring($serversockets[$id], 8024); if($mes === CLOSED_SOCKET){ close($id); break; } if($mes !== NO_DATA) if(sendstring($clientsockets[$id], $mes) === FALSE){ close($id); break; } } } if(rand(1,5) == 5) if(file_exists($settings['STOPFILE'])) stop(); } /*-------------------------------------------------------------------------------------*/ ?>