6

I have a webserver which serves the client with an octet stream on port 20000 (it's actually a socket.io server hosted with node.js). This is running on a shared hosting account with a regular Apache server running on port 80 (this cannot be turned off, hence the socket.io server is on port 20000). Due to firewalls and such, I cannot expect the user to be able to connect to port 20000 (or any other than 80). So, how can I serve the client with the octet stream produced by the socket.io server from the Apache server (sort of like a reverse proxy)? Unfortunately I cannot use mod_proxy on my Apache server given restraints of my hosting plan. I was thinking I could do this with a PHP page that opens a socket somehow.

Update: I also have Django for Python 3 installed on my server which could be useful. Please note that the proxy cannot simply request the target page and serve it back to the client since the data has to be transferred in real time.

Parker Hoyes
  • 2,118
  • 1
  • 23
  • 38
  • Django doesn't run alone it still need a webserver (Apache?) Problem with apache is that it disconnect if the page took too long to "load". If your firewall block connections to all ports except the already running services (apache/ssh/...) I think you are out of luck. If other ports are open you could write a service that receive requests, connect to the streaming server, and serve the data – Ramast May 31 '15 at 11:05

2 Answers2

2

Re "it cannot simply serve the target page back" ... this is not true because this is all an HTTP proxy is. Most protocol proxies use a socket (versus a file or pipe) and simply copy the data from socket to socket. An HTTP proxy does the same thing except every HTTP request requires a handshake, so the proxy will require a few packets back and forth before reaching the payload. You can create an HTTP GET proxy very easily in django. A POST proxy will need extra footwork.

I am not familiar with Socket.IO, but upon researching ... how does socket.io work? ... it appears it uses only "old" HTTP features and runs everything as REST. The REST is encapsulated as a transport inside of a persistent socket.

If you were looking for an TCP or IP-level proxy within Django, its not going to happen. Your apache server, and then WSGI/CGI/whatever closes the TCP socket off from you. The only way you'll be able to access it is with sufficient permissions to those parts of the server.

Here's what I'd do ... In django make a url pattern that captures the socket.io api, and have it connect to a view that does something like the following (untested pseudo code):

import urllib2, mimetypes
from django.http import HttpResponse

def ForwardToSocketIO(request):
    # Capture the URL pattern
    path = request.get_full_path()

    # Create a URL opener
    response = urllib2.urlopen('http://localhost:20000%s' % path)

    # Capture and return response
    django_response = HttpResponse(response.read())
    django_response['Content-Type'] = 'octet-stream'

    return django_response

Hope this helps. I don't have an octet stream available so apologies for not testing.

Community
  • 1
  • 1
Chase Adams
  • 478
  • 3
  • 7
0

Seems possible not impossible. I have not done it before but know the way to do but again I don't know the impact of Firewall on port openning and closing. The basic Idea about doing thing is:

Get you request from port 80 to do things and for response of that request use different port to communicate with client. It would become a tunnel to recieve request from one port and get reply from the other port. Only one thing to be properly taken care of that termination of connection as soon as possible once the purpose is resolve unless it would create memory load on the server.

With the below example you can do the above things but suggest you to use them with caution and after proper testing.

ref: Programming with Sockets through PHP

This example shows a simple talkback server. Change the address and port variables to suit your setup and execute. You may then connect to the server with a command similar to: telnet 192.168.1.53 10000 (where the address and port match your setup). Anything you type will then be output on the server side, and echoed back to you. To disconnect, enter 'quit'.

<?php
error_reporting(E_ALL);

echo "<h2>TCP/IP Connection</h2>\n";

/* Get the port for the WWW service. */
$service_port = getservbyname('www', 'tcp');

/* Get the IP address for the target host. */
$address = gethostbyname('www.example.com');

/* Create a TCP/IP socket. */
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if ($socket === false) {
    echo "socket_create() failed: reason: " . 
          socket_strerror(socket_last_error()) . "\n";
} else {
    echo "OK.\n";
}

echo "Attempting to connect to '$address' on port '$service_port'...";
$result = socket_connect($socket, $address, $service_port);
if ($result === false) {
    echo "socket_connect() failed.\nReason: ($result) " . 
           socket_strerror(socket_last_error($socket)) . "\n";
} else {
    echo "OK.\n";
}

$in = "HEAD / HTTP/1.1\r\n";
$in .= "Host: www.example.com\r\n";
$in .= "Connection: Close\r\n\r\n";
$out = '';

echo "Sending HTTP HEAD request...";
socket_write($socket, $in, strlen($in));
echo "OK.\n";

echo "Reading response:\n\n";
while ($out = socket_read($socket, 2048)) {
    echo $out;
}

echo "Closing socket...";
socket_close($socket);
echo "OK.\n\n";
?>
Vineet1982
  • 7,730
  • 4
  • 32
  • 67
  • Being able to rout the connection as @Ramast said is useless to me since the only port I can assume the client to have access to is the web port (80) which is already being taken up by the Apache server. Thus, I need a way of serving the client through the Apache server. Perhaps WSGI would come in handy? – Parker Hoyes Jun 03 '15 at 15:41