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.
Files changed (81) hide show
  1. data/.document +6 -0
  2. data/.gitignore +7 -0
  3. data/.rspec +1 -0
  4. data/Gemfile +2 -0
  5. data/Gemfile.lock +41 -0
  6. data/LICENSE.txt +20 -0
  7. data/README.rdoc +231 -0
  8. data/Rakefile +44 -0
  9. data/bin/makeder.sh +6 -0
  10. data/bin/tlspretense +7 -0
  11. data/bin/view.sh +3 -0
  12. data/doc/general_setup.rdoc +288 -0
  13. data/doc/linux_setup.rdoc +64 -0
  14. data/lib/certmaker.rb +61 -0
  15. data/lib/certmaker/certificate_factory.rb +106 -0
  16. data/lib/certmaker/certificate_suite_generator.rb +120 -0
  17. data/lib/certmaker/ext_core/hash_indifferent_fetch.rb +12 -0
  18. data/lib/certmaker/runner.rb +27 -0
  19. data/lib/certmaker/tasks.rb +20 -0
  20. data/lib/packetthief.rb +167 -0
  21. data/lib/packetthief/handlers.rb +14 -0
  22. data/lib/packetthief/handlers/abstract_ssl_handler.rb +249 -0
  23. data/lib/packetthief/handlers/proxy_redirector.rb +26 -0
  24. data/lib/packetthief/handlers/ssl_client.rb +87 -0
  25. data/lib/packetthief/handlers/ssl_server.rb +174 -0
  26. data/lib/packetthief/handlers/ssl_smart_proxy.rb +143 -0
  27. data/lib/packetthief/handlers/ssl_transparent_proxy.rb +225 -0
  28. data/lib/packetthief/handlers/transparent_proxy.rb +183 -0
  29. data/lib/packetthief/impl.rb +11 -0
  30. data/lib/packetthief/impl/ipfw.rb +140 -0
  31. data/lib/packetthief/impl/manual.rb +54 -0
  32. data/lib/packetthief/impl/netfilter.rb +109 -0
  33. data/lib/packetthief/impl/pf_divert.rb +168 -0
  34. data/lib/packetthief/impl/pf_rdr.rb +192 -0
  35. data/lib/packetthief/logging.rb +49 -0
  36. data/lib/packetthief/redirect_rule.rb +29 -0
  37. data/lib/packetthief/util.rb +36 -0
  38. data/lib/ssl_test.rb +21 -0
  39. data/lib/ssl_test/app_context.rb +17 -0
  40. data/lib/ssl_test/certificate_manager.rb +33 -0
  41. data/lib/ssl_test/config.rb +79 -0
  42. data/lib/ssl_test/ext_core/io_raw_input.rb +31 -0
  43. data/lib/ssl_test/input_handler.rb +35 -0
  44. data/lib/ssl_test/runner.rb +110 -0
  45. data/lib/ssl_test/runner_options.rb +68 -0
  46. data/lib/ssl_test/ssl_test_case.rb +46 -0
  47. data/lib/ssl_test/ssl_test_report.rb +24 -0
  48. data/lib/ssl_test/ssl_test_result.rb +30 -0
  49. data/lib/ssl_test/test_listener.rb +140 -0
  50. data/lib/ssl_test/test_manager.rb +116 -0
  51. data/lib/tlspretense.rb +13 -0
  52. data/lib/tlspretense/app.rb +52 -0
  53. data/lib/tlspretense/init_runner.rb +115 -0
  54. data/lib/tlspretense/skel/ca/goodcacert.pem +19 -0
  55. data/lib/tlspretense/skel/ca/goodcakey.pem +27 -0
  56. data/lib/tlspretense/skel/config.yml +523 -0
  57. data/lib/tlspretense/version.rb +3 -0
  58. data/packetthief_examples/em_ssl_test.rb +73 -0
  59. data/packetthief_examples/redirector.rb +29 -0
  60. data/packetthief_examples/setup_iptables.sh +24 -0
  61. data/packetthief_examples/ssl_client_simple.rb +27 -0
  62. data/packetthief_examples/ssl_server_simple.rb +44 -0
  63. data/packetthief_examples/ssl_smart_proxy.rb +115 -0
  64. data/packetthief_examples/ssl_transparent_proxy.rb +97 -0
  65. data/packetthief_examples/transparent_proxy.rb +56 -0
  66. data/spec/packetthief/impl/ipfw_spec.rb +98 -0
  67. data/spec/packetthief/impl/manual_spec.rb +65 -0
  68. data/spec/packetthief/impl/netfilter_spec.rb +66 -0
  69. data/spec/packetthief/impl/pf_divert_spec.rb +82 -0
  70. data/spec/packetthief/impl/pf_rdr_spec.rb +133 -0
  71. data/spec/packetthief/logging_spec.rb +78 -0
  72. data/spec/packetthief_spec.rb +47 -0
  73. data/spec/spec_helper.rb +53 -0
  74. data/spec/ssl_test/certificate_manager_spec.rb +222 -0
  75. data/spec/ssl_test/config_spec.rb +76 -0
  76. data/spec/ssl_test/runner_spec.rb +360 -0
  77. data/spec/ssl_test/ssl_test_case_spec.rb +113 -0
  78. data/spec/ssl_test/test_listener_spec.rb +199 -0
  79. data/spec/ssl_test/test_manager_spec.rb +324 -0
  80. data/tlspretense.gemspec +35 -0
  81. 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