<p>卡在 * TLS handshake 表明 DNS 和 TCP 已通,但 TLS 握手失败或卡死,根本原因是系统时间偏差、证书链不全、OpenSSL 版本过旧(如不支持 TLS 1.3)、IPv6 不兼容或企业中间人代理拦截,调高 http.timeout 无效,需校准时间、同步 curl.cainfo 与 openssl.cafile 绝对路径、强制 IPv4 或 TLS 1.2 并重启 PHP 服务。</p>

卡在 * TLS handshake 是什么信号
看到 curl -v https://mirrors.aliyun.com/composer/packages.json 停在 * TLS handshake 这一行,说明 DNS 已解析、TCP 连接已建立,但 TLS 握手失败或卡死。这不是超时配置能解决的,http.timeout 再大也无效——它只管“从开始到收到响应头”的总时间,而 TLS 卡住时连 HTTP 请求都没发出去。
- 常见诱因:WSL2 系统时间不同步(
date显示明显偏差)、企业中间人代理未导入根证书、镜像站 TLS 版本不兼容(如只支持 TLS 1.3 而本地 OpenSSL 太旧) - 错误日志典型特征:
error:14090086:SSL routines:ssl3_get_server_hello:certificate verify failed或直接 hang 无报错 - 验证方式:用
openssl s_client -connect mirrors.aliyun.com:443 -servername mirrors.aliyun.com看是否卡在CONNECTED(00000003)后无后续
怎么绕过 TLS 验证(仅限可信内网)
生产环境严禁禁用证书校验,但在开发机、CI 内网或调试阶段,可临时跳过验证快速定位是否为证书链问题。
- 全局禁用(不推荐):
composer config -g cafile /dev/null(Linux/macOS)或composer config -g cafile NUL(Windows) - 临时生效(推荐):
COMPOSER_CAFILE= /path/to/your/cert.pem composer install—— 若你有内部 CA 证书,显式指定比禁用更安全 - PHP 层级绕过(应急):
php -d openssl.cafile=/dev/null $(which composer) install,注意这会影响所有 PHP SSL 操作 - 注意:
http-basic和process-timeout对此完全无作用
调高 TLS 握手容忍时间?不行,但可以换底层行为
cURL 和 PHP stream 层没有独立控制 TLS 握手超时的参数,http.timeout 包含它,但无法单独拆分。真正有效的干预点是降低协商强度或强制协议版本。
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
- 强制 TLS 1.2(兼容性更强):
export COMPOSER_TLS_VERSION=1.2,再运行composer install - 禁用 IPv6(国内镜像常对 IPv6 支持不全):
COMPOSER_IPV4=1 composer install - 升级 OpenSSL 或 PHP(若
php -v显示 OpenSSL < 1.1.1,TLS 1.3 支持不稳定,升级到 PHP 8.1+ 更稳妥) - 不要设
http.timeout到 3600——它只会让卡在握手的时间更长,掩盖真实问题
为什么改了 timeout 还是卡住?检查 default_socket_timeout
即使你设了 http.timeout 600,PHP CLI 的 default_socket_timeout 仍可能提前掐断连接。这个 ini 值默认是 60 秒,且优先级高于 Composer 配置。
- 查当前值:
php -i | grep default_socket_timeout - 临时覆盖:
php -d default_socket_timeout=600 $(which composer) install - 永久修改需改
php.ini中的default_socket_timeout = 600,但注意这会影响所有 CLI 下的 socket 操作 - CI 环境尤其容易踩坑:容器启动时未重载 php.ini,导致
composer config -g http.timeout看似生效,实则被底层 socket 截断
TL;DR:TLS 握手卡住不是“慢”,是协商失败;调 timeout 是徒劳,得查系统时间、证书链、OpenSSL 版本和 IPv6 状态。最常被忽略的是 default_socket_timeout 和 WSL2 时间不同步——这两项修完,80% 的 TLS 卡顿就消失了。

















