快速探索 Tetragon:基于 eBPF 的安全可觀察性和執(zhí)行工具
Tetragon[1] 是一種靈活的安全可觀察性和運行時策略執(zhí)行工具,可直接使用 eBPF 應(yīng)用策略和過濾,從而減少了監(jiān)控、進程跟蹤以及實時執(zhí)行策略的開銷。
Tetragon 提供了如下功能:
- 監(jiān)控進程執(zhí)行
- 監(jiān)控文件操作
- 監(jiān)控網(wǎng)絡(luò)活動
- 執(zhí)行策略
最后一個側(cè)重策略的執(zhí)行,可以通過發(fā)送信號或覆蓋系統(tǒng)調(diào)用的返回值對重要的安全事件做出反應(yīng);前三種側(cè)重監(jiān)控,并可以將監(jiān)控數(shù)據(jù)與容器、Kubernetes 元數(shù)據(jù)進行關(guān)聯(lián)。
圖片
演示
環(huán)境
- 操作系統(tǒng):Ubuntu 20.04
- 內(nèi)核:5.15.122
- K8s 集群:k3s v1.27.1+k3s1
創(chuàng)建集群
export INSTALL_K3S_VERSION=v1.27.1+k3s1
curl -sfL https://get.k3s.io | sh -s - --disable traefik --disable local-storage --disable metrics-server --disable servicelb --write-kubeconfig-mode 644 --write-kubeconfig ~/.kube/config
部署示例應(yīng)用
示例應(yīng)用使用我們在 使用 Cilium 增強 Kubernetes 網(wǎng)絡(luò)安全 中有用過的”星球大戰(zhàn)“的場景。
kubectl create -f https://raw.githubusercontent.com/cilium/cilium/v1.15.0-pre.1/examples/minikube/http-sw-app.yaml
安裝 Tetragon
使用 helm 來安裝 Tetragon。
helm repo add cilium https://helm.cilium.io
helm repo update
helm install tetragon cilium/tetragon -n kube-system
查看 Tetragon 的組件。
kubectl get pod -n kube-system -l app.kubernetes.io/instance=tetragon
NAME READY STATUS RESTARTS AGE
tetragon-operator-f68fdfcf6-jltn2 1/1 Running 0 6m23s
tetragon-mh8fp 2/2 Running 0 6m23s
其中 tetragon 是 Daemonset 類型,在每個節(jié)點上都會運行其示例。在后面的演示中,我們將使用其獲取事件信息。
該命令會使用 pod 中的 tetra CLI 鏈接 Tetragon 的 daemon server 打印和過濾事件。
-o 支持 json 和 compact:前者打印詳細信息,后者打印緊湊的信息 --pods 打印指定 pods 的事件,這里支持正則
kubectl exec -ti -n kube-system ds/tetragon -c tetragon -- tetra getevents -o compact --pods xwing
監(jiān)控進程執(zhí)行
我們在 xwing 的 pod 中嘗試 curl 發(fā)送請求。
kubectl exec -ti xwing -- bash -c 'curl -I https://ebpf.io/applications/#tetragon'
在 CLI 事件監(jiān)控中可以看到監(jiān)控到進行的執(zhí)行。
?? process default/xwing /usr/bin/bash -c "curl -I https://ebpf.io/applications/#tetragon"
?? process default/xwing /usr/bin/curl -I https://ebpf.io/applications/#tetragon
?? exit default/xwing /usr/bin/curl -I https://ebpf.io/applications/#tetragon 0
要獲取詳細的事件信息,可以使用 -o json。在詳細信息中,是記錄更多進程的詳細內(nèi)容(pid、時間戳等)以及 Kubernetes 的元數(shù)據(jù)(所在的 pod、label、容器相關(guān)、node 等信息)。
{
"process_exec": {
"process": {
"exec_id": "bWFzdGVyOjEwOTE5NTI2MzMxNDc4OTM6ODY1Njk3",
"pid": 865697,
"uid": 0,
"cwd": "/",
"binary": "/usr/bin/bash",
"arguments": "-c \"curl -I https://ebpf.io/applications/#tetragon\"",
"flags": "execve rootcwd clone",
"start_time": "2023-11-15T21:09:01.365214693Z",
"auid": 4294967295,
"pod": {
"namespace": "default",
"name": "xwing",
"container": {
"id": "containerd://53d9871b8ef6acb30a918cd2edd036ef2482f3d2f50322296b846f9a964f23c6",
"name": "spaceship",
"image": {
"id": "docker.io/cilium/json-mock@sha256:4abfabfc1ac49834ce79b5594719e82b518107aa97e1867c42234a5126b1e1be",
"name": "docker.io/cilium/json-mock:latest"
},
"start_time": "2023-11-15T14:09:41Z",
"pid": 39
},
"pod_labels": {
"app.kubernetes.io/name": "xwing",
"class": "xwing",
"org": "alliance"
},
"workload": "xwing",
"workload_kind": "Pod"
},
"docker": "53d9871b8ef6acb30a918cd2edd036e",
"parent_exec_id": "bWFzdGVyOjEwOTE5NTI1OTA0NDY0NzM6ODY1Njg3",
"tid": 865697
},
"parent": {
"exec_id": "bWFzdGVyOjEwOTE5NTI1OTA0NDY0NzM6ODY1Njg3",
"pid": 865687,
"uid": 0,
"cwd": "/run/k3s/containerd/io.containerd.runtime.v2.task/k8s.io/9a020d636a187acf021007efe3aaf2bc2ac5af8c7bcaec8cff80834e1e456c49",
"binary": "/var/lib/rancher/k3s/data/ead6a1703a6dcb4fa71296173ee208c5b05b95a27574fe74946557324bab2582/bin/runc",
"arguments": "--root /run/containerd/runc/k8s.io --log /run/k3s/containerd/io.containerd.runtime.v2.task/k8s.io/53d9871b8ef6acb30a918cd2edd036ef2482f3d2f50322296b846f9a964f23c6/log.json --log-format json --systemd-cgroup exec --process /tmp/runc-process2446102553 --console-socket /tmp/pty4128173919/pty.sock --detach --pid-file /run/k3s/containerd/io.containerd.runtime.v2.task/k8s.io/53d9871b8ef6acb30a918cd2edd036ef2482f3d2f50322296b846f9a964f23c6/eaef092e99f54c7c3898984db0e0c36bc8859d695c753db86e672c8db576f4d8.pid 53d9871b8ef6acb30a918cd2edd036ef2482f3d2f50322296b846f9a964f23c6",
"flags": "execve clone",
"start_time": "2023-11-15T21:09:01.322512873Z",
"auid": 4294967295,
"parent_exec_id": "bWFzdGVyOjEwNjY3Nzk1NTk0MzcxNTE6NzgyNTA4",
"tid": 865687
}
},
"node_name": "master",
"time": "2023-11-15T21:09:01.365213793Z"
}
監(jiān)控文件操作
接下來在 xwing pod 中的操作文件。在 Linux 中 /etc 目錄通常包含系統(tǒng)級的配置文件和腳本,這些文件用于配置系統(tǒng)的各種方面,因此對該目錄的操作應(yīng)當(dāng)謹慎。
kubectl exec -ti xwing -- bash -c 'echo foo >> /etc/bar'
此時這里看到還只是進程相關(guān)的事件。
?? process default/xwing /usr/bin/bash -c "cat /etc/bar"
?? process default/xwing /usr/bin/cat /etc/bar
?? exit default/xwing /usr/bin/cat /etc/bar 0
應(yīng)用下面的策略:
kubectl apply -f - <<EOF
apiVersion: cilium.io/v1alpha1
kind: TracingPolicy
metadata:
name: "file-monitoring-filtered"
spec:
kprobes:
- call: "security_file_permission"
syscall: false
return: true
args:
- index: 0
type: "file" # (struct file *) used for getting the path
- index: 1
type: "int" # 0x04 is MAY_READ, 0x02 is MAY_WRITE
returnArg:
index: 0
type: "int"
returnArgAction: "Post"
selectors:
- matchArgs:
- index: 0
operator: "Prefix"
values:
- "/etc"
- index: 1
operator: "Equal"
values:
- "2" # MAY_WRITE
EOF
然后就可以看到文件操作的相關(guān)事件了。
?? process default/xwing /usr/bin/bash -c "echo foo >> /etc/bar"
?? write default/xwing /usr/bin/bash /etc/bar
?? write default/xwing /usr/bin/bash /etc/bar
?? exit default/xwing /usr/bin/bash -c "echo foo >> /etc/bar" 0
監(jiān)控網(wǎng)絡(luò)活動
應(yīng)用下面的策略,監(jiān)控 TCP 連接的建立,但是排除集群內(nèi)的網(wǎng)絡(luò)連接,將容器的 IP CIDR 排除添加到 NotDAddr 的列表中。
10.42.0.0/16 和 10.43.0.0/16 分別是 K3s 的 pod CIDR 和 service CIDR。
kubectl apply -f - <<EOF
apiVersion: cilium.io/v1alpha1
kind: TracingPolicy
metadata:
name: "monitor-network-activity-outside-cluster"
spec:
kprobes:
- call: "tcp_connect"
syscall: false
args:
- index: 0
type: "sock"
selectors:
- matchArgs:
- index: 0
operator: "NotDAddr"
values:
- 127.0.0.1
- 10.42.0.0/16
- 10.43.0.0/16
matchActions:
- action: Sigkill
EOF
在監(jiān)控的事件就可以看到 TCP 連接的建立了。
?? process default/xwing /usr/bin/bash -c "curl -I https://ebpf.io/applications/#tetragon"
?? process default/xwing /usr/bin/curl -I https://ebpf.io/applications/#tetragon
?? connect default/xwing /usr/bin/curl tcp 10.42.0.7:38676 -> 104.198.14.52:443
?? exit default/xwing /usr/bin/curl -I https://ebpf.io/applications/#tetragon 0
執(zhí)行策略
假如需要對 /etc 目錄進行寫保護,需要上面創(chuàng)建的 file-monitoring-filtered 策略,添加 matchActions。
kubectl apply -f - <<EOF
apiVersion: cilium.io/v1alpha1
kind: TracingPolicy
metadata:
name: "file-monitoring-filtered"
spec:
kprobes:
- call: "security_file_permission"
syscall: false
return: true
args:
- index: 0
type: "file" # (struct file *) used for getting the path
- index: 1
type: "int" # 0x04 is MAY_READ, 0x02 is MAY_WRITE
returnArg:
index: 0
type: "int"
returnArgAction: "Post"
selectors:
- matchArgs:
- index: 0
operator: "Prefix"
values:
- "/etc"
- index: 1
operator: "Equal"
values:
- "2" # MAY_WRITE
matchActions:
- action: Sigkill
EOF
現(xiàn)在嘗試修改 /etc 下的文件時,進程會直接退出。
kubectl exec -ti xwing -- bash -c 'echo foo >> /etc/bar'
command terminated with exit code 137
在事件監(jiān)控中可以看到進程執(zhí)行收到了 SIGKILL 指令。
?? process default/xwing /usr/bin/bash -c "echo foo >> /etc/bar"
?? write default/xwing /usr/bin/bash /etc/bar
?? write default/xwing /usr/bin/bash /etc/bar
?? exit default/xwing /usr/bin/bash -c "echo foo >> /etc/bar" SIGKILL
同樣,針對網(wǎng)絡(luò)活動的監(jiān)控也可以如法炮制,有興趣的可以試試。
分析
Tetragon 架構(gòu)
這個架構(gòu)圖跟之前在 探索 Cilium 的工作機制 所做的圖類似,實際的工作機制也類似。
圖片
通過命令可以看到 tetragon pod 中實際上有兩個容器:export-stdout 和 tetragon。
kubectl get pod tetragon-mh8fp -o=jsnotallow='{.spec.containers[*].name}' -n kube-system
export-stdout tetragon
tetragon 容器中運行了 Tetragon 的 Daemon 進程,在這個容器中還可以執(zhí)行 tetra 命令(tetragon CLI)。
Daemon 進程:
- 加載/卸載 BPF 程序
- 監(jiān)控策略的變化,將策略寫入到 eBPF Map 中。在非 K8s 環(huán)境,會監(jiān)控文件目錄中的策略更新。
- 對外提供了 gRPC 的 API,監(jiān)聽在 127.0.0.1:54321。CLI 的執(zhí)行實際上都是通過該 API 與 Daemon 進行交互。
跟蹤策略
上面演示中不管是監(jiān)控還是策略執(zhí)行,都是通過 跟蹤策略(Tracing Policy)[2] 來完成。跟蹤策略 TracingPolicy 是 Tetragon 的自定義資源,允許用戶跟蹤內(nèi)核中的任意事件,并可定義對匹配采取的操作。
策略由掛鉤點(hook point,支持 kprobes、tracepoint 和 uprobes)以及用于內(nèi)核過濾和指定操作的選擇器組成。
掛鉤點 Hook Point
Tetragon 支持三種掛鉤點:支持 kprobes、tracepoint 和 uprobes。kprobes 和 tracepoints 可用于連接內(nèi)核空間,而 uprobes 用于連接到用戶空間程序。
- kprobes 內(nèi)核空間探針:將 BPF 代碼掛載到內(nèi)核函數(shù),比如前面監(jiān)控網(wǎng)絡(luò)活動時用的 tcp_connect,與內(nèi)核版本強相關(guān),也就是說不同內(nèi)核版本的內(nèi)核函數(shù)探針可能存在差異。
- tracepoints 跟蹤點:與 kprobes 相比,在不同內(nèi)核版本間的差異很小,更加穩(wěn)定??梢酝ㄟ^ sudo ls /sys/kernel/debug/tracing/events 查看內(nèi)核上可用的跟蹤點列表。
- uprobes 內(nèi)核空間探針:在用戶空間程序的特定地址設(shè)置探針,監(jiān)控和跟蹤用戶空間代碼的執(zhí)行。(目前 Tetragon 這部分的文檔是缺失的)。
選擇器 Selector
在 Tetragon 中,TracingPolicy使用選擇器來定義對事件所要執(zhí)行的內(nèi)核 BPF 過濾和操作,也就是策略中指定關(guān)注的事件以及事件發(fā)生時要觸發(fā)的操作。選擇器包含如下幾種:
- 參數(shù)
- 返回值
- 進程 PID
- 二進制文件的路徑
- Linux 命名空間
- Linux 功能
- 命名空間變更
- Linux 功能變更
- 對選擇器應(yīng)用操作
比如我們在前面的例子中,針對 /etc 目錄的寫保護就用到了參數(shù)選擇器(匹配操作的目錄和操作類型)和操作選擇器(返回 Sigkill 信號)。
總結(jié)
Tetragon 是一個專注于 eBPF、實時處理、安全性、可觀測性和策略執(zhí)行的工具,特別是在 Kubernetes 環(huán)境中。它通過利用一系列高級的掛鉤點(hook points)和選擇器(selectors),為基礎(chǔ)設(shè)施安全提供了強大支持,并能夠針對關(guān)鍵事件進行有效防護。
深入理解 Tetragon,我們可以看到它主要是一個底層工具,專注于圍繞進程、文件和網(wǎng)絡(luò)活動實施安全策略。在網(wǎng)絡(luò)方面,Tetragon 主要處理第三層(L3)的基礎(chǔ)信息事件,如 IP 層面的通信。但它在處理更高層次的應(yīng)用協(xié)議,如第四層(L4)的傳輸控制協(xié)議(TCP)或第七層(L7)的應(yīng)用層協(xié)議方面,能力有限。這種限制反映了 Tetragon 的核心定位:專注于底層結(jié)構(gòu)的監(jiān)控和安全,而非高層應(yīng)用協(xié)議的分析。
總的來說,Tetragon 提供了一個針對 Kubernetes 環(huán)境優(yōu)化的、底層的安全和監(jiān)控工具,其強大的 eBPF 支持使其在處理基礎(chǔ)設(shè)施安全事件時表現(xiàn)出色,盡管在更高層次的網(wǎng)絡(luò)協(xié)議處理上有所局限。
參考資料
[1] Tetragon: https://tetragon.io/
[2] 跟蹤策略(Tracing Policy): https://tetragon.io/docs/concepts/tracing-policy/