LD
Change your colour scheme

TIL: Forwarding ports using SSH and proxying with Apache

Published:

I have two servers: a VPS, and a small server that I primarily use on my home network. The server at home is quite a bit more powerful than my VPS, and significantly cheaper to run, so I’d like to start moving some of my hosted services to it. The problem is that I don’t have a static IP, so I’d need to get dynamic DNS setup and open the right ports on my router, which is a bit tedious (and not officially supported by my ISP).

My interim solution is to use port-forwarding via SSH, wherein I can specify a target host and port, and map it to a local port, so that requests on the target machine that go to http://localhost:<port> will instead be directed to the machine running SSH (relevant guide on Ubuntu documentation). The basic command looks like this:

ssh -R 8080:localhost:3000 user@my-remote-server

Which is useful, but also just opens a regular SSH connection, which has to then be kept alive - I could use screen or tmux but that’s still not ideal, if the pipe gets broken I’ll have to reconnect it manually.

A tool called autossh can be used to run the SSH connection in the background, and will automatically spawn a new process if the old one fails:

autossh -M <echo port> -f -N -T 8080:localhost:3000 user@my-remote-server

<echo port> is just an open port that autossh will attach to, and use that to check if the connection is running. -f runs the command in the background, so I don’t need to keep a terminal alive, and -N and -T mean no command executed, and don’t open a tty connection, respectively.

So now the port has been forwarded, but it’s probably not accessible to the outside world, partly because unless the relevant ssh config setting is set on the remote machine (GatewayPorts yes), and the port is open in the server firewall, this will only be available on localhost:8080. So to use this, we also need to proxy queries.

I’m using Apache on my server, because that’s what the Wordpress auto-installer setup for me and I’m lazy, but you could also use Nginx:

<VirtualHost my.subdomain:80>
ServerAdmin you@yourtld
ServerName my.subdomain

<Proxy *>
Order allow,deny
Allow from all
</Proxy>

# http://httpd.apache.org/docs/2.0/mod/core.html#limitrequestbody
LimitRequestBody 0

# Pass requests on
ProxyPass / http://localhost:8080/ keepalive=On
ProxyPassReverse / http://localhost:8080/
</VirtualHost>

I’m not including SSL in the above config, which you absolutely should enable for this, because I use certbot, which generates the configuration for me. Add this to /etc/apache2/sites-available/<site-name>.conf and activate it with a2siteenable <site-name>. Restart apache, and assuming the domain is configured correctly, it should be accessible at the domain configured as ServerName.

Tags:

About the author

My face

I'm Lewis Dale, a software engineer and web developer based in the UK. I write about writing software, silly projects, and cycling. A lot of cycling. Too much, maybe.

Responses