MQTT Auth transfer for EmonESP WIFI devices + Device module

As part of the recent developments exploring the further integration of the device module as developed by @nchaveiro into emoncms and the input interface I have been working on a way to simplify the setup procedure of WIFI devices running EmonESP.

The idea is to reduce the setup requirement of an EmonESP node down to just signing on to a local network and for the additional settings such as MQTT authentication details to be transferred by a special mechanism from the basestation to the EmonESP node.

A user logging in to emoncms on their basestation (emonbase/emonpi) would see a notification saying that device called say “EmonTx WIFI” on ip address 192.168.1.103 would like to connect, with the option to “Allow” or “Deny”.

If the connection is allowed the MQTT username and password would essentially be made available specifically to the IP address of the requesting device for a brief time. Ideally the whole process would take place over a HTTPS/TLS connection.

Initial basestation discovery could be performed by using hostnames such as emonpi.local but in the event that this fails or is unreliable there would be a fall back to a UDP Broadcast method.

I would be interested to hear of peoples experience with hostname reliability on different networks, I’ve had a bit of trouble with getting hostnames to work reliably or at all on the emonesp and so my prototyping so far has used a UDP Broadcast from the basestation.

Initial device discovery and MQTT authentication

  1. WIFI device attempts to connect to emonpi.local hostname or picks up UDP broadcast.
  2. WIFI device sends an authentication request to a special API on the basestation.
  3. Base station receives authentication request and in doing so now knows the smart meter’s IP Address.
  4. Base station displays message to user in an authenticated context:
    “Device “EmonTx WIFI” is requesting a connection, allow or deny access”
  5. User clicks “Allow”
  6. Hub provides ideally a TLS enabled API with access restricted to the IP Address of the requesting device temporarily, to which the WIFI Device connects in order to retrieve the MQTT authentication details.
  7. WIFI Device saves MQTT authentication details
  8. WIFI Device attempts MQTTS connection
  9. WIFI Device publishes data

Re-discovery of new ip address - using UDP Broadcast

  1. WIFI Device waits for UDP Broadcast from base station
  2. WIFI Device attempts secure connection to UDP Broadcast detected IP Address.

I can see one potential issue where an attacker places another device on the network which sends a UDP broadcast or changes/pushes the hostname of the original basestation from emonpi.local to emonpi-2.local. The WIFI device would then attempt a mqtt connection to the impersonating device giving the MQTT details to the impersonating device.
Im not sure what the best way of addressing this would be, but it does rely on a compromised local area network to begin with, interested in anyone’s thoughts?

Prototype 1

I have a prototype of the above working and implemented in the device-integration branch of emoncms. The code that handles the authentication request API can be found here:

https://github.com/emoncms/emoncms/blob/device-integration/Modules/device/device_controller.php#L35

A request to

http://emonpi.local/emoncms/device/auth/request.json 

will return the message “request registered”

The emoncms inputs interface then shows the following notification:

Once allow has been clicked by the user a subsequent auth/request API call, limited to the devices IP Address and within a time limited 60 second window, returns the MQTT details.

The “fetchmqttauth_async” branch of EmonESP handles the WIFI device part primarily handled in the file autoauth.cpp here: https://github.com/openenergymonitor/EmonESP/blob/fetchmqttauth_async/src/autoauth.cpp

Can anyone see any big holes in this approach? suggestions welcome.

You shouldn’t need any other method for discovery than mDNS, any alternative is unlikely to be any more reliable as UDP broadcast is how mDNS works (well it uses multicast but the principle is the same and broadcast shouldn’t be used as it is not available in IPv6 and generally not friendly to the network).

Which libraries have you used for mDNS resolution? I have tried (and am partly through integrating) esp8266_mdns but there also looks to be a client build into the ESP8266 core now (but not hooked into the normal DNS resolution so you can’t just resolve emonesp.local as far as I can see).

Thanks @jeremypoulter, It would be great if we can rely on mDNS. @glyn.hudson mentioned he had hostnames working with emonesp but it did not work for me, I havent looked into the implementation either though, it sounds like your suggesting its not in there at all?

Great if you’re working on it!

I have always been curious about this, the docs do look to indicate that it should just work, however I too have never got it working with the current code. I suspect that it is not mDNS that is being used and just normal DNS and a helpful router (eg OpenWRT).

I will make an effort to complete the mDNS client work.

Just found an example of using mDNS to discover an MQTT server: https://github.com/arendst/Sonoff-Tasmota/blob/master/sonoff/support.ino#L581

1 Like