coderrr-rtunnel 0.3.9 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
metadata CHANGED
@@ -1,50 +1,94 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: coderrr-rtunnel
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.9
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - coderrr
8
+ - costan
8
9
  autorequire:
9
10
  bindir: bin
10
11
  cert_chain: []
11
12
 
12
- date: 2008-10-25 00:00:00 -07:00
13
+ date: 2009-01-11 00:00:00 -08:00
13
14
  default_executable:
14
15
  dependencies:
15
16
  - !ruby/object:Gem::Dependency
16
- name: uuidtools
17
+ name: eventmachine
17
18
  version_requirement:
18
19
  version_requirements: !ruby/object:Gem::Requirement
19
20
  requirements:
20
21
  - - ">="
21
22
  - !ruby/object:Gem::Version
22
- version: 1.0.2
23
+ version: 0.12.2
23
24
  version:
24
- description: reverse tunnel server and client
25
+ - !ruby/object:Gem::Dependency
26
+ name: net-ssh
27
+ version_requirement:
28
+ version_requirements: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 2.0.4
33
+ version:
34
+ description: ""
25
35
  email: coderrr.contact@gmail.com
26
- executables: []
27
-
36
+ executables:
37
+ - rtunnel_client
38
+ - rtunnel_server
28
39
  extensions: []
29
40
 
30
41
  extra_rdoc_files: []
31
42
 
32
43
  files:
33
- - lib/rtunnel_server_cmd.rb
34
- - lib/client.rb
35
- - lib/core.rb
36
- - lib/rtunnel_client_cmd.rb
37
- - lib/server.rb
38
- - lib/cmds.rb
39
- - bin/rtunnel_server
40
- - bin/rtunnel_client
41
- - ab_test.rb
44
+ - CHANGELOG
45
+ - LICENSE
46
+ - Manifest
42
47
  - README.markdown
43
- - rtunnel.gemspec
44
- - stress_test.rb
45
48
  - Rakefile
46
- - rtunnel_client.rb
47
- - rtunnel_server.rb
49
+ - bin/rtunnel_client
50
+ - bin/rtunnel_server
51
+ - lib/rtunnel.rb
52
+ - lib/rtunnel/client.rb
53
+ - lib/rtunnel/command_protocol.rb
54
+ - lib/rtunnel/commands.rb
55
+ - lib/rtunnel/core.rb
56
+ - lib/rtunnel/crypto.rb
57
+ - lib/rtunnel/frame_protocol.rb
58
+ - lib/rtunnel/io_extensions.rb
59
+ - lib/rtunnel/leak.rb
60
+ - lib/rtunnel/rtunnel_client_cmd.rb
61
+ - lib/rtunnel/rtunnel_server_cmd.rb
62
+ - lib/rtunnel/server.rb
63
+ - lib/rtunnel/socket_factory.rb
64
+ - lib/rtunnel/connection_id.rb
65
+ - lib/rtunnel/command_processor.rb
66
+ - spec/client_spec.rb
67
+ - spec/cmds_spec.rb
68
+ - spec/integration_spec.rb
69
+ - spec/server_spec.rb
70
+ - spec/spec_helper.rb
71
+ - test/command_stubs.rb
72
+ - test/protocol_mocks.rb
73
+ - test/scenario_connection.rb
74
+ - test/test_client.rb
75
+ - test/test_command_protocol.rb
76
+ - test/test_commands.rb
77
+ - test/test_crypto.rb
78
+ - test/test_frame_protocol.rb
79
+ - test/test_io_extensions.rb
80
+ - test/test_server.rb
81
+ - test/test_socket_factory.rb
82
+ - test/test_tunnel.rb
83
+ - test/test_connection_id.rb
84
+ - test_data/known_hosts
85
+ - test_data/ssh_host_rsa_key
86
+ - test_data/random_rsa_key
87
+ - test_data/ssh_host_dsa_key
88
+ - test_data/authorized_keys2
89
+ - tests/_ab_test.rb
90
+ - tests/_stress_test.rb
91
+ - tests/lo_http_server.rb
48
92
  has_rdoc: false
49
93
  homepage: http://github.com/coderrr/rtunnel
50
94
  post_install_message:
@@ -70,10 +114,6 @@ rubyforge_project:
70
114
  rubygems_version: 1.2.0
71
115
  signing_key:
72
116
  specification_version: 2
73
- summary: reverse tunnel server and client
74
- test_files:
75
- - spec/integration_spec.rb
76
- - spec/spec_helper.rb
77
- - spec/client_spec.rb
78
- - spec/cmds_spec.rb
79
- - spec/server_spec.rb
117
+ summary: Reverse tunnel server and client.
118
+ test_files: []
119
+
data/ab_test.rb DELETED
@@ -1,23 +0,0 @@
1
- #require 'facets'
2
- require 'net/http'
3
- require 'logger'
4
- require 'stringio'
5
- require 'webrick'
6
-
7
- require 'lib/core'
8
-
9
- puts "make sure a fast responding webserver is started on port 4000"
10
-
11
- base_dir = File.dirname(__FILE__)
12
-
13
- fork{ exec "ruby #{base_dir}/rtunnel_server.rb > /dev/null 2>&1" }
14
- fork{ exec "ruby #{base_dir}/rtunnel_client.rb -c localhost -f 5000 -t 4000 > /dev/null" }
15
-
16
- sleep 2
17
-
18
- (puts "you need ab (apache bench) to run this stress test" ; exit) if %x{which ab}.empty?
19
-
20
- Process.wait fork { exec("ab -c 500 -n 10000 http://localhost:5000/") }
21
-
22
- puts "done, hit ^C"
23
- sleep 999999
data/lib/client.rb DELETED
@@ -1,150 +0,0 @@
1
- require 'core'
2
- require 'cmds'
3
- require 'leak'
4
-
5
- require 'gserver'
6
- require 'timeout'
7
-
8
- module RTunnel
9
- class Client
10
- CONNECTIONS = {}
11
-
12
- def initialize(options = {})
13
- @control_address = options[:control_address]
14
- @control_address << ":#{DEFAULT_CONTROL_PORT}" if @control_address !~ /:\d+$/
15
- @control_host = @control_address.split(/:/).first
16
-
17
- @remote_listen_address = options[:remote_listen_address]
18
- @remote_listen_address.insert 0, "0.0.0.0:" if @remote_listen_address =~ /^\d+$/
19
-
20
- @tunnel_to_address = options[:tunnel_to_address]
21
- @tunnel_to_address.insert 0, "localhost:" if @tunnel_to_address =~ /^\d+$/
22
-
23
- [@control_address, @remote_listen_address, @tunnel_to_address].each do |addr|
24
- addr.replace_with_ip!
25
- end
26
-
27
- @ping_timeout = options[:ping_timeout] || PING_TIMEOUT
28
- end
29
-
30
- def start
31
- @threads = []
32
-
33
- @last_ping = Time.now
34
-
35
- @threads << Thread.safe do
36
- loop do
37
- if @check_ping and (Time.now - @last_ping) > @ping_timeout
38
- D "control connection timeout"
39
- @control_sock.close rescue nil
40
- end
41
-
42
- sleep 1
43
- end
44
- end
45
-
46
- # Memory leak testing
47
- LeakTracker.start
48
-
49
- @main_thread = Thread.safe do
50
- loop do
51
- stop_ping_check
52
- D "connecting to control address (#{@control_address})"
53
- @control_sock = begin
54
- timeout(5) { TCPSocket.new(*@control_address.split(/:/)) }
55
- rescue Exception
56
- D "fail"
57
- sleep 1
58
- next
59
- end
60
-
61
- start_ping_check
62
-
63
- write_to_control_sock RemoteListenCommand.new(@remote_listen_address)
64
-
65
- cmd_queue = ""
66
- while data = (@control_sock.readpartial(16384) rescue (D "control sock read error: #{$!.inspect}"; nil))
67
- cmd_queue << data
68
- while Command.match(cmd_queue)
69
- case command = Command.parse(cmd_queue)
70
- when PingCommand
71
- @last_ping = Time.now
72
- when CreateConnectionCommand
73
- begin
74
- # TODO: this currently blocks, but if we put it in thread, a SendDataCommand may try to get run for this connection before the connection exists
75
- CONNECTIONS[command.conn_id] = TCPSocket.new(*@tunnel_to_address.split(/:/))
76
-
77
- Thread.safe do
78
- cmd = command
79
- conn = CONNECTIONS[cmd.conn_id]
80
-
81
- begin
82
- while localdata = conn.readpartial(16834)
83
- write_to_control_sock SendDataCommand.new(cmd.conn_id, localdata)
84
- end
85
- rescue Exception
86
- begin
87
- D "to tunnel closed, closing from tunnel"
88
- conn.close
89
- CONNECTIONS.delete cmd.conn_id
90
- write_to_control_sock CloseConnectionCommand.new(cmd.conn_id)
91
- rescue
92
- p $!
93
- puts $!.backtrace.join("\n")
94
- end
95
- end
96
- end
97
- rescue Exception
98
- D "error connecting to local port"
99
- write_to_control_sock CloseConnectionCommand.new(command.conn_id)
100
- end
101
- when CloseConnectionCommand
102
- D "closing connection #{command.conn_id}"
103
- if connection = CONNECTIONS[command.conn_id]
104
- # TODO: how the hell do u catch a .close error?
105
- connection.close_read
106
- #connection.close unless connection.closed?
107
- CONNECTIONS.delete(command.conn_id)
108
- end
109
- when SendDataCommand
110
- if connection = CONNECTIONS[command.conn_id]
111
- connection.write(command.data)
112
- else
113
- puts "WARNING: received data for non existant connection!"
114
- end
115
- end
116
- end
117
- end
118
- end
119
- end
120
-
121
- @threads << @main_thread
122
- end
123
-
124
- def join
125
- @main_thread.join
126
- end
127
-
128
- def stop
129
- @threads.each { |t| t.kill! rescue nil}
130
- @control_sock.close rescue nil
131
- end
132
-
133
- private
134
-
135
- def write_to_control_sock(data)
136
- (@control_sock_mutex ||= Mutex.new).synchronize do
137
- @control_sock.write data
138
- end
139
- end
140
-
141
- def start_ping_check
142
- @last_ping = Time.now
143
- @check_ping = true
144
- end
145
-
146
- def stop_ping_check
147
- @check_ping = false
148
- end
149
- end
150
- end
data/lib/cmds.rb DELETED
@@ -1,166 +0,0 @@
1
- module RTunnel
2
- class Command
3
-
4
- def to_s
5
- CLASSES_TO_CODES[self.class].dup
6
- end
7
-
8
- class << self
9
- def parse(data)
10
- klass = class_from_code(data[0..0])
11
-
12
- new_data = data[1..-1]
13
- cmd = klass.parse(new_data)
14
-
15
- data.replace(new_data)
16
-
17
- cmd
18
- end
19
-
20
- def match(data)
21
- return false if ! (klass = class_from_code(data[0..0]))
22
-
23
- klass.match(data[1..-1])
24
- end
25
-
26
- private
27
-
28
- def class_from_code(code)
29
- CODES_TO_CLASSES[code]
30
- end
31
- end
32
- end
33
-
34
- class ConnectionCommand < Command
35
- attr_reader :conn_id
36
-
37
- def initialize(conn_id)
38
- @conn_id = conn_id
39
- end
40
-
41
- def to_s
42
- super + "#{conn_id}|"
43
- end
44
-
45
- class << self
46
- RE = %r{^([^|]+)\|}
47
-
48
- def parse(data)
49
- data =~ RE
50
- conn_id = $1
51
-
52
- cmd = self.new(conn_id)
53
-
54
- data.sub! RE, ''
55
-
56
- cmd
57
- end
58
-
59
- def match(data)
60
- !! (data =~ RE)
61
- end
62
- end
63
-
64
- end
65
-
66
- class CreateConnectionCommand < ConnectionCommand
67
- end
68
-
69
- class CloseConnectionCommand < ConnectionCommand
70
- end
71
-
72
- class SendDataCommand < Command
73
- attr_reader :conn_id
74
- attr_reader :data
75
-
76
- def initialize(conn_id, data)
77
- @conn_id = conn_id
78
- @data = data
79
- end
80
-
81
- def to_s
82
- super + "#{conn_id}|#{data.size}|#{data}"
83
- end
84
-
85
- class << self
86
- RE = %r{^([^|]+)\|([^|]+)\|}
87
-
88
- def parse(data)
89
- data =~ RE
90
-
91
- conn_id = $1
92
- data_size = $2.to_i
93
-
94
- new_data = data.sub(RE, '')
95
- cmd_data = new_data[0,data_size]
96
-
97
- cmd = SendDataCommand.new(conn_id, cmd_data)
98
-
99
- data.replace(new_data[data_size..-1])
100
-
101
- cmd
102
- end
103
-
104
- def match(data)
105
- return false if ! (data =~ RE)
106
-
107
- data_size = $2.to_i
108
-
109
- data.sub(RE, '').size >= data_size
110
- end
111
- end
112
- end
113
-
114
- class RemoteListenCommand < Command
115
- attr_reader :address
116
-
117
- def initialize(address)
118
- @address = address
119
- end
120
-
121
- def to_s
122
- super + "#{address}|"
123
- end
124
-
125
- class << self
126
- RE = %r{^([^|]+)\|}
127
-
128
- def parse(data)
129
- data =~ RE
130
- address = $1
131
-
132
- cmd = self.new(address)
133
-
134
- data.sub! RE, ''
135
-
136
- cmd
137
- end
138
-
139
- def match(data)
140
- !! (data =~ RE)
141
- end
142
- end
143
-
144
- end
145
-
146
- class PingCommand < Command
147
- def self.parse(data)
148
- PingCommand.new
149
- end
150
-
151
- def self.match(data)
152
- true
153
- end
154
- end
155
-
156
- class Command
157
- CODES_TO_CLASSES = {
158
- "C" => CreateConnectionCommand,
159
- "X" => CloseConnectionCommand,
160
- "D" => SendDataCommand,
161
- "P" => PingCommand,
162
- "L" => RemoteListenCommand,
163
- }
164
- CLASSES_TO_CODES = CODES_TO_CLASSES.invert
165
- end
166
- end