I have created a simple embedded WebSocket server using jetty 9.2.5. The server works flawlessly when using an unsecured connection. When I add an SSL connector, the client cannot connect using the https scheme, "wss" vs "ws", and I see a badMessage warning:
31710 [qtp6566818-16] WARN org.eclipse.jetty.http.HttpParser - badMessage: 400 Illegal character 0x16 in state=START in '\x16<<<\x03\x01\x00\xAb\x01\x00\x00\xA7\x03\x037%\x03d\xFf\xBd\xE8...\x01\x05\x01\x02\x01\x04\x03\x05\x03\x02\x03\x04\x02\x02\x02>>>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00...\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' for HttpChannelOverHttp@f59306{r=0,c=false,a=IDLE,uri=-}
There is no problem in the client when I revert the URI to an unsecured WebSocket scheme:
40559 [qtp6566818-17] INFO com.datafascia.emerge.websocketEchoService.EchoService - Connected ...
40562 [qtp6566818-17] INFO com.datafascia.emerge.websocketEchoService.EchoService - Session: WebSocketSession[websocket=JettyAnnotatedEventDriver[com.datafascia.emerge.websocketEchoService.EchoService@18c45017],behavior=SERVER,connection=WebSocketServerConnection@77882dcc{IDLE}{f=Flusher[queueSize=0,aggregateSize=0,failure=null],g=Generator[SERVER,validating],p=Parser@61ed4bc3[ExtensionStack,s=START,c=0,len=0,f=null,p=WebSocketPolicy@379e5d9e[behavior=SERVER,maxTextMessageSize=65536,maxTextMessageBufferSize=32768,maxBinaryMessageSize=65536,maxBinaryMessageBufferSize=32768,asyncWriteTimeout=60000,idleTimeout=300000,inputBufferSize=4096]]},remote=WebSocketRemoteEndpoint@2e93a9a8[batching=true],incoming=JettyAnnotatedEventDriver[com.datafascia.emerge.websocketEchoService.EchoService@18c45017],outgoing=ExtensionStack[queueSize=0,extensions=[],incoming=org.eclipse.jetty.websocket.common.WebSocketSession,outgoing=org.eclipse.jetty.websocket.server.WebSocketServerConnection]]
40571 [qtp6566818-16] INFO com.datafascia.emerge.websocketEchoService.EchoService - incomingMessage= 05501140317063844 123CYC EMERGE-123C015083
40578 [qtp6566818-17] INFO com.datafascia.emerge.websocketEchoService.EchoService - Connection closed with statusCode: 1005, reason: null
The code for the server was taken pretty much from the examples I've encountered both on the jetty site and on the Internet. Here is the code that sets up the WebSocket servlet:
// Setup the websocket server
Server server = new Server(websocketPort);
if (wssEnabled) {
// Add http/s connectors
//connector = new ServerConnector(server);
//connector.setPort(websocketPort);
// HTTP Configuration
HttpConfiguration http_config = new HttpConfiguration();
http_config.setSecureScheme("https");
http_config.setSecurePort(8443);
http_config.setOutputBufferSize(32768);
http_config.setRequestHeaderSize(8192);
http_config.setResponseHeaderSize(8192);
http_config.setSendServerVersion(true);
http_config.setSendDateHeader(false);
SslContextFactory sslContextFactory = new SslContextFactory();
sslContextFactory.setKeyStorePath("/home/jedwards/keystore");
logger.info("keystore path: {}", sslContextFactory.getKeyStorePath());
sslContextFactory.setKeyStorePassword("1deadparrot");
sslContextFactory.setKeyManagerPassword("1deadparrot");
sslContextFactory.setExcludeCipherSuites(
"SSL_RSA_WITH_DES_CBC_SHA","SSL_DHE_RSA_WITH_DES_CBC_SHA","SSL_DHE_DSS_WITH_DES_CBC_SHA",
"SSL_RSA_EXPORT_WITH_RC4_40_MD5","SSL_RSA_EXPORT_WITH_DES40_CBC_SHA","SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA",
"SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA");
// SSL HTTP Configuration
HttpConfiguration https_config = new HttpConfiguration(http_config);
https_config.addCustomizer(new SecureRequestCustomizer());
// SSL Connector
connector = new ServerConnector(server,
new SslConnectionFactory(sslContextFactory,HttpVersion.HTTP_1_1.asString()),
new HttpConnectionFactory(https_config));
connector.setPort(8443);
connector.setIdleTimeout(500000);
} else {
// Basic HTTP connector
connector = new ServerConnector(server);
connector.setPort(websocketPort);
}
ServletContextHandler ctx = new ServletContextHandler();
ctx.setContextPath("/");
ctx.addServlet(EmergeEchoServiceSocketServlet.class, websocketServicePoint);
server.setHandler(ctx);
server.addConnector(connector);
// Start the websocket server
server.start();
logger.info("server status: {}", server.dump());
server.join();
I created a self-signed certificate and key pair using the recommended command:
keytool -keystore keystore -alias jetty -genkey -keyalg RSA
I'm at a loss at this point as I believe I have set the embedded WebSocket servlet up properly. So I figure it's something obvious but I just can't figure out the problem.
I simplified the code slightly and was able to get the SSL WebSockets server working. I'm still using the self-signed cert so it's local only. I can use the IP address but not "localhost" e.g. "wss://192.168.2.115:8443/servicePoint".
Here is the new code:
// Setup the websocket server
Server server = new Server();
if (wssEnabled) {
// HTTP Configuration
HttpConfiguration https_config = new HttpConfiguration();
https_config.setSecureScheme("https");
https_config.setSecurePort(8443);
https_config.setSendServerVersion(true);
https_config.setSendDateHeader(false);
https_config.addCustomizer(new SecureRequestCustomizer());
SslContextFactory sslContextFactory = new SslContextFactory();
sslContextFactory.setKeyStorePath("/pathTo//keystore");
sslContextFactory.setTrustStorePath("/pathTo/keystore");
logger.info("keystore path: {}", sslContextFactory.getKeyStorePath());
sslContextFactory.setKeyStorePassword("myPassword");
sslContextFactory.setKeyManagerPassword("myPassword");
sslContextFactory.setTrustStorePassword("myPassword");
sslContextFactory.setExcludeCipherSuites(
"SSL_RSA_WITH_DES_CBC_SHA",
"SSL_DHE_RSA_WITH_DES_CBC_SHA",
"SSL_DHE_DSS_WITH_DES_CBC_SHA",
"SSL_RSA_EXPORT_WITH_RC4_40_MD5",
"SSL_RSA_EXPORT_WITH_DES40_CBC_SHA",
"SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA",
"SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA");
// SSL Connector
connector = new ServerConnector(server,
new SslConnectionFactory(sslContextFactory,HttpVersion.HTTP_1_1.asString()),
new HttpConnectionFactory(https_config));
connector.setPort(8443);
} else {
// Basic HTTP connector
connector = new ServerConnector(server);
connector.setPort(websocketPort);
}
ServletContextHandler ctx = new ServletContextHandler();
ctx.setContextPath("/");
ctx.addServlet(EmergeEchoServiceSocketServlet.class, "/dF" + websocketServicePoint);
server.setHandler(ctx);
server.addConnector(connector);
// Start the websocket server
server.start();
logger.info("server status: {}", server.dump());
server.join();
}
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