Rubyで外部のAPIにSSLで接続したらエラーが出た。
Faraday::SSLError: SSL_connect returned=1 errno=0 state=error: wrong signature type
このエラーの対処法についてまとめ
結論
OpenSSLの設定ファイル /etc/ssl/openssl.cnf
のセキュリティレベルを以下のように変える。
[system_default_sect]
MinProtocol = TLSv1.2
CipherString = DEFAULT@SECLEVEL=1
< CipherString = DEFAULT@SECLEVEL=2
---
> CipherString = DEFAULT@SECLEVEL=1
発生している環境
ruby:2.6.6のコンテナイメージ。
OSはDebianなのでDebian系のコンテナだと同じ現象が発生する可能性がある。
コンテナで確認したらDebian10.4だった。
# cat /etc/debian_version
10.4
ruby:2.6.6のDockerfileのFROMをたどっていくとdebian:busterにたどり着くことからもDebian10.4であることがわかる。
原因
OpenSSLを使って暗号化通信(SSL,TLS)を外部と行うとき、Debianではデフォルトでより安全な設定が行われている。
このとき証明書の署名ではSHA-1はサポートされなくなり、少なくともSHA-256が必要となる。
相手側が少なくともTLS1.2以降をサポートしていない場合にエラーが発生する。
https://wiki.debian.org/ContinuousIntegration/TriagingTips/openssl-1.1.1
公式のWikiにも記載がある。
Dockerfileで自動で編集する方法
sed
コマンドを使って設定ファイルを編集できます。
FROM ruby:2.6.6
RUN sed -i 's/DEFAULT@SECLEVEL=2/DEFAULT@SECLEVEL=1/' /etc/ssl/openssl.cnf
注意したいこと
同じようなエラーで、
OpenSSL::SSL::SSLError SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed
というものがあり、エラーメッセージで検索すると、これの検索結果も混じってくるので注意したいところ。
証明書を http://curl.haxx.se/ca/cacert.pem
からダウンロードして設置、みたいなことはやっても関係ない。