PostgreSQL はクライアントが VPN 上にいることを知りません。アドレスと認証情報の組で TCP 接続を受け取り、それらをどう扱うかを決めます。したがってトンネルに応じてアクセスを制御するには、三つの別々の決定を整合させたうえで、図に描いたアドレスではなくサーバーが実際に見る一つのアドレスを確認する必要があります。

統合してはならない三つの決定

サーバーがどこで待ち受けるかは一つの決定です。どのトラフィックがそのアドレスに到達できるかは二つ目で、ホストのファイアウォールとその前にあるネットワーク境界が決めます。どのデータベース識別子がどの送信元から認証できるかは三つ目で、pg_hba.conf で決めます。

それぞれ別のコンポーネントが適用し、それぞれ別のメッセージで失敗します。これらを議論で混ぜると、ファイアウォールの問題を直そうとして HBA ファイルを編集する結果になります。順序を守ってください:バインドされていないリスナーには到達できず、フィルタされたポートには接続できず、HBA ルールは接続が成立した後の挙動だけを決めます。変更が効果を生まないときは、三つの層のどれを実際に変えたのかを特定してください。

サーバーが待ち受ける場所

インターフェース名ではなく、実際にマシンへ割り当てられたアドレスにバインドします:

listen_addresses = '10.20.0.30'

データベースは独自のトンネルインターフェースを持たずに VPN ゲートウェイの背後に置かれることがあり、だからこそアドレスを指定するのが正解です。この設定の変更には完全な再起動が必要で、リロードでは足りません。

次にポート、通常は 5432 を、ホスト上とその前にあるすべての境界でフィルタします。プライベートアドレスへのバインドは公開遮断の証明にはならず、ポート転送やクラウドのアドレス対応付けが今もそのプライベートなリスナーにパケットを届け得るからです。

HBA が実際に見るアドレス

ルーテッドアクセスでは、サーバーは各クライアントの内部トンネルアドレスを見ます。送信元変換では代わりにゲートウェイの変換後アドレスを見るため、すべてのクライアントがその一つの値に潰れます。許可するプレフィックスを選ぶ前に、サーバー自身の接続証拠を通じて送信元を調べてください。

すでに TLS と SCRAM を使っている配備では、意図的に狭くしたリモートアクセスの例は次のとおりです:

hostssl appdb app_login 10.8.0.0/24 scram-sha-256
host all all 0.0.0.0/0 reject
host all all ::/0 reject

これは指定したプールから TLS 経由で一つのロールと一つのデータベースを許可し、その後で他のリモート TCP アクセスを拒否します。完全な HBA ファイルの代替ではありません:ローカル管理、レプリケーション、その他の許可されたサービスを残し、狭いルールを広い許可より前に置いてください。

変換が関わる場合、HBA は元のアドレスでクライアントを区別できません。ネットワークの受け入れを厳しく保ち、実際のデータベース認証情報を要求し、trust 認証を実在のアカウントの代わりにしないでください。

最初の一致が勝ち、フォールバックはない

PostgreSQL はファイルを上から下へ読み、接続に一致する最初のレコードを使います。そのレコードの認証が失敗しても二度目の試行はないため、以前の広い許可が後の拒否を静かに打ち消します。

この順序の規則が、注意深く書いた拒否が決して効かない最も一般的な理由です。具体的なルールを先に、広いルールを最後に置き、ファイルを集合ではなく順序として読んでください。末尾に追加したルールはポリシーではなくコメントです。ファイルが無視されていると結論づける前に、それを上へ移してリロードしてください。

HBA リファレンスは順序と、host と hostssl レコードの違いの両方を定義しており、ルールの要点が接続の暗号化必須である場合に重要です。

リロード、再起動、そして拒否された場合

HBA の変更はリロードで適用され、pg_hba_file_rules ビューは解析エラーの発見に役立ちます。このビューが示すのはファイルの現在の内容であり、稼働中のサーバーがそれを正常に読み込んだかどうかではないため、きれいな一覧は新しいルールが有効である証拠になりません。

リスナーの変更には独自の再起動が必要で、変更が効果を生まないように見えるとき、この二つの操作は混同されやすくなります。

新しいセッションで試してください:想定したアカウントを持つ承認済みクライアントは接続し、同じアカウントでも未承認の経路からは接続せず、許可されていないデータベース識別子は VPN の内側からでも失敗します。この三つの結果がネットワーク境界とデータベース認可を切り分け、それが決定を分けておくことの要点です。

関連記事