mirror of
https://github.com/yrutschle/sslh.git
synced 2025-06-04 01:21:20 +03:00
Added 'minlength' option
This commit is contained in:
parent
5b309a9b97
commit
a7b4462c6e
@ -1,3 +1,12 @@
|
|||||||
|
vNEXT:
|
||||||
|
Added 'minlength' option to skip a probe if less
|
||||||
|
than that many bytes have been received (mostly for
|
||||||
|
regex)
|
||||||
|
|
||||||
|
Moved configuration and command-line management to
|
||||||
|
use conf2struct. Hopefully this should be transparent
|
||||||
|
to users.
|
||||||
|
|
||||||
v1.20: 20NOV2018
|
v1.20: 20NOV2018
|
||||||
Added support for socks5 protocol (Eugene Protozanov)
|
Added support for socks5 protocol (Eugene Protozanov)
|
||||||
|
|
||||||
|
@ -93,9 +93,11 @@ port: "dns" } ),
|
|||||||
# OpenVPN
|
# OpenVPN
|
||||||
{ name: "regex"; host: "localhost"; port: "1194"; regex_patterns: [ "^\x00[\x0D-\xFF]$", "^\x00[\x0D-\xFF]\x38" ]; },
|
{ name: "regex"; host: "localhost"; port: "1194"; regex_patterns: [ "^\x00[\x0D-\xFF]$", "^\x00[\x0D-\xFF]\x38" ]; },
|
||||||
# Jabber
|
# Jabber
|
||||||
{ name: "regex"; host: "localhost"; port: "5222"; regex_patterns: [ "jabber" ]; },
|
{ name: "regex"; host: "localhost"; port: "5222"; regex_patterns: [ "jabber" ];
|
||||||
|
minlength: 60; # Won't even try to match the regex if we don't have that many bytes
|
||||||
|
},
|
||||||
|
|
||||||
# Catch-all
|
# Catch-all (but better use 'anyprot')
|
||||||
{ name: "regex"; host: "localhost"; port: "443"; regex_patterns: [ "" ]; },
|
{ name: "regex"; host: "localhost"; port: "443"; regex_patterns: [ "" ]; },
|
||||||
|
|
||||||
# Where to connect in case of timeout (defaults to ssh)
|
# Where to connect in case of timeout (defaults to ssh)
|
||||||
|
11
probe.c
11
probe.c
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
# probe.c: Code for probing protocols
|
# probe.c: Code for probing protocols
|
||||||
#
|
#
|
||||||
# Copyright (C) 2007-2015 Yves Rutschle
|
# Copyright (C) 2007-2019 Yves Rutschle
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it
|
# This program is free software; you can redistribute it
|
||||||
# and/or modify it under the terms of the GNU General Public
|
# and/or modify it under the terms of the GNU General Public
|
||||||
@ -360,11 +360,18 @@ int probe_client_protocol(struct connection *cnx)
|
|||||||
|
|
||||||
if (! p->probe) continue;
|
if (! p->probe) continue;
|
||||||
|
|
||||||
|
if (cfg.verbose) fprintf(stderr, "probing for %s\n", p->name);
|
||||||
|
|
||||||
/* Don't probe last protocol if it is anyprot (and store last protocol) */
|
/* Don't probe last protocol if it is anyprot (and store last protocol) */
|
||||||
if ((i == cfg.protocols_len - 1) && (!strcmp(p->name, "anyprot")))
|
if ((i == cfg.protocols_len - 1) && (!strcmp(p->name, "anyprot")))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (cfg.verbose) fprintf(stderr, "probing for %s\n", p->name);
|
if (p->minlength_is_present && (cnx->q[1].deferred_data_size < p->minlength )) {
|
||||||
|
fprintf(stderr, "input too short, %d bytes but need %d\n", cnx->q[1].deferred_data_size , p->minlength);
|
||||||
|
again++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
res = p->probe(cnx->q[1].begin_deferred_data, cnx->q[1].deferred_data_size, p);
|
res = p->probe(cnx->q[1].begin_deferred_data, cnx->q[1].deferred_data_size, p);
|
||||||
if (cfg.verbose) fprintf(stderr, "probed for %s: %s\n", p->name, probe_str[res]);
|
if (cfg.verbose) fprintf(stderr, "probed for %s: %s\n", p->name, probe_str[res]);
|
||||||
|
|
||||||
|
17
sslh-conf.c
17
sslh-conf.c
@ -1,5 +1,5 @@
|
|||||||
/* Generated by conf2struct (https://www.rutschle.net/tech/conf2struct/README)
|
/* Generated by conf2struct (https://www.rutschle.net/tech/conf2struct/README)
|
||||||
* on Sun Jan 27 18:51:35 2019. */
|
* on Sun Feb 3 11:11:15 2019. */
|
||||||
|
|
||||||
#define _GNU_SOURCE
|
#define _GNU_SOURCE
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@ -12,8 +12,6 @@ static void sslhcfg_protocols_init(struct sslhcfg_protocols_item* cfg) {
|
|||||||
cfg->fork = 0;
|
cfg->fork = 0;
|
||||||
cfg->log_level = 1;
|
cfg->log_level = 1;
|
||||||
cfg->keepalive = 0;
|
cfg->keepalive = 0;
|
||||||
cfg->minlength = 0;
|
|
||||||
cfg->maxlength = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sslhcfg_listen_init(struct sslhcfg_listen_item* cfg) {
|
static void sslhcfg_listen_init(struct sslhcfg_listen_item* cfg) {
|
||||||
@ -145,13 +143,10 @@ static int sslhcfg_protocols_parser(
|
|||||||
if (config_setting_lookup_int(cfg, "minlength", &sslhcfg_protocols->minlength) == CONFIG_FALSE) {
|
if (config_setting_lookup_int(cfg, "minlength", &sslhcfg_protocols->minlength) == CONFIG_FALSE) {
|
||||||
*errmsg = "Parsing of option \"minlength\" failed";
|
*errmsg = "Parsing of option \"minlength\" failed";
|
||||||
return 0;
|
return 0;
|
||||||
} ;
|
} else {
|
||||||
}
|
sslhcfg_protocols->minlength_is_present = 1;
|
||||||
if (config_setting_lookup(cfg, "maxlength")) {
|
}
|
||||||
if (config_setting_lookup_int(cfg, "maxlength", &sslhcfg_protocols->maxlength) == CONFIG_FALSE) {
|
;
|
||||||
*errmsg = "Parsing of option \"maxlength\" failed";
|
|
||||||
return 0;
|
|
||||||
} ;
|
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -385,8 +380,6 @@ static void sslhcfg_protocols_print(
|
|||||||
}
|
}
|
||||||
indent(depth);
|
indent(depth);
|
||||||
printf("minlength: %d\n", sslhcfg_protocols->minlength);
|
printf("minlength: %d\n", sslhcfg_protocols->minlength);
|
||||||
indent(depth);
|
|
||||||
printf("maxlength: %d\n", sslhcfg_protocols->maxlength);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sslhcfg_listen_print(
|
static void sslhcfg_listen_print(
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Generated by conf2struct (https://www.rutschle.net/tech/conf2struct/README)
|
/* Generated by conf2struct (https://www.rutschle.net/tech/conf2struct/README)
|
||||||
* on Sun Jan 27 18:51:35 2019. */
|
* on Sun Feb 3 11:11:15 2019. */
|
||||||
|
|
||||||
#ifndef C2S_SSLHCFG_H
|
#ifndef C2S_SSLHCFG_H
|
||||||
#define C2S_SSLHCFG_H
|
#define C2S_SSLHCFG_H
|
||||||
@ -31,8 +31,8 @@ struct sslhcfg_protocols_item {
|
|||||||
const char** alpn_protocols;
|
const char** alpn_protocols;
|
||||||
size_t regex_patterns_len;
|
size_t regex_patterns_len;
|
||||||
const char** regex_patterns;
|
const char** regex_patterns;
|
||||||
|
int minlength_is_present;
|
||||||
int minlength;
|
int minlength;
|
||||||
int maxlength;
|
|
||||||
T_PROBE* probe;
|
T_PROBE* probe;
|
||||||
struct addrinfo* saddr;
|
struct addrinfo* saddr;
|
||||||
void* data;
|
void* data;
|
||||||
|
@ -80,9 +80,7 @@ config: {
|
|||||||
type: "array",
|
type: "array",
|
||||||
element_type: "string"
|
element_type: "string"
|
||||||
},
|
},
|
||||||
{ name: "minlength"; type: "int"; default: 0 },
|
{ name: "minlength"; type: "int"; optional: true },
|
||||||
{ name: "maxlength"; type: "int"; default: 0 },
|
|
||||||
|
|
||||||
|
|
||||||
# Runtime data
|
# Runtime data
|
||||||
{ name: "probe"; type: "runtime"; c_type: "T_PROBE*" },
|
{ name: "probe"; type: "runtime"; c_type: "T_PROBE*" },
|
||||||
|
34
t
34
t
@ -31,11 +31,11 @@ my $SSH_MIX_SSL = 1;
|
|||||||
# coverage, but do not necessarily result in an actual test
|
# coverage, but do not necessarily result in an actual test
|
||||||
# (e.g. some tests need to be run with valgrind to check all
|
# (e.g. some tests need to be run with valgrind to check all
|
||||||
# memory management code).
|
# memory management code).
|
||||||
my $RB_CNX_NOSERVER = 0;
|
my $RB_CNX_NOSERVER = 1;
|
||||||
my $RB_PARAM_NOHOST = 0;
|
my $RB_PARAM_NOHOST = 1;
|
||||||
my $RB_WRONG_USERNAME = 0;
|
my $RB_WRONG_USERNAME = 1;
|
||||||
my $RB_OPEN_PID_FILE = 0;
|
my $RB_OPEN_PID_FILE = 1;
|
||||||
my $RB_RESOLVE_ADDRESS = 0;
|
my $RB_RESOLVE_ADDRESS = 1;
|
||||||
|
|
||||||
`lcov --directory . --zerocounters`;
|
`lcov --directory . --zerocounters`;
|
||||||
|
|
||||||
@ -162,12 +162,10 @@ sub test_probes {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} elsif ($p->{name} eq 'regex') {
|
} elsif ($p->{name} eq 'regex') {
|
||||||
foreach my $pattern (@{$p->{regex_patterns}}) {
|
foreach my $test (@{$p->{test_patterns}}) {
|
||||||
$pattern =~ /(\w+)/;
|
|
||||||
my $out = $1;
|
|
||||||
test_probe(
|
test_probe(
|
||||||
data => $out,
|
data => $test->{pattern},
|
||||||
expected => $p->{name},
|
expected => $test->{result},
|
||||||
%opts
|
%opts
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -199,6 +197,7 @@ foreach my $s (@{$conf->fetch_array("protocols")}) {
|
|||||||
|
|
||||||
|
|
||||||
my @binaries = ('sslh-select', 'sslh-fork');
|
my @binaries = ('sslh-select', 'sslh-fork');
|
||||||
|
|
||||||
for my $binary (@binaries) {
|
for my $binary (@binaries) {
|
||||||
warn "Testing $binary\n";
|
warn "Testing $binary\n";
|
||||||
|
|
||||||
@ -206,10 +205,9 @@ for my $binary (@binaries) {
|
|||||||
my $sslh_pid;
|
my $sslh_pid;
|
||||||
if (!($sslh_pid = fork)) {
|
if (!($sslh_pid = fork)) {
|
||||||
my $user = (getpwuid $<)[0]; # Run under current username
|
my $user = (getpwuid $<)[0]; # Run under current username
|
||||||
#my $cmd = "./$binary -v -f -u $user --listen localhost:$sslh_port --ssh $ssh_address --ssl $ssl_address -P $pidfile";
|
my $cmd = "./$binary -v 3 -f -u $user -Ftest.cfg";
|
||||||
my $cmd = "./$binary -v -f -u $user -Ftest.cfg";
|
|
||||||
verbose_exec $cmd;
|
verbose_exec $cmd;
|
||||||
#exec "valgrind --leak-check=full ./$binary -v -f -u $user --listen localhost:$sslh_port --ssh $ssh_address -ssl $ssl_address -P $pidfile";
|
#exec "valgrind --leak-check=full ./$binary -v 3 -f -u $user --listen localhost:$sslh_port --ssh $ssh_address -ssl $ssl_address -P $pidfile";
|
||||||
exit 0;
|
exit 0;
|
||||||
}
|
}
|
||||||
warn "spawned $sslh_pid\n";
|
warn "spawned $sslh_pid\n";
|
||||||
@ -294,7 +292,7 @@ if ($RB_CNX_NOSERVER) {
|
|||||||
print "***Test: Connecting to non-existant server\n";
|
print "***Test: Connecting to non-existant server\n";
|
||||||
my $sslh_pid;
|
my $sslh_pid;
|
||||||
if (!($sslh_pid = fork)) {
|
if (!($sslh_pid = fork)) {
|
||||||
exec "./sslh-select -v -f -u $user --listen localhost:$sslh_port --ssh localhost:$no_listen --ssl localhost:$no_listen -P $pidfile";
|
exec "./sslh-select -v 3 -f -u $user --listen localhost:$sslh_port --ssh localhost:$no_listen --tls localhost:$no_listen -P $pidfile";
|
||||||
}
|
}
|
||||||
warn "spawned $sslh_pid\n";
|
warn "spawned $sslh_pid\n";
|
||||||
|
|
||||||
@ -327,7 +325,7 @@ if ($RB_PARAM_NOHOST) {
|
|||||||
print "***Test: No hostname in address\n";
|
print "***Test: No hostname in address\n";
|
||||||
my $sslh_pid;
|
my $sslh_pid;
|
||||||
if (!($sslh_pid = fork)) {
|
if (!($sslh_pid = fork)) {
|
||||||
exec "./sslh-select -v -f -u $user --listen $sslh_port --ssh $ssh_address --ssl $ssl_address -P $pidfile";
|
exec "./sslh-select -v 3 -f -u $user --listen $sslh_port --ssh $ssh_address --tls $ssl_address -P $pidfile";
|
||||||
}
|
}
|
||||||
warn "spawned $sslh_pid\n";
|
warn "spawned $sslh_pid\n";
|
||||||
waitpid $sslh_pid, 0;
|
waitpid $sslh_pid, 0;
|
||||||
@ -341,7 +339,7 @@ if ($RB_WRONG_USERNAME) {
|
|||||||
print "***Test: Changing to non-existant username\n";
|
print "***Test: Changing to non-existant username\n";
|
||||||
my $sslh_pid;
|
my $sslh_pid;
|
||||||
if (!($sslh_pid = fork)) {
|
if (!($sslh_pid = fork)) {
|
||||||
exec "./sslh-select -v -f -u ${user}_doesnt_exist --listen localhost:$sslh_port --ssh $ssh_address --ssl $ssl_address -P $pidfile";
|
exec "./sslh-select -v 3 -f -u ${user}_doesnt_exist --listen localhost:$sslh_port --ssh $ssh_address --tls $ssl_address -P $pidfile";
|
||||||
}
|
}
|
||||||
warn "spawned $sslh_pid\n";
|
warn "spawned $sslh_pid\n";
|
||||||
waitpid $sslh_pid, 0;
|
waitpid $sslh_pid, 0;
|
||||||
@ -355,7 +353,7 @@ if ($RB_OPEN_PID_FILE) {
|
|||||||
print "***Test: Can't open PID file\n";
|
print "***Test: Can't open PID file\n";
|
||||||
my $sslh_pid;
|
my $sslh_pid;
|
||||||
if (!($sslh_pid = fork)) {
|
if (!($sslh_pid = fork)) {
|
||||||
exec "./sslh-select -v -f -u $user --listen localhost:$sslh_port --ssh $ssh_address --ssl $ssl_address -P /dont_exist/$pidfile";
|
exec "./sslh-select -v 3 -f -u $user --listen localhost:$sslh_port --ssh $ssh_address --tls $ssl_address -P /dont_exist/$pidfile";
|
||||||
# You don't have a /dont_exist/ directory, do you?!
|
# You don't have a /dont_exist/ directory, do you?!
|
||||||
}
|
}
|
||||||
warn "spawned $sslh_pid\n";
|
warn "spawned $sslh_pid\n";
|
||||||
@ -371,7 +369,7 @@ if ($RB_RESOLVE_ADDRESS) {
|
|||||||
my $sslh_pid;
|
my $sslh_pid;
|
||||||
if (!($sslh_pid = fork)) {
|
if (!($sslh_pid = fork)) {
|
||||||
my $user = (getpwuid $<)[0]; # Run under current username
|
my $user = (getpwuid $<)[0]; # Run under current username
|
||||||
exec "./sslh-select -v -f -u $user --listen blahblah.dontexist:9000 --ssh $ssh_address --ssl $ssl_address -P $pidfile";
|
exec "./sslh-select -v 3 -f -u $user --listen blahblah.dontexist:9000 --ssh $ssh_address --tls $ssl_address -P $pidfile";
|
||||||
}
|
}
|
||||||
warn "spawned $sslh_pid\n";
|
warn "spawned $sslh_pid\n";
|
||||||
waitpid $sslh_pid, 0;
|
waitpid $sslh_pid, 0;
|
||||||
|
10
test.cfg
10
test.cfg
@ -31,7 +31,15 @@ protocols:
|
|||||||
{ 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: "regex"; host: "localhost"; port: "9011";
|
{ name: "regex"; host: "localhost"; port: "9011";
|
||||||
regex_patterns: [ "^foo", "^bar" ];
|
regex_patterns: [ "^foo", "^bar" ];
|
||||||
|
minlength: 4;
|
||||||
|
test_patterns: (
|
||||||
|
{ pattern: "foo"; result: "ssh"; }, # After timeout
|
||||||
|
{ pattern: "fooo"; result: "regex"; },
|
||||||
|
{ pattern: "bar"; result: "ssh"; },
|
||||||
|
{ pattern: "barr"; result: "regex"; },
|
||||||
|
{ pattern: "barrrr"; result: "regex"; }
|
||||||
|
);
|
||||||
},
|
},
|
||||||
{ name: "tls"; host: "localhost"; port: "9021"; alpn_protocols: [ "alpn1", "alpn2" ]; sni_hostnames: [ "sni1" ]; },
|
{ name: "tls"; host: "localhost"; port: "9021"; alpn_protocols: [ "alpn1", "alpn2" ]; sni_hostnames: [ "sni1" ]; },
|
||||||
{ name: "tls"; host: "localhost"; port: "9022"; alpn_protocols: [ "alpn1", "alpn2" ]; sni_hostnames: [ "sni2", "sni3" ]; },
|
{ name: "tls"; host: "localhost"; port: "9022"; alpn_protocols: [ "alpn1", "alpn2" ]; sni_hostnames: [ "sni2", "sni3" ]; },
|
||||||
|
Loading…
x
Reference in New Issue
Block a user