Linux 核心網路包路徑追蹤利器 skbtracer,Go 語言版本
skbtracer 是基於 eBPF 技術的 skb 網路包路徑追蹤利器,基於 goebpf , libbpf-bootstrap (required Linux Kernel 4.15+ with CONFIG_DEBUG_INFO_BTF=y, Go 1.16+) 實現,參考 Python 版本 github.com/DavadDi/skbtracer。
skbtracer 是一個 Linux 可執行檔案,不依賴 libbcc.so 動態連結庫,就可以在開啟了 CONFIG_DEBUG_INFO_BTF 的環境中執行。
使用
執行效果:
$ sudo ./skbtracer -c 10
TIME NETWORK_NS CPU INTERFACE DEST_MAC IP_LEN PKT_INFO TRACE_INFO
[13:43:45] [0 ] 3 nil 00:00:00:00:00:00 168 T_ACK,PSH:10.0.1.10:22->10.0.4.15:55343 ffff9a271b1b3ae0.0:ip_output
[13:43:45] [0 ] 3 ens18 00:00:00:00:00:00 168 T_ACK,PSH:10.0.1.10:22->10.0.4.15:55343 ffff9a271b1b3ae0.0:ip_finish_output
[13:43:45] [0 ] 3 ens18 00:00:00:00:00:00 168 T_ACK,PSH:10.0.1.10:22->10.0.4.15:55343 ffff9a271b1b3ae0.0:__dev_queue_xmit
[13:43:45] [0 ] 3 nil 00:00:00:00:00:00 248 T_ACK,PSH:10.0.1.10:22->10.0.4.15:55343 ffff9a271b1b36e0.0:ip_output
[13:43:45] [0 ] 3 ens18 00:00:00:00:00:00 248 T_ACK,PSH:10.0.1.10:22->10.0.4.15:55343 ffff9a271b1b36e0.0:ip_finish_output
[13:43:45] [0 ] 3 ens18 00:00:00:00:00:00 248 T_ACK,PSH:10.0.1.10:22->10.0.4.15:55343 ffff9a271b1b36e0.0:__dev_queue_xmit
[13:43:45] [0 ] 3 nil 00:00:00:00:00:00 120 T_ACK,PSH:10.0.1.10:22->10.0.4.15:55343 ffff9a271b1b2ce0.0:ip_output
[13:43:45] [0 ] 3 ens18 00:00:00:00:00:00 120 T_ACK,PSH:10.0.1.10:22->10.0.4.15:55343 ffff9a271b1b2ce0.0:ip_finish_output
[13:43:45] [0 ] 3 ens18 00:00:00:00:00:00 120 T_ACK,PSH:10.0.1.10:22->10.0.4.15:55343 ffff9a271b1b2ce0.0:__dev_queue_xmit
[13:43:45] [0 ] 3 nil 00:00:00:00:00:00 120 T_ACK,PSH:10.0.1.10:22->10.0.4.15:55343 ffff9a271b1b30e0.0:ip_output
15 event(s) received
0 event(s) lost (e.g. small buffer, delays in processing)
使用幫助:
$ ./skbtracer -h
examples:
skbtracer # trace all packets
skbtracer --proto=icmp -H 1.2.3.4 --icmpid 22 # trace icmp packet with addr=1.2.3.4 and icmpid=22
skbtracer --proto=tcp -H 1.2.3.4 -P 22 # trace tcp packet with addr=1.2.3.4:22
skbtracer --proto=udp -H 1.2.3.4 -P 22 # trace udp packet wich addr=1.2.3.4:22
skbtracer -t -T -p 1 -P 80 -H 127.0.0.1 --proto=tcp --callstack --icmpid=100 -N 10000
Usage:
skbtracer [flags]
Flags:
--callstack output kernel stack trace (DEPRECATED: not implemented to print the function stack)
-c, --catch-count uint catch and print count (default 1000)
--dropstack output kernel stack trace when drop packet (DEPRECATED: not supported on Ubuntu 18.04.5 LTS with kernel 5.10.29-051029-generic)
-h, --help help for skbtracer
--icmpid uint trace icmp id
-H, --ipaddr string ip address
--iptable output iptable path
--keep keep trace packet all lifetime (DEPRECATED: not implemented yet)
-N, --netns uint trace this Network Namespace only
--noroute do not output route path
-p, --pid uint trace this PID only
-P, --port uint udp or tcp port
--proto string tcp|udp|icmp|any
-T, --time show HH:MM:SS timestamp (default true)
-t, --timestamp show timestamp in seconds at us resolution
編譯
編譯 skbtracer 需要使用較新版本的 llvm,要求 Go 語言的版本 1.16 及以上,因為需要使用 embed
包將 BPF 的 ELF 檔案內嵌到 Go 程式裡面,不依賴 Linux 核心標頭檔案。
只需要以下幾步即可編譯得到可執行檔案:
$ git clone https://github.com/Asphaltt/skbtracer.git
$ cd skbtracer
$ make
$ ./bin/skbtracer -h # 可執行檔案在 bin 目錄下
實現原理
使用 clang -target bpf
編譯 BPF 程式碼,得到對應的 ELF 檔案。
然後在 Go 程式碼裡使用
//go:embed skbtracer.elf
var bpfProg []byte
將 BPF ELF 檔案內嵌進來。接著使用 goebpf 載入 BPF ELF 檔案,並將 BPF 程式裝載到核心裡去執行。
BPF 程式通過 perf event 將網路包路徑資訊傳送到 Go 程式,Go 程式就可以解析 perf event 得到 struct。
BPF 程式裡使用以下 kprobe
追蹤網路包路徑資訊:
- netif_rx
- __netif_receive_skb
- tpacket_rcv
- packet_rcv
- napi_gro_receive
- __dev_queue_xmit
- br_handle_frame_finish
- br_nf_pre_routing
- br_nf_pre_routing_finish
- br_pass_frame_up
- br_netif_receive_skb
- br_forward
- __br_forward
- br_forward_finish
- br_nf_forward_ip
- br_nf_forward_finish
- br_nf_post_routing
- br_nf_dev_queue_xmit
- ip_rcv
- ip_rcv_finish
- ip_output
- ip_finish_output
使用 kprobe
、kretprobe
探測 ipt_do_table
去追蹤網路包的 iptables 資訊。
相關文件
- 使用 ebpf 深入分析容器網路 dup 包問題
- 使用 Linux tracepoint、perf 和 eBPF 跟蹤資料包 (2017)
- BPF Portability and CO-RE
- BPF binaries: BTF, CO-RE, and the future of BPF perf tools
更多原創文章乾貨分享,請關注公眾號
- 加微信實戰群請加微信(註明:實戰群):gocnio
相關文章
- 網路安全追蹤利器IpTicker
- go的鏈路追蹤Go
- GO語言————6.4 defer 和追蹤Go
- 分散式鏈路追蹤的利器——Zipkin分散式
- Go 鏈路追蹤入門 OpentelemetryGo
- Rust 語言的全鏈路追蹤庫 tracingRust
- Go - 實現專案內鏈路追蹤Go
- go語言工程專案錯誤找不到路徑Go
- go-kit微服務:服務鏈路追蹤Go微服務
- Jaeger Client Go 鏈路追蹤|入門詳解clientGo
- Go - 實現專案內鏈路追蹤(二)Go
- (16)go-micro微服務jaeger鏈路追蹤Go微服務
- Go 語言多版本安裝及管理利器 - GVMGo
- 容器網路中的 Iptables 包路徑
- go-zero的全鏈路追蹤與超時Go
- 匿名網路追蹤溯源機制及方法
- 跟蹤Kubernetes中的網路流量路徑
- 網路語言
- go-zero 是如何追蹤你的請求鏈路?Go
- Spring Cloud 鏈路追蹤SpringCloud
- skywalking鏈路追蹤
- 上海登陸最強颱風 & 颱風路徑追蹤 All In One
- go-zero 是如何追蹤你的請求鏈路的Go
- 前後端、多語言、跨雲部署,全鏈路追蹤到底有多難?後端
- 龍蜥開源核心追蹤利器 Surftrace:協議包解析效率提升 10 倍! | 龍蜥技術協議
- 深入Go語言網路庫的基礎實現Go
- Go 語言學習路線指南Go
- 分散式鏈路追蹤技術分散式
- Spring Cloud Sleuth 鏈路追蹤SpringCloud
- 古語與網路語言
- go-kit 微服務 服務鏈路追蹤 (jaeger 實現)(2)Go微服務
- go-kit 微服務 服務鏈路追蹤 (jaeger 實現)(1)Go微服務
- 一文詳解|Go 分散式鏈路追蹤實現原理Go分散式
- Go微服務框架go-kratos實戰05:分散式鏈路追蹤 OpenTelemetry 使用Go微服務框架分散式
- 最新網路流行語言
- Go 語言編寫輕量級網路庫,GrapeNetGo
- 如何追蹤Go動態Go
- 網路廣告商的畫素追蹤是如何工作的?