概述

伯克利包过滤器(Berkeley Packet Filter,缩写 BPF),是类Unix系统上数据链路层的一种原始接口,提供原始链路层封包的收发。除此之外,如果网卡驱动支持混杂模式,那么它可以让网卡处于此种模式,这样可以收到网络上的所有包,不管他们的目的地是不是所在主机。另外,BPF支持过滤数据包——用户态的进程可以提供一个过滤程序来声明它想收到哪些数据包。通过这种过滤可以避免从操作系统内核向用户态复制其他对用户态程序无用的数据包,从而极大地提高性能。

BPF简介

多年前很多程序,例如网络监控器,都是作为用户级进程运行的。为了分析只在内核空间运行的数据,它们必须将这些数据从内核空间复制到用户空间的内存中去,并进行上下文切换。这与直接在内核空间分析这些数据相比,导致了巨大的性能开销。而随着近年来网络速度和流量井喷式增长,一些应用程序必须处理大量的数据(如音频、视频流媒体数据)。要在用户空间监控分析那么多的流量数据已经不可行了,因而BPF应运而生——一种在内核空间执行高效安全的程序的机制。 BPF发展到现在名称升级为eBPF: extended Berkeley Packet Filter

  • 演进成一套通用执行引擎,不再仅仅是网络分析,可以基于eBPF开发性能分析、系统追踪、网络优化等多种类型工具和平台。
  • 原来的BPF就被称为cBPF(classic BPF),目前已基本作废,当前Linux内核只运行eBPF,内核会将cBPF透明转换成eBPF。

bgp 过滤 bpf过滤规则_数据

BPF 在数据包过滤上引入了两大革新:

  • 一个新的虚拟机 (VM) 设计,可以有效地工作在基于寄存器结构的 CPU 之上;
  • 应用程序使用缓存只复制与过滤数据包相关的数据,不会复制数据包的所有信息,最大程度地减少BPF 处理的数据,提高处理效率;eBPF 由执行字节码指令、存储对象和辅助函数组成。下图是eBPF工作原理演示:

bgp 过滤 bpf过滤规则_数据_02


eBPF字节码指令在内核执行前必须通过 BPF 验证器的验证,同时在启用 BPF JIT 模式的内核中,会直接将字节码指令转成内核可执行的本地指令运行,具有很高的执行效率。原来的 BPF 就被称为cBPF(classic BPF),目前已基本废弃。当前Linux 内核只运行 eBPF,内核会将cBPF 透明转换成 eBPF 再执行。下文提到的BPF字样没有特别说明的话,是泛指cBPF和eBPF。

BPF技术发展史

从1992年发布以来,BPF技术快速发展,除了技术本身得到了升级,基于它的工具和平台也如雨后春笋一般层出不穷,下面是BPF技术发展史,里面罗列几个重要的eBPF发展里程碑和基于eBPF技术的工具和平台的诞生事件,其中包括BCC、Cilium、Falco、bpftrace、kubectl-trace等等

bgp 过滤 bpf过滤规则_linux_03


BPF过滤规则

设置过滤规则就是让网络设备只是捕获我们感兴趣的网络数据包,如果没有设置过滤规则,那么网络设备就捕获所有类型的数据包,否则只是捕获过滤规则设置的数据包,此时过滤规则的逻辑值为真。此过滤规则是通用的,由著名的网络程序 tcpdump 推出,其他很多的网络程序都是基于此规则进行设计的。此过滤规则的内部解析机制上面介绍过,下面我们参考 tcpdump 的过滤规则形式着重介绍一下BPF过滤规则的定义形式。

限定词

说明

例子

Type

指出ID或数字所代表的含义

host, net, port

Dir

指明数据包传输方向

src, dst

Proto

限定所要匹配的协议

ether, ip, tcp, udp, http, ftp

可以使用以下3种逻辑运算符,对原语进行组合,从而创建出更高级的表达式

&&:连接运算符 与
||:选择运算符 或
!:否定运算符 非

BPF过滤流程

BPF过滤流程如下:

bgp 过滤 bpf过滤规则_内核空间_04