อุโมงค์ขึ้นมา QGIS เชื่อมต่อ และการเข้าสู่ระบบล้มเหลวด้วยข้อผิดพลาดใบรับรองที่ระบุ 127.0.0.1 แทนโฮสต์ของฐานข้อมูล ก้าวต่อไปที่ชวนให้ทำคือผ่อน sslmode ซึ่งจะปิดเสียงการตรวจสอบและทิ้งการรับประกันตัวตนที่คุณต้องการตั้งแต่แรก ปัญหาจริงคือพอร์ตภายในและชื่อเซิร์ฟเวอร์ถูกเก็บไว้ในฟิลด์เดียวกัน รายการบริการของ libpq แยกสองสิ่งนี้ออกจากกัน ดังนั้นซ็อกเก็ตจึงไปยังพอร์ตที่ส่งต่อ ขณะที่ TLS ยังตรวจสอบชื่อที่พิมพ์บนใบรับรอง

ไคลเอนต์คิดว่าตัวเองกำลังเชื่อมต่อกับอะไร

ภายใต้ sslmode=verify-full libpq เปรียบเทียบใบรับรองที่เซิร์ฟเวอร์นำเสนอกับชื่อโฮสต์ที่ร้องขอ เมื่อชื่อนั้นเป็นที่อยู่ loopback การเปรียบเทียบจะล้มเหลวแม้ใบรับรองจะใช้ได้กับโฮสต์ฐานข้อมูลจริง การส่งต่อ SSH เปลี่ยนว่าซ็อกเก็ตใดขนส่งไบต์ ไม่ใช่ตัวตนที่ไคลเอนต์ควรคาดหวัง เมื่อแยกสองแนวคิดนี้ออกจากกัน ข้อผิดพลาดก็ไม่ดูเหมือนความผิดพลาดของ TLS อีกต่อไป

การส่งต่อไม่ใช่การอนุญาตเช่นกัน PostgreSQL ยังคงใช้กฎของตัวเองกับคอนเน็กชันที่เซิร์ฟเวอร์ SSH สร้างขึ้น ดังนั้นแยกชั้นการขนส่งและชั้นฐานข้อมูลออกจากกันก่อนจะเปลี่ยนอะไร

ผูกการส่งต่อกับ loopback เท่านั้น

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

ssh -N -L 127.0.0.1:15432:127.0.0.1:5432 [email protected]

ปลายทางหลังเครื่องหมายทวิภาคตัวที่สองถูกแก้ไขจากฝั่งเซิร์ฟเวอร์ SSH ดังนั้นตัวอย่างนี้จึงถือว่า PostgreSQL อยู่บนโฮสต์เดียวกับ sshd ฐานข้อมูลบนเครื่องอื่นต้องใช้ที่อยู่และสิทธิ์ของที่อยู่นั้น เริ่มเซสชันด้วย -N เพื่อไม่ให้เปิดเชลล์ใด ๆ อย่าแตะการตรวจสอบคีย์โฮสต์ และยืนยันว่าตัวรับฟังปรากฏขึ้นก่อนโทษ QGIS หากพอร์ตถูกใช้อยู่แล้ว การส่งต่อจะล้มเหลวตอนเริ่มต้น ไม่ใช่ตอนคิวรี

ใส่ชื่อและซ็อกเก็ตไว้ในรายการบริการเดียว

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

[gis-via-ssh]
host=db.geo.example
hostaddr=127.0.0.1
port=15432
dbname=gisdb
user=gis_reader
sslmode=verify-full
gssencmode=disable
sslrootcert=/path/to/approved-root.crt

ที่นี่ host รักษาตัวตนที่ใช้ในการตรวจสอบใบรับรอง ขณะที่ hostaddr ส่งแพ็กเก็ตไปยังพอร์ต loopback ที่ส่งต่อ และทั้งสองอย่างจำเป็นเพื่อให้การจัดวางนี้ทำงาน gssencmode=disable สำคัญในบิลด์ที่มิฉะนั้นจะเจรจาการเข้ารหัส GSSAPI ก่อน เพราะเส้นทางนั้นไม่สนใจการตั้งค่า TLS ที่เพิ่งกำหนด QGIS อ้างอิงบริการตามชื่อจากกล่องโต้ตอบการเชื่อมต่อ PostgreSQL และส่งรหัสผ่านผ่านพรอมป์ปกติ ไม่ใช่ในไฟล์ที่แชร์ ชื่อและเส้นทางข้างต้นเป็นตัวยึดตำแหน่ง ให้แทนที่ด้วยค่าที่ได้รับอนุมัติของคุณเอง

PostgreSQL ยังตรวจสอบอะไรอีกหลังอุโมงค์

เซิร์ฟเวอร์เห็นการเชื่อมต่อจากโฮสต์ SSH ซึ่งในที่นี้คือ loopback และจับคู่ตามลำดับกับกฎการรับรองความถูกต้องที่อิงโฮสต์ บทบาทฐานข้อมูลของคุณยังต้องรับรองความถูกต้อง และการเข้าสู่ระบบ SSH ไม่ได้ให้ตัวตนในฐานข้อมูลโดยตัวมันเอง ตรวจสอบสิ่งที่เซิร์ฟเวอร์เชื่อ ไม่ใช่สิ่งที่ไคลเอนต์สันนิษฐาน

psql "service=gis-via-ssh" -c "select inet_server_addr(), current_user"

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

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