Skip to content

Instantly share code, notes, and snippets.

@halo
Last active October 3, 2015 06:57
Show Gist options
  • Save halo/2412677 to your computer and use it in GitHub Desktop.
Save halo/2412677 to your computer and use it in GitHub Desktop.
A small Ruby tool making it easy to establish an SSH tunnel
#!/usr/bin/env ruby
require 'optparse'
require 'ostruct'
# Extension for colored Strings
class String
def red() colored(:red); end
def green() colored(:green); end
def yellow() colored(:yellow); end
def blue() colored(:blue); end
def magenta() colored(:magenta); end
def cyan() colored(:cyan); end
def colored(color=nil)
code = case color
when :red then 31
when :green then 32
when :yellow then 33
when :blue then 34
when :magenta then 35
when :cyan then 36
end
self.gsub!('<b>', "\033[1m")
self.gsub!('</b>', "\033[22m")
self.gsub!('<blink>', "\033[5m")
self.gsub!('</blink>', "\033[25m")
"\033[#{code}m#{self}\033[0m"
end
end
# Setting default options
options = OpenStruct.new({
:local => OpenStruct.new({
:host => `hostname -f`.chomp,
:port => 2000,
}),
:proxy => OpenStruct.new({
:host => 'proxy.example.com',
:ssh => OpenStruct.new({
:user => nil,
:port => nil,
}),
}),
:target => OpenStruct.new({
:host => 'target.example.com',
:port => 3306,
}),
})
# Draws a graph of the tunnel according to options
def graph(options)
result = "Port <b>#{options.local.port}</b> of #{options.local.host}</b>".green
result << " ➜ "
if options.proxy.host
result << "<b>#{options.proxy.ssh.user}@</b>".yellow if options.proxy.ssh.user
result << "<b>#{options.proxy.host}</b>".yellow
result << " (using port <b>#{options.proxy.ssh.port}</b> for SSH access)".yellow if options.proxy.ssh.port
result << ' ➜ '
end
result << "Port <b>#{options.target.port}</b> of <b>#{options.target.host}</b>".red
result
end
help = ''
OptionParser.new do |parser|
parser.banner = ""
parser.separator " TUNNEL ENTRANCE".green
parser.on("--local-port=PORT", "The tunnel begins on this port on <b>#{options.local.host}</b> ".colored) do |value|
options.local.port = value
end
parser.separator ""
parser.separator " TUNNEL PROXY".yellow + " (optional)"
parser.on("--proxy-host=HOST", "If this is set, the Tunnel will go via this server. ") do |value|
options.proxy.host = value
end
parser.on("--proxy-user=USER", "The SSH user for connecting to the proxy server <b>#{options.proxy.host ? options.proxy.host + ' ' : ''}</b>".colored) do |value|
options.proxy.ssh.user = value
end
parser.on("--proxy-port=PORT", "The SSH port for connecting to the proxy server <b>#{options.proxy.host ? options.proxy.host + ' ' : ''}</b>".colored) do |value|
options.proxy.ssh.port = value
end
parser.separator ""
parser.separator " TUNNEL EXIT".red
parser.on("--target-host=HOST", 'The server you\'re trying to establish a tunnel to. Use "localhost" if it\'s the proxy.'.colored) do |value|
options.target.host = value
end
parser.on("--target-port=PORT", "The port on the target-host at the very end of the tunnel.".colored) do |value|
options.target.port = value
end
parser.on('--go', 'Establishes the tunnel') do |value|
options.go = true
end
parser.separator ""
help = parser.help
end.order!
proxy_user_addon = options.proxy.ssh.user ? "#{options.proxy.ssh.user}@" : ''
proxy_port_addon = options.proxy.ssh.port ? "-p #{options.proxy.ssh.port} " : ''
command = %{ssh #{proxy_user_addon}#{options.proxy.host} #{proxy_port_addon}-N -L #{options.local.port}:#{options.target.host}:#{options.target.port}}
if options.go
puts
puts " Establishing tunnel..."
puts ' ' + graph(options)
puts
puts ' ' + command
puts
exec command
else
puts
puts " USAGE".cyan
puts " Add the parameter " + '--go'.cyan + ' to establish the tunnel according to the "current configuration" below.'.colored
puts
puts " CURRENT CONFIGURATION".cyan
puts " #{graph(options)}"
puts help
puts " COMMAND USED".cyan
puts " #{command}"
puts
exit
end
@halo
Copy link
Author

halo commented Apr 18, 2012

Running this in bash, you'll get this help message.

  USAGE
        Add the parameter --go to establish the tunnel according to the "current configuration" below.

  CURRENT CONFIGURATION
        Port 2000 of mycomputer.local ➜  proxy.example.com ➜  Port 3306 of target.example.com

  TUNNEL ENTRANCE
        --local-port=PORT            The tunnel begins on this port on mycomputer.local 

  TUNNEL PROXY (optional)
        --proxy-host=HOST            If this is set, the Tunnel will go via this server. 
        --proxy-user=USER            The SSH user for connecting to the proxy server proxy.example.com 
        --proxy-port=PORT            The SSH port for connecting to the proxy server proxy.example.com 

  TUNNEL EXIT
        --target-host=HOST           The server you're trying to establish a tunnel to. Use "localhost" if it's the proxy.
        --target-port=PORT           The port on the target-host at the very end of the tunnel.
        --go                         Establishes the tunnel

  COMMAND USED
        ssh proxy.example.com -N -L 2000:target.example.com:3306

Note that it presents to you the ssh command it would use (the last line shown above)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment