2012-12-13

Quick Bits #1 - Nginx proxy

I've been developing social games for over a year now for most of the time I had simply open ports to my laptop at office. Also our office has domain. So inside of social apps I have set iframe url as myofficedomain.com:<myport>. This is convenient only when working inside office. Sometimes shit happens and you have to help/work from home and if you want to load the same app within laptop on different network - you're shit out of luck. You have to get outgoing domain for that, network you're in might require port-forwarding that cannot be changed and so on. So I found the easiest solution for that is to setup proxy to witch you could ssh from any machine and use it as gateway for your social apps.

This brings few good things. You don't need port (for example new vk.com payment system disallows to use links with ports in payment system). You don't need change iframe urls within apps since sometimes that can become annoying since it might require confirmation true emal or even worse - phone, also sometimes these notifications lags quite a bit and it's dead time waiting.

So all you need to do is to get a server that has your soon-to-be-proxy domain pointing to it and Nginx installed in it.

You need to setup Nginx vhost as displayed:
server {
    listen 80;
    server_name myawesomeproxydomain.com;

    location / {
        proxy_pass        http://127.0.0.1:5000;
        proxy_set_header  Host $host;
        proxy_set_header  X-Real-IP $remote_addr;
        proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}
This will proxy all requests that will come to your domain to localhost:5000

Sure on the server nothing runs on localhost:5000 (sure you can change the port) so we need now to setup proxy from your machine to the server. It's simple as connecting to the server. SSH has -R attribute that will setup reverse proxy. Or as manual writes:
     -R [bind_address:]port:host:hostport
             Specifies that the given port on the remote (server) host is to be forwarded to the given host and port on the local side.  This works by allocating a socket to listen to port on the remote side, and whenever a connection is made to this port, the
             connection is forwarded over the secure channel, and a connection is made to host port hostport from the local machine.

             Port forwardings can also be specified in the configuration file.  Privileged ports can be forwarded only when logging in as root on the remote machine.  IPv6 addresses can be specified by enclosing the address in square braces.

             By default, the listening socket on the server will be bound to the loopback interface only.  This may be overridden by specifying a bind_address.  An empty bind_address, or the address ‘*’, indicates that the remote socket should listen on all
             interfaces.  Specifying a remote bind_address will only succeed if the server's GatewayPorts option is enabled (see sshd_config(5)).

             If the port argument is ‘0’, the listen port will be dynamically allocated on the server and reported to the client at run time.  When used together with -O forward the allocated port will be printed to the standard output.
So it's as easy as opening SSH connection with such command line:
ssh -R 127.0.0.1:5000:127.0.0.1:8000 proxyuser@yourawesomeserver.com
So if you run your project in localhost:8000 it will receive everything that comes to proxy domain.

Another good thing to do here is to increase life time of a SSH session. This can be done on both sides - server and your local machine. I suggest to do it on your local machine. Simply edit /etc/ssh/ssh_config if you're in Linux and add ServerAliveInterval 60 this will send each 60 seconds a packet to the server to mention that the user is still around.

SSH session fix is taken from here: http://ocaoimh.ie/2008/12/10/how-to-fix-ssh-timeout-problems/