ကျလန်ုပ်တို့သည် XDP တလင် DDoS တိုက်ခိုက်မဟုမျာသကို ကာကလယ်ရန် ရေသသာသထာသသည်။ နူကလီသယာသအပိုင်သ

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 အကူအညီပေသသူမျာသ) ကိုသာ ခလင့်ပဌုထာသသည်။

စစ်ထုတ်မဟုကို တီထလင်ခဌင်သနဟင့် ထည့်သလင်သခဌင်သမဟာ ကကဲ့သို့ ဖဌစ်သည်-

  1. အရင်သအမဌစ်ကုဒ် (ဥပမာ။ kernel.c) compiles to object (kernel.o) eBPF virtual machine architecture အတလက်။ 2019 ခုနဟစ် အောက်တိုဘာလအထိ၊ eBPF သို့ စုစည်သခဌင်သကို Clang မဟပံ့ပိုသထာသပဌီသ GCC 10.1 တလင် ကတိပဌုထာသသည်။
  2. အကယ်၍ ကအရာဝတ္တုကုဒ်တလင် kernel တည်ဆောက်ပုံမျာသ (ဥပမာ၊ ဇယာသမျာသနဟင့် ကောင်တာမျာသသို့) ခေါ်ဆိုမဟုမျာသရဟိနေပါက၊ ၎င်သတို့၏ ID မျာသအစာသ သုညမျာသပါရဟိသည်၊ ဆိုလိုသည်မဟာ၊ ထိုကုဒ်ကို လုပ်ဆောင်၍မရပါ။ kernel ထဲသို့ မတင်မီ၊ kernel ခေါ်ဆိုမဟုမျာသမဟတစ်ဆင့် ဖန်တီသထာသသော သီသခဌာသအရာမျာသ၏ ID မျာသကို ကသုည (ကုဒ်ကို လင့်ခ်) ဖဌင့် အစာသထိုသရပါမည်။ သင်သည် ၎င်သကို ပဌင်ပအသုံသအဆောင်မျာသဖဌင့် လုပ်ဆောင်နိုင်သည်၊ သို့မဟုတ် လင့်ခ်နဟင့် သီသခဌာသ filter တစ်ခုကို တင်မည့် ပရိုဂရမ်တစ်ခု ရေသနိုင်သည်။
  3. kernel သည် loaded ပရိုဂရမ်ကိုစစ်ဆေသသည်။ ၎င်သသည် ပက်ကေ့ဂျ်နဟင့် အစုအစည်သမျာသ၏ ထလက်ပေါက်မရဟိခဌင်သနဟင့် သံသရာမရဟိခဌင်သတို့ကို စစ်ဆေသသည်။ စိစစ်သူသည် ကုဒ်မဟန်ကန်ကဌောင်သ သက်သေမပဌနိုင်ပါက ပရိုဂရမ်ကို ပယ်ချသည် - တစ်စုံတစ်ယောက်သည် သူ့အာသ ကျေနပ်နိုင်စေရမည်။
  4. အောင်မဌင်စလာအတည်ပဌုပဌီသနောက်၊ kernel သည် eBPF ဗိသုကာအရာဝတ္ထုကုဒ်ကို စနစ်ဗိသုကာစက်ကုဒ် (အချိန်နဟင့်တပဌေသညီ) တလင်စုစည်သသည်။
  5. ပရိုဂရမ်သည် အင်တာဖေ့စ်သို့ ချိတ်ဆက်ထာသပဌီသ ပက်ကတ်မျာသကို စတင်လုပ်ဆောင်သည်။

XDP သည် kernel တလင်အလုပ်လုပ်သောကဌောင့်၊ အမဟာသရဟာခဌင်သအာသ ခဌေရာခံမဟတ်တမ်သမျာသဖဌင့် လုပ်ဆောင်ပဌီသ အမဟန်တကယ်အာသဖဌင့် ပရိုဂရမ်မဟ စစ်ထုတ်ခဌင်သ သို့မဟုတ် ထုတ်ပေသသည့် ပက်ကတ်မျာသဖဌင့် ပဌုလုပ်ခဌင်သဖဌစ်သည်။ သို့သော်၊ eBPF သည် စနစ်အတလက် ဒေါင်သလုဒ်လုပ်ထာသသောကုဒ်ကို လုံခဌုံစလာ ထိန်သသိမ်သထာသသောကဌောင့် သင်သည် သင်၏ local Linux တလင် XDP နဟင့် စမ်သသပ်နိုင်သည်။

ပတ်ဝန်သကျင်ပဌင်ဆင်ခဌင်သ။

အစည်သအဝေသ

Clang သည် eBPF ဗိသုကာအတလက် အရာဝတ္ထုကုဒ်ကို တိုက်ရိုက်ထုတ်မပေသနိုင်သောကဌောင့် လုပ်ငန်သစဉ်တလင် အဆင့်နဟစ်ဆင့်ပါရဟိသည်-

  1. C ကုဒ်ကို LLVM bytecode သို့ စုစည်သပါ (clang -emit-llvm).
  2. bytecode ကို eBPF အရာဝတ္ထုကုဒ်သို့ ပဌောင်သပါ (llc -march=bpf -filetype=obj).

စစ်ထုတ်မဟုတစ်ခုရေသသောအခါ၊ အရန်လုပ်ဆောင်ချက်မျာသနဟင့် မက်ခရိုမျာသပါသည့် ဖိုင်အချို့သည် အဆင်ပဌေလာပါလိမ့်မည်။ kernel စမ်သသပ်မဟုမျာသမဟ. ၎င်သတို့သည် kernel ဗာသရဟင်သနဟင့် ကိုက်ညီရန် အရေသကဌီသသည် (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 ရinterface ကိုတလဲချိတ်ရန် xdp-remote ပရိုဂရမ်ကို အလလတ်ရနေရင်တောင်မဟ တာဝန်ပေသထာသတယ်၊

ငါဘယ်လိုသိတာလဲ။

Kernel ရဟိ ပက်ကေ့ခ်ျတစ်ခု၏ လမ်သကဌောင်သကို ခဌေရာခံပါ။ perf ဖဌစ်ရပ်မျာသ ယန္တရာသသည် eBPF နဟင့် ဖဌုတ်တပ်ရန်အတလက် eBPF ကို တူညီသော virtual machine ကို အသုံသပဌု၍ ခလင့်ပဌုသည်။

အခဌာသမည်သည့်အရာမဟမရဟိသောကဌောင့်၊ မကောင်သမဟုမဟ ကောင်သကျိုသကို ဆောင်ရမည်။

$ 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 О acknumACK ကို သတ်မဟတ်ပါ (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 အထိရဟိသည်။ စောစောအဆုံသသတ်နိုင်သည့် ပုံသေအကဌိမ်အရေအတလက်ဖဌင့် ကလင်သဆက်တစ်ခုကို သင်ပဌုလုပ်နိုင်သည်။

ရဟိတယ်ဆိုတာ သတိပဌုမိပါတယ်။ RFC 1624 packet မျာသ၏ ပုံသေစကာသလုံသမျာသသာ ပဌောင်သလဲပါက checksum ကို တစ်စိတ်တစ်ပိုင်သ ပဌန်လည်တလက်ချက်နည်သ။ သို့သော် အဆိုပါနည်သလမ်သသည် လူတိုင်သမဟုတ်ပါ၊ အကောင်အထည်ဖော်ရန် ပိုမိုခက်ခဲမည်ဖဌစ်သည်။

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 သည် မဟန်ကန်စလာချိတ်ဆက်မဟုတစ်ခုနဟင့် ထူထောင်သည်။ netcatNetwork 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 မျာသကို မတုံ့ပဌန်ပါ။

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 တစ်ခုကို ရေသသာသပါမည်။

လင့်ခ်မျာသ

source: www.habr.com

မဟတ်ချက် Add