Этот скрипт прослушивает IP-порт и намеревается действовать как прокси-сервер HTTP (S).cURL как прокси, обрабатывать метод HTTPS/CONNECT
Запросы на HTTP-URL работают нормально, но я натыкаюсь на то, как обращаться с HTTPS-запросами и, более конкретно, с подтверждением SSLv3 после того, как клиент отправляет запрос CONNECT в прокси-сервер.
Ближайший я пришел к тому, что выглядит как ответ является:
- CURLOPT_HTTPPROXYTUNNEL вариант Libcurl для туннельных данных между клиентом и целевым сервером
- stream_socket_enable_crypto(), чтобы, возможно, «делать вещи» с зашифрованные данные
Я действительно не уверен, поэтому указатель на то, как с этим бороться, будет очень признателен.
Вот пример запроса: http://pastebin.com/xkWhGyjW
<?php
class proxy {
static $server;
static $client;
static function headers($str) { // Parses HTTP headers into an array
$tmp = preg_split("'\r?\n'",$str);
$output = array();
$output[] = explode(' ',array_shift($tmp));
$post = ($output[0][0] == 'POST' ? true : false);
foreach($tmp as $i => $header) {
if($post && !trim($header)) {
$output['POST'] = $tmp[$i+1];
break;
}
else {
$l = explode(':',$header,2);
$output[$l[0]] = $l[0].': '.ltrim($l[1]);
}
}
return $output;
}
public function output($curl,$data) {
socket_write(proxy::$client,$data);
return strlen($data);
}
}
$ip = "127.0.0.1";
$port = 50000;
proxy::$server = socket_create(AF_INET,SOCK_STREAM, SOL_TCP);
socket_set_option(proxy::$server,SOL_SOCKET,SO_REUSEADDR,1);
socket_bind(proxy::$server,$ip,50000);
socket_getsockname(proxy::$server,$ip,$port);
socket_listen(proxy::$server);
while(proxy::$client = socket_accept(proxy::$server)) {
$input = socket_read(proxy::$client,4096);
preg_match("'^([^\s]+)\s([^\s]+)\s([^\r\n]+)'ims",$input,$request);
$headers = proxy::headers($input);
echo $input,"\n\n";
if(preg_match("'^CONNECT '",$input)) { // HTTPS
// Tell the client we can deal with this
socket_write(proxy::$client,"HTTP/1.1 200 Connection Established\r\n\r\n");
// Client sends binary data here (SSLv3, TLS handshake, Client hello?)
// socket_read(proxy::$client,4096);
// ?
}
else { // HTTP
$input = preg_replace("'^([^\s]+)\s([a-z]+://)?[a-z0-9\.\-]+'","\\1 ",$input);
$curl = curl_init($request[2]);
curl_setopt($curl,CURLOPT_HEADER,1);
curl_setopt($curl,CURLOPT_HTTPHEADER,$headers);
curl_setopt($curl,CURLOPT_TIMEOUT,15);
curl_setopt($curl,CURLOPT_RETURNTRANSFER,1);
curl_setopt($curl,CURLOPT_NOPROGRESS,1);
curl_setopt($curl,CURLOPT_VERBOSE,1);
curl_setopt($curl,CURLOPT_AUTOREFERER,true);
curl_setopt($curl,CURLOPT_FOLLOWLOCATION,1);
curl_setopt($curl,CURLOPT_WRITEFUNCTION, array("proxy","output"));
curl_exec($curl);
curl_close($curl);
}
socket_close(proxy::$client);
}
socket_close(proxy::$server);
?>
Не могли бы вы отправить на Pastebin код для запросов HTTP URL? –
Конечно ... Я использую командную строку cURL для тестирования. http://pastebin.com/xkWhGyjW – innvo
Вы пробовали другие сайты, чем google.com (в зависимости от вашего pastebin)? (см. здесь http://superuser.com/questions/404116/cannot-connect-to-website-ssl-handshaking-fails) И вы пытались подключиться без прокси-сервера, то есть 'curl -L -i -v ' https://www.google.com/ "'? Каков результат, если вы добавляете '--trace tracetxt.tmp' к вашему зависанию, при использовании вашего прокси-сервера и при непосредственном подключении? Возможно, может помочь различие в трассировке? – stef77