一.DDS介绍
1.1.DDS的来源
DDS即Data Distribution Service,是位于应用程序与操作系统之间的中间件,在互联网的工业应用背景下正被广泛使用。随着互联网和软件技术的发展,不断丰富的信息改变了数据服务的模式、服务的类型和服务的质量,加上工业应用对性能、安全性和可扩展性有非常严格的要求作为标准,DDS在工业互联网领域应运而生,以满足该领域对数据服务的需求和对数据的治理能力,使分散的数据得到集中、统一的处理和应用。
DDS在车联网领域的应用也十分广泛,一方面,自动驾驶催生了对高速信息交换的大量需求,另一方面,车辆与道路基础设施之间的信息交换以及车辆之间的信息交换也产生了大量的数据交换需求,DDS的一些特性能够很好地契合这些需求。
此外,在很多工业互联网的领域都存在DDS的应用场景。比如空中交通管制系统使用DDS作为各个飞行控制中心交流飞行计划并作出飞行决定的方式,风力发电的涡轮机使用DDS监控每台涡轮机的工作状态,等等。
1.2.DDS的特性
1.2.1.以数据为中心的体系结构概念
DDS以数据为中心来建立数据分发的体系结构,即DDS更关注的是数据本身的状态,而不是数据的变化状态。我们使用DDS不需要对历史数据进行关联分析,而是直接使用数据当前的状态。比如,自动驾驶车辆根据雷达和摄像头等感知系统采集的信息做出驾驶决策,需要用到的是车辆当前环境下的道路信息,而不是任何状态的变化信息,这是以数据为中心的数据分发体系与以消息为中心的分发体系的重要区别。
1.2.2.用点对点的机制实现中心化模型
在具体的实现层面,DDS的核心设计理念是用点对点的机制实现中心化的模型。DDS使用了数据总线的概念,以集中的方式思考信息,同时对数据进行分布式点对点访问,以解决传输效率的问题。这种实现思路类似于一个基于p2p的cdn系统,当客户端想要下载视频的时候,通过请求*服务器获取下载地址,而这个下载地址指向了离客户端最近的一个终端,客户端最终与它相近的终端建立点对点的连接获取视频内容,这样的传输高效且不容易遇到性能瓶颈。
DDS中间件封装了复杂的连接逻辑,应用程序只需要关心想要获取的数据、想要发布的数据以及想要使用的服务,而无需关心连接建立的过程,这极大简化了开发者的接入过程,降低了研发成本。
1.2.3.与数据库的区别
DDS是在TCP/IP协议基础之上实现的“数据共享中心”,它的功能与数据库比较相似,但却又有很大的区别。我们在使用数据库时必须使用已经存在于数据库中的数据,即检索的是历史数据;但使用DDS时,使用的是未来的还未生成的数据,即你只要订阅了你感兴趣的数据,未来无论什么时候当这个数据生成的时候,你都会收到最新的数据。
二.DDS的安全特性
2.1.DDS安全特性概述
DDS安全特性包含两个大的方面,一方面,DDS提供域级别的安全保护;另一方面,保护手段的粒度也可以细化到域内部。(本文提到的DDS安全特性均指的是RTI DDS的安全特性,除非明确提到OMG DDS)
2.1.1.基于域的安全保护
由开发者或维护者决定域的成员,被包含在域内的成员具备在域内执行任何允许的操作。域内成员对topic的访问权限也由其域身份所决定。从域的内部来看,就是一个没有经过安全防护的网络(在不考虑域内访问控制规则的情况下)。
(图片来源:hxxps://community.rti.com/static/documentation)
基于域的安全防护可以达到如下效果:
1)检测针对消息的篡改和注入,即完整性保护;
2)保护消息的机密性。
关于域级别的安全防护需要明确的一点是,域级别的安全防护一般通过TLS 或 DTLS来实现,即通过传输层的安全特性来实现安全域。
2.1.2.域内粒度的保护
域内粒度的保护基于最小权限原则制定,约束对每个topic和partition的读、写权限。
(图片来源:hxxps://community.rti.com/static/documentation)
2.2.RTI DDS安全插件介绍
RTI DDS通过安全插件的机制实现诸如认证、加密等安全功能。安全插件允许以细粒度和可插拔的方式满足数据总线安全要求,每个安全插件覆盖不同的安全范围,主要包含以下几个方面:
认证:提供针对调用DDS接口的应用程序或用户的身份认证。还包括通信双方相互认证和共享密钥的基础设施;
加解密:实现加解密算法、hash算法、签名算法等。还包括从共享密钥衍生密钥的算法;
访问控制:提供针对DDS实体可执行操作的访问控制决策;
日志:审计所有安全相关的事件,以此增强系统的透明度,保证系统的可用性。
(图片来源:hxxps://community.rti.com/static/documentation)
RTI 安全插件具备以下特性:
- 解耦插件以解决不同的安全问题
- 安全插件可能会在任何传输上层协议上运行,包括内置的基于多播的UDP协议和 TCP协议
- 安全组播支持可将数据高效且可扩展地分发给许多订阅者
- 可以自定义安全插件以适应专有或符合 FIPS 140-2 的加密解决方案,利用自定义安全硬件或以多种方式更改插件的行为。安全插件 SDK 能够自定义安全插件以满足系统的安全要求。
- OMG DDS 安全规范以一对多、友好、以数据为中心的方式处理通信的安全方面,使应用程序能够根据共享数据的性质定义不同的安全策略。这与 DDS 的去中心化性质相一致并证明其优势:
- 无单点故障
- 高性能和可扩展性
2.3.DDS支持的加解密算法
2.3.1.数据流相关
2.3.1.1.针对数据完整性
算法: AES-GCM, used in GMAC mode (not configurable)
密钥长度: 128, 192 or 256 bits (selectable via configuration)
2.3.1.2.数据机密性和完整性保护
算法: AES-GCM (not configurable)
密钥长度: 128, 192 or 256 bits (selectable via configuration)
2.3.2.数据来源认证
算法: AES-GCM, used in GMAC mode (not configurable)
密钥长度: 256 (not configurable)
2.3.3.密钥交换
2.3.3.1.共享密钥
- 支持Diffie-Hellman in ephemeral mode (DHE), with 2048-bit MODP Group parameters as specified in RFC 3526 (not configurable)
- 支持EC Diffie-Hellman in ephemeral mode (ECDHE), with secp256r1 as specified in FIPS PUB 186-4 1 as its curve (not configurable)
- Selection between DHE and ECDHE happens via configuration
2.3.3.2.密钥衍生
- HMAC-based Key Derivation Function (HKDF) with SHA-256 as specified in RFC5869 (not configurable)
2.3.3.3.保证密钥交换过程中的机密性和完整性
- AES-GCM with 256 bits key (not configurable)
2.3.4.数字签名
- 内置对RSAwithSHA256的支持
- 内置对ECDSAwithSHA256的支持
- 通过配置选择密钥对
2.4.DDS安全特性的落地
2.4.1.两种文件保障DDS分布式系统的安全性
DDS通过一个Governance文件来制定domain和topic相关的安全规则,这个文件包含domain id与规则的映射关系。管理文件规定什么类型的保护手段将被应用,明确哪些类型的topic将被保护。所有域成员都必须加载同一个Governance文件,无论通过复制还是共享路径的方式。
每一个加入到安全域的成员必须关联一个Permissions文件,Permissions文件规定本地成员被授权的行为集合。
Governance文件与Permissions文件的区别:
Governance文件定义保护的范围和对应安全手段的范围,而Permissions文件定义访问控制的细节。
需要重点指出的是,两个文件都需要使用Permissions CA进行签名。
2.4.2.两类证书提供安全基础支持
DDS通过如下三类证书来支撑其安全特性的实现:
1)Permissions CA Certificate
由所有域成员共享,用来认证Governance文件和Permissions文件的合法性。
2)Identity CA Certificate
由所有域成员共享,用来认证其他域成员的身份。
2.4.3.针对域成员的安全实现
在同一个安全域下的成员需要相互进行身份认证,为达到这个目的,每个域成员都需要一个Identity证书和私钥。Identity证书需要被Identity CA签名,域成员将使用Identity CA来认证对端通信者的身份。经认证的成员通过交换Permission文件来声明自己的权限。Permission文件需要经过Permission CA的签名,另外,Permission文件里的授权信息需要和Identity 证书绑定,以证明经过认证的Identity具备对应的权限。
Identity和permission由如下文件定义:
- Identity Certificate由Identity CA签发, 域内成员通过请求获取Identity Certificate来认证本地的其他域成员;
- Private key,由本地成员自己持有自己的私钥,主要用于身份认证的过程。
- Permissions CA签发的Permissions文件,用来声明该成员可以加入的domain以及partition以及可以读写的Topic。
(图片来源:hxxps://community.rti.com/static/documentation)
DDS实现了比较完整的身份认证及访问控制的手段,但如果这套机制想要达到其安全目标,需要解决一个DDS解决不了的问题留:私钥的安全存储。密钥的安全存储可能是所有中间件面对的共同难题。
2.5.使用DDS安全特性
本小节将详细地介绍DDS安全特性中提到的几个关键元素,包括Governance文件、Permissions文件等等。
2.5.1.QOS
使用域成员的PROPERTY QosPolicy使能和配置Security Plugin,既可以在代码中设置属性的值,也可以在xml文件中设置。
在安全插件中有两类属性:
- 以dds.sec.开头,在DDS安全标准中定义的,用来配置指定插件的特征,如认证、访问控制等;
- 以com.rti.serv.secure.开头,实现相关的属性。用于额外的功能或参数,可以根据DDS安全声明配置,但是没有声明配置方法。
...
<property>
<value>
<element>
<name>com.rti.serv.load_plugin</name>
<value>com.rti.serv.secure</value>
</element>
<element>
<name>com.rti.serv.secure.library</name>
<value>nddssecurity</value>
</element>
<element>
<name>com.rti.serv.secure.create_function</name>
<value>RTI_Security_PluginSuite_create</value>
</element>
</value>
</property>
...
2.5.2.公钥基础设施
2.5.2.1.Identity证书
每一个域成员的身份由两部分组成:
- 由Identity CA签发的X.509证书(PEM格式),包含一个公钥,并于主体名称绑定。通过dds.sec.auth.identity_certificate属性声明Identity证书。
- 2048位的RSA私钥、256位的Elliptic Curve私钥,或其他OpenSSL支持的私钥。使用dds.sec.auth.private_key属性声明私钥。
2.5.2.2.Certificate Chaining
如果Identity 证书不是由Identity CA签发,则需要在同一个文件(或字符串)中声明完整的证书链,使用dds.sec.auth.identity_certificate属性进行声明。
2.5.2.3.Alternative Cas
当涉及到多个不同的Identity CA时,无法将他们声明为同一个证书链,可以使用authentication.alternative_ca_files属性来声明所有的证书链,每个都需要进行认证。
2.5.2.4.Certificate Revocation
通过authentication.crl属性声明被废止的证书。
2.5.2.5.Multiple Certificate Revocation Lists
authentication.crl属性可以声明多个crl。
2.5.2.6.Governance and Permissions
Governance通过dds.sec.access.governance属性声明,访问控制规则通过dds.sec.access.permissions属性声明。两个文件都要经过Permissions CA签名,签名标准遵循PKCS#7。通过dds.sec.access.permissions_ca属性声明Permissions CA。
Permissions CA 和 Identity CA可以相同也可以不同。可以通过access_control.alternative_permissions_authority_files属性声明多个Permissions CA,每个证书都会用来认证Permissions 文件。
2.5.3.Governance文件
Governance文件声明哪个DDS domain将被保护,以及保护的细节。可以在Governance XML文件中声明domain级别和topic级别的规则。
Governance 文件必须经过Permissions CA签名,签名标准为PKCS#7。通过dds.sec.access.governance属性声明签过名的Governance文件。
所有的域参与者需要加载同一个Governance文件或者兼容的版本。
2.5.3.1.声明Domain IDs
32位无符号证书,一般0到232之间,可以单独声明,也可以声明一个区间:
<domains>
<!-- Domains 3 and 7 -->
<id>3</id>
<id>7</id>
<!-- Domains from 10 to 20, inclusive -->
<id_range>
<min>10</min>
<max>20</max>
</id_range>
<!-- Domain 50 and above -->
<id_range>
<min>50</min>
</id_range>
</domains>
2.5.3.2.domain级别的规则
- 在<domain_rule>标签中声明,影响<domain>标签中声明的domain;
- < allow_unauthenticated_participants>是否运行未经认证的domain;
- < enable_join_access_control>规定Permissions文件中participant级别的规则是否对远程参与者生效;
- <discovery_protection_kind> and< liveliness_protection_kind>:OMG DDS Security定义了一系列终端发现和参与者安全生命周期的内置Topic,这些规则规定针对这些Topic实施什么样的保护级别,包括ENCRYPT, ENCRYPT_WITH_ORIGIN_AUTHENTICATION, SIGN, SIGN_WITH_ORIGIN_AUTHENTICATION, NONE;
- < rtps_protection_kind>规则什么样的保护被应用于RTPS消息,包括ENCRYPT, ENCRYPT_WITH_ORIGIN_AUTHENTICATION,SIGN,SIGN_WITH_ORIGIN_AUTHENTICATION, NONE;
2.5.3.3.topic级别的规则
Topic级别的规则定义在< topic_rule>标签下,通过< topic_expression>属性识别需要应用规则的topic。所有的<topic_rule>规则都定义在< topic_access_rules>标签下。
- <enable_discovery_protection> / <enable_liveliness_protection>: 是否使能 domain-level 的规则中<discovery_protection_kind> and <liveliness_protection_kind> 定义的规则;
- <enable_read_access_control> / <enable_write_access_control>: 读写权限控制对本地或远程的域参与者的DataReader/DataWriter是否生效;
- <metadata_protection_kind>: 应用到RTPS 子消息的保护类别。可选值范围包括ENCRYPT, ENCRYPT_WITH_ORIGIN_AUTHENTICATION,SIGN,SIGN_WITH_ORIGIN_AUTHENTICATION, NONE;
- <data_protection_kind>: 相关Topic数据的payload的保护类别,可选值的范围包括ENCRYPT, SIGN, NONE。
如下是一个来自rti官方的例子:
<?xml version="1.0" encoding="UTF-8"?>
<dds xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://community.rti.com/schema/6.1.0/dds_security_governance.xsd">
<domain_access_rules>
<domain_rule>
<domains>
<id_range>
<min>0</min>
</id_range>
</domains>
<allow_unauthenticated_participants>
FALSE
</allow_unauthenticated_participants>
<enable_join_access_control>TRUE</enable_join_access_control>
<discovery_protection_kind>ENCRYPT</discovery_protection_kind>
<liveliness_protection_kind>ENCRYPT</liveliness_protection_kind>
<rtps_protection_kind>SIGN</rtps_protection_kind>
<topic_access_rules>
<topic_rule>
<topic_expression>Sq*</topic_expression>
<enable_discovery_protection>FALSE</enable_discovery_protection>
<enable_liveliness_protection>FALSE</enable_liveliness_protection>
<enable_read_access_control>FALSE</enable_read_access_control>
<enable_write_access_control>FALSE</enable_write_access_control>
<metadata_protection_kind>NONE</metadata_protection_kind>
<data_protection_kind>NONE</data_protection_kind>
</topic_rule>
<topic_rule>
<topic_expression>*</topic_expression>
<enable_discovery_protection>TRUE</enable_discovery_protection>
<enable_liveliness_protection>TRUE</enable_liveliness_protection>
<enable_read_access_control>TRUE</enable_read_access_control>
<enable_write_access_control>TRUE</enable_write_access_control>
<metadata_protection_kind>ENCRYPT</metadata_protection_kind>
<data_protection_kind>ENCRYPT</data_protection_kind>
</topic_rule>
</topic_access_rules>
</domain_rule>
</domain_access_rules>
</dds>
2.5.4.Permissions文件
Permissions文件规定允许域成员执行的行为,如是否允许其加入某个安全域、是否允许其发布订阅指定topic等。Permissions文件包含一组授权,在<allow_rule> and <deny_rule>节中进行定义。
授权和域成员的identity绑定,<subject_name>节指定了grant所授予的具体域成员。< subject_name >标签指示的内容要与identity证书里的主体名词一致。可以通过dds.sec.access.permissions属性指定签名过的Permissions文件。
如下是一个来自rti官方的例子:
<?xml version="1.0" encoding="UTF-8"?>
<dds xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://community.rti.com/schema/6.1.0/dds_security_permissions.xsd">
<permissions>
<grant name="ParticipantA">
<subject_name>
C=US, ST=CA, O=Real Time Innovations,
CN=dtlsexampleECdsa
/emailAddress=meECdsa@rti.com
</subject_name>
<validity>
<!-- Format is CCYY-MM-DDThh:mm:ss[Z|(+|-)hh:mm] in GMT -->
<not_before>2020-06-30T13:00:00</not_before>
<not_after>2030-06-30T13:00:00</not_after>
</validity>
<allow_rule>
<domains>
<id>0</id>
<id>2</id>
</domains>
<publish>
<topics>
<topic>Cir*</topic>
</topics>
<partitions>
<partition>P1*</partition>
</partitions>
</publish>
<subscribe>
<topics>
<topic>*Sq*</topic>
</topics>
<partitions>
<partition>P2</partition>
</partitions>
<data_tags>
<tag>
<name>Title</name>
<value>*Software*</value>
</tag>
</data_tags>
</subscribe>
<subscribe>
<topics>
<topic>Triangle</topic>
</topics>
</subscribe>
</allow_rule>
<default>DENY</default>
</grant>
</permissions>
</dds>
三.DDS安全特性中包含的消息中间件的安全设计要点
通过对RTI DDS的安全机制学习,我认为RTI DDS的安全设计非常地完善,几乎可以作为所有中间件安全设计的教程,值得参考的有以下几个方面。
1)身份认证
基于私钥、证书(链)的身份认证体系,但可惜的是几乎所有的中间件都无法解决密钥的安全存储的问题,可能的解决的途径是白盒密码,另外,主机厂可以在SE芯片或HSE上层增加一层系统级的Framework来解决这个问题。
2)访问控制
RTI DDS实现的访问控制模型为基于规则的主客体访问控制模型,其中:
主体:Permissions文件中使用证书subject标识主体,即使用合法的Permissions文件来声明主体的身份
规则:不同粒度的访问控制规则、规则文件签名、规则与主体身份绑定
客体:主体在规则的限制下访问客体
RTI DDS通过CA签名的方式来构造全局可信的Permissions文件,以解决规则的安全性。从中我们至少可以受到的一点启发是,想要构建安全的系统,必须完善底层的基础安全设施,不要偷懒。
3)安全机制与业务的耦合性
安全机制与业务的耦合性的解决一方面体现在RTI DDS的插件化机,另一方面体现在Governance文件对安全手段的按需配置。这两种手段都很好地解决了安全机制与业务耦合的问题,做到了按需配置,不需要就可以不配置,让安全轻装上阵,减少业务方的性能焦虑。
4)难题:私钥的安全存储
这一点前面也提过了,可以通过白盒的方式,如果是主机厂,也可以在系统中增加一层Framework,将SE芯片、HSE模块的安全存储能力延申到系统中,开放给中间件。