使用TLS 1.2及以下版本时OpenSSL握手后卡住问题求助
结合你描述的现象(Yocto构建系统上TLS1.2握手卡住,TLS1.3正常,甚至无法用CTRL+C终止进程),以及提供的调试日志,我整理了几个核心排查方向和具体操作步骤:
1. 加密套件协商不兼容
TLS 1.2依赖客户端与服务器协商双方都支持的加密套件,而TLS 1.3的套件列表是标准化的,不容易出现不兼容问题。你的系统默认的TLS1.2套件可能和目标服务器(比如files.pythonhosted.org背后的Fastly服务)不匹配,导致握手卡在密钥交换阶段。
排查操作:
- 先查看当前OpenSSL支持的TLS1.2套件:
openssl ciphers -v 'TLSv1.2' - 尝试强制指定服务器大概率支持的套件,比如ECDHE系列:
# 用curl测试 curl -vvv --tlsv1.2 --tls-max 1.2 --ciphers ECDHE-RSA-AES256-GCM-SHA384 --ipv4 https://google.com:443 # 用openssl测试 openssl s_client -connect files.pythonhosted.org:443 -tls1_2 -cipher ECDHE-RSA-AES256-GCM-SHA384 -showcerts
如果指定套件后能完成握手,就说明是默认套件列表的问题,需要调整OpenSSL配置文件(/etc/ssl/openssl.cnf)中的CipherString参数。
2. Yocto构建时的组件裁剪问题
Yocto在构建系统时经常会裁剪不必要的功能,可能你的OpenSSL或curl配方中禁用了TLS1.2相关的关键组件,比如ECDHE密钥交换支持、某些加密算法库(如libcrypto的部分模块)。从调试日志看,服务器已经发送了密钥交换消息,但客户端没有回应,大概率是客户端无法处理这些参数。
排查操作:
- 检查OpenSSL的构建配置:
看输出中是否有openssl version -aENABLE_TLS1_2相关的启用标记,或者有没有禁用ECDHE的选项。 - 查看Yocto中OpenSSL的配方文件(比如
recipes-connectivity/openssl/openssl_*.bb),确认是否有类似EXTRA_OECONF += "no-ecdhe"这样的禁用配置,如果有,去掉后重新构建系统。 - 同样检查curl的配方,确认它链接的是完整的OpenSSL库,而不是裁剪后的版本。
3. 系统熵池不足导致阻塞
TLS握手需要生成随机密钥,OpenSSL默认可能使用/dev/random作为随机数源,当系统熵池不足时,进程会阻塞等待足够的随机数据。TLS1.3可能使用了更高效的随机数生成机制,或者你的系统中TLS1.3配置使用了/dev/urandom(非阻塞源),所以没有这个问题。
排查操作:
- 查看当前熵池可用量:
如果数值低于1000,说明熵不足。cat /proc/sys/kernel/random/entropy_avail - 临时解决:安装
rng-tools(Yocto中有对应的配方),它可以利用硬件随机数生成器或者其他方式补充熵池:# 启动rngd服务 rngd -r /dev/urandom - 永久解决:修改OpenSSL配置文件,将随机数源改为
/dev/urandom:
在/etc/ssl/openssl.cnf中添加或修改:RANDFILE = /dev/urandom
4. 内核网络栈异常
某些定制的Yocto内核可能对TLS1.2握手的数据包处理有问题,比如TCP窗口大小设置不合理、MTU过大导致分片失败,或者缺少必要的网络模块。进程无法被CTRL+C终止,说明可能在内核态阻塞了。
排查操作:
- 抓包分析握手流程:
运行卡住的openssl命令,等待10秒后停止tcpdump,用Wireshark打开抓包文件,查看:tcpdump -w tls12_handshake.pcap -i any host files.pythonhosted.org and port 443- 客户端是否发送了
Client Key Exchange和Finished消息? - 服务器是否回应了这些消息?
如果客户端根本没发这些消息,说明问题在用户态的OpenSSL/curl;如果发了但没收到回应,再排查网络路由或防火墙(但TLS1.3正常的话这个可能性较低)。
- 客户端是否发送了
- 尝试调整MTU值:
再测试TLS1.2连接。ifconfig eth0 mtu 1400 # 替换成你的网卡名
总结
结合你的场景,最可能的原因是Yocto构建时裁剪了TLS1.2的关键组件,或者加密套件不兼容。建议先从指定加密套件测试入手,再检查OpenSSL的构建配置,最后用抓包确认具体的握手阻塞点。
内容的提问来源于stack exchange,提问作者Abagnale

