问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

xcap:基于eBPF技术的下一代内核网络抓包工具

创作时间:
作者:
@小白创作中心

xcap:基于eBPF技术的下一代内核网络抓包工具

引用
1
来源
1.
https://juejin.cn/post/7366166521798606911

Linux内核网络丢包是开发者经常遇到的问题场景,通常大家会借助tcpdump等传统网络抓包工具定位问题,但其效率较低,且在深度网络问题定位方面能力有限。随着eBPF技术的快速发展,出现了更高级的问题跟踪能力,借助这种能力,我们开发了下一代内核网络抓包工具:xcap。

简介

Linux内核网络丢包是开发者经常遇到的问题场景,通常大家会借助tcpdump等传统网络抓包工具定位问题,但其效率较低,且在深度网络问题定位方面能力有限。随着eBPF技术的快速发展,出现了更高级的问题跟踪能力,借助这种能力,我们开发了下一代内核网络抓包工具:xcap。

与传统网络工具只能作用于内核网络协议栈特定的点相比,xcap可以几乎跟踪整个内核网络协议栈。我们用tcpdump语法作为过滤条件,以skb(socket buffer)为上下文,可以轻松掌握整个报文在内核网络协议栈的完整踪迹,可以帮助开发者大大提高内核网络丢包问题的定位效率。另外xcap还可以抓取AF_XDP的包和bypass中内核协议栈的网络包(如DPDK),能够覆盖多种网络场景。

传统工具的弊端

tcpdump

tcpdump抓包点位置固定:入向是xdp之后,tc之前;出向是tc之后。如果网络包通过其他方式进行路径优化后,不经过这几个位置,那么tcpdump就抓不到了,另外tcpdump还无法支持进程名、pid、namespace id等其他过滤条件。

bpftrace+skboutput

bpftrace+skboutput虽然支持了网络包的抓取和保存,但是它缺少了tcpdump语法的过滤功能。

xcap的优势

  • 自定义抓包位置:xcap以hook函数来实现抓包,保证了抓包位置的灵活性,给使用者更大的自由度,可以覆盖更多的网络场景。
  • 功能可高度定制:xcap基于cbpfc库,支持tcpdump过滤语法转成c代码,然后使用bcc go库可以实现即时编译,具备了tcpdump语法过滤包的功能。xcap的hook是依赖bpf来实现的,我们可以通过丰富的bpf helper函数,获取很多的信息,诸如用栈的信息、进程名、pid、namespcace id等等,基于这些信息,就可以高度定制多种功能。

另外bpf社区非常活跃,很多特性不断合入,也为xcap在高版本内核上的更多功能和更少overhead提供了助力。

xcap通过kprobe/tracepoint方式实现函数的hook,通过函数参数获取skb和sock关键结构体,拿到网络包的数据,通过bpf map和用户态进行数据传递。

典型使用场景

内核丢包

上述例子是用iptables下一条规则,eth1上发出去icmp包全部丢掉。针对这样的场景,tcpdump抓不到这个包,也很难分析其原因。而用xcap可以直接hookkfree_skb_reason函数,所有包的skb都会通过该函数进行释放内存,通过tcpdump过滤语法找到对应网络包的调用栈,然后找到丢包原因。

AF_XDP环境抓包

上述例子是AF_XDP的应用,使用AF_XDP进行发包,AF_XDP网络包不会经过tcpdump抓包位置的流程,我们通过xcap和tcpdump同时抓包可以发现,tcpdump没有抓到。

针对越来越丰富的网络场景,xcap依靠其灵活的特性,可以覆盖更多的使用场景。

实现原理

整体架构图

xcap主体框架依赖cbpfc库实现tcpdump语法转换成c函数,然后进行字符串替换,生成真正的bpf代码,然后再基于go版本bcc库,实现bpf代码即时编译。数据交互使用BPF_MAP_TYPE_PERF_EVENT_ARRAY将抓包的数据传递给用户态进程。

bpf侧框架

bpf代码通过clang进行编译转成字节码,然后通过bpf syscall进行load和attach,在load阶段,内核bpf模块中的verifier会进行校验,检测bpf代码是否安全。

tcpdump语法到c函数的转换

实现逻辑比较清晰:解析tcpdump语法,然后转成对skb数据进行相应的偏移,最后读取数据进行比较。

以图中举例,tcp过滤struct ethhdr:14个字节struct iphdr.protocol:9个字节

IPPROTO_TCP = 6,              /* Transmission Control Protocol        */

data+23当地址解引用获取的值和6进行比较

skb结构体和报文的对应关系

sk_buff结构体在网卡驱动层分配后,它的生命周期贯穿了整个内核协议栈,包含了网络包的所有数据,这也是我们抓包过程中需要获取到的最重要的参数之一,根据它的head结构体可以获取到网络包的内容,然后通过偏移量获取各个头部信息和payload,存放到map中,然后进行tcpdump语法过滤。

利用sock伪造skb报文

考虑到抓包函数的不固定,所以就会碰到这样的情况:部分头部信息还没有走到解析流程,从而无法获取对应的偏移量和内容,这时候xcap会根据sock结构体中的其他成员来进行推导,然后fake头部信息放到pcap buf中。

pcap文件生成

bpf根据pcap文件的格式,初始化pcap头部,然后将ethhdr、iphdr和后续的数据进行填充,通过BPF_MAP_TYPE_PERF_EVENT_ARRAY进行数据的传递,用户态通过epoll系统调用进行事件监听和拷贝。

未来计划

为了进一步推进eBPF技术的发展,xcap未来计划对外开源,并集成到火山引擎veLinux操作系统,与各位Linux系统、eBPF开发者共享技术成果,通过开源的力量,与大家携手共同推进eBPF技术在国内的发展,同时欢迎大家关注后续开源进展。未来我们也将在以下几个方向进行优化,以达到更高的性能:

  • 使用bpf ringbuf代替perf ringbuf,已达到更高的性能、更少的内存消耗;
  • 使用vmlinux btf来自动解析内核函数的参数
  • 使用fentry、fexit来降低hook的性能损耗
  • 尝试用低开销的uprobe技术,支持DPDK抓包(如:bpftime项目)
© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号