test suite for SNI/ALPN with multiple targets and all combinations covered

This commit is contained in:
yrutschle 2018-08-30 19:50:53 +02:00
parent 1693436cc3
commit ffe9971624
3 changed files with 63 additions and 27 deletions

View File

@ -15,6 +15,13 @@ vNEXT:
thing to know when writing the configuration file is thing to know when writing the configuration file is
that 'anyprot' needs to be last. that 'anyprot' needs to be last.
Test suite heavily refactored; `t` uses `test.cfg`
to decide which probes to test and all setup is
automatic; probes get tested with 'fast' (entire
first message in one packet) and 'slow' (one byte at
a time); when SNI/ALPN are defined, all combinations
are tested.
v1.19: 20JAN2018 v1.19: 20JAN2018
Added 'syslog_facility' configuration option to Added 'syslog_facility' configuration option to
specify where to log. specify where to log.

72
t
View File

@ -51,6 +51,17 @@ sub verbose_exec
# For SNI/ALPN, build a protocol name as such:
# tls:sni1,sni2,...;alpn1,alpn2,...
# input: a protocol entry from Libconfig
sub make_sni_alpn_name {
my ($prot) = @_;
return "tls:" . (join ",", @{$prot->{sni_hostnames} // []})
. ";" . (join ",", @{$prot->{alpn_protocols} // [] });
}
# Tests one probe: given input data, connect, verify we get # Tests one probe: given input data, connect, verify we get
# the expected server, verify shoveling works # the expected server, verify shoveling works
# Named options: # Named options:
@ -103,8 +114,13 @@ sub test_probes {
data => "GET index.html HTTP/1.1", data => "GET index.html HTTP/1.1",
no_frag => 1 }, no_frag => 1 },
'ssl' => { data => "\x16\x03\x031234" }, 'ssl' => { data => "\x16\x03\x031234" },
# Capture of `openssl s_client -connect server2.org:443 -alpn alpn1 -servername sni1` 'tls' => {
'tls' => { data => "\x16\x03\x01\x00\xc4\x01\x00\x00\xc0\x03\x03\x03\x19\x01\x00\x40\x14\x13\xcc\x1b\x94\xad\x20\x5d\x13\x1a\x8d\xd2\x65\x23\x70\xde\xd1\x3c\x5d\x05\x19\xcb\x27\x0d\x7c\x2c\x89\x00\x00\x38\xc0\x2c\xc0\x30\x00\x9f\xcc\xa9\xcc\xa8\xcc\xaa\xc0\x2b\xc0\x2f\x00\x9e\xc0\x24\xc0\x28\x00\x6b\xc0\x23\xc0\x27\x00\x67\xc0\x0a\xc0\x14\x00\x39\xc0\x09\xc0\x13\x00\x33\x00\x9d\x00\x9c\x00\x3d\x00\x3c\x00\x35\x00\x2f\x00\xff\x01\x00\x00\x5f\x00\x00\x00\x09\x00\x07\x00\x00\x04\x73\x6e\x69\x31\x00\x0b\x00\x04\x03\x00\x01\x02\x00\x0a\x00\x0a\x00\x08\x00\x1d\x00\x17\x00\x19\x00\x18\x00\x23\x00\x00\x00\x0d\x00\x20\x00\x1e\x06\x01\x06\x02\x06\x03\x05\x01\x05\x02\x05\x03\x04\x01\x04\x02\x04\x03\x03\x01\x03\x02\x03\x03\x02\x01\x02\x02\x02\x03\x00\x10\x00\x08\x00\x06\x05\x61\x6c\x70\x6e\x31\x00\x16\x00\x00\x00\x17\x00\x00hello alpn" # Packet with SNI and ALPN (`openssl s_client -connect localhost:443 -alpn alpn1 -servername sni1`)
data_sni_alpn => "\x16\x03\x01\x00\xc4\x01\x00\x00\xc0\x03\x03\x03\x19\x01\x00\x40\x14\x13\xcc\x1b\x94\xad\x20\x5d\x13\x1a\x8d\xd2\x65\x23\x70\xde\xd1\x3c\x5d\x05\x19\xcb\x27\x0d\x7c\x2c\x89\x00\x00\x38\xc0\x2c\xc0\x30\x00\x9f\xcc\xa9\xcc\xa8\xcc\xaa\xc0\x2b\xc0\x2f\x00\x9e\xc0\x24\xc0\x28\x00\x6b\xc0\x23\xc0\x27\x00\x67\xc0\x0a\xc0\x14\x00\x39\xc0\x09\xc0\x13\x00\x33\x00\x9d\x00\x9c\x00\x3d\x00\x3c\x00\x35\x00\x2f\x00\xff\x01\x00\x00\x5f\x00\x00\x00\x09\x00\x07\x00\x00\x04\$sni\x00\x0b\x00\x04\x03\x00\x01\x02\x00\x0a\x00\x0a\x00\x08\x00\x1d\x00\x17\x00\x19\x00\x18\x00\x23\x00\x00\x00\x0d\x00\x20\x00\x1e\x06\x01\x06\x02\x06\x03\x05\x01\x05\x02\x05\x03\x04\x01\x04\x02\x04\x03\x03\x01\x03\x02\x03\x03\x02\x01\x02\x02\x02\x03\x00\x10\x00\x08\x00\x06\x05\$alpn\x00\x16\x00\x00\x00\x17\x00\x00hello sni/alpn",
# Packet with SNI alone
data_sni => "\x16\x03\x01\x00\xb8\x01\x00\x00\xb4\x03\x03\x97\xe4\xe9\xad\x86\xe1\x21\xfd\xc4\x5b\x27\x0e\xad\x4b\x55\xc2\x50\xe4\x1c\x86\x2f\x37\x25\xde\xe8\x9c\x59\xfc\x1b\xa9\x37\x32\x00\x00\x38\xc0\x2c\xc0\x30\x00\x9f\xcc\xa9\xcc\xa8\xcc\xaa\xc0\x2b\xc0\x2f\x00\x9e\xc0\x24\xc0\x28\x00\x6b\xc0\x23\xc0\x27\x00\x67\xc0\x0a\xc0\x14\x00\x39\xc0\x09\xc0\x13\x00\x33\x00\x9d\x00\x9c\x00\x3d\x00\x3c\x00\x35\x00\x2f\x00\xff\x01\x00\x00\x53\x00\x00\x00\x09\x00\x07\x00\x00\x04\$sni\x00\x0b\x00\x04\x03\x00\x01\x02\x00\x0a\x00\x0a\x00\x08\x00\x1d\x00\x17\x00\x19\x00\x18\x00\x23\x00\x00\x00\x0d\x00\x20\x00\x1e\x06\x01\x06\x02\x06\x03\x05\x01\x05\x02\x05\x03\x04\x01\x04\x02\x04\x03\x03\x01\x03\x02\x03\x03\x02\x01\x02\x02\x02\x03\x00\x16\x00\x00\x00\x17\x00\x00hello sni",
# packet with ALPN alone
data_alpn => "\x16\x03\x01\x00\xb7\x01\x00\x00\xb3\x03\x03\xe2\x90\xa2\x29\x03\x31\xad\x98\x44\x51\x54\x90\x5b\xd9\x51\x0e\x66\xb5\x3f\xe8\x8b\x09\xc9\xe4\x2b\x97\x24\xef\xad\x56\x06\xc9\x00\x00\x38\xc0\x2c\xc0\x30\x00\x9f\xcc\xa9\xcc\xa8\xcc\xaa\xc0\x2b\xc0\x2f\x00\x9e\xc0\x24\xc0\x28\x00\x6b\xc0\x23\xc0\x27\x00\x67\xc0\x0a\xc0\x14\x00\x39\xc0\x09\xc0\x13\x00\x33\x00\x9d\x00\x9c\x00\x3d\x00\x3c\x00\x35\x00\x2f\x00\xff\x01\x00\x00\x52\x00\x0b\x00\x04\x03\x00\x01\x02\x00\x0a\x00\x0a\x00\x08\x00\x1d\x00\x17\x00\x19\x00\x18\x00\x23\x00\x00\x00\x0d\x00\x20\x00\x1e\x06\x01\x06\x02\x06\x03\x05\x01\x05\x02\x05\x03\x04\x01\x04\x02\x04\x03\x03\x01\x03\x02\x03\x03\x02\x01\x02\x02\x02\x03\x00\x10\x00\x08\x00\x06\x05\$alpn\x00\x16\x00\x00\x00\x17\x00\x00hello alpn",
}, },
'openvpn' => { data => "\x00\x00" }, 'openvpn' => { data => "\x00\x00" },
'tinc' => { data => "0 hello" }, 'tinc' => { data => "0 hello" },
@ -115,36 +131,49 @@ sub test_probes {
my $pattern = $protocols{$p->{name}}->{data}; my $pattern = $protocols{$p->{name}}->{data};
# protocol name with SNI/ALPN spec if present
my $pname;
if ($p->{sni_hostnames} or $p->{alpn_protocols}) {
$pname = $p->{name} . ":" . (join ",", @{$p->{sni_hostnames}})
. ";" . (join ",", @{$p->{alpn_protocols}});
}
$opts{no_frag} = 1 if $protocols{$p->{name}}->{no_frag}; $opts{no_frag} = 1 if $protocols{$p->{name}}->{no_frag};
test_probe(
data => $pattern,
expected => $p->{name},
%opts
);
if ($p->{sni_hostnames} or $p->{alpn_protocols}) {
my $pname = make_sni_alpn_name($p);
my @sni = @{$p->{sni_hostnames} // [""] };
my @alpn = @{$p->{alpn_protocols} // [""] };
foreach my $sni ( @sni ) {
foreach my $alpn ( @alpn ) {
print "sni: $sni\nalpn: $alpn\n";
$pattern = $protocols{tls}->{
"data". ($sni ? "_sni" : "") .
($alpn ? "_alpn": "")
};
$pattern =~ s/(\$\w+)/$1/eeg;
test_probe(
data => $pattern,
expected => $pname,
%opts
);
}
}
} else {
test_probe(
data => $pattern,
expected => $p->{name},
%opts
);
}
} }
} }
# Start an echoserver for each service # Start an echoserver for each service
foreach my $s (@{$conf->fetch_array("protocols")}) { foreach my $s (@{$conf->fetch_array("protocols")}) {
my $prefix = $s->{name}; my $prefix = $s->{name};
# For SNI/ALPN, build a protocol name as such:
# tls:sni1,sni2,...;alpn1,alpn2,...
if ($s->{sni_hostnames} or $s->{alpn_protocols}) { if ($s->{sni_hostnames} or $s->{alpn_protocols}) {
$prefix .= ":" . join ",", @{$s->{sni_hostnames}}; $prefix = make_sni_alpn_name($s);
$prefix .= ";";
$prefix .= join ",", @{$s->{alpn_protocols}};
} }
verbose_exec "./echosrv --listen $s->{host}:$s->{port} --prefix '$prefix: '"; verbose_exec "./echosrv --listen $s->{host}:$s->{port} --prefix '$prefix: '";
@ -152,7 +181,6 @@ foreach my $s (@{$conf->fetch_array("protocols")}) {
my @binaries = ('sslh-select', 'sslh-fork'); my @binaries = ('sslh-select', 'sslh-fork');
@binaries = ('sslh-select');
for my $binary (@binaries) { for my $binary (@binaries) {
warn "Testing $binary\n"; warn "Testing $binary\n";

View File

@ -1,7 +1,7 @@
# Configuration file for testing (use both by sslh under # Configuration file for testing (use both by sslh under
# test and the test script `t`) # test and the test script `t`)
verbose: true; verbose: 2;
foreground: true; foreground: true;
inetd: false; inetd: false;
numeric: false; numeric: false;
@ -29,12 +29,13 @@ protocols:
{ name: "tinc"; host: "localhost"; port: "9003"; }, { name: "tinc"; host: "localhost"; port: "9003"; },
{ name: "openvpn"; host: "localhost"; port: "9004"; }, { name: "openvpn"; host: "localhost"; port: "9004"; },
{ name: "ssl"; host: "localhost"; port: "9005"; }, { name: "ssl"; host: "localhost"; port: "9005"; },
{ name: "tls"; host: "localhost"; port: "9006"; alpn_protocols: [ "alpn1", "alpn2" ]; sni_hostnames: [ "sni1" ]; },
{ name: "tls"; host: "localhost"; port: "9007"; alpn_protocols: [ "alpn1", "alpn2" ]; sni_hostnames: [ "sni2", "sni3" ]; }
{ name: "tls"; host: "localhost"; port: "9008"; alpn_protocols: [ "alpn1" ]; sni_hostnames: [ "sni3" ]; }
{ name: "xmpp"; host: "localhost"; port: "9009"; }, { name: "xmpp"; host: "localhost"; port: "9009"; },
{ name: "adb"; host: "localhost"; port: "9010"; }, { name: "adb"; host: "localhost"; port: "9010"; },
{ name: "anyprot"; host: "localhost"; port: "9011"; } { name: "tls"; host: "localhost"; port: "9020"; alpn_protocols: [ "alpn1", "alpn2" ]; sni_hostnames: [ "sni1" ]; },
{ name: "tls"; host: "localhost"; port: "9021"; alpn_protocols: [ "alpn1", "alpn2" ]; sni_hostnames: [ "sni2", "sni3" ]; },
{ name: "tls"; host: "localhost"; port: "9023"; alpn_protocols: [ "alpn3" ]; },
{ name: "tls"; host: "localhost"; port: "9024"; sni_hostnames: [ "sni3" ]; },
{ name: "anyprot"; host: "localhost"; port: "9099"; }
); );
on-timeout: "ssh"; on-timeout: "ssh";