ืื ื• ื›ื•ืชื‘ื™ื ื”ื’ื ื” ืžืคื ื™ ื”ืชืงืคื•ืช DDoS ืขืœ XDP. ื—ืœืง ื’ืจืขื™ื ื™

ื˜ื›ื ื•ืœื•ื’ื™ื™ืช eXpress Data Path (XDP) ืžืืคืฉืจืช ืขื™ื‘ื•ื“ ืฉืจื™ืจื•ืชื™ ืฉืœ ืชืขื‘ื•ืจื” ื‘ืžืžืฉืงื™ ืœื™ื ื•ืงืก ืœืคื ื™ ืฉื”ืžื ื•ืช ื ื›ื ืกื•ืช ืœืžื—ืกื ื™ืช ืจืฉืช ื”ืงืจื ืœ. ื™ื™ืฉื•ื XDP - ื”ื’ื ื” ืžืคื ื™ ื”ืชืงืคื•ืช DDoS (CloudFlare), ืžืกื ื ื™ื ืžื•ืจื›ื‘ื™ื, ืื™ืกื•ืฃ ืกื˜ื˜ื™ืกื˜ื™ืงื•ืช (Netflix). ืชื•ื›ื ื™ื•ืช XDP ืžื‘ื•ืฆืขื•ืช ืขืœ ื™ื“ื™ ื”ืžื›ื•ื ื” ื”ื•ื•ื™ืจื˜ื•ืืœื™ืช eBPF, ื•ืœื›ืŸ ื™ืฉ ื”ื’ื‘ืœื•ืช ื”ืŸ ืขืœ ื”ืงื•ื“ ื•ื”ืŸ ืขืœ ืคื•ื ืงืฆื™ื•ืช ื”ืœื™ื‘ื” ื”ื–ืžื™ื ื•ืช, ื‘ื”ืชืื ืœืกื•ื’ ื”ืžืกื ืŸ.

ื”ืžืืžืจ ื ื•ืขื“ ืœืคืฆื•ืช ืขืœ ื”ื—ืกืจื•ื ื•ืช ืฉืœ ื—ื•ืžืจื™ื ืจื‘ื™ื ื‘-XDP. ืจืืฉื™ืช, ื”ื ืžืกืคืงื™ื ืงื•ื“ ืžื•ื›ืŸ ืฉืขื•ืงืฃ ืžื™ื“ ืืช ื”ืชื›ื•ื ื•ืช ืฉืœ XDP: ืžื•ื›ืŸ ืœืื™ืžื•ืช ืื• ืคืฉื•ื˜ ืžื›ื“ื™ ืœื’ืจื•ื ืœื‘ืขื™ื•ืช. ื›ืืฉืจ ืืชื” ืžื ืกื” ืœื›ืชื•ื‘ ืงื•ื“ ืžืฉืœืš ืžืืคืก ืžืื•ื—ืจ ื™ื•ืชืจ, ืื™ืŸ ื”ื‘ื ื” ืžื” ืœืขืฉื•ืช ืขื ืฉื’ื™ืื•ืช ื˜ื™ืคื•ืกื™ื•ืช. ืฉื ื™ืช, ื–ื” ืœื ืžื›ืกื” ื“ืจื›ื™ื ืœื‘ื“ื™ืงื” ืžืงื•ืžื™ืช ืฉืœ XDP ืœืœื VM ื•ื—ื•ืžืจื”, ืœืžืจื•ืช ื”ืขื•ื‘ื“ื” ืฉื™ืฉ ืœื”ื ืืช ื”ืžืœื›ื•ื“ื•ืช ืฉืœื”ื. ื”ื˜ืงืกื˜ ืžื™ื•ืขื“ ืœืžืชื›ื ืชื™ื ื”ืžื›ื™ืจื™ื ืจืฉืชื•ืช ื•ืœื™ื ื•ืงืก ื”ืžืชืขื ื™ื™ื ื™ื ื‘-XDP ื•ื‘-eBPF.

ื‘ื—ืœืง ื–ื” ื ื‘ื™ืŸ ื‘ืคื™ืจื•ื˜ ื›ื™ืฆื“ ืžื•ืจื›ื‘ ืžืกื ืŸ XDP ื•ื›ื™ืฆื“ ืœื‘ื“ื•ืง ืื•ืชื•, ืœืื—ืจ ืžื›ืŸ ื ื›ืชื•ื‘ ื’ืจืกื” ืคืฉื•ื˜ื” ืฉืœ โ€‹โ€‹ืžื ื’ื ื•ืŸ ื”ืขื•ื’ื™ื•ืช SYN ื”ื™ื“ื•ืข ื‘ืจืžืช ืขื™ื‘ื•ื“ ื”ืžื ื•ืช. ืขื“ ืฉื ื™ืฆื•ืจ "ืจืฉื™ืžื” ืœื‘ื ื”"
ืœืงื•ื—ื•ืช ืžืื•ืžืชื™ื, ืฉืžื•ืจ ืžื•ื ื™ื ื•ื ื”ืœ ืืช ื”ืžืกื ืŸ - ืžืกืคื™ืง ื™ื•ืžื ื™ื.

ื ื›ืชื•ื‘ ื‘-C - ื–ื” ืœื ืื•ืคื ืชื™, ืืœื ืคืจืงื˜ื™. ื›ืœ ื”ืงื•ื“ ื–ืžื™ืŸ ื‘-GitHub ื‘ืงื™ืฉื•ืจ ื‘ืกื•ืฃ ื•ืžื—ื•ืœืง ืœ-commits ืœืคื™ ื”ืฉืœื‘ื™ื ื”ืžืชื•ืืจื™ื ื‘ืžืืžืจ.

ื›ืชื‘ ื•ื™ืชื•ืจ. ื‘ืžื”ืœืš ื”ืžืืžืจ ื™ืคื•ืชื— ืžื™ื ื™ ืคืชืจื•ืŸ ืœื”ืจื—ืงืช ื”ืชืงืคื•ืช DDoS, ื›ื™ ื–ื• ืžืฉื™ืžื” ืจื™ืืœื™ืช ืขื‘ื•ืจ XDP ื•ื”ืื–ื•ืจ ืฉืœื™. ืขื ื–ืืช, ื”ืžื˜ืจื” ื”ืขื™ืงืจื™ืช ื”ื™ื ืœื”ื‘ื™ืŸ ืืช ื”ื˜ื›ื ื•ืœื•ื’ื™ื”, ื–ื” ืœื ืžื“ืจื™ืš ืœื™ืฆื™ืจืช ื”ื’ื ื” ืžื•ื›ื ื”. ืงื•ื“ ื”ื”ื“ืจื›ื” ืื™ื ื• ืžื•ืชืื ื•ืžืฉืžื™ื˜ ื›ืžื” ื ื™ื•ืื ืกื™ื.

ืกืงื™ืจื” ืงืฆืจื” ืฉืœ XDP

ืืฆื™ื™ืŸ ืจืง ืืช ื ืงื•ื“ื•ืช ื”ืžืคืชื— ื›ื“ื™ ืœื ืœืฉื›ืคืœ ืืช ื”ืชื™ืขื•ื“ ื•ื”ืžืืžืจื™ื ื”ืงื™ื™ืžื™ื.

ืื–, ืงื•ื“ ื”ืกื™ื ื•ืŸ ื ื˜ืขืŸ ืœืชื•ืš ื”ืงืจื ืœ. ื”ืžืกื ืŸ ืžื•ืขื‘ืจ ืžื ื•ืช ื ื›ื ืกื•ืช. ื›ืชื•ืฆืื” ืžื›ืš, ืขืœ ื”ืžืกื ืŸ ืœืงื‘ืœ ื”ื—ืœื˜ื”: ืœื”ืขื‘ื™ืจ ืืช ื”ื—ื‘ื™ืœื” ืœืงืจื ืœ (XDP_PASS), ื–ืจื•ืง ื—ื‘ื™ืœื” (XDP_DROP) ืื• ืฉืœื— ืื•ืชื• ื‘ื—ื–ืจื” (XDP_TX). ื”ืžืกื ืŸ ื™ื›ื•ืœ ืœืฉื ื•ืช ืืช ื”ื—ื‘ื™ืœื”, ื–ื” ื ื›ื•ืŸ ื‘ืžื™ื•ื—ื“ ืขื‘ื•ืจ XDP_TX. ืืชื” ื™ื›ื•ืœ ื’ื ืœืงืจื•ืก ืืช ื”ืชื•ื›ื ื™ืช (XDP_ABORTED) ื•ืฉื—ืจืจ ืืช ื”ื—ื‘ื™ืœื”, ืื‘ืœ ื–ื” ื“ื•ืžื” assert(0) - ืขื‘ื•ืจ ืื™ืชื•ืจ ื‘ืื’ื™ื.

ื”ืžื›ื•ื ื” ื”ื•ื•ื™ืจื˜ื•ืืœื™ืช eBPF (Extended Berkley Packet Filter) ื ืขืฉื™ืช ืคืฉื•ื˜ื” ื‘ื›ื•ื•ื ื” ื›ืš ืฉื”ืงืจื ืœ ื™ื•ื›ืœ ืœื‘ื“ื•ืง ืฉื”ืงื•ื“ ืื™ื ื• ืขื•ื‘ืจ ืœื•ืœืื” ื•ืื™ื ื• ืคื•ื’ืข ื‘ื–ื™ื›ืจื•ืŸ ืฉืœ ืื ืฉื™ื ืื—ืจื™ื. ื”ื’ื‘ืœื•ืช ื•ื‘ื“ื™ืงื•ืช ืžืฆื˜ื‘ืจื•ืช:

  • ืœื•ืœืื•ืช (ืงืคื™ืฆื•ืช ืื—ื•ืจื”) ืืกื•ืจื•ืช.
  • ื™ืฉ ืžื—ืกื ื™ืช ืœื ืชื•ื ื™ื, ืื‘ืœ ืื™ืŸ ืคื•ื ืงืฆื™ื•ืช (ื›ืœ ืคื•ื ืงืฆื™ื•ืช C ื—ื™ื™ื‘ื•ืช ืœื”ื™ื•ืช ืžื•ื˜ื‘ืขื•ืช).
  • ื’ื™ืฉื” ืœื–ื™ื›ืจื•ืŸ ืžื—ื•ืฅ ืœืžืื’ืจ ื”ืžื—ืกื ื™ืช ื•ืžืื’ืจ ื”ื—ื‘ื™ืœื•ืช ืืกื•ืจื”.
  • ื’ื•ื“ืœ ื”ืงื•ื“ ืžื•ื’ื‘ืœ, ืื‘ืœ ื‘ืคื•ืขืœ ื–ื” ืœื ืžืื•ื“ ืžืฉืžืขื•ืชื™.
  • ืจืง ืคื•ื ืงืฆื™ื•ืช ืœื™ื‘ื” ืžื™ื•ื—ื“ื•ืช (ืขื•ื–ืจื™ื eBPF) ืžื•ืชืจื•ืช.

ืคื™ืชื•ื— ื•ื”ืชืงื ื” ืฉืœ ืžืกื ืŸ ื ืจืื” ื›ืš:

  1. ืงื•ื“ ืžืงื•ืจ (ืœืžืฉืœ. kernel.c) ืžื”ื“ืจ ืœืื•ื‘ื™ื™ืงื˜ (kernel.o) ืขื‘ื•ืจ ืืจื›ื™ื˜ืงื˜ื•ืจืช ื”ืžื—ืฉื‘ ื”ื•ื•ื™ืจื˜ื•ืืœื™ eBPF. ื”ื—ืœ ืžืื•ืงื˜ื•ื‘ืจ 2019, ืงื•ืžืคื™ืœืฆื™ื” ืœ-eBPF ื ืชืžื›ืช ืขืœ ื™ื“ื™ Clang ื•ืžื•ื‘ื˜ื—ืช ื‘-GCC 10.1.
  2. ืื ื‘ืงื•ื“ ื”ืื•ื‘ื™ื™ืงื˜ ื”ื–ื” ื™ืฉ ืงืจื™ืื•ืช ืœืžื‘ื ื™ ืœื™ื‘ื” (ืœื“ื•ื’ืžื”, ืœื˜ื‘ืœืื•ืช ื•ืœืžื•ื ื™ื), ื‘ืžืงื•ื ื”ืžื–ื”ื™ื ืฉืœื”ื ื™ืฉ ืืคืกื™ื, ื›ืœื•ืžืจ, ืœื ื ื™ืชืŸ ืœื”ืคืขื™ืœ ืงื•ื“ ื›ื–ื”. ืœืคื ื™ ื”ื˜ืขื™ื ื” ืœืชื•ืš ื”ืœื™ื‘ื”, ื™ืฉ ืœื”ื—ืœื™ืฃ ืืช ื”ืืคืกื™ื ื”ืœืœื• ื‘ืžื–ื”ื™ื ืฉืœ ืื•ื‘ื™ื™ืงื˜ื™ื ืกืคืฆื™ืคื™ื™ื ืฉื ื•ืฆืจื• ื‘ืืžืฆืขื•ืช ืงืจื™ืื•ืช ืœื™ื‘ื” (ืงืฉืจ ืืช ื”ืงื•ื“). ืืชื” ื™ื›ื•ืœ ืœืขืฉื•ืช ื–ืืช ืขื ื›ืœื™ ืขื–ืจ ื—ื™ืฆื•ื ื™ื™ื, ืื• ืฉืืชื” ื™ื›ื•ืœ ืœื›ืชื•ื‘ ืชื•ื›ื ื™ืช ืฉืชืงืฉืจ ื•ืชื˜ืขืŸ ืžืกื ืŸ ืกืคืฆื™ืคื™.
  3. ื”ืงืจื ืœ ืžืืžืช ืืช ื”ืชื•ื›ื ื™ืช ื”ื ื˜ืขื ืช. ื”ื•ื ื‘ื•ื“ืง ืืช ื”ื™ืขื“ืจ ืžื—ื–ื•ืจื™ื ื•ืื™ ื™ืฆื™ืื” ืฉืœ ื’ื‘ื•ืœื•ืช ื”ื—ื‘ื™ืœื” ื•ื”ืขืจื™ืžื”. ืื ื”ืžืืžืช ืœื ื™ื›ื•ืœ ืœื”ื•ื›ื™ื— ืฉื”ืงื•ื“ ืชืงื™ืŸ, ื”ืชื•ื›ื ื™ืช ื ื“ื—ื™ืช - ืฆืจื™ืš ืœื”ื™ื•ืช ืžืกื•ื’ืœ ืœืจืฆื•ืช ืื•ืชื•.
  4. ืœืื—ืจ ืื™ืžื•ืช ืžื•ืฆืœื—, ื”ืœื™ื‘ื” ืžืจื›ื™ื‘ื” ืืช ืงื•ื“ ื”ืื•ื‘ื™ื™ืงื˜ ืฉืœ ืืจื›ื™ื˜ืงื˜ื•ืจืช eBPF ืœืงื•ื“ ืžื›ื•ื ื” ืฉืœ ืืจื›ื™ื˜ืงื˜ื•ืจืช ื”ืžืขืจื›ืช (ื‘ื“ื™ื•ืง ื‘ื–ืžืŸ).
  5. ื”ืชื•ื›ื ื™ืช ืžื—ื•ื‘ืจืช ืœืžืžืฉืง ื•ืžืชื—ื™ืœื” ืœืขื‘ื“ ืžื ื•ืช.

ืžื›ื™ื•ื•ืŸ ืฉ-XDP ืคื•ืขืœ ื‘ืงืจื ืœ, ืื™ืชื•ืจ ื‘ืื’ื™ื ืžื‘ื•ืกืก ืขืœ ื™ื•ืžื ื™ ืžืขืงื‘ ื•ืœืžืขืฉื”, ืขืœ ืžื ื•ืช ืฉื”ืชื•ื›ื ื™ืช ืžืกื ื ืช ืื• ืžื™ื™ืฆืจืช. ืขื ื–ืืช, eBPF ืฉื•ืžืจ ืขืœ ื”ืงื•ื“ ืฉื”ื•ืจื“ืช ื‘ื˜ื•ื— ืขื‘ื•ืจ ื”ืžืขืจื›ืช, ื›ืš ืฉืชื•ื›ืœ ืœื”ืชื ืกื•ืช ืขื XDP ื™ืฉื™ืจื•ืช ื‘ืœื™ื ื•ืงืก ื”ืžืงื•ืžื™ ืฉืœืš.

ื”ื›ื ืช ื”ืกื‘ื™ื‘ื”

ื”ืขืฆืจืช

Clang ืœื ื™ื›ื•ืœ ืœื”ื ืคื™ืง ื™ืฉื™ืจื•ืช ืงื•ื“ ืื•ื‘ื™ื™ืงื˜ ืขื‘ื•ืจ ืืจื›ื™ื˜ืงื˜ื•ืจืช eBPF, ื•ืœื›ืŸ ื”ืชื”ืœื™ืš ืžื•ืจื›ื‘ ืžืฉื ื™ ืฉืœื‘ื™ื:

  1. ื”ื™ื“ื•ืจ ืงื•ื“ C ืœืงื•ื“ ื‘ื™ื™ื˜ LLVM (clang -emit-llvm).
  2. ื”ืžืจืช 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

Makefile ืขื‘ื•ืจ Arch Linux (ืงืจื ืœ 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 ืžื›ื™ืœ ืืช ื”ื ืชื™ื‘ ืœื›ื•ืชืจื•ืช ื”ืงืจื ืœ, ARCH - ืืจื›ื™ื˜ืงื˜ื•ืจืช ืžืขืจื›ืช. ื ืชื™ื‘ื™ื ื•ื›ืœื™ื ืขืฉื•ื™ื™ื ืœื”ืฉืชื ื•ืช ืžืขื˜ ื‘ื™ืŸ ื”ื”ืคืฆื•ืช.

ื“ื•ื’ืžื” ืœื”ื‘ื“ืœื™ื ืขื‘ื•ืจ Debian 10 (ืงืจื ืœ 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__ ืคื™ืจื•ืฉื• ืฉื›ื•ืชืจื•ืช UAPI (Userspace API) ืžื•ื’ื“ืจื•ืช ืขื‘ื•ืจ ืงื•ื“ ืœื™ื‘ื”, ืžื›ื™ื•ื•ืŸ ืฉื”ืžืกื ืŸ ืžื‘ื•ืฆืข ื‘ืœื™ื‘ื”.

ื ื™ืชืŸ ืœื”ืฉื‘ื™ืช ืืช ื”ื’ื ืช ืžื—ืกื ื™ืช (-fno-stack-protector) ืžื›ื™ื•ื•ืŸ ืฉืžืืžืช ื”ืงื•ื“ ืฉืœ eBPF ื‘ื•ื“ืง ื‘ื›ืœ ืžืงืจื” ืœื ืžื—ื•ืฅ ืœื’ื‘ื•ืœื•ืช ื”ืžื—ืกื ื™ืช. ืขืœื™ืš ืœื”ืคืขื™ืœ ืžื™ื“ ืื•ืคื˜ื™ืžื™ื–ืฆื™ื•ืช, ืžื›ื™ื•ื•ืŸ ืฉื’ื•ื“ืœ ื”-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. ืื™ืคื” ืืคืฉืจ ืœื‘ื“ื•ืง ืืช ื–ื” ืขื›ืฉื™ื•?

ืขืžื“ืช ืžื‘ื—ืŸ

ื”ืžืขืžื“ ืฆืจื™ืš ืœื›ืœื•ืœ ืฉื ื™ ืžืžืฉืงื™ื: ืขืœื™ื”ื ื™ื”ื™ื” ืžืกื ืŸ ื•ืžืžื ื• ื™ื™ืฉืœื—ื• ืžื ื•ืช. ืืœื” ื—ื™ื™ื‘ื™ื ืœื”ื™ื•ืช ืžื›ืฉื™ืจื™ ืœื™ื ื•ืงืก ืžืœืื™ื ืขื ื›ืชื•ื‘ื•ืช IP ืžืฉืœื”ื ื›ื“ื™ ืœื‘ื“ื•ืง ืื™ืš ื™ื™ืฉื•ืžื™ื ืจื’ื™ืœื™ื ืขื•ื‘ื“ื™ื ืขื ื”ืžืกื ืŸ ืฉืœื ื•.

ืžื›ืฉื™ืจื™ื ื›ืžื• veth (ืืชืจื ื˜ ื•ื™ืจื˜ื•ืืœื™) ืžืชืื™ืžื™ื ืœื ื•: ื”ื ื–ื•ื’ ืžืžืฉืงื™ ืจืฉืช ื•ื™ืจื˜ื•ืืœื™ื™ื "ืžื—ื•ื‘ืจื™ื" ื™ืฉื™ืจื•ืช ื–ื” ืœื–ื”. ืืชื” ื™ื›ื•ืœ ืœื™ืฆื•ืจ ืื•ืชื ื›ืš (ื‘ื—ืœืง ื–ื”, ื›ืœ ื”ืคืงื•ื“ื•ืช 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) ืชื™ืฉืœื— ืชื ื•ืขื” ื ื›ื ืกืช. ืขื ื–ืืช, ื™ืฉ ื‘ืขื™ื”: ื”ืžืžืฉืงื™ื ื ืžืฆืื™ื ืขืœ ืื•ืชื• ืžื›ื•ื ื”, ื•ืœื™ื ื•ืงืก ืœื ื™ืฉืœื— ืชืขื‘ื•ืจื” ืœืื—ื“ ืžื”ื ื“ืจืš ื”ืฉื ื™. ืืชื” ื™ื›ื•ืœ ืœืคืชื•ืจ ืืช ื–ื” ืขื ื›ืœืœื™ื ืžืกื•ื‘ื›ื™ื iptables, ืื‘ืœ ื”ื ื™ืฆื˜ืจื›ื• ืœืฉื ื•ืช ื—ื‘ื™ืœื•ืช, ื•ื–ื” ืœื ื ื•ื— ื‘ืขืช ื ื™ืคื•ื™ ื‘ืื’ื™ื. ืขื“ื™ืฃ ืœื”ืฉืชืžืฉ ื‘ืžืจื—ื‘ื™ ืฉืžื•ืช ื‘ืจืฉืช (ืžืจื—ื‘ื™ ืฉืžื•ืช ื‘ืจืฉืช, ืจืฉืชื•ืช ื ื•ืกืคื•ืช).

ืžืจื—ื‘ ื”ืฉืžื•ืช ืฉืœ ื”ืจืฉืช ืžื›ื™ืœ ืงื‘ื•ืฆื” ืฉืœ ืžืžืฉืงื™ื, ื˜ื‘ืœืื•ืช ื ื™ืชื•ื‘ ื•ื›ืœืœื™ NetFilter ื”ืžื‘ื•ื“ื“ื™ื ืžืื•ื‘ื™ื™ืงื˜ื™ื ื“ื•ืžื™ื ื‘ืจืฉืชื•ืช ืื—ืจื•ืช. ื›ืœ ืชื”ืœื™ืš ืคื•ืขืœ ื‘ืžืจื—ื‘ ืฉืžื•ืช ื›ืœืฉื”ื•, โ€‹โ€‹ื•ืจืง ื”ืื•ื‘ื™ื™ืงื˜ื™ื ืฉืœ ื”-netns ื”ื–ื” ื–ืžื™ื ื™ื ืœื•. ื›ื‘ืจื™ืจืช ืžื—ื“ืœ, ืœืžืขืจื›ืช ื™ืฉ ืžืจื—ื‘ ืฉืžื•ืช ืจืฉืช ืื—ื“ ืœื›ืœ ื”ืื•ื‘ื™ื™ืงื˜ื™ื, ื›ืš ืฉืชื•ื›ืœ ืœืขื‘ื•ื“ ืขืœ ืœื™ื ื•ืงืก ื•ืœื ืœื“ืขืช ืขืœ netns.

ื‘ื•ืื• ื ื™ืฆื•ืจ ืžืจื—ื‘ ืฉืžื•ืช ื—ื“ืฉ 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 ื™ืขื‘ื™ืจ ืื•ืชื” ื“ืจื›ื” xdp-remote, ื›ื™ ื–ื” ื”ืžืžืฉืง ื”ื™ื—ื™ื“ ื‘-192.0.2.0/24 ื”ื–ืžื™ืŸ ืœืชื”ืœื™ืš ื–ื”. ื–ื” ืขื•ื‘ื“ ื’ื ื”ืคื•ืš.

ื‘ืžืขื‘ืจ ื‘ื™ืŸ ืจืฉืชื•ืช, ื”ืžืžืฉืง ื™ื•ืจื“ ื•ืžืื‘ื“ ืืช ื”ื›ืชื•ื‘ืช. ื›ื“ื™ ืœื”ื’ื“ื™ืจ ืžืžืฉืง ื‘-netns, ืืชื” ืฆืจื™ืš ืœื”ืคืขื™ืœ ip ... ื‘ืžืจื—ื‘ ื”ืฉืžื•ืช ืฉืœ ื”ืคืงื•ื“ื” ื”ื–ื• 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

ื›ืคื™ ืฉืืชื” ื™ื›ื•ืœ ืœืจืื•ืช, ื–ื” ืœื ืฉื•ื ื” ืžื”ื’ื“ืจื” xdp-local ื‘ืžืจื—ื‘ ื”ืฉืžื•ืช ื”ืžื•ื’ื“ืจ ื›ื‘ืจื™ืจืช ืžื—ื“ืœ:

    ip address add 192.0.2.1/24 dev xdp-local
    ip link set xdp-local up

ืื ืœืจื•ืฅ tcpdump -tnevi xdp-local, ืืชื” ื™ื›ื•ืœ ืœืจืื•ืช ืฉืžืžื ื” ื ืฉืœื—ื• ืžื ื•ืช xdp-test, ื ืžืกืจื™ื ืœืžืžืฉืง ื–ื”:

ip netns exec xdp-test   ping 192.0.2.1

ื–ื” ื ื•ื— ืœื”ืคืขื™ืœ ืžืขื˜ืคืช xdp-test. ืœืžืื’ืจ ื™ืฉ ืกืงืจื™ืคื˜ ืฉื”ื•ืคืš ืืช ื”ืขื‘ื•ื“ื” ืœืื•ื˜ื•ืžื˜ื™ืช ืขื ื”ืขืžื“ื”, ืœืžืฉืœ, ื ื™ืชืŸ ืœื”ื’ื“ื™ืจ ืืช ื”ืขืžื“ื” ืขื ื”ืคืงื•ื“ื” sudo ./stand up ื•ืœื”ืกื™ืจ ืื•ืชื• sudo ./stand down.

ืžึทืขึฒืงึธื‘

ื”ืžืกื ืŸ ืžื—ื•ื‘ืจ ืœืžื›ืฉื™ืจ ื›ืš:

ip -force link set dev xdp-local xdp object xdp_filter.o verbose

ืžืคืชื— -force ื ื“ืจืฉ ืœืงืฉืจ ืชื•ื›ื ื™ืช ื—ื“ืฉื” ืื ืชื•ื›ื ื™ืช ืื—ืจืช ื›ื‘ืจ ืžืงื•ืฉืจืช. "ืื™ืŸ ื—ื“ืฉื•ืช ื–ื” ื—ื“ืฉื•ืช ื˜ื•ื‘ื•ืช" ื–ื” ืœื ืขืœ ื”ืคืงื•ื“ื” ื”ื–ื•, ื”ืคืœื˜ ืžืžื™ืœื ืขืฆื•ื. ืžืฆื‘ื™ืข verbose ืื•ืคืฆื™ื•ื ืœื™, ืื‘ืœ ื™ื—ื“ ืขื ื–ื” ืžื•ืคื™ืข ื“ื•ื— ืขืœ ืขื‘ื•ื“ืชื• ืฉืœ ืžืืžืช ื”ืงื•ื“ ืขื ืจื™ืฉื•ื ื”ืืกืžื‘ืœืจ:

Verifier analysis:

0: (b7) r0 = 2
1: (95) exit

ื ืชืง ืืช ื”ืชื•ื›ื ื™ืช ืžื”ืžืžืฉืง:

ip link set dev xdp-local xdp off

ื‘ืชืกืจื™ื˜, ืืœื• ื”ืคืงื•ื“ื•ืช sudo ./stand attach ะธ sudo ./stand detach.

ืขืœ ื™ื“ื™ ืงืฉื™ืจืช ื”ืžืกื ืŸ, ืืชื” ื™ื›ื•ืœ ืœื•ื•ื“ื ื–ืืช 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;
   }

ื”ืคืœื˜ ืขื•ื‘ืจ ืœืขืจื•ืฅ ืžืขืงื‘ ืœื™ื‘ื”, ืฉืฆืจื™ืš ืœื”ืคืขื™ืœ ืื•ืชื•:

echo -n 1 | sudo tee /sys/kernel/debug/tracing/options/trace_printk

ื”ืฆื’ ืืช ื–ืจื™ืžืช ื”ื”ื•ื“ืขื•ืช:

cat /sys/kernel/debug/tracing/trace_pipe

ืฉื ื™ ื”ืฆื•ื•ืชื™ื ื”ืืœื” ืžืชืงืฉืจื™ื sudo ./stand log.

ืคื™ื ื’ ืืžื•ืจ ืœื™ื™ืฆืจ ื‘ื• ื”ื•ื“ืขื•ืช ื›ืžื• ื–ื”:

<...>-110930 [004] ..s1 78803.244967: 0: got packet: 00000000ac510377

ืื ืืชื” ืžืกืชื›ืœ ืžืงืจื•ื‘ ืขืœ ื”ืคืœื˜ ืฉืœ ื”ืžืืžืช, ืืชื” ื™ื›ื•ืœ ืœื”ื‘ื—ื™ืŸ ื‘ื—ื™ืฉื•ื‘ื™ื ืžื•ื–ืจื™ื:

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:

$ python -c "import binascii; print(bytes(reversed(binascii.unhexlify('0a7025203a74656b63617020746f67'))))"
b'got packet: %pn'

ืžืกื™ื‘ื” ื–ื•, ืคืœื˜ ื ื™ืคื•ื™ ื‘ืื’ื™ื ืžื ืคื— ืžืื•ื“ ืืช ื”ืงื•ื“ ืฉื ื•ืฆืจ.

ืฉืœื™ื—ืช ืžื ื•ืช XDP

ื‘ื•ื ื ืฉื ื” ืืช ื”ืžืกื ืŸ: ืชืŸ ืœื• ืœืฉืœื•ื— ืืช ื›ืœ ื”ื—ื‘ื™ืœื•ืช ื”ื ื›ื ืกื•ืช ื‘ื—ื–ืจื”. ื–ื” ืœื ื ื›ื•ืŸ ืžื ืงื•ื“ืช ืžื‘ื˜ ืฉืœ ืจืฉืช, ืฉื›ืŸ ื™ื”ื™ื” ืฆื•ืจืš ืœืฉื ื•ืช ืืช ื”ื›ืชื•ื‘ื•ืช ื‘ื›ื•ืชืจื•ืช, ืื‘ืœ ืขื›ืฉื™ื• ื”ืขื‘ื•ื“ื” ื”ืขืงืจื•ื ื™ืช ื—ืฉื•ื‘ื”.

       bpf_printk("got packet: %pn", ctx);
-      return XDP_PASS;
+      return XDP_TX;
   }

ืจื•ืฅ tcpdump ืขืœ xdp-remote. ื–ื” ืฆืจื™ืš ืœื”ืฆื™ื’ ICMP Echo Request ื™ื•ืฆืื•ืช ื•ื ื›ื ืกื•ืช ื–ื”ื•ืช ื•ืœื”ืคืกื™ืง ืœื”ืฆื™ื’ ICMP Echo Reply. ืื‘ืœ ื–ื” ืœื ืžื•ืคื™ืข. ืžืกืชื‘ืจ ืฉืขื•ื‘ื“ XDP_TX ื‘ืชื•ื›ื ื™ืช ืขื‘ื•ืจ xdp-local ื—ื™ื™ื‘ืœื”ืชืืžื” ืฉืœ ืžืžืฉืง xdp-remote ื”ื•ืงืฆืชื” ื’ื ืชื•ื›ื ื™ืช, ื’ื ืื ื”ื™ื™ืชื” ืจื™ืงื”, ื•ื”ื™ื ื”ื•ืขืœืชื”.

ืื™ืš ื™ื“ืขืชื™?

ืžืขืงื‘ ืื—ืจ ื”ื ืชื™ื‘ ืฉืœ ื—ื‘ื™ืœื” ื‘ืงืจื ืœ ืžื ื’ื ื•ืŸ perf events ืžืืคืฉืจ, ืื’ื‘, ืฉื™ืžื•ืฉ ื‘ืื•ืชื” ืžื›ื•ื ื” ื•ื™ืจื˜ื•ืืœื™ืช, ื›ืœื•ืžืจ, eBPF ืžืฉืžืฉ ืœืคื™ืจื•ืง ืขื eBPF.

ืืชื” ื—ื™ื™ื‘ ืœืขืฉื•ืช ื˜ื•ื‘ ืžื”ืจืข, ื›ื™ ืื™ืŸ ืฉื•ื ื“ื‘ืจ ืื—ืจ ืœืขืฉื•ืช ืžืžื ื•.

$ 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])
                                     <...>

ืžื” ื–ื” ืงื•ื“ 6?

$ errno 6
ENXIO 6 No such device or address

ืคื•ื ืงืฆื™ื” veth_xdp_flush_bq() ืžืงื‘ืœ ืงื•ื“ ืฉื’ื™ืื” ืž 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, ืœืื—ืจ ืžื›ืŸ ื”ืชืงืŸ ืžืกื ื ื™ื ื•ื ืกื” ืฉื•ื‘. ื”ื‘ืขื™ื” ื”ื™ื ืฉื”ืคื™ืœื˜ืจ XDP_TX ืžืฉืคื™ืข ื’ื ืขืœ ARP, ื•ืื ื”ืžื—ืกื ื™ืช
ืžืจื—ื‘ื™ ืฉืžื•ืช xdp-test ื”ืฆืœื™ื— "ืœืฉื›ื•ื—" ืืช ื›ืชื•ื‘ืช ื”-MAC 192.0.2.1, ื”ื•ื ืœื ื™ื•ื›ืœ ืœืคืชื•ืจ ืืช ื”-IP ื”ื–ื”.

ื”ืฆื”ืจืช ื”ื‘ืขื™ื”

ื ืขื‘ื•ืจ ืœืžืฉื™ืžื” ื”ืžื•ืฆื”ืจืช: ืœื›ืชื•ื‘ ืžื ื’ื ื•ืŸ SYN cookie ื‘-XDP.

ืขื“ ื›ื”, ืžื‘ื•ืœ ื”-SYN ื ื•ืชืจ ื”ืชืงืคืช DDoS ืคื•ืคื•ืœืจื™ืช, ืฉืžื”ื•ืชื” ื”ื™ื ื›ื“ืœืงืžืŸ. ื›ืืฉืจ ื ื•ืฆืจ ื—ื™ื‘ื•ืจ (ืœื—ื™ืฆืช ื™ื“ TCP), ื”ืฉืจืช ืžืงื‘ืœ SYN, ืžืงืฆื” ืžืฉืื‘ื™ื ืœื—ื™ื‘ื•ืจ ืขืชื™ื“ื™, ืžื’ื™ื‘ ืขื ื—ื‘ื™ืœืช SYNACK ื•ืžื—ื›ื” ืœ-ACK. ื”ืชื•ืงืฃ ืคืฉื•ื˜ ืฉื•ืœื— ืžื ื•ืช SYN ืžื›ืชื•ื‘ื•ืช ืžื–ื•ื™ืคื•ืช ื‘ื›ืžื•ืช ืฉืœ ืืœืคื™ื ื‘ืฉื ื™ื™ื” ืžื›ืœ ืžืืจื— ื‘ืจืฉืช ื‘ื•ื˜ื ื˜ ืจื‘-ืืœืคื™ื. ื”ืฉืจืช ื ืืœืฅ ืœื”ืงืฆื•ืช ืžืฉืื‘ื™ื ืžื™ื“ ืขื ื”ื’ืขืช ื”ื—ื‘ื™ืœื”, ืืš ืžืฉื—ืจืจ ืื•ืชื” ืœืื—ืจ ื–ืžืŸ ืงืฆื•ื‘ ืืจื•ืš, ื›ืชื•ืฆืื” ืžื›ืš, ื”ื–ื™ื›ืจื•ืŸ ืื• ื”ืžื’ื‘ืœื•ืช ืžื•ืฆื•, ื—ื™ื‘ื•ืจื™ื ื—ื“ืฉื™ื ืื™ื ื ืžืชืงื‘ืœื™ื, ื”ืฉื™ืจื•ืช ืื™ื ื• ื–ืžื™ืŸ.

ืื ืืชื” ืœื ืžืงืฆื” ืžืฉืื‘ื™ื ืขืœ ื—ื‘ื™ืœืช SYN, ืืœื ืจืง ืžื’ื™ื‘ ืขื ื—ื‘ื™ืœืช SYNACK, ืื– ืื™ืš ื”ืฉืจืช ื™ื›ื•ืœ ืœื”ื‘ื™ืŸ ืฉื—ื‘ื™ืœืช ACK ืฉื”ื’ื™ืขื” ืžืื•ื—ืจ ื™ื•ืชืจ ืฉื™ื™ื›ืช ืœื—ื‘ื™ืœืช SYN ืฉืœื ื ืฉืžืจื”? ืื—ืจื™ ื”ื›ืœ, ืชื•ืงืฃ ื™ื›ื•ืœ ื’ื ืœื™ืฆื•ืจ ACKs ืžื–ื•ื™ืคื™ื. ื”ืžื”ื•ืช ืฉืœ ืขื•ื’ื™ื™ืช SYN ื”ื™ื ืœื”ืฆืคื™ืŸ ืคื ื™ืžื” seqnum ืคืจืžื˜ืจื™ ื—ื™ื‘ื•ืจ ื›-hash ืฉืœ ื›ืชื•ื‘ื•ืช, ื™ืฆื™ืื•ืช ื•ืžืœื— ืžืฉืชื ื”. ืื ื”-ACK ื”ืฆืœื™ื— ืœื”ื’ื™ืข ืœืคื ื™ ื”ื—ืœืคืช ื”ืžืœื—, ืืชื” ื™ื›ื•ืœ ืœื—ืฉื‘ ืฉื•ื‘ ืืช ื”-hash ื•ืœื”ืฉื•ื•ืช ืขื acknum. ืžึฐื–ื•ึผื™ึธืฃ acknum ื”ืชื•ืงืฃ ืœื ื™ื›ื•ืœ, ืžื›ื™ื•ื•ืŸ ืฉื”ืžืœื— ื›ื•ืœืœ ืืช ื”ืกื•ื“, ื•ืœื ื™ื”ื™ื” ืœื• ื–ืžืŸ ืœืžื™ื™ืŸ ืื•ืชื• ื‘ื’ืœืœ ื”ืขืจื•ืฅ ื”ืžื•ื’ื‘ืœ.

ืงื•ื‘ืฆื™ SYN ืžื™ื•ืฉืžื™ื ื‘ืœื™ื‘ืช ืœื™ื ื•ืงืก ื‘ืžืฉืš ื–ืžืŸ ืจื‘ ื•ื ื™ืชืŸ ืืคื™ืœื• ืœื”ืคืขื™ืœ ืื•ืชื ื‘ืื•ืคืŸ ืื•ื˜ื•ืžื˜ื™ ืื SYN ืžื’ื™ืขื™ื ืžื”ืจ ืžื“ื™ ื•ื‘ื›ืžื•ืช ื’ื“ื•ืœื”.

ืชื•ื›ื ื™ืช ื—ื™ื ื•ื›ื™ืช ื‘ื ื•ืฉื ืœื—ื™ืฆืช ื™ื“ ืฉืœ TCP

TCP ืžืกืคืง ืืช ื”ืขื‘ืจืช ื”ื ืชื•ื ื™ื ื›ื–ืจื ืฉืœ ื‘ืชื™ื, ืœื“ื•ื’ืžื”, ื‘ืงืฉื•ืช HTTP ืžื•ืขื‘ืจื•ืช ื“ืจืš TCP. ื”ื–ืจื ืžื•ืขื‘ืจ ื—ืชื™ื›ื” ืื—ืจ ื—ืชื™ื›ื” ื‘ื—ื‘ื™ืœื•ืช. ืœื›ืœ ืžื ื•ืช ื”-TCP ื™ืฉ ื“ื’ืœื™ื ืœื•ื’ื™ื™ื ื•ืžืกืคืจื™ ืจืฆืฃ ืฉืœ 32 ืกื™ื‘ื™ื•ืช:

  • ืฉื™ืœื•ื‘ ื”ื“ื’ืœื™ื ืžื’ื“ื™ืจ ืืช ืชืคืงื™ื“ื” ืฉืœ ื—ื‘ื™ืœื” ืžืกื•ื™ืžืช. ื“ื’ืœ SYN ืื•ืžืจ ืฉื–ื• ื”ื—ื‘ื™ืœื” ื”ืจืืฉื•ื ื” ืฉืœ ื”ืฉื•ืœื— ื‘ื—ื™ื‘ื•ืจ. ื“ื’ืœ ACK ืื•ืžืจ ืฉื”ืฉื•ืœื— ืงื™ื‘ืœ ืืช ื›ืœ ื ืชื•ื ื™ ื”ื—ื™ื‘ื•ืจ ืขื“ ืœื‘ื™ื™ื˜. acknum. ืœืžื ื•ืช ืขืฉื•ื™ื•ืช ืœื”ื™ื•ืช ืžืกืคืจ ื“ื’ืœื™ื ื•ื”ื™ื ื ืงืจืืช ืขืœ ืฉื ื”ืฉื™ืœื•ื‘ ืฉืœื”ืŸ, ืœืžืฉืœ, ื—ื‘ื™ืœืช SYNACK.

  • ืžืกืคืจ ืจืฆืฃ (seqnum) ืžืฆื™ื™ืŸ ืืช ื”ื”ื™ืกื˜ ื‘ื–ืจื ื”ื ืชื•ื ื™ื ืขื‘ื•ืจ ื”ื‘ืช ื”ืจืืฉื•ืŸ ืฉื ืฉืœื— ื‘ื—ื‘ื™ืœื” ื–ื•. ืœื“ื•ื’ืžื”, ืื ื‘ื—ื‘ื™ืœื” ื”ืจืืฉื•ื ื” ืขื X ื‘ืชื™ื ืฉืœ ื ืชื•ื ื™ื ื”ืžืกืคืจ ื”ื–ื” ื”ื™ื” N, ื‘ื—ื‘ื™ืœื” ื”ื‘ืื” ืขื ื ืชื•ื ื™ื ื—ื“ืฉื™ื ื”ื•ื ื™ื”ื™ื” N+X. ื‘ืชื—ื™ืœืช ื”ื—ื™ื‘ื•ืจ, ื›ืœ ืฆื“ ื‘ื•ื—ืจ ืืช ื”ืžืกืคืจ ื”ื–ื” ื‘ืื•ืคืŸ ืืงืจืื™.

  • ืžืกืคืจ ืื™ืฉื•ืจ (acknum) - ืงื™ื–ื•ื– ื–ื”ื” ืœ-seqnum, ืื‘ืœ ื”ื•ื ืœื ืงื•ื‘ืข ืืช ืžืกืคืจ ื”ื‘ื™ื˜ ื”ืžืฉื•ื“ืจ, ืืœื ืืช ืžืกืคืจ ื”ื‘ื™ืช ื”ืจืืฉื•ืŸ ืžื”ื ืžืขืŸ, ืฉื”ืฉื•ืœื— ืœื ืจืื”.

ื‘ืชื—ื™ืœืช ื”ืงืฉืจ ืขืœ ื”ืฆื“ื“ื™ื ืœื”ืกื›ื™ื seqnum ะธ acknum. ื”ืœืงื•ื— ืฉื•ืœื— ื—ื‘ื™ืœืช SYN ื™ื—ื“ ืขื ื–ื” seqnum = X. ื”ืฉืจืช ืžื’ื™ื‘ ืขื ื—ื‘ื™ืœืช SYNACK, ืฉื ื”ื•ื ื›ื•ืชื‘ ืืช ืฉืœื• seqnum = Y ื•ื—ื•ืฉืฃ acknum = X + 1. ื”ืœืงื•ื— ืžื’ื™ื‘ ืœ-SYNACK ืขื ื—ื‘ื™ืœืช ACK, ืฉื seqnum = X + 1, acknum = Y + 1. ืœืื—ืจ ืžื›ืŸ, ื”ืขื‘ืจืช ื”ื ืชื•ื ื™ื ื‘ืคื•ืขืœ ืžืชื—ื™ืœื”.

ืื ื‘ืŸ ื”ืฉื™ื— ืœื ืžืืฉืจ ืืช ืงื‘ืœืช ื”ื—ื‘ื™ืœื”, TCP ืฉื•ืœื— ืื•ืชื” ืžื—ื“ืฉ ืœืคื™ ืคืกืง ื–ืžืŸ.

ืžื“ื•ืข ืœื ืชืžื™ื“ ื ืขืฉื” ืฉื™ืžื•ืฉ ื‘ืขื•ื’ื™ื•ืช SYN?

ืจืืฉื™ืช, ืื ืื‘ื“ SYNACK ืื• ACK, ืชืฆื˜ืจืš ืœื—ื›ื•ืช ืœืฉืœื™ื—ื” ื—ื•ื–ืจืช - ื™ืฆื™ืจืช ื”ื—ื™ื‘ื•ืจ ืžืื˜ื”. ืฉื ื™ืช, ื‘ื—ื‘ื™ืœืช SYN - ื•ืจืง ื‘ื”! - ืžืฉื•ื“ืจื•ืช ืžืกืคืจ ืืคืฉืจื•ื™ื•ืช ื”ืžืฉืคื™ืขื•ืช ืขืœ ื”ืžืฉืš ืคืขื•ืœืช ื”ื—ื™ื‘ื•ืจ. ืœื ื–ื•ื›ืจ ืžื ื•ืช SYN ื ื›ื ืกื•ืช, ื”ืฉืจืช ืžืชืขืœื ืžื”ืืคืฉืจื•ื™ื•ืช ื”ืœืœื•, ื‘ืžื ื•ืช ื”ื‘ืื•ืช ื”ืœืงื•ื— ื›ื‘ืจ ืœื ื™ืฉืœื— ืื•ืชืŸ. TCP ื™ื›ื•ืœ ืœืขื‘ื•ื“ ื‘ืžืงืจื” ื–ื”, ืื‘ืœ ืœืคื—ื•ืช ื‘ืฉืœื‘ ื”ืจืืฉื•ื ื™, ืื™ื›ื•ืช ื”ื—ื™ื‘ื•ืจ ืชืจื“.

ืžื‘ื—ื™ื ืช ื—ื‘ื™ืœื•ืช, ืชื•ื›ื ื™ืช XDP ืฆืจื™ื›ื” ืœืขืฉื•ืช ืืช ื”ืคืขื•ืœื•ืช ื”ื‘ืื•ืช:

  • ืœื”ื’ื™ื‘ ืœ-SYN ืขื SYNACK ืขื ืงื•ื‘ืฅ Cookie;
  • ืœืขื ื•ืช ACK ืขื RST (ืœืฉื‘ื•ืจ ืืช ื”ื—ื™ื‘ื•ืจ);
  • ื–ืจื•ืง ืžื ื•ืช ืื—ืจื•ืช.

ืคืกืื•ื“ื•ืงื•ื“ ืฉืœ ื”ืืœื’ื•ืจื™ืชื ื™ื—ื“ ืขื ื ื™ืชื•ื— ืžื ื•ืช:

ะ•ัะปะธ ัั‚ะพ ะฝะต Ethernet,
    ะฟั€ะพะฟัƒัั‚ะธั‚ัŒ ะฟะฐะบะตั‚.
ะ•ัะปะธ ัั‚ะพ ะฝะต IPv4,
    ะฟั€ะพะฟัƒัั‚ะธั‚ัŒ ะฟะฐะบะตั‚.
ะ•ัะปะธ ะฐะดั€ะตั ะฒ ั‚ะฐะฑะปะธั†ะต ะฟั€ะพะฒะตั€ะตะฝะฝั‹ั…,               (*)
        ัƒะผะตะฝัŒัˆะธั‚ัŒ ัั‡ะตั‚ั‡ะธะบ ะพัั‚ะฐะฒัˆะธั…ัั ะฟั€ะพะฒะตั€ะพะบ,
        ะฟั€ะพะฟัƒัั‚ะธั‚ัŒ ะฟะฐะบะตั‚.
ะ•ัะปะธ ัั‚ะพ ะฝะต TCP,
    ัะฑั€ะพัะธั‚ัŒ ะฟะฐะบะตั‚.     (**)
ะ•ัะปะธ ัั‚ะพ SYN,
    ะพั‚ะฒะตั‚ะธั‚ัŒ SYN-ACK ั cookie.
ะ•ัะปะธ ัั‚ะพ ACK,
    ะตัะปะธ ะฒ acknum ะปะตะถะธั‚ ะฝะต cookie,
        ัะฑั€ะพัะธั‚ัŒ ะฟะฐะบะตั‚.
    ะ—ะฐะฝะตัั‚ะธ ะฒ ั‚ะฐะฑะปะธั†ัƒ ะฐะดั€ะตั ั N ะพัั‚ะฐะฒัˆะธั…ัั ะฟั€ะพะฒะตั€ะพะบ.    (*)
    ะžั‚ะฒะตั‚ะธั‚ัŒ RST.   (**)
ะ’ ะพัั‚ะฐะปัŒะฝั‹ั… ัะปัƒั‡ะฐัั… ัะฑั€ะพัะธั‚ัŒ ะฟะฐะบะตั‚.

ืื—ื“ (*) ื”ื ืงื•ื“ื•ืช ื‘ื”ืŸ ืืชื” ืฆืจื™ืš ืœื ื”ืœ ืืช ืžืฆื‘ ื”ืžืขืจื›ืช ืžืกื•ืžื ื•ืช - ื‘ืฉืœื‘ ื”ืจืืฉื•ืŸ, ืืชื” ื™ื›ื•ืœ ืœื”ืกืชื“ืจ ื‘ืœืขื“ื™ื”ื ืคืฉื•ื˜ ืขืœ ื™ื“ื™ ื™ื™ืฉื•ื ืœื—ื™ืฆืช ื™ื“ ืฉืœ TCP ืขื ื™ืฆื™ืจืช ืงื•ื‘ืฅ Cookie ืฉืœ SYN ื›ืงื•ื‘ืฅ ื”ืžืฉืš.

ื‘ืžืงื•ื (**), ื‘ืขื•ื“ ืฉืื™ืŸ ืœื ื• ืฉื•ืœื—ืŸ, ื ื“ืœื’ ืขืœ ื”ื—ื‘ื™ืœื”.

ื™ื™ืฉื•ื ืœื—ื™ืฆืช ื™ื“ ืฉืœ TCP

ื ื™ืชื•ื— ื—ื‘ื™ืœื” ื•ืื™ืžื•ืช ืงื•ื“

ืื ื—ื ื• ืฆืจื™ื›ื™ื ืžื‘ื ื™ ื›ื•ืชืจื•ืช ืจืฉืช: Ethernet (uapi/linux/if_ether.h), IPv4 (uapi/linux/ip.h) ื•-TCP (uapi/linux/tcp.h). ื”ืื—ืจื•ืŸ ืœื ื™ื›ื•ืœืชื™ ืœื”ืชื—ื‘ืจ ืขืงื‘ ืฉื’ื™ืื•ืช ื”ืงืฉื•ืจื•ืช ืืœื™ื• atomic64_t, ื”ื™ื™ืชื™ ืฆืจื™ืš ืœื”ืขืชื™ืง ืืช ื”ื”ื’ื“ืจื•ืช ื”ื“ืจื•ืฉื•ืช ืœืงื•ื“.

ื›ืœ ื”ืคื•ื ืงืฆื™ื•ืช ื”ื ื‘ื“ืœื•ืช ื‘-C ืœืงืจื™ืื•ืช ื—ื™ื™ื‘ื•ืช ืœื”ื™ื•ืช ืžื•ื˜ื‘ืขื•ืช ื‘ืืชืจ ื”ืฉื™ื—ื”, ืฉื›ืŸ ื”-eBPF Verifier ื‘ืงืจื ืœ ืื•ืกืจ ืขืœ ืงืคื™ืฆื•ืช ืื—ื•ืจื”, ื›ืœื•ืžืจ ืœืžืขืฉื”, ืœื•ืœืื•ืช ื•ืงืจื™ืื•ืช ืคื•ื ืงืฆื™ื•ืช.

#define INTERNAL static __attribute__((always_inline))

ืžืืงืจื• LOG() ืžืฉื‘ื™ืช ื”ื“ืคืกื” ื‘ื‘ื ื™ื™ืช ืžื”ื“ื•ืจื”.

ื”ืชื•ื›ื ื™ืช ื”ื™ื ืฆื™ื ื•ืจ ืฉืœ ืคื•ื ืงืฆื™ื•ืช. ื›ืœ ืื—ื“ ืžืงื‘ืœ ื—ื‘ื™ืœื” ืฉื‘ื” ืžื•ื“ื’ืฉืช ื›ื•ืชืจืช ืฉืœ ื”ืจืžื” ื”ืžืชืื™ืžื”, ืœืžืฉืœ, process_ether() ืžื—ื›ื” ืœื”ืชืžืœื ether. ื‘ื”ืชื‘ืกืก ืขืœ ืชื•ืฆืื•ืช ื ื™ืชื•ื— ืฉื“ื”, ื”ืคื•ื ืงืฆื™ื” ื™ื›ื•ืœื” ืœื”ืขื‘ื™ืจ ืืช ื”ื—ื‘ื™ืœื” ืœืจืžื” ื’ื‘ื•ื”ื” ื™ื•ืชืจ. ื”ืชื•ืฆืื” ืฉืœ ื”ืคื•ื ืงืฆื™ื” ื”ื™ื ืคืขื•ืœืช XDP. ื‘ืขื•ื“ ืฉืžื˜ืคืœื™ SYN ื•-ACK ื ื•ืชื ื™ื ืœื›ืœ ื”ื—ื‘ื™ืœื•ืช ืœืขื‘ื•ืจ.

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): ื™ืฉื ื ื ืชื™ื‘ื™ ื‘ื™ืฆื•ืข ื›ืืฉืจ ื”ื‘ืช ื”ืฉืœื•ืฉ ืขืฉืจื” ืžืชื—ื™ืœืช ื”ืžืื’ืจ ื ืžืฆื ืžื—ื•ืฅ ืœื—ื‘ื™ืœื”. ืงืฉื” ืœื“ืขืช ืžื”ืจืฉื™ืžื” ืขืœ ืื™ื–ื• ืฉื•ืจื” ืื ื—ื ื• ืžื“ื‘ืจื™ื, ืื‘ืœ ื™ืฉ ืžืกืคืจ ื”ื•ืจืื•ืช (12) ื•ืžืคืจืง ืฉืžืฆื™ื’ ืืช ื”ืฉื•ืจื•ืช ืฉืœ ืงื•ื“ ื”ืžืงื•ืจ:

llvm-objdump -S xdp_filter.o | less

ื‘ืžืงืจื” ื–ื”, ื–ื” ืžืฆื‘ื™ืข ืขืœ ื”ืงื•

LOG("Ether(proto=0x%x)", bpf_ntohs(ether->h_proto));

ืžื” ืฉืžื‘ื”ื™ืจ ืฉื”ื‘ืขื™ื” ื”ื™ื ether. ื–ื” ืชืžื™ื“ ื™ื”ื™ื” ื›ื›ื”.

ื”ืฉื‘ ืœ-SYN

ื”ืžื˜ืจื” ื‘ืฉืœื‘ ื–ื” ื”ื™ื ืœื™ืฆื•ืจ ื—ื‘ื™ืœืช SYNACK ื ื›ื•ื ื” ืขื ืงื•ื‘ืฅ ืงื‘ื•ืข seqnum, ืืฉืจ ื™ื•ื—ืœืฃ ื‘ืขื•ื’ื™ื™ืช SYN ื‘ืขืชื™ื“. ื›ืœ ื”ืฉื™ื ื•ื™ื™ื ืžืชืจื—ืฉื™ื ื‘ process_tcp_syn() ื•ื”ืกื‘ื™ื‘ื”.

ื‘ื•ื“ืงื™ื ืืช ื”ื—ื‘ื™ืœื”

ื‘ืื•ืคืŸ ืžื•ื–ืจ, ื”ื ื” ื”ืฉื•ืจื” ื”ืžื“ื”ื™ืžื” ื‘ื™ื•ืชืจ, ืื• ืœื™ืชืจ ื“ื™ื•ืง, ื”ืขืจื” ืขืœื™ื”:

/* Required to verify checksum calculation */
const void* data_end = (const void*)ctx->data_end;

ื‘ืขืช ื›ืชื™ื‘ืช ื”ื’ืจืกื” ื”ืจืืฉื•ื ื” ืฉืœ ื”ืงื•ื“, ื ืขืฉื” ืฉื™ืžื•ืฉ ื‘ืงืจื ืœ 5.1, ืฉืขื‘ื•ืจ ื”ืžืืžืช ืฉืœื• ื”ื™ื” ื”ื‘ื“ืœ ื‘ื™ืŸ data_end ะธ (const void*)ctx->data_end. ื‘ื–ืžืŸ ื›ืชื™ื‘ืช ืฉื•ืจื•ืช ืืœื”, ืœื’ืจืขื™ืŸ 5.3.1 ืœื ื”ื™ื™ืชื” ื‘ืขื™ื” ื–ื•. ืื•ืœื™ ื”ืžื”ื“ืจ ื ื™ื’ืฉ ืœืžืฉืชื ื” ืžืงื•ืžื™ ื‘ืฆื•ืจื” ืฉื•ื ื” ืžืฉื“ื”. ืžื•ืกืจื™ - ืขืœ ืงื™ื ื•ืŸ ื’ื“ื•ืœ, ืคื™ืฉื•ื˜ ื”ืงื•ื“ ื™ื›ื•ืœ ืœืขื–ื•ืจ.

ื‘ื“ื™ืงื•ืช ืฉื’ืจืชื™ื•ืช ื ื•ืกืคื•ืช ืฉืœ ืื•ืจื›ื™ื ืœืชืคืืจืช ื”ืžืืžืช; O 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);

ื—ื™ืฉื•ื‘ ืžื—ื“ืฉ ืฉืœ ืกื›ื•ื ื‘ื“ื™ืงื”

ืกื™ื›ื•ืžื™ ื‘ื™ืงื•ืจืช IPv4 ื•-TCP ื“ื•ืจืฉื™ื ื”ื•ืกืคืช ื›ืœ ืžื™ืœื•ืช 16 ืกื™ื‘ื™ื•ืช ื‘ื›ื•ืชืจื•ืช, ื•ื’ื•ื“ืœ ื”ื›ื•ืชืจื•ืช ื›ืชื•ื‘ ื‘ื”ืŸ, ื›ืœื•ืžืจ, ื‘ื–ืžืŸ ื”ื”ื™ื“ื•ืจ ืื™ื ื• ื™ื“ื•ืข. ื–ื• ื‘ืขื™ื” ืžื›ื™ื•ื•ืŸ ืฉื”ืžืืžืช ืœื ื™ื“ืœื’ ืขืœ ื”ืœื•ืœืื” ื”ืจื’ื™ืœื” ืขื“ ืœืžืฉืชื ื” ื”ื’ื‘ื•ืœ. ืื‘ืœ ื’ื•ื“ืœ ื”ื›ื•ืชืจื•ืช ืžื•ื’ื‘ืœ: ืขื“ 64 ื‘ืชื™ื ื›ืœ ืื—ื“. ืืชื” ื™ื›ื•ืœ ืœืขืฉื•ืช ืœื•ืœืื” ืขื ืžืกืคืจ ืงื‘ื•ืข ืฉืœ ืื™ื˜ืจืฆื™ื•ืช, ืฉื™ื›ื•ืœ ืœื”ืกืชื™ื™ื ืžื•ืงื“ื.

ืื ื™ ืžืฆื™ื™ืŸ ืฉื™ืฉ RFC 1624 ื›ื™ืฆื“ ืœื—ืฉื‘ ืžื—ื“ืฉ ืืช ืกื›ื•ื ื”ื‘ื“ื™ืงื” ื‘ืื•ืคืŸ ื—ืœืงื™ ืื ืจืง ื”ืžื™ืœื™ื ื”ืงื‘ื•ืขื•ืช ืฉืœ ื”ื—ื‘ื™ืœื•ืช ืžืฉืชื ื•ืช. ืขื ื–ืืช, ื”ืฉื™ื˜ื” ืื™ื ื” ืื•ื ื™ื‘ืจืกืœื™ืช, ื•ื”ื™ื™ืฉื•ื ื™ื”ื™ื” ืงืฉื” ื™ื•ืชืจ ืœืชื—ื–ื•ืงื”.

ืคื•ื ืงืฆื™ื™ืช ื—ื™ืฉื•ื‘ ืกื›ื•ื ื‘ื™ืงื•ืจืช:

#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 ื ื‘ื“ืง ืขืœ ื™ื“ื™ ื”ืงื•ื“ ื”ืžืชืงืฉืจ, ืชื ืื™ ื”ื™ืฆื™ืื” ื”ืฉื ื™ ื ื—ื•ืฅ ื›ื“ื™ ืฉื”ืžืืžืช ื™ื•ื›ืœ ืœื”ื•ื›ื™ื— ืืช ืกื•ืฃ ื”ืœื•ืœืื”.

ืขื‘ื•ืจ ืžื™ืœื™ื ืฉืœ 32 ืกื™ื‘ื™ื•ืช, ืžื™ื•ืฉืžืช ื’ืจืกื” ืคืฉื•ื˜ื” ื™ื•ืชืจ:

INTERNAL u32
sum16_32(u32 v) {
    return (v >> 16) + (v & 0xffff);
}

ืœืžืขืฉื” ื—ื™ืฉื•ื‘ ืžื—ื“ืฉ ืฉืœ ืกื›ื•ืžื™ ื”ื‘ื“ื™ืงื” ื•ืฉืœื™ื—ืช ื”ื—ื‘ื™ืœื” ื—ื–ืจื”:

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() ืขื•ืฉื” ืกื›ื•ื ื‘ื™ืงื•ืจืช ืžืกื›ื•ื ืฉืœ 32 ืกื™ื‘ื™ื•ืช ืฉืœ ืžื™ืœื™ื ืฉืœ 16 ืกื™ื‘ื™ื•ืช, ืœืคื™ RFC 791.

ื‘ื“ื™ืงืช ืœื—ื™ืฆืช ื™ื“ ืฉืœ TCP

ื”ืžืกื ืŸ ื™ื•ืฆืจ ื—ื™ื‘ื•ืจ ื ื›ื•ืŸ ืขื netcat, ื“ื™ืœื•ื’ ืขืœ ื”-ACK ื”ืกื•ืคื™, ืืœื™ื• ื”ื’ื™ื‘ื” ืœื™ื ื•ืงืก ื‘ื—ื‘ื™ืœืช RST, ืžืื—ืจ ืฉืžื—ืกื ื™ืช ื”ืจืฉืช ืœื ืงื™ื‘ืœื” SYN - ื”ื™ื ื”ื•ืžืจื” ืœ-SYNACK ื•ื ืฉืœื—ื” ื—ื–ืจื” - ื•ืžื ืงื•ื“ืช ืžื‘ื˜ ืฉืœ ืžืขืจื›ืช ื”ื”ืคืขืœื”, ื”ื’ื™ืขื” ื—ื‘ื™ืœื” ืฉืœื ื”ื™ื™ืชื” ืงืฉื•ืจ ืœื—ื™ื‘ื•ืจื™ื ืคืชื•ื—ื™ื.

$ 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 ืื™ื ื• ืžื’ื™ื‘ ืœืกื›ื•ืžื™ื ืฉื’ื•ื™ื™ื.

ืžื ืงื•ื“ืช ื”ืžื‘ื˜ ืฉืœ XDP, ื”ืฆ'ืง ืขืฆืžื• ื”ื•ื ื˜ืจื™ื•ื•ื™ืืœื™. ืืœื’ื•ืจื™ืชื ื”ื—ื™ืฉื•ื‘ ื”ื•ื ืคืจื™ืžื™ื˜ื™ื‘ื™ ื•ื›ื ืจืื” ืคื’ื™ืข ืœืชื•ืงืฃ ืžืชื•ื—ื›ื. ืœื™ื‘ืช ืœื™ื ื•ืงืก, ืœืžืฉืœ, ืžืฉืชืžืฉืช ื‘- SipHash ื”ื”ืฆืคื ื”, ืื‘ืœ ื”ื™ื™ืฉื•ื ืฉืœื” ืขื‘ื•ืจ XDP ื”ื•ื ื‘ื‘ื™ืจื•ืจ ืžืขื‘ืจ ืœืชื—ื•ื ืฉืœ ืžืืžืจ ื–ื”.

ื”ื•ืคื™ืข ืขื‘ื•ืจ ืžื˜ืœื•ืช ื—ื“ืฉื•ืช ื”ืงืฉื•ืจื•ืช ืœืื™ื ื˜ืจืืงืฆื™ื” ื—ื™ืฆื•ื ื™ืช:

  • ืชื•ื›ื ื™ืช XDP ืœื ื™ื›ื•ืœื” ืœืื—ืกืŸ cookie_seed (ื”ื—ืœืง ื”ืกื•ื“ื™ ืฉืœ ื”ืžืœื—) ื‘ืžืฉืชื ื” ื’ืœื•ื‘ืœื™, ืฆืจื™ืš ื—ื ื•ืช ื’ืจืขื™ื ื™ื ืฉืขืจื›ื” ื™ืชืขื“ื›ืŸ ืžืขืช ืœืขืช ืžืžื—ื•ืœืœ ืืžื™ืŸ.

  • ืื ืงื•ื‘ืฅ ื”-SYN ื‘ื—ื‘ื™ืœืช ื”-ACK ืชื•ืื, ืื™ืŸ ืฆื•ืจืš ืœื”ื“ืคื™ืก ื”ื•ื“ืขื”, ืืœื ืœื–ื›ื•ืจ ืืช ื”-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 ื”ื•ื ื›ืœื™ ืœื”ืชืขืจื‘ื•ืช ื‘ืขื™ื‘ื•ื“ ืžื ื•ืช ืœื™ื‘ื”, ื•ืœื ื—ืœื•ืคื” ืœืขืจื™ืžืช ื”ืœื™ื‘ื”, ื›ืžื• DPDK ื•ืืคืฉืจื•ื™ื•ืช ืžืขืงืฃ ืงืจื ืœ ืื—ืจื•ืช. ืžืฆื“ ืฉื ื™, XDP ืžืืคืฉืจ ืœืš ืœื™ื™ืฉื ืœื•ื’ื™ืงื” ืžื•ืจื›ื‘ืช ืœืžื“ื™, ืืฉืจ, ื™ืชืจื” ืžื›ืš, ืงืœ ืœืขื“ื›ืŸ ืœืœื ื”ืคืกืงื” ื‘ืขื™ื‘ื•ื“ ื”ืชืขื‘ื•ืจื”. ื”ืžืืžืช ืœื ื™ื•ืฆืจ ื‘ืขื™ื•ืช ื’ื“ื•ืœื•ืช, ืื™ืฉื™ืช ืœื ื”ื™ื™ืชื™ ืžืกืจื‘ ื›ืืœื” ืขื‘ื•ืจ ื—ืœืงื™ื ืžืงื•ื“ ื”-userspace.

ื‘ื—ืœืง ื”ืฉื ื™, ืื ื”ื ื•ืฉื ืžืขื ื™ื™ืŸ, ื ืฉืœื™ื ืืช ื˜ื‘ืœืช ื”ืœืงื•ื—ื•ืช ื”ืžืื•ืžืชื™ื ื•ื ื ืชืง ื—ื™ื‘ื•ืจื™ื, ื ื™ื™ืฉื ืžื•ื ื™ื ื•ื ื›ืชื•ื‘ ื›ืœื™ ืขื–ืจ ืœืžืจื—ื‘ ืžืฉืชืžืฉ ืœื ื™ื”ื•ืœ ื”ืžืกื ืŸ.

ืงื™ืฉื•ืจื™ื:

ืžืงื•ืจ: www.habr.com

ื”ื•ืกืคืช ืชื’ื•ื‘ื”