問題の概要
SSL_ERROR_SYSCALL が表示される場合、通常は接続が予期せず切断されたことを意味します。サーバーが「信頼できない」と応答する証明書の不一致とは異なり、このエラーは暗号化ハンドシェイクが完了する前に接続が強制終了されたときに発生します。基盤となるシステムコール(通常は read() または write())が、データを期待しているときにリセット(RST)パケットまたは EOF を受信した状態です。
ターミナルには通常、次のような苛立たしい行が表示されます。
curl: (35) OpenSSL SSL_connect: SSL_ERROR_SYSCALL in connection to example.com:443
主な原因
- プロキシの干渉: 企業内プロキシが SSL プロトコルを認識できない、または届くはずの認証を待機しているために接続を遮断している可能性があります。
- ミドルボックスと DPI: 深層パケット検査(DPI)ファイアウォールは、復号化や検査ができない暗号化トラフィックをドロップすることがよくあります。
- MTU のボトルネック: VPN を使用している場合、パケットがトンネルに対して大きすぎると、サイレントドロップ(通知なしの破棄)が発生することがあります。
- IPv6 の問題:
curlが IPv6 経由でサーバーにアクセスしようとしている一方で、プロキシが IPv4 しか認識しない可能性があります。
ステップバイステップの解決策
1. IPv4 を強制する
プロキシは IPv6 アドレスでつまづくことがよくあります。curl に IPv4 を強制することは、DNS やルーティングの不一致を排除する最も手っ取り早い方法です。
curl -4 -v https://example.com
2. プロキシ環境変数の整理
環境変数の設定ミスは頻繁に起こる原因です。プロキシ文字列の http:// プレフィックスの欠落や、末尾のスラッシュがハンドシェイクを壊すことがあります。まず現在の設定を確認してください。
env | grep -i proxy
設定に誤りがある場合は、標準の形式でリセットしてください。ポート番号の後にスラッシュを追加しないように注意しましょう。
export http_proxy="http://proxy.example.com:8080"
export https_proxy="http://proxy.example.com:8080"
ローカル環境の問題を完全に回避するには、コマンドに直接プロキシを渡します。
curl -x http://proxy.example.com:8080 -v https://example.com
3. MTU (Maximum Transmission Unit) の調整
ネットワークパケットのサイズは一律ではありません。標準の Ethernet は 1500 バイトの MTU を使用しますが、VPN ヘッダー(OpenVPN や Cisco AnyConnect など)によって使用可能なスペースが減少します。パケットが制限を超えるとドロップされ、システムコールエラーがトリガーされることがよくあります。MTU を 1400 または 1300 に下げて、接続が安定するか確認してください。
# アクティブなインターフェースを確認(例: eth0, en0, wlan0)
ip link show
# 一時的に MTU を 1400 に下げる
sudo ip link set dev eth0 mtu 1400
curl コマンドを再度実行してください。これで動作すれば、ネットワークのフラグメンテーションの問題であることが確認できます。
4. TLS 1.2 へのダウングレード
レガシーなハードウェアや古い「セキュリティアプライアンス」は、TLS 1.3 で動作が不安定になることがよくあります。curl に、より互換性の高い古い TLS 1.2 を強制的に使用させることで、これらの気難しいミドルボックスを回避できる場合があります。
curl --tls-max 1.2 -v https://example.com
5. curl と OpenSSL の更新
古いバージョンの OpenSSL(1.0.2 シリーズなど)は、最新の暗号スイートをサポートしていません。curl --version でバージョンを確認してください。数年前のバージョンを使用している場合は、最新のバイナリを導入する時期です。
# Ubuntu/Debian ユーザーの場合
sudo apt update && sudo apt install curl openssl
# RHEL/CentOS ユーザーの場合
sudo yum update curl openssl
動作確認
詳細フラグ(-v)を使用してハンドシェイクを検査します。証明書の交換が完了することを確認してください。正常な接続は次のような行で終わります。
* SSL connection using TLSv1.3 / AEAD-AES256-GCM-SHA384
* ALPN, server accepted to use h2
「SSL connection using」という行が表示されれば、システムコールエラーの回避に成功しています。
ヒントと予防策
ネットワークレベルのエラーは、通常、サブネットの設定ミスや過度に厳格なファイアウォールルールに起因します。プロキシが特定のトラフィックを拒否する理由をデバッグする際、私は サブネット計算機 を使用してネットワークの境界を再確認しています。これにより、ファイアウォールで許可されている IP 範囲が、プロキシで使用されている CIDR ブロックと実際に一致していることを確認できます。
最後にもう一つのテクニックです。非常に厳しいファイアウォールの内側にいる場合は、--trace-ascii output.txt を使用してください。これにより接続の完全な 16 進ダンプが生成されます。このファイルをネットワーク管理者に渡すことで、どのパケット(多くの場合 Client Hello)がブロックされているかを正確に示すことができます。

