一个通过 (e)BPF 附加到 Linux 内核的 XDP 挂钩的程序,用于快速数据包处理并执行基本的 3/4 层转发。该程序执行类似于 IPTables 和 NFTables 的源端口映射来处理连接。现有连接根据每纳秒连接的数据包进行优先级排序。这意味着在端口耗尽时,每纳秒数据包最少的连接将被替换。我相信这是最好的,因为每纳秒具有更高数据包的连接将更加敏感。
此外,如果主机的网络配置或网络接口卡 (NIC) 不支持 XDP DRV 挂钩(又名本机;发生在 SKB 创建之前),则程序将尝试附加到 XDP SKB 挂钩(又名通用;发生在 SKB 之后)创建,这是通过netfilter
内核模块处理 IPTables 和 NFTables 的地方)。您可以通过命令行使用覆盖来强制 SKB 或卸载模式。
话虽如此,主机的网络配置不支持 XDP 的 DRV 挂钩的原因可能如下。
我希望这个项目可以帮助有兴趣利用 XDP 的现有网络工程师/程序员或任何有兴趣进入这些领域的人!高性能路由器/数据包转发和 (D)DoS 缓解/预防是网络安全的重要组成部分,了解中低水平的网络和数据包流的概念肯定会对那些在该领域追求职业的人有所帮助?
警告- 这个项目还有很多事情需要做,到目前为止,它只支持 IPv4。正式发布前将添加 IPv6 支持。截至目前,该程序可能存在错误,并且转发功能尚不可用。
每个绑定地址可使用的默认最大源端口为21 ,并在此处设置(如果您愿意,可以调整这些)。默认情况下,我们使用端口范围500 - 520 ,但这可以配置。
起初,我尝试使用大多数可用端口(1 - 65534)。然而,由于 BPF 验证器的限制,我不得不在 Linux 内核中添加几个常量并重新编译内核。我为这些补丁制作了补丁,并将所有内容记录在这里。我能够在每个绑定地址有 65534 个最大端口的情况下运行该程序,而使用我制作的补丁构建的自定义内核不会出现任何问题。但请记住,可用的源端口越多,XDP 程序在检查可用端口时必须执行的处理就越多。
如果您打算将其用于生产,我强烈建议您使用上面提出的常量编译您自己的内核。每个绑定地址 21 个最大源端口并不多,但不幸的是,默认的 BPF 验证器限制目前不允许我们进一步进行。
导致这些限制的主要代码位于此处,当我们尝试找到用于新连接的最佳源端口时,就会发生这些代码。根据我的理解,确实没有其他方法可以检查可用的最佳源端口,因为我们必须循环所有源端口并检查每纳秒值的数据包(BPF 映射按键搜索)。
您将需要make
、 clang
、 libelf
和llvm
因为我们使用这些包来构建项目。此外,您还需要libconfig
( libconfig-dev
是 Ubuntu/Debian 系统上的软件包)来解析配置文件。
对于 Ubuntu/Debian,以下内容应该有效。
apt install build-essential make clang libelf-dev llvm libconfig-dev
我假设其他 Linux 发行版上的软件包名称类似。
为了使用xdpfwd-add
和xdpfwd-del
,您必须挂载 BPF 文件系统,因为 XDP 程序将 BPF 映射固定到/sys/fs/bpf/xdpfwd
。这很可能已经通过iproute2
或类似的东西为您完成,但如果没有,您可以使用以下命令。
mount -t bpf bpf /sys/fs/bpf/
基本命令行用法包括以下内容。
-o --offload => Attempt to load XDP program with HW/offload mode. If fails, will try DRV and SKB mode in that order.
-s --skb => Force program to load in SKB/generic mode.
-t --time => The amount of time in seconds to run the program for. Unset or 0 = infinite.
-c --config => Location to XDP Forward config (default is /etc/xdpfwd/xdpfwd.conf).
-l --list => List all forwarding rules.
-h --help => Print out command line usage.
将 XDP/BPF 程序卸载到系统的 NIC 可以实现最快的数据包处理,因为 NIC 使用其硬件处理/转发数据包。然而,支持此功能的 NIC 制造商并不多,并且您受到 NIC 内存/处理的限制(例如,您的 BPF 映射大小将受到极大限制)。此外,对于卸载的 BPF 程序通常有更严格的 BPF 验证器限制,但您可以尝试联系 NIC 制造商,看看他们是否会给您一个特殊版本的 NIC 驱动程序来提高这些限制(这是我与一家制造商所做的)我用过)。
截至目前,由于 BPF 的复杂性和循环要求,我不知道有任何 NIC 制造商能够将该工具完全卸载到 NIC。老实说,在当前的网络时代,我认为最好将卸载的程序留给 BPF 映射查找和最小数据包检查。例如,简单的 BPF 第 2 层路由表映射查找,然后将数据包从 NIC 发送回。然而,XDP 仍然非常新,我想我们将在未来几年看到这些限制的放松或取消。这就是为什么我在这个程序中添加了对卸载模式的支持。
安装时通过/usr/bin
添加到$PATH
xdpfwd-add
可执行文件接受以下参数。
-b --baddr => The address to bind/look for.
-B --bport => The port to bind/look for.
-d --daddr => The destination address.
-D --dport => The destination port.
-p --protocol => The protocol (either "tcp", "udp", "icmp", or unset for all).
-a --save => Save rule to config file.
这将在 XDP 程序运行时添加转发规则。
安装时通过/usr/bin
添加到$PATH
xdpfwd-del
可执行文件接受以下参数。
-b --baddr => The address to bind/look for.
-B --bport => The port to bind/look for.
-p --protocol => The protocol (either "tcp", "udp", "icmp", or unset for all).
-a --save => Remove rule from config file.
这将在 XDP 程序运行时删除转发规则。
默认配置文件位于/etc/xdpfwd/xdpfwd.conf
并使用libconfig
语法。这是使用其所有当前功能的示例配置。
interface = "ens18"; // The interface the XDP program attaches to.
// Forwarding rules array.
forwarding = (
{
bind = "10.50.0.3", // The bind address which incoming packets must match.
bindport = 80, // The bind port which incoming packets must match.
protocol = "tcp", // The protocol (as of right now "udp", "tcp", and "icmp" are supported). Right now, you must specify a protocol. However, in the future I will be implementing functionality so you don't have to and it'll do full layer-3 forwarding.
dest = "10.50.0.4", // The address we're forwarding to.
destport = 8080 // The port we're forwarding to (if not set, will use the bind port).
},
...
);
假设您已经下载了所有必需的软件包,那么构建该项目应该很简单。您可以使用以下 shell 和 Bash 命令!
# Clone respository and its sub-modules such as LibBPF.
git clone --recursive https://github.com/gamemann/XDP-Forwarding
# Change directory.
cd XDP-Forwarding
# Make project using all cores.
make -j $( nproc )
# Install binaries to PATH as root so you may use 'xdpfwd', 'xdpfwd-add', 'xdpfwd-del'.
sudo make install