【问题标题】:php ratchet websocket SSL connect?php棘轮websocket SSL连接?
【发布时间】:2013-06-03 12:09:12
【问题描述】:

我有一个棘轮聊天服务器文件

use Ratchet\Server\IoServer;
use Ratchet\WebSocket\WsServer;
use MyAppChat\Chat;
require dirname(__DIR__) . '/vendor/autoload.php';
$server = IoServer::factory(
    new WsServer(
        new Chat()
    )
  , 26666
);
$server->run();

我使用 Websocket 与ws 连接,它工作正常

if ("WebSocket" in window) {
    var ws = new WebSocket("ws://ratchet.mydomain.org:8888");
    ws.onopen = function() {
        // Web Socket is connected. You can send data by send() method.
        ws.send("message to send");
    };
    ws.onmessage = function (evt) { 
        var received_msg = evt.data;
    };
    ws.onclose = function() { 
        // websocket is closed. 
    };
} else {
  // the browser doesn't support WebSocket.
}

我想要安全连接,所以我尝试使用 SSL 进行连接,但无法正常工作。

if ("WebSocket" in window) {
    var ws = new WebSocket("wss://ratchet.mydomain.org:8888");
    ws.onopen = function() {
        // Web Socket is connected. You can send data by send() method.
        ws.send("message to send");
    };
    ws.onmessage = function (evt) { 
        var received_msg = evt.data;
    };
    ws.onclose = function() { 
        // websocket is closed. 
    };
} else {
  // the browser doesn't support WebSocket.
}

我的问题是如何使用 SSL 连接来连接 websocket

有什么想法吗?

【问题讨论】:

    标签: php ssl websocket ratchet


    【解决方案1】:

    如果您使用的是 Apache Web 服务器(2.4 或更高版本),请在 httpd.conf 文件中启用这些模块:

    1. mod_proxy.so
    2. mod_proxy_wstunnel.so

    将此设置添加到您的 httpd.conf 文件中

    ProxyPass /wss2/ ws://ratchet.mydomain.org:8888/
    

    当您需要 WSS 连接时,在您的 JavaScript 调用中使用此 URL:

    var ws = new WebSocket("wss://ratchet.mydomain.org/wss2/NNN");
    

    重新启动 Apache 网络服务器并确保在应用设置(telnet 主机名端口)之前您的 Ratchet 工作器(网络套接字连接)已打开。

    【讨论】:

    • 很好,这行得通,但有一个问题:为什么最后是“/NNN”?谢谢!
    • 引用我们的下一个 URL 参数(例如:/wss2/param1/param2...),我们的系统可以使用这些参数来识别请求目的。如果不需要,您可以将其删除,但请注意,您必须具有相同的匹配身份 url 参数(在本例中为“/wss2/”),以便服务器能够匹配/捕获请求并将其转发到自定义域/端口。
    • 这些指令在什么样的虚拟主机中起作用?你需要监听哪个端口?能否给出一个包含 HTTP 和 WS 协议的 vhost 示例?
    • 作为后续行动:我终于使用 https 在 Chrome 和 Firefox 的 localhost 上工作了,但在我的情况下,我必须使用端口 8080...我对使用哪个端口感到困惑和这导致了很多试验和错误。主要是错误。这对我有用:var conn = new WebSocket('wss://localhost/wss2/');ProxyPass /wss2/ ws://localhost:8080/$server = IoServer::factory( new HttpServer( new WsServer( new Chat() ) ), 8080 );
    • 这样做会影响性能还是造成漏洞?
    【解决方案2】:

    几天前我正在寻找这个问题的答案,我在 Github Ratchet 问题中找到了这个:https://github.com/ratchetphp/Ratchet/issues/489

    heidji 回答的最后一个答案是这样说的:

    我只为像我这样需要快速指导如何实施 SSL 的新手添加此评论: 通过 ReactPHP 文档,您只需要以这种方式构建 SecureServer:
    $webSock = new React\Socket\Server('0.0.0.0:8443', $loop);
    $webSock = new React\Socket\SecureServer($webSock, $loop, ['local_cert' => '/etc/ssl/key.pem', 'allow_self_signed' => true, 'verify_peer' => false]);
    然后注入上面cboden提到的IoServer

    所以现在似乎有一种方法可以使用 Ratchet 实现安全的 websocket 服务器,而无需 HTTPS 代理。

    这里有 SecureServer 类文档:https://github.com/reactphp/socket#secureserver

    【讨论】:

    • 这是最新的答案,现在应该是公认的答案,因为已经添加了 SSL 支持!
    【解决方案3】:

    问题在于 React(构建 Ratchet 的基础上)不支持直接 SSL 连接。请参阅此issue

    有一个简单的解决方法。将stunnel 与如下配置一起使用:

    [websockets]
    accept = 8443
    connect = 8888
    

    Stunnel 将处理端口 8443 上的 SSL 流量并将它们移植到您的 websocket 服务器。

    【讨论】:

    • 不是说 nginx 支持 proxy_passing websocket,我会建议使用它。这样我们可以方便地在端口 443 上服务 wss,因此不会被大多数公司防火墙阻止。
    • 自 2017 年初以来,现在似乎支持 SSL。请参阅下面的 reactphp/socket#55@Jordi's answer
    【解决方案4】:

    我在Ratchet's google groupChris Boden 上找到了这个答案:

    最好的解决方案是使用 Nginx 作为您的 Web 服务器。有 Nginx 在端口 80 上侦听传入连接并让它处理您的 SSL。 Nginx 将为您的 PHP-FPM 转发传入连接 常规网站,如果它检测到连接是 WebSocket 连接让它代理到您在端口上运行的 Ratchet 应用程序 你的选择。然后您的 javascript 可以通过以下方式连接 wss://mydomain.org

    如果您的应用程序将使用nginx 提供服务,这是使用stunnel 的替代方法。

    【讨论】:

    • 感谢您的回答,我完成了这项工作:D,现在我将在 python 中使用 scapy 来欺骗源 IP 地址,但真的很辛苦:(您能帮帮我吗?
    • @temuri 是的,前段时间我发现了一个要点,其中包含使其工作的配置。可惜现在找不到了
    • 啊...有 stunnel 配置示例吗?
    • @Songo 谢谢!不幸的是,我不是 nginx 配置方面的专家。我不确定如何更改我现有的配置。这是我的想法:gist.github.com/temuri416/9633097。我做错了什么?
    【解决方案5】:

    如果您使用的是 Nginx,只需将以下内容写入您的 SSL 服务器块:

    location /services/myservice {
        # switch off logging
        access_log off;
    
        # redirect all HTTP traffic to localhost
        proxy_pass http://localhost:1234;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    
        # WebSocket support (nginx 1.4)
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    
        # Path rewriting
        rewrite /services/myservice/(.*) /$1 break;
        proxy_redirect off;
    
        # timeout extension, possibly keep this short if using a ping strategy
        proxy_read_timeout 99999s;
    }
    

    这会将任何wss://yoursite.com/services/myservice 调用升级到在端口 1234 上运行的套接字。请确保您记住不要让端口 1234 对外开放。

    【讨论】:

    • 嗨@RaisinBranCrunch 你能告诉我那么最终代码是什么?我的意思是这行代码var ws = new WebSocket("wss://ratchet.mydomain.org/wss2/NNN"); 会有什么变化。谢谢
    • @MushfiqurRahman 在我的帖子中的位置块之前,我在我的服务器中阻止了这一行:server_name subdomain.mysite.com; 所以,这意味着我的帖子中的位置块是/services/myservice,最后一件事Javascript 将是var ws = new WebSocket("wss://subdomain.mysite.com/services/myservice");
    【解决方案6】:

    Apache 也为我工作,只需添加域配置:

    ProxyPass /wss/ wss://127.0.0.1:8888/
    

    重新加载 apache,然后在客户端设置 wss 以包含 /wss/ 位置

    wss://127.0.0.1/wss/
    

    【讨论】:

    • 在 apache 2.4 中我们需要在哪个文件中添加这个?
    【解决方案7】:

    如果您使用的是 Windows IIS,请确保您已将其配置为 HTTPS(我使用的是自签名证书),然后安装反向代理:

    网址重写: https://www.iis.net/downloads/microsoft/url-rewrite 和 ARR 3.0: https://www.iis.net/downloads/microsoft/application-request-routing

    您还需要在 IIS 中启用 websockets 支持:

    创建用于 URL 重写的文件夹(例如 myproxyfolder),在此文件夹上创建包含内容的 web.config 文件:

    <?xml version="1.0" encoding="UTF-8"?>
    <configuration>
        <system.webServer>
            <rewrite>
                <rules>
                    <rule name="WebSocketProxy" stopProcessing="true">
                        <match url="(.*)" />
                        <action type="Rewrite" url="http://127.0.0.1:8080" />
                    </rule>
                </rules>
            </rewrite>
        </system.webServer>
    </configuration>
    

    并将“http://127.0.0.1:8080”更改为您的 websocket 服务(我在 WIN 上使用 Ratched for PHP)。

    在 javascript 客户端,使用安全的 websockets wss:// 协议,例如:

        mysock = new WebSocket('wss://127.0.0.1/myproxyfolder');
    ...
    

    【讨论】:

      【解决方案8】:

      它适用于 ubuntu 18.04。

      var ws = new WebSocket('wss://domain.com/ws/');

      通过在终端中运行以下命令来启用代理模块。

      sudo a2enmod 代理 proxy_balancer proxy_wstunnel proxy_http

      在我的 Apache 虚拟主机配置文件 (/etc/apache2/sites-available/000-default-le-ssl.conf) 中添加了这些行

      ProxyRequests 关闭

      ProxyPass "/ws/" "ws://domain.com:5555/"

      重新启动 apache 服务。并且 websocket 开始在 https 中工作。

      【讨论】:

        【解决方案9】:

        我试图为子域执行此操作。例如:从 apache 将 realtime.domain.org 重定向到 localhost:8080。

        这是它的工作原理。您可以创建一个虚拟主机和代理传递它。

        <VirtualHost *:80>
            ServerName realtime.domain.org
        
            RewriteEngine On
            RewriteCond %{HTTP:Connection} Upgrade [NC]
            RewriteCond %{HTTP:Upgrade} websocket [NC]
            RewriteRule /(.*) ws://localhost:8080/$1 [P,L]
        
            ProxyPreserveHost On
            ProxyRequests off
            ProxyPass / http://localhost:8080/
            ProxyPassReverse / http://localhost:8080/
        </VirtualHost>
        

        因此,所有对 realtime.domain.org 的请求都可以重定向到端口 8080,您可以在该端口运行 WebSocket 处理程序。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-09-20
          • 1970-01-01
          • 2013-04-17
          • 1970-01-01
          • 2016-08-22
          • 2015-09-03
          • 1970-01-01
          相关资源
          最近更新 更多