QGIS PostGIS の SSH トンネル:TLS のためにサーバー名を保つ
SSH 転送は QGIS にローカルポートを与えますが、データベースは TLS のために本来の名前を依然として必要とします。hostaddr とループバックリスナーを備えた libpq サービスを使ってください。
トンネルは上がり、QGIS も接続しますが、ログインはデータベースホストではなく 127.0.0.1 を名指す証明書エラーで落ちます。次に試したくなるのは sslmode を緩めることですが、それは検査を黙らせ、そもそも欲しかった身元の保証を捨ててしまいます。本当の問題は、ローカルポートとサーバー名が同じフィールドに保存されていることです。libpq のサービス項目はその二つを分けるので、ソケットは転送されたポートへ向かい、TLS は証明書に印刷された名前を検証し続けます。
クライアントが何に接続しているつもりなのか
sslmode=verify-full では、libpq はサーバーが提示した証明書を、要求されたホスト名と比較します。その名前がループバックアドレスだと、証明書が実際のデータベースホストに対して有効であっても比較は失敗します。SSH 転送が変えるのはどのソケットがバイトを運ぶかであり、クライアントが期待すべき身元ではありません。この二つの考えを切り離せば、エラーは TLS の不具合には見えなくなります。
転送は認可でもありません。PostgreSQL は SSH サーバーが作る接続に自前の規則を適用し続けるので、何かを変える前にトランスポート層とデータベース層を分けておいてください。
転送はループバックにだけ束縛する
リスナーは 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 はパケットを転送されたループバックポートへ送ります。この構成が機能するには両方が必要です。gssencmode=disable は、そうしなければ先に GSSAPI 暗号化を交渉するビルドで重要です。その経路は今設定した TLS の設定を無視するからです。QGIS の PostgreSQL 接続ダイアログからサービスを名前で参照し、パスワードは共有ファイルの中ではなく通常のプロンプトで渡してください。上の名前とパスはプレースホルダーです。承認済みの値に置き換えてください。
トンネルの後も PostgreSQL が確認すること
サーバーには SSH ホストから、この構成ではループバックからの接続が見え、ホストベースの認証規則と順に照合されます。データベースのロールは依然として認証が必要で、SSH ログインだけではデータベースの身元は得られません。クライアントが想定したことではなく、サーバーが何を信じているかを確認してください。
psql "service=gis-via-ssh" -c "select inet_server_addr(), current_user"作業が終わったら転送セッションを閉じてください。ローカルの項目はそれ以降機能しなくなり、ほかの何も変わりません。データベースへの一つの経路は GIS クライアント全体の VPN ではありません。それを VPN として扱うからこそ、次の接続が誤診されるのです。