golang基于eBPF实现TCP网络监控与分析插件tcpdog的使用
Golang基于eBPF实现TCP网络监控与分析插件tcpdog的使用
概述
TCPDog是一个完整的解决方案,通过eBPF从Linux内核高效导出TCP统计信息,并将其存储到Elasticsearch或InfluxDB数据库中,包含Geo和ASN信息。它可以通过简单的yaml配置同时处理所有TCP跟踪点,并提供不同的自定义请求。
主要特性
- 通过eBPF TCP跟踪点获取TCP socket统计信息
- 同时支持所有TCP跟踪点
- 在内核空间自定义TCP字段
- 支持Elasticsearch、ClickHouse或InfluxDB作为数据存储
- 通过gRPC或Kafka进行中央收集
- 支持内核空间的采样和过滤
- 通过Maxmind支持Geo和ASN信息
系统要求
- Linux内核版本4.16及以上
- Libbcc
安装与使用示例
基本使用示例
package main
import (
"context"
"log"
"time"
"github.com/mehrdadrad/tcpdog/config"
"github.com/mehrdadrad/tcpdog/ebpf"
"github.com/mehrdadrad/tcpdog/egress"
)
func main() {
// 加载配置文件
cfg, err := config.Load("config.yaml")
if err != nil {
log.Fatal(err)
}
// 初始化eBPF
bpf, err := ebpf.New(cfg)
if err != nil {
log.Fatal(err)
}
defer bpf.Close()
// 初始化输出插件(如Elasticsearch)
egress, err := egress.New(cfg)
if err != nil {
log.Fatal(err)
}
// 创建上下文
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
// 启动监控
go bpf.Start(ctx)
// 处理数据
for {
select {
case <-ctx.Done():
return
case data := <-bpf.Chan():
// 发送数据到输出插件
if err := egress.Send(data); err != nil {
log.Printf("发送数据失败: %v", err)
}
default:
time.Sleep(1 * time.Second)
}
}
}
配置示例 (config.yaml)
ebpf:
tracepoints:
- tcp:tcp_probe
- tcp:tcp_retransmit_skb
fields:
- RTT
- AdvMSS
- TotalRetrans
- SAddr
- DAddr
- DPort
- LPort
- BytesReceived
- BytesSent
sampling: 1
egress:
type: elasticsearch
config:
hosts:
- "http://localhost:9200"
index: "tcpdog-%{+2006.01.02}"
flush_interval: 10s
geo:
enabled: true
path: "/usr/share/GeoIP/GeoLite2-City.mmdb"
asn:
enabled: true
path: "/usr/share/GeoIP/GeoLite2-ASN.mmdb"
数据输出示例
JSON Lines格式输出
[RTT,AdvMSS,TotalRetrans,SAddr,DAddr,DPort,LPort,BytesReceived,BytesSent,timestamp]
[172,1460,0,"10.0.2.15","103.17.108.173",80,0,456,73,1612298721]
[55,1460,0,"10.0.2.15","187.141.67.60",80,0,389,74,1612298722]
[140,1460,0,"10.0.2.15","154.118.230.171",443,0,5209,551,1612298723]
[118,1460,0,"10.0.2.15","88.204.157.165",443,0,4445,514,1612298724]
[8,1460,0,"10.0.2.15","47.254.92.5",80,0,760,70,1612298731]
[1,1460,0,"10.0.2.15","184.51.206.209",443,0,4820,577,1612298735]
[238,1460,0,"10.0.2.15","164.100.61.151",80,0,141,71,1612298737]
[171,1460,0,"10.0.2.15","77.238.121.220",80,0,158,74,1612298742]
Kibana可视化示例
许可证
该项目使用MIT许可证,请阅读LICENSE文件。
贡献
欢迎任何形式的贡献,请按照以下步骤进行:
- 在github.com上fork该项目
- 创建一个新的分支
- 将更改提交到新分支
- 发送pull请求
更多关于golang基于eBPF实现TCP网络监控与分析插件tcpdog的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
更多关于golang基于eBPF实现TCP网络监控与分析插件tcpdog的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
基于eBPF的TCP网络监控与分析工具tcpdog
tcpdog是一个基于eBPF技术的TCP网络监控与分析工具,它能够高效地捕获和分析TCP网络流量,提供详细的连接统计和性能指标。
tcpdog简介
tcpdog利用Linux内核的eBPF功能,无需修改内核代码即可实现对TCP连接的监控,具有以下特点:
- 低开销:在内核空间进行数据过滤和处理
- 高精度:能够捕获微秒级的TCP事件
- 丰富指标:提供RTT、重传、窗口大小等关键指标
安装与依赖
首先确保系统满足以下要求:
- Linux内核版本 >= 4.9
- 已安装LLVM和clang
- 已安装libbpf和BPF Compiler Collection (BCC)
# 安装依赖
sudo apt-get install -y make gcc libelf-dev clang llvm libbpf-dev bpfcc-tools
基本使用示例
以下是使用tcpdog的基本示例代码:
package main
import (
"fmt"
"os"
"os/signal"
"syscall"
"github.com/mehrdadrad/tcpdog"
)
func main() {
// 创建tcpdog配置
cfg := tcpdog.Config{
Fields: []string{"saddr", "daddr", "sport", "dport", "rtt", "retrans"},
EBPF: tcpdog.EBPFConfig{
Interface: "eth0",
Filter: "port 80 or port 443",
},
}
// 初始化tcpdog
td, err := tcpdog.New(cfg)
if err != nil {
fmt.Printf("Failed to initialize tcpdog: %v\n", err)
return
}
defer td.Close()
// 创建通道接收TCP事件
ch := make(chan map[string]interface{}, 100)
go td.Start(ch)
// 设置信号处理
sig := make(chan os.Signal, 1)
signal.Notify(sig, syscall.SIGINT, syscall.SIGTERM)
// 处理TCP事件
for {
select {
case m := <-ch:
fmt.Printf("TCP Event: %+v\n", m)
case <-sig:
fmt.Println("Received signal, exiting...")
return
}
}
}
高级功能实现
1. 自定义BPF程序
// 自定义BPF程序示例
const customBPF = `
#include <uapi/linux/ptrace.h>
#include <net/sock.h>
#include <bcc/proto.h>
BPF_HASH(stats, u32);
int trace_tcp_retrans(struct pt_regs *ctx, struct sock *sk) {
u32 pid = bpf_get_current_pid_tgid();
u64 *count, zero = 0;
count = stats.lookup_or_init(&pid, &zero);
(*count)++;
return 0;
}
`
cfg := tcpdog.Config{
EBPF: tcpdog.EBPFConfig{
CustomProg: customBPF,
},
}
2. 性能指标聚合
// 聚合统计示例
type TCPStats struct {
Count int
TotalRTT time.Duration
Retrans int
}
stats := make(map[string]*TCPStats)
for m := range ch {
key := fmt.Sprintf("%s:%d->%s:%d",
m["saddr"], m["sport"], m["daddr"], m["dport"])
if _, ok := stats[key]; !ok {
stats[key] = &TCPStats{}
}
stats[key].Count++
stats[key].TotalRTT += time.Duration(m["rtt"].(uint64)) * time.Microsecond
stats[key].Retrans += m["retrans"].(int)
// 定期打印统计
if stats[key].Count%100 == 0 {
avgRTT := stats[key].TotalRTT / time.Duration(stats[key].Count)
fmt.Printf("Connection %s: AvgRTT=%v, Retrans=%d\n",
key, avgRTT, stats[key].Retrans)
}
}
实际应用场景
1. 网络延迟分析
// 高延迟连接检测
highLatencyThreshold := 100 * time.Millisecond
for m := range ch {
rtt := time.Duration(m["rtt"].(uint64)) * time.Microsecond
if rtt > highLatencyThreshold {
fmt.Printf("High latency detected: %s:%d->%s:%d RTT=%v\n",
m["saddr"], m["sport"], m["daddr"], m["dport"], rtt)
}
}
2. 重传率监控
// 计算重传率
type ConnRetrans struct {
TotalPackets int
Retrans int
}
retransStats := make(map[string]*ConnRetrans)
for m := range ch {
key := fmt.Sprintf("%s:%d->%s:%d",
m["saddr"], m["sport"], m["daddr"], m["dport"])
if _, ok := retransStats[key]; !ok {
retransStats[key] = &ConnRetrans{}
}
retransStats[key].TotalPackets++
retransStats[key].Retrans += m["retrans"].(int)
retransRate := float64(retransStats[key].Retrans) / float64(retransStats[key].TotalPackets)
if retransRate > 0.05 { // 5%重传率阈值
fmt.Printf("High retrans rate: %s %.2f%%\n", key, retransRate*100)
}
}
性能优化建议
-
减少用户空间-内核空间数据传输:
- 只收集必要的字段
- 使用BPF聚合数据后再传递到用户空间
-
合理设置缓冲区大小:
cfg := tcpdog.Config{ EBPF: tcpdog.EBPFConfig{ PerfBufferSize: 128, // 每CPU缓冲区页数 PollTimeout: 100, // 毫秒 }, }
-
使用批处理处理事件:
// 批处理示例 const batchSize = 100 var batch []map[string]interface{} for m := range ch { batch = append(batch, m) if len(batch) >= batchSize { processBatch(batch) batch = batch[:0] } }
总结
tcpdog结合eBPF技术为Golang开发者提供了强大的TCP网络监控能力。通过本文的示例,您可以快速实现TCP连接监控、性能分析以及网络问题诊断等功能。eBPF的高效性和灵活性使其成为现代网络监控的理想选择,而Golang的简洁语法和强大并发模型则让开发这类工具变得更加容易。