mirror of
https://github.com/yrutschle/sslh.git
synced 2025-04-13 07:37:15 +03:00
new probing algorithm
This commit is contained in:
parent
b6db83a701
commit
677e385fec
17
ChangeLog
17
ChangeLog
@ -1,3 +1,20 @@
|
||||
vNEXT:
|
||||
New probing method:
|
||||
Before, probes were tried in order, repeating on the
|
||||
same probe as long it returned PROBE_AGAIN before
|
||||
moving to the next one. This means a probe which
|
||||
requires a lot of data (i.e. returne PROBE_AGAIN for
|
||||
a long time) could prevent sucessful matches from
|
||||
subsequent probes. The configuration file needed to
|
||||
take that into account.
|
||||
|
||||
Now, all probes are tried each time new data is
|
||||
found. If any probe matches, use it. If at least one
|
||||
probe requires more data, wait for more. If all
|
||||
probes failed, connect to the last one. So the only
|
||||
thing to know when writing the configuration file is
|
||||
that 'anyprot' needs to be last.
|
||||
|
||||
v1.19: 20JAN2018
|
||||
Added 'syslog_facility' configuration option to
|
||||
specify where to log.
|
||||
|
67
probe.c
67
probe.c
@ -180,13 +180,16 @@ static int is_tinc_protocol( const char *p, int len, struct proto *proto)
|
||||
* */
|
||||
static int is_xmpp_protocol( const char *p, int len, struct proto *proto)
|
||||
{
|
||||
if (memmem(p, len, "jabber", 6))
|
||||
return PROBE_MATCH;
|
||||
|
||||
/* sometimes the word 'jabber' shows up late in the initial string,
|
||||
sometimes after a newline. this makes sure we snarf the entire preamble
|
||||
and detect it. (fixed for adium/pidgin) */
|
||||
if (len < 50)
|
||||
return PROBE_AGAIN;
|
||||
|
||||
return memmem(p, len, "jabber", 6) ? 1 : 0;
|
||||
return PROBE_NEXT;
|
||||
}
|
||||
|
||||
static int probe_http_method(const char *p, int len, const char *opt)
|
||||
@ -372,8 +375,8 @@ static int regex_probe(const char *p, int len, struct proto *proto)
|
||||
int probe_client_protocol(struct connection *cnx)
|
||||
{
|
||||
char buffer[BUFSIZ];
|
||||
struct proto *p;
|
||||
int n;
|
||||
struct proto *p, *last_p;
|
||||
int n, res, again = 0;
|
||||
|
||||
n = read(cnx->q[0].fd, buffer, sizeof(buffer));
|
||||
/* It's possible that read() returns an error, e.g. if the client
|
||||
@ -382,40 +385,40 @@ int probe_client_protocol(struct connection *cnx)
|
||||
* function does not have to deal with a specific failure condition (the
|
||||
* connection will just fail later normally). */
|
||||
|
||||
/* Dump hex values of the packet */
|
||||
if (verbose>1) {
|
||||
fprintf(stderr, "hexdump of incoming packet:\n");
|
||||
hexdump(buffer, n);
|
||||
}
|
||||
|
||||
if (n > 0) {
|
||||
int res = PROBE_NEXT;
|
||||
|
||||
defer_write(&cnx->q[1], buffer, n);
|
||||
|
||||
for (p = cnx->proto; p && res == PROBE_NEXT; p = p->next) {
|
||||
char* probe_str[3] = {"PROBE_NEXT",
|
||||
"PROBE_MATCH",
|
||||
"PROBE_AGAIN"};
|
||||
if (! p->probe) continue;
|
||||
if (verbose) fprintf(stderr, "probing for %s...", p->description);
|
||||
|
||||
cnx->proto = p;
|
||||
res = p->probe(cnx->q[1].begin_deferred_data, cnx->q[1].deferred_data_size, p);
|
||||
if (verbose) fprintf(stderr, "%s\n", probe_str[res]);
|
||||
if (verbose > 1) {
|
||||
fprintf(stderr, "hexdump of incoming packet:\n");
|
||||
hexdump(buffer, n);
|
||||
}
|
||||
if (res != PROBE_NEXT)
|
||||
return res;
|
||||
defer_write(&cnx->q[1], buffer, n);
|
||||
}
|
||||
|
||||
if (verbose)
|
||||
fprintf(stderr,
|
||||
"all probes failed, connecting to first protocol: %s\n",
|
||||
protocols->description);
|
||||
for (p = cnx->proto; p; p = p->next) {
|
||||
char* probe_str[3] = {"PROBE_NEXT", "PROBE_MATCH", "PROBE_AGAIN"};
|
||||
if (! p->probe) continue;
|
||||
|
||||
/* If none worked, return the first one affected (that's completely
|
||||
* arbitrary) */
|
||||
cnx->proto = protocols;
|
||||
/* Don't probe last protocol if it is anyprot (and store last protocol) */
|
||||
if (! p->next) {
|
||||
last_p = p;
|
||||
if (!strcmp(p->description, "anyprot"))
|
||||
break;
|
||||
}
|
||||
|
||||
res = p->probe(cnx->q[1].begin_deferred_data, cnx->q[1].deferred_data_size, p);
|
||||
if (verbose) fprintf(stderr, "probing for %s: %s\n", p->description, probe_str[res]);
|
||||
|
||||
if (res == PROBE_MATCH) {
|
||||
cnx->proto = p;
|
||||
return PROBE_MATCH;
|
||||
}
|
||||
if (res == PROBE_AGAIN)
|
||||
again++;
|
||||
}
|
||||
if (again)
|
||||
return PROBE_AGAIN;
|
||||
|
||||
/* Everything failed: match the last one */
|
||||
cnx->proto = last_p;
|
||||
return PROBE_MATCH;
|
||||
}
|
||||
|
||||
|
6
t
6
t
@ -70,7 +70,7 @@ sub test_probes {
|
||||
'tinc' => { data => "0 hello" },
|
||||
'xmpp' => {data => "I should get a real jabber connection initialisation here" },
|
||||
'adb' => { data => "CNXN....................host:..." },
|
||||
'anyprot' => {data => "hello, this needs to be longer than the longest probe that returns PROBE_AGAIN" },
|
||||
'anyprot' => {data => "hello anyprot this needs to be longer than xmpp and adb which expect about 50 characters, which I all have to write before the timeout!" },
|
||||
);
|
||||
|
||||
my $cnx = new IO::Socket::INET(PeerHost => "localhost:$sslh_port");
|
||||
@ -94,8 +94,8 @@ sub test_probes {
|
||||
print "Received: protocol $prefix data [$data]\n";
|
||||
close $cnx;
|
||||
|
||||
is($prefix, $p->{name});
|
||||
is($data, $protocols{$p->{name}}->{data});
|
||||
is($prefix, $p->{name}, "probe $p->{name} connected correctly");
|
||||
is($data, $protocols{$p->{name}}->{data}, "data shoveled correctly");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user