遊びで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を設定することで回避した(参考)。
この件で、そもそもPostgreSQLのSSL接続の様子をちょっと見てみたいなと思ったので、軽く調査したのをメモしておく。
そもそも証明書はどうなってる?
以下のコマンドで確認できる。
$ 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を送っている。
6番目のパケットでSが返ってきている。
それ以降、TLSv1.3のClient Helloが送られ、SSL通信が始まっていることが分かる。