Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Websockets not working on iOS and Safari - OSSStatus Error 9837

I am developing a chat application that makes use of socket.io for matchmaking. Clients using Windows machines and Android Devices are able to make a websocket connection. However clients using Safari on Desktop and iOS are unable to connect using both Safari and Chrome. My application works from socket.io client -> NGINX Proxy -> Node.js socket server

I have been able to track down the error by inspecting the iOS browser through a Mac and this error shows up [Error] WebSocket network error: The operation couldn’t be completed. (OSStatus error -9836.) enter image description here

After doing some research into the error I found that Safari is picky when it comes to creating secure websocket connections. I am currently using a CloudFlare issues certificate and key which is in my NGINX configuration. I also tried adding the credentials to my node server but the same problem persists. Here is the NGINX server block:

server {
  listen 80;
  listen 443;

  ssl                   on;
  ssl_certificate       /var/site-certificates/website.com/cloudflare.website.com.pem;
  ssl_certificate_key   /var/site-certificates/website.com/cloudflare.website.com.key;
  ssl_protocols TLSv1.3;

  server_name chat0.website.com;

  location / {
    proxy_http_version 1.1;
    # proxy_ssl_certificate     /var/site-certificates/website.com/cloudflare.website.com.pem; //tried with and without, same result
    # proxy_ssl_certificate_key /var/site-certificates/website.com/cloudflare.website.com.key;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header X-Real-IP $remote_addr ; 
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for ; 
    proxy_set_header Host $host;
    proxy_pass http://127.0.0.1:5555; //tried https with credentials but same result
  } 
}

Here is how the Socket Connection is defined client side:

<script src="https://cdn.jsdelivr.net/npm/socket.io-client@2/dist/socket.io.js"></script>
<meta http-equiv="Content-Security-Policy" content="default-src ... connect-src 'self' * ws://* wss://*;">

SocketConn = io.connect(socket_endpoint, {
                    forceNew: false,
                    transports: ['websocket'],
                    reconnection: true,
                    reconnectionDelay: 2000,
                    reconnectionDelayMax: 5000,
                    reconnectionAttempts: 10
                });

It seems like not that many people are running into this problem so the resources are sparse. My main guess may be incorrect ssl certificate format for Apple Devices however this configuration works for All other browsers bar Apple Devices.

like image 585
trecoolable Avatar asked Jun 12 '20 21:06

trecoolable


People also ask

Does iOS support WebSockets?

Apple has finally added Websockets as first-class citizen to its platforms. Websockets in iOS 13, macOS 10.15, tvOS 13, watchOS 6, and Mac Catalyst have gained first-class citizen status in networking stack. Apple has finally added support in URLSession and for lower level in Network.

Why are WebSockets blocked?

A blocked connection can be caused by: AdBlocker / Cookie blocker browser extensions. Antivirus and Firewall software. Proxy and VPN connections.


2 Answers

While not a solution for production environments, this can be resolved in Safari by enabling the experimental feature NSURLSession WebSocket. To do this go to Develop > Experimental Features and make sure NSURLSession WebSocket is checked.

like image 112
Reidsy Avatar answered Oct 16 '22 17:10

Reidsy


I had the same problem and managed to fix (or rather work around) it by additionally allowing TLSv1.2 - so there seems to be some problem with websockets and TLSv1.3 in current versions of Safari.

like image 37
Jan Avatar answered Oct 16 '22 18:10

Jan