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

การตอบกลับ echo พิสูจน์อะไรได้จริง

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

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

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

ถาม Android เรื่องการขนส่ง ไม่ใช่ ping

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

เวอร์ชัน Java นี้คืนค่า false แทนการโยนข้อยกเว้นเมื่อไม่มีเครือข่ายที่ใช้งานอยู่ เพราะอ่านเครือข่ายที่ใช้งานอยู่ จึงสะท้อนโปรไฟล์ที่ผู้ใช้เลือกใน Settings

ConnectivityManager cm = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE);
NetworkCapabilities caps = cm.getNetworkCapabilities(cm.getActiveNetwork());
boolean tunnel = caps != null && caps.hasTransport(NetworkCapabilities.TRANSPORT_VPN);

สำหรับการแจ้งเตือนการเปลี่ยนแปลง ให้ลงทะเบียน NetworkCallback แทนการสำรวจด้วยตัวจับเวลา อย่าสับสนกับ VpnService.prepare ซึ่งรายงานเพียงว่าผู้ใช้อนุญาต VPN หรือไม่ ไม่ใช่ว่าแพ็กเก็ตไหลอยู่หรือไม่ การเพิกถอนมาทาง VpnService.onRevoke แต่การลืมโปรไฟล์ใน Settings ไม่ก่อให้เกิดการออกอากาศใด ๆ

iOS: ชื่ออินเทอร์เฟซเป็นเพียงการคาดเดา ไม่ใช่สัญญา

โค้ด iOS จำนวนมากตรวจสอบการตั้งค่าพร็อกซี่ พจนานุกรม __SCOPED__ แล้วมองหาคีย์อินเทอร์เฟซอย่าง tap, tun, utun2, ppp หรือ ipsec วิธีนี้เป็นเพียงธรรมเนียมการตั้งชื่อ ไม่ใช่การรับประกันที่มีเอกสาร จึงอาจพังเมื่อระบบปฏิบัติการอัปเดตแล้วเปลี่ยนชื่ออินเทอร์เฟซ อีกทั้งมักรายงาน true สำหรับรายการเก่าที่อยู่ยืนยาวกว่าอุโมงค์

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

โหลดการตั้งค่าใหม่ก่อนอ่านสถานะ เพราะค่าจะเปลี่ยนเมื่ออุโมงค์ขึ้นและลง:

let manager = NEVPNManager.shared()
manager.loadFromPreferences { error in
    let up = manager.connection.status == .connected
    print(up)
}

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

โปรไฟล์ Windows เปิดเผยฟิลด์สถานะจริง

Windows ติดตามโปรไฟล์ VPN แยกจากอะแดปเตอร์ และ Get-VpnConnection เปิดเผย ConnectionStatus สำหรับทุกโปรไฟล์ที่รู้จัก โปรไฟล์ที่สร้างผ่านไคลเอนต์ Windows หรือแพ็กเกจการจัดเตรียมจะปรากฏที่นี่ คำสั่งนี้ไม่ใช่ตัวตรวจจับอุโมงค์ทั่วไป

อ่านฟิลด์สำหรับโปรไฟล์ที่ระบุชื่อ และเพิ่ม -AllUserConnection เมื่อโปรไฟล์เป็นของผู้ใช้ทั้งหมด:

Get-VpnConnection -Name "Fabrikam" | Select-Object Name, ConnectionStatus, ServerAddress

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

สถานะบวกเส้นทาง: การตรวจสอบสองส่วน

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

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

ip route get 192.0.2.10
resolvectl query intranet.example.test

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

การทดสอบที่คุณรันตามลำดับได้

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

บนเครื่อง Linux ที่มี dig และ curl สามคำสั่งครอบคลุมการแก้ชื่อ เส้นทาง และตัวบริการเอง รันเมื่ออุโมงค์ขึ้นและอีกครั้งเมื่อลง:

dig +short intranet.example.test
ip route get 198.51.100.20
curl -sS -o /dev/null -w "%{http_code}" --max-time 8 https://intranet.example.test/health

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

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