homieiot / homie-esp8266

💡 ESP8266 framework for Homie, a lightweight MQTT convention for the IoT
http://homieiot.github.io/homie-esp8266
MIT License
1.36k stars 308 forks source link

Allow disabling of configuration mode on initial boot #125

Closed rakeshpai closed 8 years ago

rakeshpai commented 8 years ago

I am building a standalone device that should work by itself even in the absence of a network setup. It's a bunch of sensors that decide if a relay should turn on. If I make this device and give it to my friends, and they never connect it to a wifi, it should still function well locally. If they choose to connect it to the network, the device will publish sensor and relay status over mqtt, essentially logging its behavior.

Homie almost fits this perfectly. I can check in the main arduino loop() if the network is available (.isReadyToOperate()) and only then publish (.setNodeProperty(...)), which should do the trick.

This however poses a security risk. Since my friends might never bother with trying to get these logs, they might never configure the device to connect. This means Homie will open an AP for curious neighbors with which they can claim the device and view its activity.

A solution can be to make the configuration-mode-on-boot optional, and let it boot into normal mode. In this normal mode, .isReadyToOperate() can return false and setupHandler and loopHandler are never called, as one would expect.

If the user wants configuration mode, it could be done by proving that they have physical access to the device. In fact the current 5-second-hold reset button behavior which boots into configuration mode would work just fine.

So, really the only API change needed is a way to disable configuration mode on first boot. Not sure how big a change this is internally though. Is this something that fits within Homie?

marvinroger commented 8 years ago

This would defeat the purpose of Homie for ESP8266, which is basically to provide a framework for a network-enabled sensor. This is actually the whole point of the framework. I am not in favor of implementing this, to be honest! I won't close the issue, as you may not be the only one who would like this feature, so this is not a definitive no, let's call this an on hold. :)

rakeshpai commented 8 years ago

Thanks for the quick response, Marvin. I'm fine with waiting for consensus. :)

I disagree that this defeats the purpose of Homie though. In fact, I think it fits like a glove, and that's evidenced by almost no other change required to make it work. (Homie is awesome!)

Take for example a motion controlled light switch that turns off on a timeout. It doesn't need network connectivity for its basic functionality. However, when connected, we could configure the switch's turn off timeout by publishing a retained property for the node (thus overriding a hard-coded default).. Or we could use the motion sensor's published data to do occupancy tracking. Point being that the network connectivity is what makes the node interesting, but it is functional even without the network ever being configured. It's a form of resilience from network unavailability, if you will. It looks like I can actually do all of this with Homie already (which again shows that Homie is awesome for this), just that I'll have an open AP that I can't turn off unless Homie is configured first.

Another way to think about this is to consider the experience of installing Homie devices. If the device isn't configured immediately when powered up, it is open to be claimed by anyone in range, which is a security problem. This problem is especially big when configuration can't be done immediately, for example when physical installation is done by an electrician, and configuration is done by a system administrator / home owner at a later time.

Hope this helps clarify why I think Homie is a perfect fit here, and all that's needed is something like Homie.disableConfigModeOnBoot() to prevent the AP from starting by default. I don't mind waiting for other opinions though. :)

marvinroger commented 8 years ago

You've conviced me. It is very simple to implement by the way, so it'll land into the v2.

Thanks for the idea :+1:

rakeshpai commented 8 years ago

Thanks for considering this suggestion. :)

As I think about it though, I think even more fine-grained control might be more desirable. I'm coming from the point of view that an open AP that allows reconfiguration of the device is a bad idea from a security standpoint, even if unavoidable. So, it's a good idea to keep the AP open only for short periods of time, ideally when the user has demonstrated that he/she has physical access. So, the AP should close itself based on a timeout, say a minute, which will avoid at least the casual hackers.

Two possible ways to implement this come to mind. First, provide a .startConfigurationMode() and .endConfigurationMode(). While this provides the best flexibility, it requires boilerplate code in the sketch. The second is that APs time out by default (timeout could be configurable with a .setConfigModeTimeout(...)). This is slightly more opinionated, but encapsulates good practices and reduces boilerplate. The user does the 5-second reset to get back into config mode, thus proving that he/she has physical access.

I can't decide which is better. The first gives full programmatic control, while the second reduces boilerplate. Maybe Homie can actually do both, with the second option being implemented in terms of the first.

Hope that made sense. I'm happy to clarify if you want. Wish I could contribute code, but I'm not good with C++.

flaviostutz commented 8 years ago

I was implementing a pull request almost like this!

My scenario is:

Requirements:

I will like this feature very much! +1!

Thanks.

Sent from my iPhone

On Aug 13, 2016, at 16:06, Rakesh Pai notifications@github.com wrote:

Thanks for considering this suggestion. :)

As I think about it though, I think even more fine-grained control might be more desirable. I'm coming from the point of view that an open AP that allows reconfiguration of the device is a bad idea from a security standpoint, even if unavoidable. So, it's a good idea to keep the AP open only for short periods of time, ideally when the user has demonstrated that he/she has physical access. So, the AP should close itself based on a timeout, say a minute, which will avoid at least the casual hackers.

Two possible ways to implement this come to mind. First, provide a .startConfigurationMode() and .endConfigurationMode(). While this provides the best flexibility, it requires boilerplate code in the sketch. The second is that APs time out by default (timeout could be configurable with a .setConfigModeTimeout(...)). This is slightly more opinionated, but encapsulates good practices and reduces boilerplate. The user does the 5-second reset to get back into config mode, thus proving that he/she has physical access.

I can't decide which is better. The first gives full programmatic control, while the second reduces boilerplate. Maybe Homie can actually do both, with the second option being implemented in terms of the first.

Hope that made sense. I'm happy to clarify if you want. Wish I could contribute code, but I'm not good with C++.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub, or mute the thread.

marvinroger commented 8 years ago

@rakeshpai implemented! You have to call Homie.setStandalone() before Homie.setup() to boot the device in standalone mode. This is a special mode that only handles the reset (the same way it works from normal mode to config mode).

@flaviostutz this is not exactly the same thing, closing this issue as the initial request is implemented. :)

About AP timeouts, exposing the device for 1 minute or an hour will expose it to the same risks. As you say, this is unavoidable, because if an attacker wants to attack you, it will probably be an automated attack anyway. The only secure solution would be a PIN on an OLED screen or something, but we can't require an OLED screen...