棘轮没有从浏览器接收WebSocket数据包?

问题描述:

我想通过使用棘轮测试简单的ping & pong与WebSockets的响应。我的WebSocket服务器是而不是看到来自我的Web浏览器的WebSocket客户端的任何响应由WebSocket服务器发送的数据包被浏览器看好。我试图找到原因。棘轮没有从浏览器接收WebSocket数据包?

我目前的猜测是:

  • 我丢失了一些HTTP头(一个或多个)
  • 我有编码wsclient.send(encodeFrame("{'action': 'pong'}"));
  • 的CloudFlare是不承认在WS流包为有效浏览器的数据包,砸它
  • EC2实例中的CloudFlare或nginx正在做一些奇怪的缓冲
  • 棘轮不识别最低IOServer级别上的数据包并将其抖动
    • 但我从来没有从这个层面上得到任何错误或异常

设置:

  • Linux服务器@亚马逊EC2
  • 有免费计划,并加速对DNS @的CloudFlare +强制HTTPS重定向
  • HTTP服务器是nginx
  • 没有HTTPS上的nginx(CloudFlare的重定向HTTPS - > EC2 HTTP)
  • /api127.0.0.1:65000(救护车)

在测试了自己的WebSocket客户

  • 的WebSocket服务器(救护车)在127.0.0.1:65000运行在EC2上
  • Nginx的重定向EC2实例:
    • 127.0.0.1:65000工作正常
    • <Amazon NAT IP of instance>:80工作正常
    • <Amazon public IP of instance>:80工作正常
    • <CloudFlare IP of Amazon public IP>:80连接到WebSocket的服务器上的应用程序implementatuin的水平,但没有看到任何一级onMessage方法包(应用程序,WsServer,HttpServer的)
    • <CloudFlare IP of Amazon public IP>:443给人400 Bad Request因为测试客户端仅仅是简单的TCP流

    从本地机器测试:

    直接连接通过CloudFlare的缓存的IP,以提供主机。 Dojox.Socket连接到wss://host/api。在Ratchet的应用程序实现级别上再次出现连接(已启动onOpen)。我的浏览器看到ping包很好,所以从棘轮发送工作正常。

    但后来我试着发送pong回复到ping从浏览器和onMessage方法不是从来没有在任何关于Ratched的级别上被解雇。连接保持开放,如果我用Fiddler观看ping和pongs都会不断发送,但WebSocket服务器永远不会收到这些pong(onMessage)。

    继提琴手的WebSocket的流显示,从浏览器pongs具有“数据由键屏蔽:<some hex>”,而是来自拉契特坪是掩盖。

    连接摘要:

    页面加载:

    本地机器http://host/ → CloudFlare的HTTPS重定向https://host/加载WSS WebSocket连接到/api

    WebSocket连接到/apihttp://host-with-amazon-public-ip/http://host-with-amazon-NAT-ip/ → HTML + JS网页:

    CloudFlare的HTTPS重定向WSS://主机/ API → http://host-with-amazon-public-ip/apihttp://host-with-amazon-NAT-ip/api →本地服务器nginx的重定向/ API → 127.0.0.1:65000 →连接升级→网页浏览器的WebSocket流→的WebSocket流

    nginx.conf

    server { 
        listen 80; 
    
        server_name test.example.com; 
        root /home/raspi/test/public; 
        autoindex off; 
        index index.php; 
    
        access_log /home/raspi/test/http-access.log; 
        error_log /home/raspi/test/http-error.log notice; 
    
        location/{ 
        index index.php; 
        try_files $uri $uri/ /index.php?$args; 
        } 
    
    location /api { 
        access_log /home/raspi/test/api-access.log; 
        error_log /home/raspi/test/api-error.log; 
    
        expires epoch; 
    
        proxy_ignore_client_abort on; 
        proxy_buffering off; 
        proxy_request_buffering off; 
        proxy_cache off; 
        proxy_pass http://127.0.0.1:65000/; 
    
        proxy_http_version 1.1; 
    
        proxy_set_header Host $host; 
        proxy_set_header Connection "keep-alive, Upgrade"; 
        proxy_set_header Upgrade "websocket"; 
        proxy_set_header Accept-Encoding "gzip, deflate"; 
        proxy_set_header Sec-WebSocket-Extensions "permessage-deflate"; 
        proxy_set_header Sec-WebSocket-Protocol "game"; 
        proxy_set_header X-Real-IP $remote_addr; 
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 
        } 
    
        location ^~ /js/app/ { 
        try_files $uri /; 
        expires epoch; 
        add_header Cache-Control "no-cache" always; 
        } 
    
        location ~* ^.+.(jpg|jpeg|gif|css|png|js|ico|html|xml|txt)$ { 
        try_files $uri /; 
        access_log off; 
        expires max; 
        } 
    
        location = /robots.txt { access_log off; log_not_found off; } 
        location = /favicon.ico { access_log off; log_not_found off; }  
        location ~ /\. { access_log off; log_not_found off; deny all; } 
    
        location ~ \.php$ { 
        try_files $uri =404; 
        fastcgi_split_path_info ^(.+\.php)(/.+)$; 
        fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock; 
        fastcgi_index index.php; 
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 
        include fastcgi_params; 
        } 
    } 
    
    +0

    *您的* Cloudflare帐户是否支持websockets? https://blog.cloudflare.com/cloudflare-now-supports-websockets/由于websockets通过“升级”HTTP连接的方式工作,单向服务器到客户端的传输似乎是可能的在某些情况下,通过代理不完全支持协议,并假定服务器仍然返回HTTP响应主体。 –

    Web套接字目前仅在商业和企业级别可用。你提到你在免费计划。这是这个问题。

    问题是您的提供商拒绝连接和更新标头。你可以去棘轮/的WebSocket /版本/ RFC6455/HandshakeVerifier.php并修改代码:

    ... 
        public function verifyAll(RequestInterface $request) { 
        $passes = 0; 
    
        $passes += (int)$this->verifyMethod($request->getMethod()); 
        $passes += (int)$this->verifyHTTPVersion($request->getProtocolVersion()); 
        $passes += (int)$this->verifyRequestURI($request->getPath()); 
        $passes += (int)$this->verifyHost((string)$request->getHeader('Host')); 
        $passes += (int)$this->verifyUpgradeRequest((string)$request->getHeader('Upgrade')); 
        $passes += (int)$this->verifyConnection((string)$request->getHeader('Connection')); 
    
        die((string)$request); 
        ... 
    

    而且你会看到结果的请求不具有所需的字段;

    解决方法:重写WsServer :: onOpen函数并添加该字段以手动请求。但这是不安全的...