Skip to content

Tap/raw recorder#1

Open
krowd3v wants to merge 4 commits into
masterfrom
tap/raw-recorder
Open

Tap/raw recorder#1
krowd3v wants to merge 4 commits into
masterfrom
tap/raw-recorder

Conversation

@krowd3v
Copy link
Copy Markdown
Owner

@krowd3v krowd3v commented May 1, 2026

No description provided.

krowd3v added 2 commits May 1, 2026 19:23
Adds opt-in byte-level recording to the generic TCP forwarder. A recorder
configured with `record: recorder.service.handler.raw` (new constant) is
wired through a recorderConn wrapper — same pattern as handler/serial —
that emits one record per Read/Write with the standard Direction /
Hexdump / TimestampFormat options from the core recorder.Options struct.

Use case: plaintext protocols that GOST's sniffer doesn't recognize
(WHOIS, DNS-over-TCP, port-43 registry protocols) can now be captured
through the existing recorder pipeline without a protocol-specific
handler fork and without client-side instrumentation.

Coexists with the default recorder.service.handler (one JSON per
request with route/duration/bytes). A service can attach both: raw
for payload, handler for metadata.

Files:
- recorder/recorder.go            +1 const RecorderServiceHandlerRaw
- handler/forward/local/conn.go   +new recorderConn (mirror of
                                   handler/serial/conn.go pattern)
- handler/forward/local/handler.go
    - new rawRecorder field on forwardHandler
    - Init picks up the new record type
    - Handle wraps the incoming conn when rawRecorder is set
Three small enhancements on top of the raw-bytes recorder patch.

listener/grpc:
- New metadata key `grpc.maxStreams` / `maxStreams` (uint). When set,
  passes `grpc.MaxConcurrentStreams(n)` to the embedded grpc.NewServer.
  grpc-go default is math.MaxUint32 (unlimited) but the server does
  not advertise that in SETTINGS, so clients brief-cap at 100 streams
  until the first settings frame arrives (http2_client.go:349). Setting
  this explicitly makes the server advertise, eliminating the transient
  cap for the first ~RTT after a ClientConn is established.

- Unix domain socket support. `addr: unix:///tmp/foo.sock` or `addr:
  /path/to.sock` / `addr: ./path.sock` switches the listener's network
  to "unix" instead of "tcp". Stale socket files are removed before
  bind, matching other GOST unix-capable listeners. Saves ~20% syscall
  overhead vs loopback TCP at high message rates.

handler/forward/local (raw recorder):
- Embed the session id (SID, same one used in the meta
  recorder.service.handler JSON) in every raw record emitted by the
  wrapped recorderConn. Prefix format:

      sid:<sid>\n
      <direction>[timestamp]\n   (optional, per Options)
      <payload>                  (raw bytes or hex.Dump)

  The SID lets the receiver join raw-byte records with the parent
  metadata record server-side without relying on timestamp-window or
  proxy-node heuristics. Backward compatible: when SID is empty the
  prefix line is omitted.
@krowd3v krowd3v force-pushed the tap/raw-recorder branch 2 times, most recently from a82c001 to 113f4a0 Compare May 1, 2026 17:38
Extends the raw-recorder preamble so every record self-describes: a
receiver can persist a complete row keyed by sid without cross-referring
to the sibling meta record.

Record format (all context lines optional; appear only when known):

    sid:<sid>\n                  session id (matches meta record sid)
    route:<route>\n              proxy-<hash>@<ip>:<port> > <target>
                                 (same string as meta record route)
    svc:<name>\n                 GOST service name
    <direction>[timestamp]\n     direction + optional fmt timestamp
    <payload>                    raw bytes (or hex.Dump)

route is the most useful addition: it identifies which proxy node the
chain selected for THIS request, inline, so a sink can attribute bytes
to a proxy without joining a meta record first.

The route is pushed into the wrapper by the handler after Router.Dial
resolves the chain (ro.Route is already computed there for the meta
record -- same string, zero extra work).

Backward-compatible: fields without a known value are simply omitted;
no new metadata knobs to configure.
@krowd3v krowd3v force-pushed the tap/raw-recorder branch from 113f4a0 to c560cf1 Compare May 1, 2026 18:04
@krowd3v krowd3v marked this pull request as ready for review May 1, 2026 19:10
@krowd3v
Copy link
Copy Markdown
Owner Author

krowd3v commented May 1, 2026

@codex review

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c560cf1537

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines 62 to +66
for _, ro := range h.options.Recorders {
if ro.Record == xrecorder.RecorderServiceHandler {
switch ro.Record {
case xrecorder.RecorderServiceHandler:
h.recorder = ro
break
case xrecorder.RecorderServiceHandlerRaw:
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve first matching handler recorder selection

This loop no longer stops after finding recorder.service.handler, so the last matching entry now overwrites earlier ones. Other handlers in this repo keep first-match behavior (break on first match), so configs with multiple handler recorder entries will silently change which sink receives service metadata after this commit. That regression is hard to detect and can redirect records to the wrong backend.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant