如何在Apache与Ratchet环境下实现HTTPS搭配WSS?
问题原因
当前你的Ratchet服务器仅监听未加密的WS协议,而WSS需要加密的SSL/TLS连接,直接修改前端协议为wss://会因为后端未配置SSL支持而连接失败。以下提供两种可行的配置方案,推荐使用Apache反向代理方案(适配你已有的Apache+Certbot环境)。
方案一:Apache反向代理(推荐)
利用已配置好SSL的Apache作为中间层,将WSS请求转发到本地的Ratchet WS服务器,无需修改Ratchet代码。
启用Apache代理模块
执行以下命令启用所需模块:sudo a2enmod proxy proxy_http proxy_wstunnel sudo systemctl restart apache2添加反向代理规则
编辑你的网站Apache配置文件(例如/etc/apache2/sites-available/your-domain.conf),在<VirtualHost *:443>区块内添加:# 反向代理WSS请求到本地WS端口 ProxyPass /wss ws://localhost:8001 ProxyPassReverse /wss ws://localhost:8001修改前端连接地址
更新app.js中的WebSocket连接代码,去掉端口,改用代理路径:var hostname = window.location.hostname; var ws = new WebSocket('wss://' + hostname + '/wss?id_class=' + id + '&id_user=' + id_user + '&chap_name=' + chap_name);重启服务并测试
重启Apache,然后重启你的Ratchetserver.php,刷新页面测试WSS连接。
方案二:给Ratchet服务器直接配置SSL
让Ratchet服务器自身处理SSL加密,需要用到Certbot生成的证书文件。
获取证书路径
Certbot生成的证书默认存放在/etc/letsencrypt/live/your-domain/下,包含fullchain.pem(证书链)和privkey.pem(私钥)。修改Ratchet服务器代码
将server.php中的IoServer替换为SslServer,添加SSL配置:<?php require __DIR__ . '/../vendor/autoload.php'; use Ratchet\Server\SslServer; use Ratchet\Http\HttpServer; use Ratchet\WebSocket\WsServer; require "EditorServer.php"; $port = isset($_SERVER["CHAT_SERVER_PORT"]) ? $_SERVER["CHAT_SERVER_PORT"] : 8001; $bindAddr = isset($_SERVER['CHAT_BIND_ADDR']) ? $_SERVER['CHAT_BIND_ADDR'] : '0.0.0.0'; $file = "lecon.txt"; # SSL配置 $sslOptions = [ 'local_cert' => '/etc/letsencrypt/live/your-domain/fullchain.pem', // 替换为你的域名证书路径 'local_pk' => '/etc/letsencrypt/live/your-domain/privkey.pem', // 替换为你的域名私钥路径 'verify_peer' => false, ]; $server = SslServer::factory( new HttpServer( new WsServer( new MyApp\EditorServer($file) ) ), $port, $bindAddr, $sslOptions ); printf("Websocket Editor server running on wss://%s:%s.\n--\n", $bindAddr, $port); $server->run();调整证书权限
确保运行Ratchet的用户(如www-data或你的登录用户)能读取证书文件:sudo usermod -aG ssl-cert www-data # 将用户加入ssl-cert组 sudo chmod 750 /etc/letsencrypt/live/your-domain/ # 调整目录权限修改前端连接地址
更新app.js中的协议为wss://,保持端口不变:var hostname = window.location.hostname; var port = 8001; var ws = new WebSocket('wss://' + hostname + ':' + port + "?id_class=" + id + "&id_user=" + id_user + "&chap_name=" + chap_name);重启服务并测试
重启Ratchet服务器,测试WSS连接。
排查要点
- 若使用方案二,确保防火墙开放8001端口:
sudo ufw allow 8001 - 检查Chrome控制台的具体错误信息,若为证书错误,确认证书路径和权限是否正确
- 确保域名解析正常,且证书未过期
内容的提问来源于stack exchange,提问作者nathabon

