workerman https服务必须显式配置ssl_context数组,含绝对路径的local_cert和local_pk,且verify_peer必须设为false;否则即使监听443端口也仅为裸tcp,触发err_ssl_protocol_error。

Workerman HTTPS 服务必须手动配置 SSL 上下文,不能靠 Nginx 反代就忽略
Workerman 本身不自动加载证书或解析 https:// 协议,哪怕你绑了 443 端口,没配 ssl_context 就是裸 TCP,浏览器会直接报 ERR_SSL_PROTOCOL_ERROR。这不是配置错,是根本没启用 TLS 握手。
关键点在于:Workerman 的 WebServer 或 TcpConnection 子类(如 HttpConnection)必须显式传入 ssl_context 数组,且证书路径必须是绝对路径、PHP 进程有读取权限。
-
ssl_context必须包含local_cert(全链 PEM,含私钥+证书+中间证书)和local_pk(私钥文件)——或者合并进local_cert,但必须用file://前缀或绝对路径 - 别用相对路径,
./cert.pem在 daemon 模式下大概率失效,因为工作目录已变 - 私钥不能带密码,否则启动时卡住无报错;可用
openssl rsa -in key.pem -out key-no-pass.pem去密
workerman/webserver 中配置 ssl_context 的正确写法
用 Workerman\Protocols\Http\WebServer 启 HTTPS 时,ssl_context 是构造参数之一,不是运行时 set 方法能补上的。漏掉这个数组,服务起来也是 HTTP。
示例片段:
LANUX V1.0 蓝脑商务网站系统 适用于网店、公司宣传自己的品牌和产品。 系统在代码、页面方面设计简约,浏览和后台管理操作效率高。 此版本带可见即可得的html编辑器, 方便直观添加和编辑要发布的内容。 安装: 1.解压后,更换logo、分类名称、幻灯片的图片及名称和链接、联系我们等等页面。 2.将dbconfig.php里面的数据库配置更改为你的mysql数据库配置 3.将整个文件夹上传至
$web = new WebServer('ssl://0.0.0.0:443', [
'ssl_context' => [
'local_cert' => '/absolute/path/to/fullchain.pem',
'local_pk' => '/absolute/path/to/privkey.pem',
'verify_peer' => false,
]
]);
-
verify_peer => false是必需的,Workerman 不校验客户端证书,设为true会导致握手失败 - 不要加
crypto_method,PHP 7.4+ 默认用TLSv1_2_METHOD,硬指定反而可能触发SSL routines::unsupported protocol - 证书文件必须是 PEM 格式,DER 或 PFX 会直接抛
failed to load certificate
常见错误:证书能用 curl 测通,但 Workerman 启动失败或连接重置
curl 成功只说明证书链和端口通,不代表 Workerman 能加载。典型现象是:php start.php start 无报错但访问白屏 / ERR_CONNECTION_RESET。
- 检查
local_cert是否同时包含了证书和私钥(顺序:私钥 → 域名证书 → 中间证书),缺一不可 - 用
openssl x509 -in cert.pem -text -noout和openssl rsa -in key.pem -check -noout分别验证证书和私钥有效性 - 确认 PHP 进程用户(如 www-data)对两个文件有
read权限,ls -l看权限位,别只 chmod 755 目录却忘了文件 - Workerman 不支持 SNI,单个进程只能绑定一套证书;多域名需用 Nginx 反代或多个 Worker 实例
HTTP 自动跳转 HTTPS 的坑:别在 Workerman 层做 301
Workerman 的 WebServer 没有内置协议识别,$_SERVER['HTTPS'] 永远为空,$_SERVER['REQUEST_SCHEME'] 也不可靠。想做跳转,必须依赖反向代理头(如 X-Forwarded-Proto)或监听双协议端口后手动判断。
- 如果用了 Nginx 反代,应让 Nginx 处理跳转,Workerman 只跑 HTTP;否则容易陷入重定向循环
- 若坚持 Workerman 内跳转,需在
onMessage中检查$connection->transport === 'ssl',但注意:非 SSL 连接无法访问该属性,要先判空 - 更稳的做法是监听两个端口(80 + 443),80 上只返回 301 到
https://$host$request_uri,但需确保 DNS 和防火墙允许 80 端口
证书路径权限、PEM 格式完整性、以及 ssl_context 必须作为启动参数传入——这三点漏掉任一,HTTPS 就只是个监听在 443 的假象。









