skaiuijing

引言

eBPF 是 Linux 内核中近年来最受关注的技术之一,它允许我们在不修改内核源码的前提下,实现高性能、低开销的内核扩展。

笔者最近遇到一个需求:需要对某个端口的网络流量进行监控和限速。

传统工具无法关联网络行为,tc 配置复杂且粒度粗,iptables 虽然能过滤流量,但缺乏实时速率统计和动态调度能力。

花了点时间,笔者写了 一个基于 eBPF 的流量控制工具,目的是实现精确、高效的流量监控与限速。

四个控制维度

Wirefisher 支持从以下四个维度进行流量识别与限速:

  • 进程维度(PID):可精确控制某个进程的入站或出站带宽
  • cgroup 维度:适用于容器或服务组的统一流量管理
  • 网卡维度(Interface):对指定网卡进行 ingress/egress 流量调度
  • IP/端口/协议维度:支持对特定 IP、端口或协议(TCP/UDP)进行限速与过滤

每个维度都可以独立启用,互不干扰,也可以组合使用,实现更复杂的流量策略。

程序框架

Wirefisher 的整体框架很简单分为两层:

1. BPF 层(C语言编写)

  • 使用原生 C 编写 eBPF 程序,挂载在 Netfilter 或 tc 等钩子点上
  • 实现流量统计、速率计算、令牌桶限速逻辑
  • 所有逻辑运行在内核态,性能极高,延迟极低

2. 控制层(C++ + YAML)

  • 使用 C++ 编写用户态控制程序
  • 集成 YAML 解析库,支持模块化配置文件
  • 根据配置动态加载对应的 BPF 程序,并传入参数(如 PID、网卡名、速率等)

如果读者有分布式监控需求,可以尝试使用python等编写http接口,使用Prometheus等作为分布式监控平台。

限速机制

Wirefisher 的限速逻辑参考了 Cilium 的令牌桶算法实现,并结合 Linux 内核的 BBR 拥塞控制算法,具备以下特点:

  • 令牌桶算法:每个流量实体维护一个独立的令牌桶,根据速率定期补充令牌,发送数据时消耗令牌,超限则丢包或延迟处理
  • BBR 宽容机制:对偶发丢包具有一定容忍度,避免误判突发流量为拥塞
  • 平滑速率计算:支持瞬时速率、平均速率、峰值速率和指数加权平滑速率,便于动态调度和策略调整

这种机制既保证了限速的精度,又避免了对突发流量的过度惩罚,所以如果使用限速机制,最好启用BBR算法。

使用方式

Wirefisher 的使用非常简单,只需编写YAML 配置文件,指定你要控制的对象和速率即可:

功能特点

  • 按进程限速(PID)
  • 按 IP、端口、协议过滤与限速
  • 按网卡进行速率控制
  • 按 cgroup 统一调度
  • 支持 ingress / egress 双向控制
  • 实时速率统计:平均速率、峰值速率、平滑速率

配置文件示例

进入配置目录:

先git:

1
git@github.com:skaiui2/wirefisher.git

然后进入配置目录:

1
2
cd config
vim config.yaml

可以这样配置:

1
2
3
4
5
6
process_module:
process_rule:
target_pid: 4580
rate_bps: 1M
gress: ingress
time_scale: 1s

编译与运行

编译 BPF 程序:

1
2
3
cd bpf
make
cd ..

构建用户态控制程序:

1
2
3
4
mkdir build
cd build
cmake ..
make

启动 Wirefisher:

1
sudo ./ebpf_system

程序将根据 config.yaml 中的配置自动加载限速规则并开始运行。

环境要求

  • Linux 内核版本 ≥ 5.4,需支持 eBPF 和 CO-RE
  • 需要 root 权限运行
  • 安装 libbpf 和 clang 工具链

输出

1
2
3
4
5
6
=== process_traffic ===
instant_rate_bps : 0.10 MB/s
rate_bps : 0.10 MB/s
peak_rate_bps : 0.10 MB/s
smoothed_rate_bps: 0.10 MB/s
timestamp : 00:15:50.348

字段解释

  • instant_rate_bps
    当前包的瞬时速率(单位:MB/s),根据最近一次数据包的大小与时间间隔计算,反映突发流量情况。

    rate_bps
    平均速率(单位:MB/s),从窗口起始时间到当前时间的总流量除以时间差,反映整体带宽使用情况。

  • peak_rate_bps
    峰值速率(单位:MB/s),记录历史上出现过的最大瞬时速率,用于识别突发流量峰值。

  • smoothed_rate_bps
    平滑速率(单位:MB/s),采用指数加权移动平均(EWMA)算法计算,用于消除瞬时波动,更适合用于限速判断。

  • timestamp
    当前输出时间戳,格式为 HH:MM:SS.mmm,便于对比不同时间点的流量变化。

如需启用其他维度(如 IP、端口、网卡、cgroup)或调整输出频率,可在配置文件中进行设置。