物联网具有令人兴奋的前景,在物联网世界中,简单对象通过互相连接来交换数据,并相互协作以提供高级服务。为了使对象安全无缝地连接, 开放式连接基金会(OCF) 批准并开发 “设备互通性规范”,在该规范下连接物联网设备,无需考虑其制造商和实施。
开源项目 IoTivity 提供了OCF规范的参考实例,为开发人员创建 “可互通设备” 奠定了基础。为了能在OCF快速原型设备上使用JavaScript,开源项目 iotivity-node 提供了绑定loTivity的 Node.js
总之,这些项目不仅可以让你快速开发物联网设备,还可以利用IoTivity的安全功能来保护设备免遭未授权的访问。本文将引导你完成一个练习,向你展示如何在IoTivity安全框架上使用JavaScript对OCF设备进行快速原型设计。
黑客通过网络入侵银行的终端服务器,并向ATM发送指令来远程取款,即使终端和ATM在不同的国家,他们还是在同一个专用网络里面。由于这些设备不是处于物理隔离网络中,因此,软件安全会对它们构成威胁,并让整个系统处于风险之中。
随着物联网领域的兴起,越来越多的设备加入到网络中,技术也从智能家居和智能建筑扩展到工厂自动化,并一直延伸到智能城市应用。即使是简单的家庭网络,也会面临被黑客攻击的风险,除非物联网设备与外界完全隔离,否则黑客可能会利用物联网设备上的一些不安全的软件来劫持你的设备。
OCF在审查物联网的安全需求后定义了其规格。OCF安全体系结构的目标是保护托管在服务器上的资源, 访问许可 只对具有 访问控制 和 授权机制 的客户端提供。此外,端对端设备的交互可以使用 session保护协议 ,如 DTLS (数据报传输层安全)和 数据加密 等方法进行保护,如图1所示。
在OCF安全体系结构中,对于顶层应用资源的保护,是通过实施 访问控制 , 身份验证 和 机密性保护 来实现的。 访问控制条目 (ACE)定义了访问特定资源所需的权限,以及授予该权限的可选有效期,而资源访问控制依赖于一组预定义的 访问策略 ,该 访问策略 正是以 访问控制条目 为形式。在下面的章节中,我将以Node.js为基础的IoTivity虚拟服务器为例,并一步步演示如何仅对授权的客户端授予访问权限。
在本教程中,我先创建了一个 容器镜像 ,该镜像包含了OCF服务器,OCF客户端和入门工具软件以便可以在沙箱环境中完成关于安全性的探索。容器技术是一种操作系统级别的虚拟化,它允许在受支持的平台上运行独立的应用程序,而不考虑环境。 Docker 是一种提供容器的流行软件技术,可在Windows,Linux和Mac上使用。如果你要在你的开发平台上设置Docker,请参考 Docker安装指南 ,以下代码块中显示的Linux命令供您参考。
从GitHub存储库克隆容器Dockerfile和示例脚本,并使用以下命令构建容器镜像。
$ git clone https://github.com/ttzeng/iotivity-inabox.git
Cloning into 'iotivity-inabox'...
remote: Counting objects: 19, done.
remote: Compressing objects: 100% (17/17), done.
remote: Total 19 (delta 1), reused 19 (delta 1), pack-reused 0
Unpacking objects: 100% (19/19), done.
Checking connectivity... done.
$ cd iotivity-inabox
$ sudo docker build -t iotivity-inabox .
构建过程需要一段时间,因为有些部分要从互联网上获取,而且它还要在容器内部构建软件。另外还需要注意,除了Docker所需的磁盘空间之外,请确保Docker守护程序至少有20 GB的空间,用于存储包含了IoTivity程序,Android SDK等镜像。
在构建容器镜像的Docker时,我们来仔细研究如何创建一个使用JavaScript的OCF服务器,并且还能被其他OCF设备发现。以下代码片段展示了在URL /a/led
处托管资源的服务器实施框架。
var device = require ('iotivity-node' ), var device = require('iotivity-node'), server = device.server; var ocResource; // 托管资源 function getProperties() { // 托管资源的Representation (e.g. LED) // 将下面的'value' 属性设置为每一个LED灯的状态 var properties = { rt: [ 'oic.r.switch.binary' ], id: 'led', value: false }; return properties; } // 注册一个LED资源 server.register({ resourcePath: '/a/led', resourceTypes: [ 'oic.r.switch.binary' ], interfaces: [ 'oic.if.baseline' ], discoverable: true, observable: true, properties: getProperties() }).then( function(resource) { // 成功注册资源 ocResource = resource; // 资源注册回调处理程序 ocResource.onretrieve(getRepresentation) .onupdate(setRepresentation); }, function(error) { // 当注册资源失败 });
上述脚本需要 iotivity-node
模块,该模块为IoTivity提供Node.js绑定,以便使用JavaScript对OCF设备进行快速原型设计。 server
对象中的 register()
的方法在OCF网络中注册资源。传递给该方法的参数是一个包含属性的对象,表示托管资源。
成功注在网络中注册资源后,远程设备可以发现该资源,并获取或设置资源的 representation
。这些请求将分别由下面的代码片段中的 getRepresentation()
和 setRepresentation()
回调处理。
...
function getRepresentation(request) {
//将资源的Represention回复给请求者。
ocResource.properties = getProperties();
request.respond(ocResource).catch(handleError);
}
function setProperties(properties) {
// 通过每一个给定的'properties.value'值改变LED状态
}
function setRepresentation(request) {
// 根据从远程接收到的Represention设置LED状态
setProperties(request.data);
ocResource.properties = getProperties();
request.respond(ocResource).catch(handleError);
}
Docker构建完成后,使用以下命令运行容器镜像以加载包含示例脚本的文件夹。
$ sudo docker run -it -v `pwd`:/opt/mnt /
-p 5901:5901 --privileged iotivity-inabox
You will require a password to access your desktops.
Password:
Verify:
我们将使用容器中的示例脚本来练习IoTivity安全,以上命令指示主机连接到网络端口5901,因为该镜像将启动VNC服务器用于用户交互。Android x86模拟器需要--privileged参数。
设置容器第一次运行时,需要创建VNC会话密码。在使用任何VNC远程桌面客户端软件连接到容器时,你需要输入该密码。
启动VNC客户端软件以连接到容器,有些操作系统可能没有在package中包含VNC客户端软件,你可以下载一个与你系统兼容的第三方VNC客户端。
用VCN会话中的 start-emulator.sh
脚本来启动安卓模拟器连接到容器。
# /opt/mnt/scripts/start-emulator.sh
如果你是第一次启动模拟器,请输入以下命令将配套应用程序安装到模拟器。配套应用程序充当OCF本机客户端,它也是一个用于检索虚拟服务器和配置设备的资源状态的入门工具。
# adb install ~/companion-debug.apk
输入以下命令以开始在服务器上托管 OCF二进制交换机 虚拟资源。
# cd /opt/mnt/simpleserver
# node binarySwitch.js
请注意图3中 Device ID
字段,它是OCF堆栈实例的唯一标识符。该值可能会有所不同,并会在重置SVR(安全虚拟资源)数据库后进行更改。
在OCF访问控制模型中,资源实例必须具有关联的访问控制策略,否则资源将不可访问。由于我们尚未在服务器的SVR数据库中设置适当的 访问控制条目
(ACE)来访问资源,因此希望在配套应用访问二进制交换机资源时看到 UNAUTHORIZED_REQ
错误消息,如图4所示。
安全资源管理器(SRM)在OCF安全架构中起着关键作用,因为它对通过安全端口收到的传入请求进行身份验证,并管理SVR,访问控制列表(ACL),证书和设备所有者传输状态等安全资源。
在接收对托管资源的请求时,如果请求是通过安全端口到达,则只有称为“subject”的授权请求者将被用于匹配ACL条目。如果ACE匹配失败,则访问被拒绝。如果请求是通过不安全端口到达,则允许的ACL策略,要么是使用匿名连接类型的ACE,要么是匹配任何匿名请求的subject通配符。
在OCF安全框架中,访问策略可能由本地ACL或访问管理服务(AMS)存储。为了简单起见,本教程使用本地ACL机制。
IoTivity软件实施中的SVR可选地在初始化期间接收配置文件,配置文件是CBOR(简明二进制对象表示)格式,并且 json2
实用程序可以从一个JSON文件中生成二进制配置文件。另外,还提供了一个包装脚本 cborinit-svr-db.sh
来简化SVR数据库的创建过程。
按 CTRL-C
停止运行服务器脚本,并在设置默认SVR数据库后,用以下命令重新启动服务器。
# /opt/mnt/scripts/init-svr-db.sh binarySwitch.js
# node binarySwitch.js
由于当前的服务器脚本不指定使用安全端点进行通信,因此配套应用程序通过不安全的通道将访问请求发送到服务器。在接收到请求时,服务器将该请求视为匿名,并且没有设备UUID或角色ID与该请求相关联。然后,服务器将查询ACL并查找与任何已配置的访问策略匹配的ACE。
在OCF术语中,作为服务器的设备储存并控制资源,提供作为客户端访问这些资源的设备,并遵循一组安全机制。因此,让我们打开一个新窗口,并通过以下命令将客户端引入我们的实验中,以设置其SVR数据库并启动客户端脚本。
# cd /opt/mnt/simpleclient
# /opt/mnt/scripts/init-svr-db.sh index.html
# npm start
虽然客户端可以更改服务器的资源状态,但是在新客户端在没有接受到确认的情况下,就能访问现有服务器,这似乎是不对的!
让我们回顾一下我们为服务器配置的名为 oic_svr_db.json
的默认SVR数据库。 acl
部分包含一系列ACE访问策略,用于管理资源上允许的subjects和操作。尽管访问控制机制可以是基于subject的,基于角色的或基于连接的,但为简单起见,本教程仅应用基于连接的访问控制机制。
前四个ACE策略指示SRM允许 “资源发现” 和 “所有权传输请求” 可以通过安全或者非安全的端口,但第五个ACE策略对任何请求都授予“读/写”访问权限,尽管这些请求来自不安全的匿名端口。
"acl": {
"aclist2": [
{
"aceid": 1,
"subject": { "conntype": "anon-clear" },
"resources": [
{ "href": "/oic/res" },
{ "href": "/oic/d" },
{ "href": "/oic/p" }
],
"permission": 2
},
{
"aceid": 2,
"subject": { "conntype": "auth-crypt" },
"resources": [
{ "href": "/oic/res" },
{ "href": "/oic/d" },
{ "href": "/oic/p" }
],
"permission": 2
},
{
"aceid": 3,
"subject": { "conntype": "anon-clear" },
"resources": [
{ "href": "/oic/sec/doxm" }
],
"permission": 6
},
{
"aceid": 4,
"subject": { "conntype": "auth-crypt" },
"resources": [
{ "href": "/oic/sec/doxm" }
],
"permission": 6
},
{
"aceid": 5,
"subject": { "conntype": "anon-clear" },
"resources": [
{ "href": "/a/switch" }
],
"permission": 6
}
]
为了正确管理服务器上的访问,而不是将ACE配置为允许默认SVR数据库中的匿名连接,我们需要修改配置,第一步仅允许加密连接。
启动预先包含的编辑器 geany
,将相应ACE 的 subject
字段从 anon-clear
修改为 auth-crypt
,并重置SVR数据库。
# cd /opt/mnt/simpleserver
# geany oic_svr_db.json
# /opt/mnt/scripts/init-svr-db.sh binarySwitch.js
为了强制使用相互认证的安全通道来交换消息,服务器必须在资源注册期间设置宿主资源的 secure
属性。每个设备上的SVR数据库中的 oic.sec.cred
资源也应该持有用于相互验证和证书验证的凭据。在两台设备通过配套应用程序配对时,客户端凭据会被交换并安装在服务器上。
启动 geany
编辑器将资源服务器的 secure
属性从 false
更改为 true
,如下面的图8所示。
只有设备正确的启动,才可以在OCF环境中与其他设备进行交互。启动过程从配置设备的所有权开始,因此只有购买该设备的合法用户才能使用启动工具(OBT)建立其所有权。一旦所有权建立,OBT就成为设备供应机制。在启动过程结束时,设备已准备好进行正常操作。
要使用配套应用程序与设备建立所有权,请在控制面板中选择 Provisioning
操作以发现OCF网络中的有主设备和无主设备,如图9所示。
一旦发现一个无主/新设备,按下 “associated” 按钮即可将配套应用作为设备的所有者和管理员。配套应用使用一个设备支持的 “所有者转移方法”(OxM)来安全地建立对设备的信任,并且授权配套应用来管理设备,以及为设备供应做好准备。为了能让设备和配套应用在随后的交互期间相互认证,我们需要将所有者凭据提供给设备。
客户端和服务器设备同时启用后,配套应用的凭证已安装到两台设备的 oic.sec.cred
资源中,现在,配套应用已被客户端和服务器所信任。但是,为了能让客户端和服务器通过相互认证的安全通道进行交互,他们还需要拥有对方的凭据。
配套应用通过 Device ID
来识别客户端和服务器。单击所需设备的复选框,然后按菜单栏中的按钮将所选设备配对。配套应用会将对等证书安装到每个设备上,以实现客户端和服务器之间的相互信任状态。
在完成启动流程并配对客户端和服务器之后,服务器上托管的资源就可以通过客户端来检索和更新,如图12所示。加入网络的其他客户端需要经过相同的认证过程才能进行访问服务器。
通过这些技术,包括相互认证,资源访问控制,数据传输层保护机制等,OCF完成了物联网设备间资源机密性保护,确保了消息的完整性和稳健性。参考 OCF安全规范 了解更多详细信息。