mitmproxy, DevTools, Gradle: สามชั้นหลัง VPN
loopback ไม่เคยเข้าอุโมงค์ จัดอาการให้เป็นฝั่งผู้ฟัง ที่เก็บความเชื่อถือ หรือตัวกรองแพ็กเก็ต แล้วซ่อมชั้นที่ล้มเหลวจริง
VPN เชื่อมต่อได้ และเครื่องมือสามตัวที่ไม่เกี่ยวข้องกันล้มเหลวคนละแบบในบ่ายวันเดียวกัน mitmproxy มองไม่เห็นคำขอ Chrome ปฏิเสธดีบักเกอร์ และ Gradle โยนBindExceptionขณะผูกซ็อกเก็ตภายใน ความสงสัยร่วมคืออุโมงค์บล็อก localhost ซึ่งเป็นไปไม่ได้:127.0.0.1ถูกจัดการภายในเคอร์เนลและไม่เคยไปถึงอะแดปเตอร์ ไม่ต้องพูดถึงเกตเวย์
สามชั้น สามความล้มเหลวที่ต่างกัน
สิ่งที่เปลี่ยนไปพร้อมไคลเอนต์ไม่ใช่เส้นทางไปยัง loopback แต่เป็นพร็อกซีภายในเครื่อง ที่เก็บความเชื่อถือของเครื่อง และตัวกรองแพ็กเก็ต และแต่ละอย่างทำให้ส่วนต่าง ๆ ของเวิร์กโฟลว์นักพัฒนาพัง การจัดอาการให้อยู่แถวที่ถูกต้องคือส่วนใหญ่ของการวินิจฉัย:
| Symptom | Layer | First check |
|---|---|---|
| Proxy sees no traffic | Local proxy or listener | ss -lntp, ornetstat -anoon Windows |
| TLS error in one tool only | Trust store | Which CA bundle does that runtime read? |
| Local bind or connect refused | Packet filter or port owner | Who holds the port, and what rule drops it? |
รายงานแบบนี้เกือบทั้งหมดเริ่มจากแถวสุดท้ายแล้วไล่ขึ้นไป ซึ่งกลับด้าน อุโมงค์เป็นชั้นเดียวที่พิสูจน์ได้ว่าไม่เห็นทราฟฟิก loopback จึงควรถูกสงสัยน้อยที่สุด เริ่มจากสิ่งที่โปรเซสผูกไว้ ถามต่อว่าเชื่อถือใบรับรองใด แล้วจึงดูนโยบายบนเครื่อง
เริ่มจากฝั่งผู้ฟัง ไม่ใช่อุโมงค์
เมื่อพร็อกซีบน127.0.0.1:8080หยุดรับทราฟฟิก มีหนึ่งในสามอย่างเกิดขึ้น: ไม่เคยเริ่ม ไปผูกพอร์ตอื่น หรือตัวกรองทิ้งการเชื่อมต่อ loopback การแสดงรายการซ็อกเก็ตที่กำลังฟังตอบได้ด้วยคำสั่งเดียว และยังบอกว่าพร็อกเซสใดเป็นเจ้าของพอร์ตเมื่อเครื่องมือสองตัวเถียงกันว่าใครมาก่อน
ที่อยู่ภายในเครื่องในการค้นหาเส้นทางยืนยันเรื่องเดียวกันจากอีกด้านip route getต่อปลายทาง loopback จะรายงานอุปกรณ์ loopback ไม่เคยรายงานอุโมงค์ ซึ่งเป็นประโยคที่มีประโยชน์เตรียมไว้เมื่อมีคนเสนอให้เปลี่ยนเส้นทางเป็นทางแก้
ชั้นพร็อกซี: สภาพแวดล้อมไม่ใช่การตั้งค่า
ไคลเอนต์องค์กรจำนวนมากรันพร็อกซี HTTP และคาดว่าแอปพลิเคชันจะใช้ การตั้งค่าHTTPS_PROXYในเชลล์แก้ไขเครื่องมือบรรทัดคำสั่งที่ให้ความสำคัญกับมัน และไม่ทำอะไรกับเครื่องมือที่อ่านไฟล์ตั้งค่าของตัวเอง Gradle, Selenium และ gRPC ต่างปรึกษาการตั้งค่าของตัวเอง และพร็อกซีที่ส่งออกในเทอร์มินัลเดียวจะมองไม่เห็นจากเดมอนที่ IDE เริ่มขึ้น
เครื่องมือคอนเทนเนอร์เป็นจุดที่เห็นได้ทั่วไป loopback ของคอนเทนเนอร์เป็นของตัวเอง ดังนั้น127.0.0.1ภายในคอนเทนเนอร์ไม่เคยหมายถึงพร็อกซีของโฮสต์ ต้องใช้ที่อยู่โฮสต์หรือการตั้งค่าเครือข่ายโฮสต์ การแก้ไขที่ได้ผลในเชลล์แต่ล้มเหลวในการบิลด์มักเป็นแถวนี้ ไม่ใช่อุโมงค์
ชั้นความเชื่อถือ: เครื่องมืออ่านที่เก็บอื่น
การดักจับคือการเปลี่ยนแปลงที่สอง และสร้างข้อผิดพลาดที่หลอกลวงที่สุด ไคลเอนต์นำเสนอใบรับรองของตัวเองสำหรับการเชื่อมต่อที่ถูกตรวจสอบ เบราว์เซอร์ที่เชื่อถือรูทองค์กรจึงสำเร็จ ขณะที่เครื่องมือที่มีที่เก็บ CA ฝังตัวล้มเหลว requests ของ Python ผ่าน certifi คือกรณีคลาสสิก ที่เก็บของระบบปฏิบัติการอาจถูกต้องและการร้องขอยังล้มเหลว เพราะรันไทม์นั้นไม่เคยอ่านมัน ข้อความข้อผิดพลาดแทบไม่กล่าวถึงการดักจับ จึงทำให้แถวนี้ถูกวินิจฉัยผิดว่าเป็นปลายทางที่เสีย
เปรียบเทียบสิ่งที่ปลายทางนำเสนอจริงกับสิ่งที่เครื่องมือตรวจสอบopenssl s_clientแสดงห่วงโซ่ที่เซิร์ฟเวอร์ส่งมา ผลลัพธ์การตรวจสอบของเครื่องมือเองแสดงสิ่งที่มันตัดสินใจ เมื่อทั้งสองไม่ตรงกันREQUESTS_CA_BUNDLEหรือSSL_CERT_FILEคือคันโยกสำหรับรันไทม์นั้น และรูทองค์กรควรอยู่ในที่เก็บที่รันไทม์นั้นอ่าน ไม่ใช่ในตำแหน่งส่วนกลางที่มีเพียงบางเครื่องมือให้ความสำคัญ
การเปลี่ยนเวอร์ชันที่แก้ข้อผิดพลาด SSL เป็นหลักฐานเกี่ยวกับนโยบายความเชื่อถือและการเข้ารหัส ไม่ใช่เกี่ยวกับ VPN การดาวน์เกรด Python ที่ทำให้ไคลเอนต์ SOAP ทำงานได้เปลี่ยนที่เก็บ CA ฝังตัวและการตั้งค่า TLS โดยค่าเริ่มต้น เส้นทางเครือข่ายไม่ได้ขยับ
ชั้นตัวกรอง: มันทิ้ง loopback ได้เช่นกัน
การเปลี่ยนแปลงที่สามคือตัวกรองแพ็กเก็ต และผลิตภัณฑ์บางตัวติดตั้งกฎที่ทิ้งทราฟฟิกที่ไม่เข้าอุโมงค์ ผู้ฟังภายในเครื่องอาจถูกรวมด้วย สิ่งนี้เปลี่ยนซ็อกเก็ตที่ทำงานอยู่ให้เป็นการเชื่อมต่อที่ถูกปฏิเสธหรือหมดเวลา และข้อผิดพลาดที่ได้ดูเหมือนบั๊กในแอปพลิเคชันมากกว่านโยบายบนเครื่อง
ความเป็นเจ้าของพอร์ตคืออีกครึ่งหนึ่งของชั้นนี้BindExceptionหมายความว่าซ็อกเก็ตเปิดไม่ได้ ซึ่งเป็นความล้มเหลวที่ต่างจากการเชื่อมต่อถูกปฏิเสธ ตรวจสอบว่ามีโปรเซสอื่นถือพอร์ตอยู่แล้วหรือไม่ก่อนโทษตัวกรอง แล้วมองหากฎที่ทิ้งทราฟฟิกภายในและเพิ่มการอนุญาตที่แคบที่สุดที่ผลิตภัณฑ์รองรับ เครื่องมือสองตัวที่แย่งพอร์ตดีบักเดียวกันสร้างข้อความเหมือนการบล็อกโดยนโยบายทุกประการ และมีเพียงตัวเดียวที่แก้ได้ด้วยการเปลี่ยนไฟร์วอลล์
พอร์ตดีบักของ Chrome ล้มเหลวในตระกูลเดียวกัน เบราว์เซอร์เริ่มทำงาน ไดรเวอร์ไปไม่ถึงปลายทาง DevTools และข้อความระบุชื่อ DevTools ไม่ใช่เครือข่าย แฟล็กเริ่มทำงานเพิ่มเติมและตัวจัดการไดรเวอร์ที่ซ้ำซ้อนเปลี่ยนว่าพร็อกเซสใดเป็นเจ้าของพอร์ต จึงทำให้การลบออกดูเหมือนแก้ VPN ได้ในบางครั้ง
ซ่อมชั้นที่ล้มเหลว
ซ่อมชั้นที่ล้มเหลว ไม่ใช่อุโมงค์ ผู้ฟัง loopback ที่เข้าถึงไม่ได้ต้องแก้ไขผู้ฟังหรือพอร์ตของมัน ใบรับรองที่ไม่น่าเชื่อถือต้องติดตั้งรูทองค์กรในที่ที่รันไทม์เฉพาะนั้นมอง โดยเก็บข้อยกเว้นให้แคบ ตัวกรองที่ทิ้งทราฟฟิกภายในต้องมีกฎอนุญาตที่เฉพาะเจาะจงไม่ใช่ตัวกรองที่ถูกปิด เพราะการปิดยังเปิดทุกอย่างอื่นที่มันปกป้องไว้ด้วย
การเชื่อมต่อ VPN ใหม่ไม่ได้ทดสอบชั้นใดเลย มันเพียงรันการเปลี่ยนแปลงที่ทำให้ชั้นเหล่านั้นพังซ้ำ ซึ่งเป็นเหตุให้ความล้มเหลวสามอย่างเดิมกลับมาหลังการเชื่อมต่อใหม่ทุกครั้ง และหายไปหลังการรีบูตทุกครั้งที่ปล่อยให้ไคลเอนต์ไม่ทำงาน