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

เริ่มจากซ็อกเก็ตที่แต่ละโปรเซสขอ

bind สำเร็จหรือล้มเหลวตามสามสิ่งนั้น สองเดมอนจึงชนกันก็ต่อเมื่อทั้งสามส่วนตรงกัน นี่คือเหตุผลที่เว็บไซต์บน TCP 443 อยู่ร่วมกับผู้รับฟัง OpenVPN บน UDP 443 ได้อย่างไม่มีกำหนด และเป็นเหตุผลที่การย้ายตัวใดตัวหนึ่งไปยังที่อยู่โลคอลที่สองบนโฮสต์เดียวกันก็จบข้อโต้แย้งเช่นกัน อ่านผู้รับฟังที่ทำงานอยู่จริง ไม่ใช่ไฟล์ที่ควรจะสร้างมันขึ้นมา เพราะ include เก่าหรือไฟล์ unit ที่ถูกลืมมีอายุยืนกว่าการแก้ไขที่คุณจำได้

Line in the listener listWhat it establishesWhat to do next
One udp row and one tcp row, each on 443Separate transport sockets, nothing contestedPoint the VPN profile at udp and stop editing
A single tcp address and port listed by two processesA real bind collision between two daemonsMove one service, or put a dispatcher in front of both
A proxy process owns the socket, no vpn processThe proxy accepts and has to hand off correctlyCheck 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 รู้ว่าโปรเซสใดรับและโปรโตคอลอีกตัวไปที่ใด ยืนยันความเป็นเจ้าของหลังการเปลี่ยนแปลงแทนที่จะเชื่อว่าการแก้ไขตั้งใจจะทำอะไร

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