2

Hello I've been facing a weird problem the past few days. I send out a demo of my app to a few people. however for around 75% of the people the demo didn't work, while for the other 25% it works great. (even for myself)

so I investigated and found the issue. the mayority is getting the following error when connecting to the web-socket: Caused by: java.security.cert.CertificateException: No subject alternative names matching IP address 45.116.104.89 found

Full stack trace:

[21:48:31] [pool-4-thread-1/INFO]: [com.heckvision.bingosplash.web.WebSocketManager:lambda$tryStartConnection$0:48]: Attempting to connect to WebSocket...
[21:48:32] [WebSocketConnectReadThread-106/INFO]: [com.heckvision.bingosplash.web.WebSocketManager$1:onError:77]: WebSocket error:
[21:48:32] [WebSocketWriteThread-107/INFO]: [com.heckvision.bingosplash.web.WebSocketManager$1:onError:77]: WebSocket error:
[21:48:32] [WebSocketConnectReadThread-106/INFO]: [com.heckvision.bingosplash.web.WebSocketManager$1:onError:78]: javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No subject alternative names matching IP address 45.116.104.89 found
[21:48:32] [WebSocketConnectReadThread-106/INFO]: [com.heckvision.bingosplash.web.WebSocketManager$1:onError:78]:   at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
[21:48:32] [WebSocketConnectReadThread-106/INFO]: [com.heckvision.bingosplash.web.WebSocketManager$1:onError:78]:   at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1949)
[21:48:32] [WebSocketConnectReadThread-106/INFO]: [com.heckvision.bingosplash.web.WebSocketManager$1:onError:78]:   at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:302)
[21:48:32] [WebSocketConnectReadThread-106/INFO]: [com.heckvision.bingosplash.web.WebSocketManager$1:onError:78]:   at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:296)
[21:48:32] [WebSocketConnectReadThread-106/INFO]: [com.heckvision.bingosplash.web.WebSocketManager$1:onError:78]:   at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1497)
[21:48:32] [WebSocketConnectReadThread-106/INFO]: [com.heckvision.bingosplash.web.WebSocketManager$1:onError:78]:   at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:212)
[21:48:32] [WebSocketConnectReadThread-106/INFO]: [com.heckvision.bingosplash.web.WebSocketManager$1:onError:78]:   at sun.security.ssl.Handshaker.processLoop(Handshaker.java:979)
[21:48:32] [WebSocketConnectReadThread-106/INFO]: [com.heckvision.bingosplash.web.WebSocketManager$1:onError:78]:   at sun.security.ssl.Handshaker.process_record(Handshaker.java:914)
[21:48:32] [WebSocketConnectReadThread-106/INFO]: [com.heckvision.bingosplash.web.WebSocketManager$1:onError:78]:   at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1062)
[21:48:32] [WebSocketConnectReadThread-106/INFO]: [com.heckvision.bingosplash.web.WebSocketManager$1:onError:78]:   at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375)
[21:48:32] [WebSocketConnectReadThread-106/INFO]: [com.heckvision.bingosplash.web.WebSocketManager$1:onError:78]:   at sun.security.ssl.SSLSocketImpl.readDataRecord(SSLSocketImpl.java:928)
[21:48:32] [WebSocketConnectReadThread-106/INFO]: [com.heckvision.bingosplash.web.WebSocketManager$1:onError:78]:   at sun.security.ssl.AppInputStream.read(AppInputStream.java:105)
[21:48:32] [WebSocketConnectReadThread-106/INFO]: [com.heckvision.bingosplash.web.WebSocketManager$1:onError:78]:   at java.io.InputStream.read(InputStream.java:101)
[21:48:32] [WebSocketConnectReadThread-106/INFO]: [com.heckvision.bingosplash.web.WebSocketManager$1:onError:78]:   at com.heckvision.shadowed.java_websocket.client.WebSocketClient.run(WebSocketClient.java:543)
[21:48:32] [WebSocketConnectReadThread-106/INFO]: [com.heckvision.bingosplash.web.WebSocketManager$1:onError:78]:   at java.lang.Thread.run(Thread.java:745)
[21:48:32] [WebSocketConnectReadThread-106/INFO]: 

after researching I found out that this error means that the SSL certificate is not valid. this is weird since I have a valid 'lets encrypt' cert and domain. and the other 25% can connect proving the cert is valid.

the error shows I'm connecting directly to a raw IP but I'm not. im using wss://testserver.heckvision.com this domain is linked to a freshly setup test server for this demo. running nginx (for upgrading to wss) and docker (to host the web-socket)

the project is on JAVA 8. I've tried multiple versions of JAVA 8 and sorts, but nothing seems to help.

even weirder is that when I used the same class in a JAVA 21 project it works great and for 100% of the people.

I use the following java class to connect to the web-socket:

package com.heckvision.bingosplash.web;

import org.java_websocket.client.WebSocketClient;
import org.java_websocket.enums.ReadyState;
import org.java_websocket.handshake.ServerHandshake;

import javax.net.ssl.SSLContext;
import java.net.URI;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class WebSocketManager {
    private final URI serverUri;
    private volatile WebSocketClient client; // Made volatile for thread safety
    private final ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
    private volatile boolean shouldConnect = false; // Made volatile for thread safety
    private volatile boolean connecting = false; // Made volatile for thread safety

    private MessageListener messageListener;

    public void setMessageListener(MessageListener listener) {
        this.messageListener = listener;
    }

    public WebSocketManager(String serverUrl) {
        this.serverUri = URI.create(serverUrl);
    }

    public void setShouldConnect(boolean shouldConnect) {
        this.shouldConnect = shouldConnect;

        if (shouldConnect) {
            tryStartConnection();
        } else {
            disconnect();
        }
    }

    private void tryStartConnection() {
        if (client != null && client.getReadyState() == ReadyState.OPEN) return;
        if (connecting) return;

        connecting = true;

        executor.execute(() -> {
            try {
                System.out.println("Attempting to connect to WebSocket...");
                WebSocketClient socket = new WebSocketClient(serverUri) {
                    @Override
                    public void onOpen(ServerHandshake handshakedata) {
                        System.out.println("WebSocket connected.");
                        connecting = false; // Connection successful, clear connecting flag
                    }

                    @Override
                    public void onMessage(String message) {
                        System.out.println("Received: " + message);
                        if (messageListener != null) {
                            messageListener.onMessage(message);
                        }
                    }

                    @Override
                    public void onClose(int code, String reason, boolean remote) {
                        System.out.println("WebSocket closed: " + reason);
                        client = null;
                        connecting = false;
                        if (shouldConnect) {
                            scheduleReconnect();
                        }
                    }

                    @Override
                    public void onError(Exception ex) {
                        System.err.println("WebSocket error:");
                        ex.printStackTrace();
                        client = null;
                        connecting = false;
                        if (shouldConnect) {
                            scheduleReconnect();
                        }
                    }
                };

                SSLContext sslContext = SSLContext.getDefault();
                socket.setSocketFactory(sslContext.getSocketFactory());

                client = socket;
                socket.connect(); // Non-blocking

            } catch (Exception e) {
                System.err.println("WebSocket connect exception:");
                e.printStackTrace();
                connecting = false;
                // FIX: Only reconnect if we should still be connecting
                if (shouldConnect) {
                    scheduleReconnect();
                }
            }
        });
    }

    private void scheduleReconnect() {
        executor.schedule(this::tryStartConnection, 5, TimeUnit.SECONDS);
    }

    private void disconnect() {
        if (client != null && (client.getReadyState() == ReadyState.OPEN || client.getReadyState() == ReadyState.NOT_YET_CONNECTED)) {
            try {
                client.close();
                System.out.println("WebSocket disconnected by request.");
            } catch (Exception e) {
                System.err.println("WebSocket disconnect exception:");
                e.printStackTrace();
            }
        }
        client = null;
    }

    public void shutdown() {
        shouldConnect = false;
        disconnect();
        executor.shutdownNow();
    }
}
  • multiple versions and sorts of java - did not help
  • multiple pc and operating systems - did not help
  • adding custom ssl handshake checker - did not work and eventually came back wit the same error
  • hosting websocket on another server - did not work same error
3
  • This question is similar to: Certificate for <localhost> doesn't match any of the subject alternative names. If you believe it’s different, please edit the question, make it clear how it’s different and/or how the answers on that question are not helpful for your problem. Commented Aug 4 at 10:55
  • Has your Java 8 project the same audience than the Java 21 project? To me this looks like a client-side error like a TLS intercepting proxy that does something wrong causing a redirect to https://45.116.104.89. Commented Aug 4 at 16:52
  • @Robert yes it's the same audience for both projects Commented Aug 4 at 18:23

0

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.