tlspretense 0.6.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
data/.document
ADDED
data/.gitignore
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
tlspretense (0.6.0)
|
5
|
+
eventmachine (>= 1.0.0)
|
6
|
+
ruby-termios (>= 0.9.6)
|
7
|
+
|
8
|
+
GEM
|
9
|
+
remote: http://rubygems.org/
|
10
|
+
specs:
|
11
|
+
diff-lcs (1.1.3)
|
12
|
+
eventmachine (1.0.0)
|
13
|
+
json (1.7.5)
|
14
|
+
multi_json (1.5.0)
|
15
|
+
rake (10.0.3)
|
16
|
+
rdoc (3.12)
|
17
|
+
json (~> 1.4)
|
18
|
+
rspec (2.8.0)
|
19
|
+
rspec-core (~> 2.8.0)
|
20
|
+
rspec-expectations (~> 2.8.0)
|
21
|
+
rspec-mocks (~> 2.8.0)
|
22
|
+
rspec-core (2.8.0)
|
23
|
+
rspec-expectations (2.8.0)
|
24
|
+
diff-lcs (~> 1.1.2)
|
25
|
+
rspec-mocks (2.8.0)
|
26
|
+
ruby-termios (0.9.6)
|
27
|
+
simplecov (0.7.1)
|
28
|
+
multi_json (~> 1.0)
|
29
|
+
simplecov-html (~> 0.7.1)
|
30
|
+
simplecov-html (0.7.1)
|
31
|
+
|
32
|
+
PLATFORMS
|
33
|
+
ruby
|
34
|
+
|
35
|
+
DEPENDENCIES
|
36
|
+
bundler (~> 1.0)
|
37
|
+
rake (>= 0.8.7)
|
38
|
+
rdoc (~> 3.12)
|
39
|
+
rspec (~> 2.8.0)
|
40
|
+
simplecov (~> 0.7)
|
41
|
+
tlspretense!
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2012 iSEC Partners
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,231 @@
|
|
1
|
+
= TLSPretense --- SSL/TLS Client Testing Framework
|
2
|
+
|
3
|
+
A test framework for testing SSL/TLS client certificate validation.
|
4
|
+
|
5
|
+
== Description
|
6
|
+
|
7
|
+
Note: TLSPretense is still undergoing a lot of polishing. It is currently
|
8
|
+
usable, but features may change and documentation may be missing. As such,
|
9
|
+
please bear with us over next few months as we find time to work on the tools,
|
10
|
+
and feel free to file a bug with details.
|
11
|
+
|
12
|
+
TLSPretense provides a test framework for testing SSL certificate validation.
|
13
|
+
It generates a set of certificates containing specific flaws, and it presents
|
14
|
+
the certificates to a client that has been configured to trust a CA used by
|
15
|
+
TLSPretense. The test framework then configures its system's firewall to
|
16
|
+
redirect and intercept network traffic so that the test runner can present its
|
17
|
+
certificate to the client. To speed up testing, the test runner starts the next
|
18
|
+
test as soon as the current test finishes.
|
19
|
+
|
20
|
+
The test framework must be run on a Unix-like OS that contains a supported
|
21
|
+
firewall, but the program being tested can run on any device whose network
|
22
|
+
traffic can be routed through the system hosting the test framework. Currently,
|
23
|
+
it supports netfilter (Linux), ipfw (Mac OS X 10.6, *BSD), and PF on Mac OS X
|
24
|
+
Lion.
|
25
|
+
|
26
|
+
It also has an implementation for a newer version of PF, although this is
|
27
|
+
untested.
|
28
|
+
|
29
|
+
|
30
|
+
== Links
|
31
|
+
|
32
|
+
* {Generated Documentation}[http://isecpartners.github.com/tlspretense/]
|
33
|
+
|
34
|
+
|
35
|
+
== How It Works
|
36
|
+
|
37
|
+
TLSPretense requires the TLS client software to be configured to trust a CA
|
38
|
+
that TLPretense controls. That way "good" certificates created by TLSPretense
|
39
|
+
will be accepted by the client.
|
40
|
+
|
41
|
+
Once the system hosting the test runner has been configured to be a gateway for
|
42
|
+
the network traffic of thest client being tested, it will add a firewall rule
|
43
|
+
to redirect network traffic to a test listener. The test listener checks to see
|
44
|
+
whether the client is trying to connect to a predefined host. If the client is
|
45
|
+
connecting to the desired host, then the test listener presents a test
|
46
|
+
certificate chain to the client. The test runner then determines whether the
|
47
|
+
test passes or fails based on whether the client completes the TLS handshake or
|
48
|
+
not.
|
49
|
+
|
50
|
+
The test harness was designed to anticipate working with a client that may
|
51
|
+
connect to more than one host. The config.yml file specifies a hostname that
|
52
|
+
should be used for the actual test --- all other intercepted SSL connections
|
53
|
+
are essentially ignored (although they currently have their certificate
|
54
|
+
re-signed by the goodca in order to make interception easier).
|
55
|
+
|
56
|
+
== Requirements
|
57
|
+
|
58
|
+
* A Unix-like system that uses a supported firewall/routing implementation.
|
59
|
+
TLSPretense currently supports:
|
60
|
+
* Netfilter on Linux
|
61
|
+
* IPFW on MacOSX 10.6 and earlier, and *BSD
|
62
|
+
* PFRdr on MacOSX 10.7 (and probably also 10.8)
|
63
|
+
|
64
|
+
* Ruby 1.9.x (Developed with 1.9.3). Check your version with:
|
65
|
+
|
66
|
+
ruby --version
|
67
|
+
|
68
|
+
Some systems will install Ruby 1.9.x with a suffix, like `ruby1.9`. Ruby must
|
69
|
+
also be built against a version of OpenSSL that supports the SNI TLS
|
70
|
+
extension. You can check for this if you run the following Ruby script (on
|
71
|
+
some systems, Ruby 1.9.x will be installed as ruby1.9, and commands like gem
|
72
|
+
will also have the 1.9 suffix):
|
73
|
+
|
74
|
+
ruby -ropenssl -e 'puts OpenSSL::SSL::SSLSocket.public_instance_methods.include? :hostname='
|
75
|
+
|
76
|
+
Ruby 1.8.7 will mostly work, but Ruby 1.8's OpenSSL wrapper library does not
|
77
|
+
support the ability for clients to use the SNI TLS extension, which is needed
|
78
|
+
to grab the correct remote certificate for proxying miscellaneous
|
79
|
+
connections. Use Ruby 1.8.x at your own risk.
|
80
|
+
|
81
|
+
* The SSL client/HTTPS user agent has to trust the CA used by TLSPretense.
|
82
|
+
You can either generate a new goodca and install it in the client's trust
|
83
|
+
store, or you can use an existing test CA with TLSPretense to generate the
|
84
|
+
test certificates.
|
85
|
+
|
86
|
+
== Quick Start
|
87
|
+
|
88
|
+
Install with rubygems:
|
89
|
+
|
90
|
+
umask 0022 ; sudo gem install tlspretense
|
91
|
+
|
92
|
+
Create a new project:
|
93
|
+
|
94
|
+
tlspretense init myproject
|
95
|
+
cd myproject
|
96
|
+
|
97
|
+
And edit config.yml to suit your needs. If you want to create a new test CA
|
98
|
+
(not necessary if you want to use the default or your own):
|
99
|
+
|
100
|
+
tlspretense ca
|
101
|
+
|
102
|
+
Generate certificates for the test cases:
|
103
|
+
|
104
|
+
tlspretense certs
|
105
|
+
|
106
|
+
You will also need to setup the host's networking stack and firewall to support
|
107
|
+
TLSPretense. More details can be found in {TLSPretense
|
108
|
+
Setup}[rdoc-ref:general_setup] and in the system-specific guides.
|
109
|
+
|
110
|
+
Finally, run all of the configured test cases:
|
111
|
+
|
112
|
+
sudo tlspretense run
|
113
|
+
|
114
|
+
Or just certain tests (in the order specified):
|
115
|
+
|
116
|
+
sudo tlspretense run unknownca wrongcname
|
117
|
+
|
118
|
+
== Limitations
|
119
|
+
|
120
|
+
* The Server Name Indication (SNI) TLS extension does not have full support in
|
121
|
+
Ruby 1.8.7.
|
122
|
+
|
123
|
+
* Protocols that explicitly call STARTTLS to enable SSL/TLS (eg, SMTP and IMAP)
|
124
|
+
are not yet supported. They would require protocol-specific support. The
|
125
|
+
version of these protocols where they are wrapped in SSL should be testable
|
126
|
+
though.
|
127
|
+
|
128
|
+
* It currently uses the goodca to re-sign certificates from hostnames that do
|
129
|
+
not match the configured test hostname.
|
130
|
+
|
131
|
+
* The existing PFDivert rule implementation does not work on Mac OS X 10.7 (and
|
132
|
+
probably not on 10.8 either). OpenBSD 5.0(?) and FreeBSD 9 can make use of
|
133
|
+
this functionality though.
|
134
|
+
|
135
|
+
== TODO
|
136
|
+
|
137
|
+
* Convert SSLClient's initial connection to use a non-blocking connect.
|
138
|
+
|
139
|
+
* Change the pre-flight in SSLSmartProxy to disable the accepted server socket
|
140
|
+
until the pre-flight finishes. (the SSLClient within SSLTransparentProxy
|
141
|
+
probably also should do this until the client connects)
|
142
|
+
|
143
|
+
* Fix the subjectAltName null byte test. It requires manual construction of the
|
144
|
+
ASN1 encoding due to the null byte causing a truncation somewhere in OpenSSL
|
145
|
+
or Ruby's OpenSSL.
|
146
|
+
|
147
|
+
* Add wildcard tests
|
148
|
+
* cert hostname: \*.%PARENTHOSTNAME%
|
149
|
+
* bad hostname: \*.other.com
|
150
|
+
* tld hostname: \*.%TLDHOSTNAME% (reject)
|
151
|
+
* do we want to test more complicated wildcards?
|
152
|
+
|
153
|
+
* Decide how to deal with a wildcard cert at the original destination. If we
|
154
|
+
are testing foo.somehost.com, and the client connects to other hostnames like
|
155
|
+
bar.somehost.com, and they all use a *.somehost.com certificate, then
|
156
|
+
TLSPretense gets confused.
|
157
|
+
|
158
|
+
* Add extension criticality tests (need an extension oid that nobody knows how to verify)
|
159
|
+
* If an extension is marked critical and the verifier doesn't know how to
|
160
|
+
verify, then it should fail. If it is not marked critical, then it is
|
161
|
+
allowed to skip the extension.
|
162
|
+
|
163
|
+
* Advanced: Add name constraints tests.
|
164
|
+
* success: dnsName of leaf matches exactly the dnsName permitted constraint
|
165
|
+
nameConstraints=permitted;dnsName:%HOSTNAME%
|
166
|
+
* reject: constraint is a different hostname
|
167
|
+
nameConstraints=permitted;dnsName:some.other.com
|
168
|
+
* success: dnsName of leaf is a subdomain in addition to dnsName constraint
|
169
|
+
constraint = parent domain of hostname (need to ensure hostname has enough labels)
|
170
|
+
nameConstraints=permitted;dnsName:%PARENTHOSTNAME%
|
171
|
+
do it this way vs trying a subdomain of the original hostname to
|
172
|
+
* reject: constraint is a slightly different hostname
|
173
|
+
nameConstraints=permitted;dnsName:a%HOSTNAME%
|
174
|
+
* success: dirname matches the default subject's DN
|
175
|
+
* reject: dirname does not match the default subject's DN
|
176
|
+
* URI constraints
|
177
|
+
|
178
|
+
* Document how to run SSLTest from MacOSX
|
179
|
+
|
180
|
+
* Document how to run SSLTest from a Linux VM on Windows (eg, with VMWare)
|
181
|
+
|
182
|
+
* Document how to deal with certificate pinning and other things that may make
|
183
|
+
testing certificate validation logic difficult.
|
184
|
+
|
185
|
+
* Command line option to specify where to write the results to
|
186
|
+
|
187
|
+
* Add more result output formats
|
188
|
+
* (X)HTML
|
189
|
+
* CSV
|
190
|
+
* LaTeX?
|
191
|
+
* XML?
|
192
|
+
* SQLite?
|
193
|
+
|
194
|
+
* truly unique serial numbers for a given CA. Alternatively, we could use the
|
195
|
+
first cert's serial as a starting point and increment from there.
|
196
|
+
|
197
|
+
* Build certs and chains of certs for each test so that something like
|
198
|
+
s\_server could use them.
|
199
|
+
|
200
|
+
* Make initialization interactive. It should prompt the user to choose or
|
201
|
+
confirm configuration details like the interception/firewalling method to
|
202
|
+
use, the network device to listen on, the default hostname, etc. It could
|
203
|
+
then auto-generate the necessary certificates as well.
|
204
|
+
|
205
|
+
* Config file validator
|
206
|
+
|
207
|
+
* Add an API for interacting with an external test controller. This could be a
|
208
|
+
little web service, although that lacks real-time responses. A TCP/unix
|
209
|
+
socket interface that sends/receives JSON messages (or something simpler)
|
210
|
+
might be better. The client would tell TLSPretense which test to start, and
|
211
|
+
then TLSPretense would reply with a result when it completes.
|
212
|
+
|
213
|
+
== Contributing to TLSPretense
|
214
|
+
|
215
|
+
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
|
216
|
+
* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.
|
217
|
+
* Fork the project.
|
218
|
+
* Start a feature/bugfix branch.
|
219
|
+
* Commit and push until you are happy with your contribution.
|
220
|
+
* Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
|
221
|
+
* Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
|
222
|
+
|
223
|
+
== Authors
|
224
|
+
|
225
|
+
* William (B.J.) Snow Orvis (iSEC Partners)
|
226
|
+
|
227
|
+
== Copyright
|
228
|
+
|
229
|
+
Copyright (c) 2012 iSEC Partners
|
230
|
+
|
231
|
+
See LICENSE.txt for further details.
|
data/Rakefile
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
|
2
|
+
require 'bundler/gem_tasks'
|
3
|
+
|
4
|
+
require 'rspec/core/rake_task'
|
5
|
+
RSpec::Core::RakeTask.new(:spec) do |spec|
|
6
|
+
spec.pattern = FileList['spec/**/*_spec.rb']
|
7
|
+
end
|
8
|
+
|
9
|
+
namespace(:spec) do
|
10
|
+
desc "Create rspec code coverage"
|
11
|
+
task :coverage do
|
12
|
+
ENV['COVERAGE'] = 'true'
|
13
|
+
Rake::Task["spec"].execute
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
task :default => :spec
|
18
|
+
|
19
|
+
require 'rdoc/task'
|
20
|
+
Rake::RDocTask.new do |rdoc|
|
21
|
+
require 'tlspretense/version'
|
22
|
+
version = TLSPretense::VERSION
|
23
|
+
|
24
|
+
rdoc.rdoc_dir = 'rdoc'
|
25
|
+
rdoc.main = 'README.rdoc'
|
26
|
+
rdoc.title = "TLSPretense #{version}"
|
27
|
+
rdoc.rdoc_files.include('README*')
|
28
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
29
|
+
rdoc.rdoc_files.include('doc/**/*.rdoc')
|
30
|
+
|
31
|
+
rdoc.before_running_rdoc do
|
32
|
+
unless File.exist? 'rdoc'
|
33
|
+
begin
|
34
|
+
sh 'git clone --branch gh-pages --single-branch `git config remote.origin.url` rdoc'
|
35
|
+
rescue
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
require 'certmaker/tasks'
|
42
|
+
|
43
|
+
desc "Runs certs:clean"
|
44
|
+
task :clean => ['certs:clean']
|
data/bin/makeder.sh
ADDED
data/bin/tlspretense
ADDED
data/bin/view.sh
ADDED
@@ -0,0 +1,288 @@
|
|
1
|
+
= TLSPretense Setup
|
2
|
+
|
3
|
+
The following sections cover a basic configuration to get TLSPretense up and
|
4
|
+
running. It should be straightforward to modify the test setup from there.
|
5
|
+
|
6
|
+
== Test Environment
|
7
|
+
|
8
|
+
TLSPretense was designed to be run as an intercepting proxy in order to be able
|
9
|
+
to test a client that may make multple HTTPS/SSL/TLS requests to multiple
|
10
|
+
remote hosts. This means that TLSPretense is expected to run on a different
|
11
|
+
system from the client software being tested, although it is possible to run
|
12
|
+
TLSPretense within one virtual machine and to have the client software run in
|
13
|
+
another.
|
14
|
+
|
15
|
+
First, a few definitions:
|
16
|
+
|
17
|
+
[client] A piece of software that makes network requests using
|
18
|
+
SSL/TLS.
|
19
|
+
[client host] The computer or virtual machine that will run the client
|
20
|
+
software.
|
21
|
+
[TLSPretense host] A computer or virtual machines running a Unix-like OS that
|
22
|
+
will act as a network gateway for the client host.
|
23
|
+
|
24
|
+
The TLSPretense host needs to have two network interfaces: an external
|
25
|
+
interface for connecting to the outer LAN/Internet and to the remote hosts that
|
26
|
+
the client will connect to, and an internal interface that the client host will
|
27
|
+
use as its gateway.
|
28
|
+
|
29
|
+
One common setup is to use a laptop for the TLSPretense host with an ethernet
|
30
|
+
connection and wifi. The ethernet can be wired into an actual network, and the
|
31
|
+
wifi can be run as a wireless access point that the client host will connect
|
32
|
+
to.
|
33
|
+
|
34
|
+
This setup has the following network topography:
|
35
|
+
|
36
|
+
+------------------------+ LAN +------------------+ WAN
|
37
|
+
| Client Host | . | TLSPretense Host | .
|
38
|
+
| +--------------------+ | . | | .
|
39
|
+
| | Client | | . | +----------+ | .
|
40
|
+
| | ==============>| Firewall | | .
|
41
|
+
| | +----------------+ | | . | +----------+ | .
|
42
|
+
| | | CA TrustStore | | | . | | | . +-------------+
|
43
|
+
| | | | | | . | +------V-------+ | . | Original |
|
44
|
+
| | | TLSPretense CA | | | . | | TLSPretense ==========>| Destination |
|
45
|
+
| | +----------------+ | | . | | Test Harness | | . +-------------+
|
46
|
+
| +--------------------+ | . | +--------------+ | .
|
47
|
+
+------------------------+ . +------------------+ .
|
48
|
+
|
49
|
+
|
50
|
+
== Installing TLSPretense
|
51
|
+
|
52
|
+
Install with rubygems:
|
53
|
+
|
54
|
+
umask 0022 ; sudo gem install tlspretense
|
55
|
+
|
56
|
+
Create a new project:
|
57
|
+
|
58
|
+
tlspretense init myproject
|
59
|
+
cd myproject
|
60
|
+
|
61
|
+
Now edit the config.yml file to suit your needs. TLSPretense installs a default
|
62
|
+
CA when you create your project directory, but you can replace it with your own
|
63
|
+
test CA. You can also create a new CA if you want (using the goodca certificate
|
64
|
+
definition in the project's config.yml):
|
65
|
+
|
66
|
+
tlspretense ca
|
67
|
+
|
68
|
+
Next, create certificates for the test cases (you should rerun this if you
|
69
|
+
modify any of the certificate descriptions in config.yml):
|
70
|
+
|
71
|
+
tlspretense certs
|
72
|
+
|
73
|
+
You will also need to setup the host's networking stack and firewall to support
|
74
|
+
TLSPretense. More details can be found in {TLSPretense
|
75
|
+
Setup}[rdoc-ref:general_setup] and in the system-specific guides.
|
76
|
+
|
77
|
+
Finally, to run all of the configured test cases:
|
78
|
+
|
79
|
+
sudo tlspretense run
|
80
|
+
|
81
|
+
Or just certain tests (in the order specified):
|
82
|
+
|
83
|
+
sudo tlspretense run unknownca wrongcname
|
84
|
+
|
85
|
+
== Updating TLSPretense
|
86
|
+
|
87
|
+
Just install TLSPretense again using rubygems. At present, TLSPretense does not
|
88
|
+
provide any versioning or migration of its configuration file.
|
89
|
+
|
90
|
+
== Configuration
|
91
|
+
|
92
|
+
All configuration of the test suite happens through your project's config.yml.
|
93
|
+
What follows is a brief discussion of each section and what you might want to
|
94
|
+
change.
|
95
|
+
|
96
|
+
=== top-level settings
|
97
|
+
|
98
|
+
[hostname: www.isecpartners.com]
|
99
|
+
This is the most important setting in the configuration file. It specifies
|
100
|
+
the hostname that the client will connect to that you would like to have
|
101
|
+
tested. For connections to this hostname (determined by whether the
|
102
|
+
certificate supplied by the original destination matches the hostname),
|
103
|
+
TLSPretense will present a test certificate chain. For all other hosts, it
|
104
|
+
will take the host certificate used by that host and re-sign it using the
|
105
|
+
"goodca" certificate.
|
106
|
+
|
107
|
+
[listener_port: 54321]
|
108
|
+
The port that the proxy will listen on. You probably don't need to change
|
109
|
+
this.
|
110
|
+
|
111
|
+
=== packetthief
|
112
|
+
|
113
|
+
packetthief:
|
114
|
+
protocol: tcp
|
115
|
+
dest_port: 443
|
116
|
+
in_interface: eth1
|
117
|
+
|
118
|
+
This section describes the firewall rule that will redirect traffic. The most
|
119
|
+
relevant subvalue is +:in_interface+, which should contain the name of the
|
120
|
+
network interface that the client's network traffic will come in on. Also, if
|
121
|
+
you will be testing non-https traffic, change +dest_port+ to the port that the
|
122
|
+
client will connect to.
|
123
|
+
|
124
|
+
One additional optional parameter exists in this this section:
|
125
|
+
|
126
|
+
[implementation]
|
127
|
+
If this optional value is set, then the specified implementation will be
|
128
|
+
used. If implementation is left commented out, then TLSPretense will choose
|
129
|
+
the most appropriate firewall implementation, if possible. Current values:
|
130
|
+
|
131
|
+
* *netfilter* Linux netfilter
|
132
|
+
* *ipfw* MacOSX/BSD ipfw
|
133
|
+
|
134
|
+
=== certmaker
|
135
|
+
|
136
|
+
certmaker:
|
137
|
+
defaultsubject: &defaultsubject "C=US, CN=%HOSTNAME%"
|
138
|
+
defaultsubjectwithnull: &defaultsubjectwithnull "C=US, CN=%HOSTNAME%\0.foo.com"
|
139
|
+
defaultparentsubject: &defaultparentsubject "C=US, CN=%PARENTHOSTNAME%"
|
140
|
+
outdir: certs
|
141
|
+
missing_serial_generation: random
|
142
|
+
customgoodca:
|
143
|
+
certfile: ca/goodcacert.pem
|
144
|
+
keyfile: ca/goodcakey.pem
|
145
|
+
#keypass: changeme
|
146
|
+
|
147
|
+
This section deals with configuring the creation of the certificates used by
|
148
|
+
the tests.
|
149
|
+
|
150
|
+
[+defaultsubject+, +defaultsubjectwithnull+, and +defaultparentsubject+]
|
151
|
+
These keys are just placed here to get them out of the way. They are
|
152
|
+
referenced later in the certificate definitions.
|
153
|
+
[outdir]
|
154
|
+
This specifies where to write the generated certificates to. For now, don't
|
155
|
+
modify this option or it may break something.
|
156
|
+
[missing_serial_generation]
|
157
|
+
This key specifies how to choose a serial number for each generated
|
158
|
+
certificate. Currently, there are only two options. You can set a number,
|
159
|
+
which will be used as the serial number for all generated certificates
|
160
|
+
(this will break any SSL client that checks for serial number uniqueness).
|
161
|
+
The other option is to set it to "random" which will generate a random
|
162
|
+
serial number --- this is the recommended setting, and there is an
|
163
|
+
incredibly small chance that two certificates might have the same serial
|
164
|
+
number.
|
165
|
+
[customgoodca]
|
166
|
+
If this key exists and contains the +certfile+ and +keyfile+ sub-keys, then
|
167
|
+
it specifies a certificate authority to be used as the "goodca" instead of
|
168
|
+
generating a new CA. The third optional value, +keypass+, can specify a
|
169
|
+
password for the private key's file.
|
170
|
+
|
171
|
+
=== logger
|
172
|
+
|
173
|
+
logger:
|
174
|
+
level: INFO
|
175
|
+
file: '-'
|
176
|
+
|
177
|
+
These options set up the logging facility.
|
178
|
+
|
179
|
+
[level]
|
180
|
+
The log severity to report. Log messages that are less severe than this
|
181
|
+
level go unreported.
|
182
|
+
[file]
|
183
|
+
Where to write log entries to. The default of '-' refers to STDOUT.
|
184
|
+
|
185
|
+
=== certs
|
186
|
+
|
187
|
+
This section defines the certificates used by the test cases. It makes heavy
|
188
|
+
use of YAML's references and anchors to mutate a particular certificate. The
|
189
|
+
only special entry is "goodca". If +customgoodca+ is configured in the
|
190
|
+
+certmaker+ section, then that certificate will be used in tests in place of
|
191
|
+
the goodca defined here.
|
192
|
+
|
193
|
+
Make changes to the certificates if you need to customize them for your client.
|
194
|
+
|
195
|
+
=== tests
|
196
|
+
tests:
|
197
|
+
- alias: baseline
|
198
|
+
name: Baseline Happy Test
|
199
|
+
certchain:
|
200
|
+
- baseline
|
201
|
+
- goodca
|
202
|
+
expected_result: connected
|
203
|
+
...
|
204
|
+
|
205
|
+
|
206
|
+
This final section defines a list of all of the tests to run.
|
207
|
+
|
208
|
+
[alias]
|
209
|
+
The "short" identifier for the test.
|
210
|
+
[name]
|
211
|
+
A longer description of the test.
|
212
|
+
[certchain]
|
213
|
+
A list of certificates to present to the client in the order they should be
|
214
|
+
presented. SSL/TLS requires the certificate chain to present the
|
215
|
+
certificate representing the server first, followed by the chain of
|
216
|
+
certificate authorities and intermediate CAs, with the final certificate
|
217
|
+
being a CA.
|
218
|
+
[expected_result]
|
219
|
+
The expected outcome for the test. "connected" means that we expect the
|
220
|
+
client to finish the TLS handshake, while "rejected" means we expect the
|
221
|
+
TLS handshake to fail before finishing.
|
222
|
+
|
223
|
+
|
224
|
+
== Certificate Generation
|
225
|
+
|
226
|
+
You need to pre-generate the certificates you'll use for the tests. You can do
|
227
|
+
this from your project directory with:
|
228
|
+
|
229
|
+
tlspretense certs
|
230
|
+
|
231
|
+
It can generate an entire ecosystem of certificates from scratch, or it can use
|
232
|
+
an existing CA instead of generating a new _goodca_. See the _certmaker_ and
|
233
|
+
_certs_ sections of config.yml.
|
234
|
+
|
235
|
+
WARNING: Running this command a second time will regenerate all of the
|
236
|
+
certificates in the _certs_ directory! However, by default it will just copy
|
237
|
+
the CA from the ca directory each time it is run.
|
238
|
+
|
239
|
+
It you want to create a new CA, run:
|
240
|
+
|
241
|
+
tlspretense ca
|
242
|
+
|
243
|
+
|
244
|
+
== Client Host Setup
|
245
|
+
|
246
|
+
The client host must be configured to use the TLSPretense host as its gateway.
|
247
|
+
This involves configuring the TLSPretense host to act like a NAT router or
|
248
|
+
network bridge, and it requires you to configure the client host. You must also
|
249
|
+
install the "goodca" CA used by TLSPretense onto the client host and configure
|
250
|
+
the client to trust that CA. You do not need to configure any client-side proxy
|
251
|
+
settings (like you would for HTTP-level proxying).
|
252
|
+
|
253
|
+
If you are planning to use Linux for the TLSPretense host and you are familiar
|
254
|
+
with {Mallory}[http://intrepidusgroup.com/insight/mallory/], then Mallory's
|
255
|
+
network configuration tutorials may help you out, although TLSPretense manages
|
256
|
+
the firewall rule that redirects network traffic itself.
|
257
|
+
|
258
|
+
For a sample Linux-specific configuration, see: {Linux
|
259
|
+
Setup}[rdoc-ref:linux_setup].
|
260
|
+
|
261
|
+
|
262
|
+
== Running the tests
|
263
|
+
|
264
|
+
While in your project directory, run all tests with:
|
265
|
+
|
266
|
+
sudo tlspretense run
|
267
|
+
|
268
|
+
The command will more than likely need to be run as root so that it can add and
|
269
|
+
remove its firewall rules.
|
270
|
+
|
271
|
+
If you only want to run certain tests, you can do so by specifying which tests
|
272
|
+
you want to run as command line arguments, and it will run just those tests in
|
273
|
+
the order specified, instead of in the order they are defined in config.yml:
|
274
|
+
|
275
|
+
sudo tlspretense run baseline nullincname selfsigned
|
276
|
+
|
277
|
+
For information about other command line options run TLSPretense without any
|
278
|
+
options, or call the run sub-command with -h or --help:
|
279
|
+
|
280
|
+
tlspretense
|
281
|
+
|
282
|
+
tlspretense run -h
|
283
|
+
|
284
|
+
|
285
|
+
== Output
|
286
|
+
|
287
|
+
At present, TLSPretense prints a summary of the tests run and their results
|
288
|
+
once all tests have run.
|