Falco 作為 Kubernetes 叢集的執行時安全工具,能有效監控系統呼叫,並透過 EFK 堆積疊提供集中化的日誌管理和警示分析。在 Kubernetes 環境中佈署 Falco 時,核心模組的相容性至關重要。Falco 提供多種方式建立核心模組,包含使用預編譯模組、核心標頭檔或 driverkit。driverkit 工具能簡化核心模組的建立過程,尤其適用於 KinD 等特殊環境。透過本文提供的安裝指令碼和 driverkit 使用方法,能快速在 Kubernetes 叢集中佈署 Falco,並根據需求自定義規則,有效提升叢集安全性。

使用Falco與EFK進行稽核

瞭解Falco的規則、巨集和清單

在Falco中,規則(rules)、巨集(macros)和清單(lists)是三個基本的構成要素,用於定義和觸發安全事件的警示。

規則(Rules)

規則是Falco的核心,用於定義什麼樣的事件應該觸發警示。規則由條件(condition)、輸出(output)和優先順序(priority)組成。

巨集(Macros)

巨集是一種用於簡化規則條件的機制。它允許將複雜的條件表示式封裝成一個簡單的名字,從而使規則更易讀、更易維護。

- macro: k8s_api_server
  condition: (fd.sip.name="kubernetes.default.svc.cluster.local")

清單(Lists)

清單允許將多個專案分組到一個單一的物件中,該物件可以在規則、巨集或其他清單中使用。

- list: editors
  items: [vi, nano, emacs]

內容解密:

  1. 巨集的定義:在上述範例中,k8s_api_server 巨集定義了一個條件,用於檢查伺服器IP的網域名稱是否等於 kubernetes.default.svc.cluster.local
  2. 清單的使用:清單 editors 將多個編輯器名稱分組,使得在規則條件中可以直接參照該清單,而無需列舉所有編輯器名稱。

自定義規則的建立與附加

Falco提供了一組預設的規則檔案 falco_rules.yaml,但不建議直接修改該檔案。相反,應當在 falco_rules.local.yaml 檔案中新增或修改規則。

附加到現有規則

若要修改現有的規則,需要在 falco_rules.local.yaml 檔案中使用相同的規則名稱,並新增 append: true

- rule: program_accesses_file
  append: true
  condition: and not user.name=root

建立新規則

建立新規則只需在 falco_rules.local.yaml 檔案中新增新的規則定義。

佈署Falco

本章節提供了一個名為 falco-install.sh 的指令碼,用於佈署Falco到Kubernetes叢集。佈署Falco最常見的方法是使用官方的Helm chart或DaemonSet manifest。

內容解密:

  1. 佈署方法:Falco可以透過Helm chart或DaemonSet manifest佈署到Kubernetes叢集。
  2. 自定義佈署:本文使用了一個修改過的DaemonSet安裝方法,從GitHub倉函式庫中取得。

圖表翻譯:

此圖示展示了Falco的基本架構和元件之間的關係。

圖表翻譯: 此圖示呈現了Falco的工作流程,包括如何根據規則觸發警示,以及如何與Kubernetes叢集互動。圖中顯示了Falco規則如何根據監控資料觸發警示,並受到組態檔案的影響。

Falco 核心模組安裝詳解

在 Kubernetes 環境中使用 Falco 進行系統呼叫監控,需要佈署一個與主機作業系統核心版本相容的核心模組。本章節將詳細介紹如何使用包含的指令碼安裝 Falco,以及探討 Falco 核心模組的建立和佈署過程。

使用安裝指令碼佈署 Falco

執行安裝指令碼是佈署 Falco 的簡便方法。該指令碼位於 chapter12 資料夾中,名稱為 install-falco.sh。執行此指令碼將自動完成 Falco 的安裝。同時,資料夾中也提供了 delete-falco.sh 指令碼,用於從叢集中移除 Falco。

指令碼執行步驟解析

該安裝指令碼主要分為兩個部分:

  1. 建立 Falco 探針

    • 安裝 Go 語言環境
    • 提取 Falco 的 driverkit-builder 容器
    • 從 Git 下載 driverkit 原始碼並編譯
    • 使用 driverkit 建立 ubuntu-generic Falco 探針
    • falco.ko 複製到模組資料夾
    • 使用 modprobe 新增 Falco 探針
  2. 將 Falco 新增到叢集

    • 建立 Falco 名稱空間
    • falco/falco-config 中的檔案建立名為 falco-config 的 ConfigMap
    • 佈署 Falco DaemonSet

深入理解 Falco 核心模組

Falco 透過佈署核心模組來監控主機系統的系統呼叫。由於核心模組必須與主機核心相容,因此需要根據工作節點的主機作業系統選擇合適的模組。

Falco 載入或建立核心模組的方式

Falco 嘗試透過多種方式載入或建立核心模組:

  • 如果存在與主機核心相匹配的預編譯模組,Falco 將自動下載並使用該模組。
  • 如果沒有預編譯模組可用,Falco 將嘗試使用主機上已安裝的核心標頭檔構建模組。

使用 driverkit 建立 Falco 探針

目前,Falco 提供了一種早期存取的替代方法,使用名為 driverkit 的工具來建立探針。driverkit 根據主機機器的核心資訊自動建立新的探針。本文將詳細介紹如何使用 driverkit 為 KinD 叢集建立 Falco 探針。

在沒有預編譯模組的情況下建立核心模組

如果工作節點上沒有正確的核心標頭檔,Falco Pod 將嘗試下載與主機核心版本相匹配的預編譯探針。但在某些企業環境中,由於伺服器處於隔離狀態,無法連線網際網路,因此使用 driverkit 或核心標頭檔建立方法更為常見。

使用核心標頭檔建立 Falco 模組

對於 Ubuntu 系統,可以使用以下命令下載正確的核心標頭檔:

sudo apt install linux-headers-$(uname -r)

這將根據目前執行的核心版本安裝相應的核心標頭檔。安裝後,可以在 /lib/modules/ 目錄下驗證是否成功新增了對應的核心版本目錄。

為 KinD 叢集佈署 Falco

本文選擇使用 driverkit 方法建立核心模組,以簡化在 KinD 叢集上佈署 Falco 的過程。相較於使用核心標頭檔建立方法,driverkit 提供了一種更為便捷的解決方案。

為什麼選擇 driverkit

  • 簡化了在 KinD 環境中佈署 Falco 的過程。
  • 無需在每個工作節點上安裝核心標頭檔。
  • 自動化建立與主機核心相容的 Falco 探針。

Falco 安裝流程圖示

圖表翻譯: 此圖示展示了Falco的安裝流程。首先檢查是否存在預編譯的核心模組,如果存在則直接下載使用;如果不存在,則根據情況選擇使用核心標頭檔或driverkit來建立模組。最終將Falco佈署到叢集中,完成安裝流程。

使用 Driverkit 建立 Falco 核心模組

在某些特定的使用場景中,安裝核心標頭檔案可能會面臨挑戰或根本無法實作。如果無法使用標頭檔案來建立模組,可以利用 Falco 提供的一個名為 driverkit 的工具來建立核心模組。

Driverkit 簡介與支援的 Linux 發行版

Driverkit 允許為多種不同的 Linux 發行版建立核心模組。目前,該工具支援以下發行版:

  • Ubuntu-generic
  • Ubuntu-aws
  • CentOS 8
  • CentOS 7
  • CentOS 6
  • AmazonLinux
  • AmazonLinux2
  • Debian
  • Vanilla Kernel

開發團隊正在積極徵求其他發行版的建議,因此隨著 driverkit 的發展,可以預期將支援更多發行版。

使用 Driverkit 建立 Ubuntu 核心模組

Driverkit 的先決條件

在開始使用 driverkit 建立模組之前,需要滿足幾個先決條件:

  • 一個正在執行的 Docker 守護程式。
  • 已安裝 Go(由於我們使用的是 Ubuntu,因此將使用 longsleep/golang-backports)。
  • 目標核心版本和核心修訂版。

安裝 Falco 的 Driverkit

建立核心模組的第一步是安裝 driverkit 所需的依賴項:

  1. 首先,需要安裝 Go。由於我們使用的是 Ubuntu,可以使用 snap 安裝 Go:
sudo snap install --classic go
  1. 我們選擇使用 Docker 建構方法進行建構。driverkit 專案頁面中記載了多種建構方法,如果您想使用不同的建構方法,可以參考相關檔案。我們將提取 Docker 映像,以便在執行建構時準備就緒:
docker pull falcosecurity/driverkit-builder
  1. 下載容器後,可以建立 driverkit 可執行檔。建構過程將從 GitHub 下載原始碼,然後使用 Go 建立可執行檔。整個過程需要幾分鐘才能完成:
GO111MODULE="on" go get github.com/falcosecurity/driverkit
  1. 可執行檔將在您的 Go 路徑中建立。要驗證 driverkit 可執行檔是否成功建立,請輸入以下命令檢查版本:
driverkit -v
  1. 這可能會傳回版本號,或者在目前的早期版本中,可能只傳回以下內容:
driverkit version -+

如果 driverkit 命令傳回 -+ 或版本號,則表示成功建立。但是,如果在檢查版本時收到 driverkit: command not found 錯誤,則建構可能失敗,或者您的 Go 路徑在環境變數中未正確設定。如果在執行建構後找不到可執行檔,請驗證您的 Go 環境變數是否正確,然後再次執行 Go 建構步驟。

建立模組並將其新增至主機

在建立並驗證 driverkit 之後,我們可以建立我們的模組並將其新增至主機。在建立模組之前,需要知道主機的核心版本和修訂版。以我們在本文前幾章中使用的 KinD 叢集為例,Linux 有一些內建命令可以取得我們需要的兩個詳細資訊:

  1. 要取得核心版本,請執行 uname -v,而要取得修訂版,請執行 uname -r
uname -v
uname -r

此圖顯示了 Docker 主機的核心版本。

  1. 如果您正在使用安裝指令碼,我們將檢索選項並自動提供它們。如果您手動執行此步驟,可以使用以下兩行程式碼將資訊儲存在變數中,以傳遞給建構命令:
kernelversion=$(uname -v | cut -f1 -d'-' | cut -f2 -d'#')
kernelrelease=$(uname -r)

我們使用 cut 命令從 uname -v 命令中移除不必要的資訊,並將其儲存在名為 kernelversion 的變數中。我們還將 uname -r 命令的輸出儲存在名為 kernelrelease 的變數中。

  1. 現在,您可以使用我們提取的 Docker 映像和 driverkit 可執行檔來建立模組:
driverkit docker --output-module /tmp/falco.ko --kernelversion=$kernelversion --kernelrelease=$kernelrelease --driverversion=dev --target=ubuntu-generic

內容解密:

此命令使用 driverkit 工具,以 Docker 建構方法建立 Falco 核心模組。其中,--output-module 指定了輸出的模組檔案路徑,--kernelversion--kernelrelease 指定了目標核心的版本和修訂版,--driverversion 指定了驅動程式的版本,--target 指定了目標 Linux 發行版。

  1. 模組建構過程需要一分鐘,建構完成後,driverkit 將顯示新模組的位置:
INFO driver building, it will take a few seconds processor=docker
INFO kernel module available path=/tmp/falco.ko
  1. 最後一步是將新模組複製到正確的位置,並使用 modprobe 載入模組:
sudo cp /tmp/falco.ko /lib/modules/$kernelrelease/falco.ko
sudo depmod
sudo modprobe falco
  1. 您可以使用 lsmod 命令驗證模組是否已新增:
lsmod | grep falco

如果載入成功,您將看到類別似以下的輸出:

falco 634880 4

這樣,您就在主機上安裝了 Falco 模組,並且可以讓 KinD 叢集使用它。

在叢集上使用模組

在標準的 Kubernetes 叢集中,Falco 佈署會將 Falco 容器中的 /dev掛載點對映到主機的 /dev 掛載點。透過掛載 /dev,Falco pod 可以使用在工作節點主機作業系統上執行的核心模組。

在 KinD 中使用模組

您可能會問自己,將 Falco 模組新增到主機上如何使其可供 KinD 叢集使用?我們只將其新增到主機本身,而 KinD 叢集是在另一個 Docker 容器中執行的容器。那麼,KinD pod 如何使用來自 Docker 主機的模組?

Falco 模組載入流程

@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle

title Falco與EFK整合Kubernetes稽核

package "Kubernetes Cluster" {
    package "Control Plane" {
        component [API Server] as api
        component [Controller Manager] as cm
        component [Scheduler] as sched
        database [etcd] as etcd
    }

    package "Worker Nodes" {
        component [Kubelet] as kubelet
        component [Kube-proxy] as proxy
        package "Pods" {
            component [Container 1] as c1
            component [Container 2] as c2
        }
    }
}

api --> etcd : 儲存狀態
api --> cm : 控制迴圈
api --> sched : 調度決策
api --> kubelet : 指令下達
kubelet --> c1
kubelet --> c2
proxy --> c1 : 網路代理
proxy --> c2

note right of api
  核心 API 入口
  所有操作經由此處
end note

@enduml

圖表翻譯: 此圖表描述了 Falco 核心模組的載入流程。首先,建立 Driverkit,接著建立 Falco 核心模組,然後將模組新增至主機。最後,在 Kubernetes 叢集中佈署 Falco,並透過掛載 /dev 使 Falco Pod 能夠使用核心模組。