PostgreSQLは、セキュリティを高めるためにクライアントサーバ間の通信を暗号化するSSL接続の使用を元来サポートしています。 サーバ側のSSL機能についての詳細は項17.8を参照してください。
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モードでは、証明書のcn属性はホスト名と一致させられます。 cn属性がアスタリスク(*)で始まると、それはワイルドカードとして取り扱われ、ドット(.)を除く全ての文字と一致します。 これは、証明書がサブドメインと一致しないことを意味します。 もし接続がホスト名ではなくIPアドレスを使用するのであれば、(いかなるDNS検索もせず)IPアドレスが一致させられます。
検証を可能にするには、信頼するCAの証明書は、ユーザのホームディレクトリの~/.postgresql/root.crtファイルに置かれなければ成りません。(Microsoft Windowsの場合、このファイルの名前は%APPDATA%\postgresql\root.crtです。)
~/.postgresql/root.crlファイル(Microsoft Windowsでは%APPDATA%\postgresql\root.crl)が存在する場合証明書失効リスト(CRL)の項目もまた検査されます。
ルート証明書の格納場所とCRLは接続パラメータ、sslrootcertとsslcrl、もしくは環境変数、PGSSLROOTCERTとPGSSLCRLで上書きされます。
サーバが信頼できるクライアント証明を要求する場合、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で上書きされます。
sslmodeパラメータに対する異なった値は異なったレベルの保護を異なった環境で提供します。SSLそれ自身は3つの異なる形式の攻撃に対する保護を提供します。
表 30-2. SSL攻撃
形式 | 説明 |
---|---|
盗聴 | クライアント・サーバ間のネットワークトラフィックを第三者が聴くことができれば、(ユーザ名とパスワードを含め)双方の接続情報と通過するデータを読み取ることができます。SSLはこれを防止するために暗号を使用します。 |
中間者攻撃(MITM) | データがクライアント・サーバ間で渡されている時に、第三者がそのデータを変更できれば、サーバを装うことができ、従ってたとえ暗号化されていてもデータを理解し変更することができます。第三者はそこで、この攻撃を検出不可能にする接続情報とデータをサーバに送ることができます。これを行う共通した媒介はDNS位置決めとアドレス乗っ取りを含み、それに従ってクライアントは意図したサーバではなく異なったサーバに誘導されます。同時に、このことを成し遂げるいくつかの異なった攻撃も存在します。SSLはクライアントに対しサーバを認証することで、この防止に証明書検証を行います。 |
成りすまし攻撃 | 第三者が認定されたクライアントを装うことができれば、それはアクセスしてはならないデータに簡単にアクセス可能になります。典型的にこれは心もとないパスワード管理から生じます。SSLは有効な証明書の所持者のみサーバにアクセスできることを確実にすることで、この防止策としてクライアント証明書を使用します。 |
信頼できるとされる接続に対し、これら最初の2つが接続開始前にクライアントとサーバの双方に対し設定されなければなりません。サーバのみに構成されると、クライアントはサーバが高度なセキュリティを必要とすることが判る以前に、(例えばパスワードのような)機密事項を扱う情報を結局送ることになります。libpqにおいてこれはsslmodeパラメータをverify-full、またはverify-caに設定し、そして対象を検証するためルート証明書をシステムに提供することで管理されます。これは暗号化されたweb閲覧に対するhttps URLの使用とよく似ています。
一度サーバが認証されると、クライアントは機密事項を扱うデータを送ることができます。この意味は、これまでクライアントは認証に証明書が使われているかどうかを知る必要がなく、サーバ構成においてのみこのことを指定しても安全だと言うことです。
全てのSSLオプションは暗号化の形式と鍵交換の負荷を背負っていて、性能と安全性間で決定されるべきトレードオフです。以下の表は異なるsslmode値が対象を防御するかの危険性と、安全性と負荷に対してどんなメッセージを行うのかを示したものです。
表 30-3. SSLモードの説明
sslmode | 盗聴防止 | MITM防止 | メッセージ |
---|---|---|---|
disabled | いいえ | いいえ | セキュリティはどうでもよく、暗号化の負荷を払いたくない |
allow | たぶん | いいえ | セキュリティはどうでもよいが、サーバがそれを強く要求するのであれば暗号化の負荷を払ってもよい |
prefer | たぶん | いいえ | セキュリティはどうでもよいが、サーバがそれをサポートするのであれば暗号化の負荷を払ってもよい |
require | はい | いいえ | データを暗号化して欲しい。そして負荷も受け入れる。サーバに接続する必要時に常にネットワークが確認してくれることを信用する |
verify-ca | はい | CAの規定に依存 | データを暗号化して欲しい。そして負荷も受け入れる。信頼するサーバに接続することを確認してほしい |
verify-full | はい | はい | データを暗号化して欲しい。そして負荷も受け入れる。信頼するサーバ、そしてそのサーバはこちらから指定したものに接続することを確認してほしい |
verify-caとverify-fullの差異はルートCAの規定に依存します。公共のCAが使用されるとき、verify-caはそのCAと他の誰かが成功裏に登録できているということでサーバへの接続を許可します。この場合、verify-fullが常に使用されなければなりません。私的CAが使用されるとき、または自署証明書であったとしてもverify-caは十分な防御策を提供します。
sslmodeのデフォルト値はpreferです。表で示したように、これはセキュリティの視点では意味がなく、可能であれば性能上の負荷を保証するだけです。これは後方互換性を提供するためのみにデフォルトとなっているもので、安全性確保の観点からは推奨されません。
表 30-4. 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, init 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
の方が好ましいかもしれません。