swoole不支持php层配置ssl_ciphers,该选项无效;其加密套件由底层openssl版本及默认策略决定,可控方式仅有升级openssl后重新编译swoole,或通过nginx/envoy前置代理实现精细控制。

ssl_ciphers 在 Swoole 中不是直接配置项
你不能像 Nginx 那样在 $server->set() 里写 'ssl_ciphers' => 'ECDHE-...' —— Swoole 的 PHP 层 API **不暴露 ssl_ciphers 设置入口**。它的 SSL/TLS 行为由底层 OpenSSL 库决定,实际生效的是 OpenSSL 编译时的默认策略 + 运行时环境(如系统 OpenSSL 版本、是否启用 TLSv1.3)。
常见误解是复制 Nginx 的 ssl_ciphers 字符串粘贴进 Swoole 配置,结果完全无效,且无任何报错提示。
- Swoole 4.x/5.x 均未提供 PHP 层可设置
ssl_ciphers的选项 - 底层调用的是
SSL_CTX_set_cipher_list()或SSL_CTX_set_ciphersuites()(TLSv1.3),但这些由 Swoole 内部硬编码或继承 OpenSSL 默认值 - 你看到的某些示例中出现
'ssl_ciphers' => '...',是开发者误用或旧版非官方补丁,生产环境切勿照搬
真正可控的加密行为靠 OpenSSL 环境和 Swoole 启动参数
要影响 Swoole 的加密套件选择,必须从运行环境入手,而非 PHP 配置:
- 确认 Swoole 编译时链接的 OpenSSL 版本 ≥ 1.1.1(否则不支持 TLSv1.3 和
CHACHA20-POLY1305):运行php --ri swoole | grep OpenSSL - 升级系统 OpenSSL 并重新编译 Swoole(静态链接需重编,动态链接可直接替换系统库)
- 通过
openssl ciphers -v 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-CHACHA20-POLY1305'验证该套件是否被当前 OpenSSL 支持并启用 - 禁用弱协议必须靠
ssl_protocols—— Swoole 支持此配置项:'ssl_protocols' => TLSv1.2,TLSv1.3(注意:字符串格式,非数组)
例如,以下配置能有效排除 TLSv1.0/1.1,但对套件本身无筛选作用:
$server->set([
'ssl_cert_file' => '/path/to/cert.pem',
'ssl_key_file' => '/path/to/key.pem',
'ssl_protocols' => 'TLSv1.2,TLSv1.3'
]);
需要精细控制套件?只能改 C 源码或换方案
如果你的合规要求强制指定某几个 AES-GCM 套件、禁用所有 CBC、或启用 ECDHE-ECDSA,Swoole 原生 PHP 接口做不到。可行路径只有两条:
-
修改 Swoole 源码:在
swoole_server.cc或 SSL 上下文初始化处,手动调用SSL_CTX_set_cipher_list(ctx, "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384"),然后重新编译扩展 -
前置代理 TLS 终结:用 Nginx 或 Envoy 做 WSS 入口,配置完整的
ssl_ciphers+ssl_prefer_server_ciphers on,Swoole 退回到普通 TCP 或 HTTP 协议通信 —— 这是生产环境最主流、最可控的做法
后者不仅解决套件控制问题,还能卸载 TLS 握手 CPU 开销、支持 OCSP Stapling、证书自动续期等高级特性。
容易被忽略的关键点
即使你设了 'ssl_protocols' => 'TLSv1.2,TLSv1.3',若客户端(比如老 Android WebView 或 Java 7)只支持 ECDHE-RSA-AES128-SHA 这类 CBC 套件,而你的 OpenSSL 默认已禁用 SHA1 套件(新版默认行为),连接会直接失败,错误日志里只显示 SSL handshake failed,没有具体原因。
这时候你得查 OpenSSL 实际启用的套件列表,而不是盯着 PHP 配置——openssl ciphers -v 'DEFAULT@SECLEVEL=1'(SECLEVEL=1 可临时放宽限制,仅用于调试)。











