一個透過 (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