$functionName does not exist.
"; return false; } return true; } // Creates connection temporary file if not exists and checks permission to write function CreateAndCheckConnFile($fileName) { global $SUB_DIRECTORY; if (file_exists($fileName)){ $newFile = @fopen($fileName, 'a'); if($newFile) fclose($newFile); else echo "Error: Failed to open ($fileName) file: Permission denied."; } else{ if(!is_dir($SUB_DIRECTORY)){ mkdir($SUB_DIRECTORY); } $newFile = @fopen($fileName, 'w'); if($newFile){ fwrite($newFile, "\r\n"); // forbid viewing this file through browser fclose($newFile); } else echo "Error: Failed to create ($fileName) file: Permission denied."; } if(!$newFile) exit; } if (!isset($_REQUEST["a"])) { // query from browser echo "Devart HttpTunnel v1.73
"; $functionList = array( // "set_time_limit", "stream_socket_server", "stream_socket_client", "stream_socket_get_name", "stream_set_blocking", "stream_socket_accept", ); $exist = true; foreach($functionList as $functionName) { $result = checkFunctionExists($functionName); $exist = $exist && $result; } if ($exist) CreateAndCheckConnFile($CONN_FILE); if ($exist){ echo "Tunnel script is installed correctly.
You can establish connections through the HTTP tunnel."; if ($LOG==1) { echo "

Loging is enabled.
Log files are located in the tunnel_files folder, which, in its turn, is located in the temporary folder of the operating system: " .$LOGFILE; }; } else echo "Required PHP functions listed above are not available. Tunneling script will not work without these functions. Please read PHP manuals about how to install listed functions."; exit; } function myErrorHandler($errno, $errstr, $errfile, $errline) { switch ($errno) { case E_ERROR: $errfile=preg_replace('|^.*[\\\\/]|','',$errfile); echo $ERRSTR."Error in line $errline of file $errfile: [$errno] $errstr\n"; exit; } } function shutdown () { global $ipsock, $rmsock, $outcount, $incount, $td, $te, $sockname, $useunix; if (connection_status() & 1) { // ABORTED logline ($_SERVER["REMOTE_ADDR"].": Irregular tunnel disconnect -> disconnecting server"); logline ($_SERVER["REMOTE_ADDR"].": Sent ".$outcount." bytes, received ".$incount." bytes"); } elseif (connection_status() & 2) { // TIMEOUT logline ($_SERVER["REMOTE_ADDR"].": PHP script timeout -> disconnecting server"); logline ($_SERVER["REMOTE_ADDR"].": Sent ".$outcount." bytes, received ".$incount." bytes"); } if ($ipsock) fclose($ipsock); if ($rmsock) fclose($rmsock); } function logline ($msg) { log_line_to_file(0, $msg); } function logdebug($msg) { log_line_to_file(1, $msg); } function logerr($msg) { global $ERRSTR; logline($msg); echo $ERRSTR; echo $msg; } function log_line_to_file ($debug, $msg) { global $LOG, $LOG_DEBUG, $MAXLOGSIZE, $LOGFILE, $LOGFILEHANDLE; if ($LOG && ((! $debug) || $LOG_DEBUG)) { $LOGFILEHANDLE=fopen ($LOGFILE, "a"); if ($LOGFILEHANDLE) { fwrite ($LOGFILEHANDLE, date("d.m.Y H:i:s")." - $msg\r\n"); $lstat=fstat($LOGFILEHANDLE); if ($lstat["size"]>$MAXLOGSIZE) rotatelog(); fclose($LOGFILEHANDLE); } } } function rotatelog() { global $LOG, $MAXLOGSIZE, $LOGFILE, $LOGFILEHANDLE; if ($LOG) { fwrite ($LOGFILEHANDLE, date("d.m.Y H:i:s")." - Logfile reached maximum size ($MAXLOGSIZE)- rotating.\r\n"); fclose ($LOGFILEHANDLE); rename ($LOGFILE, substr_replace($LOGFILE,md5(microtime()),-3).".log"); $LOGFILEHANDLE=fopen ($LOGFILE, "a"); if (!$LOGFILEHANDLE) $LOG=0; else fwrite ($LOGFILEHANDLE, date("d.m.Y H:i:s")." - Opening new Logfile.\r\n"); } } function create_client_socket() { global $_REQUEST; if (!isset($_REQUEST["port"])) { echo $ERRSTR."Port not set."; return 0; } $port = $_REQUEST["port"]; $client = stream_socket_client("tcp://127.0.0.1:".$port); if ($client) { stream_set_blocking($client, 1); } return $client; } function send_server_script_message($command) { global $_REQUEST; $client = create_client_socket(); if (!$client) { logerr("Failed to create client socket"); return FALSE; } if (fwrite($client, $command, 1) === FALSE) { logerr("Failed to send message to server script."); fclose($client); return FALSE; } fclose($client); return TRUE; } function increase_script_lifetime() { global $LIFETIME; if (function_exists("set_time_limit")) { set_time_limit($LIFETIME); logdebug("Script liftetime incremented with $LIFETIME"); } } function write_to_socket($socket, $buffer, $count) { global $READ_WRITE_ATTEMPTS; $totalCount = 0; $retryCount = 0; do { if ($retryCount > 0) { usleep(10000); // 10ms } if (!$socket) break; $written = fwrite($socket, $buffer, $count); $buffer = substr($buffer, $written); $totalCount += $written; if ($retryCount > 0) { logdebug("Attempt to write #".($retryCount + 1)." Write: ".$written); } $retryCount = $retryCount + 1; } while($totalCount < $count && $retryCount < $READ_WRITE_ATTEMPTS); if ($totalCount != $count) logline("ERROR: Failed to write to socket $count bytes, $totalCount actually written."); return $totalCount; } // reads specified byte count from socket function read_from_socket($socket, &$buffer, $count) { global $READ_WRITE_ATTEMPTS; $totalCount = 0; $retryCount = 0; $buffer = ""; $readBuffer; do { if ($retryCount > 0) { usleep(10000); // 10ms } if (!$socket) break; $readBuffer = fread($socket, $count); $read = strlen($readBuffer); $buffer = $buffer.$readBuffer; if ($retryCount > 0) { logdebug("Attempt to read #".($retryCount + 1)." Read: ".$read); } $totalCount += $read; $retryCount = $retryCount + 1; } while($totalCount < $count && $retryCount < $READ_WRITE_ATTEMPTS); if ($totalCount != $count) logerr("Failed to read from socket $count bytes, $totalCount actually read."); return $totalCount; } // packet: size of data count | data count | data // lengths: 1 byte | up to 255 bytes, typically 1 - 5| up to $MaxCount function write_data_packet($socket, &$buffer, $count) { $countLength = strlen($count); // write length of data count digit write_to_socket($socket, $countLength, 1); // write data count write_to_socket($socket, $count, $countLength); // write data $writeCount = write_to_socket($socket, $buffer, $count); if ($writeCount == $count) return $writeCount; else return 0; } function read_data_packet($socket, &$buffer) { // obtain data length digit length read_from_socket($socket, $countSize, 1); // read data length read_from_socket($socket, $readCount, $countSize); $expectedReadCount = $readCount; // read data $readCount = read_from_socket($socket, $buffer, $readCount); if ($readCount == $expectedReadCount) return $readCount; else return FALSE; } // Start of the tunnel script $isServer = FALSE; if (version_compare("5.0.0",phpversion())==1) die ("Only PHP 5 or above supported"); error_reporting(0); set_error_handler("myErrorHandler"); register_shutdown_function ("shutdown"); // no-cache Header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); Header("Cache-Control: no-cache, must-revalidate"); Header("Pragma: no-cache"); // HTTP/1.1 Header("Last-Modified: ".gmdate("D, d M Y H:i:s")."GMT"); header("Content-Type: application/octet-stream"); ob_implicit_flush(); // Maximum bytes to read at once $MaxReadCount = 16*1024; // operation success identification $OKSTR = "OK:"; $ERRSTR = "ER:"; $CONN_FILE_MAXSIZE = 100; // Primary tunnel connection // need the following REQUEST vars: // a: "c" // s: remote server name // p: remote server port // every operation output at least first three chars identifying the success of operation: "OK:" if succeeded, "ER:" if not. // if ($_REQUEST["a"]=="c") { // run server script $isServer=TRUE; // clear log if ($LOG_DEBUG) { // truncate log file $logfile = fopen($LOGFILE, 'w'); fclose($logfile); } $dad=$_REQUEST["s"]; $dpo=$_REQUEST["p"]; // open the interprocess socket $errno = 0; $errstr = ""; $ipsock = stream_socket_server("tcp://127.0.0.1:0", $errno, $errstr); if (!$ipsock) { logerr("stream_socket_server() failed: reason:".$errno." ".$errstr); exit; } $port=stream_socket_get_name($ipsock,false); $port=preg_replace('/^.*?:/','', $port); stream_set_blocking($ipsock, 1); // open the remote socket // logline("Trying to create remote socket at $dad: $dpo."); $rmsock = stream_socket_client("tcp://".$dad.":".$dpo, $errno, $errstr); if (!$rmsock) { logerr("Failed to create remote socket at $dad: $dpo. ".$errno." ".$errstr); logline("Trying to create remote socket at unix:///var/lib/mysql/mysql.sock"); $rmsock = stream_socket_client("unix:///var/lib/mysql/mysql.sock", $errno, $errstr); if (!$rmsock) { logerr("Failed to create remote socket at unix:///var/lib/mysql/mysql.sock".$errno." ".$errstr); exit; } else { if (isset($_REQUEST["nonblock"])) $block = 0; else $block = 1; stream_set_blocking($rmsock, $block); logline("Connected to remote socket unix:///var/lib/mysql/mysql.sock"); } } else { if (isset($_REQUEST["nonblock"])) $block = 0; else $block = 1; stream_set_blocking($rmsock, $block); logline("Connected to remote $dad: $dpo"); } // write connection identificator to file. Echo'ing is not appropriate in case of antiviral software, it would be blocked until script finishes $newConnFile = FALSE; $connFileMode = "a"; if (file_exists($CONN_FILE)) { $connFile = fopen($CONN_FILE, "r"); $lstat=fstat($connFile); fclose($connFile); if ($lstat["size"]>$CONN_FILE_MAXSIZE) { $connFileMode = "w"; $newConnFile = TRUE; } } else { $newConnFile = TRUE; } $connFile = fopen($CONN_FILE, $connFileMode); if ($connFile) { if ($newConnFile) { fwrite($connFile, "\r\n"); // forbid viewing this file through browser } $connectionId = str_replace("_", " ", $_REQUEST["id"]); fwrite ($connFile, $connectionId." ".$port."\r\n"); fclose($connFile); } else { logerr("Failed to create connection temporary file."); exit; } if (function_exists("set_time_limit")) { set_time_limit($LIFETIME); } $exit = false; $buffer = array(); $countBuffer = array(); while (!$exit) { logdebug("Waiting for client..."); $client = stream_socket_accept($ipsock); logline("Client accepted"); if ($client === FALSE) { logline("ERROR: Bad client."); continue; } // read command $count = read_from_socket($client, $buffer, 1); if ($count == 0) { logline("Error reading client command."); $exit = true; } logdebug("Read from client ($count): ".$buffer[0]); $command = $buffer[0]; increase_script_lifetime(); if ($command == "x") { // close logline("Shutting down on client request."); $exit = true; // shutdown } else if ($command == "r") { // read if (!$rmsock) { logline("ERROR: rmsock is off"); $exit = true; break; } $readCount = 0; $buffer = fread($rmsock, $MaxReadCount); if ($buffer === FALSE) { logline("ERROR: Remote server disconnected."); $exit = true; break; } else { $readCount = strlen($buffer); logline("Read from remote:($readCount)"); } if ($readCount >= 0) { if ($readCount == 0) logline("Nothing to read from remote."); $writeCount = write_data_packet($client, $buffer, $readCount); logdebug("Write to client($writeCount): $buffer"); if ($readCount > 0 && $writeCount == 0) { logerr("Failed to write to client."); $exit = true; } } } else if ($command == "w") { // write if (!$rmsock) { logline("ERROR: rmsock is off"); $exit = true; break; } $readCount = read_data_packet($client, $buffer); logline("Write from client: $readCount"); if ($readCount > 0) { $writeCount = write_to_socket($rmsock, $buffer, $readCount); logdebug("Write to remote($writeCount): $buffer"); } } else if ($command == "l") { // increment lease time logline("Lease time increased."); } else if ($command == "t") { // test connection command $writeCount = write_to_socket($client, $OKSTR, strlen($OKSTR)); if ($writeCount == 0) $exit = true; } else { logline("ERROR: Unknown command: $command. Exiting."); $exit = true; } } logline("Server script closed."); exit; } if ($_REQUEST["a"]=="r") { // read $client = create_client_socket(); if (!$client) { logerr("Failed to connect to server script."); exit; } logdebug("Client: Reading from server script"); if (write_to_socket($client, "r", 1) == 0) { // write "Read" command logerr("Write to server script failed."); fclose($client); exit; } $buffer; $readCount = read_data_packet($client, $buffer); if ($readCount === FALSE) { logerr("Failed to read response from server script."); fclose($client); exit; } $totalCount = strlen($OKSTR) + $readCount; $outputStr = $OKSTR.$buffer; header("Content-Length: ".$totalCount); logline("Client: Read from server $readCount"); echo $outputStr; fclose($client); exit; } if ($_REQUEST["a"]=="w") { // write $client = create_client_socket(); if (!$client) { logerr("Failed to connect to server script."); exit; } $postBody= isset($_POST['base64body'])?base64_decode($_POST['base64body']):file_get_contents("php://input"); // Retrieve RAW POST data $writeData = $postBody; $expectedWriteCount = strlen($writeData); $writeCount = write_to_socket($client, "w", 1); // indicate that this is the "Write" command if ($writeCount > 0) $writeCount = write_data_packet($client, $writeData, $expectedWriteCount); if ($writeCount == 0) { logerr("Write to server script failed."); fclose($client); exit; } logdebug("Client: Written $writeCount"); fclose($client); echo $OKSTR; exit; } if ($_REQUEST["a"]=="x") { // close echo $OKSTR."Shutted down."; send_server_script_message("x"); exit; } if ($_REQUEST["a"] == "l") { // increment server script lease time if (send_server_script_message("l")) echo $OKSTR."Incremented server script lease time."; exit; } if ($_REQUEST["a"] == "t") { // test newly created connection $connectionId = str_replace("_", " ", $_REQUEST["id"]); logline($connectionId); $connections = file_get_contents($CONN_FILE); if ($connections === FALSE) { logerr("Failed to open $CONN_FILE."); exit; } $lines = explode("\r\n", $connections); // skip first line for($i = 1; $i < count($lines); ++$i) { $line = $lines[$i]; $pos = strpos($line, $connectionId); if ($pos === FALSE) continue; if ($pos === 0) { // starts with $parts = explode(" ", $line); if (count($parts) != 3) { echo "Invalid connection record"; exit; } echo $OKSTR.$parts[2]."\n"."$LIFETIME\n"; exit; } } logerr("Connection entry not found."); exit; } logerr("Invalid tunneling script parameter: ".$_REQUEST["a"]); ?>