- 作者:老汪软件技巧
- 发表时间:2024-08-21 21:02
- 浏览量:
在我职业生涯的后期,我在威斯康星大学史蒂文斯角分校 (UWSP) 的美丽校园内任教。 UWSP 的计算机项目使学生能够在多个学科和重点方向上追求学位。课堂经验表明,学生需要接触到超出其专业或重点领域的主题。例如,专注于开发的专业学生从命令行工具和传统上以运维为重点的领域(如 DNS)的经验中获益。同样,网络和服务器方向的学生通过学习编程技术来编写脚本也得到了帮助。
如果说有一种所有 DevSecOps 从业者都需要熟悉的通用技术技能,那就是在 shell 或终端中工作,也称为命令行环境。无论是编写脚本和配置文件、运行命令,还是排查日志文件中的错误,命令行都是掌握 DevSecOps 以及你作为开发人员、安全管理员或运维人员的具体角色的关键技能。命令行技能是进入 DevSecOps 更高层次的一个重要区分因素。
本章提供了对许多组织在践行和使用 DevSecOps 实践和流程时遇到的主题的高层概述。如果我对100个有一定计算机经验的人进行调查,那么对于涵盖的主题至少会有101种不同的回应。考虑到这一点,本章不会试图涵盖你在职业生涯或 DevSecOps 旅程中可能需要的所有主题的广度。本章也无法对每个主题提供所需的深度覆盖。整个学位项目的设计就是为了提供这种深度。
本章首先介绍命令行界面,然后继续介绍当今使用的基本网络模型。由于 DNS 在排查故障中的重要性以及在 DevSecOps 团队之间讨论时有助于知识共享,因此本章也将涉及 DNS。
命令行界面
如果要区分计算机专业人员、从事计算机相关工作的人员和铁杆爱好者的不同之处,命令行界面 (CLI) 的使用就是其中的一个重要标志。许多网络和计算设备都有命令行界面,通过它们可以快速高效地管理设备。互联网上最繁忙的网站和骨干服务大多基于 BSD 或 Linux 系统,且不使用或甚至未安装桌面图形用户界面 (GUI)。这使得命令行界面成为工作中的一个重要组成部分。在大多数现代环境中,自动化、配置和脚本编写都围绕命令行界面进行。
命令行与终端与 Shell
我所说的命令行界面有很多名称。你可能会听到命令行、命令行界面、命令提示符、命令行环境、Shell、Shell 提示符、Shell 环境、终端、SSH 或其变体。虽然存在一些关键区别,但这些区别对 DevSecOps 从业者来说大多数都不重要。
Shell 是一个提供计算设备命令行界面的程序。就像有许多看起来功能相同的程序一样,也有许多 Shell 程序。一种常见的 Shell 被称为 Bourne-again shell 或 bash。它足够常见且广泛可用,因此除非另有说明,本书其余部分默认使用 bash。如果你使用的是 Mac 或 Linux,那么你可以通过终端访问已安装的 Shell。值得注意的是,根据 macOS 的版本,默认的 Shell 可能是 bash 或 Z shell。
注意
在谈论 bash 时,大小写问题值得注意。当“bash”一词出现在句首时,需要大写。然而,当将 bash 作为命令引用时,它应为小写,因为在你使用命令或 Shell 的任何系统上它都会是小写。我的建议是:忽略你在引用 bash 时看到的大小写差异。我保证不会以此为借口随意大写“bash”,但你可能会偶尔在本书或互联网上看到“Bash”这个词。在这种格式下,“Bash”和“bash”是相同的,但在使用命令时,命令本身总是小写的。幸运的是,你通常只会在编写脚本时将“Bash”作为开头的行使用。
并非所有的 CLI 都是一样的
Windows 中的命令提示符提供了基于 DOS(磁盘操作系统)的界面,与 Linux 中更强大的 Shell 环境相比,其功能非常有限。Windows 的 PowerShell 是对命令提示符的一种改进,使得对 Windows 环境的完全脚本化访问成为可能。然而,鉴于 Linux 的重要性,微软创建了 Windows Subsystem for Linux (WSL),它提供了几乎完整的 Linux 体验,使 Windows 用户能够通过安装一个或多个流行的 Linux 发行版来利用 CLI。
过去几年中,安装 WSL 的过程不断演变,现在 WSL 已被称为 WSL 2。我还没有找到一种“百试百灵”的方法来在 Windows 系统上安装 WSL,因为在特定的 Windows 系统上可能会安装许多不同的配置和功能。甚至我从比尔·盖茨那里得到的 Windows 安装程序在第一次尝试安装 WSL 2 时也没有成功,且中间还需要进行一系列重启。抛开这些不谈,你可以在 WSL 文档中找到安装 WSL 2 的说明。
为什么我需要命令行?
多年来,我听到过“为什么我需要命令行 [或 SSH 或终端]?”这个问题的各种版本。答案很简单:速度。DevSecOps 从业者的许多(可能是所有)工作都可以通过 CLI 更快、更高效地完成。在使用 CLI 时,你的手不需要离开键盘去点击菜单或按钮。
在编程时,可以使用像 Vim 这样的编辑器完全在键盘的初始位置上操作,而涉及安全和运维的软件将有一个命令来运行,无论是作为 GUI 的补充,还是作为执行程序的唯一手段。
一个非常简单的 CLI 用例,包括安装 WSL Linux,就是创建重要文件的备份。rsync 命令可以用于将文件从本地计算机同步或传输到共享存储或备份的 USB 驱动器。我管理一个 DJ 的音乐库,其中包含大约 2 万个文件,分布在一个深层目录结构中。这些文件以一个大/未压缩的版本存储,然后以几种其他格式存储,文件大小较小。我使用 rsync 命令来创建这些文件的备份。如果网络连接出现问题或进程由于某种原因停止,rsync 将从中断处继续。如果添加了文件,rsync 只会发送更改过的文件,而不是重新发送所有文件。
开始使用命令行
如果你使用的是 Mac 或 Linux,那么你已经可以通过终端窗口使用功能齐全的 CLI。如果你使用的是 Mac,那么在“应用程序”→“实用工具”中找到终端,将直接进入 CLI。访问 Linux 上的 CLI 方式因发行版和访问方式的不同而有所不同。如果有桌面环境,你通常会找到一个终端程序。否则,使用安全 Shell (SSH) 连接到 Linux 计算机也能达到同样的效果。
如果你使用的是 Windows 10 或 11 电脑,那么安装 WSL 2 是一个简单的入门方式。如果你使用的是更早版本的 Windows 或无法安装 WSL 2,那么虚拟化软件如 VirtualBox 可以让你安装一个完整的 Linux 发行版。
在本章后面以及整个书中,将频繁使用命令行。此外,附录 B 包含了一些帮助你在命令行中导航的精选命令。现在,让我们从命令行转向对协议的高层概述。
协议:高级概述
互联网通过一系列协议进行通信。谈到通信时,协议仅仅是对每一方如何行动的约定。想象一下电话中的语音对话。一方拨打电话,接收方接听电话并以某种形式说“你好”或类似的问候语。拨打电话的一方随后回应问候,可能也说“你好”。拨打方可能在问候之后进行自我介绍,并说明通话的目的。
这个叙述描述了语音通话的典型协议,其中每一方都应该以某种方式行事。考虑当协议因某种原因中断时会发生什么情况。有时,在接收方刚拿起电话听筒时会有来电,这样他们可能不知道有来电,因此不会说“你好”来开始对话。更常见的情况是接收方回答“你好”后,接着是一个长时间的停顿,等待自动拨号软件连接到另一端的真人。这引入了协议中的超时概念。当接收方说“你好”时,他们通常期望在短时间内得到回应。如果没有回应,那么这很可能是一通自动拨号的电话。
关于电话对话的协议讨论可以扩展到日常生活中的许多人际互动。没有协议,就会一片混乱。计算机,尤其是网络通信,都是围绕协议的遵从性构建的。就像人际互动一样,这些协议确保了互操作性。如果没有协议,每个供应商都会有自己实现的各种通信方式,而这些通信方法很少会兼容。想要向使用不同供应商产品的人发送电子邮件吗?你需要注册那个网络并使用专有软件来进行操作。
为了避免不可互操作软件的噩梦,互联网主要建立在共同、共享和开放的协议之上。通信的基础是互联网协议(IP),它有多种方式可以从一个点传输到另一个点,从一个设备传输到另一个设备。许多其他常见且基础的网络服务也是类似的,依赖于 IP 作为通信的基础。本节将探讨协议层及相关的网络模型。
协议层
与网络相关的通信通常由两种模型之一表示,即开放系统互连 (OSI) 模型或 TCP/IP 模型。图2-1展示了 OSI 模型。
TCP/IP 模型与 OSI 模型类似,只是将会话层、表示层和应用层合并为一个单一的应用层,而数据链路层和物理层则合并为一个单一的链路层或本地网络层。图2-2展示了这一模型。
当设备通过网络通信时,数据从应用程序(如网页浏览器)沿着层次向下传输,最终到达物理介质,如有线以太网或用于 WiFi 的无线信号。接收方然后将数据沿层次向上传递到接收方的对应应用程序。
两种协议及另一个协议
传输控制协议 (TCP) 和用户数据报协议 (UDP) 是你日常最常遇到的协议。TCP 是面向连接的,而 UDP 是无连接的。这种差异意味着,使用 TCP 的应用程序应该会按顺序接收数据包,而使用 UDP 的应用程序则需要负责确保数据包已经到达,并在数据包未到达时请求重新传输。对于 DevSecOps 从业者而言,许多关键内容依赖于 TCP,唯一显著的例外是域名系统 (DNS) 协议,本章稍后将对此进行讨论。
一个与众不同的协议是互联网控制消息协议 (ICMP)。ICMP 是你可能用来验证连接性的 ping 命令背后的协议。本章不会深入探讨 ICMP,仅会做表面介绍。然而,在 ICMP 的背景下,有各种消息类型由路由器和网络设备用于标识网络状态。使用 ping 命令时,你发送的是 ICMP 消息类型 8,即“回声请求”,如果被测设备响应,它会以“回声应答”回应,也就是 ICMP 消息类型 0。
为什么这很重要?
如果你是一名开发人员,正在学习 DevSecOps,可能已经问过:“为什么这些内容重要?”或“它们如何帮助我?”这些问题是合理的。学习协议和协议层很重要,因为 DevSecOps 在每个团队彼此更多了解时最为成功。安全分析师和运维人员必须熟悉协议,至少为了能够在防火墙中打开端口。开发人员可以通过以安全分析师容易理解的方式表达需求来更快地打开这些端口,例如说“此应用程序需要 tcp/443 出站”比“它需要连接到他们的服务器进行激活”更有效。
基础互联网协议
前一节简要定义了协议,并进一步探讨了表示互联网通信分层性质的两种模型。本节将继续探讨协议,涵盖一些在 DevSecOps 组织中经常遇到的基础互联网相关协议。本节从 DNS 开始,它是其他服务赖以存在的基础。值得注意的是,本节和本书确实有意跳过了对协议头的讨论。尽管会讨论 IP 地址,并介绍 TCP 和 UDP 之间的简单区别,但无需熟记 TCP 的三次握手过程。
在本节和本书的其余部分中,你将看到“RFC”或其复数形式“RFCs”这一术语。RFC,或称请求评论 (Requests for Comments),是互联网运行的标准。由互联网工程任务组 (IETF) 创建,RFC 负责将软件和硬件的预期行为编纂成文。有关 RFC 和其背后过程的更多信息,可以在 IETF 网站上找到。
DNS
域名系统 (DNS) 是使我们无需记住 IP 地址就能在互联网上进行通信和获取信息的原因。从技术上讲,名称解析本身实现了这一点,还有其他手段可以提供名称解析。但维护一个包含我可能想要通信的每个主机的文本文件将非常麻烦。因此,DNS 是互联网名称解析的焦点。
DNS 由 RFC 1034 和 1035 定义,提供了一种分层方法,用于共享对域的控制权和命名节点或主机的责任。在 DNS 的根部是一个单一的点,它分支到几个顶级域 (TLDs)。TLDs 是通用的,如 com、net、edu 和其他许多。TLDs 也可以是国家代码顶级域 (ccTLDs),如 uk 或 de。图 2-3 展示了 DNS 的分层结构。
在顶级域名 (TLD) 向公众开放之前,只有少数几个通用顶级域名。现在有许多通用顶级域名。根区数据库包含当前顶级域名的列表。
个人和组织可以在所需的顶级域名下注册域名,并且必须遵守被授权管理该顶级域名的注册商的规则。在 com 顶级域名下注册一个域名通常为期一年,并且需要支付少量费用。注册域名时,至少需要两个权威名称服务器,在这种情况下,“权威”一词具有特别的含义。
当一个域名被注册时,该域名内的命名控制权被委托给注册人,即注册该域名的个人或组织。与该域名关联的 DNS 服务器是权威服务器,这意味着当有关于该域名主机的查询发送时,该查询会被发送到其中一个权威服务器,然后由其作出相应的回应。
主机名解析
假设主机有一个有效的 IP 地址,并且有一个或多个 DNS 服务器可用,当该主机想要开始在网络上进行通信时,主机需要将友好名称转换为 IP 地址,以确定将消息发送到哪里。大多数计算机和服务器首先会检查存储在本地的一个名为“hosts”的文件。hosts 文件在 macOS 和 Linux 系统中存储在 /etc/ 目录中,在较新版本的 Windows 中则位于 %SystemRoot%\System32\Drivers\etc 目录中。hosts 文件的内容各不相同,但通常包含有关本地主机地址的信息。例如,macOS Big Sur 中的 /etc/hosts 文件包含以下内容:
##
# Host Database
#
# localhost is used to configure the loopback interface
# when the system is booting. Do not change this entry.
##
127.0.0.1 localhost
255.255.255.255 broadcasthost
::1 localhost
Android 和 iOS 系统也包含 hosts 文件,但编辑这些文件更为困难,通常不是 DevSecOps 工程师会做的事情。
由于 hosts 文件是首先被查询的,因此有机会劫持或绕过正常的名称解析过程。当开发人员希望请求被发送到他们的本地计算机或与 DNS 中定义的不同的计算机时,这样做可能对开发和测试有帮助。然而,假设目标计算机未在 hosts 文件中定义,则接下来会查询 DNS。
从广义上讲,每个接收到 IP 地址的设备通常还会接收到一个或多个 DNS 服务器,这些服务器代表这些设备从其他 DNS 服务器获取主机名。“通常”和“接收到”这两个词在这里有特殊含义。没有规定必须包含或使用 DNS 服务器。一个主机可以在没有 DNS 服务器的情况下接收 IP 地址并正常通信,前提是主机要么有本地 hosts 文件,要么不使用主机名进行通信。此外,“接收到”一词可以指手动分配 IP 信息或通过动态主机配置协议 (DHCP) 等自动方式获取 IP 信息。
这些 DNS 服务器被称为解析器,因为它们提供主机名解析。如果你正在阅读的设备连接到 WiFi 网络,那么你可能有一个本地网络中的 DNS 服务器,当你尝试访问 时,它负责获取 IP 地址。
请注意解析器和权威名称服务器之间的区别。解析器负责从客户端设备获取查询答案,即使该解析器不对所查询的域负责或不是权威的。权威名称服务器是一个或多个域的所有者或授权者。解析器也可能是一个或多个域的权威服务器,但从逻辑上讲,主机名解析和权威名称解析是两个不同的概念。从技术上讲,你可能听说过“递归解析”或“递归解析器”这个术语,指的是为你获取答案的 DNS 解析器,但就本章而言,知道解析器和权威名称服务器之间存在区别就足够了。
图2-4展示了从客户端计算机到本地解析器的 DNS 解析过程,解析器随后查询 的权威服务器以获取 的 IP 地址。然后回复被返回给解析器,再由解析器将答案传回客户端。
图2-5 展示了当本地解析器同时也是某个域的权威服务器时会发生什么情况。虽然这种情况对于家庭用户来说比较罕见,但在企业场景中则更加常见,因此对于 DevSecOps 工程师来说,理解这一点尤为重要。
此外,在企业场景中,可能会存在分割授权的情况,即当从内部查询时,主机名解析为内部 IP 地址,而从外部查询时,解析为不同的 IP 地址。这种情况出现的原因有很多,包括测试的方便性以及控制流量的能力。图2-6 展示了这种情况;请注意,根据查询者的不同,同一个查询会得到不同的答案。
这些图示有助于说明 DNS 的复杂性,以及为什么在从开发阶段转移到测试阶段再到生产阶段时,DNS 可能会引发困难。
起始授权和生存时间
在这变成一本 DNS 书籍之前(已经有许多这样的书籍,其中包括由 Cricket Liu 和 Paul Albitz 撰写的权威著作《DNS and BIND》(O'Reilly, 2006)),还有一个问题需要简要讨论。每个 DNS 区域都包含一个起始授权 (SOA) 记录,用于定义域的元数据。与 DevSecOps 从业者相关的一些关键点包括:
除了 SOA 本身存储的值外,还有一个生存时间 (TTL) 值,它是为整个域配置的,也可以按记录进行配置。TTL 控制递归服务器在再次请求之前缓存有关给定记录的信息的时间。TTL 越长,对权威名称服务器的负载就越小。然而,TTL 越长,递归服务器发现更改所需的时间就越长。
从 DevSecOps 的角度来看,当存在停机时间或需要 DNS 更改的配置更改时,DNS TTL 变得尤为重要。当你知道即将进行的部署需要更改 DNS 记录时,最佳实践是降低受影响记录的 TTL,这样更改传播所需的时间就会减少。较小的 TTL 带来的较短停机时间通常会抵消对 DNS 服务器的较高负载。
通过降低 TTL,你迫使所有地方的解析器请求新的 IP 地址信息。降低 TTL 需要计划,因为现有 TTL 值需要过期,新的 TTL 值才能生效。例如,如果 A 记录的 TTL 为 604,800 秒或 7 天,那么如果你在部署前一晚更改 TTL 并没有多大意义,因为任何请求名称解析的解析器还有 6 天时间才会再次请求。因此,了解现有的 TTL 并计划需要 DNS 更改的部署是必需的。
附录 B 包含一些在故障排除 DNS 时有用的命令。在附录中,你会找到用于确定给定 DNS 记录 TTL 的 dig 命令,以及其他基本的 Linux 命令等。