H25E Posted July 11, 2022 Share Posted July 11, 2022 (edited) 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? Thanks for your time! Héctor Edited July 11, 2022 by H25E Quote Link to comment https://forums.phpfreaks.com/topic/315026-reverse-proxy-pass-websocket-request-with-php-in-apache/ Share on other sites More sharing options...
kicken Posted July 11, 2022 Share Posted July 11, 2022 2 hours ago, H25E said: 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. That's exactly the issue. Websockets are a persistent and bi-directional connection, unlike your typical http requests. This means they don't really work with your typical HTTP tools, you need something that can specifically deal with websockets. As far as I know you can't really use PHP to deal with a websocket via apache, nor do I expect it to be a good idea even if you could. What you'd typically do is essentially write your own websocket server in PHP that is run as it's own service, separate from apache or nginx. You could then code your server to act as a proxy between the vnc server and the browser with whatever extra checks you want. Quote Link to comment https://forums.phpfreaks.com/topic/315026-reverse-proxy-pass-websocket-request-with-php-in-apache/#findComment-1598134 Share on other sites More sharing options...
Solution kicken Posted July 11, 2022 Solution Share Posted July 11, 2022 As an alternative to making your own proxy server (or finding one) you might be able to simply configure Nginx to authenticate the request for you by making a sub-request to your PHP script. I don't use Nginx so not sure if that would work but it sounds promising. Quote Link to comment https://forums.phpfreaks.com/topic/315026-reverse-proxy-pass-websocket-request-with-php-in-apache/#findComment-1598135 Share on other sites More sharing options...
H25E Posted July 11, 2022 Author Share Posted July 11, 2022 (edited) 2 hours ago, kicken said: As an alternative to making your own proxy server (or finding one) you might be able to simply configure Nginx to authenticate the request for you by making a sub-request to your PHP script. I don't use Nginx so not sure if that would work but it sounds promising. Wow, that has been great!! Didn't know something like that existed!! Works perfectly and probably with better performance, and barely without any extra code!! Thank you so much!! Edited July 11, 2022 by H25E Quote Link to comment https://forums.phpfreaks.com/topic/315026-reverse-proxy-pass-websocket-request-with-php-in-apache/#findComment-1598138 Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.