智能家居设备的另一种打开方式——如何控制局域网中的小米设备

近两年,物联网技术发展迅猛,各样的智能设备渐渐地走进了我们的家居生活。在众多的智能设备厂商中,小米是较早的布局智能家居生态的厂商,购买智能家居设备的用户几乎都会有一到两个小米设备。那么是否可以控制这些小米设备呢,其中过程是否会有安全风险呢?本文接下来会主要介绍这些内容。

具体地,除了米家app控制小米设备外,小米还提供一种局域网控制的方式,但前提是要获得用于设备认证一串字符串(即token),所以接下来主要介绍如何获取设备token,以及如何实现局域网控制设备。

一、总体流程介绍

在同一局域网下,小米设备可以使用专有的加密UDP网络协议miio协议通信控制。在网络可达的前提下,向小米设备发送一串hello bytes即可获得含有token的结构体数据。之后,构造相应的结构体,并以同样的方式发送给设备即可实现控制。具体流程如下图所示:

二、小米设备token获取

小米设备的token获取有三种途径,如下所述:

2.1 miio获取token

miio有基于Python实现的库,其Github项目地址为:https://github.com/rytilahti/python-miio。该项目支持所有兼容miio协议的设备,并将设备发现、识别和控制的方法进行了分类。

2.1.1 环境安装

python-miio需要Python3.5以上版本上才能运行,所以首先搭建Python环境。下面,我们在操作系统为Ubuntu的电脑或者树莓派中安装Python3.5:

  • 安装5依赖(本机存在的会忽略)

  • 编译安装5

  • 编译后运行一下5,结果如下证明安装成功

  • 安装miio库,下载库代码到本地并安装

2.1.2 通过脚本获取token

下面就以小米智能插座为例,说明如何获取该设备的token。

  • 脚本编写

首先要保证获取token的客户端要与插座网络可达。为了显示直观,我们将主要实现代码从库中提取出来(如下)。将文件放在python-miio/miio目录下(该脚本主要就是使用socket向设备ip的54321端口发送固定字符串,返回值即为设备token):

  • 运行:5 miio_test.py

返回如下消息结构,其中checksum即为设备的token,解码之后为:’1d0616858062b8f836ebcacc98e62dd2’。

支持这种方式拿token的还有小米的空气净化器、净水器、扫地机器人、智能插座插线板等。具体列表见https://github.com/rytilahti/python-miio

2.2 从米家app获取token

如果能用上述的探测方法获取token还是比较便捷的,但目前只有部分小米设备支持。接下来还有一种方法可以直接从app获取token。以小米绿米网关为例:首先下载米家app,将绿米网关配置入网后,点击网关设备。接下来步骤如下组图,最后的密码即为网关的token。

目前绿米的这种设计模式是用户友好的,而且设备的所有者还可以选择是否开放局域网控制以及刷新控制token的有效性,比较安全。个人还是很希望小米的其他设备同样开放app侧获取设备token,因为毕竟获取需要搭建复杂的环境以及调试代码,大部分使用者应该不能接受的。

2.3 从数据库获取token

该方法是读取手机中米家的app中的数据记录来获取设备的token,具体步骤如下:

  • 准备一部获取root权限的安卓手机
  • 安装米家app并登录账号
  • 进入/data/data/com.xiaomi.smarthome/databases/
  • 拷贝db,下载到电脑
  • 前往网站(http://miio2.yinhh.com/),上传db,点击提交,即可获得token。

因为没有root的安卓手机,笔者没有具体测试这种方式获取token的有效性,具体可以参考这篇文章(https://homekit.loli.ren/docs/show/12)

三、控制小米WiFi插座

如果获得了token,就能对小米的设备进行操作,接下来介绍使用miio协议控制小米插座的主要步骤。

3.1 控制脚本编写

基于1.1.2获取到的回传的token信息,构造如下数据结构,用来控制设备。

其中:

token为获取到的设备token;

device_id为获取token返回结构中的device_id字段;

ts是一个时间结构,控制传的ts的需要在获取到ts基础上加1秒;

cmd中的method包括:set_power(控制开关)、get_prop(获取状态),控制的params是[‘on’]/ [‘off’],获取状态的params是[‘power’, ‘temperature’]

下面的代码是实现打开插座的控制,其中插座的IP为192.168.42.17。

3.2 执行控制脚本

执行上面编写的控制代码,得到返回状态,如果返回状态中value变量中的result字段为[ ‘ok’],即为控制成功。当cmd使用get_prop方法时,如果返回的value变量值为{‘id’: 1, ‘result’: [‘on’, 59]}时,表示插座状态是开的,温度为59℃。因为篇幅关系具体就不贴了。

四、总结

从目前的智能家居市场来看,用户不会只使用单个智能设备厂商的设备,所以对于厂商来说,通过开放接口给用户一些局域网的控制“自由”,实现不同厂商设备的联动是一个不错的选择。

从另外一个角度,本文中体现的安全问题我们也不容忽视。如果如2.1所示在局域网中不经过认证就能获取物联网设备的访问凭证,并进而进行控制,无形中给入侵者留了一扇门。例如,攻击者可经过扫描互联网发现家庭路由器,并利用弱口令或设备漏洞获得路由器的shell权限,接下来就可按照文中步骤就可以获得设备token进而控制。

在接下来的文章中,我们会给大家介绍一些智能家居的平台,以及家庭环境中智能设备的一些安全防护方法,让智能与安全同行。

发表评论