# HG changeset patch # User Sergey Kandaurov # Date 1435838799 -10800 # Node ID f27fb891503cef46dba7e7fa2e072d85f09bf723 # Parent 0597ca82c26aa448deab0fd6a361ca895390a890 Tests: stream proxy protocol tests to ssl backend. diff --git a/stream_proxy_protocol_ssl.t b/stream_proxy_protocol_ssl.t new file mode 100644 --- /dev/null +++ b/stream_proxy_protocol_ssl.t @@ -0,0 +1,179 @@ +#!/usr/bin/perl + +# (C) Sergey Kandaurov +# (C) Nginx, Inc. + +# Tests for stream proxy module with haproxy protocol to ssl backend. + +############################################################################### + +use warnings; +use strict; + +use Test::More; + +use IO::Select; +use Socket qw/ CR LF CRLF /; + +BEGIN { use FindBin; chdir($FindBin::Bin); } + +use lib 'lib'; +use Test::Nginx qw/ :DEFAULT http_end /; + +############################################################################### + +select STDERR; $| = 1; +select STDOUT; $| = 1; + +eval { require IO::Socket::SSL; }; +plan(skip_all => 'IO::Socket::SSL not installed') if $@; + +my $t = Test::Nginx->new()->has(qw/stream stream_ssl/)->has_daemon('openssl'); + +$t->write_file_expand('nginx.conf', <<'EOF'); + +%%TEST_GLOBALS%% + +daemon off; + +events { +} + +stream { + proxy_ssl on; + proxy_protocol on; + + server { + listen 127.0.0.1:8080; + proxy_pass 127.0.0.1:8081; + } + + server { + listen 127.0.0.1:8082; + proxy_pass 127.0.0.1:8083; + proxy_protocol off; + } +} + +EOF + +$t->write_file('openssl.conf', <testdir(); + +foreach my $name ('localhost') { + system('openssl req -x509 -new ' + . "-config '$d/openssl.conf' -subj '/CN=$name/' " + . "-out '$d/$name.crt' -keyout '$d/$name.key' " + . ">>$d/openssl.out 2>&1") == 0 + or die "Can't create certificate for $name: $!\n"; +} + +$t->run_daemon(\&stream_daemon_ssl, 8081, path => $d, pp => 1); +$t->run_daemon(\&stream_daemon_ssl, 8083, path => $d, pp => 0); +$t->try_run('no stream proxy_protocol')->plan(2); + +$t->waitforsocket('127.0.0.1:8081'); +$t->waitforsocket('127.0.0.1:8083'); + +############################################################################### + +my %r = pp_get('test'); +is($r{'data'}, "PROXY TCP4 127.0.0.1 127.0.0.1 $r{'sp'} 8080" . CRLF . 'test', + 'protocol on'); + +%r = pp_get('test', '127.0.0.1:8082'); +is($r{'data'}, 'test', 'protocol off'); + +############################################################################### + +sub pp_get { + my ($data, $peer) = @_; + + my $s = http($data, socket => getconn($peer), start => 1); + my $sockport = $s->sockport; + $data = http_end($s); + return ('data' => $data, 'sp' => $sockport); +} + +sub getconn { + my $peer = shift; + my $s = IO::Socket::INET->new( + Proto => 'tcp', + PeerAddr => $peer || '127.0.0.1:8080' + ) + or die "Can't connect to nginx: $!\n"; + + return $s; +} + +############################################################################### + +sub stream_daemon_ssl { + my ($port, %extra) = @_; + my $d = $extra{path}; + my $pp = $extra{pp}; + my $server = IO::Socket::INET->new( + Proto => 'tcp', + LocalHost => "127.0.0.1:$port", + Listen => 5, + Reuse => 1 + ) + or die "Can't create listening socket: $!\n"; + + local $SIG{PIPE} = 'IGNORE'; + + while (my $client = $server->accept()) { + my ($buffer, $data) = ('', ''); + $client->autoflush(1); + + log2c("(new connection $client on $port)"); + + # read no more than haproxy header of variable length + + while ($pp) { + my $prev = $buffer; + $client->sysread($buffer, 1) or last; + $data .= $buffer; + last if $prev eq CR && $buffer eq LF; + } + + log2i("$client $data"); + + # would fail on waitforsocket + + eval { + IO::Socket::SSL->start_SSL($client, + SSL_server => 1, + SSL_cert_file => "$d/localhost.crt", + SSL_key_file => "$d/localhost.key", + SSL_error_trap => sub { die $_[1] } + ); + }; + next if $@; + + $client->sysread($buffer, 65536) or next; + + log2i("$client $buffer"); + + $data .= $buffer; + + log2o("$client $data"); + + $client->syswrite($data); + + close $client; + } +} + +sub log2i { Test::Nginx::log_core('|| <<', @_); } +sub log2o { Test::Nginx::log_core('|| >>', @_); } +sub log2c { Test::Nginx::log_core('||', @_); } + +###############################################################################