Hello, and apologies for the long post.
I have spent the last several days trying to work out exactly how to implement a client/server connection using secure websockets. I have had no joy in getting this to work. Below is an outline of what the hardware infrastructure is, what the requirements are and what I've tried to date.
I have searched and read just about every example in the forum for websockets. But, I still have a few questions about how to communicate between the client and server.
Requirement:
I need to have a desktop app (later will need Android / iOS, and web app) that will connect to a web app server using TLS1.2 secure web sockets.
This is a requirement for the client. Previously, I had everything working nicely with simple TCP Sockets. The requirement has come about due to the need to increase security and provide encryption between the client (a device - Android/iOS/custom hardware) and the server.
If there is a way to communicate between a client and server using TCP sockets while using SSL/TLS1.2 then please do let me know how to implement it. I could not find anything in the forums or documentation that explains how to do this.
Infrastructure:
What I have is a VPS hosted with Amazon Web Services (AWS) and an Elastic Load Balancer (ELB) in front of the VPS. Also, I have used LetsEncrypt.com to obtain a SSL certificate and successfully installed the certificate onto the VPS and on the ELB.
To the ELB I have added a Listener for SSL traffic on port 65534 and this is the port I need the web socket to connect to. I have also added listeners for HTTP and HTTPS (80 / 443 respectively) on the ELB. All three listeners also have the equivalent ports open in the Security Group assigned to both the VPS and the ELB.
What I Have Tried:
The below code snippet is what I currently have for the client.
Client
Server
The next code snippet is what I have implemented in the server.
The 'App' WebSocket Class is barebones right now...
Questions:
I understand how TCP Sockets work very well and I'm probably (most likely) not fully understanding how websockets work.
I require the client (a device) to send a message to the server and then the server to respond by sending a message back. With TCP sockets this is rather trivial and I am hoping that websockets will be just as simple.
How can I retrieve the message on the server that is sent by the client? I am not seeing any documentation on any events that I can use to achieve this. With TCP sockets this is done using the NewData() event.
Once I have received the message from the client I need to send back a response but again, I cannot find anything in the documentation on how to simply do this. Again, with TCP sockets this is done by using the Write() method of Asyncstreams.
In addition, when adding the websocket class/handler to the server I am wanting the class to be tied to the root path '/' but if I use this then I get errors about multiple servlets attempting to bind to the same path. So for the websocket class I have simply left it as an empty string (""). Is this the way to do it? If not, how can I add the websocket class to the root path "/"?
The above questions are moot until I can work out how to make a successful connection. This leads me to the next section...
Connection Error
When I attempt to make the connection to the server I get the following error message.
I have tried changing the port number from 65534 to 443 without any luck. There are no other web servers (apache/nginx) running that would/could interfere with the websocket connections on the VPS.
I would be most grateful to anyone that has any ideas on what to try next or if someone has successfully implemented secure websockets and is able to share their experience.
I have spent the last several days trying to work out exactly how to implement a client/server connection using secure websockets. I have had no joy in getting this to work. Below is an outline of what the hardware infrastructure is, what the requirements are and what I've tried to date.
I have searched and read just about every example in the forum for websockets. But, I still have a few questions about how to communicate between the client and server.
Requirement:
I need to have a desktop app (later will need Android / iOS, and web app) that will connect to a web app server using TLS1.2 secure web sockets.
This is a requirement for the client. Previously, I had everything working nicely with simple TCP Sockets. The requirement has come about due to the need to increase security and provide encryption between the client (a device - Android/iOS/custom hardware) and the server.
If there is a way to communicate between a client and server using TCP sockets while using SSL/TLS1.2 then please do let me know how to implement it. I could not find anything in the forums or documentation that explains how to do this.
Infrastructure:
What I have is a VPS hosted with Amazon Web Services (AWS) and an Elastic Load Balancer (ELB) in front of the VPS. Also, I have used LetsEncrypt.com to obtain a SSL certificate and successfully installed the certificate onto the VPS and on the ELB.
To the ELB I have added a Listener for SSL traffic on port 65534 and this is the port I need the web socket to connect to. I have also added listeners for HTTP and HTTPS (80 / 443 respectively) on the ELB. All three listeners also have the equivalent ports open in the Security Group assigned to both the VPS and the ELB.
What I Have Tried:
The below code snippet is what I currently have for the client.
Client
B4X:
Sub Process_Globals
Private webskt As WebSocketClient
Private uriRelayServer As String = $"wss://server.somedomain.com:65534"$
End Sub
Sub AppStart (Form1 As Form, Args() As String)
webskt.Initialize("RelayServerSSL")
webskt.Connect(uriRelayServer)
End Sub
Private Sub RelayServerSSL_Connected
' This sub never gets called - so far
lblStatus.Text = "Connected to server."
End Sub
Server
The next code snippet is what I have implemented in the server.
B4X:
Sub Process_Globals
Dim WebServer As Server
Dim mApplicationPort As Int = 65534
Dim KeyStorePassword As String = "some_password"
End Sub
Sub AppStart (Args() As String)
WebServer.Initialize("WebServer")
ConfigureSSL(mApplicationPort)
WebServer.AddWebSocket("", "App")
WebServer.Start
StartMessageLoop
End Sub
private Sub ConfigureSSL(SSLPort As Int)
Dim ssl As SslConfiguration
ssl.Initialize
' Do the following lines really need to be there?
' If they do then every time the SSL Cert expires a new keystore
' will need to be used.
' ssl.SetKeyStorePath(File.DirApp, "domain.keystore")
' ssl.KeyStorePassword = KeyStorePassword
' ssl.KeyManagerPassword = KeyStorePassword
WebServer.SetSslConfiguration(ssl, SSLPort)
End Sub
The 'App' WebSocket Class is barebones right now...
B4X:
'WebSocket class
Sub Class_Globals
Private ws As WebSocket
End Sub
Public Sub Initialize
End Sub
Private Sub WebSocket_Connected(WebSocket1 As WebSocket)
ws = WebSocket1
End Sub
Private Sub WebSocket_Disconnected
End Sub
Questions:
I understand how TCP Sockets work very well and I'm probably (most likely) not fully understanding how websockets work.
I require the client (a device) to send a message to the server and then the server to respond by sending a message back. With TCP sockets this is rather trivial and I am hoping that websockets will be just as simple.
How can I retrieve the message on the server that is sent by the client? I am not seeing any documentation on any events that I can use to achieve this. With TCP sockets this is done using the NewData() event.
Once I have received the message from the client I need to send back a response but again, I cannot find anything in the documentation on how to simply do this. Again, with TCP sockets this is done by using the Write() method of Asyncstreams.
In addition, when adding the websocket class/handler to the server I am wanting the class to be tied to the root path '/' but if I use this then I get errors about multiple servlets attempting to bind to the same path. So for the websocket class I have simply left it as an empty string (""). Is this the way to do it? If not, how can I add the websocket class to the root path "/"?
The above questions are moot until I can work out how to make a successful connection. This leads me to the next section...
Connection Error
When I attempt to make the connection to the server I get the following error message.
B4X:
Program started.
2016-03-28 19:17:42.518:INFO::JavaFX Application Thread: Logging initialized @6499ms
java.io.IOException: Cannot init SSL
at org.eclipse.jetty.websocket.client.io.WebSocketClientSelectorManager.newConnection(WebSocketClientSelectorManager.java:98)
at org.eclipse.jetty.io.ManagedSelector.createEndPoint(ManagedSelector.java:411)
at org.eclipse.jetty.io.ManagedSelector.access$1600(ManagedSelector.java:56)
at org.eclipse.jetty.io.ManagedSelector$CreateEndPoint.run(ManagedSelector.java:587)
at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.produceAndRun(ExecuteProduceConsume.java:213)
at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.execute(ExecuteProduceConsume.java:101)
at org.eclipse.jetty.io.ManagedSelector.run(ManagedSelector.java:136)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:654)
at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:572)
at java.lang.Thread.run(Thread.java:745)
java.io.IOException: Cannot init SSL
at org.eclipse.jetty.websocket.client.io.WebSocketClientSelectorManager.newConnection(WebSocketClientSelectorManager.java:98)
at org.eclipse.jetty.io.ManagedSelector.createEndPoint(ManagedSelector.java:411)
at org.eclipse.jetty.io.ManagedSelector.access$1600(ManagedSelector.java:56)
at org.eclipse.jetty.io.ManagedSelector$CreateEndPoint.run(ManagedSelector.java:587)
at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.produceAndRun(ExecuteProduceConsume.java:213)
at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.execute(ExecuteProduceConsume.java:101)
at org.eclipse.jetty.io.ManagedSelector.run(ManagedSelector.java:136)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:654)
at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:572)
at java.lang.Thread.run(Thread.java:745)
java.util.concurrent.ExecutionException: java.io.IOException: Cannot init SSL
at org.eclipse.jetty.util.FuturePromise.get(FuturePromise.java:123)
at anywhersoftware.b4j.objects.WebSocketClientWrapper.Close(WebSocketClientWrapper.java:76)
at anywhersoftware.b4j.objects.WebSocketClientWrapper$WSHandler.onWebSocketError(WebSocketClientWrapper.java:118)
at org.eclipse.jetty.websocket.common.events.JettyListenerEventDriver.onError(JettyListenerEventDriver.java:112)
at org.eclipse.jetty.websocket.client.io.ConnectPromise.failed(ConnectPromise.java:58)
at org.eclipse.jetty.websocket.client.io.WebSocketClientSelectorManager.connectionFailed(WebSocketClientSelectorManager.java:61)
at org.eclipse.jetty.io.ManagedSelector$Connect.failed(ManagedSelector.java:636)
at org.eclipse.jetty.io.ManagedSelector$Connect.access$1300(ManagedSelector.java:603)
at org.eclipse.jetty.io.ManagedSelector$1.failed(ManagedSelector.java:355)
at org.eclipse.jetty.io.ManagedSelector$CreateEndPoint.run(ManagedSelector.java:592)
at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.produceAndRun(ExecuteProduceConsume.java:213)
at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.execute(ExecuteProduceConsume.java:101)
at org.eclipse.jetty.io.ManagedSelector.run(ManagedSelector.java:136)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:654)
at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:572)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.io.IOException: Cannot init SSL
I have tried changing the port number from 65534 to 443 without any luck. There are no other web servers (apache/nginx) running that would/could interfere with the websocket connections on the VPS.
I would be most grateful to anyone that has any ideas on what to try next or if someone has successfully implemented secure websockets and is able to share their experience.