[PATCH] Mail: tests for PROXY PROTOCOL support
muradm
mail at muradm.net
Sat Jan 16 11:58:07 UTC 2021
# HG changeset patch
# User muradm <mail at muradm.net>
# Date 1610797338 -10800
# Sat Jan 16 14:42:18 2021 +0300
# Node ID 76e7def783657962088ec2e8346b839cda744efb
# Parent 6c323c672a8678b7cff4c0ccc7b303ef2e477f7c
Mail: tests for PROXY PROTOCOL support
diff -r 6c323c672a86 -r 76e7def78365 mail_proxy_protocol_handle.t
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mail_proxy_protocol_handle.t Sat Jan 16 14:42:18 2021 +0300
@@ -0,0 +1,112 @@
+#!/usr/bin/perl
+
+# Tests for imap/pop3/smtp proxy protocol handling.
+# Note: testing only v1 protocol here with hope that v2 is tested by core
+
+###############################################################################
+
+use warnings;
+use strict;
+
+use Test::More;
+
+BEGIN { use FindBin; chdir($FindBin::Bin); }
+
+use lib 'lib';
+use Test::Nginx;
+use Test::Nginx::IMAP;
+use Test::Nginx::POP3;
+use Test::Nginx::SMTP;
+
+###############################################################################
+
+select STDERR; $| = 1;
+select STDOUT; $| = 1;
+
+my $t = Test::Nginx->new()->has(qw/mail imap pop3 smtp/)->plan(7);
+
+$t->write_file_expand('nginx.conf', <<'EOF');
+
+%%TEST_GLOBALS%%
+
+daemon off;
+
+events {
+}
+
+mail {
+ auth_http http://127.0.0.1:8080; # unused
+
+ server {
+ listen 127.0.0.1:8143 proxy_protocol;
+ protocol imap;
+ }
+
+ server {
+ listen 127.0.0.1:8110 proxy_protocol;
+ protocol pop3;
+ }
+
+ server {
+ listen 127.0.0.1:8025 proxy_protocol;
+ protocol smtp;
+ }
+}
+
+EOF
+
+$t->run();
+
+###############################################################################
+
+# imap, proxy protocol handler
+
+my $s = Test::Nginx::IMAP->new(PeerAddr => '127.0.0.1:' . port(8143));
+$s->send('PROXY TCP4 192.168.1.10 192.168.1.1 18143 8143');
+$s->read();
+
+$s->send('1 CAPABILITY');
+$s->check(qr/^\* CAPABILITY IMAP4 IMAP4rev1 UIDPLUS AUTH=PLAIN/, 'imap proxy protocol');
+$s->ok('imap proxy protocol handler');
+
+###############################################################################
+
+# pop3, proxy protocol handler
+
+$s = Test::Nginx::POP3->new(PeerAddr => '127.0.0.1:' . port(8110));
+$s->send('PROXY TCP4 192.168.1.10 192.168.1.1 18143 8110');
+$s->read();
+
+$s->send('CAPA');
+$s->ok('pop3 capa');
+
+my $caps = get_auth_caps($s);
+like($caps, qr/USER/, 'pop3 - user');
+like($caps, qr/TOP:USER:UIDL:SASL PLAIN LOGIN/, 'pop3 - methods');
+unlike($caps, qr/STLS/, 'pop3 - no stls');
+
+###############################################################################
+
+# smtp, proxy protocol handler
+
+$s = Test::Nginx::SMTP->new(PeerAddr => '127.0.0.1:' . port(8025));
+$s->send('PROXY TCP4 192.168.1.10 192.168.1.1 18143 8110');
+$s->read();
+
+$s->send('EHLO example.com');
+$s->check(qr/^250 AUTH PLAIN LOGIN\x0d\x0a?/, 'smtp ehlo');
+
+###############################################################################
+
+sub get_auth_caps {
+ my ($s) = @_;
+ my @meth;
+
+ while ($s->read()) {
+ last if /^\./;
+ push @meth, $1 if /(.*?)\x0d\x0a?/ms;
+ }
+ join ':', @meth;
+}
+
+###############################################################################
diff -r 6c323c672a86 -r 76e7def78365 mail_proxy_protocol_handle_ssl.t
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mail_proxy_protocol_handle_ssl.t Sat Jan 16 14:42:18 2021 +0300
@@ -0,0 +1,156 @@
+#!/usr/bin/perl
+
+# Tests for mail proxy protocol handler with ssl.
+# Note: testing only v1 protocol here with hope that v2 is tested by core
+
+###############################################################################
+
+use warnings;
+use strict;
+
+use Socket qw/ CRLF /;
+
+use Test::More;
+
+BEGIN { use FindBin; chdir($FindBin::Bin); }
+
+use lib 'lib';
+use Test::Nginx;
+
+###############################################################################
+
+select STDERR; $| = 1;
+select STDOUT; $| = 1;
+
+eval {
+ require Net::SSLeay;
+ Net::SSLeay::load_error_strings();
+ Net::SSLeay::SSLeay_add_ssl_algorithms();
+ Net::SSLeay::randomize();
+};
+plan(skip_all => 'Net::SSLeay not installed') if $@;
+
+my $t = Test::Nginx->new()->has(qw/mail mail_ssl imap pop3 smtp/)
+ ->has_daemon('openssl')->plan(6);
+
+$t->write_file_expand('nginx.conf', <<'EOF');
+
+%%TEST_GLOBALS%%
+
+daemon off;
+
+events {
+}
+
+mail {
+ auth_http http://127.0.0.1:8080; # unused
+
+ ssl_certificate_key localhost.key;
+ ssl_certificate localhost.crt;
+ ssl_session_tickets off;
+
+ ssl_password_file password;
+
+ ssl_session_cache none;
+
+ server {
+ listen 127.0.0.1:8993 ssl;
+ protocol imap;
+ }
+
+ server {
+ listen 127.0.0.1:8994 ssl proxy_protocol;
+ protocol imap;
+ }
+
+ server {
+ listen 127.0.0.1:8995 ssl;
+ protocol pop3;
+ }
+
+ server {
+ listen 127.0.0.1:8996 ssl proxy_protocol;
+ protocol pop3;
+ }
+
+ server {
+ listen 127.0.0.1:8465 ssl;
+ protocol smtp;
+ }
+
+ server {
+ listen 127.0.0.1:8466 ssl proxy_protocol;
+ protocol smtp;
+ }
+}
+
+EOF
+
+$t->write_file('openssl.conf', <<EOF);
+[ req ]
+default_bits = 2048
+encrypt_key = no
+distinguished_name = req_distinguished_name
+[ req_distinguished_name ]
+EOF
+
+my $d = $t->testdir();
+
+foreach my $name ('localhost', 'inherits') {
+ system("openssl genrsa -out $d/$name.key -passout pass:localhost "
+ . "-aes128 2048 >>$d/openssl.out 2>&1") == 0
+ or die "Can't create private key: $!\n";
+ system('openssl req -x509 -new '
+ . "-config $d/openssl.conf -subj /CN=$name/ "
+ . "-out $d/$name.crt "
+ . "-key $d/$name.key -passin pass:localhost"
+ . ">>$d/openssl.out 2>&1") == 0
+ or die "Can't create certificate for $name: $!\n";
+}
+
+my $ctx = Net::SSLeay::CTX_new() or die("Failed to create SSL_CTX $!");
+$t->write_file('password', 'localhost');
+
+open OLDERR, ">&", \*STDERR; close STDERR;
+$t->run();
+open STDERR, ">&", \*OLDERR;
+
+###############################################################################
+
+my @list = (qw(8993 8994 8995 8996 8465 8466));
+
+while (my ($p1, $p2) = splice (@list,0,2)) {
+ my ($s, $ssl, $ses);
+
+ $s = get_socket($p1);
+
+ $ssl = make_ssl_socket($s);
+ $ses = Net::SSLeay::get_session($ssl);
+ like(Net::SSLeay::dump_peer_certificate($ssl), qr/CN=localhost/, 'CN');
+
+ $s = get_socket($p2);
+ $s->print('PROXY TCP4 192.168.1.10 192.168.1.1 18143 8110' . CRLF);
+
+ $ssl = make_ssl_socket($s);
+ $ses = Net::SSLeay::get_session($ssl);
+ like(Net::SSLeay::dump_peer_certificate($ssl), qr/CN=localhost/, 'CN');
+}
+
+###############################################################################
+
+sub get_socket {
+ my ($port) = @_;
+ return IO::Socket::INET->new('127.0.0.1:' . port($port));
+}
+
+sub make_ssl_socket {
+ my ($socket, $ses) = @_;
+
+ my $ssl = Net::SSLeay::new($ctx) or die("Failed to create SSL $!");
+ Net::SSLeay::set_session($ssl, $ses) if defined $ses;
+ Net::SSLeay::set_fd($ssl, fileno($socket));
+ Net::SSLeay::connect($ssl) or die("ssl connect");
+ return $ssl;
+}
+
+###############################################################################
diff -r 6c323c672a86 -r 76e7def78365 mail_proxy_proxy_protocol.t
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mail_proxy_proxy_protocol.t Sat Jan 16 14:42:18 2021 +0300
@@ -0,0 +1,199 @@
+#!/usr/bin/perl
+
+# Tests for nginx mail proxy module, the proxy_protocol directive.
+
+###############################################################################
+
+use warnings;
+use strict;
+
+use Socket qw/ CRLF /;
+
+use Test::More;
+
+use MIME::Base64;
+
+BEGIN { use FindBin; chdir($FindBin::Bin); }
+
+use lib 'lib';
+use Test::Nginx;
+use Test::Nginx::SMTP;
+
+###############################################################################
+
+select STDERR; $| = 1;
+select STDOUT; $| = 1;
+
+local $SIG{PIPE} = 'IGNORE';
+
+my $t = Test::Nginx->new()->has(qw/mail smtp http rewrite/)->plan(9);
+
+$t->write_file_expand('nginx.conf', <<'EOF');
+
+%%TEST_GLOBALS%%
+
+daemon off;
+
+events {
+ worker_connections 48;
+}
+
+mail {
+ auth_http http://127.0.0.1:8080/mail/auth;
+ smtp_auth login plain external;
+
+ server {
+ listen 127.0.0.1:8025;
+ protocol smtp;
+ xclient off;
+ }
+
+ server {
+ listen 127.0.0.1:8027;
+ protocol smtp;
+ xclient off;
+ proxy_protocol on;
+ }
+
+ server {
+ listen 127.0.0.1:8029 proxy_protocol;
+ protocol smtp;
+ xclient off;
+ proxy_protocol on;
+ proxy_smtp_auth on;
+ }
+}
+
+http {
+ %%TEST_GLOBALS_HTTP%%
+
+ server {
+ listen 127.0.0.1:8080;
+ server_name localhost;
+
+ location = /mail/auth {
+ add_header Auth-Status OK;
+ add_header Auth-Server 127.0.0.1;
+ add_header Auth-Port %%PORT_8026%%;
+ add_header Auth-User test at example.com;
+ add_header Auth-Pass test at example.com;
+ return 204;
+ }
+ }
+}
+
+EOF
+
+$t->run();
+
+###############################################################################
+
+my ($s, $pp_data);
+
+# no proxy_protocol in or out
+
+$t->run_daemon(\&smtp_test_listener, port(8026));
+$t->waitforsocket('127.0.0.1:' . port(8026));
+
+$s = Test::Nginx::SMTP->new(PeerAddr => '127.0.0.1:' . port(8025));
+$s->check(qr/ESMTP ready/);
+$s->send('EHLO example.com');
+$s->check(qr/250 AUTH PLAIN LOGIN EXTERNAL/);
+$s->send('AUTH PLAIN ' . encode_base64("\0test\@example.com\0secret", ''));
+$s->authok('ehlo, auth');
+$t->stop_daemons();
+
+# proxy_protocol only out
+
+$pp_data = 'PROXY TCP4 192.168.1.10 192.168.1.11';
+$t->run_daemon(\&smtp_test_listener, port(8026), $pp_data);
+$t->waitforsocket('127.0.0.1:' . port(8026));
+
+$s = Test::Nginx::SMTP->new(PeerAddr => '127.0.0.1:' . port(8027));
+$s->check(qr/ESMTP ready/);
+$s->send('EHLO example.com');
+$s->check(qr/250 AUTH PLAIN LOGIN EXTERNAL/);
+$s->send('AUTH PLAIN ' . encode_base64("\0test\@example.com\0secret", ''));
+$s->authok('ehlo, auth');
+$t->stop_daemons();
+
+# proxy_protocol only out and in
+$pp_data = 'PROXY TCP4 192.168.1.10 192.168.1.11';
+$t->run_daemon(\&smtp_test_listener, port(8026), $pp_data);
+$t->waitforsocket('127.0.0.1:' . port(8026));
+
+$s = Test::Nginx::SMTP->new(PeerAddr => '127.0.0.1:' . port(8029));
+$s->send($pp_data . ' 51298 8027');
+$s->check(qr/ESMTP ready/);
+$s->send('EHLO example.com');
+$s->check(qr/250 AUTH PLAIN LOGIN EXTERNAL/);
+$s->send('AUTH PLAIN ' . encode_base64("\0test\@example.com\0secret", ''));
+$s->authok('ehlo, auth');
+$t->stop_daemons();
+
+
+###############################################################################
+
+sub smtp_test_listener {
+ my ($port, $expected) = @_;
+ my $server = IO::Socket::INET->new(
+ Proto => 'tcp',
+ LocalAddr => '127.0.0.1:' . ($port || port(8026)),
+ Listen => 5,
+ Reuse => 1
+ )
+ or die "Can't create listening socket: $!\n";
+
+ while (my $client = $server->accept()) {
+ $client->autoflush(1);
+
+ if (defined($expected)) {
+ $expected = $expected . CRLF;
+ while (<$client>) {
+ if (/^proxy/i) {
+ Test::Nginx::log_core('||>>', $_);
+ last;
+ }
+ }
+ }
+
+ sub send_client {
+ my ($c, $d) = @_;
+ Test::Nginx::log_core('||<<', $d);
+ print $c $d . CRLF;
+ }
+
+ print $client "220 fake esmtp server ready" . CRLF;
+
+ while (<$client>) {
+ Test::Nginx::log_core('||>>', $_);
+
+ my $res = '';
+
+ if (/^quit/i) {
+ send_client($client, '221 quit ok');
+ } elsif (/^(ehlo|helo)/i) {
+ send_client($client, '250-ok');
+ send_client($client, '250 AUTH PLAIN LOGIN EXTERNAL');
+ } elsif (/^rset/i) {
+ send_client($client, '250 rset ok');
+ } elsif (/^auth plain/i) {
+ send_client($client, '235 auth ok');
+ } elsif (/^mail from:[^@]+$/i) {
+ send_client($client, '500 mail from error');
+ } elsif (/^mail from:/i) {
+ send_client($client, '250 mail from ok');
+ } elsif (/^rcpt to:[^@]+$/i) {
+ send_client($client, '500 rcpt to error');
+ } elsif (/^rcpt to:/i) {
+ send_client($client, '250 rcpt to ok');
+ } else {
+ send_client($client, '500 unknown command');
+ }
+ }
+
+ close $client;
+ }
+}
+
+###############################################################################
More information about the nginx-devel
mailing list