5

My code is connecting to AWS-END-POINT properly but when I tried connecting to Greengrass core using local network ip. I get this error.

E/flutter (12349): [ERROR:flutter/lib/ui/ui_dart_state.cc(148)] Unhandled Exception: HandshakeException: Handshake error in client (OS Error:
E/flutter (12349): CERTIFICATE_VERIFY_FAILED: Hostname mismatch(handshake.cc:352))

I have already checked the greengrass core. it's working fine. It is connecting to web client very well. I think there might be some issue of using ip address instead of URL address. but i am not sure. Can anyone help please?

The Code I am running is:

import 'dart:async';
import 'dart:io';
import 'package:mqtt_client/mqtt_client.dart';
import 'dart:convert' show utf8;
import 'dart:convert';
Future<int> main() async {
  const String url =
      '192.168.8.106';
  const int port = 8883;
  const String clientId =
      'MY CLIENT ID';
  MqttClient client = MqttClient(url,clientId);
  client.port = port;
  client.secure = true;
  final SecurityContext context = new SecurityContext(withTrustedRoots: true);
 context.setTrustedCertificatesBytes(utf8.encode(' CERT '));
    context.useCertificateChainBytes(utf8.encode(' CERT '));
      context.usePrivateKeyBytes(utf8.encode(' PRIVEATE KEY '));
  client.securityContext = context;
  client.setProtocolV311();
  // logging if you wish
  client.logging(on: false);
   print('Before Connecting');
 try{
await client.connect();
 }catch(e){
   print('CATCH IS : ');
print (e);
 }
   print('After Connecting');
  if (client.connectionStatus.state == MqttConnectionState.connected) {
    print('iotcore client connected');
  } else {
    client.disconnect();
  }
  print('Sleeping....');
  for (int i=1; i>0; i++)
    {
        const String topic = '\$aws/things/Pi_tmfacility_0_1/shadow/update';
        Map<dynamic, dynamic> payload = 
    {'state': {
      'desired': {
        'number' : i
      }
    }
    };
        final MqttClientPayloadBuilder builder = MqttClientPayloadBuilder();
      builder.addString(json.encode(payload));
      print('into the publish to get single device shadow ');
      client.publishMessage(topic, MqttQos.atMostOnce, builder.payload);
     print('Ready to Sleep');
    await MqttUtilities.asyncSleep(10);
    print('Loop no = $i');
  } 
  print('Disconnecting');
  client.disconnect();
  return 0;
}
Muhammad Usama
  • 321
  • 1
  • 4
  • 12
  • open https url "https://192.168.8.106:8883" in browser i think you will get certificate error coz certificate is not valid as per ip.you try to use and http url of local resource – Dev Dec 13 '19 at 08:03
  • I am trying to make mqtts connection instead of https so obviously it would not open anything in browser. But i have connected using mqttfx desktop client and it connects instantly – Muhammad Usama Dec 13 '19 at 08:22

2 Answers2

4

The problem is that the CN (or SANs) in the certificate presented by the local machine do not include 192.168.8.106.

You can verify this by using the openssl s_client command:

openssl s_client -connect 192.168.8.106:8883 -CAfile /path/to/ca/cert

This means that the SSL/TLS library in flutter will complain that certificate doesn't reliably represent that machine.

This is important as this is what stops Man-in-the-Middle attacks.

You have 2 options to solve this.

  1. reissue the certificate with a CN or SAN entry with 192.168.8.106
  2. See if you can find a way to influence the Certificate verification. There are examples of how to do this with the dart http library (https://stackoverflow.com/a/59303283/504554) but I haven't found this in the MQTT client library (I haven't looked that hard).

You have to be very careful if you go with option 2 to ensure that you do not open up too big a hole for Man-in-the-middle attacks.

hardillb
  • 54,545
  • 11
  • 67
  • 105
1

I got the same error in my flutter app but my solution and reason was a bit different.

My certificate was "*.xxxxxx.com" (star certificate). (xxxxxx.com is not for +18 site, just sample :) )

My subdomain name was sub_domain.xxxxxx.com.

Solution was simple, but it take time to solve it.

"_" (underscore) was the main problem in the domain name. I changed it to subdoman.xxxxxx.com and it worked.

Davut Engin
  • 811
  • 8
  • 9