Simple Quick SSH Tunneling to expose your web app

I’ve been a localtunnel user for quite some time now and I really love the fact that its a free service, quick to install and easy to expose your development app to the world. There are quite a few worthy alternatives now with showoff.io and pagekite that pretty much do the same thing. 

But at times it gets annoying (especially when in the middle of other work) that I’m unable to access localtunnel because its down or I outran the free usage limit for Pagekite

I generally end up using localtunnel when I have to wait for an IPN from Paypal or Authorize.net (relay response) while working on my development environment. So here is a quick way to roll out a basic version of the service for your own needs.

Before we move to the “how to” here is a quick intro to ssh tunneling

Now, I assume that you have a staging server (or some server you have ssh access to).

The following terminal command does pretty much the same thing we do with the Ruby code that follows:

ssh -R0.0.0.0:9999:localhost:3000 sid@abc.example.com

view raw
ssh_tunneling.sh
hosted with ❤ by GitHub

The -R indicates that you’ll be forwarding your local app running on port 3000 to the remote port 9999 on the remote host abc.example.com so that everyone can access it. Now your application running on localhost:3000 is accessible at abc.example.com:9999

We do the same thing now using the ruby net-ssh library. The following code snippet is customised to my defaults but its simple enough to change those settings.

#! /usr/bin/env ruby
require 'rubygems'
require 'net/ssh'
require "net/ssh/gateway"
# Terminal equivalent
# #ssh -R0.0.0.0:9999:localhost:3000 sid@abc.idyllic-software.com
puts "Enter the remote server name you wish to forward your local port to: (staging.example.com)"
remote_host = gets.chomp
puts "Enter the remote port you wish your local app to be available on – on the remote server (ex: 9999)"
remote_port = gets.chomp
puts "Enter remote server user to ssh with"
remote_user = gets.chomp
puts "Enter local port to forward"
local_port = gets.chomp
remote_host = "abc.idyllic-software.com" if remote_host.empty? || remote_host.nil?
remote_port = 9999 if remote_port.empty? || remote_port.nil?
remote_user = "sid" if remote_user.empty? || remote_user.nil?
local_port = 3000 if local_port.empty? || local_port.nil?
gateway = Net::SSH::Gateway.new(remote_host, remote_user)
puts "Forwarding 127.0.0.1:#{local_port} to #{remote_host}:#{remote_port}"
#remote_host = "abc.idyllic-software.com"
Net::SSH.start(remote_host, remote_user) do |ssh|
puts "Connecting…"
#puts ssh.inspect
ssh.logger.sev_threshold = Logger::Severity::DEBUG
#remote forward from remote 127.0.0.1:3000 to 0.0.0.0:9999 established
ssh.forward.remote(local_port, '127.0.0.1', remote_port, remote_host)
ssh.loop { true }
end

view raw
ssh_tunneling_wp.rb
hosted with ❤ by GitHub

Hope this helps