使用SSL通过nginx实现PHP WebSockets

10
如何在nginx中使用PHP设置WebSockets?
我看过这个教程,但无法使其工作。

https://www.sanwebe.com/2013/05/chat-using-websocket-php-socket

已将这三个文件复制到www目录的根目录中

/index.php /jquery-3.1.1.js /websocket/server.php

index.php 中,我已更改了 URI
var wsUri = "wss://domain.com/websocket/server.php";

在nginx中,我添加了这个。
http {
    map $http_upgrade $connection_upgrade {
        default upgrade;
        ''      close;
    }
    server {
        location /websocket/ {
            proxy_pass https://domain.com:9000/websocket/server.php;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection $connection_upgrade;
        }
    }
}

http://nginx.org/en/docs/http/websocket.html

启动 WebSocket 服务器

php -q /var/www/websocket/server.php

聊天室位于https://domain.com/chat.php,可以加载但在聊天窗口中出现错误:错误发生-连接关闭 还尝试通过此工具连接,但出现以下错误。

http://www.websocket.org/echo.html

ERROR: undefined
DISCONNECTED

如果通过浏览器请求
wss://domain.com/websocket/server.php


ERR_DISALLOWED_URL_SCHEME

1
我假设错误是在浏览器窗口中显示的,而不是在nginx或php日志中。你有没有用谷歌浏览器来测试这个(https://productforums.google.com/forum/#!topic/chrome/leVmLPNVISI )?如果是的话,请尝试使用另一个浏览器来测试。 - Tom Regner
是的,这个错误发生在Google Chrome浏览器中。我也尝试过使用FF。但是在这里我甚至没有收到任何错误提示。 - clarkk
1
尝试使用例如 tcpdump 窃听客户端和 nginx 以及 nginx 和 php 之间的流量,以检查设置在网络层面上是否按预期工作。 - Tom Regner
@TomRegner,你能给我一个如何做到的例子吗? - clarkk
在SO上搜索“tcpdump websocket”,您会找到相关讨论并开始入手。 - Tom Regner
你解决了这个问题吗?如果是的话,你能回答这个问题吗?点击这里 - Nɪsʜᴀɴᴛʜ ॐ
2个回答

4
我发现你的配置文件中有一些小问题,我的观察如下:
  • 运行php -q /var/www/websocket/server.php将启动简单的socket服务器。它不会是SSL;我猜这就是为什么你要通过nginx传递它。对吧?
  • 因此,proxy_pass https://domain.com:9000/websocket/server.php;不应该是https。你也不需要完整路径,因为它只是一个简单的tcp socket而不是文件路径。因此,只需proxy_pass http://127.0.0.1:9000;即可。
  • 如果你在nginx上实现了SSL,那么SSL设置在哪里?
  • 在所有新的浏览器中,你无法从安全的https页面访问不安全的http或ws资源。
因此,以下是我的配置文件,看起来可以按预期工作。
 server {
    listen 8080 default_server;
    listen 8443 ssl;

    ssl_certificate /home/ubuntu/Desktop/php-sock/newcert.pem;
    ssl_certificate_key /home/ubuntu/Desktop/php-sock/newkey.pem;

    root /home/ubuntu/Desktop/php-sock;

    index index.php index.html index.htm;

    location / {
        try_files $uri $uri/ =404;
    }

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php7.0-fpm.sock;
    }

    location /websocket/ {
        proxy_pass http://127.0.0.1:9000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_read_timeout 86400;
    }
}

同时在index.php中进行更改,将var wsUri = "wss://localhost:8443/websocket/";替换为新的内容。


2

您在nginx配置中使用的是9000端口,而PHP内置的Web服务器运行在8000端口。

尝试将端口更改为8000,看看是否解决了问题。

proxy_pass http://domain.com:8000/websocket/;

编辑:

关于 ERR_DISALLOWED_URL_SCHEME 错误

自Chrome 50版本以来,要求所有websocket通信都必须使用SSL。您可能需要启用SSL以使您的应用程序在Chrome中正常工作。

您有两个选项:

  1. 使用由可信证书颁发机构颁发的证书
  2. 将证书手动添加到受信任的证书根目录中。如果没有手动添加证书,则您的Web应用程序将无法为任何人工作

请求WebSocket URL时得到相同的错误ERR_DISALLOWED_URL_SCHEME - clarkk
现在已经在nginx中更改了配置以运行SSL,但仍然收到相同的错误。 - clarkk
你正在使用的证书是否是自签名的?Chrome也可能因此拒绝它。 - Karl Buys
@clarkk 根据你的评论,我修改了我的答案。 - Karl Buys
让我们在聊天中继续这个讨论 - Karl Buys
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接