eclipse-paho / eclipse-paho/paho.mqtt.java

Unable to connect via SSL/WSS when no proxy is involved

Open
#854 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
Java
Stars
2.3k
Forks
919
PR merge metrics
No merged PRs in 30d

Description

Please fill out the form below before submitting, thank you!

- [X ] Bug exists Release Version 1.2.5 ( Master Branch)
- [X ] Bug exists in MQTTv3 Client on Snapshot Version 1.2.6-SNAPSHOT (Develop Branch)
- [X ] Bug exists in MQTTv5 Client on Snapshot Version 1.2.6-SNAPSHOT (Develop Branch)

Hi,

I'm trying to connect via SSL/WSS to some MQTT broker, through **optional** proxy. ~~It works fine behind a proxy~~, but I cannot make it work using direct connection.

The `TCPNetworkModule` class has a `start()` method where we can find the following code:
```
SocketAddress sockaddr = new InetSocketAddress(host, port);
socket = factory.createSocket();
socket.connect(sockaddr, conTimeout*1000);
```

So, I provide a custom `MySSLSocketFactory` class, extending `SSLSocketFactory`, where I override the default `createSocket()` method.

The main idea is to generate some `SSLContext`, then use its `getSocketFactory()` method to retrieve appropriate `SSLSocketFactory` and finally use one of its `createSocket` methods.

Behind a Proxy, there is no problem as we can write something like this:
```
Socket tunnelSocket = new Socket(myProxy);
tunnelSocket.connect(new InetSocketAddress(myProxyHost, myProxyPort), myTimeout);
return mySSLContext.getSocketFactory().createSocket(tunnelSocket, host, port, true);
```
We actually provide an ~~**unconnected**~~ socket (let's call it the "main socket") to the same host and port used by `TCPNetworkModule` when it defines `sockaddr`, but through some kind of a *proxied SSL tunnel*. Notice that the `tunnelSocket` **must** be connected before we call the above `createSocket` method, otherwise we get an "Underlying socket is not connected" `SocketException`.

then `TCPNetworkModule` connects this socket through the line
```
socket.connect(sockaddr, conTimeout*1000);
```
~~and all goes fine~~...

When no proxy is involved, we cannot use the above *tunneling* feature.

Let's try something like that:
```
return mySSLContext.getSocketFactory().createSocket(host, port);
```
Unfortunately, here we actually provide a **connected** main socket, as the above `createSocket(String host, int port)` method creates **and connects** the socket. Then, of course, when `TCPNetworkModule` connects this socket, we have an "already connected" `SocketException`.

We cannot write something like that
```
return mySSLContext.getSocketFactory().createSocket();
```
as creating an **unconnected** `Socket` seems forbidden and we get an "Unconnected sockets not implemented" `SocketException`.

I can see some simple solution, changing `TCPNetworkModule` code a bit, adding a simple condition:
```
if (!socket.isConnected()) {
socket.connect(sockaddr, conTimeout*1000);
}
```
I guess that it should solve the problem.

Best regards

Contributor guide

Open the contributing guide

Research direction

Start in TCPNetworkModule.start(), then trace how its socket.connect call interacts with the SSLSocketFactory createSocket methods described in the issue. Verify that direct SSL/WSS connections work when the factory returns an already-connected socket, while proxied connections continue to work without an already-connected exception.

Written by the indexing model from the issue text.

Assessment

Tech stack
java
Domain
networking
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.