tlspretense 0.6.1
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.
- data/.document +6 -0
- data/.gitignore +7 -0
- data/.rspec +1 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +41 -0
- data/LICENSE.txt +20 -0
- data/README.rdoc +231 -0
- data/Rakefile +44 -0
- data/bin/makeder.sh +6 -0
- data/bin/tlspretense +7 -0
- data/bin/view.sh +3 -0
- data/doc/general_setup.rdoc +288 -0
- data/doc/linux_setup.rdoc +64 -0
- data/lib/certmaker.rb +61 -0
- data/lib/certmaker/certificate_factory.rb +106 -0
- data/lib/certmaker/certificate_suite_generator.rb +120 -0
- data/lib/certmaker/ext_core/hash_indifferent_fetch.rb +12 -0
- data/lib/certmaker/runner.rb +27 -0
- data/lib/certmaker/tasks.rb +20 -0
- data/lib/packetthief.rb +167 -0
- data/lib/packetthief/handlers.rb +14 -0
- data/lib/packetthief/handlers/abstract_ssl_handler.rb +249 -0
- data/lib/packetthief/handlers/proxy_redirector.rb +26 -0
- data/lib/packetthief/handlers/ssl_client.rb +87 -0
- data/lib/packetthief/handlers/ssl_server.rb +174 -0
- data/lib/packetthief/handlers/ssl_smart_proxy.rb +143 -0
- data/lib/packetthief/handlers/ssl_transparent_proxy.rb +225 -0
- data/lib/packetthief/handlers/transparent_proxy.rb +183 -0
- data/lib/packetthief/impl.rb +11 -0
- data/lib/packetthief/impl/ipfw.rb +140 -0
- data/lib/packetthief/impl/manual.rb +54 -0
- data/lib/packetthief/impl/netfilter.rb +109 -0
- data/lib/packetthief/impl/pf_divert.rb +168 -0
- data/lib/packetthief/impl/pf_rdr.rb +192 -0
- data/lib/packetthief/logging.rb +49 -0
- data/lib/packetthief/redirect_rule.rb +29 -0
- data/lib/packetthief/util.rb +36 -0
- data/lib/ssl_test.rb +21 -0
- data/lib/ssl_test/app_context.rb +17 -0
- data/lib/ssl_test/certificate_manager.rb +33 -0
- data/lib/ssl_test/config.rb +79 -0
- data/lib/ssl_test/ext_core/io_raw_input.rb +31 -0
- data/lib/ssl_test/input_handler.rb +35 -0
- data/lib/ssl_test/runner.rb +110 -0
- data/lib/ssl_test/runner_options.rb +68 -0
- data/lib/ssl_test/ssl_test_case.rb +46 -0
- data/lib/ssl_test/ssl_test_report.rb +24 -0
- data/lib/ssl_test/ssl_test_result.rb +30 -0
- data/lib/ssl_test/test_listener.rb +140 -0
- data/lib/ssl_test/test_manager.rb +116 -0
- data/lib/tlspretense.rb +13 -0
- data/lib/tlspretense/app.rb +52 -0
- data/lib/tlspretense/init_runner.rb +115 -0
- data/lib/tlspretense/skel/ca/goodcacert.pem +19 -0
- data/lib/tlspretense/skel/ca/goodcakey.pem +27 -0
- data/lib/tlspretense/skel/config.yml +523 -0
- data/lib/tlspretense/version.rb +3 -0
- data/packetthief_examples/em_ssl_test.rb +73 -0
- data/packetthief_examples/redirector.rb +29 -0
- data/packetthief_examples/setup_iptables.sh +24 -0
- data/packetthief_examples/ssl_client_simple.rb +27 -0
- data/packetthief_examples/ssl_server_simple.rb +44 -0
- data/packetthief_examples/ssl_smart_proxy.rb +115 -0
- data/packetthief_examples/ssl_transparent_proxy.rb +97 -0
- data/packetthief_examples/transparent_proxy.rb +56 -0
- data/spec/packetthief/impl/ipfw_spec.rb +98 -0
- data/spec/packetthief/impl/manual_spec.rb +65 -0
- data/spec/packetthief/impl/netfilter_spec.rb +66 -0
- data/spec/packetthief/impl/pf_divert_spec.rb +82 -0
- data/spec/packetthief/impl/pf_rdr_spec.rb +133 -0
- data/spec/packetthief/logging_spec.rb +78 -0
- data/spec/packetthief_spec.rb +47 -0
- data/spec/spec_helper.rb +53 -0
- data/spec/ssl_test/certificate_manager_spec.rb +222 -0
- data/spec/ssl_test/config_spec.rb +76 -0
- data/spec/ssl_test/runner_spec.rb +360 -0
- data/spec/ssl_test/ssl_test_case_spec.rb +113 -0
- data/spec/ssl_test/test_listener_spec.rb +199 -0
- data/spec/ssl_test/test_manager_spec.rb +324 -0
- data/tlspretense.gemspec +35 -0
- metadata +262 -0
@@ -0,0 +1,98 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__),'..','..','spec_helper'))
|
2
|
+
|
3
|
+
module PacketThief
|
4
|
+
module Impl
|
5
|
+
describe Ipfw do
|
6
|
+
before(:each) do
|
7
|
+
Ipfw.stub(:system).and_return(:true)
|
8
|
+
end
|
9
|
+
|
10
|
+
describe ".redirect" do
|
11
|
+
context "when it is told to redirect TCP port 443 traffic to localhost port 654321" do
|
12
|
+
it "calls ipfw with a rule that performs the diversion" do
|
13
|
+
|
14
|
+
Ipfw.should_receive(:system).with(*%W{/sbin/ipfw add set 30 fwd 127.0.0.1,65432 tcp from any to any dst-port 443}).and_return true
|
15
|
+
|
16
|
+
Ipfw.redirect(:to_ports => 65432).where(:protocol => :tcp, :dest_port => 443).run
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
context "when it is run on a Mac OS X system" do
|
21
|
+
it "calls sysctl to set net.inet.ip.scopedroute to 0" do
|
22
|
+
with_constants :RUBY_PLATFORM => "x86_darwin10" do
|
23
|
+
|
24
|
+
Ipfw.should_receive(:system).with(*%W{/usr/sbin/sysctl -w net.inet.ip.scopedroute=0}).ordered.and_return(true)
|
25
|
+
Ipfw.should_receive(:system).ordered.and_return(true)
|
26
|
+
|
27
|
+
Ipfw.redirect(:to_ports => 65432).where(:protocol => :tcp, :dest_port => 443).run
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context "when the system is Lion and setting net.inet.ip.scopedroute fails" do
|
32
|
+
before(:each) do
|
33
|
+
Ipfw.should_receive(:system).with(*%W{/usr/sbin/sysctl -w net.inet.ip.scopedroute=0}).and_return(false)
|
34
|
+
end
|
35
|
+
it "does not raise an exception" do
|
36
|
+
with_constants :RUBY_PLATFORM => "x86_64-darwin11" do
|
37
|
+
expect do
|
38
|
+
Ipfw.redirect(:to_ports => 65432).where(:protocol => :tcp, :dest_port => 443).run
|
39
|
+
end.to_not raise_error
|
40
|
+
end
|
41
|
+
end
|
42
|
+
it "logs the error" do
|
43
|
+
with_constants :RUBY_PLATFORM => "x86_64-darwin11" do
|
44
|
+
Ipfw.should_receive(:logerror)
|
45
|
+
|
46
|
+
Ipfw.redirect(:to_ports => 65432).where(:protocol => :tcp, :dest_port => 443).run
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
context "when it is told to watch a particular interface" do
|
53
|
+
it "calls ipfw with a rule that performs the diversion" do
|
54
|
+
Ipfw.should_receive(:system).with(*%W{/sbin/ipfw add set 30 fwd 127.0.0.1,65432 tcp from any to any dst-port 443 recv eth1}).and_return true
|
55
|
+
|
56
|
+
Ipfw.redirect(:to_ports => 65432).where(:protocol => :tcp, :dest_port => 443, :in_interface => 'eth1').run
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
|
63
|
+
describe ".revert" do
|
64
|
+
context "when a rule has been previously added" do
|
65
|
+
before(:each) do
|
66
|
+
Ipfw.redirect(:to_ports => 3234).where(:protocol => :tcp, :dest_port => 80).run
|
67
|
+
end
|
68
|
+
it "removes the rule" do
|
69
|
+
Ipfw.should_receive(:system).with(*%W{/sbin/ipfw del set 30}).and_return true
|
70
|
+
|
71
|
+
Ipfw.revert
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
describe ".original_dest" do
|
77
|
+
context "when passed an object that implements Socket's #getsockname" do
|
78
|
+
it "returns the destination socket's details" do
|
79
|
+
@socket = double("socket")
|
80
|
+
@socket.stub(:getsockname).and_return("\020\002?2\ne`a\000\000\000\000\000\000\000\000")
|
81
|
+
|
82
|
+
Ipfw.original_dest(@socket).should == [16178, "10.101.96.97"]
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
context "when passed an object that implements EM::Connection's #getsockname" do
|
87
|
+
it "returns the destination connection's details" do
|
88
|
+
@socket = double("EM::Connection")
|
89
|
+
@socket.stub(:get_sockname).and_return("\020\002?2\ne`a\000\000\000\000\000\000\000\000")
|
90
|
+
|
91
|
+
Ipfw.original_dest(@socket).should == [16178, "10.101.96.97"]
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__),'..','..','spec_helper'))
|
2
|
+
|
3
|
+
module PacketThief
|
4
|
+
module Impl
|
5
|
+
describe Manual do
|
6
|
+
before(:each) do
|
7
|
+
subject.stub(:system).and_return(:true)
|
8
|
+
end
|
9
|
+
|
10
|
+
subject {Manual}
|
11
|
+
|
12
|
+
describe ".redirect" do
|
13
|
+
context "when it is told to redirect TCP port 443 traffic to localhost port 654321" do
|
14
|
+
it "does not call a external command" do
|
15
|
+
subject.should_not_receive(:system)
|
16
|
+
|
17
|
+
subject.redirect(:to_ports => 65432).where(:protocol => :tcp, :dest_port => 443).run
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
context "when it is told to watch a particular interface" do
|
22
|
+
it "does not call a external command" do
|
23
|
+
subject.should_not_receive(:system)
|
24
|
+
|
25
|
+
subject.redirect(:to_ports => 65432).where(:protocol => :tcp, :dest_port => 443).run
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe ".revert" do
|
31
|
+
context "when a rule has been previously added" do
|
32
|
+
before(:each) do
|
33
|
+
subject.redirect(:to_ports => 3234).where(:protocol => :tcp, :dest_port => 80).run
|
34
|
+
end
|
35
|
+
it "does not call a external command" do
|
36
|
+
subject.should_not_receive(:system)
|
37
|
+
|
38
|
+
subject.revert
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe ".original_dest" do
|
44
|
+
after(:each) do
|
45
|
+
subject.set_dest(nil, nil)
|
46
|
+
end
|
47
|
+
|
48
|
+
context "when .set_dest(host, port) has not been set" do
|
49
|
+
it "raises an error" do
|
50
|
+
expect { subject.original_dest(double('socket')) }.to raise_error
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
context "when .set_dest(host, port) has been set" do
|
55
|
+
before(:each) { subject.set_dest('somehost', 1234) }
|
56
|
+
|
57
|
+
it "returns the specified port and host" do
|
58
|
+
subject.original_dest(double('socket')).should == [1234, 'somehost']
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__),'..','..','spec_helper'))
|
2
|
+
|
3
|
+
module PacketThief
|
4
|
+
module Impl
|
5
|
+
describe Netfilter do
|
6
|
+
describe ".redirect" do
|
7
|
+
it { Netfilter.redirect.table.should == 'nat' }
|
8
|
+
it { Netfilter.redirect.chain.should == 'PREROUTING' }
|
9
|
+
|
10
|
+
context "when it is told to redirect TCP port 443 traffic to localhost port 654321" do
|
11
|
+
it "calls iptables with a rule that performs the diversion" do
|
12
|
+
Netfilter.should_receive(:system).with(*%W{/sbin/iptables -t nat -A PREROUTING -p tcp --destination-port 443 -j REDIRECT --to-ports 65432}).and_return true
|
13
|
+
|
14
|
+
Netfilter.redirect(:to_ports => 65432).where(:protocol => :tcp, :dest_port => 443).run
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
context "when it is told to watch a particular interface" do
|
19
|
+
it "calls iptables with a rule that performs the diversion" do
|
20
|
+
Netfilter.should_receive(:system).with(*%W{/sbin/iptables -t nat -A PREROUTING -p tcp --destination-port 443 --in-interface eth1 -j REDIRECT --to-ports 65432}).and_return true
|
21
|
+
|
22
|
+
Netfilter.redirect(:to_ports => 65432).where(:protocol => :tcp, :dest_port => 443, :in_interface => 'eth1').run
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
describe ".revert" do
|
30
|
+
context "when a rule has been previously added" do
|
31
|
+
before(:each) do
|
32
|
+
Netfilter.stub(:system).and_return(:true)
|
33
|
+
Netfilter.redirect(:to_ports => 3234).where(:protocol => :tcp, :dest_port => 80).run
|
34
|
+
end
|
35
|
+
it "removes the rule" do
|
36
|
+
Netfilter.should_receive(:system).with(*%W{/sbin/iptables -t nat -D PREROUTING -p tcp --destination-port 80 -j REDIRECT --to-ports 3234}).and_return true
|
37
|
+
|
38
|
+
Netfilter.revert
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe ".original_dest" do
|
44
|
+
context "when passed an object that implements Socket's #getsockopt" do
|
45
|
+
it "returns the destination socket's details" do
|
46
|
+
@socket = double("socket")
|
47
|
+
@socket.should_receive(:getsockopt).with(Socket::IPPROTO_IP, Netfilter::SO_ORIGINAL_DST).and_return("\020\002?2\ne`a\000\000\000\000\000\000\000\000")
|
48
|
+
|
49
|
+
Netfilter.original_dest(@socket).should == [16178, "10.101.96.97"]
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
context "when passed an object that implements EM::Connection's #get_sock_opt" do
|
54
|
+
it "returns the destination connection's details" do
|
55
|
+
@socket = double("EM::Connection")
|
56
|
+
@socket.should_receive(:get_sock_opt).with(Socket::IPPROTO_IP, Netfilter::SO_ORIGINAL_DST).and_return("\020\002?2\ne`a\000\000\000\000\000\000\000\000")
|
57
|
+
|
58
|
+
Netfilter.original_dest(@socket).should == [16178, "10.101.96.97"]
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__),'..','..','spec_helper'))
|
2
|
+
|
3
|
+
module PacketThief
|
4
|
+
module Impl
|
5
|
+
describe PFDivert do
|
6
|
+
subject { PFDivert }
|
7
|
+
|
8
|
+
before(:each) do
|
9
|
+
subject.stub(:system).and_return(:true)
|
10
|
+
end
|
11
|
+
|
12
|
+
# Either write our current ruleset to a file, or echo it into pfctl.
|
13
|
+
describe ".redirect" do
|
14
|
+
after(:each) do
|
15
|
+
subject.revert
|
16
|
+
end
|
17
|
+
context "when it is told to redirect TCP port 443 traffic to localhost port 65432" do
|
18
|
+
it "calls pfctl with a rule that performs the diversion" do
|
19
|
+
|
20
|
+
subject.should_receive(:system).with(*['echo', 'pass in proto tcp from any to any port 443 divert-to 127.0.0.1 port 65432']+%W{| pfctl -a packetthief -f -}).and_return true
|
21
|
+
|
22
|
+
subject.redirect(:to_ports => 65432).where(:protocol => :tcp, :dest_port => 443).run
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
context "when it is told to watch a particular interface" do
|
27
|
+
it "calls pf with a rule that performs the diversion" do
|
28
|
+
subject.should_receive(:system).with(*['echo', 'pass in on eth1 proto tcp from any to any port 443 divert-to 127.0.0.1 port 65432']+%W{| pfctl -a packetthief -f -}).and_return true
|
29
|
+
|
30
|
+
subject.redirect(:to_ports => 65432).where(:protocol => :tcp, :dest_port => 443, :in_interface => 'eth1').run
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
context "when it is called with two rules" do
|
35
|
+
it "sends both rules to pfctl on the second invocation" do
|
36
|
+
subject.should_receive(:system).with(*['echo', 'pass in proto tcp from any to any port 80 divert-to 127.0.0.1 port 65432']+%W{| pfctl -a packetthief -f -}).ordered.and_return true
|
37
|
+
subject.should_receive(:system).with(*['echo', "pass in proto tcp from any to any port 80 divert-to 127.0.0.1 port 65432\npass in proto tcp from any to any port 443 divert-to 127.0.0.1 port 65433"]+%W{| pfctl -a packetthief -f -}).ordered.and_return true
|
38
|
+
|
39
|
+
subject.redirect(:to_ports => 65432).where(:protocol => :tcp, :dest_port => 80).run
|
40
|
+
subject.redirect(:to_ports => 65433).where(:protocol => :tcp, :dest_port => 443).run
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
describe ".revert" do
|
48
|
+
context "when a rule has been previously added" do
|
49
|
+
before(:each) do
|
50
|
+
subject.redirect(:to_ports => 3234).where(:protocol => :tcp, :dest_port => 80).run
|
51
|
+
end
|
52
|
+
it "removes the packetthief anchor" do
|
53
|
+
subject.should_receive(:system).with(*%W{pfctl -a packetthief -F rules}).and_return true
|
54
|
+
|
55
|
+
subject.revert
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
describe ".original_dest" do
|
61
|
+
context "when passed an object that implements Socket's #getsockname" do
|
62
|
+
it "returns the destination socket's details" do
|
63
|
+
@socket = double("socket")
|
64
|
+
@socket.stub(:getsockname).and_return("\020\002?2\ne`a\000\000\000\000\000\000\000\000")
|
65
|
+
|
66
|
+
subject.original_dest(@socket).should == [16178, "10.101.96.97"]
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
context "when passed an object that implements EM::Connection's #getsockname" do
|
71
|
+
it "returns the destination connection's details" do
|
72
|
+
@socket = double("EM::Connection")
|
73
|
+
@socket.stub(:get_sockname).and_return("\020\002?2\ne`a\000\000\000\000\000\000\000\000")
|
74
|
+
|
75
|
+
subject.original_dest(@socket).should == [16178, "10.101.96.97"]
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,133 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__),'..','..','spec_helper'))
|
2
|
+
|
3
|
+
module PacketThief
|
4
|
+
module Impl
|
5
|
+
describe PFRdr do
|
6
|
+
subject { PFRdr }
|
7
|
+
|
8
|
+
before(:each) do
|
9
|
+
subject.stub(:system).and_return(:true)
|
10
|
+
IO.stub(:popen)
|
11
|
+
end
|
12
|
+
|
13
|
+
# Either write our current ruleset to a file, or echo it into pfctl.
|
14
|
+
describe ".redirect" do
|
15
|
+
after(:each) do
|
16
|
+
subject.revert
|
17
|
+
end
|
18
|
+
context "when it is told to redirect TCP port 443 traffic to localhost port 65432" do
|
19
|
+
it "calls pfctl with a rule that performs the diversion" do
|
20
|
+
@pfctlio = double('pfctl io')
|
21
|
+
IO.should_receive(:popen) do |args, &block|
|
22
|
+
args.should == %W{pfctl -q -a packetthief -f -}
|
23
|
+
block.call(@pfctlio)
|
24
|
+
`true`
|
25
|
+
$?.exitstatus.should == 0
|
26
|
+
end
|
27
|
+
@pfctlio.should_receive(:puts).with("rdr proto tcp from any to any port 443 -> 127.0.0.1 port 65432")
|
28
|
+
|
29
|
+
subject.redirect(:to_ports => 65432).where(:protocol => :tcp, :dest_port => 443).run
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
context "when it is told to watch a particular interface" do
|
34
|
+
it "calls pf with a rule that performs the diversion" do
|
35
|
+
@pfctlio = double('pfctl io')
|
36
|
+
IO.should_receive(:popen) do |args, &block|
|
37
|
+
args.should == %W{pfctl -q -a packetthief -f -}
|
38
|
+
block.call(@pfctlio)
|
39
|
+
`true`
|
40
|
+
$?.exitstatus.should == 0
|
41
|
+
end
|
42
|
+
@pfctlio.should_receive(:puts).with("rdr on eth1 proto tcp from any to any port 443 -> 127.0.0.1 port 65432")
|
43
|
+
|
44
|
+
subject.redirect(:to_ports => 65432).where(:protocol => :tcp, :dest_port => 443, :in_interface => 'eth1').run
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
context "when it is called with two rules" do
|
49
|
+
it "sends both rules to pfctl on the second invocation" do
|
50
|
+
@pfctlio = double('pfctl io')
|
51
|
+
@pfctlio2 = double('pfctl io')
|
52
|
+
IO.should_receive(:popen).ordered do |args, &block|
|
53
|
+
args.should == %W{pfctl -q -a packetthief -f -}
|
54
|
+
block.call(@pfctlio)
|
55
|
+
`true`
|
56
|
+
$?.exitstatus.should == 0
|
57
|
+
end
|
58
|
+
@pfctlio.should_receive(:puts).with("rdr proto tcp from any to any port 80 -> 127.0.0.1 port 65432")
|
59
|
+
IO.should_receive(:popen).ordered do |args, &block|
|
60
|
+
args.should == %W{pfctl -q -a packetthief -f -}
|
61
|
+
block.call(@pfctlio2)
|
62
|
+
`true`
|
63
|
+
$?.exitstatus.should == 0
|
64
|
+
end
|
65
|
+
@pfctlio2.should_receive(:puts).with("rdr proto tcp from any to any port 80 -> 127.0.0.1 port 65432").ordered
|
66
|
+
@pfctlio2.should_receive(:puts).with("rdr proto tcp from any to any port 443 -> 127.0.0.1 port 65433").ordered
|
67
|
+
|
68
|
+
subject.redirect(:to_ports => 65432).where(:protocol => :tcp, :dest_port => 80).run
|
69
|
+
subject.redirect(:to_ports => 65433).where(:protocol => :tcp, :dest_port => 443).run
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
describe ".revert" do
|
76
|
+
context "when a rule has been previously added" do
|
77
|
+
before(:each) do
|
78
|
+
subject.redirect(:to_ports => 3234).where(:protocol => :tcp, :dest_port => 80).run
|
79
|
+
end
|
80
|
+
it "removes the packetthief anchor" do
|
81
|
+
subject.should_receive(:system).with(*%W{pfctl -q -a packetthief -F all}).and_return true
|
82
|
+
|
83
|
+
subject.revert
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
describe ".original_dest" do
|
89
|
+
context "when passed an object that implements Socket's #getsockname and #getpeername" do
|
90
|
+
let(:peername) { double('peername') }
|
91
|
+
let(:sockname) { double('sockname') }
|
92
|
+
let(:socket) { double('socket', :getpeername => peername, :getsockname => sockname) }
|
93
|
+
|
94
|
+
before(:each) do
|
95
|
+
Socket.stub(:unpack_sockaddr_in).with(peername).and_return([52999, '192.168.2.2'])
|
96
|
+
Socket.stub(:unpack_sockaddr_in).with(sockname).and_return([54321, '127.0.0.1'])
|
97
|
+
end
|
98
|
+
|
99
|
+
context "when `pfctl -s state` returns info that includes the current connection" do
|
100
|
+
let(:statetable) do
|
101
|
+
<<-QUOTE.gsub(/^\s*/, '')
|
102
|
+
No ALTQ support in kernel
|
103
|
+
ALTQ related functions disabled
|
104
|
+
ALL tcp 13.37.13.37:80 <- 192.168.2.2:52995 ESTABLISHED:ESTABLISHED
|
105
|
+
ALL tcp 192.168.2.2:52995 -> 10.0.1.2:33596 -> 74.125.224.68:80 ESTABLISHED:ESTABLISHED
|
106
|
+
ALL tcp 127.0.0.1:54321 <- 173.194.79.147:443 <- 192.168.2.2:52998 CLOSED:SYN_SENT
|
107
|
+
ALL tcp 127.0.0.1:54321 <- 173.194.79.147:443 <- 192.168.2.2:52999 CLOSED:SYN_SENT
|
108
|
+
ALL tcp 127.0.0.1:54321 <- 173.194.79.147:443 <- 192.168.2.2:53000 CLOSED:SYN_SENT
|
109
|
+
ALL tcp 127.0.0.1:54321 <- 173.194.79.147:443 <- 192.168.2.2:53001 CLOSED:SYN_SENT
|
110
|
+
ALL udp 192.168.2.1:53 <- 192.168.2.2:53690 SINGLE:MULTIPLE
|
111
|
+
ALL tcp 74.125.224.105:80 <- 192.168.2.2:53002 ESTABLISHED:ESTABLISHED
|
112
|
+
ALL tcp 192.168.2.2:53002 -> 10.0.1.2:38466 -> 74.125.224.105:80 ESTABLISHED:ESTABLISHED
|
113
|
+
ALL udp 224.0.0.251:5353 <- 10.0.1.4:5353 NO_TRAFFIC:SINGLE
|
114
|
+
ALL udp ff02::fb[5353] <- fe80::72de:e2ff:fe41:5ddd[5353] NO_TRAFFIC:SINGLE
|
115
|
+
QUOTE
|
116
|
+
end
|
117
|
+
|
118
|
+
before(:each) do
|
119
|
+
subject.stub(:`).with(/pfctl -q -s state/).and_return(statetable)
|
120
|
+
end
|
121
|
+
|
122
|
+
it "returns the original destination" do
|
123
|
+
subject.original_dest(socket).should == [443, '173.194.79.147']
|
124
|
+
end
|
125
|
+
|
126
|
+
end
|
127
|
+
|
128
|
+
end
|
129
|
+
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|