Having problems connecting with M2MQTT client library to AWS IoT using ALPN on port 443

1.5k views Asked by At

I'm using the .net Framework build of m2mqtt.net (available here: https://github.com/mohaqeq/paho.mqtt.m2mqtt). Connecting with standard mqtt on port 8883 works fine:

_MqttClient = new MqttClient(IoTHost, IoTPort, true, certificate.CertCA, certificate.CertClient, MqttSslProtocols.TLSv1_2);

Connecting with mqtt on port 443 with ALPN extension doesn't work:

_MqttClient = new MqttClient(IoTHost, IoTPort, true, certificate.CertCA, certificate.CertClient, MqttSslProtocols.TLSv1_2, new RemoteCertificateValidationCallback(RemoteCertificateValidationCallback), new LocalCertificateSelectionCallback(SelectLocalCertificate), ALPNProtocols);

ALPNProtocols argument is set up per requirements:

List<string> ALPNProtocols = new List<string>();
ALPNProtocols.Add("x-amzn-mqtt-ca");

When I connect (_MqttClient.Connect(serial);) everything runs smoothly in the m2mqtt.net project file until it reaches line 1102 in MqttClient.cs:

// wait for answer from broker
if (this.syncEndReceiving.WaitOne(timeout))

It then waits for 30 secs and then times out and throws an exception: "Exception of type 'uPLibrary.Networking.M2Mqtt.Exceptions.MqttCommunicationException' was thrown."

I did a network trace and there is no ALPN information/negotiation seen in the TLS handshake, so probably that's why the server doesn't reply.

I'm running the standard project without any modifications. SSL symbol is defined, project is set to .net framework 4.5.

I assume ALPN is supported in the .net framework version of the build since nothing is mentioned here: https://libraries.io/nuget/M2MqttDotnetCore. I can't seem to find any issues with my ALPN arguments.

Anybody had any luck with this?

1

There are 1 answers

0
WeekendHacker On

I think the below code snippet taken from MqttNetworkChannel.cs shows that M2Mqtt will only respect the ALPN argument if it's running in a .net standard/.net core environment.

It would have been nice if the documentation made clear that ALPN is not supported in the .net framework build...

#if (NETSTANDARD1_6 || NETSTANDARD2_0 || NETCOREAPP3_1)

                if ((this.alpnProtocols != null) && (0 < this.alpnProtocols.Count))
                {
                    this.sslStream = new SslStream(this.netStream, false);
                    SslClientAuthenticationOptions authOptions = new SslClientAuthenticationOptions();
                    List<SslApplicationProtocol> sslProtocolList = new List<SslApplicationProtocol>();
                    foreach (string alpnProtocol in this.alpnProtocols)
                    {
                        sslProtocolList.Add(new SslApplicationProtocol(alpnProtocol));
                    }
                    authOptions.ApplicationProtocols = sslProtocolList;
                    authOptions.EnabledSslProtocols = MqttSslUtility.ToSslPlatformEnum(this.sslProtocol);
                    authOptions.TargetHost = remoteHostName;
                    authOptions.AllowRenegotiation = false;
                    authOptions.ClientCertificates = clientCertificates;
                    authOptions.EncryptionPolicy = EncryptionPolicy.RequireEncryption;

                    this.sslStream.AuthenticateAsClientAsync(authOptions).Wait();
                }
                else
                {
                    this.sslStream.AuthenticateAsClientAsync(this.remoteHostName,
                        clientCertificates,
                        MqttSslUtility.ToSslPlatformEnum(this.sslProtocol),
                        false).Wait();
                }
#else
                this.sslStream.AuthenticateAsClient(this.remoteHostName,
                    clientCertificates,
                    MqttSslUtility.ToSslPlatformEnum(this.sslProtocol),
                    false);
#endif