From 2106bd6527af3ed096087885884d53dd82ea30d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yves=20R=C5=B1tschl=C3=A9?= Date: Fri, 29 Aug 2025 20:39:42 +0200 Subject: [PATCH] added test for client-side proxyprotocol --- t/run | 48 ++++++++++++++++++++++++++++++++++++++---------- t/test_pp2.cfg | 45 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+), 10 deletions(-) create mode 100644 t/test_pp2.cfg diff --git a/t/run b/t/run index 4ac853c..cab02d1 100755 --- a/t/run +++ b/t/run @@ -124,16 +124,18 @@ sub stop_echosrv } -# Runs sslh -my ($sslh_pid); +# Runs sslh, restart it if configuration has changed +my ($sslh_pid, $sslh_conf); sub start_sslh { my ($exe, $conf) = @_; + stop_sslh() if (defined $sslh_conf and ($conf ne $sslh_conf)); return if defined $sslh_pid; + $sslh_conf = $conf; my ($valgrind); if (!($sslh_pid = fork)) { my $user = (getpwuid $<)[0]; # Run under current username - my $cmd = "../$exe -u $user -F $conf"; + my $cmd = "../$exe -F $conf"; print "****CMDLINE [$cmd]\n"; #$valgrind = 1; #$cmd = "valgrind --leak-check=full $cmd"; @@ -150,6 +152,7 @@ sub stop_sslh { if (defined $sslh_pid) { kill TERM => $sslh_pid or warn "kill process: $!\n"; + `killall sslh-ev sslh-select sslh-fork`; undef $sslh_pid; } } @@ -188,8 +191,9 @@ sub run_ending_test # Runs one test for one probe. Start echosrv's if required. -# Extract sslh's listening port from the config file, run -# sslh, connect, write the test pattern, read the result, +# Connect to port specified in the test, otherwise to the +# first port in the sslh configuration. +# run sslh, connect, write the test pattern, read the result, # check it connected to the right echosrv, check the data # was transfered ok. sub run_test_probe @@ -202,7 +206,7 @@ sub run_test_probe my $expected = $test->{expected}; - my $sslh_port = $conf->value("listen")->[0]->{port}; + my $sslh_port = $test->{port} // $conf->value("listen")->[0]->{port}; print "test_probe [$expected] $sslh_port\n"; my $cnx = new IO::Socket::INET(PeerHost => "localhost:$sslh_port"); warn "t: $!\n" unless $cnx; @@ -218,10 +222,10 @@ sub run_test_probe print "Received $n bytes: protocol $prefix data [$data]\n"; close $cnx; - my_is($prefix, $expected, "$exe:$expected: probe"); - my $data_expected = $test->{data_expected}; + my_is($prefix, $expected, "$exe:$test->{desc}:probe"); + my $data_expected = $test->{data_expected} // "^$test->{data}\$"; $data_expected =~ s/INPUT_DATA/$test->{data}/; - my_like($data, qr/$data_expected/s, "$exe:$expected: shoveled"); + my_like($data, qr/$data_expected/s, "$exe:$test->{desc}:shoveled"); } @@ -262,10 +266,12 @@ sub test_wrong_user # # * `expected`: protocol prompt added by the echosrv (should be the protocol name) # +# * `data`: what is sent to sslh, as a client +# # * `data_expected` is a regex for the expected return (which can be # different when using Proxyprotocol). INPUT_DATA gets # replaced with $_->{data}, i.e. data sent originally, -# before matching. +# before matching. Use `data` if not specified. # my @tests = ( @@ -319,6 +325,28 @@ my @tests = ( expected => "socks5", }, + # test_pp2.cfg has proxyprotocol on port 8080 + { + desc => "Client-side ProxyProtocol active", + run => \&run_test_probe, + cfg => "test_pp2.cfg", + data => "PROXY TCP4 127.0.0.1 127.0.0.1 8080 8081\x0D\x0ASSH-2.0 hello", + expected => "ssh", + data_expected => "^PROXY TCP4 127.0.0.1 127.0.0.1 \\d+ \\d+\x0D\x0AINPUT_DATA", + }, + + # test_pp2.cfg has no proxyprotocol on port 8081, so ssh + # should pass untouched + { + desc => "Client-side ProxyProtocol not active", + run => \&run_test_probe, + cfg => "test_pp2.cfg", + port => 8081, + data => "SSH-2.0 hello", + expected => "ssh", + }, + + ); diff --git a/t/test_pp2.cfg b/t/test_pp2.cfg new file mode 100644 index 0000000..749e716 --- /dev/null +++ b/t/test_pp2.cfg @@ -0,0 +1,45 @@ +# Testing for client-side ProxyProtocol + +foreground: true; +inetd: false; +numeric: true; +transparent: false; +timeout: 10; # Probe test writes slowly +pidfile: "/tmp/sslh_test.pid"; + +syslog_facility: "auth"; + +# Logging configuration +# Value: 1: stdout; 2: syslog; 3: both +# Defaults should be sensible. Generally, you want *-error +# to be always enabled, to know if something is going wrong. +verbose-config: 1; # print configuration at startup +verbose-config-error: 1; # print configuration errors +verbose-connections: 1; # trace established incoming address to forward address +verbose-connections-error: 1; # connection errors +verbose-connections-try: 1; # connection attempts towards targets +verbose-fd: 0; # file descriptor activity, open/close/whatnot +verbose-packets: 1; # hexdump packets on which probing is done +verbose-probe-info: 1; # what's happening during the probe process +verbose-probe-error: 1; # failures and problems during probing +verbose-system-error: 1; # system call problem, i.e. malloc, fork, failing +verbose-int-error: 1; # internal errors, the kind that should never happen + +# List of interfaces on which we should listen +# Options: +listen: +( + { host: "localhost"; port: "8080"; keepalive: true; proxyprotocol: true; }, + { host: "localhost"; port: "8081"; keepalive: true; proxyprotocol: false; } +); + + +protocols: +( + { name: "ssh"; host: "localhost"; port: "9000"; }, + { name: "socks5"; host: "localhost"; port: "9001"; }, + { name: "anyprot"; host: "localhost"; port: "9099"; } +); + +on_timeout: "ssh"; +