写点什么

车联网通信安全之 SSL/TLS 协议|车联网系列专题 06

作者:EMQ映云科技
  • 2022 年 4 月 19 日
  • 本文字数:7055 字

    阅读完需:约 23 分钟

车联网通信安全之 SSL/TLS 协议|车联网系列专题 06

前言

在汽车出行愈加智能化的今天,我们可以实现手机远程操控车辆解锁、启动通风、查看车辆周围影像,也可以通过 OTA(空中下载技术)完成升级车机固件、更新地图包等操作,自动驾驶技术更是可以让车辆根据路面状况自动辅助实施转向、加速和制动。


然而,每项提升我们使用体验的功能,都有可能成为致命的安全漏洞

腾讯安全科恩实验室曾向外界披露并演示过如何凭借 3/4G 网络或者 WiFi 网络,在远程无物理接触的情况下入侵智能汽车,实现对车辆信号灯、显示屏、门锁甚至是刹车的远程控制。不仅如此,攻击者甚至可以利用某个已知漏洞获取智能汽车的 Autopilot 控制权,对车辆行驶方向进行操控。

因此,我们在车联网平台构建时也应充分认识到通信安全、身份认证、数据安全的重要性,正确使用相关加密认证等技术手段来提供保障。

本篇文章我们将全面介绍 SSL/TLS 协议在车联网通信安全中的应用,希望能让大家对 SSL/TLS 的作用有更清晰直观的认识。此外,我们还将详细讲解 SSL/TLS 的配置方式,确保大家能正确使用 SSL/TLS,实现安全性保障。

车联网安全通信 MQTTS 协议

MQTTS 协议是在 MQTT 协议的基础上,封装了一层基于 SSL/TLS(传输层安全)的加密协议, 它确保车机端和车联网平台通信是加密的。

但如果没有正确配置 SSL/TLS,依然会存在很多安全隐患。想要真正运用好 SSL/TLS,我们必须了解 SSL/TLS 解决了哪些问题,以及对 SSL/TLS 用到的密码技术有初步的认知。

通常情况下,通信过程需要具备以下四个特性,才能被认为是安全的,分别是:机密性、完整性、身份认证不可否认

机密性

机密性是安全通信的基础,缺少机密性任何窃听通信的人都可以轻而易举获取到你的诸如登录密码、支付密码等关键隐私信息。

实现机密性最常用的手段就是加密

根据密钥的使用方法,加密方式可以分为对称加密和非对称加密两种。

对称加密的通信双方要使用相同的密钥来进行加解密,所以必然会遇到密钥配送问题,即我需要对方能够解密我发送过去的密文,我就必须把我加密时使用的密钥告诉对方,但是我如何保证将密钥与对方同步的过程中密钥不会泄漏?这就是对称加密的密钥配送问题。

目前常用的解决方案是使用非对称加密和使用 Diffie-Hellman 密钥交换算法

非对称加密的核心是生成一对密钥,一个是公钥,一个是私钥,公钥用于加密,它是公开的,可以派发给任何人使用,私钥用于解密,不参与通信过程,需要被妥善保管,这样就解决了密钥配送问题。

Diffie-Hellman 密钥交换算法的核心思想则是通信双方交换一些公开的信息就能够计算出相同的共享密钥,而窃听者获得这些公开信息却无法计算出相同的密钥。

Diffie-Hellman 算法的一个好处是没有非对称加密的性能问题,非对称加密虽然解决了密钥配送问题,但非对称加密算法的运算速度远远不及对称加密算法,它们甚至能有几百倍的差距。虽然保障了安全,但严重影响了通信的效率,丧失了实用性。

因此,实际应用时通常会将对称加密和非对称加密结合使用,这样既解决了密钥配送问题,又解决了非对称加密带来的性能问题,这种方式通常又被称为混合加密

完整性

仅仅具备机密性还不足以实现安全的通信。

尽管对加密之后的密文进行针对性篡改的难度有所上升,例如篡改之后明文的数据结构很有可能会遭到破坏,

带来意想不到的隐患。

因此,我们还需要在机密性的基础上进一步保证信息的完整性

常见的做法就是使用单向散列函数计算消息的散列值,然后将消息和散列值一起发送给接收者

身份认证

但可惜的是,当攻击者同时伪造消息和对应的散列值时,接收者依然无法识破这个伪装。

因此,我们不仅需要确认消息的完整性,还需要确认消息是否来自合法的发送者,也就是说还需要对身份进行认证。这个时候我们就需要用到消息认证码。

由于消息认证码本身并不提供消息机密性的保证,所以在实际使用中,通常会将对称加密与消息认证码结合使用,以同时满足机密性、完整性和认证的要求,这种机制也被称作认证加密(AEAD)。

目前业界推荐的安全方案是采用 AEAD 算法,SSL/TLS 1.3 版本中也正式废除了其他加密方式,仅支持 AEAD 加密。

不可否认

现在,我们已经保证了消息的机密性,同时也能识别出伪装和篡改,但是由于消息认证码的核心是需要通信双方共享密钥,因此又引发了新的问题,即无法对第三方证明以及无法防止否认

假设 Bob 接收了来自 Alice 的消息,想要向第三方证明这条消息的确是 Alice 发送的,就需要将原本只有两个人知道的密钥告诉给第三方,这显然会增加后续继续使用这个密钥通信的安全风险。同时,即便第三方拿到了密钥,也无法得出有效的结论,例如 Bob 可以宣称这条消息是由 Alice 构造的,因为 Alice 也持有相同的密钥。

因此,我们还需要引入数字签名机制。由于只有持有私钥的人才能施加正确的签名,这样发送者就无从否认了。而公钥只是用来验证签名,所以可以随意派发给任何人。

可能敏感的读者到这里心中已经有些疑问了,是的,取到公钥的人如何确认这个公钥的确来自自己期望的通信对象呢?

到了这一步,我们只能借助外力的帮助了,委托公认的可信第三方,也就是我们现在常说的认证机构或 CA,由它来给各个公钥施加签名,形成公钥证书

以上这些密码技术,共同构成了现代安全通信领域的基石。

 SSL/TLS 作为目前世界上应用最广泛的密码通信方法,综合运用了前面提到的对称加密、非对称加密、消息认证码、数字签名、伪随机数生成器等密码技术,来提供通信安全保障。

考虑到密码学技术是不断进步发展的,或者说目前看似可靠的加密算法,可能在第二天就会被宣告攻破,所以 SSL/TLS 并没有强制使用某一种密码技术,而是提供了密码套件(Cipher Suite)这一机制,当某项密码技术被发现存在弱点,可以随时像零件一样替换它,当然前提是客户端和服务端使用相同的密码技术。

这也延伸出了 SSL/TLS 的握手协议,协商使用的密码套件就是这一部分协议的主要工作之一。

因此,如何正确选择密码套件,也成为了保障安全性的一个重要环节。这里我也会对目前推荐的密码技术和加密算法进行一个简单的整理,希望可以帮助各位读者查漏补缺:

  • 对称加密算法中 RC4、DES、3DES 都已经被认为是不安全的了,目前推荐使用的只有 AES 和 ChaCha20。ChaCha20 是 Google 设计的一种加密算法,如果 CPU 或软件不支持 AES 指令集,ChaCha20 可提供比 AES 更好的性能。

  • AES 这类对称加密算法只能加密固定长度的明文,想要加密任意长度的明文,还需要用到分组模式。早期的 ECB、CBC、CFB、OFB 等分组模式已经被认定为存在安全漏洞,目前更推荐使用 GCM、CCM 和 Poly1305。

  • 常用的非对称加密算法有 DH、RSA、ECC 这几种。由于 DH 和 RSA 都不具备前向安全性,目前已经不推荐使用,TLS 1.3 中更是直接废除了 DH 和 RSA 算法,取而代之的是安全强度和性能都明显优于 RSA 的 ECC 算法,它有两个子算法,ECDHE 用于密钥交换,ECDSA 用于数字签名。但需要注意的是,由于 ECDHE/DHE 不提供身份验证,因此服务端应当启用对客户端证书的验证。

  • 散列算法方面,我们熟知的 MD5 和 SHA-1 都已经被认定为不再可靠,不推荐继续使用。目前通常建议使用 SHA256 或更高版本。

在了解推荐使用的密码技术以后,也许我们想要修改客户端或服务端的密码套件配置,但此时我们可能会发现这些密码套件的名称还有点难以理解。

例如 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,其中 TLS 只是表示协议,ECDHE 表示密钥交换算法,ECDSA 表示身份认证算法,AES_256_CBC 表示批量加密算法,SHA384 表示消息认证码 MAC 算法。这通常是 TLS 1.2 中密码套件的命名格式,而到了 TLS 1.3 则又发生了一些变化。由于 TLS 1.3 只接受使用 ECDHE 算法进行密钥交换,并且使用 ECDSA 进行身份认证,因此它的密码套件名称可以精简成 TLS_AES_256_GCM_SHA384 这种格式。

如果仅从安全性角度出发,个人建议使用 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 和 TLS_AES_256_GCM_SHA384。但考虑到目前仍有很多以 RSA 方式签发的证书正在使用,因此我们还需要根据自身情况来选择是否要继续使用 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384

构建安全认证体系典型架构

采用基于 PKI/CA 的数字证书体系是解决车联网安全关键的一步,也是大多数车企典型安全管理体系。其主要的设计思路如下:

1. 基于数字证书的身份标识:通过 PKI/CA 系统建立严谨的证书管理和使用规范,为车联网的应用和终端颁发数字证书,虚拟身份和真实身份进行绑定,解决身份标识和唯一性问题(可实现一机一密或一型一密);

2. 所有数据交互时通过终端的身份唯一标识证明身份的真实性,防止第三方恶意入侵;

3. 基于数字证书安全功能,提供身份鉴别、身份认证、数据加解密、数字签名与验签等多种功能,满足车联网中 TSP、OTA 等多业务安全需求。

车联网平台安全通信交互流程,一般是将车机端申请终端证书,下载并完整安装后通过 MQTTS 安全协议与云端平台请求建立安全连接。

在云端我们可以选择在云厂商的负载均衡产品、基于 Nginx/HAProxy 自行搭建的 LB 层或是 MQTT Broker 层进行认证鉴权,同时通过 proxy_protocol v2 将车机端的 ID 信息、用户名密码及证书的 CN/SN 等信息通过调用 PKI/CA 统一认证接口进行唯一性认证,实现一机一密或一型一密的安全认证。

MQTTS 通信中单、双向认证的配置方式

SSL/TLS 连接认证认证的是对方身份,是否是可信的通信对象,认证的依据则是通信对象提供的证书。

通常情况下是由客户端对服务端的身份进行认证,也就是所谓的单向认证。那么双向认证顾名思义就是在单向认证的基础上,服务端对客户端的身份进行认证。

认证的原理其实非常简单,以单向认证为例,最简单的情况就是服务端在 SSL/TLS 握手阶段发送服务端证书,客户端验证该证书是否由受信任的 CA 机构签发,也就是使用受信任的 CA 证书中的公钥来验证服务端证书中的数字签名是否合法。

当然,大部分情况会比上述的稍微复杂一些,以尽可能保护根证书的安全。

大部分情况下常见 CA 机构的根 CA 证书和中间 CA 证书都已经内置在我们的操作系统中了,只有少数情况下需要自行添加信任的 CA 证书。


多级证书或者说证书链的认证过程会稍微复杂一些,但如果我们搞明白了前面说的证书签发逻辑,其实理解起来也很简单。

还是以单向认证为例,如果客户端只信任了根 CA 证书,那么服务端在握手阶段就需要发送服务端证书和根 CA 证书到服务端证书之间的所有中间 CA 证书。只有客户端拿到了完整的证书链,才能通过自己持有的根 CA 证书一层一层往下验证,缺少中间 CA 导致证书链不完整或者包含了错误的中间 CA,都会导致信任链中断而无法通过认证。

如果客户端除根 CA 证书以外,还持有一部分中间 CA 证书,那么在认证过程中,服务端还可以省略这些中间 CA 证书的发送,来提高握手效率。

因此,当我们配置单向认证时,需要在服务端指定服务端证书和中间 CA 证书(可选),以及服务端私钥文件。客户端则需要信任相应的根 CA 证书,信任的方式可以是在连接时指定或者通过证书管理工具将该根 CA 证书添加到信任列表。通常客户端库还提供了对端验证选项允许选择是否验证证书,关闭对端验证将在不验证证书的情况下直接创建加密的 TLS 连接。但这会带来中间人攻击的安全风险,因此强烈建议启用对端验证

在启用对端验证后,客户端通常还会检查服务器证书中的域名(SAN 字段或 CN 字段)与自己连接的服务器域名是否匹配。如果域名不匹配,则客户端将拒绝对服务器进行身份验证或建立连接。

双向认证的配置方式只需要在单向认证的基础上,在服务端启用对端验证即表示启用双向认证以外,再参考服务端证书的配置方式正确配置客户端证书即可。

常见 TLS 选项介绍

当使用 EMQX 配置 SSL/TLS 连接时,通常会有 certfile、keyfile 等选项,为了帮助大家更好地了解这些选项的配置方式,接下来我们会对这些常见的 TLS 选项做一个简单的梳理和介绍:

  • certfile,用于指定服务端或客户端证书和中间 CA 证书,需要指定多个证书时通常将它们简单地合并到一个证书文件中即可。

  • keyfile,用于指定服务端或客户端私钥文件。

  • cacertfile,用于指定 Root CA 证书,单向认证时客户端需要配置此选项以校验服务端证书,双向认证时服务端也需要配置此选项以校验客户端证书。

  • verify,用于指定是否启用对端验证。客户端启用对端验证后通常还会去检查连接的服务器域名与服务器证书中的域名是否匹配。客户端与服务端同时启用则意味着这将是一个双向认证。

  • fail_if_no_peer_cert,这是一个服务端的选项,通常在服务端启用对端验证时使用,设置为 false 表示允许客户端不发送证书或发送空的证书,相当于同时开启单向认证和双向认证,这会增加中间人攻击的风险。

  • versions,指定支持的 TLS 版本。通信双方会在握手过程中,将 versions 选项中指定的版本发送给对方,然后切换至双方都支持的最高版本。同时也会基于该协议版本来协商密码套件。

  • ciphers,指定支持的密码套件。注意事项:避免使用前文提到的或其他被认定为弱安全性的密码套件,以及当使用包含 ECDSA 签名算法的密码套件时,需要额外注意自己的证书是否为 ECC 类型。

  • server_name_indication,服务器名称指示,这是一个客户端的选项。通常在客户端启用对端验证且连接的服务器域名与服务器证书中的域名不匹配时使用。例如服务器证书中的域名为 abc.com,而客户端连接的是 123.com,那么就需要客户端在连接时指定 server_name_indication 为 abc.com 表示自己信任该域名以通过证书检查。又或者将 server_name_indication 设置为 disable 来关闭此项检查,但这会增加中间人攻击的风险,通常并不建议这样做。

示例

为了便于演示,我们会使用 EMQX Broker (4.3.0 版本及以上)作为服务端,在 EMQX Broker 的控制台中使用 Erlang 的 ssl:connect/3 函数作为客户端。

单向认证

修改 EMQ X Broker 配置如下:

# 监听端口我们使用默认的 8883listener.ssl.external = 8883# 服务端私钥文件listener.ssl.external.keyfile = etc/certs/zhouzb.club/Nginx/2_zhouzb.club.key# 证书捆绑包文件,包含了服务端证书和中间 CA 证书listener.ssl.external.certfile = etc/certs/zhouzb.club/Nginx/1_zhouzb.club_bundle.crt# 不开启对端验证listener.ssl.external.verify = verify_none# 支持 TLS 1.2 和 TLS 1.3listener.ssl.tls_versions = tlsv1.3,tlsv1.2# 服务端支持的密码套件listener.ssl.external.ciphers = TLS_AES_256_GCM_SHA384,TLS_AES_128_GCM_SHA256,TLS_CHACHA20_POLY1305_SHA256,TLS_AES_128_CCM_SHA256,TLS_AES_128_CCM_8_SHA256,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
复制代码

启动 EMQ X Broker 并进入控制台:

$ ./emqx console
复制代码

使用 ssl:connect/3 函数连接:

%% 1. 指定用于验证服务端证书的 Root CA 证书%% 2. 启用对端验证%% 3. 仅支持 TLS 1.2%% 4. 仅支持 TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 这一个密码套件ssl:connect("zhouzb.club", 8883, [{cacertfile, "etc/certs/zhouzb.club/DigiCertGlobalRootCA.crt.pem"},                                  {verify, verify_peer},                                  {versions, ['tlsv1.2']},                                  {ciphers, ["TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"]}]).
复制代码

 

双向认证

为简化表意,这里将继续使用服务端证书来充当客户端证书。但是这存在严重的安全隐患,在生产环境中请勿这样使用!

修改 EMQ X Broker 配置如下:

# 监听端口我们使用默认的 8883listener.ssl.external = 8883# 服务端私钥文件listener.ssl.external.keyfile = etc/certs/zhouzb.club/Nginx/2_zhouzb.club.key# 证书捆绑包文件,包含了服务端证书和中间 CA 证书listener.ssl.external.certfile = etc/certs/zhouzb.club/Nginx/1_zhouzb.club_bundle.crt# 指定用于验证客户端证书的 Root CA 证书listener.ssl.external.cacertfile = etc/certs/zhouzb.club/DigiCertGlobalRootCA.crt.pem# 启用对端验证listener.ssl.external.verify = verify_peer# 要求客户端必须提供证书listener.ssl.external.fail_if_no_peer_cert = true# 支持 TLS 1.2 和 TLS 1.3listener.ssl.tls_versions = tlsv1.3,tlsv1.2# 服务端支持的密码套件listener.ssl.external.ciphers = TLS_AES_256_GCM_SHA384,TLS_AES_128_GCM_SHA256,TLS_CHACHA20_POLY1305_SHA256,TLS_AES_128_CCM_SHA256,TLS_AES_128_CCM_8_SHA256,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
复制代码

启动 EMQ X Broker 并进入控制台,然后使用 ssl:connect/3 函数连接:

%% 1. 指定用于验证服务端证书的 Root CA 证书%% 2. 启用对端验证%% 3. 仅支持 TLS 1.2%% 4. 仅支持 TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 这一个密码套件ssl:connect("zhouzb.club", 8883, [{cacertfile, "etc/certs/zhouzb.club/DigiCertGlobalRootCA.crt.pem"},                                  {certfile, "etc/certs/zhouzb.club/Nginx/1_zhouzb.club_bundle.crt"},                                  {keyfile, "etc/certs/zhouzb.club/Nginx/2_zhouzb.club.key"},                                  {verify, verify_peer},                                  {versions, ['tlsv1.2']},                                  {ciphers, ["TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"]}]).
复制代码

结语

车联网领域的网络通信安全和数据安全受到越来越多的关注,是车联网企业提高竞争力的关键影响因素之一。希望通过本文,读者可以掌握 SSL/TLS 协议的使用方式,在实际业务场景中正确应用,实现车联网通信安全保障。

用户头像

全球领先的开源物联网基础设施软件供应商 2021.06.09 加入

面向 5G 和物联网市场的消息与流处理开源软件公司。

评论

发布
暂无评论
车联网通信安全之 SSL/TLS 协议|车联网系列专题 06_车联网_EMQ映云科技_InfoQ写作社区