$shibayu36->blog;

クラスター株式会社のソフトウェアエンジニアです。エンジニアリングや読書などについて書いています。

PostgreSQLのSSL接続の様子を観察する

遊びでNode.jsのprismaからherokuのPostgreSQLのDBへ接続しようとしたら、error: no pg_hba.conf entryというエラーが出て困ってしまった。ちょっと調べてみると、herokuのPostgreSQLのFreeなプランはSSL通信を自己署名証明書を使っているためエラーになってしまっているということがわかった。これについては遊びで使っていたこともあるのでNode.js, PostgreSQL error: no pg_hba.conf entry for host - Stack Overflowとかを見ながら一旦rejectUnauthorized=falseを設定することで回避した(参考)。

この件で、そもそもPostgreSQLSSL接続の様子をちょっと見てみたいなと思ったので、軽く調査したのをメモしておく。

そもそも証明書はどうなってる?

以下のコマンドで確認できる。

$ openssl s_client -starttls postgres -connect <domain>:5432 -showcerts
CONNECTED(00000005)
depth=0 CN = ip-10-0-69-188.ec2.internal
verify error:num=18:self signed certificate
verify return:1
depth=0 CN = ip-10-0-69-188.ec2.internal
verify return:1
---
Certificate chain
 0 s:CN = ip-10-0-69-188.ec2.internal
   i:CN = ip-10-0-69-188.ec2.internal
...

これをみるとherokuのFreeのPostgreSQLはEC2が提供しているself signed certificateを使っている(というかDNSを見てみると普通にEC2に接続しようとする)。このため、証明書のチェック部分でエラーとなり、接続できていなかったことがわかる。

どうやってSSL通信に変わっている?

https://www.postgresql.org/docs/current/protocol-flow.html#id-1.10.5.7.11 を見ると、クライアントからStartupMessageより前にSSLRequestを送り、サーバからSが帰ってきたらSSL通信になると書いてある。これを元にWiresharkをみてみると

4番目のパケットでSSLRequestを送っている。 f:id:shiba_yu36:20210425151950p:plain

6番目のパケットでSが返ってきている。 f:id:shiba_yu36:20210425152121p:plain

それ以降、TLSv1.3のClient Helloが送られ、SSL通信が始まっていることが分かる。