嵌入式-Linux-安全手册-全-

嵌入式 Linux 安全手册(全)

原文:annas-archive.org/md5/e50b83747de08670d28b398597e26f9e

译者:飞龙

协议:CC BY-NC-SA 4.0

前言

欢迎来到嵌入式 Linux 安全手册。我们将共同踏上知识的旅程——深入探讨被许多人认为是部落知识的内容。这些东西你在网上找不到。写这本书的目的,就是分享我在将安全和最佳实践应用于 Linux 设备创建过程中的广泛经验。

安全不仅仅是做几项配置就能完成的任务。它是永无止境的知识与演化,结合了充分的准备和警惕。

本书将带你亲身实践,学习何时以及如何应用最佳实践,访问公共和私有安全资源,并了解在创建一个安全且可支持的基于 Linux 的设备解决方案过程中,如何复杂地应用安全措施。

到了这段旅程的尽头,你将能够前所未有地设计、原型化、构建和支持嵌入式 Linux 系统(及其产品)。所以,拿起你最喜欢的饮品和笔记本,让我们开始吧。

本书的读者群体

尽管这本书应该能吸引广泛的技术人员,但最能从中受益的群体是产品团队、嵌入式软件工程师、安全专家和架构师——更具体地说,是那些直接或间接参与嵌入式 Linux 系统设备的范围定义、设计、创建和支持的人员。

本书涵盖的内容

第一章欢迎来到网络安全领域,介绍了我们为何共同踏上这段旅程,以及安全为何如此重要。

第二章安全从设计桌开始,随着我们共同踏上旅程,它向你介绍了安全不是一项功能,而是我们默认将其内置于所做的一切中的理念。

第三章应用设计需求标准——硬件选择,回顾了已知标准硬件平台的优点、陷阱以及选择这些平台的利弊。

第四章应用设计需求标准——操作系统,从定义硬件需求开始,识别某些发行版中的现有限制和功能,这些都会影响你的硬件和操作系统配对——就像美酒搭配美餐一样。

第五章我的构建链中的基本需求,回顾了在确保产品安全时,你需要利用的众多附加组件。

第六章磁盘加密,深入探讨了如何自动化加密解决方案数据的安全性,并配有实际操作练习。

第七章受信平台模块,通过实际操作练习,深入研究如何利用系统的 TPM 模块存储加密密钥和密码短语。

第八章启动、BIOS 和固件安全,深入探讨了如何保护你的 BIOS 以及你的系统如何启动。

第九章基于镜像的部署,探索了基于镜像的操作系统,以及它们如何提高你的解决方案的安全性。

第十章保护解决方案:防止终端用户及其环境的影响,回顾了如何保护设备免受终端用户影响的方法,同时创造一个丰富、积极的用户体验。

第十一章了解威胁格局——保持信息灵通,回顾了你可以用来保持信息灵通和了解不断变化的威胁格局的丰富资源。

第十二章我的设备的通信和互动安全吗?,探讨了连接到你的 Linux 系统的设备实际有多安全。我们还将进行实践深度探讨,了解如何正确地保护和加密你的网络通信。

第十三章应用政府安全标准——系统强化,深入探讨了如何将政府安全标准应用到我们的系统中。

第十四章客户与社区反馈循环,回顾了如何将所有内容整合起来,并如何将你的客户、用户和合作伙伴纳入到持续改进的循环中。

为了最大程度地从本书中获益

本书假设读者已经具备一定的 Linux 系统管理经验或作为 Linux 系统用户的经验。

本书中的许多概念非常高级。本书中的课程与你已有的知识结合起来,应该能迅速将你提升到不仅理解 Linux 系统内部结构的精通级别,而且还能基于 Linux 构建产品的水平。

本书中有许多实践练习,旨在增强学习活动。如果你选择跟随这些练习,作者建议至少准备两台 PC 级系统,每台系统至少 16GB 的内存和 1TB 的存储空间,以获得最佳效果。

此外,本书包含了若干截图。这些截图旨在提供关键过程的概览。因此,这些图像中的文字在 100%缩放时可能显得较小。不过,你可以通过以下链接查看这些图像的更清晰版本:packt.link/gbp/9781835885642

如果你使用的是本书的数字版本,我们建议你自己输入代码或从本书的 GitHub 仓库获取代码(下节提供了链接)。这样做有助于你避免因复制粘贴代码而可能引发的任何错误。

下载示例代码文件

您可以从 GitHub 下载本书的示例代码文件,链接为github.com/PacktPublishing/The-Embedded-Linux-Security-Handbook。如果代码有更新,GitHub 仓库会随之更新。请经常查看此处,以获取与本书相关的更新、新内容、备忘单、参考资料和新的练习。

我们还有更多来自我们丰富图书和视频目录的代码包,您可以在github.com/PacktPublishing/查看。赶紧去看看吧!

使用的约定

本书中使用了许多文本约定。

文本中的代码: 表示文本中的代码词汇、数据库表名、文件夹名称、文件名、文件扩展名、路径名、虚拟网址、用户输入和 Twitter 用户名。例如:“为了确保即使$USER没有登录,服务也能运行,我们需要使用linger。”

一块代码如下所示:


# we will use these registries only
[registries.search]
registries = ['registry.redhat.io','quay.io']

任何命令行输入或输出如下所示:


$ systemctl –user start myapplication.service
$ systemctl –user enable myapplication.service

当我们希望在一组步骤中引起您注意某个命令行输入或输出时,相关的行或项目会以粗体显示:

  1. 运行测试扫描。

    
    $  oscap-ssh <username>@<hostname> <port> oval eval --report <scan-report.html> <path to rhel-9.oval.xml>
    

粗体:表示新术语、重要单词或您在屏幕上看到的单词。例如,菜单或对话框中的单词以粗体显示。举个例子:“进入应用程序,然后选择SCAP Workbench。”

提示或重要说明

如此显示。

与我们联系

我们始终欢迎读者的反馈。

一般反馈:如果您对本书的任何部分有疑问,请通过 customercare@packtpub.com 给我们发送电子邮件,并在邮件主题中提及书名。

勘误:虽然我们已经尽力确保内容的准确性,但难免会有错误。如果您在本书中发现了错误,我们将非常感激您向我们报告。请访问www.packtpub.com/support/errata并填写表格。

盗版:如果您在互联网上发现任何我们作品的非法复制品,我们将非常感激您提供其位置地址或网站名称。请通过 copyright@packt.com 联系我们,并附上相关材料的链接。

如果您有兴趣成为作者:如果您在某个话题上具有专业知识,并且有兴趣撰写或参与书籍的编写,请访问authors.packtpub.com

加入我们在 Discord 上的社区

加入我们社区的 Discord 空间,与作者和其他读者讨论:

packt.link/embeddedsystems

Discord

分享您的想法

一旦你阅读完《嵌入式 Linux 安全手册》,我们很想听听你的想法!请点击这里直接前往 Amazon 评价页面并分享你的反馈。

你的评论对我们和技术社区来说非常重要,能帮助我们确保提供卓越的内容质量。

下载本书的免费 PDF 副本

感谢购买本书!

你喜欢在路上阅读,但又无法随身携带纸质书籍吗?

你的电子书购买与所选设备不兼容吗?

别担心,现在每本 Packt 书籍,你都能免费获得该书的无 DRM PDF 版本。

随时随地,在任何设备上阅读。在你最喜欢的技术书籍中搜索、复制并粘贴代码,直接用到你的应用程序中。

优惠不止于此,你还可以获得独家折扣、新闻简报,并每天在收件箱中收到大量免费内容。

按照这些简单的步骤来享受福利:

  1. 扫描二维码或访问以下链接

下载本书的免费 PDF 副本

  1. packt.link/free-ebook/9781835885642

  2. 提交你的购买证明

  3. 就是这样!我们会直接将免费的 PDF 和其他福利发送到你的电子邮件。

第一部分:嵌入式系统与安全设计概述

在本部分中,我们将介绍那些影响你决策过程、硬件选择、操作系统选择的威胁,以及可能改变你设计标准的所有优点和漏洞。

本部分包括以下章节:

  • 第一章欢迎来到网络安全领域

  • 第二章安全始于设计桌面

  • 第三章应用设计需求标准——硬件选择

  • 第四章应用设计需求标准——操作系统

第一章:欢迎来到网络安全领域

播放音乐。欢迎来到丛林。网络安全领域是不断变化和发展的。人们很容易将其与美国东北部新英格兰地区变幻莫测的天气模式进行比较。这种天气对登山者来说可能很危险;同样,网络威胁的变化也可能对技术解决方案造成毁灭性的影响。

在接下来的章节中,我们将深入探讨Linux 嵌入式系统(或嵌入式 Linux 系统,也被称为 Linux 家电,或简单称为家电),并详细了解如何应用这些新知识来保护你的解决方案。我们将一起走这段旅程,最终,你将能够更好地构建一个更安全的家电。

本章仅作为设置 Linux 嵌入式系统基础的起点,随后我们将更深入地讨论。在本章中,我们将涵盖以下主题:

  • 什么是 Linux 嵌入式系统?

  • Linux 嵌入式系统是如何使用的?

  • 为什么保护 Linux 嵌入式系统如此重要?

让我们开始吧。

什么是 Linux 嵌入式系统?

如果你正在阅读这本书,可能可以合理推测你对你公司定义的 Linux 嵌入式系统有所了解。为了真正深入理解这一主题,让我们回顾一下家电模型,它是用于创建可销售解决方案的。

家电模型提供了解决方案和服务,这些是组织(或个人)无法轻易自行构建的。这也解决了另一个限制;通常,这些家电的用户几乎没有或根本没有接触任何技术人员来负责解决方案的维护。家电模型在家庭消费电子产品中最为常见,但也涉及行业中的每一个已知垂直领域。

大多数家电采用专用硬件,并具有独特的外形因素,以最佳方式支持其使用。这些解决方案每天都在我们周围。几个容易辨认的消费类家电示例包括你家里的 Wi-Fi 路由器、有线电视盒子或智能洗衣机。一个响亮的例子就是我们所有人都携带的智能手机,我们无法想象没有它们的生活。

让我们亲切地选择一个通用的家庭 Wi-Fi 路由器来深入理解家电模型的概念。几乎任何人都可以使用它的服务,而无需理解其底层技术是如何工作的或是如何实现的。

路由器有一个定制的外形设计,远不止为了美观。外壳包含了所有电子元件,这些元件是成功提供其预期服务所必需的。在内部,有一台运行 Linux 操作系统的小型计算机。我敢打赌你能猜到我想表达的意思。这就是我们为什么称这些设备为Linux 嵌入式系统,因为它们包含了一个定制的计算机和 Linux 操作系统,并配有定制的软件,为最终用户提供一系列独特的服务。

定义一个设备并不止于此。它必须提供一种或多种服务,能够被最终用户轻松使用。在设备中,这是通过实现复杂的软件和适当的硬件来实现的。在那个家庭 Wi-Fi 路由器的例子中,制造商将其设计成提供一个简单易用的基于网页的界面,以便管理提供的服务。在这种情况下,这就是最终用户允许人们访问无线互联网的方式。

设备模型中必须内置的另一个关键方面是能够接受并处理其配置或软件的更新,这当然包括其 Linux 操作系统。必须确保对最终用户来说是简单的;我们必须假设最终用户没有技术背景。如果最终用户真的具备技术能力,他们理论上可以自己构建这个系统,而你就会失业。以 Wi-Fi 路由器为例,它在其网页界面中内置了一个简单的自我更新功能。最终用户点击界面中的一个按钮,背后的“魔法”就开始了。从程序上讲,设备从解决方案提供商提供的安全仓库中获取更新包;它下载该包;然后最终处理所有这些应用程序和 Linux 更新,而无需最终用户的任何干预。这个过程会通知最终用户完成状态(有时需要重启设备)。

并非每个嵌入式 Linux 系统(设备)都运行在专用硬件上。虚拟化的出现以及最近大力推动将事务迁移到云端,释放了一种全新的交付方式:虚拟设备

虚拟设备在多个云市场中迅速获得了关注。为什么?很简单。那些多年来一直生产本地设备解决方案的公司,必须进行演变以保持他们的客户群。正因为如此,许多解决方案提供商现在提供本地硬件设备、一种本地设备的虚拟化解决方案,以及基于云提供商的虚拟设备解决方案。

通常,所有这些解决方案都可以从相同的代码库构建,但根据设备为最终用户提供的具体功能,它们可能需要根据每个虚拟化平台的网络和安全要求进行定制和重构。这是因为云服务提供商(通常称为超大规模云服务商)各自有自己的专有方法和 API 来处理网络、安全和最终用户访问。具体来说,我的意思是,应用程序堆栈可以统一于所有交付方式;然而,虚拟机镜像格式、网络以及其他方面会有所不同。例如,Azure 和 Google 处理其网络栈的方式完全不同,存储方式也大不相同。因此,用户界面UI),特别是设备设置时,需要考虑这些虚拟化平台或超大规模云服务商的差异化要求。

接下来,我们将回顾嵌入式 Linux 系统的应用。

嵌入式 Linux 系统是如何使用的?

嵌入式 Linux 系统无处不在。大多数人并没有多加思考。我敢猜测,早晨醒来时,你就会触碰其中之一,并且每天都与之进行无数次互动。你的智能手机就是一个嵌入式 Linux 系统,在我看来,它是一个非常棒的例子。

嵌入式 Linux 系统无处不在;有些默默无闻,有些则以纯粹的优雅和娱乐展现自我,充满了设计者赋予的美丽与优雅。这些设备解决方案适用于广泛的应用场景。有些是完整的解决方案,另一些只是更大生态系统或解决方案的简单组件。

大多数在成功设计和实施后,能够无缝地为用户社区提供服务,用户甚至不需要思考背后发生了什么。这其中很大一部分功劳要归功于 Linux 解决方案的高韧性、轻量级和灵活性。与 Linux 相比,Microsoft Windows 嵌入式系统在很大程度上依赖于其 GUI 组件。在 Linux 上提供完整解决方案并带有 GUI,比其基于 Windows 的竞争对手要容易得多。

在这里,我将尝试提供一个概括性的列表,展示如今 Linux 如何在提供服务方面得到应用(无论是分发版还是硬件平台)。我还要做个声明——这个列表最多只能算是一般性概述,可能并不包括所有当前部署的应用场景。我按顺序展示,并尽量不遗漏任何内容,但列出所有嵌入式 Linux 系统的应用场景是不可能的。下面是这个列表:

  • 人工智能 (AI):Linux 是近年来所有 AI 进展的核心。由于其灵活性和庞大的开发者基础,它是首选的操作系统。随着这一领域的快速发展,可能性是无限的,且往往是保密的,例如以下几种:

    • 面部识别系统

    • 艺术图形渲染系统

    • 语言处理

  • 农业:随着全球农业开始适应日益扩展的运营规模,技术开始成为以下操作的重要支持:

    • 重型设备监控解决方案

    • GPS 引导设备导航

    • 农产品分级与分类系统

    • 生产追踪系统

  • 汽车:嵌入式 Linux 在这个迅速发展的交通领域中占据主导地位。如今,可以找到无数的嵌入式 Linux 系统,它们悄无声息地提供许多关键服务,诸如:

    • 自动驾驶汽车操作系统和组件

    • 传感器和安全系统

    • GPS 导航

    • 电动汽车充电基础设施

  • 航空:民用航空和运输业是 Linux 嵌入式系统解决方案的一个蓬勃发展的行业。这些复杂的设备可以在以下领域找到(假设你拥有适当的安全许可):

    • 行李扫描系统

    • 乘客安检解决方案

    • 行李运输和追踪系统

    • 雷达和空中交通控制系统

    • 旅客身份识别与验证系统

  • 建筑管理与建设:建筑管理控制长期以来一直是由基于 Linux 的解决方案提供商来解决的。以下仅是一些高科技解决方案的示例:

    • 刷卡门禁系统

    • 环境控制系统

    • HVAC 管理系统

    • 火灾探测与抑制系统

    • 报警系统

  • 电信:在我看来,这一行业的增长速度仅次于与军事项目相关的领域。虚拟化技术推动了网络功能虚拟化NFV)解决方案的迅速普及。该领域的物理和虚拟设备的部署规模远超其他任何地方。这些虚拟设备可以在服务器机房、电信机房、数据中心和云服务提供商的市场中找到,目的是简化以下服务的提供:

    • 无线接入 网络RANs

    • 负载均衡器

    • 路由解决方案

    • 对讲PTT)电话系统

    • 地理位置跟踪解决方案

    • 域名系统(DNS)解决方案

    • IP 地址管理解决方案

    • 防火墙解决方案

    • 邮件过滤解决方案

    • 管控基于光纤的互联网连接的运营管理系统

  • 地质学:这一领域主要受到能源公司和政府机构需求的驱动,在过去五年中取得了显著增长。尽管这些设备可能不是主流,但它们为学术界和能源行业提供了许多有价值的服务,如下所示:

    • 接近实时的地质扫描与评估解决方案

    • 建模系统

    • 地震跟踪解决方案

  • 医疗保健:Linux 系统广泛应用于医疗保健的几乎每个领域,安全性和患者安全是其核心关注点。医院的效率也大大提高。许多新型的设备解决方案几乎可以在任何医疗机构中找到,提供以下一些拯救生命的服务:

    • 患者安全解决方案

    • 电子记录解决方案

    • 患者监护解决方案

    • 呼吸机

    • 实验室测试解决方案

    • 成像系统(PET 扫描、MRI 扫描、CAT 扫描等)

  • 工业和制造:工业自动化已经发展了二十多年,然而,这一领域的一些关键企业革新了曾经的手动流程。嵌入式 Linux 系统通过提供以下一些服务,减少了成本并加速了生产速度:

    • 工业制造自动化系统

    • 环境和安全监控系统

  • 军事:因此,为了避免那些穿黑西装的人以不友好的方式来拜访我,我将以更为普遍的方式表述,特别是在这一领域,以保障我的生命安全(并且增加一点神秘感)。Linux 设备可以悄无声息地为重要的安全与防御相关服务提供支持,例如以下内容:

    • 面部识别系统

    • 数据采集解决方案

    • 无数车辆和飞行器的组件

    • 雷达系统

    • 导航系统

    • 导航系统

  • 太空:没有 Linux 和开源技术,这一领域今天无法取得如此成就。嵌入式 Linux 系统正在向天空进发。以下是一些例子:

    • 太空探测车(例如:卡西尼号)

    • 卫星

    • 探测器

    • 传感器系统

    • GPS 系统

    • 地面管理系统

    • 太空望远镜

  • 天气:政府机构、航空、交通安全、公路运输、海洋航运等各类交通机构都依赖于 Linux 嵌入式系统提供的数据来保证旅行的连续性和公共安全。全球范围内可以找到这些设备,它们提供以下服务:

    • 天气建模与预测解决方案

    • 地面和空中雷达系统

总结来说,我们只挑选了一些嵌入式 Linux 系统今天所提供的关键且有趣的服务,这些服务丰富了我们的生活,默默地保护着我们,并帮助我们到达曾经无法企及的地方。

为什么确保 Linux 嵌入式系统的安全性如此重要?

为什么确保 Linux 嵌入式解决方案(设备)系统的安全如此重要?这个问题的答案根据询问对象的不同,实际上有多个层面。

最明显的答案可能只是为了避免市场中的责任和信誉损失。最近,似乎越来越多的公司因为其产品被破坏而面临客户的重大损失。

此类漏洞的影响可能是用户个人信息的丢失(插入倒吸一口气!),甚至更糟的是,未经授权访问系统或数据,而系统的管理者对此毫不知情。每年,这些漏洞导致数十亿美元的相关损失,并使这些公司面临用户的法律诉讼。一个品牌形象的损害可能在人们心中留下的印象,比你想象的要持久得多。

许多文献中都有详细记录,数据泄露、漏洞以及其他安全失误通常是由内部员工和承包商造成的。这并不意味着恶意行为。通常情况下,这可能是判断失误,忘记从开发环境中删除敏感数据,或者不小心将敏感数据带回家,而设备本身被遗失、被盗或被攻击。

接着,有些情况是由于系统的故意滥用所造成的。遗憾的是,我认为这些事件是最容易预防的。我们会在后续章节深入探讨这一问题。滥用有很多种形式。一开始是未经授权的访问系统或超出预定权限的操作。接着,是那些人故意以不当方式使用应用程序或系统的情况。最糟糕的情况是,当系统上的软件被修改、安装或禁用,以便个人能够执行任务或监视他人。这些就是系统崩溃的时刻。

嵌入式 Linux 系统发生安全漏洞的例子

2019 年,黑客攻破了 Ring 的安全摄像头,获取了视频和音频流,给这些设备拥有者的生活带来了严重破坏。多个州报告了此类事件。如今,软件更新和更严格的密码要求已能有效防止恶意行为者的入侵。

另一个安全漏洞的例子是 2017 年发现圣裘德心脏植入物可能会被黑客攻击。当我听到这个消息时,我既感到惊讶又为那些患者感到害怕。幸运的是,圣裘德已修补了该漏洞,且实际上没有患者受到伤害。

IBM 的一个研究团队在 2015 年中期成功攻破了吉普车的固件更新机制。他们展示了恶意行为者如何通过加速、转动方向盘或踩刹车来控制车辆。想到恶意行为者可能会毁掉你的家庭出行,确实让人感到害怕。这些漏洞已经迅速得到了修复。

希望这些公开的例子能帮助强化设计嵌入式 Linux 设备时考虑安全性的重要性。

发现这些未经授权的更改或漏洞可能非常困难,尤其是当客户接收产品并开始使用其服务后,你可能就无法再访问你的产品了。完全防止这些问题要容易得多。

你可能听过这句老话,预防胜于治疗。如果你能应用本书中传授的部分或全部教训,那就相当于拥有了十磅的预防措施和所有的治疗方法。我们将深入探讨硬件安全、操作系统安全、安全连接性,以及如何了解你必须为哪些威胁做好准备。

本书中的每种方法或技术可能并不适用于你的解决方案,甚至可能不可行,但你越多地运用这些方法论,就越有可能打造出一个牢不可破的产品。话虽如此,愿你公司创造的唯一头条新闻是成功与荣誉。

总结

在本章中,你将对嵌入式 Linux 系统的定义有一个扎实的理解。我们展示了一些广泛的例子,说明今天嵌入式 Linux 系统的应用场景。最重要的是,我们回顾了一些关键原因,解释了为何将这些设备以尽可能安全的方式交付给客户,对于构建此类解决方案的人来说是强制性的。在下一章中,我们将深入探讨为何安全性始于出色的设计。

第二章:安全从设计桌开始

安全不仅仅是一个过程。安全不能是事后考虑的事情。安全是一种心态。当你考虑将新产品或升级产品推向市场时,安全从设计桌开始。你在这里做出的选择将定义一些你可能以前没有考虑过的结果。

在上一章中,我们简要回顾了嵌入式 Linux 系统(即设备)是什么,以及它们如何解决现实世界的问题。接下来的几章将重点讲解设计和构建阶段。每一章都会在上一章的基础上进行扩展,正如你很快会发现的那样,所有这些都是需要注意的考虑因素。

在设计阶段,产品团队在减轻未来风险方面有着最高的成功机会。通过适当的范围定义、规划和执行,你的团队可以在创造高度高效的设备解决方案方面取得巨大成功。如果在这一阶段考虑到我们即将回顾的各个因素,它们将成为成功的因素,而非风险因素。

安全审计员、系统架构师和产品经理,凭借他们预期的职位描述,都是风险缓解者。这就是我们现在在这里做的原因。感谢你与我一起踏上这段旅程。

三思而后行 是许多人都很熟悉的一句格言。在设计阶段,我认为这还远远不够。我说的是 三思而后行,换一把尺子,把新尺子与旧尺子对比,再用新尺子量两次,然后仔细考虑切割。如果仍然有疑虑,应该拿第三把尺子(重新开始!)。我还建议在初次切割前进行同行评审。同行评审是我无法过度推荐的。第二双眼睛(或者更多的眼睛)通常能发现并指出你可能忽略的东西。

说实话,我有点夸张了。这样做是有很多合理的原因的。没有考虑到解决方案的关键方面可能会导致产品薄弱或不足。在最糟糕的情况下,你可能会陷入一堆冒烟的垃圾中,并且将你的职业生涯置于危险之中。在本章中,我们将深入探讨许多在产品设计阶段常被忽视的因素。这些风险并不全是纯粹的技术问题。然而,每一个单独的风险都可能引发问题。有些是社会性的,有些是政治性的,大多数与必须验证的设计因素相关。

本章将涵盖的流程可以通过以下图表来说明:

图 2.1 – 本章流程图

图 2.1 – 本章流程图

在本章中,我们将涵盖以下主题:

  • 解决方案面向的商业需求是什么?

  • 我的目标买家和目标用户是谁?

  • 是否有任何特定的政府合规标准会影响决策树?

  • 我们将如何支持这个设备解决方案?

  • 其他影响产品的需求和关注点

我们开始吧。

解决方案满足的商业需求是什么?

你有了一个新产品的创意,这太棒了。在你花时间向管理层推销这个提案之前,必须花一些时间,袖子挽起来,设定一些明确的产品设计目标。

让我们一起走一遍这个过程。你需要问自己一些问题,并且能够详细回答这些问题。单纯为了市场上有个亮眼的技术解决方案就投放产品的时代早已过去。你的潜在客户有紧张的预算和巨大的时间压力。为客户创造价值必须是任何提议的解决方案中最重要的特性。

首先,你的解决方案到底会为未来的终端用户提供哪些服务?这个答案必须清晰且精确地回答这个问题:你的设备解决方案到底是为了应对什么商业需求或问题,以便为终端客户增加价值? 要回答这个问题,必须清楚几个关键点。问题到底是什么?有没有什么替代方案(如果有的话)?

那么,添加价值到底是什么意思?你的解决方案必须在多个方面打勾。接下来,问问自己,这个解决方案的实施有多复杂?普通客户是否有能力自己设计/实现一个自家的解决方案? 答案必须是:我的解决方案为人们的生活增值,或提供了其他方式难以获得的宝贵服务。

如果你的解决方案可以轻松被其他人设计、构建或实施,那么将来卖出你的创意的机会可能会非常渺茫。能够解决复杂且棘手问题的解决方案,才是那些能为客户带来直接价值的解决方案。

研究,研究,研究! 我对所有正在评估或考虑创建新产品的人这么说。为什么? 可能会有人问。我的回答既关键又简单。如果别人已经解决了这个问题,并且围绕它创建了产品,那么你就处于一个不利的位置。现有的竞争者显然占有优势,并且很可能控制了市场。

市场上如果已经有多个解决方案,这该怎么办?在这种情况下,我开玩笑地建议你质疑一下自己的理智。你的公司将面临一场艰苦的战斗,需要为每一个可能的客户而努力。在这里,我希望你的解决方案能够压倒竞争对手,且这段旅程能够帮助你达成目标。

现在你已经明确了你的产品旨在解决的具体使用案例,接下来我们可以进入下一步设计标准,那就是确定你的目标用户画像

我的目标买家和目标用户是谁?

我为什么要关心这些人物角色? 或者 我以为这本书是关于安全的! 你可能会默默地想。太好了!我让你开始思考了。这本书确实是关于安全和降低风险的。这对你未来的产品和公司成功至关重要,我们将分两部分来讨论。答案的复杂度可以与未来你的公司销售团队、产品经理和售前工程师将要接触的人物角色的复杂性相匹配。

收集目标买家和用户需求的详细知识,需要应用相当多的心理学。这些洞察力将极大帮助你确定必须规划哪些功能,以实现技术上的胜利,最终促成你的嵌入式 Linux 系统设备的销售。两者的驱动力和动机完全不同,直接影响他们对解决方案的需求。预先直接或间接接触这些目标行业中的人物角色,以便收集情报,将是你团队的战略活动。焦点小组和调查也可以成为收集需求信息的宝贵工具。利用你手头的每一个工具和方法。商业就像战争,所以不要玩得太“公平”。要充分利用每个优势。

在我们继续讨论各种人物角色的重要性之前,请允许我再给你一个警告。未能满足目标受众的需求和期望,最终会导致解决方案的采纳率低下。如果我不提及客户组织内部的政治因素,这将是我的失职。这些因素可能是一个隐藏的变量。在与这些人物角色沟通之前,尽可能多地收集信息。准备工作非常重要,提前准备好他们可能会问的问题及答案至关重要。虽然客户的政治动机与安全性没有直接关系,但它们很容易转向安全功能的讨论,或者变成一个批评会议,把你的竞争对手与您一起推向聚光灯下(当然是比喻意义上的)。

目标买家

目标买家可能是最难以把握的人物角色。他们可能并不是直接参与产品部署、测试或使用的人。这些客户人物角色可能是部门负责人、高管、财务部门人员或采购专家。那么,让我们深入探讨这些例子中驱动因素的不同。

重要提示

目标买家可能是这些例子的组合(也就是说,既是高管又是部门负责人,或者是财务部门人员和采购专家)。

这也是一个公平的说法,根据你的解决方案的规模和成本,可能涉及决策过程的不同人物角色及其数量。

高管

通常,他们拥有最终的决策权和发言权。他们的驱动力更多是聚焦于在市场上取得竞争优势、创造利润以及保持足够的合规性,避免损害公司品牌或陷入法律问题。

让一位高管支持你的项目,可能意味着成功、较低的采用率,或者更糟糕的是,完全失败的部署。他们在各自组织中的重要性通常能为你的团队扫清障碍,但请记住——如果你没有在解决方案中考虑到他们的需求,他们推动的那些障碍,可能正是阻碍你项目的障碍。

一个部门主管

部门主管可以成为你最轻松的盟友,也可能是你最难逾越的障碍,因为他们的控制领域和经验与其组织需求高度契合。他们可能在不同职位时已经有过使用你或竞争对手解决方案的经验(或一般了解)。他们的安全要求可能既具战略性,又具战术性,基于他们独特的领域知识。

部门主管也可能倾向于采用自家研发的解决方案,或者你的解决方案可能正在竞选取代他们之前创建的方案(这也是他们最初被晋升为部门主管的原因)。

通常,部门主管这一角色也很可能依赖他们的一个或多个员工提供意见和考虑。这种协作程度使得他们成为目标买家中最知情的人。因此,他们常常带着自己的一份必备安全功能清单和一份次要的可选功能清单来到讨论桌前。

一个采购专家

采购专家是压低成本的高手,他们的报酬完全基于这一点。这些人是任何销售团队的噩梦。他们根本不关心解决方案的价值或它所提供的赋能。通常,这些人来自法律或金融背景,这也是合情合理的,因为他们的职责是谈判采购合同。

在为公司寻找解决方案时,他们通常会收到一份功能需求清单,但通常,他们并不完全了解这些解决方案的功能或工作原理。这个角色可能需要额外的赋能,帮助他们理解为什么你的解决方案是最好的。如果你能在设计阶段接触到他们,他们可以帮助推动所需的功能,并帮助产品团队为你的解决方案定一个初始的价格点。根据我的经验和谦虚的看法,这些人是任何销售/售前周期中最难对付的客户。

确定并规划好你的关键目标买家群体的需求是一个挑战,但了解他们的驱动力能让你在设计中占得先机。现在,让我们继续下一个小节,回顾目标用户群体。

目标用户

目标用户是您的关键影响者。他们有望定期使用您的解决方案。他们对使他们生活更轻松的功能最为了解。他们对您的界面和设备操作具有最高的意见水平。他们可能已经使用您的旧版解决方案,甚至更糟糕的是,使用了竞争对手的解决方案。这一群体可以决定成败。作为解决方案的最终消费者,他们的影响力在采购其组织的产品和服务时至关重要。

在许多情况下,假设这一群体理解您正在解决方案中构建的技术是不公平的。您解决方案的目的是使他们的工作更轻松,并为他们提供他们自身可能没有的额外能力。电器解决方案的唯一目的是为那些在组织内没有技术能力或高级支持的人提供先进的功能。

这一群体也是您解决方案被采纳的最佳盟友。他们可以为您提供关于实地情况的最大情报。他们的意见可以推动功能和安全性要求的实现。

我们审查了最关键的用户角色,您的解决方案中必须考虑到他们的需求和期望。这并非包罗万象,但应该在消除特定安全功能需求的猜测方面提供巨大优势,哪些安全功能是“必须有的”,最终哪些安全功能可能被初步视为可选的。请带着一颗谨慎的心看待这一切,因为形势在变化,人员在变动,您正在创建的这份设计要求清单也可能会变动。

在我们即将讨论的下一组关键因素中,我们将审查合规对产品设计的影响。

是否有特定的政府合规标准会影响决策树?

遵守一个或多个政府标准的要求可能会限制您解决方案的功能性,同时增加其设计难度和市场准备工作。由于这本书可能在全球范围内销售,我的多年经验更直接地集中在北美市场。可以争论的是,嵌入式系统最大的市场可能就是北美本身;仅凭这一事实,就为全球制造商创造了在那里销售解决方案的机会。

确定您的目标买家、用户及其所在地,显然将决定您需要考虑哪些合规标准。了解许多国家都有类似和不同的限制以及适用的安全法律,这一点至关重要。

许多国家将源自美国的标准作为基础。在美国,我们也关注其他国家的强制性要求。全球安全社区的多样性和技术性都非常突出。就像开源社区一样,信息共享和同行评审是其核心精神之一。我们将在未来的章节中对许多这些资源进行深入细致的审查。

让我们深入了解一些行业领域,并讨论哪些合规标准可以直接应用于它们中的任何计算机系统。这些例子将强调联邦/国家级的举措,但请记住,也可能存在州级或地方性的立法推动合规标准。在我们深入探讨之前,我想再给你一个免责声明:全球范围内有成千上万的法律、规则和条例管理着商业的各个方面;然而,在接下来的市场和其主要关注点的列表中,我们将重点关注一些对安全性和设计规范直接产生影响的重要举措。深呼吸一下,开始吧!

医疗保健系统(及数据隐私)

首先,让我们谈谈医疗保健。在北美,医疗保健行业的客户基础超过 3.83 亿人。保护他们的系统、隐私以及患者的数据是由法律强制执行的。接下来会解释一些相关内容。

HIPAA

让我们从美国联邦政府的标准——健康保险可携性与责任法案HIPAA)开始说起。自 1996 年实施以来,HIPAA 在美国全国范围内推动了大量投资和行业审查。它是数据隐私如何处理的典范。

点击此链接了解更多关于该法律及其对医疗保健系统要求的详细信息:aspe.hhs.gov/reports/health-insurance-portability-accountability-act-1996

其他对医疗保健系统至关重要的标准将对你的嵌入式 Linux 系统产生较大影响,可能需要你提交设备进行测试和认证。

IEC 60601

该标准适用于医疗设备的电气安全和电磁辐射(如无线电信号、辐射和 Wi-Fi),并定义了基本安全性的测试。

这个标准在全球范围内有很多名字;以下是一些国家如何遵循该标准,但称其为不同名称的例子:

  • 加拿大称其为CAN/CSA C22.2 Number 60601-1

  • 欧盟EU)称其为EN 60601-1

  • 日本称其为JIS T0601-1

  • 澳大利亚和新西兰称其为AS/NZ 3200.1.0

这并非一个详尽无遗的列表。这也是我建议你研究适用于你的标准的原因。可惜的是,我知道在本书的过程中,我将时不时地重复这一点。

有关法律及其对医疗系统要求的更多细节,请点击此链接:www.iso.org/standard/65529.html

CE 标志/认证

这是欧盟的要求,证明医疗设备已通过评估,符合严格的安全、健康和环境标准,适用于医疗设备。它还证明了有害物质限制(全球称为RoHS)。

有关法律及其对医疗系统要求的更多细节,请点击此链接:single-market-economy.ec.europa.eu/single-market/ce-marking_en

医疗行业可能会比较复杂,接下来我们将转向下一个垂直行业,你应该会发现审查的力度会更强。接下来我们来看看金融服务系统。

金融服务系统

在全球范围内,金融服务行业受到严格监管,以保护普通消费者。该行业涵盖了广泛的服务,从普通银行和贷款到信用卡、房地产贷款、商业融资、股票市场、债券、年金和其他投资工具。

因此,多个政府机构应运而生,负责监管和监控金融市场的各个方面。接下来,让我们来看看一些更为重要的机构(以美国为例)。全球范围内还有更多类似的机构:

  • 联邦存款保险公司FDIC)是美国国会创建的一个机构,负责维护美国金融系统的可持续性和公众信任(基本上涵盖整个银行业)。

  • 证券交易委员会SEC)负责广泛的职责,监管证券和股票市场行业。

  • 联邦储备委员会的成立目的是控制 12 家联邦储备银行的运营并监督其业务。

  • 支付卡行业安全标准委员会PCI SSC)成立的目的是监管和规范信用卡行业。

在美国,这些机构以及执法机构、国内税务局IRS)和美国财政部,确保严格执行保护公众的规则和法规。这种情况在全球范围内大致相同。

无论你居住或工作的国家是哪里,技术在其中扮演着重要角色。这个行业的系统受多项安全法律和标准的管辖。让我们来看看一些全球范围内(不仅仅是美国)的重大法律,它们可以在你的产品安全方面带来更多的审查:

好了!哇,这有点激烈。你准备好参加测验了吗?!我只是开玩笑的。这是许多法规和政府官僚主义要突破的障碍。让我们继续下一个行业吧。

零售和在线市场系统

零售和在线市场系统(也称为电子商务系统)与金融服务领域的许多法规相同,以强制系统标准。对我来说,这很有道理。这是逻辑的。这两个垂直领域都涉及个人数据和金融交易的处理。以下是一些熟悉的倡议和您可能不熟悉的倡议。所有这些(以及未列出的其他内容)可能会对零售和电子商务产生重大影响。

零售业与金融服务行业类似,如 PCI DSS、EU-GDPR 和 UK-GDPR 等法律也适用于该行业。然而,由于这个行业还向公众提供服务,其责任不仅限于简单的数据保护,正如下面这些法律所示:

所以,这就是了。已为您概述了致力于保护您的购物体验和数字隐私的机构。让我们继续讨论大象房间里的大问题,那就是政府本身。

政府和军事系统

作为一名军事退伍军人和前美国政府承包商,我认为这一特定的合规标准集合是我心中的至爱。好吧,我承认曾经有过痛苦和疤痕,但达到并超越标准一直是我的基因。话虽如此,在这里你需要格外留意。

美国政府机构

下面是一些在网络安全领域具有显著监管水平并经常与国际分享其标准的美国机构的列表。尽管不是全部列举,这些政府机构是需要密切关注的,我们在后续章节中也会讨论它们的许多公开资源:

  • 网络安全和基础设施安全局(CISA) (www.cisa.gov/):CISA 是美国的首席网络安全机构,领导其他政府机构和行业合作伙伴确保该国、其公民及其数字资产的数字安全。

  • 国家标准与技术研究院NIST)(www.nist.gov/): 虽然 NIST 实际上隶属于美国商务部,但 NIST 在网络安全方面的贡献最为人熟知的是其对系统进行安全标准认证的工作。

  • 国家安全局NSA)(www.nsa.gov/Cybersecurity/): NSA 在美国政府机构中领导着密码学和情报收集工作。它向政府机构提供各种产品和服务,并且在使开源软件OSS)和 Linux 对所有人更安全方面做出了重大贡献。

  • 国土安全部DHS)(www.dhs.gov/topics/cybersecurity): DHS 是美国另一个覆盖面极广的机构。它在网络安全方面的作用通常涉及对网络安全犯罪和相关活动的调查。

现在我们已经了解了一些负责网络安全的主要政府机构,让我们来看看一些非政府组织NGOs)和外国政府机构,它们在安全和标准方面也有重要影响。

非美国政府的网络安全机构

由于本文希望在美国及海外阅读,我想将这些机构单独列出,因为它们也是值得关注的机构,并且应当留意它们的工作。它们还在各自的领域内制定并且经常执行网络安全措施。让我们来看几个关键的例子:

  • 欧洲网络与信息安全局ENISA)(www.enisa.europa.eu/): ENISA 专注于制定适用于整个欧洲的安全标准。它不仅制定政策,还设计流程,并有认证机制。在欧盟范围内,它是网络安全标准领域的首要机构。

  • 欧洲安全与合作组织OSCE)(www.osce.org/): OSCE 是一个非营利组织,每个欧洲国家在其中都有发言权,涉及经济、反恐、执法策略以及(当然)网络安全等事务。

  • 网络与信息安全部门C&IS)(www.mha.gov.in/en/divisionofmha/cyber-and-information-security-cis-division): C&IS 是印度政府的一个部门,负责处理所有与网络安全、网络犯罪、国家安全政策相关的事务,同时还涉及技术安全标准和建议。

  • 互联网安全中心CIS)(www.cisecurity.org/): CIS 是一个基于社区的非营利组织,通过销售安全最佳实践材料和相关服务来资助自己。

  • 国家网络安全事件处置与战略准备中心 (NISC) (www.nisc.go.jp/eng/index.html):NISC 是日本的网络安全监管机构。负责制定并实施商业和政府系统的标准。

现在,我们已经回顾了一些国际和外国政府机构在网络安全领域的责任,让我们在下一节中更深入地审视数据的影响和关键性定义。

Impact Levels

美国政府已经明确定义了隐含的临界性水平,以确定应用于特定级别的系统安全性和审核。他们将这些级别分类为 Impact Levels。关于这些级别影响的图形描述可以在美国 国防部 (DoD) 网站上找到 – media.defense.gov/2020/May/18/2002302035/-1/-1/1/NAVY_TELEWORK_CAPABILITIES_V14.PDF

美国国防部对 IL 确定的快速总结如下:

  • IL-2: Impact Level 2 指的是公共或非关键任务信息。拥有 Federal Risk and Authorization Management Program (FEDRAMP) 认证的产品将自动达到此等级。

  • IL-4: Impact Level 4 指的是 受控非机密信息 (CUI),非任务关键信息,与国家安全系统无关。

  • IL-5: Impact Level 5 指的是具有更高敏感性的 CUI 系统,实际的任务关键信息或实际的国家安全系统。

  • IL-6: Impact Level 6 指的是处理机密 机密 数据和其他国家安全系统的信息系统。

  • IL-7: Impact Level 7 指的是处理机密 绝密 数据和关键国家安全系统的信息系统。

正如我们在上一节中突出的那样,美国政府非常重视数据分类级别。但他们并不止步于此。我们将在下一节中讨论美国政府的一系列指令和标准。

美国政府的标准和认证

政府或军事机构要求的联邦强制执行的标准和认证有很多。让我们看看需要注意的关键标准:

  • Federal Information Security Modernization Act (FISMA): 符合 FISMA 制定的标准强制要求公司进行年度详细的系统安全审计 (security.cms.gov/learn/federal-information-security-modernization-act-fisma)。

  • FEDRAMP: FEDRAMP 认证用于产品和 Web 服务,使其能够销售并供政府机构使用,前提是这些产品也符合适当的影响等级要求 (www.fedramp.gov/)。

  • 安全技术实施指南 (STIGs): 这些公开共享的操作系统、网络组件和应用程序的加固指南是获得和保持其他政府和军事认证的基准。它们也为非政府实体提供了更高的标准,这些标准可以应用于任何行业垂直领域的系统。我在我的职业生涯中已经无数次使用过这些指南(尤其是在我作为政府承包商从事敏感系统工作时) (public.cyber.mil/stigs/downloads/)。

  • 通用准则 (ISO/IEC 15408): 这是一个多国合作的典范,多个国家已经标准化并强制执行遵守网络安全基本原则的标准基准。许多国家参与了这一全球标准,并且提供相应的认证 (www.commoncriteriaportal.org/index.cfm)。

  • 联邦信息处理标准 (FIPS) (FIPS 140-2/140-3): 这两个 FIPS 标准及其认证通过全面的测试和认证强制执行对加密技术的详细遵守。FIPS 140-3是更新且当前的标准。这个极为全面的过程不仅对那些将产品通过认证的制造商来说成本高昂,而且在某些情况下需要数年的时间。NIST 是认证机构。我在这个过程中有着丰富的个人经验,并且曾帮助我当前公司的一些合作伙伴完成该过程。更多细节请参阅以下链接:

  • 美国政府标准配置(USGv6/USGv6-r1) (www.nist.gov/programs-projects/usgv6-program): 该项目由 NIST 创建并执行,用以规范所有在产品中使用互联网协议第六版 (IPv6) 的系统。

总结来说,我们已经看到许多政府在计算机系统的使用上施加影响。如果你计划将你的解决方案推向政府部门,那么显然你的产品需要具备最高的安全性,因为有大量的标准可能适用于你的嵌入式 Linux 系统设备。

我们审查了一些关于如何在产品设计中满足合规性需求的关键示例。在后续章节中,我们将深入探讨如何应用非常具体的标准,并为你提供一些实践练习。合规性遵守不是那些可有可无的内容,因为不遵守可能带来刑事指控或民事责任的严重后果;这将使你的公司面临风险。

现在我们已经看到一些标准和合规性措施如何推动你解决方案的安全足迹,让我们来看看你的组织如何考虑在将解决方案销售给终端客户后进行支持。

我们将如何支持该设备解决方案?

另一个可能影响你设备解决方案商业模式的关键设计因素是你计划如何为客户群体提供支持和服务。

支持和服务的规划将直接影响你设备的安全性。远程访问、虚拟私人网络VPN)、用户账户、补丁方法、终端用户自助支持能力等,都是必须在设计过程中考虑的选项。现在,让我们来看看一些交付和支持模型,这些模型将影响访问控制和你解决方案的安全足迹。

托管服务

托管服务提供允许你的公司完全控制解决方案的使用、更新周期和访问控制。无论围绕这一点的商业模型如何,仍有几个关键因素需要在你的解决方案架构中得到处理,例如以下几点:

  • 客户级别(终端用户访问)

  • 初始网络配置

  • 扩展性和冗余

  • 远程访问或本地访问

  • 解决方案是否为气隔式(air-gapped)?

  • 审计要求

托管服务模型并不适合所有人。让我们继续讨论下一个模型,即在线支持模型。

在线支持

在线支持是指通过网页方式提供设备更新和客户信息的方式。它通常可能包括通过网页或电子邮件创建帮助请求的方式。也可能出现这样的情况:用户可以在线获取帮助/支持,但设备本身处于离线或气隔状态。在建立在线支持模型后,让我们来看看可能影响其成功的关键因素:

  • 你如何考虑设备的初始设置和配置?

  • 该设备是否可以连接互联网?

  • 该设备将使用哪些方法来获取和处理更新?

  • 你将如何提供自动更新与用户发起更新?

提供在线支持可以为终端客户提供便捷的资源访问,并提供简单的更新和信息传递方式。然而,并非所有商业模型(或使用模型)都会接受这种方式。在这种情况下,我们进入下一个模型:离线支持模型。

离线支持

在这种情况下,设备不会直接从制造公司获取任何东西。设备本身假定处于受限的、与外部网络隔离或不联网的环境中。我们来看看一些需要考虑并进行规划的关键因素:

  • 你如何处理初始设备设置与配置?

  • 用户将使用什么方法来获取并处理解决方案的更新?

无支持/自助支持

无支持或自助支持是市场上最不常见的模式。它迫使最终用户自己做所有事情,而解决方案的制造商在产品发货后对产品没有控制权。这是一种设定后就不再关注的模式。对于一些非常低成本的项目,如传感器设备,这种方式可能合适,但最终会让客户认为你的解决方案是一次性的。虽然这种过于简化的有限支持模式能为公司带来一些成本优势,但仍然有一些因素需要规划,以确保客户满意:

  • 初始设备设置与配置

  • 客户端的故障修复选项

替换

没有任何硬件平台是完美的。有时候,设备就是会损坏。对于某些解决方案来说,在现场(也就是远程)进行更新或故障排除实在是太困难或不现实。解决这一问题的方法其实非常简单。贵公司可以与客户交换一个新的系统,以替换无法正常工作的单元,或为客户提供一个更更新或升级的单元。现在,让我们看看你必须考虑和计划的内容:

  • 客户数据备份和从旧系统到新系统的转移是否可行?

  • 你如何处理初始设备设置与配置?

由于这是任何产品团队常见的痛点,我们仍然必须为不可避免的情况做规划。现在,让我们看看一些你可能没有考虑到的其他事项。

其他影响产品的需求和关注点

在本节中,我们将继续深入反思那些可能被忽视或遗忘的因素。通过这样做,我们将为产品的安全性和长寿命进行规划,并最终迈出确保其成功的步伐。

硬件生命周期

如果你是产品经理,本节内容将非常适合你。确保你的计划与硬件供应商的支持生命周期一致至关重要,这样才能确保你能在设备预定的生命周期内获得所有单元和替换零件。

知道你的供应商当前硬件版本处于生命周期的哪个阶段是非常有帮助的。大多数主流硬件供应商会在 3 到 5 年内维护一个特定的平台。在此期间,一些组件或主板的小幅改动是常见的。替换零件可能会在这一时间段后再供应几年,但价格会较高。

假设你的解决方案使用的是主流供应商的现成平台,我们来回顾几个关键因素:

  • 我们将为生命周期支持分配多少预算?

  • 我的供应商平台的微小变动是否会对设备造成问题?

  • 我对于设备未来版本的升级和更换计划是什么?

  • 我在我的设备中使用了哪些第三方硬件组件?

  • 我打算为即时更换准备多少备用系统和备件?

好的……为什么这与安全相关?我的回答很简单。如果你未能确保硬件供应链的安全,一旦产品被最终客户采纳,你将会在未来遇到大量支持风险。这到底意味着什么呢?如果你无法再支持最初部署的现有硬件,就会变成一个问题,甚至可能造成一个复杂的局面,使得产品出现多个平台,这会成为一个支持噩梦和物流噩梦。更糟糕的是,如果你更换平台,你可能会引入一个未知的漏洞或软件不兼容。说实话,我们在这里是为了降低风险,对吧?

哎呀!我刚刚打开了一个潘多拉的盒子。那么,让我们用最简单的术语来解析它。确保供应链的安全并准备好备件,将避免你部署多个平台后产品变得更难以支持的风险。我的指导的目的就是帮助你降低风险和成本。

让我们一起走过这一过程。我们将为生命周期支持分配多少预算? 这是产品经理在销售活动中能提出的最重要问题,因为它直接关系到大多数产品经理每天追踪的盈亏P&L)账目。生命周期支持是一个复杂的计算。

必须规划多种不同类型的支出:

  • 人员成本

  • 支持方法(网页、电子邮件、电话等)

  • 更换成本

  • 备件成本

  • 由于硬件或软件(或两者)与实际规划的解决方案生命周期不匹配而可能产生的额外成本

现在我们已经审查了硬件平台的生命周期如何影响管道和产品交付的安全性,让我们来看看与硬件紧密相关的另一个明显问题:操作系统的生命周期。

Linux 发行版生命周期

大多数 Linux 发行版,无论是社区版还是企业版,都有其预定的生命周期。这是故意为之的。拥有明确的生命周期定义,使得支持该发行版的人员能够规划更新、功能发布和版本过渡。

这些知识还能帮助你和你的团队最好地规划产品的需求。与操作系统相关的关键里程碑日期将推动设计、部署/发布,并最终决定产品的生命周期。

生命周期状态还将直接与产品的成本结构相关。付费、支持的企业级发行版按单元计算费用。费用形式可能是年度订阅、永久许可证或额外的支持费用。一些供应商为超过正常生命周期的发行版提供简化支持。这种延长生命周期的支持通常是额外收费的,且通常仅涉及操作系统的一个小子集。此时提供的通常只是被认为至关重要或重要的安全修复的回溯。较为常见的漏洞与暴露CVEs)和错误修复通常不包括在内,也不支持新功能或新硬件兼容性。

今天有无数种 Linux 发行版可供选择。大多数发行版声称定位于某个特定的细分市场,并针对特定的使用场景。另一些则是企业和政府领域的领导者。有的发行版易于使用(也就是面向 Linux 初学者),而其他的则需要更深的知识和技能,这些技能远超现代职场中常见的水平。由于有这么多选择,我认为最好缩小范围,专注于一些最常见且在嵌入式 Linux 系统生态中声音最大的参与者。

我再次声明:这个列表并不完全,但这些是目前(2024 年)大多数设备所依赖的基础。如果我遗漏了您认为应该在此列表中的发行版,请接受我的歉意。详细列举当前所有可能的 Linux 发行版本身就可以成为一本书。这些列出的发行版按无特定顺序并无任何偏见地呈现给您。在本节中,我们将回顾生命周期、付费模式和支持周期。在接下来的章节中,我们将更深入地探讨这些操作系统,看看它们如何最好或不适合您的产品。

我将如何格式化并展示关于分布式采样的数据,这些数据可能会成为嵌入式 Linux 系统设备基础的一部分,展示方式如下:

  • 发行版名称

  • 发行版主页的 URL

  • 发布计划总结

  • 主要生命周期时长

  • 授权/订阅信息

  • 支持选项信息

  • 其他重要提示(可选)

那么,让我们根据上述格式深入了解一些优秀的例子:

  • Rocky Linux™ (rockylinux.org/)

    每 3 年发布一次重大版本

    每 5 个月更新子版本

    10 年生命周期

    免费使用

    没有原生支持选项

重要提示

从每个重大版本迁移时,需要重新安装——例如,它们不提供从版本 8.x 到 9.x 的升级路径。

该发行版由 CentOS 的创始人创建,回应 Red Hat 停止对操作系统的下游支持,因此将 CentOS 过渡为介于 Fedora 和Red Hat Enterprise Linux (RHEL)之间的开发版发布集,而不是一个与 RHEL 相似的下游免费操作系统。Rocky 的命名是为了纪念 CentOS 的创始人之一,遗憾的是他已经去世。

  • AlmaLinux™ (almalinux.org/)

    每 3 年发布一次完整版本

    每 6 个月发布一次更新子版本

    10 年生命周期

    免费使用

    付费支持选项由 AlmaLinux 网站上列出的第三方提供

  • CentOS™ (centos.org/)

    官方已被名为 CentOS Stream 的非生产级开发者沙箱所取代

    最后的更新已于 2024 年 6 月停止发布

    免费使用

    第三方付费支持选项仍然存在,且其中一些可能能延续至 2024 年 6 月之后数年

  • SUSE Linux Enterprise Server™ (SLES) (www.suse.com/)

    10 年生命周期,另外提供最多 3 年的付费长期系统支持(www.suse.com/lifecycle/#product-suse-linux-enterprise-server

    订阅模式

    订阅中包括支持选项

重要说明

提供免费不支持的 SLES 变体(openSUSE):

www.opensuse.org/

重要说明

个人可免费获得开发用订阅:developers.redhat.com。企业开发订阅有多个付费和无成本订阅选项,可以选择是否包含支持。

现在我们已经了解了最可能的操作系统及其支持的生命周期,接下来让我们讨论整体供应链问题。

供应链问题

这与供应链问题有什么关系?你可能会问。嗯,这是一个很好的问题。为此准备多个计划以应对问题是更为重要的。如果你正在制造基于硬件的设备解决方案,这一点尤为关键。

使你的计划生命周期与硬件供应商保持一致是很常见的做法,甚至是至关重要的。假设你的解决方案需要额外的第三方组件怎么办?你还有哪些备用零件来源?是否有计划在维修设施中保持某些部件?还有,别忘了确保支持人员在实验室中拥有可能出现的所有平台硬件和第三方组件组合,以便排除客户问题并提供优质支持。

另一个增加复杂性的情况是,当硬件组件的变化引起所需驱动程序、内核模块、库等的变化时。这意味着每种组合必须经过全面的审查、扫描和验证,并确保符合相同级别的安全措施。保持组合数量最小化,最终将有助于你的团队能够大规模交付。否则,这就变成了千刀万剐;每个客户的情况与下一个客户略有不同,甚至更糟的是,某个客户的每个系统可能都不相同。于是,问题来了:这将变成一个安全支持的噩梦。每次发布新版本或修补程序时,必须考虑到每个组合。这也可能影响你如何向客户提供更新,并进一步影响客户体验。

摘要

哇!我们已经涵盖了许多不同但同样重要的标准,这些标准将融入到你的设计和产品规划策略中。我强烈推荐根据你的产品未来需求和期望创建一个详细的检查清单。确保解决方案的稳定性、可支持性和长久性,将使设计、创造和销售更好的、更安全的设备变得更加容易。最终,你只是在为最终客户提供更多他们期望从你的解决方案中得到的东西。

在下一章节中,我们将回顾如何将这些设计标准应用于硬件选择和采购过程中。

第三章:3

应用设计要求标准——硬件选择

在本章中,我们将深入探讨设计标准,这些标准将决定你选择什么硬件。仅仅选择一个平台的简单决定,可能会带来成千上万的其他依赖项,而这些依赖项你可能之前从未考虑过。本章及下一章(即本章的伴侣)将成为你在构建设备时所有未来工作的基石。

此外,我理解如果你正在阅读本书(顺便说一句,我非常感激你选择了这本书!),那么你对其核心主题有一定的兴趣。作为作者,我假设你不仅对嵌入式 Linux 系统感兴趣,而且你可能正深入参与此类项目。基于这一点,我认为你应该具备一定的基础技术知识。我相信本章及下一章中提供的信息足够有价值,能够为你的项目增添助力,而又不会过于基础到冒犯你已经掌握的技能。本章及下一章的目的是帮助你连接所有隐喻性的点,照亮你的解决方案可能达到的更大图景。

重要说明

如果你打算构建虚拟设备,本章的内容可能对你和你的团队不太相关,因为我们将重点讨论硬件。本章主要面向物理设备。我们将简要回顾虚拟设备。在虚拟设备(或云服务)方面,你需要考虑为哪些平台创建镜像。近年来,虚拟设备变得越来越普遍,特别是在任何超大规模云服务商(如 Azure、AWS 或 Google)的应用商店中。许多人仍在为 OpenStack、KVM、Hyper-V 和(主要)VMware ESXi 构建虚拟设备。

无论你选择将产品做成物理的、虚拟的,还是两者兼具,本章将帮助你和你的设计团队理清所有标准,以便做出合适的硬件平台选择。此外,我们还将回顾最佳实践如何在性能和可扩展性方面影响这些选择。这些最佳实践直接关联到你的安全性足迹,但它们也会帮助你构建更好的产品。

在本章中,我们将讨论以下内容:

  • 目标性能要求是什么?

  • 是否存在任何环境限制?

  • 现成商品COTS)与定制硬件

  • 当前有哪些主流硬件平台可用?

  • 硬件和使用案例标准将决定你操作系统的选择

让我们开始吧。

目标性能要求是什么?

现在,是时候进入技术层面了。希望你的解决方案开发人员至少对虚拟设备的最终需求有一个大致的了解。如果没有这些关键信息,你的原型设计过程可能会非常昂贵,因为你可能需要测试多个硬件平台的不同迭代版本。

无论你的解决方案的规模大小,或是物理的还是虚拟的,你都必须确保进行广泛的性能测试,以确保所实施的安全措施仍然能够让解决方案按预期执行任务。我们将在后续章节中讨论如何将这些安全措施集成到解决方案中。

另一个需要考虑的关键因素是你解决方案的未来状态。确保你为应用程序、安全措施和用户数据规模设定的规格具有一定的安全缓冲。未来的安全补丁或应用程序的变化对性能的影响是无法预见的。给你的解决方案额外分配一些 CPU、内存和存储,能在未来为你的支持团队节省不少麻烦。

现在,让我们来了解一下,如果我们决定这样做,我们需要哪些内容,以便能够虚拟化我们的解决方案。

虚拟设备

如果你计划将你的产品交付为虚拟设备,这个过程将会减少很多压力。你不需要测试硬件!你不需要担心采购符合生命周期需求的平台。这是令人解放的。决定创建一个虚拟设备(或公共云产品)将资源需求交给客户。

然后,你的客户可以决定具体分配多少 vCPU、RAM、存储和网络带宽给虚拟设备。他们提供平台。这样做的附加好处是,你知道你需要选择的操作系统必须支持 Intel/AMD,因为这是企业中的通用标准。当然,你的公司可以为这些基准提供建议。在公共云提供商方面,你可以将基础虚拟机大小作为市场产品的一部分。

在这个阶段,关键的决定变成了你打算为哪个虚拟化平台提供你的解决方案——VMware、OpenStack、KVM、Hyper-V、Google、Azure 还是 AWS。最初,你可能会从一个平台开始,然后根据团队的可行性决定是否添加其他平台。

我不得不提到,一个优秀的产品经理会进行调研,以确定最适合平台化的选择。根据这些调研,你可能会发现目标用户群体之间的差异,包括他们的偏好、采购周期,以及最重要的,他们对云平台和/或本地虚拟化平台的偏好。

尽管许多解决方案无法以虚拟设备的形式交付,但如果你的产品可行,我建议认真考虑这一方法。它可以提供巨大的灵活性,我们将在本书后面进行详细介绍。

现在我们已经讨论了物理设备的性能,接下来考虑硬件设计。

T 恤尺寸划分

T 恤尺寸划分是一种根据所需容量来扩展和交付解决方案的方法。它旨在标准化并简化将解决方案交付给最终客户的过程,适用于最常见的需求规模。

让我通过一个例子来帮助描述 T 恤尺寸划分方法。为了讨论的方便,假设某公司想要提供一个独立的存储解决方案。该公司计划提供小型、中型和大型解决方案。现在很清楚为什么他们称之为 T 恤尺寸划分。

他们决定小型解决方案将具有以下硬件属性:

  • 单个多核 CPU(具有低核心数)

  • 32 GB 内存

  • 双千兆以太网接口

  • 4 个 1 TB SATA SSD 驱动器

进入下一个级别,他们决定中型存储解决方案具有以下硬件属性:

  • 单个多核 CPU(具有高核心数)

  • 64 GB 内存

  • 四个千兆以太网接口

  • 8 个 1 TB SATA SSD 驱动器

他们在确定硬件配置时决定,大型存储设备的硬件属性如下:

  • 双多核 CPU(具有高核心数)

  • 128 GB 内存

  • 四个千兆以太网接口

  • 双 10G 以太网接口

  • 16 个 1 TB SATA SSD 驱动器

这些例子已简化以说明一个观点。虚构的公司选择了三个级别,每个级别的规模都比前一个大。在物理设备的世界里,这种尺寸划分方法也意味着,要创建一个 T 恤大小的产品,必须做更多工作,确保每次发布的解决方案都能稳定地提供预期的性能和安全性。选择创建这种分步尺寸的产品,可能迫使企业完全采用不同的硬件供应商和平台,这种情况并不罕见。

为解决方案进行 T 恤尺寸划分会给团队带来额外的工作量,但我认为这是一个值得考虑的优秀方法。这样做可以使你为不同需求规模的广泛受众提供解决方案。现在我们已经回顾了规模对设计的影响,接下来看看硬件领域的其他因素。

CPU/VCPU

CPU 是决定解决方案其他所有方面的最重要因素。它在性能、功耗和价格方面有着广泛的差异。解决方案的外形、环境阈值和性能需求最终将决定选择。

在我们讨论每个 CPU 系列带来的优点之前,我希望您了解这个方程式的阴暗面。没错——我从坏消息开始,希望在接下来的几个部分中能够以积极的消息结束。由于本书聚焦于安全性,我们必须深入探讨选择错误平台时可能出现的局限性、漏洞、利用这些弱点的行为以及其他不当行为。

本书稍后将深入探讨您团队可以使用的所有资源,这些资源将帮助您了解新的威胁、漏洞、修复和缓解措施。目前,让我们先来了解今天需要避免的那些问题。以下列表基于常见漏洞和暴露(CVE)数据库中的条目。

值得注意的是,那些严重的漏洞会被命名,但并不会使用像热带风暴、飓风和台风这样的友好人类名称。它们会被命名为让人感到不祥和压抑的名字。通常,发现漏洞的团队还会为其设计一个标志。

目前 CVE 数据库中大约有 24 万个已知的各类漏洞,我将只回顾一些在全球范围内引起关注的漏洞。这个列表将帮助您入门,但请不要止步于此——在做出选择之前,继续进行研究。以下列表突出显示了一些最具影响力的 CVE,这些 CVE 应该影响您的 CPU 和平台尽职调查。我们还将探讨它们的影响以及缓解技术:

  • Meltdown:这一漏洞家族包含在多个 CVE 中,核心问题是能够利用 CPU 中的竞争条件,获取特权信息。它有 5 个 CVE——CVE-2023-46836,CVE-2022-42331,CVE-2018-7112,CVE-2018-19965 和 CVE-2017-5754:

    • 影响:Intel x86 微处理器,AMD 微处理器,IBM Power 处理器以及一些 ARM 微处理器。

    • 缓解措施:大多数操作系统供应商已经创建了补丁来缓解这一漏洞,但一旦应用这些修复,系统的性能会受到严重影响。2019 年以后制造的较新处理器应该内置了硬件和固件缓解措施,但仍然存在 2023 年才出现的新型瞬态执行 CPU 漏洞。

  • Spectre:这一漏洞家族包含在许多 CVE 中,其漏洞利用方式与 Meltdown 非常相似,都是通过 CPU 条件的漏洞来获取未经授权用户的特权信息。它有 31 个 CVE,所以我将重点介绍最重要的两个——CVE-2017-5753 和 CVE-2017-5715:

    • 影响:Intel x86 微处理器,AMD 和 ARM 微处理器。

    • 缓解措施:大多数操作系统厂商已经创建了补丁来缓解这个漏洞,但一旦这些修复应用到系统中,会对性能产生严重影响。2019 年后发布的较新处理器应内置硬件和固件缓解措施,但仍然存在新的瞬态执行 CPU 漏洞,最早可追溯到 2023 年。

  • 崩溃:也被称为数据采样收集GDS),崩溃是另一种瞬态执行 CPU 漏洞,攻击的是 CPU 中的推测执行功能,称为高级向量扩展AVX)。通过这一弱点,有可能利用漏洞访问向量寄存器中的数据(CVE-2022-40982):

    • 影响范围:第 6 代至第 11 代 Intel X86-64 消费级微处理器,第一代至第四代 Intel Xeon X86-64 处理器。

    • 缓解措施:预计 Linux 内核 6.5 或更高版本将包含用来缓解此漏洞的代码。然而,即便到了 2024 年,几乎所有现代消费类计算机仍然容易受到这一漏洞的影响。

  • 预示:此漏洞也被称为L1 终端故障L1TF)。它通过攻击内存管理来瞄准虚拟机、虚拟机监控程序(hypervisor),最终影响相关的操作系统(CVE 编号:CVE-2018-3615 和 CVE-2018-3620):

    • 影响范围:几乎所有 Intel 和 AMD 微处理器系列。

    • 缓解措施:更换处理器似乎是解决该问题的最佳方法。此问题在 Intel Xeon 处理器系列中已经得到解决,从 Cascade Lake 版本开始。所有较新的芯片组应对这些漏洞免疫。

  • 起源:此漏洞,也称为返回地址安全RAS),是一种新型的侧信道攻击,针对的是推测执行(CVE-2023-20569):

这个列表是我自己版本的五个最需要警惕的可利用漏洞。每个漏洞通常都与多个 CVE 关联,并且并非所有漏洞都已得到完全缓解。新的变种或类似的攻击仍在困扰所有 CPU 平台,威胁与 AI 使用不断演变,寻找新漏洞。

在有了这些基础信息后,你可以看到硬件选择如何影响你的安全性足迹。当我们进入下一部分时,记住这些因素将在下章讨论操作系统选择时重新出现。现在,我们先来看看各种内存考虑事项。

内存

内存类型与 CPU 及其相关的内存控制器密切相关。这些都是系统主板或母板上不可更改的部分。由于这些依赖关系,这是一个相对简单的选择点。然而,从安全性和可靠性角度来看,在做设计选择时需要考虑一些差异。每一个因素都有其成本和其他影响。

根据我的经验,你可能被迫考虑的唯一值得质疑的选择是使用错误校正码内存ECC RAM)或非 ECC RAM。

什么是 ECC RAM?它是一种容错内存,主要用于高端服务器和工作站。虽然它确实提供更高的可靠性,但使用它可能会稍微影响性能。如果你需要可靠性,那么大约 2%的性能损失可能并不重要。

由于 ECC RAM 的成本高于标准 RAM 模块,它在物联网设备或小规模嵌入式 Linux 系统中并不常见。

接下来,我们将考虑一个更重要的因素,它可能会受到你的安全性足迹的影响。

磁盘输入/输出(I/O)

为了最好地理解这对你的设计的影响,你必须了解输入/输出每秒操作次数IOPS)这一术语的定义。由于本书的重点是安全性,而不是教学技术术语,我认为在这里使用一个标准的、公开接受的定义是合适的。

IOPS 定义为“一种输入/输出性能测量,用于描述计算机存储设备,如硬盘驱动器(HDD)、固态硬盘(SSD)和存储区域网络(SAN)。像基准测试一样,存储设备制造商发布的 IOPS 数字与实际应用性能没有直接关系。”

提示

欲了解更多相关信息,请访问维基百科页面:en.wikipedia.org/wiki/IOPS。维基百科是一个宝贵的公共资源,如果它对你有帮助,应该考虑向其捐赠。多年来,它确实帮了我不少忙。

其次,你必须理解加密对系统性能的影响,特别是在开销和 IOPS 下降方面。

第三个也是最后一个需要考虑的因素是你的解决方案将使用哪种类型的存储。无论你是在创建虚拟设备还是物理设备,这一点都很重要。两种交付方式之间的痛苦区别在于,物理设备可以控制内建的存储类型,而虚拟设备则无法控制,只能提供建议。如果最终用户可以控制所使用的存储类型,你的解决方案可能无法如广告中所示那样工作,甚至更糟的是,如果存储速度过慢而无法满足应用需求,可能根本无法正常运行。那么,让我们看看有哪些存储选项。

在接下来的存储分类列表中,我将重点关注存储本身的基本单元,而不是讨论不同的海量存储选项,比如阵列或网络附加存储。这本身可能就是一本书。那么,让我们看看各类独立存储驱动器的选项:

  • 硬盘驱动器HDD)是计算机系统中最古老的存储设备之一。几十年来,旋转磁盘的尺寸大大缩小,但存储容量却不断增加。早期的 HDD 容量以兆字节为单位,但如今它们可以容纳多达几个太字节。限制这种存储平台整体性能的其他因素包括连接驱动器的总线和 IOPS 数量:

    • 总线: SATA

    • IOPS: 平均在 50 到 80 之间

提示

所有提到的存储平台都提供总线和 IOPS。

  • 固态硬盘SSD)是存储技术从 HDD 硬盘的一个飞跃。SSD 没有活动部件,且通常以非常小的形式因数提供。它们一般以 2.5 英寸硬盘或卡片形式交付:

    • 总线: SATA 或 PCIe

    • IOPS: 根据平台不同,从 4,000 到数万(或更多)

  • 非易失性内存快照NVME)是最新的消费者存储平台。NVME 驱动器通常以小卡片的形式提供。有时,多个 NVME 驱动卡可以安装到一个更大的 PCIe 卡上以提高存储密度:

    • 总线: PCIe

    • IOPS: 根据平台不同,从 10,000 到数百万不等

现在我们已经深入探讨了一些最常见的存储类型,让我们看看添加加密如何影响它们的性能。

在磁盘、卷或文件系统级别的加密可以轻松分为两种交付方式。这两种方式是基于硬件的加密和基于软件的加密。每种方式都有其优缺点。

基于硬件的解决方案通常通过 PCIe RAID 卡提供。这些卡不仅可以让你创建弹性卷,还能将加密的开销从主 CPU 或操作系统中卸载出去。唯一的缺点是需要有适合的插槽来安装这些卡,以及这些卡的成本较高。

Linux 统一密钥设置LUKS)是 Linux 发行版中标准的软件加密方法。LUKS 被广泛应用于各种规模的解决方案中,尽管它在内存和 CPU 性能上会增加一些开销。大规模应用时,它需要外部密钥管理,但在单个系统上,它会要求用户在访问文件系统之前输入密码短语。这可能会对启动和更新过程造成一定的麻烦,因为它需要手动干预。除了这些因素外,实施 LUKS 不需要额外的费用。

对静态数据进行加密被认为是系统安全的基石。另一方面,传输中的数据加密通常是在应用程序或网络层处理的。

网络

在本节中,我们将回顾几种可以实施的选项,以增强网络配置的安全性,同时减轻解决方案 CPU 的负担。对于每一个选项,我们将为你提供一些链接,进一步了解其技术。每一项技术将在这里简要介绍,但它们都能大大帮助你的团队设计出更加安全的解决方案。

我不想浪费你时间去讨论防火墙、VLAN、地址段白名单或其他基本网络安全内容。由于本书专注于设计、构建和支持安全的嵌入式 Linux 系统设备,我打算重点介绍能帮助你的硬件。让我们来看看几个有趣的技术,你应该考虑将其纳入你的解决方案中。

TCP 卸载引擎

近年来,一些高端网络接口卡NICs)增加了内建的附加功能,可以将整个 TCP/IP 网络栈从系统的主 CPU 中卸载。这种功能以TCP 卸载引擎的形式出现。目前几乎所有操作系统都支持这些 NIC。

利用一张或多张这样的卡片可以提高你解决方案的性能,但现实中,你仍然需要在应用程序和系统配置中考虑加密和安全性。将网络栈迁移到 NIC 上,可以让其他类型的应用程序安全性在主 CPU 上不受阻碍地运行。

你可以通过en.wikipedia.org/wiki/TCP_offload_engine了解更多关于该技术的信息。

TLS 加速卡

传输层安全性TLS)加速器(以前也称为SSL 加速器)是用于卸载与加密和解密网络流量相关的处理器密集型工作卡。通过利用这些解决方案,性能提升和网络安全能力的增强是显著的。一些高端设备制造商将这些硬件直接集成在主板上,尽管如果系统有 PCI 插槽,也可以轻松通过该插槽添加。

你可以在en.wikipedia.org/wiki/TLS_acceleration了解更多关于此技术的信息。

GPU

好吧——我知道我的观点可能会引起一些争议。近年来,GPU 在全球许多设备解决方案中更多地被用来卸载工作负载,而不是处理视频输出。可以争论并讨论,大多数现代 GPU 在工作负载处理方面比大多数主流 CPU 更为出色。

无论你对其使用的看法如何,将计算处理任务卸载到 GPU 上已成为许多 Linux 系统中的主流功能。这通常与人工智能AI)和机器学习ML)应用相关。

这是一个设计问题,基于你选择的操作系统可能支持的内容(我们计划在下一章深入探讨这一点)。将 GPU 添加到系统中并不是一个小决定。这些卡通常在大小上相当显著,并且它们需要大量额外的电力(通过系统本身的电源供应单元PSU)的直接电缆提供)。在大多数情况下,这些额外的电力为卡的冷却风扇提供动力,因为它们会像烤箱一样产生热量!

实现一个需要显著 GPU 或多个 GPU 的解决方案,将需要更大的电源供应单元(PSU)和更强的冷却系统来构建在设备内。我认为有必要提到这一点,因为我们很快将讨论环境因素对你的解决方案的影响。

接下来,我们将考虑在你的设备中可能需要的其他定制硬件。

定制硬件和外围设备

这是一个可能与你息息相关的部分,因为你正在构建定制解决方案。根据你的解决方案将连接到什么或内部包含什么内容,存在巨大的安全影响和因素需要考虑。构建一个设备解决方案几乎意味着在硬件和软件层面上都需要某种程度的定制。最能说明这一点的是,你正在解决一个或多个最终客户无法轻松应对的问题。

抛开物理安全问题,我们来探讨一下使用定制硬件和/或外部外围硬件设备可能带来的安全隐患。这些硬件可以是内部的,也可以是外部连接到你的解决方案的。它们可能需要你的解决方案安装第三方驱动程序和软件,而你对这些软件的生命周期几乎没有控制权或输入。

对于外部连接的设备,问题不仅在于软件超出了你的控制范围,还在于你的解决方案与这些设备连接的物理介质。也许你的解决方案是为了控制或维护外部工业机器。你的解决方案与这些机器的连接方式以及使用的协议是最大的安全隐患。

如果定制硬件或外设需要第三方支持和软件,你的团队必须确保生命周期和支持周期与你预计的解决方案的时间表一致。如果你正在构建一个预计会持续 5-10 年的解决方案,但所需的第三方软件可能在几年后就不再提供支持,那么这就会造成巨大的差距。没有做好这方面的规划是一个安全问题。如果发现了新的漏洞,但你的供应商不再提供支持或更新,你的解决方案最终将被妥协。

对你的产品而言,这里的影响可能非常重大,因此我建议在确认任何第三方构建的解决方案是否可支持之前,做好尽职调查。关键在于 细节

现在,让我们进入另一个至关重要的因素——涉及到终端客户可能部署你的解决方案的方式和地点。这就是它将存在的环境。

是否存在任何环境限制?

在这一部分,我们将涵盖一组通常交织在一起的关注点,这些关注点将影响你产品的设计和物理安全性。并非所有硬件都能适应挑战性环境。让我们面对现实,承认大多数电子设备需要一个相当稳定和安全的环境才能高效运作。暴露在外部环境、冷却不足、电力供应、缺乏互联网连接和物理安全性等因素都在这里发挥作用(还有更多)。这些因素可能会极大地影响你的团队是否能够利用现有的现货硬件平台,或者是否需要设计并构建一个定制平台。无论如何,全球有许多供应商可以提供帮助,但最终决定权在于你和你的团队。让我们来看一下你必须考虑的因素。

电力

电力消耗与冷却要求直接相关,另一个至关重要的计算和要求就是你的解决方案的电力消耗。电力消耗受到硬件平台电源的限制。根据容量的规模和解决方案中的组件,这些电力消耗可能会有很大差异。

另一个需要考虑的电力因素与部署的位置和方式有关。让我们回顾一些例子。

一般的 CPU 并不消耗太多电力。然而,如果你构建的解决方案中包含了一个或多个 GPU,那么就需要为额外的电力和更强的冷却能力做好规划。这可能需要额外的组件,如额外的风扇、液体冷却系统或额外的散热片。

运行过热的系统无法长时间保持高效工作。它们更容易随机崩溃,导致解决方案受到损害或造成负面的客户体验问题。热量是一个关键的环境因素。我们将在本章稍后再次讨论环境因素,并讨论一些供应商如何应对这些问题。

让我们继续讨论另一个影响因素。

离线/隔离网络

尽管对于嵌入式 Linux 系统设备来说,无法连接互联网是非常常见的,但这并不一定是坏事。被屏蔽在外部威胁之外可以被视为系统的一种积极特性。可悲的是,这种保护也有代价。通过基于网络的资源直接提供设备更新的简单方法变得不可行。

这些系统需要为其接口编写额外的代码,并采用其他方法来处理软件更新。这可以像在防火墙后面为设备创建一个 DNF 仓库来更新一样简单,也可以像通过加密的 tarball、ISO 镜像或二进制文件引入更新的接口一样复杂。

你必须充分了解你的目标市场,以便为这一需求做好规划。对于一些行业,例如政府,这是被视为必须遵循的基础标准。然而,也有例外,这就是为什么我们在本书中早些时候提到影响级别的原因。一些机构可能会允许那些非关键且不包含任何敏感数据的系统通过互联网更新。虽然这种情况确实存在,但不能假设这是标准做法。通常,标准会更加严格。

如果你的设备是某辆车的组成部分呢?我们假设这辆车本身没有互联网接入,并且它的更新仅在车主将车辆送到经销商进行维修时提供。听起来像是未来的事情吗?其实不然。今天这种情况已经是现实。对于一些最先进的车辆来说,也许它们可以在停放在你家外面时通过你的 Wi-Fi 连接自我更新。有些甚至有卫星连接。你能明白这会带来什么吗?但大多数情况下,这种更新是严格由制造商控制的。老实说,我认为他们更愿意通过经销商向你收费提供这些服务。

许多设备部署在那些无法连接到蜂窝网络、Wi-Fi 或局域网的地方。因此,了解你的目标用户并规划如何最好地为他们服务至关重要。

我们将在接下来的章节中进一步讨论这个话题,并通过实际练习深入探讨(你也可以通过本书的 GitHub 仓库访问相关资源)。

我本可以继续讲述离线系统的事情。我猜你现在在想,请不要继续!。所以暂时让我们继续讨论下一个我们需要规划的重要因素。

气候控制

你的解决方案将部署在哪里?这是另一个关键的信息点。为什么?请做好准备,因为它真的很重要。如果你的目标用户在沙漠环境下工作,比如说,那么普通的现成硬件将无法满足需求。你需要能够在那种环境中生存并茁壮成长的硬件。这样的例子还会带来其他系统设计的考量。这个系统会暴露在阳光下并面临天气元素的侵蚀吗?

希望你能理解我想表达的意思。如果你还不明白,我们来看另一个示例情境。假设你的设备面向农业行业,并且安装在为广阔农田服务的巨大拖拉机上。在这种情况下,你的解决方案能否承受温度、湿度和天气的巨大变化?

现在,让我们考虑一个极端的例子,这种情况已经存在了几十年。如果你的解决方案是某个在外太空中运行的设备的组成部分,比如卫星或深空探测器呢?你的解决方案是否能承受辐射、极端的高温和低温情况,以及最重要的是,是否能抵御每小时时速达到 10 万公里的太空尘埃或碎片?

如果没有做好充分的规划,环境条件很容易会影响你的解决方案。然而,如果机器不在受保护的地方,还有一个额外的安全层级需要考虑:设备的物理安全。很少有平台内建防篡改功能,因此,如果你的解决方案可能位于户外或暴露在人群中,这一点也需要考虑。也许你需要确保解决方案有一个带锁的外壳或其他保护措施。

保护你的解决方案免受目标环境的影响。保护你的解决方案免受未经授权的访问。保护你的解决方案免受最终用户的影响。是的,我说的没错——保护你的设备免受最终用户的影响。你的解决方案可能部署的整体环境决定了我们下一个设计因素。结合你至今收集到的所有信息,让我们继续选择使用现成硬件还是定制硬件。

现成硬件与定制硬件

是的,我把这一部分留到了最后,因为之前的所有内容都引出了这一点。在这里,我真心希望你一直在关注那些可能影响你最终解决方案设计的各种情况。

在我为这本书进行深入研究的过程中,我联系了几家对嵌入式 Linux 系统市场有影响的硬件供应商,无论是在北美还是全球。我震惊地发现,几家公司不再提供完全定制的解决方案,只提供定制的外框和外壳,因此我觉得有必要在这里提到这一点。

一些较小的或国外的商店会根据规格为你定制系统,但你需要知道,选择这种服务,你将需要支付额外的费用。我谦虚地承认,根据你的解决方案的需求,这可能是你唯一的选择。

一些全球供应商,如戴尔、HPE 和联想,乐于创建他们已经生产的硬件的重新品牌版本。然而,至少在美国,很少有供应商会从主板开始为你定制系统。那些愿意从主板开始创建完整定制构建的供应商,除非你订单的系统数量达到天文数字,否则价格通常不会便宜。

由于定制化成本非常高,因此利用大厂商现有的外形因子/构建确实有其优势。首先,你知道交付给你的系统是有支持的,具备一定的质量,并且可以轻松复制。更大的优势在于,通过这种方式你可以获得符合你环境需求和外形因子要求的系统。

在本节中,我们将介绍几家全球公司,它们生产出色的系统,可以作为嵌入式 Linux 系统的基础平台。我在本职工作中得到了极好的机会与这两家公司(以及其他几家公司)进行接触,但我需要声明,全球范围内还有更多这样的公司。这两家公司都有许多优秀的产品和服务,可以帮助你的团队创建最终的安全嵌入式 Linux 系统。

戴尔

那么,戴尔到底是谁,他们在嵌入式 Linux 系统领域做了什么呢?作为全球最大的 OEM 技术解决方案制造商之一,戴尔拥有先进的能力和服务,可以定制帮助其嵌入式合作伙伴在物流、构建和提供关键解决方案生命周期服务。换句话说,他们可以帮助你构建、设计,并为你的团队承担所有的重担。这意味着,一旦你确定了设计规格,戴尔的服务可以进行构建、发货给客户,甚至提供最终客户的更新和支持。你可以通过 www.dell.com 或在 YouTube 上通过 www.youtube.com/channel/UC01FW5V9UVohbPtqKSmXX-w 了解更多信息。

戴尔生产广泛的服务器和工作站产品。戴尔另一个著名的特点是,它是全球首批将 Linux 预装在其系统上的主要 OEM 供应商之一。

OnLogic™

那么,OnLogic™ 是谁?他们在嵌入式 Linux 系统领域做什么?正如官方网站上所述 (www.OnLogic.com/company/press/cl250/),“OnLogic™ 是一家全球性的工业计算机制造商,设计高度可配置、以解决方案为导向的计算机,专为物联网边缘可靠性而工程打造。它们的系统可在世界上最恶劣的环境中运行,帮助客户解决他们最复杂的计算挑战,无论所属行业如何。公司成立于 2003 年,拥有美国、荷兰、台湾和马来西亚的办事处。OnLogic™ 帮助了全球超过 70,000 名客户推进他们的创意,提供经久耐用、按需定制、并且在几天内交付的计算机。 了解更多请访问 www.OnLogic™.com 或在 YouTube 上访问 www.youtube.com/OnLogic™。”

OnLogic 提供多种可定制的系统,适用于创建解决方案的用户,涵盖从非常小的基于 ARM™ 的系统,到一系列坚固的 PC,再到坚固的模块化小型工业服务器。这些系统针对各种环境条件而设计,能够在极端气候和情境中进行操作,承受普通系统无法承受的挑战。

让我们考虑一个 OnLogic 系统在工业环境中的应用示例。下图展示了一台基于 ARM 的 OnLogic Factor 201™ 系统,安装在电气柜中,作为 可编程逻辑控制器 (PLC) 控制工厂环境中的机器功能:

图 3.1 – OnLogic Factor 201

关于 OnLogic Factor 201 系统解决方案的更多信息,请访问之前提供的 OnLogic Factor 201 系统网站链接。

现在我们已经回顾了一些 COTS 系统的示例,如果你认为它们无法满足你的需求,那么是时候考虑从头开始定制构建。这是一项艰巨的任务,我没有任何深刻的建议。

目前有哪些主流的 CPU/硬件平台可用?

现在,让我们快速了解一些最常见的平台(以及一些不那么常见的平台),这些平台通常被用于构建嵌入式 Linux 系统的公司。每个平台都有其独特的性能特征和成本。以下平台是我过去十年与合作伙伴一起使用过的。一些平台比其他平台更为流行。让我们深入了解。

Xeon™

英特尔 Xeon™ 处理器系列自 1998 年推出以来,一直是高性能服务器和工作站解决方案的旗舰。这些处理器通常用于 AI、HPC、数据库和分析,以及关键应用工作负载。

有关如何为你的解决方案选择合适的 Xeon 处理器的更多信息,请访问英特尔® 官网 www.intel.com/content/www/us/en/products/docs/processors/xeon/server-processor-overview.html

Core™

英特尔® Core™ 系列处理器涵盖了从物联网设备到笔记本电脑,再到高端游戏 PC(i3、i5、i7 和 i9)等各种设备。这个处理器家族能够轻松应对从边缘计算到商业应用,再到高端游戏的所有需求。

有关如何为你的解决方案选择合适的 Core 处理器的更多信息,请访问英特尔官网 www.intel.com/content/www/us/en/products/details/processors/core.html

Atom™

英特尔® Atom™ 系列处理器提供低功耗的 x64 平台,专为家电和物联网设备设计。你甚至可能认为这些处理器是为大多数网络设备、边缘设备,尤其是嵌入式 Linux 系统解决方案的多样化环境需求量身定做的。别让它们轻巧的体积和较低的功耗欺骗了你——这些处理器在处理能力方面表现不凡。要了解更多关于 Atom 处理器的信息,请访问英特尔官网 www.intel.com/content/www/us/en/products/details/processors/atom.html

Ryzen™

AMD® Ryzen™ 系列处理器具有内建的 AI 能力和 Radeon GPU 功能。它使这些芯片组不仅能够满足游戏 PC 市场的需求,还能在小型化设计中处理 AI 工作负载。AMD 还承诺将继续支持这一系列处理器所使用的插槽技术多年。如果你希望为你的解决方案做好未来兼容性准备,或者希望简单地更换 CPU 本身,这无疑是一个非常酷的特点。要了解更多关于 Ryzen™ 系列处理器的信息,请访问 AMD 官网 www.amd.com/en/products/processors/business-systems/ryzen-ai.html

高级精简指令集计算机(ARM™)

ARM® 不仅仅是一个平台——它是一种授权架构,因此许多制造商将这一架构的定制变体集成到他们的系统中。近年来,NVIDIA 曾尝试收购拥有这一架构权利和专利的公司。虽然这一计划未能如愿以偿,但现在 NVIDIA 因为结合其行业领先的 GPU 技术,推出最先进的基于 ARM 的解决方案而闻名,而这些解决方案正在快速占领日益增长的 AI/ML 战场。

ARM 作为平台的使用案例数量与其在性能方面的可扩展性一样广泛。从手机到物联网设备,再到搭载多个 GPU 驱动的 ARM 大规模数据中心集群,这一切都能跨越并适用于不同领域。这些都需要其制造商向 ARM 公司支付许可费用。如果你有兴趣了解更多关于这一切是如何运作的,建议访问他们的网站:www.arm.com/

随着众多公司推出自己版本的架构,Linux 社区在尝试支持整个平台时遇到了一些障碍。许多问题将在下一章中深入讨论。如果你想提前了解一些即将讨论的内容,我可以简要概述一下:UEFI BIOS 兼容性、驱动程序问题以及常见工具是支持这个平台时遇到的主要难题。

无论是感知到的问题还是实际情况,某些 Linux 发行版在这个领域蓬勃发展,而其他一些则在努力跟上进度,仅能支持 ARM 平台架构的有限实现。这一平台以及接下来要讨论的平台,确实是值得密切关注的领域。接下来我们继续。

RISC-V®

RISC-V® 是一种新的国际开放标准架构,提供了一个框架,任何人都可以基于此构建解决方案。其许可模式类似于开源软件模式。我认为这是一次颠覆性的变革。在写这篇文章时,关于这一新兴平台的支持几乎没有,但在未来一年左右,我猜测 RISC-V 可能会给 ARM 带来强有力的竞争,甚至在市场上超过 ARM。最近,我开始在我的家庭实验室中尝试这个平台。许多 Linux 发行版正急于为这一改变游戏规则的平台添加支持。你应该密切关注它。非常,非常密切。

欲了解更多关于这一开放架构的信息,请访问 RISC-V 官网:riscv.org/

Power® 和 IBM Z®

这两款 IBM® 平台通常以其巨大的规模和弹性而闻名。IBM Z® 是一款主机平台,已经投入生产的时间比我能想象的还要久,而且它在 Linux 世界中仍然强劲运行。IBM® Power® 系统虽然问世的时间不如 Z 系列长,但它也提供了某种特定的环境,这在一些行业领域中仍然存在。

这些系统是弹性和持续运行的支柱。它们是承受损害后依然能够继续前行的基石。也就是说,它们通常不是嵌入式 Linux 系统设备的首选平台。它们体积庞大,需要一套在 IT 行业中已不再普及的特殊技能。

这就是我多年经验发挥作用的地方。在过去十年里,我看到过几个例子,这些平台作为设备解决方案交付。是的,我说的就是它们。这些庞然大物作为设备交付给最终客户。这些稀有的解决方案通常专注于为需要此类高级服务的最终客户提供高级存储和灾难恢复解决方案,这些客户觉得在今天以 X86 为主的世界中,这些服务过于复杂。

如今,设计、构建和支持这些解决方案被认为是一项巨大的努力。随着时间的推移,掌握这些平台所需的技能变得越来越稀有。有关 Power 平台的更多信息,请访问 IBM 网站:www.ibm.com/power。此外,关于 Z 系列平台的更多信息,请访问 IBM 网站:www.ibm.com/z。这些系统非常有韧性,但需要进行深度投资。

到此为止,我们已经结束了这一章。那么,接下来让我们总结一下我们学到的内容。

总结

在本章中,我们涵盖了众多的选择标准。本章中回顾的所有数据将直接影响我们在下一章选择的操作系统。它们是相互依赖的。你为解决方案选择的硬件将限制能够正确支持你的硬件和需求的 Linux 发行版的选择。

这里没有简单按钮,你不能按一下就得到答案。你决定的平台将与可用的 Linux 发行版选择深度相关。这可能不是坏事,因为有很多 Linux 发行版可以选择。任何有助于推动选择的帮助都可能是有用的。在本章中,你了解了许多复杂的硬件因素如何影响你系统的支持性、限制安全性配置,或者变得如此复杂,以至于你可能需要雇佣更多专门人员来处理该平台。

我在这里能给出的最重要建议是,做足功课,并且在选择过程中不要限制自己。拥有更多的选择是好事。我祝你在这项工作中好运。

在下一章中,我们将把这里所回顾的所有内容应用到不同的选择标准上,以便你为公司的解决方案选择最合适的 Linux 发行版。

第四章:应用设计需求标准——操作系统

在上一章中,我们深入探讨了选择硬件平台标准时需要考虑的许多因素。在前面的章节中,我们也回顾了其他需要考虑的因素。每一章的内容都在为此做铺垫,所有内容最终都与解决方案的安全性紧密相连——有些是直接的,有些是间接的。

在本章中,我们希望能为你介绍你团队在选择适合你设备的 Linux 操作系统时需要考虑的所有因素。本章结束时,你将准备好最终确定设计标准,并真正开始构建你的初步原型。

自 1990 年代末以来,我一定尝试了无数种 Linux 发行版。在最早的日子里,新的发行版层出不穷。早在高速互联网普及之前,我们必须购买包含新发行版 CD-ROM 的每月 Linux 杂志。我这些年来一定买过数百本这样的杂志。遗憾的是,只有少数 Linux 发行版经受住了时间和流行度的考验。多年来,毫无疑问地说,我一直是并且依然是一个真正的 Linux 爱好者。

在本章中,我们将涵盖以下内容:

  • 将操作系统与基础硬件平台匹配

  • 驱动程序支持、厂商支持和稳定性

  • 企业版与社区版 Linux 发行版

  • 操作系统的生命周期与你的解决方案

  • 硬性成本与软性成本

让我们开始吧。

将操作系统与基础硬件平台匹配

精心挑选最适合你的硬件平台的 Linux 发行版,可以比作为你的美味大餐搭配一款上等的美酒。我希望在这里的结果是,你的团队能够考虑所有相关因素,并结合你们自己的研究成果,最终达成一个普遍的设计共识。

如果你打算利用 Intel 或 AMD x86_64-类型处理器,那么这个选择过程可能会相当繁琐,因为几乎所有现有的 Linux 发行版的主要平台都是这种类型。自从 Linux 诞生之初,它作为 x86 平台便宜的替代品,取代了运行昂贵且专有的 Unix 发行版的大型 RISC 系统。从 2024 年开始,至少有一百个面向x86_64平台的 Linux 发行版。大多数是主流发行版的冷门分支。我敢说,几乎可以肯定地认为,有一款发行版能满足任何人的需求。

当你决定在非 x86_64 平台上构建时,选择的范围会被缩小。选择 Power、System z、Arm 或 RISC-V 作为平台,可能会使可选的发行版减少到不到几个。有人可能认为这是一种限制,而其他人则可能欢迎不必在实验室中研究或试验许多发行版的实现。

例如,在我自己的家庭实验室中,我维护超过 20 个系统,全部由我自己支付(而不是我的雇主)。虽然它们维护起来很昂贵,但对我来说能够满足多平台和操作系统测试的需求至关重要。这也使我有自由根据需要构建我想要的东西,使用我认为适合任务的任何工具。我建立,测试,拆除,重复这个过程,根据需要更改操作系统或硬件平台本身。

理解如何将所选硬件与安全操作系统配对所考虑的因素可以与美食餐厅中的大厨如何将优质葡萄酒与他们的烹饪佳肴搭配相比较。本章的接下来几节将做到这一点。我们现在要进入我们的建筑厨房,所以让我们继续并开始做饭。

IBM Power

IBM® Power® 系列服务器具有相当可扩展性和优质硬件。这些系统在将物理硬件划分为部分并将其专门分配给个别操作系统方面与主机非常相似。在 Power 系列中,这种功能被称为LPAR逻辑分区)。

该平台在嵌入式 Linux 系统空间中越来越稀少。

该平台被认为是今天使用它的人的一种利基市场。请注意,您的操作系统选择在很大程度上受到付费发行版的限制。Red Hat® Enterprise Linux®,SUSE Linux Enterprise Server™和 Ubuntu®似乎是今天可用的选择。

让我们继续到下一个平台。

IBM System z

IBM Z® 系列(又名 System z)主机显然是任何现存的嵌入式 Linux 系统设备可能拥有的最昂贵的硬件平台,也是我认为在今天这种设备中最稀有的平台的最佳示例。

此外,该平台在物理尺寸上是最大的,并且在我的专业观点中,可能是最难找到人员资源的。如果您绝对不需要像主机提供的大量基于硬件的冗余性等好处,我绝对会说这不是适合您的平台。话虽如此,我也怀疑,到目前为止,是否有比 Z 系列主机更具容错性和弹性的硬件平台。

然而,在当今背景下,我必须使用宠物与牲畜的伟大类比,这基本上是云技术的服务模式——使用大量廉价的可替换机器集群(即牲畜),而不是单一昂贵的单体机器。由于互联网上有无数关于这一点的引用,我会让你自己对这种方法论做出评判。

最终,我必须承认,Z 系列机器是韧性和可靠性的典范。可惜,仅仅是它们的尺寸和成本就让它们失去了 99.99% 嵌入式 Linux 系统市场的机会。Z 系列机器简直就是最昂贵的“宠物”。

这里的选择很有限。就像 Power 平台一样,Z 系列,你只能选择像 IBM LinuxOne、zLinux 和 Red Hat Enterprise Linux 这样的付费发行版。这些似乎是目前市场上对于这些非常规嵌入式 Linux 平台的有限选择。

让我们继续讨论另一个平台。

RISC-V

在物联网领域,最新的“亮点”是 RISC-V® 系统。我最近刚刚购买了我的第一台尖端系统。目前,在选择这个平台时,你的选择不仅有限,而且在系统本身上获得它们也变得更加困难。记住,这个平台正在快速发展,每天都在增长。尽管如此,我个人对这个新兴平台充满了期待。

由于我使用的测试设备没有 UEFI BIOS,安装任何操作系统都相当麻烦。

这是我从亚马逊上获得的样品 RISC-V IoT 开发板的照片。

图 4.1 – 亚马逊上可购买的初始通用 RISC-V 开发板

图 4.1 – 亚马逊上可购买的初始通用 RISC-V 开发板

我最近才开始使用这款新硬件,因此在撰写时,这个平台的支持还相当有限。正是社区发行版在这一领域大放异彩,它们处在硬件支持的最前沿。到目前为止,我发现的支持有 Debian、Ubuntu 和 Fedora® 的兼容性。

在这里,Ubuntu 似乎是领先的发行版,而 Fedora 也在迅速赶上。不过,我期待有一天,付费的企业级操作系统能够将这个新平台纳入它们的支持范围。

我们未来肯定会更多地讨论这个平台。目前,咱们先转到可能是整个嵌入式 Linux 系统领域中最重要的一个平台。让我们来看看高级精简指令集机器ARM)架构。

ARM

在过去的几年里,ARM® 架构在嵌入式 Linux 系统的生态系统中得到了广泛应用。如前一章所述,ARM 是由 Arm 公司授权的架构,或者可以说是一个蓝图。硬件制造商可以选择将哪些芯片放置到他们的定制板上。此外,还有许多预先构建的、极其廉价的 ARM 系统,例如树莓派类型的开发板。

在这个生态系统中,最接近 Linux 世界最新动态的 Linux 发行版往往拥有最大的采用率。换句话说,社区发行版(其中大部分最新的开发工作都在测试)可能与最新的硬件板具有最深的兼容性。像 Raspberry Pi OS、Ubuntu 和 Fedora 这样的发行版在这一领域是关键角色。其他开源项目,如 Yocto(www.nvidia.com/en-us/data-center/),也为 Linux 用户提供了极好的构建和部署工具。

社区与企业之间的差距正在迅速缩小。随着全球范围内物联网设备的爆炸性增长,企业市场被迫加入其中,否则将被甩在后头。Wind River Linux 在这方面似乎处于领先地位,特别是在工业 ARM 系统方面。Ubuntu Pro 服务器、SUSE Linux Enterprise Server 和 Red Hat Enterprise Linux 在努力争取自己在 ARM 生态系统中的份额方面也毫不落后。

边缘计算和物联网市场并不是企业发行版希望占领的唯一市场。随着 NVIDIA 将 ARM 平台带入数据中心,推出其全新的超级 AI 处理系统,这些系统将大核心 ARM 处理器与 GPU 芯片相结合,NVIDIA Grace Hopper 系统将会改变全球计算机和操作系统的格局。

各种形式的 ARM 支持正在迅速提升。我要归功于 NVIDIA 将它们带入数据中心并推动了更大的平台认知。ARM 绝对是一个值得考虑的平台。我们继续讨论。

驱动程序支持、供应商支持与稳定性

在我们讨论 Linux 生态系统中所有可用的硬件平台时,我认为有必要提醒你和你的团队,确保你们考虑的任何 Linux 发行版也能满足你们产品的需求(以及你们客户的期望)。

我是什么意思呢?基本上,我建议你和你的团队在确定最终选择之前,评估不止一个操作系统。确保硬件在候选操作系统上以预期的速度运行。记录指标。记录软件包版本。对原型进行压力测试。这个过程保证了,当你比较和对比候选操作系统时,你的团队能够做出最好的选择。

并非所有的发行版都基于相同的内核版本,这直接影响到可能包含的驱动程序(或在某些情况下,从发行版中废弃的驱动程序)。此外,根据你计划使用的硬件,你可能还需要第三方驱动程序,而这些驱动程序并未包含在你的发行版中。这些驱动程序是否与发行版的内核和库兼容?

此外,每个发行版都配备了不同的一组核心软件包和一组扩展的可选软件包。您的发行版是否能够支持您的设备应用堆栈所需的正确软件包/版本组合?您是否需要寻找第三方库或应用程序来完成您的解决方案?

为什么我要让您和团队提出这些问题?让我来解释一下。很遗憾,这其实相当简单。大多数社区发行版并未充分测试软件包组合及其基础内核。有些社区发行版基本上就像一个厨房水槽,里面包含了开发者假设您可能想尝试的东西,但实际上,他们希望您能帮助他们测试稳定性和报告错误。

这正是我为何主张采用您所选择的企业 Linux 操作系统的原因。企业级发行版以稳定性、安全性、支持性和二进制兼容性为傲,因为这些正是商业对它们的需求。因此,让我们进入下一部分,深入探讨这一思路。

企业与社区 Linux 发行版的对比

在本节中,我们将讨论社区 Linux 发行版与企业 Linux 发行版的区别,或者说,正如我们许多 Linux 行业内的人所称之的,免费与收费。您所选择的发行版受前面章节中所讨论的多种因素的驱动。合规性、支持、生命周期以及您自身的需求都将在此过程中发挥作用。

选择标准的这一点不仅影响构建设备的成本,还能帮助您的产品更好地定位为更安全,因为企业发行版提供了安全功能、文档、培训机会、自动化工具以及最佳实践,以支持您的团队。

收费发行版往往具有较长的生命周期,这是客户群体所期望的。企业级 Linux 的平均支持生命周期为 10 年。这些发行版通常还会提供更长的支持期限(需额外付费)。这一点至关重要,因为它确保您的团队能够访问关键的安全修复,即使社区驱动的操作系统已经停止支持其发行版。

考虑选择企业发行版而非免费的社区版的一个重要原因是软件供应链的安全性。这是本书中我们将多次提到的话题。在 2024 年 3 月,发现了一个在与上游开发者最接近的发行版中存在的最高等级 CVE。CVE-2024-3094www.cve.org/CVERecord?id=CVE-2024-3094)是由于一个名为xz的软件包的供应链被破坏,GitHub 仓库被入侵,其中恶意代码被注入到软件包中。这段恶意代码随后通过在系统中创建后门来干扰 OpenSSH。

这个漏洞直接影响了数十万台运行社区版 Linux 操作系统的系统;然而,那些使用企业版 Linux 发行版的客户,如 Suse 或 Red Hat,并未受到影响,因为这些发行版的供应链被认为是高度安全且经过充分测试的。

既然我们在讨论社区版和企业版的差异,我认为有必要为你展示一个对比列表,列出两者的例子。实际上,有成百上千个小型社区发行版,但最有可能出现在嵌入式 Linux 系统设备中的大多数都列在这里。

这里列举了一些可以用于嵌入式设备的优秀免费社区发行版的例子:

  • Fedora

  • OpenSuse

  • AlmaLinux™

  • Rocky Linux™

  • Ubuntu

  • Debian

  • Arch Linux™

  • Slackware

  • Raspberry Pi® OS

这里列举了一些付费企业版发行版的例子,它们提供更高的安全性、更多的支持选项,并可能提供延长的生命周期选项:

  • Red Hat Enterprise Linux

  • Ubuntu Pro Server

  • Suse Enterprise Linux Server

  • Oracle Enterprise Linux

  • Wind River Linux™

现在我们已经列出了更多常见的免费/社区发行版,并与更稳定、更安全的企业版进行对比,我相信你已经看到了它们之间的真实区别。接下来,让我们看看它们如何经受住时间的考验。

操作系统生命周期与解决方案的关系

确保你所选的操作系统的支持时间窗口与基于其构建的硬件的支持时间窗口相匹配是至关重要的。

在现场更换设备的操作系统是一项痛苦的工作。一般来说,可以安全地假设你的支持团队无法直接访问任何已售出并正在客户现场使用的系统。除非你的产品作为远程管理服务提供给最终用户,否则嵌入式系统通常无法与母公司(即制造商)进行通信,除非这些系统被允许自动在线获取来自厂商的更新。

更换操作系统就像进行全新安装。通常,我们会尽量避免让最终用户看到这个过程,因为如果他们在过程中参与并且有权限访问,系统很容易被破坏,并且可能会给予最终用户一些原本不应获得的访问权限。这会让你的解决方案面临配置被篡改或破坏的风险,或者给未授权人员赋予访问权限。没错,这就是一个安全问题!

所以,明智地选择操作系统和硬件。计划好硬件和 Linux 发行版的支持窗口时间的充足缓冲区。如果这一点无法完全对齐,确保你有一个计划来管理未来的升级,既能保持解决方案的安全性,又能防止数据丢失。尽可能地将最终客户远离这个过程(在可行的情况下)。我想你明白我的意思。我们继续。

硬成本与软成本

这个讨论可能会给你的公司带来棘手的情况,但它是一个必须进行的讨论。这肯定会影响设计决策和未来的支持结构。最终,你为解决方案收取的费用必须合理高于设计、构建和支持它的成本。我强烈建议你和你的团队在项目设计阶段彻底制定所有成本模型。功能膨胀、培训成本、物流成本、技术债务、延误、研究和营销预算以及其他因素都在此深刻影响。简单来说,这与安全相关,因为如果没有提前规划所有成本,极有可能你将以固定预算运作,并且某些事情可能没有得到应有的关注,从而导致某些问题被忽视,进而成为安全漏洞。

成本模型在现代世界中主导一切。利润至关重要。找到最小化成本与提供最佳产品之间的平衡,是产品经理面临的持续挑战。你需要确定产品的适当平衡点。我恳请你不要在影响产品安全的因素上偷工减料。深入了解你的人工成本、硬件成本、软件成本,以及你研究所确定的产品价格在客户心中最合适的“甜点”将对你的决策产生重大影响。接下来,我们将讨论一些这些因素。

硬件成本

这些成本可能是最容易计算的,却是你项目中最大的开销。这些成本超出了你选择的平台。你可能需要建立一个全新的工具链来构建和支持你的设备。我鼓励你和你的团队确保计划足够的系统储备,保留这些系统用于测试和故障排除。

如前一章所述,定制硬件有额外的成本。这些成本不仅仅是金钱上的,还包括所需时间的增加。定制硬件需要更长的时间来设计和原型制作;此外,它通常还需要进行更多的测试。如果你打算使用企业级 Linux 发行版,提供该发行版的公司可能会要求你对硬件进行兼容性认证。如果没有考虑到这一点,可能会导致操作系统供应商无法提供对该硬件解决方案的支持。这可能会给你的公司带来实际或潜在的问题。

我理解任何组织在削减成本方面的驱动力至关重要,但我还是要鼓励你考虑并获得足够的资源,以便为未来的开发维护一组系统,并解决未来可能出现的终端客户问题。测试直接影响产品的质量,当然也包括产品的安全性。不要在测试上省钱。

让我们继续讨论其他成本。

软件成本

就像为硬件成本规划一样,为团队的软件需求进行规划同样重要。这不仅仅涉及产品本身的操作系统成本,还涵盖了设计、构建和支持电器解决方案的各个方面。所有软件都必须考虑在内——操作系统、应用程序、源代码控制系统、自动化系统、安全扫描系统、备份和恢复系统等。

与软件供应商的合作可以大大帮助减少成本。此外,为了合法地将他们的产品作为自己产品的一部分使用,这种合作可能是必要的。这些合作伙伴计划通常也需要支付会员费用,无论是项目费用、最低购买要求,还是维持软件或服务订阅的要求。

软件成本

软件成本是任何项目的渐进性死敌,因为它们往往很难核算或预测。硬成本指的是材料、硬件和软件,而软件成本通常与员工有关。更具体地说,这受到他们目前所拥有的技能和设计、构建并支持所需电器解决方案的技能差距的影响。

当你的设计团队进行电器原型设计时,这些需求可能并不明显。在设计/构建嵌入式 Linux 系统的团队与负责提供客户支持服务的团队之间,很可能会存在知识空白。这些空白必须通过培训和知识转移来填补。

如果不解决这些知识空白,可能会带来许多问题。假如你的设计团队不熟悉目标平台,或者更糟糕的是,连它选择的操作系统都不熟悉呢?这就会让最终的设计暴露出可能无数的漏洞,而这些漏洞在此情况下可能还没有被考虑到。此外,未能解决在推出最佳产品时所需的技能空缺,最终会导致技术债务,而技术债务本身也是一种安全风险。

最好通过培训来填补这些空白,或者在最坏的情况下,雇佣新的员工或顾问,他们可以帮助提升其他产品和支持团队的能力。不管这些知识空白存在于哪里(例如硬件、配置、操作系统或一般使用),如果不加以解决,就会成为一个安全挑战。

好吧,我已经把这个话题说得够多了。我相信它不会让你感到太痛苦。确实,我承认当我想要强调一个观点时,有时可能会显得过于戏剧化。但我们不能低估每个团队成员为设计桌上以及设计之外所带来的真正价值。不全力以赴会产生负面影响。让我们继续前进。

总结

目前为止我们所讨论的内容都是为这一刻做铺垫。在过去的四章中,我们涵盖了影响设计标准的众多因素,并在本章中将这些内容与 Linux 操作系统结合,这将成为你解决方案中应用程序的基础。

你从本章学到的知识是复杂的。市面上有许多优秀的 Linux 发行版和公司。它们的每个发行版,或者在某些情况下,它们的定制版本(这些是发行版的变种),都针对特定的硬件平台或最终用户使用场景。这些使用场景可以从定制的图形界面到工业控制管理,从人工智能驱动的分析到高级安全策略执行不等。

我们在本章中涵盖了许多内容,接下来我们来总结一下你需要记住的要点。你的硬件选择将完全决定你选择的 Linux 发行版的能力或限制。在浩瀚的 Linux 发行版宇宙中, 希望你现在能更好地理解免费社区发行版与稳定安全的付费企业版之间的差异。你还应该了解硬件和软件选择的生命周期如何赋能或限制你的解决方案。最后,你的团队还应该理解相对于你所做决策的整体成本模型。所有这些共同构成了你产品架构计划的基础。

现在,是时候将你学到的东西付诸实践了。我们将进入下一章,其中包含一些实践练习,帮助你搭建构建链、工具,并实施我们之前提到的一些技术,还有一些可能对你来说是新的内容。

第二部分:设计组件

在这一部分,我们将深入探讨与您的设备相关的安全活动,同时在实验室中进行高级 Linux 配置和安全技术的实践操作。

本部分包含以下章节:

  • 第五章构建链中的基本需求

  • 第六章磁盘加密

  • 第七章受信平台模块

  • 第八章启动、BIOS 和固件安全

  • 第九章基于镜像的部署

  • 第十章解决方案的儿童防护:保护免受最终用户及其环境的影响

第五章:我的构建链中的基本需求

安全从设计桌面开始。这是事实。然而,它在构建链中得到增强并焕发活力。正是在这里,我们将实施并验证我们的安全政策,测试、扫描我们的原型,利用我们手头所有的信息资源,确保我们的产品在看到第一个客户之前,尽可能地安全且稳健。

这里才是真正的“魔法”发生的地方(或者不幸的是,如果你选择忽视它,它就不会发生)。在前几章中,我们讨论了无数的设计因素,这些因素最终促成了你概念上的初步设计标准。从这里起,我们将开始动手操作,确保遵循嵌入式系统的最佳实践,并应用安全措施。

这里是你公司构建环境中可能出现的一个非详尽的示例。这些工具应该仅对直接参与该产品或支持生产发布的人员开放。从安全的仓库到扫描工具及其间的一切,这些关键工具将极大地助力你的产品生命周期的成功。

你将需要的众多工具是广泛的,包括(但不限于)以下内容:

  • 本地仓库

  • 源代码控制系统

  • 项目管理系统

  • 客户支持系统

  • 构建自动化系统

  • 合规性和安全扫描系统

  • 更新已部署设备的基础设施

  • 最重要的是,一套完整的测试系统

这是成功的构建链基础设施所需的系统和工具的视角:

图 5.1 – 安全构建和支持链中的示例系统

图 5.1 – 安全构建和支持链中的示例系统

拿上你喜欢的饮品,清空日程,准备好一些 USB 闪存驱动器,咱们去实验室吧。我邀请你与我一同踏上这段旅程,卷起袖子,开始敲击键盘。你准备好开始实践如何保护你的软件供应链了吗?

在接下来的章节中,我将阐述关键概念,并引导你完成一些详细的练习:

  • 软件供应链控制

  • 自动化和工具集成 – 简要概述

  • 安全扫描、测试和修复

  • 清单和配置跟踪

  • 更新控制机制

让我们开始吧。

技术要求

如果你想跟随本章的练习,你至少需要两台运行相同 Linux 发行版的机器(物理或虚拟)。在练习中,我会标明我使用了哪个发行版以及其他相关的配置信息。出于本书的目的,假设你和你的团队对任何一种源代码控制/管理解决方案有足够的经验。

本书本身有一个 GitHub 页面和仓库。许多练习和示例配置文件都可以在那里找到:

github.com/PacktPublishing/The-Embedded-Linux-Security-Handbook/tree/main/Chapter05/exercises

软件供应链控制

作为解决方案提供商,您有责任了解、跟踪并保持每个组成部分的记录。如果您的解决方案需要遵守政府或行业的合规性要求,那么如果这些记录没有维护,可能会产生严重后果。

在这种情况下,我再次推荐使用企业级 Linux 发行版。它们的软件源是安全的,从源代码到编译、打包,最终交付给您。它们有很好的记录——它们必须有!这些供应商可以为您的团队提供我们所说的软件物料清单SBOM)。这是一份完整的组件及其版本清单。此外,它也是一份声明,证明他们使用的是经过安全测试和验证的软件。

市场上有几种商业解决方案。像 Aqua、Synopsys® 和 Red Hat® 等公司(仅举几例)提供了一些出色的综合解决方案,用于保护软件管道的安全。团队可以考虑的可行选项有很多,接下来我们进入下一个部分——源代码控制。

源代码控制

知识产权,也就是使您的解决方案与众不同的那些特殊代码,应该受到保护。有时,几乎是任何代价都值得的。

有许多优秀的商业和开源解决方案。通常,这些解决方案与其他服务(如 bug 跟踪、敏捷项目管理、软件打包解决方案等)集成。无论您组织选择了哪种源代码控制系统,我建议确保采取所有可行的措施来最小化访问并确保平台安全。保护您公司的知识产权。接下来我们来看一看软件供应链的其他部分。

自动化和工具集成——简要概述

没有适当的自动化水平,任何 DevOps 环境都无法算完整。就像源代码控制一样,这方面有许多优秀的商业和开源解决方案。Red Hat Ansible®、SaltStack®、Puppet Enterprise®、Chef®、Ansible AWX® 和 Puppet Bolt® 是最常用的。

在构建链中,其他产品也可能包含大量自动化。例如,CloudBees 公司提供的平台。它们的 Jenkins 产品在全球 DevOps 环境中处于领先地位。这只是众多解决方案中的一个例子。

自动化是一个我可以滔滔不绝讲上好几个小时的话题。但这绝不是我在这一简短部分中想表达的重点。我想告诉你的是,正确实施自动化可以减轻许多人力操作时会犯错的繁琐和单调任务。风险缓解与效率,简单明了。

无论你的团队选择哪个工具(或多个工具)进行项目,我都建议你们像审查其他敏捷流程一样审查它们的使用效果和效率。这里没有错误的选择,唯一的错误是完全不在构建、测试和支持链条中使用任何自动化。不要只是找到一个工具,而是要找到最适合你们预算和团队技能,并能在项目的时间范围内轻松使用的工具。

我们肯定会在后续章节中深入探讨更多关于工具和集成的内容,接下来让我们继续前进。

安全扫描、测试和修复

通过使用自由开源软件FOSS),你的团队可以实现产品生命周期中的许多(如果不是全部的话)方面。是的,我确实是开源软件的倡导者,自上世纪 90 年代末以来一直如此,尤其是在 Linux 的世界里。原因很简单,那就是技能的可移植性。

几乎所有的 Linux 发行版都共享大约 90% 的相同命令和工具。它们不共享的那 10%,正是让这些发行版独特、可扩展或更安全的地方。为了讨论方便,我想专注于这 90% —— 常见的工具。

在 Linux 的命令提示符下(无论是哪个发行版),有一些基本的命令是我们都熟悉并依赖的。虽然确实存在一些差异,但我这里重点讨论的是最常用的工具。

我想提到的第一个命令行工具是Nmap。Nmap 有一个图形界面版本,叫做Zenmap(或者在旧版本中叫做nmap-fe)。它几乎可以在所有 Linux 发行版和平台上找到。为什么?因为它擅长找出哪些端口是开放的,甚至能进行所谓的操作系统指纹识别(即,识别主机使用的是哪种操作系统)。

那么,让我们快速看一下 Nmap 和 Zenmap 在实际操作中的表现,做一个简短的实操练习。

练习 – 执行网络端口扫描

在本次练习中,我们将对一些测试机器进行详细的网络端口扫描。我们将使用两个类似的工具。第一个工具是 Nmap,它是一个开源的命令行端口扫描工具。第二个工具是 Zenmap,它也是开源工具,但它有一个图形用户界面。

练习要求

在这个练习中,你需要访问启用了图形桌面的 Linux 主机以及一个定义好的目标主机(用于扫描)。在随附的截图中,我使用的是 Fedora®作为 Linux 发行版,但几乎任何发行版都可以。Nmap 应该可以从你的发行版自己的仓库中获取,但我们需要从 FlathubTM 下载 Zenmap。在 Fedora 上,如果你在 gnome-software 应用中启用了第三方仓库,这个仓库已经为你配置好了。

首先,你需要登录到主机并打开终端会话。我们通常假设它默认没有安装,因此在继续之前我们将进行安装。如果你已经安装了相关工具,可以跳过这一步。

然后,我们将安装 Flathub flatpak 仓库(如果它尚未安装):


$ flatpak remote-add --if-not-exists flathub \ 
https://dl.flathub.org/repo/flathub.flatpakrepo
[mstonge@bm03 ~]$

接下来,我们将在命令行确认 Flathub 仓库是否可用。

提示

请注意,即使在 gnome-software 中进行了配置,除非你亲自安装/启用它,否则它可能无法在命令行中使用。


$ flatpak remotes
Name    Options
fedora  system,oci
flathub system

现在我们将安装zenmap flatpak


$ sudo flatpak install zenmap
Looking for matches…
Found ref 'app/org.nmap.Zenmap/x86_64/stable' in remote 'flathub' (system).
Use this ref? [Y/n]: y
Required runtime for org.nmap.Zenmap/x86_64/stable (runtime/org.gnome.Platform/x86_64/45) found in remote flathub
Do you want to install it? [Y/n]: y
org.nmap.Zenmap permissions:
    ipc    network    x11    file access [1]
    [1] home
        ID                                  Branch          Op          
Remote           Download
 1\. [✓] org.gnome.Platform.Locale           45              i           
flathub           18.1 kB / 369.6 MB
 2\. [✓] org.gnome.Platform                  45              i           
flathub          242.7 MB / 378.4 MB
 3\. [✓] org.nmap.Zenmap                     stable          i           
flathub            7.0 MB / 8.6 MB
Installation complete.

接下来,我们将从操作系统的自身仓库安装 Nmap。


$ sudo dnf install -y nmap

我们将获得以下输出:


Last metadata expiration check: 0:00:27 ago on Tue 30 Apr 2024 
09:08:18 PM EDT.
Dependencies resolved.
========================================================================
 Package                Architecture             Version                 
           Repository                 Size
========================================================================
Installing:
 nmap                   x86_64                   3:7.95-1.fc40          
            updates                   5.8 M
Transaction Summary
========================================================================
Install  1 Package
Total download size: 5.8 M
Installed size: 25 M
Downloading Packages:
nmap-7.95-1.fc40.x86_64.rpm                                             
            299 kB/s | 5.8 MB     00:19
------------------------------------------------------------------------
--------------------------------------------
Total                                                                   
            297 kB/s | 5.8 MB     00:20
Fedora 40 - x86_64 - Updates                                            
            1.6 MB/s | 1.6 kB     00:00
Importing GPG key 0xA15B79CC:
 Userid     : "Fedora (40) <fedora-40-primary@fedoraproject.org>"
 Fingerprint: 115D F9AE F857 853E E844 5D0A 0727 707E A15B 79CC
 From       : /etc/pki/rpm-gpg/RPM-GPG-KEY-fedora-40-x86_64
Key imported successfully
Running transaction check
Transaction check succeeded.
Running transaction test
Transaction test succeeded.
Running transaction
  Preparing        :                                                   
                                         1/1
  Installing       : nmap-3:7.95-1.fc40.x86_64                         
                                         1/1
  Running scriptlet: nmap-3:7.95-1.fc40.x86_64                         
                                         1/1
Installed:
  nmap-3:7.95-1.fc40.x86_64
Complete!

这是我在网络中使用 Nmap 工具进行扫描的示例。

其实是我在对一个名为ks01的主机进行详细端口扫描。我们将看到的是开放端口和运行的服务。

图 5.2 – Nmap 端口扫描及结果

图 5.2 – Nmap 端口扫描及结果

在那个示例扫描中,我们可以看到 SSH 和 HTTP 都可以被外部主机访问。

首先,让我们看看我们的选项是什么(提示 – 其实有很多!)。


$ nmap --help

我们将获得以下输出:


Nmap 7.95 ( https://nmap.org )
Usage: nmap [Scan Type(s)] [Options] {target specification}
TARGET SPECIFICATION:
  Can pass hostnames, IP addresses, networks, etc.
  Ex: scanme.nmap.org, microsoft.com/24, 192.168.0.1; 10.0.0-255.1-254
  -iL <inputfilename>: Input from list of hosts/networks
  -iR <num hosts>: Choose random targets
  --exclude <host1[,host2][,host3],...>: Exclude hosts/networks
  --excludefile <exclude_file>: Exclude list from file
HOST DISCOVERY:
  -sL: List Scan - simply list targets to scan
  -sn: Ping Scan - disable port scan
  -Pn: Treat all hosts as online -- skip host discovery
  -PS/PA/PU/PY[portlist]: TCP SYN, TCP ACK, UDP or SCTP discovery to given ports
  -PE/PP/PM: ICMP echo, timestamp, and netmask request discovery probes
  -PO[protocol list]: IP Protocol Ping
  -n/-R: Never do DNS resolution/Always resolve [default: sometimes]
  --dns-servers <serv1[,serv2],...>: Specify custom DNS servers
  --system-dns: Use OS's DNS resolver
  --traceroute: Trace hop path to each host
SCAN TECHNIQUES:
  -sS/sT/sA/sW/sM: TCP SYN/Connect()/ACK/Window/Maimon scans
  -sU: UDP Scan
  -sN/sF/sX: TCP Null, FIN, and Xmas scans
  --scanflags <flags>: Customize TCP scan flags
  -sI <zombie host[:probeport]>: Idle scan
  -sY/sZ: SCTP INIT/COOKIE-ECHO scans
  -sO: IP protocol scan
  -b <FTP relay host>: FTP bounce scan
PORT SPECIFICATION AND SCAN ORDER:
  -p <port ranges>: Only scan specified ports
    Ex: -p22; -p1-65535; -p U:53,111,137,T:21-25,80,139,8080,S:9
  --exclude-ports <port ranges>: Exclude the specified ports from scanning
  -F: Fast mode - Scan fewer ports than the default scan
  -r: Scan ports sequentially - don't randomize
  --top-ports <number>: Scan <number> most common ports
  --port-ratio <ratio>: Scan ports more common than <ratio>
SERVICE/VERSION DETECTION:
  -sV: Probe open ports to determine service/version info
  --version-intensity <level>: Set from 0 (light) to 9 (try all probes)
  --version-light: Limit to most likely probes (intensity 2)
  --version-all: Try every single probe (intensity 9)
  --version-trace: Show detailed version scan activity (for debugging)
SCRIPT SCAN:
 -sC: equivalent to --script=default
  --script=<Lua scripts>: <Lua scripts> is a comma separated list of
           directories, script-files or script-categories
  --script-args=<n1=v1,[n2=v2,...]>: provide arguments to scripts
  --script-args-file=filename: provide NSE script args in a file
  --script-trace: Show all data sent and received
  --script-updatedb: Update the script database.
  --script-help=<Lua scripts>: Show help about scripts.
           <Lua scripts> is a comma-separated list of script-files or
           script-categories.
OS DETECTION:
  -O: Enable OS detection
  --osscan-limit: Limit OS detection to promising targets
  --osscan-guess: Guess OS more aggressively
TIMING AND PERFORMANCE:
  Options which take <time> are in seconds, or append 'ms' (milliseconds),
  's' (seconds), 'm' (minutes), or 'h' (hours) to the value (e.g. 30m).
  -T<0-5>: Set timing template (higher is faster)
  --min-hostgroup/max-hostgroup <size>: Parallel host scan group sizes
  --min-parallelism/max-parallelism <numprobes>: Probe parallelization
  --min-rtt-timeout/max-rtt-timeout/initial-rtt-timeout <time>: Specifies
      probe round trip time.
  --max-retries <tries>: Caps number of port scan probe retransmissions.
  --host-timeout <time>: Give up on target after this long
  --scan-delay/--max-scan-delay <time>: Adjust delay between probes
  --min-rate <number>: Send packets no slower than <number> per second
  --max-rate <number>: Send packets no faster than <number> per second
FIREWALL/IDS EVASION AND SPOOFING:
  -f; --mtu <val>: fragment packets (optionally w/given MTU)
  -D <decoy1,decoy2[,ME],...>: Cloak a scan with decoys
  -S <IP_Address>: Spoof source address
  -e <iface>: Use specified interface
  -g/--source-port <portnum>: Use given port number
  --proxies <url1,[url2],...>: Relay connections through HTTP/SOCKS4 proxies
  --data <hex string>: Append a custom payload to sent packets
  --data-string <string>: Append a custom ASCII string to sent packets
  --data-length <num>: Append random data to sent packets
  --ip-options <options>: Send packets with specified ip options
  --ttl <val>: Set IP time-to-live field
  --spoof-mac <mac address/prefix/vendor name>: Spoof your MAC address
  --badsum: Send packets with a bogus TCP/UDP/SCTP checksum
OUTPUT:
  -oN/-oX/-oS/-oG <file>: Output scan in normal, XML, s|<rIpt kIddi3,
     and Grepable format, respectively, to the given filename.
  -oA <basename>: Output in the three major formats at once
  -v: Increase verbosity level (use -vv or more for greater effect)
  -d: Increase debugging level (use -dd or more for greater effect)
  --reason: Display the reason a port is in a particular state
  --open: Only show open (or possibly open) ports
  --packet-trace: Show all packets sent and received
  --iflist: Print host interfaces and routes (for debugging)
  --append-output: Append to rather than clobber specified output files
  --resume <filename>: Resume an aborted scan
  --noninteractive: Disable runtime interactions via keyboard
  --stylesheet <path/URL>: XSL stylesheet to transform XML output to HTML
  --webxml: Reference stylesheet from Nmap.Org for more portable XML
  --no-stylesheet: Prevent associating of XSL stylesheet w/XML output
MISC:
  -6: Enable IPv6 scanning
  -A: Enable OS detection, version detection, script scanning, and traceroute
  --datadir <dirname>: Specify custom Nmap data file location
  --send-eth/--send-ip: Send using raw ethernet frames or IP packets
  --privileged: Assume that the user is fully privileged
  --unprivileged: Assume the user lacks raw socket privileges
  -V: Print version number
  -h: Print this help summary page.
EXAMPLES:
  nmap -v -A scanme.nmap.org
  nmap -v -sn 192.168.0.0/16 10.0.0.0/8
  nmap -v -iR 10000 -Pn -p 80
SEE THE MAN PAGE (https://nmap.org/book/man.html) FOR MORE OPTIONS AND EXAMPLES

现在,让我们对目标主机进行简单扫描。请将我的目标主机名称(ks01)替换为你的目标主机名称;否则,这个操作对你来说无法生效。这个第一个示例是快速端口扫描。


$ nmap -F ks01
Starting Nmap 7.95 ( https://nmap.org ) at 2024-04-30 21:41 EDT
Nmap scan report for ks01 (10.101.0.40)
Host is up (3.4s latency).
rDNS record for 10.101.0.40: ks01.local
Not shown: 68 filtered tcp ports (no-response), 30 filtered tcp ports (host-unreach)
PORT   STATE SERVICE
22/tcp open  ssh
80/tcp open  http
Nmap done: 1 IP address (1 host up) scanned in 28.40 seconds
$

现在,让我们对目标主机进行更复杂的扫描。同样,请将我的目标主机名称(ks01)替换为你的目标主机。在这个扫描中,我们将查找正在运行的服务的详细版本信息(如果已检测到)。


$ nmap -sV ks01
Starting Nmap 7.95 ( https://nmap.org ) at 2024-04-30 21:26 EDT
Nmap scan report for ks01 (10.101.0.40)
Host is up (0.021s latency).
rDNS record for 10.101.0.40: ks01.local
Not shown: 980 filtered tcp ports (no-response), 17 filtered tcp ports (host-unreach)
PORT     STATE SERVICE  VERSION
22/tcp   open  ssh      OpenSSH 8.7 (protocol 2.0)
80/tcp   open  http     Apache httpd 2.4.57 ((Red Hat Enterprise Linux))
9090/tcp open  ssl/http Cockpit web service 282 or later
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 95.55 seconds

接下来,我将展示这个 Nmap 工具不仅能扫描单个主机,还能一次扫描整个子网。此操作可能需要更长时间,执行的总时间会根据网络中目标的数量而有所不同。

警告

在没有提前与网络和系统运维团队协调的情况下,千万不要在工作中尝试这个——你可不想引发任何警报(或惹上麻烦)。


$ nmap 10.82.0.0/25
Starting Nmap 7.95 ( https://nmap.org ) at 2024-04-30 21:18 EDT
RTTVAR has grown to over 2.3 seconds, decreasing to 2.0
RTTVAR has grown to over 2.3 seconds, decreasing to 2.0
RTTVAR has grown to over 2.3 seconds, decreasing to 2.0
RTTVAR has grown to over 2.3 seconds, decreasing to 2.0
RTTVAR has grown to over 2.3 seconds, decreasing to 2.0
RTTVAR has grown to over 2.3 seconds, decreasing to 2.0
Nmap scan report for _gateway (10.82.0.1)
Host is up (0.0013s latency).
Not shown: 996 closed tcp ports (conn-refused)
PORT     STATE SERVICE
53/tcp   open  domain
80/tcp   open  http
443/tcp  open  https
1900/tcp open  upnp
Nmap scan report for 10.82.0.41
Host is up (0.93s latency).
Not shown: 856 filtered tcp ports (no-response), 141 filtered tcp ports (host-unreach)
PORT     STATE  SERVICE
22/tcp   open   ssh
80/tcp   open   http
9090/tcp closed zeus-admin
Nmap scan report for 10.82.0.42
Host is up (3.7s latency).
Not shown: 847 filtered tcp ports (no-response), 151 filtered tcp ports (host-unreach)
PORT   STATE SERVICE
22/tcp open  ssh
80/tcp open  http
Nmap scan report for bm03.local (10.82.0.52)
Host is up (0.00060s latency).
Not shown: 998 closed tcp ports (conn-refused)
PORT     STATE SERVICE
22/tcp   open  ssh
9090/tcp open  zeus-admin
Nmap done: 128 IP addresses (4 hosts up) scanned in 151.69 seconds

Nmap 能够执行多种类型的扫描,如果不小心,它也可能会有些侵入性。我建议你阅读相关文档,或许可以在线获取一些免费的 Nmap 备忘单。

现在我们简要介绍了命令行中的端口扫描,让我们继续使用稍微功能丰富一些的 GUI 工具:Zenmap。

这是我运行的一个 Zenmap 扫描示例,也针对与前一个练习和演示中相同的主机。请注意,输出格式比命令行工具 Nmap 更加优化,并且为用户提供了更多可扩展的细节选项。

图 5.3 – Zenmap 扫描

图 5.3 – Zenmap 扫描

这是我进行的另一个扫描示例。这次,当我获得结果后,我点击了界面中的Ports / Hosts标签。

图 5.4 – 另一个 Zenmap 扫描;聚焦于 Ports / Hosts 标签

图 5.4 – 另一个 Zenmap 扫描;聚焦于 Ports / Hosts 标签

我无法过分强调确保你扫描发布候选版本的漏洞,以验证开放端口/服务的重要性。我们将在后面的章节中讨论不同类型的扫描。

现在我们已经回顾了开源扫描,让我们继续讨论如何跟踪设备中的变化。

清单和配置跟踪

创建软件清单是了解如何维护系统安全的关键步骤。这最终是一个详细的软件包及其版本的列表,包含了你操作系统和应用堆栈中的所有包,以及任何额外的第三方包或组合依赖项。

了解每个发布版本包含什么,以及这些包的来源,并策划一个安全的包清单,将帮助你掌控解决方案的生命周期。

我并不是说这会很容易。它有可能会,但随着解决方案变得越来越复杂,这确实会变成一项艰苦的工作——尤其是当你的解决方案所使用的并非全部都是以相同格式提供时。

让我详细讲解一下。假设你的操作系统提供商将包以 RPM 格式提供,而你有一些依赖项是作为tarballs或者 flatpaks 下载的。那么,如果我们还运行一些容器化的微服务呢?跟踪这一切会变得非常复杂,实际上,几乎不可能完全跟踪。这就是为什么变更跟踪和 SBOM 变得如此重要的原因。所以,让我们看看如何在我们自己的设备中跟踪变化。

练习 – 跟踪你产品的变化

在本次练习中,我们将深入探讨如何将现有版本与下一个更新轮次中的变化(即增量)进行对比。了解哪些包是新的(这些增量再次出现)将明显突出你的团队需要提供给现有用户的更新包,这可以通过自定义仓库或其他方式提供。

练习要求

对于这个动手操作,你只需要访问一台 Linux 机器(物理机或虚拟机)。需要 root(或sudo)权限。我在我的 Fedora 40 机器上做这个示例,但你也可以在任何类似 RHEL 的发行版上跟着我一起操作。

首先,我们将创建一个脚本,使用你喜欢的编辑器。创建一个名为my-inventory-creator.sh的文件。确保设置文件权限,使其可执行。


#!/usr/bin/bash
#############################
#
# my-inventory-creator.sh
#
#############################
MYDATE=$(date +"%Y%m%d%H%M")
MYFILE1="my-software-sources_$MYDATE.txt"
MYFILE2="my-software-details_$MYDATE.txt"
# Notify user of the output filenames for this run
echo "Checking for RPMs and Flatpak sources"
echo "and what's installed..."
echo
echo "Your output files for this check are: "
echo "$MYFILE1"
echo "$MYFILE2"
# Determine software sources and output to file
dnf repolist | sort > "$MYFILE1"
flatpak remotes | sort >> "$MYFILE1"
# Determine the software & versions installed and output to file
rpm -qa | sort > "$MYFILE2"
flatpak list | sort >> "$MYFILE2"
echo "Completed."

现在让我们运行脚本,并注意输出的文件名(包括日期戳)。这些文件名对于你来说是唯一的。


$ bash ./my-inventory-creator.sh

我们将得到以下输出:


Checking for RPMs and Flatpak sources
and what's installed...
Your output files for this check are:
my-software-sources_202405011944.txt
my-software-details_202405011944.txt
Completed.

现在让我们查看这些输出文件。这些文件对于你的构建/系统也是唯一的。我们将从软件源文件开始。


$ cat my-software-sources_202405011944.txt
fedora-cisco-openh264          Fedora 40 openh264 (From Cisco) - x86_64
fedora                         Fedora 40 - x86_64
google-chrome                  google-chrome
repo id                        repo name
updates                        Fedora 40 - x86_64 - Updates
fedora  system,oci
flathub system

现在让我们来看一下软件详情文件(这将非常长)。此命令的输出很庞大,因此我提前提醒你——我为了节省空间不得不截取了它。


$  cat my-software-details_202405011944.txt
aajohan-comfortaa-fonts-3.105-0.3.20210729git2a87ac6.fc40.noarch
aardvark-dns-1.10.0-1.fc40.x86_64
abattis-cantarell-fonts-0.301-12.fc40.noarch
abattis-cantarell-vf-fonts-0.301-12.fc40.noarch
abrt-2.17.5-1.fc40.x86_64
abrt-addon-ccpp-2.17.5-1.fc40.x86_64
abrt-addon-kerneloops-2.17.5-1.fc40.x86_64
abrt-addon-pstoreoops-2.17.5-1.fc40.x86_64
abrt-addon-vmcore-2.17.5-1.fc40.x86_64
abrt-addon-xorg-2.17.5-1.fc40.x86_64
abrt-cli-2.17.5-1.fc40.x86_64
(((output truncated)))
Red Hat, Inc.   io.podman_desktop.PodmanDesktop 1.9.1   stable  flathub system
Zenmap  org.nmap.Zenmap 7.94    stable  flathub system
$

现在我们有了构建的完整软件和源清单。让我们快速搜索一个特定的包。以我的例子为例,我使用的是httpd,但你可以练习搜索任何你喜欢的包或版本。


$ grep httpd my-software-details_202405011944.txt
fedora-logos-httpd-38.1.0-5.fc40.noarch
httpd-2.4.59-2.fc40.x86_64
httpd-core-2.4.59-2.fc40.x86_64
httpd-filesystem-2.4.59-2.fc40.noarch
httpd-tools-2.4.59-2.fc40.x86_64
[mstonge@bm03 ~]$

现在让我们安装一个会带来一些依赖项的包。我将安装一个名为kdiff3的包,它属于“diff”工具的大家族,这些工具用于找出文件或命令行输出之间的差异。同样,此命令的输出非常长,因此我再次对其进行了截取。


$ sudo dnf install -y kdiff3
Last metadata expiration check: 0:57:55 ago on Wed 01 May 2024 07:06:13 PM EDT.
Dependencies resolved.
========================================================================================================
 Package                         Architecture Version                               Repository     Size
========================================================================================================
Installing:
 kdiff3                          x86_64       1.10.7-3.fc40                         fedora        1.9 M
Installing dependencies:
 SDL_image                       x86_64       1.2.12-37.fc40                        fedora         45 k
 aspell                          x86_64       12:0.60.8-14.fc40                     fedora        713 k
 breeze-icon-theme               noarch       6.1.0-1.fc40                          updates       9.7 M
 daala-libs                      x86_64       0-27.20200724git694d4ce.fc40          fedora        211 k
 dbusmenu-qt5                    x86_64       0.9.3-0.34.20160218.fc40              fedora         79 k
 docbook-dtds                    noarch       1.0-85.fc40                           fedora        335 k
 docbook-style-xsl               noarch       1.79.2-22.fc40                        fedora        1.5 M
 hspell                          x86_64       1.4-21.fc40                           fedora        684 k
 kde-settings                    noarch       40.0-1.fc40                           fedora         40 k
 kdsoap                          x86_64       2.2.0-4.fc40                          fedora        133 k
 kf5-kactivities                 x86_64       5.115.0-1.fc40                        fedora        137 k
 kf5-kactivities-stats           x86_64       5.115.0-1.fc40                        fedora        111 k
((( output truncated )))
Installed:
  SDL_image-1.2.12-37.fc40.x86_64                        aspell-12:0.60.8-14.fc40.x86_64
  aspell-en-50:2020.12.07-10.fc40.x86_64                 breeze-icon-theme-6.1.0-1.fc40.noarch
  daala-libs-0-27.20200724git694d4ce.fc40.x86_64         dbusmenu-qt5-0.9.3-0.34.20160218.fc40.x86_64
  docbook-dtds-1.0-85.fc40.noarch                        docbook-style-xsl-1.79.2-22.fc40.noarch
  hspell-1.4-21.fc40.x86_64                              kde-settings-40.0-1.fc40.noarch
  kdiff3-1.10.7-3.fc40.x86_64                            kdsoap-2.2.0-4.fc40.x86_64
  kf5-kactivities-5.115.0-1.fc40.x86_64                  kf5-kactivities-stats-5.115.0-1.fc40.x86_64
  kf5-karchive-5.115.0-1.fc40.x86_64                     kf5-kauth-5.115.0-1.fc40.x86_64
  kf5-kbookmarks-5.115.0-1.fc40.x86_64                   kf5-kcodecs-5.115.0-1.fc40.x86_64
(((output truncated)))
  speech-dispatcher-libs-0.11.5-5.fc40.x86_64            speexdsp-1.2.1-6.fc40.x86_64
  vlc-libs-1:3.0.20-12.fc40.x86_64                       vlc-plugin-pipewire-3-2.fc40.x86_64
  vlc-plugins-base-1:3.0.20-12.fc40.x86_64               voikko-fi-2.5-6.fc40.noarch
Complete!

在最后一步中,我们安装了一个包(但它带来了 113 个依赖项)。所以,让我们重新运行我们的清单脚本,并对实际发生的更改进行一些自我检查。

提示

注意这次运行中创建的新文件。


$ bash ./my-inventory-creator.sh
Checking for RPMs and Flatpak sources
and what's installed...

你这次检查的输出文件是:


my-software-sources_202405012008.txt
my-software-details_202405012008.txt
Completed.
$

现在让我们生成两个文件集之间的差异列表。


$ diff my-software-sources_202405011944.txt my-software-sources_202405012008.txt

重要提示

我们从中获取文件的源没有发生变化,但软件详情列表会有显著的变化。让我们进行并排比较。请注意,输出将会很大。


$ diff -y my-software-details_202405011944.txt my-software-details_202405012008.txt  | less
aajohan-comfortaa-fonts-3.105-0.3.20210729git2a87ac6.fc40.noa   aajohan-comfortaa-fonts-3.105-0.3.20210729git2a87ac6.fc40.noa
aardvark-dns-1.10.0-1.fc40.x86_64                               aardvark-dns-1.10.0-1.fc40.x86_64
abattis-cantarell-fonts-0.301-12.fc40.noarch                    abattis-cantarell-fonts-0.301-12.fc40.noarch
abattis-cantarell-vf-fonts-0.301-12.fc40.noarch                 abattis-cantarell-vf-fonts-0.301-12.fc40.noarch
abrt-2.17.5-1.fc40.x86_64                                       abrt-2.17.5-1.fc40.x86_64
abrt-addon-ccpp-2.17.5-1.fc40.x86_64                            abrt-addon-ccpp-2.17.5-1.fc40.x86_64
((( output truncated )))
brcmfmac-firmware-20240410-1.fc40.noarch                        brcmfmac-firmware-20240410-1.fc40.noarch
                                                              > breeze-icon-theme-6.1.0-1.fc40.noarch
brlapi-0.8.5-13.fc40.x86_64                                     brlapi-0.8.5-13.fc40.x86_64
((( output truncated )))

现在你可以看到使用此方法添加(或更改)的内容。在上面的例子中,共有 114 项更改(实际上是添加)。为了节省空间并避免让你感到无聊,我只截取了部分输出。

这是我喜欢利用一些图形用户界面工具的地方,像我刚刚安装的那个工具。让我们快速看看kdiff3

我们将选择之前步骤中的相同文件。

图 5.5 – 启动 kdiff3 比较操作

图 5.5 – 启动 kdiff3 比较操作

接下来,选择界面中的文件。A (Base) 是旧的软件详情文件。最后,选择B文件作为最新的文件。

图 5.6 – 选择文件

图 5.6 – 选择文件

现在我们已经定义了所有要比较的文件,我们点击OK

这个操作的输出将图形化显示两个列表之间的差异。

图 5.7 – 运行比较

图 5.7 – 运行比较

这些差异对你和你的团队来说是至关重要的知识。掌握这些知识后,你就知道哪些文件需要策划,以为客户提供合适的更新版本(假设你将这种比较作为发布候选审查过程的一部分)。这是完美的过渡到我们下一节,关于如何在产品中提供更新控制机制。

更新控制机制

多年来,我与嵌入式合作伙伴讨论过的最喜欢的话题之一就是如何创建一个合适的更新方法论,并建立支持该方法的流程和基础设施。最终,根据客户的操作环境、用例和合规性要求,我们已经知道这些机制是简单的在线形式,还是复杂的离线形式。

你在这里的选择将直接影响你产品的用户界面(UI)。打包你的软件和配置将简化生命周期管理和支持成本,同时改善最终用户体验。

对于接下来的这组练习,我们假设你的团队已经选择了将特定功能与使用 RPM 包和自定义仓库一起打包,在构建和支持链中使用。这是最简单的路径,但并非总是最可行的。

我们稍后将在书本的 GitHub 仓库中讨论其他更新控制机制(并在线提供)。这些机制可以是(但不限于)加密的 tar 包、ISO 镜像、U 盘、FTP 包等。每一个都需要在构建链中做额外的工作,并且在支持链中需要更多的关注,更不用说更多经过良好培训的支持人员了。

现在我们已经回顾了如何追踪和记录你设备中的变更,接下来让我们讨论保持对你的 SBOM(软件物料清单)控制的另一个关键方面——这次通过自定义打包。

练习 – 构建自定义软件包

希望你已经准备好开始输入了。我们将从这里开始构建。由于在自定义软件包中可以做的事情非常多,我将仅涵盖一些与嵌入式系统最佳实践相关的内容,那就是创建你自己的发布定义文件。

我分享的以下链接基本上是所有与 RPM 相关的事项的必备参考资料。我建议你在此花些时间:

rpm-packaging-guide.github.io/

练习要求

你需要访问一台 Linux 服务器。必须具有 root 或 sudo 权限。关于我的演示环境:我正在使用 Fedora 40 Workstation,并且创建了一个名为 mattbuild 的用户(你可以在开始本练习之前创建自己的构建环境用户),并且我已经将其添加到 sudoers 文件中。现在让我们设置你的 RPM 包构建环境。

首先,我们将安装打包工具(以及它们的众多依赖项)。


$ sudo dnf install -y fedora-packager fedora-review \
rpm-build rpm-devel rpmlint make python \
coreutils diffutils rpmdevtools
  ((( OUTPUT Truncated )))
Complete!

接下来,我们将修改用于构建软件包的用户账户,成为mock系统组的成员。


$ sudo usermod -a -G mock mattbuild

最后,我们将确认用户账户的更改。你可以使用newgrp命令,或者注销后重新登录以重置你的环境。完成其中任何一个操作后,验证组更改是否已生效。


$ newgrp
$ id
uid=1001(mattbuild) gid=1001(mattbuild) groups=1001(mattbuild),135(mock) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
[mattbuild@fedora  ~]$

现在让我们为该用户创建一个合适的 rpm 构建环境。运行rpmdev-setuptree命令将构建一个构建过程中所需的文件夹结构。


$ rpmdev-setuptree
$ tree rpmbuild/
rpmbuild/
├── BUILD
├── RPMS
├── SOURCES
├── SPECS
└── SRPMS
6 directories, 0 files

现在让我们为我们的项目创建一个.spec文件。我使用vivim,但你可以随意使用你喜欢的编辑器。如果你不想自己输入这个文件,我会将这个文件的副本放到 GitHub 仓库里。


$ vi myapprel.spec

现在,我们将编辑文件的内容。完成后,请确保保存文件。

重要提示

在此文件中,只能使用空格而不是制表符


(code - myapprel.spec)
Name:          myapprel
Version:       1.0
Release:       1
Summary:       Example custom app release file installer
License:       MIT License
%description
This will install a custom release text for your appliance
%prep
# we have no source code - so let's skip this
%build
cat > myappliance-release << EOF
Welcome to my secure embedded linux system
version 1.0
EOF
%install
mkdir -p %{buildroot}/etc
install -m 644 myappliance-release %{buildroot}/etc/myappliance-release
%files
/etc/
/etc/myappliance-release
%changelog
# nothing to report on the first attempt

现在让我们尝试第一次 rpm 构建。这个过程的输出会非常庞大(所以我不会列出全部内容)。


$ rpmbuild -ba myapprel.spec
warning: source_date_epoch_from_changelog set but %changelog is missing
Executing(%prep): /bin/sh -e /var/tmp/rpm-tmp.w4pHxJ
+ umask 022
+ cd /home/mattbuild/rpmbuild/BUILD
+ RPM_EC=0
++ jobs -p
+ exit 0
Executing(%build): /bin/sh -e /var/tmp/rpm-tmp.q2Jeer
+ umask 022
+ cd /home/mattbuild/rpmbuild/BUILD
+ CFLAGS='-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1  -m64   -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer '
+ export CFLAGS
(((output truncated)))

现在让我们进行一次测试安装。


$ cp ./rpmbuild/RPMS/x86_64/myapprel-1.0-1.x86_64.rpm ~/
[mattbuild@fedora  ~]$    total 12
-rw-r--r--. 1 mattbuild mattbuild 6861 Apr 20 16:37 myapprel-1.0-1.x86_64.rpm
-rw-r--r--. 1 mattbuild mattbuild  572 Apr 20 16:35 myapprel.spec
drwxr-xr-x. 8 mattbuild mattbuild   89 Apr 20 16:05 rpmbuild
[mattbuild@fedora  ~]$    sudo dnf install -y ./myapprel-1.0-1.x86_64.rpm
[sudo] password for mattbuild:
Last metadata expiration check: 0:08:09 ago on Sat 20 Apr 2024 04:31:26 PM EDT.
Dependencies resolved.
=======================================================================
 Package                     Architecture              Version         
           Repository                       Size
=======================================================================
Installing:
 myapprel                    x86_64                    1.0-1           
           @commandline                   6.7 k
Transaction Summary
=======================================================================
Install  1 Package
Total size: 6.7 k
Installed size: 55
Downloading Packages:
Running transaction check
Transaction check succeeded.
Running transaction test
Transaction test succeeded.
Running transaction
  Preparing        :                                                  
                                              1/1
  Installing       : myapprel-1.0-1.x86_64                            
                                              1/1
  Verifying        : myapprel-1.0-1.x86_64                            
                                              1/1
Installed:
  myapprel-1.0-1.x86_64
Complete!
$

好的!我们已经有了第一个自定义软件包和第一个自定义文件安装程序(而且它有效!)

让我们来展示一下它。


$ cat /etc/myappliance-release
Welcome to my secure embedded linux system
version 1.0

干得好!现在你正在通过创建自己的软件包来保护你的软件供应链。我真心希望你在这个练习中至少有一点乐趣。

练习 – 签署你的自定义 RPM 包

现在是时候为你增加额外的学分了。这不是一门入门课程,而是一个高级课程。是的,我们现在可以创建自定义的 RPM 包了,但本章的重点是保护你的软件供应链。是时候提升难度了,加入你自己的 GPG 签名到你的自定义包中吧!

首先,我们将退出构建账户并切换到 root 权限。


$ su -
#

我们现在将确保你已经安装了正确的软件,以签署你为设备构建的 RPM 包。安装rpm-sign包。


# dnf install rpm-sign
Last metadata expiration check: 1:37:57 ago on Sat 20 Apr 2024 04:31:26 PM EDT.
Dependencies resolved.
================================================================================
========================================
 Package                    Architecture             Version                    
        Repository                 Size
=================================================================================
=======================================
Installing:
 rpm-sign                   x86_64                   4.19.1.1-1.fc39             
       updates                    22 k
Transaction Summary
=================================================================================
=======================================
Install  1 Package
Total download size: 22 k
Installed size: 22 k
Is this ok [y/N]: n
Operation aborted.
[root@bm02 ~]# dnf install -y rpm-sign
Last metadata expiration check: 1:38:20 ago on Sat 20 Apr 2024 04:31:26 PM EDT.
Dependencies resolved.
=======================================================================
 Package                    Architecture             Version                     
       Repository                 Size
=======================================================================
Installing:
 rpm-sign                   x86_64                   4.19.1.1-1.fc39              
      updates                    22 k
Transaction Summary
=======================================================================
Install  1 Package
Total download size: 22 k
Installed size: 22 k
Downloading Packages:
rpm-sign-4.19.1.1-1.fc39.x86_64.rpm                                 

       49 kB/s |  22 kB     00:00
-------------------------------------------------------------------
---------------
--------------------------------------
Total                                                               
                     28 kB/s |  22 kB     00:00
Running transaction check
Transaction check succeeded.
Running transaction test
Transaction test succeeded.
Running transaction
  Preparing        :                                                
                                                                  1/1
  Installing       : rpm-sign-4.19.1.1-1.fc39.x86_64                 
                                               1/1
  Running scriptlet: rpm-sign-4.19.1.1-1.fc39.x86_64                 
                                         1/1
  Verifying        : rpm-sign-4.19.1.1-1.fc39.x86_64                 
                                              1/1
Installed:
  rpm-sign-4.19.1.1-1.fc39.x86_64
Complete!

在接下来的步骤中,你将生成自己的超级酷的安全gpg密钥。当你在生产环境中实际操作时,必须确保使用官方的名称、电子邮件地址等来为你的gpg密钥生成信息。

对于这个示例,我们将使用 John Doe 的名字,电子邮件地址为john_doe@gmail.com,密码短语为不太安全的Embedded。接下来的命令是交互式的,其中一些对话框实际上会展示我戏谑地称之为“屏幕呕吐”的内容,以吸引用户注意这些对话框。其他人可能会将其称为松散管理的文本用户界面TUI)。

重要提示

使用gpg --full-generate-key命令来启动一个完整功能的密钥生成对话框。


# gpg --gen-key
gpg (GnuPG) 2.4.4; Copyright (C) 2024 g10 Code GmbH
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
GnuPG needs to construct a user ID to identify your key.
Real name: John Doe
Email address: john_doe@gmail.com
You selected this USER-ID:
    "John Doe <john_doe@gmail.com>"
Change (N)ame, (E)mail, or (O)kay/(Q)uit?

接下来,以下对话框将会出现;你需要输入密码短语Embedded并选择<OK>继续。


Please enter the passphrase to protect your new key
 Passphrase: ________________________________________
       <OK>                              <Cancel>

系统很可能会因为你没有使用超级安全的密码短语而批评你,但这只是训练,所以请选择 <Take this one anyway> 继续。真该感谢这些交互式文本界面,它们确实避免了你需要学习一个超长的命令行。


Warning: You have entered an insecure passphrase.
A passphrase should contain at least 1 digit or special character.
 <Take this one anyway>             <Enter new passphrase>

我们离创建密钥已经不远了。我们必须确认密码短语 Embedded 才能继续。


 Please re-enter this passphrase
   Passphrase: ________________________________________
       <OK>                              <Cancel>

现在,让我们看看它如何工作。你的输出应该类似于这样(但每次密钥生成都是独特的,所以可能不完全一样)。


We need to generate a lot of random bytes. It is a good idea to perform some other action (type on the keyboard, move the mouse, utilize the disks) during the prime generation; this gives the random number generator a better chance to gain enough entropy.
We need to generate a lot of random bytes. It is a good idea to perform some other action (type on the keyboard, move the mouse, utilize the disks) during the prime generation; this gives the random number generator a better chance to gain enough entropy.
gpg: directory '/root/.gnupg/openpgp-revocs.d' created
gpg: revocation certificate stored as '/root/.gnupg/openpgp-revocs.d/417CAC67C4F673DEDC13C95CA01133131459C4AD.rev'
public and secret key created and signed.
pub   ed25519 2024-04-20 [SC] [expires: 2027-04-20]
      417CAC67C4F673DEDC13C95CA01133131459C4AD
uid                 Matt St. Onge <matt_st_onge@yahoo.com>
sub   cv25519 2024-04-20 [E] [expires: 2027-04-20]
[root@fedora  ~]#

现在,让我们来看看我们系统中目前所有的密钥。


# gpg --list-keys
gpg: checking the trustdb
gpg: marginals needed: 3  completes needed: 1  trust model: pgp
gpg: depth: 0  valid:   1  signed:   0  trust: 0-, 0q, 0n, 0m, 0f, 1u
gpg: next trustdb check due at 2027-04-20
[keyboxd]
---------
pub   ed25519 2024-04-20 [SC] [expires: 2027-04-20]
      417CAC67C4F673DEDC13C95CA01133131459C4AD
uid           [ultimate] John Doe <john_doe@gmail.com>
sub   cv25519 2024-04-20 [E] [expires: 2027-04-20]

你的密钥已经被导入。让我们查询 rpm 数据库,看看它是否真的存在。简单的查询可能不够,所以我们可能需要添加一些字段解析。


# rpm -q gpg-pubkey
gpg-pubkey-18b8e74c-62f2920f
gpg-pubkey-7fac5991-45f06f46
gpg-pubkey-d38b4796-570c8cd3
gpg-pubkey-1459c4ad-6624378b
#    rpm -q gpg-pubkey --qf '%{name}-%{version}-%{release} --> %{summary}\n'
gpg-pubkey-18b8e74c-62f2920f --> Fedora (39) <fedora-39-primary@fedoraproject.org> public key
gpg-pubkey-7fac5991-45f06f46 --> Google, Inc. Linux Package Signing Key <linux-packages-keymaster@google.com> public key
gpg-pubkey-d38b4796-570c8cd3 --> Google Inc. (Linux Packages Signing Authority) <linux-packages-keymaster@google.com> public key
gpg-pubkey-1459c4ad-6624378b --> John Doe <john_doe@gmail.com> public key

好的。现在,让我们为 root 设置签名环境,然后验证它是否已准备好。作为 root,使用你喜欢的编辑器在 root 主页目录下创建 .rpmmacros 文件。


# vi .rpmmacros

下面是你需要放入 .rpmmacros 文件中的内容。别忘了保存文件。


%_signature gpg
%_gpg_path /root/.gnupg
%_gpg_name Matt St. Onge
%_gpgbin /usr/bin/gpg2

正如许多人听我说过的(可能太频繁了),信任但要验证。所以要验证!


# rpm --showrc | grep __gpg_sign_cmd -A 5
-13: __gpg_sign_cmd     %{shescape:%{__gpg}}
        gpg --no-verbose --no-armor --no-secmem-warning
        %{?_gpg_digest_algo:--digest-algo=%{_gpg_digest_algo}}
        %{?_gpg_sign_cmd_extra_args}
        %{?_gpg_name:-u %{shescape:%{_gpg_name}}}
        -sbo %{shescape:%{?__signature_filename}}
#

你等待的神奇时刻到了。让我们用你那崭新的 GPG 密钥来签署刚刚构建的 RPM!记住,你将被要求输入我们的超级秘密密码短语——Embedded。输入它后,选择 <OK>


# cp ~mattbuild/myapprel-1.0-1,x86_65.rpm ~/
# rpm --addsign myapprel-1.0-1.x86_64.rpm
 Please enter the passphrase to unlock the OpenPGP secret key: x
  "Matt St. Onge <matt_st_onge@yahoo.com>"
   255-bit EDDSA key, ID A01133131459C4AD,
 created 2024-04-20.
  Passphrase: _________________________________________ x
      <OK>                                   <Cancel>
[root@fedora  ~]#

你通过在设备中安装发布文件,创建了符合嵌入式最佳实践的第一个自定义文件。由于安全在软件供应链中至关重要,你还通过添加自己的 GPG 密钥签名确保了包的完整性。为自己鼓掌吧。

展示你那炫酷的新技能,再次测试一下这个包。


# rpm -K ./myapprel-1.0-1.x86_64.rpm
./myapprel-1.0-1.x86_64.rpm: digests signatures OK
#

到达这里。任务完成。让我们继续迈向确保软件供应链安全的下一步。

练习——创建一个自定义 DNF 仓库

实际上,对于这个问题有两种不同的思路。一种是为应用堆栈和操作系统创建独立的仓库,另一种是将所有内容放在一个单一的自定义仓库中。我更倾向于后一种。我认为把所有内容放在一起会更简单,跟踪起来也更方便。我还认为,在这个仓库中创建大量自定义 RPM 以帮助团队维护解决方案是非常有必要的。我在打字时简直能感觉到自己的眼睛在翻白眼。我是不是在重复自己?很可能是的。

这个自定义存储库中还应该包含哪些内容?首先,我建议添加一个定义您版本的 rpm,就像我们刚才创建的那样。其次,我建议创建一个文档 rpm,最好与您的应用程序分开。最后,也是最重要的,我强烈建议创建一个 rpm,直接将您的存储库信息安装到设备中。将存储库定义在其自己的 rpm 中非常关键。这有助于支持和生命周期管理,如果您需要对存储库(或 GPG 密钥)进行更改,它为最终客户提供了最简单的更新方式。

这些自定义存储库不仅仅用于设备的更新。它们可以作为您安全构建链的一部分,在内部大大发挥作用。那么,话说回来,我们该如何构建一个自定义存储库呢?

练习要求

对于这个动手练习,您只需要访问一台 Linux 机器(物理机或虚拟机)。需要 root(或sudo)权限。我在我的 Fedora 40 系统上做这个示例,但您也可以在任何 RHEL 类的发行版上跟着我一起操作。

首先,我们将确保已安装httpdcreaterepo工具。然后,我们还需要确保 Web 服务器正在正常运行。


# dnf install httpd createrepo -y
….output truncated
Complete!
# systemctl enable –now httpd
Created symlink /etc/systemd/system/multi-user.target.wants/httpd.service → /usr/lib/systemd/system/httpd.service.
# systemctl status httpd
● httpd.service - The Apache HTTP Server
     Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; preset: disabled)
    Drop-In: /usr/lib/systemd/system/service.d
             └─10-timeout-abort.conf
     Active: active (running) since Mon 2024-04-22 21:39:01 EDT; 31s ago
       Docs: man:httpd.service(8)
   Main PID: 2712 (httpd)
     Status: "Total requests: 0; Idle/Busy workers 100/0;Requests/sec: 0; Bytes served/sec:   0 B/sec"
      Tasks: 177 (limit: 38325)
     Memory: 19.7M
        CPU: 93ms
     CGroup: /system.slice/httpd.service
             ├─2712 /usr/sbin/httpd -DFOREGROUND
             ├─2713 /usr/sbin/httpd -DFOREGROUND
             ├─2715 /usr/sbin/httpd -DFOREGROUND
             ├─2716 /usr/sbin/httpd -DFOREGROUND
             └─2717 /usr/sbin/httpd -DFOREGROUND
Apr 22 21:39:01 bm02.local systemd[1]: Starting httpd.service - The Apache HTTP Server...
Apr 22 21:39:01 bm02.local (httpd)[2712]: httpd.service: Referenced but unset environment variable evaluates to an>
Apr 22 21:39:01 bm02.local httpd[2712]: Server configured, listening on: port 80
Apr 22 21:39:01 bm02.local systemd[1]: Started httpd.service - The Apache HTTP Server.
lines 1-22/22 (END)

接下来,我们将在 html 目录下创建一个文件夹来存放我们的存储库。然后,我们将把之前练习中创建的 rpm 文件复制到该目录。


# cd /var/www/html
# mkdir myapp-for-x86_64-rpms
# cd myapp-for-x86_64-rpms
# cp ~/myapprel-1.0-1.x86_64.rpm .
# ls -l
total 8
-rw-r--r--. 1 root root 6861 Apr 22 21:44 myapprel-1.0-1.x86_64.rpm
[root@bm02 myapp-for-x86_64-rpms]#

接下来,我们将初始化存储库。


# createrepo /var/www/html/myapp-for-x86_64-rpms/
Directory walk started
Directory walk done - 1 packages
Temporary output repo path: /var/www/html/myapp-for-x86_64-rpms/.repodata/
Pool started (with 5 workers)
Pool finished
#

测试以确保我们可以通过本地的 Web 浏览器访问存储库。

这是在本地浏览器中测试时您会看到的一个示例。它将显示您新创建的自定义存储库中的可访问内容。

图 5.8 – 在网页浏览器中查看本地存储库

图 5.8 – 在网页浏览器中查看本地存储库

这个内部存储库的其他步骤包括在防火墙上启用http(这样我们的新存储库可以被您实验室内的机器访问),如果正在使用,还需将存储库目录和文件的selinux文件上下文设置为httpd_syscontent_t。由于这不是一本基础的系统管理员书籍,我相信您和您的团队已经知道如何做这些简单的任务。

这通常是实验室环境中的合适设置。对于任何面向外部的应用(即面向互联网的),这种设置是完全不可接受的。对于这种使用情况,有许多书籍和资源可供参考,教您如何保护 Web 服务器;但是,我会做一些基础性建议,这些建议应该是显而易见的。

对于面向公众的 Web 服务器,您的系统应使用带有签名证书的https。服务器应该在您公司外部的 DNS 中,以便客户能够找到它。应采用方法控制访问,或许在单个客户或用户级别上进行控制。尽可能保护您的系统。

现在我们已经创建了一个自定义包并通过自定义仓库进行托管,剩下的就是如何配置设备以使用新的自定义内容。接下来的练习将带你完成这一过程。

练习 – 配置你的解决方案以使用自定义仓库

现在让我们配置设备以访问自定义仓库。这是确保将来只向最终用户提供经过测试和验证的内容的关键步骤。

练习要求

对于这个动手练习,你需要访问之前创建了示例仓库的同一台 Linux 机器,并且还需要另一台机器来配置以访问该仓库。必须具有 root(或sudo)权限。我在我的 Fedora 40 系统上做这个示例,但你也可以在任何类似 RHEL 的发行版上跟着我一起操作。

这些文件存储在/etc/yum.repos.d/目录下,文件扩展名为.repo。它们应该由 root 用户拥有,所有人可读,但只有 root 可以写。这样可以确保它们的安全性。

在创建你自己的示例仓库定义文件之前,我们先来看一下我为之前练习中创建的自定义仓库所做的详细拆解。这是一个名为mycustomstuff.repo的示例文件。我会把这个文件的副本放在 GitHub 仓库中,以防你不想自己输入这个文件内容。


# ID definition of the repository
[my-custom-stuff]
# NAME of the repository
name=my-custom-stuff
# the base URL - update this for your systems information
baseurl=http://bm02.local/myapp-for-x86_64-rpms/
# Repository enabled =1 ... disabled =0
enabled=1
# setting up a gpg key for the repo is a great idea if public facing
# repo gpg check enabled =1 disabled =0
repo_gpgcheck=0
# definition for the gpg key for the repo itself (if enabled)
# example formatting:
# gpgkey=file:///(path to file)
# (or)
# gpgkey=(URL to gpgkey)
#

现在你有了一个示例,创建你自己的mycustomstuff.repo文件,并将其放在没有托管仓库的 Linux 机器上。该文件应该由 root 用户拥有,但所有用户和所有组都可以读取。

完成后,通过在已设置仓库访问的机器上安装 RPM 包myapprel来测试其功能。


$ sudo dnf install -y myapprel
Last metadata expiration check: 0:21:52 ago on Wed 01 May 2024 10:45:50 PM EDT.
Dependencies resolved.
=======================================================================
===================================
 Package                 Architecture          Version               
Repository                      Size
======================================================================
====================================
Installing:
 myapprel                x86_64                1.0-1                 
my-custom-stuff                6.7 k
Transaction Summary
=====================================================================
=====================================
Install  1 Package
Total download size: 6.7 k
Installed size: 55
Downloading Packages:
myapprel-1.0-1.x86_64.rpm                                        
         1.9 MB/s | 6.7 kB     00:00
-----------------------------------------------------------------
-----------------------------------------
Total                                                             
        670 kB/s | 6.7 kB     00:00
Running transaction check
Transaction check succeeded.
Running transaction test
Transaction test succeeded.
Running transaction
  Preparing        :                                              
                                    1/1
  Installing       : myapprel-1.0-1.x86_64                        
                                    1/1
  Verifying        : myapprel-1.0-1.x86_64                        
                                    1/1
Installed:
  myapprel-1.0-1.x86_64
Complete!

现在我们已经成功地将系统连接到仓库并安装了自定义包,我们可以庆祝我们的成功了。这些练习对于你的团队未来如何支持设备至关重要。

需要考虑的其他问题

这本该不言而喻,但我还是要说一遍。让实际人员测试你的原型和发布候选版本。只有这样,你的团队才能知道你是否真正取得了成功。我并不是说你不应该进行自动化测试——实际上,恰恰相反,你应该同时进行。首先做所有自动化测试、渗透测试和扫描。一旦对这些结果感到满意,再进行人工测试。

你还必须测试你的流程和支持基础设施。测试新版本将如何影响支持链,以及每个新版本将如何被你的客户使用。失败或损坏的更新可能会导致停机、服务阻塞、无法使用的设备,最糟糕的是,客户会非常不满和失望。

总结

那么,让我们来总结一下。我们在这一章中确实涵盖了很多内容。你应该感觉自己已经取得了一定的成就。你在短时间内已经走了很长一段路。最初,你建立了你的设备物料清单(SBOM),然后你定义了自己的自定义包、发布版本和自定义仓库。所有这些最终都通过授权设备访问你的自定义仓库并安装新包来付诸实践。你已经确保了自己的软件供应链安全!希望你现在能感到有能力跟踪未来产品的生命周期,接下来我们将进入下一章,深入探讨加密技术的使用以及如何保护你解决方案中的数据。

第六章:磁盘加密

Linux 统一密钥设置LUKS)标准用于加密 Linux 中的块设备,它的创建可以追溯到 2004 年。难怪我觉得自己好像已经使用它很久了!二十年是一个工具稳定并丰富功能的漫长时间。它也已经存在了足够长的时间,成为全球工程师喜爱和推崇的工具。几乎每个 Linux 发行版的安装器选项中,都能看到它作为配置存储的一部分。但每个安装器所能提供的 LUKS 功能都有所限制。你将不得不每次启动或重启时手动输入密钥。由于本书并非入门书籍,我们假设你具备一定的 Linux 基础技能,并将继续深入复杂的技术领域,培养更高级的技能。

本章的目标是拓宽你对系统存储安全的思路。在这里,我计划扩展你对如何以其他方式配置存储安全的理解。

拿上一些含咖啡因的饮料和零食吧。这将是一次更深入的探讨,帮助你了解如何将 LUKS 应用于你的未来产品。

本章我们将涵盖以下主题:

  • LUKS 介绍

  • 在配备自动化密钥的设备上实现 LUKS

  • 恢复是否可能?

让我们开始吧。

技术要求

本章的练习要求你拥有一台物理或虚拟机器,你可以在上面安装或重新安装 Linux 以完成这些任务。需要具有管理员(root)权限。你需要创建一些自定义分区/文件系统。你需要一个全新的 Linux 系统安装,并创建你常规使用的文件系统。同时,创建一个 500 MiB 的 XFS LUKS 加密分区,标记为 data3,挂载点设置为 /data3。初始密钥密码短语使用 CreatePass。需要 root 或 sudo 权限。我无法强调这个前提条件有多重要——如果不按指定操作,将影响你顺利完成本章练习的能力。

LUKS 介绍

使用 LUKS 后,任何 Linux 文件系统都可以被加密。但在此之前,你应该了解一些预先需要注意的事项。

对你的数据进行静态加密(即存储在磁盘、SSD 或 NVME 上的所有内容)不仅仅是一个“锦上添花”的选项,它几乎在你的目标客户群体中是一个默认要求。为了便于讨论,我们假设你的解决方案的预期客户是政府实体。大多数政府客户(无论我们指的是哪个国家)都被要求在其部署的任何系统中都具备极高的安全标准。他们的标准远高于常规标准,风险也更大。可以说,磁盘加密是被默认要求的。稍后我们将在第十三章中讨论如何实施一些更严格的政府安全标准。

加密过程中的关键工具是一个名为cryptsetup的开源实用程序。它依赖于dm-cryptLinux 内核模块提供的功能。这些工具以及你自己的发行版特定的存储管理工具,通常会在每个 Linux 发行版中默认安装。一旦使用 LUKS 加密了一个卷,只有在卷脱机且未挂载时,才能完全移除加密。

简单来说,LUKS 利用dm-crypt模块对磁盘上的数据进行加密/解密。LUKS 要求每次挂载和访问一个卷时,都需要输入密码短语。其内部工作原理对我们这些最终用户来说是隐藏的,实际上相当复杂。自动化这个过程更为复杂。

对于使用/boot分区的系统,GRUB 和 GRUB2 都支持这种加密。其他一些引导程序可能不支持此功能,因此在考虑此选项之前需要检查。

最常见的做法是加密根分区以及任何应用分区,以防止系统被篡改。交换分区和用户主目录分区也应该考虑加密。

当前版本的 LUKS(LUKS2)支持每个加密卷最多 32 个加密密钥,而 LUKS1 最多只支持 8 个密钥。当我们在本章后面讨论恢复时,这将是一个至关重要的黄金法则。

基本实现回顾

在今天的 Linux 发行版中,优秀的图形化安装程序已经可以让你看到它们如何在构建过程中帮助你配置 LUKS 加密。我们不会深入讲解 LUKS 的基础知识,但如果你需要参考资料,请查看该项目的仓库:gitlab.com/cryptsetup/cryptsetup/blobmC5#WdW07?dhVJ4aster/README.md。不过,我想特别指出的是,通过基础安装程序配置 LUKS 时,每次系统启动或重启时都会强制手动输入密钥密码短语。

由于这不是一个 Linux 安装的初学者指南,我想强调一个重要点。安装程序只能最小化地配置 LUKS 加密。这种配置可能适合在实验室中构建东西的人,但从客户的角度来看,当他们为一个精心设计的安全解决方案支付高额费用时,这种配置是不可接受的。

这是一个通过 Linux 发行版安装程序配置 LUKS 的示例:

图 6.1 – 通过安装程序配置加密

图 6.1 – 通过安装程序配置加密

通过安装程序创建加密文件系统无疑是保护设备构建的一个积极的起点,但如果仅止于此,客户关于可用性和安全性的投诉(因为他们至少需要将密码短语提供给所有管理员)迟早会迫使你进行更改。

当我们继续在本书中构建每个安全性和可用性标准的基础上,让我们继续到下一节,这将显然改善客户的最终用户体验,并且毫无疑问,将改善设备本身的安全性。自动化加密/解密过程并保护此信息免受最终用户访问变得至关重要。能够解密数据的人员越少,解决方案就会被认为越好。现在让我们确切地探讨这种自动化的样子,并开始动手。

在具有自动化密钥的设备上实施 LUKS

在实施任何安全因素的解决方案中,始终将您的最终用户体验放在首位。本书旨在帮助您和您的团队创建一个安全但可用的嵌入式 Linux 系统。

根据您的解决方案及其被最终用户使用的方式,防止最终用户每次启动系统时必须输入密钥是至关重要的。首先,该设备可能甚至没有连接控制台或键盘。其次,强制最终用户手动输入这样的密钥最终将导致他们在工作场所的某处或其他地方清晰可见的地方写下密钥。如果可能,应避免让最终用户输入密钥短语。

这里是一个例子截图,显示您在引导顺序继续之前可能会提示输入密码短语的方式:

图 6.2 – 启动时手动输入加密密钥密码

图 6.2 – 启动时手动输入加密密钥密码

现在您可以看到,强制最终用户输入密码短语并不是一个好主意,我们将在下一节中展开旅程,看看如何可以安全地自动化这个过程。让我们继续。

练习 - 使用存储的密钥实现 LUKS 并利用 crypttab 文件

在我们开始猛击键盘之前,请允许我介绍一个可能是您在这场战斗中拥有的盟友。/etc/crypttab文件被所有 Linux 发行版用于存储关于加密块设备的信息,以便它们可以在启动时自动解锁。在我看来,这是 Linux 中真正的隐藏宝藏之一。

对于此练习,我们将使用本章节“技术要求”部分提到的机器,并且我们将自动解锁/data3文件系统。让我们从以下步骤开始:

  1. 以 root 身份登录。

  2. 检查设备可用性。识别您为此练习创建的分区的 UUID 和设备名称。您的输出很可能会有所不同:

    
    $ sudo lsblk
    NAME           MAJ:MIN RM   SIZE RO TYPE  MOUNTPOINTS
    sda            8:0    0 476.9G  0 disk
    ├─sda1         8:1    0     2M  0 part
    ├─sda2         8:2    0     3G  0 part  /boot
    ├─sda3         8:3    0    55G  0 part  /
    ├─sda4         8:4    0    64G  0 part  [SWAP]
    ├─sda5         8:5    0    40G  0 part  /var
    ├─sda6         8:6    0    40G  0 part  /home
    └─sda78:7    0   500M  0 part
      └─luks-8e1fb810-b471-491a-adcf-32048a0eb534 253:0    0   484M  0 crypt /data3
    zram0          252:0    0     8G  0 disk  [SWAP]
    
  3. 现在,让我们确定我们特定卷的 UUID。您的设备可能是不同的,请注意:

    
    $ sudo blkid /dev/sda7
    /dev/sda7: UUID="8e1fb810-b471-491a-adcf-32048a0eb534" TYPE="crypto_LUKS" PARTUUID="b5906739-06d2-44d2-8770-17f2ffd75212"
    

重要说明

对我而言,我的设备名称是/dev/sda7——由于种种原因,你的设备名称可能会不同(磁盘类型、系统的分区方案等)。无论何时我输入/dev/sda7或该卷的唯一 UUID 时,你必须用自己的信息替换它

  1. 以 root 用户生成一个随机的密码并将其保存在/etc下,命名为luks-keyfile

    
    # dd if=/dev/random of=/etc/luks-keyfile \
    bs=1024 count=4
    4+0 records in
    4+0 records out
    luks-keyfile file as root:
    
    

    luks-keyfile 文件:

    
    # restorecon -vvRF /etc/luks-keyfile
    luks-keyfile file as another way of decrypting the drive we just created. You will be prompted for the original passphrase that you used in the prep for this exercise – CreatePass:
    
    

    cryptsetup luksAddKey /dev/sda7 /etc/luks-keyfile

    /etc/crypttab文件由 Linux 安装程序创建。我们需要查看安装程序是否为我们的卷手动解密创建了定义(在我的情况下,确实创建了):

    
    # cat /etc/crypttab
    /data3 volume and then run the command to ensure the LUKS has also closed the volume:
    
    

    umount /data3

    cryptsetup -v luksClose luks-8e1fb810-b471-491a-adcf-32048a0eb534

    命令成功。

    
    
    
    
    
    

重要提示

在这个练习中,我们还将卷命名为data3。由于我的/data3分区是在安装过程中创建的(为了提高速度),所以已经有一个与我的/data3卷相同 UUID 的条目,因此我创建了一个新的条目,将data3作为新的第一个条目,并将原始条目注释掉了。这是一个非常重要的步骤。你可以稍后选择删除旧的条目,但在测试中,我建议仅将其注释掉。此外,我必须提醒你,你的 UUID 与我的不同。

  1. 使用你喜欢的编辑器编辑/etc/crypttab文件:

    
    $ sudo vi /etc/crypttab
    

/etc/crypttab


data3   UUID=8e1fb810-b471-491a-adcf-32048a0eb534 /etc/luks-keyfile luks
###luks-8e1fb810-b471-491a-adcf-32048a0eb534 UUID=8e1fb810-b471-491a-adcf-32048a0eb534 none discard
  1. 现在,让我们手动强制 LUKS 使用我们的新密钥文件并测试解密,然后挂载该卷:

    
    # cryptsetup -v luksOpen /dev/sda7 data3 \
    --key-file=/etc/luks-keyfile
    No usable token is available.
    Key slot 2 unlocked.
    Command successful.
    
  2. 现在,让我们挂载设备:

    
    /data3 is mounted. Depending on how you built your test machine, your output may vary. Please pay attention:
    
    

    $ df –h

    文件系统      大小  已用 可用 使用% 挂载点

    /dev/sda3        55G  7.2G   48G  13% /

    devtmpfs        4.0M     0  4.0M   0% /dev

    tmpfs            16G     0   16G   0% /dev/shm

    tmpfs           6.3G  1.9M  6.3G   1% /run

    tmpfs            16G   76K   16G   1% /tmp

    /dev/sda2       3.0G  406M  2.6G  14% /boot

    /dev/sda5        40G  2.6G   38G   7% /var

    /dev/sda6        40G  875M   40G   3% /home

    tmpfs           3.2G  224K  3.2G   1% /run/user/1000

    /dev/dm-0       444M  135K  415M   1% /data3

    
    
  3. 最后,我们需要重新启动系统并重新验证所有自动挂载的文件系统。

到目前为止,我们通过一些高级自动化已经走了很长一段路。你的客户一定会非常欣赏你对细节的关注以及你的解决方案提供的易用性(同时还包含加密)。但我们还没有结束。让我们在下一部分深入探讨百万美元问题。

恢复可能吗?

哇。恢复有可能吗?这是百万美元的问题。请允许我为你描绘一幅图,并提供一个可能是唯一解决方案的建议。最真实的答案是不是。大部分情况下是不是!那么,让我们来探讨一下我的意思,以及为什么我称之为百万美元问题。

请稍微容忍我一会儿。让我们设想最糟糕的情况已经发生——由于一个完美的风暴,无论是因为损坏的 TPM 模块、文件系统损坏,还是更糟糕的情况,由于某个恶意员工或黑客的行为,您客户设备上的自动加密密钥库丢失了。

您的支持团队感到手足无措。不仅该客户离线,而且很可能会涉及到重大的数据丢失。“天哪,”你自言自语,“为什么我今天没请病假呢?

您的支持团队如何帮助客户?您的公司会失去信誉或最终客户的信任吗?您本可以如何防止这种情况发生?

好吧,坏消息来了。做好心理准备。如果您只有一个密钥,并且它丢失、被破坏或者发生了其他问题,您和客户肯定会度过一个非常非常糟糕的日子。丢失唯一的密钥/密码存储是无法恢复的。就此而已。这种加密方式是有深远影响的。它内置于设计中。没有密钥或密码就意味着完全无法访问,这正是它的目的!

无法帮助客户恢复的后果可能是昂贵的,但也许并不容易预测究竟会有多昂贵。如果您无法帮助客户从密钥/加密问题中恢复,他们失去了数据,也失去了时间。我们无法知道,也无法计算这是否会影响到他们的客户。您很可能会失去他们作为客户。您将失去市场的信誉。希望他们不会因损失起诉您的公司。正如我所说,这是代价惨重的。

现在,在这里我要说:“有志者事竟成!” 完全公开地说,完全无法防止不可预见的故障,但一些额外的工程和规划将为您的支持团队提供虚拟的救生艇,以便在发生船难时能生还。请再稍微容忍我一点时间。

我们已经提到,当前版本的 LUKS(即 LUKS2)支持最多 32 个密钥或密码槽。这样做是有充分理由的。您需要不止一个。从我的经验来看,您实际上需要几个。不要偷懒。设置多个。为您的产品和支持团队记录它们。它们可以在灾难发生时成为客户的救生艇。

如何应用这些知识取决于您自己。我推荐至少拥有三种选择,我再强调一次,这是最低标准。它们如下:

  • 在安装程序中使用的 LUKS 密码

  • 您为自动解密文件系统创建的密钥

  • 所有加密文件系统的紧急密码,仅为您的支持团队所知

话虽如此,根据某些客户实现您解决方案的规模,您可能考虑将标准的恢复密码作为第四种选择。这将使您的支持团队能够与客户更密切、更自由地合作,处理任何加密问题。

到这个阶段,您自己的内部文档和构建及支持流程必须是精确无误的。然而,在这一切中,谁能够访问这些特定的密钥/密码短语必须加以控制和规范。有人可能会问:“为什么?” 让我直言不讳。最坏的情况是,一名心怀不满的员工获取了这些关键信息并将其泄露——无论在哪里——例如在互联网上。如果所有客户的安全受到威胁,其后果将是灾难性的。

您可能在想,“天哪,这本书充满了灾难和悲观情绪!” 嗯,是的——这毕竟是一本安全书籍。恐惧是一种激励因素。继续往下看。但说正经的,这确实是一个非常严肃的话题,也是您和您的团队必须做出的设计决策。

总结

现在,让我们回顾一下本章的内容。我们已经超越了常见 Linux 安装程序中的 LUKS 基础配置。我们回顾了如何自动化 LUKS 来提高安全性和最终用户体验的高级方法;我们还讨论了配置加密密钥和密码短语的更高级方法;最后,同样重要的是,我们介绍了通过使用多个密钥和密码短语来采取预防措施,几乎消除了在关键支持问题期间数据丢失的可能性。我希望您和我一样,享受了这次对 LUKS 的深入分析。

利用这种加密自动化的好处是显而易见的。通过实施这一措施,您将立即创造更好的最终用户体验,因为用户在每次启动时不再需要强制记住或输入密码短语。这种加密保护了您的设备以及最终客户的数据或知识产权。强大的加密使最终客户在获取和使用您的解决方案时能获得更大的安心感。归根结底,一切都是为了帮助您的客户解决问题,并创造回头客,他们又会向朋友和同事推荐您的解决方案。

使用 LUKS 不应为您的客户和最终用户增加复杂性。这就是自动化密码密钥实施至关重要的原因。最终,用户体验和安全性都可以在这种情况下同时实现。我希望这次对 LUKS 的深入探讨能给您带来启发,并为您提供关于如何保护文件系统的新思路。

现在,让我们进入下一章,深入探讨 BIOS 和启动安全性。

第七章:受信平台模块

通常简称为TPM,即受信平台模块,这种专注于安全的微控制器芯片组使用先进的加密技术来存储重要或敏感信息。这些信息可能是凭证、密码、生物识别数据、加密密钥或其他非常敏感的数据。

本章中的练习将挑战你对家电中可以或应该自动化的内容的认知。在本章中,我们将基于方法论,利用这个工具进一步自动化你在解决方案中的加密密码短语认证,正如在第六章中最初介绍的那样。当 TPM 得当使用时,它可以成为你实现更高安全性和良好用户体验的催化剂。话虽如此,TPM 并非没有缺点和怪异之处。它 notoriously 不够用户友好,有时它的一些寄存器可能不可靠。无论这是硬件问题还是软件问题,我无法确定。无论如何,我将演示如何操作它以实现成功。

无论你是否选择利用 TPM,都不是一个简单的决定。权衡利弊。如果你允许它,它确实可以将你的家电带到一个新的高度。本章将包括以下几个部分:

  • 什么是 TPM?

  • 通过示例配置 TPM

让我们开始吧。

什么是 TPM?

超越作为你主板上数百个芯片中的一个,大多数人甚至无法识别的 TPM,它正在迅速成为大多数操作系统的重要工具。在本书写作时,普通的 Linux 系统甚至不需要你激活 TPM。而其他操作系统,比如 Microsoft Windows 11,实际上要求它才能安装操作系统。

TPM 提供了机制来安全存储各种信息。这些对象可以是(但不限于)许可证密钥、用户凭证、加密密钥或其他类型的数据,这些数据允许在没有用户互动的情况下进行消费。

TPM 的实现有不同类型——固件 TPM、离散 TPM 和集成 TPM。TPM 还可以通过软件实现(即虚拟 TPM),但由于它没有比运行在操作系统上的任何其他软件程序更多的保护,因此可能会被绕过。除非是最后的手段,否则避免使用软件 TPM。

固件 TPM利用系统 CPU 的受信执行功能。默认情况下,这会创建一个被称为信任锚的系统元素。这些只能通过物理到控制台并通过UEFI BIOS设置清除。这些是最常见的——在我看来也是最可靠的。

独立 TPM类似于基于固件的 TPM,只不过它们是通过其他 API 和软件在 UEFI BIOS 之外进行控制。独立 TPM 利用的是 CPU 本身的功能,而非固件。如果更换 CPU 或更改操作系统,您将丧失先前存储的所有 TPM 数据。否则,这些 TPM 功能几乎和固件中的 TPM 一样好。

最后,集成 TPM出现了;这类芯片组执行许多功能,但也内建了 TPM 功能。这种类型的 TPM 功能在这一领域中最为少见。

我曾被问过“选择使用其中一个会使自己更易受到攻击吗?”。简短且正确的答案是,不使用任何 TPM 解决方案才可能使解决方案变得脆弱。所有 TPM 实现都有效,选择哪一个完全取决于您自己的标准以及您所选择的平台是否有该功能。

当前的黄金标准是 TPM 2.0。TPM 2.0 功能丰富,能够存储多个密钥和值。它几乎出现在所有最新的服务器、PC 和笔记本电脑中。其算法和内建加密技术令人印象深刻。

较旧的系统可能会使用较早版本的 TPM 1.2。此版本容量有限,加密技术较弱,但它仍然远胜于没有任何 TPM。

全球大多数政府的要求标准将 TPM 1.2 设定为接触敏感数据的任何系统的最低要求。当然,TPM 2.0 是最敏感平台的必要标准。

现在让我们简要回顾一下 TPM 的发展历史。

TPM 的历史

我将为您总结一个简短的历史概述,并且会刻意保持简洁,避免任何繁琐内容。TPM 是由一个名为可信计算组的技术行业智囊团在 2009 年进行头脑风暴的结果。这个概念在国际标准化组织ISO)与国际电工委员会IEC)的合作下转变为全球标准。因此,TPM 诞生为ISO/IEC 11889:2009

TPM 1.2 在 2011 年成为全球标准,并统治了许多年。直到 2019 年,ISO/IEC 11889:2015发布,才由 TPM 2.0 取而代之。遗憾的是,现在大多数安全组织认为它已经不足够且过时。我依然认为使用 TPM 1.2 模块总比什么都不用要好。所以,显然,您可以根据自己的判断做出决定。

这里是 TPM 工作原理的图示(图片来源,维基百科,upload.wikimedia.org/wikipedia/commons/thumb/b/be/TPM.svg/2880px-TPM.svg.png):

图 7.1 – TPM 描述

图 7.1 – TPM 描述

截至本书出版时,TPM 2.0 仍然是全球标准。本章的练习将仅聚焦于 TPM 2.0 版本。现在,我们就开始这些练习吧。

通过示例配置 TPM

在这个练习中,我们将通过将加密密码存储在 TPM 中来实现存储卷解密的自动化。这样做可以让你的解决方案更安全,并防止将加密密码与公众分享,从而本质上提高你的解决方案的安全性。

练习要求

对于这个实验,我将 Fedora40(工作站版)安装到裸机硬件上。在此安装过程中,我创建了一个 500 MiB 的加密 XFS 文件系统,并将其挂载到 /data。我使用 TPMmaster2024 作为加密密钥。

这是在创建过程中该设置的样子:

图 7.2 – Fedora 安装过程中的加密文件系统设置

图 7.2 – Fedora 安装过程中的加密文件系统设置

安装完成后,当系统启动时,我们会被提示输入 LUKS 密钥,以便启动并挂载该文件系统:

图 7.3 – 在启动时手动输入 LUKS 密钥

图 7.3 – 在启动时手动输入 LUKS 密钥

对于这个实验,我建议你向现有的测试机器添加一个非常小的 LUKS 加密分区,而不是进行完整的重新安装。由你决定。在我的示例中,我使用了一个非系统分区/文件系统,但在生产环境中,你将加密几乎所有内容,除了 /boot 和 EFI 分区。

练习 – 启用 TPM 2 与 LUKS 加密结合使用

首先,让我们确保你的系统确实拥有正确的硬件。我们将浏览日志,查看上一次启动周期是否检测到 TPM 2.0 模块。如果没有返回良好的结果,可能是你的硬件不符合这个实验的要求:


$ sudo dmesg | grep TPM

这个命令的输出可能会比较长,因此我不会展示所有可能的输出。在你运行命令后,最重要的是观察输出中的 TPM2


[    0.011277] ACPI: TPM2 0x000000009AECAF08 000034 (v04 LENOVO TC-M1U   00001450 AMI  00000000)
[    0.011320] ACPI: Reserving TPM2 table memory at [mem 0x9aecaf08-0x9aecaf3b]
[    1.105253] tpm_tis MSFT0101:00: 2.0 TPM (device-id 0x1B, rev-id 16)
[    1.726489] systemd[1]: systemd 255.6-1.fc40 running in system mode (+PAM +AUDIT +SELINUX -APPARMOR +IMA +SMACK +SECCOMP -GCRYPT +GNUTLS +OPENSSL +ACL +BLKID +CURL +ELFUTILS +FIDO2 +IDN2 -IDN -IPTC +KMOD +LIBCRYPTSETUP +LIBFDISK +PCRE2 +PWQUALITY +P11KIT +QRENCODE +TPM2 +BZIP2 +LZ4 +XZ +ZLIB +ZSTD +BPF_FRAMEWORK +XKBCOMMON +UTMP +SYSVINIT default-hierarchy=unified)
[    4.604247] systemd[1]: systemd 255.6-1.fc40 running in system mode (+PAM +AUDIT +SELINUX -APPARMOR +IMA +SMACK +SECCOMP -GCRYPT +GNUTLS +OPENSSL +ACL +BLKID +CURL +ELFUTILS +FIDO2 +IDN2 -IDN -IPTC +KMOD +LIBCRYPTSETUP +LIBFDISK +PCRE2 +PWQUALITY +P11KIT +QRENCODE +TPM2 +BZIP2 +LZ4 +XZ +ZLIB +ZSTD +BPF_FRAMEWORK +XKBCOMMON +UTMP +SYSVINIT default-hierarchy=unified)
[    5.477528] systemd[1]: systemd-pcrextend.socket - TPM2 PCR Extension (Varlink) was skipped because of an unmet condition check (ConditionSecurity=measured-uki).
[    5.507674] systemd[1]: systemd-pcrmachine.service - TPM2 PCR Machine ID Measurement was skipped because of an unmet condition check (ConditionSecurity=measured-uki).
[    5.508733] systemd[1]: systemd-tpm2-setup-early.service - TPM2 SRK Setup (Early) was skipped because of an unmet condition check (ConditionSecurity=measured-uki).

重要说明

如果你没有收到任何 TPM2 输出,可能可以安全地说,你的实验硬件不足以支持本章的练习。

既然我们已经确认你有一个 TPM 2.0 模块,让我们确保它在 UEFI BIOS 中正确设置。重启你的计算机,打断启动过程以进入 UEFI BIOS 设置,然后找到 TPM 配置:

图 7.4 – UEFI BIOS – 设置 TPM

图 7.4 – UEFI BIOS – 设置 TPM

你可能会有多个 TPM 选项;如果是这样,选择 Firmware TPM 而不是 Discrete TPM。将芯片组设置为 Enabled,并确保清除芯片内的任何旧数据,然后再继续。别忘了保存并退出 UEFI BIOS(并重启)。

让我们安装所需的包来利用 TPM 自动化解密过程:


$ sudo dnf install -y clevis clevis-luks clevis-dracut clevis-systemd clevis-pin-tpm2

这个输出相当长,所以我已经将显示的内容进行了截断。需要注意的是,包安装必须成功完成:


Installed:
  clevis-20-2.fc40.x86_64               clevis-dracut-20-2.fc40.x86_64    clevis-luks-20-2.fc40.x86_64
  clevis-pin-tpm2-0.5.3-5.fc40.x86_64   clevis-systemd-20-2.fc40.x86_64   jose-13-1.fc40.x86_64
  libjose-13-1.fc40.x86_64              libluksmeta-9-22.fc40.x86_64      luksmeta-9-22.fc40.x86_64
Complete!

我们还没有完成。还有更多的软件包需要确保正确安装:


$ sudo dnf install -y tpm2-tss tpm2-tools tpm2-abrmd tpm2-pkcs11

该命令的输出内容较为冗长,因此我已将其截断,只显示我建议你在执行过程中检查的内容(即,软件包安装已成功完成——请注意,某些软件包可能已经预先安装,这取决于你如何配置实验机器):


Installed:
  tpm2-abrmd-3.0.0-5.fc40.x86_64                 tpm2-abrmd-selinux-2.3.1-10.fc40.noarch
  tpm2-pkcs11-1.9.0-5.fc40.x86_64
Complete!

接下来,我们需要确定加密设备的确切设备名称:


$ lsblk

该命令的输出内容相当重要,因为它将引导你了解磁盘如何分配以及文件系统的大小:

重要提示

你的系统输出可能与我的结果不同——请注意你如何分配磁盘。这在本练习中非常重要。


NAME                                          MAJ:MIN RM   SIZE RO TYPE  MOUNTPOINTS
sda                                             8:0    0 476.9G  0 disk
├─sda1                                          8:1    0   200M  0 part  /boot/efi
├─sda2                                          8:2    0     3G  0 part  /boot
├─sda3                                          8:3    0    50G  0 part  /
├─sda4                                          8:4    0    64G  0 part  [SWAP]
├─sda5                                          8:5    0    50G  0 part  /var
├─sda6                                          8:6    0    50G  0 part  /usr
├─sda7                                          8:7    0    50G  0 part  /home
└─sda8                                          8:8    0   500M  0 part
  └─luks-463aba53-7189-4920-a128-b4db2a314848 253:0    0   484M  0 crypt /data
zram0                                         252:0    0     8G  0 disk  [SWAP]

例如,我的块设备是/dev/sda8(请注意,你的设备名会有所不同)。

我们将把这些信息输入到下一个命令中,该命令会将我们的密钥绑定到 TPM 中:


$ sudo clevis luks bind -d /dev/sda8 tpm2 '{"hash":"sha256","key":"rsa","pcr_bank":"sha256","pcr_ids":"6,7"}'

请注意,此命令将要求你进行身份验证以使用提升的权限。然后,它会要求你确认希望用于自动解密卷的现有 LUKS 密码:


[sudo] password for mstonge:
Enter existing LUKS password:

现在,让我们告诉systemd在尝试访问该驱动器时始终优先使用 TPM2 模块:


$ sudo systemctl enable clevis-luks-askpass.path --now
$ sudo systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs=6+7 /dev/sda8

此命令将要求你确认现有的 LUKS 密码:


 Please enter current passphrase for disk /dev/sda8: •••••••••••••
New TPM2 token enrolled as key slot 2.

好的,我们还没有完成。我们将使用dracut重新生成正确的启动设置。


$ sudo dracut -fv --regenerate-all

同样,该命令的输出将非常冗长,但我确实要求你密切关注你自己的输出结果。在这里,我将截断我的结果并仅突出显示最终状态:


dracut[I]: *** Stripping files ***
dracut[I]: *** Stripping files done ***
dracut[I]: *** Creating image file '/boot/initramfs-6.8.5-301.fc40.x86_64.img' ***
dracut[I]: Using auto-determined compression method 'pigz'
dracut[I]: *** Creating initramfs image file '/boot/initramfs-6.8.5-301.fc40.x86_64.img' done ***

现在我们已经配置了新的启动参数和内核映像,是时候重新启动系统了。如果一切顺利,你将不会被要求输入 LUKS 密码(它会通过 TPM 自动为你完成):


$ sudo systemctl reboot

重要提示

TPM2 可能会比较麻烦。根据你的系统情况,常常需要在一些修补周期后,使用clevis重新绑定 LUKS 密码。

众所周知,TPM 对 Linux 来说是一个麻烦,甚至是难以合作的技术。许多 Linux 开发者正在努力解决这些问题。我怀疑,在不久的将来,随着这些问题的解决,我们将看到一些发行版像今天的 Windows 一样强制使用 TPM2。

我相信你享受了这个平台练习模块。(看到了吧?父亲笑话——抱歉,哈哈哈!)

总结

在本章中,我们介绍了 TPM、其版本和历史。我尽量简洁,以免让你感到无聊。本书的目的是帮助你了解如何提高安全性,而不是作为技术演变的编年史。

你获得了一瞥这种低调的 TPM 技术如何帮助你自动化设备的安全性。尽管 TPM 并不是一个完美的解决方案,但它有其优点和风险。更重要的是,你应该考虑实施 TPM 来自动化你的加密文件系统。

在下一章中,我们将深入探讨磁盘加密功能。让我们继续。

加入我们社区的 Discord

加入我们社区的 Discord 空间,与作者和其他读者讨论:

packt.link/embeddedsystems

第八章:启动、BIOS 和固件安全性

到目前为止,我们已经讨论了 TPM 和 LUKS 磁盘加密来保护数据。本章将促使你更深入思考最基础的硬件功能和你的启动系统本身。我事先警告你,这些设置确实是把双刃剑,换句话说,它们可以保护系统,但也可能使在客户现场支持同一系统变得异常困难。

了解如何最好地锁定和保护你的 BIOS(基本输入输出系统),其固件,以及操作系统安全启动的能力,将确保你的客户获得更具韧性的产品,同时你的团队可以减少公司面临的风险。

尽管锁定 BIOS 和启动选项是一个好主意,但它确实有支持方面的影响,我觉得有必要强调一下。我们将在后续详细讨论其中的一些问题。

本章将涉及以下主题:

  • 深入探讨各种启动系统组件

  • 使用实例理解启动级安全性

  • 固件中的潜在威胁

深入探讨各种启动系统组件

曾经想过开机时 Linux 系统发生了什么吗?我们来快速了解一下实际发生的事情。

首先,我们将深入研究系统的 BIOS。几乎所有现代 x86_64 平台都使用统一可扩展固件接口(UEFI)BIOS,它基本上是一个固件接口,作为操作系统与其控制的硬件之间的桥梁。较旧的平台使用厂商特定或遗留的 BIOS 类型,遵循的标准在不同系统之间有限。为了便于理解遗留 BIOS 与新标准 UEFI BIOS 之间的差异,我在这里创建了一个表格来对比它们的功能或特性。

关注点 遗留 BIOS UEFI BIOS
标准化 每个厂商都有自己的功能/特性 无论厂商如何,都是行业标准功能
数字签名 安全启动
分区表支持 仅支持 MBR 分区表 增加了对 GUID 分区表的支持
平台 有限 x86, X86_64, ARM, ARM64, PowerPC 等
模块化 模块化 – 厂商可以添加额外的支持(例如:网络、存储等)

表 8.1 – 两种 BIOS 类型的对比

一切从按下电源按钮开始。现代技术的连锁反应随之展开。系统的固件 BIOS/UEFI 启动工作。它执行 POST(电源自检)。完成自检后,它搜索并启动主引导记录(MBR)。

MBR 启动引导程序,我们的例子中是 GRUB2。GRUB2 然后加载定义的内核可执行文件。接着 Initramfs 启动并处理诸如解密、软件 RAID 和文件系统加载程序等任务。

一旦所有的协调工作完成并且根文件系统被加载,systemd 就会启动。systemd 会加载所有其他文件系统并启动所有启用的网络功能和应用服务。就这样…一个功能完备的 Linux 系统。

图 8.1 – 启动

图 8.1 – 启动

没有你的固件 UEFI BIOS,这一切都无法实现。限制可以访问的内容以及如何使用启动设备至关重要。如果没有这样的预防措施,将无法保护系统免受重大变化,例如使备用启动源可用,这将使任何有直接访问硬件的人不仅能够从未批准的设备启动,还可能向系统中引入恶意代码,甚至更糟糕的是,清除你整个系统的驱动器。

接下来,我们将进入下一个部分,讨论一些安全示例。

通过示例理解启动级安全性

在本节中,我们将看看如何访问 UEFI 配置,然后逐步了解一些你需要注意的关键安全设置。我们还将回顾这些配置的优缺点。

根据你选择部署的 Linux 发行版(以及该发行版的版本),你可用的工具和使用这些工具的复杂性千差万别。再次强调,选择一个企业支持的 Linux 版本最终会带来更好的结果。

此外,硬件平台越新,你的固件、CPU 以及当然还有 BIOS 中可能包含的安全增强功能也就越新。现在让我们继续讨论如何访问这些安全设置。

访问 UEFI 配置

让我从保障 UEFI 配置安全的关键步骤开始。这个步骤要求你有物理访问计算机控制台的权限。

如何访问计算机上的 UEFI BIOS 界面?有几条路径都可以通向相同的目的地。

首先,可以中断启动序列;通常,在 GRUB 开始其启动过程之前,通过按下某个功能键来完成此操作。具体按哪个键通常因供应商和系统型号而异。我认为这是中断 POST 过程的真正方式,也是进入 BIOS 的最简单方法。

第二,可以使用 GRUB2 的菜单。通常会有一个选项允许你进入 UEFI 配置,但这并非所有系统或发行版都有。某些平台可能会将编辑 UEFI 固件设置作为与启动加载程序分开的手动操作。

第三,从操作系统内部……嗯,严格来说并非如此。操作系统可以在没有提示的情况下重启并进入固件设置。这里有一个快速而准确的例子,教你如何让系统直接重启并进入 UEFI 配置工具。像所有管理功能一样,这个操作必须以 root 身份执行:


# systemctl reboot --firmware-setup

上述命令本身没有输出,但会立即重新启动并进入 UEFI 配置屏幕。

好吧,既然我们在谈论引导过程,那么我们也应该提到这里可能存在(或设置的)密码。根据我的专业意见,UEFI 管理员密码设置是一把双刃剑。出于同样的原因,我对设置引导加载程序(即 GRUB2)密码的看法也一样。这与我在第六章第七章中提到的,利用类似 LUKS 而没有 TPM 自动化的问题非常相似。

假设你选择为其中一个设置密码。我们来看看这对最终用户的影响。对于 UEFI 管理员密码,虽然概率很小——大约 1/100,000 的概率,最终用户才会有合理的理由访问这个密码——这可能永远都不是问题。不幸的是,这种情况并不适用于设置引导加载程序(即 GRUB2)密码。每次启动或重启都会迫使用户手动在控制台上输入密码才能启动系统。对于没有键盘永远连接的设备来说,这几乎是不可能的,甚至不切实际。对于有键盘的设备,最终用户往往会在设备上贴个便条,写上启动系统的密码,这样一来,原本设置密码的好处就完全没有了。

所以,你可能会问,为什么这会是一个问题?我的回答是人性和坏习惯。一般来说,可以安全地假设大多数人总是会选择最轻松的路径。这显然适用于每次引导周期都需要的情况。最终客户绝对需要访问这个密码。

以 UEFI 管理员密码为例,假设这是一个支持问题,迫使你的公司必须将这个信息提供给客户。在这两种情况下,密码所暗示的安全性会被削弱,因为最终用户不仅有这些密码,而且他们将其分享给客户组织外部的概率是最大的威胁。

我建议谨慎使用这两者,除非每个设备都分配了唯一的密码,并且你的支持团队有这些密码的数据库。即便如此,一旦与最终客户共享,密码也应视为已泄露,从而失去其原本的保护作用。

什么是安全启动?

简而言之,安全启动是向用户表明你的操作系统运行的是经过你公司亲自测试并签署的内核和二进制文件的一个优秀方式。

有一些关键变量在发挥作用,如表 8.2所示:

凭证/变量 目的 创建实体
平台密钥 (PK) 根密钥 平台制造商
密钥交换密钥 (KEK) 证书拥有者列表 操作系统合作伙伴或 OEM
授权数据库 (db) 允许的驱动程序或应用程序列表 操作系统合作伙伴或 CA
排除数据库 (dbx) 被撤销的签名者列表 签名授权机构
SetupMode 1 = 设置模式,0 = 启用安全启动
SecureBoot 1 = 强制启用安全启动,0 = 禁用安全启动

表 8.2 – 安全启动中关键变量及其角色

在我们开始进行练习之前,先看看没有启用安全启动和启用安全启动时启动过程的不同。这里是没有启用安全启动的启动过程的图示。

图 8.2 – 非安全启动链

图 8.2 – 非安全启动链

正如前面的图示所示,在没有任何检查或平衡的情况下,任何东西都可以被加载。一般来说,在构建产品时这是一个不好的主意。因此,让我们朝着确保我们的客户正在运行经过验证、真实且安全的系统的目标努力。这是描述安全启动过程的图示。

图 8.3 – 利用安全启动和密钥

图 8.3 – 利用安全启动和密钥

对大多数尝试使用自定义密钥的人来说,配置 Linux 中的安全启动变得更加困难了。在本书编写时,实现此功能的主要工具是一个名为efitools的包。这个全面的工具箱提供了密钥的备份和恢复,直接在 UEFI 固件中设置密钥等功能。可惜的是,正如开源项目时常发生的那样,一个关键工具被遗弃,而其替代品尚未准备好投入使用。

根据我目前看到的最佳信息,计划中的替代方案是一种名为sbctl的新工具。目前关于这个工具的信息有限。我希望它能很快出现在 Fedora 42 和其他发行版中。这是该项目 GitHub 的链接 – github.com/Foxboron/sbctl – 在这里你可以找到一些关于这个激动人心的项目的有趣信息。

因此,这确实为那些想在自己的设备上使用自定义密钥进行安全启动的用户带来了一个临时的困境。有几个选项。在新的工具进入主流 Linux 发行版之前,你必须做出自己的判断。我很难在这里给出具体的建议:

  • 选项 1:你可以仅依赖 Linux 发行版本身的密钥来启用安全启动。这可能会起作用,也可能不起作用,取决于你的解决方案是否需要自定义内核模块,而这些模块可能包含正确的签名,或者根本没有签名。

  • 选项 2:暂时放弃使用安全启动,直到你能在自己的条件下并用自己的密钥来运行。除非你考虑探索其他选项,否则目前还没有时间表告诉你何时可以偏离这个路径。正如一位好朋友提醒我的,这还缺少一个免责声明,告知你可能会暴露在恶意软件的风险中。

  • 选项 3:尽管直接使用您自己的密钥并仅使用您自己的密钥启用 Secure Boot 是可行的,您可以下载适用于您的发行版的 efitools 包,或从源代码自行编译。

  • 选项 4:如果您有点冒险精神,您可以尝试使用 sbctl 的早期版本,通过从项目的 GitHub 获取并自行构建来实现。

对于这个 Secure Boot 问题,您并非没有选择,但这是您需要考虑的其中一个问题。接下来让我们讨论其他可能影响您固件的问题。

固件中的潜在威胁

恶意代码感染固件,例如 BIOS rootkit,似乎是全球范围内最新的攻击方式。这也是一个安全团队很难发现的问题。这个问题在整个行业中都存在,因此几乎所有为 x86_64 平台系列开发解决方案的硬件厂商都会受到影响。一个典型的恶意攻击案例就是名为 LogoFAIL 的攻击。

LogoFAIL 利用所有制造商的 UEFI BIOS 中的一个功能,该功能使他们能够在启动时创建自定义的启动画面,从而显示他们的公司 logo。它找到了一种方法,将恶意代码注入到该过程当中,进而在用户不知情的情况下执行代码,带来了严重的安全隐患。

在过去几年里,已经创建了两打高危 CVE 漏洞,这些漏洞影响了全球数百万系统——网络硬件、存储系统、服务器、工业控制器、边缘设备和笔记本电脑几乎都受到了影响。几乎所有全球制造商都被迫进行紧急更新,以应对这些潜在的攻击途径。截止到今天(2024 年 9 月),当我在 NIST 的国家漏洞数据库中进行搜索时,查询结果仅固件 CVE 就超过了 4500 个。对我来说,这个数量令人震惊,难以想象。唯一的好消息是,绝大多数漏洞已经被报告为已解决。

这些漏洞中的一些源于支持访问的硬编码凭据被泄露,另一些则源于它们自身字节码存在严重的安全漏洞。最严重的情况是,恶意代码已被安装,但最终用户根本不知道。无论漏洞的起因是什么,它的影响都可能是毁灭性的。这些都是定时炸弹,因为攻击者可以妥协一个系统,然后静静等待再利用漏洞。

对于产品经理来说,这些 CVE(公共漏洞和暴露)必须被记录、跟踪和修复。从这些固件噩梦故事中,你的主要收获有两点。首先,确保你的设备固件版本符合硬件厂商的推荐版本。其次,确保你的固件供应链本身是安全的。只接受来自可信来源或厂商本身的更新。不要假设你系统出厂时的固件版本就应该是你团队发货时的版本。同样的,信任但要验证,仔细检查,再仔细检查。

病毒扫描器无法帮助检测。它们查看的是已拆解的文件,而不是固件。它们有其作用,但它们只是整体安全评估的一部分,而不是全部。

一代新工具已被创建,帮助管理员检测、报告和更新脆弱的固件和 BIOS 模块。开源在这项工作中起到了极大的帮助。硬件厂商可以通过像固件更新管理器(也叫 Linux 厂商固件服务)这样的工具,公开与社区分享他们的更新。厂商可以选择公开具体固件的版本信息,或将更新提供给生态系统。通过 Linux 中的这一新服务,管理员可以轻松地了解到可用的更新,并/或自动将它们安装到设备上。这也是一种将更新发送到现场设备的好方法。

总结

我希望你已经将本章内容牢记于心。我们在这里讨论了一个话题,它由于所带来的复杂性,常常被安全领域称为黑暗艺术。我的意思是,保护固件和启动过程,以及你技术栈的数字签名。我相信本章已经帮助你更深入地理解如何配置启动级别的安全性。最后,我们还涉及了那些隐藏且常常不被谈论的固件漏洞。通过像 Linux 提供的服务或 NIST 数据库,你可以及时了解已报告的威胁。知道问题就是胜利的一半。在下一章中,我们将探索通过不可变镜像部署 Linux 设备的新方法。

第九章:基于镜像的部署

在本章中,我们将真正偏离现有的基于软件包的安装(和更新)规范,而这已经是 Linux 三十多年之久的主流方式。让我们来谈谈不可变的基于镜像的系统。不可变镜像只出现了几年,最近才引起了广泛关注。有些人会争辩(包括我自己在内),认为面向设备的不可变操作系统是所有嵌入式系统的未来。想到一个不可变且不变的系统,给人的感觉比其他系统更安全。或者它真的是吗?如果你也认为它更安全,那么你是对的。更安全——是的——但并非完美……本章将为您提供一个关于这个话题的概述,在我专业的看法中,由于其复杂性和迅速发展的未来,它应该有一本专门的书。本章中,我们将回顾并进行一些集中练习,帮助您更好地理解不可变操作系统所提供的安全级别。我们将了解一些可用的工具,并且学习如何利用它们构建、部署,并在客户拿到设备后继续支持您的设备。

到本章结束时,您可能会说服自己,认为这种新的 Linux 部署方式是为我们嵌入式 Linux 系统社区量身定制的。相反,在深入了解这项技术之后,您也许会决定它并不适合您(至少现在不适合)。

在本章中,我们将涵盖以下主要内容:

  • 引入基于镜像的 Linux 部署

  • bootc 和可启动容器镜像

  • 特殊工具和支持基础设施的差异

  • 基于镜像部署的局限性

  • 更新和回滚更改

  • 实践练习 —— 按步骤演示如何部署基于镜像的系统

现在,让我们继续深入探索。

技术要求

为了顺利完成本章中的练习,您将需要两台可以修改或重新安装操作系统的裸机或虚拟机。需要具备根权限、互联网访问权限和 DHCP IP 地址分配。此外,您还需要能够下载 ISO 镜像并且拥有一个 16 GB(或更大)USB 闪存驱动器。最后,您需要一个免费的 Red Hat 开发者账户,并能访问您自己的Quay注册表(也是免费的)。由于这些练习的结果更为重要,因此对要求的配置也更高。我希望您在过程中能够享受乐趣,在我看来,这也是一个必须的条件。

在这些练习中,我使用 CentOS Streams 9 作为我的构建机器操作系统,并且我们将创建一个 CentOS Streams 9 可启动容器镜像。现在,让我们继续深入探讨本章的主题——基于镜像的 Linux 部署。

引入基于镜像的 Linux 部署

这个主题对我来说非常重要,因为我是嵌入式系统专家,过去十年专注于这项工作。我坚信这套技术几乎是专门为我们的嵌入式 Linux 系统设备以及支持它们的人群量身定制的。你可能会质疑,为什么我和许多行业领袖认为这是未来的技术。我会在这里简短地回答,但在本章的进展中我们将深入讨论。简化的生命周期管理是采纳这项新技术的最大理由。

在接下来的章节中,我将介绍这两种方法论、它们的特点、限制以及工具,还有一些实践操作让你更加了解。

rpm-ostree 和 atomic images

我们将要审查的第一种基于镜像的安装方法是rpm-ostree。这种部署类型有时也被称为atomic,因为它是不可变的。一些供应商有他们自己的营销名称。红帽® 将其称为 RHEL for Edge™。不管他们怎么称呼,我称之为改变游戏规则的技术。在最近几年,许多其他发行版都添加了 rpm-ostree 部署选项。也许你还想听几个例子?Fedora® Silverblue,NixOS,openSUSE® MicroOS,Nitrux,Vanilla OS,Talos Linux™ 和 BlendOS 是许多完全基于 atomic 的发行版之一。

任何你之前在 Linux 上使用的用例,现在都可以通过基于镜像的部署来提供更高的安全性和稳定性。你部署的位置无关紧要;这些系统可以轻松运行在裸机、虚拟机或云实例上。

/etc/var。由于这种镜像格式,传统的分区方法基本上已经不再适用。……或者说是不可变的?

OSTree 的核心通过 HTTP 复制只读树。它还具有应用层和安装机制,可以在 /var/home 中进行(关于它们实际的文件系统布局的更多细节将在下一节介绍)。这种机制类似于 rpm 存储库的托管方式;然而,它们在镜像作为参考数据(版本控制、标签等)的方式上有所不同。为了你的解决方案,你需要创建支持已部署设备的基础设施。

如果你想大概了解在标准部署模型中可能作为其自己可写分区的变化有多大,看看这种新模型的处理方式吧。因为 /var 是可写的,这里有几个关键目录/文件系统映射与你在 Linux 中习惯的不同。请仔细留意。

让我们看看文件系统是如何映射及其权限:

  • /home 链接到 /var/home 作为 RW

  • /srv 链接到 /var/srv 作为 RW

  • /root 链接到 /var/roothome 作为 RW

  • /opt 链接到 /var/opt 作为 RW

  • /mnt 链接到 /var/mnt 作为 RW

  • /sysroot 是只读的

  • /boot/boot/efi 是 RW

注意

rpm-ostree 是启用 ostree 镜像基础的机制。使用 rpm-ostree 安装 RPM 包会强制创建一个新镜像,这个镜像只是基础镜像的更新。

为了简化说明,我会尽量将这种方法论与我自己的理解相联系:一系列相互叠加的提交,可以轻松回滚,并以不可变的镜像部署方式呈现,类似于设备化部署。我再说一遍,我感觉有时这简直是为嵌入式 Linux 系统和定制化设备解决方案量身定做的。

那么,我们如何利用 rpm-ostree 并在其上添加更多强大的功能呢?让我们快速看一下几种方法,因为我们已经知道基础镜像本身是不可变的。首先,给你一个免责声明:你在其上层叠的任何内容可能不会作为该镜像的一部分进行维护,并且随着系统更新的推进,可能会被遗忘。

也就是说,我们可以在 rpm-ostree 系统之上添加一些东西(镜像本身之外)。这可以通过完全自包含的应用程序(通过 flatpacks 部署)或作为一个运行中的容器镜像(部署在镜像之外)来实现。在这种用例中,基础镜像仅仅是一个提供动态应用程序的平台。

另一种方法是将 RPM 包安装到镜像之上。我想可能有人有这种用例,但我认为这应该是镜像的一部分,系统应该通过包含额外 RPM 包的最新镜像进行更新。现在我们了解了 rpm-ostree 及其关键特性,下面是可以作为 可选 rpm-ostree 部署的发行版示例。请注意,这只是一个不完全的列表:

  • Red Hat® Enterprise Linux®

  • Fedora®(多种变体;最常见的是 Silverblue)

  • Vanilla OS(基于 Ubuntu®/Debian® 的变体)

  • Debian® ostree

  • openSUSE®(Slowroll)

  • SUSE Linux Enterprise Server™

  • CoreOS®

  • Rocky Linux®

  • AlmaLinux®

  • Oracle Enterprise Linux™

  • CentOS® Stream

所以,请了解你有许多选项可以测试 rpm-ostree。更多详情,请访问 libostree 在线文档:ostreedev.github.io/ostree/

让我们进入下一个主题,那就是可启动容器。

bootc 和可启动容器镜像

自从我开始写这本书之前,我就深度参与了与产品团队在这一前沿技术的范围、测试和文档方面的工作。这些努力让我结识了一些非常优秀的工程师,他们善于从不同角度思考问题。

什么是 bootc?一种简化的理解方式是将 bootc 定义为将 Linux 内核层叠到容器镜像中的工具,这样容器镜像就可以独立启动,无需外部操作系统来托管它。

如果你有兴趣参与这一全球技术变革的努力(或者只是想了解更多),这里是 bootc 的 GitHub 仓库:github.com/containers/bootc。在这里,你可以找到维护得很好的广泛文档。

让我们明确一点,bootc 是前沿技术。红帽®(引领这一新技术的组织)将其视为技术预览状态,直到工具和支持基础设施到位,他们才会考虑其完全可支持性。基本上,在 RHEL 10 和 RHEL 9.6 发布之前,这项技术将不会被视为完全可支持的,或者像红帽所说的,一般可用GA)并且适合生产工作负载,预计这两个版本都将在 2025 年 5 月发布。

这并不意味着你应该坐等。我强烈建议你进行全面的测试和尽职调查,看看这种部署方法现在及未来是否能为你的产品带来价值。

bootc 究竟是什么?bootc 是一个开源项目,利用开放容器倡议OCI)标准的容器镜像创建完整的操作系统镜像。它采用了现有容器基础设施中用于创建和更新容器镜像的相同分层技术。它还利用其他项目的功能,例如 rpm-ostree,来创建和更新这些操作系统镜像。

bootc 与 rpm-ostree 的区别是什么?两者都是基于镜像的部署方法,都具有一定程度的不可变性。它们的不同之处在于构建方式和更新方式。最重要的区别是 bootc 独特的能力,它能以容器为基础构建不可变镜像。

bootc 方法的独特优势在于,已经有一个庞大的开发者生态系统和工具集,专门用于构建容器。如果你能构建容器,你现在就可以构建一个完整的系统。这个构建链已经发生了变革,对于大多数公司来说,如果它们现在已经在使用容器化应用,那么适应这种新方法几乎不需要额外的工具。

但等等……在美国公司和全球其他地区,并不是每个容器化应用都需要转换为基于镜像的设备。对于我们来说,真正的变革是嵌入式 Linux 系统社区。通过这项技术,我们可以设计、创建、构建和自动化驱动公司成功的产品生命周期。

目前,许多工程师正在努力工作,以提供支持这种部署方法的新工具。等到 RHEL 9.5 发布时,社区应该已经能够在被认为是构建系统镜像和安装程序的首选工具中,获取所有的新功能,这个工具就是Image Builder。Image Builder 自 RHEL 8.3 以来就存在(已经有一段时间了),但它一直在不断发展,并且每个月都在变得更好。

对于在 Fedora 和 CentOS Stream 中构建镜像的我们来说,我们可以今天就利用新的功能,虽然这样做意味着我们处于前沿阶段,可能缺乏企业发行版的支持和稳定性。我强烈推荐查看在这个 GitHub 仓库中关于 Image Builder 功能的持续开发:github.com/osbuild/bootc-image-builder

现在我们已经介绍了 rpm-ostree 和 bootc 镜像,让我们继续前进,看看它们有何不同。

特殊工具和支持基础设施差异

这就是我们可以轻松将一种方法论与另一种方法论进行对比的地方。两种方法都能巧妙地工作;然而,仅仅通过 rpm-ostree 来创建、维护和支持构建的设备更加困难,并且它们的工具也更需要动手操作。

在接下来的几节中,我将主要聚焦于最相关的开源工具,适用于这两种方法论。让我们从查看可以帮助你交付 rpm-ostree 解决方案的工具开始。

rpm-ostree 开源工具

今天,开源社区为团队提供了大量可用的工具,无论你选择了什么操作系统。也就是说,每个发行版可能会有一些轻微的修改或功能差异,旨在使工具更适应其特定发行版的基础。

一些很好的示例工具,用于在跨发行版的 rpm-ostree 镜像部署中构建或维护功能,包含:

  • Composer-cli: 一款用于定义 Linux 镜像复杂内容的命令行工具,并能够将镜像渲染为多种格式

  • Osbuild: 一款用于构建 Linux 镜像的命令行工具

  • Composer(在一些发行版中也称为 Image Builder):一款图形化的基于 web 的工具,用于定义、构建和更新 Linux 镜像

  • Cockpit-composer: 一个在 Linux 机器上的 web 控制台插件,使用户能够在 cockpit/web 控制台的网页 UI 中使用 Composer。

  • Toolbox: 一款交互式命令行工具,帮助排查操作系统故障

接下来让我们继续探讨我们可以利用的其他镜像部署方法工具。

bootc 可启动容器镜像工具

在我看来,这里是事情变得有趣的地方。bootc 基于镜像的系统并不需要一堆复杂的工具来构建和支持。在本章的动手练习中,我们将深入探讨这一概念。

请允许我详细说明。正如我们将很快看到的,你在构建机上所需的只是一款文本编辑器和对注册表的访问权限,就能构建和更新你的应用程序。在构建过程中,我们还将利用一些容器工具。

这是一个可以利用的工具列表示例,用于创建和支持 bootc 基于镜像系统的生命周期:

  • 编辑器(vi、emacs、nano 等):简单的文本编辑程序,可以是基于控制台或图形界面的,但功能不如 IDE 套件丰富。

  • Podman:一个容器管理工具,用于在 Linux 上构建、运行和管理容器

  • IDE(Podman-Desktop、Eclipse、Visual Studio):各种图形化的综合开发工具

  • Image Builder:一个图形化的基于 Web 的工具,用于定义、构建和更新 Linux 镜像。

  • Cockpit-composer:一个用于 Linux 机器上 Web 控制台的插件,允许用户在 cockpit/Web 控制台 Web UI 中使用 Composer。

  • Console.redhat.com:由 Red Hat® 托管的一个全面服务,可以协助系统的构建、维护和自检

  • 注册表:注册表对于托管容器镜像并提供分发更新的中心位置至关重要,例如 Quay™、Amazon Elastic Container Registry™(ECR)、Harbor、Azure Container Registry(ACR)、GitHub Container Registry™、Google Container Registry™(GCR)、JFrog Container Registry™。

让我们进入一个更严肃的话题,今天基于镜像的部署的局限性。

基于镜像的部署的局限性

虽然基于镜像的部署是我们创建和维护解决方案的范式转变,但它们确实具有标准基于包的部署所没有的特殊性。对于基于镜像的系统,更新以重启的速度进行。而基于包的系统更新操作可能需要数小时,并且需要多次重启,同时希望没有依赖关系被破坏,最后一切正常。

一个显著的被认为的局限性是文件系统被定义为不可写。尽管许多人将不可变性的更广泛概念视为一项特性,但如果你试图将第三方解决方案安装到镜像中,而该解决方案期望被安装在一个非常特定的位置(文件系统),该位置需要是可读可写的,而实际位置是只读的,那么问题会立刻显现。

这是一个被认为的局限性,而非实际局限性。通过创造性地使用符号链接,这个问题很可能可以轻松绕过。

对于那些未参与生态系统的人来说,这些部署有时可能会被误分类或被认为是缺乏灵活性,或者认为它们在定制或调整解决方案方面的能力有限,而且通常必要的软件可能需要被添加到非标准文件系统位置,以便这些应用程序能够在读/写模式下运行。这其中有些是误解,但并非全是。让我们深入探讨一下。

rpm-ostree 镜像局限性

好的,rpm-ostree 是一个很好的解决方案。它确实很棒,我必须给予它应有的赞扬。我非常喜欢它。话虽如此,我也必须回应一些人认为它可能不够灵活的看法。我提出这样一个说法,实际上它的确是有意如此的。它是一个非常安全、不可变的基于镜像的部署方式。它的工具本身有助于使 rpm-ostree 成为一种非常规范化的部署方法。rpm-ostree 的设计本质上是为了成为一个安全的平台,能够轻松地托管容器化应用或虚拟机,同时保持非常小的系统占用。

但我必须揭示一些限制和难点。首先,内核定制是一项挑战,因为目前的工具并没有在这方面提供帮助(还没有)。我认为,如果你有任何想在最终状态中实现的定制需求,你的团队应该为这些定制创建自定义的 RPM 包。这还要求你对计划作为设备基础的具体硬件有深入了解。管理操作系统级别的用户账户可能会是一个重要的挑战,因为任何添加到部署后,诸如密码或用户组关联等修改,都可能会丢失,因为它们有可能被下一个镜像更新覆盖。在 第十章 中,我们会更深入地探讨这一点;我们将回顾最佳实践,即永远不要让最终用户直接登录到操作系统。 我能理解在企业环境中,这可能被看作一个巨大的问题,但在一个安全的设备中,我想问:这真的是问题吗?

此外,数据实际上是可读/写的地方,确实会增加设计和支持过程中的额外工作。用户数据、应用数据等,都是这种部署方法中的一些复杂因素。规划、测试,以及创造性地使用符号链接到可写位置,将是帮助你克服大部分这些感知问题的关键概念。

我经常争辩说,前面提到的这些方面其实并不是限制,而只是设计上的考虑,因为如果你选择通过 rpm-ostree 部署,你将开始一段不同且复杂的旅程,并且能获得许多安全上的好处。记得我曾说过,安全从设计桌开始吗?

让我们继续讨论其他系统为何可能被视为受限。

bootc 可启动容器镜像的限制

在这里,我觉得我必须宽容一些,因为这项技术甚至还没有达到 1.0 版本的状态。bootc 仍在不断发展,而且它的潜力巨大。此外,我还需要重申,支持 bootc 的先进工具也仍在不断演进。或许我有些偏见,但我看到 bootc 镜像的未来前景极为光明。

对于嵌入式设备来说,拥有一个稳定且安全的更新方法论是一个重要的设计点。今天,bootc 镜像最容易通过访问其创建者的在线注册表来支持。如果你的解决方案在客户将其部署到自己的环境中后可以访问互联网,那就没问题。今天,对于基于 bootc 的嵌入式 Linux 系统设备来说,在线 是最佳选择。

我今天看到的一个被认为的限制实际上并不是真正的限制,而是一个必须在设计阶段认真考虑的重大设计问题。今天,离线的 bootc 镜像部署是可能的,只是稍微复杂一些。如果你的产品需要在隔离环境或无网络环境中部署,就必须在设备的接口中设计一种更新导入方式。这实际上意味着要有一种方式,能够在本地导入新的容器镜像,作为更新和重建的基准。

再次提醒,像 rpm-ostree 一样,我建议通过仅允许应用程序级别的访问并限制操作系统账户,来将操作系统从终端用户面前隐藏。这将解决在每次更新/镜像重构时,操作系统用户账户维护的类似难题。是的,在 bootc 镜像中,管理或控制操作系统级别的用户也是一个问题。我猜随着 bootc 的发展,可能会为此开发更多的工具。

与 rpm-ostree 相比,bootc 超越了灵活性和定制化。内核修改变得更容易实现。为什么?因为容器本身非常灵活,并且更容易维护。

我的专业观点是,这项技术值得密切关注,因为它可以改变并简化你构建设备的方式。我不会说它没有痛点,但我确实认为它有着非常光明的未来。接下来我们来看看如何更新或者在最糟糕的情况下回滚。

更新和回滚更改

基于包的系统,无论是哪个包管理系统(RPM、DNF、APT、Zypper 等),在升级操作系统版本或尝试回滚安装时,都可能出现问题和遗留问题,导致一些意想不到的后果。如果你曾经遇到过这种情况,你一定明白我说的意思,我向你表示同情。对于那些幸运或没有遭遇过失败包更新过程的人来说,这就是区别所在。

基于包管理的系统在处理更新时必须实时检查其依赖项。这一过程的结果是,某些包可能会被添加或废弃,而你可能在过程中都没有意识到。这个过程不仅笨拙且难以理解,而且还会消耗大量时间。希望你在向客户发布更新之前,已经对每个版本进行了无休止的测试。有时,甚至经常需要多次重启。我为那些在经历这些的人感到同情。这就是停机时间。希望它第一次就能成功,因为如果不能,回滚通常需要从备份或快照中恢复,哈哈哈哈——如果这些备份或快照甚至存在的话。

基于镜像的操作系统不会受到那些问题的困扰。无论是提供增量更新,还是完全新的操作系统,这种交付方式都能快速进行就地升级,而不会影响用户或应用数据。如何做到的?这些系统准备好新的镜像后,直接重启进入新的镜像。快速、干净、高效。更重要的是,由于你和你的团队已经测试过这些镜像,所以几乎不需要担心新镜像是否有问题。

所以,假设最坏的情况:镜像在下载过程中出现了某些损坏。没问题。我们可以轻松地从之前的镜像中恢复。这真是太棒了,对吧?!接下来,让我们看看这些系统如何在不增加压力的情况下进行就地升级。

就地升级操作系统版本

这是另一个所有基于镜像的部署闪光点:就地升级。

对于 atomic/rpm-ostree 系统,我们所需要做的就是基于更新的操作系统创建一个新镜像,并将该镜像放入设备的更新仓库中。设备可以下载并准备新镜像,重启后将升级到操作系统的新版本。

对于 bootc-based 系统,我们所需要做的就是基于更新的操作系统镜像创建我们的容器镜像,重新构建容器,然后将容器上传到注册表。当系统检查更新时,它会拉取新的容器并重新渲染自己为一个升级后的系统。

就像我说的,这些东西几乎是为嵌入式 Linux 系统量身定做的,对吧?现在让我们开始动手实践,自己构建一个吧。

实践练习

现在是我们卷起袖子,敲击键盘的时候了。如果你按照呈现的顺序进行操作,最后你将为自己设置一个基于 bootc 镜像的部署生态系统。

在我们开始之前,我想与您分享一些有用的信息。此类基础设施的工具正在快速发展,已经不止一种方法可以设计、构建和部署这些镜像。我认为这是 Linux 社区一个令人惊叹的机会。我在这里展示的方法简单且易于通过像 Ansible 这样的工具进行脚本化或自动化。在整个练习过程中,我会提到其他方法或替代工具,它们可以增强开发者体验并使系统更具扩展性。

由于这些练习要求我们创建的配置文件要非常精确,我强烈建议你在选择通过复制粘贴的方式快速创建文件时要非常小心。因为这样做很容易将隐藏的 ASCII 字符(或格式化字符)复制到文件中,导致你的配置文件无法正常工作,并且几乎无法调试,因为当你打开文本编辑器时,可能只会看到一个空白空间(如果有的话)。我已经提供了可以下载并根据你自己实验室环境进行定制的模板文件。它们可以在本书的 GitHub 仓库中找到(github.com/PacktPublishing/The-Embedded-Linux-Security-Handbook/tree/main/Chapter09/exercises),同时它们还会为你提供一些我们没有涵盖的其他选项。

所以,拿出一只可格式化的 16 GB USB 闪存驱动器和你最喜欢的饮料(也许不止一瓶),让我们开始吧。

练习 1 – 准备环境

在第一个练习中,我们将安装必要的工具,并安装一些可选工具,以创建我们的最小可启动容器镜像构建链。让我们按照以下步骤来操作:

  1. 首先,我们将设置一个构建环境,配置我们的注册表,并创建一个容器,作为我们应用程序及操作系统的基础:

    
    $ sudo dnf install -y containers-common crun \ 
    iptables netavark nftables slirp4netns \
    composer-cli cockpit cockpit-composer \
    skopeo buildah runc podman
    
  2. 现在我们将确保 web 控制台已启用:

    
    $ sudo systemctl enable cockpit.socket
    
  3. 在这里,我们将启动 web 控制台的 socket:

    
    $ sudo systemctl start cockpit.socket
    
  4. 确认 web 控制台已经启动:

    
    $ sudo systemctl status cockpit.socket
    

    你的输出应类似于以下内容:

    ● cockpit.socket - Cockpit Web Service Socket
         Loaded: loaded (/usr/lib/systemd/system/cockpit.socket; enabled; preset: disabled)
         Active: active (listening) since Fri 2024-08-09 12:39:24 EDT; 1 month 13 days ago
    Triggers: ● cockpit.service
           Docs: man:cockpit-ws(8)
         Listen: [::]:9090 (Stream)
          Tasks: 0 (limit: 38320)
         Memory: 648.0K (peak: 2.5M)
            CPU: 26ms
         CGroup: /system.slice/cockpit.socket
    Aug 09 12:39:24 bm03.local systemd[1]: Starting cockpit.socket - Cockpit Web Service Socket...
    centos-bootc repository.
    
  5. 点击链接访问 centos-bootc/centos-bootc

  6. 请记下这个 URL,我们很快会用到它,也可以考虑将此页面添加到书签。

图 9.1 – 搜索 CentOS Stream 的 bootc 基础镜像

图 9.1 – 搜索 CentOS Stream 的 bootc 基础镜像

  1. 回到终端,配置你的非 root 用户帐户,使其能够搜索注册表:

    
    $ cd ~
    
  2. 创建所需的目录来存储你的容器配置,这样 Podman 就知道从哪里查找信息:

    
    $ mkdir -p ~/.config/containers
    
  3. 让我们切换到刚刚创建的目录:

    
    registries.conf file to contain the defined contents:
    
    

    $ vi registries.conf

    
    Set the file’s contents to match the following and save the file:
    
    

    我们将仅使用这些注册表

    [registries.search]

    registries = ['registry.redhat.io','quay.io']

    
    
  4. 现在,我们将返回到我们的主目录:

    
    $ cd ~
    
  5. 让我们下载 CentOS Stream 9 DVD ISO 镜像,以便稍后在创建自定义安装程序时使用。使用你的网页浏览器访问 centos.org/download/,然后点击 x86_64 按钮。

图 9.2 – CentOS Stream 9 下载

图 9.2 – CentOS Stream 9 下载

  1. 让我们验证文件大小,并确保它已完全下载:

    
    quay.io via the command line. Use your own user account and the password you have previously set in order to access the quay.io registry:
    
    

    $ podman login quay.io

    
    If the login was successful, you will receive the following message:
    
    

    登录成功!

    
    

重要提示

如果你选择了生成加密的 CLI 密码,login 命令应该会有所不同。将 [your username] 替换为你自己的用户名,将 [encrypted pass] 替换为你长而加密的密码:

$ podman login -u='[your username]' -p='[encrypted pass]' quay.io

  1. 让我们拉取基础容器镜像:

    
    $ podman pull quay.io/centos-bootc/centos-bootc:stream9
    

    这个输出非常长(再次)。在这里,我们已经截断了输出,向你展示你一般可以预期看到的内容:

    ((( output truncated)))
    Copying blob 775d29f76a39 done   |
    Copying blob 7eff373befa3 done   |
    Copying blob 8c789e616763 done   |
    Copying blob fd730fb4a24b done   |
    Copying blob 54246c915569 done   |
    Copying blob 232fb94490b0 done   |
    Copying blob ad312c5c40cc done   |
    Copying blob bd9ddc54bea9 done   |
    Copying config a1163a9d15 done   |
    Writing manifest to image destination
    a1163a9d15d2f9a3f7f81748baf8fbcfc69690ed38030e770fe2006c090b0f83
    
  2. 让我们检查一下本地容器清单,并验证我们是否在清单中拥有预期的 CentOS Stream 9 启动镜像:

    
    $ podman images
    

    你的输出应该类似于此:

    REPOSITORY                         TAG         IMAGE ID      CREATED       SIZE
    quay.io/centos-bootc/centos-bootc  stream9     a1163a9d15d2  43 hours ago  1.52 GB
    
  3. 现在,在 Quay.io 网页界面中,我们将为我们的容器镜像项目创建一个公共仓库。我们将从 Repositories 标签开始。

重要提示

简单提醒一下,这不是生产环境中应当采用的方法。我们这里只是为了实验室目的使用公共配置。私有、安全的注册表才是我推荐在连接互联网时使用的部署方式。

图 9.3 – Quay – 仓库主页

图 9.3 – Quay – 仓库主页

  1. 接下来,我们点击 bootc,确保选择了 Public 单选按钮,并且选择了 (Empty repository) 单选按钮。然后,点击底部的 Create Public Repository 按钮。

图 9.4 – 在 Quay 中创建一个新仓库

图 9.4 – 在 Quay 中创建一个新仓库

记下你的仓库 URL;我们稍后会使用它。我还建议你在浏览器中将其加入书签。

图 9.5 – 你的自定义 Quay 仓库

图 9.5 – 你的自定义 Quay 仓库

现在,我们已经在你的系统上配置了基础构建环境。通过配置我们如何利用注册表、安装容器工具,并准备容器基础镜像和 Linux 安装 ISO 镜像,我们已经拥有了成功所需的一切。此外,我们还设置了构建系统的网页控制台,稍后会派上用场。接下来,让我们开始构建我们的初始容器,它将作为未来不可变镜像的基础。

练习 2 – 创建一个容器文件

在本练习中,我们将创建一个容器文件,我们将使用在前一个练习中下载的基础镜像来构建它。此练习的结果将为我们提供一个可以运行简单的 Linux Apache mySQL 和 PHPLAMP)堆栈的容器。如果你决定不手动输入此文件,书籍的 GitHub 仓库中有一个预构建的文件供参考。

让我们构建我们的容器:

  1. 让我们创建容器文件并命名为mycontainerfile.cf

    
    $ vi mycontainerfile.cf
    

    将文件内容设置为如下所示:

    FROM quay.io/centos-bootc/centos-bootc:stream9
    #install the lamp components
    RUN dnf install -y httpd mariadb mariadb-server php-fpm php-mysqlnd && dnf clean all
    #start the services automatically on boot
    RUN systemctl enable httpd mariadb php-fpm
    #create an awe inspiring home page (all one command line)
    RUN echo '<h1 style="text-align:center;">Welcome to My Appliance</h1> <?php phpinfo(); ?>' >> /var/www/html/index.php
    
  2. 让我们构建我们的容器镜像:

重要提示

在命令行中,将[my_account]替换为你自己的 Quay.io 用户名。


$ podman build -f mycontainerfile.cf -t quay.io/[my_account]/bootc/lamp-bootc:latest

这个输出也非常长。为了节省空间,我们对输出进行了部分截断,同时仍然展示了你可以预期看到的内容:


STEP 1/4: FROM quay.io/centos-bootc/centos-bootc:stream9
STEP 2/4: RUN dnf install -y httpd mariadb mariadb-server php-fpm php-mysqlnd && dnf clean all
--> Using cache a525b1bb126820c8522199f6d42b292210f06e4d178efbc148d97a92b94a64ed
--> a525b1bb1268
STEP 3/4: RUN systemctl enable httpd mariadb php-fpm
--> Using cache 9400a8bbc0287454ae0db9f42f9b49e518daf2b410fd3c3d0bb91a8b58e0a2a3
--> 9400a8bbc028
STEP 4/4: RUN echo '<h1 style="text-align:center;">Welcome to My Appliance</h1> <?php phpinfo(); ?>' >> /var/www/html/index.php
--> Using cache 4bcb220e3de6429f9f83264e84f064f2101c715c78e1104e388d11f6007b560e
COMMIT quay.io/matt_st_onge/bootc/lamp-bootc:latest
--> 4bcb220e3de6
Successfully tagged quay.io/matt_st_onge/bootc/lamp-bootc:latest
4bcb220e3de6429f9f83264e84f064f2101c715c78e1104e388d11f6007b560e

很棒!我们现在有了容器镜像。让我们做一个快速测试,看看它运行得如何:

重要提示

在命令行中,将[my_account]替换为你自己的 Quay.io 用户名。


$ podman run -d --rm --name lamp -p 8080:80 \ 
quay.io/[my_account]/bootc/lamp-bootc:latest

你的输出大致会像这样:


7d9c474d9dd4e6ab32d910c72775cdb111adfed764f29887c110461ca67c54a6
  1. 启动容器后,让我们打开浏览器窗口并验证你是否可以查看提供的内容:http://[your_ip_address]:8080。

    如果页面没有加载,仔细检查你的防火墙设置。如果你在运行容器的同一系统上,回送地址应该也能正常工作。

图 9.6 – 测试我们的容器

图 9.6 – 测试我们的容器

  1. 现在我们应该也能在容器运行时进入容器:

    
    $ podman exec -it lamp /bin/bash
    
  2. 当出现提示时,可以自由测试一些命令,但记得退出:

    
    bash-5.1# exit
    

    然后你将返回到系统中的常规 shell 提示符。

  3. 停止正在运行的容器,因为我们知道镜像已经能够正常工作:

    
    lamp.
    
  4. 我们的最后一步是将我们功能齐全的容器镜像保存到你自己在 Quay.io 中的仓库:

重要提示

如果你还没有登录,请通过命令行重新登录 Quay.io。

在命令行中,将[my_account]替换为你自己的 Quay.io 用户名。


$ podman push quay.io/[my_account]/bootc/lamp-bootc:latest

这个操作的输出会非常长,所以我只展示最后几行:


(((output truncated)))
Copying blob 7685af3680f8 skipped: already exists
Copying blob 9046686a9227 skipped: already exists
Copying blob d1c1676ee4e9 skipped: already exists
Copying blob 7a1c4a9ce068 skipped: already exists
Copying blob 0811ec9b544a done   |
Copying blob abef090ec865 done   |
Copying blob 6394663daed5 done   |
Copying blob 2daf40f13a19 skipped: already exists
Copying blob 9dad063a624b skipped: already exists
Copying config 8a4585ebc8 done   |
Writing manifest to image destination

很棒!你通过基础镜像创建了未来操作系统的基础,并叠加了应用堆栈,所有这些都通过创建一个可工作的容器镜像来完成。在接下来的练习中,我们将创建一个安装程序,以便将其部署为可引导镜像。

练习 3 – 创建一个安装程序

在这个练习中,我们将创建一个 Kickstart 文件,然后将这个 Kickstart 文件与供应商提供的标准 ISO 安装镜像一起,创建我们自己定制的 ISO 安装镜像用于我们令人惊叹的新系统。这种安装方式非常适合在实验室或数据中心使用。如果你是在云服务提供商环境中部署系统,可能需要使用其他方法。关于如何构建 Kickstart 文件的一个好参考可以参考这个指南:docs.fedoraproject.org/en-US/fedora/f36/install-guide/appendixes/Kickstart_Syntax_Reference/

让我们开始本练习的第一步:

  1. 在第一步中,你将创建一个 Kickstart 文件(mykickstart.ks)。在这个文件中,你需要将我提到的 [you] 替换为你自己的账户用户名,并设置操作系统的文件系统布局和 root 密码的基本配置。完成后保存并退出该文件。如果你选择不输入整个文件,书本的 GitHub 仓库中有一个示例:

重要提示

在文件内容中,将出现[my_account]的位置替换为你自己的 Quay.io 用户名。


mykickstart.ks look similar (with your substitutions) to this:

mykickstart.ks

版本 1

anaconda 安装程序类型

文本

确保将设备连接到一个具有活动 DHCP 的以太网网络。

network -–bootproto=dhcp -–device=link -–activate

基本分区

clearpart –-all -–initlabel -–disklabel=gpt

reqpart --add-boot

part / --grow --fstype xfs

这是我们引用容器镜像的地方

注意这个 Kickstart 文件没有包裹部分

ostreecontainer –-url quay.io/ [quay_username]/bootc/lamp-bootc:latest –-no-signature-verification

用于演示目的的附加设置

在生产环境中使用更好的设置

这个练习的目的是不是教你如何使用 Kickstart。

但为了展示如何在自定义安装程序中使用它

firewall –-disabled

services –-enabled=sshd

将你自己的用户账户添加到系统中

user –-name=mstonge –-groups=wheel –-plaintext –-password=embedded

设置 root 密码

rootpw –-plaintext embedded


				1.  Now, we will install the `lorax` software package, which will enable us to create a custom installer ISO image:

    ```

    完成:

    ```
    ((( output truncated)))
    mkksiso command, which is part of the lorax RPM package we just installed. This will create a custom installer for us:
    ```

    ```

			Important note
			You will need to substitute exact paths of your own here.
			For example,
			`sudo mkksiso --ks /``home/mstonge/mykickstart.ks \`
			`/``home/mstonge/CentOS-Stream-9-latest-x86_64-dvd1.iso \`
			`/``home/mstonge/mycustominstaller.iso`

$ sudo mkksiso –ks [mykickstart.ks 的绝对路径] \

[CentOS Stream 9 ISO 的绝对路径] \

[你希望创建的新 ISO 的绝对路径]


			The output for this step is significantly long. I have truncated it here to prevent my editor from murdering me. The part you must pay attention to is the last line, which confirms the operation has completed successfully and that it wrote your custom ISO image:

((( 输出已截断)))

xorriso : 更新 : 写入: 830548s 74.1% fifo 0% buf 50% 137.6xD

xorriso : 更新 : 写入: 932628s 83.2% fifo 0% buf 50% 150.7xD

xorriso : 更新 : 写入: 1007616s 89.9% fifo 29% buf 50% 110.7xD

xorriso : 更新 : 写入: 1097728s 97.9% fifo 10% buf 50% 133.0xD

生成的 ISO 镜像:1120832 扇区

已写入介质:1121008 个扇区,LBA 48

写入 '/home/mstonge/mycustominstaller.iso' 完成。


				1.  Now that we have our own custom installer ISO image, let’s create boot media. For this step, you will need to use Fedora Media Writer. It should already be on your system; if not, download it first. If you need assistance downloading or installing the tool (which works on all major platforms), check out this reference link: [`docs.fedoraproject.org/en-US/fedora/latest/preparing-boot-media/#_fedora_media_writer`](https://docs.fedoraproject.org/en-US/fedora/latest/preparing-boot-media/#_fedora_media_writer).

			Important note
			This step may be optional if you are working with virtual machines – you might be able just to boot from the ISO file itself within the hypervisor.
			Let’s look at how Fedora Media Writer can simplify the creation of boot media.

					![Figure 9.7 – Fedora Media Writer](https://github.com/OpenDocCN/freelearn-sec-pt3-zh/raw/master/docs/emb-linux-sec-hb/img/B22104_09_07.jpg)

			Figure 9.7 – Fedora Media Writer

				1.  Here, you select the ISO image and the USB thumb drive that you want to commit the bootable image to.

					![Figure 9.8 – Choosing ISO images](https://github.com/OpenDocCN/freelearn-sec-pt3-zh/raw/master/docs/emb-linux-sec-hb/img/B22104_09_08.jpg)

			Figure 9.8 – Choosing ISO images
			As the Fedora Media Writer requires elevated access, you’ll be prompted for authentication to achieve `sudo` status.

					![Figure 9.9 – Elevated permissions – authentication](https://github.com/OpenDocCN/freelearn-sec-pt3-zh/raw/master/docs/emb-linux-sec-hb/img/B22104_09_09.jpg)

			Figure 9.9 – Elevated permissions – authentication
			It will definitely take a few minutes to render the ISO image to the physical media. Have patience, grab a beverage, and enjoy the break.

					![Figure 9.10 - ISO build in progress](https://github.com/OpenDocCN/freelearn-sec-pt3-zh/raw/master/docs/emb-linux-sec-hb/img/B22104_09_10.jpg)

			Figure 9.10 - ISO build in progress
			Once the ISO build is completed, you’ll be greeted by this screen.

					![](https://github.com/OpenDocCN/freelearn-sec-pt3-zh/raw/master/docs/emb-linux-sec-hb/img/B22104_09_11.jpg)

			Figured 9.11 – ISO image created
			You can now remove the thumb drive from the USB port. We’re just moments away from installation. You’ve successfully created your own custom installer. Let’s move on and put it to good use.
			Exercise 4 – initial installation
			In this exercise, we will install our first **Image Mode system** with our newly created custom installer. You will boot the test system from the newly created thumb drive (or from the ISO file we just created in the case of a virtual machine). You may need to interrupt your system’s normal boot process to get it to boot from the USB thumb drive.
			Sit back, relax, and watch the magic happen. Let’s move on to deploying our first system leveraging the automated installer that we just created:

				1.  With your newly created boot media, use it to boot (or create a new virtual machine). If you are booting onto physical hardware, you need to be aware of some things before your installation:
    1.  Ensure all previous partitions are removed from the drive (especially the **UEFI** partition) before the installation process begins.
    2.  Ensure that, within your **UEFI BIOS**, any previous entries for **Secure Boot** are removed (**RESET**) and that **Secure Boot** is set to **DISABLED** before the installation.
    3.  Boot your system from the USB media (physical hardware) or directly from the ISO image (virtual machine). This is an automated install and it will notify you upon completion (or failure).

    Here’s what a successful text-based unattended installation looks like.

					![Figure 9.12 – Installation success!](https://github.com/OpenDocCN/freelearn-sec-pt3-zh/raw/master/docs/emb-linux-sec-hb/img/B22104_09_12.jpg)

			Figure 9.12 – Installation success!

				1.  Once the installation is complete, test your login credentials at the console.

					![Figure 9.13 – First login to our new appliance](https://github.com/OpenDocCN/freelearn-sec-pt3-zh/raw/master/docs/emb-linux-sec-hb/img/B22104_09_13.jpg)

			Figure 9.13 – First login to our new appliance

				1.  Next, let’s determine the IP address of our new system:

    ```

    $ ip addr show

    ```

    Your output should indicate that you have successfully obtained a DHCP address. Make a note of that IP address.

    				2.  Now, let’s open a web browser on another machine and test the LAMP stack.

    Go to the IP address that you found in the previous step.

    Your result should look something like this:

					![Figure 9.14 – Viewing your appliance’s application](https://github.com/OpenDocCN/freelearn-sec-pt3-zh/raw/master/docs/emb-linux-sec-hb/img/B22104_09_14.jpg)

			Figure 9.14 – Viewing your appliance’s application
			Welcome to the new world where, if you can create a container, you can build a whole system. Let’s now move on to how we update these awesome beasts.
			Exercise 5 – creating an updated container
			In this exercise, we will make updates to our previously built container image, which will in turn provide updates to our Image Mode machine:

				1.  Your new appliance is defined by its container image. To create an update for your appliance, all we need to do is create a new container and then publish it to our registry. In this step, we will start by creating a new container file called `mycontainerfile2.cf`:

    ```

    $ vi mycontainerfile2.cf

    ```

    The contents of your file should look like this. Don’t forget to save the file:

    ```

    FROM quay.io/centos-bootc/centos-bootc:stream9

    RUN dnf install -y httpd mariadb mariadb-server php-fpm php-mysqlnd && dnf clean all

    RUN systemctl enable httpd mariadb php-fpm

    # 下面的命令是单行命令,尽管看起来像是多行

    # 像两个或更多

    运行 echo '<h1 style="Text-align:center;">Welcome to My Appliance</h1><?php phpinfo(); ?>' >> /var/www/html/index.php

    # 新内容

    运行 dnf 安装 -y cockpit

    运行 systemctl enable cockpit.socket

    ```

    				2.  Build the new version of your container image:

			Important note
			Replace your own Quay.io username where `[my_account]` appears in the command line. You may also have to log in to Quay before running this command (see *Exercise 1*, *step 13*).

$ podman build -f mycontainerfile2.cf -t \

quay.io/[my_account]/lamp-bootc:latest


			The output for this one is significantly long. I have truncated the output in a few locations, so what we can see here is more of a short summary:

(((输出被截断)))

已更新的已安装产品。

已安装:

PackageKit-1.2.6-1.el9.x86_64

PackageKit-glib-1.2.6-1.el9.x86_64

abattis-cantarell-fonts-0.301-4.el9.noarch

adobe-source-code-pro-fonts-2.030.1.050-12.el9.1.noarch

((( 输出被截断更多 )))

sscg-3.0.0-7.el9.x86_64

tracer-common-1.1-2.el9.noarch

udisks2-iscsi-2.9.4-11.el9.x86_64

udisks2-lvm2-2.9.4-11.el9.x86_64

webkit2gtk3-jsc-2.44.3-2.el9.x86_64

完成!

--> 6ab95e317a3c

步骤 6/6:运行 systemctl enable cockpit.socket

创建符号链接 /etc/systemd/system/sockets.target.wants/cockpit.socket → /usr/lib/systemd/system/cockpit.socket。

提交 quay.io/matt_st_onge/bootc/lamp-bootc:latest

--> fe247cf7e89d

成功标记 quay.io/matt_st_onge/bootc/lamp-bootc:latest

fe247cf7e89d97d5832d889718750d63cc5f2f24dcfd5ed4cce39dfafd150778


				1.  Now that you’ve rebuilt your container image, feel free to test it in the same way we did in a previous exercise, or don’t (it’s optional). We do, however, have to push this new image to our registry and set it as the latest version:

			Important note
			Replace your own Quay.io username where `[my_account]` appears in the command line.

$ podman push quay.io/[my_account]/bootc/lamp-bootc:latest


			The output from this command has been truncated significantly due to its length. You can expect your output to resemble this:

(((输出被截断)))

复制 blob ad312c5c40cc 被跳过:已存在

复制 blob bd9ddc54bea9 被跳过:已存在

复制 blob 386e8ecea514 完成 |

复制 blob 2463de35bc3e 被跳过:已存在

复制 blob d4cfe3c3d422 被跳过:已存在

复制 blob eedcea4f81f6 完成 |

复制 blob 2bca4ceb08f4 被跳过:已存在

复制配置 fe247cf7e8 完成 |

将清单写入镜像目标


			Wow! This is all that you have to do if you want your system to pick up an update automatically. As we are impatient creatures, let’s move on to the next exercise and force the update manually.
			Exercise 6 – updating your system
			In this exercise, we will leverage the latest updates to the container you have created to improve and update our bootable container (bootc) machine.
			Important note
			Your machine will check for updates automatically every few hours. The default time check period can be modified.
			Log back into the console of your appliance machine. Run the following as root:

/usr/bin/bootc update –-apply –-quiet


			Your machine will pull down its updates and reboot itself automatically.
			Well done! You have not only created your first bootc machine, but you have established an update mechanism and successfully updated your new machine. Congratulations!
			Success! You have updated your appliance by adding the web console to your image. Although you probably cannot log in as root, I hope you know that you can add additional users in the kickstart if you want to rebuild or you can add a user in your console now. Here, we only wanted to show just how easy it is to create an update. It works… gorgeously.

					![Figure 9.15 – Appliance is updated with new functionality](https://github.com/OpenDocCN/freelearn-sec-pt3-zh/raw/master/docs/emb-linux-sec-hb/img/B22104_09_15.jpg)

			Figure 9.15 – Appliance is updated with new functionality
			I hope that you have enjoyed walking through these exercises and that they have inspired thoughts as to how you could leverage this technology to build a better appliance. Additionally, I hope you continue to experiment and add to what we’ve covered in this chapter in your own lab.
			Summary
			Thanks for sticking with me. I never said this journey would be easy. rpm-ostree has been around now for several years, but its time in the limelight has been overshadowed by bootc and bootable container images, an upcoming technology that builds upon its positive facets and the management is much simpler.
			In this chapter, we have done an overview of the option of deploying your Linux appliance as an immutable system. I truly believe this technology could fill an entire book itself, so I do use the term overview quite sparingly. As this does greatly enhance the security of the system, it clearly will add some additional complexity to your build and support processes. Now that you’ve been armed with the knowledge of the tools you may need, you will clearly have some homework to do to determine whether this methodology is right for your team or your product. If time permits, I highly recommend your team does additional research into the feasibility of leveraging this technology in your future solutions. I know that may be a heavy lift. So, let’s now move on to the next chapter, where we will dive deep into the art of tamper-proofing.

第十章:对解决方案进行儿童保护:防止最终用户及其环境的影响

本章将为您提供一个关于如何在确保积极客户体验的同时对设备进行儿童保护的速成课程。没错,这两者必须同时进行。提供一个出色的用户界面(UI)绝对是一个挑战,需要在解决方案开发中投入一些额外的努力。只需提前知道,您的付出将在采用率上获得指数级的回报。

在本章中,您将学习一些关键信息,比如为什么将最终用户锁定在操作系统之外对安全至关重要。此外,您还将了解硬件级别的一些关键安全问题。我们还将回顾托管的应用程序本身是否是最终用户真正需要访问的内容。最后,我们将通过提供对 UI 设计影响的更深入理解,帮助您提高设备成功的机会。

本章包含以下主要章节:

  • 儿童保护介绍(即,保护设备免受最终用户干扰)

  • 确保硬件级别的保护

  • 操作系统级别和应用程序保护

  • 构建一个简化配置的 UI,同时提供出色的用户体验(UX)

儿童保护介绍(即,保护设备免受最终用户干扰)

如何对设备原型进行儿童保护,绝对是我最喜欢与产品团队讨论的话题之一。请允许我详细阐述。这一过程可能是决定什么符合设备定义的最大因素。所有确保最终解决方案安全并专注于其预定功能的努力都是至关重要的。必须在初始设置要求上正确引导最终用户,并将其控制在您选择允许他们访问设备/功能之外的范围内。

这里需要考虑很多努力。我的产品最终用户将如何访问解决方案?我们可以做什么来最小化或防止任何最终用户获得未经授权的提升或 root 权限?需要通过设备的 UI 进行哪些自动化,并使其隐藏?

我在这里描述的一个典型例子是防止最终用户利用退出键序列逃脱您的应用程序,无论它是基于控制台的还是图形化的。我称之为No Escape! 这是通过巧妙地修改一般控制台设置或编辑键盘映射来实现的。在本章将讨论的所有可能的保护措施中,我认为这是一个必须采取的第一步。

让我们继续进行硬件访问的安全保护。

确保硬件级别的保护

好的,我知道我们在 第八章 中已经讨论过这个问题……但我觉得我必须提醒你,这是真的。确保最终用户无法更改配置是关键。你在这方面有两个主要责任。第一个责任是保护解决方案,第二个责任是防止最终用户控制操作系统。通过实现这两点,你可以确保你的团队控制最终用户的体验。

如果你创建一个简化设备安全操作的用户界面,最终该设备将易于使用,而最终用户无需了解其工作原理。我恳请你考虑所有这些因素。将最终用户从操作系统的所有访问权限中剥离。

创建一种体验,让最终用户可以信任你已经实现了最重要的——一个安全且用户友好的平台。这才是真正的梦想之地。这是我们所有人都渴望创造的目标。这应该是我们的遗产。

硬件安全性是我们已经深入讨论过的内容。然而,我仍然觉得我们必须重新审视这个话题,哪怕只是简短地提及。所以,让我们深入探讨。请原谅我提前提醒,你会看到在这一章中我会重复一些细节。这是为了保护你和你的解决方案。所以,现在让我们继续讨论如何正确配置你的 BIOS 设置。

BIOS 安全性防篡改

在这一部分,我想要加强之前在许多章节中提到的内容。仔细选择你的安全设置。请了解每个配置选项的利弊。并不是每个设置都会提供最佳的结果。有些设置,甚至大多数,都有我们之前审查过的限制,我们将继续深入探讨。

锁定 BIOS 管理员密码是把双刃剑。是的,你可以完全确保最终用户无法更改 BIOS 设置……但是……这也确保了你的支持团队必须更换设备——而不是远程维修。如果你需要更多关于 BIOS 和启动安全功能的想法,随时可以重新查阅 第八章

这是你的支持计划至关重要的地方。知道它是什么,并拥有它。让我们继续讨论下一个硬件安全选项。

禁用 USB

对于这种安全预防措施和防篡改方法,我持中立态度,我将解释为什么。禁用系统上的 USB 端口,无论是通过 BIOS 设置还是操作系统,都可以是一个复杂的安全措施,或者它会永久确保你的支持模式不是故障排除,而是直接更换。消除连接设备(如 USB 闪存驱动器)的能力,通过防止数据传输、未经授权的系统启动或运行你团队未授权的代码,增加了另一层安全性。

选择这种级别的安全性是一个重要的决定。或者……也许并不是。对于某些解决方案,禁用 USB 端口是显而易见的。我们可以举几个例子,说明禁用任何可能的外部 USB 端口在解决方案机箱上的理由。

第一个例子是一个假设的移动呼吸机,用于医院和救护车队以及医疗行业中的其他设备。它有一个 LED 显示屏,所有的控制都集成在触摸屏中。禁用 USB 端口是出于防篡改的目的。因为大多数这些呼吸机可能永远不会连接到网络,或者会被放置在走廊和储物间,直到在它们服务需要的那个关键时刻,防篡改至关重要。这些设备需要经过政府审查和认证。因此,更新操作仍然由经过培训的人员来执行。

我的第二个假设例子是军用车辆中的视觉目标系统。这个设备有自己的显示屏和定制的硬接线控制。禁用 USB 是默认的,因为这个设备永远不会在现场进行更新或维护,只有当车辆本身送到维护厂时,才会由该解决方案的制造商派出的工程师进行服务。现场士兵无法接触,也不应该接触到底层系统。

这些理由足够支持“赞成”这一立场。接下来是一些“反对”的理由。我将以医疗成像系统为例。这可以是 MRI 或 CT 扫描仪——这些只是一些假设例子。这些系统复杂但维护良好,必须如此。它们并不是由拥有(或租赁)它们的医院维护。定期的维护是支持协议的一部分,尤其是当获取这些昂贵设备时。通常,这些复杂的系统由制造商派出的现场工程师按月或按季度进行维护。这些支持工程师绝对需要 USB 端口来运行诊断、修补操作等。医院的工作人员与此无关,这些系统都被保存在有严格限制访问的安全房间中,所以篡改的风险要小得多。

我的第二个例子是一个医疗健康领域的病人监控解决方案设备,需要与键盘、鼠标保持持久连接,更重要的是,需要一个指定的 USB 扬声器,用于在护士站提醒护士。

我最后一个关于禁用 USB 端口的例子适用于任何物理设备,其中可能通过类似自助终端的触摸屏提供正常的用户界面。如果需要对该设备进行任何支持活动,可能需要物理键盘和鼠标,仅仅是为了在等待支持人员帮助解决问题时能操作界面。这只是我认为的简化版示例,至少允许连接键盘和鼠标在任何情况下可能都是必要的。

对于这一套安全预防措施,我相信你和你的团队会权衡利弊。我们继续看下一个防篡改选项。

外壳防篡改

这在最终阶段是一个有限价值的选项。很少有硬件制造商启用了这种详细程度。要确定你的最终用户是否在没有你的允许或指导下打开了外壳,是一项徒劳的努力。

我说,谁在乎他们是否打开了系统外壳?如果你的团队正确地锁定了操作系统和 BIOS,那么恶意行为者几乎无法做任何事来破坏系统。他们肯定无法在没有你帮助的情况下添加新硬件。也不应该允许他们这么做。

在最好的情况下,只有在外壳被打开时,才会通过在系统启动时显示消息来突出显示(假设能看到控制台)……对于这种类型的封锁,如果你的硬件甚至支持它,你(和你的团队)也无法得知,最终用户可能有能力从任何日志中完全删除此信息,前提是没有任何东西阻止他们进入并更改 BIOS 设置。

奇怪的是,技术供应商可以从运输行业获得一些启示——更具体来说,是卡车运输和航运。你的外壳将需要类似于锁或防篡改夹具或编号标签的东西,以防止最终用户打开外壳(在某种程度上)。一些示例可以通过亚马逊轻松获得。类似的设备可以大大增强并保护你的产品免受篡改。我建议像这些示例一样定制制作。你应该考虑在标签上放置两个信息。首先,放置一个序列号,你可以在内部追踪,它与销售给客户的硬件绑定。其次,放置一个警告,表示破坏封条将使任何保修失效(为了你的保护)。

亚马逊的示例:

由于有几种方法可以防篡改并保护硬件本身,我谦虚地承认,并非所有方法都适合你的解决方案。请明智地选择。现在,让我们继续探讨如何为你的解决方案锁定操作系统。

操作系统级别和应用程序保护

好的,这里事情可能会变得有些复杂。我知道你可能会对我这样的陈述感到一些担忧。所以考虑到这一点,我提供一下免责声明:我不了解你的应用程序。我怎么会知道呢?我(和你)必须相信你的团队了解它。

在这一部分,我将挑战你和你的团队构建一个全面的界面,不仅仅是为你的应用程序,还包括用户访问、更新等。你能通过应用程序/用户界面隐藏的越多,你的设备就会越安全。这一部分以及接下来的几节内容,致力于帮助你实现这一目标。我给你的挑战最终可能决定你的产品是成功还是失败。你在提供丰富且愉悦的用户体验上投入的努力越多,最终客户就越有可能称赞你的产品并全面采纳它。

这些措施不仅仅是为了安全,还能为最终用户创造丰富而愉悦的体验。现在让我们深入探讨其中的几个因素。

最小化对根目录的访问

从定义上讲,设备应该易于使用,但不要求最终用户具有深厚的应用程序管理或操作系统管理技能。这些因素是隐含的。如果最终用户的组织具备(或有意愿)维护这样的解决方案,他们最终会自己构建这些解决方案。

因此,在这一思维过程中,我的建议可能显得有些过于严苛。当我写下这些时,我不禁感到有些不安,但我觉得你也应该采纳这种心态。这将最终保护你的支持团队,免受无数不必要的电话困扰。防篡改你的解决方案。是的,我刚刚说了。你越是防止最终用户直接访问操作系统,你的解决方案就会越安全。

如果不采取措施,最终用户获得 root 权限可能会给你的设备带来重大情绪性事件。此时,他们可以对设备做任何他们想做的事。我是不是该列出一些可能出现的恐怖情况?哦,是的,我会。

如果你的最终用户拥有 root 权限,他们可能会在有或没有恶意意图的情况下执行以下任何行为:

  • 添加或删除软件

  • 修改系统配置

  • 向系统或应用程序添加或删除用户

  • 删除安全预防措施或配置

  • 修改或删除日志以掩盖痕迹(或完全删除日志记录)

  • 在系统中进行更改,使得设备无法实现其采购目的

我甚至没有提到那些可能发生的真正邪恶、恶意的活动。对于这些,我将允许你展开想象。尽情享受吧!也许现在你明白为什么我恳求你和你的团队采取一切合理步骤来保护你的解决方案了。

无论你的解决方案是如何访问或交互的,将这些设置从所有最终用户处隐藏并在后台处理,将确保你的解决方案的安全性和稳定性(希望还包括持久性)。

SUDO 和限制控制台访问

根据你的解决方案的具体设计和实现方式,接下来的建议可能并不可行。嗯……至少可能并不是最初设想的那样。请张开思维,我是为了帮你避免未来的麻烦。

现在我将再次强调一些最佳实践,希望你已经知道。最小化或完全消除最终用户直接访问操作系统的权限。设备应当是一个黑箱。最终用户应该只能访问为解决方案设计的服务,以及解决方案未自动化的任何管理任务。

对于管理任务,我认为至关重要的是遮蔽并移除最终用户直接访问操作系统的能力。将 root 权限交给用户群体,实际上会确保在某个时刻,一些恶意(或意外)用户将故意破坏某些东西、逆向工程解决方案,或者——更糟糕的是——重新配置系统以执行恶意活动。

那么,我们如何实现这一点呢?其实并不难。在你的图形界面或 Web UI 背后,设置以非 root 用户身份运行的脚本,该用户具有受限的 sudo 权限。这是保持用户远离操作系统或 shell 的最简单方法。

但是,如果最终用户可以登录系统并有终端访问权限怎么办……限制他们能看到的内容,限制他们可以执行的操作。确保他们被允许执行的操作受到 ACL、SUID、SGID 和其他文件权限设置的控制。此外,对于任何可以访问系统的用户,我建议提供一个受限的界面(即使是基于 shell 的),唯一的例外是你为支持人员(如果有的话)创建的访问权限。

在这种情况下,最终用户可以被视为敌人——无论是有意还是无意。因此,您在界面中所能做的任何防止直接访问操作系统的努力都应该被视为强制性措施。让我们继续。

非交互式 LUKS 加密

我们已经在第六章第七章中详细介绍了确保磁盘加密(无需最终用户交互)的方法;然而,我觉得如果不再提一次会显得疏忽,因为这也是确保解决方案“防儿童”的另一种方式。

使用自动化磁盘加密时,您将责任从最终用户手中移除,并且防止其恶意更改。不进行自动化会导致糟糕的最终用户体验,并使您的解决方案存在漏洞。既然我知道您已经理解我的意思,那么我们继续。

保持用户在应用程序空间中

他所说的“保持用户在应用程序空间中”是什么意思?这是个好问题。为此,我有一个很好的推荐,请允许我详细说明。

另一种有效防止您的应用程序或最终用户破坏操作系统的方式是将所有最终用户保持为应用程序级别的用户,而非操作系统级别的用户。通过这种方式,您的应用程序界面将是用户唯一能够与之互动的地方——永远如此。我的意思是,最终用户在您的应用程序堆栈中只有一个用户帐户,该帐户由应用程序控制,而不是 Linux 本身。这可以防止最终用户访问命令行界面。

可以将其视为应用程序沙箱化...但我们是将其应用于最终用户...这是一个很好的隔离层,能够为您的解决方案增加一层保护性安全。

启动时自动启动应用程序

确保您的界面和应用程序在启动时自动启动是理所当然的,但我建议再进一步。以非 root 用户身份使用systemd来运行它们。

这是如何设置 systemd 和 myapplication 的示例。启用 linger 允许应用程序或服务在非 root 用户登录时正确运行,无需交互。

启动并启用您的应用程序:


$ systemctl --user start myapplication.service
$ systemctl --user enable myapplication.service

为了确保服务即使在$USER未登录时也能运行,我们需要使用linger。请记住,$USER是您希望运行应用程序/服务的用户帐户:作为。


$ sudo loginctl enable-linger $USER

现在,您的应用程序将在每次启动时以定义的用户身份运行,无需任何提升或 root 访问权限。通过采用本节中详细说明的定制,我们已采取更多措施确保系统安全性和稳定性。接下来,让我们继续探讨如何在确保安全性的同时提供良好的用户体验。

构建一个用户界面以简化配置,同时提供出色的用户体验(UX)

在某个时刻,你的潜在客户已经做出了决策,决定寻求一个商业化解决方案来解决他们遇到的问题。这个决定是是否选择自行开发解决方案,还是购买别人已开发的解决方案。这确实是一个需要记住的重要事实。总有一天——希望尽快——有人会选择购买你的未来产品!

尊重那些做出这个决定的人,通过提供积极且有意义的用户体验UX)来回馈他们。为他们提供一个安全的解决方案是显而易见的。如果你的解决方案是一个聚焦于安全服务的家电,他们对你公司的信任将更为深厚。在这种情况下,信任也意味着责任。你的团队需要负责创建一个不需要客户 IT 员工是火箭科学家的家电,甚至不需要任何 IT 员工帮助他们使用你的解决方案。我要挑战你们超越这一点,向最终客户提供一个超出预期的界面,涵盖以下几个方面:

  • 在直观性方面超出所有预期(即,用户能够轻松导航)。

  • 向最终用户提供适当数量的细节,并且不会让他们在管理问题上负担过重。

  • 考虑到所有可能出现的支持和配置需求,以确保最终用户永远不需要直接访问操作系统。

  • 为最终用户提供在无需大量培训的情况下使用家电功能的能力。

一个安全且成功的家电体验可以通过其界面中规划和自动化的程度来突出。这些决策在设计阶段早期就已做出,并在此得以实施。无论用户如何与家电交互,隐藏或完全移除操作系统对用户的可见性至关重要。让我们来探讨一些文本和网页 UI 的例子。

初始配置 – 文本 UI

对于这一组示例界面,我将向你展示一个最基础的文本 UI,用于家电的初始配置。为了讨论的方便,我们假设最终用户已连接键盘并具有控制台访问权限。

对于这种类型的初始配置 UI,你至少需要为用户设置一个非 root 用户,以便他们能够登录,并且希望在登录后,这个用户只能运行这个简单的设置工具。

我们的第一张截图模拟了一个欢迎界面,供最终用户使用。你也可以添加一些其他友好的信息,比如感谢选择我们……或类似的内容。

图 10.1 – 文本 UI – 欢迎界面

图 10.1 – 文本 UI – 欢迎界面

一旦通过欢迎界面,最终用户将看到一个配置选项的主菜单。

图 10.2 – 文本 UI – 主菜单

图 10.2 – 文本 UI – 主菜单

让我们也假设这个设备在网络中有一些功能。因此,让我们帮助最终用户定义网络设置。他们只需提供属性值,而你的后台自动化真正进行配置更改,限制最终用户可以访问和执行的内容 – 没有 root 访问权限。

接下来的几个界面将展示用户定义网络设置的交互过程,并最终要求确认以便保存和应用这些设置。

用户可能首先需要提示输入设备的主机名设置。

Figure 10.3 – 文本 UI – 网络配置 – 开始

图 10.3 – 文本 UI – 网络配置 – 开始

随着我们继续进行网络配置,IP 地址分配开始:

Figure 10.4 – 文本 UI – 网络配置 – 进行中

图 10.4 – 文本 UI – 网络配置 – 进行中

随着我们的进展,还有更多的网络设置。在这里,我们展示了更多向内部的设置,其中可以配置子网掩码和 DNS 设置。

Figure 10.5 – 文本 UI – 网络配置 – 继续

图 10.5 – 文本 UI – 网络配置 – 继续

作为最佳实践,我们应该始终在最后提示用户确认(或取消)设置,然后再将其提交到运行配置中。

Figure 10.6 – 文本 UI – 网络配置 – 确认

图 10.6 – 文本 UI – 网络配置 – 确认

现在,你的后台自动化正在进行实际的配置工作。

Figure 10.7 – 文本 UI – 网络配置 – 后台执行

图 10.7 – 文本 UI – 网络配置 – 后台执行

所以,这就是简单的基于文本的设备网络配置。尽量保持尽可能简单,但考虑到所有设备用途和配置的方面添加到这样的菜单系统中。隐藏所有操作系统操作,同时保护系统免受最终用户的影响。

让我们继续看看模拟的简化 Web 配置界面可能会是什么样子。

初始配置 – Web UI

基于 Web 的界面可以提供更美观的体验,但需要更多的编程。你仍然会收集与文本 UI 相同的信息,但是不是立即调用 sudo 脚本,而是通过 cgi-bin GETPOST 操作来执行 sudo 脚本。我不会远程教你如何编写网页,因为有成百上千本书可以比我做得更好。

但是,对于初始配置,你应该考虑利用预定义和文档化的 IP 地址,以便新的最终用户访问你的初始设置页面。

在接下来的几张截图中,我们将看到一个简化的 Web UI 初始设备配置的模拟演示。

让我们从一个欢迎页面开始。欢迎您的新客户,并让他们知道系统正在正常工作!该页面礼貌地表明,我们需要进行一些基本的配置工作,才能让最终用户开始使用该设备提供的服务。

图 10.8 – Web UI – 欢迎页面

图 10.8 – Web UI – 欢迎页面

从欢迎页面开始,我们选择开始初始配置并进入一个模拟的主菜单,侧边栏中有简单的导航选项。此时,最终用户将看到一些明显的选项,这些选项在初始配置事件之后也应继续保持可用。

在这个主要配置菜单中,最终用户将拥有一些关键选项,这些选项应根据需要进行规划——管理员访问、用户访问、网络配置、恢复出厂设置,当然,还有处理更新的方法。

由于最终用户急于开始使用该设备,逻辑的第一步包括引导最终用户设置管理员密码,然后配置网络/主机名。

在这个示例中,我们将看到设备管理主菜单的简化基于 Web 的 UI 至少应包含哪些内容。

图 10.9 – Web UI – 设备主配置菜单

图 10.9 – Web UI – 设备主配置菜单

假设我们在这里选择了网络配置,并希望为该设备设置基本的网络设置。此类初始配置的基本需求不仅应包括网络配置,还应允许最终用户分配适当的主机名,以便系统也能通过他们自己的 DNS 系统进行引用。

图 10.10 – Web UI – 网络配置

现在,我们已经通过简洁的基础设备配置过程引导了新的最终用户,他们可以利用您的产品提供的所有出色服务。最终,和现在的任何计算机系统一样,该设备将需要打补丁和更新,这将引导我们进入下一部分。

更新控制 – 文本 UI

您设备的最终用户体验将不完整,除非您为设备添加一个获取更新的方法。所谓更新,指的是操作系统的错误修复和增强、应用程序的补丁和增强、新功能,甚至如果您的解决方案是物理设备,还包括固件更新。

创建这种类型的界面还创建了一个边界层,将最终用户能够做的事情与设备可以为自己做的事情区分开来。我们必须消除任何可能导致最终用户直接访问操作系统本身的需求或借口。

根据使用场景和部署方法,界面应考虑如何呈现更新。由于隔离的系统无法连接互联网检查更新,因此界面应能够以其他方式接收更新。USB 闪存盘、tar 包和 ISO 镜像都是可以将更新传递给最终用户的方式,然而,最终用户需要将它们传送到界面,并且设备应处理这些更新,而不让最终用户访问操作系统。

这是一个文本 UI 中的设备更新控制示例,其中设备可以访问互联网检查更新。

图 10.11 – 文本 UI 更新菜单

图 10.11 – 文本 UI 更新菜单

现在我们已经解决了为设备提供更新的基本需求,接下来我们可以讨论另一个关键的最终用户功能:设备重置。

恢复出厂设置控制

每个好的设备都应有一种将其恢复到出厂新状态的方法。为最终用户创建这个体验,还可以简化他们将设备重新配置到公司不同网络或位置的过程,通过删除任何存储的应用数据或以前的配置。这种功能还可以让客户放心,如果他们将设备寄回公司,可能敏感的数据已经被擦除。接下来的截图将展示这在文本 UI 和网页上的示例。

让我们从一个网页 UI 重置功能页面开始。这个页面将呈现一个两步流程,确保他们确实知道机器将恢复到全新状态(所有数据和配置已被擦除)。为了实现这一状态,他们首先需要在界面中勾选复选框,然后按下重置按钮。

重要提示

我还建议弹出窗口询问他们是否再次确认是否真的想恢复出厂设置,如果你想做得更人性化的话。

图 10.12 – 网页恢复出厂设置示例

图 10.12 – 网页恢复出厂设置示例

这里是一个文本 UI 中的恢复示例。最终用户会看到一个提示,确认他们是否真的要将设备恢复到出厂新配置并擦除所有数据。就像之前展示的网页示例一样,他们始终可以选择取消操作。

图 10.13 – 文本 UI 中的示例恢复出厂设置

图 10.13 – 文本 UI 中的示例恢复出厂设置

我相信这些针对您未来 UI 所需功能的模拟已经为您提供了有价值的见解。当然,您的 UI 将显得更加精致,并与贵公司产品的品牌指南保持一致。通过建立一个安全的 UI/终端用户环境,您为您的解决方案确保了另一个安全因素——防篡改性。现在,让我们进入章节总结部分。

总结

再次感谢你与我一同继续这段旅程。在本章中,我们回顾了为什么锁定我们的设备至关重要。我们总结了一些需要考虑的硬件和存储安全选项。最重要的是,我们已经确定了确保良好用户体验的关键方法,同时通过将操作系统的访问隐藏起来,保持安全性。

在下一章中,我们将深入探讨所有可用的信息资源,帮助你和你的团队保持在威胁环境的前沿。

第三部分:构建链、设备生命周期与持续改进

在这一部分,我们将回顾您的设备的额外加固过程,探讨如何将一些关键的政府安全标准应用于系统,以及如何从各个方面收集信息,以便在设备生命周期内持续改进。

本部分包括以下章节:

  • 第十一章了解威胁环境——保持信息更新

  • 第十二章我的设备通信和交互安全吗?

  • 第十三章应用政府安全标准——系统加固

  • 第十四章客户和社区反馈循环

第十一章:了解威胁格局 – 保持信息畅通

在本章中,我们将进行一次数据收集之旅,这与超级技术性的动手练习略有不同。相反,我们将通过增强数据收集工作来锻炼思维。这不是用户数据或性能数据,而是潜在的威胁和预防数据——贯穿其中的宝贵信息。

我将带你快速浏览一些网站、博客和其他各种资源,这些你将想要加入到你个人的安全工具包中。在我带你穿越这片丛林之前,我会先给出几个免责声明。首先,单单提到这些内容,并不意味着我对其进行推荐。你聪明且富有资源,完全能够根据即将学到的内容做出自己的决策。其次,我承认我的语言能力有限;我知道我遗漏了许多外文和非英语网站。这并不是因为我没有结论,而是因为一旦语言障碍存在,几乎不可能涵盖所有内容。幸运的是,大多数国际技术网站自然都会使用英语。

跟随这些资源,订阅新闻通讯,并确保你的供应商通过电子邮件向你发送更新,这是确保你和你的团队保持信息畅通并做好准备的重要一步。我还建议你不仅仅是观察;如果可能的话,积极参与并在安全社区内产生积极影响。

请理解,本章旨在引导你到可用的信息资源(大多数是免费资源)。我希望这能为你和你的团队提供一个良好的起点,帮助你们在收集信息时做出更明智的决策。

作为本章的补充,将会有一份包含大量网址和建议的备忘单,其中涵盖了我们在本章讨论的内容。你可以在本书的 GitHub 仓库中找到它(github.com/PacktPublishing/The-Embedded-Linux-Security-Handbook/blob/main/Chapter11/Resource_Cheat_Sheet.pdf)。我计划将这份备忘单保持为一个动态文档,并在有更新时进行更新。所以,记得定期查看该仓库以获取最新信息。

在本章中,你将学习到许多公开和商业上可用的资源。你将了解如何找到与设备相关的安全数据,以及如何将这些信息应用到你的构建链中。我也希望能引导你积极参与,并加入 Linux 社区。

本章将涵盖以下主要内容:

  • 在网络上导航信息与虚假信息

  • 了解哪些漏洞可能会影响你的构建

  • 成为解决方案的一部分

在网络上导航信息与虚假信息

正如我们大家所知道的,并非所有互联网资源都是平等的。有些可以被视为璞玉,而大多数网站一般只是还可以。我还觉得有必要提到的是,有些网站根本是需要避免的地方,哪怕是付出任何代价也不要去触碰。我们很少知道哪些网站属于这一类,直到为时已晚。可以肯定地说,我们每个人至少都有过一次点击了某个链接,然后在页面加载完成之前就对自己说,“天啊,为什么我点了这个?!”瞬间的后悔。我的唯一建议是,仔细考虑并筛选自己的信息来源。

在接下来的几个部分中,我将重点介绍一些你和你的团队应该利用的优秀资源。这些资源包括政府机构的合规性资源、开源资源、商业可用内容以及博客、新闻通讯和视频频道。我并不是说你必须使用所有这些资源,我只是为你提供了一场永远不会过时的知识盛宴。吃得好,吃得常。有时,我建议你换个口味,尝试不同的资源。

由于我更喜欢保持积极态度,因此我选择不去过多关注那些我认为无效或根本没有生产力的网站。我也从不愿意为把某人引导到这些网站上负责。永远不会。如果我做了那样的事,我想我都无法安然入睡。话虽如此,带上你对知识的渴求,让我们继续深入探索我们的一大堆安全资源盛宴吧。

政府资源

让我们从常见的网站开始——这些网站由于您的行业、地点或市场地位,受到一个或多个合规性法规的约束。弄清楚到底需要什么可能会很繁琐,而实施这些要求则更加有趣

不要期待直观的界面、时尚的主题和图形,甚至有时连导航的简便性都没有。政府网站通常考验人的耐心。然而,它们也是在需要详细技术安全要求和配置以确保合规时,真实可靠的信息来源。不过,你可以期待的是极高的专业性和技术细节。忽视这些资源可能会自担风险。以下是我个人认为的美国政府资源,它们是收集和维护与安全威胁相关信息的关键起点,可以应用到您的设备构建链中。

计算机安全资源中心(CSRC)

这是由 NIST 托管的网站。可以说,这是进入北美所有网络安全领域的门户。世界上没有其他网站或组织能提供如此详细和深度的信息。

话虽如此,这里很容易迷失。为什么呢?因为信息实在是太多了,而且它们还在不断变化。项目、事件、出版物,甚至是如何正确与 NIST 互动的信息,都可以在这里找到。

从这里开始。做笔记,收藏书签,规划后续操作。

国家漏洞数据库 (NVD)

这个也由 NIST 主办,是 CVE 数据库的所在地。如果是风险或漏洞,这里都有记录。经常在这里搜索。它维护得很好,是网络安全漏洞的真实支柱。

这个资源的价值在于其可搜索性。这里是一个示例:

图 11.1 – 搜索 NIST 的 NVD

图 11.1 – 搜索 NIST 的 NVD

很可能,你很快就会与 NIST 网站中的搜索功能变得非常熟悉。希望本书的介绍能够帮助你找到所需的资源。这就是事情的本质。这个网站将成为你在风暴中的灯塔,所以越早习惯它的独特性和用户友好性越好——这里提供的信息真的是无价的。我只是希望他们能让界面看起来更舒服一些,懂我意思吗?接下来,让我们继续旅程,学习如何以及配置什么来增强我们的系统安全。

安全技术实施指南 (STIGs)

这些是由国防信息系统局DISA)发布的,针对他们的主要客户——美国国防部(DOD)。这些作为完整的配置库发布。DISA 宣传其使命是:“为联合战斗员开展 DODIN 操作,确保在所有战斗领域中实现致命性,以捍卫我们的国家。”由于其军事背景,访问该网站会受到监控,甚至不登录时,你也需要同意追踪你的使用情况。

这里是今天可用于 Linux 的 STIG 示例:

图 11.2 – 今天可用的 Linux STIG

图 11.2 – 今天可用的 Linux STIG

为了正确查看这些内容,你还需要下载它们的查看器工具。利用它们的建议将有助于确保你的解决方案已经以最佳的安全级别进行配置。

就我个人而言,我在我的实验室中的多个系统以及我的工作笔记本上都安装了 STIG 查看器。我更倾向于保持随时可以深入了解可能需要的配置,无论我身处何地。随着你自己旅程的推进,你可能也会得出相同的结论。

让我们继续旅程,了解一下商业可用资源。

商业资源

我们必须去那里。书中提到的并非所有内容都是免费的。这是可以预料的,尤其是在企业安全领域。并非所有这些工具和资源都能在家庭实验室中可行运行,因为成本和硬件要求最终可能会使大多数人无法实现。尽管如此,所有这些解决方案提供商确实提供了免费且公开可用的资源,大家都可以利用。

这份供应商列表并非详尽无遗,也不应将此处的任何列出公司视为背书。了解主要玩家。以下是其中的一些。

Reversing Labs®

总部位于马萨诸塞州剑桥的 Reversing Labs®为那些具备高级安全意识的用户提供了独特的产品。它们的旗舰产品具有在没有源代码访问权限的情况下检查风险的能力。它们还提供广泛的企业安全和物料清单解决方案。

Qualys®

总部位于加利福尼亚州福斯特市的 Qualys®提供广泛的产品,专门为多个行业领域量身定制,包括政府。它们最为人知的是能够扫描并检测企业范围内的风险。Qualys 在安全行业中是一个巨大的玩家。

Tenable®

总部位于马里兰州哥伦比亚的 Tenable®是另一家安全行业的巨头。它们同样以其安全扫描工具而闻名,尽管它们还有许多其他产品和解决方案。

McAfee®

总部位于加利福尼亚州圣荷西的 McAfee®是病毒防护领域的知名品牌。它们还提供许多其他产品和服务,主要集中在安全 VPN 和身份保护方面。

诺顿®

总部位于亚利桑那州坦佩和捷克共和国布拉格的 Norton®以其杀毒解决方案、身份保护、性能管理和 VPN 解决方案而闻名。Norton 的产品通常仅支持 Windows、macOS 和 Android(实际上是 Linux 的一个变种)。

卡巴斯基®

总部位于英国伦敦的卡巴斯基®公司是另一个在杀毒领域的巨头。它还在身份保护和智能家居监控领域拥有产品,并且提供广泛的 Linux 支持。

社区资源

无论是 Linux 社区还是安全社区,都为公众提供了丰富的在线资源。用户组、新闻通讯、文档、最佳实践指南以及项目网站仅仅是你开始收集数据的起点。

这些资源不需要你支付任何费用,只需时间和精力。在我看来,这段时间非常值得。打字时我并没有忽略这一点;这句话将会出现在我的书里。是的,我其实重复了一遍自己,并笑出了声。我坚持这个立场。参与社区,成为社区的一部分。

网络安全中心®(CIS®)

CIS基准通常被视为配置安全 Linux 系统的全球标准。预计会有从简单到复杂的优秀详细配置建议,可以应用于你的解决方案。CIS®是一个由社区驱动并支持的非营利组织,旨在帮助全球社区构建更安全的解决方案。

当我第一次开始探索 Linux 安全资源时,那似乎是一个世纪之前的事情了,而 OpenSCAP 网站是我的第一个“中途站”。也许这只是因为我自认为是一个以社区为先的工程师。花时间在这个网站上就是高质量的时间。CIS 网站拥有大量的信息、安全基准、配置建议,甚至是预构建的、准备好部署的系统镜像。

如果政府合规性不是你的任务要求,那么这里只提供的资源可能就足以满足你大部分甚至所有的需求。我不会代替你做任何假设,因此我建议你在利用 CIS 提供的资源时,形成你自己的观点和评估。

OpenSCAP

一个重要的社区资源是 OpenSCAP 网站。这个网站为你提供了对系统进行行业标准、政府或自定义政策扫描的工具。它真的是你团队构建链中不可或缺的工具。我们将在后面的章节中更深入讨论这个工具。如果不使用这个工具或类似工具,可能会让你的产品面临未来的风险。选择时请谨慎。我真心希望你成功。

这是 OpenSCAP 网站上可用工具的一个很好的例子:

图 11.3 – 来自 OpenSCAP 的工具

图 11.3 – 来自 OpenSCAP 的工具

Linux 用户组

Linux 用户组是以最低的投入方式参与的绝佳途径。参加这些会议可以远离营销人员和销售人员的干扰,给人一种耳目一新的感觉。大多数时候,它是工程师们与其他工程师分享经验的场所。多年来,我主持了许多这样的会议,发现与会者来自技术领域的各行各业。然而,我常常发现学生、IT 经理甚至高管也悄悄地参加这些会议,目的是在一个无压力的环境中了解新技术。与其他所有社区资源相比,用户组是与那些活跃参与技术的人建立联系的最佳途径。

安全用户组

安全用户组(或网络安全用户组)与以 Linux 为焦点的用户组一样具有教育意义。它们通常由产品供应商主办,但并非总是如此。这些小组通常更专注于某个行业领域或特定产品集。我强烈推荐加入一个或多个安全用户组。你所获得的知识将是无价的,甚至可能帮助你提前防止产品灾难的发生。

了解你的团队使用的工具以及他们希望在设备中使用的社区资源是关键知识,并且是进入下一部分的完美过渡。

了解哪些漏洞可能会影响你的构建

与追踪产品内容同样重要的是,追踪这些内容与现存漏洞之间的关系,它不仅为你提供了一个明确的清单,帮助你从缺陷和安全漏洞的角度确定需要追踪的内容。这些清单不是持久的,因为随着更新,某些包可能会被弃用,依赖关系也会发生变化。追踪工作随着产品的结束而结束,但安全问题永无止境。黑客和不法分子从不休息。投资优质的软件和更好的流程。始终,始终,始终知道你的“配方”中的成分。

在前面的章节中,我们详细回顾了如何创建一个软件清单,列出你产品的特定构建或发布版本中包含的内容。我们还回顾了硬件方面的影响,如固件和驱动程序。这些知识为你提供了一个虚拟的检查清单,帮助你检查所有可能存在的缺陷和安全问题,并为所有问题提供解决方案。这些清单成为你开始可能漫长且永无止境调查的起点。

平均的 Linux 发行版可能有 7,000 个或更多的软件包可供选择。你的安全团队是否希望为你追踪所有 7,000 个包?他们是否希望你使用如此多的包?这就是人们通常讨论如何最小化软件足迹的地方(即,只安装最基本的软件包以确保系统正常运行)。一旦你自己进行这样的追踪,你会更加欣赏最小化安装的价值。

更小的足迹不仅让从更新角度支持解决方案变得更容易,还减少了攻击者可能攻击解决方案的途径。所以,我建议在初始原型阶段使用你喜欢的任何内容,但在去除(或根本不安装)任何不需要的东西时要精确和谨慎。这项工作将使你更加贴近你的产品,并进一步帮助你在我们深入了解如何追踪解决方案组件时。

基于你的组件进行智能搜索

查找可能影响你产品的所有问题,可能会变成一项全职工作,所以除非你拥有无限的预算,否则你和你的团队需要高效地完成这项工作。在可能的情况下,使用自动化确认是否存在问题。

这可能需要你创建一些脚本或一个组件数据库,并将所有来自社区源或供应商的电子邮件更新、发布说明和通讯信息输入到该机制中。

如果没有自动化,这将是一项非常繁琐的工作——总有一些问题会漏掉,哪怕是最强大的团队也难免出现这种情况。所以,我强烈建议整理这些数据,以便你的团队能够定期审查任何有趣的发现。在我看来,知道某个软件包有一个未修复的公开 CVE 漏洞是关键信息。我敢肯定,你的团队也会同意这一点。

可惜的是,这里并没有一个真理支柱可以为你提供指导。从多个来源获取漏洞和安全问题数据是最好的。首先是你希望已经订阅的供应商电子邮件更新,但这并不是最后的途径。你还可以从博客、新闻通讯和政府合规网站收集数据。通过这些,你应该能够为你的产品创建一个虚拟的安全天气报告,并将这些知识与产品的路线图结合起来。

将所有收集的数据存储为文本。这时,一套好的脚本可以帮助你查看你的清单,看看是否有任何软件包或硬件受到影响。尽管这是一个复杂的过程或工作流,但你最终应该能够创建一个自己的数据库来进行报告。在你完全识别出所有数据和数据源之前,电子表格可能会更方便。CSV 格式也能给你一个快速入门的机会。无论如何,你可以通过多种方式梳理这些数据,创建一个简洁的组件级报告,将为你提供所需的虚拟安全天气报告。这可能会有一些盲点,因为你是从已知的可搜索数据构建的。尚未发现的零日漏洞仍然可能对我们造成伤害。

构建链中的安全扫描工具是另一个数据来源,而且是一个至关重要的源头,不容忽视。但请不要 100%依赖它们。一些供应商还提供额外的产品,以补充他们销售的扫描工具。这些工具,如 Tenable 的漏洞管理套件,能协助你的工作,并提供你所寻求的全局视角。

我发现自己陷入了困境,虽然不太愿意提及,但我认为在不久的将来,AI 的创造性应用可能会是件好事。所以,请稍微容忍我一下。当安全专家今天开发 AI 增强的安全工具时,你也可以相信,全球各地一定有不法分子在寻求利用 AI 将他们的恶意行为提升到一个新的水平。话虽如此,我还是建议保持警觉,接下来让我们看看你如何能成为解决方案的一部分。

成为解决方案的一部分

你可以通过许多方式为 Linux 和安全社区做出贡献。

通过阅读这本书,如果你还没有深入研究嵌入式 Linux 系统的安全性,你已经开始了这段旅程。欢迎加入,感谢你购买我的书。不要让这只是一个单一的事件。时不时查看这本书的 GitHub(github.com/PacktPublishing/The-Embedded-Linux-Security-Handbook)。随着事态的发展,它也会进行更新。

这个社区可能和现在寻求教育、答案或指导的许多人一样古老(甚至更久)。年龄在这里几乎没有意义,也不应该有意义。重要的是你是否有学习或分享知识和经验的渴望。安全风险是不分年龄的。如果你不做好准备,它们会找上你。因此,我们有一个充满活力和多样化的工程师、开发者、测试员、技术写作人员和思想领袖的社区。我并不打算做出过于自命不凡的规划,告诉你该如何或不该如何参与或贡献。我和社区中的许多人一样希望的,只是你能迈出那一步,积极参与其中。在接下来的章节中,你将看到我所说的内容。

参与开发过程

你不需要是开发者才能在这里做出贡献。你可以志愿测试早期版本的代码,提交错误报告,甚至提交增强请求(RFE)。你提供的反馈对于开发人员来说至关重要。

如果你决定成为这一过程的一部分,你可以加入多个 Linux 社区。每个开源社区都有自己的贡献和积极参与的流程与指南。每个社区都有其独特的文化,但所有社区都会欢迎你的加入。

下面是一些关于如何加入多个流行的社区 Linux 发行版的测试和开发工作的链接:

谁知道呢?你的贡献可能会帮助别人避免很多麻烦,同时解决你自己遇到的 Linux 安全问题。作为社区的活跃成员,这不也会让人感到些许自豪吗?让我们继续看看如何在社区中积极参与。

多年来,我的个人和工作经验让我对许多社区开发项目有了独特的了解。我还是 OpenStack 社区的成员(也叫 OpenInfra 社区)。对我来说,选择一个要参与的群体并不容易。有许多很棒的群体。我推荐的做法是跟随你的内心。加入一个离你最喜欢的 Linux 发行版最近的社区。如果那不适合你,至少可以考虑加入一个专注于你在工作中使用的发行版的用户组,这也是我们接下来要讨论的内容——用户组。

加入用户组

我认为,聚会用户组是社区中最好的社交方式。它们没有过多的产品推销,而是专注于分享解决实际技术和安全问题的创新方案。

你不需要成为火箭科学家或拥有什么高级头衔。对我来说,这两种情况都不适用。我只是一个普通人,在我的职业生涯中获得了一些相当有趣的知识和经验。这些小组是学习或分享你所学的好地方。一天,你可能甚至会选择参与到小组的领导工作中,或展示你和你的团队所制定的解决方案。我真的很喜欢用户小组,并且在我的日程允许时,享受分享。

了解所有的事情,我想我们都能同意,实际上这是完全不可能的。30 年来,我一直活跃在 Linux 社区,而且我仍然在不断学习新的东西。有时很难传达 Linux 的广度、深度和影响力。你可以遇到、与其他专注于 Linux 不同方面的人建立联系并向他们学习,而这些你可能并未关注过(反之亦然——你也可以帮助他们)。我的意思是,永远不要认为你的经验不重要。它们很重要。分享你的经验和解决方案,可能会为别人省下大量的麻烦。

加入用户小组是一个让你在职业上成长的途径,唯一需要付出的就是你的时间和注意力。即使你选择仅仅旁观,我敢保证,你也会有大量的学习机会。有一天,我敢打赌,会有一个讨论,而你(没错,就是你!)将是那个提供别人一直在寻找答案的人。或许,这种情境也能成为你想要更多参与和投入的催化剂。组织、设置、展示,以及在即兴技术主题上进行快速演讲——这些都是你可以参与的方式。你可能会发现你也很喜欢用户小组。

为什么我们要这样做?很简单:分享就是关心……而关心有助于建立社区。不论你在哪个层次上参与,都可以参与。知识和网络的可能性是无穷的。

利用 MeetUp

MeetUp 是一个旨在赋能和连接具有共同兴趣的人的网站。这里不仅有技术爱好者,还有登山者、书籍爱好者、动物保护主义者、骑行者以及更多的兴趣小组(比我能想到的还要多),他们都在寻找你。

查找你附近的 Linux 用户组或网络安全小组:www.meetup.com/。这是一个无价的资源,可以帮助你与成千上万的志同道合的爱好者建立联系。我鼓励你试试 MeetUp:你可能会喜欢它。我期待着不久后在 Linux 见面会上见到你。

总结

感谢你和我一起继续踏上这段探索 Linux 世界中网络安全资源和参考资料的精彩旅程。正如我之前提到的,请经常查看本书的 GitHub 仓库,了解更新和新信息,特别是更新的备忘单资源。

我相信你已经享受了这一章的内容,它不同于让你输入代码并测试新技术。我知道技术领域每天都在变化。这就是为什么我强烈建议你尽可能寻找可靠的资源。

本章我们简要提到了一许多公司和资源。你现在应该对一些最具影响力的公共和私营资源(超出你自己供应商的范围)有了牢固的掌握。既然你已经知道如何确定构成整体解决方案的内容,你也已具备了如何在这些组件中寻找风险的能力。最后,也是最重要的,你现在知道有一个庞大的以 Linux 和安全为核心的社区,随时准备帮助你并欢迎你加入。他们重视你的想法和反馈。分享并参与其中,真的是双赢的。

现在让我们进入下一章,回到一些严肃的技术工作。准备好在下一章中了解你的设备和外围设备是如何进行通信的吗?

第十二章:我的设备的通信和交互安全吗?

可以说,唯一真正安全的计算机就是关机并锁在保险库里的那台。虽然这样没有乐趣,也没有可用性,但我们必须采取适当的措施,以限制漏洞暴露,同时确保系统能够继续执行它原本的任务。

在本章中,你将学习如何确定常用外部总线在硬件通信中的使用场景和局限性。我们将回顾防火墙网络安全。我们会通过一些实际操作来加固你基于 Web 的服务,使用 SSL 证书。我们还会深入探讨传统硬件和软件的问题,并以设备安全验证来结束本章内容。

你可能会问:“这对我的项目为什么重要?”简而言之,你可能把系统本身的安全性做好得无懈可击,但这个系统与外设或其他应用程序的连接,可能并不像你想象的那样安全。知晓即为预警。

本章的主要内容包括:

  • 总线类型及其问题

  • 通过证书增强安全性

  • 确认你的网络是安全的

  • 传统硬件和软件的限制

  • 在交付前验证你的解决方案

让我们进入第一部分,看看不同的系统总线。

技术要求

要完成本章的练习,你需要对你之前在第五章中构建的自定义 DNF 仓库所在的 Web 服务器拥有 root 权限。

如果你已经删除了该服务器/工作,你需要按照之前练习中的详细说明重新建立一个新的自定义仓库服务器,然后再开始本次练习。

总线类型及其问题

那么,什么是总线呢?最简单来说,总线是一种设备与系统 CPU 之间的通信通道。通过这个通道,设备的数据信号(来自或发送到设备)可以被 CPU 处理。如果没有这条通信线路,连接的设备将无法工作。

更通俗地讲,总线可以从最少的技术术语来描述。让我们看一下整体,忽略细节。总线是硬件、软件和所需电缆的总和,它们共同允许数据传输。我举一个非技术性的童年例子。你有没有用两个锡罐和一根绳子做过通信系统?那两个罐子通过绳子连接,当绳子拉紧时,它承载了你的声音(即数据),从一个罐子(外设)传递到另一个罐子(主处理器),接收端的最终用户会解读这些声音。

系统总线以更为技术化的方式实现这一功能,但结果是一样的。数据从外设传输到 CPU 并被处理。对于我的超级技术读者们,请允许我更深入一点。传感器、摄像头、控制器或其他直接连接外设时,会涉及多种总线,它们的交互通过连接介质传输,最终由系统 CPU 接收和处理。有几种标准总线,但在本章中,我们将重点介绍你在嵌入式 Linux 系统工作时可能遇到的最重要的几种,具体来说就是CAN 总线USB。在接下来的几节中,我们将重点讨论系统总线(以及标准连接类型和协议),这些总线利用外部连接到你的硬件。继续往下走时,我希望你能设想所有可能连接到你的解决方案的事物,无论是否经过你的许可。有时,正如我们在第十章中推测的那样,你必须几乎假设最终用户是个可能把三明治塞进录像机的婴儿。我知道提到录像机可能让人感觉自己变老了,但这样做是为了强调一个点,我希望这个点能被理解。计划最坏的情况,期待最好的结果。

会出什么问题呢?嗯,如果你的系统使用不安全的总线或外设连接,并且某个不法分子能够物理接触到该连接,它可能在你不知情的情况下被劫持(或者更糟)。当不安全连接被利用时,物理安全必须作为设计考虑和部署计划的一部分。

让我们也希望你的完美解决方案有一个定制外壳或外壳,遮住任何你不希望最终用户知道的端口。这种选项并不常见,但我觉得有必要提一下。此外,定制外壳还可以让解决方案看起来更美观。有些外壳甚至具有内置的防天气性。让你的使用场景引导你的设计。

重要提示

对于嵌入式 Linux 系统,我们假设外壳具有一定的防篡改功能,即使它只是一个警告贴纸,声明如果打开外壳则所有保修失效。因此,我们不会涉及系统硬件内部,如著名的PCI 总线……关于硬件和内核开发有无数相关文献,所以我们将专注于外部连接的部分。

说完这些,我们来谈谈一个家喻户晓的名字——我们都知道的总线和连接类型——通用串行总线USB)。

USB

自 1996 年首次推出以来,USB 接口已经成为几乎所有消费类设备的全球标准连接方式。现代 USB 端口具有如此多的多功能性(取决于设备),这也是它们在日常生活中无处不在的原因。

USB 使计算机能够连接鼠标、键盘、存储设备、打印机、游戏控制器、认证密钥以及许多其他类型的商业硬件。同一个端口还可以为一些设备如手机、平板电脑或便携电源单元充电。USB 甚至可以用来为系统添加多个显示器。

USB 在数据传输过程中并不保护你的数据。大多数人选择加密 USB 附加存储设备,但默认情况下,在访问或处理数据时,传输中的数据并没有加密。这一限制不仅限于 Linux 系统,而是所有使用 USB 框架的系统。

市面上有一些商用解决方案可以保护数据在传输过程中安全;然而,它们不是开源的,而且肯定不是免费的。它们作为企业级的数据丢失防护系统出售,支持多个平台(不仅仅是 Linux)。如果在将数据传输到 USB 存储设备时需要加密,你将需要使用这些第三方解决方案。

现在让我们进入下一部分,回顾 USB 连接。

USB 连接器

USB 系列连接器多年来一直在演变,但从一开始到现在,USB-A 可能是世界上最常见的连接接口。它可以在家庭墙插座、个人电脑、笔记本电脑、外部存储设备、客机座椅背后、汽车和休闲车的仪表板、太阳能发电机、充电宝中找到,简直无处不在……(是的,我知道这语法不太对,但我真想强调的是 USB-A 是无处不在的!!

USB 的讽刺之处在于,几乎所有展示的连接器至今仍然在积极使用。诚然,当前版本与旧版在所用材料的质量上有所不同,但这是为了更好地支持数据传输速度。数据线本身并不是安全问题,问题出在芯片和 USB 总线上。让我们快速看一下这些连接器类型。

在下图中,从左到右分别是 USB-B、USB-A、USB-mini、USB-micro 和 USB-C:

图 12.1 – 多年来的 USB 连接器

图 12.1 – 多年来的 USB 连接器

在思考如何比较你将遇到的各种 USB 标准版本时,我认为有必要以表格的形式展示一些关键数据,以便更易查看。尽管这些连接器可能都兼容,但不同版本的速度和吞吐量差异巨大且令人震惊。

下面是一个关于 USB 版本、性能和当前使用连接器的表格:

USB 版本 带宽 数据 传输速度 连接器
USB4 20 或 40 Gbps 2560–5120 MB/s C
USB 3.2 20 Gbps 2560 MB/s C
USB 3.1 10 Gbps 1280 MB/s A, C
USB 3.0 5 Gbps 640 MB/s A, B, C
USB 2.0 480 Mbps 60 MB/s A, B, Mini, Micro
USB 1.1 12 Mbps 1.5 MB/s A, B, Mini, Micro
USB 1.0 1.5 Mbps 1.5 MB/s A, B, Mini, Micro

表 12.1 – 不同 USB 版本的速度和能力

从上表可以看出,USB 标准在过去 30 年间的广泛连接范围经历了巨大的发展。USB 已经成为游戏规则的改变者和潮流的引领者,并将在未来许多年继续发展。接下来,我们来看一下它的前身——串行总线。

串行端口

因为串行端口以其极易受攻击而闻名,自旧版 Unix 时代以来,它们一直提供文本终端访问。如今,仍有许多串行设备被每天使用。键盘和鼠标(如今通过 USB 使用)仍然是非常普遍的,并且可能也是你解决方案的一部分。串行连接依然是工程师从笔记本电脑到网络设备(如交换机、防火墙和路由器)之间常用的方式。如今,这通常需要一个适配器设备,它通过 USB 连接到工程师的笔记本电脑,然后通过串行电缆连接到要管理的设备上的串行端口。这些设备一旦连接到你的 Linux 系统,便会自动建立连接,你无需做任何操作。

串行端口(更常被称为终端端口)可以是物理的也可以是虚拟的。如今,大多数物理串行连接通过 USB 总线自动协商;然而,在旧系统上,这些设备可能使用 PS2 连接或更早的串行端口,也就是DB9。串行端口还可以被工业自动化系统、打印机、扫描仪和一些医疗设备使用。下图展示了串行连接的女性连接器(左)和男性连接器(右):

图 12.2 – 串行连接器示例

图 12.2 – 串行连接器示例

Linux 系统也可以有虚拟串行连接。了解你的系统如何映射这些连接非常重要。那么,为什么你需要关心这个呢?这直接影响到可以同时与系统建立多少个终端会话。如果你的设备是基于控制台/文本的设备,这一指标对于其管理和控制至关重要。用最简单的术语来说,这个指标表示可以同时打开多少扇门。当这些 TTY 控制台会话对你的设备用户体验不至关重要时,它们应该尽量受到限制,而不会破坏设备的正常运行。

为了更好地了解你的系统在启动时启动了多少个 TTY 会话,这里有一个示例命令,展示了你的系统如何命名和映射这些端口。可以将每一个端口视作一个打开的门,它要么应该被锁上,要么被封住,要么只是被看守。

让我们来看看在当前系统中可以进行多少个 TTY 会话:


$ ls -l /sys/class/tty/*

这部分的输出肯定会很长,因此我已经进行了截断……你将看到的是一个详尽的物理和虚拟终端端口可能性列表。


     ((( output truncated )))
lrwxrwxrwx. 1 root root 0 Aug 25 09:33 /sys/class/tty/ttyS4 -> ../../devices/pci0000:00/0000:00:16.3/0000:00:16.3:0/0000:00:16.3:0.0/tty/ttyS4
lrwxrwxrwx. 1 root root 0 Aug 25 09:33 /sys/class/tty/ttyS5 -> ../../devices/platform/serial8250/serial8250:0/serial8250:0.5/tty/ttyS5
lrwxrwxrwx. 1 root root 0 Aug 25 09:33 /sys/class/tty/ttyS6 -> ../../devices/platform/serial8250/serial8250:0/serial8250:0.6/tty/ttyS6
lrwxrwxrwx. 1 root root 0 Aug 25 09:33 /sys/class/tty/ttyS7 -> ../../devices/platform/serial8250/serial8250:0/serial8250:0.7/tty/ttyS7
lrwxrwxrwx. 1 root root 0 Aug 25 09:33 /sys/class/tty/ttyS8 -> ../../devices/platform/serial8250/serial8250:0/serial8250:0.8/tty/ttyS8
lrwxrwxrwx. 1 root root 0 Aug 25 09:33 /sys/class/tty/ttyS9 -> ../../devices/platform/serial8250/serial8250:0/serial8250:0.9/tty/ttyS9

了解如何追踪这些连接对于维护设备安全至关重要。接下来我们来看一下另一种也使用 DB9 连接器的总线——CAN 总线。

CAN 总线

控制器局域网 (CAN) 总线是一种车辆标准。它的主要目的是控制 电子控制单元 (ECUs) 之间的通信。它最早于 1983 年推出;然而,至今仍没有标准连接器,尽管 DB9 连接器今天似乎已经成为事实上的标准。

由于如今的汽车正变成滚动的数据中心(即使是非自动驾驶的汽车),我觉得有必要提到这种总线类型,因为许多制造商正在跃跃欲试,准备在这一不断发展的领域中构建嵌入式系统。

然而,CAN 并不限于汽车。CAN 总线架构可以在海事环境、农业设备,甚至是大型建筑中用于控制电梯、自动扶梯和其他建筑自动化系统中看到。它甚至被现代机器人技术所利用。

可惜,CAN 没有加密功能。请保持警惕,留意这个问题。CAN 的另一个问题是缺乏身份验证。这意味着,最终,任何能够访问总线的人都能控制总线。所有的安全性都将被放弃。会发生什么不好的事情呢?

有一个专门的社区致力于破解汽车的控制系统。大多数参与这项活动的人,目的是从自己的车辆中挤出更多的性能。没有恶意,只是工程师的好奇心。不过,恶意行为者很容易访问到汽车的锁、GPS 记录或控制系统,甚至可能进行其他恶意活动。

另一个因素,像 USB 和串口一样,缺乏加密意味着任何通过总线传输的凭证都是以明文方式传输的。任何监控总线流量的人都可以看到这些数据,并可能利用它做一些不太友好的事情。

随着越来越多的车辆依赖电子设备来创造更好的驾驶体验,大家都希望 CAN 标准本身能在下一个版本中加入一些急需的安全功能。

接下来我们来讨论设置加密时的一个关键组件——创建证书。

使用证书增强安全性

证书被用于全球许多安全通信领域。你的硬件和软件供应商通常会为他们的驱动程序和操作系统包进行数字签名。受信任的机构使用证书来确保你可以安全地使用 DNS 和互联网。证书的使用案例非常广泛。通常,这些安全证书是通过全球 证书颁发机构 (CA) 获得的。许多互联网服务提供商(ISP)也能够为他们的客户颁发 SSL 证书。

这些共享的系统证书使得像 NSS、TLS、OpenSSL 以及应用程序等能够通过系统证书(信任锚)共享信任源。没有 SSL 证书将阻止你使用加密的 Web 服务器。

在 Linux 中也可以创建自签名证书。这些证书通常足够用于内部实验室工作,但在生产环境中被认为不足够,绝对不适合用于你的产品。

在思考在哪里展示一个适合实验室或演示用途的例子时,我想到这个问题:“我们可以在哪些地方考虑使用证书?你的 DNF 仓库服务器?”

让我们通过一些动手练习来探索这个思路。

练习 1:创建一个自签名证书

在这个动手练习中,我们将创建一个自签名证书,可能用于加密一个 Web 服务器。让我们开始:

  1. 首先,我们将验证网络服务器是否按之前在第五章中配置的方式托管我们的仓库。

    
    $ sudo systemctl status httpd.service
    ● httpd.service - The Apache HTTP Server
         Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; preset: disabled)
        Drop-In: /usr/lib/systemd/system/service.d
                 └─10-timeout-abort.conf
         Active: active (running) since Sun 2024-10-06 17:53:55 EDT; 2min 43s ago
           Docs: man:httpd.service(8)
       Main PID: 1215 (httpd)
         Status: "Total requests: 1; Idle/Busy workers 100/0;Requests/sec: 0.00617; Bytes served/sec:  12 B/sec"
          Tasks: 178 (limit: 38323)
         Memory: 21.2M (peak: 22.4M)
            CPU: 225ms
    CGroup: /system.slice/httpd.service
                 ├─1215 /usr/sbin/httpd -DFOREGROUND
                 ├─1294 /usr/sbin/httpd -DFOREGROUND
                 ├─1295 /usr/sbin/httpd -DFOREGROUND
                 ├─1296 /usr/sbin/httpd -DFOREGROUND
                 ├─1297 /usr/sbin/httpd -DFOREGROUND
                 └─1298 /usr/sbin/httpd -DFOREGROUND
     Oct 06 17:53:55 bm02.local systemd[1]: Starting httpd.service - The Apache HTTP Server...
    Oct 06 17:53:55 bm02.local (httpd)[1215]: httpd.service: Referenced but unset environment variable evaluates to an >
    Oct 06 17:53:55 bm02.local httpd[1215]: Server configured, listening on: port 443, port 80
    Oct 06 17:53:55 bm02.local systemd[1]: Started httpd.service - The Apache HTTP Server.
    

重要提示

你需要替换成你为系统配置的主机名或 IP 地址。

  1. 确认服务通过浏览器托管了你的仓库。

图 12.3 – 通过浏览器验证你的仓库

图 12.3 – 通过浏览器验证你的仓库

  1. 我们现在将开始设置环境,首先设置一个系统变量。在这一步中,将<hostname>替换为你系统的 FQDN。作为 root,执行以下命令。

    
    .pem file, which will store your certificate information.
    
    

    .pem 文件。

    
    # ls -l *.pem
    EmbeddedBook as the challenge password at the end. Please feel free to use your own challenge password (but do make a note of it for later). As root, run the following command:
    
    

    openssl req -new -key ${ssl_name}.pem -out ${ssl_name}.csr

    
    Let’s see the interactive prompts/output:
    
    

    你即将被要求输入一些信息,这些信息将被纳入

    输入到证书请求中。

    你即将输入的内容被称为“区分名称”或 DN。

    有很多字段,但你可以留空某些字段

    对于某些字段,将有默认值,

    如果你输入'.',该字段将留空。


    国家名称(2 个字母代码)[XX]:US

    州或省名称(全名) []:MA

    本地名称(例如,城市)[默认城市]:威尔明顿

    组织名称(例如,公司)[默认公司有限公司]:嵌入式安全书籍

    组织单位名称(例如,部门) []:开发

    通用名称(例如,你的名字或服务器的主机名) []:bm02.local

    电子邮件地址 []:admin@bm02.local

    请按要求输入以下“额外”属性

    将随证书请求一起发送

    挑战密码 []:嵌入式书籍

    .csr 文件正确。

    
    # ls -l *.csr
    -rw-r--r--. 1 root root 1850 Aug 25 21:22 bm02.local.csr
    

    这个 CSR 文件是你在申请企业 SSL 证书时会发送给 CA 的文件。我们也可以利用这个文件在本地创建一个临时的自签名证书。

    
    
    
    
  2. 让我们创建一个有效期为 90 天的临时证书。

    
    # openssl x509 -req -days 90 -in ${ssl_name}.csr \
    -signkey ${ssl_name}.pem \
    -out ${ssl_name}.cert
    

    你的输出应该类似于以下内容:

    Certificate request self-signature ok
    <hostname> with your system’s hostname. Mine is shown just for example purposes.
    
    

    ls -l

    
    Your output should contain at least the files shown that are identified by your system’s hostname.
    
    

    -rw-r--r--. 1 root root 2110 8 月 25 21:30 bm02.local.cert

    -rw-r--r--. 1 root root 1850 8 月 25 21:22 bm02.local.csr

    -rw-------. 1 root root 3272 8 月 25 21:12 bm02.local.pem

    
    

哇,难道这不简单吗?!你现在已经创建了第一个自签名的服务器证书。除非没有其他方式来保护你的网络服务,否则请永远不要在生产环境中使用这个证书。现在我们已经创建了证书,让我们在下一个练习中将它应用到实际的网络服务中。

练习 2:将证书添加到自定义仓库服务器

在本练习中,我们将把之前创建的自签名证书安装到你之前搭建的 web 服务器中,用来托管你自定义的 DNF 仓库。完成后,web 服务器将默认使用 HTTPS 协议,而不是之前的默认 HTTP 协议。协议的更改意味着你还需要确保防火墙规则已经更新。我们开始吧。

  1. 以 root 用户安装 mod_ssl

    
    # dnf install -y mod_ssl
    

    你的输出可能很长,但它应该大致像这样——我已将输出截断以节省空间。

    ((( truncated output )))
    Running transaction check
    Transaction check succeeded.
    Running transaction test
    Transaction test succeeded.
    Running transaction
      Preparing        :                               
    
               1/1
      Installing       : mod_ssl-1:2.4.62-2.fc40.x86_64
    
               1/1
      Running scriptlet: mod_ssl-1:2.4.62-2.fc40.x86_64
    
               1/1
    Installed:
      mod_ssl-1:2.4.62-2.fc40.x86_64
    .cert file (mine is shown as an example).
    
    

    将 .pem 文件放到正确的目录。记得替换成你自己的 .pem 文件(我的文件作为示例)。

    
    .pem file to an additional directory. Remember to substitute your own .pem file (mine is shown as an example).
    
    

    /etc/httpd/conf.d/ssl.conf 文件以 root 用户身份编辑。按照指示取消注释并编辑相应行。完成修改后,保存并退出编辑器。

    
    443.
    
    
    
    
    
#ServerName www.example.com:443
ServerName bm02.local:443
  1. 将这一行更改为你自己的 CRT 文件——我的文件作为示例。
SSLCertificateFile /etc/pki/tls/certs/localhost.crt
SSLCertificateFile /etc/pki/tls/certs/bm02.local.cert
  1. 将这一行更改为你自己的 PEM 文件——我的文件作为示例。
SSLCertificateKeyFile /etc/pki/tls/private/localhost.key
.pem file – mine is shown for example.

SSLCertificateChainFile /etc/pki/tls/certs/server-chain.crt

以 root 用户身份运行 httpd 服务并进行测试。以下命令以 root 用户身份运行。


httpd service is running as expected.

systemctl status httpd


Your output should resemble something like this:

● httpd.service - Apache HTTP 服务器

已加载: 加载 (/usr/lib/systemd/system/httpd.service; 启用; 预设: 禁用)

Drop-In: /usr/lib/systemd/system/service.d

└─10-timeout-abort.conf

活跃状态: 活跃(运行中),自 2024 年 8 月 25 日 22:14:15 EDT 起,已运行 8 秒

文档: man:httpd.service(8)

主进程 PID: 4907 (httpd)

状态: "已启动,监听端口:443,端口 80"

任务: 178(限制: 38323)

内存: 16.2M(峰值: 17.8M)

CPU: 115ms

CGroup: /system.slice/httpd.service

├─4907 /usr/sbin/httpd -DFOREGROUND

├─4908 /usr/sbin/httpd -DFOREGROUND

├─4909 /usr/sbin/httpd -DFOREGROUND

├─4910 /usr/sbin/httpd -DFOREGROUND

├─4911 /usr/sbin/httpd -DFOREGROUND

└─4912 /usr/sbin/httpd -DFOREGROUND

2024 年 8 月 25 日 22:14:15 bm02.local systemd[1]: 正在启动 httpd.service - Apache HTTP 服务器...

2024 年 8 月 25 日 22:14:15 bm02.local (httpd)[4907]: httpd.service: 引用但未设置的环境变量被解析为 e>

2024 年 8 月 25 日 22:14:15 bm02.local httpd[4907]: 服务器配置完成,监听端口:443,端口 80

https)。由于我们使用了自签名证书,浏览器肯定不喜欢它,并且会要求你确认是否要继续访问该网站。某些浏览器比其他浏览器更宽容(无论它们运行在哪个操作系统上)。在浏览器窗口中确认你希望继续,点击 https 并接受自签名证书。

                ![图 12.4 – 因为自签名证书而出现的 SSL 警告](https://github.com/OpenDocCN/freelearn-sec-pt3-zh/raw/master/docs/emb-linux-sec-hb/img/B22104_12_04.jpg)

        图 12.4 – 因为自签名证书而出现的 SSL 警告

        如果一切按计划顺利进行,您应该能够访问到新加密的 Web 服务器,页面应该如下所示:

                ![图 12.5 – HTTPS 主要测试页面](https://github.com/OpenDocCN/freelearn-sec-pt3-zh/raw/master/docs/emb-linux-sec-hb/img/B22104_12_05.jpg)

        图 12.5 – HTTPS 主要测试页面

            1.  现在让我们测试仓库 URL。记得在 URL 中使用 HTTPS(而不是 HTTP)。您可能会看到相同的 SSL 证书警告。继续并确认它是安全的(替换为您自己的 URL——这里再次使用的是我的 URL 作为示例)。

                ![图 12.6 – 我们自定义的 DNF 仓库现在使用 HTTPS !!!](https://github.com/OpenDocCN/freelearn-sec-pt3-zh/raw/master/docs/emb-linux-sec-hb/img/B22104_12_06.jpg)

        图 12.6 – 我们自定义的 DNF 仓库现在使用 HTTPS !!!

        现在,我们已经完成了自签名证书的创建,并使我们的自定义 DNF 仓库启用了 SSL,在结束之前,我想再给你们一个需要考虑的事项。

        如果您的解决方案将使用 HTTPS,请在界面中提供一种方式,让最终用户可以点击按钮,自动执行此过程。更好的是,在界面中加入让设备自动从 CA 获取密钥和证书的选项。这些工作与*第十章*中讨论的防篡改和用户体验主题相一致。我们应该始终致力于为最终用户提供积极的用户体验。

        在本节中,我们通过加密和证书确保了 HTTPS 服务的安全性。接下来我们将进入下一节,回顾用于保护您的设备服务和端口实际网络连接的工具。

        确认您的网络是否安全

        几乎所有机器在某种程度上都会与其他机器进行通信。在嵌入式 Linux 系统领域,这一点并不总是成立。某些设备仅仅是独立解决方案,没有连接到任何网络。在其他使用案例中,它们可能所在的安全环境要求它们位于一个严格限制的局域网段,只有有限的对其他系统的访问权限,且完全无法访问互联网或企业的其他网络段。

        网络配置和安全化是基本 Linux 系统管理的一部分。但我们并不是设计要部署在自己数据中心或网络中的系统。我们在构建将部署在客户生态系统中的产品,不论这种部署需要何种级别的安全性。我们的客户已将信任和责任交给我们,确保我们交付给他们的产品已经过锁定并安全可靠。很多时候,这比他们有限的员工可能具备的技能要好。这也是他们购买你解决方案的原因。

        在接下来的几个模块中,我们将简要介绍我真心希望你已经了解的命令行和图形工具。我的理由直白且简单:使用适合你的团队、环境和公司构建链风格的工具。我实际上希望这一部分对你来说是多余且不必要的。如果它能稍微帮上一点忙,那就更好了。接下来,让我们快速回顾一下如何通过使用工具来为我们的设备(稍微)做好迎接新家准备,确保在下一部分的防火墙章节中可以控制哪些流量能够通过。

        防火墙

        这是一个关于 Linux 防火墙主要设置组的快速概览:

            +   **连接**:这是一个定义好的*命名*网络连接。

            +   **区域**:一个 firewalld 区域是你可以利用的预定义信任级别。

            +   **接口**:这个很简单明了。它是你计划应用新设置的接口。

            +   **服务**:这些是可以使其可访问的预定义服务。预定义服务在配置过程中大有帮助,因为记住每个服务与端口的映射关系,以及它是 UDP 还是 TCP,都可能让人头大。

            +   **端口**:这是快速定义多个端口或端口范围使其可访问的一种方式。

            +   **配置**:你正在编辑的配置有两种可能的状态——**运行时**和**永久性**。运行时状态的更改在重启或重启**firewalld**服务后会丢失。

            +   **IPSets**:这些是你可以管理和轻松部署的白名单或黑名单。

        有几种不同的方式可以配置 Linux 防火墙(firewalld)。让我们浏览一些示例。

        命令行

        管理防火墙的命令行工具在你构建新系统时几乎总是会预装。我们在这里重点介绍的主要工具是**firewall-cmd**。正如你从*大幅缩减*的所有可能设置列表中看到的,firewall-cmd 是一个功能丰富的工具集。它也可以轻松地编写脚本。

        对于所有选项的示例,可以在终端中运行以下命令。

$ firewall-cmd --help
        那个命令的输出内容相当长。我建议你在自己的机器上研究它,将输出结果通过管道传输给 `more` 或 `less` 命令,然后分页浏览。

Usage: firewall-cmd [OPTIONS...]
General Options
  -h, --help        Prints a short help text and exits
  -V, --version     Print the version string of firewalld
  -q, --quiet       Do not print status messages
Status Options
  --state           Return and print firewalld state
((( output truncated )))
Options to Handle Bindings of Sources
  --list-sources    List sources that are bound to a zone
                    [P] [Z]
  --add-source=<source>[/<mask>]|<MAC>|ipset:<ipset>
                    Bind the source to a zone [P] [Z]
  --change-source=<source>[/<mask>]|<MAC>|ipset:<ipset>
                    Change zone the source is bound to [Z]
  --query-source=<source>[/<mask>]|<MAC>|ipset:<ipset>
                    Query whether the source is bound to a
                    zone [P] [Z]
  --remove-source=<source>[/<mask>]|<MAC>|ipset:<ipset>
                    Remove binding of the source from a
                    zone [P] [Z]
Helper Options
  --new-helper=<helper> --module=<module> [--family=<family>]
                    Add a new helper [P only]
  --new-helper-from-file=<filename> [--name=<helper>]
                    Add a new helper from file with optional name [P only]
  --delete-helper=<helper>
                    Delete an existing helper [P only]
  --load-helper-defaults=<helper>
                    Load helper default settings [P only]
  --info-helper=<helper> Print information about an helper
(((output truncated)))
Lockdown Options
  --lockdown-on      Enable lockdown.
  --lockdown-off     Disable lockdown.
  --query-lockdown   Query whether lockdown is enabled
Lockdown Whitelist Options
  --list-lockdown-whitelist-commands
                     List all command lines that are on the
                     whitelist [P]
  --add-lockdown-whitelist-command=<command>
                     Add the command to the whitelist [P]
(((output truncated)))
Panic Options
  --panic-on         Enable panic mode
  --panic-off        Disable panic mode
  --query-panic      Query whether panic mode is enabled
        命令行是设置防火墙参数最强大、最灵活的方式,但说实话,掌握它需要一点技巧。这种方法是全球系统管理员的首选,因为它可以编写脚本并轻松重复。正是脚本化的便利将大大帮助你的团队,在用户看不见的后台实现这些功能。

        让我们来看看其他一些配置防火墙的替代方式。

        Web 控制台

        **网络控制台**在过去几年里快速发展,逐步将其基础的系统管理员功能扩展到创建系统镜像或管理容器和虚拟机等方面。网络控制台的进一步增强降低了其他平台管理员对 Linux 系统管理的门槛,尤其是当他们的技能来源于其他平台时。

        这是一个展示在 Fedora 40 上运行的网络控制台(即 Cockpit)的截图。在**网络**子菜单下,我们可以轻松修改防火墙规则,并配置连接和其他网络设置。

                ![图 12.7 – 通过网络控制台配置防火墙](https://github.com/OpenDocCN/freelearn-sec-pt3-zh/raw/master/docs/emb-linux-sec-hb/img/B22104_12_07.jpg)

        图 12.7 – 通过网络控制台配置防火墙

        网络控制台非常适合在实验室或数据中心环境中配置您的系统;然而,我强烈建议避免终端用户在您的设备上使用它,因为执行大多数任务需要管理员权限……而现在我们又回到了防护措施的讨论。接下来,我们将快速回顾防火墙的图形用户界面工具。

        基于图形用户界面的工具

        在 Fedora(以及大多数 Linux 发行版)中,实际上有多个图形防火墙配置工具。任何工具都可以通过 gnome-software 应用程序或命令行进行安装。这些工具使得配置和管理防火墙比尝试记住命令行中成千上万的选项要容易得多。

        请注意,当您搜索管理防火墙的工具时,gnome-software(Gnome 桌面中的应用商店)也会提供网络控制台(Cockpit)作为一种解决方案。

                ![图 12.8 – 通过 gnome-software 图形界面搜索软件](https://github.com/OpenDocCN/freelearn-sec-pt3-zh/raw/master/docs/emb-linux-sec-hb/img/B22104_12_08.jpg)

        图 12.8 – 通过 gnome-software 图形界面搜索软件

        这是防火墙管理图形用户界面的截图,展示了它在 Gnome 桌面环境下运行的样子。

                ![图 12.9 – 防火墙图形用户界面](https://github.com/OpenDocCN/freelearn-sec-pt3-zh/raw/master/docs/emb-linux-sec-hb/img/B22104_12_09.jpg)

        图 12.9 – 防火墙图形用户界面

        我对这些基于图形用户界面的防火墙工具的态度与网络控制台相同。它们在数据中心和实验室中很有用,但我不会让任何设备的终端用户访问它们。永远不会。真的。

        如果您的设备提供可能需要终端用户打开额外端口的服务,您应该自动化并将所有可能需要终端用户具有 root 权限的功能集成到您的界面中——就像我们在*第十章*中深入讨论的那样。这不仅仅是防篡改。您应该把它当作是未来-proofing,或者更好的是,增强用户体验。

        说实话,没人会在乎你用了哪些工具或没用哪些工具来配置你的设备。这里我们从配置防火墙转到确认你认为已配置的内容是否就是设备的实际状态。再次提醒你那句老话,*信任,但要验证*。信任你团队的努力,但要验证你认为自己已配置的内容是否与设备的实际状态一致。我强烈建议在适当的地方进行自动化处理,但要确保依然有人工接触设备、人工检查设备,并且每个单元的所有操作都要有文档记录。

        让我们继续讨论在构建或升级周期结束时应始终严格执行的活动。让我们回顾一下如何验证你的解决方案。

        遗留硬件和软件的局限性

        这里我觉得有必要传达一些坏消息。你可能无法总是选择你的解决方案所使用的硬件、连接方式或总线。解决方案的长期可维护性可能迫使你和你的团队实现某些不理想的设计,以保持向前和向后兼容性(一个典型的例子就是 CAN 总线)。

        如果没有一个普遍的做法来淘汰对极其老旧或不支持芯片组的驱动程序支持,老旧的遗留硬件可能不会那么糟糕。这意味着你可能被迫使用不受支持的驱动程序,这些驱动程序可能不包含在操作系统中,可能已经很久没有更新,或者来自不可靠的来源。不受支持的驱动程序(软件)也可能意味着有一些风险和漏洞没有得到解决。这是一个定时炸弹。

        一个加重的问题是,较新的操作系统往往需要更新的组件。似乎每发布一个新的 Linux 版本(无论是哪个发行版),我们就能获得更多的功能和能力。这些新的花里胡哨的功能都有一个代价——需要更新、更强大的硬件。

        为什么使用最新的硬件和软件很重要?这里有一个现实的例子:大多数汽车,除非发生灾难性事故,否则通常可以在路上行驶多年,甚至超出其计算机子系统的正常生命周期。这只是无数可能性中的一个例子。

        安全从设计阶段开始,但这并不意味着你总是能选择到最好的组件(硬件或软件)。要记住,总会有一些限制。

        在交付前验证你的解决方案

        在我们尽可能确保解决方案安全的过程中,仍然有一些关键活动必须完成,才能让你自信地交付解决方案。这些活动应视为不可妥协的,忽视它们后果自负。

        首先是合规集成和测试,你需要确认你的设备是否符合或超出了可能适用于它使用领域的任何政府或行业标准。我认为这是一个至关重要的主题,整个下一个章节将专门讲解这一部分内容。

        其次,**渗透测试**(也称为**渗透测试**)通过第三方可以让你安心,并深入了解任何你可能忽略的细节。在这种情况下,专业的道德黑客(承包商)将利用所有行业工具,试图获取未经授权的访问权限或降低设备的可用性。通过这种测试将是你团队成功和你产品未来前景光明的证明。

        让我们继续进行章节总结。

        摘要

        你的解决方案所附带的内容以及它与之通信的对象绝对重要。这些通信也将决定需要主动解决的安全问题。在本章中,我们介绍了一组你最有可能遇到的关键总线和连接类型,以及它们的独特应用场景。随着内容的推进,我们审视了一个关键的安全措施集——你的防火墙和网站流量加密。这些活动需要特别关注细节。本章中获得的知识应使你和你的团队能够为此类连接风险做好准备并进行设计。最后,我们通过一个简单的提醒结束本章,你可能需要考虑向前和向后兼容性问题,这将影响你的安全配置。

        再次感谢你继续和我一起走这段旅程。在接下来的章节中,我们将深入探讨如何将安全标准应用到我们的解决方案中。


第十三章:应用政府安全标准 – 系统加固

无论你的团队是试图通过增强安全性为你的产品提供竞争优势,还是你的客户群体(即政府、军队或其他公共部门客户)对所有系统有合规性要求,应用一个或多个政府安全标准通常都不是一项简单的任务。

对于这一层次的合规性,你必须基于已接受和认证的操作系统构建解决方案。显然,这一合规性要求将把大多数社区发行版排除在外,正如我们在第二章中所讨论的那样。在这个领域,符合要求的 Linux 操作系统列表非常短暂。你可以用一只手指数出这个领域的参与者(或许还能剩下几根手指)。这并不是贬低任何发行版,无论是社区版还是商业版。这个过程冗长、昂贵,并且毫无疑问,对于大多数人来说可能非常令人沮丧。很少有发行版拥有资源与 NIST 一同完成这一过程。

对你来说,好消息是经过认证的 Linux 操作系统的列表正在扩大,但很少有操作系统能够与Red Hat® Enterprise Linux®(RHEL)相媲美,它遵循广泛的政府认证和标准,并且被视为美国政府领域 Linux 的事实标准。这个领域的其他几个参与者通常是 RHEL 的克隆或衍生版本,唯独 Ubuntu®是最受欢迎的 Debian Linux 变种。

在这个过程中,我们将探索的另一个因素是额外的工具,这些工具使得遵循这些安全标准的艰巨任务成为可能。安全内容自动化协议SCAP)可以说是最常见的自动化应用集安全措施的标准(也就是 SCAP 服务器配置文件),用于系统或应用堆栈。实施这些配置文件的实际过程需要工具支持。这正是开源工具再次发挥作用的地方。OpenSCAP 项目提供了广泛的工具。许多 Linux 发行版在其安装程序和软件仓库中都包括这些工具包。SCAP 定义为应用安全标准和修复提供了一种行业标准的方式。无论你试图应用什么安全标准,它们都是实现合规性的“高速公路”。在本章中,我们将通过实例展示如何应用美国服务器安全的两个最常见标准——FIPS 140-3 和通用的STIG(即安全技术实施指南)。

本章的主要内容包括:

  • 遵守美国政府的关键标准

  • 我该如何实现这一点?

  • 我该如何认证我的解决方案?

让我们进入下一个部分,详细讨论你可能需要完成本章练习的相关细节。

技术要求

在本章的实践练习中,你将需要两台 RHEL 9.4(或更新版本)机器(可以是物理机或虚拟机),并且它们都应该是干净的安装。我们将在练习中一起完成其中一台机器的安装。

为了实现这一点,你需要访问一个 Red Hat® 账户(开发者账户或生产账户)、安装介质、Fedora® 媒体写入工具,以及能够在这两台机器上安装/重新安装操作系统的能力。

此外,你需要能够从第三方或政府网站下载并安装额外的包。STIG Viewer 工具可以安装在 Windows® 或 Linux 系统上。你也需要这个工具,但它不必专门安装在你的实验室机器上。可以查看本书的 GitHub 仓库以获取有用的链接:github.com/PacktPublishing/The-Embedded-Linux-Security-Handbook/blob/main/Chapter11/Resource_Cheat_Sheet.pdf

让我们继续讨论为什么遵守安全标准可能很重要。

遵守美国政府关键标准

很多人寻求将他们的解决方案维持在比要求的标准更高的水平。很多人会同意我的看法;我赞赏这种对安全的承诺以及超越最低要求的精神。通过这样做,他们可以轻松地将自己的解决方案与任何竞争对手的解决方案区分开来。为什么?因为如果解决方案符合美国军方或某些三字母机构的苛刻安全标准,那么它一定足够好。嗯,应该是这样理解的。

继续这个思路,我想强调的是,通过在特定行业中超越最低要求(或通常认为的标准),你可以有效地在目标社区内建立信任。通过提高自己和产品的标准,你最终会提前(且非正式地)为他人设定一个新的标准,促使他们去努力达到这个标准。这将使你的客户的审计工作变得更加轻松,他们一定会感激这种减少压力的合规工作。

遵守政府标准,即使不是特别要求,也可以让潜在客户在选择你的解决方案时更加安心。客户的审计人员也可能会感谢他们在选择你的产品时进行了更多的尽职调查。这对每个人来说都是双赢的局面。你团队的额外努力将大大促进你产品的广泛采用。

除了信任和安心外,减少一个客户网络上的系统也为他们带来了好处。我向你保证,他们也一定会对此表示感激。

然后是另一面。当合规性由于客户群体的要求而被强制执行时,你的团队将面临重重任务。无论你的产品在需求空间中处于何种位置,产品越安全,所有相关方的结果就会越好。

让我们回顾一下第二章中的早期讨论,当时我们确定了最重要的因素:你的目标客户群体的合规性需求。也许你的产品面向多个行业领域。

如果你的用户群体位于政府部门,那么你的产品最好能展现出最佳表现。未能遵守政府基础设施中对任何系统施加的适用标准,将导致你的解决方案无法被采纳。

政府只是一个需要关注细节的行业领域。医疗保健和金融服务也有自己的监管安全标准(尽管与政府/军事标准差异不大)。

无论你销售的行业领域和部门是什么,从合规性角度拉宽网格都是一种聪明的做法。此外,我觉得如果我没有提到这一点就结束,那就是许多安全标准在多个行业之间存在大量重叠。

让我们更重要地讨论如何成功地将这些标准应用到我们的解决方案中。

我该如何实施这一点?

问题我该如何实施这一点?并没有单一的答案。真实的回答是这很复杂。维持合规性有许多接触点。它从设计桌开始,在那里你必须确定哪些标准会影响整体解决方案。有些人可能会认为,大量的研究时间是花费最多时间的部分。我不同意。我相信(并且我猜你很快也会这么认为)从发布到发布,长时间保持合规性,远远比最初在产品中实施这些措施更加繁重。

这里面也有一个陷阱。保持合规性并不是一次性完成的过程。做好心理准备,因为接下来会有一些挫折。设置服务器配置文件,无论是在安装期间还是之后,都不是终点,而是起点。每次对配置进行更改时,无论大小,你都必须重新扫描并确认合规性。这一维护和测试过程可能相当繁琐,但它是必要的。

接下来的几个部分中,我们将探讨如何在产品的生命周期中实施并维持标准合规性。

安全标准的实施

安全性从设计阶段开始,但安全措施的实施和维护才是真正的关键所在。关注最细微的细节,可能会在保护你的产品免遭破坏上产生决定性的作用。我们为什么要这么做(好像我们需要提醒一样)?永恒的风险缓解。

我们首次涉足实施安全标准的工作从 Linux 安装程序开始。

近年来对一些安装程序的改进,确实让这一过程对实施者来说变得更容易。但正如我之前所说,这只是你和你的团队所投入的长期承诺的开始。

在安装时利用 RHEL 服务器配置文件

RHEL 安装程序 Anaconda 具有让最终用户选择预定义 SCAP 安全指南服务器配置文件的能力。这些服务器配置文件代表了多个政府机构和行业标准。在安装时利用其中之一,可以大大加速确保系统符合相关标准的进程。这并不意味着在完成服务器设置后,它就 100%符合标准。你仍然需要在后续的质量检查过程中确认合规性。

你可以在 Anaconda 安装过程中选择多个 SCAP 配置文件(或其他标准)中的一个。再次感谢那些开发者,他们花时间使这一繁琐的过程变得更加简单。

对于那些好奇有哪些配置文件被包含的朋友,不必再等了。最近,几乎所有主要 Linux 发行版的公开共享 SCAP 配置文件的主列表已移至 GitHub,可以通过这个链接找到:complianceascode.github.io/content-pages/guides/index.html。RHEL 9 安装程序中包含的 SCAP 配置文件列表相当广泛。以下是安装程序中包含的一些配置文件的简短列表:

  • 法国信息系统安全国家局(ANSSI BP-028)定义的各种安全级别(低、中、高和增强)

  • 西班牙国家密码中心Centro Criptológico Nacional aka CCN)定义的各级服务器安全级别

  • 各种 CIS 基准级别

  • 草案版非机密 FIPS 标准(NIST 800-171)

  • 澳大利亚网络安全中心ACSC)基本八项

  • ACSC ISM 官方标准

  • 健康保险可携带性与责任法案HIPAA

  • 通用操作系统的保护配置文件

  • PCI-DSS 版本 3.2.1 控制基准

  • 国防信息系统局DISASTIG针对 RHEL 9 Server 和带 GUI 的 RHEL 9 Server

以下是浏览 RHEL 9 安装过程中可用 SCAP 配置文件的广泛列表时拍摄的截图。在单个截图中不可能显示所有内容。

图 13.1 – 在 RHEL 安装程序中选择服务器配置文件

图 13.1 – 在 RHEL 安装程序中选择服务器配置文件

在 RHEL 中启用 FIPS 模式

自几年前开始初步开发以来,RHEL 9 一直专注于 FIPS 140-3 标准。Red Hat 已经确定,如果尝试将 FIPS 140-3 添加到已获得 FIPS 140-2 认证的 RHEL 8 中,所需的重构工作量过大,而且由于该操作系统处于生命周期的最后五年,因此这种努力是不可行的。在 RHEL 发布的最后五年里,操作系统通常处于维护模式,不再引入新功能,但会继续进行安全和错误修复。

构建 FIPS 合规的系统从安装时开始,通过将安装程序置于 FIPS 模式来实现。这一步非常简单,只需在系统启动过程中编辑一行。在安装过程中,在安装程序的启动内核选项中附加 fips=1 到内核行。

这是我在 GRUB 中设置内核启动选项的截图,以便让安装程序以 FIPS 模式启动:

图 13.2 – 配置安装程序以 FIPS 模式启动

图 13.2 – 配置安装程序以 FIPS 模式启动

让系统更接近 FIPS 合规性的下一个步骤是在安装过程中选择 FIPS SCAP 服务器配置文件。

图 13.3 – 安装过程中选择 FIPS 服务器配置文件

图 13.3 – 安装过程中选择 FIPS 服务器配置文件

如果你像我一样(注重细节)并希望再次检查你的工作,你也可以在安装后配置 FIPS 合规模式。系统发生任何更改后,都需要进行此过程。

让我们看一个通过命令行在安装后强制启用 FIPS 模式的配置示例。这本身就是企业发行版(如 RHEL)如何简化复杂标准遵循的一个明显例子。在这种情况下,您可以以 root 用户身份运行以下命令:


#  fips-mode-setup

输出可能非常长,晦涩且冗长。你可以根据自己的需求在实验室中进行尝试。

现在,我们可以查看在执行系统扫描之前验证 FIPS 模式的几个步骤。这些步骤并没有特定的顺序,但我认为所选顺序看起来有一定的逻辑性。

通过在实际启动 Linux 之前检查内核启动选项,确保已设置 FIPS 支持的内核启动选项。然而,这并不保证已完成 FIPS 140-3 合规性所需的所有其他配置。这仅仅是旅程的开始。

在这个示意图中,你可以看到启动的配置,并清楚地展示了内核选项……更具体地说,就是我们关注的那个 fips=1

图 13.4 – 确认 GRUB 中的 FIPS 模式启动选项

图 13.4 – 确认 GRUB 中的 FIPS 模式启动选项

这是确保在你的 RHEL 服务器上启用 FIPS 模式的另一种方法。它将为你在配置过程中做很多繁重的工作。

你应该运行以下命令以强制设置系统策略:


#  update-crypto-policies  –-set FIPS

你可能会好奇(或非常担心)你的系统在遵循 FIPS 140-3 标准方面的表现如何,因此我们提供了这个示例步骤来教你如何检查。我们将确保 FIPS 模式验证完成(无论它以前是如何配置的):

  1. 首先,我们将通过以 root 身份运行以下命令来检查 FIPS 模式是否已启用:

    
    #  fips-mode-setup --check
    

    在这一点上,你需要密切关注输出结果,因为你可能会看到这样的输出——然后你还需要做更多的工作。这是正常的。完美是难以实现的。你的输出很可能会像下面这样,通知你还需要完成更多的工作:

    Installation of FIPS modules is not completed.
    FIPS mode is disabled.
    
  2. 假设你的系统需要更多的工作,因为你没有从上一个命令中得到理想的结果,让我们继续往下走。然后我们可以运行下一个命令,并(当然)重新验证 FIPS 模式是否在我们的主机上正常。这可能比大多数命令需要更多的时间,请耐心等待。

    
    #  fips-mode-setup –-enable
    

    该命令将需要一些时间——预计输出将类似于以下内容:

    Kernel initramdisks are being regenerated. This might take some time.
    Setting system policy to FIPS
    Note: System-wide crypto policies are applied on application start-up.
    It is recommended to restart the system for the change of policies
    to fully take place.
    FIPS mode will be enabled.
    Please reboot the system for the setting to take effect.
    
  3. 好的,现在情况好多了。由于我们从上一个命令中得到了结果,我们需要做一些修复。这是预期的。现在按照建议重启系统:

    
    #  reboot
    
  4. 系统重启后,让我们回到 root 提示符下,并重新运行验证命令。正如我一直说的,信任 但验证!

    
    #  fips-mode-setup --check
    FIPS mode is enabled.
    

现在我们可以松一口气了。我们已经完成了如何实现 FIPS 模式并测试结果的过程。接下来,让我们进入另一组安全措施,即 DISA 的 STIG 配置文件。

DISA STIG SCAP 配置文件

在我们深入了解 STIG 合规系统的设置之前,让我们首先达到一个可以真正理解 STIG 标准文档的水平。这需要你从 DISA 安装一个工具。是的,你将需要另一个工具来查看 STIG 本身的详细信息。DISA STIG Viewer 是一款免费的软件工具,支持 Windows 和 Linux 系统。抱歉大家——不支持 Mac®。我相信有一些有趣的背景故事解释了为什么不支持 Mac,但我不知道具体情况。这个工具由 DISA 的安全专家维护,并公开提供给所有人使用。

首先,让我们打开浏览器并访问 DISA 网站,然后下载免费的 STIG Viewer 工具。该工具可以在以下网址找到:public.cyber.mil/stigs/srg-stig-tools/

图 13.5 – 下载 STIG Viewer

图 13.5 – 下载 STIG Viewer

现在我们有了这个极好的免费工具,让我们充分利用它,下载适用于我们示例 RHEL 9.x 实验服务器的 STIG。这也是一个相对简单的过程。

前往 public.cyber.mil/stigs/downloads/?_dl_facet_stigs=operating-systems 并选择 RHEL 9 STIG。您可能需要浏览几个其他操作系统的 STIG 条目才能找到它(我认为它在第三页)。

图 13.6 – 下载 RHEL 9 STIG SCAP 配置文件

图 13.6 – 下载 RHEL 9 STIG SCAP 配置文件

在我的实验室中,我在我的 Windows 笔记本电脑和几台 Linux 服务器上都安装了 STIG Viewer。这是使用 STIG Viewer 进入 RHEL 9 STIG 库的屏幕截图。

图 13.7 – 查看 RHEL 9 STIG 库

图 13.7 – 查看 RHEL 9 STIG 库

这是我建议您花一些时间不仅熟悉 STIG 查看工具,而且使用它来检查不仅仅是 RHEL 9.x STIG SCAP 配置文件,还有您想更加熟悉的任何其他配置文件。这个工具是无价的。

现在我们已经花时间查看了我们可以应用于产品的配置文件,让我们继续进行实际允许我们将系统配置强制符合规定的工具。

无论您选择在安装(和配置过程)期间遵循哪些标准,您仍然需要详细验证解决方案作为发布流程的一部分。让我们看看这可能是什么样子。

作为 QA 过程的一部分进行验证

我之前有没有说过信任但要验证?我想我有。是的。我再说一遍。

知道在哪里获取关于如何应用 SCAP 配置文件和扫描的最新信息是很重要的。由于我们专注于这些活动和 RHEL,这里是 Red Hat 关于这一过程的文档链接:docs.redhat.com/en/documentation/red_hat_enterprise_linux/9/html/security_hardening/scanning-the-system-for-configuration-compliance-and-vulnerabilities_security-hardening#configuration-compliance-tools-in-rhel_scanning-the-system-for-configuration-compliance-and-vulnerabilities

提示

您需要一个帐户来登录查看信息。

让我们继续进行一个练习,我们将运行我们的第一个扫描。

练习:安装 OpenSCAP 工具并运行扫描

在这个练习中,您将在您的实验室机器上安装 OpenSCAP 工具,下载一个 RHEL 9 SCAP 配置文件,并运行安全扫描。让我们看看如何做:

  1. 安装软件包:

    
    $  sudo dnf install -y scap-workbench  \
    openscap-utils openscap-engine-sce \
    openscap-scanner scap-security-guide bzip2
    

    这个输出非常长;但是,我已经截断了它以显示安装的重要部分:

    Updating Subscription Management repositories.
    Last metadata expiration check: 0:04:16 ago on Wed 16 Oct 2024 04:52:00 AM EDT.
    Package openscap-scanner-1:1.3.10-2.el9_3.x86_64 is already installed.
    Package bzip2-1.0.8-8.el9.x86_64 is already installed.
    Dependencies resolved.
    ==========================================================
         ((( output truncated )))
    Installed products updated.
    Installed:
      adwaita-gtk2-theme-3.28-14.el9.x86_64         gtk2-2.24.33-8.el9.x86_64                        ibus-gtk2-1.5.25-5.el9.x86_64
      libcanberra-gtk2-0.30-27.el9.x86_64           openscap-engine-sce-1:1.3.10-2.el9_3.x86_64      openscap-utils-1:1.3.10-2.el9_3.x86_64
      openssh-askpass-8.7p1-38.el9_4.4.x86_64       pcre2-utf16-10.40-5.el9.x86_64                   qt5-qtbase-5.15.9-10.el9_4.x86_64
      qt5-qtbase-common-5.15.9-10.el9_4.noarch      qt5-qtbase-gui-5.15.9-10.el9_4.x86_64            qt5-qtdeclarative-5.15.9-3.el9.x86_64
      qt5-qtxmlpatterns-5.15.9-2.el9.x86_64         rpmdevtools-9.5-1.el9.noarch                     scap-workbench-1.2.1-13.el9.x86_64
      xcb-util-image-0.4.0-19.el9.x86_64            xcb-util-keysyms-0.4.0-17.el9.x86_64             xcb-util-renderutil-0.3.9-20.el9.x86_64
      xcb-util-wm-0.4.1-22.el9.x86_64
    Complete!
    
  2. 从 Red Hat 下载一个适用于 RHEL 9 的通用 SCAP 配置文件。就像我们之前下载的 STIG SCAP 配置文件一样,这将是一个 XML 文件,用于扫描工具:

    
    #  wget -O - https://www.redhat.com/security/data/oval/v2/RHEL9/rhel-9.oval.xml.bz2 | bzip2 --decompress > rhel-9.oval.xml
    

    这个输出也相当长;我已对其进行了截断,以节省空间,只保留了一些重要的信息:

    --2024-10-16 04:59:45--  https://www.redhat.com/security/data/oval/v2/RHEL9/rhel-9.oval.xml.bz2
    Resolving www.redhat.com (www.redhat.com)... 23.37.1.210, 2600:1401:4000:58d::d44, 2600:1401:4000:58b::d44
    Connecting to www.redhat.com (www.redhat.com)|23.37.1.210|:443... connected.
    HTTP request sent, awaiting response... 301 Moved Permanently
    Location: https://security.access.redhat.com/data/oval/v2/RHEL9/rhel-9.oval.xml.bz2 [following]
    --2024-10-16 04:59:45--  https://security.access.redhat.com
    /data/oval/v2/RHEL9/rhel-9.oval.xml.bz2
    Resolving security.access.redhat.com 
    (security.access.redhat.com)
    ... 23.194.190.138, 23.194.190.193, 
    2600:1401:2000::b819:94a8, ...
    Connecting to security.access.redhat.com 
    (security.access.redhat.com)|23.194.190.138|:443... connected.
    HTTP request sent, awaiting response... 200 OK
    Length: 444671 (434K) [application/x-bzip2]
    Saving to: 'STDOUT'
    -                                   100%[===============
    =========
    ========================================>] 434.25K  --.-KB/s
        in 0.1s
    2024-10-16 04:59:46 (3.26 MB/s) - written to stdout 
    [444671/444671]
    
  3. 运行一次测试扫描:

    
    $  oscap-ssh <username>@<hostname> <port> oval eval --report 
    <scan-report.html> <path to rhel-9.oval.xml>
    

重要说明

oscap 工具(即 openscap-utils 包)必须安装在目标主机和执行命令的主机上。请根据需要替换适当的用户名、主机名和文件路径。请注意,这个命令的输出可能非常长。如果你没有两台安装了工具的机器,可以简单地在本地主机上针对自己的用户帐户运行该命令。这个练习的重点仅仅是展示过程。

这个命令的交互式输出相当长。为了节省空间,我已将显示的内容进行了截断:


Connecting to 'mstonge@testmachine' on port '22'...
mstonge@testmachine's password:
Connected!
Copying input file '/home/mstonge/rhel-9.oval.xml' to remote 
working directory '/tmp/tmp.10rp1SVS0z'...
rhel-9.oval.xml                                                  
                                         100% 9879KB 336.5MB/s
   00:00
Starting the evaluation...
Definition oval:com.redhat.rhsa:def:20248112: false
Definition oval:com.redhat.rhsa:def:20248111: false
     ((( output truncated )))
Definition oval:com.redhat.rhba:def:20228256: false
Definition oval:com.redhat.rhba:def:20228077: false
Definition oval:com.redhat.rhba:def:20225749: false
Definition oval:com.redhat.rhba:def:20223945: false
Definition oval:com.redhat.rhba:def:20223893: false
Evaluation done.
oscap exit code: 0
Copying back requested files...
report.html                                       

      100%  700KB 241.9MB/s   00:00
Removing remote temporary directory...
Disconnecting ssh and removing control ssh socket
 directory...
Exit request sent.
  1. 接下来,打开浏览器查看报告。

提示

如果没有安装图形桌面,你可能希望将报告的 HTML 文件复制到其他系统中查看。查看所有项目。你的输出会与我的不同。

图 13.8 – 查看扫描报告 HTML 文件

图 13.8 – 查看扫描报告 HTML 文件

现在你已经有了第一次扫描报告,请花些时间吸收内容及其格式。注意它可能发现的任何缺陷,因为这些正是我们用这个工具来寻找的。提供的详细报告可以轻松节省数小时或数天的人工检查时间。

此外,我强烈建议将这些报告作为构建和测试操作的文档保存,因为它们将成为你在提交产品进行政府认证时,证明你尽职调查的证据。

在这个练习中,我们安装了 SCAP 工具,下载了一个来自 Red Hat 的通用 SCAP 配置文件,然后执行了第一次扫描。这个过程可以轻松地通过不同的 SCAP 配置文件来重复,这些配置文件可以来自 NIST、其他第三方,或者你自己创建的。我们刚刚看到的是一个很好的命令行扫描工具示例。

现在你已经通过命令行执行了第一次扫描,让我们继续前进,看看图形化工具如何帮助处理配置文件和扫描。

示例:使用 OpenSCAP Workbench

在之前的练习中,我们安装了多个软件包。提前,你已经安装了 scap-workbenchscap-security-guide 包。当你的扫描系统处于图形用户界面模式时,你将能够查看、编辑和创建自己的 SCAP 配置文件,针对主机运行这些配置文件,甚至自动修复扫描工具发现的缺陷。

让我们逐步了解如何在 UI 中打开并使用 OpenSCAP 工作台:

  1. 首先,让我们在 Gnome 桌面环境中打开 OpenSCAP Workbench 应用程序。进入 Applications,然后选择 SCAP Workbench

图 13.9 – 在 Gnome 的应用菜单中启动 OpenSCAP Workbench

图 13.9 – 在 Gnome 的应用菜单中启动 OpenSCAP Workbench

  1. 启动工作台应用程序后,系统会首先提示你选择加载哪个 SCAP 配置文件。在这里,我们将从下拉菜单中选择 Other SCAP Content

图 13.10 – 从下拉菜单中选择“Other SCAP content”

图 13.10 – 从下拉菜单中选择“Other SCAP content”

  1. 接下来,我们将选择之前下载的 RHEL 9 STIG SCAP 配置文件。

图 13.11 – 选择 RHEL 9 STIG SCAP 配置文件(之前已下载)

图 13.11 – 选择 RHEL 9 STIG SCAP 配置文件(之前已下载)

在决定执行路径之前,你可以在此审查设置并选择前进的方向。

图 13.12 – 准备执行

图 13.12 – 准备执行

在此屏幕上,你可以执行多种操作。你可以选择远程执行扫描。其他人可能会选择编辑此配置文件以满足公司需求。显然的路径是对本地主机或远程主机执行扫描。在此我还要指出,一旦扫描完成,这个工具可以帮助你生成修复自动化。

OpenSCAP Workbench 是一款功能强大且丰富的工具,我认为它值得比本书由于篇幅限制所能提供的更多的细节。如果你喜欢这个介绍,别忘了查看本书的 GitHub 仓库,里面有更多关于如何利用这个强大工具以及许多其他资源的内容。

现在,让我们继续进入下一个部分,在这里我们将讨论如何将安全扫描集成到你的 CI/CD 链中。

作为持续集成/持续部署(CI/CD)过程的一部分进行实施

这不仅仅是对你的质量保证工作的重复,而是对你当前所维护的标准和认证进行审查,以及你可能选择添加到产品中或停止维护的工作。

紧跟为你的设备提供安全标准的机构的更新非常重要,以便及时了解变化或新的法规。

对于敏捷团队,我强烈建议将这些活动添加到你的待办事项中,并确保每年至少进行两次此类审查。你们团队审查的频率越高,希望他们心中对安全的重视也能维持得更好。

此外,我还建议在此处实施一种独立的自动化程度,自动对任何发布候选主机进行扫描。你选择的自动化工具由你决定,或者由你的雇主已定为公司标准。也许你更喜欢脚本。让我们深入探讨一下。

在之前的练习中,我们下载了 STIG SCAP 配置文件和通用 RHEL SCAP 配置文件,设置了扫描主机,并学习了如何执行扫描。为了使这一过程更加标准化,我有一些针对您的 CI/CD 链和产品原型的建议。

接下来,我想分享一些我为您的构建链、原型测试以及更多任务提供的建议。

这是我对您 CI/CD 链的建议:

  • 为运行这些 OpenSCAP 扫描构建一个永久主机

  • 维护适当的 SCAP 配置文件库

  • 自动化扫描活动和结果报告的分发

  • 将您的扫描结果作为工件与构建/发布一起保存,以便将来参考

  • 不丢弃任何东西——保持审计痕迹(始终)

这是我对您原型/发布候选版的建议:

  • 从可能的最高安全级别开始

  • 仅启用对您设备功能至关重要的插座、端口或服务

  • 拥有非 root 的服务帐户,这些帐户可以运行 systemd 服务,并用于支持和扫描活动

  • 确保每个主机都启用了 SSH

  • 确保安装了openscap-utils

如果未能将合规扫描集成并自动化到您的长期(也许是短期)流程中,将会对您产品的质量产生负面影响。我的最终建议是在产品生命周期的任何阶段都不要忽视安全问题。将其作为每个过程的组成部分,最终,它将成为您和您的产品团队的第二天性。

让我们进入您努力的最终阶段:实际获得产品认证。

如何认证我的解决方案?

关于如何获得您的解决方案认证,可能值得写一本完整的书。不同的行业和政府标准有许多不同类型的认证。也就是说,针对我们的安全重点,我选择将其精炼为认证的圣杯:与 NIST 共同获得的 FIPS 140-3 认证。

并不是要打击或劝阻您,但我必须提到,已经有一些公司构建了商业模式,帮助其他企业在实验室和 NIST 之间通过这项艰苦且漫长的过程。您可以通过简单的 Google 搜索在寻找 FIPS 认证时轻松找到它们。它们的服务很可能会出现在所有搜索结果的顶部。

FIPS 140-3 认证不仅仅是软件认证,它还是针对特定硬件的验证。为该过程提供这些服务的测试实验室每个测试周期使用特定的硬件平台。每个实验室所使用的平台可能有所不同。

这个过程是复杂的,并且不是没有成本的。根据您解决方案认证的安全级别,您可能需要向 NIST 支付从$1,000 到超过$4,000 的费用。这还不包括由为 NIST 进行繁重工作的实验室收取的任何费用。

要找到一个 NIST 认证的实验室,你需要在 NIST 网站上进行搜索。这里是一个很好的起点:www-s.nist.gov/niws/index.cfm?event=directory.search#no-back

一旦实验室测试了你的产品并将结果提交给 NIST,NIST 团队将审核所有文档,并希望最终发出认证。此备受追捧的奖项随后可以被搜索,因为所有经过验证的 FIPS 解决方案(及其状态)都可以在 NIST 网站上找到,如下图所示。

图 13.13 – 寻找已验证/认证的模块

图 13.13 – 寻找已验证/认证的模块

供应商的 FIPS 认证重新品牌

提交、测试、验证和认证过程可能需要超过两年的时间。对于任何试图将新竞争产品推向市场的人来说,这段时间简直不可思议。即使是已经认证的操作系统供应商,也很少能提供帮助。红帽有一个计划,在这个计划中,嵌入式系统合作伙伴可以利用他们基于 RHEL 构建的产品的现有认证。我怎么知道这些?因为我曾是该计划的三位创始人之一。

选择走这条路径的红帽合作伙伴可以与红帽嵌入式团队合作,他们将提供适当的文件(即关于现有软件认证的文件),合作伙伴可以将这些文件带到 NIST 及其选择的实验室,加速认证过程。凭借这份认证重新品牌的文档,原本可能需要超过两年的过程,可能会缩短为几周或几个月,因为无需对已认证的模块进行测试。这为合作伙伴提供了巨大的价值,并为其带来了收入的路径。

总结

在本章中,我们走了很长一段路。我们回顾了遵守政府标准的重要性,无论你的行业是否要求这样做。我们还简要了解了一些跨越多个领域的关键标准,并学习了如何实施最重要的标准。最后,我们总结了如何通过 NIST 认证你的设备以及这个过程可能带来的乐趣。你在例子和练习中的经历应该让你获得了新的信心,这些努力并非不可能,而是非常可实现的。

让我们进入最后一章,在这一章中,我们将讨论最重要的资源——最终用户,以及他们的反馈如何帮助你的流程。我们还将对本书中学到的所有内容进行全面回顾。

第十四章:客户和社区反馈循环

欢迎来到最后一章,我们希望通过指导你如何与潜在社区互动,帮助你完成无限循环的闭环。归根结底,是你的客户推动了你的解决方案,因为他们有未满足的需求。不要只是帮他们解痒,更要帮助他们取得巨大的成功。他们的成功也将成为你的成功。

本章的目标不是教授你 CI/CD,而是启发你认识到来自最终用户、管理层以及利用你的产品解决问题的整体社区的持续互动和反馈所带来的价值。你可以期待这些互动为用例、方法论和使用模式提供宝贵的洞见,这些你之前可能未曾预见。所获得的数据将为未来的功能和创新提供动力,同时无疑帮助你在这个过程中提高产品的安全性。这就是你的客户为事业带来价值的地方。

你收集反馈的努力是持续CI/CD 循环的最后一步,然后才进入开发下一个更新:

  1. 计划

  2. 构建

  3. 持续集成

  4. 部署

  5. 持续反馈

本章不会有动手实践的练习,但请不要以为你没什么工作要做。我将给你和你的团队设定一些挑战。你如何应对这些挑战可能决定了你项目的整体成功或严重失败。所以,废话不多说,让我们一起迈出最后的步伐,完成 CI/CD 循环。

本章的主要内容包括:

  • 用例开发

  • 用户群体

  • 高管圆桌会议

  • 社区反馈循环

  • 闭环:书末总结

现在,让我们进入第一部分,回顾你的用例。

用例开发

等等,我们之前不是在书中已经讲过这个了吗?嗯,没错,实际上是的——就在第二章中。不过我们只是浅尝辄止。本章你会发现的内容将远远更加…具有针对性。本章的一个重要部分将是我之前提到的关于参与的另一面。

这不会是重复的内容。之前,我要求你与客户进行更多的互动。这一点现在已经假设了。在本章中,我们将完成整个 CI/CD 循环,我挑战你采取超越基本互动的步骤。事实上,我建议你和你的团队制定与潜在客户群体的具体互动方式,更重要的是,建立一个社区。换句话说,不要只是加入一个社区——要创建并领导一个社区!

在这里,我要求你真正从那些将成为你客户群体的人那里获取实际信息、研究和指导。这些人是你到达一个能够定义未来产品必须做什么、必须遵守的安全要求,并且理解他们想要什么和必须拥有什么功能的关键。

用例本身将决定你未来的用户群体如何利用你的解决方案。他们如何消费你的设备提供的服务,将驱动必须规划的安全措施(UI、用户级别访问、抗篡改等)。你如何获取这些信息是本章要解决的挑战。

此外,来自用户的反馈可能会帮助识别安全问题或缺失的安全措施,这些可能是你的团队未在该版本的设备中加入的。鼓励用户提供开放的反馈总是一个很好的产品改进建议来源。忽视他们的反馈,后果自负。

让我们进入第一种信息收集方法——创建并主持用户 群体会议。

用户群体

在本书早些时候,在第十一章中,我建议你参与安全社区的用户群体。我并没有偏离这个建议。本节内容并非关于这个。这里,我挑战你去找到可能成为你用户群体的最高集中度,并在该区域创建一个用户群体。

这个用户群体将专注于你的产品、它的使用方式、未来发展,以及他们希望你维护或改进的部分。为你的产品创建自己的社区。我无法强调这有多么重要。你从这些人那里获得的反馈对你的产品成功至关重要。如果用户群体认为你没有朝着正确的方向发展,他们可能会放弃你的产品。

了解你的产品如何部署和使用可能会让你感到惊讶。你可能会发现它们并未按预期使用。这本身就可能影响到你产品的安全性和完整性。相反,你也可能得出结论,某个功能或安全措施可能被忽视了。

你甚至可能会从用户那里获得关于如何使他们的体验更愉快、更高效的宝贵见解,还可能获得一些关于哪些功能能够让你的产品与众不同的建议。永远不要低估用户群体可能揭示的宝贵信息。

你与这些人互动的方式将改变他们对你产品的看法,并最终影响他们对你公司整体的认知。要积极互动,保持开放,最重要的是倾听他们的想法和关注点。这些互动是建立与用户群体之间信任的宝贵机会,不仅能让他们的声音被听见,还能强化他们的意见至关重要。当他们知道自己的意见被重视时,他们会觉得自己不仅是解决方案的一部分,更像是一个社区的一员,而不仅仅是供应商的客户。

这是一个成功的用户群体互动的示例。

图 14.1 – 用户群体促进客户互动

图 14.1 – 用户群体促进客户互动

这些会议绝不能表现得像销售推销;事实上,你应该避免让销售团队参与。这些小组在用户可以与产品管理团队和工程师互动时效果最好。技术人员与技术人员对话——这是最有效的方式。

这是一个建议。在前几次会议接近尾声时,向听众询问他们对会议节奏、未来会议内容以及会议时长的看法(是太长,太短,还是刚好合适?)。

我发现一件总是能激发参与感并导致成功的方法,就是邀请听众公开分享他们与产品的最近一次体验,无论是正面还是负面的。没有什么是正式的。这是鼓励与会者更多参与的好方法。

最后,一旦你的用户群体逐渐成型,你的下一个任务就是鼓励客户和合作伙伴参与议程。无论是演示、示范,还是由客户或合作伙伴进行的简短闪电演讲,都有助于建立你的社区并赢得信任。让他们谈谈好的、坏的和丑陋的,讲述他们是如何解决问题的,以及产品如何为他们的组织带来价值。

在下一节中,我们将回顾如何与不同层级的领导进行互动——如何获得高层支持——并且这些领导层来自你的客户群体。

高层圆桌会议

虽然吸引用户群体的参与可以激发他们对产品的极大热情,并提供关于使用模式的重要见解,但与行业高层建立有意义的关系将推动产品的采纳和曝光度,并为客户提供真正的渠道,帮助你推动产品的创新、可用性和安全性提升。

拥有高层支持者相当于获得了一个力量倍增器。该高层领导可以推动你产品的快速采纳。更重要的是,他们能够为你的团队提供关键的见解,了解实施和集成操作的实际进展,以及产品的市场反馈。

高层领导还可能对与工程团队协调或联系功能产生兴趣。他们在安全性和合规性方面的见解可能会改变你的看法。

这是一个可能的高层圆桌会议形式,适用于你的团队。

图 14.2 – 高层圆桌会议推动参与

图 14.2 – 高层圆桌会议推动参与

既然你已经获得了高层支持并建立了关键领导层沟通渠道,那么接下来我们来讨论如何深入接触普通社区。

社区反馈循环

有许多方法可以用来吸引你的社区参与。请使用所有这些方法:活动、用户小组、圆桌会议、调查和积极的研究工作。在本书的早期,特别是在第十一章中,我曾挑战你参与到 Linux 和安全社区中来。现在,我直接挑战你去创建属于你自己的社区。

一旦你的公司开始销售产品,不管你愿不愿意,你的用户都会找到一种方式非正式地分享信息。这些信息共享活动可能会从留言板开始,逐渐自然演变成非正式的群体。

这是你塑造发展中的社区的最大机会。主持留言板。创建一个用户小组,最好是在你的用户聚集较多的地方。这可能意味着在多个地理区域或城市创建几个独特的群体会议环境。从用户集中度最大的地方开始,并在决定扩展并在其他地方创建新小组时,获取他们的反馈。

你可能无法覆盖全球各地的所有用户群体。你可以通过新闻通讯和调查保持用户的参与度。除非你的产品出现问题,否则不要期待调查会有 100%的回应率。但这些沟通方式无法替代直接互动。这里的目标不仅仅是持续的参与(虽然它确实有一些价值),而是希望通过让用户的声音被听到并保持他们的信息更新,鼓励他们进一步成为一个社区。我的个人观点是,你其实可能会过度参与。不要像某些不愿透露姓名的在线供应商那样,每次订单都要求你填写调查问卷。确保你的互动能为接收者带来价值,否则就不要互动。

在这里,我建议你举办活动。这些活动的目标观众是每个人。潜在客户、合作伙伴、用户、高管和行业媒体都是你希望吸引的目标。每个群体都会提供自己的意见和反馈。这些活动可以由多个同时进行的环节组成,每个环节针对不同的受众。产品信息、培训和基于小组的问答环节是这里的主角。

最终,我这里并不是在谈论如何营销你的产品。很多人能够比我做得更好,讨论这一点。我说这些的目的是要你与社区保持联系,并使其积极发展。了解他们的需求,并在你的解决方案中加以回应,将继续推动成功,并帮助你在此过程中实现更安全的产品。

总结

我们现在已经走到了终点。这一章涉及了如何从组织外部收集和吸收反馈的关键方面。这些努力通常是并行进行的,它们将共同为你的团队提供一个类似天气预报的虚拟报告,准确反映你的产品如何被接收和感知,以及你可以做出哪些改变,以提高安全性和采用率。它们也是一个很好的指标,表明社区认为你的产品在哪些方面做得很好,你应该在未来的版本中持续这些优点……把这些宝贵的见解当作它们本身的价值吧——这是一个你不需要为之付费给行业分析师就能得到的惊人洞察力。

最后,让我们来总结一下这本书,或者说是本书的结尾总结。

闭环

首先,我必须说——感谢你与我一起走过这段旅程。虽然这本书已经结束,但我真心希望这仅仅是你新旅程的开始,并且那个旅程将会有许多美好的事情等待着你和你的公司。能够成为你的引导者,是一种荣幸和愉快。

对我而言,这本书的结束,意味着我的叙述结束,我的安全-focused 长篇大论也告一段落,但故事并未结束。我将继续为书籍的 GitHub 仓库提供更新。你应该定期查看,看看新增了哪些新内容。可能是修改后的实验、更新,或更多嵌入式 Linux 的精彩示例。

将所有的部分拼接在一起

这本书的目的是带领你,我亲爱的读者,经历一段知识的渐进过程,无论你在做决定时需要面对什么样的挑战,你都可以将这些知识应用到你的项目中。让我们一起回顾这段最佳实践、安全操作、配置和工具的进展,看看我们应该如何将它们结合起来。

在本书的第一部分——嵌入式系统与安全设计简介中,我们深入反思了嵌入式 Linux 系统:这些系统是什么,谁在使用它们,以及应用设计标准的艰难任务。

现在你应该更牢固地掌握的关键概念是:理解什么是嵌入式 Linux 系统设备,谁在使用它,以及合规性工作如何推动整体解决方案的实现,从硬件和操作系统的选择开始。

在本书的第二部分——设计组件中,我们从理解设计标准的知识出发,将不同的安全组件应用到我们的设计中。这一部分是我们开始以动手操作的方式实际使用许多技术的地方。我们告别了第一部分的理论思维,转而采用了实际应用。

本节你应该从中获得的关键概念,首先是你可能需要在构建链中实现的工具,接着是一些非常详细和具体的安全措施,这些措施需要在你的软件和硬件配置中执行,最后是所有由于防篡改而导致的特殊情况,这些情况是为了防止最终用户自身篡改你的解决方案。

在本书的第三部分,也是最后一部分——构建链、设备生命周期与持续改进——我们讨论了如何创建一个可持续的 CI/CD 链,这个链不仅仅是自动化构建和测试。要实现最完美的闭环,这个链中还必须有人类的输入和输出。也就是说,你需要为你的产品/项目创建一个社区。维护和培养这个社区的工作,和你对产品的关注与尽职调查同样重要。

本节的要点是巨大的。到目前为止,你应该已经在脑海中将所有内容整合起来。你现在知道了可以随手获取哪些资源,帮助你保持信息更新并领先一步。你也知道如何实际测试和实施解决方案中的安全性。接下来,我们进入本章,完成了与社区的持续反馈环路。

我们一起走过了漫长的旅程,现在我想给你最后的挑战。

保持参与

这不应该是你旅程的终点。现在我能留给你的最大挑战就是保持参与,甚至更重要的是保持警觉。威胁环境不断变化,因此你必须保持领先,保持信息的更新和学习。

不仅要保持自己的参与,还要保持团队的参与。确保你产品的安全需要一个团队的持续努力。这不是一次性的工作。不要在几次成功发布后放松警惕。

另一个禁忌——我恳请你重视这个警告:“不要停止学习!”个人和职业上进步的速度要超过威胁环境的变化。推动你自己的成功。安全不仅仅是一个过程——它是一种心态。

再次感谢你的时间、支持和关注。我真心希望这本书能对你有所帮助。

结束…还是一个新的开始?这由你决定。接下来你打算做什么?

加入我们的 Discord 社区

加入我们社区的 Discord 空间,与作者和其他读者讨论:

packt.link/embeddedsystems

posted @ 2025-07-07 14:37  绝不原创的飞龙  阅读(12)  评论(0)    收藏  举报