Erlang の HTTP/2 ライブラリで mTLS を利用して失敗するとクラッシュしていた問題を報告して解決して貰った話
まとめ
Erlang でかかれた HTTP クライアントライブラリ Gun で、HTTP/2 で mTLS を利用した際にサーバー側で証明書の Verify に失敗した際、Bad Certificate アラートが飛ぶ。Gun 側は証明書が失敗したかどうかは気にせず、 HTTP/2 利用の ALPN のためのネゴシエーションが走っている。そのタイミングではアラートが来ても Gun 側(正しくは Erlang の ssl ライブラリ) は気づけない。
ALPN 用にネゴシエーションを行おうとするため ssl ライブラリを呼ぶが、すでに Bad Certificate アラートが送られてきているため ssl 接続は終了しており {error, closed}
が返ってきてしまう。
そもそも Erlang/OTP の ssl ドキュメントにはそのタイミングで {error, closed}
が返ってくるとは書いていなかったため、Gun 側ではエラーハンドリングをしていなかった。
これはドキュメントを修正する Erlang/OTP への pull-request
ssl:negotiated_protocol can return {error,closed} by essen · Pull Request #7279 · erlang/otp
ハンドシェイクのタイミングでクラッシュすれば良いが、これはアラートとのレースになるので、ハンドシェイクの後にアラートが飛んでくることもある。そのときはネゴシエーションのために ssl ライブラリ経由で send したタイミングで {error, closed}
が返ってきてしまい、クラッシュする。
問題が2つ絡み合っためんどくさい問題だった。Gun の作者がとても丁寧に、素早く対応してくれた。本当に感謝。