TLS/SSL Capture Modules
Relevant source files
The following files were used as context for generating this wiki page:
Purpose and Scope
This page provides an overview of eCapture's TLS/SSL capture capabilities across multiple encryption libraries. TLS/SSL capture modules use eBPF uprobes to intercept encryption library functions and extract plaintext data or TLS handshake secrets without requiring CA certificates, application modifications, or library recompilation.
eCapture supports four major TLS/SSL library families through dedicated modules:
| Module | CLI Command | Supported Libraries | Version Coverage |
|---|---|---|---|
| OpenSSL | ecapture tls | OpenSSL, LibreSSL, BoringSSL | OpenSSL 1.0.2-3.5.x, BoringSSL Android 12-16 |
| Go TLS | ecapture gotls | Go crypto/tls | Go 1.8+ (all versions) |
| GnuTLS | ecapture gnutls | GnuTLS | 3.x series |
| NSS/NSPR | ecapture nss | Mozilla NSS | NSS 3.x series |
All modules share the IModule interface user/module/imodule.go:47-75 and implement three capture modes:
- Text Mode: Real-time plaintext output with HTTP/HTTP2 parsing
- PCAP Mode: Network packets saved to PCAP-NG files with embedded secrets
- Keylog Mode: TLS master secrets in SSLKEYLOGFILE format
Sub-Section Navigation:
- OpenSSL/BoringSSL implementation details: See page 3.1.1
- Go TLS implementation and ABI handling: See page 3.1.3
- GnuTLS and NSS implementations: See page 3.1.4
- TLS 1.2/1.3 master secret extraction: See page 3.1.5
Sources: user/module/imodule.go:47-75, README.md:36-43, cli/cmd/root.go:80-113 </old_str>
<old_str>
Three Capture Modes Overview
Diagram: TLS Module Capture Pipeline by Mode
Sources: user/module/probe_openssl.go:58-76, user/module/probe_openssl.go:128-154, user/module/probe_openssl.go:280-350, user/config/iconfig.go:73-79 </old_str>
<new_str>
Supported Libraries and Versions
eCapture provides comprehensive TLS/SSL capture across multiple library implementations. Each module automatically detects library versions and selects appropriate eBPF bytecode with version-specific structure offsets.
Version Coverage by Library
OpenSSL Module (ecapture tls):
- OpenSSL 1.0.2a-u: 26 versions grouped into shared bytecode
- OpenSSL 1.1.0a-l: 12 versions with standard hooks
- OpenSSL 1.1.1a-w: Common bytecode across patch versions
- OpenSSL 3.0.0-3.0.15: Support for
ssl_connection_ststructure - OpenSSL 3.1.0-3.5.4: Latest stable releases
- LibreSSL: Uses OpenSSL 1.1.1 compatible bytecode
- BoringSSL Android 12-16: Version-specific offsets per Android release
Go TLS Module (ecapture gotls):
- Go 1.8-1.16: Stack-based ABI calling convention
- Go 1.17+: Register-based ABI calling convention
- Auto-detects Go version from binary metadata
GnuTLS Module (ecapture gnutls):
- GnuTLS 3.x series: Full data and keylog support
NSS/NSPR Module (ecapture nss):
- NSS 3.x series: Used by Firefox and NSS-based applications
Platform Support Matrix
| Architecture | Kernel Requirement | Supported Modules |
|---|---|---|
| Linux x86_64 | 4.18+ | All modules |
| Linux aarch64 | 5.5+ | All modules |
| Android x86_64 | Android 12+ | OpenSSL (BoringSSL) |
| Android aarch64 | Android 12+ | OpenSSL (BoringSSL) |
Sources: README.md:14-16, CHANGELOG.md:1-45, user/module/probe_openssl.go:178-278
Supported TLS/SSL Libraries
eCapture supports multiple TLS/SSL library implementations through dedicated modules. Each module uses eBPF uprobes to intercept encryption library functions and extract plaintext data or master secrets.
| Module Name | Supported Libraries | Version Coverage | Platform Support |
|---|---|---|---|
tls | OpenSSL, LibreSSL, BoringSSL | OpenSSL 1.0.2 - 3.5.x BoringSSL Android 12-16 | Linux x86_64/aarch64 Android |
gotls | Go crypto/tls | Go 1.8+ (all versions) | Linux x86_64/aarch64 |
gnutls | GnuTLS | 3.x series | Linux x86_64/aarch64 |
nss | NSS/NSPR (Firefox, Chrome) | NSS 3.x series | Linux x86_64/aarch64 |
Sources: README.md:38-42, CHANGELOG.md:202-204, cli/cmd/root.go:152-161
Capture Modes
All TLS/SSL modules support three operational modes that determine how captured data is processed and output. The mode is selected via the -m command-line flag.
Mode Configuration and Behavior
The capture mode is controlled by the TlsCaptureModelType enumeration user/module/probe_openssl.go:58-64 and configured via the -m CLI flag:
| Mode | CLI Flag | eBPF Program Type | Primary Use Case |
|---|---|---|---|
| Text | -m text (default) | TlsCaptureModelTypeText | Real-time monitoring and debugging |
| PCAP | -m pcap or -m pcapng | TlsCaptureModelTypePcap | Network analysis in Wireshark |
| Keylog | -m keylog or -m key | TlsCaptureModelTypeKeylog | TLS key extraction for external tools |
Text Mode Characteristics:
- Captures plaintext data from
SSL_read/SSL_writecalls - Events flow through
EventProcessorwith HTTP/HTTP2 parsing - Output format: Structured text with parsed protocol headers
- Real-time console output or file logging
- Command:
sudo ecapture tls -m text
PCAP Mode Characteristics:
- Combines uprobe data capture with TC (Traffic Control) packet capture
- Generates PCAP-NG files with Decryption Secrets Block (DSB)
- Supports PCAP filter expressions for packet filtering
- Requires network interface specification via
-iflag - Output compatible with Wireshark, tshark, tcpdump
- Command:
sudo ecapture tls -m pcap -i eth0 --pcapfile=capture.pcapng
Keylog Mode Characteristics:
- Extracts TLS handshake secrets only (no data capture)
- Outputs SSLKEYLOGFILE format compatible with Wireshark
- Supports both TLS 1.2 (single master secret) and TLS 1.3 (multiple derived secrets)
- Can be used with live
tsharkfor real-time decryption - Command:
sudo ecapture tls -m keylog --keylogfile=keys.log
Mode Selection Implementation:
The mode is set during MOpenSSLProbe.Init() user/module/probe_openssl.go:128-154:
switch modConfig.Model {
case config.TlsCaptureModelKeylog, config.TlsCaptureModelKey:
m.eBPFProgramType = TlsCaptureModelTypeKeylog
m.keylogger = os.OpenFile(keylogFile, ...)
case config.TlsCaptureModelPcap, config.TlsCaptureModelPcapng:
m.eBPFProgramType = TlsCaptureModelTypePcap
m.tcPacketsChan = make(chan *TcPacket, 2048)
default:
m.eBPFProgramType = TlsCaptureModelTypeText
}The selected mode determines which setupManagers*() function is called in Start() user/module/probe_openssl.go:284-299.
Sources: user/module/probe_openssl.go:58-76, user/module/probe_openssl.go:128-154, user/module/probe_openssl.go:284-299, user/config/iconfig.go:73-79
Module Architecture
High-Level Component Interaction
Diagram: TLS Module Architecture with Code Entities
Sources: cli/cmd/root.go:249-403, user/module/probe_openssl.go:83-106, user/module/probe_openssl.go:109-176, user/module/probe_openssl.go:280-350
Connection Tracking System
The TLS modules maintain connection state through two synchronized maps in MOpenSSLProbe:
Primary Data Structures:
pidConns: map[PID]map[FD]ConnInfo
├─ Purpose: Forward lookup PID+FD → network tuple
└─ Used by: dumpSslData() to correlate SSL events with connections
sock2pidFd: map[socket_address][PID, FD]
├─ Purpose: Reverse lookup for cleanup operations
└─ Used by: DestroyConn() when socket closes
masterKeys: map[hex_client_random]bool
├─ Purpose: Deduplicate TLS master secrets
└─ Used by: saveMasterSecret() to prevent redundant keylog entriesConnection Lifecycle Operations:
| Operation | Trigger Event | Function | Behavior |
|---|---|---|---|
| Create | ConnDataEvent (IsDestroy=0) | AddConn() line 398 | Populates both maps with tuple, socket info |
| Lookup | SSLDataEvent | GetConn() line 464 | Returns ConnInfo for tuple association |
| Schedule Destroy | ConnDataEvent (IsDestroy=1) | DelConn() line 455 | Sets 3-second timer for cleanup |
| Execute Destroy | Timer expiration | DestroyConn() line 418 | Removes from both maps, notifies EventProcessor |
Thread Safety: All operations acquire pidLocker mutex user/module/probe_openssl.go:94 before map access.
Sources: user/module/probe_openssl.go:83-106, user/module/probe_openssl.go:398-481
Architecture Overview
Module Initialization and Configuration Flow
Diagram: TLS Module Initialization with Code Entity Details
Sources: cli/cmd/root.go:249-403, user/module/probe_openssl.go:109-176, user/module/probe_openssl.go:280-350, user/module/imodule.go:47-75, user/module/imodule.go:236-262
Automatic Version Detection
TLS modules automatically detect the target library version and select compatible eBPF bytecode with correct structure offsets. This enables support for multiple OpenSSL, BoringSSL, GnuTLS, and Go versions without user intervention.
Version Detection and Bytecode Selection Flow
Diagram: Library Version Detection Pipeline
Detection Methods:
ELF Parsing:
detectOpenssl()user/module/probe_openssl.go:207 reads the.rodatasection and searches for version strings using regexOpenSSL\s\d\.\d\.[0-9a-z]+Fallback to libcrypto: If
libssl.so.3lacks version info, checks importedlibcrypto.soviagetImpNeeded()user/module/probe_openssl.go:221-235Android Detection: Uses
--androidverflag to select BoringSSL bytecode:boringssl_a_12throughboringssl_a_16user/module/probe_openssl.go:247-262Version Downgrade:
autoDetectBytecode()user/module/probe_openssl.go:273 iteratively truncates version (e.g.,3.0.12→3.0.0→3.0) to find closest compatible bytecode
Version-to-Bytecode Mapping:
The sslVersionBpfMap populated by initOpensslOffset() maps detected versions to bytecode filenames:
"openssl 1.1.1a" → "openssl_1_1_1_kern.o"
"openssl 3.0.0" → "openssl_3_0_0_kern.o"
"boringssl_a_14" → "boringssl_a_14_kern.o"Bytecode File Naming:
Pattern: <library>_<major>_<minor>_<patch>_kern[_core|_noncore].o
Examples:
openssl_3_0_0_kern_core.o- OpenSSL 3.0.x with BTF CO-RE supportboringssl_a_14_kern_noncore.o- BoringSSL Android 14 without BTF
The suffix is determined by geteBPFName() user/module/imodule.go:191-214 based on kernel BTF availability.
Sources: user/module/probe_openssl.go:178-278, user/module/imodule.go:191-214
Quick Start Examples
Text Mode - Real-Time Monitoring
Captures and displays plaintext TLS traffic with HTTP parsing:
sudo ecapture tls
# Output: Real-time HTTP requests/responses to consoleOutput Example:
UUID:233479_233479_curl_5_1_39.156.66.10:443, Name:HTTPRequest, Type:1, Length:73
GET / HTTP/1.1
Host: baidu.com
User-Agent: curl/7.81.0Sources: README_CN.md:76-126, README.md:72-149
PCAP Mode - Network Analysis
Saves encrypted traffic with embedded decryption keys:
sudo ecapture tls -m pcap -i eth0 --pcapfile=capture.pcapng tcp port 443
# Opens in Wireshark with automatic decryptionThe PCAP-NG file includes a DSB (Decryption Secrets Block) containing master secrets, enabling Wireshark to decrypt TLS traffic automatically.
Sources: README_CN.md:156-201, README.md:177-232
Keylog Mode - External Tool Integration
Extracts TLS master secrets for use with tshark or other tools:
# Terminal 1: Start key extraction
sudo ecapture tls -m keylog --keylogfile=keys.log
# Terminal 2: Live decryption with tshark
tshark -o tls.keylog_file:keys.log -Y http -T fields -e http.file_data -f "port 443" -i eth0Keylog Format:
CLIENT_RANDOM 5a6f2b3c1d8e9f0a... 1d8e9f0a2b3c4d5e...
CLIENT_HANDSHAKE_TRAFFIC_SECRET 5a6f2b3c... 8c7d6e5f...
SERVER_HANDSHAKE_TRAFFIC_SECRET 5a6f2b3c... 3b2a1c0d...Sources: README_CN.md:205-220, README.md:234-253
Module-Specific Implementations
eCapture provides four specialized TLS/SSL modules, each tailored to a specific library family. Implementation details, hook strategies, and advanced configuration for each module are covered in dedicated sub-sections:
OpenSSL and BoringSSL (page 3.1.1)
Module: ecapture tlsImplementation: MOpenSSLProbe user/module/probe_openssl.go:83-106
Comprehensive support for OpenSSL 1.0.2 through 3.5.x and BoringSSL for Android 12-16. Features automatic version detection, structure offset management, and BoringSSL-specific master secret extraction.
Key Topics in 3.1.1:
- Version-specific structure offsets (ssl_st vs ssl_connection_st)
- BoringSSL Android detection and bytecode selection
- Uprobe hook point differences across versions
- OpenSSL 1.0.x compatibility (SSL_state vs SSL_in_before)
Sources: user/module/probe_openssl.go:777-786
BoringSSL Module (page 3.1.2)
Module: ecapture tls (with --android flag)
Android-specific BoringSSL capture for versions 12-16. Covers Android APEXmodule path detection, per-version offset files, and unique master secret hook strategies.
Sources: CHANGELOG.md:32, README.md:14-16
Go TLS Module (page 3.1.3)
Module: ecapture gotlsImplementation: MGoTLSProbe
Captures plaintext from Go applications using the standard library crypto/tls package. Handles Go ABI differences (register vs stack), PIE binary analysis, and structure offset calculation from Go debug information.
Sources: README.md:254-276
GnuTLS and NSS Modules (page 3.1.4)
Modules: ecapture gnutls, ecapture nss
Alternative TLS library support for GnuTLS and Mozilla NSS. Covers distinct hook points, application-specific considerations (Firefox, wget, etc.), and keylog mode support.
Sources: README.md:155-158, CHANGELOG.md:126-127
Master Secret Extraction (page 3.1.5)
Deep dive into TLS 1.2 and TLS 1.3 master secret capture, HKDF key derivation for TLS 1.3 traffic secrets, deduplication strategies, and SSLKEYLOGFILE format generation across all supported libraries.
Sources: user/module/probe_openssl.go:482-731
Key Capabilities
1. Master Secret Extraction
All TLS/SSL modules extract master secrets for both TLS 1.2 and TLS 1.3 protocols. The extraction logic differs between OpenSSL and BoringSSL implementations.
Event Structures:
| Event Type | Struct | Size | Used By |
|---|---|---|---|
| TLS 1.2/1.3 (OpenSSL) | event.MasterSecretEvent | ~192 bytes | saveMasterSecret() line 482 |
| TLS 1.2/1.3 (BoringSSL) | event.MasterSecretBSSLEvent | ~256 bytes | saveMasterSecretBSSL() line 577 |
TLS 1.2 Master Secret Format:
// user/module/probe_openssl.go:494-500
if secretEvent.Version == event.Tls12Version {
// Output: CLIENT_RANDOM <32-byte-hex> <48-byte-hex>
b = fmt.Sprintf("%s %02x %02x\n",
hkdf.KeyLogLabelTLS12, // "CLIENT_RANDOM"
secretEvent.ClientRandom, // 32 bytes
secretEvent.MasterKey) // 48 bytes
}TLS 1.3 Master Secret Derivation:
TLS 1.3 requires HKDF key derivation to generate multiple secrets:
// user/module/probe_openssl.go:502-550
// 1. Determine cipher suite for hash algorithm
switch secretEvent.CipherId {
case hkdf.TlsAes128GcmSha256, hkdf.TlsChacha20Poly1305Sha256:
length = 32; transcript = crypto.SHA256
case hkdf.TlsAes256GcmSha384:
length = 48; transcript = crypto.SHA384
}
// 2. Derive handshake traffic secrets
clientHandshakeSecret := hkdf.ExpandLabel(
secretEvent.HandshakeSecret[:length],
hkdf.ClientHandshakeTrafficLabel, // "c hs traffic"
secretEvent.HandshakeTrafficHash[:length],
length, transcript)
serverHandshakeSecret := hkdf.ExpandLabel(
secretEvent.HandshakeSecret[:length],
hkdf.ServerHandshakeTrafficLabel, // "s hs traffic"
secretEvent.HandshakeTrafficHash[:length],
length, transcript)TLS 1.3 Output Format:
Five secret types are output:
CLIENT_HANDSHAKE_TRAFFIC_SECRET- Derived from handshake secretSERVER_HANDSHAKE_TRAFFIC_SECRET- Derived from handshake secretCLIENT_EARLY_TRAFFIC_SECRET- FromEarlyTrafficSecretfield (if non-null)CLIENT_TRAFFIC_SECRET_0- FromClientAppTrafficSecretfieldSERVER_TRAFFIC_SECRET_0- FromServerAppTrafficSecretfieldEXPORTER_SECRET- FromExporterMasterSecretfield
Deduplication:
// user/module/probe_openssl.go:483-489
k := fmt.Sprintf("%02x", secretEvent.ClientRandom)
_, found := m.masterKeys[k]
if found {
return // Already saved this client random
}
m.masterKeys[k] = trueNull Secret Detection:
Both TLS 1.2 and 1.3 have null-checking logic to prevent writing empty secrets:
oSSLEvent12NullSecrets(): Checks ifMasterKeyis all zerosoSSLEvent13NullSecrets(): Checks if all five TLS 1.3 secrets are non-zerobSSLEvent12NullSecrets(),bSSLEvent13NullSecrets(): BoringSSL equivalents
Output Destinations:
Secrets are written to different destinations based on eBPFProgramType:
- PCAP Mode:
savePcapngSslKeyLog()adds to DSB (Decryption Secrets Block) - Keylog Mode:
keylogger.WriteString()appends to file - Text Mode: No master secret output
Sources: user/module/probe_openssl.go:482-642, user/module/probe_openssl.go:644-731, README.md:234-247
2. Protocol Parsing
Text Mode HTTP Support:
The modules include built-in HTTP/1.x and HTTP/2 protocol parsers:
- HTTP/1.x: Request/response parsing with headers and body
- HTTP/2: Frame parsing including HEADERS, DATA, SETTINGS, PING
- HPACK header decompression for HTTP/2
- Automatic content-type detection and display
Sources: CHANGELOG.md:487, cli/cmd/root.go:152
3. Multi-Architecture Support
Supported Platforms:
- Linux x86_64: Kernel 4.18+
- Linux aarch64: Kernel 5.5+
- Android x86_64: Android 12+
- Android aarch64: Android 12+
Cross-Compilation:
- Dual-mode bytecode (CO-RE and non-CO-RE) in single binary
- Automatic BTF detection and mode selection
- Kernel version-specific bytecode variants (<5.2)
Sources: README.md:14-16, CHANGELOG.md:553-561
4. Filtering and Targeting
Process Filtering:
--pidflag: Target specific process ID--uidflag: Target specific user ID- Default: Capture all processes/users
Network Filtering (PCAP mode):
- PCAP filter expression support (tcpdump syntax)
- Example:
tcp port 443 - Applied via TC eBPF program instruction patching
Sources: user/module/probe_openssl.go:361-387, README.md:183-184
5. Connection Lifecycle Tracking
4-Tuple Generation:
The modules track network connections using 4-tuple information:
- Source IP:Port
- Destination IP:Port
- IPv4 and IPv6 support
Tracking Mechanism:
- TC hook captures packets and generates 4-tuple
- Kprobe on
tcp_sendmsg/__sys_connectassociates socket with PID/FD - SSL data events correlate with tuple via
pidConnsmap - Connection cleanup on socket destroy or process exit
Delayed Cleanup:
- 3-second delay via
time.AfterFunc()to handle race conditions - Prevents premature deletion while events are in-flight
- Coordinated with EventProcessor merge interval
Sources: user/module/probe_openssl.go:398-462, CHANGELOG.md:306-309
Configuration Parameters
Common TLS Module Flags
| Flag | Type | Default | Description |
|---|---|---|---|
-m, --model | string | text | Capture mode: text/pcap/pcapng/keylog/key |
--libssl | string | auto-detect | Path to SSL library or statically linked binary |
--pcapfile | string | ecapture_openssl.pcapng | PCAP output file (pcap mode) |
--keylogfile | string | ecapture_masterkey.log | Keylog output file (keylog mode) |
-i, --ifname | string | - | Network interface (pcap mode, required) |
--pid | uint64 | 0 | Target process ID (0 = all) |
--uid | uint64 | 0 | Target user ID (0 = all) |
-b, --btf | uint8 | 0 | BTF mode: 0=auto, 1=core, 2=non-core |
Android-Specific Flags
| Flag | Type | Description |
|---|---|---|
--android | bool | Enable Android/BoringSSL mode |
--androidver | string | Android version (12-16) for bytecode selection |
Sources: user/config/iconfig.go:73-93, cli/cmd/root.go:140-152
Output Examples
Text Mode Output
UUID:233479_233479_curl_5_1_39.156.66.10:443, Name:HTTPRequest, Type:1, Length:73
GET / HTTP/1.1
Host: baidu.com
Accept: */*
User-Agent: curl/7.81.0UUID Format: <pid>_<tid>_<comm>_<fd>_<direction>_<tuple>
Sources: README_CN.md:103-125
PCAP Mode Output
- File format: PCAP-NG
- Contains: Network packets with plaintext payload
- Decryption Secrets Block (DSB): Embedded master secrets
- Compatible with: Wireshark, tshark, tcpdump
Sources: README.md:187-232
Keylog Mode Output
CLIENT_RANDOM 5a6f2b3c... 1d8e9f0a...
CLIENT_HANDSHAKE_TRAFFIC_SECRET 5a6f2b3c... 8c7d6e5f...
SERVER_HANDSHAKE_TRAFFIC_SECRET 5a6f2b3c... 3b2a1c0d...
CLIENT_TRAFFIC_SECRET_0 5a6f2b3c... f9e8d7c6...
SERVER_TRAFFIC_SECRET_0 5a6f2b3c... b5a49382...
EXPORTER_SECRET 5a6f2b3c... 71625348...Usage with tshark:
tshark -o tls.keylog_file:ecapture_masterkey.log -Y http -T fields -e http.file_data -f "port 443" -i eth0Sources: README.md:239-247, user/module/probe_openssl.go:492-554