kerryb-net-ssh-socks 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,3 @@
1
+ pkg/*
2
+ *.gem
3
+ .bundle
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in net-ssh-socks.gemspec
4
+ gemspec
@@ -0,0 +1,16 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ net-ssh-socks (0.0.2)
5
+ net-ssh (~> 2.0)
6
+
7
+ GEM
8
+ remote: http://rubygems.org/
9
+ specs:
10
+ net-ssh (2.1.4)
11
+
12
+ PLATFORMS
13
+ ruby
14
+
15
+ DEPENDENCIES
16
+ net-ssh-socks!
@@ -0,0 +1,28 @@
1
+ # Net::SSH::Socks
2
+
3
+ ## Description
4
+
5
+ Net::SSH::Socks is a library for programmatically creating a SOCKS proxy server that tunnels through SSH. Similar to Net::SSH::Service::Forward#local except the host is dynamic (determined by the client application, such as a browser).
6
+
7
+ Useful for securing traffic over SSH or getting in/out of a firewall.
8
+
9
+ ## Use cases
10
+
11
+ * If your company blocks certain sites/resources but allows SSH, then you can tunnel out to a machine outside the firewall.
12
+ * If you need to access sites/resources inside a firewall, then you can tunnel into a machine inside the firewall.
13
+ * Encrypt your traffic to protect yourself from things like Firesheep on public wifi.
14
+
15
+ ## Synopsis
16
+
17
+ require 'net/ssh/socks'
18
+
19
+ Net::SSH.start('host', 'user') do |ssh|
20
+ ssh.forward.socks(8080)
21
+ ssh.loop { true }
22
+ end
23
+
24
+ Now, configure your browser to use a SOCKS proxy at localhost:8080
25
+
26
+ ## Install
27
+
28
+ gem install net-ssh-socks
@@ -0,0 +1,2 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
@@ -0,0 +1,146 @@
1
+ require 'net/ssh'
2
+
3
+ module Net
4
+ module SSH
5
+ class Socks
6
+ VERSION = "0.0.3"
7
+
8
+ METHOD_NO_AUTH = 0
9
+ CMD_CONNECT = 1
10
+ REP_SUCCESS = 0
11
+ RESERVED = 0
12
+ ATYP_IPV4 = 1
13
+ ATYP_DOMAIN = 3
14
+ ATYP_IPV6 = 4
15
+ SOCKS4 = 4
16
+ SOCKS4_SUCCESS = [0, 0x5a, 0, 0, 0, 0, 0, 0].pack("C*")
17
+ SOCKS5 = 5
18
+
19
+ # client is an open socket
20
+ def initialize(client)
21
+ @client = client
22
+ end
23
+
24
+ # Communicates with a client application as described by the SOCKS 5
25
+ # specification: http://tools.ietf.org/html/rfc1928 and
26
+ # http://en.wikipedia.org/wiki/SOCKS
27
+ # returns the host and port requested by the client
28
+ def client_handshake
29
+ version = @client.recv(1).unpack("C*").first
30
+ case version
31
+ when SOCKS4 then client_handshake_v4
32
+ when SOCKS5 then client_handshake_v5
33
+ else
34
+ raise "SOCKS version not supported: #{version.inspect}"
35
+ end
36
+ end
37
+
38
+ def client_handshake_v4
39
+ command = @client.recv(1)
40
+ port = @client.recv(2).unpack("n").first
41
+ ip_addr = @client.recv(4).unpack("C*").join('.')
42
+ username = @client.recv(1024) # read the rest of the stream
43
+
44
+ @client.send SOCKS4_SUCCESS, 0
45
+ [ip_addr, port]
46
+ end
47
+
48
+ def client_handshake_v5
49
+ nmethods, *methods = @client.recv(8).unpack("C*")
50
+
51
+ if methods.include?(METHOD_NO_AUTH)
52
+ packet = [SOCKS5, METHOD_NO_AUTH].pack("C*")
53
+ @client.send packet, 0
54
+ else
55
+ @client.close
56
+ raise 'Unsupported authentication method. Only "No Authentication" is supported'
57
+ end
58
+
59
+ version, command, reserved, address_type, *destination = @client.recv(256).unpack("C*")
60
+
61
+ packet = ([SOCKS5, REP_SUCCESS, RESERVED, address_type] + destination).pack("C*")
62
+ @client.send packet, 0
63
+
64
+ remote_host, remote_port = case address_type
65
+ when ATYP_IPV4
66
+ host = destination[0..-3].join('.')
67
+ port = destination[-2..-1].pack('C*').unpack('n')
68
+ [host, port]
69
+ when ATYP_DOMAIN
70
+ host = destination[1..-3].pack('C*')
71
+ port = destination[-2..-1].pack('C*').unpack('n')
72
+ [host, port]
73
+ when ATYP_IPV6
74
+ @client.close
75
+ raise 'Unsupported address type. Only "IPv4" is supported'
76
+ else
77
+ raise "Unknown address_type: #{address_type}"
78
+ end
79
+
80
+ [remote_host, remote_port]
81
+ end
82
+ end
83
+ end
84
+ end
85
+
86
+ class Net::SSH::Connection::Session
87
+ def on_close(&block)
88
+ @on_close = block
89
+ end
90
+
91
+ alias_method :close_without_callbacks, :close
92
+ def close
93
+ close_without_callbacks
94
+ @on_close.call if @on_close
95
+ end
96
+ end
97
+
98
+ class Net::SSH::Service::Forward
99
+ # Starts listening for connections on the local host, and forwards them
100
+ # to the specified remote host/port via the SSH connection. This method
101
+ # accepts either one or two arguments. When two arguments are given,
102
+ # they are:
103
+ #
104
+ # * the local address to bind to
105
+ # * the local port to listen on
106
+ #
107
+ # If one argument is given, it is as if the local bind address is
108
+ # "127.0.0.1", and the rest are applied as above.
109
+ #
110
+ # ssh.forward.socks(8080)
111
+ # ssh.forward.socks("0.0.0.0", 8080)
112
+ def socks(*args)
113
+ if args.length < 1 || args.length > 2
114
+ raise ArgumentError, "expected 1 or 2 parameters, got #{args.length}"
115
+ end
116
+
117
+ bind_address = "127.0.0.1"
118
+ bind_address = args.shift if args.first.is_a?(String) && args.first =~ /\D/
119
+ local_port = args.shift.to_i
120
+ info { "socks on #{bind_address} port #{local_port}" }
121
+
122
+ socks_server = TCPServer.new(bind_address, local_port)
123
+ session.listen_to(socks_server) do |server|
124
+ client = server.accept
125
+
126
+ socks = Net::SSH::Socks.new(client)
127
+ remote_host, remote_port = socks.client_handshake
128
+ info { "connection requested on #{remote_host} port #{remote_port}" }
129
+
130
+ channel = session.open_channel("direct-tcpip", :string, remote_host, :long, remote_port, :string, bind_address, :long, local_port) do |channel|
131
+ info { "direct channel established" }
132
+ prepare_client(client, channel, :local)
133
+ end
134
+
135
+ channel.on_open_failed do |ch, code, description|
136
+ error { "could not establish direct channel: #{description} (#{code})" }
137
+ client.close
138
+ end
139
+ end
140
+
141
+ session.on_close do
142
+ debug { "cleaning up socks server" }
143
+ socks_server.close
144
+ end
145
+ end
146
+ end
@@ -0,0 +1,23 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require 'net/ssh/socks'
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "kerryb-net-ssh-socks"
7
+ s.version = Net::SSH::Socks::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Mike Enriquez"]
10
+ s.email = ["mike@edgecase.com"]
11
+ s.homepage = ""
12
+ s.summary = %q{An extension to Net::SSH that adds dynamic port forwarding through a SOCKS proxy}
13
+ s.description = %q{Net::SSH::Socks is a library for programmatically creating a SOCKS proxy. Similar to Net::SSH::Service::Forward#local except the host is dynamic (determined by the client application, such as a browser).}
14
+
15
+ s.rubyforge_project = "net-ssh-socks"
16
+
17
+ s.add_dependency "net-ssh", "~> 2.0"
18
+
19
+ s.files = `git ls-files`.split("\n")
20
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
21
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
22
+ s.require_paths = ["lib"]
23
+ end
metadata ADDED
@@ -0,0 +1,73 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: kerryb-net-ssh-socks
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.0.3
6
+ platform: ruby
7
+ authors:
8
+ - Mike Enriquez
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2011-05-02 00:00:00 +01:00
14
+ default_executable:
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: net-ssh
18
+ prerelease: false
19
+ requirement: &id001 !ruby/object:Gem::Requirement
20
+ none: false
21
+ requirements:
22
+ - - ~>
23
+ - !ruby/object:Gem::Version
24
+ version: "2.0"
25
+ type: :runtime
26
+ version_requirements: *id001
27
+ description: Net::SSH::Socks is a library for programmatically creating a SOCKS proxy. Similar to Net::SSH::Service::Forward#local except the host is dynamic (determined by the client application, such as a browser).
28
+ email:
29
+ - mike@edgecase.com
30
+ executables: []
31
+
32
+ extensions: []
33
+
34
+ extra_rdoc_files: []
35
+
36
+ files:
37
+ - .gitignore
38
+ - Gemfile
39
+ - Gemfile.lock
40
+ - README.md
41
+ - Rakefile
42
+ - lib/net/ssh/socks.rb
43
+ - net-ssh-socks.gemspec
44
+ has_rdoc: true
45
+ homepage: ""
46
+ licenses: []
47
+
48
+ post_install_message:
49
+ rdoc_options: []
50
+
51
+ require_paths:
52
+ - lib
53
+ required_ruby_version: !ruby/object:Gem::Requirement
54
+ none: false
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ version: "0"
59
+ required_rubygems_version: !ruby/object:Gem::Requirement
60
+ none: false
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ version: "0"
65
+ requirements: []
66
+
67
+ rubyforge_project: net-ssh-socks
68
+ rubygems_version: 1.6.2
69
+ signing_key:
70
+ specification_version: 3
71
+ summary: An extension to Net::SSH that adds dynamic port forwarding through a SOCKS proxy
72
+ test_files: []
73
+