터널이 올라오고 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"

작업이 끝나면 포워딩 세션을 닫으세요. 그러면 로컬 항목이 작동을 멈추고 다른 것은 아무것도 바뀌지 않습니다.데이터베이스로 가는 한 경로는 전체 GIS 클라이언트를 위한 VPN이 아닙니다. 그것을 VPN으로 취급하는 것이 바로 다음 연결이 잘못 진단되는 이유입니다.

관련 글