Сообщение об ошибке
error:0A000126:SSL routines::unexpected eof while reading
Также выводится как
- SSL routines::unexpected eof while reading
CLI-утилита openssl выводит «<thread id>:error:0A000126:SSL routines::unexpected eof while reading:<source>»; curl оборачивает это в «curl: (56) OpenSSL SSL_read: … unexpected eof while reading, errno 0», Python — в «[SSL: UNEXPECTED_EOF_WHILE_READING] EOF occurred in violation of protocol».
OpenSSL 3 — SSL_R_UNEXPECTED_EOF_WHILE_READING (peer closed the TCP connection without close_notify)
Что это означает
Другая сторона закрыла TCP-соединение, не отправив перед этим оповещение TLS close_notify, пока OpenSSL ещё ждал данных (во время рукопожатия или посреди потока). OpenSSL 3 считает это ошибкой, потому что молчаливое закрытие невозможно отличить от атаки, при которой поток обрезают; OpenSSL 1.1.1 сообщал о нём только как об ошибке системного вызова.
Почему это происходит
Сервер отказал в соединении или оборвал его
частоСерверы, которые вместо отправки оповещения просто закрывают рукопожатия, которые им не подходят (неизвестный SNI, нет общей версии), либо падают или прерываются по тайм-ауту посреди ответа.
Соединение оборвал межсетевой экран, прокси или балансировщик нагрузки
частоТайм-ауты простоя, ограничения на число соединений и межсетевые экраны с фильтрацией TLS обрывают TCP-соединения без штатного завершения TLS.
Устаревший узел, который никогда не отправляет close_notify
иногдаНекоторые встроенные серверы и старые реализации закрывают сокет после каждого ответа без штатного завершения TLS; с OpenSSL 3 каждый такой ответ заканчивается этой ошибкой.
Как исправить
- 1.
Выясните, в какой момент обрывается соединение
Если ошибка появляется до того, как показан хоть один сертификат, рукопожатие отклонил сервер или сеть; если после данных — поток оборвала другая сторона или промежуточное устройство.
bash # During the handshake (no certificate printed) -> the server or network refused the connection # After data was exchanged -> the peer stopped mid-stream echo | openssl s_client -connect api.example.com:443 -servername api.example.com -state 2>&1 | grep -E 'SSL_connect|error' - 2.
Устаревшие узлы под вашим контролем: SSL_OP_IGNORE_UNEXPECTED_EOF
OpenSSL 3 может считать молчаливое закрытие обычным концом потока. Включайте этот флаг только для конкретных устаревших узлов, где усечение обнаруживает сам протокол (например, по Content-Length), потому что он отключает обнаружение усечения.
python # Only for peers you control that close without close_notify (legacy embedded servers): # OpenSSL 3 option SSL_OP_IGNORE_UNEXPECTED_EOF, exposed by Python 3.10+ as ssl.OP_IGNORE_UNEXPECTED_EOF import ssl ctx = ssl.create_default_context() ctx.options |= ssl.OP_IGNORE_UNEXPECTED_EOF # truncation is then no longer detected - 3.
Исправьте другую сторону: штатно завершайте TLS
Если отправлять close_notify перед закрытием, ошибка исчезает у всех клиентов.
text Server code: call SSL_shutdown() (or the library's close/unwrap) before closing the socket, and delimit HTTP responses with Content-Length or chunked encoding.
Связанные ошибки
curl: (56) OpenSSL SSL_read: error:0A000126:SSL routines::unexpected eof while…curl (OpenSSL 3 backend)[SSL: UNEXPECTED_EOF_WHILE_READING] EOF occurred in violation of protocolPython ssl module (OpenSSL)Client network socket disconnected before secure TLS connection was establishedNode.js tls / https / fetchGnuTLS recv error (-110): The TLS connection was non-properly terminated.git over HTTPS with libcurl-gnutls (Debian, Ubuntu)