คุณเพิ่มกฎสำหรับทราฟฟิก VPN ในเชน FORWARD รันคำขอจากเครื่อง Linux เครื่องเดียวกัน แล้วตัวนับก็ยังเป็นศูนย์ กฎนั้นน่าจะถูกต้อง แพ็กเก็ตไม่เคยไปตามเส้นทางนั้น เพราะคำขอที่เกิดขึ้นบนเครื่องเองจะไม่ถูกส่งต่อโดยเชนนั้น การไล่ชีวิตของแพ็กเก็ตตั้งแต่ซ็อกเก็ตจนถึงสายไฟอธิบายว่าทำไมจึงเป็นเช่นนี้ และกฎควรอยู่ที่ใดแทน

หาให้ได้ว่าแพ็กเก็ตถือกำเนิดที่ไหน

ลำดับ hook ของ Netfilter แยกสามกรณี และมีเพียงกรณีเดียวที่เกี่ยวกับ FORWARD:

OriginPathHook that sees it
Local processOUTPUT then POSTROUTINGOUTPUT, POSTROUTING
Addressed to a local servicePREROUTING then INPUTPREROUTING, INPUT
Received for another hostPREROUTING, FORWARD, POSTROUTINGFORWARD

แอปพลิเคชันโลคอลเริ่มในเส้นทาง OUTPUT เพราะเคอร์เนลระบุแล้วว่าแพ็กเก็ตเกิดขึ้นที่นี่และไม่เคยเป็นผู้สมัครให้ส่งต่อ การสร้างทันเนลไม่ได้เปลี่ยนการจำแนกนั้น ทันเนลเป็นอุปกรณ์ที่แพ็กเก็ตออกไปได้ ไม่ใช่ขั้นตอนที่เปลี่ยนเอาต์พุตโลคอลให้กลายเป็นการผ่าน

สองแพ็กเก็ต เรื่องเดียว

เมื่อทันเนลขึ้นแล้ว แพ็กเก็ตชั้นในของแอปกับแพ็กเก็ตชั้นนอกที่เข้ารหัสเป็นวัตถุที่ต่างกัน แพ็กเก็ตชั้นในพาปลายทางและเพย์โหลดที่แอปเลือก แพ็กเก็ตชั้นนอกพาข้อความเข้ารหัสไปยังที่อยู่และพอร์ตของคู่ตรงข้าม และเป็นสิ่งที่ข้ามอินเทอร์เฟซทางกายภาพจริง

นโยบายของคุณเกี่ยวกับตัวใดตัวหนึ่ง และการเลือกผิดตัวเป็นสาเหตุทั่วไปที่ทำให้กฎดูเหมือนไม่ทำอะไรเลย กฎที่ตรงกับที่อยู่ชั้นนอกของคู่ตรงข้ามจะเห็นแพ็กเก็ตทันเนลทุกใบเหมือนกัน ไม่ว่าแอปข้างในจะทำอะไร กฎที่ตรงกับปลายทางชั้นในจะเห็นทราฟฟิกที่คุณสนใจ และจะทำงานก็ต่อเมื่อแพ็กเก็ตนั้นไปถึง hook ที่คุณติดตั้งกฎไว้

namespace เลื่อนขอบเขต

คอนเทนเนอร์ทำให้ยากขึ้นโดยไม่เปลี่ยนหลักการ คำขอของแอปเป็นเอาต์พุตโลคอลภายใน namespace เครือข่ายของคอนเทนเนอร์ โฮสต์รับทราฟฟิกนั้นบนอินเทอร์เฟซ Ethernet เสมือนและอาจส่งต่อได้ ดังนั้นกฎ FORWARD บนโฮสต์จึงอาจมีความหมายได้ แม้โปรเซสที่สร้างคำขอจะไม่เคยแตะเชน OUTPUT ของโฮสต์เลย

ก่อนเลือก hook ให้ระบุว่าชุดกฎและทันเนลอยู่ที่ใดจริง ๆ ทันเนลในคอนเทนเนอร์ ทันเนลบนโฮสต์ที่ route คอนเทนเนอร์ผ่านมัน และทันเนลใน namespace แยก เป็นสามโทโพโลยีที่ต่างกันพร้อมตำแหน่งกฎที่ต่างกัน อ่านกฎภายใน namespace ที่เป็นเจ้าของอุปกรณ์ ไม่ใช่แค่ในค่าเริ่มต้น

ถามตัวเองว่าจำเป็นต้องใช้ mark จริงหรือไม่

หากเป้าหมายคือส่งคำนำหน้าปลายทางหนึ่งรายการผ่านทันเนล เส้นทางสำหรับคำนำหน้านั้นอาจเพียงพอ ตรวจเส้นทางที่มีผลก่อน รวมถึงทุกสิ่งที่เซิร์ฟเวอร์ดันมา เส้นทางเริ่มต้นที่ถูกเปลี่ยนทิศจะส่งทราฟฟิกผ่าน VPN มากกว่านโยบายแคบ ๆ ที่คุณคิดไว้มาก และการทำ mark เท่าไรก็ไม่ทำให้ผลลัพธ์ตรงกับเจตนา

การจำแนกจำเป็นเมื่อการตัดสินใจขึ้นกับสิ่งที่เส้นทางบอกไม่ได้ เช่น แหล่งที่มา ผู้ใช้ หรือโปรเซส สำหรับทราฟฟิกที่รับเข้ามา การทำ mark ใน PREROUTING ได้ผล สำหรับทราฟฟิกโลคอล การทำ mark ต้องเกิดในขั้นตอนเอาต์พุตที่กระตุ้นการค้นหาเส้นทางใหม่ได้หลังใส่ mark แล้ว ใน nftables นั่นคือเชนชนิด route บน hook เอาต์พุต ส่วนเชนฟิลเตอร์เอาต์พุตธรรมดาจะใส่ค่าและปล่อยเส้นทางไว้เหมือนเดิม

ใน iptables สิ่งที่เทียบเท่าอยู่ในการจัดเรียง mangle OUTPUT และเงื่อนไขเดียวกันใช้บังคับ คือต้องทบทวนการตัดสินใจ route ใหม่หลังจากมี mark แล้ว จากนั้นกฎนโยบายต้องใช้ mark และชี้ไปยังตารางที่มีเส้นทางใช้ได้ การใส่ mark ของ conntrack เป็นการดำเนินการที่สามแยกต่างหาก มันเก็บค่าไว้บนโฟลว์และไม่ได้ใส่ค่านั้นบนแพ็กเก็ตปัจจุบันให้ route อ่านเอง

ตรวจสอบการค้นหาและตัวนับไปพร้อมกัน

nft list ruleset
ip route get 198.51.100.25
ip route get 198.51.100.25 mark 0x1

ที่อยู่และ mark เป็นเพียงตัวอย่าง และการถามเส้นทางสองครั้งตอบคำถามต่างกัน ครั้งที่สองถามว่าเคอร์เนลจะทำอะไรหากแพ็กเก็ตพา mark นั้นมา ไม่ได้แสดงว่าชุดกฎของคุณกำหนดค่าใดค่าหนึ่ง มองมันเป็นการทดสอบสมมติฐาน ไม่ใช่หลักฐานว่านโยบายได้ผล

จากนั้นรันคำขอที่ไม่เป็นอันตรายและดูสองอย่างพร้อมกัน ตัวนับบน hook ที่คุณเลือก และทางออกที่แพ็กเก็ตใช้จริง หากตัวนับขยับและแพ็กเก็ตออกไปที่อื่น mark หรือตารางผิด หากทั้งสองไม่ขยับ แพ็กเก็ตไปไม่ถึง hook นั้นเลย และคำถามถัดไปคือ namespace หรือเส้นทาง

สุดท้าย จำกัดการทดสอบไว้เท่าที่กลไกสื่อได้ เส้นทางหนึ่งเส้นสำหรับที่อยู่หนึ่งที่อยู่ไม่กลายเป็นนโยบายถาวรสำหรับบริการที่ที่อยู่หมุนเวียน กำหนดขอบเขตแพ็กเก็ตก่อน แล้วตรวจว่าการออกแบบ route และ mark รักษาขอบเขตนั้นได้หลังเชื่อมต่อใหม่

บทความที่เกี่ยวข้อง