3、安全更新通道设计:TLS/mTLS通信加密,证书管理与轮换,防重放攻击
安全更新通道,说白了就是给设备送固件的那条路。路如果不安全,你固件写得再好也没用。我见过太多项目,加密算法选得挺强,结果传输通道裸奔,中间人随便改个字节就能让设备变砖。嗯,这一章咱们就把这条路修结实。
3.1 为什么不能只用HTTP?
你想想看,设备要下载一个几十兆的固件包。如果走明文HTTP,攻击者在路由器上就能把包换了。更狠的是,他不需要改你的固件逻辑,只要在固件头里塞一段恶意脚本,设备启动时就能被远程控制。
所以,通道加密是底线。我个人习惯,不管设备多便宜,更新通道必须走TLS。哪怕资源受限,至少也要用DTLS或者精简的TLS 1.2。
3.2 TLS vs mTLS:选哪个?
TLS是单向认证——客户端验证服务器证书。mTLS是双向认证——两边都掏证书。选哪个,取决于你的设备能不能管好自己的私钥。
| 特性 | TLS(单向) | mTLS(双向) |
|---|---|---|
| 客户端验证服务器 | 是 | 是 |
| 服务器验证客户端 | 否 | 是 |
| 设备需要管理私钥 | 不需要 | 需要 |
| 防伪冒设备接入 | 弱(靠设备ID/Token) | 强(证书链验证) |
| 适合场景 | 消费级IoT、低成本设备 | 工业设备、网关、高安全场景 |
我在项目中遇到过这样的情况:客户选了mTLS,但设备私钥是硬编码在Flash里的。结果固件被逆向,私钥全泄露,整个产品线的设备都能被冒充。所以,选mTLS之前,先问问自己:你的设备能安全存私钥吗?如果不行,老老实实用TLS + 设备ID + Token认证,反而更安全。
3.3 证书管理与轮换
证书会过期,这是常识。但很多设备厂商把证书有效期设成10年、20年,觉得省事。嗯,这里要注意:证书有效期越长,私钥泄露后的影响范围越大。一旦泄露,攻击者能用那张证书伪装到天荒地老。
我建议的做法是:
- 设备端证书: 有效期1-2年,通过更新通道下发新证书。
- 服务器端证书: 有效期1年,提前30天预下发新证书。
- 根证书: 有效期5-10年,但私钥离线存储,只在签发中间CA时使用。
3.3.1 证书轮换流程
- 服务器生成新证书,用旧证书私钥签名。
- 设备在更新包中收到新证书 + 签名。
- 设备用本地存储的旧证书公钥验证签名。
- 验证通过后,设备存储新证书,并删除旧证书私钥(如果有)。
- 设备用新证书发起下一次TLS握手。
我曾经踩过一个坑:证书轮换时,设备只验证了新证书的签名,没检查新证书的颁发者。结果攻击者伪造了一个自签名证书,设备也接受了。从那以后,我强制要求设备必须验证新证书的完整证书链,直到信任的根证书。
3.4 防重放攻击:Nonce与时间戳
重放攻击是什么?攻击者截获一次合法的更新请求,然后反复发给服务器。服务器以为是新请求,就不断下发固件。设备流量被耗尽,或者固件被反复刷写导致损坏。
防重放,说白了就是让每个请求独一无二,且只能被接受一次。
3.4.1 方案一:Nonce(一次性随机数)
服务器每次下发更新通知时,带一个随机Nonce。设备发起更新请求时,必须把这个Nonce带回来。服务器收到后,检查Nonce是否在已使用列表中。如果重复,直接拒绝。
// 服务器生成Nonce
nonce = secure_random(16 bytes)
存储 nonce 到已下发列表(有效期5分钟)
// 设备请求更新
POST /update
{
"device_id": "abc123",
"nonce": "a1b2c3d4e5f6...",
"signature": "rsa_sign(nonce + device_id)"
}
// 服务器验证
if nonce 在已使用列表中:
拒绝
else:
标记 nonce 为已使用
处理更新请求
3.4.2 方案二:时间戳 + 窗口
设备在请求中带上当前时间戳,服务器检查时间戳是否在允许的偏差范围内(比如±30秒)。超出窗口的请求直接丢弃。
这个方案简单,但依赖设备时钟的准确性。如果设备时钟不准,或者被攻击者篡改,就容易出问题。
我个人习惯把两者结合:Nonce + 时间戳。Nonce防重放,时间戳防延迟。攻击者即使截获了请求,也无法在几分钟后重放,因为时间戳已经过期。
3.5 整体通道设计架构
下面这张图,是我在项目中常用的更新通道架构。你可以看到,从设备启动到固件下载,每一步都有安全措施。
3.6 避坑指南
做安全更新通道,有几个坑我反复踩过,今天一并列出来:
- 证书硬编码: 我曾经见过产品把服务器证书硬编码在固件里,结果证书一换,所有设备都得OTA升级才能连上新服务器。正确做法是证书可配置,通过安全通道下发。
- Nonce重用: 有些实现用设备ID + 递增序列号当Nonce。攻击者只要拿到一次请求,就能伪造后续请求。Nonce必须真随机,且服务端严格去重。
- 忽略时钟同步: 时间戳方案依赖设备时钟。如果设备电池没电、时钟复位到1970年,所有请求都会被拒绝。我建议设备每次上线先NTP同步,同步失败则用Nonce方案兜底。
- 证书链不完整: 设备只验证服务器证书,不验证中间CA。攻击者如果拿到一张由合法CA签发的证书(比如通过泄露的中间CA私钥),就能伪装服务器。设备必须验证完整证书链到根证书。