* fix(tcp): stop the read-deadline re-arm from swallowing a cancelled ctx
the cancel watchdog trips conn.SetDeadline(now) once. if that trip
lands while the probe write is still in flight, readTCP's later
SetReadDeadline(now+timeout) call silently overwrote it, so the read
blocked for the full timeout instead of returning promptly. thread
ctx into readTCP and check it before arming the deadline and on every
read iteration so a cancellation already in flight aborts immediately.
* test(tcp): make the cancel-during-write test exercise the actual race
the old test cancelled ctx before calling ExecuteTCPModule, so the
pre-write ctx.Err() guard returned immediately and the test never
reached readTCP at all; reverting the fix and rerunning it still
passed in ~0ms. cancel from a goroutine mid-write instead, so the
watchdog trips the deadline while readTCP is the next call on the
path, and assert the call returns promptly rather than blocking for
the full timeout. also add a case proving a legitimately slow but
uncancelled connection still completes and matches normally.
* feat(modules): tcp module executor
dial+probe+banner with word/regex/size matchers, ctx-honest watcher,
port required.
* feat(modules): add redis unauthenticated access tcp module
first shipped tcp module: sends INFO to redis (6379) and matches
redis_version in the reply, which an auth-required server never returns
(it answers -NOAUTH). extracts the leaked version.
* docs(modules): document the tcp module type
flip the http-only note and add a tcp config section (port, data,
word/regex/size matchers and regex extractors against the banner),
pointing at the redis demo module.
* feat(modules): support matchers-condition in tcp modules
tcp matchers were and-only; add the matchers-condition key (and default,
or) mirroring the http executor's checkMatchers, validated at load via the
shared validateMatchersCondition. documents the override in the combining
matchers section.
* feat(modules): decode escape sequences in tcp data payloads
decode C-style escapes (\\ \a \b \f \n \r \t \v \xHH) in a tcp module's
data value before it goes on the wire, so a single-quoted or plain yaml
scalar reaches the service with the same control bytes a double-quoted
one already would. an unrecognized escape is kept verbatim so no bytes
are silently lost.
* feat(modules): add tcp recon modules for common services
add five built-in tcp modules alongside the redis one so the executor
ships a real service set: memcached (unauth version probe), ssh and ftp
(passive banner version disclosure), mysql/mariadb (handshake exposure,
matched with matchers-condition: or across both auth plugin names), and
vnc (rfb handshake exposure). each fingerprint tracks the documented
on-wire protocol and pulls the version into an extractor.
* feat(modules): add mail and rsync tcp recon modules
add four more passive-banner tcp modules: smtp, pop3, and imap read the
greeting each mail service sends on connect (the smtp matcher requires
an esmtp/smtp marker so it does not fire on a bare 220 ftp greeting),
and rsync detects an exposed daemon by its @RSYNCD handshake. each pulls
the banner or protocol version into an extractor.