I have a websocket server that I need to protect behind a PHP session and currently I'm unable because I can't make PHP to reverse proxy to the websocket server. Let's go to the details.
I have a NGINX server acting as general reverse proxy, that passes the request to the apache server that it's running with the PHP module. This apache-php server is the one that should check if the user has a valid session (no problem with that) and if it does redirect the request to the final websocket server, a x11VNC. If I remove the apache step and proxy pass NGINX directly to x11VNC it works perfectly, but once I want to add the session check, I get stuck.
Searching the internet I have been able to write the following code:
$vnc_request_headers = apache_request_headers();
$vnc_request_headers_simple_array = [];
foreach ($vnc_request_headers as $vnc_request_header => $value) {
array_push($vnc_request_headers_simple_array, $vnc_request_header . ': ' . $value);
}
$options = [
CURLOPT_HTTPHEADER => $vnc_request_headers_simple_array,
CURLOPT_RETURNTRANSFER => true, // return web page
CURLOPT_HEADER => true, // return headers
CURLOPT_FOLLOWLOCATION => true, // follow redirects
CURLOPT_ENCODING => "", // handle all encodings
CURLOPT_AUTOREFERER => true, // set referer on redirect
CURLOPT_CONNECTTIMEOUT => 120, // timeout on connect
CURLOPT_TIMEOUT => 120, // timeout on response
CURLOPT_MAXREDIRS => 10, // stop after 10 redirects
];
$ch = curl_init('http://192.168.100.13:5900');
curl_setopt_array($ch, $options);
$vnc_response_headers = [];
// this function is called by curl for each header received
curl_setopt($ch, CURLOPT_HEADERFUNCTION,
function($curl, $header) use (&$vnc_response_headers)
{
$len = strlen($header);
$header = explode(':', $header, 2);
if (count($header) < 2) // ignore invalid headers
return $len;
$vnc_response_headers[strtolower(trim($header[0]))][] = trim($header[1]);
return $len;
}
);
$vnc_response = curl_exec($ch);
$vnc_header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
$vnc_httpCode = curl_getinfo($ch , CURLINFO_HTTP_CODE);
curl_close($ch);
$vnc_body = substr($vnc_response, $vnc_header_size);
http_response_code($vnc_httpCode);
foreach ($vnc_response_headers as $vnc_response_header => $array) {
foreach($array as $vnc_response_header_value) {
header($vnc_response_header . ": " . $vnc_response_header_value);
}
}
echo $vnc_body;
This grabs the apache icomming headers and forward them to the proxied server, and then graps the proxied answer along with the response headers and code. Then sets the headers and the code and finally echoes the body. I have tested it and works perfectly with standard http(s) requests. The request headers reach the proxied server and the response headers reach the client browser.
But it doesn't work when working with websocket connections, curl gets stuck in curl_exec(). Maybe because websocket connections are never really closed until the data streamming it's closed from one party? I'm pretty lost because it's my first time working with websockets.
How to reverse proxy the websocket request, and all the following messages exchange that is going to take place between x11VNC and the client, with PHP?