Skip to content

Initial TLS 1.2 handshake test #103

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 26 commits into from
Jul 31, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
1eea6da
Initial TLS 1.2 handshake test
krizhanovsky Jun 12, 2019
7f14f2e
Use smaller receive timeout for the test suite
krizhanovsky Jun 19, 2019
1734ecf
Make pylint happier
krizhanovsky Jun 20, 2019
c49388f
that the connections are correctly terminated.
krizhanovsky Jun 20, 2019
38708b9
Preliminary deproxy ssl support. The code doesn't work, but
krizhanovsky Jun 27, 2019
351a4e2
Use the new framework for tls_stress test
krizhanovsky Jun 27, 2019
519f4d8
Also introduces TLS mode for Deproxy.
krizhanovsky Jun 29, 2019
fb2d97c
The x509 certificate generator is placed in /framework and
krizhanovsky Jul 3, 2019
621cbd5
Tests for per-vhost certificates and SNI handling:
krizhanovsky Jul 14, 2019
c16b8eb
Test extensions from RFC 6066, invalid extensions and too long extens…
krizhanovsky Jul 15, 2019
43ad7cc
Fixes for tests for #715 by @ikoveshnikov
krizhanovsky Jul 17, 2019
3356b75
Fix bugs in TLS handle_read() and config parsing.
krizhanovsky Jul 18, 2019
840ac46
Add tests for default SNI handling versus tls_fallback_default.
krizhanovsky Jul 18, 2019
58786e1
Replace example.com by tempesta-tech.com
krizhanovsky Jul 18, 2019
14754d2
Basic TLS test for wrong HTTP request
krizhanovsky Jul 20, 2019
2424aab
Test for bad renegotiation info (RFC 5746 3.6)
krizhanovsky Jul 21, 2019
4dd72f6
Fuzzing test and test for alerts
krizhanovsky Jul 22, 2019
0758f01
Chunked TLS transfers. Fix small bug.
krizhanovsky Jul 24, 2019
61430eb
TCP segmentation test for TLS
krizhanovsky Jul 25, 2019
8e9e790
Using Exception considered as a bad practice, pylint also isn't happy
krizhanovsky Jul 25, 2019
2fc93d0
Test case for Connection: close (issue #1326)
krizhanovsky Jul 26, 2019
0d18c6b
Several fixes; disable several tests; adopt to #715
krizhanovsky Jul 28, 2019
f3d58d9
Sevaral small fixes and cleanups
krizhanovsky Jul 30, 2019
f99a725
Start Tempesta synchronously and wait for appropriate message in dmesg
krizhanovsky Jul 30, 2019
e558680
Unlimit net ratelimiter to have dmesg records for tests
krizhanovsky Jul 30, 2019
e4e7fb3
Multiple fixes in TLS tests and the infrastructure
krizhanovsky Jul 31, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions framework/tester.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ def __create_client_deproxy(self, client, ssl):
addr = fill_template(client['addr'], client)
port = int(fill_template(client['port'], client))
clt = deproxy_client.DeproxyClient(addr=addr, port=port, ssl=ssl)
if ssl:
server_hostname = fill_template(client['ssl_hostname'], client)
clt.set_server_hostname(server_hostname)
return clt

def __create_client_wrk(self, client, ssl):
Expand Down
6 changes: 1 addition & 5 deletions helpers/analyzer.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,7 @@ def __init__(self, node, host, count=0,
self.captured = 0
self.packets = []
self.dump_file = '/tmp/tmp_packet_dump'
str_ports = ""
for port in ports:
if str_ports:
str_ports += " or "
str_ports += 'tcp port %s' % port
str_ports = ' or '.join(('tcp port %s' % p) for p in ports)
cmd = 'timeout %s tcpdump -i any %s -w - %s || true'
count_flag = ('-c %s' % count) if count else ''
self.cmd = cmd % (timeout, count_flag, str_ports)
Expand Down
17 changes: 11 additions & 6 deletions helpers/deproxy.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@
a test with heavy load condition.

TODO Why do we implement HttpMessage, Request, and Response on our own instead
of using HTTPMessage, HTTPRequest, and HTTPResponse correspondingly fro httplib?
Rewrite the code to use httplib or other standard (present in CentOS and
Debian distros) package or write a reasining comment why can't we use standard
tools.
of using HTTPMessage, HTTPRequest, and HTTPResponse correspondingly from
httplib? Rewrite the code to use httplib or other standard (available in CentOS
and Debian distros) package or write a reasoning comment why can't we use
standard tools.
"""
from __future__ import print_function
import abc
Expand Down Expand Up @@ -542,6 +542,10 @@ def __init__(self, ssl=False):
self.ssl = ssl
self.want_read = False
self.want_write = True # TLS CLientHello is the first one
self.server_hostname = None

def set_server_hostname(self, server_hostname):
self.server_hostname = server_hostname

def save_handlers(self):
"""
Expand Down Expand Up @@ -587,8 +591,9 @@ def handle_connect(self):
self.writable = self.tls_handshake_writable
self.readable = self.tls_handshake_readable
try:
self.socket = ssl.wrap_socket(self.socket,
do_handshake_on_connect=False)
self.socket = ssl.SSLSocket(self.socket,
do_handshake_on_connect=False,
server_hostname=self.server_hostname)
except IOError as tls_e:
tf_cfg.dbg(2, 'Deproxy: cannot establish TLS connection')
raise tls_e
Expand Down
8 changes: 8 additions & 0 deletions tests_disabled.json
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,14 @@
"name" : "tls.test_tls_handshake.TlsVhostHandshakeTest.test_empty_sni_default",
"reason" : "Bug #1308: Tempesta doesn't send TLS alerts."
},
{
"name" : "tls.test_tls_handshake.TlsHandshakeTest.test_many_ciphers",
"reason" : "Bug #1308: Tempesta doesn't send TLS alerts."
},
{
"name" : "tls.test_tls_handshake.TlsHandshakeTest.test_fuzzing",
"reason" : "Bug #1318: crash on ttls_recv()."
},
{
"name" : "tls.test_tls_integrity",
"reason" : "Bug #1283: all messages longer than 4096 aren't processed."
Expand Down
2 changes: 2 additions & 0 deletions tls/handshake.py
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,8 @@ def try_tls_vers(self, version):
resp = tls_sock.recv(100)
tls_sock.close()
if resp.startswith(GOOD_RESP):
if self.verbose:
print("bad response:\n%s\n" % resp)
return False
return True

Expand Down
5 changes: 3 additions & 2 deletions tls/test_tls_cert.py
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,7 @@ class TlsDuplicateCerts(tester.TempestaTest):
'addr' : "${tempesta_ip}",
'port' : '443',
'ssl' : True,
'ssl_hostname' : 'tempesta-tech.com'
},
]

Expand Down Expand Up @@ -368,7 +369,7 @@ def gen_cert(host_name, alg=None):

def test_duplicate(self):
self.gen_cert("tempesta")
self.gen_cert("tempesta2")
self.gen_cert("tempesta_dup")

deproxy_srv = self.get_server('0')
deproxy_srv.start()
Expand All @@ -387,7 +388,7 @@ def test_duplicate(self):

def test_2_diff_certs(self):
self.gen_cert("tempesta")
self.gen_cert("tempesta2", 'rsa')
self.gen_cert("tempesta_dup", 'rsa')

deproxy_srv = self.get_server('0')
deproxy_srv.start()
Expand Down
25 changes: 16 additions & 9 deletions tls/test_tls_handshake.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,6 @@ class TlsHandshakeTest(tester.TempestaTest):
}
vhost tempesta-tech.com {
proxy_pass srv_grp1;
# TODO tls_certificate ${general_workdir}/tempesta.crt;
# TODO tls_certificate_key ${general_workdir}/tempesta.key;
}
http_chain {
host == "tempesta-tech.com" -> tempesta-tech.com;
Expand Down Expand Up @@ -86,7 +84,13 @@ def test_many_ciphers(self):
hs12.ciphers = [i for i in xrange(2000)] # TTLS_HS_CS_MAX_SZ = 984
# Test compressions as well - they're just ignored anyway.
hs12.compressions = [i for i in xrange(15)]
self.assertTrue(hs12.do_12(), "Extra ciphers aren't ignored")
warns = dmesg.count_warnings(WARN)
# Tempesta must send a TLS alert raising TLSProtocolError exception.
# Nginx/OpenSSL sends DECODE_ERROR FATAL alert for the ClientHello.
with self.assertRaises(tls.TLSProtocolError):
hs12.do_12()
self.assertEqual(dmesg.count_warnings(WARN), warns + 1,
"No warning about bad ClientHello")

def test_long_sni(self):
""" Also tests receiving of TLS alert. """
Expand All @@ -107,7 +111,6 @@ def test_empty_sni_default(self):
self.assertTrue(hs12.do_12(), "Empty SNI isn't accepted by default")

def test_bad_sni(self):
# FIXME Two or more certificates configured, please use custom_cert option in Tempesta configuration
self.start_all()
hs12 = TlsHandshake(addr='127.0.0.1', port=443)
hs12.sni = ["bad.server.name"]
Expand Down Expand Up @@ -196,12 +199,14 @@ def test_fuzzing(self):
try:
res = tls_conn.do_12(fuzzer)
self.assertFalse(res, "Got request on fuzzed connection")
except socket.error:
pass # broken pipe is expected
except:
# Broken pipe socket error and TLS fatal alerts are
# expected in the test.
pass

def test_old_handshakes(self):
self.start_all()
res = TlsHandshakeStandard(addr='127.0.0.1', port=443).do_old()
res = TlsHandshakeStandard(addr='127.0.0.1', port=443, verbose=True).do_old()
self.assertTrue(res, "Wrong old handshake result: %s" % res)


Expand Down Expand Up @@ -241,10 +246,12 @@ class TlsVhostHandshakeTest(tester.TempestaTest):
srv_group be1 { server ${server_ip}:8000; }
srv_group be2 { server ${server_ip}:8001; }

# Ensure that vhost1 only is using the global certificate.
tls_certificate ${general_workdir}/vhost1.crt;
tls_certificate_key ${general_workdir}/vhost1.key;

vhost vhost1.net {
proxy_pass be1;
tls_certificate ${general_workdir}/vhost1.crt;
tls_certificate_key ${general_workdir}/vhost1.key;
}

vhost vhost2.net {
Expand Down