Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

We’re showing branches in this repository, but you can also compare across forks.

base fork: progrium/localtunnel
base: master
...
head fork: rtyler/passageway
compare: v0.0.2
  • 7 commits
  • 18 files changed
  • 0 commit comments
  • 1 contributor
22 .gitignore
View
@@ -1,3 +1,19 @@
-.idea
-.idea/*
-.idea/**/*
+*.gem
+*.rbc
+.bundle
+.config
+.yardoc
+Gemfile.lock
+InstalledFiles
+_yardoc
+coverage
+doc/
+lib/bundler/man
+pkg
+rdoc
+spec/reports
+test/tmp
+test/version_tmp
+tmp
+.rvmrc
+
9 Gemfile
View
@@ -0,0 +1,9 @@
+source 'https://rubygems.org'
+
+# Specify your gem's dependencies in passageway.gemspec
+gemspec
+
+
+group :test do
+ gem 'rspec', '> 2.10'
+end
22 LICENSE.txt
View
@@ -0,0 +1,22 @@
+Copyright (c) 2013 R. Tyler Croy
+
+MIT License
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
6 Manifest
View
@@ -1,6 +0,0 @@
-Rakefile
-lib/localtunnel.rb
-lib/localtunnel/tunnel.rb
-lib/localtunnel/net_ssh_gateway_patch.rb
-bin/localtunnel
-Manifest
64 README.md
View
@@ -0,0 +1,64 @@
+# Passageway -- instant public tunnel to your local web server
+
+## Install
+
+Now you can install Passageway with RubyGems:
+
+ % gem install passageway
+
+or to get the source:
+
+ git clone http://github.com/rtyler/passageway.git
+
+## Usage
+
+ passageway [options] <localport>
+ -k, --key FILE upload a public key for authentication
+
+Passageway is a client to a free and open source reverse tunneling
+service made specifically for web traffic. It's intended to be used to
+temporarily expose local web servers to the greater Internet for
+debugging, unit tests, demos, etc.
+
+This is how you make your local port 8080 public:
+
+ $ passageway 8080
+ Port 8080 is now publicly accessible from http://8bv2.localtunnel.com ...
+
+ $ passageway 8080
+ Port 8080 is now publicly accessible from http://8bv2.localtunnel.com ...
+
+Using Passageway is comparable to using SSH reverse/remote port
+forwarding on a remote host that has GatewayPorts enabled, but without
+all the configuration or the need of a host. The localtunnel command
+works with a server component that is running on localtunnel.com,
+which is provided as a free service.
+
+If you have never run localtunnel before, you'll need to upload a public
+key to authenticate. You do this once:
+
+ $ passageway -k ~/.ssh/id_rsa.pub 8080
+
+After that, you shouldn't have to use -k again.
+
+Passageway can be started before or after the local web server. It
+tunnels through to the url given in that status message "publicly
+accessible from..." for as long as the command is running. The tunnel
+is closed if the command exits.
+
+Passageway will search for the file `.localtunnel_callback` in the current
+working directory. If it exists, it will execute the file with one argument,
+the public endpoint, when the tunnel is opened. This is useful for starting
+other tools or processes that need the name of the endpoint.
+
+## Contributors
+
+ andyl (andy@r210.com)
+ Charles Merriam (charles.merriam@gmail.com)
+ Hunter Gillane (hunter.gillane@gmail.com)
+ Michael Sofaer (msofaer@pivotallabs.com)
+ Jeff Lindsay (progrium@gmail.com)
+
+## License
+
+MIT
65 README.rdoc
View
@@ -1,65 +0,0 @@
-= localtunnel -- instant public tunnel to your local web server
-
-== Install
-
-To get the dependencies if you don't have them, type:
-
- sudo apt-get install ruby ruby1.8-dev rubygems1.8 libopenssl-ruby
-
-Now you can install localtunnel with RubyGems:
-
- sudo gem install localtunnel
-
-or to get the source:
-
- git clone http://github.com/progrium/localtunnel.git
-
-== Usage
-
- localtunnel [options] <localport>
- -k, --key FILE upload a public key for authentication
-
-Localtunnel is a client to a free and open source reverse tunneling
-service made specifically for web traffic. It's intended to be used to
-temporarily expose local web servers to the greater Internet for
-debugging, unit tests, demos, etc.
-
-This is how you make your local port 8080 public:
-
- $ localtunnel 8080
- Port 8080 is now publicly accessible from http://8bv2.localtunnel.com ...
-
-Using localtunnel is comparable to using SSH reverse/remote port
-forwarding on a remote host that has GatewayPorts enabled, but without
-all the configuration or the need of a host. The localtunnel command
-works with a server component that is running on localtunnel.com,
-which is provided as a free service.
-
-If you have never run localtunnel before, you'll need to upload a public
-key to authenticate. You do this once:
-
- $ localtunnel -k ~/.ssh/id_rsa.pub 8080
-
-After that, you shouldn't have to use -k again.
-
-Localtunnel can be started before or after the local web server. It
-tunnels through to the url given in that status message "publicly
-accessible from..." for as long as the command is running. The tunnel
-is closed if the command exits.
-
-Localtunnel will search for the file .localtunnel_callback in the CWD.
-If it exists, it will execute the file with one argument, the public
-endpoint, when the tunnel is opened. This is useful for starting other
-tools or processes that need the name of the endpoint.
-
-== Contributors
-
- andyl (andy@r210.com)
- Charles Merriam (charles.merriam@gmail.com)
- Hunter Gillane (hunter.gillane@gmail.com)
- Michael Sofaer (msofaer@pivotallabs.com)
- Jeff Lindsay (progrium@gmail.com)
-
-== License
-
-MIT
21 Rakefile
View
@@ -1,16 +1,7 @@
-require 'rubygems'
-require 'rake'
-require 'echoe'
+require "bundler/gem_tasks"
+require "rspec/core/rake_task"
-Echoe.new('localtunnel', '0.3.1') do |p|
- p.description = "instant public tunnel to your local web server"
- p.url = "http://github.com/progrium/localtunnel"
- p.author = "Jeff Lindsay"
- p.email = "jeff.lindsay@twilio.com"
- p.rdoc_pattern = //
- p.rdoc_options = []
- p.ignore_pattern = ["tmp/*", "script/*"]
- p.executable_pattern = ["bin/*"]
- p.runtime_dependencies = ["json >=1.2.4", "net-ssh >=2.0.22", "net-ssh-gateway >=1.0.1"]
- p.development_dependencies = []
-end
+RSpec::Core::RakeTask.new(:spec) do |s|
+ s.rspec_opts = '--color --format d --fail-fast --order random'
+ s.pattern = 'spec/**_spec.rb'
+end
11 bin/localtunnel → bin/passageway
View
@@ -1,5 +1,6 @@
#!/usr/bin/env ruby
# Copyright (c) 2010 Jeff Lindsay
+# Copyright (c) 2013 R. Tyler Croy
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation
@@ -24,16 +25,16 @@
require 'rubygems'
require 'optparse'
-require 'localtunnel'
+require 'passageway'
key = nil
options = OptionParser.new do |o|
- o.banner =
- "Usage: localtunnel [options] <localport>\n\n" +
+ o.banner =
+ "Usage: passageway [options] <localport>\n\n" +
"The file .localtunnel_callback, if it exists in the current working directory,\n"+
"will be executed with the tunnel endpoint as the first argument once the \n" +
"tunnel is started\n\n"
-
+
o.on("-k", "--key FILE", "upload a public key for authentication") do |k|
key = File.exist?(k.to_s) ? File.open(k).read : nil
end
@@ -47,6 +48,6 @@ unless local_port.to_i.between?(1, 65535)
exit
end
-t = LocalTunnel::Tunnel.new(local_port, key)
+t = Passageway::Client.new(local_port, key)
t.register_tunnel
t.start_tunnel
2  lib/localtunnel.rb
View
@@ -1,2 +0,0 @@
-$: << File.expand_path(File.dirname(__FILE__))
-require 'localtunnel/tunnel'
72 lib/localtunnel/tunnel.rb
View
@@ -1,72 +0,0 @@
-require 'rubygems'
-require 'net/ssh'
-require 'net/ssh/gateway'
-require 'net/http'
-require 'uri'
-require 'json'
-
-require 'localtunnel/net_ssh_gateway_patch'
-
-module LocalTunnel; end
-
-class LocalTunnel::Tunnel
-
- SHELL_HOOK_FILE = "./.localtunnel_callback"
-
- attr_accessor :port, :key, :host
-
- def initialize(port, key)
- @port = port
- @key = key
- @host = ""
- end
-
- def register_tunnel(key=@key)
- url = URI.parse("http://open.localtunnel.com/")
- if key
- resp = JSON.parse(Net::HTTP.post_form(url, {"key" => key}).body)
- else
- resp = JSON.parse(Net::HTTP.get(url))
- end
- if resp.has_key? 'error'
- puts " [Error] #{resp['error']}"
- exit
- end
- @host = resp['host'].split(':').first
- @tunnel = resp
- return resp
- rescue
- puts " [Error] Unable to register tunnel. Perhaps service is down?"
- exit
- end
-
- def start_tunnel
- port = @port
- tunnel = @tunnel
- gateway = Net::SSH::Gateway.new(@host, tunnel['user'], :auth_methods => %w{ publickey })
- gateway.open_remote(port.to_i, '127.0.0.1', tunnel['through_port'].to_i) do |rp,rh|
- puts " " << tunnel['banner'] if tunnel.has_key? 'banner'
- if File.exists?(File.expand_path(SHELL_HOOK_FILE))
- system "#{File.expand_path(SHELL_HOOK_FILE)} ""#{tunnel['host']}"""
- if !$?.success?
- puts " An error occurred executing the callback hook #{SHELL_HOOK_FILE}"
- puts " (Make sure it is executable)"
- end
- end
- puts " Port #{port} is now publicly accessible from http://#{tunnel['host']} ..."
- begin
- sleep 1 while true
- rescue Interrupt
- gateway.close_remote(rp, rh)
- exit
- end
- end
- rescue Net::SSH::AuthenticationFailed
- possible_key = Dir[File.expand_path('~/.ssh/*.pub')].first
- puts " Failed to authenticate. If this is your first tunnel, you need to"
- puts " upload a public key using the -k option. Try this:\n\n"
- puts " localtunnel -k #{possible_key ? possible_key : '~/path/to/key.pub'} #{port}\n\n"
- puts " Don't have a key? Check out http://bit.ly/createsshkey"
- exit
- end
-end
5 lib/passageway.rb
View
@@ -0,0 +1,5 @@
+require "passageway/client"
+require "passageway/version"
+
+module Passageway
+end
80 lib/passageway/client.rb
View
@@ -0,0 +1,80 @@
+require 'rubygems'
+require 'net/ssh'
+require 'net/ssh/gateway'
+require 'net/http'
+require 'uri'
+require 'json'
+
+require 'passageway/net_ssh_gateway_patch'
+
+module Passageway
+ class Client
+
+ SHELL_HOOK_FILE = "./.localtunnel_callback"
+
+ attr_accessor :port, :key, :host
+
+ def initialize(port, key)
+ @port = port
+ @key = key
+ @host = ""
+ end
+
+ def register_tunnel(key=@key)
+ url = URI.parse("http://open.localtunnel.com/")
+ if key
+ resp = JSON.parse(Net::HTTP.post_form(url, {"key" => key}).body)
+ else
+ resp = JSON.parse(Net::HTTP.get(url))
+ end
+ if resp.has_key? 'error'
+ puts " [Error] #{resp['error']}"
+ exit
+ end
+ @host = resp['host'].split(':').first
+ @tunnel = resp
+ return resp
+ rescue
+ puts " [Error] Unable to register tunnel. Perhaps service is down?"
+ exit
+ end
+
+ def start_tunnel
+ port = @port
+ tunnel = @tunnel
+ gateway = Net::SSH::Gateway.new(@host, tunnel['user'], :auth_methods => %w{ publickey })
+ gateway.open_remote(port.to_i, '127.0.0.1', tunnel['through_port'].to_i) do |rp,rh|
+ puts " " << tunnel['banner'] if tunnel.has_key? 'banner'
+ if File.exists?(File.expand_path(SHELL_HOOK_FILE))
+ system "#{File.expand_path(SHELL_HOOK_FILE)} ""#{tunnel['host']}"""
+ if !$?.success?
+ puts " An error occurred executing the callback hook #{SHELL_HOOK_FILE}"
+ puts " (Make sure it is executable)"
+ end
+ end
+ puts " Port #{port} is now publicly accessible from http://#{tunnel['host']} ..."
+ begin
+ # If we're using Passageway from within Ruby
+ if block_given?
+ yield
+ else
+ # Otherwise, we're probably calling it on the command line, so
+ # let's just block forever
+ sleep 1 while true
+ end
+ rescue Interrupt
+ gateway.close_remote(rp, rh)
+ exit
+ end
+ end
+ rescue Net::SSH::AuthenticationFailed
+ possible_key = Dir[File.expand_path('~/.ssh/*.pub')].first
+ puts " Failed to authenticate. If this is your first tunnel, you need to"
+ puts " upload a public key using the -k option. Try this:\n\n"
+ puts " localtunnel -k #{possible_key ? possible_key : '~/path/to/key.pub'} #{port}\n\n"
+ puts " Don't have a key? Check out http://bit.ly/createsshkey"
+ exit
+ end
+ end
+end
+
0  lib/localtunnel/net_ssh_gateway_patch.rb → lib/passageway/net_ssh_gateway_patch.rb
View
File renamed without changes
3  lib/passageway/version.rb
View
@@ -0,0 +1,3 @@
+module Passageway
+ VERSION = "0.0.2"
+end
27 passageway.gemspec
View
@@ -0,0 +1,27 @@
+# coding: utf-8
+lib = File.expand_path('../lib', __FILE__)
+$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
+require 'passageway/version'
+
+Gem::Specification.new do |spec|
+ spec.name = "passageway"
+ spec.version = Passageway::VERSION
+ spec.authors = ["R. Tyler Croy"]
+ spec.email = ["tyler@monkeypox.org"]
+ spec.description = "A Ruby-based client for localtunnel"
+ spec.summary = "This is a fork off the original localtunnel Ruby gem, which has since been deprecated"
+ spec.homepage = "https://github.com/rtyler/passageway"
+ spec.license = "MIT"
+
+ spec.files = `git ls-files`.split($/)
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
+ spec.require_paths = ["lib"]
+
+ spec.add_development_dependency "bundler", "~> 1.3"
+ spec.add_development_dependency "rake"
+
+ spec.add_dependency 'json'
+ spec.add_dependency 'net-ssh'
+ spec.add_dependency 'net-ssh-gateway'
+end
106 server.py
View
@@ -1,106 +0,0 @@
-try:
- from twisted.internet import pollreactor
- pollreactor.install()
-except: pass
-from twisted.internet import protocol, reactor, defer, task
-from twisted.web import http, proxy, resource, server
-from twisted.python import log
-import sys, time
-import urlparse
-import socket
-import simplejson
-import re
-
-SSH_USER = 'localtunnel'
-AUTHORIZED_KEYS = '/home/localtunnel/.ssh/authorized_keys'
-PORT_RANGE = [32000, 64000]
-BANNER = "This localtunnel service is brought to you by Twilio."
-SSH_OPTIONS = 'command="/bin/echo Shell access denied",no-agent-forwarding,no-pty,no-user-rc,no-X11-forwarding '
-KEY_REGEX = re.compile(r'^ssh-(\w{3}) [^\n]+$')
-
-def port_available(port):
- try:
- socket.create_connection(['127.0.0.1', port]).close()
- return False
- except socket.error:
- return True
-
-def baseN(num,b=32,numerals="23456789abcdefghijkmnpqrstuvwxyz"):
- return ((num == 0) and "0" ) or (baseN(num // b, b).lstrip("0") + numerals[num % b])
-
-class LocalTunnelReverseProxy(proxy.ReverseProxyResource):
- isLeaf = True
-
- def __init__(self, user, host='127.0.0.1'):
- self.user = user
- self.tunnels = {}
- proxy.ReverseProxyResource.__init__(self, host, None, None)
-
- def find_tunnel_name(self):
- name = baseN(abs(hash(time.time())))[0:4]
- if (name in self.tunnels and not port_available(self.tunnels[name])) or name == 'open':
- time.sleep(0.1)
- return self.find_tunnel_name()
- return name
-
- def find_tunnel_port(self):
- port = PORT_RANGE[0]
- start_time = time.time()
- while not port_available(port):
- if time.time()-start_time > 3:
- raise Exception("No port available")
- port += 1
- if port >= PORT_RANGE[1]: port = PORT_RANGE[0]
- return port
-
- def garbage_collect(self):
- for name in self.tunnels:
- if port_available(self.tunnels[name]):
- del self.tunnels[name]
-
- def install_key(self, key):
- if not KEY_REGEX.match(key.strip()):
- return False
- key = ''.join([SSH_OPTIONS, key.strip(), "\n"])
- fr = open(AUTHORIZED_KEYS, 'r')
- if not key in fr.readlines():
- fa = open(AUTHORIZED_KEYS, 'a')
- fa.write(key)
- fa.close()
- fr.close()
- return True
-
- def register_tunnel(self, superhost, key=None):
- if key and not self.install_key(key): return simplejson.dumps(dict(error="Invalid key."))
- name = self.find_tunnel_name()
- port = self.find_tunnel_port()
- self.tunnels[name] = port
- return simplejson.dumps(
- dict(through_port=port, user=self.user, host='%s.%s' % (name, superhost), banner=BANNER))
-
- def render(self, request):
- host = request.getHeader('host')
- name, superhost = host.split('.', 1)
- if host.startswith('open.'):
- request.setHeader('Content-Type', 'application/json')
- return self.register_tunnel(superhost, request.args.get('key', [None])[0])
- else:
- if not name in self.tunnels: return "Not found"
-
- request.content.seek(0, 0)
- clientFactory = self.proxyClientFactoryClass(
- request.method, request.uri, request.clientproto,
- request.getAllHeaders(), request.content.read(), request)
- self.reactor.connectTCP(self.host, self.tunnels[name], clientFactory)
- return server.NOT_DONE_YET
-
-#if 'location' in request.responseHeaders and host in request.responseHeaders['location']:
-# # Strip out the port they think they need
-# p = re.compile(r'%s\:\d+' % host)
-# location = p.sub(host, request.responseHeaders['location'])
-# request.responseHeaders['location'] = location
-
-
-log.startLogging(sys.stdout)
-reactor.listenTCP(80, server.Site(LocalTunnelReverseProxy(SSH_USER)))
-reactor.run()
6 spec/client_spec.rb
View
@@ -0,0 +1,6 @@
+require 'spec_helper'
+require 'passageway/client'
+
+describe Passageway::Client do
+
+end
2  spec/spec_helper.rb
View
@@ -0,0 +1,2 @@
+$LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
+

No commit comments for this range

Something went wrong with that request. Please try again.