PostgreSQLは、セキュリティを高めるためにクライアントサーバ間の通信を暗号化するSSL接続の使用を元来サポートしています。 サーバ側のSSL機能についての詳細は17.9. SSLによる安全なTCP/IP接続を参照してください。
libpqはシステム全体に対するOpenSSL設定ファイルを読み込みます。
デフォルトでは、ファイル名はopenssl.cnf
で、openssl version -d
で報告されるディレクトリに格納されています。
このデフォルトはOPENSSL_CONF
環境変数に希望する設定ファイル名を設定することで変更することができます。
デフォルトではPostgreSQLはサーバ証明書の検証をまったく行いません。 これは、(例えば、DNSレコードを変更したり、もしくはサーバのIPアドレスを接収したりして)クライアントに知られずにサーバの属性をなりすませることを意味します。 なりすましを防止するにはSSL証明書検証を使用しなければなりません。
パラメータsslmode
がverify-ca
に設定されている場合、libpqは信頼される認証局(CA)までの証明書連鎖を検査することで、サーバが信用に足るかを検証します。
sslmode
がverify-full
に設定されていると、libpqは同時にサーバホスト名が証明書のそれと一致するかを検証します。
SSL接続はサーバ証明書が検証されない場合失敗します。
安全性に慎重を期するほとんどのサーバ環境ではverify-full
を推奨します。
verify-full
モードでは、ホスト名を証明書のサブジェクト別名(Subject Alternative Name)属性と、あるいはdNSNameタイプのサブジェクト別名がないときはコモンネーム属性とマッチさせます。
証明書の名前属性がアスタリスク(*
)で始まると、それはワイルドカードとして取り扱われ、ドット(.
)を除くすべての文字とマッチします。
これは、証明書がサブドメインとマッチしないことを意味します。
もし接続がホスト名ではなくIPアドレスを使用するのであれば、(いかなるDNS検索もせず)IPアドレスがマッチさせられます。
サーバ証明書の検証を可能にするには、1つ以上の信頼するCAの証明書を、ユーザのホームディレクトリの~/.postgresql/root.crt
ファイルに置かなければなりません。
中間CAがroot.crt
にあるのであれば、そのファイルはそのルートCAへの証明書チェーンも含まなければなりません。
(Microsoft Windowsの場合、このファイルの名前は%APPDATA%\postgresql\root.crt
です。)
~/.postgresql/root.crl
ファイル(Microsoft Windowsでは%APPDATA%\postgresql\root.crl
)が存在する場合、証明書失効リスト(CRL)の項目もまた検査されます。
ルート証明書ファイルとCRLの格納場所を接続パラメータsslrootcert
とsslcrl
、もしくは環境変数PGSSLROOTCERT
とPGSSLCRL
で変更することができます。
より古いバージョンのPostgreSQLとの後方互換性のために、ルートCAファイルが存在する場合、sslmode
=require
の動作はverify-ca
の場合と同じになっています。
つまり、サーバ証明書がCAに対して検証されます。
この動作に依存することは勧めません。
また証明書の検証を必要とするアプリケーションは常にverify-ca
またはverify-full
を使用すべきです。
サーバが信頼できるクライアント証明書を要求する場合、libpqはユーザのホームディレクトリにある~/.postgresql/postgresql.crt
ファイルに格納された証明書を送信します。
証明書はサーバで信頼された認証局(CA)のいずれかで署名されなければなりません。
対応する~/.postgresql/postgresql.key
秘密キーファイルも存在しなければなりません。
秘密キーファイルは他者やグループからのアクセスを許可してはいけません。
chmod 0600 ~/.postgresql/postgresql.key
コマンドでこれを実現してください。
Microsoft Windowsでは、このファイルの名前はそれぞれ%APPDATA%\postgresql\postgresql.crt
と%APPDATA%\postgresql\postgresql.key
であり、このディレクトリは安全であると想定されますので、特別な権限検査は行われません。
証明書とキーファイルの格納場所はsslcert
およびsslkey
接続パラメータ、またはPGSSLCERT
およびPGSSLKEY
環境変数で上書きされます。
クライアント証明書が、サーバにより直接信頼された認証局ではなく、「中間」認証局で署名されている場合があります。
こうした証明書を使用するためには、署名した認証局の証明書を、さらにその親の認証局の証明書を、サーバにより信頼される「ルート」もしくは「中間」認証局までpostgresql.crt
ファイルに追加してください。
サーバにより信頼されるとは、すなわちサーバのroot.crt
ファイルにある証明書により署名されているということです。
クライアントの~/.postgresql/root.crt
には、サーバ証明書の署名に関して信頼できるとみなされる、最上位のCAが列挙されていることに注意してください。
原理的にはクライアント証明書を署名するCAを列挙する必要はありませんが、ほとんどの場合において、そのCAは同時にサーバ証明書に対しても信頼されています。
sslmode
パラメータ値を変更することで、異なったレベルの保護を提供します。
SSLは以下の3種類の攻撃に対する保護を提供することができます。
クライアント・サーバ間のネットワークトラフィックを第三者が監視することができれば、(ユーザ名とパスワードを含め)双方の接続情報と通過するデータを読み取ることができます。 SSLはこれを防止するために暗号を使用します。
データがクライアント・サーバ間で渡されている時に、第三者がそのデータを変更できれば、サーバを装うことができ、従ってたとえ暗号化されていてもデータを理解し変更することができます。 第三者はそこで、この攻撃を検出不可能にする接続情報とデータを元のサーバに送ることができます。 これを行う共通した媒介はDNSポイズニングとアドレス乗っ取りを含み、それに従ってクライアントは意図したサーバではなく異なったサーバに誘導されます。 同時に、このことを成し遂げるいくつかの異なった攻撃も存在します。 SSLはクライアントに対しサーバを認証することで、この防止に証明書検証を使用します。
第三者が認定されたクライアントを装うことができれば、それはアクセスしてはならないデータに簡単にアクセス可能になります。 典型的にこれは心もとないパスワード管理から生じます。 SSLは有効な証明書の所持者のみサーバにアクセスできることを確実にすることで、この防止策としてクライアント証明書を使用します。
信頼できるとされる接続では、SSLの使用を接続確立前にクライアントとサーバの双方において設定されなければなりません。
サーバのみに構成されると、クライアントはサーバが高度なセキュリティを必要とすることが判る以前に、(例えばパスワードのような)機密事項を扱う情報を結局送ることになります。
libpqにおいて、sslmode
パラメータをverify-full
またはverify-ca
に設定し、そして対象を検証するためルート証明書をシステムに提供することで、安全な接続を確実に行うことができます。
これは暗号化されたweb閲覧に対するhttps
URLの使用とよく似ています。
一度サーバが認証されると、クライアントは機密事項を扱うデータを送ることができます。 この意味は、これまでクライアントは認証に証明書が使われているかどうかを知る必要がなく、サーバ構成においてのみこのことを指定しても安全だと言うことです。
すべてのSSLオプションでは暗号化の形式と鍵交換といったオーバヘッドがかかります。
このため性能と安全性との間で決定されるべきトレードオフがあります。
表31.1「SSLモードの説明」は異なるsslmode
値が防御する危険性と、安全性とオーバヘッドに対する声明を示したものです。
表31.1 SSLモードの説明
sslmode | 盗聴防止 | MITM防止 | 声明 |
---|---|---|---|
disable | いいえ | いいえ | セキュリティはどうでもよく、暗号化の負荷を払いたくない |
allow | たぶん | いいえ | セキュリティはどうでもよいが、サーバがそれを強く要求するのであれば暗号化のオーバヘッドを払ってもよい |
prefer | たぶん | いいえ | セキュリティはどうでもよいが、サーバがそれをサポートするのであれば暗号化のオーバヘッドを払ってもよい |
require | はい | いいえ | データを暗号化して欲しい。そしてオーバヘッドも受け入れる。意図したサーバに常に接続することをネットワークが確実にしてくれると信用する |
verify-ca | はい | CA の規定に依存 | データを暗号化して欲しい。そしてオーバヘッドも受け入れる。信頼するサーバに確実に接続したい |
verify-full | はい | はい | データを暗号化して欲しい。そしてオーバヘッドも受け入れる。信頼するサーバに接続すること、そのサーバが指定したものであることを確実にしたい |
verify-ca
とverify-full
の差異はルートCAの規定に依存します。
公的なCAが使用されるとき、verify-ca
はそのCAで他の誰かが登録したかもしれないサーバへの接続を許可します。
この場合、verify-full
が常に使用されなければなりません。
独自CAが使用されるとき、または自己署名証明書であったとしてもverify-ca
は十分な防御策を提供します。
sslmode
のデフォルト値はprefer
です。
表で示したように、これはセキュリティの視点では意味がなく、可能であれば性能上のオーバヘッドを保証するだけです。
これは後方互換性を提供するためのみにデフォルトとなっているもので、安全性確保の観点からは推奨されません。
表31.2「libpq/クライアントにおけるSSLファイルの使用方法」にクライアントにおけるSSL設定に関連するファイルをまとめます。
表31.2 libpq/クライアントにおけるSSLファイルの使用方法
ファイル | 内容 | 効果 |
---|---|---|
~/.postgresql/postgresql.crt | クライアント証明書 | サーバにより要求されます |
~/.postgresql/postgresql.key | クライアントの秘密キー | 所有者により送信されるクライアント証明書を証明します。証明書の所有者が信頼できることを意味していません。 |
~/.postgresql/root.crt | 信頼できる認証局 | サーバ証明書が信頼できる認証局により署名されたか検査します。 |
~/.postgresql/root.crl | 認証局により失効された証明書 | サーバ証明書はこのリストにあってはいけません |
使用するアプリケーションがlibssl
とlibcrypto
の両方またはいずれか一方のライブラリを初期化し、libpqがSSLサポート付きで構築された場合、libssl
とlibcrypto
の両方またはいずれか一方のライブラリはアプリケーションによって初期化されたことをlibpqに伝えるためPQinitOpenSSL
を呼び出さなければなりません。
これにより、libpqはこれらのライブラリを初期化しなくなります。
SSL APIの詳細はhttp://h71000.www7.hp.com/doc/83final/BA554_90007/ch04.htmlを参照してください。
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
は含まれていますが、PQinitOpenSSL
はPostgreSQL 8.4で追加されました。
従って、旧バージョンのlibpqで動かす必要があるアプリケーションではPQinitSSL
の方が好ましいかもしれません。