Skip to content

feat(proxy): Oracle session TNS dump capture#78

Merged
fclairamb merged 15 commits intomainfrom
feat/oracle-session-dump
Apr 4, 2026
Merged

feat(proxy): Oracle session TNS dump capture#78
fclairamb merged 15 commits intomainfrom
feat/oracle-session-dump

Conversation

@fclairamb
Copy link
Copy Markdown
Owner

Summary

  • Add binary dump file capture of raw TNS packet traffic for Oracle proxy sessions
  • New DumpWriter/DumpReader in internal/proxy/oracle/dump.go with full round-trip tests
  • Configuration via DBB_ORACLE_DUMP_DIR, DBB_ORACLE_DUMP_MAX_SIZE, DBB_ORACLE_DUMP_RETENTION
  • API endpoints: GET /connections/:uid/dump (download) and DELETE /connections/:uid/dump (admin delete)
  • Periodic cleanup of old dumps based on retention config
  • Python replay script (scripts/replay_dump.py) for offline analysis

Test plan

  • 6 new unit tests for dump writer/reader (header, write, max size, round-trip, invalid file, cleanup)
  • All 790 existing tests pass
  • go vet clean
  • Deploy with DBB_ORACLE_DUMP_DIR set, connect Oracle client, verify dump files created
  • Download dump via API, verify with replay script

🤖 Generated with Claude Code

fclairamb and others added 14 commits April 4, 2026 20:56
- Multi-row: rows now captured correctly (0x07 separator between rows,
  0x08 footer detection)
- Multi-column: limit column name scanning to area before 0x06 0x22
  marker, eliminating false positive column names from row data
- DATE type: decode Oracle DATE (7 bytes) to YYYY-MM-DD HH:MM:SS
- Single-column multi-row: fix premature pendingQuery completion by
  not completing queries from legacy Response handler (0x08) which
  fires during auth negotiation
- NULL values: properly shown as empty string (0x00 length byte)
- Column names: require minimum 2 chars to avoid false positives

Tested with 7 query patterns against Oracle 19c on abynonprod:
all produce correct column names, multiple rows, and decoded values.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The connect data offset in TNS Connect packets is from the start of the
full packet (including 8-byte header), not from the payload start.
Subtract tnsHeaderSize when indexing into the payload.

This fixes DBeaver/JDBC thick driver connections returning 'database
not found' because SERVICE_NAME was read from the wrong offset.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Try both interpretations of the connect data offset:
1. Raw offset (works for v315+ thin client with extended data)
2. Offset minus header size (works for JDBC thick with inline data)

Validate by checking if the extracted string contains DESCRIPTION
or SERVICE_NAME keywords.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace fixed-offset SQL extraction with scanning approach:
1. Scan offsets 40-70 for length-prefixed SQL strings
2. Fallback: find SQL keywords (SELECT, INSERT, etc.) directly in payload
3. Extract SQL text until end of printable ASCII

Fixes JDBC thin driver SQL appearing as 'ELECT' (offset 54 vs 50),
and supports go-ora which uses yet another offset.

Tested with all 3 client types through local proxy:
- Python oracledb thin: SELECT 42 → {ANSWER: 42}
- JDBC thin (ojdbc11): SELECT 1 → logged correctly
- Go go-ora: SELECT 42 → logged correctly

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Stream rows directly to database as they arrive (no memory buffering)
- Create query record eagerly when SQL is intercepted
- Capture rows from continuation packets (func=0x06) in multi-packet results
- Detect end-of-data (ORA-01403) across any response packet
- Robust SQL extraction scanning offsets 40-70 + keyword fallback
- Update query record with duration on completion

Tested: 117-row result set captures 49 rows (first+continuation packets).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Binary packet capture per session for offline replay and TTC parser
development. Includes dump writer/reader, REST API for download,
Python replay script, configurable retention, and max size cap.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
CLAUDE.md: update description, add Oracle proxy to stack/structure,
add DBB_LISTEN_ORA env var, update connection flow diagram.

docs/oracle.md: comprehensive TNS/TTC protocol documentation covering
v315+ packet format (4-byte length), TTC function codes, piggyback
sub-operations, SQL extraction offsets per client, result row format,
Oracle NUMBER/DATE encoding, multi-packet results, and known limitations.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Binary dump format captures raw TNS packet traffic for offline replay
and analysis. Includes DumpWriter, DumpReader, and CleanupOldDumps.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
New env vars: DBB_ORACLE_DUMP_DIR, DBB_ORACLE_DUMP_MAX_SIZE,
DBB_ORACLE_DUMP_RETENTION.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Captures raw TNS packets in both directions during relay. Dump writer
is initialized after upstream connection, closed on session cleanup.
Periodic cleanup goroutine removes old dumps based on retention config.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
GET /connections/:uid/dump - download raw TNS dump (admin/viewer)
DELETE /connections/:uid/dump - delete dump file (admin only)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Python script for analyzing .dbbat-dump files. Updated CLAUDE.md
with DBB_ORACLE_DUMP_* environment variable documentation.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@fclairamb fclairamb enabled auto-merge (squash) April 4, 2026 22:24
- Check error returns on f.Close() and os.Remove()
- Add t.Parallel() to all test functions
- Use assert.GreaterOrEqual instead of assert.True for comparisons
- Use defer func() { _ = r.Close() }() pattern

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@fclairamb fclairamb merged commit 7e0b45a into main Apr 4, 2026
6 checks passed
@fclairamb fclairamb deleted the feat/oracle-session-dump branch April 4, 2026 22:32
@fclairamb fclairamb mentioned this pull request Apr 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant