VPN บน Android ทำงานบน IPv6 แต่เบราว์เซอร์ยังเลือก IPv4
ตามสี่ขั้นตอนที่ที่อยู่ IPv6 ส่วนตัวหายไป: ตัวแปลงชื่อ การประกาศของ VpnService การตรวจสอบผู้สมัครของเบราว์เซอร์ และการส่งมอบเส้นทาง
VPN ทำงานอยู่ อินเทอร์เฟซเว็บส่วนตัวตอบกลับผ่าน IPv6 จากแล็ปท็อป แต่โทรศัพท์ Android ยังเปิดหน้าเดียวกันผ่าน IPv4 หรือปฏิเสธที่จะโหลดเลย บันทึก AAAA มีอยู่ อุโมงค์รายงานที่อยู่ IPv6 ไม่มีอะไรดูผิดในไคลเอนต์ ผลลัพธ์ถูกกำหนดโดยการตัดสินใจสี่อย่างแยกกัน: ตัวแปลงชื่อใดตอบว่า VpnService ประกาศอะไรกับ Android เบราว์เซอร์ยินดีลองตระกูลที่อยู่ใด และแพ็กเก็ตสามารถเดินทางไปกลับได้หรือไม่ จัดการตามลำดับนั้นแทนที่จะเพิ่มเส้นทางเริ่มต้นแล้วหวังว่าอาการจะย้าย
ขั้นตอนที่ 1: พิสูจน์ว่าตัวแปลงชื่อใดตอบคำถาม AAAA
Android ไม่มีเส้นทาง DNS เดียว VPN สามารถดันเซิร์ฟเวอร์ DNS สำหรับเครือข่ายของตน ระบบอาจใช้ Private DNS สำหรับชื่อโฮสต์ที่เห็นว่าเข้าข่าย และ Chrome อาจเรียกใช้ตัวแปลงชื่อที่เข้ารหัสของตัวเองจาก chrome://settings/security บนโทรศัพท์ที่อุโมงค์ดัน 10.61.0.1 แต่ Private DNS ชี้ไปยังผู้ให้บริการสาธารณะ ชื่อภายในโซนส่วนตัวของคุณไม่ได้ถูกแปลงโดยเครื่องที่เป็นเจ้าของโซน เบราว์เซอร์ได้รับคำตอบจากตัวแปลงชื่อที่ไม่มีอำนาจเหนือชื่อนั้นและถือว่าไม่มีอยู่ และข้อความแสดงข้อผิดพลาดไม่เคยกล่าวถึง DNS
ถามตัวแปลงชื่อของอุโมงค์โดยตรงก่อนจะเปลี่ยนอย่างอื่น คำสั่งสองคำสั่งแรกแสดงว่า Android ผูกเซิร์ฟเวอร์ DNS ใดกับเครือข่ายที่ใช้งานอยู่ และ Private DNS อยู่ในโหมดอัตโนมัติหรือเข้มงวด คำสั่งที่สามทำงานจากไคลเอนต์ใดก็ได้ภายในอุโมงค์ ไม่ใช่จากโทรศัพท์
adb shell dumpsys connectivity | grep -A3 "DnsAddresses"
adb shell settings get global private_dns_mode
nslookup -type=AAAA nas.lan 10.61.0.1
ขั้นตอนที่ 2: อ่านว่า VpnService ประกาศอะไรจริง ๆ
ฝั่ง Android เป็นการประกาศชัดเจนไม่ใช่การอนุมาน VpnService.Builder เพิ่มที่อยู่ด้วย addAddress เส้นทางด้วย addRoute เซิร์ฟเวอร์ DNS ด้วย addDnsServer และสามารถจำกัดอุโมงค์ทั้งหมดให้เหลือตระกูลที่อยู่เดียวด้วย allowFamily ตัวสร้างที่เรียก allowFamily(AF_INET) แล้วเพิ่มเส้นทาง IPv6 ภายหลังได้บอกระบบสองสิ่งที่สุดขัดแย้งกัน และระบบเก็บข้อจำกัดตระกูลไว้ เส้นทางที่ครอบคลุม fd00:61::/64 รวมกับที่อยู่อินเทอร์เฟซในคำนำหน้าอื่นล้มเหลวด้วยเหตุผลเดียวกัน: ที่อยู่มีอยู่ แต่ไม่ใช่ on-link สำหรับเส้นทางนั้น
อ่านการประกาศแทนที่จะเชื่อสวิตช์ในแอป dumpsys netd พิมพ์ที่อยู่และเส้นทางที่ผูกกับอินเทอร์เฟซ tun และ LinkProperties ต่อเครือข่ายภายใน dumpsys connectivity แสดงรายการ DNS ข้างตระกูลที่เครือข่ายอ้าง
adb shell ip -6 addr show tun0
adb shell ip -6 route show table all | grep tun0
adb shell dumpsys connectivity | grep -E "LinkAddresses|Routes"
หากอินเทอร์เฟซ tun มีที่อยู่ IPv6 แต่ไม่มีเส้นทางใดตรงกับคำนำหน้าของบริการ การส่งมอบ IPv6 ก็เสียก่อนที่เบราว์เซอร์จะเข้ามาเกี่ยวข้อง นี่เป็นข้อบกพร่องที่ต่างจากเบราว์เซอร์ที่ปฏิเสธที่จะลอง และต้องแก้ต่างกัน
ขั้นตอนที่ 3: เบราว์เซอร์ตัดสินใจว่าจะลอง IPv6 หรือไม่
Chromium ไม่ได้ใช้ทุกระเบียน AAAA ที่ได้รับ ตัวแปลงชื่อโฮสต์มีงานตรวจสอบการเข้าถึง IPv6 และการกรองผู้สมัครที่อาจทิ้งหรือลดลำดับความสำคัญของ IPv6 เมื่อตัดสินว่าเครือข่ายไม่สามารถรองรับได้ และซอร์สของตัวแปลงชื่อแสดงการตรวจนั้นพร้อมเงื่อนไขรอบข้าง ตรรกะขึ้นกับเวอร์ชันและแฟล็ก จึงเป็นเหตุผลที่โทรศัพท์สองเครื่องบนอุโมงค์เดียวกันอาจทำงานต่างกัน เมื่อมีผู้สมัครแล้ว Happy Eyeballs ให้ตระกูลแข่งกันต่อการเชื่อมต่อ ดังนั้นเส้นทาง IPv6 ที่ตอบช้าอาจยังแพ้ IPv4 ที่ตอบเร็ว
สังเกตการตัดสินใจแทนการอนุมาน เซสชันที่บันทึกผ่าน chrome://net-export และเล่นซ้ำในตัวดู netlog แสดงการแปลงแต่ละครั้งและตระกูลที่เลือก chrome://net-internals/#dns แสดงผลลัพธ์ที่แคชไว้ การแปลงที่คืนเฉพาะระเบียน A สำหรับชื่อที่มี AAAA ที่ตัวแปลงชื่อของคุณเองชี้ตรงมาที่ขั้นตอนนี้
ขั้นตอนที่ 4: ตรวจสอบว่าแพ็กเก็ตเดินทางไปกลับได้
การเลือกที่อยู่ไม่ใช่การส่งมอบ Android เก็บตารางเส้นทางและกฎนโยบายต่อเครือข่ายที่เลือกตารางด้วย fwmark ดังนั้นเส้นทางที่มองเห็นในตารางหลักไม่ใช่เส้นทางที่ซ็อกเก็ตใช้โดยอัตโนมัติ การอ่านกฎและการขอให้เคอร์เนลแปลงปลายทางสำหรับที่อยู่ต้นทางแยกสองสิ่งนั้น
adb shell ip -6 rule show
adb shell ip -6 route get fd00:61::20 from fd00:61::10
ผลลัพธ์ของ route get คือสิ่งที่ตอบคำถาม หากระบุ tun0 แต่แพ็กเก็ตยังตาย ให้ไปที่ MTU ของอุโมงค์และการส่งต่อ IPv6 ของเกตเวย์แทนการกลับไปที่โทรศัพท์
ทำไมการเพิ่ม ::/0 มักทำให้แย่ลง
การเพิ่ม ::/0 เปลี่ยนข้อเรียกร้องของอุโมงค์จากคำนำหน้าเดียวเป็นทุกปลายทาง IPv6 บนโทรศัพท์อาจทำให้ผ่านการตรวจการเข้าถึงได้ เพราะที่อยู่ทดสอบนอกคำนำหน้าของคุณดูเหมือนส่งต่อได้แล้ว แต่ไม่ได้สร้างความจุ IPv6 ขาขึ้นที่เกตเวย์ และเกตเวย์ตามบ้านหลายแห่งไม่มีลิงก์ขาขึ้น IPv6 ที่ใช้งานได้เลย ผลลัพธ์คือหลุมดำสำหรับ IPv6 สาธารณะ: ชื่อที่เคยถอยกลับไป IPv4 ตอนนี้ค้าง และหน้าส่วนตัวอาจดูดีขึ้นเพียงเพราะการตรวจวัดสิ่งอื่น
ยังมีต้นทุนด้านนโยบายอีก ด้วย ::/0 ในอุโมงค์ ทราฟฟิก IPv6 ทั้งหมดออกผ่าน VPN รวมถึงทราฟฟิกที่เจ้าของเครือข่ายไม่เคยตกลงจะรับไว้ มองสิ่งนี้เป็นการตัดสินใจติดตั้งที่มีเจ้าของระบุชื่อ ไม่ใช่ขั้นตอนดีบักที่ทำตอนตี 1
ลำดับงานที่ยุติเรื่องนี้
ยืนยันว่าคำตอบ AAAA มาจากตัวแปลงชื่อที่ถือโซน อ่านสถานะ VpnService และ netd สำหรับอินเทอร์เฟซ tun เก็บร่องรอย net-export เพื่อดูว่า Chromium ทิ้งผู้สมัครหรือไม่ แล้วทดสอบการไปกลับด้วย ip -6 route get แก้ไขชั้นที่ล้มเหลวจริงและปล่อยนโยบายการแยกไว้ ถ้าชื่อส่วนตัวต้องการคำตอบต่างจากชื่อสาธารณะ นั่นคือสิ่งที่ split tunneling มีไว้
บันทึก build ของโทรศัพท์ เวอร์ชันเบราว์เซอร์ และตัวแปลงชื่อที่คุณถาม ข้อเท็จจริงสามข้อนั้นเปลี่ยน "IPv6 is broken" ให้เป็นสิ่งที่คนถัดไปทำซ้ำได้