本篇介紹
XDP(Express Data Path)是一個安全月培,可編程平斩,高性能的網(wǎng)絡數(shù)據(jù)包處理器码倦,可以集成bpf程序。本篇主要介紹xdp的使用以及現(xiàn)實中的使用場景潮剪。
XDP介紹
xdp可以想對于tc在更早階段對收到的數(shù)據(jù)包作出處理涣楷,比如丟棄,轉(zhuǎn)發(fā)鲁纠,修改总棵,還是讓數(shù)據(jù)包繼續(xù)進入下一個協(xié)議棧。xdp程序主要是通過bpf系統(tǒng)調(diào)用來執(zhí)行bpf程序改含。
接下來了解一些相關概念情龄,首先是操作模式。xdp擁有3個操作模式:
- Native XDP 這個是默認的模式捍壤,xdp bpf會在網(wǎng)卡驅(qū)動收包的較早路徑上執(zhí)行骤视,不過需要網(wǎng)卡驅(qū)動支持。
- Offloaded XDP xdp bpf車給你需會直接在網(wǎng)卡上執(zhí)行鹃觉,不需要在cpu上執(zhí)行专酗,這樣比native xdp 性能高。
- Generic XDP 上述兩個模式均對驅(qū)動有要求盗扇,而這個模式則沒有任何要求祷肯,可以用來作為測試模式使用沉填。
xdp包處理器
是內(nèi)核中的一個模塊,在數(shù)據(jù)包出現(xiàn)在RX隊列上就可以開始按照xdp程序處理佑笋,可以按照“busy polling”模式來處理翼闹,這樣可以避免上下文切換,也可以按照“interrupt driven”模式處理蒋纬,也就是基于中斷猎荠。
xdp 返回碼
XDP_DROP: 丟棄該數(shù)據(jù)包,在網(wǎng)絡驅(qū)動的最早RX環(huán)節(jié)就可以丟包蜀备,這樣可以最大化節(jié)省CPU與功耗关摇,用于DOS場景。
XDP_TX:轉(zhuǎn)發(fā)該數(shù)據(jù)包碾阁,將數(shù)據(jù)包返回至到達的網(wǎng)卡上输虱。
DXP_REDIRECT: 重定向數(shù)據(jù)包,可以將數(shù)據(jù)包重定向到另外一個網(wǎng)卡上瓷蛙,或者BPF cpumap上悼瓮,這樣可以做負載均衡。
XDP_PASS:將數(shù)據(jù)包交給協(xié)議棧處理艰猬,這也是內(nèi)核默認的行為
XDP_ABORTED:表示bpf程序出現(xiàn)錯誤横堡,導致數(shù)據(jù)包被丟棄
xdp程序加載
我們前面看到過bpftool 可以加載bpf程序,也可以手動寫代碼來加載冠桃,xdp 可以使用ip命令來加載:
ip link set dev eth0 xdp obj program.o sec mysection
命令解釋如下:
ip: ip 命令
link: 配置網(wǎng)絡接口
set:修改設備屬性
dev eth0:指定要操作的目標網(wǎng)絡設備
xdp obj program.o: 將program.o作為xdp程序進行加載
sec mysection:目標的bpf函數(shù)所在的section
接下來我們看一個xdp的例子命贴,作用是屏蔽所有tcp的請求,首先啟動一個網(wǎng)絡服務:
python3 -m http.server
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
這時候可以看到在8000端口上開始監(jiān)聽了食听,用ss命令看下:
ss -tulpn |grep 8000
tcp LISTEN 0 5 0.0.0.0:8000 0.0.0.0:* users:(("python3",pid=329945,fd=3))
也可以用nmap看下:
nmap -sS 192.168.0.112
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-10-05 22:02 CST
Nmap scan report for 192.168.0.112 (192.168.0.112)
Host is up (0.0000060s latency).
Not shown: 995 closed tcp ports (reset)
PORT STATE SERVICE
22/tcp open ssh
25/tcp open smtp
139/tcp open netbios-ssn
445/tcp open microsoft-ds
8000/tcp open http-alt
nmap 可以進行端口掃描胸蛛,查看監(jiān)聽的網(wǎng)絡端口
接下來準備xdp 代碼:
#include <linux/if_ether.h>
#include <linux/in.h>
#include <linux/ip.h>
#define SEC(NAME) __attribute__((section(NAME), used))
SEC("mysection")
int myprogram(struct xdp_md *ctx) {
int ipsize = 0;
void *data = (void *)(long)ctx->data;
void *data_end = (void *)(long)ctx->data_end;
struct ethhdr *eth = data;
struct iphdr *ip;
ipsize = sizeof(*eth);
ip = data + ipsize;
ipsize += sizeof(struct iphdr);
if (data + ipsize > data_end) {
return XDP_DROP;
}
if (ip->protocol == IPPROTO_TCP) {
return XDP_DROP;
}
return XDP_PASS;
}
按照如下方式編譯:
clang -target bpf -c xdp.c -o xdp.o
接下來按照如下方式進行加載xdp程序:
sudo ip link set dev wlp4s0 xdp obj xdp.o sec mysection
然后執(zhí)行如下命令:
ip a show wlp4s0
3: wlp4s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 xdpgeneric/id:874 qdisc noqueue state UP group default qlen 1000
link/ether e4:a4:71:b3:62:17 brd ff:ff:ff:ff:ff:ff
inet 192.168.0.112/24 brd 192.168.0.255 scope global dynamic noprefixroute wlp4s0
valid_lft 3710sec preferred_lft 3710sec
inet6 fe80::a7fa:5c7f:99ae:bd31/64 scope link noprefixroute
valid_lft forever preferred_lft forever
可以看到接口wlp4s0 之后出現(xiàn)了xdpgeneric,序號是874樱报,用bpftool 就可以看到:
sudo bpftool prog show id 874
874: xdp name myprogram tag d864d21e56eaab5f
loaded_at 2024-10-05T22:04:37+0800 uid 0
xlated 80B jited 55B memlock 4096B
btf_id 219
接下來用另外一個設備葬项,打開瀏覽器,輸入0.0.0.0.8000, 就會發(fā)現(xiàn)鏈接不上了迹蛤。 接下卸載該程序:
sudo ip link set dev wlp4s0 xdp off
此時用另外一個設別再鏈接民珍,發(fā)現(xiàn)就可以訪問到了。
xdp使用場景
從上述例子可以看出盗飒,編寫xdp代碼相對容易嚷量,不需要修改內(nèi)核,也不需要重啟逆趣,對開發(fā)比較友好蝶溶,接下來看下使用場景。
- Monitoring
做網(wǎng)絡數(shù)據(jù)包監(jiān)控統(tǒng)計宣渗,xdp 實現(xiàn)比較容易抖所,而且對性能影響也很小 - DDoS Mitigation
利用xdp丟棄固定來源的數(shù)據(jù)包梨州,避免對服務器造成攻擊,而來源列表可以在用戶態(tài)提供部蛇,該方案對cpu性能影響很小 - Load Balancing
利用負載均衡算法將收到的數(shù)據(jù)包交給目標服務 - Firewalling
利用xdp做防火墻摊唇,合法名單動態(tài)更新,可以提設性能