# XDP firewall contributed by < `chiacyu` > ## What is XDP? XDP(Express Data Path)是一種基於 ebpf (Extended Berkeley Packet Filter) 的高速資料傳輸技術,可提供高效率的封包處理服務。 ### What is ebpf #### ebpf 簡介 ebpf (Extended Berkeley Packet Filter) 則是運行於 Linux 核心內部的虛擬機器(virtual machine)使用者可自行撰寫 ebpf 程式並透過相關 API 載入。不同 `program type` 則提供不同的功能,有些可用於系統功能的量測與紀錄系統呼叫的次數等等。 ![image](https://hackmd.io/_uploads/HyrkXaE4T.png) ### 載入 ebpf program ![image](https://hackmd.io/_uploads/BJekqeABN6.png) 編譯過後的 `bpf program` 需要透過一些工具來將程式載入,可以使用 [bpf system call](https://man7.org/linux/man-pages/man2/bpf.2.html)外, 也可以用`int bpf(int cmd, union bpf_attr *attr, unsigned int size);` 透過傳入的參數來定義後續的行為,可以看到 [`union bpf_attr *attr`](https://elixir.bootlin.com/linux/v4.9/source/include/uapi/linux/bpf.h#L110) 的內容 ```c union bpf_attr { struct { /* anonymous struct used by BPF_MAP_CREATE command */ __u32 map_type; /* one of enum bpf_map_type */ __u32 key_size; /* size of key in bytes */ __u32 value_size; /* size of value in bytes */ __u32 max_entries; /* max number of entries in a map */ __u32 map_flags; /* prealloc or not */ }; struct { /* anonymous struct used by BPF_MAP_*_ELEM commands */ __u32 map_fd; __aligned_u64 key; union { __aligned_u64 value; __aligned_u64 next_key; }; __u64 flags; }; struct { /* anonymous struct used by BPF_PROG_LOAD command */ __u32 prog_type; /* one of enum bpf_prog_type */ __u32 insn_cnt; __aligned_u64 insns; __aligned_u64 license; __u32 log_level; /* verbosity level of verifier */ __u32 log_size; /* size of user buffer */ __aligned_u64 log_buf; /* user supplied buffer */ __u32 kern_version; /* checked when prog_type=kprobe */ }; ... ... ``` 其中透過 `prog_type` 可以將 ebpf program 分成幾種類型,每一種則對應到不同的事件,當該事件發生時已載入的 `ebpf program` 也會被啟動。更詳細的 `program type` 可以參考 ```c enum bpf_prog_type { BPF_PROG_TYPE_UNSPEC, BPF_PROG_TYPE_SOCKET_FILTER, BPF_PROG_TYPE_KPROBE, BPF_PROG_TYPE_SCHED_CLS, BPF_PROG_TYPE_SCHED_ACT, BPF_PROG_TYPE_TRACEPOINT, BPF_PROG_TYPE_XDP, BPF_PROG_TYPE_PERF_EVENT, BPF_PROG_TYPE_CGROUP_SKB, BPF_PROG_TYPE_CGROUP_SOCK, BPF_PROG_TYPE_LWT_IN, ... ... ... ``` 除了撰寫客製化的 bpf program 之外也可以使用 [`bcc`](https://github.com/iovisor/bcc) 提供的許多現成的工具 ![image](https://hackmd.io/_uploads/S1Nlh3NET.png) ### ebpf 觸發方式 從 [bcc/tools/](https://github.com/iovisor/bcc/tree/master/tools) 可以看到許多現成的工具可以使用,首先需要針對作業系統的版本安裝所需的套件。 先將 bcc 專案複製到本機端並進入 `tools` 資料夾執行 `sudo python opensnoop.py` 可以看到 ```c chiacyu@chiacyu-Alpha-15-B5EEK:~/Desktop/bcc/tools$ sudo python opensnoop.py [sudo] password for chiacyu: PID COMM FD ERR PATH 581 systemd-oomd 7 0 /proc/meminfo 581 systemd-oomd 7 0 /proc/meminfo 581 systemd-oomd 7 0 /proc/meminfo 666 iio-sensor-prox 9 0 /dev/iio:device2 666 iio-sensor-prox 9 0 /dev/iio:device4 667 irqbalance 6 0 /proc/interrupts 667 irqbalance 6 0 /proc/stat 667 irqbalance 6 0 /proc/irq/106/smp_affinity 667 irqbalance 6 0 /proc/irq/99/smp_affinity ... ... ... ``` `opensnoop.py` 這個檔案內容可以看到 `syscall__trace_entry_open` 就是將程式對 `open` 這個 系統呼叫做 `hook` ,當 `open` 被呼叫時 `bpf program` 就會被啟動。 ```c # initialize BPF b = BPF(text=bpf_text) if not is_support_kfunc: b.attach_kprobe(event=fnname_open, fn_name="syscall__trace_entry_open") b.attach_kretprobe(event=fnname_open, fn_name="trace_return") b.attach_kprobe(event=fnname_openat, fn_name="syscall__trace_entry_openat") b.attach_kretprobe(event=fnname_openat, fn_name="trace_return") ... ... ... ``` ### 撰寫XDP program 撰寫 `XDP program` 可以參考 [xdp-tutorial](https://github.com/xdp-project/xdp-tutorial/tree/master/basic01-xdp-pass) 的內容。 ```c SEC("xdp") int xdp_prog_simple(struct xdp_md *ctx) { return XDP_PASS; } ``` 接著透過 [`llvm-objdump`](https://llvm.org/docs/CommandGuide/llvm-objdump.html) 可以看到內容為 ```c chiacyu@server:~/Desktop/xdp-tutorial/basic01-xdp-pass$ llvm-objdump -S xdp_pass_kern.o xdp_pass_kern.o: file format elf64-bpf Disassembly of section xdp: 0000000000000000 <xdp_prog_simple>: ; return XDP_PASS; 0: b7 00 00 00 02 00 00 00 r0 = 2 1: 95 00 00 00 00 00 00 00 exit ``` 其中 section xdp 透過 `SEC` 巨集來定義,可以看到 `0000000000000000` 的 section 出現先前定義的程式 xdp_prog_simple,而 `SEC` 的實做可以詳見 [/tools/lib/bpf/bpf_helpers.h](https://elixir.bootlin.com/linux/latest/source/tools/lib/bpf/bpf_helpers.h#L32) ### XDP-firewall 的運作原理 看到