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.)
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.
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.
A blocked connection can be caused by: AdBlocker / Cookie blocker browser extensions. Antivirus and Firewall software. Proxy and VPN connections.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With