RabbitMQ启用SSL后Pika握手失败问题排查求助
RabbitMQ SSL连接失败排查:SSLZeroReturnError问题
环境与问题现象
服务端通过Docker部署RabbitMQ,客户端运行在本地Conda环境使用Pika库连接。服务端启动日志显示已成功开启SSL监听器,但客户端连接时触发SSL握手失败,报错SSLZeroReturnError: TLS/SSL connection has been closed (EOF)。
服务端启动日志
test-rabbitmq-1 | 2023-01-20 08:22:01.692731+00:00 [info] <0.726.0> started TCP listener on [::]:5672 test-rabbitmq-1 | 2023-01-20 08:22:01.694836+00:00 [info] <0.746.0> started TLS (SSL) listener on [::]:7575
客户端错误日志
(rabbitmq-test) ➜ RabbitMQ-TSL ✗ python3 test.py Enter PEM pass phrase: ******** INFO:pika.adapters.utils.connection_workflow:Pika version 1.3.1 connecting to ('127.0.0.1', 7575) INFO:pika.adapters.utils.io_services_utils:Socket connected: <socket.socket fd=6, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=6, laddr=('127.0.0.1', 43142), raddr=('127.0.0.1', 7575)> ERROR:pika.adapters.utils.io_services_utils:SSL do_handshake failed: error=SSLZeroReturnError(6, 'TLS/SSL connection has been closed (EOF) (_ssl.c:997)'); <ssl.SSLSocket fd=6, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=6, laddr=('127.0.0.1', 43142), raddr=('127.0.0.1', 7575)> Traceback (most recent call last): File "/.../.local/lib/python3.10/site-packages/pika/adapters/utils/io_services_utils.py", line 636, in _do_ssl_handshake self._sock.do_handshake() File "/usr/lib/python3.10/ssl.py", line 1342, in do_handshake self._sslobj.do_handshake() ssl.SSLZeroReturnError: TLS/SSL connection has been closed (EOF) (_ssl.c:997) ERROR:pika.adapters.utils.connection_workflow:Attempt to create the streaming transport failed: SSLZeroReturnError(6, 'TLS/SSL connection has been closed (EOF) (_ssl.c:997)'); 'localhost'/(<AddressFamily.AF_INET: 2>, <SocketKind.SOCK_STREAM: 1>, 6, '', ('127.0.0.1', 7575)); ssl=True ERROR:pika.adapters.utils.connection_workflow:AMQPConnector - reporting failure: AMQPConnectorTransportSetupError: SSLZeroReturnError(6, 'TLS/SSL connection has been closed (EOF) (_ssl.c:997)') ERROR:pika.adapters.utils.connection_workflow:AMQP connection workflow failed: AMQPConnectionWorkflowFailed: 1 exceptions in all; last exception - AMQPConnectorTransportSetupError: SSLZeroReturnError(6, 'TLS/SSL connection has been closed (EOF) (_ssl.c:997)'); first exception - None. ERROR:pika.adapters.utils.connection_workflow:AMQPConnectionWorkflow - reporting failure: AMQPConnectionWorkflowFailed: 1 exceptions in all; last exception - AMQPConnectorTransportSetupError: SSLZeroReturnError(6, 'TLS/SSL connection has been closed (EOF) (_ssl.c:997)'); first exception - None ERROR:pika.adapters.blocking_connection:Connection workflow failed: AMQPConnectionWorkflowFailed: 1 exceptions in all; last exception - AMQPConnectorTransportSetupError: SSLZeroReturnError(6, 'TLS/SSL connection has been closed (EOF) (_ssl.c:997)'); first exception - None ERROR:pika.adapters.blocking_connection:Error in _create_connection(). Traceback (most recent call last): File "/.../.local/lib/python3.10/site-packages/pika/adapters/blocking_connection.py", line 451, in _create_connection raise self._reap_last_connection_workflow_error(error) File "/.../.local/lib/python3.10/site-packages/pika/adapters/utils/io_services_utils.py", line 636, in _do_ssl_handshake self._sock.do_handshake() File "/usr/lib/python3.10/ssl.py", line 1342, in do_handshake self._sslobj.do_handshake() ssl.SSLZeroReturnError: TLS/SSL connection has been closed (EOF) (_ssl.c:997) Traceback (most recent call last): File "/.../test.py", line 16, in <module> with pika.BlockingConnection(conn_params) as conn: File "/.../.local/lib/python3.10/site-packages/pika/adapters/blocking_connection.py", line 360, in __init__ self._impl = self._create_connection(parameters, _impl_class) File "/.../.local/lib/python3.10/site-packages/pika/adapters/blocking_connection.py", line 451, in _create_connection raise self._reap_last_connection_workflow_error(error) File "/.../.local/lib/python3.10/site-packages/pika/adapters/utils/io_services_utils.py", line 636, in _do_ssl_handshake self._sock.do_handshake() File "/usr/lib/python3.10/ssl.py", line 1342, in do_handshake self._sslobj.do_handshake() ssl.SSLZeroReturnError: TLS/SSL connection has been closed (EOF) (_ssl.c:997)
服务端配置
rabbitmq.conf
# Enable AMQPS listeners.ssl.default = 7575 ssl_options.cacertfile = /etc/rabbitmq/cer/ca_certificate.pem ssl_options.certfile = /etc/rabbitmq/cer/server_certificate.pem ssl_options.keyfile = /etc/rabbitmq/cer/server_key.pem ssl_options.verify = verify_peer ssl_options.fail_if_no_peer_cert = true # Enable HTTPS management.listener.port = 15671 management.listener.ssl = true management.listener.ssl_opts.cacertfile = /etc/rabbitmq/cer/ca_certificate.pem management.listener.ssl_opts.certfile = /etc/rabbitmq/cer/server_certificate.pem management.listener.ssl_opts.keyfile = /etc/rabbitmq/cer/server_key.pem
Docker Compose配置
version: '3.8' services: rabbitmq: image: rabbitmq:3-management hostname: rabbitmq-server volumes: - ./rabbitmq-config/rabbitmq-cert:/etc/rabbitmq/cer - ./rabbitmq-config/rabbitmq.conf:/etc/rabbitmq/rabbitmq.conf - ./rabbitmq/data:/var/lib/rabbitmq/mnesia/rabbit@my-rabbit - ./rabbitmq/logs:/var/log/rabbitmq/log ports: - 5672:5672 - 7575:7575 - 15672:15672
客户端代码
import logging import pika import ssl from pika.credentials import ExternalCredentials logging.basicConfig(level=logging.INFO) context = ssl.create_default_context( cafile = '/rabbitmq-config/rabbitmq-cert/ca_certificate.pem' ) context.load_cert_chain( '/rabbitmq-config/rabbitmq-cert/client_certificate.pem', '/rabbitmq-config/rabbitmq-cert/client_key.pem' ) ssl_options = pika.SSLOptions(context, "localhost") conn_params = pika.ConnectionParameters( port = 7575, ssl_options = ssl_options, credentials = ExternalCredentials() ) with pika.BlockingConnection(conn_params) as conn: ch = conn.channel() ch.queue_declare("foobar") ch.basic_publish("", "foobar", "Hello, world!") print(ch.basic_get("foobar"))
排查与解决要点
证书与权限验证
- 进入RabbitMQ容器,检查证书路径
/etc/rabbitmq/cer/下的文件是否存在,且权限允许rabbitmq用户读取(执行ls -l /etc/rabbitmq/cer/查看)。 - 确认客户端证书由服务端配置的CA签发,证书链完整,无过期或格式错误。
- 进入RabbitMQ容器,检查证书路径
强制证书验证配置
- 服务端开启了
verify_peer和fail_if_no_peer_cert=true,必须确保客户端在握手时正确发送了证书。检查客户端代码中load_cert_chain的路径是否正确,证书密码输入无误。
- 服务端开启了
主机名匹配检查
- 客户端
SSLOptions中指定的localhost必须与服务端证书的CN(通用名称)或SAN(主题备用名称)一致。如果服务端证书的CN不是localhost,需修改客户端的主机名参数或重新签发证书。
- 客户端
服务端日志调试
- 在rabbitmq.conf中添加
log.level = debug,重启容器后查看日志,获取SSL握手失败的具体原因(如证书验证失败、主机名不匹配等)。
- 在rabbitmq.conf中添加
端口与网络检查
- 在容器内执行
netstat -tulpn确认7575端口是否正常监听,同时检查本地防火墙是否未拦截该端口。
- 在容器内执行
内容的提问来源于stack exchange,提问作者carlesh
相关产品推荐
相关产品推荐

