OpenVPN และ HTTPS บนพอร์ต 443: ใครเป็นเจ้าของผู้รับฟัง
TCP และ UDP 443 เป็นซ็อกเก็ตคนละตัว การแชร์ผู้รับฟัง TCP หนึ่งตัวต้องมีเจ้าของ และการแชร์พอร์ตของ OpenVPN เป็นข้อตกลงแคบ ๆ ไม่ใช่กลอุบายพร็อกซี
บริการสองตัวสามารถตอบบนพอร์ต 443 ได้ทั้งคู่โดยไม่ต้องแข่งขันกันเลย เพราะผู้รับฟังถูกกำหนดด้วยการขนส่ง ที่อยู่ และพอร์ตรวมกัน ไม่ใช่แค่หมายเลขอย่างเดียว วางเว็บเซิร์ฟเวอร์และ OpenVPN ไว้บนเครื่องเดียว แล้วคำถามเดียวที่ควรตอบก่อนคือแต่ละโปรเซสขอซ็อกเก็ตใดจากเคอร์เนล จดรายการนั้นไว้ก่อนแก้ไขการกำหนดค่า แล้วข้อผิดพลาด «ที่อยู่ถูกใช้อยู่แล้ว» ส่วนใหญ่จะอธิบายตัวเองได้ ทุกอย่างหลังรายการคือการเลือกระหว่างผู้รับฟัง UDP ซ็อกเก็ต TCP ที่แชร์กัน หรือส่วนหน้าที่เปลี่ยนเส้นทางตามโปรโตคอล
เริ่มจากซ็อกเก็ตที่แต่ละโปรเซสขอ
bind สำเร็จหรือล้มเหลวตามสามสิ่งนั้น สองเดมอนจึงชนกันก็ต่อเมื่อทั้งสามส่วนตรงกัน นี่คือเหตุผลที่เว็บไซต์บน TCP 443 อยู่ร่วมกับผู้รับฟัง OpenVPN บน UDP 443 ได้อย่างไม่มีกำหนด และเป็นเหตุผลที่การย้ายตัวใดตัวหนึ่งไปยังที่อยู่โลคอลที่สองบนโฮสต์เดียวกันก็จบข้อโต้แย้งเช่นกัน อ่านผู้รับฟังที่ทำงานอยู่จริง ไม่ใช่ไฟล์ที่ควรจะสร้างมันขึ้นมา เพราะ include เก่าหรือไฟล์ unit ที่ถูกลืมมีอายุยืนกว่าการแก้ไขที่คุณจำได้
| Line in the listener list | What it establishes | What to do next |
|---|---|---|
| One udp row and one tcp row, each on 443 | Separate transport sockets, nothing contested | Point the VPN profile at udp and stop editing |
| A single tcp address and port listed by two processes | A real bind collision between two daemons | Move one service, or put a dispatcher in front of both |
| A proxy process owns the socket, no vpn process | The proxy accepts and has to hand off correctly | Check that its backend speaks the protocol it forwards |
เรียก ss -lntup ในฐานะ root แล้วอ่านทุกบรรทัดที่กล่าวถึง 443 รวมถึงรายการ IPv6 โดยทั่วไปผู้รับฟัง v6 แบบไวลด์การ์ดยังรับทราฟฟิก v4 ด้วย และนั่นคือวิธีที่ผู้รับฟังที่คุณลืมยังคงยึดพอร์ตไว้หลังจากคุณเปลี่ยนไฟล์ที่คิดว่าเป็นตัวการ หากชื่อโปรเซสทำให้คุณประหลาดใจ ให้จำกัดผลลัพธ์ด้วย ss -lntup 'sport = :443' ก่อนแตะต้องสิ่งใด
เปลี่ยนอุโมงค์เป็น UDP เมื่อเครือข่ายอนุญาต
ผู้รับฟัง UDP เลี่ยงการชนกันได้ทั้งหมดและมักเป็นการซ่อมที่สั้นที่สุด เพราะไม่มีซ็อกเก็ตใดถูกแชร์และไม่มีผลิตภัณฑ์เพิ่มเติมเข้ามาในเส้นทาง แต่ก็ไม่ฟรี เครือข่ายลูกค้าบางแห่งทิ้ง UDP 443 โดยไม่ส่ง reset อุโมงค์จึงหยุดสร้างแทนที่จะล้มเหลวที่ bind และผู้ใช้รายงานว่า VPN ล่มโดยไม่มีข้อผิดพลาดให้อ่าน ผู้รับฟัง UDP ยังอยู่รอดจากการรีสตาร์ทชั้นเว็บ ซึ่งสำคัญบนเครื่องที่เว็บไซต์ถูกนำขึ้นใหม่บ่อย ทดสอบจากเครือข่ายที่ผู้ใช้อยู่ เพราะเชลล์บนเซิร์ฟเวอร์พิสูจน์เพียงว่าเซิร์ฟเวอร์เข้าถึงตัวเองได้
เปลี่ยนการขนส่งทั้งในการกำหนดค่าเซิร์ฟเวอร์และในโปรไฟล์ไคลเอนต์พร้อมกัน โปรไฟล์ที่ยังขอ TCP จะวนอยู่ในการเชื่อมต่อใหม่กับผู้รับฟังที่มีแต่ UDP และดูเหมือนเครือข่ายขัดข้องจนกว่าคุณจะเทียบไฟล์ทั้งสอง
ให้โปรเซส VPN เป็นเจ้าของ TCP 443 แล้วส่งต่อส่วนที่เหลือ
Community OpenVPN ในโหมดเซิร์ฟเวอร์ TCP อ่านไบต์แรกของการเชื่อมต่อขาเข้า แล้วส่งต่อทุกอย่างที่ไม่ใช่โปรโตคอลของตัวเองไปยังแบ็กเอนด์ HTTPS ซึ่งเป็นสิ่งที่ไดเรกทีฟ port-share มีไว้ ตัวแบ็กเอนด์คือเว็บเซิร์ฟเวอร์ธรรมดาที่เปิด TLS ระบุชื่อด้วยโฮสต์และพอร์ตในไดเรกทีฟนั้น ไม่ใช่ด้วย URL
port-share 10.0.0.5 8080
บนเครื่องที่เว็บไซต์มีที่อยู่ส่วนตัวที่สอง บรรทัดนั้นส่งทราฟฟิกที่ไม่ใช่ VPN ไปยัง 10.0.0.5:8080 ดังนั้นโฮสต์เสมือน HTTPS ต้องผูกไว้ที่นั่นและไฟร์วอลล์ต้องอนุญาตการกระโดดภายใน เว็บเซิร์ฟเวอร์ต้องยุติ TLS เอง เพราะไบต์ที่มาถึงคือแฮนด์เชกดั้งเดิมของเบราว์เซอร์และไม่มีอะไรระหว่างกลางถอดรหัสเลย ชี้ไดเรกทีฟไปที่ผู้รับฟัง HTTP ธรรมดาแล้วเบราว์เซอร์จะได้ข้อผิดพลาดวิธีไม่ถูกต้อง ซึ่งอ่านได้เหมือนเว็บไซต์พังมากกว่าแบ็กเอนด์ที่วางผิดที่ ไดเรกทีฟนี้มีเฉพาะในโหมดเซิร์ฟเวอร์ TCP และผู้รับฟัง UDP ไม่มีสตรีมให้ตรวจ
เพราะโปรเซส VPN รับทุกการเชื่อมต่อ แอปพลิเคชันเว็บจึงเห็นคำขอที่ส่งต่อมาจากที่อยู่ของโฮสต์เองแห่งใดแห่งหนึ่ง ไม่ใช่จากผู้เยี่ยมชม ทุกอย่างที่ต้องการที่อยู่ไคลเอนต์จริงขึ้นอยู่กับการรองรับโปรโตคอล PROXY ในแบ็กเอนด์หรือส่วนหน้าที่เพิ่มเข้าไป การย้ายแบ็กเอนด์ไปยังที่อยู่โลคอลอื่นไม่ได้นำที่อยู่ผู้เยี่ยมชมกลับมา แต่เปลี่ยนเพียงว่าที่อยู่ใดของโฮสต์ที่เว็บไซต์บันทึก จดข้อจำกัดนั้นไว้ในบันทึกการติดตั้งก่อนรายงานวิเคราะห์จะตั้งคำถาม
พร็อกซีย้อนกลับเป็นเครื่องมือผิด ส่วนเราเตอร์เลเยอร์สี่ไม่ใช่
พร็อกซีย้อนกลับ HTTP ยุติ TLS เพื่ออ่านคำขอ ซึ่งหมายความว่ามันส่งผ่านสตรีม OpenVPN ไปโดยไม่แตะต้องไม่ได้ เราเตอร์เลเยอร์สี่ที่ส่งต่อตาม SNI หรือตามการตรวจแพ็กเก็ตแรกสามารถยืนอยู่หน้าได้ทั้งคู่ ตราบใดที่มันไม่ยุติเซสชันที่ VPN พึ่งพา อุปกรณ์สองตัวดูคล้ายกันในแผนภาพและทำงานต่างกันอย่างสิ้นเชิงที่ซ็อกเก็ต
Access Server เชิงพาณิชย์มาพร้อมการตั้งค่าการแชร์พอร์ตของตัวเอง และการตั้งค่าเหล่านั้นไม่ได้แมปหนึ่งต่อหนึ่งกับไดเรกทีฟของชุมชน ระบุผลิตภัณฑ์และเวอร์ชันก่อนดัดแปลงคู่มือที่เขียนไว้สำหรับอีกตัว การตั้งค่าที่คัดลอกมาแล้วถูกละเลยอย่างเงียบ ๆ แย่กว่าไม่มีการตั้งค่า เพราะรายการผู้รับฟังยังดูสมเหตุสมผลอยู่หลังจากนั้น
ทดสอบเว็บไซต์และอุโมงค์เป็นสองเส้นทางแยกกัน
โหลดเว็บไซต์และเชื่อมต่ออุโมงค์ แล้วอ่านรายการผู้รับฟังอีกครั้งเพื่อดูว่าโปรเซสใดเป็นเจ้าของ 443 ตอนนี้ หน้าที่โหลดได้ไม่ได้พิสูจน์อะไรเกี่ยวกับ VPN และอุโมงค์ที่เชื่อมต่อได้ก็ไม่ได้พิสูจน์อะไรเกี่ยวกับเว็บไซต์ แม้ทั้งคู่จะใช้หมายเลขเดียวกัน สามคำสั่งด้านล่างตรวจซ็อกเก็ตที่แชร์กัน เส้นทางเว็บ และบริการ VPN ตามลำดับนั้น
ss -lntup 'sport = :443' curl -sI https://vpn.example.com/ | head -n 1 journalctl -u openvpn-server@server -n 20
เทียบที่อยู่ไคลเอนต์ในบันทึกการเข้าถึงของแบ็กเอนด์กับที่อยู่ในบันทึก VPN ในช่วงเวลาเดียวกัน หากเว็บไซต์บันทึกผู้เยี่ยมชมทุกรายเป็นโฮสต์เอง การส่งต่อทำงานแต่การจัดการที่อยู่ไม่ทำงาน หากบันทึกทั้งสองเงียบ แสดงว่าส่วนหน้าไม่เคยส่งมอบการเชื่อมต่อ ไม่ว่าจะทางใด รายการผู้รับฟังเป็นตัวตัดสินว่าใครรับซ็อกเก็ต และนั่นคือข้อเท็จจริงที่ต้องยืนยันก่อนเปลี่ยนไฟล์อื่น
วางแผนที่ผู้รับฟังนั้นไว้ข้างการกำหนดค่า เพื่อให้คนถัดไปที่แตะ 443 รู้ว่าโปรเซสใดรับและโปรโตคอลอีกตัวไปที่ใด ยืนยันความเป็นเจ้าของหลังการเปลี่ยนแปลงแทนที่จะเชื่อว่าการแก้ไขตั้งใจจะทำอะไร