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

เริ่มจากสองโฟลว์ที่คุณต้องการแยก

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

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

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

ทำเครื่องหมายที่ซ็อกเก็ตที่พาซอง

การกำหนดค่าไคลเอนต์ได้รับเครื่องหมายสำหรับแพ็กเก็ตขาออกที่เข้ารหัส และเลิกติดตั้งเส้นทางด้วยตัวเอง เพื่อให้นโยบายแทนที่เป็นสิ่งเดียวที่กำหนดเส้นทาง:

mark 42
route-noexec
disable-dco

เลขฐานสิบ 42 คือเลขฐานสิบหก 0x2a และรูปแบบฐานสิบหกคือสิ่งที่กฎเราเตอร์จะจับคู่ เอกสารอ้างอิง link-options อธิบาย mark ว่าใช้กับแพ็กเก็ตขาออกที่เข้ารหัสบน Linux ซึ่งก็คือซ็อกเก็ตที่คุณต้องควบคุมเส้นทาง การปิดออฟโหลดของช่องข้อมูลทำให้ตัวอย่างนี้อยู่บนเส้นทางของผู้ใช้ทั่วไป ซึ่งพฤติกรรมของเครื่องหมายคือสิ่งที่อธิบายไว้

route-noexec ระงับการเพิ่มและลบเส้นทางอัตโนมัติของ OpenVPN มันไม่ได้ติดตั้งสิ่งใดแทน ดังนั้นจากนี้ไปเจ้าของเส้นทางต้องดูแลทุกเส้นทางที่ทันเนลต้องการ หากปลายทางส่วนตัวหายไปหลังการเปลี่ยนแปลง นั่นคือนโยบายแทนที่ที่ขาดหาย ไม่ใช่ข้อบกพร่องของเครื่องหมาย

อย่าเก็บเส้นทางโฮสต์ในตารางหลักสำหรับ 198.51.100.25 ขณะทำสิ่งนี้ เส้นทางเช่นนั้นจะนำข้อยกเว้นที่การออกแบบพยายามจำกัดกลับมา และมันจะชนะสำหรับโฟลว์ HTTPS ก่อนที่จะมีการสอบถามนโยบายใด ๆ ด้านล่าง

ส่งทุกอย่างอื่นไปยังตารางทันเนล

เมื่ออินเทอร์เฟซทันเนลมีอยู่และถือที่อยู่ของมันแล้ว นโยบายจะมีลักษณะเช่นนี้:

ip -4 route add default dev tun1 src 10.90.0.10 table 47100
ip -4 rule add priority 20000 lookup main suppress_prefixlength 0
ip -4 rule add priority 20001 not fwmark 0x2a lookup 47100
ip -4 rule add priority 20002 not fwmark 0x2a unreachable

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

ทราฟฟิกที่ไม่ได้ทำเครื่องหมายจะตกไปยังตารางทันเนล รับแหล่งทันเนล และออกผ่าน VPN ทราฟฟิกที่ทำเครื่องหมายจะล้มเหลวในการทดสอบ fwmark ที่กฎสองข้อถัดไป และดำเนินต่อไปยังการค้นหาหลักปกติที่ต่ำกว่าในรายการ ซึ่งเส้นทางเริ่มต้นของอัปลิงก์ยังอยู่ กฎ unreachable ปิดท้ายคือสิ่งที่ป้องกันไม่ให้โฟลว์ที่ไม่ได้ทำเครื่องหมายตกลงกลับไปยังอัปลิงก์อย่างเงียบ ๆ เมื่อเส้นทางทันเนลหายไป ตัวเลือกคือเครื่องหมายตั้งแต่ต้นจนจบ และที่อยู่ปลายทางไม่เคยเข้าไปในการตัดสินใจ

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

ให้เส้นทางขากลับเห็นเครื่องหมายเดียวกัน

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

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

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

พิสูจน์ด้วยการค้นหาเส้นทางสองครั้ง

เปรียบเทียบสิ่งที่เคอร์เนลตัดสินใจสำหรับสองบริบท และอ่านฟิลด์ dev และ src แทนสถานะออก:

ip -4 route get 198.51.100.25
ip -4 route get 198.51.100.25 mark 0x2a

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

จดบันทึกสิ่งที่การออกแบบไม่ครอบคลุมก่อนจะประกาศว่าเสร็จสิ้น DNS, IPv6 และวงจรชีวิตของกฎแต่ละอย่างต้องมีการตัดสินใจของตัวเอง และนี่คือตัวอย่างการกำหนดเส้นทาง IPv4 ไม่ใช่การกำหนดค่าความเป็นส่วนตัวที่สมบูรณ์ คุณค่าของมันคือตัวเลือก: ซองได้รับข้อยกเว้นของอัปลิงก์ และบริการธรรมดาที่ที่อยู่เดียวกันไม่จำเป็นต้องสืบทอดมัน

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