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

ตัวจับคู่นาน ๆ ครั้งจะเป็นตัวการ

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

ระเบียน A ว่างเปล่าคือความผิดพลาดคลาสสิก การตอบ NOERROR พร้อมคำตอบศูนย์ดูเหมือนคำตอบที่ถูกต้อง ตัวแปลงชื่อ stub จึงยอมรับ เบราว์เซอร์ลองใหม่ ลอง AAAA ลองตัวแปลงชื่ออื่น แล้วยอมแพ้ในเวลาที่นานกว่ามาก รหัสคำตอบ 3 คือ NXDOMAIN พร้อมส่วนคำถามที่สะท้อนกลับและ ID ธุรกรรมที่คัดลอกมา จะจบการสนทนาทันที ใช้กับทุกชื่อที่คุณปฏิเสธโดยเจตนา

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

เส้นทางที่ดักทุกอย่างเป็นเจ้าของทุกอย่าง

การออกแบบที่มีแต่ DNS ไม่เคยเพิ่ม addRoute("0.0.0.0", 0) คำถามจึงเข้าไปในอินเทอร์เฟซ TUN เท่านั้น และทุกอย่างอื่นยังใช้เครือข่ายข้างใต้ต่อไป นั่นคือรูปแบบที่ปลอดภัย และยังอธิบายว่าทำไมรายการที่อนุญาตบางรายการดูเหมือนทำงานบน Wi-Fi แต่ล้มเหลวบนเครือข่ายมือถือ

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

ซ็อกเก็ตของตัวแปลงชื่อต้องออกจากอุโมงค์

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

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

ขนาดและเช็กซัมล้มเหลวโดยไม่มีข้อความ

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

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

สิ่งที่ VpnService ไม่ทำให้คุณ

มีสองขีดจำกัดที่ควรรู้ก่อนออกแบบโดยรอบ ไม่มีแอปธรรมดาใดติดตั้งพร็อกซีทั้งระบบหรือไฟล์ PAC นอก Wi-Fi ได้ และส่วนนั้นไม่เปลี่ยน เส้นทางรายแอปเปลี่ยนแล้ว: ก่อน API 29 นั้น VpnService.Builder ไม่สามารถพกพร็อกซีได้เลย และตั้งแต่ API 29 setHttpProxy(ProxyInfo.buildPacProxy(uri)) มอบสคริปต์ PAC ให้แพลตฟอร์มประเมินสำหรับเครือข่าย VPN ประเมินกฎในโค้ดของคุณเองเมื่อกำหนดเป้าหมาย API เก่าหรือเมื่อโมเดล PAC แสดงกฎนั้นไม่ได้ UDP ก็ไม่ฟรีเช่นกัน เบราว์เซอร์ส่งเฉพาะ TCP ผ่านพร็อกซี SOCKS และไคลเอนต์ SOCKS5 ส่วนใหญ่ไม่เคยใช้งาน UDP ASSOCIATE การออกแบบที่อิงพร็อกซีจึงทิ้งหรือรั่ว UDP ขณะที่ TCP ดูปกติ

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

ตรวจตามลำดับนี้

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

  1. แสดงรายการเส้นทางที่ติดตั้งและยืนยันว่าแพ็กเก็ตที่ไม่ใช่ DNS เข้าอินเทอร์เฟซ TUN หรือไม่
  2. บันทึกชื่อคำถาม การตัดสินใจ และรหัสคำตอบสำหรับชื่อที่ถูกบล็อกหนึ่งชื่อและชื่อที่อนุญาตหนึ่งชื่อ
  3. ยืนยันว่าซ็อกเก็ตของตัวแปลงชื่อได้รับการปกป้องและตัวแปลงชื่อที่เลือกตอบจากภายในอุโมงค์
  4. ยืนยัน MTU ของอินเทอร์เฟซและเช็กซัมของคำตอบหนึ่งรายการที่สร้างด้วยมือ
  5. ทำซ้ำหน้าเดิมบน Wi-Fi และเครือข่ายมือถือ เพราะตัวแปลงชื่อของผู้ให้บริการและ MTU ของเส้นทางต่างกัน

ถ้าทั้งห้าผ่านและหน้ายังค้าง ผู้ต้องสงสัยรายต่อไปคือตัวส่งต่อเอง: เปรียบเทียบคำขอที่ดักได้กับคำตอบที่ดักได้ และมองหาจำนวนไบต์ที่หายไปหรือซ็อกเก็ตที่ปิดครึ่งเดียว เอกสารอ้างอิง VpnService.Builder ครอบคลุมสัญญาเรื่องเส้นทาง DNS และ MTU และ protect() เป็นการเรียก VpnService แยกต่างหาก ไม่ใช่ตัวเลือกของ builder อินเทอร์เฟซที่เชื่อมต่อแล้วหมายความเพียงว่าสัญญาแรกสำเร็จ

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