CherryPy服务器SSL握手异常,Chrome报ERR_SSL_PROTOCOL_ERROR求助
CherryPy 18.8.0 HTTPS服务器ERR_SSL_PROTOCOL_ERROR问题排查与解决
问题背景
使用Python 3.7搭配CherryPy 18.8.0搭建HTTPS服务器,监听443端口并配置Comodo SSL证书,但Chrome连接时始终返回ERR_SSL_PROTOCOL_ERROR。切换builtin和pyopenssl两种SSL模块后问题依旧。
已完成的排查步骤
- 通过
sudo lsof -i tcp:443确认服务器已正常监听443端口 - 修改
server.socket_host为::切换IPv6监听模式,问题未解决 - 实例内执行
sudo curl -v https://localhost返回error:140770FC:SSL routines:SSL23_GET_SERVER_HELLO:unknown protocol - 实例外执行
curl https://<ip_address>返回error:1404B42E:SSL routines:ST_CONNECT:tlsv1 alert protocol version - 直接执行
curl <ip_address>:443能得到预期输出,说明443端口实际提供的是HTTP服务而非HTTPS
关键发现
采用代码内cherrypy.config.update()方式配置的测试服务器可正常建立安全连接,将该配置迁移到主服务器后也能正常运行,推测问题出在配置文件的语法解析上。
解决方案
1. 修正配置文件语法错误
原配置文件中cherrypy.server.ssl_certificate_chain和cherrypy.server.ssl_private_key末尾多了逗号,这是INI配置文件的语法错误,会导致CherryPy无法正确读取这些参数。修正后的配置如下:
[global] server.socket_host = '::' server.socket_port = 443 server.thread_pool = 10 server.protocol_version = 'HTTP/1.1' cherrypy.server.ssl_module = 'builtin' #cherrypy.server.ssl_module = 'pyopenssl' cherrypy.server.ssl_certificate = '/etc/pki/tls/certs/<your_server_cert>.crt' # 替换为实际服务器证书路径 cherrypy.server.ssl_certificate_chain = '/etc/pki/tls/certs/<ip_address>.ca-bundle' cherrypy.server.ssl_private_key = '/etc/pki/tls/private/custom.key'
2. 确认证书路径正确性
ssl_certificate必须指向Comodo颁发的服务器端证书文件(通常是.crt格式),而非CA根证书集合(ca-bundle.crt)ssl_certificate_chain指向Comodo提供的中间证书链文件(即<ip_address>.ca-bundle)- 确保私钥文件
custom.key权限正确,建议设置为chmod 600 /etc/pki/tls/private/custom.key,仅root用户可读
3. 验证配置加载有效性
在服务器代码中添加配置打印逻辑,确认SSL参数被正确读取:
import cherrypy # 加载配置文件 cherrypy.config.update('/path/to/your/config.ini') # 打印SSL相关配置 print("SSL模块:", cherrypy.server.ssl_module) print("证书路径:", cherrypy.server.ssl_certificate) print("私钥路径:", cherrypy.server.ssl_private_key)
如果输出为空或与配置文件不符,说明配置文件未被正确解析。
4. 重启服务器并测试
- 执行
sudo openssl s_client -connect localhost:443验证SSL握手是否正常完成 - 用Chrome访问
https://<ip_address>确认ERR_SSL_PROTOCOL_ERROR是否消失
原因分析
CherryPy的INI配置文件对语法要求严格,多余的逗号会导致键值对解析失败,服务器无法启用SSL功能,最终在443端口提供HTTP服务,引发SSL协议错误。而代码内的config.update()使用Python字典格式,允许末尾逗号,因此能正常加载配置。
内容的提问来源于stack exchange,提问作者Ryusei
相关产品推荐
相关产品推荐

