coderrr-rtunnel 0.3.9 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. data/CHANGELOG +13 -0
  2. data/LICENSE +21 -0
  3. data/Manifest +48 -0
  4. data/README.markdown +40 -15
  5. data/Rakefile +31 -4
  6. data/bin/rtunnel_client +2 -1
  7. data/bin/rtunnel_server +2 -1
  8. data/lib/rtunnel.rb +20 -0
  9. data/lib/rtunnel/client.rb +308 -0
  10. data/lib/rtunnel/command_processor.rb +62 -0
  11. data/lib/rtunnel/command_protocol.rb +50 -0
  12. data/lib/rtunnel/commands.rb +233 -0
  13. data/lib/rtunnel/connection_id.rb +24 -0
  14. data/lib/rtunnel/core.rb +58 -0
  15. data/lib/rtunnel/crypto.rb +106 -0
  16. data/lib/rtunnel/frame_protocol.rb +34 -0
  17. data/lib/rtunnel/io_extensions.rb +54 -0
  18. data/lib/rtunnel/leak.rb +35 -0
  19. data/lib/rtunnel/rtunnel_client_cmd.rb +41 -0
  20. data/lib/rtunnel/rtunnel_server_cmd.rb +32 -0
  21. data/lib/rtunnel/server.rb +351 -0
  22. data/lib/rtunnel/socket_factory.rb +119 -0
  23. data/test/command_stubs.rb +77 -0
  24. data/test/protocol_mocks.rb +43 -0
  25. data/test/scenario_connection.rb +109 -0
  26. data/test/test_client.rb +48 -0
  27. data/test/test_command_protocol.rb +82 -0
  28. data/test/test_commands.rb +49 -0
  29. data/test/test_connection_id.rb +30 -0
  30. data/test/test_crypto.rb +127 -0
  31. data/test/test_frame_protocol.rb +109 -0
  32. data/test/test_io_extensions.rb +70 -0
  33. data/test/test_server.rb +70 -0
  34. data/test/test_socket_factory.rb +42 -0
  35. data/test/test_tunnel.rb +186 -0
  36. data/test_data/authorized_keys2 +4 -0
  37. data/test_data/known_hosts +4 -0
  38. data/test_data/random_rsa_key +27 -0
  39. data/test_data/ssh_host_dsa_key +12 -0
  40. data/test_data/ssh_host_rsa_key +27 -0
  41. data/tests/_ab_test.rb +16 -0
  42. data/tests/_stress_test.rb +96 -0
  43. data/tests/lo_http_server.rb +55 -0
  44. metadata +67 -27
  45. data/ab_test.rb +0 -23
  46. data/lib/client.rb +0 -150
  47. data/lib/cmds.rb +0 -166
  48. data/lib/core.rb +0 -58
  49. data/lib/rtunnel_client_cmd.rb +0 -23
  50. data/lib/rtunnel_server_cmd.rb +0 -18
  51. data/lib/server.rb +0 -197
  52. data/rtunnel.gemspec +0 -18
  53. data/rtunnel_client.rb +0 -3
  54. data/rtunnel_server.rb +0 -3
  55. data/stress_test.rb +0 -68
data/lib/core.rb DELETED
@@ -1,58 +0,0 @@
1
- require 'resolv'
2
-
3
- module RTunnel
4
- VERSION = '0.3.9'
5
-
6
- DEFAULT_CONTROL_PORT = 19050
7
- PING_TIMEOUT = 10
8
- end
9
-
10
- if ENV['RTUNNEL_DEBUG']
11
- def D(msg)
12
- puts msg
13
- end
14
- else
15
- def D(*a);end
16
- end
17
-
18
- class << Thread
19
- def safe(*a)
20
- Thread.new(*a) do
21
- begin
22
- yield
23
- rescue Exception
24
- puts $!.inspect
25
- puts $!.backtrace.join("\n")
26
- end
27
- end
28
- end
29
- end
30
-
31
- class String
32
- def replace_with_ip!
33
- host = self.split(/:/).first
34
-
35
- ip = timeout(5) { Resolv.getaddress(host) }
36
-
37
- self.replace(self.gsub(host, ip))
38
- rescue Exception
39
- puts "Error resolving #{host}"
40
- raise
41
- end
42
- end
43
-
44
- class IO
45
- def while_reading(data = nil, &b)
46
- while buf = readpartial_rescued(1024)
47
- data << buf if data
48
- yield buf if block_given?
49
- end
50
- data
51
- end
52
-
53
- def readpartial_rescued(size)
54
- readpartial(size)
55
- rescue EOFError
56
- nil
57
- end
58
- end
@@ -1,23 +0,0 @@
1
- #!/usr/bin/ruby
2
-
3
- $LOAD_PATH << 'lib'
4
- require 'optparse'
5
- require 'client'
6
-
7
- control_address = tunnel_from_address = tunnel_to_address = remote_listen_address = nil
8
-
9
- (opts = OptionParser.new do |o|
10
- o.on("-c", "--control-address ADDRESS") { |a| control_address = a }
11
- o.on("-f", "--remote-listen-port ADDRESS") { |a| remote_listen_address = a }
12
- o.on("-t", "--tunnel-to ADDRESS") { |a| tunnel_to_address = a }
13
- end).parse! rescue (puts opts; exit)
14
-
15
- (puts opts; exit) if [control_address, remote_listen_address, tunnel_to_address].include? nil
16
-
17
- client = RTunnel::Client.new(
18
- :control_address => control_address,
19
- :remote_listen_address => remote_listen_address,
20
- :tunnel_to_address => tunnel_to_address
21
- )
22
- client.start
23
- client.join
@@ -1,18 +0,0 @@
1
- #!/usr/bin/ruby
2
-
3
- $LOAD_PATH << 'lib'
4
- require 'optparse'
5
- require 'server'
6
-
7
- control_address = tunnel_port = nil
8
-
9
- (opts = OptionParser.new do |o|
10
- o.on("-c", "--control ADDRESS") { |a| control_address = a }
11
- end).parse! rescue (puts opts; exit)
12
-
13
- server = RTunnel::Server.new(
14
- :control_address => control_address
15
- )
16
-
17
- server.start
18
- server.join
data/lib/server.rb DELETED
@@ -1,197 +0,0 @@
1
- require 'rubygems'
2
- gem 'uuidtools', '>=1.0.2'
3
- require 'uuidtools'
4
-
5
- require 'core'
6
- require 'cmds'
7
-
8
- require 'gserver'
9
-
10
- Socket.do_not_reverse_lookup = true
11
-
12
- module RTunnel
13
- # listens for incoming connections to tunnel
14
- class RemoteListenServer < GServer
15
- CONNECTIONS = {}
16
- CONTROL_CONNECTION_MAPPING = {}
17
-
18
- def initialize(port, host, control_connection)
19
- super(port, host, 10)
20
- @control_connection = control_connection
21
- @maxConnections = 1024
22
- end
23
-
24
- def serve(sock)
25
- D "new incoming connection"
26
-
27
- conn_id = UUID.timestamp_create.hexdigest
28
- CONNECTIONS[conn_id] = sock
29
- CONTROL_CONNECTION_MAPPING[conn_id] = @control_connection
30
- begin
31
- ControlServer.new_tunnel(conn_id)
32
-
33
- sock.while_reading do |buf|
34
- begin
35
- ControlServer.send_data(conn_id, buf)
36
- rescue Exception
37
- D "error talking on control connection, dropping incoming connection: #{$!.inspect}"
38
- break
39
- end
40
- end
41
- rescue IOError
42
- raise unless $!.message =~ /stream closed/i
43
- end
44
-
45
- ControlServer.close_tunnel(conn_id)
46
-
47
- CONNECTIONS.delete conn_id
48
- CONTROL_CONNECTION_MAPPING.delete conn_id
49
-
50
- D "sock closed"
51
- rescue
52
- p $!
53
- puts $!.backtrace.join("\n")
54
- end
55
- end
56
-
57
- class ControlServer < GServer
58
- @@control_connections = []
59
- @@remote_listen_servers = []
60
-
61
- @@m = Mutex.new
62
-
63
- attr_accessor :ping_interval
64
-
65
- def initialize(*args)
66
- super
67
- @maxConnections = 1024
68
- end
69
-
70
- class << self
71
- def new_tunnel(conn_id)
72
- D "sending create connection command: #{conn_id}"
73
-
74
- @@m.synchronize { control_connection_for(conn_id).write CreateConnectionCommand.new(conn_id) }
75
- end
76
-
77
- def send_data(conn_id, data)
78
- @@m.synchronize { control_connection_for(conn_id).write SendDataCommand.new(conn_id, data) }
79
- end
80
-
81
- def close_tunnel(conn_id)
82
- D "sending close connection command"
83
-
84
- @@m.synchronize { control_connection_for(conn_id).write CloseConnectionCommand.new(conn_id) }
85
- end
86
-
87
- private
88
-
89
- def control_connection_for(conn_id)
90
- RemoteListenServer::CONTROL_CONNECTION_MAPPING[conn_id]
91
- end
92
- end
93
-
94
- def starting
95
- start_pinging
96
- end
97
-
98
- def serve(sock)
99
- D "new control connection"
100
- @@control_connections << sock
101
- sock.sync = true
102
-
103
- cmd_queue = ""
104
- sock.while_reading(cmd_queue = '') do
105
- while Command.match(cmd_queue)
106
- case cmd = Command.parse(cmd_queue)
107
- when RemoteListenCommand
108
- @@m.synchronize do
109
- addr, port = cmd.address.split(/:/)
110
- if rls = @@remote_listen_servers.detect {|s| s.port == port.to_i }
111
- rls.stop
112
- @@remote_listen_servers.delete rls
113
- end
114
- (new_rls = RemoteListenServer.new(port, addr, sock)).start
115
- @@remote_listen_servers << new_rls
116
- end
117
- D "listening for remote connections on #{cmd.address}"
118
- when SendDataCommand
119
- conn = RemoteListenServer::CONNECTIONS[cmd.conn_id]
120
- begin
121
- conn.write(cmd.data) if conn
122
- rescue Errno::EPIPE
123
- D "broken pipe on #{cmd.conn_id}"
124
- end
125
- when CloseConnectionCommand
126
- if connection = RemoteListenServer::CONNECTIONS[cmd.conn_id]
127
- D "closing remote connection: #{cmd.conn_id}"
128
- connection.close
129
- end
130
- else
131
- D "bad command received: #{cmd.inspect}"
132
- end
133
- end
134
- end
135
- rescue Errno::ECONNRESET
136
- D "client disconnected (conn reset)"
137
- rescue
138
- D $!.inspect
139
- D $@*"\n"
140
- raise
141
- ensure
142
- @@control_connections.delete sock
143
- end
144
-
145
- def stopping
146
- @ping_thread.kill
147
- @@remote_listen_server.stop
148
- end
149
-
150
- private
151
-
152
- def start_pinging
153
- @ping_thread = Thread.safe do
154
- loop do
155
- sleep @ping_interval
156
-
157
- @@m.synchronize do
158
- @@control_connections.each {|cc| cc.write PingCommand.new }
159
- end
160
- end
161
- end
162
- end
163
- end
164
-
165
- class Server
166
- def initialize(options = {})
167
- @control_address = options[:control_address]
168
- if ! @control_address
169
- @control_address = "0.0.0.0:#{DEFAULT_CONTROL_PORT}" if ! @control_address
170
- elsif @control_address =~ /^\d+$/
171
- @control_address.insert 0, "0.0.0.0:"
172
- elsif @control_address !~ /:\d+$/
173
- @control_address << ":#{DEFAULT_CONTROL_PORT}"
174
- end
175
- @control_host = @control_address.split(/:/).first
176
-
177
- @ping_interval = options[:ping_interval] || 2.0
178
- end
179
-
180
- def start
181
- @control_server = ControlServer.new(*@control_address.split(/:/).reverse)
182
- @control_server.ping_interval = @ping_interval
183
- @control_server.audit = true
184
-
185
- @control_server.start
186
- end
187
-
188
- def join
189
- @control_server.join
190
- end
191
-
192
- def stop
193
- @control_server.shutdown
194
- ControlServer.stop(@control_server.port, @control_server.host)
195
- end
196
- end
197
- end
data/rtunnel.gemspec DELETED
@@ -1,18 +0,0 @@
1
- Gem::Specification.new do |s|
2
- s.name = "rtunnel"
3
- s.version = "0.3.9"
4
- s.summary = "reverse tunnel server and client"
5
- s.email = "coderrr.contact@gmail.com"
6
- s.homepage = "http://github.com/coderrr/rtunnel"
7
- s.description = "reverse tunnel server and client"
8
- s.has_rdoc = false
9
- s.authors = ["coderrr"]
10
- s.files = [
11
- "lib/rtunnel_server_cmd.rb", "lib/client.rb", "lib/core.rb", "lib/rtunnel_client_cmd.rb", "lib/server.rb", "lib/cmds.rb", "bin/rtunnel_server", "bin/rtunnel_client",
12
- "ab_test.rb", "README.markdown", "rtunnel.gemspec", "stress_test.rb", "Rakefile", "rtunnel_client.rb", "rtunnel_server.rb"
13
- ]
14
- s.test_files = [
15
- "spec/integration_spec.rb", "spec/spec_helper.rb", "spec/client_spec.rb", "spec/cmds_spec.rb", "spec/server_spec.rb"
16
- ]
17
- s.add_dependency("uuidtools", [">= 1.0.2"])
18
- end
data/rtunnel_client.rb DELETED
@@ -1,3 +0,0 @@
1
- #!/usr/bin/ruby
2
-
3
- load 'lib/rtunnel_client_cmd.rb'
data/rtunnel_server.rb DELETED
@@ -1,3 +0,0 @@
1
- #!/usr/bin/ruby
2
-
3
- load 'lib/rtunnel_server_cmd.rb'
data/stress_test.rb DELETED
@@ -1,68 +0,0 @@
1
- require 'rubygems'
2
- require 'thin'
3
-
4
- require 'lib/core'
5
-
6
- require 'logger'
7
- require 'stringio'
8
-
9
-
10
- CONCURRENT_CONNECTIONS = 25
11
- DISPLAY_RTUNNEL_OUTPUT = false
12
- TUNNEL_PORT = 5000
13
- HTTP_PORT = 4444
14
-
15
- #################
16
-
17
- pids = []
18
- at_exit do
19
- pids.each {|pid| Process.kill 9, pid }
20
- p $!
21
- puts "done, hit ^C"
22
- sleep 999999
23
- end
24
-
25
- module Enumerable
26
- def parallel_map
27
- self.map do |e|
28
- Thread.new(e) do |element|
29
- yield element
30
- end
31
- end.map {|thread| thread.value }
32
- end
33
- end
34
-
35
- TUNNEL_URI = "http://localhost:#{TUNNEL_PORT}"
36
- EXPECTED_DATA = (0..10*1024).map{0until(c=rand(?z).chr)=~/(?!_)\w/;c}*'' # gen random string GOLF FTW!
37
- puts EXPECTED_DATA
38
-
39
- app = lambda { |env| [200, {}, EXPECTED_DATA] }
40
- server = ::Thin::Server.new('localhost', HTTP_PORT, app)
41
- Thread.new { server.start }
42
-
43
- base_dir = File.dirname(__FILE__)
44
-
45
- d = !DISPLAY_RTUNNEL_OUTPUT
46
- pids << fork{ exec "ruby #{base_dir}/rtunnel_server.rb #{d && '> /dev/null'} 2>&1" }
47
- pids << fork{ exec "ruby #{base_dir}/rtunnel_client.rb -c localhost -f #{TUNNEL_PORT} -t #{HTTP_PORT} #{d &&' > /dev/null'} 2>&1" }
48
-
49
- puts 'wait 2 secs'
50
- sleep 2
51
-
52
- STDOUT.sync = true
53
- 999999999.times do |i|
54
- puts i if i%10 == 0
55
- threads = []
56
- CONCURRENT_CONNECTIONS.times do
57
- threads << Thread.new do
58
- text = %x{curl --silent #{TUNNEL_URI}}
59
- if text != EXPECTED_DATA
60
- puts "BAD!!!!"*1000
61
- puts "response: #{text.inspect}"
62
- exit
63
- end
64
- end
65
- end
66
-
67
- threads.parallel_map {|t| t.join; print '.'; STDOUT.flush }
68
- end