MQTT连接AWS IoT

MQTT常见连接方式

MQTT(Message Queuing Telemetry Transport)支持多种不同的连接方式,主要体现在传输层协议安全特性的选择上。下面分别介绍常见的几种连接方式及其区别和适用场景。


明文TCP连接(tcp)

  • URI格式mqtt://<broker-address>:1883
  • 端口:1883(默认)
  • 安全性:无加密,明文传输
  • 客户端认证:常为用户名/密码(可选)
  • 适用场景
    • 内网环境/本地测试
    • 对安全性要求不高的应用
  • 缺点
    • 数据易被窃听/篡改,不建议在公网环境使用
  • 备注
    • AWS IoT Core等云服务不允许明文MQTT

单向TLS加密(ssl/tls)

  • URI格式ssl://<broker-address>:8883
  • 端口:8883(默认)
  • 安全性:TLS加密,客户端校验服务端证书CA根证书
  • 客户端认证:通常为用户名/密码,也可仅凭CA根证书
  • 适用场景
    • 需要加密传输但不强制客户端证书认证的应用
  • 缺点
    • 客户端未被服务端验证,安全性一般
  • 备注
    • 部分云服务支持,但AWS IoT Core不支持单向,只支持双向认证

双向TLS/证书认证(ssl_mutual_auth)

  • URI格式ssl://<broker-address>:8883mqtts://<broker-address>:8883
  • 端口:8883
  • 安全性:TLS加密,双向证书认证(mTLS)
  • 客户端认证:必须加载CA根证书、客户端证书、客户端私钥
  • 适用场景
    • 高安全需求(如工业物联网、金融、云服务)
    • AWS IoT Core等云服务的推荐/强制方式
  • 优点
    • 服务端和客户端都能确认对方身份,安全性高

基于WebSocket的MQTT(ws/wss)

  • ws(明文WebSocket)

    • URI格式ws://<broker-address>:80
    • 端口:80
    • 安全性:无加密,明文
    • 适用场景:内网、开发测试、受限于Web环境
  • wss(加密WebSocket)

    • URI格式wss://<broker-address>:443
    • 端口:443
    • 安全性:TLS加密
    • 适用场景
      • 需要穿越防火墙/代理
      • Web App、云平台集成
    • 备注AWS IoT Core支持wss方式,不支持ws

设备安全模块/硬件加密(ssl_ds)

  • 说明:证书和密钥存储在安全芯片/模块(如TPM、ATECC)内,提升物理安全。
  • 适用场景:高安全需求的物联网设备

预共享密钥TLS(ssl_psk)

  • URI格式ssl://<broker-address>:8883
  • 端口:8883
  • 安全性:TLS加密,认证基于PSK(Pre-Shared Key)
  • 客户端认证:通过预共享密钥
  • 适用场景
    • 设备资源受限,无法安全存储证书
  • 缺点
    • PSK管理复杂,不如证书灵活
    • AWS IoT Core不支持此方式

选择建议

  • 本地测试tcp 或 ws
  • 公网/生产环境:ssl_mutual_auth 或 wss
  • AWS IoT Core强烈建议使用 ssl_mutual_auth(双向证书认证)

小结对比表

方式 安全性 端口 认证类型 适用云服务
tcp 1883 可选用户名密码
ssl 较高 8883 服务器证书 有些支持
ssl_mutual_auth 很高 8883 双向证书 AWS/阿里云等
ssl_psk 较高 8883 PSK密钥 少数支持
ws 80 可选
wss 很高 443 可选 AWS/阿里云等

推荐生产环境优先使用TLS加密和证书双向认证,保障设备和数据安全。

例程:使用MCU连接至AWS IoT

快速连接

  1. 在AWS IoT的连接界面,执行图中步骤,使用ping测试是否连通。

image-20250516134059991

该服务器地址的作用:

  1. AWS IoT Core 设备连接地址
    • 这是你所有物联网设备(比如 MCU、网关、传感器等)连接到 AWS IoT 云服务时要用的服务器地址。
    • 设备在进行 MQTT/TLS 或 WSS 连接时,服务器地址就是这一串。
  2. 唯一标识你的 AWS IoT 实例
    • 每个 AWS 账号在每个区域的 IoT Core 都有唯一的 endpoint,类似于你的“云端大门”。
    • 设备必须通过这个 endpoint 才能连接和收发数据。
  3. 用于连通性测试
    • 在当前页面建议用 ping 命令测试该 endpoint,确认你的设备能正常访问 AWS 云端(网络连通性OK)。
    • 只有 ping 通这个 endpoint,设备后续才能成功连接和通信。
  1. 创建新事物Thing(第一次使用的话),并取名

image-20250516134517321

  1. 选择对应的平台和SDK语言,后续AWS会准备相应语言的示例代码、依赖包、工具指令、帮助快速连接设备。

​ 这里我们选择windows 和 python

image-20250516134603072

  1. 下载对应的连接工具包。该数据包中包含python测试连接的脚本,以及相应的CA根证书客户端证书客户端私钥。这三个证书在后面的双向认证会使用

image-20250516134912689

image-20250516135002294

  1. 解压后在根目录运行该脚本后,会先准备环境。然后目录下会出现根证书root-CA.crt和python的sdk,同时此处的订阅和本地的终端上都能订阅到消息,即测试连接成功

image-20250516135249711

手动创建物品Things连接

创建Things

  1. 在管理->所有设备下->物品,可以我们的创建的Things进行管理,之前快速连接的Things也会出现在这里。

我们可以在此页面直接创建Things

image-20250516135729552

  1. 选择创建单个物品或多个物品,然后点击下一步即可

配置Things属性、证书

  1. 配置相关物品属性、证书
  • 创建自定义物品名称,其他配置可选,同时设备影子是用于设备与AWS同步使用,这里我们不使用

image-20250516140148061

  • 配置设备证书,这里我们使用AWS IoT的自动生成。包括root-CA、公有密钥和私有密钥

image-20250516140445767

物品证书策略附加与创建

  1. 将策略附加到证书

AWS IoT策略(Policy)类似于一组“权限规则”,控制你的物联网设备(通过证书、IAM或其它身份)对AWS IoT资源的访问能力。
它本质上和IAM策略很像,但专门用于设备和IoT资源,主要作用是:

  • 授权设备发布(Publish)/订阅(Subscribe)特定主题(Topic)
  • 授权设备连接(Connect)到特定客户端ID
  • 控制哪些消息流向设备,哪些操作被允许

image-20250516141736187

这里可以看到之前创建的一些策略,但是我们通常对不同Things会有不同的策略,所以我们要新建策略,点击新建策略

创建策略页面

image-20250516142329142

自定义策略的名称:MY_SHT20_POLICY,下方的选择允许策略效果

image-20250516143740897

策略操作:选择对应的策略操作,包括CONNECT(连接到AWS权限)、PUBLISH(发布权限)。这里我们选择所有权限(用 * 表示)

image-20250516143318487

策略资源:填写允许访问的资源 ARN

image-20250516144116312

格式通常为:

Topic发布:arn:aws:iot:ap-northeast-2:你的账号ID:topic/你的topic名

Topic订阅:arn:aws:iot:ap-northeast-2:你的账号ID:topicfilter/你的topic名

Connect:arn:aws:iot:ap-northeast-2:你的账号ID:client/你的clientId

通配符:

我们可以使用 * 作为通配符(如允许所有 topic,可以写 arn:aws:iot:ap-northeast-2:你的账号ID:topic/*),但不建议无脑填 *,要遵循最小权限原则。

IoT策略是一个JSON对象,我们通常使用JSON来配置更方便,选择生成器右边的JSON

格式中:”Effect”、”Action” 、”Resource” 分别对应上述的策略效果、策略操作、策略资源,生成器中对应的填写也会在这边同步

image-20250516144205905

基本策略示例如下:共有三个部分,分别是对不同资源的,不同权限分配

image-20250516145229739

第一部分:允许发布和接收消息

image-20250516145550545

效果:

允许(Allow)被附加此策略的设备/证书对指定的3个MQTT主题(topic)进行如下操作

  • iot:Publish:向指定 topic 发布消息
  • iot:Receive:接收从这些 topic 发送来的消息
  • iot:PublishRetain:发布带有 Retain 标记的消息(即保留消息)

只限于这3个指定的topic/sdk/test/java/sdk/test/python/sdk/test/js

其余设备向其余topic发布消息都不行

第二部分:允许订阅主题过滤器

image-20250516150225004

效果:

  • 允许设备/证书 订阅(Subscribe)这3个主题(topic)过滤器。

  • 主题过滤器(topic filter)用于 MQTT 订阅操作,控制设备能订阅哪些主题。未出现topic将会订阅失败

    例如,设备可以通过这些过滤器订阅 /sdk/test/java 等topic的消息。

第三部分:允许连接(Connect)

image-20250516150436499

允许设备以指定的Client ID连接到 AWS IoT Core,

具体是:

  • sdk-java
  • basicPubSub
  • 以及所有以 sdk-nodejs- 开头的 Client ID(因为 sdk-nodejs-* 使用了通配符)

只有用这些 Client ID 连接时才被允许,否则连接将会连不上

证书全OK,但是连接不上

image-20250516151159468

所以一定要在这里配置指定的client_id,同时连接mqtt时一定要指定对应策略允许的client_Id

image-20250516150856085

策略示例1:全部操作全部资源都允许

1
2
3
4
5
6
7
8
9
10
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "*",
"Resource": "*"
}
]
}
  • "Action": "*" 表示允许所有操作(如 Connect、Publish、Subscribe、Receive 等)。
  • "Resource": "*" 表示对所有资源(全部 topic、全部 clientId、全部 topicfilter)都允许。

这样配置后,连接的MCU可以以任意Client_id连接AWS,同时向任意Topic发布任意消息,订阅任意Topic

⚠️ 注意:最小权限原则是最佳实践,实际生产建议只授权需要的操作和资源。
仅在开发或调试阶段用全允许策略,防止误操作或安全隐患。

策略示例2:指定资源允许(SHT20温湿度举例)

image-20250516152744890

image-20250516152615779

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"iot:Publish",
"iot:Receive"
],
"Resource": [
"arn:aws:iot:ap-northeast-2:194722442811:topic/sensor/sht20/temperature",
"arn:aws:iot:ap-northeast-2:194722442811:topic/sensor/sht20/humidity"
]
},
{
"Effect": "Allow",
"Action": "iot:Subscribe",
"Resource": [
"arn:aws:iot:ap-northeast-2:194722442811:topicfilter/sensor/sht20/temperature",
"arn:aws:iot:ap-northeast-2:194722442811:topicfilter/sensor/sht20/humidity"
]
},
{
"Effect": "Allow",
"Action": "iot:Connect",
"Resource": "arn:aws:iot:ap-northeast-2:194722442811:client/sht20"
}
]
}

我们回到之前创建Things附加策略到证书的页面,可以发现已经多了新附加的策略,我们选择相应策略,然后创建Things即可

image-20250516154118713


下载证书

点击创建后将会出现提供下载的证书,出现的所有证书都要下载,最好像快速连接的做法那样将所有证书下载后保存到一起

设备证书:

  • 作用:这是分配给你设备的唯一标识凭证(公钥证书),用于证明设备身份。
  • 用途:设备连接 AWS IoT Core 时,需携带此证书进行身份认证。

密钥文件:

  • 作用:用于加密和解密通讯内容,确保数据安全。每个证书都配有一对密钥:公钥和私钥。
  • 公有密钥文件(Public Key):一般不直接使用,主要用于加密、验证签名等。
  • 私有密钥文件(Private Key)必须妥善保存,只下载一次! 设备用它和证书配合完成身份认证。
  • 用途:设备连接 AWS IoT 时,需同时用到证书文件和私钥文件。
  • 注意:私钥丢失后无法再次下载,只能重生成新证书。

根CA证书:

  • 作用:这是 AWS IoT 使用的权威机构签发的根证书,用于验证 AWS 云端的身份,是 TLS 连接的信任基础。
  • 用途:设备在连接 AWS IoT Core 时需要用到根 CA 证书,确认自己连接的是“真正的”AWS服务器而非冒充者。
  • 选择:有多种加密算法(RSA 2048、ECC 256)可供选择,下载一种与你设备SDK/固件兼容的即可,我们一般选择RSA

image-20250516154204925

一般只会使用三个证书进行双向认证

pem.crt:客户端证书

private.key:私钥

ca.crt:根CA证书

物品证书策略修改与删除

找到对应的物品,点击进入

image-20250516155017126

这里可以看到物品的证书,我们这里可以对证书进行操作,也可以进行分离证书和重新创建证书

image-20250516155153821

点击证书进入就是策略,可以对证书附加的策略进行删除和修改

image-20250516155257729

image-20250516155324753

image-20250516155335820

MCU连接AWS

我们使用指定策略进行连接,使用类似于ESP32的W800MCU进行连接

策略:指定资源允许(SHT20温湿度举例)

image-20250516152744890

image-20250516152615779

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"iot:Publish",
"iot:Receive"
],
"Resource": [
"arn:aws:iot:ap-northeast-2:194722442811:topic/sensor/sht20/temperature",
"arn:aws:iot:ap-northeast-2:194722442811:topic/sensor/sht20/humidity"
]
},
{
"Effect": "Allow",
"Action": "iot:Subscribe",
"Resource": [
"arn:aws:iot:ap-northeast-2:194722442811:topicfilter/sensor/sht20/temperature",
"arn:aws:iot:ap-northeast-2:194722442811:topicfilter/sensor/sht20/humidity"
]
},
{
"Effect": "Allow",
"Action": "iot:Connect",
"Resource": "arn:aws:iot:ap-northeast-2:194722442811:client/sht20"
}
]
}

AWS只能通过双向TLS/证书认证(ssl_mutual_auth),所以我们需要在AWS生成证书的时候保存的三个证书:CA根证书客户端证书私钥,将其放到项目根目录下

image-20250518170107398

在MQTT测试客户端处找到我们的**端点(ENEPOINT)**的链接:

image-20250518173349224

配置中,设置对应的wifi并连接,以及服务器的URL,使用ssl或者mqtts。

image-20250518173830726

使用文件嵌入代码的功能,加载对应的三个证书

image-20250518173941626

配置MQTT:对应的URL三个证书认证模式:选择双向认证

client_id:这个参数需要看AWS上的策略,这里是只能允许sht20连接,所以我们必须设置为sht20,否则将连接不上。如果策略允许所有client连接,可以不用指定,使用默认client_id即可

image-20250518174703053

启动MQTT注意要使用SNTP同步MCU系统时间,否则会出现TLS握手失败的问题。以下是正常发布和订阅,以及未连接上的情况

正常mqtt连接成功发布和订阅

image-20250518200852337


未同步时间:SSL handshake失败,return -0x2700

image-20250518194254091

946684800这个时间是2000-01-01 00:00:00,设备时间不对

mbedtls_ssl_handshake returned -0x2700
这是 mbedtls 的通用 TLS 握手失败错误,常见原因是证书校验失败
如果设备时间不对,mbedtls 会认为证书“未生效”或“已过期”,导致握手失败。

客户端id不被允许:SSL handshake成功,mqtt连接失败

image-20250518201312641

该情况是同步时间,client_id不对,就会导致证书通过,mqtt连接不上