网上看了一些台灯,最后选了这一款,据说得了2017 iF 设计金奖,不过最主要是价格还合适。小米和飞利浦有合作的智能台灯,不过评价都不是很好,价格也高,也就没选。这个台灯很多人说不喜欢红线裸露,也有人说这个是亮点,产品设计者说这是故意裸露出来的。我觉得价格合适,控制方便,外观设计也过得去,也就它了。
可以通过手机App来控制,调节亮度色温,响应速度很快。
使用IoT安全测试环境来简单的分析下通信过程。
域名解析
台灯打开后,通过dhcp获取IP地址,然后解析了一个域名地址ot.io.mi.com,这个就是米家的云端。
可以看到这个域名的A记录有很多IP地址,后面与云端通讯时会选择其中一个,开始不间断的与云端进行通信,所有通讯都是UDP的。一般设备断电重启会重新选择一个云端地址。
心跳
每隔几秒,台灯会向云端发送一个报文,Len=32。同时云端也会发送一个报文,可以看到两个报文Data部分都是一样的。网上说这是UDP打洞机制,这样才可以实时判断设备是否在线,App对设备控制时反应很快,应该也是基于此。关灯后心跳包也一直存在,这样才能随时通过手机App控制。UDP打洞参考:
https://en.wikipedia.org/wiki/UDP\_hole\_punching
控制命令下发
通过手机App端控制灯泡,调节亮度和色温(这部分没抓包),可以看到云端向台灯发送了很多UDP数据包。
测试发现,直接重放云端发送给设备的UDP数据包,比如开灯、关灯、调节亮度和色温操作这些,在一段时间内(大概40秒左右),都是可以重放的。但是过了一段时间,重放数据包就不能控制了。这个我不确定是不是在数据Data部分做了控制,有了解的可以说下(对协议不是很了解^_^)。
OTA升级
台灯升级时,手机App端确定升级,设备会向云端服务器下载更新包。
升级使用http,把升级包下载下来看看,使用文本查看下bin文件里都有什么内容。
现在智能设备基本都开启了UPnP。
这里有个向cloud.yeelight.com发送统计信息的请求,不过我没抓到,估计要等待一段时间。不过这有句话很有意思哈:
sometimes, we don't want to be loved as much to be understood.
IDLE ゥゥゥゥゥゥゥゥゥゥTmr Svc 8.8.8.8 tiT
ot.netif_change Oct 12 2017 17:15:57 ot_config psm_model _miap
network.ssid network.password _miio %u network.configured
stationTimer { ????? %s.%s _psm_object_open (NULL) %02X%c
%02x%c %02X %02x 0123456789abcdef 0123456789ABCDEF
NOTCONNECTED CONNECTING unknown CONNECTED ONLINE
{"result":{"state":"%s","auth_fail_count":%d,"conn_succes_count":%d,"conn_fail_count":%d,"dhcp_fail_count":%d
}} no mem ot_config.uid %d ot_config.gmt_offset
ot_config.enauth enauth Invalid json. Invalid param. otn OTd not
available. ot_config.psm_model ot_config.mcu_ver ot_config.psm_token
country_domain esp8266
%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x
%d.%d.%d.%d "%s": "%s %s {"localIp":" ","mask":" ","gw":" "}
"%s":" "%s" {"rssi":%hd,"ssid":"%s","bssid":" "life":%u,
"token":" mac "hw_ver":"%s", ESP8266 "uid":%s, "channel":"%s",
mcu_fw_ver wifi_fw_ver ap "}, netif "mmfree":%u {"result":{ Mem
error. network ap2staTmr rebootTimer Config router fail passwd
channel uid gmt_offset miio_default 0x82562647 MIIO_net_change uap
MIIO_net_change unprov MIIO_net_change updating MIIO_net_change
cloud MIIO_net_change local MIIO_net_change offline config_JsDlgt
reboot_JsDlgt restore_JsDlgt stop_diag_mode_JsDlgt
wifi_assoc_state_JsDlgt config_router_JsDlgt info_JsDlgt
{"result":[%s]} reboot_timer get_down result "ready" down
update_fw error ok ota_progress 20 ota failed app_url
mcu_url ota_state ota_reboot "idle" "downloading" "downloaded"
"installing" "installed" "failed" ota_install_JsDlgt ota_JsDlgt
get_ota_state_JsDlgt get_ota_progress_JsDlgt ?$@0 $@4$@,$@?$@0
$@
用的esp8266芯片,标红部分应该是与云端通信时传递的一些参数,标绿部分是OTA升级的一些状态吧。
HTTP resps:%s Content-Length: Content-Length err. Header err. Open
error. Write. HTTP resps: http:// 渞%@爎%@|$@?$@T$@?$@Invalid json.
Busy. {"id":%u,"error":{"code":%d,"message":"%s"}} Resp general error.
Resp invalid json. ip result otc_list Try out. Method not found.
ot.online method from sid params Req object invalid. _JsDlgtS _JsDlgt
ot.offline "ott_stat": [%u, %u, %u, %u] ,"otstat":{
"timestamp":%u,"proto":1,"otip":" ","otport":80, "sendcnt":%u,
"ackcnt":%u, "costtime":%u} {"method":"_otc.info","params":{
竢%@紃%@p$@(*$@?$@?$@{"id":%u,"result":0} otc_test R. error model retry
timeout "method": ,"params": ,"sid": ,"model": ,"from":"%s" "result":
"error": ,"id":%u} nbl.%u not sync. {"method":"_otc.login","params":{
DnFull. LocalOnly. K@%c. Invalid param. redirect failed. _otd.redirect
host _otd.neighbor token did NeighborAckProbErrIP. LanPktHdrErrDID.
NeighborAckErrIP. LanPktErrDID. WanPktHdrErrDID. WanPktErrDID.
WanPktNotFromHost. KPstop. KPTstop. "otu_stat": [%u,%u,%u,%u,%u,%u]
"timestamp":%u,"proto":0,"otip":" ","otport":8053, ,"err":"%s"}}
s%@s%@hP$@user miIO user ot.online true false up_task
_otc.log _async.store null
{"retry":0,"timeout":2000,"method":"props","params":{ "%s":%s "ota_
"method": {%s {"retry":%u,"timeout":2000,"method":"event.%s","params":[%s]} {"retry":0,"method":"%s","params":{"%s":%s}}
这里也可以看到云端通讯使用的8053端口,设备端使用固定的端口54321,应该都是为了满足UDP打洞要求。
简单分析就到这,网上有人专门拆解了小米的扫地机器人、智能灯泡等,感兴趣的可以去看看。