エラーメッセージ
[SSL: UNEXPECTED_EOF_WHILE_READING] EOF occurred in violation of protocol
別の表記
- ssl.SSLEOFError: EOF occurred in violation of protocol
OpenSSL 3 では、Python は理由コード「[SSL: UNEXPECTED_EOF_WHILE_READING]」を表示します。OpenSSL 1.1.1 では、テキストは「EOF occurred in violation of protocol」だけです。その後に「(_ssl.c:1082)」のようなソースの位置が続きます。
Python ssl module (OpenSSL) — ssl.SSLEOFError, SSL_R_UNEXPECTED_EOF_WHILE_READING
このエラーの意味
Python がまだ TLS ハンドシェイク中(またはデータの読み取り中)に、相手側が TLS アラートも close_notify も送信せずに TCP 接続を閉じました。OpenSSL は、この通知なしの切断をプロトコル違反として扱います。Python には相手が切断した理由はわかりません。原因はサーバー、プロキシ、または途中にあるファイアウォールにあります。
発生する理由
サーバーが受け入れないハンドシェイクを切断している
よくある一部のサーバーやロードバランサーは、ClientHello に SNI がない場合、受け入れ可能なバージョンや暗号スイートが提示されていない場合、または名前が設定されていない場合に、アラートを送信する代わりに接続を閉じます。
プロキシ、ファイアウォール、VPN が接続を切断している
よくあるプロキシの設定の誤り(HTTPS_PROXY が TLS プロキシのポートを指している、社内ホストに対する NO_PROXY がない)、宛先をブロックするディープパケットインスペクション、VPN クライアントは、多くの場合、通知なしで TCP 接続を終了させます。
レート制限やボット対策
ときどき負荷がかかっている API や CDN、Python の TLS フィンガープリントを嫌うボット対策システムは、HTTP エラーを返す代わりに接続をリセットすることがあります。
サーバーがレスポンスの途中で接続を閉じた
ときどきレスポンスの読み取り中にこのエラーが発生した場合は、サーバーまたはプロキシが close_notify を送信せずに接続を終了しています。たとえば、タイムアウトの後やワーカーのクラッシュ後に起こります。
修正方法
- 1.
openssl s_client でハンドシェイクを再現する
s_client でも切断される場合は、SNI と TLS のバージョンを変えて、サーバーが何を拒否しているかを確認してください。s_client で成功する場合は、その設定を Python クライアントの設定(プロキシ、SNI、バージョン)と比較してください。
bash # Does a plain OpenSSL handshake work from the same machine? openssl s_client -connect api.example.com:443 -servername api.example.com -brief </dev/null # Without SNI, and pinned to TLS 1.2, to see what the server objects to openssl s_client -connect api.example.com:443 -noservername -brief </dev/null openssl s_client -connect api.example.com:443 -servername api.example.com -tls1_2 -brief </dev/null - 2.
プロキシの環境変数を確認する
requests、urllib、pip は HTTPS_PROXY と NO_PROXY に従います。プロキシ URL のスキームを修正し、直接接続しなければならない社内ホストを除外してください。
bash env | grep -i -E '^(https?|no|all)_proxy=' # Proxy URLs should normally be http:// (CONNECT tunnel), and internal hosts listed in NO_PROXY export HTTPS_PROXY=http://proxy.example.net:3128 export NO_PROXY=localhost,127.0.0.1,.internal.example.com - 3.
原因が一時的な場合はリトライする
レート制限や不安定なネットワークに対しては、バックオフ付きのリトライによって、散発的なリセットを、時間はかかっても成功に変えられます。ただし、常にハンドシェイクを拒否するサーバーは、リトライでは解決しません。
python import requests from requests.adapters import HTTPAdapter from urllib3.util.retry import Retry session = requests.Session() session.mount("https://", HTTPAdapter(max_retries=Retry(total=3, backoff_factor=1))) session.get("https://api.example.com/")
関連するエラー
[SSL: WRONG_VERSION_NUMBER] wrong version numberPython ssl module (OpenSSL)curl: (56) OpenSSL SSL_read: error:0A000126:SSL routines::unexpected eof while…curl (OpenSSL 3 backend)error:0A000126:SSL routines::unexpected eof while readingOpenSSL 3Client network socket disconnected before secure TLS connection was establishedNode.js tls / https / fetch