Tracing Encrypted Traffic (TLS)
Kubeshark can detect TLS traffic and display encrypted traffic (TLS). In most cases, Kubeshark can also show the unencrypted payload.
Detecting Encrypted Traffic
Before attempting to display encrypted traffic in clear text, Kubeshark detects and marks TLS TCP packets, identifying various TLS-related messages (e.g., ClientHello
and ServerHello
).
TLS traffic is marked with an open lock icon to the left of the entry. You can use the helper
tls
as a KFL query to filter and view all TLS traffic.
TLS 1.x Items
At the very least, Kubeshark will display the ClientHello and ServerHello TLS messages and related information.
TLS TCP Packets
In addition to the TLS messages mentioned above, Kubeshark shows all encrypted TCP packets within Kubernetes contexts, including information such as namespaces, pod and service names, IPs, ports, and more.
Displaying Unencrypted Payloads
Kubeshark can display the unencrypted payload in clear text by utilizing eBPF. It hooks into entry and exit points in specific functions within the OpenSSL library, Go’s crypto/tls package and Google’s BoringSSL. If Kubeshark detects TLS termination via one of these libraries, the entire message is reassembled into a request-response pair, similar to HTTP, allowing you to view encrypted traffic in clear text.
TL;DR - Use of eBPF
Kubeshark traces both kernel-space and user-space functions using eBPF (Extended Berkeley Packet Filter). eBPF is an in-kernel virtual machine that runs programs passed from user space. First introduced in Linux kernel version 4.4, it has since matured significantly.
OpenSSL
Kubeshark attaches uprobes to SSL_read
and SSL_write
, capturing unencrypted incoming responses and outgoing encrypted requests in any TLS/SSL connection.
Languages like Python, Java, PHP, Ruby, and Node.js use the OpenSSL library for encryption/decryption tasks, so any program or service using TLS for encrypted communication falls into this category.
Go
Go’s encryption process is a bit more complex than OpenSSL, but the underlying principle is similar.
Go has two ABIs: ABI0 and ABIInternal, and Kubeshark supports both amd64 and arm64, which translates into a significant number of offsets to handle.
We probe crypto/tls.(*Conn).Read
and crypto/tls.(*Conn).Write
, much like OpenSSL’s SSL_read
and SSL_write
. Additionally, we disassemble targeted Go binaries using Capstone to locate the offsets of ret
instructions, as uretprobe
does not work properly in Go due to its unique ABI.
Finally, we track the Goroutine ID using offsets identified in the DWARF table.
Kernel
We use kprobes
on certain kernel tracepoints to perform tasks such as address resolution (learning the IP and port for both source and destination) and matching request-response pairs.
While these methods may sound complex, Kubeshark’s TLS sniffer has minimal performance impact due to the efficient eBPF in-kernel virtual machine and our carefully written C code. Furthermore, the Linux kernel limits the number of instructions allowed for probing purposes, ensuring there is no significant slowdown or crash risk.