โปรแกรมที่เชื่อมต่อกับ XDP hook ของเคอร์เนล Linux ผ่าน (e) BPF เพื่อการประมวลผลแพ็คเก็ตที่รวดเร็ว และทำการส่งต่อเลเยอร์พื้นฐาน 3/4 โปรแกรมนี้ทำการแมปพอร์ตต้นทางคล้ายกับ IPTables และ NFTables สำหรับการจัดการการเชื่อมต่อ การเชื่อมต่อที่มีอยู่จะถูกจัดลำดับความสำคัญตามแพ็คเก็ตของการเชื่อมต่อต่อนาโนวินาที ซึ่งหมายความว่าเมื่อพอร์ตหมดลง การเชื่อมต่อที่มีแพ็กเก็ตน้อยที่สุดต่อนาโนวินาทีจะถูกแทนที่ ฉันเชื่อว่านี่เป็นวิธีที่ดีที่สุดเนื่องจากการเชื่อมต่อกับแพ็กเก็ตที่สูงกว่าต่อนาโนวินาทีจะมีความไวมากกว่า
นอกจากนี้ หากการกำหนดค่าเครือข่ายของโฮสต์หรือการ์ดอินเทอร์เฟซเครือข่าย (NIC) ไม่รองรับ XDP DRV hook (AKA เนทีฟ; เกิดขึ้นก่อนการสร้าง SKB) โปรแกรมจะพยายามแนบเข้ากับ XDP SKB hook (AKA ทั่วไป; เกิดขึ้นหลังจาก SKB การสร้างซึ่งเป็นที่ที่ IPTables และ NFTables ถูกประมวลผลผ่านโมดูลเคอร์เนล netfilter
) คุณสามารถใช้การแทนที่ผ่านบรรทัดคำสั่งเพื่อบังคับ SKB หรือโหมดออฟโหลด
ด้วยเหตุนี้ สาเหตุของการกำหนดค่าเครือข่ายของโฮสต์ที่ไม่รองรับ DRV hook ของ XDP อาจเป็นดังต่อไปนี้
ฉันหวังว่าโครงการนี้จะช่วยให้วิศวกรเครือข่าย/โปรแกรมเมอร์ที่สนใจใช้ XDP หรือใครก็ตามที่สนใจเข้าสู่สาขาเหล่านั้น! เราเตอร์/การส่งต่อแพ็กเก็ตที่มีประสิทธิภาพสูง และการบรรเทา/ป้องกัน (D)DoS เป็นส่วนสำคัญของความปลอดภัยทางไซเบอร์ และการทำความเข้าใจแนวคิดของระบบเครือข่ายและการไหลของแพ็กเก็ตในระดับกลางต่ำจะช่วยผู้ที่กำลังใฝ่หาอาชีพในสาขานี้อย่างแน่นอน
คำเตือน - ยังมีอีกหลายสิ่งที่ต้องทำกับโปรเจ็กต์นี้ และ ณ ตอนนี้ รองรับเฉพาะ IPv4 เท่านั้น การสนับสนุน IPv6 จะถูกเพิ่มก่อนที่จะเปิดตัวอย่างเป็นทางการ ณ ขณะนี้ โปรแกรมอาจมีจุดบกพร่องและฟีเจอร์การส่งต่อยังไม่พร้อมใช้งาน
พอร์ตต้นทางสูงสุดเริ่มต้นที่สามารถใช้ได้ต่อที่อยู่การเชื่อมโยงคือ 21 และตั้งค่าไว้ที่นี่ (คุณสามารถปรับเปลี่ยนสิ่งเหล่านี้ได้หากต้องการ) เราใช้ช่วงพอร์ต 500 - 520 เป็นค่าเริ่มต้น แต่สามารถกำหนดค่าได้
ตอนแรกฉันพยายามใช้พอร์ตส่วนใหญ่ที่มีอยู่ (1 - 65534) อย่างไรก็ตาม เนื่องจากข้อจำกัดในการตรวจสอบ BPF ฉันจึงต้องเพิ่มค่าคงที่สองสามค่าภายในเคอร์เนล Linux และคอมไพล์เคอร์เนลใหม่ ฉันทำแพตช์สำหรับสิ่งเหล่านี้และมีเอกสารทุกอย่างไว้ที่นี่ ฉันสามารถรันโปรแกรมด้วยพอร์ตสูงสุด 65534 ต่อที่อยู่การเชื่อมโยงโดยไม่มีปัญหาใดๆ กับเคอร์เนลแบบกำหนดเองที่ฉันสร้างขึ้นโดยใช้แพตช์ที่ฉันทำ แม้ว่าโปรดจำไว้ว่า ยิ่งมีพอร์ตต้นทางมากเท่าใด โปรแกรม XDP จะต้องดำเนินการมากขึ้นเมื่อตรวจสอบพอร์ตที่มีอยู่
หากคุณวางแผนที่จะใช้สิ่งนี้เพื่อการใช้งานจริง ฉันขอแนะนำอย่างยิ่งให้รวบรวมเคอร์เนลของคุณเองด้วยค่าคงที่ที่ยกมาด้านบน พอร์ตต้นทางสูงสุด 21 พอร์ตต่อที่อยู่การเชื่อมโยงนั้นไม่มากนัก แต่น่าเสียดายที่ข้อจำกัดตัวตรวจสอบ BPF เริ่มต้นไม่อนุญาตให้เราดำเนินการต่อไปได้ในขณะนี้
รหัสหลักที่ทำให้เกิดข้อจำกัดเหล่านี้อยู่ที่นี่และเกิดขึ้นเมื่อเราพยายามค้นหาพอร์ตต้นทางที่ดีที่สุดที่จะใช้สำหรับการเชื่อมต่อใหม่ ไม่มีวิธีอื่นใดในการตรวจสอบพอร์ตต้นทางที่ดีที่สุดที่มีอยู่พร้อมจำนวนความยืดหยุ่นที่เรามีต่อความเข้าใจของฉัน เนื่องจากเราต้องวนซ้ำพอร์ตต้นทางทั้งหมดและตรวจสอบแพ็กเก็ตต่อค่านาโนวินาที (การค้นหาแผนที่ BPF ด้วยคีย์)
คุณจะต้อง make
, clang
, libelf
และ llvm
เนื่องจากเราใช้แพ็คเกจเหล่านี้เพื่อสร้างโปรเจ็กต์ นอกจากนี้ คุณจะต้องมี libconfig
( libconfig-dev
เป็นแพ็คเกจบนระบบ Ubuntu/Debian) เพื่อแยกวิเคราะห์ไฟล์ปรับแต่ง
สำหรับ Ubuntu/Debian สิ่งต่อไปนี้ควรใช้งานได้
apt install build-essential make clang libelf-dev llvm libconfig-dev
ฉันคิดว่าชื่อแพ็คเกจจะคล้ายกันใน Linux distros อื่น ๆ
ในการใช้ xdpfwd-add
และ xdpfwd-del
คุณต้องเมาต์ระบบไฟล์ BPF เนื่องจากโปรแกรม XDP จะปักหมุดแมป BPF ไปที่ /sys/fs/bpf/xdpfwd
มีโอกาสสูงที่จะดำเนินการนี้ให้คุณแล้วผ่าน iproute2
หรือสิ่งที่คล้ายกัน แต่ถ้าไม่เป็นเช่นนั้น คุณสามารถใช้คำสั่งต่อไปนี้
mount -t bpf bpf /sys/fs/bpf/
การใช้บรรทัดคำสั่งพื้นฐานมีดังต่อไปนี้
-o --offload => Attempt to load XDP program with HW/offload mode. If fails, will try DRV and SKB mode in that order.
-s --skb => Force program to load in SKB/generic mode.
-t --time => The amount of time in seconds to run the program for. Unset or 0 = infinite.
-c --config => Location to XDP Forward config (default is /etc/xdpfwd/xdpfwd.conf).
-l --list => List all forwarding rules.
-h --help => Print out command line usage.
การถ่ายโอนโปรแกรม XDP/BPF ของคุณไปยัง NIC ของระบบช่วยให้สามารถประมวลผลแพ็กเก็ตได้เร็วที่สุดที่คุณสามารถทำได้เนื่องจากการประมวลผล NIC/ส่งต่อแพ็กเก็ตด้วยฮาร์ดแวร์ อย่างไรก็ตาม มีผู้ผลิต NIC ไม่ กี่รายที่สนับสนุนคุณลักษณะนี้ และ คุณถูกจำกัดไว้เพียงหน่วยความจำ/การประมวลผลของ NIC (เช่น ขนาดแมป BPF ของคุณจะถูกจำกัดอย่างมาก) นอกจากนี้ โดยปกติจะมีข้อจำกัดตัวตรวจสอบ BPF ที่เข้มงวดกว่าสำหรับโปรแกรม BPF ออฟโหลด แต่คุณอาจลองติดต่อผู้ผลิตของ NIC เพื่อดูว่าพวกเขาจะให้ไดรเวอร์ NIC เวอร์ชันพิเศษแก่คุณหรือไม่ ซึ่งทำให้เกิดข้อจำกัดเหล่านี้ (นี่คือสิ่งที่ฉันทำกับผู้ผลิตรายหนึ่ง) ฉันใช้)
ณ เวลานี้ ฉันยังไม่ทราบผู้ผลิต NIC รายใดที่จะสามารถถ่ายโอนเครื่องมือนี้ไปยัง NIC ได้อย่างสมบูรณ์ เนื่องจากความซับซ้อนของ BPF และข้อกำหนดในการวนซ้ำ พูดตามตรง ในยุคเครือข่ายปัจจุบัน ฉันเชื่อว่าเป็นการดีที่สุดที่จะปล่อยให้โปรแกรมที่ออฟโหลดไว้เป็นการค้นหาแผนที่ BPF และการตรวจสอบแพ็กเก็ตขั้นต่ำ ตัวอย่างเช่น การค้นหาแผนที่ตารางเส้นทาง BPF เลเยอร์ 2 อย่างง่าย จากนั้น TX แพ็กเก็ตจะกลับออกจาก NIC อย่างไรก็ตาม XDP ยังใหม่อยู่มาก และฉันคิดว่าเราจะได้เห็นข้อจำกัดเหล่านี้คลายหรือยกเลิกในปีต่อๆ ไป นี่คือเหตุผลที่ฉันเพิ่มการรองรับโหมดออฟโหลดลงในโปรแกรมนี้
ไฟล์ปฏิบัติการ xdpfwd-add
ซึ่งเพิ่มใน $PATH
ผ่าน /usr/bin
เมื่อติดตั้งยอมรับอาร์กิวเมนต์ต่อไปนี้
-b --baddr => The address to bind/look for.
-B --bport => The port to bind/look for.
-d --daddr => The destination address.
-D --dport => The destination port.
-p --protocol => The protocol (either "tcp", "udp", "icmp", or unset for all).
-a --save => Save rule to config file.
สิ่งนี้จะเพิ่มกฎการส่งต่อในขณะที่โปรแกรม XDP กำลังทำงาน
ไฟล์ปฏิบัติการ xdpfwd-del
ซึ่งเพิ่มเข้าไปใน $PATH
ผ่าน /usr/bin
เมื่อติดตั้ง ยอมรับอาร์กิวเมนต์ต่อไปนี้
-b --baddr => The address to bind/look for.
-B --bport => The port to bind/look for.
-p --protocol => The protocol (either "tcp", "udp", "icmp", or unset for all).
-a --save => Remove rule from config file.
การดำเนินการนี้จะลบกฎการส่งต่อในขณะที่โปรแกรม XDP กำลังทำงานอยู่
ไฟล์กำหนดค่าเริ่มต้นอยู่ที่ /etc/xdpfwd/xdpfwd.conf
และใช้ไวยากรณ์ libconfig
นี่คือตัวอย่างการกำหนดค่าโดยใช้ฟีเจอร์ปัจจุบันทั้งหมด
interface = "ens18"; // The interface the XDP program attaches to.
// Forwarding rules array.
forwarding = (
{
bind = "10.50.0.3", // The bind address which incoming packets must match.
bindport = 80, // The bind port which incoming packets must match.
protocol = "tcp", // The protocol (as of right now "udp", "tcp", and "icmp" are supported). Right now, you must specify a protocol. However, in the future I will be implementing functionality so you don't have to and it'll do full layer-3 forwarding.
dest = "10.50.0.4", // The address we're forwarding to.
destport = 8080 // The port we're forwarding to (if not set, will use the bind port).
},
...
);
สมมติว่าคุณได้ดาวน์โหลดแพ็คเกจที่จำเป็นทั้งหมดแล้ว การสร้างโปรเจ็กต์นี้ควรจะตรงไปตรงมา คุณสามารถใช้คำสั่งเชลล์และ Bash ต่อไปนี้ได้!
# Clone respository and its sub-modules such as LibBPF.
git clone --recursive https://github.com/gamemann/XDP-Forwarding
# Change directory.
cd XDP-Forwarding
# Make project using all cores.
make -j $( nproc )
# Install binaries to PATH as root so you may use 'xdpfwd', 'xdpfwd-add', 'xdpfwd-del'.
sudo make install