Self-hosted service
qpoint-io/qtap avatar
qpoint-io/qtap

Qtap: eBPF Traffic Capture at the TLS Boundary

Qtap: An eBPF agent that captures pre-encrypted network traffic, providing rich context about egress connections and their originating processes.

1,458 stars55 forksCApache-2.0

At a glance

What is it?
Qtap is a C eBPF agent that hooks TLS/SSL functions in the Linux kernel to read plaintext before encryption and after decryption, then hands it to plugins with process, container and host context. It is worth a look if you run Linux 5.10+ with BTF and want egress visibility without a proxy or a certificate store.
Who is it for?
Adopt Qtap if you control the Linux nodes, run kernel 5.10 or newer with BTF (check that /sys/kernel/btf/vmlinux exists), and your real question is which process on which host opened which egress connection with what payload.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 4 days ago.
What is it written in?
Mainly C, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

The problem Qtap targets: knowing which process sent what, after TLS

Once traffic leaves a process through a TLS library, the payload on the wire is opaque to anything watching the network. A packet capture gives you endpoints, timing and volume. It does not give you the request body, the response body, or the identity of the process that produced them. The conventional fixes are a forward proxy with a generated certificate authority, or an agent that terminates TLS inside the application. Both require you to change how applications are deployed, and both move a copy of your plaintext through a component you now have to operate. Qtap takes a third route. According to the README, it attaches to TLS/SSL functions in the Linux kernel and intercepts data before encryption and after decryption, then passes it to plugins together with context: process, container, host, user and protocol. The stated benefit is that you do not modify apps, install proxies or manage certificates. The audience is narrower than the topic list suggests. This is for engineers who already have root or equivalent capability on Linux hosts and want egress visibility for security auditing, API debugging, third-party integration checks, or investigating systems whose source they cannot read.

How the interception works and what a plugin receives

The mechanism is uprobe-style attachment to the TLS and SSL functions a process calls, not packet reassembly. Because the hook sits at the library boundary, the data Qtap sees is the plaintext argument to the encryption function and the plaintext result of the decryption function, which is why the README describes it as capturing traffic "before and after encryption." That ordering matters: there is no key material to recover and no handshake to replay, because the plaintext exists in the process at the moment of the call. The captured stream is then handed to plugins alongside available context, which the README lists as process, container, host, user and protocol. Qtap positions itself as something that can feed an existing observability pipeline or act as a base for a custom build, and the README names Qpoint as one such consumer. The repository layout supports that split: the agent is written in C with libbpf listed among the topics, while the DevTools interface lives under pkg/devtools/app, which puts the user-facing part in Go. The practical consequence is that the value of Qtap is bounded by where the hook lands. Anything that does not call the TLS functions it attaches to is invisible, and the README does not enumerate the covered libraries, so that set has to be confirmed against your own stack rather than assumed.

Getting it running: demo mode, install script, container flags

The README gives two entry points. For a temporary instance in demo mode, which it describes as showing traffic in real time in your terminal, the command is curl -s https://get.qpoint.io/demo | sudo sh. For a normal install it is curl -s https://get.qpoint.io/install | sudo sh, followed by sudo qtap to run with defaults. Piping a remote script into a root shell is the distribution model here, so the download path is part of your trust boundary and there is no package signature step described in the material. Container deployment is spelled out with an explicit flag set: --user 0:0, --privileged, --cap-add CAP_BPF, --cap-add CAP_SYS_ADMIN, --pid=host, --network=host, mounts for /sys and /var/run/docker.sock, the environment variable TINI_SUBREAPER=1, and --ulimit=memlock=-1, against the image us-docker.pkg.dev/qpoint-edge/public/qtap:v0, with --log-level=info passed as an argument. The memlock limit and the privileged flag are not optional decoration; eBPF programs and their maps are accounted against locked memory, and host PID visibility is what makes the process and container context meaningful. The requirements section states Linux kernel 5.10 or newer with BPF Type Format enabled, and tells you to check for /sys/kernel/btf/vmlinux to confirm BTF is present.

DevTools is the part that makes the data inspectable without a backend

Raw intercepted streams are not useful on their own, and the README is explicit that Qtap can either augment an existing observability pipeline or serve as a foundation for a custom solution. The built-in answer to the first case is the DevTools interface in pkg/devtools/app, described as a Chrome DevTools-like network tab for monitoring processes and traffic on a single Linux node. It offers real-time monitoring of HTTP transactions, network connections and processes, with filtering, search and detailed inspection. Two constraints follow from that description. It is scoped to a single node, so it is a debugging surface rather than a fleet view. And it is HTTP-oriented, which means the richer inspection experience is tied to HTTP transactions even though the capture layer itself sits below the protocol. For a security audit of an arbitrary binary speaking a non-HTTP protocol over TLS, the DevTools UI is not the interface you would reach for. This is the clearest fork in how the project is meant to be used: a small team debugging one host gets value from DevTools immediately, while anyone with more than a handful of nodes is really evaluating the plugin interface and the pipeline they will build on top of it.

Where Qtap is the wrong tool

The failure modes are structural rather than incidental. First, the hook depends on the TLS implementation being called. Traffic that is encrypted inside a statically linked library, in a language runtime with its own crypto path, or by a custom protocol stack may never reach the interception point, and the README does not publish a list of supported libraries, so this is a gap you have to close by testing your own workloads. Second, the privilege requirements are heavy: CAP_BPF and CAP_SYS_ADMIN, privileged mode, host PIDs, and a memlock ulimit set to unlimited. On a managed Kubernetes platform or any environment where you do not control the node, this is often not grantable at all, and the Docker example in the README is a clear signal about how much access is expected. Third, this is a Linux-only design tied to kernel 5.10 and BTF, so a mixed fleet splits into covered and uncovered nodes. Fourth, interception happens in the target process's call path, which is a different risk profile from an out-of-band network tap; the README claims minimal overhead and no added latency, but it offers no measurement, and the honest position is that any inline hook adds work to the calling thread. Treat the overhead claim as unverified until you measure it on your own binaries.

The alternative it replaces, and what actually differs

The realistic alternative is a TLS-terminating forward proxy with a private CA installed into application trust stores, which is how most egress inspection is done today. The difference is where the plaintext is exposed. A proxy sits in the network path, so it sees every connection that is routed through it regardless of which library produced it, and it can enforce policy in the same place it observes. That breadth is exactly why it costs more: you distribute and rotate a CA, you accept a man-in-the-middle position in your own infrastructure, you may break certificate pinning, and you add a hop that can fail. Qtap inverts each of those properties. Nothing is routed through it, so there is no added hop and no certificate to manage, and pinned clients keep working. In exchange, coverage becomes conditional on the hook landing, the agent needs node-level privilege instead of a network position, and the captured data is only as complete as the plugin you write for it. A second alternative is application-level instrumentation such as OpenTelemetry, which gives structured spans with full semantic context but requires code or SDK changes in every service. Qtap's pitch is that it needs none, and that is the trade: less integration work, less certain coverage.

Maintenance, licensing and what to check before committing

Qtap is licensed Apache-2.0, which permits commercial use, modification and redistribution provided you keep the licence and notice files and state significant changes, and it includes a patent grant. It also means there is no copyleft obligation on your own code and no requirement to publish modifications. Nothing here is legal advice; if you are embedding the agent in a product, have counsel read the LICENSE file in the repository rather than a summary. The maintenance picture is the weaker side. The repository is not archived and was last pushed on 2026-09-09, but no releases were retrieved, so the material does not show a versioned artifact history you can pin against. The install path is a curl-to-shell script and the container example uses a v0 tag, which is the kind of moving reference that makes reproducible deployments harder. The plugin interface is the part most likely to change under you, since it is the extension point the project expects consumers to build against, and the DevTools app lives in the same tree and will move with it. Before adopting, confirm three things: that /sys/kernel/btf/vmlinux exists on every node class you care about, that the TLS libraries your services actually use are intercepted, and that the plugin API at the commit you pin is the one you are willing to maintain against.

Editorial conclusion

Adopt Qtap if you control the Linux nodes, run kernel 5.10 or newer with BTF (check that /sys/kernel/btf/vmlinux exists), and your real question is which process on which host opened which egress connection with what payload. Do not adopt it if your traffic is not TLS handled by a library it can attach to, if you cannot grant CAP_BPF and CAP_SYS_ADMIN plus host PIDs, or if you need a signed, versioned release before you put anything in production, since no releases were retrieved for this repository. Verify first that the interception points match your runtimes: statically linked TLS, custom protocol stacks and non-Linux nodes will not appear in the output, and the README does not enumerate the exact library set covered.

Official sources

  1. Issues
  2. License: Apache-2.0
  3. Project website
  4. qpoint-io/qtap on GitHub
  5. README
Community notes

Community notes