云服务器价格_云数据库_云主机【优惠】最新活动-搜集站云资讯

企业邮箱_企业邮箱客户端下载_速度快

小七 141 0

xdpcap:xdpcap包捕获

我们的服务器处理大量的网络数据包,不管是合法流量还是大规模的拒绝服务攻击。为了有效地做到这一点,我们采用了eXpress Data Path(XDP),这是一种Linux内核技术,它为低级数据包处理提供了一种高性能的机制。我们用它来删除与L4Drop的DoS攻击包,也在我们的新的第4层负载平衡器。但是XDP也有一个缺点:因为它在正常的Linux网络堆栈看到包之前处理这些包,重定向或丢弃的包对于常规调试工具来说是不可见的,比如tcp泵送至为了解决这个问题,我们构建了一个tcpdump替代xdpcap。我们正在开源这个工具:代码和文档可以在GitHub.xdpcap使用我们的经典BPF(cBPF)来eBPF或C编译器cbpfc,我们也是开源的:代码和文档可以在GitHub.CCchristophmüllerTcpdump提供了一种简单的方法来转储感兴趣的特定数据包。例如,要捕获所有ipv4dns包,可以使用:$tcpdump ip和udp端口53xdpcap重用相同的语法!xdpcap可以将数据包写入pcap文件:$xdpcap/path/to/hook捕获.pcap"ip和udp端口53"xdported:0/0 XDPDrop:0/0 xdpass:254/0 XDPTx:0/0(已接收/匹配的数据包)XDP端口:0/0 XDPDrop:0/0 XDPPass:995/1 XDPTx:0/0(已接收/匹配的数据包)或者将pcap写入stdout,并使用tcpdump对数据包进行解码:$xdpcap/path/to/hook-"ip和udp端口53"| sudo tcpdump-r-从文件读取,链接类型EN10MB(以太网)16: 18:37.911670 IP 1.1.1.1>1.2.3.4.21563:26445$1/0/1 A 93.184.216.34(56)本文的其余部分将解释如何构建xdpcap,包括如何使用/path/to/hook/连接到XDP程序.tcpdumpTo复制tcpdump,我们首先需要了解它的内部工作原理。马雷克·马基科夫斯基此前曾就此主题写过一篇详细的帖子。Tcpdump公开了高级过滤语言pcap filter,以指定感兴趣的数据包。重复使用我们前面的示例,下面的过滤器表达式将捕获到端口53(可能是DNS)的所有ipv4udp数据包流量:ip和udp端口53在内部,tcpdump使用libpcap将过滤器编译为经典BPF(cBPF)。cBPF是一种简单的字节码语言,用来表示检查包内容的程序。程序返回非零表示数据包与筛选器匹配,否则返回零。执行cBPF程序的虚拟机非常简单,只有两个寄存器a和x。无法检查输入数据包[1]的长度;相反,任何超出边界的数据包访问都将终止cBPF程序,返回0(不匹配)。Linux文档中列出了完整的操作码集。回到我们的示例过滤器,ip和udp端口53编译为以下cBPF程序,用带注释的流程图:cBPF示例filter flowchartTcpdump使用带有SO\u ATTACH_filter的setsockopt系统调用将生成的cBPF筛选器附加到原始数据包套接字。内核对每个发往套接字的包运行过滤器,但只传递匹配的包。Tcpdump显示已传递的数据包,或将其写入pcap捕获文件以备以后使用分析.xdpcapInXDP的上下文,我们的tcpdump替代品应:接受筛选器动态匹配CBxDPF指令版本的PDxDPF程序使用扩展的CBxDPF语言包过滤设置eBPF,允许对网卡接收到的每个数据包运行任意程序,可能会修改这些数据包。严格的内核验证器静态地分析eBPF程序,确保每个包都检查内存边界负荷.eBPF程序可以返回:XDP_DROP:丢弃数据包xdp_TX:将数据包发送回网络接口dp_PASS:将数据包传递到网络堆栈上pf引入了几个新功能,特别是helper函数调用,使程序能够调用内核公开的函数。这包括检索或设置映射中的值,也可以从用户空间.FilterAtcpdump的关键特性是能够有效地挑选感兴趣的数据包;在到达用户空间之前对数据包进行过滤。要在XDP中实现这一点,必须将所需的过滤器转换为eBPF.cBPF公司已经在我们基于XDP的DoS缓解管道中使用:cbpfc首先将cBPF过滤器转换为C,然后使用Clang将结果编译为eBPF。重用此机制允许我们完全支持libpcap filter ex压力:管道到使用cbpfc将pcap过滤器表达式转换为eBPF,以删除Clang运行时依赖关系,我们的cbpfc编译器cbpfc,扩展到直接生成eBPF:管道到使用cbpfc将pcap筛选器表达式直接转换为eBPF;使用cbpfc、ip和udp端口53将pcap筛选器表达式转换为eBPF产量:cBPF示例使用cbpfc流程图将过滤器转换为eBPF发出的eBPF需要一个序言,它负责加载指向开始和结束的指针,将输入数据包分别放入寄存器r6和r7中[2],生成的代码遵循与原始cBPF过滤器非常相似的结构,但是使用:Bswap说明将大端数据包数据转换为少量数据恩迪安。守卫在我们从包中加载数据之前检查它的长度。这些都是内核所必需的验证者epilogue可以使用过滤器的结果对输入执行不同的操作包。如前面提到过,我们是开源的cbpfc;代码和文档可以在GitHub上找到。它可以用来将cBPF编译成C,也可以直接编译成eBPF,生成的代码被内核接受验证器.仪器cpdump可以随时启动和停止捕获数据包,而不需要应用程序的协调。这就排除了修改现有的XDP程序以直接运行生成的eBPF过滤器的可能性;每次运行xdpcap时都必须修改这些程序。相反,程序应该公开一个钩子,xdpcap可以使用该钩子在运行时.xdpcap的钩子支持是围绕eBPF尾部调用构建的。XDP程序可以使用tail call helper将控制权交给其他程序。控件不会返回给调用程序,而是使用后续程序的返回代码。例如,考虑两个XDP程序,foo和bar,foo连接到网络接口。Foo可以跟踪呼叫巴:流量XDP程序foo tail calling into program bart要跟踪调用的程序在运行时配置,使用一个特殊的eBPF程序数组映射。eBPF程序尾调用映射的特定索引,其值由用户空间设置。从上面的示例中,foo的tail call map包含一个条目:指数程序0酒吧对空索引的尾部调用不会起任何作用,XDP程序在尾部调用失败后总是需要返回操作本身。再一次,这是由内核验证器执行的。如果是程序福:国际福(结构xdp_md*ctx){//尾调用到索引0-程序栏尾部调用(ctx,&map,0);//尾部呼叫失败,请传递数据包返回XDP_PASS;}为了利用这个作为钩子点,插入指令的程序被修改为总是尾部调用,使用一个映射,该映射通过将其固定到bpff而暴露给xdpcap。要附加过滤器,xdpcap可以在映射中设置它。如果没有附加筛选器,插入指令的程序将返回正确的操作本身。用一个附加到foo程序的过滤器,我们有:流量XDP程序foo tail调用xdpcap筛选器筛选器筛选器必须返回插入指令的程序所执行的原始操作,以确保正确处理数据包。为了实现这一点,xdpcap为每个可能的XDP操作生成一个过滤器程序,每个程序都硬编码以返回该特定操作。所有程序都设置在地图中:指数程序0(XDP U中止)过滤器XDP_中止1(XDP U下降)过滤器XDP_-DROP2(XDP U通道)过滤器XDP_PASS3(XDP U-TX)XDP_TX过滤器通过tail调用正确的索引,插入指令的程序确定最终作用:流动XDP程序foo tail调用到xdpcap过滤器中,每个actionxdpcap提供了一个helper函数,该函数尝试对给定的操作进行尾部调用。如果失败,则返回操作相反:enum xdp_actionxdpcap_exit(struct xdp_md*ctx,枚举xdp_action action){//使用操作作为索引将尾部调用到筛选器中tail_call((void*)ctx,&xdpcap_hook,action);//尾部呼叫失败,返回操作返回动作;}这允许XDP程序简单地说:intfoo(结构xdp_md*ctx){返回xdpcap_exit(ctx,XDP_PASS);}ExposeMatching包以及为它们采取的原始操作都需要向用户空间公开。再一次,这样的机制已经是我们基于XDP的DoS缓解管道的一部分!另一个eBPF助手perf_event_output允许XDP程序生成一个perf事件,其中包含一些元数据包。由于xdpcap为每个XDP操作生成一个过滤器,所以filter程序可以在元数据中包含所采取的操作。用户空间程序可以创建perf事件环缓冲区来接收事件,同时获得操作和包。这个对于最初的cBPF是正确的,但是Linux实现了许多扩展,其中一个允许检索输入包的长度。↩本例使用寄存器r6和r7,但cbpfc可以配置为使用任何寄存器。↩︎