reverse-tunnel 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,3 @@
1
+ module ReverseTunnel
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,33 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'reverse-tunnel/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "reverse-tunnel"
8
+ gem.version = ReverseTunnel::VERSION
9
+ gem.authors = ["Alban Peignier", "Florent Peyraud"]
10
+ gem.email = ["alban@tryphon.eu", "florent@tryphon.eu"]
11
+ gem.description = %q{Create easily a tunnel to forward connection (like a ssh) to the client host}
12
+ gem.summary = %q{Forward a tcp connection to client host}
13
+ gem.homepage = "http://projects.tryphon.eu/projects/reverse-tunnel"
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ["lib"]
19
+
20
+ gem.add_runtime_dependency "eventmachine"
21
+ gem.add_runtime_dependency "msgpack"
22
+ gem.add_runtime_dependency "eventmachine_httpserver"
23
+ gem.add_runtime_dependency "json"
24
+ gem.add_runtime_dependency "trollop"
25
+ gem.add_runtime_dependency "SyslogLogger"
26
+
27
+ gem.add_development_dependency "simplecov"
28
+ gem.add_development_dependency "rspec"
29
+ gem.add_development_dependency "guard"
30
+ gem.add_development_dependency "guard-rspec"
31
+ gem.add_development_dependency "rake"
32
+ gem.add_development_dependency "rest-client"
33
+ end
@@ -0,0 +1,118 @@
1
+ require 'spec_helper'
2
+
3
+ describe ReverseTunnel::CLI do
4
+
5
+ describe "#debug=" do
6
+
7
+ context "when true" do
8
+ it "should change Logger level to debug" do
9
+ ReverseTunnel.logger.level = Logger::INFO
10
+ lambda {
11
+ subject.debug = true
12
+ }.should change(ReverseTunnel.logger, :level).to(Logger::DEBUG)
13
+ end
14
+ end
15
+
16
+ context "when false" do
17
+ it "should change Logger level to info" do
18
+ ReverseTunnel.logger.level = Logger::DEBUG
19
+ lambda {
20
+ subject.debug = false
21
+ }.should change(ReverseTunnel.logger, :level).to(Logger::INFO)
22
+ end
23
+ end
24
+
25
+ after do
26
+ ReverseTunnel.reset_logger!
27
+ end
28
+
29
+ end
30
+
31
+ describe "#syslog=" do
32
+
33
+ context "when true" do
34
+
35
+ it "should change ReverseTunnel.logger to Syslog::Logger" do
36
+ subject.syslog = true
37
+ ReverseTunnel.logger.should be_instance_of(Syslog::Logger)
38
+ end
39
+
40
+ after do
41
+ ReverseTunnel.reset_logger!
42
+ end
43
+
44
+ end
45
+
46
+ end
47
+
48
+
49
+
50
+
51
+
52
+ end
53
+
54
+
55
+ describe ReverseTunnel::CLI::Configurator do
56
+
57
+ describe "#server=" do
58
+
59
+ it "should parse ip and port" do
60
+ subject.should_receive(:server_host=).with("host")
61
+ subject.should_receive(:server_port=).with(4893)
62
+
63
+ subject.server = "host:4893"
64
+ end
65
+
66
+ end
67
+
68
+ end
69
+
70
+ describe ReverseTunnel::CLI::Client do
71
+
72
+ describe "#api=" do
73
+
74
+ it "should parse ip and port" do
75
+ subject.should_receive(:api_host=).with("host")
76
+ subject.should_receive(:api_port=).with(4895)
77
+
78
+ subject.api = "host:4895"
79
+ end
80
+
81
+ end
82
+
83
+ describe "#token" do
84
+
85
+ it "should use first argument" do
86
+ subject.stub :arguments => [ "token"]
87
+ subject.token.should == "token"
88
+ end
89
+
90
+ end
91
+
92
+ end
93
+
94
+ describe ReverseTunnel::CLI::Server do
95
+
96
+ describe "#api=" do
97
+
98
+ it "should parse ip and port" do
99
+ subject.should_receive(:api_host=).with("host")
100
+ subject.should_receive(:api_port=).with(4894)
101
+
102
+ subject.api = "host:4894"
103
+ end
104
+
105
+ end
106
+
107
+ describe "#local=" do
108
+
109
+ it "should parse ip and port range" do
110
+ subject.should_receive(:local_host=).with("host")
111
+ subject.should_receive(:local_port_range=).with(123..456)
112
+
113
+ subject.local = "host:123-456"
114
+ end
115
+
116
+ end
117
+
118
+ end
@@ -0,0 +1,72 @@
1
+ require 'spec_helper'
2
+
3
+ require "rest_client"
4
+ require "json"
5
+
6
+ describe ReverseTunnel::Client::ApiServer do
7
+
8
+ let(:tunnel) { mock :to_json => '{"token":"1008B1A077343ED8B7AAAC9BC580","local_port":22,"server_host":"localhost","server_port":4893,"local_connections":[],"connection":{"created_at":"2012-12-27 12:13:50 +0100"}}' }
9
+
10
+ let(:api_host) { "127.0.0.1" }
11
+ let(:api_port) { 38589 }
12
+
13
+ def url(path)
14
+ "http://#{api_host}:#{api_port}#{path}"
15
+ end
16
+
17
+ def get(path)
18
+ JSON.parse RestClient.get url(path)
19
+ end
20
+
21
+ def wait_api
22
+ 5.times do
23
+ begin
24
+ s = TCPSocket.new(api_host, api_port)
25
+ s.close
26
+ return true
27
+ rescue Errno::ECONNREFUSED
28
+ sleep 0.1
29
+ end
30
+ end
31
+ end
32
+
33
+ def wait_api_stopped
34
+ 5.times do
35
+ begin
36
+ s = TCPSocket.new(api_host, api_port)
37
+ s.close
38
+ sleep 0.1
39
+ rescue Errno::ECONNREFUSED
40
+ return true
41
+ end
42
+ end
43
+ end
44
+
45
+ before do
46
+ Thread.new do
47
+ EventMachine.run do
48
+ EventMachine.start_server api_host, api_port, ReverseTunnel::Client::ApiServer, tunnel
49
+ end
50
+ end
51
+
52
+ wait_api
53
+ end
54
+
55
+ describe "GET '/status'" do
56
+
57
+ it "should return tunnel description" do
58
+ get("/status").should == JSON.parse(tunnel.to_json)
59
+ end
60
+
61
+ it "should accept requests on /tunnels.json" do
62
+ get("/status.json").should == get("/status")
63
+ end
64
+
65
+ end
66
+
67
+ after do
68
+ EventMachine.stop
69
+ wait_api_stopped
70
+ end
71
+
72
+ end
@@ -0,0 +1,79 @@
1
+ require 'spec_helper'
2
+
3
+ describe ReverseTunnel::Client do
4
+
5
+ describe "#server_host" do
6
+
7
+ it "should be nil by default" do
8
+ subject.server_host.should be_nil
9
+ end
10
+
11
+ end
12
+
13
+ describe "#server_port" do
14
+
15
+ it "should be 4893 by default" do
16
+ subject.server_port.should == 4893
17
+ end
18
+
19
+ end
20
+
21
+ describe "#local_port" do
22
+
23
+ it "should be 22 by default" do
24
+ subject.local_port.should == 22
25
+ end
26
+
27
+ end
28
+
29
+ describe "#api_host" do
30
+
31
+ it "should be nil by default" do
32
+ subject.api_host.should be_nil
33
+ end
34
+
35
+ end
36
+
37
+ describe "#api_port" do
38
+
39
+ it "should be 4895 by default" do
40
+ subject.api_port.should == 4895
41
+ end
42
+
43
+ end
44
+
45
+ describe "#tunnel" do
46
+ it "should use server_host" do
47
+ subject.server_host = "localhost"
48
+ subject.tunnel.host.should == "localhost"
49
+ end
50
+
51
+ it "should use server_port" do
52
+ subject.server_port = 123
53
+ subject.tunnel.port.should == 123
54
+ end
55
+
56
+ it "should use local_port" do
57
+ subject.local_port = 123
58
+ subject.tunnel.local_port.should == 123
59
+ end
60
+ end
61
+
62
+ describe "#start_api" do
63
+ it "should use api_host and api_port" do
64
+ subject.api_host = "localhost"
65
+ subject.api_port = 123
66
+
67
+ EventMachine.should_receive(:start_server).with("localhost", 123, anything, anything)
68
+ subject.start_api
69
+ end
70
+
71
+ it "should not start api if api_host is not defined" do
72
+ subject.api_host = nil
73
+
74
+ EventMachine.should_not_receive(:start_server)
75
+ subject.start_api
76
+ end
77
+ end
78
+
79
+ end
@@ -0,0 +1,55 @@
1
+ require 'spec_helper'
2
+
3
+ describe Message do
4
+
5
+ end
6
+
7
+ describe Message::Data do
8
+ subject { Message::Data.new(123, "dummy") }
9
+
10
+ its(:type) { should == :data }
11
+
12
+ it { should be_data }
13
+
14
+ it "should have the same session_id after pack/unpack" do
15
+ Message.unpack(subject.pack).session_id.should == subject.session_id
16
+ end
17
+
18
+ it "should have the same data after pack/unpack" do
19
+ Message.unpack(subject.pack).data.should == subject.data
20
+ end
21
+ end
22
+
23
+ describe Message::OpenSession do
24
+ its(:type) { should == :open_session }
25
+
26
+ it { should be_open_session }
27
+
28
+ it "should have the same session_id after pack/unpack" do
29
+ subject.session_id = 123
30
+ Message.unpack(subject.pack).session_id.should == subject.session_id
31
+ end
32
+ end
33
+
34
+ describe Message::OpenTunnel do
35
+ its(:type) { should == :open_tunnel }
36
+
37
+ it { should be_open_tunnel }
38
+
39
+ it "should have the same token after pack/unpack" do
40
+ subject.token = 123
41
+ Message.unpack(subject.pack).token.should == subject.token
42
+ end
43
+ end
44
+
45
+ describe Message::Ping do
46
+ its(:type) { should == :ping }
47
+
48
+ it { should be_ping }
49
+
50
+ it "should have the same sequence_number after pack/unpack" do
51
+ subject.sequence_number = 123
52
+ Message.unpack(subject.pack).sequence_number.should == subject.sequence_number
53
+ end
54
+ end
55
+
@@ -0,0 +1,125 @@
1
+ require 'spec_helper'
2
+
3
+ require "rest_client"
4
+ require "json"
5
+
6
+ describe ReverseTunnel::Server::ApiServer do
7
+
8
+ let(:server) { ReverseTunnel::Server.new }
9
+
10
+ let(:api_host) { "127.0.0.1" }
11
+ let(:api_port) { 38589 }
12
+
13
+ def url(path)
14
+ "http://#{api_host}:#{api_port}#{path}"
15
+ end
16
+
17
+ def get(path)
18
+ JSON.parse RestClient.get url(path)
19
+ end
20
+
21
+ def post(path, params)
22
+ JSON.parse RestClient.post url(path), params.to_json
23
+ end
24
+
25
+ def delete(path)
26
+ JSON.parse RestClient.delete url(path)
27
+ end
28
+
29
+ def wait_api
30
+ 5.times do
31
+ begin
32
+ s = TCPSocket.new(api_host, api_port)
33
+ s.close
34
+ return true
35
+ rescue Errno::ECONNREFUSED
36
+ sleep 0.1
37
+ end
38
+ end
39
+ end
40
+
41
+ def wait_api_stopped
42
+ 5.times do
43
+ begin
44
+ s = TCPSocket.new(api_host, api_port)
45
+ s.close
46
+ sleep 0.1
47
+ rescue Errno::ECONNREFUSED
48
+ return true
49
+ end
50
+ end
51
+ end
52
+
53
+ before do
54
+ Thread.new do
55
+ EventMachine.run do
56
+ EventMachine.start_server api_host, api_port, ReverseTunnel::Server::ApiServer, server
57
+ end
58
+ end
59
+
60
+ wait_api
61
+ end
62
+
63
+ describe "GET '/tunnels'" do
64
+
65
+ it "should return an empty array without tunnels" do
66
+ get("/tunnels").should be_empty
67
+ end
68
+
69
+ it "should return tunnels description" do
70
+ tunnel = server.tunnels.create
71
+ get("/tunnels").should include("token" => tunnel.token, "local_port" => tunnel.local_port)
72
+ end
73
+
74
+ it "should accept requests on /tunnels.json" do
75
+ get("/tunnels.json").should == get("/tunnels")
76
+ end
77
+
78
+ end
79
+
80
+ describe "POST '/tunnels'" do
81
+
82
+ it "should create a new tunnel" do
83
+ post("/tunnels", :token => "dummy")
84
+ server.tunnels.find("dummy").should_not be_nil
85
+ end
86
+
87
+ it "should return new tunnel description" do
88
+ post("/tunnels", :token => "dummy")["token"].should == "dummy"
89
+ end
90
+
91
+ end
92
+
93
+ describe "GET '/tunnels/:id'" do
94
+
95
+ it "should return tunnel description" do
96
+ tunnel = server.tunnels.create
97
+ get("/tunnels/#{tunnel.token}")["local_port"].should == tunnel.local_port
98
+ end
99
+
100
+ it "should return a 404 when tunnel doesn't exist" do
101
+ lambda { get("/tunnels/123") }.should raise_error(RestClient::ResourceNotFound)
102
+ end
103
+
104
+ end
105
+
106
+ describe "DELETE '/tunnels/:id'" do
107
+
108
+ it "should delete the specified tunnel" do
109
+ tunnel = server.tunnels.create
110
+ delete("/tunnels/#{tunnel.token}")
111
+ server.tunnels.find(tunnel.token).should be_nil
112
+ end
113
+
114
+ it "should return a 404 when tunnel doesn't exist" do
115
+ lambda { delete("/tunnels/123") }.should raise_error(RestClient::ResourceNotFound)
116
+ end
117
+
118
+ end
119
+
120
+ after do
121
+ EventMachine.stop
122
+ wait_api_stopped
123
+ end
124
+
125
+ end