基於eBPF的微服務網絡安全
翻譯自:Network security for microservices with eBPF
一些開源的kubernetes工具已經開始使用eBPF,這些工具大多數與網絡,監控和安全相關。
本文不會涵蓋eBPF的方方面面,只作為一個入門指南,包括Linux內核的BPF概念,到將該功能加入到微服務環境的優勢,以及當前使用到該功能的工具,如Cilium或Weave。
理解eBPF
Berkely Packet Filters,簡稱BPF,是一個指令集,在1992年由Steven McCanne和Van Jacobso首次引入,通常用於給應用(如tcpdump)提供包過濾功能,並長期保持在Linux內核中。
BPF可以看作是一個簡單的虛機,由此抽象出的機器只有少數寄存器,棧空間,一個隱式程序計數器以及一個允許與內核的其余部分共同作用的輔助函數的概念。
內核中的VM負責將bfp字節代碼轉換為底層可以理解的結構,並提供包過濾功能。
但在此之前,為了執行報文過濾,需要將報文拷貝到用戶空間,這樣會導致效率低下,而且資源浪費嚴重。
校驗器(verifier)會校驗程序是否會觸發循環,並保證程序能夠停止(不會產生死循環)。
最近幾年,Linux社區從內核中移除了經典的BPF(cBPF,功能僅限於報文過濾和監控)解析器,並引入了一個新的指令集,稱為eBPF。
擴展的BPF帶來了更多的靈活性和可編程性,增加了新的使用場景,如跟蹤,外部使用bpf系統調用,安全訪問內核內存或快速解析等,並更新了即時(JIT)編譯器,為運行在本機上的程序翻譯eBPF。
還可以將bpf程序附加到其他內核對象上(cBPF只能附加到socket上用於socket過濾)。可附加到的對象為:Kprobes, Tracepoints, Network schedules, XDP (eXpress Data Path)等,XDP用於與共享數據結構(map)配合使用,可以在用戶空間和內核空間之間提供通信,或在不同的BPF程序間共享信息。
創建一個BPF程序
eBPF的一個重要特性是能夠使用高級語言(如C)來實現程序。LLVM有一個eBPF后端,用於編輯包含eBPF指令的ELF文件,前端(如clang)可以用於生成程序。
在一個后端轉換為字節碼后,使用bpf()系統調用加載bpf程序,並校驗安全性。JIT會將字節碼編譯進CPU架構中,並將該程序附加到內核對象上,當這些對象發生事件時會觸發程序的執行(例如,當從一個網絡接口發送報文時)。
可以參考如下資料編寫eBPF程序,:
- Using clang/LLVM to compile programs
- Go bindings for creating BPF programs
- Go library that provides utilities for loading, compiling, and debugging eBPF programs
IPTables下的容器安全策略
歷史上,容器的運行時為Docker,通過在容器主機上配置IPTables來實現安全策略以及NAT規則。
下圖中進行了5個階段:
- connect()系統調用
- 構造報文
- 通過vETH對轉發報文
- 在主機上應用iptables
- 丟棄或轉發報文
使用iptables時,可以為每個實例配置策略,但僅限於層3和層4。需要重新構包,且需要按順序處理iptables表項來對處理需要轉發的報文。
eBPF下的容器安全策略
eBPF策略能夠在整個協議棧或構包之前應用於系統調用(),而不受使用iptables的限制。由於eBPF附加到了容器網絡命名空間中,所有的通信都會被eBPF截獲和過濾。
此外還能根據程序級別的動作應用安全策略。對於每個微服務,不僅僅可以在L3和L4配置策略,也可以在L7配置策略,如REST GET/POST/PUT/DELETE或指定特定路徑,如/service1, /restricted。
使用eBPF替換iptables
從linux內核貢獻者的手上學習為什么內核社區要取代iptables,了解kubernetes 的kube-proxy面臨的問題,或為什么在容器中基於IP地址和端口使用策略不是一個好的方式。
一部分使用eBPF特性實現的開源kubernetes工具實現了高性能和低延時,特別用於監控,安全和網絡領域。
Cilium:動態網絡控制和可視化
Cilium網絡項目大量使用了eBPF,為基於容器的系統提供了路由和網絡流量的過濾。它可以在不修改內核的前提下動態地生成和應用規則。
上述例子中的L3/L4策略僅允許app2通過80端口訪問app1,不允許app3訪問app1。
[{
endpointSelector: {matchLabels:{id:app1}},
ingress:[{
fromEndpoints:[
{matchLabels:{id:app2}}
],
toPorts:[{
ports:[{ports:80, protocol:tcp}]
}]
}]
}]
我們也可以在調用層采用更嚴格的安全策略,例如限制能夠訪問/public路徑,但不能訪問/restricted 路徑。
Cilium如何工作
每個主機運行一個代理,將網絡策略定義轉換為BPF程序(而非管理iptables)。這些程序會被加載到內核中,然后附加到容器的虛擬以太網設備上,當執行這些程序時,會對每個發送和接收的報文應用這些規則。
由於BPF運行在Linux內核中,因此,能夠在不修改應用代碼或容器配置的前提下使用和更新Cilium的安全策略。
更多參見:
- API-aware Networking andSecurity
- Component overview
- 如果要了解Cilium 如何使用eBPF,可以參考BPF and XDP reference guide
TIPS:
-
Cilium 對系統的要求比較高,例如內核的版本要求Linux kernel >= 4.9.17,更多參加官方文檔
-
受限於eBPF比較新,且需要的內核版本較高,因此目前還沒有被kubernetes大規模推廣,但該網絡方案是一個大趨勢。目前calico已經支持eBPF模式(不建議生產使用),且阿里雲的Terway插件也是基於eBPF。
-
更多參見官方文檔