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

ทำไมไคลเอนต์จึงเสนอไม่ได้

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

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

การเลือกเส้นทางตามแอปจริง ๆ มีอยู่ที่แพลตฟอร์มเพิ่มกลไกไว้ เช่น การเรียกตัวกรองบน Windows หรือการผูกบริการ VPN บน Android อินสแตนซ์ OpenVPN บนเดสก์ท็อปไม่ได้มาพร้อมสิ่งเหล่านั้น และไม่มีแฟล็กการตั้งค่าใดประดิษฐ์มันขึ้นมา

Linux: ทำเครื่องหมายที่โปรเซส แล้วเลือกเส้นทางตามเครื่องหมาย

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

iptables -t mangle -A OUTPUT -m owner --uid-owner 1001 -j MARK --set-mark 0x1
ip rule add fwmark 0x1 table 200
ip route add 192.168.1.0/24 dev eth0 src 192.168.1.0 table 200
ip route add default via 192.168.1.1 dev eth0 table 200

แพ็กเก็ตจากผู้ใช้ 1001 จะปรึกษาตาราง 200 แล้วออกผ่านเกตเวย์ปกติ ขณะที่ตารางหลักยังส่งทุกอย่างอื่นเข้าอุโมงค์ การตรงกันของ owner ใช้กับแพ็กเก็ตที่สร้างในเครื่องเท่านั้น ซึ่งก็คือทราฟฟิกที่สำคัญตรงนี้ และมันไม่สามารถจำแนกแพ็กเก็ตที่ส่งต่อให้โฮสต์อื่นได้ ตรวจสอบด้วยเครื่องมือ ไม่ใช่ด้วยเจตนา: ss -tnp แสดงที่อยู่ในเครื่องและโปรเซสเจ้าของของการเชื่อมต่อที่สร้างแล้ว และ ip route get 1.1.1.1 mark 0x1 แสดงว่าเครื่องหมายเลือกตารางใด

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

ip netns add novpn
ip link add veth-host type veth peer name veth-ns
ip link set veth-ns netns novpn
ip addr add 10.200.0.1/24 dev veth-host
ip netns exec novpn ip addr add 10.200.0.2/24 dev veth-ns
ip netns exec novpn ip route add default via 10.200.0.1

Windows: ปลายทางยังคงตัดสิน

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

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

ย้ายการตัดสินใจเมื่อโปรเซสเดียวเป็นหน่วยที่ผิด

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

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

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