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

ดูคำขอที่แอปส่งจริง

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

env | grep -i proxy            # Linux/macOS
netsh winhttp show proxy       # Windows, machine-wide
curl -sv --noproxy '*' https://svc.internal/
nc -vz svc.internal 8080

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

แอปสืบทอดพร็อกซีที่ไม่มีใครตั้งค่า

สแตก HTTP ส่วนใหญ่อ่านการตั้งค่าพร็อกซีจากระบบปฏิบัติการโดยปริยาย ไคลเอนต์ VPN องค์กรมักติดตั้งพร็อกซีเป็นส่วนหนึ่งของโปรไฟล์การเข้าถึง คำขอจึงออกผ่านพร็อกซีที่นักพัฒนาไม่เคยเอ่ยถึงในโค้ด ใน .NET ตัวจัดการเริ่มต้นดึงจากการตั้งค่า IE/WinHTTP; Java อ่าน -Dhttp.proxyHost; Node ไม่มีการรองรับพร็อกซีในตัวจนกว่าจะมีไลบรารีเพิ่มเข้ามา ความล้มเหลวมักไม่ใช่การปฏิเสธสะอาด ๆ คนจึงเริ่มมองที่เซิร์ฟเวอร์

การทดสอบมีต้นทุนหนึ่งคำขอ: ปิดพร็อกซีอย่างชัดเจนบนตัวจัดการเดียวแล้วเปรียบเทียบ

var handler = new HttpClientHandler { UseProxy = false };
using var client = new HttpClient(handler);

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

พอร์ตที่คุณเลือกไม่ใช่พอร์ตที่นโยบายอนุญาต

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

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

TCP ดิบที่เส้นทางรีเซ็ต

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

สลับทรานสปอร์ต ทดสอบซ้ำ และอย่าเปลี่ยนอย่างอื่นในการรันเดียวกัน การทดสอบตัวแปรเดียวนี้บอกว่าการรีเซ็ตมาจากเส้นทางหรือจากบริการ

การเชื่อมต่อที่ปิดเฉพาะเมื่อเพย์โหลดใหญ่

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

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

แยกสี่อย่างในรอบเดียวได้อย่างไร

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

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

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