TL;DR
curlコマンドの標準出力のエラー事由はあてにしないほうがいい。
起きた事象
外部システムとのhttpsでのシステム連携前に疎通確認を実施したところ、以下のエラーでtlsハンドシェイクがエラー(ssl alert)で通信が行えなかった。
> curl --tlsv1.2 --cert xxx.pem --key xxxx.key https://example.com -x http://〇〇.〇〇.〇〇:8080 -X POST -H "Content-Type: text/plain; charset=shift-jis" -vv
~~~~中略~~~~
* error:14094410:SSL routines:ssl3_read_bytes:sslv3 alert handshake failure
* Closing connection 0
curl: (35) error:14094410:SSL routines:ssl3_read_bytes:sslv3 alert handshake failure
>
sslv3 ? tls1.2のはずだが・・・
調査
1、curlのバージョン
curl --version
curl 7.61.1 (x86_64-redhat-linux-gnu) libcurl/7.61.1 OpenSSL/1.1.1k zlib/1.2.11 brotli/1.0.6 libidn2/2.2.0 libpsl/0.20.2 (+libidn2/2.2.0) libssh/0.9.6/openssl/zlib nghttp2/1.33.0
Release-Date: 2018-09-05
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtsp scp sftp smb smbs smtp smtps telnet tftp
Features: AsynchDNS IDN IPv6 Largefile GSS-API Kerberos SPNEGO NTLM NTLM_WB SSL libz brotli TLS-SRP HTTP2 UnixSockets HTTPS-proxy PSL
→1.1.1kでTLS1.3まで対応してる。
2、実際の通信
→tls1.2で通信していた、curlのオプションが効いていると思われる。
3、実際の通信
→Alert Messageは'handshake_failure(40)'
handshake_failure
Reception of a handshake_failure alert message indicates that the
sender was unable to negotiate an acceptable set of security
parameters given the options available. This is a fatal error.
クライアント側の暗号スイーツや証明書がおかしいじゃい!って言ってブチっと落とされている。なぜsslv3って言ってくるのだろう。。。
結論
クライアント認証のpem内部に中間証明書が入ってないだけだった。
(正常に取引できていた時のdumpを偶然に発見し比較して気づきました。)
NGパターン
>cat xxx.pem
-----BEGIN CERTIFICATE-----
XXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-----END CERTIFICATE-----
OKパターン
>cat xxx.pem
-----BEGIN CERTIFICATE-----
XXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇
〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇
-----END CERTIFICATE-----
参考