★PostgreSQLカンファレンス2024 12月6日開催/チケット販売中★
他のバージョンの文書 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9.6 | 9.5 | 9.4 | 9.3 | 9.2 | 9.1 | 9.0 | 8.4 | 8.3 | 8.2 | 8.1 | 8.0 | 7.4 | 7.3 | 7.2

34.19. SSLサポート

PostgreSQLは、TLSプロトコルを使用して、セキュリティを高めるためにクライアントサーバ間の通信を暗号化するSSL接続の使用を元来サポートしています。 サーバ側のSSL機能についての詳細は19.9を参照してください。

libpqはシステム全体に対するOpenSSL設定ファイルを読み込みます。 デフォルトでは、ファイル名はopenssl.cnfで、openssl version -dで報告されるディレクトリに格納されています。 このデフォルトはOPENSSL_CONF環境変数に希望する設定ファイル名を設定することで変更することができます。

34.19.1. サーバ証明書のクライアント検証

デフォルトではPostgreSQLはサーバ証明書の検証をまったく行いません。 これは、(例えば、DNSレコードを変更したり、もしくはサーバのIPアドレスを乗っ取ったりして)クライアントに知られずにサーバの身元をなりすませることを意味します。 なりすましを防止するには、クライアントは、トラストチェーン(chain of trust)を通じて、サーバの身元を検証できなければなりません。 トラストチェーンは、ルート(自己署名)認証局(CA)証明書をあるコンピュータに設置し、そのルート証明書によって署名されたリーフ証明書を他のコンピュータに設置することによって確立されます。 また、ルート証明書によって署名された中間証明書を使って、リーフ証明書に署名することによっても可能です。

クライアントがサーバの身元を検証するためには、ルート証明書をクライアントに設置し、そのルート証明書によって署名されたリーフ証明書をサーバに設置します。 サーバがクライアントの身元を検証するためには、ルート証明書をサーバに設置し、そのルート証明書によって署名されたリーフ証明書をクライアントに設置します。 一つ以上の中間証明書(通常リーフ証明書とともに格納されます)を使って、リーフ証明書をルート証明書につなげることもできます。

トラストチェーンがひとたび確立されれば、クライアントがサーバから送信されたリーフ証明書を検証する二つの方法があります。 パラメータsslmodeverify-caに設定されている場合、libpqはクライアントに格納されたルート証明書までの証明書連鎖を検査することで、サーバが信用に足るかを検証します。 sslmodeverify-fullに設定されていると、libpqは同時にサーバホスト名が証明書のそれと一致するかを検証します。 SSL接続はサーバ証明書が検証されない場合失敗します。 安全性に慎重を期するほとんどのサーバ環境ではverify-fullを推奨します。

verify-fullモードでは、ホスト名を証明書のサブジェクト別名(Subject Alternative Name(SAN))属性と、あるいはdNSNameタイプのサブジェクト別名がないときはコモンネーム属性とマッチさせます。 証明書の名前属性がアスタリスク(*)で始まると、それはワイルドカードとして取り扱われ、ドット(.)を除くすべての文字とマッチします。 これは、証明書がサブドメインとマッチしないことを意味します。 もし接続がホスト名ではなくIPアドレスを使用するのであれば、タイプiPAddressまたはdNSNameのSANに対してIPアドレスが照合されます(DNS検索は実行されません)。iPAddressSANが存在せず、マッチングdNSNameSANが存在しない場合、ホストIPアドレスはコモンネーム属性に対して照合されます。

注記

PostgreSQLの以前のバージョンとの後方互換性のために、ホストIPアドレスはRFC 6125とは異なる方法で検証されます。 ホストIPアドレスはDNsNameSANおよびIpAddressSANに対して常に照合され、関連するSANが存在しない場合はCommon Name属性に対して照合できます。

サーバ証明書の検証を可能にするには、1つ以上のルート証明書を、ユーザのホームディレクトリの~/.postgresql/root.crtファイルに置かなければなりません。 (Microsoft Windowsの場合、このファイルの名前は%APPDATA%\postgresql\root.crtです。) サーバより送信された証明書連鎖から、クライアントに格納されたルート証明書にリンクするために(中間証明書が)必要なら、中間証明書もそのファイルに追加する必要があります。

~/.postgresql/root.crlファイル(Microsoft Windowsでは%APPDATA%\postgresql\root.crl)が存在する場合、証明書失効リスト(CRL)の項目もまた検査されます。

ルート証明書ファイルとCRLの格納場所を接続パラメータsslrootcertsslcrl、もしくは環境変数PGSSLROOTCERTPGSSLCRLで変更することができます。 sslcrldirまたは環境変数PGSSLCRLDIRを使用して、CRLファイルを含むディレクトリを指定することもできます。

注記

より古いバージョンのPostgreSQLとの後方互換性のために、ルートCAファイルが存在する場合、sslmode=requireの動作はverify-caの場合と同じになっています。 つまり、サーバ証明書がCAに対して検証されます。 この動作に依存することは勧めません。 また証明書の検証を必要とするアプリケーションは常にverify-caまたはverify-fullを使用すべきです。

34.19.2. クライアント証明書

サーバが、クライアントのリーフ証明書を要求することによってクライアントの身元を検証しようとする場合、libpqはユーザのホームディレクトリにある~/.postgresql/postgresql.crtファイルに格納された証明書を送信します。 証明書は、サーバが信頼するルート証明書につながらなければなりません。 対応する~/.postgresql/postgresql.key秘密キーファイルも存在しなければなりません。 秘密キーファイルは他者やグループからのアクセスを許可してはいけません。 Microsoft Windowsでは、このファイルの名前はそれぞれ%APPDATA%\postgresql\postgresql.crt%APPDATA%\postgresql\postgresql.keyです。 証明書とキーファイルの格納場所はsslcertおよびsslkey接続パラメータ、またはPGSSLCERTおよびPGSSLKEY環境変数で上書きされます。

Unixシステムにおいて、秘密鍵ファイル権限はグループ、他者へのアクセスをすべて拒否しなければなりません。 これはchmod 0600~/.postgresql/postgresql.keyといったコマンドによって行います。 あるいは、このファイルをrootが所有し、グループの読み取りアクセス権(つまり0640のアクセス権)を持つこともできます。 このセットアップは、証明書と鍵ファイルがオペレーティングシステムによって管理されているインストールを対象としています。 libpqのユーザは、これらの証明書と鍵ファイルへのアクセス権を持つグループのメンバになる必要があります。 (Microsoft Windowsにおいては、%APPDATA%\postgresqlディレクトリが安全であると考えられるため、ファイルの権限の検査は行われません。)

postgresql.crt中の最初の証明書は、クライアント証明書でなければなりません。 クライアントの秘密鍵と一致していなければならないからです。 オプションで、ファイルに中間証明書を追加することができます。 そうすることによって、サーバ上に中間証明書(ssl_ca_file)の格納が不要になります。

証明書とキーはPEMまたはASN.1 DER形式です。

キーは平文テキストで、あるいは、OpenSSLで対応しているAES-128など任意のアルゴリズムを使ってパスフレーズで暗号化して、格納できます。 キーが暗号化されて格納された場合、パスフレーズはsslpassword接続オプションで供給してもよいです。 暗号化されたキーが供給されて、かつ、sslpasswordが無いか空欄の場合、TTYが利用可能であればパスワードはOpenSSLによりEnter PEM pass phrase:プロンプトで対話的に入力が要求されます。 アプリケーションはクライアント証明書のプロンプトとsslpasswordパラメータの操作を、自身のキーパスワードコールバックを供給することで置き換えできます。 PQsetSSLKeyPassHook_OpenSSLを参照してください。

証明書の作成手順については、19.9.5をご覧ください。

34.19.3. 異なるモードで提供される保護

sslmodeパラメータ値を変更することで、異なったレベルの保護を提供します。 SSLは以下の3種類の攻撃に対する保護を提供することができます。

盗聴

クライアント・サーバ間のネットワークトラフィックを第三者が監視することができれば、(ユーザ名とパスワードを含め)双方の接続情報と通過するデータを読み取ることができます。 SSLはこれを防止するために暗号を使用します。

中間者攻撃(MITM

データがクライアント・サーバ間で渡されている時に、第三者がそのデータを変更できれば、サーバを装うことができ、従ってたとえ暗号化されていてもデータを理解し変更することができます。 第三者はそこで、この攻撃を検出不可能にする接続情報とデータを元のサーバに送ることができます。 これを行う共通した媒介はDNSポイズニングとアドレス乗っ取りを含み、それに従ってクライアントは意図したサーバではなく異なったサーバに誘導されます。 同時に、このことを成し遂げるいくつかの異なった攻撃も存在します。 SSLはクライアントに対しサーバを認証することで、この防止に証明書検証を使用します。

なりすまし

第三者が認定されたクライアントを装うことができれば、それはアクセスしてはならないデータに簡単にアクセス可能になります。 典型的にこれは心もとないパスワード管理から生じます。 SSLは有効な証明書の所持者のみサーバにアクセスできることを確実にすることで、この防止策としてクライアント証明書を使用します。

SSLで信頼できるとされる接続では、SSLの使用を接続確立前にクライアントとサーバの双方において設定されなければなりません。 サーバのみに構成されると、クライアントはサーバが高度なセキュリティを必要とすることが判る以前に、(例えばパスワードのような)機密事項を扱う情報を結局送ることになります。 libpqにおいて、sslmodeパラメータをverify-fullまたはverify-caに設定し、そして対象を検証するためルート証明書をシステムに提供することで、安全な接続を確実に行うことができます。 これは暗号化されたweb閲覧に対するhttps URLの使用とよく似ています。

一度サーバが認証されると、クライアントは機密事項を扱うデータを送ることができます。 この意味は、これまでクライアントは認証に証明書が使われているかどうかを知る必要がなく、サーバ構成においてのみこのことを指定しても安全だと言うことです。

すべてのSSLオプションでは暗号化の形式と鍵交換といったオーバーヘッドがかかります。 このため性能と安全性との間で決定されるべきトレードオフがあります。 表 34.1は異なるsslmode値が防御する危険性と、安全性とオーバーヘッドに対する声明を示したものです。

表34.1 SSLモードの説明

sslmode盗聴防止MITM防止声明
disableいいえいいえセキュリティはどうでもよく、暗号化の負荷を払いたくない
allowたぶんいいえセキュリティはどうでもよいが、サーバがそれを強く要求するのであれば暗号化のオーバーヘッドを払ってもよい
preferたぶんいいえセキュリティはどうでもよいが、サーバがそれをサポートするのであれば暗号化のオーバーヘッドを払ってもよい
requireはいいいえデータを暗号化して欲しい。そしてオーバーヘッドも受け入れる。意図したサーバに常に接続することをネットワークが確実にしてくれると信用する
verify-caはいCAの方針に依存データを暗号化して欲しい。そしてオーバーヘッドも受け入れる。信頼するサーバに確実に接続したい
verify-fullはいはいデータを暗号化して欲しい。そしてオーバーヘッドも受け入れる。信頼するサーバに接続すること、そのサーバが指定したものであることを確実にしたい

verify-caverify-fullの差異はルートCAの規定に依存します。 公的なCAが使用されるとき、verify-caはそのCA他の誰かが登録したかもしれないサーバへの接続を許可します。 この場合、verify-fullが常に使用されなければなりません。 独自CAが使用されるとき、または自己署名証明書であったとしてもverify-caは十分な防御策を提供します。

sslmodeのデフォルト値はpreferです。 表で示したように、これはセキュリティの視点では意味がなく、可能であれば性能上のオーバーヘッドを保証するだけです。 これは後方互換性を提供するためのみにデフォルトとなっているもので、安全性確保の観点からは推奨されません。

34.19.4. SSLクライアントファイル使用方法

表 34.2にクライアントにおけるSSL設定に関連するファイルをまとめます。

表34.2 libpq/クライアントにおけるSSLファイルの使用方法

ファイル内容効果
~/.postgresql/postgresql.crtクライアント証明書サーバにより要求されます
~/.postgresql/postgresql.keyクライアントの秘密キー所有者により送信されるクライアント証明書を証明します。証明書の所有者が信頼できることを意味していません。
~/.postgresql/root.crt信頼できる認証局サーバ証明書が信頼できる認証局により署名されたか検査します。
~/.postgresql/root.crl認証局により失効された証明書サーバ証明書はこのリストにあってはいけません

34.19.5. SSLライブラリの初期化

使用するアプリケーションがlibssllibcryptoの両方またはいずれか一方のライブラリを初期化し、libpqSSLサポート付きで構築された場合、libssllibcryptoの両方またはいずれか一方のライブラリはアプリケーションによって初期化されたことをlibpqに伝えるためPQinitOpenSSLを呼び出さなければなりません。 これにより、libpqはこれらのライブラリを初期化しなくなります。 ただし、OpenSSLバージョン1.1.0以降を使用している場合は、重複の初期化に問題がなくなるため、これは不要です。

PQinitOpenSSL

アプリケーションがどのセキュリティライブラリを初期化するか選択することができます。

void PQinitOpenSSL(int do_ssl, int do_crypto);

do_sslが非ゼロの時、libpqは最初のデータベース接続を開始する以前にOpenSSLライブラリを初期化します。 do_cryptoが非ゼロの時、libcryptoライブラリが初期化されます。 デフォルトでは(PQinitOpenSSLが呼ばれない場合)、両方のライブラリが初期化されます。 SSLサポートがコンパイルされていない場合、この関数は存在しますが何もしません。

使用するアプリケーションがOpenSSLまたはその基礎をなすlibcryptoライブラリのいずれかを使用し、そして初期化するのであれば、最初のデータベース接続開始以前に、適切なパラメータをゼロにしてこの関数を呼び出さなければなりません。 同時に、データベース接続開始前に初期化を行ったことの確認をしてください。

PQinitSSL

アプリケーションがどのセキュリティライブラリを初期化するか選択することができます。

void PQinitSSL(int do_ssl);

この関数はPQinitOpenSSL(do_ssl, do_ssl)と等価です。 OpenSSLおよびlibcryptoの両方を初期化する、もしくは両方ともしないアプリケーションにとっては(この関数で)十分です。

PostgreSQL 8.0以降、PQinitSSLは含まれていますが、PQinitOpenSSLPostgreSQL 8.4で追加されました。 従って、旧バージョンのlibpqで動かす必要があるアプリケーションではPQinitSSLの方が好ましいかもしれません。