Lúc 2 giờ sáng và một cái alert khiến mình tỉnh giấc
Cluster Kubernetes đang chạy ổn. Prometheus + Grafana báo CPU, memory bình thường. Không có pod nào crash. Nhưng hệ thống thanh toán xử lý chậm bất thường — chậm theo kiểu không giải thích được bằng metric thông thường.
Sau 40 phút đào bới log, mình tìm ra vấn đề: một container đang chạy một tiến trình curl gọi ra ngoài internet mỗi 30 giây. Không phải code ứng dụng. Không phải cron job nào được cấu hình. Image bị compromise từ lúc nào không hay.
Prometheus + Grafana lúc đó đang theo dõi 15 server. Metric đầy đủ, dashboard sạch sẽ. Setup đó rất tốt cho metrics cơ sở hạ tầng — nhưng mù tịt với những gì đang xảy ra bên trong container ở tầng syscall. Đó là lúc mình quyết định triển khai Falco.
Falco là gì và tại sao nó khác với những gì bạn đang dùng
Falco do Sysdig phát triển, hiện là dự án CNCF graduated. Điểm làm nó khác biệt không phải thương hiệu — mà là chỗ nó nhìn vào: thay vì metrics hay log, nó nghe trực tiếp ở tầng Linux kernel syscall. Mọi thứ container làm — mở file, tạo process, kết nối mạng — đều đi qua đây.
Nếu Prometheus + Grafana trả lời câu hỏi “hệ thống đang hoạt động thế nào”, thì Falco trả lời “ai đang làm gì bên trong container của tôi”.
Cơ chế hoạt động
Có hai cách để Falco hook vào kernel:
- Kernel module: load module trực tiếp vào kernel — hiệu năng cao hơn nhưng cần quyền đặc biệt và phụ thuộc kernel version.
- eBPF probe: dùng eBPF (extended Berkeley Packet Filter) — an toàn hơn, không cần kernel module, là lựa chọn recommended cho Kubernetes hiện đại.
Cơ chế khá trực tiếp: đọc syscall theo thời gian thực, so với tập rules định nghĩa bằng YAML, bắn alert khi match. Rules mặc định đã cover những pattern nguy hiểm phổ biến nhất: shell trong container, đọc file /etc/shadow, mount sensitive path, leo thang đặc quyền.
Cài đặt Falco trên Kubernetes với Helm
Điều kiện tiên quyết
- Kubernetes cluster (1.19+)
- Helm 3.x
- kubectl có quyền cluster-admin
Bước 1: Thêm Helm repository và cài đặt
# Thêm repo Falco
helm repo add falcosecurity https://falcosecurity.github.io/charts
helm repo update
# Tạo namespace riêng
kubectl create namespace falco
# Cài đặt Falco với eBPF driver (recommended)
helm install falco falcosecurity/falco \
--namespace falco \
--set driver.kind=ebpf \
--set falcosidekick.enabled=true \
--set falcosidekick.webui.enabled=true
Flag falcosidekick.enabled=true cài thêm Falcosidekick — forwarder chuyển alert từ Falco sang Slack, Telegram, PagerDuty, Elasticsearch và hơn 50 output khác. Bỏ qua nó là mình không có cách nào nhận alert ngoài đọc log thủ công.
Bước 2: Kiểm tra pod đang chạy
kubectl get pods -n falco
# Output mong đợi:
# NAME READY STATUS RESTARTS
# falco-6xk9p 2/2 Running 0
# falco-falcosidekick-7d8f9c-abc12 1/1 Running 0
# falco-falcosidekick-ui-5f6b8d-xyz34 1/1 Running 0
Falco chạy như DaemonSet — một pod trên mỗi node, đảm bảo toàn bộ cluster được cover.
Bước 3: Xem alert đầu tiên
# Xem log realtime từ Falco
kubectl logs -n falco -l app.kubernetes.io/name=falco -f
# Thử trigger một alert: exec vào container đang chạy
kubectl exec -it <pod-name> -- /bin/sh
# Trong log Falco, bạn sẽ thấy ngay:
# Notice A shell was spawned in a container with an attached terminal
# (user=root shell=sh parent=runc cmdline=sh container_id=abc123...)
Chỉ cần exec vào một container là đủ để trigger alert. “Terminal shell in container” là một trong những dấu hiệu đáng ngờ nhất — developer thỉnh thoảng làm vậy để debug, nhưng attacker cũng làm vậy sau khi vào được.
Tùy chỉnh rules cho môi trường của bạn
Rules mặc định của Falco khá noisy — nhiều false positive nếu team bạn thỉnh thoảng exec vào container để debug. Cần tuning.
Tạo custom rules
Tạo file custom-rules.yaml:
customRules:
custom-rules.yaml: |-
# Cho phép exec vào container trong namespace 'dev' không alert
- rule: Terminal shell in container
condition: >
spawned_process
and container
and shell_procs
and proc.tty != 0
and not container.image.repository in (trusted_images)
and not k8s.ns.name in (dev, staging)
desc: A shell was spawned in a container
output: >
Shell spawned in production container
(user=%user.name container=%container.name image=%container.image.repository
pod=%k8s.pod.name ns=%k8s.ns.name)
priority: WARNING
tags: [shell, mitre_execution]
# Rule mới: phát hiện cryptocurrency miner
- rule: Outbound connection to known crypto mining pool
desc: Detect connection to cryptocurrency mining pools
condition: >
outbound
and fd.sip.name in (mining_pool_domains)
output: >
Crypto mining connection detected
(pod=%k8s.pod.name image=%container.image.repository
dest=%fd.sip.name:%fd.sport)
priority: CRITICAL
tags: [network, cryptomining]
# Apply custom rules
helm upgrade falco falcosecurity/falco \
--namespace falco \
--set driver.kind=ebpf \
--set falcosidekick.enabled=true \
-f custom-rules.yaml
Kiểm tra rule có được load
# Kiểm tra Falco đọc rule thành công, không có syntax error
kubectl logs -n falco -l app.kubernetes.io/name=falco | grep -E "(rule|error|warn)" | head -20
Kết nối Falco với Slack hoặc Telegram
Falcosidekick hỗ trợ 50+ output. Cấu hình Slack là nhanh nhất:
helm upgrade falco falcosecurity/falco \
--namespace falco \
--set driver.kind=ebpf \
--set falcosidekick.enabled=true \
--set falcosidekick.config.slack.webhookurl="https://hooks.slack.com/services/YOUR/WEBHOOK" \
--set falcosidekick.config.slack.minimumpriority="warning"
Từ đó, mỗi khi có shell trong container, ai đó truy cập /proc/*/mem, hay file /etc/passwd bị ghi vào — Slack sẽ ping ngay. Alert kèm đủ context: pod name, namespace, image, user, command line.
Xem Falcosidekick UI
# Port-forward để xem dashboard
kubectl port-forward svc/falco-falcosidekick-ui 2802:2802 -n falco
# Mở trình duyệt: http://localhost:2802
Mình hay mở UI này khi điều tra incident. Timeline alert, filter theo priority (Critical/Warning/Notice), theo namespace, theo rule — nhìn vào là ra ngay cái gì đang xảy ra và từ lúc nào.
Những rule nên bật ngay từ đầu
Hàng trăm rules đi kèm sẵn, nhưng không phải cái nào cũng quan trọng như nhau. Dưới đây là những cái mình thấy có giá trị nhất trong môi trường production:
- Write below etc: bất kỳ tiến trình nào ghi vào
/etc— cực kỳ bất thường trong container. - Read sensitive file untrusted: đọc
/etc/shadow,/etc/sudoers, SSH private key. - Netcat Remote Code Execution in Container: netcat/ncat dùng để tạo reverse shell.
- Contact K8S API Server From Container: container gọi trực tiếp vào Kubernetes API — có thể là container escape.
- Privilege Escalation Using Sudo: sudo trong container là red flag rõ ràng.
Kết luận
Sau sự cố lúc 2 giờ sáng đó, mình deploy Falco lên toàn bộ cluster ngay tuần sau. Từ đó đến nay, nó đã bắt được hai lần nữa: một lần là container bị inject reverse shell qua lỗ hổng deserialization, một lần là developer vô tình để credential hardcode trong image và bị script kiddies scan ra.
Falco không thay thế Prometheus hay Grafana — nó lấp cái lỗ hổng mà metric-based monitoring không nhìn thấy được. Metric cho bạn biết hệ thống chậm; Falco cho bạn biết tại sao — và đôi khi câu trả lời không phải là performance issue mà là security incident.
Nếu cluster của bạn đang chạy workload production mà chưa có runtime security monitoring, đây là thứ nên có trước khi sự cố xảy ra, không phải sau.

