Skip to content

物联网安全

物联网把"能联网的设备"和"能动手脚的物理世界" 接在一起,于是一处缺口往往同时威胁数据与控制——读到一台电表的读数是隐私问题,篡改一台阀门的指令就是安全事故。这一章按设备、通信、平台、数据四个面,梳理物联网安全的威胁与对策,并说明这套思路在 IoT DC3 里如何落到鉴权、租户隔离与传输加密上。

你在这里:已读完四层参考架构,想理解贯穿四层的安全是怎么回事。读完你能画出一张"威胁—对策"地图,并知道 DC3 在每一层放了哪些防线。

这一层是什么 / 为什么存在

安全不属于感知、网络、平台、应用中的某一层,而是贯穿四层的横切关注点 。原因很直白:攻击者不会按你的分层走,他会找最薄的那一处下手。设备端固件可以被刷写,通信链路可以被监听和重放,平台接口可以被越权调用,数据库里的数据可以被脱库——任何一环失守,前面几环做得再好也白搭。所以谈物联网安全,必须四层一起谈,并且默认" 边界之外皆不可信"。

物联网的安全又比传统 IT 更难,难在三处。其一是设备资源受限:现场的传感器、网关算力小、内存少、可能靠电池供电,跑不动重型加密,也难做频繁的密钥轮换。其二是 物理可达:设备就摆在车间、田间、街头,攻击者能直接拿到手,拆芯片、读 Flash、接调试口,纯软件防护挡不住物理攻击。其三是**规模与异构 **:一个平台可能接入几十种协议、成千上万台设备,统一打补丁、统一轮换证书的成本极高,任何一台老旧设备都可能成为整片网络的入口。

正因为这些约束,物联网安全的目标不是"绝对安全",而是纵深防御:每一层都设一道关,任何单点被攻破都不至于全盘失守。下面按四层逐一展开,再用一张图把威胁与对策对齐。

关键技术与权衡

设备安全:信任从硬件开始

设备是物理可达的一环,防护必须从启动那一刻就建立信任。**安全启动(Secure Boot)**让 Bootloader 逐级校验固件签名,签名不对就拒绝运行,从根上挡住"刷入恶意固件";其信任链的根,是固化在芯片里、不可篡改的根密钥。密钥存储 则决定了私钥会不会被读走——把密钥放在普通 Flash 里等于裸奔,正确做法是用安全元件(SE)或可信执行环境(TEE)隔离存储,让密钥" 可用而不可读"。**固件升级(OTA)**必须验签后再写入,并支持回滚到已知良好版本,否则一次被劫持的升级就能批量沦陷整片设备。

权衡在于成本:带 SE/TEE、支持安全启动的芯片更贵,OTA 通道也要额外的签名与灰度机制。资源极受限的设备往往只能做到"验签升级 + 软件层密钥保护",把更强的硬件信任根留给关键节点。

通信安全:加密、认证与防重放三件套

设备到平台的链路天然暴露在网络上,三件事必须同时做到。加密用 TLS(面向 TCP,如 MQTT over TLS、HTTPS)或 DTLS(面向 UDP,如 CoAP)把链路保护起来,防窃听与篡改。认证要双向:服务端证书防止设备连到假平台(中间人),设备侧用证书或预共享密钥(PSK)证明自己是谁,防止设备伪造。 防重放则要防"录下一条合法报文、稍后原样重放"——靠时间戳、单调递增的序号或一次性随机数(nonce),让旧报文失效。

权衡在于受限设备:完整 TLS 握手的非对称运算和证书链对小设备是负担,于是出现 TLS-PSK、会话复用、用更轻的椭圆曲线算法等折中。再轻也不能省掉"认证 + 防重放"这两条,否则加密只是给攻击者也加了密。

平台安全:认证、授权、租户隔离、审计

设备的数据汇聚到平台,平台就成了高价值目标。认证回答"你是谁"——登录换取令牌,令牌可验证、有时效。授权回答"你能做什么" ——按 RBAC(基于角色的访问控制)把主体、角色、资源绑起来,并坚持最小权限fail-closed(查不到权限就拒绝,绝不默认放行)。* *多租户隔离**回答"你能碰哪条数据"——它与授权正交:有"读设备"的权限,不代表能读别家租户的设备;隔离做不好,一个租户就能看到甚至操作另一个租户的现场设备。 审计则把"谁在什么时候做了什么"记下来,既用于事后追责,也用于实时发现异常。

数据安全:隐私、脱敏、合规

物联网数据常常关联到个人与现场——一台智能电表的用电曲线能反推出家里有没有人,一段定位轨迹就是行踪。隐私 要求遵循最小采集与目的限定,不该收的别收。脱敏要求在展示、导出、给第三方(包括喂给大模型)之前,把敏感字段做掩码或匿名化。* 合规* 则把这些上升为硬要求:GDPR、个人信息保护法等法规对采集、存储、跨境传输都有约束,违规的代价远高于一次技术故障。数据安全还包括静态加密(落库加密、磁盘加密)与最小留存(过期即删),让" 即使被脱库,拿到的也是密文或残缺数据"。

威胁模型:把攻击面摊开看

把上面四层的对策对齐到具体威胁,安全设计才有靶子。下图按数据流标注五类典型威胁与对应的防线:

  • 设备伪造:冒充合法设备上报假数据或骗取指令——靠设备侧强认证(一机一密、证书)破解。
  • 固件篡改:刷入带后门的固件——靠安全启动 + 验签 OTA + 回滚机制守住。
  • 重放攻击:录下合法报文原样重放——靠时间戳、序号、nonce 让旧报文失效。
  • 中间人(MITM):在链路中间窃听或改包——靠双向认证 + 加密,让伪造的对端通不过证书校验。
  • DDoS:用海量请求打垮入口——靠把入口收敛到单一网关、配合限流与防火墙。
  • 越权 / 跨租户:合法身份越界访问别人的资源——靠 RBAC 的 fail-closed 与租户隔离双重把关。

工程要点

  • 默认不可信,边界之外皆需验证:不要假设"内网就是安全的"。后端服务即便不直接对外,也要校验调用方身份,防止有人绕过网关直连。
  • 失败要 fail-closed,不要 fail-open:鉴权组件遇到瞬时故障时,宁可把请求当作"无权限"拒掉,也不要"出错就放行" ——后者会把一次抖动变成一道后门。
  • 密钥分级、按环境收紧:开发环境可以用弱默认值图方便,但生产必须强制强随机密钥;最好让程序在生产环境发现弱密钥时**直接启动失败 **,把问题挡在上线前。
  • 入口越少越好:把对外暴露面收敛到单一网关,现场协议端口(Modbus、裸 TCP/UDP)绝不直接上公网——它们大多没有认证,一旦暴露就是开门揖盗。
  • 传输默认加密:消息总线、Broker、HTTP 入口在跨网络时一律走 TLS;明文只在本地自测可接受。
  • 审计可追溯:关键操作(登录、改授权、下发命令)都要留痕,且日志里不能出现明文密钥或口令。

在 IoT DC3 中如何落地

DC3 的安全主线集中在鉴权 · 租户 · RBAC,并辅以安全策略 里的部署基线。它把上面四层的思路具体化为下面几条,而且对"已实现"和"设计已规划未实现"严格区分。

平台认证:两步登录与令牌

DC3 对外只有网关 dc3-gateway 一个入口。登录是两步握手,对应通信安全里的"防重放"思路:

  1. POST /api/v3/auth/token/salt:传 tenantname,先确认租户存在,返回一个随机盐。盐是无状态 的——服务端不存储、不做过期校验,仅随下一次登录请求一并核对;"5 分钟"只是接口文案里的建议使用时限,由客户端自律,当前服务端未强制过期。
  2. POST /api/v3/auth/token/generate:传 tenantnamesalt 和用盐哈希后的 password,校验通过返回 access token,* 有效期 12 小时*。

盐的作用是避免口令明文或固定哈希在链路上被重放。签发的 JWT 绑定 principal_id + tenant_id(而非用户名),注销时把身份写入 Caffeine 注销名单(denylist),旧令牌即便签名合法也会因签发时间早于注销点而失效。

平台信任传递:网关验签 + HMAC 透传

中心服务各有 HTTP 端口、默认不对外。隐患是:任何能直连后端端口的人,只要伪造一个"我是租户 A 管理员"的请求头,后端若无条件信任就被冒充。DC3 的解法是把认证信任分开——认证只在网关做一次,信任靠一段 HMAC-SHA256 签名传递:

  • 网关 AuthenticGatewayFilter 用三个头 X-Auth-Tenant / X-Auth-Login / X-Auth-Token 去鉴权中心核验,解析出真实 principal,序列化为 X-Auth-Principal,再用共享密钥签名得到 X-Auth-Sign 透传给后端。
  • 后端 GatewayJwtConverter 用同一密钥重算 HMAC,与 X-Auth-Sign常量时间比对,不符即拒;缺 tenantIdprincipalId 一律拒。
  • HMAC 未启用时,网关会主动删除入站的 X-Auth-Sign,防止下游被客户端自带的假签名诱骗。

生产 HMAC/密钥 fail-fast(硬约束)

pre / pro 环境下,若 AUTH_HMAC_SECRET 为空、或仍等于默认值 io.github.pnoker.dc3,服务启动即失败(抛 IllegalStateException,判定见 HmacAuthConfig.isProtectedEnvironment())。这是有意为之:宁可不启动,也不让生产实例跑在开发密钥上。生产请用强随机值(如 openssl rand -base64 48)通过环境变量注入,绝不硬编码或写进日志。鉴权中心签发令牌用的 DC3_SECURITY_KEY(默认 dc3.security.key.2026.io.github.pnoker)则只做"必须存在"的启动检查——缺失即启动失败,但不做"不得等于默认弱值" 的拒绝;因此仍必须主动替换为强随机值,一旦泄露,攻击者可伪造登录令牌。

平台授权:RBAC 的 fail-closed

验签拿到 principal 后,由 RBAC 决定"能做什么":principal → 角色(租户内)→ 资源码(全局)。权限解析带 5 分钟短缓存(键为 (tenantId:principalId))。最关键的是失败语义:

查不到权限 = 拒绝

权限加载发生瞬时故障时,GatewayJwtConverter 仍创建一个"已认证但权限为空"的令牌,任何 @PreAuthorize 守卫返回 403 。这是有意的 fail-closed——绝不把后端抖动伪装成放行。

多租户隔离:控制器层校验

RBAC 决定"能不能做这类操作",租户隔离决定"能不能碰这条数据",两者正交。隔离落在控制器层

  • 按 ID 查到实体后,BaseController.requireTenant() 比对实体 tenantId 与调用方租户,不一致(或不存在)抛 NotFoundException返回 404 而非 403——刻意用"不存在"避免泄露"某个跨租户资源是否存在"。批量查询走 filterTenant() 剔除非本租户条目。

没有数据库层的自动租户兜底

当前实现没有 MyBatis-Plus 租户行拦截器,隔离完全靠控制器层的 requireTenant / filterTenant。新增查询时务必主动带上租户校验,SQL 层不会自动按租户裁剪。

通信与数据安全:部署基线

传输加密与数据保护落在安全策略的生产基线里:RabbitMQ 与 EMQX 默认关闭 TLS,跨网络时必须启用(如 RABBITMQ_SSL_ENABLED=true,走 TLS 端口);网关 HTTP 入口应置于反向代理后终止 HTTPS;现场协议端口绝不直接上公网( DC3_BIND_HOST 默认 127.0.0.1,需显式改为 0.0.0.0 才对外)。

外部身份(IdP)尚未实现

dc3_identity_provider(OIDC/SAML 等外部 IdP 配置)与 dc3_external_identity(外部身份绑定)两张表已在 02-iot-dc3-auth.sql 中建好,principal.source_type 也预留了 EXTERNAL 取值,但对应的登录端点未实现、处于关闭状态 。当前可用的登录路径只有上面的本地凭据两步握手。

面向 AI 调用方的 OAuth 2.1

面向大模型/MCP 客户端的访问,DC3 提供了独立的 OAuth 2.1 授权服务(强制 PKCE、刷新令牌轮换、按 scope 与风险等级过滤工具),详见 Agentic 与 MCP鉴权 · 租户 · RBAC

延伸阅读

基于 AGPL-3.0 协议发布