How to give certificate to Java Websocket?
Asked Answered
G

1

6

Forgive me for the newb question, but I am confused and obviously not understanding the fundamentals or explanations of how to use a Websocket server hosted over HTTPS. Everything I find online leads me to have more questions than answers.

I have a Websocket server hosted on my HTTPS website using Java code.

This is my WebsocketServer.java file:

import org.java_websocket.WebSocket;
import org.java_websocket.handshake.ClientHandshake;
import org.java_websocket.server.WebSocketServer;

import java.net.InetSocketAddress;
import java.util.HashSet;
import java.util.Set;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public class WebsocketServer extends WebSocketServer {

    private static final Logger logger = LogManager.getLogger(WebsocketServer.class);

    private static int TCP_PORT = 6868;

    private static Set<WebSocket> conns;

    public WebsocketServer() {
        super(new InetSocketAddress(TCP_PORT));
        conns = new HashSet<>();
    }

    @Override
    public void onOpen(WebSocket conn, ClientHandshake handshake) {
        conns.add(conn);
        logger.info("New connection from " + conn.getRemoteSocketAddress().getAddress().getHostAddress());
        logger.info("Size of connection list: " + conns.size());
    }

    @Override
    public void onClose(WebSocket conn, int code, String reason, boolean remote) {
        conns.remove(conn);
        logger.info("Closed connection to " + conn.getRemoteSocketAddress().getAddress().getHostAddress());
    }

    @Override
    public void onMessage(WebSocket conn, String message) {
        logger.info("Message from client: {}", message);
        // for (WebSocket sock : conns) {
        // sock.send("SENDING BACK" + message);
        // }
    }

    @Override
    public void onError(WebSocket conn, Exception ex) {

        // ex.printStackTrace();
        try {
            if (conn != null) {
                conns.remove(conn);
                // do some thing if required
            }
            logger.info("ERROR from {}", conn.getRemoteSocketAddress().getAddress().getHostAddress());
        } catch (Exception e) {
            logger.info("onError: WebSocketServer may already be running");

        }

    }

    public Set<WebSocket> getConns() {
        return conns;
    }

}

Then I started the WebsocketServer like this:

WebsocketServer websocketServer;
// Start socket server
websocketServer = new WebsocketServer();
websocketServer.start();

And on the client side, I connect to it like this:

    // APP_WEB_SOCKET is the url to my site: api.my_custom_domain.com
    var connection = new WebSocket("wss://" + APP_WEB_SOCKET + ":6868");

QUESTIONS: I keep reading that I need a certificate if I want to use wss over HTTPS, but cannot find any documents that explain what this means in a way that I can understand.

My app is hosted in AWS Elastic Beanstalk environment. Do I need to somehow add a certificate to the setup of the WebsocketServer in my Java code? Example:

WebsocketServer websocketServer;
// Start socket server
websocketServer = new WebsocketServer();

// example guessing
websocketServer.cert = "SOMETHING";??
websocketServer.start();

Does the client code need to be changed at all?

Who needs the certificate?

If someone could please explain what I am missing or point me in the correct direction, I would really appreciate it.

Gravois answered 10/1, 2022 at 15:9 Comment(1)
Websocket connections are "upgraded HTTP(S) calls", so your HTTP server needs the certificate so that it can "talk HTTPS", and connecting to it for WS purposes should then automatically do the right thing.Salvadorsalvadore
E
1

Keep it easy.
Certs inside your application are complex - they are hard to manage and you will get problems to run your application in a modern cloud environment (start new environments, renew certs, scale your application, ...).

Simple conclusion: Dont implement any certs.

How-to get encrypted connections?

As Mike already pointed out in the comments: WebSockets are just upgraded HTTP(S) connections. A normal webserver (nginx, apache) takes care about the certs. It can be done in kubernetes (as ingress-controller) or with a "bare-metal" webserver.
Both of them should act as a reverse-proxy. This means: Your java-application doesn't know anything about certs. It has just unencrypted connections - like in your code on port 6868.
But the client will not use this port. 6868 is only internally reachable.

The client will call your reverse-proxy at the normal HTTPS port (=443). The reverse-proxy will forward the connection to your java-application.

Here some links for further information:

Elonore answered 13/1, 2022 at 14:50 Comment(2)
Does this mean that I use port 443 (on client side) to connect to web socket server running on port 6868? Or what is the procedure here?Gravois
Yes, correct. The reverse proxy can handle multiple services which are identified by path. yoursite.com/ws is the websocket-endpoint, yoursite.com/api is the normal backend.Elonore

© 2022 - 2024 — McMap. All rights reserved.