しいしせねっとEDiCube MW【300x75】 Amazon.co.jp アソシエイト

[PostgreSQL][JDBCドライバ][SSL/PKIメモ][OpenSSL]

PostgreSQL SSL設定

一覧

2.11 SSL接続

SSLはサーバの証明書とクライアントの証明書の2種類があります。

サーバの証明書を使うと、サーバの偽装対策になります。経路は暗号化されますが、接続はだれでもできます。

ただし、クライアント側でサーバの証明書を持っていないと、偽装には対処できず、暗号化の効果しかありません。

クライアントの証明書を使うと、パスワードがアタックされる心配が減ります。

クライアント証明を使わない接続を拒否しないと、これまた効果はありませんが。

これくらいのことがわかる人が対象です。

configure に --with-openssl のオプションを付けて OpenSSL? 付きでインストールされていれば、psqlコマンドやJDBCドライバからSSLで接続することができます。

注意

参考

2.11.1 鍵と証明書の作成 サーバ証明書の場合

サーバの $PG_DATA/ディレクトリ内に server.key という鍵と server.crt という証明書ファイルを置きます。作り方はOpenSSLなどで可能。これはサーバ側の鍵と証明書になります。

$ openssl genrsa -out server.key 1024
$ openssl req -new -key server.key -x509 -days 有効日数 -out server.crt
Country Name (2 letter code) [AU]:JP
State or Province Name (full name) {Some-State]: Tokyo-to 外に公開しないのなら適当でもいいです
(中略)
Common Name (eg. YOUR name) []:pg.example.com サーバの証明書は必ずPostgreSQLのサーバ名を指定する
Email Address []: 省略可
$ chmod 400 server.key
$ chmod 444 server.crt

鍵ファイルは所有者のみアクセスできるようにしておきましよう。ふつうdataディレクトリ自体が所有者しかアクセスできませんが念のため。正しいアクセス権が指定されていないと使えないかも? 証明書は利用者もその他も読み出し権限だけ付けておきましょう。これ以降で説明するファイルについても同じです。サーバ起動時に鍵の暗号化を戻す必要がないように鍵の暗号化はしていません。

ssl = true という設定を postgresql.conf かどこかの設定ファイルに。どこだったかな。コメントになっていると思います。

あとは、pg_hba.conf でアクセス方法を指定しましょう。hostssl とか。

鍵と証明書を読み込み、設定を有効にするためにサーバを起動/再起動します。

2.11.2 psqlコマンドやlibpqの場合

何も考えずに -h でサーバを指定すればつながります。SSLで暗号化はされていますが相手を確認しているわけではありません。

サーバが本物かどうか確認するためにDNS詐称などサーバの偽装に対応するにはサーバにある server.crt を ~/.postgresql/root.crt にコピーしておきます。これで、鍵と証明書が一致しない場合は接続しなくなります。root.crt はブラウザのRoot認証局(CA)の証明書と同じ役割です。他のソフトから書き換えられないようにしておきましょう。

2.11.3 Javaクライアントの場合

Javaでは信頼できない証明書を持つサーバには接続しないようになっているので、JDBCドライバでSSL接続するためには、信頼できる証明書が必要です。信頼できる証明書というのはブラウザのroot証明書とおなじで、Javaの中にroot証明書が登録されている認証局で発行された証明書です。自分で登録することもできるので、追加してみましょう。

サーバ証明書

サーバ証明書は一般的なhttpsなSSL/TLSと同じように、サーバ側の証明書です。

サーバ側で作った証明書を Java の keystore 形式にしておきます。

keytool -import -alias pgsqlserver -file server.crt -keystore cert.keystore

server.crt 証明書はJAVA_HOME/jre/lib/security だかどこかにあるkeystoreの cacertsに入れておくといろいろ楽です。初期パスワードはchangeit です。

注意: cacertsに入れるのは、信頼できる証明書だけにしてください。信頼できない、意味がわからない場合は別のファイルに分けた方が無難かもしれません。他のroot証明書経由でおなじサーバ名の証明書が発行されて…という事まで回避したければ、cacertsは使わない方がいいです。

cacerts 以外のkeystoreを使う場合にはクライアント実行時にjavaのパラメータ等で証明書の場所とパスワードを指定します。cacearts に入れた場合は不要です。

java
-Djavax.net.ssl.trustStore=cert.keystore
-Djavax.net.ssl.trustStorePassword=certpassword
net.siisise.実行クラス等

プログラム中で指定してもかまいません。方法はいろいろあります。JavaのSSL系のサンプルを探してみてください。

System.setProperty("javax.net.ssl.trustStore", 信頼できる証明書キーストアのファイル名);
System.setProperty("javax.net.ssl.trustStorePassword", バスワード);

これも上と同じことをしています。

これで、Connectionのjdbc:postgresql:~のURLに ?ssl=true を付けるとSSL接続してくれます。

Connection con = java.sql.Driver.getConnection("jdbc:postgresql://pg.example.com/dbname?ssl=true", "account" , "password");

J2EEのServletなどから接続する場合は、他の方法もあります。J2EEサーバの管理する証明書リストに証明書を追加して、いろいろすればいいはずです。[JDBCドライバ]のプロパティの指定方法等参考に。

参考

2.11.4 クライアント認証もする場合 (Java編)

keytool でクライアントサイドの鍵を作ります。

keytool -genkey -alias client1 -keystore client.keystore

などなど。aliasや中身は何でもいいです。コマンドの詳細はJavaのドキュメントを見てください。キーストアと鍵のパスワードは同じものにしておきましょう。

-keyalg RSA -validity 600 とか付けてもいいです。付けても付けなくても忘れたころにつながらなくなります。(謎

次にクライアント証明書を作ります。alias名は何でもいいようです。

keytool -export -rfc -alias client1 -flie root.crt -keystore client.keystore

できたクライアント証明書をサーバ側の$PG_DATA/root.crt に置き、サーバを再起動します。

こちらも引数に

java
-Djavax.net.ssl.keyStore=client.keystore
-Djavax.net.ssl.keyStorePassword=keystorepassword

と付加します。省略しても ~/.keystore は見てくれないと思います。

System.setProperty("javax.net.ssl.keyStore", キーストアファイル名);
System.setProperty("javax.net.ssl.keyStorePassword", パスワード);

でもいいです。keystore内に証明書が複数あっても、適当につながる証明書を選んでくれるはずです。

参考

2.11.5 psqlコマンドやlibpqのクライアント認証

サーバ証明書があればとりあえずSSL接続はできますが、クライアント認証の前提としてサーバが認証できることが必要なので。2.11.2のroot.crtの設定は必要です。

openssl でクライアント用の鍵と証明書を作ります。作り方はサーバの場合とおなじですが、鍵ファイルは気にするのなら暗号化しておいた方がいいかな。Common Name はサーバ名でなくてもかまいません。その他もサーバの場合と同様、何でもいいです。

$ openssl req -new -newkey rsa:1024 -keyout postgresql.key -x509 -days 有効日数 -out postgresql.crt

のようにすれば鍵と証明書を同時に作った上で鍵は暗号化されます。psqlコマンドで暗号化した鍵が使えたかどうだかは不明。

~/.postgresql/postgresql.key に鍵ファイル ~/.postgresql/postgresql.crt に証明書ファイルがあればいい? サーバの鍵と証明書とは別に作ります。

サーバの root.crt にpostgresql.crt の中身を追加します。正しいクライアントを認識するためのものです。追加したらサーバを再起動しておきましょう。

2.11.6 認証局CAを使う場合

試していませんが、この方法でいいはずなのでメモ。認証局を使うと、クライアントを追加する度にroot.crtを編集してサーバを再起動する必要がありません。

サーバ、クライアント共に root.crt にはCAの証明書(だけ)を置きます。

server.crt 、 postgresql.crt は、CAの鍵で署名した server.key の証明書、postgresql.key の証明書を置きます。

接続できなさそうなときはserver.crt、postgresql.crt の後ろに root.crt の中身をコピーして連鎖証明書にしておきます。

CAの鍵はPostgreSQL系ディレクトリのどこにも置いてはいけません。証明書の署名のときだけ使います。

cert.keystore に CAの証明書 (root.crt) を入れます。

client.keystore にはCAからクライアントまでの各aliasを作ります。

参考

しいしせねっとHOME][日本PostgreSQL ユーザー会]