nv-websocket-client: Bad SSL behaviour - insecure and does not support SNI

I just spent an hour digging through this so I might be wrong, but it seems to me the wss: protocol is seriously broken.

TL;DR It connectes to a server, doesn’t support SNI and doesn’t check the certificate hostname. (I used tcpdump/wireshark).

The reason: I’d say this: http://stackoverflow.com/a/28031673/149901

https://github.com/TakahikoKawasaki/nv-websocket-client/blob/master/src/main/java/com/neovisionaries/ws/client/WebSocketFactory.java#L622

leads to this:

https://github.com/TakahikoKawasaki/nv-websocket-client/blob/master/src/main/java/com/neovisionaries/ws/client/SocketConnector.java#L110

I.e. as per the stackoverflow issue, it seems that connecting to the IP adress results in skipping all these checks. (BTW: haproxy requires correct use of SNI)

About this issue

  • Original URL
  • State: open
  • Created 7 years ago
  • Reactions: 3
  • Comments: 40 (10 by maintainers)

Most upvoted comments

I think that I got SNI working on Android 4.4.1 and up with this code:

            String serverName = Uri.parse(url).getHost();

            webSocketFactory.setServerName(serverName);
            webSocket = webSocketFactory.createSocket(url);

  Socket socket = webSocket.getSocket();
        Log.d(TAG, "Enabling SNI for " + serverName);
        try {
            Method method = socket.getClass().getMethod("setHostname", String.class);
            method.invoke(socket, serverName);
        } catch (Exception e) {
            Log.w(TAG, "SNI configuration failed", e);
        }

Inspired by: https://github.com/smarek/httpclient-android/issues/7

I’m having the same issue.

com.neovisionaries.ws.client.HostnameUnverifiedException: The certificate of the peer (CN=xx.yy.zz.co) does not match the expected hostname (ws.xx.yy.zz.co)
       at com.neovisionaries.ws.client.SocketConnector.verifyHostname(SocketConnector.java:171)
       at com.neovisionaries.ws.client.SocketConnector.doConnect(SocketConnector.java:126)
       at com.neovisionaries.ws.client.SocketConnector.connect(SocketConnector.java:83)
       at com.neovisionaries.ws.client.WebSocket.connect(WebSocket.java:2152)
       at com.neovisionaries.ws.client.ConnectThread.runMain(ConnectThread.java:32)
       at com.neovisionaries.ws.client.WebSocketThread.run(WebSocketThread.java:45)

It happens in devices with android version 6 and older… (7 and 8 works)

@twogood No, we didn’t, because we consider using reflection kind of a last resort solution. In our case we prefer using IP-based TLS even though it’s more costly. However, it’s good to know that another workaround exists, so thanks for sharing! Maybe we’ll add it as a fallback, because in situations where it wouldn’t work, it would at least not do any harm. But then again, it would make testing even more complex and error prone.