• Infrastructure / AI / MCP
Using eBPF + MCP to let agents record HTTPs traffic
Agents make network calls. Recording that traffic without changing the TLS fingerprint or installing a CA means going below the application layer. eBPF + MCP lets an agent attach to OpenSSL host-wide via uprobes, capt...
Source code: github.com/yuval1024/ebpf-https-capture-with-mcp
Agents make network calls. What if we want to record the traffic?
Two common approaches, and the friction each one carries:
- Inject JavaScript into the browser to record traffic. Application-layer change, required per browser; also harder with Chrome Manifest V3.
- MITM (mitmproxy is the standard one). Terminates the connection and opens a new one — changes the TLS fingerprint. Also requires installing a custom CA in the system.
Solution — eBPF (and wrap with MCP)
eBPF is passive. It listens to traffic by attaching to OpenSSL functions before encryption and after decryption — OpenSSL’s SSL_write (just before encrypt) and SSL_read (just after decrypt). Nothing changes on the wire.
This is what gojue/ecapture does:
- Passive — the real client does not change TLS fingerprint.
- System-wide — captures all processes on the host that use libssl (with caveats below).
- No CA install required.
Adding MCP for agent-native communication
We wrap ecapture in an MCP server so agents can drive capture as tool calls instead of CLI invocations. Code: github.com/yuval1024/ebpf-https-capture-with-mcp.

The agent gets tools like:
capture_start/capture_stop/capture_statuslist_domains,list_requests,get_request,get_pairs,searchwatch_domain— subscribe to a domain so its traffic is persisted
Capture is host-wide, but subscriptions decide what gets saved, which reduces load on the ring buffer. We don’t want to bloat the buffer — only specific events get persisted.
Problems with eBPF
- Doesn’t always work.
- Captures only HTTPs. Plain HTTP is invisible because it doesn’t go through SSL libs.
- Requires root permissions / a running daemon.
Extending eBPF for stripped binaries — using function signatures (theory only)
We can try to extend eBPF coverage to other TLS implementations. For example:
- Go
crypto/tls— an entirely separate TLS implementation in the Go runtime. - BoringSSL (Chrome, Node.js) — an OpenSSL fork, frequently statically linked and stripped.
- Stripped and static binaries in general.
The method is creating “fingerprints” for the relevant functions. Borrowing from reverse engineering (IDA FLIRT, YARA rules, AV signatures): a function’s machine code is fairly stable across builds — except for the bytes that vary (relative addresses, relocations, immediates). So you build a masked byte signature: the function’s prologue as a byte pattern with the volatile bytes wildcarded.
This is relevant only if usage volume is high enough to justify the effort. Sample scenario:
- Harness for compiling many solutions × SSL libs × build flags, with symbols on, to learn the variant space.
-
Write a fingerprint for the relevant functions. Example:
# `??` masks the bytes that change build-to-build (call targets, offsets). signature = [55, 48, 89, e5, e8, ??, ??, ??, ??, 48, 8b, ??, ??, ??, ??, ??, c3] - Data structure for searching signatures, e.g. MinHash (Mining of Massive Datasets, Ch. 3).
- Scan running targets for matching offsets and attach uprobes; cache
sha256(file) → offsetsso we don’t re-scan.
Other alternatives
- “Smart” MITM that preserves the SSL fingerprint. Current MITM solutions replace the SSL stack. We should preserve it — bundle OpenSSL, BoringSSL, and maybe even wolfSSL 😅 — and have the client pick the matching SSL version.
- Signature-based scanning for stripped binaries, as above.