08 September 2016

Making remote content accessible on a web server using reverse ssh tunneling

So, i had a flask server running on my laptop and i wanted to show the results online. I did not want to bother copying the project to the web server computer, installing all the dependencies and configuring nginx to run a flask project.

I ended up configuring a subdomain in nginx to always proxy from another empty port of the web server (1234 in my case but could be anything really). Usually there is nothing running there, so if i open that subdomain in a web browser it should usually show 502 Bad Gateway. Then i connect to the web server from my laptop and do a reverse ssh tunnel over the connecting, mapping my flask servers port (5000) to port 1234 on the web server.  When the connection is established, all incoming web traffic on the subdomain will proxy the request to the reverse ssh tunnel which will serve the flask content from the laptop.

This works even if the laptop is behind a firewall, dynamic ip, or any other problem that might be in the way of the laptop being visible online.

So, here is the nginx config (/etc/nginx/sites-enabled/ext_proxy):

server {
    listen 80;
    server_name ext.domain.com;
    location / {
        proxy_set_header   X-Real-IP $remote_addr;
        proxy_set_header   Host      $http_host;
        proxy_pass         http://127.0.0.1:1234;
    }
}



and the ssh command i run on the laptop:

ssh -R 1234:localhost:5000 user@domain.com


For simplicity i defined it as a function where you can specify which port on the laptop should be exposed through the subdomain:

extproxy () 
    ssh -R 1234:localhost:$1 user@domain.com
}

that i run as follows:

extproxy 5000

which will expose port 5000 on my laptop on ext.domain.com