اسان XDP تي DDoS حملن جي خلاف تحفظ لکندا آهيون. ائٽمي حصو

ايڪسپريس ڊيٽا پاٿ (XDP) ٽيڪنالاجي لينڪس انٽرفيس تي بي ترتيب ٽريفڪ پروسيسنگ ڪرڻ جي اجازت ڏئي ٿي ان کان اڳ جو پيڪٽس ڪرنل نيٽ ورڪ اسٽيڪ ۾ داخل ٿين. XDP جي درخواست - DDoS حملن جي خلاف تحفظ (CloudFlare)، پيچيده فلٽر، شماريات گڏ ڪرڻ (Netflix). XDP پروگرامن کي eBPF ورچوئل مشين ذريعي عمل ڪيو ويندو آهي، تنهن ڪري انهن ٻنهي تي پابنديون هونديون آهن انهن جي ڪوڊ ۽ دستياب ڪنيل ڪمن تي فلٽر جي قسم جي لحاظ سان.

مضمون جو مقصد XDP تي ڪيترن ئي مواد جي گهٽتائي کي ڀرڻ جو مقصد آهي. پهرين، اهي تيار ڪيل ڪوڊ مهيا ڪن ٿا جيڪي فوري طور تي XDP جي خاصيتن کي نظرانداز ڪن ٿا: اهو تصديق لاء تيار آهي يا مسئلا پيدا ڪرڻ لاء تمام آسان آهي. جڏهن توهان وري شروع کان پنهنجو ڪوڊ لکڻ جي ڪوشش ڪندا، توهان کي خبر ناهي ته عام غلطين سان ڇا ڪجي. ٻيو، مقامي طور تي وي ايم ۽ هارڊويئر کان سواءِ XDP کي جانچڻ جا طريقا ڍڪيل نه آهن، ان حقيقت جي باوجود ته انهن جا پنهنجا نقصان آهن. متن جو مقصد نيٽ ورڪ ۽ لينڪس سان واقف پروگرامرز لاءِ آهي جيڪي XDP ۽ eBPF ۾ دلچسپي رکن ٿا.

هن حصي ۾، اسان تفصيل سان سمجھندا سين ته XDP فلٽر ڪيئن گڏ ڪيو ويندو آهي ۽ ان کي ڪيئن جانچيو ويندو، پوء اسان پيڪٽ پروسيسنگ سطح تي مشهور SYN ڪوڪيز ميڪانيزم جو هڪ سادي نسخو لکنداسين. في الحال، اسان هڪ "سفيد فهرست" نه ٺاهينداسين.
تصديق ٿيل ڪلائنٽ، ڳڻپيوڪر رکو ۽ فلٽر کي منظم ڪريو - ڪافي لاگ.

اسان سي ۾ لکنداسين - اهو فيشن ناهي، پر اهو عملي آهي. سڀ ڪوڊ GitHub تي دستياب آهي لنڪ ذريعي آخر ۾ ۽ ورهايل آهي ڪمن ۾ ورهايل مرحلن مطابق آرٽيڪل ۾ بيان ڪيل.

رد ڪرڻ هن آرٽيڪل جي دوران، DDoS حملن کي روڪڻ لاء هڪ مني حل تيار ڪيو ويندو، ڇاڪاڻ ته هي XDP ۽ منهنجي فيلڊ لاء هڪ حقيقي ڪم آهي. جڏهن ته، بنيادي مقصد ٽيڪنالاجي کي سمجهڻ آهي؛ هي تيار ٿيل تحفظ پيدا ڪرڻ لاء هڪ گائيڊ ناهي. سبق جو ڪوڊ بهتر نه ڪيو ويو آهي ۽ ڪجهه nuances کي ختم ڪري ٿو.

XDP مختصر جائزو

مان صرف اهم نقطا بيان ڪندس ته جيئن دستاويزن ۽ موجوده مضمونن کي نقل نه ڪيو وڃي.

تنهن ڪري، فلٽر ڪوڊ ڪرنل ۾ لوڊ ڪيو ويو آهي. ايندڙ پيڪيٽ فلٽر ڏانهن گذري ويا آهن. نتيجي طور، فلٽر کي فيصلو ڪرڻ گهرجي: پيڪٽ کي ڪني ۾ داخل ڪريو (XDP_PASS)، ڊراپ پيڪٽ (XDP_DROPيا ان کي واپس موڪليو (XDP_TX). فلٽر پيڪيج کي تبديل ڪري سگهي ٿو، اهو خاص طور تي صحيح آهي XDP_TX. توھان پڻ پروگرام کي ختم ڪري سگھو ٿا (XDP_ABORTED) ۽ پيڪيج کي ري سيٽ ڪريو، پر اهو ساڳيو آهي assert(0) - ڊيبگنگ لاءِ.

eBPF (وڌايل Berkley Packet Filter) ورچوئل مشين کي عمدي طور تي سادو بڻايو ويو آھي ته جيئن ڪرنل چيڪ ڪري سگھي ته ڪوڊ لوپ ۾ نه ٿو وڃي ۽ ٻين ماڻھن جي ياداشت کي نقصان نه ٿو ڏئي. مجموعي پابنديون ۽ چڪاس:

  • لوپ (پوئتي) منع ٿيل آهن.
  • ڊيٽا لاء هڪ اسٽيڪ آهي، پر ڪو به ڪم نه آهي (سڀني سي ڪمن کي اندر اندر هجڻ گهرجي).
  • اسٽيڪ ۽ پيڪٽ بفر کان ٻاهر ياداشت جي رسائي منع ٿيل آهي.
  • ڪوڊ سائيز محدود آهي، پر عملي طور تي اهو تمام اهم ناهي.
  • صرف خاص ڪرنل افعال (eBPF مددگار) کي ڪال ڪرڻ جي اجازت آھي.

فلٽر کي ڊزائين ڪرڻ ۽ انسٽال ڪرڻ هن طرح نظر اچي ٿو:

  1. ماخذ ڪوڊ (مثال طور kernel.c) اعتراض ۾ مرتب ڪيو ويو آهي (kernel.o) eBPF ورچوئل مشين آرڪيٽيڪچر تحت. آڪٽوبر 2019 جي طور تي، اي بي پي ايف جي تاليف کي ڪلانگ جي مدد سان ۽ GCC 10.1 ۾ واعدو ڪيو ويو آهي.
  2. جيڪڏهن هي اعتراض ڪوڊ ڪالن تي مشتمل آهي ڪنييل ڍانچي (مثال طور، ٽيبل ۽ ڪائونٽر)، انهن جي آئي ڊيز کي صفر سان تبديل ڪيو ويو آهي، جنهن جو مطلب آهي ته اهڙي ڪوڊ تي عمل نه ٿو ڪري سگهجي. ڪرنل ۾ لوڊ ڪرڻ کان پهريان، توهان کي انهن صفرن کي تبديل ڪرڻ جي ضرورت آهي مخصوص شين جي ID سان جيڪي ڪنيل ڪالن ذريعي ٺاهيا ويا آهن (ڪوڊ کي ڳنڍيو). توهان اهو ڪري سگهو ٿا ٻاهرين افاديت سان، يا توهان هڪ پروگرام لکي سگهو ٿا جيڪو هڪ مخصوص فلٽر کي ڳنڍي ۽ لوڊ ڪندو.
  3. ڪرنل لوڊ ٿيل پروگرام جي تصديق ڪري ٿو. سائيڪل جي غير موجودگي ۽ پيڪٽ ۽ اسٽيڪ جي حدن جي غير لنگر جي چڪاس ڪئي وئي آهي. جيڪڏهن تصديق ڪندڙ اهو ثابت نٿو ڪري سگهي ته ڪوڊ صحيح آهي، پروگرام رد ڪيو ويو آهي - توهان کي هن کي خوش ڪرڻ جي قابل هوندو.
  4. ڪامياب تصديق کان پوء، ڪنييل اي بي پي ايف آرڪيٽيڪچر اعتراض ڪوڊ کي سسٽم آرڪيٽيڪچر مشين ڪوڊ (صرف وقت ۾) ۾ ترتيب ڏئي ٿو.
  5. پروگرام انٽرفيس سان ڳنڍي ٿو ۽ پروسيسنگ پيڪٽس شروع ڪري ٿو.

جيئن ته XDP ڪرنل ۾ هلندو آهي، ڊيبگنگ ٽريس لاگ استعمال ڪندي ڪيو ويندو آهي ۽ حقيقت ۾، پيڪيٽ جيڪي پروگرام فلٽر يا ٺاهي ٿو. بهرحال، eBPF يقيني بڻائي ٿو ته لوڊ ٿيل ڪوڊ سسٽم لاءِ محفوظ آهي، تنهنڪري توهان XDP سان سڌو تجربو ڪري سگهو ٿا پنهنجي مقامي لينڪس تي.

ماحول جي تياري

اسيمبلي

ڪلنگ سڌو سنئون اي بي پي ايف فن تعمير لاء اعتراض ڪوڊ پيدا نٿو ڪري سگهي، تنهنڪري اهو عمل ٻن مرحلن تي مشتمل آهي:

  1. LLVM bytecode ۾ سي ڪوڊ مرتب ڪريو (clang -emit-llvm).
  2. بائيٽ ڪوڊ کي اي بي پي ايف اعتراض ڪوڊ ۾ تبديل ڪريو (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

آرڪ لينڪس لاءِ ميڪ فائل (ڪرنل 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 headers جي رستي تي مشتمل آهي، ARCH - سسٽم فن تعمير. رستا ۽ اوزار ورهائڻ جي وچ ۾ ٿورو مختلف ٿي سگهن ٿا.

ڊيبين 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 بائيٽ ڪوڊ جو سائز محدود آهي.

اچو ته هڪ فلٽر سان شروع ڪريون جيڪو سڀني پيڪن کي پاس ڪري ٿو ۽ ڪجھ به نه ٿو ڪري:

#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 سان انهي کي جانچڻ لاءِ ته ڪيئن باقاعده ايپليڪيشنون اسان جي فلٽر سان ڪم ڪن ٿيون.

ويٿ (مجازي ايٿرنيٽ) قسم جا ڊوائيس اسان لاءِ موزون آهن: اهي ورچوئل نيٽ ورڪ انٽرفيس جو هڪ جوڙو آهن ”ڳنڍيل“ سڌي طرح هڪ ٻئي سان. توھان انھن کي ھن طرح ٺاھي سگھو ٿا (ھن سيڪشن ۾ سڀ حڪم 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، پر انهن کي پيڪيجز کي تبديل ڪرڻو پوندو، جيڪو ڊيبگنگ لاءِ تڪليف ڏيندڙ آهي. اهو بهتر آهي ته نيٽ ورڪ جي نالي جي جاءِ استعمال ڪجي (هتان کان پوءِ netns).

نيٽ ورڪ جي نالي واري جاءِ ۾ انٽرفيس جو هڪ سيٽ، روٽنگ ٽيبل، ۽ 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 جي وچ ۾ منتقل ٿئي ٿي، انٽرفيس هيٺ ٿي وڃي ٿو ۽ ان جو پتو وڃائي ٿو. 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
<...>

حقيقت اها آهي ته اي بي پي ايف پروگرامن وٽ ڊيٽا سيڪشن نه آهي، تنهنڪري فارميٽ اسٽرنگ کي انڪوڊ ڪرڻ جو واحد طريقو آهي 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 ايڪو درخواست ڏيکارڻ گهرجي ۽ ICMP ايڪو جواب ڏيکارڻ بند ڪرڻ گهرجي. پر اهو ظاهر نٿو ڪري. اهو ظاهر ٿئي ٿو ته ڪم لاء XDP_TX تي پروگرام ۾ xdp-local ضروري آهيجوڙو انٽرفيس ڏانهن xdp-remote هڪ پروگرام پڻ مقرر ڪيو ويو، جيتوڻيڪ اهو خالي هو، ۽ هو اٿيو ويو.

مون کي اها خبر ڪيئن پئي؟

ڪرنل ۾ پيڪيج جي رستي کي ڇڪيو perf واقعن جو ميڪانيزم اجازت ڏئي ٿو، رستي جي ذريعي، ساڳئي ورچوئل مشين کي استعمال ڪندي، اهو آهي، 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

جيڪڏهن صرف ARPs بدران ڏيکاريا ويا آهن، توهان کي فلٽر کي هٽائڻ جي ضرورت آهي (اهو ڪري ٿو sudo ./stand detach)، وڃڻ ڏيو ping، پوءِ فلٽر سيٽ ڪريو ۽ ٻيهر ڪوشش ڪريو. مسئلو اهو آهي ته فلٽر XDP_TX ARP ۽ اسٽيڪ ٻنهي لاءِ صحيح
نالي جي جڳھ xdp-test MAC ايڊريس 192.0.2.1 کي ”وساريو“ ڪرڻ ۾ ڪامياب ٿيو، اهو هن IP کي حل ڪرڻ جي قابل نه هوندو.

مسئلو جي ترتيب

اچو ته بيان ڪيل ڪم ڏانهن وڃو: XDP تي SYN ڪوڪيز ميڪانيزم لکڻ لاءِ.

SYN سيلاب هڪ مشهور DDoS حملو رهي ٿو، جنهن جو خلاصو هن ريت آهي. جڏهن هڪ ڪنيڪشن قائم ٿئي ٿو (TCP هينڊ شيڪ)، سرور هڪ SYN وصول ڪري ٿو، مستقبل جي ڪنيڪشن لاءِ وسيلا مختص ڪري ٿو، SYNACK پيڪٽ سان جواب ڏئي ٿو ۽ ACK جو انتظار ڪري ٿو. حملو ڪندڙ صرف SYN پيڪيٽ موڪلي ٿو جعلي پتي مان هزارين في سيڪنڊ ۾ هر ميزبان کان هڪ هزار-مضبوط botnet ۾. سرور کي پئڪيٽ جي اچڻ تي فوري طور تي وسيلن کي مختص ڪرڻ تي مجبور ڪيو ويندو آهي، پر انهن کي وڏي وقت کان پوء جاري ڪري ٿو؛ نتيجي طور، ياداشت يا حدون ختم ٿي وينديون آهن، نوان ڪنيڪشن قبول نه ڪيا ويا آهن، ۽ خدمت دستياب ناهي.

جيڪڏهن توهان وسيلا مختص نٿا ڪريو SYN پيڪٽ جي بنياد تي، پر صرف هڪ SYNACK پيڪٽ سان جواب ڏيو، پوء ڪيئن سرور سمجهي سگهندو ته ACK پيڪٽ جيڪو بعد ۾ آيو اهو هڪ SYN پيڪٽ ڏانهن اشارو ڪري ٿو جيڪو محفوظ نه ڪيو ويو آهي؟ آخرڪار، هڪ حملو ڪندڙ به جعلي ACKs ٺاهي سگھي ٿو. SYN ڪوڪي جو نقطو ان کي انڪوڊ ڪرڻ آهي seqnum ڪنيڪشن پيٽرولر پتي، بندرگاهن ۽ لوڻ کي تبديل ڪرڻ جي هيش وانگر. جيڪڏهن ACK لوڻ تبديل ٿيڻ کان اڳ پهچي ويو، ته توهان ٻيهر هش کي ڳڻپ ڪري سگهو ٿا ۽ ان سان مقابلو ڪري سگهو ٿا. acknum. فورج acknum حملو ڪندڙ نه ٿو ڪري سگهي، ڇاڪاڻ ته لوڻ ۾ هڪ راز شامل آهي، ۽ محدود چينل جي ڪري ان کي ترتيب ڏيڻ جي قابل نه هوندو.

SYN ڪوڪي ڊگھي عرصي کان لينڪس ڪرنل ۾ لاڳو ڪئي وئي آھي ۽ پاڻمرادو فعال ٿي سگھي ٿي جيڪڏھن SYNs تمام جلدي ۽ وڏي تعداد ۾ اچي وڃن.

TCP هٿ ملائڻ تي تعليمي پروگرام

TCP ڊيٽا جي منتقلي کي بائيٽ جي هڪ وهڪرو طور مهيا ڪري ٿو، مثال طور، HTTP درخواستون TCP تي منتقل ڪيون وينديون آهن. وهڪرو پيڪرن ۾ ٽڪرن ۾ منتقل ڪيو ويندو آهي. سڀ TCP پيڪٽس ۾ منطقي جھنڊا ۽ 32-bit ترتيب نمبر آھن:

  • جھنڊن جو ميلاپ ھڪ خاص پيڪيج جي ڪردار کي طئي ڪري ٿو. SYN پرچم جو مطلب آهي ته هي ڪنيڪشن ۾ موڪليندڙ جو پهريون پيڪٽ آهي. ACK پرچم جو مطلب آهي ته موڪليندڙ کي بائيٽ تائين سڀني ڪنيڪشن ڊيٽا ملي آهي acknum. ھڪڙي پيڪٽ ۾ ڪيترائي جھنڊا آھن ۽ انھن جي ميلاپ سان نالو رکيو ويو آھي، مثال طور، ھڪڙو SYNACK پيڪٽ.

  • تسلسل نمبر (sequnum) ڊيٽا اسٽريم ۾ آفسيٽ کي بيان ڪري ٿو پهرين بائيٽ لاءِ جيڪا هن پيڪٽ ۾ منتقل ڪئي وئي آهي. مثال طور، جيڪڏهن پهرين پيڪٽ ۾ ايڪس بائيٽ جي ڊيٽا سان اهو نمبر N هو، ايندڙ پيڪٽ ۾ نئين ڊيٽا سان اهو N + X هوندو. ڪنيڪشن جي شروعات ۾، هر پارٽي هن نمبر کي بي ترتيب سان چونڊيندو آهي.

  • اقرار نمبر (ايڪنم) ساڳيو آفسٽ آهي سيقنم، پر اهو طئي نٿو ڪري ته بائيٽ جو تعداد منتقل ٿي رهيو آهي، پر وصول ڪندڙ کان پهرين بائيٽ جو نمبر، جيڪو موڪليندڙ نه ڏٺو آهي.

ڪنيڪشن جي شروعات ۾، پارٽين کي متفق ٿيڻ گهرجي 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 پروگرام کي هيٺين ڪرڻ گهرجي:

  • ڪوڪيز سان SYNACK سان SYN کي جواب ڏيو؛
  • ACK کي RST سان جواب ڏيو (منقطع)؛
  • باقي پيڪيجز کي رد ڪريو.

الگورتھم جو Pseudocode پيڪيج پارس ڪرڻ سان گڏ:

Если это не Ethernet,
    пропустить пакет.
Если это не IPv4,
    пропустить пакет.
Если адрес в таблице проверенных,               (*)
        уменьшить счетчик оставшихся проверок,
        пропустить пакет.
Если это не TCP,
    сбросить пакет.     (**)
Если это SYN,
    ответить SYN-ACK с cookie.
Если это ACK,
    если в acknum лежит не cookie,
        сбросить пакет.
    Занести в таблицу адрес с N оставшихся проверок.    (*)
    Ответить RST.   (**)
В остальных случаях сбросить пакет.

هڪ (*) پوائنٽس جتي توهان کي سسٽم جي حالت کي منظم ڪرڻ جي ضرورت آهي، نشان لڳل آهن - پهرين مرحلي ۾ توهان انهن کان سواء ڪري سگهو ٿا صرف هڪ TCP هينڊ شيڪ لاڳو ڪرڻ سان هڪ SYN ڪوڪي جي نسل سان هڪ سيقنم.

انهيءَ جاءِ تي (**)، جڏهن ته اسان وٽ ٽيبل نه آهي، اسان پيڪٽ کي ڇڏي ڏينداسين.

TCP هٿ ملائڻ تي عمل ڪرڻ

پيڪيج کي پارس ڪرڻ ۽ ڪوڊ جي تصديق ڪرڻ

اسان کي ضرورت پوندي نيٽ ورڪ هيڊر ڍانچو: Ethernet (uapi/linux/if_ether.h)، IPv4 (uapi/linux/ip.h) ۽ TCP (uapi/linux/tcp.h). مون سان لاڳاپيل غلطين جي ڪري بعد ۾ ڪڏهن به ڳنڍڻ جي قابل نه هئي atomic64_t، مون کي ضروري وصفن کي ڪوڊ ۾ نقل ڪرڻو پيو.

سڀئي فنڪشن جيڪي C ۾ پڙهڻ جي قابليت لاءِ مختص ڪيا ويا آهن انهن کي ڪال جي نقطي تي اندر اندر هجڻ گهرجي، ڇاڪاڻ ته ڪرنل ۾ eBPF تصديق ڪندڙ پٺتي پيل جمپس کي منع ڪري ٿو، حقيقت ۾، لوپس ۽ فنڪشن ڪال.

#define INTERNAL static __attribute__((always_inline))

ميڪرو LOG() رليز بلڊ ۾ ڇپائي کي بند ڪري ٿو.

پروگرام ڪمن جو هڪ conveyor آهي. هر هڪ هڪ پيڪٽ وصول ڪري ٿو جنهن ۾ مناسب سطح جو هيڊر نمايان ٿيل آهي، مثال طور، 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 اهو مسئلو نه هو. ٿي سگهي ٿو ته مرتب ڪندڙ هڪ مقامي متغير تائين رسائي حاصل ڪري مختلف طور تي فيلڊ کان. ڪهاڻي جي اخلاقيات: وڏي nesting حالتن سان، ڪوڊ کي آسان ڪرڻ ۾ مدد ڪري سگهي ٿي.

اڳيون آهن معمول جي ڊگھائي چڪاس لاءِ تصديق ڪندڙ جي شان؛ او 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() - هڪ ميڪرو جيڪو لڪائيندو آهي ڪلانگ جي اندروني شين کي.

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-bit لفظن جو اضافو ڪرڻ جي ضرورت آهي، ۽ هيڊرن جي سائيز انهن ۾ لکيل آهي، يعني مرتب وقت تي نامعلوم. اهو هڪ مسئلو آهي ڇو ته تصديق ڪندڙ عام لوپ ذريعي متغير حد تائين لوپ نه ڪندو. پر هيڊرن جي سائيز محدود آهي: هر هڪ تائين 64 بائيٽ تائين. توهان هڪ لوپ ٺاهي سگهو ٿا هڪ مقرر ٿيل تعداد سان ٻيهر، جيڪو جلدي ختم ٿي سگهي ٿو.

مون کي ياد آهي ته اتي آهي آر ايف سي سي ايم ايس جزوي طور تي چيڪسم کي ٻيهر ڳڻپ ڪرڻ جي باري ۾ جيڪڏهن صرف پيڪيجز جا مقرر ٿيل لفظ تبديل ڪيا وڃن. بهرحال، طريقو آفاقي نه آهي، ۽ عمل درآمد برقرار رکڻ وڌيڪ ڏکيو هوندو.

چيڪسم حساب جي فنڪشن:

#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-bit لفظن لاءِ، ھڪڙو آسان ورزن لاڳو ڪيو ويو آھي:

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() RFC 32 جي مطابق، 16-bit لفظن جي 791-bit مجموعن مان چيڪسم ٺاهي ٿو.

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 نقطي نظر کان، تصديق پاڻ کي معمولي آهي. ڳڻپيوڪر الگورٿم ابتدائي آهي ۽ ممڪن آهي ته هڪ نفيس حملي آور لاءِ خطرناڪ آهي. لينڪس ڪنيل، مثال طور، استعمال ڪري ٿو cryptographic SipHash، پر XDP لاء ان جو عمل واضح طور تي هن مضمون جي دائري کان ٻاهر آهي.

خارجي رابطي سان لاڳاپيل نئين TODOs لاءِ ظاهر ٿيو:

  • 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

جڏهن ته تصديق ٿيل IPs جي ڪا به فهرست نه آهي، اتي 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

ٿڪل

ڪڏهن ڪڏهن عام طور تي اي بي پي ايف ۽ خاص طور تي ايڪس ڊي پي هڪ ترقي واري پليٽ فارم جي ڀيٽ ۾ ترقي يافته منتظم اوزار جي طور تي پيش ڪيا ويا آهن. درحقيقت، XDP هڪ اوزار آهي مداخلت ڪرڻ لاءِ پيڪيٽس جي پروسيسنگ ۾ ڪرنل طرفان، ۽ نه ڪي ڪينل اسٽيڪ جو متبادل، جهڙوڪ DPDK ۽ ٻيا ڪنيل بائي پاس آپشنز. ٻئي طرف، XDP توهان کي ڪافي پيچيده منطق کي لاڳو ڪرڻ جي اجازت ڏئي ٿو، جيڪو، وڌيڪ، ٽرئفڪ جي پروسيسنگ ۾ مداخلت کان سواء تازه ڪاري ڪرڻ آسان آهي. تصديق ڪندڙ وڏو مسئلا پيدا نه ڪندو آهي؛ ذاتي طور تي، مان هن کي استعمال ڪندڙ اسپيس ڪوڊ جي حصن لاء انڪار نه ڪندس.

ٻئي حصي ۾، جيڪڏهن موضوع دلچسپ آهي، اسان تصديق ٿيل ڪلائنٽ ۽ ڊسڪنيڪشن جي جدول کي مڪمل ڪنداسين، ڳڻپيوڪر لاڳو ڪنداسين ۽ فلٽر کي منظم ڪرڻ لاء يوزر اسپيس يوٽيلٽي لکندا.

حوالا:

جو ذريعو: www.habr.com

تبصرو شامل ڪريو