Kubernetes

The Suspicious Connection My Monitoring Dashboard Never Showed Me

Grafana showed healthy metrics while a reverse shell ran inside a Kubernetes pod. See how Tetragon and eBPF detect attacks that traditional monitoring misses.

Imagine you're running multiple microservices on a Kubernetes cluster with Prometheus collecting metrics and Grafana monitoring CPU, memory, requests, and network traffic. Everything looks healthy, and no alerts are firing. Then, during a routine review, you discover a pod communicating with an unknown external IP address. The surprising part? None of the dashboards reported anything unusual. CPU and memory usage remained normal, and the application continued serving traffic without issues.

Further investigation revealed a reverse shell running inside the container — giving an attacker interactive access to the workload.

Traditional monitoring tools can tell us whether an application is healthy, but they often cannot show what is actually happening inside a container at runtime. To uncover the suspicious activity, we needed deeper visibility into process execution and network connections. This is where Tetragon and eBPF come in.


What is eBPF?

eBPF (extended Berkeley Packet Filter) is a feature of the Linux kernel that lets you run small programs inside the kernel itself — without modifying the kernel source code or rebooting the machine.

💡
Think of it like this: imagine you could attach a tiny invisible camera to every door in your house. Every time anyone opens a door, the camera records it. You did not modify the doors. You did not rebuild the house. The cameras just attach and observe. That is what eBPF does inside Linux — it attaches to kernel functions and syscalls, and every time a process calls one of those functions, your eBPF program runs and records the event.

Tetragon: Runtime Visibility for Kubernetes

Tetragon is an open-source eBPF security tool built by Cilium. It runs as a DaemonSet on Kubernetes — one pod per node — and uses eBPF to observe everything happening at the kernel level across all containers on that node.

You tell Tetragon what to watch using TracingPolicies — Kubernetes custom resources that define which kernel functions or syscalls to hook into. Tetragon enriches every kernel event with Kubernetes context such as the pod name, namespace, container ID, process, and parent process. This allows you to trace exactly what happened inside a container, not just that something happened.


How Tracing Policies Work

Imagine installing CCTV cameras in a building. The cameras can record everything, but watching every second of footage would be overwhelming. Instead, you configure them to alert you only when specific events occur — such as someone entering a restricted room.

TracingPolicies work the same way. Instead of monitoring every kernel event happening inside Kubernetes, Tetragon watches only for the activities you define. For example, you can create policies to detect:

  1. Reverse shell execution
  2. Privilege escalation attempts
  3. Suspicious network connections
  4. Sensitive file access
  5. Container escape behavior

Whenever one of these activities occurs, Tetragon captures the event and enriches it with Kubernetes context such as the pod name, namespace, process, and container information.


Prerequisites

To set up a complete Kubernetes kernel-level monitoring system you need:

  • A running Kubernetes cluster
  • Prometheus installed on a dedicated namespace
  • Grafana installed on the same namespace as Prometheus
  • Helm 3.x
  • kubectl configured

Installation

Step 1: Add the Helm Repository

bash
helm repo add cilium https://helm.cilium.io
helm repo update

Step 2: Update Chart Dependencies

bash
helm dependency update ./helm-chart-folder

Step 3: Install Tetragon

bash
helm install tetragon-poc ./tetragon-poc \
--namespace tetragon-poc \
--create-namespace \
-f values.yaml

Step 4: Verify the Installation

bash
# Check pods
kubectl get pods -n tetragon-poc
# Check tracing policies
kubectl get tracingpolicy
# Check service monitor
kubectl get servicemonitor -n tetragon-poc
# Check Prometheus alerts
kubectl get prometheusrule -n tetragon-poc
# Check Grafana dashboard configmap
kubectl get configmap -n monitoring | grep tetragon
💡
For the complete Helm chart setup, configuration values, and full proof-of-concept, refer to the GitHub repository.

Building a Reverse Shell Detection Tracing Policy

We will create a TracingPolicy that watches for reverse shell activity and alerts us whenever a container attempts to establish a suspicious outbound connection.

Step 1: API Declaration

Every Tetragon policy starts with the Kubernetes CRD header. Tetragon uses Cilium's cilium.io/v1alpha1 API group.

yaml
apiVersion: cilium.io/v1alpha1
kind: TracingPolicy

Step 2: Metadata

Name the policy and add labels so Helm can track and manage it.

yaml
metadata:
name: reverse-shell-monitoring
labels:
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/part-of: tetragon-poc

Step 3: Choose the Hook Type

Tetragon supports two primary hook types:

Hook TypeWhen to Use
KprobesIntercept kernel functions like tcp_connect
TracepointsIntercept syscalls at a stable kernel tracepoint

Reverse shell detection watches the dup2 syscall, so we use tracepoints.

yaml
spec:
tracepoints:
- subsystem: "syscalls"
event: "sys_enter_dup2"

sys_enter_dup2 fires the moment any process calls dup2() — before the kernel executes it.

Step 4: Declare the Arguments to Capture

dup2(oldfd, newfd) takes two arguments. We declare both so Tetragon knows their types and positions.

yaml
args:
- index: 0 # oldfd — the source file descriptor (e.g. a socket)
type: "int64"
- index: 1 # newfd — the destination (stdin=0, stdout=1, stderr=2)
type: "int64"

Step 5: Add the Selector (The Detection Logic)

This is where the actual detection happens. We match on index: 1 (the newfd argument) being 0, 1, or 2 — because a reverse shell always redirects the socket to stdin, stdout, or stderr.

yaml
selectors:
- matchArgs:
- index: 1
operator: "Equal"
values:
- "0" # stdin — fd 0
- "1" # stdout — fd 1
- "2" # stderr — fd 2

Complete Policy

yaml
{{- if .Values.tracingPolicies.reverseShell.enabled }}
---
apiVersion: cilium.io/v1alpha1
kind: TracingPolicy
metadata:
name: {{ .Values.tracingPolicies.reverseShell.name }}
labels:
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/part-of: tetragon-reverseshell
spec:
tracepoints:
- subsystem: "syscalls"
event: "sys_enter_dup2"
args:
- index: 0
type: "int64"
- index: 1
type: "int64"
selectors:
- matchArgs:
- index: 1
operator: "Equal"
values:
- "0" # stdin
- "1" # stdout
- "2" # stderr
{{- end }}

How Does a Tracing Policy Detect a Reverse Shell?

Tetragon reverse shell detection flow

The diagram above illustrates the complete lifecycle of how Tetragon detects a reverse shell attack inside a Kubernetes environment.

  1. An application or process is running inside a Kubernetes pod.
  2. An attacker gains access and establishes an outbound TCP connection back to their machine.
  3. To make the shell interactive, the attacker redirects the socket to stdin, stdout, and stderr using the dup2() syscall.
  4. Tetragon, using eBPF programs attached to Linux kernel tracepoints, intercepts the dup2() call in real time.
  5. Tetragon checks whether the new file descriptor maps to stdin (0), stdout (1), or stderr (2). Matching any of these is a strong indicator of a reverse shell.
  6. Tetragon generates a security event.
  7. The event is enriched with Kubernetes context — pod name, namespace, process information, and node details.
  8. The event is logged and exported. Prometheus collects the generated metrics, and Grafana visualizes them through dashboards.
  9. AlertManager evaluates the alerting rules and triggers notifications when suspicious activity is detected.
  10. The security team receives an alert and can begin incident response before the attacker gains deeper access.
ℹ️
The reason this approach is effective is that Tetragon operates at the Linux kernel level. Instead of relying on application logs or resource metrics, it observes the actual system calls being executed — detecting reverse shell behavior even when CPU, memory, and application health metrics appear completely normal.

Simulating a Reverse Shell Attack

You can verify the detection is working by simulating the attack without an actual attacker listening:

bash
kubectl exec test-pod -n monitoring -- python3 -c \
"import socket,os; s=socket.socket(); os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2)"

This opens a socket and calls dup2 three times — redirecting stdin, stdout, and stderr to it. The connection itself will fail (no attacker listening), but Tetragon fires three events — one for each dup2 call hitting fd 0, 1, and 2.

Those events appear immediately in Grafana and trigger the TetragonReverseShellDetected alert in AlertManager.


Conclusion

In our scenario, Grafana showed healthy metrics, Prometheus continued collecting data, and the application remained available. From an operational perspective, everything appeared normal. However, a reverse shell running inside the container told a very different story.

Traditional monitoring tools are excellent at measuring application health, but they often lack visibility into what processes are actually doing at runtime. By combining eBPF with Tetragon TracingPolicies, we were able to observe kernel-level activity, detect suspicious behavior, and generate alerts before the issue escalated further.

The biggest lesson is simple: healthy metrics do not always mean a secure environment. Runtime visibility adds an additional layer of defense that helps security and platform teams understand what is happening inside containers — not just whether the application is responding.

If your organization already uses Kubernetes, Prometheus, and Grafana, tools like Tetragon can significantly improve your ability to detect threats that traditional monitoring platforms may never see.


FAQ

1. Can Grafana detect reverse shell attacks? Not directly. Grafana visualizes metrics and logs collected from monitoring systems, but it does not provide kernel-level visibility into process execution or system calls.

2. What is a reverse shell attack? A reverse shell is a technique that allows an attacker to gain command-line access to a compromised system by forcing the target to establish a connection back to the attacker's machine.

3. What is a TracingPolicy in Tetragon? A TracingPolicy is a Kubernetes custom resource that defines which kernel events Tetragon should monitor. Policies can be used to detect reverse shells, privilege escalation attempts, suspicious network connections, and other security-related activities.

4. Why does Tetragon use eBPF? eBPF allows Tetragon to observe kernel-level events without modifying the Linux kernel or restarting workloads, providing deep visibility into container activity with minimal overhead.

5. Can Tetragon work without Prometheus and Grafana? Yes. Tetragon can capture and export security events independently. Prometheus and Grafana simply provide a convenient way to collect, visualize, and alert on those events.


References

  1. Tetragon Documentation
  2. Grafana Documentation
  3. Prometheus Documentation
  4. GitHub — tetragon-ebpf codebase

Related articles