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 Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

載入 ebpf program

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

編譯過後的 bpf program 需要透過一些工具來將程式載入,可以使用 bpf system call外, 也可以用int bpf(int cmd, union bpf_attr *attr, unsigned int size); 透過傳入的參數來定義後續的行為,可以看到 union bpf_attr *attr 的內容

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 可以參考

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 提供的許多現成的工具

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

ebpf 觸發方式

bcc/tools/ 可以看到許多現成的工具可以使用,首先需要針對作業系統的版本安裝所需的套件。 先將 bcc 專案複製到本機端並進入 tools 資料夾執行 sudo python opensnoop.py 可以看到

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 就會被啟動。

# 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 的內容。

SEC("xdp")
int  xdp_prog_simple(struct xdp_md *ctx)
{
        return XDP_PASS;
}

接著透過 llvm-objdump 可以看到內容為

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

XDP-firewall 的運作原理

看到