Pipy 與 BPF:打造無侵入無感知的流量攔截方案
背景
在當代的互聯網技術領域,微服務架構已成爲應用部署的主流模式,它雖然增強了開發流程的敏捷性和系統的可擴展性,但隨着服務數量的增加,系統的內部通信變得越來越複雜。特別是在服務的接口和依賴關係不透明的情況下,整個系統的維護和優化工作變得異常困難。
今天要介紹的流量攔截技術,從本質上講,提供了一種 “上帝視角” 來觀察和分析在複雜網絡系統中流動的數據。這種方法使得開發和運維團隊能夠對通常隱蔽和不透明的服務間交互進行“抽絲剝繭”,揭露隱藏在數據流中的詳細信息和交互模式。通過這種高度的可視化和分析能力,團隊可以深入理解服務的運行機制,即使這些服務表面上看起來像是封閉和不透明的“黑盒”。
方案
Pipy 的升級到 1.0 版本 標誌着它從一個單純處理數據流的代理,轉變爲一個全面的可編程應用引擎。這一重要的演進不僅擴展了 Pipy 的使用場景,也極大地提高了其在現代網絡架構中的價值和靈活性。將 Pipy 作爲 BPF(Berkeley Packet Filter)的控制器使用,是其作爲控制面能力的一個典型示例。這種能力的加入,爲網絡流量管理和系統監控提供了更加強大和靈活的工具。
本方案利用 Pipy 代理作爲控制面,在主機節點上加載 BPF(Berkeley Packet Filter)程序,根據預設的配置(如端口映射關係)動態攔截並轉發目標流量。這一過程中,訪問原始端口(originalPort)的流量會被轉發到一個監聽指定端口(port)上的代理服務。代理服務進一步根據流量的協議類型,對數據包進行解碼和結構化處理,然後將解析後的請求內容通過 HTTP 協議發送到如 Elasticsearch 的存儲進行存儲和分析。此外,流量還會被原封不動地轉發到原始目標端口,確保服務的連續性和透明性。
接下來我們演示如何使用 Pipy 來進行 HTTP 和 Dubbo 的流量攔截和分析。
演示
這篇演示中,我們將用到項目 traffic-interceptor[1],這個項目中包含三個部分:
-
• rest2dubbo:使用 Pipy 做 HTTP 到 Dubbo 的協議轉換。
-
• port-interceptor:使用 Pipy 實現的端口攔截控制器,通過 BPF 將訪問某些原始端口(originalPort)的流量轉發到指定的端口(port)進行流量攔截。
-
• traffic-dump:使用 Pipy 實現的代理,監聽指定的端口(port)然後將流量轉發到原始端口(originalPort),同時會將流量的信息結構化後發送到 ElasticSearch 中。
下面是演示的架構圖:
前置條件
-
• Ubuntu 22.04(內核版本 6.5):運行 Dubbo 和 HTTP 應用的主機
-
• 客戶端主機(系統類型不限):用於運行 rest2dubbo 代理、發起 HTTP 請求
-
• 下載並安裝 Pipy 1.0.0[2]
-
• Docker
-
• jq
環境準備
- 1. 啓動 Dubbo 應用,服務在
20880
端口。
docker run --rm -d --name bookwarehouse -e spring.profiles.active=dubbo,dev -e dubbo.registry.register=false -p 20880:20880 addozhang/bookwarehouse-dubbo:0.3.1
-
- 啓動 HTTP 應用。
pipy "pipy.listen(8000, $ => $.serveHTTP(new Message('Hi, Pipy')))"
-
- 啓動 ElasticSearch。
docker run --rm -d --name es -p 9200:9200 -e "discovery.type=single-node" docker.elastic.co/elasticsearch/elasticsearch:7.10.1
環境驗證
在客戶端主機上,啓動 rest2dump 代理。這個代理會接收 HTTP 請求,通過協議轉換成 Dubbo 請求後轉發給上面的 Dubbo 應用。
git clone https://github.com/flomesh-io/pipy-demos.git
cd pipy-demos/traffic-interceptor
在啓動代理之前,需要將 rest2dubbo/main.js
中的 上游服務地址 [3] 改爲運行 Dubbo 服務的主機地址,比如我使用的主機地址是 20.24.215.69
。然後啓動代理。
pipy rest2dubbo/main.js
啓動成功後從日誌中可以看到其監聽 8888
端口,通過 curl
來發送請求。
curl 'http://127.0.0.1:8888/v1/getBook' --header 'Content-Type: application/json' --data '{"id": 1}'
將收到如下響應。這說明我們的 rest2dump 的協議轉換代理運行正常。
{
"date": "2024-03-14T15:18:56.982Z",
"isbn": "9787517054221",
"author": "Flomesh",
"name": "Pipy 入門",
"value": 0,
"id": "1"
}
同樣測試 HTTP 應用的訪問。
curl http://20.24.215.69:8000/hi
正常收到響應。
Hi, Pipy
接下來我們就可以測試流量攔截了,先啓動 Traffic Dump 代理。
啓動 Traffic Dump 代理
Traffic Dump 代理的運行很簡單,執行下面的命令。
git clone https://github.com/flomesh-io/pipy-demos.git
cd pipy-demos/traffic-interceptor
pipy traffic-dump/main.js
運行之後可以從日誌中可以看到其監聽 9000
和 30880
兩個端口。
啓動端口攔截
首先我們需要編譯 BPF 程序。
cd port-interceptor
make
在 bin
目錄中可以看到編譯好的 BPF 程序 port-interceptor.o
。
執行下面的命令啓動端口攔截。
sudo pipy /main.js
注意:該腳本需要
sudo
,因爲它需要調用tc
將 BPF 程序掛接到內核中的數據路徑,這需要管理員權限。
啓動後可以看到 Pipy 更新 BPF map 以及加載 BPF 程序的日誌。
2024-03-14 15:48:11.881 [INF] Updating BPF maps...
2024-03-14 15:48:11.881 [INF] Created port mapping 8000 <---> 9000
2024-03-14 15:48:11.881 [INF] Created port mapping 8443 <---> 9443
2024-03-14 15:48:11.881 [INF] Created port mapping 20880 <---> 30880
驗證
再次重發上面的 HTTP 和 Dubbo 請求,都可以正常收到響應。
curl http://20.24.215.69:8000/hi
curl 'http://127.0.0.1:8888/v1/getBook' --header 'Content-Type: application/json' --data '{"id": 1}'
訪問 ElasticSearch 查詢保存的請求記錄。
HTTP 請求:
curl -s -X GET "http://localhost:9200/http/_search" -H 'Content-Type: application/json' | jq .hits.hits
[
{
"_index": "http",
"_type": "_doc",
"_id": "W9mqPY4Bi_IvwOBjFiex",
"_score": 1,
"_source": {
"time": 1710431540691,
"host": "20.24.215.69:8000",
"path": "/hi",
"headers": "{\"host\":\"20.24.215.69:8000\",\"user-agent\":\"curl/8.4.0\",\"accept\":\"*/*\"}"
}
}
]
Dubbo 請求:
curl -s -X GET "http://localhost:9200/dubbo/_search" -H 'Content-Type: application/json' | jq .hits.hits
[
{
"_index": "dubbo",
"_type": "_doc",
"_id": "WtmqPY4Bi_IvwOBjEycL",
"_score": 1,
"_source": {
"time": 1710431539513,
"dubboVer": "2.0.2",
"interface": "io.flomesh.demo.api.BookWarehouseService",
"ver": "v1",
"method": "getBook",
"args": [
"Ljava/lang/String;",
"1"
],
"raw": "[\"2.0.2\",\"io.flomesh.demo.api.BookWarehouseService\",\"v1\",\"getBook\",\"Ljava/lang/String;\",\"1\",{\"kind\":\"map\",\"elements\":[[\"input\",\"196\"],[\"path\",\"io.flomesh.demo.api.BookWarehouseService\"],[\"interface\",\"io.flomesh.demo.api.BookstoreService\"],[\"version\",\"v1\"]]}]"
}
}
]
Bingo!演示完成。
總結
通過這一系列步驟,我們展現瞭如何利用 Pipy 來實施流量攔截與分析,全部操作均在無需改動現有網絡結構和應用代碼的前提下完成。
Pipy 1.0 的發佈,不僅代表了其從一個數據面代理向可編程應用引擎的轉變,也預示着其在現代網絡架構中角色的重大擴展。Pipy 的高度可編程性和靈活性使其成爲實現精細流量管理和深度網絡分析的強大工具。無論是提高網絡透明度、優化服務性能,還是加強安全防護,Pipy 都能提供有效的支持。
關於 Flomesh
Flomesh(易衡科技)成立於 2018 年,自主研發並開源了高性能可編程代理 Pipy(https://github.com/flomesh-io/pipy)。以 Pipy 爲基礎,Flomesh 研發了軟件負載均衡、服務網格兩款軟件產品。爲工信部認證的可信雲產品、可信開源項目。
Flomesh 核心競爭力來自完全自研的核心組件 Pipy,該組件高性能、高可靠、低延遲、可編程、可擴展、低依賴,採用 C++ 開發,內置自研的 JS 引擎,支持適用 JS 腳本做擴展開發。支持包括 x86、arm、龍芯、海光等硬件 CPU 架構;支持 Linux、FreeBSD、macOS、Windows、OpenWrt 等多種核心的操作系統。
Flomesh 成立以來,以技術爲根基、以客戶爲導向,產品被應用在頭部股份制商業銀行總行、大型保險公司、運營商總部以及研究院等衆多客戶和多個場景。
引用鏈接
[1]
traffic-interceptor: https://github.com/flomesh-io/pipy-demos/tree/main/traffic-interceptor
[2]
Pipy 1.0.0: https://github.com/flomesh-io/pipy/releases/tag/1.0.0-1
[3]
上游服務地址: https://github.com/addozhang/rest2dubbo_mtls/blob/main/pipy-rest2dubbo-proxy/main.js#L63
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/_7uOdli5yKXAhsVkNdLGkQ