LabVIEW-Open-Source / MQTT-Client

A LabVIEW-based client for MQTT
Other
27 stars 5 forks source link

Trouble connecting to Google IoT Core - Network connection refused by server #15

Open Hero-Engineering opened 2 years ago

Hero-Engineering commented 2 years ago

Hello! I'm trying to connect the published client to Google IoT Core and getting a TCP Open (Error 63) after Connect to Server (network connection refused by server, serial buffer overflow). I'm probably doing something wring in configuring the TCP.

Please see sample screenshot of VI attached. I've verified that my credentials (device private key, CA authority) work on a sample mqtt client provided by the Google IoT Core team.

For reference, I'm following this quick start guide from Google IoT Core: https://cloud.google.com/iot/docs/create-device-registry It involves creating a device key pair (rsa_private.pem for the private key, rsa_cert.pem for public key), and downloading Google's CA (roots.pem). The public key information is shared with Google IoT Core, then we set up some topics such that commands can be sent. The sample mqtt client provided by Google can be found here: git clone https://github.com/googleapis/nodejs-iot.git

Here are potential areas of concern that might be causing the error

1) In Secured TCP Client.vi, I'm unsure what to put for the input named "address", so I've left it blank. The hostname is: "mqtt.googleapis.com", the port is 8883, and the Server X.509 certificate is pointed towards roots.pem. Also, not sure what read mode to configure - or if this has any effect

2) Do we need the "Configure Secured TCP Client Certificate and Key VI"? From the sample mqtt client provided by Google, the client authenticates with a username - "unused", and a JWT signed by the client private key. I submit this information in the "Connect To Server" VI.

3) Do we need to establish the topic in the payload variable of "Connect To Server", or can we do it after the server has connected? I presume the latter.

Any help would be much appreciated! Thanks!

image

francois-normandin commented 2 years ago

@Hero-Engineering

I think you are correct in your assessment that 1) is wrongly configured.

AWS does not require any username/password combo, but the way you specify it seems fine with respect to username/JWToken.

Here is a screenshot of the configuration used for AWS IoT Core: image

You'll notice that the first configuration VI is for the Server config. That's where you set the URI, the root/server certificate along with one of the hostnames associated with this certificate (usually the same as the URI). You use this node to configure how the client authenticates the server.

The second configuration VI is for the client. This is needed ONLY if the server needs to authenticate the clients (and prevent any unauthorized client from connecting in the first place). To do that, you need the client's certificate (public key that the server uses to validate the signed request) and the client's private key which the client uses to encrypt message. It seems that Google IoT at least accepts that the user could supply a JSON Web token instead of authenticating with a private key. In this case, I don't think you would need the second config VI.

EDIT: For anyone reading this thread, the Secured TCP Connection library (LV2020+) is a pre-requisite extension to connect using LabVIEW's native TLS. https://github.com/LabVIEW-Open-Source/MQTT-Connection-SecuredTCP

francois-normandin commented 2 years ago

If you are creating a certificate and private key for your IoT device, I would be surprised if you need a username/token... But I can be wrong. I have not gone through the doc you referenced for Google Cloud.

EDIT:

You already have those correctly setup, but for documentation purpose, here there are some more pointers.

Hero-Engineering commented 2 years ago

Thanks francois! So I verified both of your points .... I've got the correct google root certificate, and the write clientID. When I try to emulate your block diagram, where the hostname is wired to the address as well (mqtt.googleapis.com), I get the following error. Perhaps I've got my configuration wrong? In the password input of the Secured TCP Client Certificate, I've put the signed token (which is signed by the device private key) .. same error. Even with password unwired.

Error -715050 occurred at Start TLS in Connection.TCP-TLS.lvclass:onConnection.vi:590001->Connection_GOSPL.lvlib:Connection.lvclass:Connect.vi:3060002->MQTT Client.lvlib:Client.lvclass:Connect to Server.vi:7180001->Test Google Cloud PubSub.vi

Possible reason(s):

LabVIEW: (Hex 0xFFF516D6) REMOTE HOST IDENTIFICATION HAS FAILED! Certificate verification failed. The remote application could not prove its identity against our trusted certificate store. This error may appear during security attacks on your network, such as man-in-the-middle attacks. It also appears if the trusted certificate store is misconfigured, and in other mundane circumstances.

francois-normandin commented 2 years ago

You're getting close because I remember getting a similar error and I was basically one parameter from getting it correct. One of the parameter is not quite right, but you are establishing a connection to a proper domain. The message seems to imply something with one of the certificates. Check that the root cert you have is for the googleapis.com and not the LTS root.

This reference might be of help: (https://cloud.google.com/iot/docs/how-tos/mqtt-bridge). It seems the hostname is fine, but you can also use the long-time support domain.

At a glance, it looks like Google API needs the JWT in the password field. They recommend setting the hostname to ignoreor unused, but it's really to fool the clients that will sometimes reject an empty username. Google API does not use the username at all.

Also, maybe specify the keep-alive to 60sec or more. It should be already set by default, but I've seen this be a concern with Mosquitto.

Hero-Engineering commented 2 years ago

Thanks Francois! following the instructions in the Google API (using paho as the client), the JWT is set as the password parameter as you mentioned. I've tried wiring the JWT into the password input of Configure Secured TCP Client Certificate and Key VI, and in the payload settings of the Connect to Server VI, as well as both - no luck. I've also tried your other suggestions - no good.

I'll try and dig deeper .. maybe there's a typo or something.