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

Guest คือสแตกแยกต่างหากหลัง NAT คงที่

เครือข่ายโหมดผู้ใช้ของ QEMU วาง guest ไว้ที่ 10.0.2.15 โดยมีเกตเวย์ที่ 10.0.2.2 และบริการ DNS ที่ 10.0.2.3 ถึง 10.0.2.6 ทราฟฟิกขาออกของ guest ไม่ได้ถูกส่งต่อโดยเคอร์เนลของโฮสต์ แต่ถูกแปลงเป็นซ็อกเก็ตฝั่งโฮสต์ หนึ่งตัวต่อการเชื่อมต่อของ guest หนึ่งครั้ง และซ็อกเก็ตเหล่านั้นออกจากพื้นที่แอดเดรสของโฮสต์ นี่คือเหตุผลที่การเชื่อมต่อของ guest สืบทอดการตัดสินใจเรื่องเส้นทางของโฮสต์ในขณะที่มันถูกสร้างขึ้น และเป็นเหตุผลที่ guest ไม่มีรายการในตารางเส้นทางที่ระบุชื่ออุโมงค์ของคุณ

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

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

DNS คือสแนปช็อต ไม่ใช่ภาพสด

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

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

adb shell dumpsys connectivity | grep -i -A2 dns
adb shell ping -c 1 build.internal.example

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

emulator -avd Pixel_API_34 -dns-server 203.0.113.53

รีโซลเวอร์สาธารณะไม่มีสำเนาของโซนภายใน ดังนั้นการปักหมุดตัวหนึ่งจึงเปลี่ยนปัญหาลำดับให้เป็นความล้มเหลวถาวร หากโปรไฟล์ดัน DNS ส่วนตัว ปล่อยให้อุโมงค์จัดหาให้ และ cold boot guest แทนการฮาร์ดโค้ดแอดเดรส

เส้นทางตามโฮสต์ ณ เวลาที่เชื่อมต่อ

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

การตรวจสอบอยู่ที่อินเทอร์เฟซของโฮสต์ ไม่ใช่สถิติของ guest:

sudo tcpdump -ni tun0 'host 203.0.113.10'

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

เมื่อไคลเอนต์เสนอพร็อกซี loopback เท่านั้น

ไคลเอนต์เชิงพาณิชย์บางตัวไม่สร้างอุโมงค์ระบบเลย พวกมันเปิดตัวฟัง HTTP หรือ SOCKS บน 127.0.0.1 และคาดว่าแอปจะใช้ guest มองไม่เห็นซ็อกเก็ตนั้นโดยตรง แต่สามารถสั่งอีมูเลเตอร์ให้ใช้ได้ ไม่ว่าจะผ่านตัวควบคุมแบบขยาย (Settings จากนั้น Proxy โหมดแมนนวล โฮสต์ 127.0.0.1 และพอร์ตที่ไคลเอนต์พิมพ์ออกมา) หรือตอนเปิดใช้:

emulator -avd Pixel_API_34 -http-proxy http://127.0.0.1:8080

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

พิสูจน์ผลลัพธ์จากภายใน guest

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

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

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