茱莉亚•埃文斯

如何过滤数据包超快:XDP & eBPF !!

你好!今天我在netdev会议上,这是第二天。

我要写关于从今天最激动人心的事情,大概是一个小时的教程eBPF和由安迪Gospodarek XDP JesperDangaard Brouer。我认为这是令人兴奋的我想写wholeblog文章只是我的笔记从这个教程。

本教程走我们如何构建一个简单的DDoS预防XDPfilter !这是惊人的,因为昨天昨天谈到了如何构建DDoSprevention抽象,但他们显示在这个tutorialexactly如何构建一个简单的例子,讨论很多细节问题。他们建立了应用程序:

  • XDP程序(运行在内核中,写在eBPF)过滤器outpackets(比iptables更迅速、更灵活!从一些IP地址指定)
  • 一个用户空间的命令行工具,它允许您添加和删除IP地址过滤
  • 计数器可以看到多少包已经被过滤

他们很清楚,这只是一个演示/例子来理解哪些概念,生产:不是立即开始使用)

本教程的所有代码都在prototype-kernel回购

eBPF入门

eBPF内核虚拟机。它很灵活(你写eBPFprograms通过编写C代码,所以你可以做很多事情!) but there are limitations.Some important limitations/facts to know about eBPF:

  • 所有与用户空间交互发生通过eBPF”地图”这arekey-value商店
  • 大约有一打不同的地图你现在可以使用
  • eBPF没有循环,所以每个eBPF程序将完成在somebounded执行时间
  • 特别是eBPF不是图灵完整:):

XDP入门

XDP内核,是一个新的系统让你编写自定义eBPF程序tofilter网络数据包。我们叫那些“XDP程序”。XDP程序运行一旦数据包到达网络驱动程序(非常迅速)。

当XDP程序时,它需要与退出XDP_TX,,XDP_DROP,或XDP-孔型。在未来可能有更多的返回代码。

他们说,Ubuntu 16.10 XDP——IIRC XDPsupport最早的内核版本是4.8。

我们的XDP项目:开始!!

对于这个项目,我们想要两个内核代码(XDP计划,也就是托伦在内核)和用户空间代码(对于我们告诉程序在内核运行哪个IP地址块)。

你可能会认为命令行工具需要作为根用户运行(因为这与内核),但事实证明,命令行工具worksby更新带通滤波器地图!你更新地图带通滤波器是通过sysfs fileinterface (/ sys /…一些…)。如果你更新somethingthrough一个文件,你可以改变该文件的权限/所有权!!

因此,命令行工具将新IP地址添加到黑名单不需要托伦作为根。

好吧,这是什么带通滤波器我们更新地图吗?它有类型BPF_MAP_TYPE_PERCPU_HASH。这张地图将IP地址作为键以及许多包我们封锁IP地址作为值。这是一个散列,好吧,每个cpu。所以每个CPUhas自己的地图。这意味着我们的用户空间工具报告如何manypackets一直封锁将需要添加每个CPU的值。

我想在地图上是每个CPU效率更高。

所以我们的地图:(这里的定义是

  • 密钥大小:32位(IPv4地址)
  • 价值大小:64位(数)
  • 马克斯条目:100000

似乎是合理的!!

为真正写XDP项目

所以这个XDP程序是如何工作的呢?吗?

几乎在这个程序中第一行(从在这里)struct ethhdr * eth =数据

任何数据包是一个以太网头部的开始。我们需要解析thatEthernet头。非常有趣的点,他们是——XDPprograms编译进内核树。这意味着你有访问所有的内核数据结构!和内核已经有一个struct thatrepresents以太网头,所以你不用写那么多fancyparsing代码,你可以重用该结构从内核。

XDP项目是这一部分的核心(第227行):我们查找源IP地址在我们的带通滤波器的地图。如果它的存在,那么我们增加价值(以便我们可以知道有多少包了!)

值= bpf_map_lookup_elem(黑名单,&ip_src);如果(值){ / *不需要__sync_fetch_and_add();作为percpu地图* / *值+ = 1;/ *保持一个计数器下降匹配* /返回XDP_DROP;}

整个程序解析数据包,发现IPheader的IP地址,看起来在带通滤波器的地图,并返回只有270行C !愈发重视真的合理!!!

也没有因为这是eBPF循环和循环不允许,使得它更容易理解。

一个非常有趣的事情,他们指出这是检查:

如果((void *)乙+偏移量> data_end)返回false;;

这是确保你不会在包。兴趣是,如果你不做你的边界检查正常,的内核将拒绝您的代码——因为eBPF thekernel内部运行代码,它需要确保它不是它不应该访问任何数据。所以不知怎么的静态分析程序,以确保它不是无所不能是非法的。超级有趣,我想了解更多的感觉到这工作!让我们继续,虽然。

XDP程序到你的内核

好吧,所以我们写XDP计划,编译到一个对象文件kern.o,我们想把它放入内核。他们说有两种方法:

  • 使用iproute2(尽管他们并不是说如何)
  • 编写自己的代码来加载它(他们)

这就是用户代码之前有关。

我理解这部分基本上是有一个(用户空间)libraryprovided由内核加载带通滤波器代码。他们复制的kerneland做了一些变化,因为他们想要它是不同的。bpf_load.c

我有点模糊的参与用户空间的代码现在但是一部分是存在的,所以我可以读它以后如果我需要知道更多。关键是程序加载到内核对象文件。

你怎么知道XDP程序加载?吗?

所以我们想这个XDP程序附加到一个网络接口。我们怎么这儿工作吗?吗?

当我运行ip链接列表在我的笔记本电脑,我得到的所有网络接口的列表:

1:瞧:
          
           mtu 65536 qdisc noqueue状态未知modeDEFAULT组默认qlen 1链接/回环00:00:00:00:00:00 brd 00:00:00:00:00:002: br0:
           
            mtu 1500 qdisc noqueue状态modeDEFAULT组默认qlen 1000链接/醚c6: f7:88: c6: d6:97 brd ff: ff: ff: ff: ff: ff3: mlan0:
            
             mtu 1500 qdisc mq状态modeDORMANT组默认qlen 1000链接/醚18:67:b0:10: e8: eb brd ff: ff: ff: ff: ff: ff5:
             (电子邮件保护):
             
              mtu 1500 qdisc noqueuemaster br0状态模式默认组默认qlen 1000链接/醚c6: f7:88: c6: d6:97 brd ff: ff: ff: ff: ff: ff link-netnsid 0
             
            
           
          

这表明所有这些设置界面,就像mtu 1500 qdisc noqueuestate…。如果有XDP程序运行界面会alsosayXDP在那里。

eBPF / XDP技巧

这里有一些建议他们给了!!

提示1:如果当你带通滤波器程序运行__bpf_prog_runperftop,你应该打开内核JIT。运行你的带通滤波器代码通过theJIT会更快地使一切的方式

技巧2:如果你的ulimit不足够高,就会遇到问题。我有点模糊的ulimit仍但这似乎是一个不错的建议。你canlook ulimitulimit - a

tip 3: dump out kern.o maps with readelf / objdump to look at them.”这才一个ELF文件,这不是魔术”。当你做什么,你可以看到部分与XDP程序和带通滤波器的部分地图!您还可以看到地图的eBPFbytecode部分但不是人类可读:)

技巧4:您可以使用bpf_trace_printk打印调试信息。这些才真正得到印刷,但他们最终在内核跟踪系统/ sys /内核/调试/跟踪/ trace_pipe

同时,,人带通滤波器是一个很好的参考

技巧5:你可以子网黑名单!有一个单词查找树带通滤波器地图类型

技巧6:你可以坚持你的带通滤波器XDP程序连接/分离时地图。

性能

他们写了一个过滤器,过滤所有UDP流量(或UDP流量吗?不清楚)。他们试图实现iptables规则和theircustom XDP方法相比它。

  • iptables:450万包/秒
  • XDP: 970万包/秒

这XDP程序确实是超过两倍iptables !太酷了!!

性能绝对不是唯一的好处在iptables - 'sdefinitely非常重要,与XDP可以编写任意代码。

就是这样!!

我真的很喜欢这个stuffworks本教程关注揭秘如何,他们说很有用使用readelf / objdump看ELFfiles生成沿途了解它们的结构。

I still don't understand everything but this made the idea of writing eBPFprograms to make my kernel filter packets seem WAY more concrete/feasible.Probably some things in this post are wrong but I hope you have learnedsomething anyway!!

netdev会议,第一天 netdev会议,第二天