阿里云 IoT 模组安全 SDK 集成范例

简介: 本文档介绍如何使用资源极低的 ESP32/8266 WiFi 模组进行前期开发联调与 BSP 无关的业务功能。方便开发人员快速上手。在基本业务功能端到端调试完毕之后再将标准的 C 语言程序移植到 cat1 或者 NBIoT 无线模组开发环境进行后续 BSP 的开发或者适配。

概述

本文档介绍如何使用资源极低的 ESP32/8266 WiFi 模组进行前期开发联调与 BSP 无关的业务功能。方便开发人员快速上手。在基本业务功能端到端调试完毕之后再将标准的 C 语言程序移植到 cat1 或者 NBIoT 无线模组开发环境进行后续 BSP 的开发或者适配。

硬件选型

ESP 有多种型号可选,这里我们选用 ESP01(1m RAM)以及 M5Stack C Plus 进行开发,这是 ESP 系列当中配置最低的模组,在资源有限的环境中增加业务逻辑,是确保在不同配置模组之间移植的较好选择。

  • ESP01

另外需要一个 CH340 下载器进行下载。

购买链接:

EPS01链接:https://item.jd.com/10023423910094.html

下载器链接:https://item.jd.com/10033537688506.html

  • M5Stack C Plus

购买链接:https://ic-item.jd.com/10034666963148.html

开发环境搭建

注明:下面的开发环境均以 ESP01 为模板编写,M5Stack 的开发环境和 ESP01 略有不同,在每一段的注释中标记。

推荐开发和构建环境为 VSCode 和 PlatformIO 插件,在各种平台上均可以开发和利用 UART 烧录固件。

  1. 安装 VSCode,并且在插件栏目中搜索 PlatformIO。

  1. 装好之后可以在 VSCode 侧边栏里看到 PlatformIO 的图标以及首页。这时如果导入带有 platformio.ini 配置的工程文件夹,即可直接被 PlatformIO 捕获,并且可以直接编辑配置和进行构建。

  1. 如果是初次安装 PlatformIO 环境,则需要在上述面板的 Platforms 当中搜索 ESP8266 基础支持库,并且进行安装。

M5Stack:下载 ESP32 基础库,Libraries 当中在 example 工程的基础上添加 M5StickCPlus 即可。

4. 装好之后,导入你的 C/C++ 功能即可进行开发和构建了,下面三个蓝色框分别对应:构建、烧录、打印调试日志。

  1. 在工程的 platformio.ini 文件中可以对构建全局变量进行编辑,例如指定额外的源码目录、头文件目录、库等。详情可参考:https://docs.platformio.org/en/latest/projectconf/index.html
  2. ESP 是一个开放的,生态丰富的社区,有许多开发者为这款开源硬件贡献自己开发的稳定的功能库,例如 MQTTPubSub,WifiManager,AliotSDK 等,可以直接在 PlatformIO 的 Libraries 栏目中搜索并下载。下载好的库均是以源码形式和项目进行混合编译,库目录位于 ${USER}/.platformio/packages/framework-arduinoespressif8266/cores/esp8266/ 目录下面。
  3. 项目当中的内容分为两部分:模组逻辑部分和模组安全 SDK 集成。在开发体验过程中,我们可以同时扮演模组开发者以及安全SDK开发者。

模组安全 SDK 代码结构

模组安全 SDK 代码树结构的简单说明如下:

das2 +

    +--board  // 模组硬件相关的 BPS 侧差异化代码,通常是一些接口

    +--example + // 可以用于测试和运行的示例,例如 ESP32 的示例就在其中

               +--esp8266 // ESP8266 WiFi 模组适配样例

               +--linux // GNULinux 通用适配样例

               +--m5720 // M5720 cat1 模组适配样例

               +--m5stack // 基于 ESP32 模组的 M5 CPLUS 1 设备适配样例(含设备 GUI 部分)

    +--src   // 主体代码

    +--test  // 单元测试代码

   


其中 src 目录下包括了所有模组安全检测和防御机能的通用能力,所有 example 均是可完整编译的工程,这些工程可以通过 symbolic link 的方式链接到 SDK 暴露出来的客户侧代码,方法如下:

Windows:

cd exmpale/esp8266

make_link.bat

M5Stack

cd example/m5stack

make_link.bat

Linux/Mac:

cd example/esp8266

./make_link.sh

M5Stack

cd example/m5stack

./make_link.sh

ESP 联网向导

在  ESP8266 example 当中,可以通过调整三元组定义,连接到阿里云物联网平台公共实例(内置一个免费三元组供体验)。方法如下:

  1. 在安装了 PlatformIO 插件的 VSCode 当中以文件夹方式打开 example/esp8266 目录,工程会自动导入和部署。
  2. 找到源码:example/esp8266/platform.ini,在其中可编辑 build.flag 的一个宏开关,来指定日常、预发和线上,其中指定:
  • -DENV_RELEASE=1 表示线上环境


  1. 找到源码:src/alink.cpp,根据上面选择的不同的宏开关,填入在物联网平台上申请的 PK,DN,DS 然后进行固件编译。
  2. 对于需要切换 WiFi 热点的模组,需要先利用 ESP8266 Downloader 对 flash 进行擦除,然后再烧写固件,具体步骤见下面 “构建、烧录和调试”章节。
  3. EPS8266 上电之后,会首先切换为 STA 模式,并向周围发布一个名为 ESPXXXX 的 WiFi 热点。开发者准备一台自己的手机,寻找到这个热点之后进行连接。
  4. 连接上之后会弹出一个 WifiManager 的配置页面,点击配置,即可扫描获得周围的 AP,选择一个公开的 AP,例如 IoT 实验室 AP(亦或者自己的手机做 AP),输入密码进行配置。如果配置正确,ESP32 会自动重启进入 Client 模式,连接到指定的 AP,随后自动建立 MQTT 连接到阿里云 IoT 平台和安全中心,开始工作。


M5Stack:PlatformIO 的仓库里的 WiFiManager 版本由于年久失修,不能直接用了,需要从 github 下载手动集成最新的 WifiManager(example 里已经带了):https://github.com/tzapu/WiFiManager

*此外 ESP32 的 LITTLEFS 和 ESP8266 的也略有不同,并且 PlatformIO 仓库里的 LITTLEFS 和 vfs api 有兼容性 bug,exist 函数的 create 布尔参数要自己改一下。

功能调试

模组侧 HOOK

在 ESP8266 的开源生态中,我们可以直接接触到 WiFi FWK 的所有源码,其中几个比较重要的部分,从协议栈接口向上依次为:

  1. Wifi-TCP 客户端 :它包含了一个用于实现对接层2协议栈的多态 C++ 实现和接口,对上接入 lwip 的 TCP 协议栈。在这个客户端上下文当中,可以自主添加代码,实现网络流量审计、保存、挂接(hook)网络访问事件。源码位置在:

ARDUINO_FRAMEWORK = ${USER}/.platformio/packages/framework-arduinoespressif8266

${ARDUINO_FRAMEWORK}/libraries/ESP8266WiFi/src/include/ClientContext.h

  • TCP 协议链接 STUB 可挂接在 tcp_connect 函数入口,捕获 ip4_addr 以及 port 参数。
  • 通过 Wifi-TCP Client 上行流量审计挂接在 write 函数入口,每次增加 dl 字节,保存。
  • 通过 Wifi-TCP Client 下行流量审计挂接在 _consume 函数的 tcp_receved 之后,每次增加 size 字节,保存。
  1. Wifi-UDP 客户端:它包含了一个用于实现对接层2协议栈的多态 C++ 实现和接口,对上接入 lwip 的 UDP 协议栈。在这个客户端上下文当中,可以自主添加代码,实现网络流量审计、保存、挂接(hook)网络访问事件。源码位置在:

${ARDUINO_FRAMEWORK}/libraries/ESP8266WiFi/src/include/UDPContext.h

  • UDP 协议链接 STUB 可挂接在 connect 函数入口,捕获 UDP 连接的 addr 和 port 信息。
  • 通过 Wifi-UDP Client 上行流量审计挂接在 trySend 函数 udp_sendto 调用成功之后,每次增加 data_size 字节,保存。
  • 通过 Wifi-UDP Client 下行流量审计挂接在 _consume 函数的末尾,每次增加 size 字节,保存。
  1. Wifi 模组作服务端,则会调用 WifiServer.cpp 当中的接口实现 listen 和 accept 等操作,暂时不做挂接,待将来有捕获网络连入事件时再进行入口捕获。

附件中为基于 ESP8266 模组已经配置好模组框架层挂接点的源代码,可以直接替换上述文件位置,随同模组固件一起编译,即可在模组层面向安全 SDK 提供相应的事件报告。

  1. 网络事件挂钩,这一组挂钩包括模组对外连接 IP:port 以及域名解析的挂钩模拟,以 TCP 为例:
  • IP:port 类型访问挂钩在:

${ARDUINO_FRAMEWORK}/libraries/ESP8266WiFi/src/include/ClientContext.h

int connect(ip_addr_t* addr, uint16_t port) 的 tcp_connect 调用之前。挂钩函数原型:

void lsocClientReportIPAccessEvent(ip_addr_t*addr, uint16_tport, intipVer, constchar*protocol);

  • host 域名访问挂钩在

${ARDUINO_FRAMEWORK}/libraries/ESP8266WiFi/src/WifiClient.cpp

int WiFiClient::connect(const char* host, uint16_t port) 开头的位置。挂钩函数原型:

void lsocClientReportHostAccessEvent(const char* hostname, uint16_t port);

这两个挂钩函数当中既需要调用 access stub 又要调用 control stub。

IPV4 UDP 协议和 IPV6 同理。

附件,修改过的 ESP8266 Wifi Client,其它埋点请自行修改。



M5Stack:

EPS32 的 ARDUINO_FRAMEWORK 是 ${USER}/.platformio\packages\framework-arduinoespressif32

TCP events:${ARDUINO_FRAMEWORK }/libraries/WiFi/src/WifiClient.cpp

  • 域名连接事件:int WiFiClient::connect(const char *host, uint16_t port, int32_t timeout) 函数,域名解析完成之后 call 回调函数:lsocClientReportHostAccessEvent,带入域名和地址信息进行关联。
  • IP 地址连接事件:int WiFiClient::connect(IPAddress ip, uint16_t port, int32_t timeout) 函数,直接 call lsocClientReportIPAccessEvent。
  • 上行流量挂钩:size_tWiFiClient::write(constuint8_t*buf, size_tsize) 函数,发送成功之后增加 res 字节数。
  • 下行流量挂钩:int WiFiClient::read(uint8_t *buf, size_t size) 函数,从 __rxBuffer 对象读取流成功之后增加 res 字节数。

(这里注意 ESP32 和 ESP8266 的数据结构略有差别)。

======================================================================

UDP events:${ARDUINO_FRAMEWORK }/libraries/WiFi/src/WifiUdp.cpp

  • 向 IP 地址发送报文:uint8_t WiFiUDP::begin(IPAddress address, uint16_t port) 函数,在建立 UDP socket 之前 call 回调 lsocClientReportIPAccessEvent。
  • 向 URL 发送报文:int WiFiUDP::beginPacket(const char *host, uint16_t port) 函数,在建立 UDP socket 之前 call 回调 lsocClientReportHostAccessEvent。
  • 上行流量挂钩:int WiFiUDP::endPacket() 函数,在 sendto 成功之后增加 sent字节数。
  • 下行流量挂钩:int WiFiUDP::parsePacket() 函数,在 rx_buffer write 成功之后增加 len 字节数。

======================================================================

附件,修改过的 ESP32 Wifi Client,其它埋点请自行修改。


模组主控流程

模组应用层的主控流程位于 src 目录下,其它 ESP 库和三方库可存放在工程目录的 lib 下。应用程序主入口在 main.cpp 的 setup() 函数当中。一些比较重要的模组主控和 SDK 集成的部分为:

  1. ${PROJECT}/lib/AliyunIoTSDK/src/AliyunIoTSDK.cpp,Alink SDK,用于连接 LP。
  2. ${PROJECT}/src/security.cpp,模组应用和 SDK 的集成点源码,当中实现了所有 hal 适配层的函数,包括填充固件信息、实现被动 stub(获取流量)接口等。
  3. ${PROJECT}/src/alink.cpp,模组应用和 AliyunIoTSDK 的集成点源码,实现阿里云上云,消息订阅和发布等基本操作,其中的 iot 对象被设置为了 SDK 当中的 session 对象,负责 SOC 消息收发和回调处理。

安全 SDK 在工程目录中为 ${DAS_ROOT}/src 下,对外部客户以静态库形式提供。包括所有的 SDK 主流程、步进驱动取证、服务、ATI、Stub 和 BSP 相关的接口等,在 ESP32 环境中可以和上述的模组协议栈、模组三方库共同通过源码进行编译。SDK 的作业驱动由模组主控的 security.cpp 当中通过调用 das_stepping 以及 MQTT 下行命令驱动实现,其中包含周期采样、消息上报等。详情参考模组安全 SDK 源代码。

构建、烧录和调试

  1. 点击 PlatformIO 的 build 按钮即可进行构建,如果需要引入额外的 include 路径,需要在 platformio.ini 当中进行 build_flag 配置:

ESP8266 如下:

build_flags =

-DLOG_DEBUG=1

-DLOG_INFO=1

-DLOG_ERROR=1

-DENV_DAILY=1

-DDAS_ESP8266=1

-DDAS_PLATFORM_ESP=1

-DDAS_DEBUG=1

-Wno-unused-function

-Wno-unused-variable

-I${common.workspace}/lib/lsoc_das2/

-I${common.workspace}/lib/lsoc_das2/include

-I${common.workspace}/lib/lsoc_das2/proto

-I${common.workspace}/lib/lsoc_das2/stubs/include

-I${common.workspace}/lib/lsoc_das2/stubs/include/at

-I${common.workspace}/lib/lsoc_das2/stubs/include/hal

-I${common.workspace}/lib/lsoc_das2/stubs/include/osa

-I${common.workspace}/lib/lsoc_das2/ati/inc

M5Stack 如下:

build_flags =

-DCORE_DEBUG_LEVEL=4

-DLOG_DEBUG=1

-DLOG_INFO=1

-DLOG_ERROR=1

-DENV_RELEASE=1

-DWITH_LCD=1

-DDAS_ESP32=1

-DDAS_PLATFORM_ESP=1

-DDAS_DEBUG=1

-Wno-unused-function

-Wno-unused-variable

-I${common.workspace}/lib/lsoc_das2/

-I${common.workspace}/lib/lsoc_das2/include

-I${common.workspace}/lib/lsoc_das2/proto

-I${common.workspace}/lib/lsoc_das2/stubs/include

-I${common.workspace}/lib/lsoc_das2/stubs/include/at

-I${common.workspace}/lib/lsoc_das2/stubs/include/hal

-I${common.workspace}/lib/lsoc_das2/stubs/include/osa

-I${common.workspace}/lib/lsoc_das2/ati/inc

-I${common.workspace}/lib/lsoc_das2/ati/inc/at/internal

  1. 构建好之后在 ${PROJECT}.pio/build/${ESP_PROFILE} 下会生成 firmware.bin 文件,将这个文件导入 ESP flash download tools 即可进行烧写。

  1. 烧写时请将 ESP01 芯片 pin2pin 插入下载器,下载器插入 PC 之后会枚举出 COM 口,选择正确的 COM 口以及波特率(115200)即可下载了。
  2. 下载完成后回到 PlatformIO,点击 monitor 按钮即可重新为更新过固件的 ESP01 模组上电并监控其日志信息,进行调试。


M5Stack 可以直接从 Platform IO 选择 Upload 或者 Upload&Monitor 进行烧录。

附 M5Stack 集成好之后并且访问白名单,不在白名单内的地址访问实施阻止演示:

通过阿里云 IoT 安全中心配置模组安全策略

在 M5Stick 上演示模组安全态势感知和主动防御



关于从 Arduino 环境移植的说明

ESP模组系列 的整个网络通信的技术栈类似常见的 cat1 模组技术栈,都分为芯片厂商闭源区、模组厂商闭源区、模组厂商开放区、用户区等区域。下图对比了二者之间的关系以及各个开发者角色需要开发的部分的工作项。



移植注意事项

  1. 在 ESP32 01 上调试时,das_policy_t 结构体由于需要进行 4 字节对齐的序列化处理,因此只能以全局变量的形态存储在 RAM 的 .bss 段。由于 100 个 IP/domain 实在是太大,会导致 .bss 越界。因此暂时调整至 10 个 IP/domain。在其它模组系统中请按实际情况调整。

此外也可以考虑使用 heap 代替 .bss 存储方式。

  1. 在网络事件上报函数 das_report_network_event 当中,由于是在 HOOK 函数中同步调用的,因此需要将事件加入缓存队列,随后在 stepping 调度中在 das_module_nfi_service 的 info 函数中从队列中取出。由于开发环境的 ESP32 是 non-os 的无锁环境(但需要屏蔽中断),因此队列操作没有上锁。在向 Free-RTOS 或者 Linux 等抢占式系统移植时请注意加锁。
  2. 在模组安全 SDK 的 stepping 驱动当中,目前忽略了第一次对流量进行 sampling 的结果,因为考虑到 SDK 初始化和 MQTT 连接不一定是发生在模组上电时刻的,因此需要轮询 2 个 sampling 周期才会产生第一次有效采样,轮询 2 个 sysinfo 周期才会触发第一次上报,也许有可以优化的空间。
  3. 如果需要 mock HTTP 访问,请在 MQTT 使用的 WiFiClient 之外额外声明一个 WiFiClient 对象,避免底层 ClientContext 实例冲突而导致 TCP 断链。
相关文章
|
1月前
|
云安全 弹性计算 安全
电子好书发您分享《阿里云第八代企业级ECS实例,为企业提供更安全的云上防护》
阿里云推出第八代企业级ECS实例,强化云安全,搭载英特尔TDX技术,结合CIPU与飞天系统,提供高效且安全的云服务解决方案。[阅读详情](https://developer.aliyun.com/ebook/8303/116162?spm=a2c6h.26392459.ebook-detail.5.5c0b7e5aZhSJ9V)
16 2
|
1月前
|
安全 编译器 Linux
精伦安全模块-身份证读卡器对接-Qt调用SDK
精伦安全模块-身份证读卡器对接-Qt调用SDK
40 0
|
2月前
|
SQL 弹性计算 安全
购买阿里云活动内云服务器之后设置密码、安全组、增加带宽、挂载云盘教程
当我们通过阿里云的活动购买完云服务器之后,并不是立马就能使用了,还需要我们设置云服务器密码,配置安全组等基本操作之后才能使用,有的用户还需要购买并挂载数据盘到云服务器上,很多新手用户由于是初次使用阿里云服务器,因此并不知道这些设置的操作流程,下面给大家介绍下这些设置的具体操作流程。
购买阿里云活动内云服务器之后设置密码、安全组、增加带宽、挂载云盘教程
|
2月前
|
供应链 安全 Linux
简单、透明、安全、高度集成!龙蜥可信 SBOM 能力探索与实践
从攻击面管理的角度解决软件供应链SBOM复杂体系的安全可信问题。
|
3月前
|
存储 监控 安全
360 企业安全浏览器基于阿里云数据库 SelectDB 版内核 Apache Doris 的数据架构升级实践
为了提供更好的日志数据服务,360 企业安全浏览器设计了统一运维管理平台,并引入 Apache Doris 替代了 Elasticsearch,实现日志检索与报表分析架构的统一,同时依赖 Doris 优异性能,聚合分析效率呈数量级提升、存储成本下降 60%....为日志数据的可视化和价值发挥提供了坚实的基础。
360 企业安全浏览器基于阿里云数据库 SelectDB 版内核 Apache Doris 的数据架构升级实践
|
3天前
|
云安全 人工智能 安全
|
2天前
|
安全 物联网 Android开发
构建未来:Android与IoT设备的无缝集成
【5月更文挑战第10天】 在数字化时代的浪潮中,智能设备与互联网的结合日益紧密。本文深入探讨了Android系统如何通过其开放性和灵活性成为连接物联网(IoT)设备的关键枢纽。我们将分析Android平台与IoT设备集成的技术途径,探索它们如何共同塑造智能家居、可穿戴技术以及工业自动化等领域的未来。文中不仅阐述了当前的发展状况,还展望了未来的发展趋势,特别是安全性和隐私保护方面的挑战及对策。
|
11天前
|
机器学习/深度学习 传感器 物联网
【Python机器学习专栏】机器学习在物联网(IoT)中的集成
【4月更文挑战第30天】本文探讨了机器学习在物联网(IoT)中的应用,包括数据收集预处理、实时分析决策和模型训练更新。机器学习被用于智能家居、工业自动化和健康监测等领域,例如预测居民行为以优化能源效率和设备维护。Python是支持物联网项目机器学习集成的重要工具,文中给出了一个使用`scikit-learn`预测温度的简单示例。尽管面临数据隐私、安全性和模型解释性等挑战,但物联网与机器学习的结合将持续推动各行业的创新和智能化。
|
13天前
|
弹性计算 运维 Serverless
Serverless 应用引擎产品使用之在阿里函数计算中,使用阿里云API或SDK从函数计算调用ECS实例的服务如何解决
阿里云Serverless 应用引擎(SAE)提供了完整的微服务应用生命周期管理能力,包括应用部署、服务治理、开发运维、资源管理等功能,并通过扩展功能支持多环境管理、API Gateway、事件驱动等高级应用场景,帮助企业快速构建、部署、运维和扩展微服务架构,实现Serverless化的应用部署与运维模式。以下是对SAE产品使用合集的概述,包括应用管理、服务治理、开发运维、资源管理等方面。
41 4
|
1月前
|
云安全 数据采集 安全
阿里云安全产品,Web应用防火墙与云防火墙产品各自作用简介
阿里云提供两种关键安全产品:Web应用防火墙和云防火墙。Web应用防火墙专注网站安全,防护Web攻击、CC攻击和Bot防御,具备流量管理、大数据防御能力和简易部署。云防火墙是SaaS化的网络边界防护,管理南北向和东西向流量,提供访问控制、入侵防御和流量可视化。两者结合可实现全面的网络和应用安全。
阿里云安全产品,Web应用防火墙与云防火墙产品各自作用简介

热门文章

最新文章