eXpress Data Path (XDP) áááºážááá¬ááẠpackets kernel network stack ááá¯á·ááááºáá® Linux interfaces ááœáẠá¡ááœá¬ážá¡áá¬áá»á¬ážááᯠááááºááŸááºáá² áá¯ááºáá±á¬ááºááŒááºážááᯠááœáá·áºááŒá¯áá«áááºá XDP ááá»áŸá±á¬ááºááœáŸá¬ - DDoS ááá¯ááºááá¯ááºááŸá¯áá»á¬áž (CloudFlare)á ááŸá¯ááºááœá±ážáá±á¬á á áºáá¯ááºááŸá¯áá»á¬ážá á á¬áááºážá¡ááºážá á¯áá±á¬ááºážááŒááºáž (Netflix) ááŸáá¬ááœááºááŒááºážá XDP áááá¯ááááºáá»á¬ážááᯠeBPF virtual machine á០áá¯ááºáá±á¬ááºááŒá®ážááŒá áºáá±á¬ááŒá±á¬áá·áº á á áºáá¯ááºááŸá¯á¡áá»áá¯ážá¡á á¬ážáá±á«áº áá°áááºá áááºážááá¯á·ááá¯ááºááŸáá·áº áááŸáááá¯ááºáá±á¬ kernel áá¯ááºáá±á¬ááºáá»ááºáá»á¬ážááᯠááá·áºáááºáá»ááºáá»á¬ážááŸááááºá
áá±á¬ááºážáá«ážááẠXDP ááŸá áá»á¬ážááŒá¬ážááŸáá±á¬ áá á¹á ááºážáá»á¬ážá áá»áá¯á·ááœááºážáá»ááºáá»á¬ážá¡ááœáẠáááºááœááºáá«áááºá ááááŠážá áœá¬á áááºážááá¯á·ááẠXDP áá¡ááºá¹áá«áááºáá»á¬ážááá¯áá»ááºáá»ááºážááŸá±á¬ááºááœáŸá²ááá¯ááºááá·áºá¡áááºááá·áºáá¯ááºáá¯ááºááá¯áá±ážáááº- á¡áááºááŒá¯ááŒááºážá¡ááœááºááŒááºáááºááẠááá¯á·ááá¯áẠááŒá¿áá¬áá»á¬ážááŒá áºá á±ááẠááá¯ážááŸááºážááœááºážáááºá áá±á¬ááºááá¯ááºážááœáẠááá·áºááá¯ááºááá¯ááºáá¯ááºááᯠá¡á á០áá±ážááẠááŒáá¯ážá á¬ážáá±á¬á¡áá«á áá¯á¶ááŸááºá¡ááŸá¬ážáá»á¬ážááŸáá·áº áááºááá¯á·áá¯ááºáá±á¬ááºááááºááᯠáá¬ážááááºáá«á áá¯áááá¡áá±ááŸáá·áºá áááºážááá¯á·ááœáẠáááºážááá¯á·áááá¯ááºááá¯ááºá¡áááºá¡áá²áá»á¬ážááŸáááá·áºáá á¬áž VM ááŸáá·áº áá¬á·ááºáá²ááá«áá² XDP ááᯠââááŒááºááœááºážááœáẠá ááºážáááºááẠáááºážáááºážáá»á¬ážááᯠá¡áá»á¯á¶ážááááºáá±á á á¬áá¬ážááẠXDP ááŸáá·áº eBPF ááᯠá áááºáááºá á¬ážáá±á¬ ááœááºáááºáá»á¬ážááŸáá·áº Linux ááŸáá·áº áááºážááŸá®ážáá±á¬ áááá¯ááááºáá¬áá»á¬ážá¡ááœáẠáááºááœááºáá«áááºá
á€á¡ááá¯ááºážááœááºá áá»áœááºá¯ááºááá¯á·ááẠXDP filter ááá¯áááºáá²á·ááá¯á·á
á¯áá±ážááŒá®áž áááºážááá¯á
ááºážáááºáááºážááᯠá¡áá±ážá
áááºáá¬ážáááºáááºááŒá
áºááŒá®ážá ááá¯á·áá±á¬áẠpacket processing á¡ááá·áºááœáẠáá¬áááºááŒá®áž SYN cookies ááá¹ááá¬ážá ááá¯ážááŸááºážáá±á¬áá¬ážááŸááºážááᯠáá±ážáá«áááºá âááŸáá¯ááºá
á¬áááºážâ áááœá²á·ááá»ááºážá
á
áá
á
áºááŒá®ážáá±á¬ áá±á¬ááºáááºáá»á¬ážá áá±á¬ááºáá¬áá»á¬ážáá¬ážááŸááᬠá
á
áºáá¯ááºááŸá¯ááᯠá
á®áá¶áá« - áá¯á¶áá±á¬ááºáá±á¬ááŸááºáááºážáá»á¬ážá
áá»áœááºá¯ááºááá¯á·ááẠC ááŒáá·áºáá±ážáá«áááá·áºááẠ- á€á¡áá¬áááºáá±ááºáááºáááºááá¯ááºáá±á¬áºáááºážáááºááœá±á·ááŒá áºáááºá áá¯ááºá¡á¬ážáá¯á¶ážááᯠá¡áá¯á¶ážááŸáááá·áºááºááœáẠGitHub ááœááºáááá¯ááºááŒá®áž áá±á¬ááºážáá«ážááœááºáá±á¬áºááŒáá¬ážááá·áºá¡ááá·áºáá»á¬ážá¡ááá¯áẠcommits áá»á¬ážá¡ááŒá Ạááá¯ááºážááŒá¬ážáá¬ážáááºá
ááááºááá¯ááºááŒá±á¬ááºážááŸááºážáááºážáá»ááºá áá±á¬ááºážáá«ážááááºáááºážááœááºá á€áááºááŸá¬ XDP ááŸáá·áº áá»áœááºá¯ááºáá§áááá¬á¡ááœáẠáááºááœá±á·áá»áá±á¬á¡áá¯ááºááŒá áºáá±á¬ááŒá±á¬áá·áºá DDoS ááá¯ááºááá¯ááºááŸá¯áá»á¬ážááᯠáá»á±ááŸá¯ááºážáááºá¡ááœáẠá¡áá±ážá á¬ážááŒá±ááŸááºážáá»ááºáá áºáᯠáá®ááœááºáááºááŒá áºáááºá ááá¯á·áá±á¬áºá á¡ááá áááºážááá¯ááºááŸá¬ áááºážááá¬ááᯠáá¬ážáááºáááºááŒá áºááŒá®ážá áááºážááẠá¡áááºááá·áºáá¯ááºáá¬ážáá±á¬ áá¬ááœááºááŸá¯ááᯠáááºáá®ážááẠáááºážááœáŸááºáá»ááºááá¯ááºáá«á áááºáááºážá á¬áá¯ááºááᯠá¡áá±á¬ááºážáá¯á¶ážááœááºážáá¶áá¬ážááŒá®áž á¡áá»áá¯á·áá±á¬ ááœá²ááŒá¬ážáá»ááºáá»á¬ážááᯠáá»ááºááŸááºáá¬ážáááºá
XDP á á¡áá»ááºážáá»á¯ááº
á á¬ááœááºá á¬áááºážááŸáá·áº áááºááŸááá±á¬ááºážáá«ážáá»á¬ážááᯠáááœá¬ážááá á±ááẠá¡áááá¡áá»ááºáá»á¬ážááá¯áᬠáá±á¬áºááŒáá«áááºá
ááá¯á·ááŒá±á¬áá·áºá filter áá¯ááºááᯠkernel áá²ááá¯á·ááá·áºáá¬ážáááºá Filter ááẠáááºáá¬áá±á¬ áááºáááºáá»á¬ážááᯠáá»á±á¬áºááœá¬ážááẠá ááááºá¡áá±ááŒáá·áºá filter ááẠáá¯á¶ážááŒááºáá»ááºáá
áºáá¯áá»ááááº- packet ááᯠkernel ááá¯á·áá±ážááá¯á·ááẠ(XDP_PASS
) áááºáá±á·áá»á² (XDP_DROP
) ááá¯á·ááá¯áẠááŒááºááá¯á·áá« (XDP_TX
) filter ááẠpackage ááá¯ááŒá±á¬ááºážáá²ááá¯ááºáááºá áááºážáááºá¡áá°ážáááŒáá·áºááŸááºáááºá XDP_TX
. áááá¯ááááºááá¯áááºáž áá»ááºááœá¬ážá
á±ááá¯ááºááẠ(XDP_ABORTED
) áááºáá±á·áá»áºáá»ááá¯ááºáá«á áá«áá±ááá·áº áá«á áá°áá®áá«áááºá assert(0)
- á¡ááŸá¬ážááŸá¬ááŒááºááŒááºážá¡ááœááºá
eBPF (extended Berkley Packet Filter) virtual machine ááᯠkernel á០á á áºáá±ážááá¯ááºá á±áááºá¡ááœáẠáá¯ááºááẠá¡ááŒá¬ážáá°áá»á¬ážá ááŸááºáá¬ááºááᯠáááááá¯ááºá á±ááŒá±á¬ááºáž á á áºáá±ážááá¯ááºááẠááá¯ážááŸááºážáá«áááºá ááá·áºáááºáá»ááºáá»á¬ážááŸáá·áº á á áºáá±ážááŸá¯áá»á¬áž-
- ááŸáá·áºáááºááŒááºáž (áá±á¬ááºááá¯á·áá¯ááºááŒááºáž) ááᯠáá¬ážááŒá áºáá¬ážáááºá
- áá±áá¬á¡ááœáẠstack áá áºáá¯ááŸááá±á¬áºáááºáž áá¯ááºáá±á¬ááºáá»ááºáá»á¬áž áááŸááá« (C áá¯ááºáá±á¬ááºáá»ááºá¡á¬ážáá¯á¶ážááᯠáá»ááºážáá¬ážáá¬ážááááº)á
- stack ááŒááºáááŸá memory ááá¯á· áááºáá±á¬ááºááœáá·áºááŸáá·áº packet ááŒá¬ážáá¶áá»á¬ážááᯠáá¬ážááŒá áºáá¬ážáááºá
- áá¯ááºá á¡ááœááºá¡á á¬ážááŸá¬ á¡ááá·áºá¡áááºááŸááá±á¬áºáááºáž áááºááœá±á·ááœáẠáááºážááẠá¡ááœááºáá°ážááŒá¬ážááŸá¯áááŸááá«á
- á¡áá°áž kernel áá¯ááºáá±á¬ááºáá»ááºáá»á¬áž (eBPF á¡áá°á¡áá®áá±ážáá°áá»á¬áž) ááá¯áᬠááœáá·áºááŒá¯áá¬ážáááºá
á á áºáá¯ááºááŸá¯ááᯠáá®ááœááºááŒááºážááŸáá·áº ááá·áºááœááºážááŒááºážááŸá¬ á€áá²á·ááá¯á· ááŒá áºáááº-
- á¡áááºážá¡ááŒá
áºáá¯áẠ(á¥ááá¬á
kernel.c
) compiles to object (kernel.o
) eBPF virtual machine architecture á¡ááœááºá 2019 áá¯ááŸá Ạá¡á±á¬ááºááá¯áá¬áá¡ááá eBPF ááá¯á· á á¯á ááºážááŒááºážááᯠClang ááŸáá¶á·ááá¯ážáá¬ážááŒá®áž GCC 10.1 ááœáẠáááááŒá¯áá¬ážáááºá - á¡áááºá á€á¡áá¬ááá¹áá¯áá¯ááºááœáẠkernel áááºáá±á¬ááºáá¯á¶áá»á¬áž (á¥ááá¬á ááá¬ážáá»á¬ážááŸáá·áº áá±á¬ááºáá¬áá»á¬ážááá¯á·) áá±á«áºááá¯ááŸá¯áá»á¬ážááŸááá±áá«áá áááºážááá¯á·á ID áá»á¬ážá¡á á¬áž áá¯ááá»á¬ážáá«ááŸááááºá ááá¯ááá¯áááºááŸá¬á ááá¯áá¯ááºááᯠáá¯ááºáá±á¬ááºááááá«á kernel áá²ááá¯á· ááááºáá®á kernel áá±á«áºááá¯ááŸá¯áá»á¬ážááŸáá áºááá·áº áááºáá®ážáá¬ážáá±á¬ áá®ážááŒá¬ážá¡áá¬áá»á¬ážá ID áá»á¬ážááᯠá€áá¯á (áá¯ááºááᯠááá·áºááº) ááŒáá·áº á¡á á¬ážááá¯ážááá«áááºá áááºááẠáááºážááᯠááŒááºáá¡áá¯á¶ážá¡áá±á¬ááºáá»á¬ážááŒáá·áº áá¯ááºáá±á¬ááºááá¯ááºáááºá ááá¯á·ááá¯áẠááá·áºááºááŸáá·áº áá®ážááŒá¬áž filter áá áºáá¯ááᯠáááºááá·áº áááá¯ááááºáá áºáᯠáá±ážááá¯ááºáááºá
- kernel ááẠloaded áááá¯ááááºááá¯á á áºáá±ážáááºá áááºážááẠáááºáá±á·áá»áºááŸáá·áº á¡á á¯á¡á ááºážáá»á¬ážá ááœááºáá±á«ááºáááŸáááŒááºážááŸáá·áº áá¶ááá¬áááŸáááŒááºážááá¯á·ááᯠá á áºáá±ážáááºá á áá á áºáá°ááẠáá¯ááºááŸááºáááºááŒá±á¬ááºáž áááºáá±áááŒááá¯ááºáá«á áááá¯ááááºááᯠáááºáá»ááẠ- áá áºá á¯á¶áá áºáá±á¬ááºááẠáá°á·á¡á¬áž áá»á±áááºááá¯ááºá á±ááááºá
- á¡á±á¬ááºááŒááºá áœá¬á¡áááºááŒá¯ááŒá®ážáá±á¬ááºá kernel ááẠeBPF áááá¯áá¬á¡áá¬ááá¹áá¯áá¯ááºááᯠá áá áºáááá¯áá¬á ááºáá¯áẠ(á¡áá»áááºááŸáá·áºáááŒá±ážáá®) ááœááºá á¯á ááºážáááºá
- áááá¯ááááºááẠá¡ááºáá¬áá±á·á áºááá¯á· áá»áááºáááºáá¬ážááŒá®áž áááºáááºáá»á¬ážááᯠá áááºáá¯ááºáá±á¬ááºáááºá
XDP ááẠkernel ááœááºá¡áá¯ááºáá¯ááºáá±á¬ááŒá±á¬áá·áºá á¡ááŸá¬ážááŸá¬ááŒááºážá¡á¬áž ááŒá±áá¬áá¶ááŸááºáááºážáá»á¬ážááŒáá·áº áá¯ááºáá±á¬ááºááŒá®áž á¡ááŸááºááááºá¡á¬ážááŒáá·áº áááá¯ááááºá០á á áºáá¯ááºááŒááºáž ááá¯á·ááá¯áẠáá¯ááºáá±ážááá·áº áááºáááºáá»á¬ážááŒáá·áº ááŒá¯áá¯ááºááŒááºážááŒá áºáááºá ááá¯á·áá±á¬áºá eBPF ááẠá áá áºá¡ááœáẠáá±á«ááºážáá¯ááºáá¯ááºáá¬ážáá±á¬áá¯ááºááᯠáá¯á¶ááŒá¯á¶á áœá¬ ááááºážááááºážáá¬ážáá±á¬ááŒá±á¬áá·áº áááºááẠáááºá local Linux ááœáẠXDP ááŸáá·áº á ááºážáááºááá¯ááºáááºá
áááºáááºážáá»ááºááŒááºáááºááŒááºážá
á¡á ááºážá¡áá±áž
Clang ááẠeBPF áááá¯áá¬á¡ááœáẠá¡áá¬ááá¹áá¯áá¯ááºááᯠááá¯ááºááá¯ááºáá¯ááºááá±ážááá¯ááºáá±á¬ááŒá±á¬áá·áº áá¯ááºáááºážá ááºááœáẠá¡ááá·áºááŸá áºááá·áºáá«ááŸááááº-
- C áá¯ááºááᯠLLVM bytecode ááá¯á· á
á¯á
ááºážáá« (
clang -emit-llvm
). - bytecode ááᯠeBPF á¡áá¬ááá¹áá¯áá¯ááºááá¯á· ááŒá±á¬ááºážáá« (
llc -march=bpf -filetype=obj
).
á
á
áºáá¯ááºááŸá¯áá
áºáá¯áá±ážáá±á¬á¡áá«á á¡áááºáá¯ááºáá±á¬ááºáá»ááºáá»á¬ážááŸáá·áº áááºáááá¯áá»á¬ážáá«ááá·áº ááá¯ááºá¡áá»áá¯á·ááẠá¡áááºááŒá±áá¬áá«áááá·áºáááºá KVER
) áááºážááá¯á·ááᯠáá±á«ááºážáá¯ááºáá¯ááºáá«á helpers/
:
export KVER=v5.3.7
export BASE=https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/plain/tools/testing/selftests/bpf
wget -P helpers --content-disposition "${BASE}/bpf_helpers.h?h=${KVER}" "${BASE}/bpf_endian.h?h=${KVER}"
unset KVER BASE
Arch Linux á¡ááœáẠMakefile (kernel 5.3.7):
CLANG ?= clang
LLC ?= llc
KDIR ?= /lib/modules/$(shell uname -r)/build
ARCH ?= $(subst x86_64,x86,$(shell uname -m))
CFLAGS =
-Ihelpers
-I$(KDIR)/include
-I$(KDIR)/include/uapi
-I$(KDIR)/include/generated/uapi
-I$(KDIR)/arch/$(ARCH)/include
-I$(KDIR)/arch/$(ARCH)/include/generated
-I$(KDIR)/arch/$(ARCH)/include/uapi
-I$(KDIR)/arch/$(ARCH)/include/generated/uapi
-D__KERNEL__
-fno-stack-protector -O2 -g
xdp_%.o: xdp_%.c Makefile
$(CLANG) -c -emit-llvm $(CFLAGS) $< -o - |
$(LLC) -march=bpf -filetype=obj -o $@
.PHONY: all clean
all: xdp_filter.o
clean:
rm -f ./*.o
KDIR
kernel áá±á«ááºážá
á®ážáá»á¬ážáá®ááá¯á· áááºážááŒá±á¬ááºážáá«áááºáááºá ARCH
- á
áá
áºáááá¯áá¬á áááºážááŒá±á¬ááºážáá»á¬ážááŸáá·áº áááááá¬áá»á¬ážááẠááŒáá·áºáá±ááŸá¯áá»á¬ážááŒá¬ážááœáẠá¡áááºážáááºááœá²ááŒá¬ážááá¯ááºáááºá
Debian 10 á¡ááœáẠááœá¬ááŒá¬ážáá»áẠá¥ááᬠ(kernel 4.19.67)
# ÐŽÑÑÐ³Ð°Ñ ÐºÐŸÐŒÐ°ÐœÐŽÐ°
CLANG ?= clang
LLC ?= llc-7
# ÐŽÑÑгПй каÑалПг
KDIR ?= /usr/src/linux-headers-$(shell uname -r)
ARCH ?= $(subst x86_64,x86,$(shell uname -m))
# Ўва ЎПпПлМОÑелÑÐœÑÑ
каÑалПга -I
CFLAGS =
-Ihelpers
-I/usr/src/linux-headers-4.19.0-6-common/include
-I/usr/src/linux-headers-4.19.0-6-common/arch/$(ARCH)/include
# Ўалее без ОзЌеМеМОй
CFLAGS
á¡áááºáá±á«ááºážá
á®ážáá»á¬ážáá«ááŸááá±á¬ áááºážááœáŸááºáá
áºáá¯ááŸáá·áº kernel áá±á«ááºážá
á®ážáá»á¬ážáá«ááŸááá±á¬ áááºážááœáŸááºáá»á¬áž áá«áááºáááºá áááºá¹áá±á __KERNEL__
á
á
áºáá¯ááºááŸá¯ááᯠkernel ááœááºáá¯ááºáá±á¬ááºáá±á¬ááŒá±á¬áá·áº UAPI (userspace API) áá±á«ááºážá
á®ážáá»á¬ážááᯠkernel áá¯ááºá¡ááœáẠáááºááŸááºáá¬ážááŒá±á¬ááºáž ááá¯ááá¯áááºá
Stack áá¬ááœááºááŸá¯ááᯠááááºáá¬ážááá¯ááºááẠ(-fno-stack-protector
) á¡áááºááŒá±á¬áá·áºááá¯áá±á¬áº eBPF áá¯ááºá¡áááºááŒá¯áá°ááẠstack boundaries ááŸááá¯ááºááŒá±á¬ááºážá
á
áºáá±ážáá±á¬ááŒá±á¬áá·áºááŒá
áºáááºá eBPF bytecode áá¡ááœááºá¡á
á¬ážááŸá¬ á¡ááá·áºá¡áááºááŸááá±á¬ááŒá±á¬áá·áº ááá¯ááá¯áá±á¬ááºážááœááºá¡á±á¬ááºááŒá¯áá¯ááºááŒááºážááᯠáááºáá»ááºáá»ááºážááœáá·áºááá·áºáááºá
áááºáá±á·áá»áºáá»á¬ážá¡á¬ážáá¯á¶ážááᯠáá»á±á¬áºááœá¬ážáᬠáá¬ááŸááá¯ááºáá² á á áºáá¯ááºááŸá¯áá áºáá¯ááŒáá·áº á áááºááŒáá«á áá¯á·á
#include <uapi/linux/bpf.h>
#include <bpf_helpers.h>
SEC("prog")
int xdp_main(struct xdp_md* ctx) {
return XDP_PASS;
}
char _license[] SEC("license") = "GPL";
á¡ááœá²á· make
á
á¯áá±á¬ááºážááẠxdp_filter.o
. á¡áá¯áááºááŸá¬á
ááºážáááºááá¯ááºááá²á
á ááºážáááºááŸá¯áááº
áááºáááºáá»ááºááœáẠá¡ááºáá¬áá±á·á áºááŸá áºáá¯áá«áááºááá·áºáááº- á á áºáá¯ááºááŸá¯áá áºáá¯ááŸááááºááŒá áºááŒá®áž áááºááá·áºáááºáááºáá»á¬ážááᯠáá±ážááá¯á·áááºáááºážá áá»áœááºá¯ááºááá¯á·á filter ááŸáá·áº áá¯á¶ááŸááºá¡ááá®áá±ážááŸááºážáá»á¬áž áááºááá¯á·á¡áá¯ááºáá¯ááºáááºááᯠá á áºáá±ážáááºá¡ááœáẠáááºážááá¯á·ááẠáááºážááá¯á·áááá¯ááºááá¯áẠIP áá»á¬ážááŒáá·áº á¡ááŒáá·áºá¡á Linux á ááºáá á¹á ááºážáá»á¬áž ááŒá áºááá«áááºá
veth (virtual Ethernet) áá²á·ááá¯á·áá±á¬ á
ááºáá
á¹á
ááºážáá»á¬ážááẠáá»áœááºá¯ááºááá¯á·á¡ááœáẠááá·áºáá»á±á¬áºáááº- áááºážááá¯á·ááẠáá
áºáá¯ááŸáá·áºáá
áºáᯠááá¯ááºááá¯áẠ"áá»áááºáááºáá¬ážááá·áº" virtual network interfaces áá
áºá
á¯á¶ááŒá
áºáááºá áááºá€áá²á·ááá¯á·áá±á¬áá°ááá¯á·ááá¯áááºáá®ážááá¯ááºááẠ(á€ááá¹áááœááºá á¡á¬ážáá¯á¶ážáá±á¬á¡áááá·áºáá»á¬áž ip
ááá¯á·á០ááŒá¯áá¯ááºáá²á·áááºá root
):
ip link add xdp-remote type veth peer name xdp-local
áá«áá¬ááŒá
áºáá«ááẠxdp-remote
О xdp-local
- á
ááºá¡áááºáá»á¬ážá áááẠxdp-local
(192.0.2.1/24) ááá¬áá
áºáá¯ááŸáá·áºá¡áá° áá°ážááœá²áá«ááŸááá«áááºá xdp-remote
(192.0.2.2/24) á¡áááºáááºážááŒá±á¬ááºážááᯠáá±ážááá¯á·áá«áááºá ááá¯á·áá±á¬áºá ááŒá¿áá¬áá
áºáá¯ááŸááá±áááº- á¡ááºáá¬áá±á·á
áºáá»á¬ážááẠáá°áá®áá±á¬á
ááºááœááºááŸáááŒá®ážá Linux ááẠáááºážááá¯á·áá²ááŸáá
áºáá¯áá¶ááá¯á· á¡ááœá¬ážá¡áá¬áá»á¬ážááᯠá¡ááŒá¬ážáá
áºáá¯ááŸáá
áºááá·áº áá±ážááá¯á·áááºááá¯ááºáá«á ááŸá¯ááºááœá±ážáá±á¬ á
ááºážáá»ááºážáá»á¬ážááŒáá·áº áááºááŒá±ááŸááºážááá¯ááºáááºá iptables
áá«áá±ááá·áº á¡ááŸá¬ážááŸá¬ááŒááºáá²á·á¡áá« á¡áááºáááŒá±áá²á· áááºáá±á·ááºá»ááœá±ááᯠááŒá±á¬ááºážááá«áááá·áºáááºá network namespaces (network namespaces, further netns) ááá¯áá¯á¶ážáá¬á ááá¯áá±á¬ááºážáá«áááºá
ááœááºááẠnamespace ááœáẠá¡ááŒá¬áž netns ááŸá á¡áá¬ážáá°á¡áá¬ááá¹áá¯áá»á¬ážá០áá®ážááŒá¬ážááœá²áá¯ááºáá¬ážáá±á¬ á¡ááºáá¬áá±á·á áºáá»á¬ážá áááºážááŒá±á¬ááºážááá¬ážáá»á¬ážááŸáá·áº NetFilter á ááºážáá»ááºážáá»á¬ážáá«ááŸááááºá áá¯ááºáááºážá ááºáá áºáá¯á á®ááẠá¡áá»áá¯á·áá±á¬ namespace ááœááºá¡áá¯ááºáá¯ááºááŒá®áž ဠnetns áá¡áá¬ááá¹áá¯áá»á¬ážááá¯áᬠáááºážááœááºáááá¯ááºáááºá áá¯á¶ááŸááºá¡á¬ážááŒáá·áºá á áá áºááœáẠá¡áá¬ááá¹áá¯á¡á¬ážáá¯á¶ážá¡ááœáẠááœááºáááºá¡áááºááœááºáá áºáᯠááŸááááºá ááá¯á·ááŒá±á¬áá·áº áááºááẠLinux ááœáẠá¡áá¯ááºáá¯ááºááá¯ááºááŒá®áž netns á¡ááŒá±á¬ááºáž ááááá«á
namespace á¡áá
áºáá
áºáá¯áááºáá®ážááŒáá«á
áá¯á· xdp-test
ááá¯áá±áá¬ááá¯á· ááœáŸá±á·áá«á xdp-remote
.
ip netns add xdp-test
ip link set dev xdp-remote netns xdp-test
ááŒá®ážááẠáá¯ááºáááºážá
ááºááœá± áááºáááºáá±áááºá xdp-test
"áááŒááºáá°áž"á xdp-local
(áá°áááºážá¡á¬ážááŒáá·áº netns ááœááºááŸááá±áááº) ááŸáá·áº 192.0.2.1 ááá¯á· packet áá
áºáá¯ááᯠáá±ážááá¯á·ááá·áºá¡áá« áááºážááᯠáá»á±á¬áºááœá¬ážáááºááŒá
áºáá«áááºá xdp-remote
á¡áááºááŒá±á¬áá·áºááá¯áá±á¬áº áááºážááẠá€áá¯ááºáááºážá
ááºá¡ááœáẠ192.0.2.0/24 ááŸá áá
áºáá¯áááºážáá±á¬ á¡ááºáá¬áá±á·á
áºááŒá
áºáááºá áá«áááºáž ááŒá±á¬ááºážááŒááºá¡áá¯ááºáá¯ááºáááºá
netns áá»á¬ážááŒá¬áž ááœáŸá±á·áá±á¬á¡áá«á á¡ááºáá¬áá±á·á
áºááẠáá»ááœá¬ážááŒá®áž ááááºá
á¬ááᯠáá¯á¶ážááŸá¯á¶ážááœá¬ážáááºá netns ááœáẠá¡ááºáá¬áá±á·á
áºááᯠá
áá
áºááá·áºááœááºážáááºá ááẠrun ááẠááá¯á¡ááºáááºá ip ...
ဠcommand namespace ááœáẠip netns exec
:
ip netns exec xdp-test
ip address add 192.0.2.2/24 dev xdp-remote
ip netns exec xdp-test
ip link set xdp-remote up
áááºááŒááºááá·áºá¡ááá¯ááºážá áááºážááẠsetting ááŸáá·áºááá°áá«á xdp-local
áá°áááºáž namespace ááœááº-
ip address add 192.0.2.1/24 dev xdp-local
ip link set xdp-local up
ááŒá±ážááẠtcpdump -tnevi xdp-local
ááá¯á·ááá¯ááºáá²á· packets ááœá±ááᯠááœá±á·ááá¯ááºáá«áááºá xdp-test
á á€á¡ááºáá¬áá±á·á
áºááá¯á· ááá¯á·áá±ážáááº-
ip netns exec xdp-test ping 192.0.2.1
á¡ááœá¶ááᯠááŒá±ážááᬠá¡áááºááŒá±áááºá xdp-test
. repository ááœáẠstand ááŒáá·áº á¡ááá¯á¡áá»á±á¬ááºá¡áá¯ááºáá¯ááºáá±á¬ script áá
áºáá¯áá«ááŸááááºá á¥ááá¬á¡á¬ážááŒáá·áºá áááºááẠstand ááᯠcommand ááŒáá·áºáááºááŸááºááá¯ááºáááºá sudo ./stand up
áááºááŸá¬ážááá¯ááºáá«á sudo ./stand down
.
ááŒá±áá¬áá¶ááŒááºážá
Filter ááᯠá€áá²á·ááá¯á·áá±á¬ á ááºááœáẠááœá²áá¬ážáááºá
ip -force link set dev xdp-local xdp object xdp_filter.o verbose
áá±á¬á· -force
áá±á¬ááºáá
áºáá¯á ááá·áºááºáá»áááºáá¬ážááŒá®ážáá¬ážááá¯ááẠáááá¯ááááºá¡áá
áºáá
áºáá¯ááᯠááá·áºááºáá»áááºááá¯á· ááá¯á¡ááºáááºá "No news is good news" ááẠဠcommand ááŸáá·áº áááºáááºá ááá¯ááºáá² output ááẠáááºááá¯á·áááºááŒá
áºá
á± áá±á¬ááºááá±áá«áááºá ááœáŸááºáጠverbose
á
áááºááŒáá¯ááºááœá±ážáá»ááºááá¯ááºáá±á¬áºáááºáž áááºážááŸáá·áºá¡áá° áááºáááºáá°á
á¬áááºážááŸáá·áºá¡áá° áá¯ááºá¡áááºááŒá¯á
áá
áºáá¡áá¯ááºá¡ááŒá±á¬ááºáž á¡á
á®áááºáá¶á
á¬áá
áºáá¯áá±á«áºáá¬áááº-
Verifier analysis:
0: (b7) r0 = 2
1: (95) exit
áááá¯ááááºááᯠá¡ááºáá¬áá±á·á áºá០áááºáá¯ááºáá«-
ip link set dev xdp-local xdp off
script ááœááºá á€á¡áá¬áá»á¬ážááẠcommand áá»á¬ážááŒá
áºáááºá sudo ./stand attach
О sudo ./stand detach
.
Filter ááᯠáá»ááºááŸá±á¬ááºááŒááºážááŒáá·áºá áááºááẠáááºážááᯠáá±áá»á¬á
á±ááá¯ááºáááºá ping
áááºáááºáá¯ááºáá±á¬ááºáá±áá±á¬áºáááºáž áááá¯ááááºá á¡áá¯ááºááŒá
áºáá«ááá¬ážá ááá¯ááá¯ááá·áºááŒáá¡á±á¬ááºá áá¯ááºáá±á¬ááºáá»áẠbpf_trace_printk()
printf()
á ááá¯á·áá±á¬áº áá¯á¶á
á¶ááŸááœá²á á¡ááŒá¬ážá¡ááŒááºážááœá¬ážááŸá¯ áá¯á¶ážáá¯á¡ááááŸáá·áº ááá·áºáááºáááºááŸááºááŸá¯á
á¬áááºážááᯠáá¶á·ááá¯ážáá±ážáááºá áááºáááᯠbpf_printk()
áá±á«áºááá¯ááŸá¯ááᯠááá¯ážááŸááºážá
á±áááºá
SEC("prog")
int xdp_main(struct xdp_md* ctx) {
+ bpf_printk("got packet: %pn", ctx);
return XDP_PASS;
}
á¡ááœááºááẠááœáá·áºáá¬ážáááºááá¯á¡ááºááá·áº kernel ááŒá±áá¬áá¶áá»ááºáááºááá¯á· ááœá¬ážáááº-
echo -n 1 | sudo tee /sys/kernel/debug/tracing/options/trace_printk
áááºáá±á·áá»áºá á®ážáááºážááŸá¯ááᯠááŒáá·áºáá«-
cat /sys/kernel/debug/tracing/trace_pipe
áá®á¡ááœá²á·ááŸá
áºááœá²á·á áá¯ááºážáááºáááºá sudo ./stand log
.
Ping ááẠááᯠá€áá²á·ááá¯á· áááºáá±á·áá»áºáá»á¬ážááᯠáá¯ááºááá·áºáááº-
<...>-110930 [004] ..s1 78803.244967: 0: got packet: 00000000ac510377
Verifier á output ááᯠá¡áá®ážáááºááŒáá·áºáá»áŸáẠáá°ážáááºážáá±á¬ ááœááºáá»ááºááŸá¯áá»á¬ážááᯠááẠáááááŒá¯ááááá¯ááºáááº-
0: (bf) r3 = r1
1: (18) r1 = 0xa7025203a7465
3: (7b) *(u64 *)(r10 -8) = r1
4: (18) r1 = 0x6b63617020746f67
6: (7b) *(u64 *)(r10 -16) = r1
7: (bf) r1 = r10
8: (07) r1 += -16
9: (b7) r2 = 16
10: (85) call bpf_trace_printk#6
<...>
á¡ááŸááºááŸá¬ eBPF áááá¯ááááºáá»á¬ážááœáẠáá±áá¬á¡ááá¯ááºážáááŸááá±á¬ááŒá±á¬áá·áº áá±á¬áºáááºá á¬áááºážááᯠáá¯ááºáá¯ááºááẠáá áºáá¯áááºážáá±á¬áááºážáááºážááŸá¬ VM command áá»á¬ážá áá»ááºááŒááºážááŒááºážáá¯á¶ááŒááºážááŒá áºáááº-
$ python -c "import binascii; print(bytes(reversed(binascii.unhexlify('0a7025203a74656b63617020746f67'))))"
b'got packet: %pn'
ááá¯á·ááŒá±á¬áá·áºá debug output ááẠááááºááœááºáá¯ááºááᯠá¡ááœááºá¡áá»ááºážáááºá á±áááºá
XDP Packets áá»á¬áž áá±ážááá¯á·ááŒááºážá
á á áºáá¯ááºááŸá¯ááᯠááŒá±á¬ááºážáá²ááá¯ááºáá¡á±á¬ááº- á¡áááºáá¯ááºááá¯ážááŸá¯á¡á¬ážáá¯á¶ážááᯠááŒááºááá¯á·áá±ážáá«á á±á áá±á«ááºážá á®ážáá»á¬ážááŸá ááááºá á¬áá»á¬ážááᯠááŒá±á¬ááºážáá²ááẠááá¯á¡ááºáá±á¬áºáááºáž ááá¯áá°á¡á á¡áá¯ááºááẠá¡áá±ážááŒá®ážáá±á¬ááŒá±á¬áá·áº ááœááºáááºá¡ááŒááºá¡á áááºážááẠááŸá¬ážááœááºážáá±áá«áááºá
bpf_printk("got packet: %pn", ctx);
- return XDP_PASS;
+ return XDP_TX;
}
á
áááºááá¯ááºáá« tcpdump
á¡áá±á«áº xdp-remote
. áááºážááẠáá°áá®áá±á¬á¡ááœááºááŸáá·áºá¡ááẠICMP Echo áá±á¬ááºážááá¯ááŸá¯ááá¯ááŒáááŒá®áž ICMP Echo Reply ááá¯ááŒáááŒááºážááá¯áááºááá·áºááá·áºáááºá áá«áá±ááá·áº áááŒáá°ážá á¡áá¯ááºááŸááœááºáááºá XDP_TX
á¡á
á®á¡á
ááºá¡ááœáẠxdp-local
xdp-remote
áááá¯ááááºááᯠá¡ááœááºááá±áááºáá±á¬ááºá០áá¬áááºáá±ážáá¬ážáááºá
áá«áááºááá¯áááá¬áá²á
á¡ááŒá¬ážáááºááá·áºá¡áá¬ááŸáááŸááá±á¬ááŒá±á¬áá·áºá ááá±á¬ááºážááŸá¯á០áá±á¬ááºážáá»áá¯ážááᯠáá±á¬ááºááááºá
$ sudo perf trace --call-graph dwarf -e 'xdp:*'
0.000 ping/123455 xdp:xdp_bulk_tx:ifindex=19 action=TX sent=0 drops=1 err=-6
veth_xdp_flush_bq ([veth])
veth_xdp_flush_bq ([veth])
veth_poll ([veth])
<...>
Code 6 ááá¯áá¬áá¬áá²á
$ errno 6
ENXIO 6 No such device or address
áá¯ááºáá±á¬ááºáá»áẠveth_xdp_flush_bq()
error code á០áááŸááááºá veth_xdp_xmit()
áááºááŸá¬ááŸá¬ááá²á ENXIO
ááŸááºáá»ááºáá
áºáá¯ááŸá¬áá«á
á¡áááºážáá¯á¶áž á
á
áºáá¯ááºááŸá¯ááᯠááŒááºáá°áá« (XDP_PASS
) ááá¯ááºáá²ááŸá¬ xdp_dummy.c
áááºážááᯠMakefile ááœááºááá·áºáá«á áá»áááºáááºáá«á xdp-remote
:
ip netns exec remote
ip link set dev int xdp object dummy.o
ááᯠtcpdump
áá»áŸá±á¬áºááá·áºáá¬ážáááºááᯠááŒááááº-
62:57:8e:70:44:64 > 26:0e:25:37:8f:96, ethertype IPv4 (0x0800), length 98: (tos 0x0, ttl 64, id 13762, offset 0, flags [DF], proto ICMP (1), length 84)
192.0.2.2 > 192.0.2.1: ICMP echo request, id 46966, seq 1, length 64
62:57:8e:70:44:64 > 26:0e:25:37:8f:96, ethertype IPv4 (0x0800), length 98: (tos 0x0, ttl 64, id 13762, offset 0, flags [DF], proto ICMP (1), length 84)
192.0.2.2 > 192.0.2.1: ICMP echo request, id 46966, seq 1, length 64
áááºážá¡á
á¬áž ARP ááá¯áᬠááŒááá«áá áááºááẠá
á
áºáá¯ááºááŸá¯áá»á¬ážááᯠáááºááŸá¬ážááẠááá¯á¡ááºááẠ(áááºážááᯠááŒá¯áá¯ááºáááºá sudo ./stand detach
) áá¬ážáá«áá±á¬á· ping
ááá¯á·áá±á¬áẠá
á
áºáá¯ááºááŸá¯áá»á¬ážááᯠááá·áºááœááºážááŒá®áž áááºá
ááºážááŒáá·áºáá«á ááŒá¿áá¬ááá±á¬á· filter áá«á XDP_TX
ARP ááá¯áááºáž áááºáá±á¬ááºááŸá¯ááŸáááŒá®áž stack ááŒá
áºáááº
á¡áááºáá±áá¬áá»á¬áž xdp-test
MAC ááááºá
ᬠ192.0.2.1 ááᯠ"áá±á·" ááẠá
á®áá¶áá¬ážááŒá®ážá áá°ááẠဠIP ááᯠââááŒá±ááŸááºážááá¯ááºááẠááá¯ááºáá«á
ááŒá¿áá¬ááá¯áá¯á¶áá±á¬áºááŒááºáž
XDP ááœáẠSYN ááœááºáá®ážááá¹ááá¬ážáá áºáá¯áá±ážááẠáá±á¬áºááŒáá¬ážááá·áºáá¬áááºááá¯á· áááºááœá¬ážááŒáá«á áá¯á·á
ááá¯á¡áá»áááºá¡áá SYN áá±ááœáŸááºážááá¯ážááŸá¯ááẠáá°ááŒáá¯ááºáá»á¬ážáá±á¬ DDoS ááá¯ááºááá¯ááºááŸá¯áá áºáá¯á¡ááŒá Ạáá»ááºááŸááá±áááºá áááºážáá¡ááŸá áºáá¬áááŸá¬ á¡á±á¬ááºáá«á¡ááá¯ááºážááŒá áºáááºá áá»áááºáááºááŸá¯áá áºáá¯áááºáá±á¬ááºáá±á¬á¡áá« (TCP áááºááœá²ááŸá¯ááºáááºááŒááºáž) áá¬áá¬ááẠSYN ááá¯áááºáá¶áááŸáááŒá®áž á¡áá¬áááºáá»áááºáááºááŸá¯á¡ááœáẠá¡áááºážá¡ááŒá áºáá»á¬ážááᯠááœá²áá±áá±ážáᬠSYNACK áááºáááºáá áºáá¯ááŒáá·áº áá¯á¶á·ááŒááºááŒá®áž ACK ááá¯á á±á¬áá·áºááá¯ááºážáááºá ááá¯ááºááá¯ááºáá°ááẠáá±á¬ááºáá±á«ááºážáá»á¬ážá áœá¬áá±á¬ botnet áá áºáá¯ááœáẠhost áá áºáá¯á á®á០áá áºá áá¹ááá·áºáá»áŸáẠáá±á¬ááºáá±á«ááºážáá»á¬ážá áœá¬áá±á¬ ááááºá á¬á¡áá¯áá»á¬ážá០SYN packet áá»á¬ážááᯠááá¯ážááŸááºážá áœá¬ áá±ážááá¯á·áá«áááºá áá¬áá¬ááẠáááºáááºáá±á¬ááºááŸááá»áááºááœáẠá¡áááºážá¡ááŒá áºáá»á¬ážááᯠáá»ááºááŒááºážááœá²áá±áá±ážááẠá¡áááºážá¡ááŒááºááá¯ááºážá á±áá±á¬áºáááºáž á¡áá»áááºá¡áá±á¬áºááŒá¬ááŒá®ážáá±á¬áẠáááºážááᯠáá¯ááºááœáŸááºááá¯ááºáᬠááááºá¡áá±ááŒáá·áº áááºááá¯áá® ááá¯á·ááá¯áẠááá·áºáááºáá»ááºáá»á¬áž áá¯ááºáá¯á¶ážááœá¬ážáᬠáá»áááºáááºááŸá¯á¡áá áºáá»á¬ážááᯠáááºáá¶ááŒááºážáááŸááá±á¬á·áá² áááºáá±á¬ááºááŸá¯ááᯠááááá¯ááºáá«á
SYN áááºáááºááœáẠá¡áááºážá¡ááŒá
áºáá»á¬ážááᯠááœá²áá±ááá±ážáá«á SYNACK áááºáá±á·ááºá»ááŒáá·áºáᬠáá¯á¶á·ááŒááºáá«áá áá±á¬ááºááŸáá¬áá±á¬ ACK áááºáááºááẠáááááºážáááºážááá±ážáá±á¬ SYN áááºáááºááŸááŒá
áºááŒá±á¬ááºáž áá¬áá¬á áááºááá¯á·áá¬ážáááºááá¯ááºáááºáááºážá áá±á¬ááºáá¯á¶ážááœááºá ááá¯ááºááá¯ááºáá°ááẠACK á¡áá¯áá»á¬ážááá¯áááºáž áááºáá®ážááá¯ááºáááºá SYN cookie á á¡ááŸá
áºáá¬áááŸá¬ áá¯ááºááœááºážááẠááŒá
áºáááºá seqnum
áá»áááºáááºááŸá¯áá±á¬ááºáá»á¬ážááẠááááºá
á¬áá»á¬ážá ááááºáááºážáá»á¬ážááŸáá·áº áá¬ážááŒá±á¬ááºážáá²ááŒááºážá hash á¡ááŒá
áºá áá¬ážáááŒá±á¬ááºážáá²áá® ACK áá±á¬ááºááŸááá¬áá«áá hash ááᯠáááºáá¶ááœááºáá»ááºááŒá®áž ááŸáá¯ááºážááŸááºááá¯ááºáá«áááºá acknum
. á¡áᯠacknum
áá¬ážááœáẠáá»áŸáá¯á·ááŸááºáá»ááºáá«áááºáá±á¬ááŒá±á¬áá·áº ááá¯ááºááá¯ááºáá°ááẠá¡ááá·áºá¡áááºááŸááá±á¬áá»ááºáááºááŒá±á¬áá·áº áááºážááᯠá
á®áááºá¡áá»áááºáááŸááá±á¬ááŒá±á¬áá·áºááŒá
áºáááºá
SYN cookies áá»á¬ážááᯠLinux kernel ááœáẠá¡áá»áááºá¡áá±á¬áºááŒá¬ á¡áá¯á¶ážááŒá¯áá¬ážááŒá®áž SYN áá»á¬áž áá»ááºááŒááºá áœá¬ááŸáá·áº á¡á á¯ááá¯ááºáá±á¬ááºááŸááá«á á¡ááá¯á¡áá»á±á¬ááºááœáá·áºáá±ážááá¯ááºáá«áááºá
TCP áááºááœá²ááŒááºážááá¯ááºáᬠááá¬áá±ážá¡á á®á¡á ááº
TCP ááẠááá¯ááºáá»á¬ážá á®ážááŒá±á¬ááºážá¡ááŒá Ạáá±áá¬ááœáŸá²ááŒá±á¬ááºážááŒááºážááᯠáá¶á·ááá¯ážáá±ážáááºá á¥ááá¬á HTTP áá±á¬ááºážááá¯áá»ááºáá»á¬ážááᯠTCP ááŸáááá·áº áá±ážááá¯á·áá«áááºá á ááºážáá»á±á¬ááºážááẠáá¯ááºááá¯ážááŸá¯áá»á¬ážááœáẠá¡ááá¯ááºážáá áºáá¯ááŒá®ážáá áºáᯠáá¯ááºááœáŸáá·áºáááºá TCP áááºáá±á·áá»áºá¡á¬ážáá¯á¶ážááœáẠáá¯áá¹áááááºáá±á¬á¡áá¶áá»á¬ážááŸáá·áº 32-áá áºááá·áºááááºážáá¶áá«ááºáá»á¬áž ááŸááááº-
-
á¡áá¶áá»á¬ážá áá±á«ááºážá ááºááŸá¯ááẠáá®ážááŒá¬áž package áá áºáá¯á á¡áááºážááá¹áááᯠáááºááŸááºáááºá SYN á¡áá¶ááẠá€áá»áááºáááºááŸá¯ááœáẠáá±ážááá¯á·áá°á ááááá¯á¶áž áááºáááºááᯠááá¯ááá¯áááºá ACK á¡áá¶ááẠáá±ážááá¯á·áá°ááẠáá áºááá¯ááºá¡áá áá»áááºáááºááŸá¯áá±áá¬á¡á¬ážáá¯á¶ážááᯠáááºáá¶áááŸááá¬ážááŒá±á¬ááºáž ááá¯ááá¯áááºá
acknum
. áááºáá±á·ááºá»áá áºáá¯ááœáẠá¡áá¶áá»á¬ážá áœá¬áá«ááŸáááá¯ááºááŒá®ážá á¥ááá¬á SYNACK áááºáááºááᯠáááºážááá¯á·áá±á«ááºážá ááºááŒá®ážáá±á¬áẠá¡áááºáá±ážáá¬ážáááºá -
áá¶áá«ááºá áẠ(seqnum) ááẠá€áááºáááºááœáẠáá±ážááá¯á·ááá·áº ááááá¯á¶áž byte á¡ááœáẠáá±áá¬á á®ážááŒá±á¬ááºážááœáẠáá±áááᯠáááºááŸááºáááºá á¥ááá¬á¡á¬ážááŒáá·áºá áá±áᬠX bytes áá«áá±á¬ ááááááºáááºááœáẠá€áá¶áá«ááºááẠN ááŒá áºáá«áá áá±áá¬á¡áá áºáá«áá±á¬ áá±á¬ááºáá¯ááºááá¯ážááœáẠN+X ááŒá áºáááá·áºáááºá áá»áááºáááºááŸá¯á¡á ááœááºá áá«áá®áá áºáá¯á á®ááẠá€áá¶áá«ááºááᯠáá»áááºážááœá±ážáá»ááºáááºá
-
á¡ááá¡ááŸááºááŒá¯áá¶áá«áẠ(acknum) - seqnum ááŸáá·áº áá°áá®áá±á¬ offset ááŒá áºáá±á¬áºáááºážá áááºážááẠááá¯á·ááœáŸááºáá±á¬ byte á¡áá±á¡ááœááºááᯠááááºááŸááºáá¬ážáá²á áááºáá¶áá°áá¶á០ááááá¯á¶áž byte á¡áá±á¡ááœááºá
áá»áááºáááºááŸá¯á¡á
ááœáẠááŸá
áºáááºááá±á¬áá°ááááºá seqnum
О acknum
. client ááẠáááºážááŸáá·áºá¡áá° SYN packet áá
áºáá¯ááᯠáá±ážááá¯á·áááºá seqnum = X
. áá¬áá¬ááẠáááºážáááá¯ááºááá¯ááºáá±ážáá¬ážááá·áº SYNACK áááºáááºááŒáá·áº áá¯á¶á·ááŒááºáááºá seqnum = Y
ááŒá®ážáá±á¬ acknum = X + 1
. client ááẠACK packet ááŒáá·áº SYNACK ááᯠáá¯á¶á·ááŒááºáááºá seqnum = X + 1
, acknum = Y + 1
. ááá¯á·áá±á¬ááºá á¡ááŸááºááááºáá±áá¬ááœáŸá²ááŒá±á¬ááºážááŒááºážá
áááºáááºá
á¡ááŒááºá¡ááŸááºááŒá±á¬ááá¯áá°ááẠpacket ááááºáá¶áááŸáááŸá¯ááᯠá¡ááá¡ááŸááºáááŒá¯áá«á TCP ááẠá¡áá»áááºááœááºááŒá®áž áááºážááá¯ááŒááºáááºáá±ážááá¯á·áá«áááºá
SYN ááœááºáá®ážáá»á¬ážááᯠá¡áááºááŒá±á¬áá·áº á¡ááŒá²á¡áá¯á¶ážáááŒá¯áááááºážá
ááááŠážá áœá¬ SYNACK ááá¯á·ááá¯áẠACK áá»á±á¬ááºáá¯á¶ážááœá¬ážáá«á ááŒááºáááºáá±ážááá¯á·ááŸá¯ááᯠá á±á¬áá·áºááá«ááẠ- áá»áááºáááºááŸá¯ áááºáá±á¬ááºááŸá¯ ááŸá±ážááœá±ážááœá¬ážáá«áááºá áá¯áááá¡áá»ááºááŸá¬ SYN packet ááœáẠ- áááºážááœááºáá¬á - áá»áááºáááºááŸá¯ááá±á¬ááºáááºáá¯ááºáá±á¬ááºááŸá¯ááá¯á¡áá»áá¯ážáááºáá±á¬ááºá á±ááá·áºááœá±ážáá»ááºá áá¬áá»á¬ážá áœá¬ááá¯áá¯ááºááœáŸáá·áºáááºá á¡ááẠSYN áááºáá±á·ááºá»áá»á¬ážááᯠáááŸááºáááá²á ááá¯á·ááŒá±á¬áá·áº áá¬áá¬ááẠá€ááœá±ážáá»ááºááŸá¯áá»á¬ážááᯠáá»á áºáá»á°ááŸá¯áá¬á á¡á±á¬ááºáá« áá¯ááºááá¯ážááŸá¯áá»á¬ážááœáẠáá¯á¶ážá áœá²áá°á áááºážááá¯á·ááᯠáá±ážááá¯á·áá±á¬á·ááẠááá¯ááºáá«á TCP á€ááá á¹á ááœááºá¡áá¯ááºáá¯ááºááá¯ááºáá±á¬áºáááºážá¡áááºážáá¯á¶ážáááŠážá¡ááá·áºááœááºá áá»áááºáááºááŸá¯á¡áááºá¡ááœá±ážáá»áááºážáááá·áºáááºá
áááºáá±á·áá»áºáá»á¬ážááŸáá·áºáááºáááºá XDP áááá¯ááááºáá áºáá¯ááẠá¡á±á¬ááºáá«á¡ááá¯ááºážáá¯ááºáá±á¬ááºááá·áºáááº-
- cookie ááŒáá·áº SYN ááᯠSYNACK ááŒáá·áº áá¯á¶á·ááŒááºáá«á
- RST ááŒáá·áº ACK ááŒá±áá« (áá»áááºáááºááŸá¯ááᯠáá»áá¯ážáá»ááºáá«);
- áááŒá¬áž packet ááœá±ááᯠáá»ááá¯ááºáá«á
áááºáááºááœá²ááŒááºážá áááºááŒá¬ááŸá¯ááŸáá·áºá¡áá° algorithm á Pseudocode
ÐÑлО ÑÑП Ме Ethernet,
пÑПпÑÑÑОÑÑ Ð¿Ð°ÐºÐµÑ.
ÐÑлО ÑÑП Ме IPv4,
пÑПпÑÑÑОÑÑ Ð¿Ð°ÐºÐµÑ.
ÐÑлО аЎÑÐµÑ Ð² ÑаблОÑе пÑПвеÑеММÑÑ
, (*)
ÑЌеМÑÑОÑÑ ÑÑеÑÑОк ПÑÑавÑОÑ
ÑÑ Ð¿ÑПвеÑПк,
пÑПпÑÑÑОÑÑ Ð¿Ð°ÐºÐµÑ.
ÐÑлО ÑÑП Ме TCP,
ÑбÑПÑОÑÑ Ð¿Ð°ÐºÐµÑ. (**)
ÐÑлО ÑÑП SYN,
ПÑвеÑОÑÑ SYN-ACK Ñ cookie.
ÐÑлО ÑÑП ACK,
еÑлО в acknum Ð»ÐµÐ¶ÐžÑ ÐœÐµ cookie,
ÑбÑПÑОÑÑ Ð¿Ð°ÐºÐµÑ.
ÐаМеÑÑО в ÑаблОÑÑ Ð°ÐŽÑÐµÑ Ñ N ПÑÑавÑОÑ
ÑÑ Ð¿ÑПвеÑПк. (*)
ÐÑвеÑОÑÑ RST. (**)
РПÑÑалÑÐœÑÑ
ÑлÑÑаÑÑ
ÑбÑПÑОÑÑ Ð¿Ð°ÐºÐµÑ.
áá
áºáá»áá¯áž (*)
á
áá
áºáá¡ááŒá±á¡áá±ááᯠá
á®áá¶ááá·áºááœá²ááẠááá¯á¡ááºááá·áºá¡áá»ááºáá»á¬ážááᯠá¡ááŸááºá¡áá¬ážááŒá¯áá¬ážáá«ááẠ- áááá¡ááá·áºááœááºá SYN cookie áá
áºáá¯ááᯠseqnum á¡ááŒá
áºáááºáá®ážááŒááºážááŒáá·áº TCP áááºááœá²ááŒááºážááᯠá¡áá±á¬ááºá¡áááºáá±á¬áºááŒááºážááŒáá·áº áááºážááá¯á·ááá«áá² áááºáá¯ááºáá±á¬ááºááá¯ááºáááºá
ááá¯áá±áá¬ááŸá¬áá² (**)
áá»áœááºá¯ááºááá¯á·ááœáẠááá¬ážáááŸááá±á¬áºáááºážá áááºáááºááᯠáá»á±á¬áºááœá¬ážáá«áááºá
TCP áááºááœá² á¡áá±á¬ááºá¡áááºáá±á¬áºááŒááºážá
áááºáá±á·áá»áºááœá²ááŒááºážá áááºááŒá¬ááŒááºážááŸáá·áº áá¯ááºá¡áááºááŒá¯ááŒááºážá
áá»áœááºá¯ááºááá¯á·ááẠááœááºáááºáá±á«ááºážá
á®ážáááºáá±á¬ááºáá¯á¶áá»á¬áž ááá¯á¡ááºáááº- Ethernet (uapi/linux/if_ether.h
), IPv4 (uapi/linux/ip.h
) ááŸáá·áº TCP (uapi/linux/tcp.h
) áááºá
ááºá¡ááŸá¬ážá¡ááœááºážááŒá±á¬áá·áº áá»áœááºáá±á¬áº áááºááœááºááááá²á·áá±á¬ áá±á¬ááºáá¯á¶ážáá
áºáᯠatomic64_t
ááá¯á¡ááºáá±á¬á¡áááá¹áá«ááºááœáá·áºááá¯áá»ááºáá»á¬ážááᯠáá¯ááºáá²ááá¯á· áá°ážáá°áá²á·áá«áááºá
kernel ááŸá eBPF á¡áááºááŒá¯áá°ááẠback jumps áá»á¬ážááᯠáá¬ážááŒá áºáá¬ážááŒá®ážá á¡ááŸááºááŸá¬á loops ááŸáá·áº function calls áá»á¬ážááᯠC ááœáẠááœá²ááŒá¬ážááááŒááºááá¯ááºá á±áááºá¡ááœáẠáá¯ááºáá±á¬ááºáá»ááºá¡á¬ážáá¯á¶ážááᯠáá±á«áºááá¯ááŸá¯ááá¯ááºááœáẠááá·áºááœááºážááá«áááºá
#define INTERNAL static __attribute__((always_inline))
ááá¹áááᯠLOG()
áá¯ááºáá±ááŸá¯áááºáá±á¬ááºááŸá¯ááœáẠáá¯á¶ááŸáááºááŒááºážááᯠááááºáááºá
áááá¯ááááºááẠáá¯ááºáááºážáá±á¬ááºáá¬áá»á¬ážá ááá¯ááºááá¯ááºážáá
áºáá¯ááŒá
áºáááºá áá
áºáá¯á
á®ááẠáááºááá¯ááºáá¬á¡ááá·áºá áá±á«ááºážá
á®ážááᯠáá®ážáá±á¬ááºážááá¯ážááŒáá¬ážááá·áº packet áá
áºáá¯ááᯠáááºáá¶áááŸááááºá á¥ááá¬á process_ether()
ááŒáá·áºááá¯á·á
á±á¬áá·áºáá±áááºá ether
. áááºáááºááœá²ááŒááºážá
áááºááŒá¬ááŸá¯ááááºáá»á¬ážá¡áá±á«áº á¡ááŒá±áá¶á áá¯ááºáá±á¬ááºáá»ááºááẠáááºáááºááᯠááá¯ááá¯ááŒáá·áºáá¬ážáá±á¬á¡ááá·áºááá¯á· ááœáŸá²ááŒá±á¬ááºážáá±ážááá¯ááºáááºá áá¯ááºáá±á¬ááºáá»ááºáááááºááẠXDP áá¯ááºáá±á¬ááºáá»ááºááŒá
áºáááºá SYN ááŸáá·áº ACK handlers áá»á¬ážááẠpacket á¡á¬ážáá¯á¶ážááᯠááŒááºáááºážááœáá·áºáá±ážáá±á¬áºáááºážá
struct Packet {
struct xdp_md* ctx;
struct ethhdr* ether;
struct iphdr* ip;
struct tcphdr* tcp;
};
INTERNAL int process_tcp_syn(struct Packet* packet) { return XDP_PASS; }
INTERNAL int process_tcp_ack(struct Packet* packet) { return XDP_PASS; }
INTERNAL int process_tcp(struct Packet* packet) { ... }
INTERNAL int process_ip(struct Packet* packet) { ... }
INTERNAL int
process_ether(struct Packet* packet) {
struct ethhdr* ether = packet->ether;
LOG("Ether(proto=0x%x)", bpf_ntohs(ether->h_proto));
if (ether->h_proto != bpf_ntohs(ETH_P_IP)) {
return XDP_PASS;
}
// B
struct iphdr* ip = (struct iphdr*)(ether + 1);
if ((void*)(ip + 1) > (void*)packet->ctx->data_end) {
return XDP_DROP; /* malformed packet */
}
packet->ip = ip;
return process_ip(packet);
}
SEC("prog")
int xdp_main(struct xdp_md* ctx) {
struct Packet packet;
packet.ctx = ctx;
// A
struct ethhdr* ether = (struct ethhdr*)(void*)ctx->data;
if ((void*)(ether + 1) > (void*)ctx->data_end) {
return XDP_PASS;
}
packet.ether = ether;
return process_ether(&packet);
}
A ááŸáá·áº B áᯠá¡ááŸááºá¡áá¬ážááŒá¯áá¬ážááá·áº áá»ááºáááºááŸááºáá»á¬ážááᯠáá»áœááºá¯áẠá¡á¬áá¯á¶á áá¯ááºáá«áááºá á¡áááºá áááºááẠA ááᯠááŸááºáá»ááºáá±ážáá«áá áááá¯ááááºá áááºáá±á¬ááºáááºá ááá¯á·áá±á¬áº ááœáá·áºááá·áºá¡áá« á¡áááºááŒá¯áá»áẠá¡ááŸá¬ážá¡ááœááºáž ááŸááááá·áºáááº-
Verifier analysis:
<...>
11: (7b) *(u64 *)(r10 -48) = r1
12: (71) r3 = *(u8 *)(r7 +13)
invalid access to packet, off=13 size=1, R7(id=0,off=0,r=0)
R7 offset is outside of the packet
processed 11 insns (limit 1000000) max_states_per_insn 0 total_states 0 peak_states 0 mark_read 0
Error fetching program/map!
áá±á¬á·ááŒáá¯áž invalid access to packet, off=13 size=1, R7(id=0,off=0,r=0)
: ááŒá¬ážáá¶áá¡á
á០12th byte ááẠpacket á¡ááŒááºáááºááœáẠááŸááá±áá±á¬á¡áá«ááœáẠáá¯ááºáá±á¬ááºááŸá¯áááºážááŒá±á¬ááºážáá»á¬ážááŸááá«áááºá áá»áœááºá¯ááºááá¯á·ááŒá±á¬áá±ááá·áºá
á¬ááŒá±á¬ááºážá
á¬áááºážááŸááŒá±á¬ááŒáááºáááºáá²áá±á¬áºáááºážá ááœáŸááºááŒá¬ážáá»ááºáá¶áá«áẠ(áá) ááŸáá·áº source code áááá¯ááºážáá»á¬ážááá¯ááŒáááá·áº disassembler áá
áºáá¯ááŸááááº-
llvm-objdump -S xdp_filter.o | less
á€ááá á¹á ááœááºá áá»ááºážááŒá±á¬ááºážááá¯ááœáŸááºááŒáááºá
LOG("Ether(proto=0x%x)", bpf_ntohs(ether->h_proto));
á¡á²áá«á ááŒá¿áá¬ááŒá
áºáááºááá¯áᬠááŸááºážáá«áááºá ether
. á¡ááŒá²áááºáž áá®ááá¯áá«áá²á
SYN ááᯠá¡ááŒá±á¬ááºážááŒááºáá«á
á€á¡ááá·áºááœáẠáááºááœááºáá»ááºááŸá¬ ááŸááºáááºáá±á¬ SYNACK packet áá
áºáá¯ááᯠáá¯á¶áá±áá
áºáá¯ááŒáá·áº áá¯ááºáá¯ááºáááºááŒá
áºáááºá seqnum
á¡áá¬áááºááœáẠSYN ááœááºáá®ážááŒáá·áº á¡á
á¬ážááá¯ážáá«áááºá á¡ááŒá±á¬ááºážá¡áá²á¡á¬ážáá¯á¶ážááẠááœááºááŸááá±áááºá process_tcp_syn()
ááŸáá·áºáááºáááºážáá»ááºá
á¡áá¯ááºááá¯á á áºáá±ážááŒááºážá
áá°ážáá°ážááŒá¬ážááŒá¬ážá á€áá±áá¬ááœáẠá¡áá°ážááŒá¬ážáá¯á¶áž á á¬ááŒá±á¬ááºážáá áºáᯠááá¯á·ááá¯áẠáááºážá¡ááœáẠááŸááºáá»ááºáá áºáá¯ááŒá áºáááºá
/* Required to verify checksum calculation */
const void* data_end = (const void*)ctx->data_end;
áá¯ááºáááááá¬ážááŸááºážááá¯áá±ážáá±á¬á¡áá«á 5.1 kernel ááá¯á¡áá¯á¶ážááŒá¯áá²á·áááºá á¡ááŒá¬ážááœá¬ááŒá¬ážáá»ááºááŸááá±á¬á¡áá¬ááá¯á¡áááºááŒá¯ááẠdata_end
О (const void*)ctx->data_end
. á
á¬áá±ážáá»áááºá 5.3.1 kernel ááœáẠá€ááŒá¿áá¬áááŸááá«á compiler ááẠá¡ááœááºáá
áºáá¯ááẠááœá²ááŒá¬ážáá±á¬ local variable áá
áºáá¯ááᯠáááºáá±á¬ááºáá±ááŒááºážááŒá
áºááá¯ááºáááºá ááá¯ááºáá»áá·áºááá¬áž - ááŒá®ážáá¬ážáá±á¬á¡ááá¯ááºááœááºá áá¯ááºááá¯ááá¯ážááŸááºážá¡á±á¬ááºááŒá¯áá¯ááºááŒááºážááŒáá·áºáá°áá®ááá¯ááºáááºá
Verifier á áá¯ááºáá»ááºááá±á¡ááœáẠáá±á¬ááºááẠáá¯á¶ááŸááºá
á
áºáá±ážááŸá¯áá»á¬ážá á¡áᯠMAX_CSUM_BYTES
á¡á±á¬ááºááœááºáá±á¬áºááŒáá¬ážáá±á¬á
const u32 ip_len = ip->ihl * 4;
if ((void*)ip + ip_len > data_end) {
return XDP_DROP; /* malformed packet */
}
if (ip_len > MAX_CSUM_BYTES) {
return XDP_ABORTED; /* implementation limitation */
}
const u32 tcp_len = tcp->doff * 4;
if ((void*)tcp + tcp_len > (void*)ctx->data_end) {
return XDP_DROP; /* malformed packet */
}
if (tcp_len > MAX_CSUM_BYTES) {
return XDP_ABORTED; /* implementation limitation */
}
á¡áá¯ááºááŒáá·áº
áá»áœááºáá±á¬áºááá¯á· ááŒáá·áºá
áœááºáá«áááºá seqnum
О acknum
ACK ááᯠáááºááŸááºáá« (SYN áááºááŸááºááŒá®ážáá¬áž)
const u32 cookie = 42;
tcp->ack_seq = bpf_htonl(bpf_ntohl(tcp->seq) + 1);
tcp->seq = bpf_htonl(cookie);
tcp->ack = 1;
TCP á¡áá±á«ááºáá»á¬ážá IP ááŸáá·áº MAC ááááºá
á¬áá»á¬ážááᯠáá²ááŸááºáá«á á
á¶á
á¬ááŒáá·áºááá¯ááºááᯠXDP áááá¯ááááºá០ááááŸáááá¯ááºáá±á¬ááŒá±á¬áá·áºá memcpy()
- Clang intrinsik ááᯠáá¯á¶ážááœááºáá¬ážááá·áº áááºáááá¯áá
áºáá¯á
const u16 temp_port = tcp->source;
tcp->source = tcp->dest;
tcp->dest = temp_port;
const u32 temp_ip = ip->saddr;
ip->saddr = ip->daddr;
ip->daddr = temp_ip;
struct ethhdr temp_ether = *ether;
memcpy(ether->h_dest, temp_ether.h_source, ETH_ALEN);
memcpy(ether->h_source, temp_ether.h_dest, ETH_ALEN);
Checksum ááŒááºáááºááœááºáá»ááºááŒááºážá
IPv4 ááŸáá·áº TCP á á áºáá±ážááŸá¯áá»á¬ážááẠáá±á«ááºážá á®ážááŸá 16-bit á áá¬ážáá¯á¶ážáá»á¬ážá¡á¬ážáá¯á¶ážááᯠáááºáá±á«ááºážááẠááá¯á¡ááºááŒá®áž áá±á«ááºážá á®ážáá¡ááœááºá¡á á¬ážááᯠáááºážááá¯á·ááœáẠáá±ážáá¬ážáááºá ááá¯ááá¯áááºááŸá¬ á á¯á ááºážáá»áááºááœáẠáááááá±ážáá«á áááºááááááºáááŒá±á¬ááºážááá»ááºáž á¡áááºááŒá¯áá°ááẠáá¯á¶ááŸááºááŸáá·áºáááºááᯠáá»á±á¬áºááœá¬ážáááºááá¯ááºáá±á¬ááŒá±á¬áá·áº áááºážááŸá¬ ááŒá¿áá¬áá áºáá¯ááŒá áºáááºá ááá¯á·áá±á¬áº áá±á«ááºážá á®ážáá»á¬ážá á¡ááœááºá¡á á¬ážááᯠááá·áºáááºáá¬ážáááº- áá áºáá¯áá»áŸáẠ64 bytes á¡ááááŸááááºá á á±á¬á á±á¬á¡áá¯á¶ážáááºááá¯ááºááá·áº áá¯á¶áá±á¡ááŒáááºá¡áá±á¡ááœááºááŒáá·áº ááœááºážáááºáá áºáá¯ááᯠáááºááŒá¯áá¯ááºááá¯ááºáááºá
ááŸááááºááá¯áᬠáááááŒá¯áááá«áááºá
Checksum ááœááºáá»ááºááŸá¯áá¯ááºáá±á¬ááºáá»ááº
#define MAX_CSUM_WORDS 32
#define MAX_CSUM_BYTES (MAX_CSUM_WORDS * 2)
INTERNAL u32
sum16(const void* data, u32 size, const void* data_end) {
u32 s = 0;
#pragma unroll
for (u32 i = 0; i < MAX_CSUM_WORDS; i++) {
if (2*i >= size) {
return s; /* normal exit */
}
if (data + 2*i + 1 + 1 > data_end) {
return 0; /* should be unreachable */
}
s += ((const u16*)data)[i];
}
return s;
}
ááá¯á·áá±ááá·áº size
áá±á«áºááá¯ááŸá¯áá¯ááºááŒáá·áº á
á
áºáá±ážáá¬ážáá±á¬á ááá¯á·ááŸáᬠverifier ááẠloop áá¡áá¯á¶ážááᯠáááºáá±ááŒááá¯ááºá
á±ááẠáá¯áááááœááºáá±á«ááºá¡ááŒá±á¡áá± ááá¯á¡ááºáá«áááºá
32-bit á áá¬ážáá¯á¶ážáá»á¬ážá¡ááœááºá ááá¯ááá¯ááá¯ážááŸááºážáá±á¬áá¬ážááŸááºážááᯠá¡áá±á¬ááºá¡áááºáá±á¬áºáááº-
INTERNAL u32
sum16_32(u32 v) {
return (v >> 16) + (v & 0xffff);
}
á¡ááŸááºáááẠchecksums áá»á¬ážááᯠááŒááºáááºááœááºáá»ááºááŒá®áž packet ááᯠááŒááºááá¯á·áá±ážáááº-
ip->check = 0;
ip->check = carry(sum16(ip, ip_len, data_end));
u32 tcp_csum = 0;
tcp_csum += sum16_32(ip->saddr);
tcp_csum += sum16_32(ip->daddr);
tcp_csum += 0x0600;
tcp_csum += tcp_len << 8;
tcp->check = 0;
tcp_csum += sum16(tcp, tcp_len, data_end);
tcp->check = carry(tcp_csum);
return XDP_TX;
áá¯ááºáá±á¬ááºáá»áẠcarry()
RFC 32 á¡á 16-bit á
áá¬ážáá¯á¶ážáá»á¬ážá 791-bit áá±á«ááºážáááºááᯠchecksum ááŒá¯áá¯ááºáááºá
TCP áááºááœá²á á áºáá±ážááŒááºážá
filter ááẠááŸááºáááºá
áœá¬áá»áááºáááºááŸá¯áá
áºáá¯ááŸáá·áº áá°áá±á¬ááºáááºá netcat
Network stack ááẠSYN ááááŸááá²á·áá±á¬ááŒá±á¬áá·áº Linux á០RST packet ááŒáá·áº áá¯á¶á·ááŒááºáá²á·ááá·áº áá±á¬ááºáá¯á¶áž ACK ááᯠáá»á±á¬áºááœá¬ážááẠ- áááºážááᯠSYNACK á¡ááŒá
áºááŒá±á¬ááºážáá²ááŒá®áž ááŒááºáááºáá±ážááá¯á·ááŒááºážááŒá
áºááẠ- OS áá¡ááŒááºá¡áá ááá¯ááºáá±á¬ packet áá
áºáá¯áá±á¬ááºááŸááá¬áá«áááºá ááœáá·áºáááºážáá±á¬áá»áááºáááºááŸá¯áá»á¬ážááŸáá·áºáááºááá¯ááºáááºá
$ sudo ip netns exec xdp-test nc -nv 192.0.2.1 6666
192.0.2.1 6666: Connection reset by peer
ááŒáá·áºá
á¯á¶áá±á¬ á¡áá¯á¶ážáá»ááá®áá±ážááŸááºážáá»á¬ážááŒáá·áº á
á
áºáá±ážááŒáá·áºááŸá¯ááẠá¡áá±ážááŒá®ážáá«áááºá tcpdump
á¡áá±á«áº xdp-remote
áá¬ááá¯á·áá²ááá¯áá±á¬á· á¥ááá¬á hping3
áááŸááºáá±á¬ checksum áá»á¬ážááᯠááá¯á¶á·ááŒááºáá«á
SYN ááœááºáá®áž
XDP áá¡ááŒááºááŸá á á áºáá±ážááŸá¯ááá¯ááºááá¯ááºáá¡áá±ážá¡ááœá²ááŒá áºáááºá ááœááºáá»ááºááŸá¯ á¡ááºáááá¯áá®áááºááẠááŸá±ážááá¯ážáááºááŒá®áž áá±ááºáá®áááºážááŒá¬ážáá±á¬ ááá¯ááºááá¯ááºáá°á¡ááœáẠá¡á¬ážáááºážáá»áẠááŒá áºááá¯ááºáááºá á¥ááá¬á¡á¬ážááŒáá·áº Linux kernel ááẠcryptographic SipHash ááá¯á¡áá¯á¶ážááŒá¯áááºá ááá¯á·áá±á¬áº XDP á¡ááœáẠáááºážáá¡áá±á¬ááºá¡áááºáá±á¬áºááŸá¯ááẠá€áá±á¬ááºážáá«ážááááºáááºáááºáá»á±á¬áºááœááºáá±áá«áááºá
ááŒááºá á¡ááŒááºá¡ááŸááºáááºááœááºááŸá¯ááŸáá·áº áááºá ááºáá±á¬ TODO á¡áá áºáá»á¬ážá¡ááœáẠáá±á«áºáá¬áááº-
-
XDP áááá¯ááááºááᯠááááºážáááºážááááá«á
cookie_seed
(áá¬ážááá»áŸáá¯á·ááŸááºá¡á áááºá¡ááá¯ááºáž) ááá¹áá¬áá¯á¶ážááá¯ááºáá¬ááŒá±á¬ááºážáá²ááŸá¯áá áºáá¯ááœááºá áááºááẠáá¯á¶ááŒááºá áááºáá»ááá±á¬ áá®ážá ááºá០á¡áá»áááºá¡áá«á¡ááá¯áẠá¡ááºááááºáá¯ááºááá·áº áááºááá¯ážááŸááá±á¬ kernel á ááá¯ážáá áºáᯠááá¯á¡ááºáá«áááºá -
ACK packet ááŸá SYN ááœááºáá®ážááẠááá¯ááºáá®áá«áá áááºááẠáááºáá±á·áá»áºááᯠáááá·áºáá¯ááºááẠáááá¯á¡ááºáá±á¬áºáááºáž áááºážá០packet áá»á¬ážááᯠáá»á±á¬áºááœá¬ážáááºá¡ááœáẠá¡áááºááŒá¯áá¬ážáá±á¬ client á IP ááᯠââááŸááºáá¬ážáá«á
ááá¬ážáááºáá±á¬ááºáááºá០á¡áááºááŒá¯ááŒááºáž-
$ sudoip netns exec xdp-test nc -nv 192.0.2.1 6666
192.0.2.1 6666: Connection reset by peer
ááŸááºáááºážáá»á¬ážááẠáá»ááºáááºááŸááºá áááºážááŒá±á¬ááºážááᯠááŸááºáááºážáááºáá¬ážááẠ(flags=0x2
SYN ááŒá
áºáá«ááẠflags=0x10
ACK ááŒá
áºáá«áááº):
Ether(proto=0x800)
IP(src=0x20e6e11a dst=0x20e6e11e proto=6)
TCP(sport=50836 dport=6666 flags=0x2)
Ether(proto=0x800)
IP(src=0xfe2cb11a dst=0xfe2cb11e proto=6)
TCP(sport=50836 dport=6666 flags=0x10)
cookie matches for client 20200c0
á á áºáá±ážáá¬ážáá±á¬ IP áá»á¬ážá á¬áááºážáááŸááááœá±á·á SYN áá±ááœáŸááºážááá¯ážááŸá¯ááá¯ááºááá¯ááºá á¡áá¬á¡ááœááºááŸááááºááá¯ááºáá±á¬áºáááºáž á€á¡áááá·áºáá±á¬áºááŸááœááºááŸááá±á¬ ACK áá±ááœáŸááºážááá¯ážááŸá¯á¡áá±á«áº áá¯á¶á·ááŒááºááŸá¯ááŸá¬ á€ááœááºááŒá áºáááº-
sudo ip netns exec xdp-test hping3 --flood -A -s 1111 -p 2222 192.0.2.1
ááŸááºáááºážáá»á¬áž-
Ether(proto=0x800)
IP(src=0x15bd11a dst=0x15bd11e proto=6)
TCP(sport=3236 dport=2222 flags=0x10)
cookie mismatch
áá±á¬ááºáá»ááº
áá áºáá«áá áºáá¶ááœáẠáá±áá°áá»á¡á¬ážááŒáá·áº eBPF ááŸáá·áº á¡áá°ážáááŒáá·áº XDP ááᯠââááœá¶á·ááŒáá¯ážááá¯ážáááºááŸá¯ááááºáá±á¬ááºážááẠá¡ááá·áºááŒáá·áºá á®áá¶ááá·áºááœá²áá°ááááááá¬á¡ááŒá ẠáááºááŒááŒáááºá á¡ááŸááºááŸá¬á XDP ááẠkernel packet áá¯ááºáá±á¬ááºááŒááºážááᯠá¡ááŸá±á¬áá·áºá¡ááŸááºáá±ážááá·áºáááááá¬áá áºáá¯ááŒá áºááŒá®áž DPDK ááŸáá·áº á¡ááŒá¬ážáá±á¬ kernel bypass ááœá±ážáá»ááºááŸá¯áá»á¬ážáá²á·ááá¯á· kernel stack áá¡ááŒá¬ážááœá±ážáá»ááºá áá¬ááá¯ááºáá«á á¡ááŒá¬ážáá áºáááºááœááºá XDP ááẠááá·áºá¡á¬áž á¡ááœá¬ážá¡áá¬áá¯ááºáá±á¬ááºáá¬ááœáẠáá±áá¹ááááºáá¬ážááŒááºážáááŸááá² á¡ááºááááºáá¯ááºááẠááœááºáá°áá±á¬ ááŸá¯ááºááœá±ážáá±á¬áá¯áá¹ááááᯠá¡áá±á¬ááºá¡áááºáá±á¬áºááá¯ááºá á±áá«áááºá verifier ááẠááŒá¿áá¬ááŒá®ážááŒá®ážáá¬ážáá¬ážááááºáá®ážáá¬ážáá±á áá»áœááºá¯ááºááẠuserspace code á á¡á áááºá¡ááá¯ááºážáá»á¬ážá¡ááœáẠáááºážáá²á·ááá¯á· ááŒááºážááá¯áááºááá¯ááºáá«á
áá¯áááá¡ááá¯ááºážááœááºá á¡ááŒá±á¬ááºážá¡áá¬ááẠá áááºáááºá á¬ážá áá¬áá±á¬ááºážáá«áá áá»áœááºá¯ááºááá¯á·ááẠá¡áááºááŒá¯áá¬ážáá±á¬ client áá»á¬ážáááá¬ážááᯠá¡ááŒá®ážáááºááŒá®áž áá»áááºáááºááŸá¯áá»á¬ážááᯠááŒááºáá±á¬ááºáá¬á áá±á¬ááºáá¬áá»á¬ážááᯠá¡áá±á¬ááºá¡áááºáá±á¬áºáᬠfilter ááá¯á á®áá¶ááá·áºááœá²ááẠuserspace utility áá áºáá¯ááᯠáá±ážáá¬ážáá«áááºá
ááá·áºááºáá»á¬áž
GitHub ááœáẠáá¯ááºá¡ááŒáá·áºá¡á á¯á¶ bpftrace Cheat Sheet BPF ááŸáá·áº XDP áááºááœáŸááºážáááºážááœáŸáẠXDP áá»á°ááá¯áá®ááẠPoC- Rust á០eBPF ááá¯á· á á¯á ááºážáá±áááºá
source: www.habr.com