shamblett / mqtt_client

A server and browser based MQTT client for dart
Other
548 stars 176 forks source link

Secured socket connection with MQTT broker using latest version cannot work #372

Closed Flynn2018 closed 2 years ago

Flynn2018 commented 2 years ago

Hello friends, I built an mqtt broker using mosquitto and work normally. The certificate configuration in mosquitto.conf is as follows: # Port to use for the default listener. port 8883

# At least one of cafile or capath must be defined. They both # define methods of accessing the PEM encoded Certificate # Authority certificates that have signed your server certificate # and that you wish to trust. # cafile defines the path to a file containing the CA certificates. # capath defines a directory that will be searched for files # containing the CA certificates. For capath to work correctly, the # certificate files must have ".crt" as the file ending and you must run # "c_rehash <path to capath>" each time you add/remove a certificate. #capath cafile /cert/ca.crt

# Path to the PEM encoded server certificate. certfile /cert/server.crt

# Path to the PEM encoded keyfile. keyfile /cert/server.key

# This option defines the version of the TLS protocol to use for this listener. # The default value allows v1.2, v1.1 and v1.0, if they are all supported by # the version of openssl that the broker was compiled against. For openssl >= # 1.0.1 the valid values are tlsv1.2 tlsv1.1 and tlsv1. For openssl < 1.0.1 the # valid values are tlsv1. tls_version tlsv1

The steps to generate the certificate files used above are as follows:

  1. generate CA key and certificate openssl req -new -x509 -days 36500 -extensions v3_ca -keyout ca.key -out ca.crt
  2. generate private key and certificate for the server, and sign it using the above CA openssl genrsa -out server.key 2048 openssl req -out server.csr -key server.key -new openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 36500

Now I write and Flutter APP using https://pub.flutter-io.cn/packages/mqtt_client package (v9.6.6), and some key codes are as follows:

MqttServerClient _client = MqttServerClient.withPort('192.168.0.251', "", 8883); // 192.168.0.251 is the broker server IP
_client.secure = true;

// Set the certificate info
final SecurityContext context = SecurityContext.defaultContext;
try {
    var caCerData = await rootBundle.load('assets/ca.crt');
    context.setTrustedCertificatesBytes(caCerData.buffer.asUint8List());

    var serverCerData = await rootBundle.load('assets/server.crt');
    context.useCertificateChainBytes(serverCerData.buffer.asUint8List());
    var serverKeyData = await rootBundle.load('assets/server.key');
    context.usePrivateKeyBytes(serverKeyData.buffer.asUint8List());
} on Exception catch (e) {
    print("SSL set error : " + e.toString());
}
_client.securityContext = context;
_client.setProtocolV311();

When invoking the await _client.connect();, I always get the 'UNSUPPORTED_PROTOCOL' error, so secure socket connect cannot get work:

I/flutter (26255): 1-2022-04-22 12:42:04.374417 -- MqttClient::connect - keep alive is enabled with a value of 60 seconds
I/flutter (26255): 1-2022-04-22 12:42:04.409720 -- MqttConnectionKeepAlive:: Initialised with a keep alive value of 60 seconds
I/flutter (26255): 1-2022-04-22 12:42:04.425497 -- MqttConnectionKeepAlive:: Disconnect on no ping response is disabled
I/flutter (26255): 1-2022-04-22 12:42:04.452049 -- MqttConnectionHandlerBase::connect - server 192.168.0.251, port 8883
I/flutter (26255): 1-2022-04-22 12:42:04.461200 -- SynchronousMqttServerConnectionHandler::internalConnect entered
I/flutter (26255): 1-2022-04-22 12:42:04.464629 -- SynchronousMqttServerConnectionHandler::internalConnect - initiating connection try 0, auto reconnect in progress false
I/flutter (26255): 1-2022-04-22 12:42:04.469895 -- SynchronousMqttServerConnectionHandler::internalConnect - secure selected
I/flutter (26255): 1-2022-04-22 12:42:04.480486 -- SynchronousMqttServerConnectionHandler::internalConnect - calling connect
I/flutter (26255): 1-2022-04-22 12:42:04.496803 -- MqttSecureConnection::connect - entered
I/flutter (26255): 1-2022-04-22 12:42:05.095989 -- MqttConnectionBase::_onError - calling disconnected callback
I/flutter (26255): MqttUtils::client exception - HandshakeException: Handshake error in client (OS Error: 
I/flutter (26255):  **UNSUPPORTED_PROTOCOL**(handshake_client.cc:697))
I/flutter (26255): MqttUtils::ERROR 192.168.0.251 client connection failed - disconnecting, status is Connection status is faulted with return code of noneSpecified and a disconnection origin of none
I/flutter (26255): mqtt connect fail

Some questions here:
1.As the above mosquitto broker server using tlsv1, Can the package mqtt_client configure the supported TLS version?

  1. Is the code that configure the certificate for SecurityContext correct? and not sure the reason why cannot connect the secured mqtt broker?
KarlMarxs commented 2 years ago

I have the same problem, please answer

shamblett commented 2 years ago

In answer to your questions -

  1. The client is not capable of configuring any TLS parameters I know of, the TLS implementation is in the Dart runtime, see the secure sockets API for more information although I believe dart does support TLS v1.
  2. Again, the client does nothing here except pass the security context you supply it to the secure socket layer, see here for details on the security context API. It does allow you to negotiate ALPN protocols which your code above doesn't seem to be doing. I can't really comment on how you generate your certificate except it must conform to whatever requirements the security context API places on it.
Flynn2018 commented 2 years ago

In answer to your questions -

  1. The client is not capable of configuring any TLS parameters I know of, the TLS implementation is in the Dart runtime, see the secure sockets API for more information although I believe dart does support TLS v1.
  2. Again, the client does nothing here except pass the security context you supply it to the secure socket layer, see here for details on the security context API. It does allow you to negotiate ALPN protocols which your code above doesn't seem to be doing. I can't really comment on how you generate your certificate except it must conform to whatever requirements the security context API places on it.

Actually, I noticed the method setAlpnProtocols (List protocols, bool isServer), however it does not clear describe how to pass the value for the first parameter protocols. Should we use context.setAlpnProtocols(['tlsv1', 'tlsv2'], false) or context.setAlpnProtocols(['tlsv1.1', 'tlsv1.2'], false)? Also, should we use which one (true or false) for the second parameter in my case?

Flynn2018 commented 2 years ago

After reading some document these days, it seems that the dart doesn't support self signed certificate. So cannot add the self signed certificate to the Flutter app local trust certificate store. Anyone has some suggestions?

kira2015 commented 2 years ago

After reading some document these days, it seems that the dart doesn't support self signed certificate. So cannot add the self signed certificate to the Flutter app local trust certificate store. Anyone has some suggestions?

I also encountered,flutter cannot add the self signed certificate to the flutter App Local Trust Certificate Store