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

เริ่มจากเส้นทางที่แพ็กเก็ตจะไป

ตารางเส้นทางคือการตัดสินใจ จึงถามตารางเกี่ยวกับปลายทางเดียวแทนการอ่านทั้งหมดแล้วเดา บน Linux ip route get บอกอินเทอร์เฟซและที่อยู่ต้นทางที่เคอร์เนลเลือก:

ip route get 203.0.113.10
ip route get 10.20.5.7

บน Windows Find-NetRoute -RemoteIPAddress 203.0.113.10 มีประโยชน์กว่า route print -4 ด้วยเหตุผลเดียวกัน คือรายงานเส้นทางที่ชนะ ไม่ใช่ทุกเส้นทางที่มี อ่านตารางสักครั้งเพื่อดูแถว 0.0.0.0 ก็ยังดี คู่ /1 ที่นั่นหมายความว่าไคลเอนต์อุโมงค์เต็มได้เขียนเส้นทางเริ่มต้นใหม่: ตัวเลือก redirect-gateway def1 ของ OpenVPN ติดตั้ง 0.0.0.0/1 และ 128.0.0.0/1 ผ่านอุโมงค์ ซึ่งชนะ 0.0.0.0/0 ที่มีอยู่ด้วยการจับคู่คำนำหน้าที่ยาวที่สุดโดยไม่ลบเส้นทางเริ่มต้นกายภาพ นั่นคือเหตุผลที่เส้นทางเริ่มต้นสองเส้นอยู่ร่วมกันได้ในขณะที่ทุกอย่างยังคงเข้าไปในอุโมงค์

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

ติดตามชื่อภายในหนึ่งชื่อและชื่อสาธารณะหนึ่งชื่อ

การค้นหาเส้นทางแสดงเจตนา ส่วนเส้นทางแสดงการส่งมอบ ขณะเชื่อมต่อ ให้ติดตามชื่อที่ต้องเป็นภายในและชื่อที่ไม่ควรเป็น แล้วเปรียบเทียบฮอปแรก:

traceroute intranet.corp.example
traceroute 1.1.1.1

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

ICMP ที่ถูกกรองทำให้การตรวจนี้โกหก ดาวทั้งสองรอยดูเหมือนอุโมงค์ตายและมักเป็นไฟร์วอลล์ ทดสอบพอร์ต TCP ที่ทำได้ — บน Linux คือ traceroute -T -p 443 — และจำไว้ว่ารอยไม่ได้บอกว่าตัวแปลงชื่อใดตอบ ชื่ออาจแปลงได้ภายในเครื่องและยังเข้าถึงได้ผ่านอุโมงค์

ดักจับบนอะแดปเตอร์กายภาพ ไม่ใช่บนอุโมงค์

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

sudo tcpdump -ni eth0 udp port 53
sudo tcpdump -ni eth0 host 10.20.0.5

ตัวกรองแรกจับการแปลงชื่อที่ออกจากเครื่อง ซึ่งเป็นการรั่วที่พบบ่อยที่สุดและเงียบที่สุด — หน้ายังโหลดได้ ตัวแปลงชื่อเพียงเห็นคำถาม ตัวที่สองจับทราฟฟิกธรรมดาไปยังที่อยู่ภายในที่ควรมีอยู่เฉพาะในอุโมงค์ บน Windows pktmon ทำงานเดียวกันได้โดยไม่ต้องมีไดรเวอร์: pktmon filter add -p 53 แล้ว pktmon start --capture --pkt-size 128 แล้ว pktmon stop และ pktmon format pktmon.etl -o capture.txt แฟล็กเหล่านี้ต่างกันเล็กน้อยระหว่างรุ่นของ Windows จึงตรวจ pktmon filter add /? ก่อนเชื่อไวยากรณ์

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

ถามบริการภายนอก แล้วถามอีกครั้งเป็นรายแอปพลิเคชัน

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

sudo curl --interface tun0 https://example.net/ip
sudo curl --interface eth0 https://example.net/ip

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

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

ใช้มุมมองเซิร์ฟเวอร์เพื่อยืนยันเพียร์

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

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

แยกการตัดสินใจออกแบบออกจากการรั่ว

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

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

เมื่อการตรวจไม่ตรงกัน ความขัดแย้งมักบอกชื่อความผิดพลาด:

What you seeWhat it meansNext step
The route picks tun0 but the capture shows cleartext to 10.20.5.7Something bypassed the table: a bound app, a policy route or a session older than the tunnelReset the flow, check the app bind, check the ip rule list
The route picks eth0 for an internal nameThe name resolves to a public address, or the route was never installedCompare the resolved address with the routes the server pushes
The capture shows DNS to the LAN resolverResolver leak: data is tunneled, lookups are notPoint the resolver inside, or push it from the server
All four checks agree and one app still failsPath selection is fine; suspect MTU, a per-app proxy or the far endTest the same destination from a known-good client

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

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