TCOIP-指南-全-

TCOIP 指南(全)

原文:The TCPIP guide

译者:飞龙

协议:CC BY-NC-SA 4.0

引言

TCP/IP 指南的目标

每个着手撰写书籍或其他文档的作者都有一定的目标,他们希望在作品完成后实现这些目标。这就是为什么你可以走进图书馆或书店,拿起几本涵盖相同主题的书,发现它们惊人地不同——不仅内容或范围不同,而且对材料的整体方法也不同。

当我开始写这本书时,我也有许多目标。你当然不需要知道它们才能阅读和欣赏这些材料,但了解我在写作时的想法可能会在阅读时帮助你。而且如果你在购买TCP/IP 指南之前阅读这些信息,了解我在写作这本书时追求的目标可能会帮助你决定这本书是否适合你。

我编写这本书的整体目标是创建一个资源,让任何人都能深入理解 TCP/IP 技术真正是如何工作的。为了实现这一目标,我设定了一系列具体目标,这些目标指导了我的写作工作:

全面性 与大多数撰写涵盖广泛主题的资源作者一样,我希望TCP/IP 指南能够全面。当然,没有任何单一文档可以涵盖一切,所以我需要限制材料的范围。然而,我感觉我涵盖的 TCP/IP 整体内容比任何其他单一书籍或其他资源都要多。

可理解性 创建一个全面性的资源很重要,但我认为更重要的是,这本书必须是可理解的。在过去的几年里,我有机会审查了数百本与网络相关的书籍、指南、网站和论文。我发现,尽管它们大多数质量很高,但太多的人使用未经解释的技术术语,或者假设读者对网络概念和技术有广泛的先验知识。我非常努力地确保我的描述,即使是关于非常复杂的概念,也能被几乎每一位网络学生理解。

理由 确实,了解每个 TCP/IP 协议的工作方式非常重要。然而,要真正理解复杂材料,一个人还需要了解事物之所以如此的原因。在编写这份材料时,我始终试图解释不仅仅是什么,还要解释 TCP/IP 的为什么。我预见了并回答了我认为在学习这项技术的人心中可能会普遍出现的问题。

插图 正如人们所说,“一图胜千言”。有许多概念,无论多少文字都无法充分解释,而一个简单的插图就能解决问题。因此,我花费了数月时间创建了 300 多个图表(有些简单,有些则不那么简单!)来补充TCP/IP 指南中的书面材料。

用户友好性 我有意打破了许多传统书籍作者的规则,创建了一个使用对话式、第一人称风格,并在适当的地方加入一些幽默的文档。我的意图是在你阅读可能相当技术性困难的内容时让你感到宾至如归。我希望你认为我是一个坐在你电脑旁边的朋友,在解释 TCP/IP 是如何工作的,而不是一个在讲台上对你布道的教授。

组织 许多网络书籍只是简单地列出数十个主题,一个接一个,让读者 wonder 如何一切事物都相互关联。当我最初开始写这本书时,我花了几周的时间来组织它,结果是结构清晰地表明了主题是如何相互关联的。我还仔细安排了每个单独的部分,以确保它以有意义的方 式涵盖了其主题。

多层次的细节 我意识到,阅读 TCP/IP 书籍的一些人可能只想对其构成协议的操作有一个快速的总结,而其他人则想了解一切工作的细微差别。我提供了大多数读者都会想要的全部细节,同时在每一章中包括了概述主题,总结了每种技术,以便快速浏览。这给了你选择的机会,要么浏览表面,要么“深入研究”,取决于你的选择。

平台独立性 我尽一切可能避免用特定于任何硬件或软件平台的术语来描述 TCP/IP。尽管我大多数计算使用 PC,一些任务使用 UNIX,但大部分材料并不特定于任何类型的设备或操作系统(尽管我更关注小型计算机的网络而不是大型计算机)。

我在实现这些目标方面取得了多大的成功?我希望认为自己做得相当不错,但最终,你们将是评判者!

《TCP/IP 指南》的范围

解决问题的第一步是认识到你有一个问题。因此,我必须向你,我的读者,坦白。我有一个问题:对……细节的沉迷。每次我着手写关于某个特定协议、技术或概念的文章时,我都会设定一个关于我想写多少内容的适度目标。我总是开始时就知道我真的需要控制自己,以防止我的项目永远进行下去。但随着我对每个主题的探索,我了解得越来越多,我开始对自己说些像,“这很重要。我必须包括对它的覆盖,”和,“如果我要涵盖主题#1,我也应该涵盖主题#2,因为它们是相关的。”就是这样,我把六个月的项目变成了多年的挑战。

然而,尽管在这个领域自我控制对我来说是一个弱点,即使是我也意识到我无法在这本书中涵盖与 TCP/IP 相关的所有内容。考虑到 TCP/IP 套件包含数十个协议和技术,每个都有厚厚的书籍来描述。我愿意花几年时间在这个项目上,但不是几十年!因此,我不得不在一定程度上限制本书的范围,既为了保留我剩余的理智,也为了避免你不得不翻阅一个荒谬庞大的文档。

这里有一些不同的观点,可以帮助解释我做出限制《TCP/IP 指南》范围的决定:

理论与实践 这本书主要是一个关于 TCP/IP 协议族的参考资源。这里的材料旨在让学生了解 TCP/IP 是如何工作的基本原理。我确实讨论了许多与 TCP/IP 互连网络操作相关的“现实世界”实际问题,但这并不是我的主要关注点。如果你真的想了解 TCP/IP 是什么以及它是如何工作的,你来到了正确的地点。如果你只是想得到如何使用 TCP/IP 在家中将几台 PC 连接起来的简单说明,这本书可能不适合你。

当前与未来协议 本书的大部分重点在于 TCP/IP 的现状。套件总是在变化中,新的协议不断被编写,现有协议的修订也在持续发布。我没有提供对仍在开发中的技术的广泛覆盖,以保持本书的规模可控,并防止本书在上架之前就过时。这一一般规则的例外是互联网协议的第 6 版(IPv6),它对 TCP/IP 大多数操作的核心进行了重大改变。尽管尚未得到广泛应用,但 IPv6 在其开发中已经足够成熟,我认为任何 TCP/IP 的学生都需要了解它是什么,学习它是如何工作的,并理解其重要性。因此,我包括了几个关于 IPv6 的详细章节,并提到了它如何影响其他几个关键协议的操作,如互联网控制消息协议(ICMP)、域名系统(DNS)和动态主机配置协议(DHCP)。

应用覆盖范围 在 TCP/IP 互连网络上运行着成千上万的不同应用,我根本不可能希望描述它们全部。本书的范围仅限于最重要的、经典的 TCP/IP 应用和应用协议,例如电子邮件、通用文件传输和万维网。

TCP/IP 与互联网 TCP/IP 协议集和互联网在许多方面非常紧密相关,正如你在阅读本书时会发现的。事实上,它们经常紧密相连,以至于很难在不提及另一个的情况下讨论其中一个。然而,互联网作为一个整体是一个庞大的主题,试图用一般术语来描述它将大大增加本书的篇幅。因此,我在解释 TCP/IP 技术时仅描述互联网问题。例如,虽然我在本书中涵盖了万维网,但我只简要讨论了其一般性。我专注于讨论实现它的超文本传输协议(HTTP)的工作原理。我不谈论如何设置网站、如何选择网页浏览器或任何这类细节。这些主题在各种各样的书籍、论文和,当然,网站上都有涉及。

有限的 TCP/IP 安全覆盖 安全是一个非常重要且庞大的主题,尤其是在现代网络中。本书确实包含了一个相当详细的关于 IP 安全协议(IPSec)操作的章节,并在描述其他几个协议和技术时也涉及了安全问题。然而,它并没有专门针对安全考虑的详细讨论。

小型计算机导向 从一般意义上讲,TCP/IP 技术可以用来连接任何具有适当硬件和软件的设备。然而,有些问题需要我专注于特定类型的底层网络和设备的工作原理;这在我的一些图表中尤其如此。在这些情况下,我的偏好通常是展示 TCP/IP 如何连接典型的小型计算机,如 PC、Macintosh 和 UNIX 工作站,这是大多数人使用的设备。

TCP/IP 指南特色

我创建了《TCP/IP 指南》以为您提供关于 TCP/IP 的无与伦比的信息广度和深度。这意味着在这本书中包含了很多内容——它有 88 章、几百个部分和超过 1600 页。然而,当我撰写这部巨著时,我意识到真正的目标不仅仅是提供大量的详细信息,而且是以一种您可以轻松理解的方式呈现。这需要不仅仅是写大量的文本并将其全部放入一个大文件中。

因此,我在这本书中融入了许多特殊功能,以帮助您更容易地“消化”。这包括本书的特殊结构、帮助您记住主题的特殊插入内容等。

首先,《TCP/IP 指南》使用三级结构来组织其内容。整本书分为三个总体部分,分别涵盖概述/背景信息、底层协议和高层应用协议。在每个部分中,有许多部分,它们将相关的章节分组在一起。每个章节又通过章节和副章节的结构来呈现,以尽可能使材料易于理解。

《TCP/IP 指南》 包含超过 300 幅详细的插图,这些插图支持 TCP/IP 技术和协议的文本描述,并有助于理解复杂的概念。大多数插图都包含简短描述,让您无需阅读全文即可快速了解插图的意义。本书还包括超过 300 个表格,以组织化和可读的方式呈现大量信息,或突出显示示例。

《TCP/IP 指南》中的大多数讨论都是以自由文本形式呈现的,正如您在任何文档中预期的那样。然而,当我需要澄清或解释一些我认为您需要知道,但与讨论的主题没有直接关系,或者足够“边缘”以至于需要从正文分离出来以避免打断其流畅性时,我会使用注释。例如,包括术语解释、“边栏”历史讨论、轶事以及与我描述特定概念相关的澄清。

最后,但绝对不能忽视的是,关键概念插入。我非常努力地编写这本书,旨在提供多种方式来呈现信息,以更好地适应不同读者的学习风格。为此,我创建了数百个这样的特殊段落,总结并突出《TCP/IP 指南》中最重要和基本的知识点。它们在快速提炼主题精髓或刷新对某一主题的记忆时非常有用。然而,显然它们包含的细节很少,因此您不应仅通过阅读此类摘要就假设您完全理解了某个主题或概念。

TCP/IP 指南在线版!

这本书最初起源于一个名为“TCP/IP 指南”的在线网站。该网站仍然活跃,并呈现与本书相同的信息,尽管格式和结构略有不同。

如果您在旅行或需要在没有书的情况下快速查找 TCP/IP 信息时,可能会发现网站的在线版本很有用。作为额外的奖励,网站的页面广泛链接,便于使用,图表也是全彩色的。在线版本还包括完整的超链接目录和搜索引擎!请访问以下网站:

www.TCPIPGuide.com.

您的反馈和建议

这本书与典型的技术参考书不同的一个方面是,它是一个非常个人的作品。当您阅读这里的内容时,我希望您感觉就像我正在亲自向您解释许多技术和概念一样,因为这就是我写作时的感觉。这类已出版的书籍本质上是一种“单向”的沟通,从我开始到您结束;然而,我也很感兴趣您想对我说什么。因此,我强烈鼓励您提供关于这本书的反馈和您可能提出的建议。

首先,我要指出的是,所有书籍都存在错误,尽管这本书经过了严格的技术审查和多次编辑过程,但可能也不例外。在联系我关于这本书中的错误或问题时,请先查看勘误表,看看您发现的问题是否已经被报告过。您可以在以下链接找到该页面:www.tcpipguide.com/bookerrata.htm。我欢迎您提出建设性的批评和建议。如果您对材料有任何不喜欢的地方,请告诉我。更好的是,提出改进的建议。我也很高兴阅读您的赞美或投诉,并且我会乐意回答与本书使用直接相关的问题。您可以通过以下邮箱联系我:tcpipbook@tcpipguide.com。

第一部分-1. 网络基础

TCP/IP 概述和背景信息

他们说最好的开始方式是从一开始,而你现在正处在这个起点。本节包含了一些背景信息,这些信息将帮助你理解网络是什么以及 TCP/IP 在整体方案中的位置。这些介绍性信息将帮助你轻松地进入 TCP/IP 的学习,对于初涉网络世界的人来说尤其有价值。

本节包含三个部分。第一部分涵盖了网络的一些重要基本方面,讨论了它们的使用方式、定义它们的标准、描述它们的术语以及更多内容。第二部分描述了重要的 OSI 参考模型,这是理解网络技术功能和组织的一个基本工具。第三部分对 TCP/IP 协议套进行了高级概述,这将为本书中后两节对单个 TCP/IP 协议的更完整讨论奠定基础。

让我们开始吧!

第一章

第二章

第三章

第四章

与许多其他 TCP/IP 相关资源的作者不同,我并不假设读者已经知道网络是什么。毕竟,这就是你读这本书的原因!

本部分提供了关于网络的一些基本问题的概述。它包括对一些最基本网络概念和思想的讨论。它不仅为你提供了有用的背景材料,而且作为一个通用信息的存储库,这样我就不需要在书的其他许多地方重复它(如果你已经了解了这些基础知识,你也不需要在其他许多地方跳过它们)。这里涉及的主题对于理解某些 TCP/IP 概念是有用的。然而,其中一些材料非常广泛地面向整个网络,并不特定于 TCP/IP 互连网络。

本部分包含四章。第一章从广义上介绍了网络,描述了其基本特征,并区分了网络的大小和类型。第二章讨论了与网络性能相关的许多不同问题。第三章解释了网络标准和标准组织的重要性。最后,第四章提供了有关数据在计算机中存储和操作背景信息;如果你是计算机新手,在阅读本书的其他部分时,这些信息可能很有用。如果你在计算机网络和相关技术方面有经验,你可能希望跳过本书的这一部分。或者,你可以扫描章节的标题;如果你理解标题中提到的术语,你可能会跳过讨论。本书其他部分的相关交叉引用会根据适当的信息引用本部分内容,因此,如果你需要即时填补特定基本知识的空白,你可以很容易地做到这一点。

第一章:网络简介、特征和类型

无标题图片

对于网络新手来说,通常会有一些非常重要的问题。网络究竟是什么?描述网络的最重要的属性是什么?以及存在哪些类型的网络?讨论网络基础知识的明显起点是使用对整个网络的高层次介绍来回答这些问题。

本章分为三个部分。第一部分提供了对网络的快速介绍。我用最基本的方式来定义网络,然后通过描述一些优点和好处以及一些缺点和成本,将网络置于整体环境中。

第二部分讨论了描述和区分不同网络和网络技术的关键概念。在这里,我将定义你在学习网络时无法避免的术语和“热门词汇”。这里包括对协议、交换方法、网络消息类型、消息格式以及消息寻址方式的解释。我还讨论了客户端/服务器网络和对等网络之间的区别。

在最后一节中,我通过根据它们的大小和范围来区分它们,描述了主要网络类型,并展示了如何使用每种类型和大小。我讨论了局域网(LAN)、无线局域网(WLAN)和广域网(WAN),以及这三个主要类别的一些变体。我还探讨了与网络各种大小相关的许多术语,以及它们的使用方式,包括段、子网、互联网、内联网和外联网。

网络简介

在这个时代,网络无处不在,尤其是以互联网的形式。作为终极网络的互联网不仅改变了计算机世界,也改变了数百万人的生活。我们往往认为计算机应该连接在一起。事实上,现在,每当我在同一个房间里有两台电脑时,我很难将它们连接起来!

考虑到网络的普遍性,很难相信这个领域仍然相对年轻,尤其是在连接个人电脑方面。在讨论网络时,退一步从更高层次看待网络非常有用。它究竟是什么,为什么现在被认为如此重要,以至于大多数个人电脑和其他设备都会联网?

什么是网络?

对于这样一个包含众多不同技术、硬件设备和协议的广泛而复杂主题,网络实际上非常简单。一个 网络 仅仅是计算机或其他硬件设备通过特殊硬件和软件连接在一起的一个集合,这些连接可以是物理的也可以是逻辑的,使得设备能够交换信息和协作。“网络”这个术语描述了设计、实施、升级、管理和与其他网络和网络技术合作所涉及的过程。

小贴士

关键概念 网络是一组物理上或逻辑上连接在一起的硬件设备。这使它们能够交换信息。

网络被用于各种令人难以置信的目的。大多数学习网络知识的人会想到网络是连接个人电脑和其他“真正的”电脑,但你每天都会使用各种类型的网络。每次你拿起电话、在商店使用信用卡、从自动取款机取款,甚至插入电器时,你都在使用某种类型的网络。

实际上,这个定义甚至可以扩展到技术领域之外。我相信你已经听说过“networking”这个术语,用来描述通过朋友和同事寻找雇主或雇员的过程。同样,这里的想法是,独立的单元连接在一起以共享信息和协作。

个人电脑的广泛联网是一个相对较新的现象。在它们存在的头十年左右,个人电脑在很大程度上是“孤岛”,很少连接在一起。在 20 世纪 90 年代初,随着企业意识到网络可以提供的优势,个人电脑联网开始变得流行。到了 20 世纪 90 年代末,拥有两台或更多电脑的家庭网络也开始真正兴起。

这种小型设备的互联,从某种意义上说,是回到了主机计算机的黄金时代。在计算机变得小型和个人化之前,它们是大型且集中的机器,许多用户通过远程终端共享这些机器。尽管将所有这些计算机功能集中在一个地方有许多缺点,但一个好处是所有用户都连接在一起,因为他们共享中央计算机。

个人电脑消除了这种优势。网络试图将计算移动到一个中间地带。它为 PC 用户提供了两全其美的优势:个人电脑的独立性和灵活性,以及主机计算机的连接性和资源共享。事实上,如今网络被认为如此重要,以至于很难想象一个拥有两台或更多计算机的组织不会想要将它们连接起来!

网络的优势和好处

你无疑听说过“整体大于部分之和”这个表达。这个短语很好地描述了网络,并解释了为什么它变得如此受欢迎。网络不仅仅是几台通过电线连接在一起的计算机。如果正确实施,网络是一个为用户提供独特功能、超越单个机器及其软件应用所能提供功能的系统。

网络的大多数好处可以分为两大基本类别:连接性共享。网络允许计算机及其用户相互连接。它们还允许轻松共享信息和资源,以及以其他方式简单合作。由于现代商业如此依赖信息的智能流动和管理,这种易用性告诉你很多关于为什么网络如此有价值的原因。

在这里,不分先后顺序,列举了一些通常与网络相关联的具体优势:

连接性和通信 网络连接计算机及其用户。建筑物内或工作组内的个人可以通过 局域网 (LANs) 连接;远距离的局域网可以相互连接形成更大的 广域网 (WANs)。一旦计算机连接,网络用户就可以使用电子邮件等技术相互通信。这使得商业(或非商业)信息的传输比没有网络时更容易、更高效、更便宜。

数据共享 网络最重要的用途之一是允许数据共享。在联网变得普遍之前,一个想要为她的经理准备报告的会计员工必须在她自己的电脑上制作报告,把它放在软盘上,然后走过去给经理,经理会将数据传输到她的电脑硬盘上。(这种基于“鞋”的网络有时被讽刺性地称为 sneakernet。)

真正的网络允许成千上万的员工比这更容易、更快地共享数据。它还使得许多应用程序成为可能,这些应用程序允许许多人访问和共享相同的数据,例如数据库、团队软件开发等等。

硬件共享 网络促进了硬件设备的共享。例如,你不必给部门中的每个员工配备昂贵的彩色打印机(或者再次求助于 sneakernet),你可以在网络上放置一台打印机供大家共享。

互联网接入 互联网本身就是一个巨大的网络,所以每次你访问互联网时,你都在使用网络。今天互联网的重要性很难夸张!

互联网接入共享 小型计算机网络允许多个用户共享单个互联网连接。特殊的硬件设备使得连接的带宽可以轻松地分配给需要的人,这些设备允许组织购买一个高速连接而不是多个较慢的连接。

数据安全和管理工作 在商业环境中,网络允许管理员更好地管理公司的关键数据。管理员不必像用户创建数据时那样随意地在几十甚至几百台小型计算机上分散数据,而是可以将数据集中存储在共享服务器上。这使得每个人都能轻松找到数据,并使管理员能够确保数据定期备份。管理员还可以实施安全措施来控制谁可以读取或更改各种关键信息。

性能提升与平衡 在某些情况下,你可以使用网络将计算任务分配到网络上的多台计算机上,从而提高某些应用程序的整体性能。

娱乐 网络促进了多种类型的游戏和娱乐。互联网本身提供了许多娱乐资源。此外,许多多人游戏在局域网(LAN)上运行。许多家庭网络正是出于这个原因而建立的,并且通过广域网(WAN,包括互联网)进行游戏也已经变得相当流行。当然,如果你在经营一家企业,并且有容易被娱乐的员工,你可能会坚持认为这实际上是网络的一个缺点而不是优点!

提示

关键概念 在高层次上,网络的优势在于它们允许计算机和人们连接在一起,以便他们可以共享资源。网络的一些具体好处包括通信、数据共享、互联网接入、数据安全和管理工作、应用性能提升和娱乐。

网络的不利因素和成本

现在我已经讨论了网络的重要价值和许多有用的好处,我必须用那个老对手——现实主义的宿敌 TANSTAAFL(There ain't no such thing as a free lunch,即“没有免费的午餐”)来让你回到现实。对于那些不是海因莱因粉丝的人来说,这个首字母缩略词代表“没有免费的午餐”。尽管网络确实代表了一个整体,其价值大于其各部分的总和,但它确实与一些真实且重要的成本和缺点相关。

这里有一些网络的不利之处:

网络硬件、软件和设置成本 当然,计算机并不是神奇地自己形成网络的。设置网络需要投资硬件和软件,以及用于规划、设计和实施网络的资金。对于一个有两个或三个 PC 的小型家庭网络来说,这相对便宜。考虑到今天网络硬件的低价格,这大约是一百美元左右,考虑到操作系统已经为网络设计,实际上几乎没有设置成本。然而,对于一家大公司来说,成本可能轻易达到数万美元或更多。

硬件和软件管理及行政成本 在除了最小的实施之外的所有情况下,网络的持续维护和管理需要 IT 专业人士的关心和注意。在一个已经有系统管理员的较小组织中,网络可能属于这个人的工作职责范围,但这会占用其他任务的时间。在更实质性的组织中,可能需要雇佣网络管理员,在大公司中,可能需要一个整个部门。

不希望共享 好事多磨;虽然网络使得有用信息的共享变得容易,但它也允许不希望的数据共享。在这方面,一个显著的共享问题与病毒有关,病毒在网络和互联网上很容易传播。减轻这些影响需要时间、金钱和行政努力。

非法或不希望的行为 与前一点类似,网络促进了有用的连接和通信,但也带来了困难。典型的问题包括滥用公司资源、减少生产力的干扰、下载非法或非法材料,甚至软件盗版。在较大的组织中,这些问题必须通过明确的政策和监控来管理,这再次增加了管理成本。

数据安全担忧 如果网络得到适当的实施,可以大大提高重要数据的安全性。相反,一个安全措施不足的网络将使关键数据面临风险,使其暴露于黑客、未经授权的访问甚至破坏的潜在问题。

大多数这些成本和潜在问题都可以由那些建立和运行网络的人来管理。最终,是否使用网络的选择是一个权衡利弊的问题。如今,几乎每个人都认为网络是有价值的。

小贴士

关键概念 网络有一些缺点,你可以权衡其许多积极方面。建立网络需要硬件、软件、维护和管理成本。还必须管理网络以确保其平稳运行并解决可能的滥用问题。当计算机连接在一起时,数据安全也成为了一个更大的关注点。

基本网络特性

有许多不同类型的网络和网络技术被用来创建它们。网络方法的激增通常有非常好的理由:不同的需求需要不同的解决方案。这种做法的缺点是,对于网络学生来说,有如此多的不同类型的协议和技术需要理解!

在你真正比较这些方法之前,你需要了解一些使网络成为其自身的最基本的特性。尽管网络类型可能非常不同,但它们通常基于许多共同属性来描述和甚至对比,我将在以下章节中讨论这些属性。

网络层、模型和架构

许多人发现网络难以学习的一个原因是它可能是一个非常复杂的话题。造成这种复杂性的主要原因是网络由如此多的硬件和软件元素组成。虽然网络用户可能认为他只在使用一个计算机程序(如网页浏览器)和一件硬件(如个人电脑),但这些只是更大谜团的一部分。为了在网络上完成最简单的任务,必须由数十个不同的组件通过传递控制信息和数据来协作,以实现网络通信的整体目标。

理解任何复杂系统的最佳方式是将它分解成部分,然后分析这些部分的功能以及它们是如何相互作用的。最合逻辑的方法是将整体功能集划分为模块化组件,每个组件负责特定的功能。同时,你还需要定义这些组件之间的接口,这些接口描述了它们是如何结合在一起的。这样,你可以通过以可消化的块来处理网络,从而简化网络的复杂性。

网络技术通常通过将它们的函数划分为来以这种方式进行细分,每一层都包含硬件和软件元素。每一层负责执行特定类型的任务,并与它上面的层和下面的层交互。层在概念上被排列成一个垂直的堆栈。底层负责更具体的工作,如硬件信号和低级通信;它们为高层提供服务。高层反过来使用这些服务来实现更抽象的功能,例如实现用户应用程序。

以这种方式将网络划分为层有点像制造设施中的劳动分工,并且会产生类似的好处。每个硬件设备或软件程序都可以专门化以执行该层所需的函数,就像装配线上的受过良好训练的专家一样。不同的模块可以根据需要以不同的方式组合。这样,也更容易理解网络的整体功能。

分层的一个其他重要好处是它使得由不同群体定义的技术能够互操作。为了实现这一点,每个人都需要就如何定义和使用层达成一致。为此最常用的工具是网络模型。该模型描述了网络中的不同层,每一层负责做什么,以及它们如何交互。一个普遍接受的模式确保了在创建硬件和软件时,每个人都处于同一页面上。

目前最常用的通用模型是开放系统互联(OSI)参考模型,它由七个堆叠层组成。这些层从底层的物理层(层 1),负责低级信号,到顶层的应用层(层 7),其中实现了应用软件。理解 OSI 模型对于理解整个网络是至关重要的。我在本书的第一部分-2 中对模型和层进行了更详细的解释,并提供了 OSI 参考模型的完整描述。

与模型的概念密切相关的是架构的概念。架构本质上是一组规则,它描述了构成堆叠层的一部分硬件和软件的功能。这样的规则集通常以规范或标准的形式出现,描述了使用该技术的设备和程序必须如何行为。网络架构旨在实现与 OSI 参考模型中特定连续层集相关的功能,无论是正式的还是非正式的。

在这本书中,我讨论了 TCP/IP,这是运行互联网的协议套件。TCP/IP 是一套复杂的技术,跨越了 OSI 模型的多层。通过检查 TCP/IP 的各个组成部分以及它们如何实现不同的 OSI 模型层,你将真正了解 TCP/IP 是如何工作的。首先,这个套件的名称 TCP/IP 来源于传输控制协议(TCP),它在 OSI 模型的第 4 层运行,以及互联网协议(IP),它在 OSI 模型第 3 层运行。IP 为第 4 层提供服务,并使用其下第 2 层的服务。TCP 使用 IP 的功能,并为它上面的层提供功能。

我将通过查看其架构以及一个专门为理解 TCP/IP 而开发的第二个特殊模型来开始对 TCP/IP 的更全面检查。这两个模型都在第八章中进行了探讨。

协议:它们究竟是什么?

如果你在这本书中会经常看到的一个词,那就是协议。你会看到对网络协议、互联网协议、高级协议、低级协议、协议栈、协议套件、子协议等的引用。显然,协议很重要,但许多参考资料和标准反复使用这个术语,却从未对其进行解释。这可能是因为这个术语有些模糊,可以有多种含义。

在某些情况下,如果你回到查看术语在日常英语中的使用方式,理解一个技术术语可能更容易。在现实世界中,协议通常指的是外交官遵守的行为准则或礼仪形式。这些人必须遵循一定的礼仪和正式规则,以确保他们能够有效地沟通而不会引起冲突。他们还必须了解在与来自其他国家的代表互动时,对他们有什么期望,确保例如,他们不会因为对当地习俗的不熟悉而冒犯任何人。事实上,大多数人都会遵循各种协议;它们是社会中的某种不成文规则。

这可能看起来与网络无关,但实际上,这是对网络协议的相当好的高级描述。它们定义了一种语言和一套规则和程序,使设备和系统能够进行通信。显然,计算机没有当地习俗,它们几乎不必担心犯下可能引起另一台计算机反感的错误。网络协议关注的是确保网络或互联网上的所有设备在通信过程中的各种操作上达成一致。

因此,协议基本上是一种确保设备能够有效通信的方式。在大多数情况下,一个单独的协议描述了在两个或更多设备中的一个特定软件或硬件元素之间如何完成通信。

在 OSI 参考模型的背景下,协议正式定义为规范同一层实体之间通信的规则集。例如,TCP 负责 TCP/IP 网络上的特定功能集。TCP/IP 网络上的每个主机都有一个 TCP 实现,这些主机在 OSI 模型的第 4 层逻辑上相互通信。

注意

“协议”一词的正式化 OSI 参考模型意义在 OSI 参考模型主题“横向层通信”(在第五章[Chapter 5. GENERAL OSI REFERENCE MODEL ISSUES AND CONCEPTS]中讨论,标题为“协议:横向(对应层)通信”)中有所涵盖

尽管 OSI 参考模型定义有时过于理论化,但这个协议的定义在评估现实世界网络中的协议时相当准确。如果某物没有指定通信方式,那么它可能不是协议。

提示

关键概念 网络协议定义了一组规则、算法、消息和其他机制,使得网络设备中的软件和硬件能够有效通信。通常,一个协议描述了在两个或更多设备中同一 OSI 参考模型层上的对应实体之间的通信方式。

尽管如此,术语协议在口语中经常用来指代网络中的许多不同概念。这里列出了该词的一些更常见的替代用法:

协议套件 很常见听到将协议这个词用来指代一组更恰当称为协议套件(或堆栈,指层堆栈)的协议。例如,当 TCP/IP 实际上是一组(大型)协议时,它通常被称为只是一个协议。

Microsoft Windows Protocols 将协议套件称为单个协议的问题的一个重要例子是微软 Windows 中的网络软件。它通常将完整的网络栈,如 TCP/IP 或 IPX/SPX,仅仅称为一个协议。然而,当你安装这些所谓的协议之一时,你实际上得到的是一个支持完整协议套件的软件模块。

其他技术 有时,一些根本不是协议的技术被称为协议,要么是出于惯例,也许是因为人们认为听起来不错。例如,TCP/IP 远程网络监控(RMON)通常被称为协议,而实际上它只是简单网络管理协议(SNMP)的增强,而 SNMP 本身就是一个协议!(有关 SNMP 和 RMON 的详细信息,请参阅第 III-4 部分[pt15.html "Part III-4. TCP/IP NETWORK MANAGEMENT FRAMEWORK AND PROTOCOLS"]。)

那么,一个协议是否真的是“真正的”协议,这真的重要吗?嗯,网络硬件设备和软件程序当然不在乎。但希望你在阅读了关于这个术语及其含义之后,在你学习过程中遇到这个术语时能够更好地理解它——尤其是在它可能并不总是与正式定义完全一致的情况下。

电路交换和分组交换网络

网络是通过特殊硬件和软件连接在一起的设备,这些硬件和软件允许它们交换信息。这句话中最重要的词是最后一个词:信息。正如你将在本书的探索中看到的那样,有许多方法可以在网络设备之间交换信息。还有许多方法可以对这些方法和使用它们的网络类型进行分类和描述。

区分网络技术的一个基本方法是基于确定信息将流经的设备之间路径的方法。用高度简化的术语来说,有两种方法:可以在设备之间预先设置路径,或者将数据作为单独的数据元素通过可变路径发送。

电路交换

电路交换网络方法中,用于整个通信的连接称为电路,在两个设备之间建立。关于电路性质的信息由网络维护。电路可以是始终存在的固定电路,也可以是根据需要创建的电路。即使两个通信设备之间可能存在许多通过中间设备的潜在路径,也只会使用其中一条路径进行任何给定的对话,如图图 1-1 所示。

电路交换网络的经典例子是电话系统。当你打电话给某人并且她接听时,你会建立一个电路连接,可以稳定地传输数据。这个电路无论使用多少中间设备来传递你的声音,其功能都是一样的。你使用它直到你需要它,然后终止电路。下次你打电话时,你会得到一个新的电路,这个电路可能(很可能)使用了与第一个电路不同的硬件,这取决于当时网络中可用的硬件。

电路交换 在电路交换网络中,在两个设备之间发生通信之前,会在它们之间建立电路。这以从设备 A 到设备 B 的数据导线的较暗线条表示,以及从 B 回 A 的匹配较亮线条。一旦建立,这些设备之间的所有通信都通过这条电路进行,尽管还有其他可能的数据通过网络设备之间传递的方式。将此图与 .

图 1-1. 电路交换 在电路交换网络中,在两个设备之间发生通信之前,会在它们之间建立电路。这以从设备 A 到设备 B 的数据导线的较暗线条表示,以及从 B 回 A 的匹配较亮线条。一旦建立,这些设备之间的所有通信都通过这条电路进行,尽管还有其他可能的数据通过网络设备之间传递的方式。将此图与图 1-2 进行比较。

数据包交换

数据包交换网络类型中,没有使用特定的路径进行数据传输。相反,数据被切割成称为数据包的小块,并通过网络发送。您可以根据需要路由、组合或分割数据包,以便将它们发送到最终目的地。在接收端,过程相反——数据从数据包中读取并重新组装成原始数据。数据包交换网络更类似于邮政系统,而不是电话系统(尽管这种比较并不完美)。一个例子在图 1-2 中显示。

数据包交换 在数据包交换网络中,在设备之间发送数据之前,不会建立电路。数据块,即使来自同一文件或通信,也可能在从一台设备到另一台设备的旅途中采取任何数量的路径。与 .

图 1-2. 分组交换 在分组交换网络中,在设备之间发送数据之前不设置电路。数据块,即使来自同一文件或通信,也可能在从一台设备到另一台设备的旅途中采取任意数量的路径。将此与图 1-1 进行比较。

小贴士

关键概念 网络技术的一种分类方式是基于用于在设备之间传输数据的路径。在电路交换中,首先建立电路,然后使用该电路来传输设备之间的所有数据。在分组交换中,在通信的设备之间不创建固定路径;它被分成数据包,每个数据包可能从发送者到接收者采取不同的路径。

应该选择哪种交换方法?

考虑这些替代方案时,一个常见的诱惑是询问哪个更好;答案是都不是。有些地方更适合其中一个,但如果其中一个明显优于另一个,两种方法就不会都被使用。

选择交换方法的一个重要问题是网络介质是共享的还是专用的。你的电话线可以用来建立电路,因为你可能是唯一可以使用它的人——假设你能让那个讨厌的配偶/孩子/姐妹/兄弟/父亲/母亲远离它。然而,这并不适用于通常使用单一共享介质和基带信令的局域网。如果两个设备要建立连接,它们将锁定所有其他设备长达一段时间。将数据分成小块并逐个发送更有意义。然后,如果其他两个设备想要通信,它们的数据包可以交错,每个人都可以共享网络。

能够在没有专用数据路径的情况下让许多设备同时通信的能力是分组交换成为今天主流的一个原因。然而,与电路交换相比,分组交换也有一些缺点。其中之一是,由于所有数据在设备之间不采取相同的可预测路径,因此某些数据块可能在传输过程中丢失或以错误的顺序出现。在某些情况下,这并不重要,但在其他情况下,这确实非常重要。

尽管电路交换和分组交换之间的理论差异非常明确,但了解如何使用它们要复杂一些。主要问题之一是,在现代网络中,它们通常被结合使用。

例如,假设你使用拨号调制解调器连接到互联网。你将使用 IP 数据报(分组)来携带高层数据,但将通过电路交换的电话网络发送。然而,数据可能以数字分组形式通过电话系统发送。因此,在某种程度上,电路交换和分组交换同时被使用。

另一个问题在于电路交换和分组交换之间的关系,以及一项技术是否是面向连接的或无连接的。这两个概念相关但并不相同,你很快就会看到这一点。

注意

“分组”这个词只是用来指代通过网络发送的消息的几个术语之一。你还会遇到的其他术语包括帧、数据报、单元格和段。你将在本章后面了解更多关于这些术语的信息

面向连接和无连接协议

我刚刚根据技术是否使用专用路径或电路来发送数据来比较了网络技术。区分技术和协议的另一种方式是它们是否在设备之间使用连接。这个问题与分组交换与电路交换的问题密切相关。

根据它们使用连接的方式,协议被分为以下两个类别:

面向连接协议 这些协议要求你在传输数据之前在两个设备之间建立逻辑连接。这通常是通过遵循一组特定的规则来完成的,这些规则指定了如何启动、协商、管理和最终终止连接。通常,一个设备会首先发送一个请求来打开连接,另一个设备会响应。设备会传递控制信息以确定是否以及如何建立连接。如果成功,数据将在设备之间发送。当它们完成时,连接会被断开。

无连接协议 这些协议不会在设备之间建立连接。一旦设备有数据要发送给另一个设备,它就会立即发送。

小贴士

关键概念 面向连接的协议是指在发送数据之前,设备之间首先建立逻辑连接的协议。在无连接协议中,数据只是发送,而不创建连接。

你可能立即就能看到电路和连接这两个概念之间的关系。显然,为了在两个设备之间建立电路,你必须将它们连接起来。因此,电路交换网络本质上基于连接。这导致了电路交换面向连接这两个术语可以互换使用。

然而,这是一个由常见的逻辑谬误导致的过度简化——人们犯了一个错误,认为如果 A 意味着 B,那么 B 意味着 A,这就像说,因为所有苹果都是水果,所以所有水果都是苹果!电路需要连接,但电路并不是连接的先决条件。因此,即使它们根本不基于基于电路的网络的使用,也存在面向连接的协议。

这些面向连接的协议很重要,因为它们使得在没有任何内在连接感的分组交换网络上实现需要连接的应用程序成为可能。例如,要使用 TCP/IP 文件传输协议(FTP),你希望能够连接到服务器,输入登录名和密码,然后执行命令来更改目录、发送或检索文件等。这需要建立一个可以传递命令、回复和数据连接。同样,Telnet 协议(TP)也涉及建立连接——它允许你远程使用另一台机器。然而,这两个协议(间接地)都是基于 IP 工作的,而 IP 是基于数据包的使用,通过分层的重要原则(参见第五章中的“数据封装、协议数据单元(PDUs)和服务数据单元(SDUs)”部分,以了解这方面的讨论。

我还应该指出,有一些协议使用不寻常的名称,这些名称在网络的其它地方并不常用,用来指代它们的消息。一个突出的例子是 TCP,它将其消息称为

小贴士

关键概念在分组交换网络中的设备之间的通信基于最一般地称为消息的项目。这些信息片段也有其他名称,如包、数据报、帧和信元,这些名称通常对应于 OSI 参考模型特定层的协议。OSI 的正式术语是协议数据单元(PDU)服务数据单元(SDU)

在这本书中,我特意避免仅根据消息使用的名称来暗示其性质,但我确实遵循了特定技术最常用的名称。例如,通过以太网发送的消息几乎总是被称为以太网帧——它们通常不被称为以太网数据报,例如。然而,我并不将讨论的结构设计成仅通过消息使用的名称来确定其类型。

消息格式:标题、有效载荷和页脚

消息是用于在网络中发送信息的结构。它们在用途上从一种协议或技术到另一种有很大的不同,正如刚才所描述的,它们也被许多不同的名称所称呼。莎士比亚关于名称的想法是正确的。消息最重要的区别不在于它们的名称,而在于它们的内容

每个协议都使用一种特殊的格式化方法来决定其使用的消息的结构。显然,旨在连接 Web 服务器和 Web 浏览器的消息将与在低级别连接两个以太网卡的消息大不相同。这就是为什么我在本书的各个领域分别描述了数十种不同协议消息的格式。

尽管特定消息类型的格式完全取决于使用它的技术的性质,但整体上,消息往往遵循相当统一的结构。用通用术语来说,每条消息包含以下三个要素(参见图 1-3

图 1-3.网络消息格式在最一般的意义上,一个消息由一个将要通信的数据有效载荷组成,由一组页眉和页脚字段包围。在网络协议中发送的任何特定消息的数据本身将包含一个封装的更高层消息,该消息包含页眉、数据和页脚。这种“嵌套”可以在数据通过协议堆栈传递时发生多次。页眉在大多数协议消息中都可以找到;页脚只在某些消息中。

由于页眉和页脚可以包含控制和信息字段,你可能会正确地想知道为什么还要有一个单独的页脚。一个原因是某些类型的控制信息是使用数据本身的值来计算的。在某些情况下,在数据有效载荷发送时执行此计算会更有效,然后将在页脚中传输结果。页脚中经常找到的一个字段示例是冗余数据,如循环冗余校验(CRC)代码,该代码可以被接收设备用于错误检测。页脚通常与低层协议相关联,尤其是在 OSI 参考模型的数据链路层。

小贴士

关键概念网络消息的一般格式由一个页眉组成,后面跟着消息的数据有效载荷,然后可选地跟着一个页脚。页眉和页脚信息在功能上相同,只是在消息中的位置不同;页脚字段仅在某些情况下使用,尤其是在字段中的数据基于传输的数据的值进行计算的情况下。

一般而言,任何特定的协议只关心它自己的头部(如果有的话)。它不太关心消息数据部分的内容,就像快递员只关心驾驶卡车而不是它里面装的是什么一样。在数据开始的地方,通常会有其他协议的头部,这些协议在协议栈中更高层;这一点也在图 1-3 中有所展示。在 OSI 参考模型中,由特定协议处理的消息被称为其 PDU;它有效载荷中携带的数据是其 SDU。较低层协议的 SDU 通常是较高层协议的 PDU。关于数据封装的讨论在第五章中包含了这一重要概念的完整解释。

消息寻址和传输方法:单播、广播和多播

在使用消息发送数据的网络技术中,你必须完成一系列任务才能成功地将数据从一地传输到另一地。其中一个是简单地寻址消息——给它加上地址,以便系统知道它应该去哪里。另一个是传输消息,即将其发送到预期的接收者。

在网络中传递消息有几种不同的方式。其中一种区分消息的方式是它们是如何被寻址的,以及有多少接收者会收到它们。所使用的方法取决于消息的功能,以及发送者是否具体或一般地知道他们试图联系的人。

为了帮助解释这些不同的方法,我将使用一个现实世界的类比。考虑一个在大型礼堂举行的 300 人的社交活动。这些人正在交谈和进行不同的对话。在这个环境中,你可能需要发送不同类型的消息,就像网络一样。

单播、多播和广播消息寻址和传输 本图展示了简化局域网中的三种基本寻址和消息传输类型。设备 6 正向设备 2 发送单播消息,用深色粗箭头表示。设备 4 正向多播组 X 发送多播消息,用中等粗细的箭头表示。在这种情况下,该组包括设备 1 和 3,它们被突出显示。最后,设备 5 正在发送广播消息,该消息将发送到局域网上的所有其他设备,用细而淡的箭头表示。

图 1-4. 单播、多播和广播消息寻址和传输 本图展示了简化局域网中的三种基本寻址和消息传输类型。设备 6 正向设备 2 发送单播消息,用深色粗箭头表示。设备 4 正向多播组 X 发送多播消息,用中等粗细的箭头表示。在这种情况下,该组包括设备 1 和 3,它们被突出显示。最后,设备 5 正在发送广播消息,该消息将发送到局域网上的所有其他设备,用细而淡的箭头表示。

考虑到这个类比,考虑以下三种消息传输方式,如图 1-4 所示:

单播消息 这些是从一个设备发送到另一个设备的消息;它们不是给其他人的。如果你在这个社交活动中有一个朋友,这相当于把他拉到一边进行私人谈话。当然,活动中还有其他人可能无意中听到你的谈话——甚至可能窃听。在网络上也是如此——将消息地址指定给特定的计算机并不能保证其他人不会阅读它;只是他们通常不会这么做。

广播消息 如其名所示,这些消息发送到网络上的每个设备。当你需要将一条信息传达给网络上的每个人时,或者当发送站点需要将其发送给单个收件人,但不知道其地址时,你会使用它们。例如,假设社交聚会的新来者看到停车场里有一辆蓝色轿车,车灯还亮着。她不知道这辆车属于谁。传达这个信息的最佳方式是通过主持人进行公告,这样所有人包括车主都能听到。在网络中,广播消息用于各种目的,包括查找特定站点或管理不同服务的设备的位置。

多播消息 这些消息是前两种类型的折中方案。多播消息发送给一组满足特定条件的站点。这些站点通常以某种方式相互关联。例如,它们执行共同的功能或被设置成特定的多播组。(注意,你也可以将广播消息视为一种特殊的多播情况,其中组是“所有人”。)

回到我们的类比:这就像一群朋友去这个大型社交大厅,然后在一个小讨论组中聚在一起——或者也许使用无线电从远处交谈。多播需要特殊的技巧,以清楚地表明谁在预期的收件人组中。

由于这些传输方法根据接收传输的设备和设备类型而有所不同,它们直接与寻址方法相关联,如下所示:

单播寻址 单播投递要求消息应发送给特定的收件人。这是最常见的信息传递类型,因此这种寻址能力几乎存在于所有协议中。

广播寻址 广播通常通过一个专门为该功能保留的地址来实现。当设备看到发送到该地址的消息时,它们都会将其解释为“这条消息发送给所有人。”

多播寻址 多播是最复杂的一种消息类型,因为它需要一种方法来识别一组特定的设备,这些设备将接收消息。通常需要创建几个这样的组,这些组在成员资格上可能部分重叠。需要某种机制来管理哪些设备在哪些组中。

小贴士

关键概念 用于在联网设备之间寻址和传输数据的基本方法有三种。单播传输从一个设备到另一个确切设备;这是大多数消息交易中最常用的方法。广播传输从一个设备发送到网络上的所有连接设备。多播传输被寻址并发送到一组选定的设备。

最后,在寻址领域的一个特殊情况值得提及。在某些网络或链路中,只有两个设备连接在一起,形成了通常所说的点对点网络。在这种情况下,一个设备发送的任何内容都隐含地旨在发送给另一个设备,反之亦然。因此,在点对点链路上对消息进行寻址并不是严格必要的。

注意

在 IP 版本 6(IPv6)中定义了一种新的消息寻址方法:任播消息。这个术语标识了一条应该发送到一组设备中最接近成员的消息。第二十五章描述了这种寻址和传输类型

网络结构模型和客户端-服务器与对等网络

在我讨论网络优势的讨论中提到,网络通常是为了两个主要目的而设置的:连接性共享性。如果你有一个连接了多台不同机器的网络,每台计算机都可以与其他计算机的硬件和软件交互,这使得你可以执行各种任务。实际上如何做到这一点在很大程度上取决于网络的总体设计。

网络设计中一个非常重要的问题是如何配置网络以共享资源。具体来说,网络设计者必须决定是否将资源管理功能分配给构成网络的设备。在某些网络中,所有设备在这方面都被同等对待,而在其他网络中,每台计算机负责提供服务的整体功能中的特定工作。在这种后一种安排中,设备有时被称为具有角色,类似于戏剧中的演员。

以下两个常用术语用于描述设置网络的不同方法:

对等网络在一个严格的对等网络设置中,每台计算机都是平等的,是网络中的对等体。每台机器都可以与其他任何机器共享资源。没有为任何特定设备分配角色,并且每个设备通常运行类似的软件。任何设备都可以并发送请求到任何其他设备,如图图 1-5 所示。

客户端-服务器网络 在这种设计中,少量计算机被指定为集中式的服务器,并负责为称为客户端的更多用户机器提供服务,如图图 1-6 所示。服务器通常是具有大量内存和存储空间以及快速网络连接的强大计算机。客户端通常是较小的、常规的计算机,如 PC;它们针对人类使用进行了优化。

术语客户端-服务器也经常指代那些设计有匹配、互补组件的协议和软件。通常,服务器软件运行在服务器硬件上,而客户端软件则用于连接到这些服务器的客户端计算机上。网络上的大多数交互都是在客户端和服务器之间进行的,而不是在客户端之间。服务器软件旨在高效地响应请求,而客户端软件则提供网络用户的人机界面。

提示

关键概念 网络通常配置为使用两种基本结构模型之一来共享资源。在对等网络中,每个设备都是平等的,没有分配特定的任务。然而,在客户端-服务器网络中,设备被分配了特定的角色——少量强大的计算机被设置为服务器,并响应来自其他设备的请求,这些设备被称为客户端。客户端-服务器计算还指代互补协议元素和软件程序之间的交互。由于其广泛用于 TCP/IP 和互联网应用,因此其受欢迎程度正在上升。

对等网络 在这个模型中,网络上的每个设备都被视为对等体,或平等。每个设备都可以发送请求和响应,没有特别指定执行特定角色。这种模型更常用于非常小的网络。与...形成对比。

图 1-5. 对等网络 在这个模型中,网络上的每个设备都被视为对等方,或平等。每个设备都可以发送请求和响应,没有特别指定执行特定角色。这种模型更常用于非常小的网络。与图 1-6。

客户端-服务器或对等网络的选择有时被称为为网络选择一种 结构模型。与大多数使用两种不同方案的情况一样,在这方面没有正确答案。你的选择完全取决于特定网络的需求。

对等网络的主要优势是简单和低成本,这意味着它传统上被用于小型网络。客户端-服务器网络在性能、可扩展性、安全性和可靠性方面提供优势,但设置起来更复杂且成本更高。这使得它更适合大型网络。然而,随着时间的推移,即使是小型网络也朝着客户端-服务器网络的方向稳步发展。许多年前,即使是拥有 20 到 50 台机器的网络也普遍使用对等模型;今天,即使是只有几台机器的网络有时也会以客户端-服务器模式设置,因为集中式资源服务的优势。

客户端-服务器网络流行的兴起有些讽刺,因为在某些方面,它实际上是对几十年前大型主机的回归。一个连接有终端的主机可以被视为客户端-服务器网络,其中主机本身是服务器,而终端是客户端。当然,这种类比并不完美,因为现代客户端计算机比主机的哑终端要完成更多的工作。

客户端-服务器结构模型成为主导地位的一个原因是它是世界上最大的网络——互联网的主要模型。客户端-服务器架构是大多数 TCP/IP 协议和服务的基础。例如,“网页浏览器”这个术语实际上是网页客户端的另一个名称,而“网站”实际上是一个网页服务器。

注意

关于客户端-服务器计算的信息,我建议您阅读第八章“TCP/IP 服务和客户端/服务器操作”部分。该主题还包含了一个非常相关的关于客户端和服务器在硬件、软件和交易环境中的不同含义的阐述

客户端-服务器网络 在客户端-服务器模型中,少数设备被指定为服务器,并配备了特殊的硬件和软件,这使得它们能够高效且同时与多个客户端机器交互。尽管客户端之间仍然可以相互交互,但大多数时候它们会向服务器发送各种请求,而服务器则向它们发送响应。这与图 1-5 中的对等网络示例形成对比。

图 1-6. 客户端-服务器网络 在客户端-服务器模型中,少数设备被指定为服务器,并配备了特殊的硬件和软件,这使得它们能够高效且同时与多个客户端机器交互。尽管客户端之间仍然可以相互交互,但大多数时候它们会向服务器发送各种请求,而服务器则向它们发送响应。这与图 1-5 中的对等网络示例形成对比。

网络的类型和大小

理解网络有时可能困难的原因之一是存在如此多的不同类型!当某人谈论网络时,她可以指从公寓里连接的两台计算机到覆盖全球的拥有数百万节点的实体。每个网络都是独特的,每个网络都在满足不同个人和组织在通信和数据共享方面的需求中扮演着重要的角色。事实上,网络多样性和灵活性的巨大优势是其最重要的优势之一。

区分和对比各种网络的最基本两种方式是它们连接的设备之间的相对距离以及它们之间通信的一般机制。做出这些区分的原因是,网络的科技需求根据你试图覆盖的地域大小以及你想要传输和接收信息的方式有很大差异。

很多人,包括我,喜欢将现有的许多种类的网络分为三大类,如下所示:

局域网(LANs) 是指连接相对较近的计算机的网络——通常是在同一个房间或建筑物内。当大多数人想到网络化个人电脑和其他小型计算机时,他们通常是指这种情况。绝大多数常规局域网使用电缆连接,因此“LAN”这个术语本身通常意味着有线局域网,但并不总是这样。

无线局域网(WLANs) 是指通过无线电频率或光连接设备的局域网。WLANs 可以是完全无线的,但大多数不是。它们通常将无线设备相互连接,同时也连接到网络的有线部分。由于大多数无线技术的限制,WLANs 通常连接彼此非常接近的设备,通常最多在几百英尺范围内。

广域网(WANs) 是指连接设备或其他网络,距离比局域网实际适用的距离更远的网络。如果设备之间的距离可以用英里来衡量,你通常会使用广域网技术而不是局域网技术来连接它们。

更多的时候,广域网(WANs)用于连接物理上距离较远的局域网。例如,一个在两个不同城市有地点的公司通常会为每座建筑设置一个局域网,然后通过广域网将它们连接起来。我也认为大多数互联网接入技术都是广域网的一种形式,尽管有些人可能不同意这一点。还有术语 无线广域网(WWAN),它仅仅指的是使用无线技术的广域网。

就像网络世界中的大多数其他区分和分类一样,这些不同定义之间的界限并不非常明确。正如我之前提到的,WLANs 通常不是完全无线的,因为它们包含有线元素。同样,绝对地说一个网络是“本地”的还是“广域”的是困难的。

在精确区分这些网络类别上花费太多精力也是没有意义的。在某些情况下,不是定义决定了使用哪种技术,而是技术本身表明了你拥有什么样的网络!由于一些协议是为广域网设计的,如果你在使用它们,许多人会说你有广域网,即使那个技术中的所有设备都彼此很近。另一方面,一些局域网技术允许使用可以运行数英里的电缆;大多数人仍然认为一英里长的以太网光纤连接是局域网连接,即使它可能跨越广域网的距离。

LAN 和 WAN 技术在许多方面都有所不同;其中最重要的两个是 成本性能。在同一个房间内的两个系统之间建立高速数据通道很容易,但如果两个系统在不同的州,那就困难得多。这意味着在广域网的世界里,要么支付更多,要么吞吐量大大减少——通常两者都会发生。

每年,局域网(LAN)和广域网(WAN)之间的灰色区域变得越来越模糊。一个原因是出现了介于这些更熟悉术语之间的中间网络类型。以下两种较为常见:

校园区域网络(CANs) 一个CAN是为了跨越同一地点的多栋建筑而创建的,例如大学的校园。校园区域网络是一个灰色区域,因为单独的局域网或广域网并不总是适合这种类型的应用。通常,根据校园的特点和组织的需要,会使用局域网和广域网的混合技术进行校园网络建设。

城域网(MANs) 你有时可能会看到另一个中间术语MAN。正如其名所示,这指的是跨越特定小区域或城市的网络。MANs 可以被认为是覆盖有限地理区域的较小广域网,或者覆盖面积大于通常与本地网络相关联的较大局域网。无线 MANs 有时被称为WMANs;IEEE 802.16 是 WMAN 标准的一个例子。

最后,还有一个偶尔使用的术语,我应该提一下:个人区域网络(PAN)。这种类型的网络通常意味着一个非常小的局域网,范围只有几英尺。PANs 主要连接由单个个人(或非常小的小组)使用的设备。这个术语最常用于蓝牙/IEEE 802.15 无线技术,因此有时你会看到无线个人区域网络(WPAN)PAN这两个术语被交替使用。

小贴士

关键概念 网络通常根据大小和一般的通信方法分为三类。局域网(LANs)通常连接附近的设备,通常使用电缆。无线局域网(WLANs)类似于有线局域网,但使用无线电频率或光技术连接设备,无需电缆。广域网(WANs)连接远程设备或局域网。校园区域网络(CANs)城域网(MANs)在整体大小上介于局域网和广域网之间。个人区域网络(PANs)类似于非常小的局域网,通常以无线个人区域网络(WPANs)的形式出现。

段落、网络、子网络和互联网

网络之所以如此强大,其中一个原因是可以用来连接不仅单个计算机,还可以是计算机组。因此,网络连接可以存在于多个级别;一个网络可以连接到另一个网络,整个网络又可以连接到另一组网络,依此类推。当然,这种连接的终极例子是互联网,它是一个由许多网络相互连接而成的巨大集合……我敢说,是一个网络?

这意味着一个较大的网络可以被描述为由几个较小的网络或甚至网络的部分组成,这些部分相互连接。相反,我们也可以谈论将单个网络或网络部分组装成更大的结构。这个概念之所以重要,是因为某些技术最好在高级别上查看整个大型网络时进行解释,而其他技术则真正需要你深入到构成网络部件的详细级别。

随着时间的推移,在计算机网络领域,一系列术语已经发展起来,用于描述较大和较小网络的相对大小。以下是一些最常见的术语:

网络 这是这里提到的术语中最不具体的一个。基本上,网络 可以是几乎任何大小,从两个设备到数千个。然而,当网络变得非常大,并且显然由较小的网络连接在一起时,它们通常不再被称为网络,而是称为 互联网,正如你马上就会看到的。尽管如此,听到有人提到像“微软的企业网络”这样的东西是很常见的,显然它包含数千甚至数万台机器。

子网(子网) 一个 子网 是网络的一部分,或者是一个属于更大互联网的网络。这个术语也是一个相当主观的术语;当它们是大型网络的一部分时,子网可以相当大。

缩写词 子网 可以泛指子网络,但在 TCP/IP 地址的上下文中也有特定的含义(参见第十八章)。

段(网络段) 一个 是网络的一个小部分。在某些上下文中,段与子网络相同,这两个术语可以互换使用。然而,更常见的是, 这个术语意味着比子网络更小。网络通常设计得使相互关联的计算机或被同一组人员使用的计算机放置在同一网络段上。

一些局域网技术——包括以太网——使用 这个术语专门指代一组地理位置相近的机器,这些机器通过单根电缆或单个设备(如集线器)直接相互连接。这些技术有关于在段上可以放置多少设备、可以连接多少段等具体规则,这些规则取决于你使用的网络互连设备。

互联网(或 Internetwork) 最常见的是指通过连接较小的网络而形成的一个更大的网络结构。同样,这个术语可以根据上下文具有泛指或具体含义。在某些技术中,互联网只是一个由网络作为组件的非常大的网络。在其他技术中,网络与互联网的区别在于设备是如何连接在一起的。

后者定义的一个重要例子是 TCP/IP,其中网络通常指在 OSI 参考模型的第 2 层连接的一组机器,使用像以太网或令牌环这样的技术,以及像集线器和交换机这样的互连设备。当这些网络在第 3 层通过传递 IP 数据报文相互连接时,就形成了互联网。当然,这非常简化,但在学习 TCP/IP 时,当你遇到“网络”和“互联网”这两个术语时,你应该记住这一点。

注意

“互联网”这个词的简称(internet)通常被那些希望避免与专有名词形式(Internet)混淆的人所避免。后者,当然,仅指众所周知的全球互联网及其提供的一切服务。我个人在这本书中大多数时候尝试使用“互联网”这个词,而不是“internet”,正是因为这个原因

理解这些不同的术语不仅对于帮助你理解关于网络的阅读内容很重要,而且因为它们是网络设计中的重要概念。这在局域网(LAN)中尤其如此,关于如何设置段以及如何将它们相互连接的决定对网络的总体性能和可用性有重要影响。

小贴士

关键概念 常常使用几个术语来描述网络和网络的各个部分的大小。最基本的术语是“网络”本身,它可以指代几乎所有事物,但通常指的是使用 OSI 层 2 技术连接的一组设备。子网络是网络(或互联网)的一部分,也是如此,尽管在特定技术中后者通常有更具体的含义。互联网泛指一个非常大的网络,或者具体来说,是指使用第 3 层路由器连接的第 2 层网络集合。

术语特别有问题,因为它通常以两种不同的方式使用,尤其是在与以太网相关的讨论中。传统上,“段”指的是特定的电缆。最早的以太网使用同轴电缆,同轴电缆段是共享的,并成为网络的冲突域。冲突域是一个术语,通常指一组硬件设备,其中一次只能有一个设备传输。像集线器和中继器这样的设备被用来通过将这些电缆段连接起来形成更宽的网络来扩展冲突域。随着时间的推移,“冲突域”和“段”这两个术语开始被互换使用。因此,今天,“段”可以指特定的电缆,也可以指代表单个冲突域的连接在一起的电缆集合。

注意

就像“段”这个词的使用可能存在的潜在歧义还不够糟糕一样,它还有一个完全无关的含义:它是 TCP 中发送的消息的名称!

互联网、内联网和外联网

我在前面关于段、网络、子网络和互联网的讨论中提到,互联网实际上是互联网之王。毕竟,除非你基本上定义了它,否则你不会被称为“the”某物!

事实上,互联网不仅仅是一个大型互联网,而且更多。互联网的定义不仅仅是连接到一起的全球计算机,还包括它提供的各种服务和功能。更重要的是,互联网定义了一种特定的方式,即人们和公司之间共享信息和资源的方式。尽管这样说可能有点夸张,但对许多人来说,互联网是一种生活方式。

在 20 世纪 90 年代互联网使用爆炸式增长时,许多人意识到,如果将这些在互联网上使用的技术和技术应用到内部公司网络上,将会很有用。术语内联网被创造出来,指的是像私人互联网一样运作的内部网络。它来自前缀“intra”,意味着内部。当然,“inter”是“intra”的反义词,所以这让一些人认为内联网是互联网的反义词。实际上,大多数内联网也是互联网!

就从术语的角度来看,这已经够糟糕的了,但那些时髦词汇的鸟儿们似乎还想更进一步。如果一个内部网络被扩展,允许不仅组织内部的人或团体访问,还包括外部公司的人或团体,那么这有时被称为外联网。当然,“extra”是一个前缀,意味着外面或超出。

因此,外联网是一种内部、私有的互联网,但并不是完全内部。外联网是扩展的内联网,实际上是一种像互联网一样工作的互联网。(您现在可以开始理解为什么我不是这些花哨术语的大粉丝了。但话又说回来,我无法选择它们;我只需帮助您理解它们!)外联网不是公开的,不对所有人开放——它由一个私人组织控制。同时,它也不是完全私有的。

小贴士

关键概念 通用名词互联网是单词 internetwork 的缩写,而专有名词互联网指的是我们所有人都知道并使用的全球 TCP/IP 网络互连。术语内联网指的是使用与互联网相同 TCP/IP 技术的内部网络。外联网就像是一个扩展到公司外部个人或组织的内联网。所有这些术语都可以模糊使用,因此您必须小心确定在任何特定情况下它们的确切含义。

如您所见,从一开始,互联网、内联网和外联网之间的界限就相当模糊,随着整个计算世界的更加紧密集成,这些概念正迅速融合成一个模糊的灰色整体。例如,即使您有一个完全私有的内联网,您也会想要将其连接到互联网,以便与外界沟通并允许访问互联网资源。外联网可能部分通过公共互联网基础设施实现,使用如虚拟专用网络(VPN)等技术。我想您已经明白了这个道理。

将所有这些概念联系在一起的关键是它们都使用互联网技术,这是一个有些模糊的术语。这通常指的是使用 TCP/IP 协议套件,它是互联网的定义性技术,也是互联网上可用的服务集合。

重要的是,被告知一家公司有一个内联网或外联网——而不是一个普通无聊的网络——实际上并没有告诉您多少信息。最好不要依赖口号,而是查看网络或互联网本身的潜在特征。此外,在设计此类网络时,您应该专注于使用有意义的技

第二章:网络性能问题和概念

无标题图片

网络在很大程度上是关于连接设备,以便它们之间可以共享信息。由于想法是将数据从一个地方发送到另一个地方,因此任何网络的一个重要特征是其速度:数据可以传输和接收多快?这个速度问题最终只是决定网络整体性能的几个问题之一。

在计算世界中,性能通常是最被讨论但最不被理解的系统或硬件设备的特性之一。这在网络领域也是如此。例如,大多数人知道他们网络硬件的原始吞吐量评级,他们甚至可能开始根据这些数字得出关于其能力的结论。然而,许多人并没有意识到,他们永远不会在现实世界中真正实现那个评级数量的性能。

与性能相关的其他许多微妙问题通常也被忽视或误解,例如软件驱动程序对硬件性能的影响,以及某些应用程序需要的不仅仅是原始比特速度——它们需要可靠的数据传输。但即使超出所有这些,与网络性能相关的一个最重要的问题是理解你的需求,因为这样你就可以确保你不会为不需要的性能花费过多的金钱——或者更糟糕的是,创建一个无法满足你要求的网络。

在本章中,我讨论了与网络相关的各种性能问题和概念。首先,我试图将性能置于适当的背景中,并与非性能问题进行对比。然后,我讨论了几个关键的性能术语和指标:速度、带宽、吞吐量和延迟。我还讨论了用于衡量网络性能的一些单位。接着,我解释了实际网络性能与其理论性能之间的差异,并讨论了影响网络性能的因素。最后,我对比了全双工和半双工网络操作,并讨论了服务质量,这是一个在实时应用(如流媒体)中使用网络时特别重要的概念。

将网络性能置于适当的背景

性能可能是计算机行业所有流行词汇的母亲。许多人认为它是任何计算机或计算机系统,乃至任何网络的最终目标。许多人花费了大量的金钱和时间来试图最大化它。这有很好的理由:性能确实非常重要。一个不能提供足够性能的网络将无法完成那些依赖它的人的工作。然而,保持性能的客观性非常重要。成功最大化性能需要你首先退一步,从大局出发来看待问题。

你必须问自己的第一个问题也是最基本的问题:性能对你来说有多重要?在你回答这个问题之前,回想一下古老的汽车拉力赛格言:“速度要花钱——你想要多快?”虽然有些情况下,你只需多花一点钱就能在网络中获得更好的性能,但总的来说,你不付费就无法获得更多的性能。这可能意味着网络成本更高,或者可能意味着牺牲一些非性能特性。

如果你正在设计或指定一个网络,你必须记住,你的目标是设计出一个系统,该系统能够满足在需求分析期间确定的网络需求。这意味着设计一个性能水平与需求相匹配且留有扩展空间的网络。除非你有无限的预算——谁有呢?——你的目标不是“不惜一切代价追求性能”。而是要创建一个满足所有用户需求的网络,包括平衡性能和非性能特性,正如你很快就会看到的。

注意

消费者请注意。公司不断推出“最新和最先进的”高性能网络技术。他们通常试图通过说服你,没有这项最新进展你将无法生活;你需要立即升级——如果不早点的话!然而,事实并非如此。例如,尽管你可以找到理论吞吐量为每秒 10,000 兆比特的以太网硬件,但许多旧网络仍然以 1/100 的速度——甚至 1/1,000 的速度——正常工作。

最后,请记住,设计网络通常不是一个不可逆转的、永久的决定。网络可以升级和扩展。虽然为网络留出一些余量以允许增长是谨慎的,但在可以稍后进行更改的情况下,花费太多时间和金钱来规划未来是不明智的。考虑到网络硬件价格随时间下降,这一点尤其正确。再次强调,这是在未来的性能规划和预算之间找到一个适当的平衡的问题。

平衡网络性能与关键非性能特性

我们都知道性能对任何网络都非常重要。然而,任何构建网络的人也必须关注许多不同的非性能特性。根据网络的不同,这些特性可能和性能一样对网络用户至关重要,甚至可能更加关键。更重要的是,非性能问题通常与性能权衡,实际上,很多时候它们必须被降低以增加性能。

在你能够创建一个非常高性能的网络之前,你必须了解你可能需要妥协的关键非性能网络特性。以下是一些这些问题:

设计和实施成本 除非你的钱包深不可测,否则你必须关注网络的成本。如前所述,成本是性能的主要权衡因素。运行得更快通常需要更多的金钱。

质量 网络的质量取决于所用组件的质量以及它们的安装方式。质量很重要,因为它影响所有其他因素,如可靠性、易于管理以及性能。质量并不直接与性能进行交易——你可以设计出高质量、高性能的网络——但它确实在预算资源上与性能竞争。在其他条件相同的情况下,实现高质量、高性能网络的成本远高于高质量、低速网络。

标准化 网络协议和硬件可以设计为符合普遍接受的标准或非标准、专有的标准。标准设计几乎总是更可取,因为它们使互操作性、升级、支持和培训变得更容易。专有标准可能包括提高性能的增强功能,但可能会增加成本或使管理更加困难。

可靠性 这与几个其他问题相关,尤其是质量和性能。快速网络并不一定比慢速网络更不可靠,但它们更难且更昂贵地确保可靠运行。

可扩展性和可升级性 在创建网络时始终为未来规划是非常重要的。高性能网络可能更难扩展,而且它们扩展的成本肯定更高。再次强调,现在实施具有未来需求容量的网络,而不是在必要时升级,这是一个重要的网络设计决策。

易于管理和维护 高性能网络需要更多的工作和资源来管理和维护,并且它们比低速网络更可能需要故障排除。

场所和公用事业问题 高速网络的实施可能受到物理场所的限制,或者可能影响它们的布局方式。选择更高速的选项可能需要更多的基础设施,从而增加成本。这一问题的经典例子是在家庭或小型办公室网络中选择有线和无线选项。你可以通过有线连接达到更高的速度,但你真的想铺设它们吗?

提示

关键概念 虽然性能是任何网络最重要的特性之一,但还有其他一些特性同样重要。在许多情况下,你必须权衡网络的整体性能与成本、质量、可靠性、可扩展性、可维护性等其他属性之间的关系。你希望网络运行得越快,就越难确保这些其他属性保持在足够高的水平。

性能测量:速度、带宽、吞吐量和延迟

有许多术语常用于指代网络性能的各个方面。其中一些彼此非常相似,你经常会看到它们被使用——在许多情况下,甚至被误用或滥用!我将逐一检查它们,看看它们通常是如何被使用的,以及它们的真正含义。

备注

然而,除了与性能相关的不同术语的问题之外,更重要的是,性能有多个方面。根据应用的不同,数据通过网络传输的方式可能比数据传输的原始速度更重要。特别是,许多多媒体应用需要实时性能;它们需要以稳定的方式发送数据。对于这些目的,原始速度并不像一致性速度那样重要。这是一个常常没有得到充分认识的问题。

速度

速度是网络中使用的最通用的性能术语。因此,它可以指代几乎所有的事情。然而,最常见的情况下,它指的是特定网络技术的额定名义速度。例如,快速以太网的名义速度为 100 Mbps(每秒兆比特);因此,它通常被称为 100 Mbps 以太网,或者被赋予如 100BASE-TX 这样的标识。

额定速度是网络性能中最大的魔法数字——你看到它被用来标记硬件设备,许多人随意地提及这些数字,好像这些数字实际上代表了网络的实际速度。使用名义速度等级的问题在于,它们仅仅是理论上的,因此只能讲述一个不完整的故事。没有任何网络技术能够达到其全部的额定速度,许多技术的运行速度甚至大大低于额定速度,这是由于现实世界的性能因素造成的。

诸如 100 Mbps 以太网这样的速度等级也常被称为该技术的吞吐量,尽管技术的最大理论速度与带宽更相似,而不是吞吐量,两者并不相同。

带宽

带宽是一个广泛使用的术语,通常指的是网络或数据传输介质的数据承载能力。它表示在单位时间内可以从一个点传输到另一个点的最大数据量。这个术语来自电磁辐射的研究,在那里它指的是用于传输数据的频率带的宽度。它通常在理论背景下给出,尽管并非总是如此。

带宽仍然用于这两种意义上:频率带宽和数据容量。例如,无线电频率被用于无线技术,这些技术的带宽可以指无线电频率带的宽度。然而,更常见的是,带宽指的是网络中可以发送的数据量,并且通常用于相对术语。例如,对于互联网接入,电缆或 xDSL 连接被认为是宽带接入;使用常规的模拟调制解调器是窄带接入。

吞吐量

通过量是衡量在单位时间内通过网络、信道或接口可以发送多少实际数据的指标。虽然通过量可以是一个理论术语,就像带宽一样,但它更常在实际意义上使用——例如,用于衡量在现实世界中通过网络实际发送的数据量。通过量受带宽或额定速度的限制:如果一个以太网网络的额定速度为 100 Mbps,那么这是通过量的绝对上限,尽管你通常会得到少得多的速度。因此,你可能会看到有人说他们使用的是 100 Mbps 的以太网连接,但他们的网络通过量仅为,比如说,71.9 Mbps。

术语带宽通过量经常被互换使用,尽管它们实际上并不完全相同。

延迟

延迟是一个非常重要但经常被忽视的术语,它指的是在通信信道或网络上的数据传输的时间。延迟的一个重要方面是从请求数据的时间开始直到它开始到达所需的时间。另一个方面是设备对发送数据的时序控制程度,以及网络是否可以安排以允许在一段时间内持续传输数据。低延迟被认为比高延迟好。

性能测量总结

与所有网络术语一样,没有硬性规则;许多人对于与性能测量相关的术语使用相当宽松。你甚至可能会看到诸如通过量带宽带宽通过量和其他来自冗余部门的迷人发明。更常见的是,你会看到很多混乱的术语使用,特别是基于网络的额定速度得出关于网络可以处理哪些数据流的错误结论。更糟糕的是,速度评级通常以每秒比特数指定,但通过量可能以每秒比特或字节给出。

小贴士

关键概念 最常用来指代网络整体性能的三个术语是速度、带宽通过量。它们是相关的,并且经常被互换使用,但并不相同。术语速度是最通用的,通常指网络技术的额定或标称速度。"带宽"可以指一个技术使用的频率带的宽度,或者更普遍地,数据容量,其中它被用作更理论性的度量。"通过量"是在给定时间内通过信道的具体数据流量度量。它通常是一个实际测量值。

通常,速度、带宽通过量会受到很多关注,而延迟则很少受到关注。然而,对于许多实时应用,如流式音频和视频以及交互式游戏,延迟的考虑非常重要。事实上,它们往往比原始带宽更重要。

例如,假设你搬到了一个乡村家庭,你选择的互联网接入方式是一个普通的 28.8 Kbps 调制解调器连接或者时尚的卫星互联网。销售卫星连接的公司将其称为“宽带”,并宣传非常高的速度——400 Kbps 或更高。他们大肆宣传这比拨号快“十倍”,并且当然为此非常高科技的服务收取高额费用。这是板上钉钉的事情,对吧?

错误。卫星连接具有高带宽,但由于信号往返卫星所需的时间,其延迟(高延迟)非常差。对于从微软下载那个小巧的 150 MB 补丁来说,它确实比调制解调器好得多。然而,由于传输中的延迟或 延迟,它对于与你的朋友在网上玩最新的在线视频游戏来说要差得多。在你游戏中做出的每一个动作都会因为信号在卫星和地球之间弹跳而被延迟超过半秒钟,这使得在线游戏几乎不可能进行。因此,卫星互联网是否值得额外付费完全取决于你打算用它做什么。

注意

与延迟密切相关的一个重要问题是服务质量,这是一个通用术语,指的是(在其他方面)网络为需要带宽和可靠数据传输的应用程序提供所需带宽的能力。请参阅本章后面的“服务质量(QoS)”部分

小贴士

关键概念 带宽和吞吐量表明数据在网络中移动的速度,而 延迟 描述了数据传输的性质。它最常用来描述数据请求时间和到达时间之间的延迟。具有非常高的吞吐量和较差(高)延迟的网络技术对于某些应用程序来说可能比具有相对较低的吞吐量和良好(低)延迟的技术更差。

理解性能测量单位

制作网络硬件的人,或者编写试图教你怎么操作它的材料的人,会使用许多术语来描述性能,例如 吞吐量带宽。(这些术语在上一节中已解释。)此外,他们还使用几个不同的 单位 来衡量性能。不幸的是,这些单位经常被错误地使用,而且它们在名称上也非常相似。更糟糕的是,它们还有重叠的缩写,很多人使用这些缩写时并没有清楚地说明他们在谈论什么。这不是很棒吗?

比特和字节

第一个问题是不为人知的字母 B。或者更确切地说,我应该说是大 B 和小 b 的问题。根据普遍的惯例,大写 B 应该用于字节,小写 b 用于比特——这就是本书中这些缩写总是被使用的方式。

注意

一个字节通常是八个比特;有时会使用术语八位组来代替。如果你不熟悉这些术语,请参阅第四章,那里有关于二进制基础入门的介绍,你还可以找到有关字节和八位组的小争议的讨论

不幸的是,这个惯例并不是每个人都严格遵守的。因此,有时你可能会看到 b 被用来指代字节,而 B 被用来指代比特。这种 bB 的问题有时会导致极大的混淆,人们可能会把比特误认为是字节,并错误地认为网络运行的速度比实际快或慢八倍。

在查看速度评级时,请记住,它们几乎总是以比特为单位给出,而不是字节。调制解调器评级中的 56K 表示 56,000 比特,而不是 56,000 字节的理论传输速度。(即使有人称之为“56K”调制解调器,这也同样适用。)同样,快速以太网以每秒 100 兆比特的速度运行,而不是兆字节,一个 1.544 Mbps 的 T1 链路每秒发送的理论最大比特数为 1,544,000。至少,这通常是相当一致的。

然而,在吞吐量测量方面,比特和字节都被使用,所以你必须小心。原始吞吐量值通常以每秒比特数给出,但许多软件应用程序报告的传输速率是以每秒字节数,包括许多网络浏览器和 FTP 客户端程序。这通常导致用户疑惑为什么他们只能获得预期下载或传输速度的八分之一。

小贴士

关键概念 在大多数关于网络性能的讨论中,小写字母 b 指的是比特,大写 B 指的是字节。然而,这些惯例并不总是被普遍遵循,因此必须根据上下文来解释特定的测量值。

比特吞吐量的标准单位是每秒比特,通常简写为 bit/s、bps 或 b/s。字节单位是每秒字节,简写为 bytes/s、Bps 或 B/s——除非某些残忍的作者决定使用小写 b 只是为了混淆你!这意味着 100BASE-TX(100 Mbps)以太网的最大理论吞吐量约为 12 MB/s。在上下文不明确的情况下,最好将单位完整写出,如 100 Mbits/s 或 12 Mbytes/s,当然,我在这本书中也尽量这样做。

你偶尔也会看到,尤其是在通信领域,吞吐量以每秒字符数(cps)来衡量。在大多数计算机系统(包括 PC)中,每个字符占用一个字节,所以 cps 相当于 bytes/s、B/s 或 Bps。

当然,大多数网络技术每秒并不只是移动几个比特和字节;它们每秒移动的是数千、数百万甚至数十亿。因此,大多数速度等级不是以每秒比特数来衡量的,而是以 比特(Kb)、 比特(Mb)或 比特(Gb)每秒来衡量的,同样也可以应用于字节。因此,你会看到诸如 100 Mbps 以太网或 700 kb/s ADSL 这样的术语。

这里,你遇到了另一个问题:存在 的十进制和二进制版本。例如,百万(兆)的前缀的十进制形式是 10⁶ 或 1,000,000,而二进制形式是 2²⁰ 或 1,048,576。这种大约 5% 的差异导致了各种混淆。当你看到这些缩写时,请记住,在网络中,它们几乎总是指十进制形式。因此,100 Mbps 以太网的速度是每秒 100,000,000 比特,而不是每秒 104,857,600 比特。

小贴士

关键概念 最常用来表示网络吞吐量的单位是 每秒比特数bps。这个术语通常以千、百万或十亿来表示,如 KbpsMbpsGbps。它几乎总是使用十进制而不是二进制的千、兆或吉乘数。

波特率

最后,还有一个术语,你会在讨论调制解调器和其他一些技术时经常遇到:波特率。这个单位是以电报先驱让-莫里斯-埃米尔·波多(Jean-Maurice-Émile Baudot,1845–1903)的名字命名的,它衡量每秒信号中发生的转换次数或变化次数。所以,如果信号每秒从一位值变为零值(或反之)一百次,那么这就是 100 波特的速率。

在非常慢的调制解调器早期,每个比特转换编码一个数据比特。因此,300 波特率的调制解调器每秒理论上最多发送 300 比特的数据。这导致人们混淆了 波特率每秒比特数 的术语——这两个术语仍然被 过于频繁 地互换使用。例如,你经常会听到人们将 28.8 Kbps 的调制解调器称为以 28,800 波特率运行。

但这两个单位实际上并不相同;一个衡量数据(通道的吞吐量),另一个衡量转换(称为 信号速率)。现代调制解调器使用高级调制技术,可以将多个比特的数据编码到每个转换中。一个 28,800 bps 的调制解调器通常将九个比特编码到每个转换中;它的波特率是 3,200 波特,而不是 28,800 波特(后者是 3,200 和 9 的乘积)。实际上,在传统的电话线上以 28,800 波特率运行调制解调器是不可能的——这超出了电话线的频率带宽。这就是为什么使用高级调制技术将更多数据编码到每个转换中的原因。

小贴士

关键概念 波特率比特率 单位通常被视为等效,但实际上并不相同。波特率 衡量的是网络的信号速率,即信号在每秒内改变值的次数。由于现代编码和调制技术通常在每个这样的转换中编码大于或小于一个比特值,因此网络技术的吞吐量和波特率通常是不同的。

理论吞吐量和实际吞吐量,以及影响网络性能的因素

在评估网络性能时,请记住,理论速度评级和实际吞吐量之间始终存在差异。如果你的网络设置得当,这种差异相对较小但仍很重要。否则,差异可能非常大。(请注意,理论和实际性能之间的差异永远不会可以忽略不计。)

网络或通信方法应该能够做到什么和实际上能够做到什么之间存在差异的原因有很多。这些原因通常分为三类:正常网络开销、外部性能限制和网络配置问题。

注意

有许多不同的方式来衡量和评估性能。合成基准程序通常用于衡量吞吐量,并可以产生令人印象深刻的性能分数,但这些分数通常与网络实际运行方式几乎没有关系。这些指标最好用于比较目的,通过显示一个网络或系统比另一个更快,而不是过分关注指标产生的实际数字。然而,即使在进行比较时,谨慎也是明智的

正常网络开销

每个网络都有一定程度上的正常网络开销,这保证了你永远无法使用任何连接的全部带宽进行数据传输。以 10 Mbps 以太网为例。当然,线路每秒可以传输 1000 万个比特,但并非所有这些比特都是数据!其中一些用于包装和寻址数据——数据不能以原始形式直接扔到网络上。此外,许多比特用于一般开销活动,它们处理传输中的冲突和其他问题。任何网络技术都存在固有的低效率。

即使如此,还存在其他开销问题。任何网络事务都涉及多个不同的硬件和软件层,每个层都存在开销,从应用和操作系统到硬件。这些开销意味着你通常至少会损失局域网(LAN)技术额定速度的 20%,有时甚至更多。例如,在常规的 10 Mbps 以太网网络上,7 Mbps 的用户数据吞吐量实际上是非常好的。

外部性能限制因素

有外部因素限制了网络的性能。这里重要的问题包括硬件处理数据的能力以及两个节点之间数据传输链路中存在的任何带宽限制。硬件问题通常在非常快的网络技术中表现出来。

考虑两个普通 PC 之间的千兆(1,000 Mbps)以太网连接。从理论上讲,这个连接应该允许每秒传输 1 GB 的数据。即使超出了之前提到的开销问题,没有任何普通 PC 能够每秒传输这么多数据。只有高端服务器才有这种能力——即使它们什么也不做,也可能会遇到问题。较老 PC 的硬盘可能甚至无法以足够快的速度传输数据,以保持 100 Mbps 以太网连接忙碌。因此,将较老机器中的 100 Mbps 以太网卡升级到千兆可能不会像你期望的那样有帮助。

带宽限制导致网络吞吐量问题,因为整个网络只能以最慢的链路速度运行。这些瓶颈造成了性能下降。以一个常见的例子来说,假设你有一个 1 Mbps 下载速度的电缆调制解调器连接到互联网。它可能大多数时候都非常快,但如果你访问的网站完全卡顿或者它本身存在连接问题,你将无法以 1 Mbps 的速度从这个网站下载。实际上,你的下载速度可能甚至接近不了那个速度。

最后,还重要的是要记住,有许多技术并不总是以恒定的固定速度运行,尽管它们可能会根据物理网络特性改变速度。一个很好的例子是模拟调制解调器,它的性能可能会根据它运行的线路质量有很大的变化。

网络配置问题

我之前提到的问题通常是您无法做任何事情的问题;这只是网络野兽的本质。性能限制的第三类,配置错误,是不同的。这指的是由于硬件或软件设置不正确而发生的网络减速。糟糕的布线、配置错误的接口卡或糟糕的驱动程序可以严重降低网络的性能——降低 90%甚至更多。

这些问题通常可以纠正,但前提是你正在寻找它们。驱动程序问题尤其狡猾,因为当出现减速时,人们的自然倾向是将责任归咎于硬件。然而,没有适当的软件来运行,你无法充分利用你的硬件设备。实际上,这些问题在尖端硬件中比在成熟产品中更为重要。

本类别的问题还包括由于设计不当而引起的问题。例如,将 30 个工作站放在共享的 10 Mbps 以太网段上很可能会导致性能不佳——使用交换机会好得多。另一个常见的错误是在客户端/服务器设置中不提供“更粗的管道”(更高带宽的连接)给服务器。这些问题可以通过重新配置网络来避免或改善——甚至更好的是,从一开始就正确设计它,对吧?

不对称性

请记住,许多网络技术,尤其是用于互联网接入的技术,都是不对称的,这意味着它们在一个方向的带宽比另一个方向高得多。通常,这是安排得更多带宽流向用户,而不是从用户流向网络,因为大多数互联网用户下载的数据远多于上传。然而,始终重要的是要弄清楚速度评级是针对两个方向的,还是仅针对一个方向,如果是后者,那么另一个方向的速度是多少。具有不对称性能的常见技术包括 56K 调制解调器、非对称数字用户线路(ADSL)、电缆调制解调器和卫星互联网接入。小心,因为销售这些技术的营销人员通常会试图隐藏他们服务的对称性,通常只突出更大的下载数值,而避免提及较慢的上传速度。

不对称性也可能对网络性能产生意想不到的影响,因为大多数通信,即使看起来是单向的,实际上并非如此。最常见的情况是,当一种互联网接入技术的下载带宽远高于上传带宽时。当使用 TCP/IP 下载数据时,必须定期发送确认信息。如果上游带宽太低,这可能会使得无法充分利用链路的下载带宽。

小贴士

关键概念 网络的理论额定速度在实际中从未达到,原因有很多。开销问题意味着网络的可能容量并非全部可用于数据传输。外部因素,例如硬件带宽限制,会限制数据的输入和输出。配置问题也可能大大降低实际性能。最后,重要的是要记住,许多技术是不对称的,一个方向的速率比另一个方向高,而且通常,较大的数值是广告中宣传的数值。

单向、全双工和半双工操作

另一个值得关注的性能方面是网络或连接的操作模式。显然,无论何时我们将设备 A 和设备 B 连接在一起,都必须有一种方式让设备 A 向设备 B 发送信息,同时设备 B 也能向设备 A 发送信息。然而,许多人并没有意识到,网络技术在处理这两个方向的通信方式上可能存在差异。根据网络的设置和所使用技术的特性,您可能通过选择性能增强模式来提高性能。

让我们从查看任何网络连接、通信信道或接口可能存在的三种基本操作模式开始。

单工操作

单工操作中,网络电缆或通信信道只能在一个方向上发送信息;它是一条单行道。这可能会让人感觉有些不合逻辑:单向传输的通信有什么意义呢?实际上,在现代网络中,至少有两个不同的地方会遇到单工操作。

第一种情况是使用两个不同的信道进行通信:一个从 A 传输到 B,另一个从 B 传输到 A。这出奇地常见,尽管这并不总是显而易见的。例如,大多数如果不是所有光纤通信都是单工的,这意味着它使用一根光纤发送每个方向的数据。但如果一对光纤线缆被合并成一根电缆,这可能并不明显。

单工操作也用于特殊类型的技术,尤其是那些不对称的技术。例如,一种卫星互联网接入类型只在下载时通过卫星发送数据,而常规的拨号调制解调器用于向服务提供商上传。在这种情况下,卫星链路和拨号连接都在单工模式下运行。

半双工操作

采用半双工操作的技术能够在两个节点之间双向发送信息,但一次只能使用一个方向。当设备之间只有单一网络介质(电缆、无线电频率等)时,这是一种相当常见的操作模式。

虽然这个术语通常用来描述一对设备的行为,但它可以更一般地指任何数量的轮流传输信息的连接设备。例如,在传统的以太网网络中,任何设备都可以传输,但一次只能有一个设备进行传输。因此,常规(未切换)的以太网网络通常被称为半双工,尽管这样描述局域网可能看起来有些奇怪。

全双工操作

全双工操作中,两个设备之间的连接能够同时向两个方向发送数据。全双工通道可以是成对的简单链路(如前面所述)或使用一个设计为允许双向同时传输的通道。全双工链路只能连接两个设备,因此如果需要连接多个设备,就需要许多这样的链路。

注意

“全双工”这个术语有些多余;双工就足够了,但每个人仍然说全双工(可能是为了区分这种模式与半双工)

在这三个选项中,全双工显然是提供最高性能的一个。全双工操作将连接的理论带宽翻倍。如果一个链路通常以 1 Mbps 的速度运行,但可以工作在全双工模式下,它实际上有 2 Mbps 的带宽(每个方向 1 Mbps)。然而,记住关键词理论——在现实生活中,你并不会真正获得双倍的性能,因为通信通常不会同时向两个方向发送大量数据。但是,你确实会比在半双工模式下获得更好的吞吐量。

在某些情况下,操作模式是技术决定的,无法更改。然而,在其他情况下,全双工模式是正确硬件设置的问题,以及软件是否支持全双工操作。因此,在这个领域获得更高的性能有时仅仅是确保适当配置的问题。

全双工操作在通信中已经相当普遍,多年以来都被视为理所当然。更有趣的发展是全双工操作在局域网中的重要性日益上升。传统上,局域网始终在共享访问介质上使用半双工操作。随着交换机的使用增加,为每台计算机提供专用带宽,全双工操作变得非常流行。以太网中的全双工操作不仅允许双向同时传输数据,而且消除了以前共享访问介质的竞争——因此,不再发生冲突。这两种效果的组合提高了性能,有时甚至显著提高。

小贴士

关键概念 描述网络中连接设备之间数据发送的基本操作模式有三个。在单工操作中,数据只能在两个设备之间单向流动。半双工网络允许任何设备传输,但一次只能有一个设备进行传输。全双工操作意味着两个连接的设备可以同时发送和接收数据。后者提供了最大的潜在性能,因为强迫一个设备在发送数据前等待另一个设备不会降低吞吐量。

服务质量(QoS)

在本章前面关于常见网络性能测量的讨论中,我提到网络性能有许多不同的方面。我还介绍了延迟的概念,它衡量数据穿越网络所需的时间。延迟是网络中一个更大的问题的一部分,有时被称为服务质量QoS

大多数网络技术的固有性质是,它们更关注尽可能快地将数据从一个地方泵送到另一个地方,而不是关注数据是如何发送的。例如,互联网是在互联网协议(IP)之上设计的,这是一种分组交换技术(在第一章网络介绍、特性和类型中描述),旨在以最有效的方式将数据包从 A 点传输到 B 点,而不需要用户了解将采取什么路由。事实上,同一数据流中的某些数据包可能沿不同的路由发送。数据包可能在转发到目的地之前存储一段时间,甚至可能被丢弃并重新传输。

对于大多数应用,例如简单的文件或消息传输,这完全没问题。然而,有些应用这类服务代表低质量。在这些情况下,数据交付的性质比仅仅速度更重要,需要提供 QoS 的技术或协议。这个通用术语可以包括以下相关功能:

带宽预留 指在网络或接口中为一段时间预留一部分带宽的能力,以便两个设备可以依赖在特定操作中拥有该带宽。这用于需要实时流式传输数据的多媒体应用,如果数据包重路由和重传会导致问题。这也被称为资源预留

延迟管理 一个功能,限制任何数据传输中两个设备之间的延迟在一个已知值。

流量优先级 在传统网络中,所有数据包都是平等的。一个有用的 QoS 功能是处理数据包的能力,以便更重要的连接比不那么重要的连接获得优先权。

流量整形 这指的是使用缓冲区和限制,两者都限制连接上的流量低于预定的最大值。

网络拥塞避免 这个 QoS 功能指的是监控网络中的特定连接,并在网络中的特定部分变得拥塞时重新路由数据。

因此,从本质上讲,网络环境中的 QoS 与现实世界中的 QoS 类似。它是在一家不错的法国餐厅点外卖和坐下来用餐之间的区别——两者都能解决饥饿,但它们满足的需求非常不同。一些应用程序,尤其是语音、音乐和视频等多媒体应用程序,是时间依赖的,并且比原始带宽更需要一个持续的信息流。

小贴士

关键概念 通用术语服务质量(QoS)描述的是数据在设备之间传输的特性,而不是传输速度。QoS 功能旨在提供更可预测的数据流,而不是更快的流。此类功能的例子包括带宽预留、最小延迟、流量优先级和整形以及拥塞限制。对于专业应用程序,如多媒体,QoS 比常规应用程序(如传输文件或消息)更为重要。

为了支持 QoS 需求,许多新技术已经被开发或增强,以向它们添加 QoS 功能。这包括支持等时传输的能力,可以在一段时间内预留一定量的带宽来支持必须实时发送数据的应用程序。一种因其 QoS 功能而受到大量关注的技术是异步传输模式(ATM)。ATM 旨在支持那些在未优化以提供 QoS 功能(如以太网)的网络上通常不可用的流量管理功能。

QoS 最近已经成为一个热门词汇。仅凭这个词本身,它传达的技术提供的信息与被告知它具有高性能的信息相差无几。你必须超越营销术语,找出确切提供的 QoS 功能是什么。

第三章:网络标准和标准组织

无标题图片

在不很快遇到与主题相关的大量标准以及创建这些标准的组织之前,你无法研究网络及其相关技术。网络标准促进了网络技术的互操作性,并且非常重要。说没有标准网络就不会存在可能有些夸张,但说没有标准我们就不会知道现在的网络可能并不夸张。网络实际上无处不在,每个硬件设备或协议至少受一个标准管理,通常受多个标准管理。

在本章中,我简要探讨了经常被忽视的主题——网络标准和标准组织。我首先讨论了标准的重要性,强调了专有、事实和开放标准之间的差异。我概述了网络标准的总体情况,然后描述了与网络相关的最重要的国际标准组织和行业集团。接着,我描述了负责互联网标准的组织的结构,包括负责管理地址、域名和协议值等资源的注册机构和注册处。最后,我讨论了用于创建互联网标准的请求评论(RFC)过程。

专有、开放和事实标准

标准为什么重要?计算机界有一句老话:“标准的美丽之处在于选择众多。”这个小小的笑话反映了技术人员在行业中发现的数千个标准所感受到的挫败感。除了在内容上有所不同——描述的技术和协议——标准在类型和产生方式上也有所不同。事实上,有时某个特定领域有如此多的选择,部分原因就是它们是如何产生的。

专有标准

在计算机的早期阶段,许多人并不完全理解通用标准的重要性。大多数公司由熟练的发明家经营,他们提出了新技术的大胆想法,但他们对分享这些想法并不特别感兴趣。与其他公司分享新发明的信息并不被视为明智的商业行为——竞争!当然,公司认为标准很重要,但他们认为更重要的是由他们来控制这些标准。

例如,设想一下,现在是 1985 年,我刚刚发明了一种出色的网络技术,并将其集成到一个名为 SooperDooperNet 的新颖局域网产品中。SooperDooperNet 是我的产品。我对这项技术拥有专利,我控制其设计和制造,而且我当然不会告诉任何人它是如何工作的,因为如果我这样做,别人就会模仿我。

我可以销售 SooperDooperNet 的接口卡、电缆和配件,想要使用它的公司可以在所有 PC 上安装这些卡,并确保这些计算机能够相互通信。通过创建一个“SooperDooperNet 标准”,这解决了该公司的互操作性问题。这是一个专有标准的例子——它归一个公司或个人所有。

专有标准的问题在于,其他公司被排除在标准开发过程之外,因此几乎没有动力与标准所有者合作。事实上,恰恰相反:他们有很强的动机开发一个竞争性的专有标准,即使它没有改进现有的标准。

所以当我的竞争对手看到我在做什么时,他不会也创建可以与 SooperDooperNet 一起工作的网络接口卡,这将需要向我支付版税。相反,他将开发一系列名为 MegaAwesomeNet 的新网络硬件,它在操作上与 SooperDooperNet 非常相似,但使用不同的连接器、电缆和逻辑。他也会试图向我的客户销售大量的卡片和电缆。

这里的问题是,市场最终会出现不同公司使用不同产品,而这些产品无法协同工作。如果你安装了 SooperDooperNet,你必须来找我进行任何升级或更改——你没有任何选择。更糟糕的是,如果拥有 50 台运行 SooperDooperNet 的 PC 的 Acme 制造业与拥有 40 台运行 MegaAwesomeNet 的 PC 的 Emca 制造业合并会发生什么?IT 人员会遇到问题。当然,会有解决方法,但不是每个人一开始就避免这些困难会更好吗?而且,如果每个人的网络都使用不同的“标准”,你如何能创造出像互联网这样的东西呢?

开放标准

最终,公司们意识到,拥有一个大家都能接受的标准化体系对他们更有利。这在网络领域尤其如此,因为设备需要相互通信。如果许多公司联合起来并同意合作,他们可以创建一个开放标准,而不是一堆专有标准。这个名字本身就很有说明性;与一个组织的严格保密不同,开放标准对任何有兴趣使用它的人都是开放的。

开放标准成功的关键之一是建立一个指导组织来推广它。通常,会建立一个中立的、非营利性的贸易协会或工作组来制定标准,各种盈利的硬件和软件公司加入这个团体并为其提供财务支持。这些团体还与标准审批机构如国际电信联盟(ITU)和国际标准化组织(ISO)合作,以获得其标准的认可。这些以及其他标准组织将在本章后面的“国际网络标准组织”部分进行描述。

当然,公司并不是为了取悦客户才这样做。在创建开放标准时,他们会在彼此之间分割市场份额,但通过吸引更多客户,他们使市场份额变得更大。客户更喜欢开放标准而不是专有标准,因为这些标准为他们提供了更多选择,并增加了他们与其他公司互动、解决问题、雇佣熟练工人以及在将来扩展的能力。至于公司,他们仍然在他们的特定产品上竞争,所以并不是他们最终都生产相同的产品。出于所有这些原因,开放标准现在比专有标准更为常见。

然而,创建这些标准的过程通常很困难。在某些情况下,标准组织会从头开始制定标准,但在其他情况下,它可能从提交的几种技术中选择一种作为标准的基础,这在通常被称为“技术烘焙”的过程中进行。因此,许多不同的公司可能会带着不同的方法来到桌前,每个公司都在争取被选为该组使用的标准。政治因素可能导致团体陷入多年关于各种选择的斗争,甚至分裂成多个团体。好的例子是 100VG-AnyLAN 支持者与快速以太网支持者之间的冲突,以及困扰电力线网络世界的标准政治问题。

此外,还有一些公司仍然强烈相信专有标准,因为他们真的想控制和引导市场。在这方面最著名(臭名昭著)的一个例子是索尼,这是一家制造优秀硬件的公司,但经常拒绝接受既定标准。因此,有些人避免使用索尼的产品,尽管它们很好,因为他们想坚持行业标准。

事实标准

这让我想到了计算机界常见的一种标准类型:事实标准。“De facto”在拉丁语中意为“实际上”。事实标准是指那些因为随着时间的推移而被广泛使用,而并非因为标准是由标准委员会开发和批准的,而被用作通用标准的。

事实标准的一个好例子是调制解调器使用的 AT 命令集。几乎所有的调制解调器都使用它,但这种接受并不是由行业团体同意采用和部署的结果。相反,它是 Hayes 这家先驱调制解调器公司单方面开发的,然后几乎所有的其他调制解调器制造商都采用了它,直到它成为标准。

专有标准有时仍然存在的一个原因是,一些公司希望生产一个将被普遍使用,从而成为事实上的标准,这样它们就可以在该市场中占据领导地位。再次,据我所知,索尼属于这一类别——开发者经常想按自己的方式行事,并创建他们试图通过强大的市场影响力推广的专有标准。

有时这会成功,但往往不会,导致不兼容产品的市场碎片化。一个很好的例子是,索尼为数码相机的闪存创建了一种新的格式(记忆棒),而不是使用其他相机制造商使用的 CompactFlash 格式。最终结果是,并非每个人都使用记忆棒,正如索尼所希望的那样,现在有两种不兼容的标准,增加了混乱,并没有给顾客带来真正的利益。

小贴士

关键概念 网络标准可以分为专有、开放事实上的标准。专有标准归一个特定组织所有。如果该组织在市场上具有足够的影响力,并且该行业缺乏其标准的替代品,那么整个行业可能会采用它,使其成为事实上的标准。然而,通常不同的专有标准会相互竞争,导致市场碎片化。相比之下,开放标准不属于任何人——它们是由中立组织创建的,以确保许多不同的公司可以设计和开发兼容的产品。这使得顾客的生活更加便利,同时也促进了整个市场的繁荣。

网络标准

所有网络技术都有与之相关的标准。这些通常是高度技术性的文件,并且它们通常假设读者对网络有一定的了解。如果你不是专家,你可能会在理解网络标准时遇到一些困难。

事实上,许多技术都有相当多的标准与之相关。一种网络技术可能因为以下任何一个或所有原因而有多个标准:

  • 原始标准已被修订或更新。

  • 技术足够复杂,需要用多份文件来描述。

  • 技术借鉴或基于相关技术中使用的文档。

  • 有多个组织参与了这项技术的发展。

在美国创建的标准文件通常用英语开发,但也经常翻译成其他语言。欧洲标准通常同时用英语、法语、德语以及可能还有其他语言发布。

现在,几乎所有网络标准都是开放标准,由标准组织或行业团体管理。正如我在上一节中解释的那样,开放标准在计算机行业中比专有标准更受欢迎,这在网络领域尤其如此。事实上,那些没有普遍接受的开源标准的少数技术正在失去市场份额,尤其是在无线局域网和家庭网络领域。这几乎证明了开放过程的重要性。

注意

在这本书中,你会找到关于各种标准的讨论。这些讨论通常可以在介绍每种技术类型的概述章节中找到,尽管更复杂的协议讨论包括一个讨论相关标准的部分

国际网络标准组织

开放标准的兴起对计算机和网络产品的客户以及销售给他们的制造商来说都是一个巨大的福音。然而,为了促进开放标准的发展,我们需要那些将协调这些文档的创建和发布的组织。通常,这些是非营利组织,它们在技术问题上持中立立场,并为整个行业的改善而努力。

这里是一个精选的列表,列出了一些你可能在阅读有关网络和互联网的书籍时可能遇到的标准组织:

国际标准化组织(ISO) 可能是世界上最大的标准组织,ISO 实际上是来自数十个国家的标准组织的联盟。在网络领域,ISO 最著名的是其 OSI 参考模型,该模型在本书的第一部分-2 中有所讨论。

注意

国际标准化组织的缩写确实是 ISO,而不是你可能想象中的 IOS。实际上,它根本不是一个首字母缩略词。由于该机构的全称在不同的语言中有所不同,因此对该名称的任何首字母缩略词也会有所不同。相反,该组织从希腊语单词isos中选择了 ISO,其含义为“相等”。许多人,尤其是在美国,认为 ISO 是国际标准化组织的缩写,但这是不正确的

美国国家标准协会(ANSI) ANSI 是美国负责协调和发布计算机和信息技术的标准的主要组织。尽管许多人认为该组织开发和维护标准,但实际上它既不开发也不维护标准。相反,它监督和认证那些实际创建标准的组织,将它们认定为标准制定组织(SDO)。ANSI 还发布 SDO 创建的标准文件,并作为美国代表参与 ISO。

信息技术产业理事会 (ITIC) ITIC 是由几十家信息技术(计算机)行业公司组成的团体。ITIC 是 ANSI 批准的开发和处理与许多计算机相关主题相关的标准的 SDO。它以前被称为 计算机和商业设备制造商协会 (CBEMA)

信息技术国家标准委员会 (NCITS) NCITS 是 ITIC 建立的委员会,负责开发和维护与信息技术世界相关的标准。NCITS 以前被称为 Accredited Standards Committee X3, Information Technology,或更常见地,仅称为 X3。它维护几个子委员会,这些子委员会开发和维护各种技术主题的标准。

电气和电子工程师协会 (IEEE) IEEE(发音为“eye-triple-ee”)是一个为电气或电子领域(包括计算机和网络)的专业人士所熟知的知名组织。IEEE 在网络行业的主要成就是 IEEE 802 项目,该项目涵盖了包括以太网在内的许多流行的网络技术。

电子工业协会 (EIA) EIA 是一个国际行业协会,最出名的是发布电气布线和传输标准。

电信行业协会 (TIA) TIA 是 EIA 的通信部门,负责制定通信标准。由于通信、布线和传输都是相关的,而且由于 TIA 和 EIA 组织也是相关的,因此由 EIA 或 TIA 制定的标准通常带有 EIA/TIA 或 TIA/EIA 的组合前缀。

国际电信联盟——电信标准化部门 (ITU-T) ITU-T 是另一个大型国际机构,负责为电信行业制定标准。ITU-T 以前被称为国际电话电报咨询委员会 (CCITT;缩写来自组织的法语名称:Comité Consultatif International Téléphonique et Télégraphique)。

欧洲电信标准研究院 (ETSI) 这是一个拥有来自数十个国家的成员的组织,包括欧洲内外,致力于为欧洲市场(及其他地方)制定电信标准。ETSI 以监管欧洲的无线电频谱使用以及制定如 HiperLAN 等标准而闻名。

许多这些组织实际上并不开发各种标准。通常,这些是监管机构——可以称之为高级管理层——它们与许多其他较小的团体合作,这些团体实际上负责制定标准。此外,在许多情况下,一个特定的标准可能由多个标准组织发布,因此它可能带有多个名称。

注意

负责创建互联网标准的组织集合未在此列表中显示,因为我在本章后面的两个专门部分中选择了覆盖它们,即互联网标准组织和注册机构

小贴士

关键概念 在开放网络标准的开发中,有一些国际组织扮演着重要的角色。其中一些最重要的组织包括 ISO、ANSI、ITIC、IEEE、EIA/TIA、ITU-T 和 ETSI。这些是监管组织,负责整体管理标准开发过程,而不是个别标准的创建细节。

网络行业团体

尽管大多数开放标准都是由少数几个大型、通常为国际性的标准组织协调和发布的,但这些并不是唯一参与网络和互联网技术标准开发的团体。许多不同的网络行业团体在标准创建过程中发挥着重要作用。

网络行业团体与标准组织在几个方面有所不同。它们通常致力于推广特定的技术,而标准组织则更为通用,监管数百个不同的技术。行业团体通常也比标准组织规模小,成员主要来自为该团体推广的技术创造产品的开发者和制造商领域。

也许是更重要的是,行业团体通常实际上编写并维护标准,而标准组织通常作为监管者,确保标准足够清晰以便实施。然而,一些行业团体只关注市场营销和推广活动。

显然,这些行业团体与标准组织紧密合作。在某些情况下,它们甚至可能是同一个整体组织的一部分,所有不同的团体都以某种方式相互关联。例如,IEEE 802 项目由多个工作组组成,负责维护和开发特定的技术标准,这些标准由更大的 IEEE 组织批准和发布。

其中一个工作组是 802.11 工作组,该工作组负责开发无线以太网技术。与此同时,有一个名为无线以太网兼容性联盟(WECA)的行业团体。该团体致力于确保 802.11b 无线网络硬件和软件的跨厂商兼容性。

其他行业团体专门成立,以开发未经正式标准化程序批准的独立标准。例如,包括 HomePNA、IrDA 和 HomeRF 等团体。

这些团体的问题之一是它们通常不将标准对公众开放。这无疑是由于某种安全担忧或希望保持其技术的内部运作秘密。不幸的是,对于这些团体来说,这种政策损害了普通人了解他们的技术是如何工作的能力。

注意

以下是我所说的封闭标准的一个例子,我可以指出我在撰写本文和其他参考作品时的个人经历。我几乎总是无法从大多数私营行业集团获得规范。他们要么拒绝让我获取文档,要么为了这种特权向我收取大量费用(在某些情况下,费用高达数千美元)。通过这样做,这些团体损害了自己的事业,从而使得对他们的技术感兴趣的人了解这些技术变得更加困难。这是拥有由 ANSI 或 IEEE 等公共组织管理的开放标准的一个重要优势

互联网标准组织(ISOC、IAB、IESG、IETF、IRSG 和 IRTF)

随着使用网络的用户数量的增加,高质量、广泛接受的开放标准变得越来越重要。所有网络中最大的当然是互联网,它将数百万人在数千个独立网络中连接成一个全球性的互联网。互联网不仅改变了网络和计算,还改变了通信、商业,甚至整个社会。互联网成功的一个关键因素是其使用开放标准的发展。

当然,没有人有一天坐下来说过,“嘿,让我们创建互联网!”(不,甚至不是戈尔。)它最初是一个小型研究网络,随着时间的推移,与实现它的技术集(TCP/IP)同时发展。最初,一个相对较小的组织足以管理互联网标准的发展和监督其活动,但随着互联网的持续增长,这个组织变得不足。最终,需要一个更正式的组织结构来管理互联网发展过程和其他活动。这确保了互联网及其所依赖的 TCP/IP 技术的持续成功和增长。

今天,有六个组织负责互联网架构、标准和政策以及相关活动的发展。它们之间紧密相关,某些组织负责监督其他组织。这些组织执行许多任务,由于许多组织名称和职责相似,理解起来可能有些令人困惑。因此,我将主要集中讨论它们在互联网标准发展中的作用,因为这是本次讨论的主要兴趣点。

这里简要描述了关键的互联网标准组织,相对简化:

互联网协会 (ISOC) 一个负责与互联网的管理、发展和推广相关的普遍、高级活动的专业协会。ISOC 有数千名个人和组织成员,他们参与研究、教育、公共政策发展和标准化等活动。它负责向本章中列出的其他组织提供财务和管理支持。从标准开发的角度来看,ISOC 的关键作用是其对 IAB 的监督责任。

互联网架构委员会 (IAB) 之前称为 互联网活动委员会,IAB 负责对互联网标准发展的整体管理。它做出与互联网技术和结构应如何运作相关的“大局”政策决策。这确保了各种标准化努力协调一致,并与互联网的整体发展保持一致。它负责发布互联网标准(RFC),如本章末尾的“互联网标准和请求评论(RFC)流程”部分所述。它向 ISOC 提供建议,并监督 IETF 和 IRTF;它还作为对 IETF 执行的标准化活动投诉的申诉机构。IAB 的章程在 RFC 2850 中描述。

互联网工程任务组 (IETF) IETF 关注与当前互联网和 TCP/IP 技术发展相关的问题。它分为多个 工作组,每个工作组负责特定领域(如路由或安全)的标准和技术开发。每个领域由一个 领域指导委员会 管理,该委员会是 IESG 的成员。IETF 直接由 IESG 和 IAB 监督;它在 RFC 3160 中进行了描述。

互联网工程指导组 (IESG) IESG 直接负责管理 IETF 和互联网标准开发流程。它由每个 IETF 领域指导委员会成员组成,他们负责对提议的标准进行最终批准的决定,并努力解决标准化过程中可能出现的任何问题。从技术角度来看,IESG 是 IETF 的一部分,并在 RFC 3160 中进行了描述。

互联网研究任务组 (IRTF) 当 IETF 主要关注短期发展问题时,IRTF 负责与互联网和 TCP/IP 技术相关的长期研究。它是一个比 IETF 小得多的组织,由一组 研究小组 组成,这些小组类似于 IETF 的工作组。IRTF 由 IRSG 和 IAB 监督,并在 RFC 2014 中进行了描述。

互联网研究指导组 (IRSG) IRSG 以类似 IESG 管理 IETF 的方式管理 IRTF。它由每个 IRTF 研究小组的主席组成,并与整个 IRTF 的主席合作,就研究活动做出适当的决策。它也在 RFC 2014 中进行了讨论。

图 3-1 展示了互联网标准协会之间的关系。ISOC 监督 IAB,IAB 再指导 IETF 和 IRTF。IETF 负责开发当前的互联网和 TCP/IP 标准,由 IESG 领导,管理 IETF 工作组。IRTF 是 IETF 的研究对应机构,包含由 IRSG 领导的 研究小组

互联网标准组织 ISOC 负责监督 IAB,而 IAB 则负责两个工作组,即 IETF 和 IRTF,它们分别由 IESG 和 IRSG 领导。

图 3-1. 互联网标准组织 ISOC 负责监督 IAB,而 IAB 则负责两个工作组,即 IETF 和 IRTF,它们分别由 IESG 和 IRSG 领导。

在这些组织中,IETF 是你最常听到的,因为它直接负责大多数互联网标准的发展。因此,每当我在本书中提到互联网标准发展工作时,我指的是 IETF 这个执行工作的组织。当然,这有点过于简化,因为所有这些组织都在标准制定过程中发挥作用,正如本章后面在讨论 RFC 流程时所述。

许多这些组织负责的不仅仅是标准制定。特别是对于 ISOC 来说,标准化只是众多活动之一。IAB 也执行一些与标准制定不直接相关的职能,包括管理由互联网数字分配机构(Internet Assigned Numbers Authority)执行的协议值分配,以及作为互联网标准组织和其他标准机构之间的联络人。

提示

关键概念 一组相关组织负责 TCP/IP 标准和互联网技术的发展。互联网协会(ISOC) 对许多互联网活动负有总体责任,包括标准制定。它监督 互联网架构委员会(IAB),该委员会负责对互联网技术发展做出高级决策。创建当前互联网标准的实际工作大多由 互联网工程任务组(IETF) 完成,该组由 互联网工程指导组(IESG) 管理。长期研究由 IETF 的姊妹组织 互联网研究任务组(IRTF) 完成,该组由 互联网研究指导组(IRSG) 领导。

互联网注册机构和注册处(IANA、ICANN、APNIC、ARIN、LACNIC 和 RIPE NCC)

全球互联网的成功依赖于协议和其他技术的普遍接受标准的开发。因此,像 IETF 这样的互联网标准组织至关重要。它们管理标准开发过程,确保每个人都同意如何创建硬件和软件,以便它们可以一起工作以实现全球通信。

虽然标准化协议的需求看似明显,但互联网标准化还有其他一些同样重要但可能并不那么为人所理解的方面:

参数标准化 大多数协议都依赖于使用控制其功能的参数。仅举两个众多例子中的例子,IP 有一组数字定义了不同的 IP 选项,而地址解析协议(ARP)有一个可以取许多不同值的操作码字段。正如设备必须同意使用哪些协议一样,它们也必须同意为这些协议使用哪些参数,如果想要通信成功的话。

全球资源分配和标识符唯一性 互联网上使用的一些资源必须从一组固定的值中进行分配。这些值的分配唯一性对于这些资源至关重要。最明显的例子是,每个 TCP/IP 主机都必须有一个唯一的 IP 地址。另一个重要的例子是确保只有一个组织使用给定的域名系统(DNS)域名。如果两个设备有相同的 IP 地址或两个组织试图使用相同的域名,结果将是不可预测的,但几乎可以肯定是不好的!

在这两种情况下,都需要某种形式的集中组织。我们需要一个团队来负责管理参数。它必须确保每个人都使用相同的参数和协议。我们还需要协调分配标识符,如地址和名称。这确保了标识符的创建和分配方式对所有参与者都是可接受的。在互联网的世界里,这些有时被称为管理机构注册机构

互联网集中注册机构

原来负责管理参数和标识符的组织是互联网分配号码权威机构(IANA)。令人惊讶的是,尽管名字听起来像 IANA 是一个庞大的官僚机构,但实际上它只由一个人负责:乔纳森·B.(乔恩)·波斯尔,他是互联网和 TCP/IP 技术最重要的先驱之一。乔恩·波斯尔一直领导 IANA,直到他在 1998 年不幸去世。

IANA 最初负责管理分配给不同公司和群体的 IP 地址块,并维护定期发布的互联网参数列表,如 UDP 和 TCP 端口号。它还负责 DNS 域名的注册,这些注册由美国政府管理的互联网网络信息中心(InterNIC)直接处理。后来,网络解决方案公司(NSI)获得了管理 InterNIC 的合同,并最终被 VeriSign 收购。

随着互联网的持续增长,在 1990 年代中期开始了一项努力,旨在定义一个新的组织,该组织将负责互联网地址和名称的中央注册。这以一个名为互联网名称与数字地址分配机构(ICANN)的新私有、非营利公司的形式出现。ICANN 正式承担了我之前提到的所有集中注册任务,包括 IP 地址分配、DNS 域名分配和协议参数管理。

在一个更简单的世界里,这一发展意味着 ICANN 将取代 IANA,而 IANA 将不再存在。相反,ICANN 保留了 IANA,让该组织负责监督 IP 地址注册和互联网参数。现在,ICANN 负责 IANA,因此这两个组织都对 IP 地址和参数负责。这往往会导致混淆,而且更糟糕的是,经常看到 IANA 和 ICANN 一起提及,作为 IANA/ICANN 或 ICANN/IANA。

小贴士

关键概念 互联网注册机构是负责协调协议参数和全球分配资源(如 IP 地址)的集中化组织。第一个这样的组织是互联网数字分配机构(IANA),最初负责 IP 地址分配、DNS 域名管理和协议参数。如今,互联网名称与数字地址分配机构(ICANN)对这些活动负有总体责任;IANA 在 ICANN 的监督下运作,并仍负责 IP 地址分配和参数协调。

注册机构现代层次结构

在原始的“类”IP 地址方案中,地址是由 IANA 直接分配给组织的,以地址块的形式:A 类、B 类和 C 类。今天,使用的是一种称为无类域间路由(CIDR)的分层、无类地址系统。CIDR 中的地址分配涉及地址块的分层分配,从分配给大型组织的大块地址开始,这些组织再将它们分割分配给更小的群体。(关于这些方法的更多详细信息可以在第第十六章到第二十章,该章节涵盖了 IP 地址分配问题。)

名称注册在过去几年中发生了变化。它不再是 IANA 的责任,ICANN 已经开放了名称注册业务,因此不再是单一组织如 InterNIC/NSI/VeriSign 的专属。现在,许多不同的认证注册商可以用于许多流行的顶级域名中的名称注册。这将在第五十四章中讨论,该章节涵盖了 DNS 公共注册。包含互联网和 TCP/IP 参数的完整文档列表可以在 IANA 的网站上找到,网址为www.iana.org/numbers.html

互联网标准和请求评论(RFC)流程

现代互联网的先驱是一小群计算机科学家和工程师开发和运行的微型网络。这些技术人员知道,开发开放、广泛采用的标准对于互联网和 TCP/IP 协议套件的最终增长至关重要。但在当时,还没有正式化的标准开发机制。

标准化主要通过就新技术和协议进行讨论来达成共识。如果有人提出了一个新的协议或技术的提案,或者对现有协议的变更想法,那个人将创建一份描述它的备忘录并将其分发给他人。由于目标是征求对提案的评论,这些备忘录被称为请求评论(RFCs)。并非所有 RFC 都描述了正式化的标准;许多只是描述性文件、澄清或包含杂项信息。

注意

定义早期标准的文档最初被称为 互联网工程笔记 (IENs) ,在它们被称为 RFC 之前

当然,今天互联网已经非常庞大,有一个官方的互联网标准组织结构,负责创建新的互联网和 TCP/IP 标准。由于有成千上万的人在积极开发互联网技术,一个任何人都可以随意撰写 RFC 的非正式系统会导致混乱。因此,互联网和 TCP/IP 标准仍然被称为 RFC,但今天创建一个的过程要正式和有组织得多。

IETF 是最直接负责创建互联网标准的标准机构。IETF 的工作组在 IESG 和 IAB 的监督下,持续开发新的协议和技术,这些发展在 RFC 中得到正式化。

RFC 编辑办公室负责 RFC 的发布。从 1969 年开始,近 30 年来,RFC 编辑一直是互联网先驱乔恩·波斯尔。他在 1998 年去世后,该职能被分配给了南加州大学信息科学研究所(ISI)的网络部门,乔恩·波斯尔曾担任所长。RFC 编辑的职能是发布和存档 RFC,并维护一个在线文档库,以便互联网社区可以访问和使用这些文档。

RFC 的开放和免费访问极大地促进了互联网的成功。即使今天,如果你考虑到标准机构为访问单个标准收取数千美元的费用,能够登录并立即检索数千个 RFC 的能力也是值得注意的。

注意

最新的 RFC 列表,每个文档都有超链接(除了早期的一些文档),可以在 RFC 编辑办公室找到。请访问 www.rfc-editor.org/rfc-index.html

RFC 类别

正如我提到的,并非所有 RFC 都是官方互联网标准。这一点很重要要记住。每个 RFC 都有一个与之相关的 类别状态,表明其处理方式:

建议标准/草案标准/标准 这些文档描述了处于标准化轨道上的技术。这意味着它们要么已经被正式批准为标准,要么未来有可能成为标准。在许多情况下,文档只是列在“标准化轨道”下,而不是这三个精确标签之一。

最佳实践 提供指南信息或来自 IETF 的建议的文档,但不是正式标准。

信息性 提供一般信息或评论的文档。

实验性 一个非标准化轨道的实验性标准的提案。在某些情况下,未被接受为正式标准的协议或对现有协议的提案更改可能会变为实验性状态。

历史性 已被淘汰的前期标准。

互联网标准化流程

在一个提案将被考虑为互联网标准化过程之前,它必须以互联网草案(ID)的形式发布。IETF 发布了一系列指南,规定了 ID 必须如何创建和提交。IETF 内部工作组中的成员,参与特定项目的人员编写了大多数 ID。然而,由于标准过程是开放的,任何公众成员都可以独立提交一个标准供审查,方法是创建一个 ID 供 IETF 和 IESG 考虑。ID 通常会根据 IETF 内部其他工作组反馈多次修订。

如果一个 ID 经过审查并被认为有价值、易于理解且稳定(意味着它不是通过新的修订快速更新的),它可能成为标准化的候选人。IESG 可以通过将其状态更改为提议标准将 ID 置于互联网标准跟踪中。处于这种状态的文档通常被认为是基本完整的,但可能根据进一步的审查、测试和技术实验进行修订。

一旦规范足够成熟且被广泛接受,它可能从提议的标准提升为草案标准。此类提升的关键要求是技术必须在至少两个独立且互操作的实施中证明其功能。这证明了该标准已被清除并完成,并且至少有两个不同的团体能够兼容地实施它。

当 IETF 社区认为文档在技术上成熟且规范完整时,文档才会达到草案标准。通常只有对草案标准进行更改,以纠正测试中遇到的问题或解决出现的新问题。

互联网标准跟踪的最终站点是互联网标准。这个名称仅适用于非常成熟、流行且被广泛实施的规范。达到这一状态的文档通常描述的是一种即将或已经普遍实施的技术,并分配了一个 STD(标准)编号。

RFC 开发过程可能需要数月甚至数年,具体取决于技术的复杂程度、对文档所需更改的数量以及提案是否被认为重要或有趣。许多 RFC 从未正式达到互联网标准状态;草案标准状态通常被认为是足够稳定的,以至于当达到这一水平时,公司通常会实施该技术。一些 RFC 甚至从未达到草案标准状态,它们所描述的技术仍在产品中使用。

一旦 RFC 发布,就不能更改。这是一个特定的政策决定,旨在避免由于存在多个版本的同一 RFC 而可能产生的混淆。RFC 发布流程包含多个步骤,在这些步骤中,RFC 作者可以修订他们的文档并检查编辑遗漏和错误。

每次更改都需要新文档的需求也是为什么提案通常以标准轨道类别而不是建议标准、草案标准和互联网标准发布的原因。这消除了在提案在标准轨道上前进时需要发布新 RFC 的需要,除非需要更改类别以外的任何实际更改。

我在这里概述了创建和发布互联网标准的过程。标准流程的完整细节可以在 RFC 2026 中找到(还能在哪里找到?)。

小贴士

关键概念 互联网标准在一系列称为 请求评论 (RFCs) 的文档中描述。RFC 流程描述了互联网标准通常是如何创建的。一个新技术或改进的想法始于创建一个 互联网草案 (ID)。经过审查和反馈后,如果提案得到支持,它可能被放置在互联网标准轨道上,其状态将更改为 建议标准。随着这个新兴标准的成熟,其状态可能提升到 草案标准,最终成为 互联网标准。然而,许多 RFC 在没有达到互联网标准状态的情况下被用于产品中。还有一些 RFC 定义了实验性技术或提供信息,而没有描述官方互联网标准。

第四章。数据表示和计算数学的回顾

无标题图片

我们使用十进制(基数为 10)数字来表示数值信息,并使用各种字母表和符号系统来表示其他类型的信息。相比之下,计算机只理解一种基本类型的信息:一和零,这些本身代表设备硬件中的开或关的电气状态。这些一和零以各种方式组合,形成我们在计算机中习惯看到的数据元素:常规数字、字符和文件。然而,所有这些都是抽象的;一和零始终在计算机内部使用的任何逻辑结构之下。

同样的基本基础,即一和零,也适用于网络。尽管网络中的大部分信息是在高层协议之间以逻辑方式交换的,但通过网络介质发送的一和零是所有网络结构的基础。理解数据在计算机系统中的表示和处理方式对于理解许多不同的技术非常重要。计算机数据表示和数学对于解释低级物理层调制和解码技术的工作方式至关重要。这两个元素甚至对于更高级的概念,如如何在互联网上设置和使用 IP 地址,也起着作用。

在本章中,我提供了一些关于如何在计算机和网络硬件中表示、存储和处理数值数据的通用背景信息。我首先描述了二进制数以及用于指代不同大小二进制信息集合的不同术语。我描述了计算机系统中使用的不同编号系统,例如八进制、十进制和十六进制,以及如何在这些不同类型之间转换数据。我解释了如何在二进制和十六进制数上执行算术运算。然后,我讨论了布尔逻辑以及如何使用逻辑函数来操作二进制数据。

这些解释构成了讨论如何使用逻辑函数来设置、清除、反转和掩码位的依据。这些操作在特定的网络技术和协议中被广泛使用。掩码操作特别常用于 IP 地址中,所以尽管这一部分看起来相当底层,但它与 TCP/IP 世界非常相关。

注意

不用说,你可能已经知道本章中的大部分或全部信息,所以如果你已经了解这些内容,可以自由跳过(或只是浏览)那些你已经知道的主题。我提供这些背景细节是为了那些对计算机新接触者或需要复习的人。然而,即使那些知道位和字节是什么,以及知道二进制和十进制数之间区别的人,也可能发现位掩码的讨论值得一读

二进制信息和表示:位、字节、半字节、八位字节和字符

计算的本质是信息。计算机硬件和软件被设计成允许输入、存储、传输和表达各种类型的信息。区分信息类型的一种主要方式是将其分为模拟数字

以一个开关和一个调光器为例。开关允许灯光打开或关闭;没有中间状态。这些离散状态,开或关,代表数字信息。相比之下,调光器允许你从全开调到全关,中间有无限多个中间状态;这是模拟信息。

二进制信息

现代数字计算机以数字方式存储信息。就像灯泡只有开启或关闭的值一样,存储和操作计算机内部信息的组件也是如此。数百万个晶体管组成计算机处理器和其他电路,以高度简化的形式,它们是数字开关。因此,计算机中的所有信息都是以可以只有开启或关闭的集合形式操作的信息片段。

由于只有两种可能的状态——开启或关闭,这被称为二进制信息(前缀bi表示两个)。使用二进制表示信息有几个优点。这是一种简单的方式来表示许多类型的信息,无论是灯开关是开启还是关闭,还是文件是否成功复制。也可以组合二进制值来表示更复杂的信息。

也许最重要的是,二进制信息是明确的:开总是开,关总是关。这个特性很重要,因为它允许设备清楚地检测特定信息片段的值。计算机喜欢黑白分明;它们在处理灰色阴影方面并不擅长。(这在网络领域尤为重要,因为数据的传输可能导致信号受到噪声的污染。)

二进制值的开启或关闭状态可以用多种方式表达。在逻辑表达式中,我们可以认为该值为真或假。当表示数学值时,最常见的方式是表示为 1(开启)或 0(关闭)。

二进制信息表示和组

计算机信息的基本构建块是比特binary digit的缩写)。每个比特可以是 0 或 1。将比特值设为 1 通常称为设置比特;将其更改为 0 称为重置清除

当然,比特只代表非常少量的信息:一个事实或值。我们必须将这些比特组合起来,以便我们可以使用它们来存储大量信息和更复杂的数据类型。最常见的组合是将 8 个比特作为一个单元来引用。8 个比特的集合在技术上称为八位组,但更常见的是称为字节(稍后将有更多介绍)。

字节是对术语比特的一种幽默的戏称。随着时间的推移,各种大小的比特集合已经被定义。一些极客喜剧演员决定,如果 8 比特组成一个字节,那么 4 比特必须是一个nybble(或“nibble”)。好笑,不是吗?更大的集合也被定义,并赋予了各种名称。表 4-1 总结了最常见的比特组表示及其术语;它们的大小关系也在图 4-1 中用图形表示。

表 4-1. 二进制信息组表示和术语

比特数 常见表示术语
1 比特/数字/标志
4 Nybble/Nibble
8 字节/八位字节/字符
16 双字节/字
32 Double Word/Long Word
64 非常长字

表 4-1 中出现的一些新术语值得特别提及。比特有时也被称为标志;这个术语最常在比特单独用来表示特定的信息状态时听到。例如,计算机可能使用一个更改标志来表示某个特定文件是否已被修改;这是一个将旗帜升起或降下来指示条件的类比。这些标志在网络消息格式中经常可以看到。

术语字符也用来表示一组 8 比特。这种用法来源于计算机通常将字母数字字符,如字母和数字,存储在一个字节中。16 位的使用相当频繁,但远不如字节。更大的比特集合,如双字等,在日常用语中很少遇到;它们用于在硬件设计或编程等技术领域表示数据块。

二进制信息表示和术语 此图显示了最常见的二进制信息集合的大小关系

图 4-1. 二进制信息表示和术语 此图显示了最常见的二进制信息集合的大小关系。

注意,这些术语中每个术语使用的比特数都是 2 的幂。正如你将在本节后面看到的那样,这是因为当比特以 2 的幂为大小成组出现时,它们更容易表示和操作。

提示

关键概念 计算机以二进制数字形式存储所有信息。这意味着所有数据——无论是文本、照片、音频还是其他任何东西——都是由一组零和一组成的。数字信息的基本构建块是二进制位比特,它代表单个零或一的状态。为了表示更大的信息量,比特可以被收集成 4、8、16、32 或 64 位的组合,分别称为半字节、字节、字、长字和超长字

字节与八位组

关于使用单词字节八位组的问题,已经有一些分歧,甚至争议。传统上,字节是表示 8 位集合的最常用术语,尤其是在北美。然而,从技术上讲,这并不是一个正确的术语。

一个字节,正式上讲,是计算机系统中一次可以读取或写入的最小数据单位。在几乎所有情况下,这确实是 8 位,但也有一些系统中的字节不是 8 位。一些较老的 36 位计算机使用了 9 位字节,而其他一些则具有 6 位或 7 位的字节大小,甚至还有可变大小的字节。因此,许多人,尤其是技术专业人士,更喜欢使用术语八位组,这个术语明确且无歧义地暗示了 8 位。这个术语在北美之外更为常见。

注意

关于八位组和字节的问题是计算机人员所喜爱的那种茶壶风暴。然而,在现代计算机系统中,底线是八位组是一个字节,一个字节也是一个八位组,这两个术语通常可以互换使用而不会造成太大的危险。你更经常会在技术标准中看到八位组的使用。在这本书中,我使用术语字节,因为这是大多数人熟悉的概念。

小贴士

关键概念 正式上讲,八位组是恰好 8 位的正确术语,而字节是计算机系统中可以访问的最小位数,它可能等于也可能不等于 8 位。在实践中,现代计算机使用 8 位字节,这两个术语可以互换使用(在北美,字节更为常见,而在欧洲八位组通常更受欢迎)。

十进制、二进制、八进制和十六进制数

我们在日常生活中习惯使用的数字称为十进制数。单词十进制指的是数字 10。每个数字可以取十个值之一:0 到 9。在十进制数上进行的算术运算也称为十进制数学,因为它是围绕数字 10 的这种取向。(为什么数字 10 是我们正常数学系统的基础?举起双手并数数!)

然而,计算机系统没有手指或脚趾;它们只处理二进制数,这些数只有两个值。每个比特只能表示 0 或 1。单个 0 或 1 值足以编码一个单一的事实,比如某事是真是假,或者答案是是或否。但是一个比特不足以存储更复杂的信息,比如你的银行账户余额、一个文本文档,或者黄石峡谷的图片。

二进制数及其十进制等价数

因此,计算机科学家创建了更大的比特集合,如字节(八位)、字等。当单个比特以这种方式收集成集合时,它们可以表示更大的整数,称为二进制数。由于二进制数中每个数字只有两种可能的值(0 或 1),因此二进制数也称为二进制数。

理解二进制数的关键是意识到它们与十进制数完全相同,只是每个数字的值在 0 到 1 之间,而不是 0 到 9 之间。例如,当你用十进制计数时,个位上的数字会增加到 9,然后你需要第二个位置来表示十。如果你超过 99,你需要第三个位置来表示百。在左边添加的每个额外位置都是十的更高次幂。

二进制与十进制相同,但每一位的极限是 1 而不是 9。因此,在二进制中,个位上的数字会增加到 1,然后需要第二个位置来表示 2(而不是十)。如果你超过 3,你需要第三个位置来表示 4(而不是百)。每个增加的数字都是 2 的后续更高次幂,而不是 10 的。

因此,当用十进制计数时,计数为 0,1,2,3,4,5,6,7,8,9,10,11,12,13 等等,而用二进制计数时,计数为 0,1,10,11,100,101,110,111,1000,1001,1010,1011,1100,1101。例如,十进制的 13 与二进制中的 1101 相同。为什么?因为在十进制中,个位上有 3,加上十位上的 1,其值为 10。这是 3 + 10,或 13。在二进制中,我们从个位上的 1 开始,加上四位上的 1(值为 4),再加上八位上的 1,值为 8。这是 1 + 4 + 8,或 13。

以一个更复杂的例子来说明,十进制的 211 在二进制中是 11010011。表 4-2 展示了这两个数是如何等价的,通过为每个有 1 的二进制位加值。从左到右,从上到下阅读。从最左边的列开始,你可以看到示例数字在 128 位上有 1。所以你从 128 开始计算总和。在下一列中,64 位上有 1,所以加上 64,得到 192 的累计总和。但在 32 位上,二进制位值是 0,所以你不需要将 32 加到总和中。如果你继续向下到个位,你会得到二进制数的十进制等价值。

表 4-2. 二进制和十进制数等价表

二进制数 1 1 0 1 0 0 1 1
二的幂 2⁷ 2⁶ 2⁵ 2⁴ 2⁰
数字位值 128 64 32 16 8 4 2 1
此数字的值 128 64 0 16 0 0 2 1
从左到右的运行总和 128 128+64 = 192 192 192+16 = 208 208 208 208+2 = 210 210+1 = 211

如你所见,一个有N位的二进制数可以存储多达 2^(N)个值。所以一个 8 位的字节可以存储 2⁸,即 256 个不同的值,这些值从 0 到 255 编号。一个 16 位的字可以存储 2¹⁶,即 65,536 个值。

通过分组位使二进制数更容易使用

二进制数的一个问题是,尽管计算机喜欢它们,但人们却难以处理它们,因为它们很快就会变得很长且难以操作。例如,十进制系统中的 1,000,000 在二进制系统中是 11110100001001000000。为了使二进制数更容易处理,已经定义了两种不同的缩写表示法。在这两种表示法中,不是单独处理每个位,而是将数字收集成小组,每个小组在另一种计数系统中分配一个单独的数字。

八进制数

考虑二进制数 11110100,它在十进制中是 244。不是单独查看每个位,而是从右开始将它们分成三位的组:11110100 变为(11)(110)(100)。这些组中的每个组都有三个位,因此每个组可以有 2³ 个值:从 0 到 7。在这种情况下,(11)(110)(100) = (3)(6)(4),或者 364 在八进制基 8计数系统中(见图 4-2). 与二进制一样,八进制数与十进制数相同,只是它们使用基 8 而不是基 10。所以八进制中的 364 是 3 x 64 + 6 x 8 + 4,即 244。正如你所看到的,八进制比二进制简单得多,尤其是在处理较大的数字时。在十进制系统中,1,000,000 是八进制的 3641100。与二进制的 11110100001001000000 相比。

二进制、八进制和十六进制数表示法 一个二进制数可以通过将其位分组为三组来表示为八进制形式,或者通过使用四位的组来表示为十六进制。这些以 8 和 16 为基数的数字比二进制数字短得多,因此更容易处理。

图 4-2. 二进制、八进制和十六进制数表示法 一个二进制数可以通过将其位分组为三组来表示为八进制形式,或者通过使用四位的组来表示为十六进制。这些以 8 和 16 为基数的数字比二进制数字短得多,因此更容易处理。

十六进制数

八进制数曾经相当普遍,但现在不太受欢迎。八进制的问题在于它将比特分成三组,但二进制数的集合通常使用的比特数是 4 的倍数。

十六进制基 16计数系统是一种类似于八进制的方法,但它使用四组。由于每组有 4 个比特,每个可以有一个 16 个值。十六进制通常简称为hex

小贴士

关键概念 常规数字被称为十进制数,因为它们建立在数学的 10 进制系统之上。计算机使用由一个或零个比特组成的集合,称为二进制数,这些数字可以像常规数字一样处理,除了每个数字只能是 0 或 1 而不是 0 到 9。二进制数中的比特可以表示为八进制数,通过将三个比特组合成一个范围从 0 到 7 的八进制数字,或者使用四个比特的集合来创建一个从 0 到 15 的单个十六进制数字。为了使用单个字符表示十六进制数中的 10 到 15 的值,你使用字母 A 到 F。

注意

十六进制的术语并不是计算中首次用于基 16 数字的名字。最初,这些被称为sexadecimal数字。这实际上是正确的术语,因为拉丁前缀(sexa-)通常用于数字,而不是希腊前缀(hexa-)。然而,在 20 世纪 50 年代初,IBM 决定这个词sexadecimal对他们来说有点过于挑衅,所以他们将其改为hexadecimalIBM 作为 IBM——尤其是在当时——意味着其他人也跟着这样做*。

现在回到之前的例子:二进制的 11110100,十进制的 244。接下来,你将其分成四组,得到(1111)(0100)。二进制值 1111 是 15,0100 是 4,所以你有(15)(4)。你需要能够表示 15,但你只有十个数字。为了解决这个问题,十六进制中的 10、11、12、13、14 或 15 分别用字母 A、B、C、D、E 和 F 表示。所以二进制的 11110100 是(15)(4),或者十六进制的 F4(也显示在图 4-2)。

在某些方面,十六进制数甚至比二进制数更不直观(需要一些练习才能习惯将字母视为数字)。尽管如此,十六进制作为一种紧凑表示二进制信息的方法特别有用。在十进制数中,1,000,000 是二进制的 11110100001001000000,而在十六进制数中,它只是 F4240——甚至比十进制数更短,因为 16 比 10 大。此外,一个字节有 8 位,因此它只能用两个十六进制位来表示。这就是为什么十六进制数在计算和网络中被广泛使用。例如,你经常会看到十六进制数被用作网络地址或表示帧或数据包格式中的不同类型信息。

注意

如果你看到一个包含从 A 到 F 字母的数字,你知道它是一个十六进制数,但并非所有十六进制数都使用这些字母。十六进制数通常以特殊符号表示,以避免与十进制数混淆。这个符号可以是 0x 的前缀或 h 的后缀(有时两者都有)。因此,数字 54 就是 54,但 0x54 在十六进制数中表示 54,即 5 乘以 16 加 4,或者十进制数中的 84。务必注意这些表示方法

十进制、二进制、八进制和十六进制数转换

由于人和计算机使用不同的数字语言,通常需要将数字从一种系统转换为另一种系统。执行转换的最简单方法是使用科学计算器。然而,有些情况下你需要手动进行转换。

注意

如果你没有科学计算器,Windows 计算器程序是一个合理的替代品。打开它,转到视图菜单,将设置从标准更改为科学。点击旁边的数字系统按钮。然后输入一个数字,如果你点击旁边不同数字系统类型的按钮,数字会为你转换。UNIX 和 Mac OS 也有类似的工具

二进制、八进制和十六进制转换

在二进制、八进制和十六进制之间转换时,记住每个八进制位是三个二进制位,每个十六进制位是四个二进制位。进行转换时,分组数字,并将每个组转换为八进制或十六进制位。要从十六进制或八进制转换为二进制,将每个十六进制或八进制位转换为位集。表 4-3 显示了从每个八进制和十六进制单个值到二进制的转换(为了方便起见,还加入了十进制位)。

表 4-3. 二进制、八进制和十六进制位转换

二进制位 八进制位 十六进制位 十进制位
0000 0 0 0
0001 1 1 1
0010 2 2 2
0011 3 3 3
0100 4 4 4
0101 5 5 5
0110 6 6 6
0111 7 7 7
1000 - 8 8
1001 - 9 9
1010 - A -
1011 - B -
1100 - C -
1101 - D -
1110 - E -
1111 - F -

这里有一些例子:

二进制转八进制 从二进制数 110101001010 开始。将其分成三组:(110)(101)(001)(010),然后将每组转换为 0 到 7 之间的数字(如果你练习一下,这在大脑中做起来很容易)。结果是 (6)(5)(1)(2),或者 6512 八进制。

十六进制转二进制 从十六进制数 0x4D1B 开始。按照 表 4-3 中的说明转换每个数字。现在你有 0x4D1B = (0100)(1101)(0001)(1011),或者 0100110100011011。

从二进制、八进制或十六进制到十进制的转换

到和从十进制转换更复杂,因为 2、8 和 16 是 2 的幂,但 10 不是。在这两个方向中,到十进制的转换更容易:你取每个二进制、八进制或十六进制数字的值,将其转换为十进制,然后乘以数字位在数中代表的 2、8 或 16 的幂。然后将所有数字加在一起。我用十进制数 211 的例子做了这个(见 表 4-2)。

表 4-4 显示了十六进制数 0x830C 转换为十进制(八进制使用类似的过程)。从左到右,从上到下阅读表格;每个数字的值乘以适当的 16 的幂,然后相加,得到十进制结果 33,548。

表 4-4. 十六进制到十进制数转换

十六进制数 8 3 0 C
数字的十进制值 8 3 0 12
16 的幂 16³ 16² 16¹ 16⁰
数字位值 4096 256 16 1
此数字的值 8 x 4096 = 32768 3 x 256 = 768 0 x 16 = 0 12 x 1 = 12
从左到右的累积和 32768 32768+768 = 33536 33536 33536+12 = 33548

从十进制到二进制、八进制或十六进制的转换

从十进制转换需要你执行之前计算的相反操作:你进行除法和减法而不是乘法和加法。

从十进制到二进制的转换

从十进制到二进制的转换是最简单的三种转换之一。因为每个数字的最大值是 1,所以不需要除法,只需要减法。要执行转换,请执行以下操作:

  1. 找到小于该数的最大 2 的幂。

  2. 在那个 2 的幂的位上放一个 1,并从十进制数中减去那个 2 的幂。

  3. 重复步骤 1 和 2,直到你减到零。

使用示例和表格来解释会更简单。让我们将十进制数 689 转换,如表 4-5 所示。再次,从左上角开始阅读表格,然后向下再向右。你首先注意到 1024 不小于或等于 689,所以 1024 位得到一个 0。在下一个位置,512 小于 689,所以你将 512 位设为 1,并从 689 中减去 512,剩下 177。计算继续进行,最终显示 689 的十进制数是 1010110001 的二进制数。

表 4-5. 十进制到二进制数转换

考虑此数字位之前的十进制值 689 689 177 177 49 49 17 1 1 1 1
2 的幂 2¹⁰ 2⁹ 2⁸ 2⁷ 2⁶ 2⁵ 2⁴ 2⁰
数字位值 1024 512 256 128 64 32 16 8 4 2 1
数字位值是否小于或等于当前十进制数?
减法步骤 跳过 689 - 512 = 177 跳过 177 - 128 = 49 跳过 49 - 32 = 17 17 - 16 = 1 跳过 跳过 跳过 1 - 1 = 0
二进制数字 0 1 0 1 0 1 1 0 0 0 1

从十进制到八进制或十六进制的转换

八进制和十六进制的处理过程几乎相同,只是你必须除以 2 的幂,而不是像这里所示的那样只是减去。

  1. 从小于该数的最高次幂的 16(十六进制)或 8(八进制)开始。

  2. 将十进制数除以该幂,只保留结果的整数部分。

  3. 在除法完成后保留余数。

  4. 重复步骤 1 到 3,直到到达个位,然后输入高位数字完成后的剩余部分。

表 4-6 显示了与表 4-5 相同的示例,但它是从十进制到十六进制而不是从十进制到二进制:十进制中的 689 是十六进制的 0x2B1。

表 4-6. 十进制到十六进制数转换

考虑此数字位之前的十进制值 689 689 177 1
16 的幂 16³ 16² 16¹ 16⁰
数字位值 4096 256 16 1
数字位值小于当前十进制数? n/a
除法步骤 跳过 689/256 = 2.691(为此位使用 2) 177/16 = 11.0625(为此位使用 B) n/a
除法后的余数 跳过 177 1 n/a
十六进制数字 0 2 B 1

二进制、八进制和十六进制算术

我们每天都在使用算术来提供我们做出决策所需的信息。就像我们一样,计算机在正常操作中不断执行算术运算,只不过计算机使用二进制数来执行它们的计算,速度非常快。

二进制、八进制和十六进制数字本质上都是数字的不同表示形式,因此它们与十进制数字并没有太大的区别;它们只是每个数字位有不同的值。在类似的方式中,用二进制、八进制或十六进制数字进行算术运算与十进制数字的等效运算并没有太大的区别。你只需要记住,你正在处理 2、8 或 16 的幂,而不是 10,这并不总是那么容易。

与数字系统转换一样,如果你需要用二进制、八进制或十六进制数字进行数学运算,计算器通常是首选。如果你的计算器只能进行十进制数字的运算,你可以使用将数字转换为十进制,然后进行运算并将结果转换回来的技巧。然而,通过使用 Windows 计算器程序,你可以相当容易地在二进制、八进制或十六进制数字上进行相同的加法、减法、乘法和除法运算,就像你在十进制数字上做的那样。

计算机经常需要执行二进制数的乘法和除法运算,但与计算机打交道的人并不经常执行这些运算。加法和减法是更常见的运算(尤其是加法),而且它们还有一个额外的优点,就是更容易解释。你可能不会经常需要做这种类型的算术,但了解它是好的。我将提供几个例子来给你一个大致的概念。

二进制算术

让我们从二进制开始。加二进制数与加十进制数相同,只是由于每个数字位允许的值很少,你最终会进行很多 1 的进位。表 4-7 显示了一个例子,每列有一个数字;就像你通常手动加法那样,从右到左、从上到下读取它。你首先从第一个数的个位上的 1 加上第二个数那个位置的 1,从而得到一个原始的数字和为 2。这意味着个位的结果是 1,并且你将 1 进位到十位。你继续这个过程,直到你加完所有的数字。

表 4-7. 二进制加法

进位 1 1 1 1
第一个二进制数 1 0 1 1 0 0 1 1
第二个二进制数 0 0 1 1 1 0 0 1
原始数字和 1 1 3 2 1 1 2 2
结果 1 1 1 0 1 1 0 0
进位到下一个更高位数字 1 1 1 1

八进制和十六进制算术

八进制和十六进制基本上是相同的,只是当某个位上的和超过 8 或 16 时,你需要进位。十六进制更常见,也更有趣,所以让我们来看看如何加两个十六进制数。在执行运算时,你需要将单个十六进制数字转换为十进制,然后再转换回来,但这并不太难。

表 4-8 中所示示例应从右向左读取。你首先将个位上的 8(十进制 8)加到 A(十进制 10)上。这得到一个原始和 18,从中进位 16 作为 1 到 16 位,留下结果 2。你将这个 1 加到 16 位上的 D(值 13)和 E(值 14)上。这是总共 28,留下 12(十六进制的 C),并向 256 位进位 1。这个过程一直持续到只剩下和 6DC2h。

表 4-8. 十六进制加法

载入 1 1
第一个十六进制数 2 C D 8
第二个十六进制数 4 0 E A
原始数字和 2+4 = 6 1+12+0 = 13 1+13+14 = 28 8+10 = 18
结果 6 D C 2
向更高位进位 1 1

布尔逻辑和逻辑函数

你会记得,计算机系统中的每个位都可以存储 1 或 0 的值,这代表着二进制数字系统中固有的基本开或关状态,并且你可以将这些开或关值解释为真或假状态。这些值可以代表系统中的各种逻辑条件,你可以使用各种逻辑运算来操作和组合这些值以表示更复杂的逻辑状态。

英国数学家乔治·布尔(1815–1864)是逻辑方程中二进制值应用的先驱之一,为了表彰他的贡献,我们称之为布尔逻辑

布尔逻辑函数

布尔逻辑定义了多种布尔逻辑函数,有时也称为运算符。这些函数中的每一个都使用逻辑算法根据一个或多个输入的值来计算输出值。算法根据输入的真和假值的组合来确定输出何时为真。因此,显示逻辑函数输入和输出的表称为真值表。每个逻辑函数都与现实世界中的逻辑操作相对应,你可以使用这些操作来定义各种逻辑情况(你很快就会看到)。

NOT

考虑最简单的函数:NOT。正如你所预期的那样,这只是一个否定;输出是输入的反面。NOT 函数只接受一个输入,因此它被称为一元函数或运算符。NOT 的真值表显示在表 4-9 中。正如你所见,当输入为假时输出为真,反之亦然。

表 4-9. NOT 运算符真值表

输入 输出

NOT 函数逻辑上表示条件的反面。例如,假设你有一个名为 B1 的位,其逻辑意义是当位为真时,屏幕上的特定像素被点亮。那么布尔表达式 NOT B1 将是相反的:当像素被点亮时,它将是假的,因此只有当像素被点亮时才是真的。

由于在计算机中,真值和假值用 1 或 0 的值表示,布尔逻辑通常用一和零来表示,而不是用真和假。计算机处理器和其他设备内部的电路直接使用这些函数直接操作一位和零位。在某些(但不是所有)情况下,它们将一和零解释为真和假,但在任何情况下,两种表示在功能上是等效的。

表 4-10 显示与 表 4-9 相同的真值表,但使用位值。每个真值用 1 表示,每个假值用 0 表示。

表 4-10. NOT 运算符真值表(使用位值)

输入 输出
0 1
1 0

AND 和 OR

另外两个广泛使用的布尔函数是 ANDOR。AND 函数的输出仅在它的第一个、第二个、第三个输入等等都为真时才为真。OR 函数的输出在第一个输入为真 第二个输入为真,等等时为真。

AND 和 OR 都可以有任意数量的输入,但至少有两个。 表 4-11 显示 AND 函数的真值表,有两个输入。你可以看到,只有当两个输入都是 1 时,输出才是 1,否则是 0。

表 4-11. AND 运算符真值表

输入 1 输入 2 输出
0 0 0
0 1 0
1 0 0
1 1 1

与 NOT 类似,AND 表示的逻辑运算类似于我们在日常用语中如何使用单词 and。例如,在午餐时间,我可能会对同事说:“我们去外面吃午餐 停在邮局。”

OR 函数的真值表(再次是两个输入)显示在 表 4-12 中。在这里,只要至少有一个输入出现 1,输出就是 1,而不一定是像上一个表中的两个输入都出现 1。

表 4-12. OR 运算符真值表

输入 1 输入 2 输出
0 0 0
0 1 1
1 0 1
1 1 1

有趣的是,与 AND 不同,OR 函数的意义并不像我们在日常英语中所理解的 or 的意义。在布尔逻辑中,OR 意味着只要 任何 输入为真,输出就是真。

排他或 (XOR 或 EOR)

OR 的一种修改称为 独立或(简称为 XOREOR),它代表了我们在现实世界中通常使用 的方式。其输出只有在其中一个输入为真时才为真,但不是两者都为真。XOR 的真值表如表 4-13 所示。注意这个表与表 4-12 的区别:当两个输入都是 1 时,输出为 0。

表 4-13. 独立或(XOR)运算符真值表

输入 1 输入 2 输出
0 0 0
0 1 1
1 0 1
1 1 0

组合布尔表达式

之前描述的函数也可以任意组合,以产生更复杂的逻辑条件。例如,当在网络上搜索时,你可能会在搜索引擎中输入“cheese AND (cheddar OR swiss) NOT wisconsin”。作为回应,搜索引擎可能会返回包含单词 cheese 和单词 cheddarswiss(或两者)的页面,但不会返回包含单词 wisconsin 的页面。

布尔函数很重要,因为它们是计算机硬件中大部分电路的构建块。这些函数作为微小的 实现,设计目的是根据函数如非、与、或等真值表描述的输入组合,只允许电能流向输出。在网络中,布尔逻辑对于描述网络操作中的某些条件和函数非常重要。布尔函数也非常重要,因为它们用于设置、清除和掩码二进制数字串,我将在下一节中探讨这一点。

小贴士

关键概念 布尔逻辑 是一种使用布尔函数根据输入数据的各种条件产生输出的系统。最常见的布尔函数如下:,其输出是其输入的反义;,只有当所有输入都为真时才为真;,只要其输入中的任何一个为真就为真;以及异或,只有当其输入中恰好有一个为真时才为真(即,如果输入不同)。这些函数可以用于布尔逻辑表达式,以表示用于做出决策的条件状态,并且它们也可以用于位操作。

使用布尔逻辑函数进行位掩码(设置、清除和反转)

NOT、AND、OR 和 XOR 等布尔函数描述了逻辑表达式可以用来操作真值以表示简单和复杂决策或条件的不同方式。然而,这些函数也可以以更平凡的方式使用,以允许直接操作二进制数据。这种布尔逻辑的使用在网络中的许多不同应用中非常重要。

您应该记得,当您给一个位赋值时,您是“设置”该位,而当您给它赋值为 0 时,您是“重置”或“清除”它。在某些情况下,位是单独处理的,并且通过将 0 或 1 的值分配给每个位来简单地设置或清除。然而,当需要同时设置或清除多个位时,通常会有一组大型的位被共同使用来表示大量信息。在这种情况下,布尔函数就派上用场了。

使用 OR 设置位组

您可以使用 OR 函数批量设置位。回想一下,OR 的输出为真(等于 1),如果其任一输入为真(等于 1)。因此,如果您将一个位与已知为 1 的值进行 OR 操作,结果将始终为 1,无论其他值是什么。相比之下,如果您与 0 进行 OR 操作,原始值,1 或 0,将不会改变。

通过在特定位置使用包含 0 和 1 的字符串,您可以设置某些位为 1,同时保持其他位不变。这个过程类似于画家使用塑料或可能使用遮蔽胶带遮蔽他不想被涂色的区域。因此,这个过程被称为“遮蔽”。在操作中使用的数字字符串称为“位掩码”,或简称为“掩码”。

例如,假设您有一个 12 位的二进制输入数 101001011010,并且您想将中间六个位都设置为 1。为此,您需要将数字与 12 位的掩码 000111111000 进行 OR 操作。表 4-14 展示了如何通过在结果中加粗显示更改的位来实现这一点——您只需将输入中的每个位与其掩码中的对应位进行 OR 操作:

表 4-14. 使用 OR 位掩码设置位

输入 1 0 1 0 0 1 0 1 1 0 1 0
掩码 0 0 0 1 1 1 1 1 1 0 0 0
OR 操作的结果 1 0 1 1 1 1 1 1 1 0 1 0

使用 AND 清除位

要清除特定的位模式,您执行类似的遮蔽操作,但使用 AND 函数而不是 OR 函数。如果您将一个位与 0 进行 AND 操作,它将清除为 0,无论该位之前是什么值,而与 1 进行 AND 操作将保持位不变。例如,要清除 表 4-14 中的中间六个位,您需要与逆位掩码 111000000111 进行 AND 操作。

表 4-15 和 图 4-3 展示了如何使用位掩码清除二进制数中的某些位,同时保留其他位。每个 1 代表一个“透明”区域,保持相应的输入位值,而每个 0 代表原始值需要清除的位。在对每一对位执行 AND 操作后,前三位和最后三位被保留,而中间六位,由于它们各自与 0 进行 AND 操作,因此在输出中被强制设置为 0。

使用 AND 位掩码清除位

图 4-3. 使用 AND 位掩码清除位 应用位掩码到输入二进制数,使用 AND 函数将掩码位为 0 的所有位清除为 0,而保留掩码位为 1 的位。

表 4-15. 使用 AND 位掩码清除位

输入 1 0 1 0 0 1 0 1 1 0 1 0
掩码 1 1 1 0 0 0 0 0 0 1 1 1
AND 操作结果 1 0 1 0 0 0 0 0 0 0 1 0

你也可以从不同的角度看待这个清除功能。你正在清除掩码为 0 的位,并在这样做的同时选择掩码为 1 的位。因此,与位掩码进行 AND 操作本质上意味着你保留掩码为 1 的位,并移除掩码为 0 的位。

使用 XOR 反转位

也有情况下你想反转一些位;也就是说,将 1 值改为 0,或将 0 值改为 1。为此,你使用 XOR 函数。虽然这不如掩码直观,但如果你参考 XOR 真值表(表 4-13 运算符真值表")),你会看到,如果你与 1 进行 XOR 操作,输入值会被翻转,而与 0 进行 XOR 操作会导致输入保持不变。要了解这是如何工作的,请使用相同的输入示例并反转中间六位,如表 4-16 所示。

表 4-16. 使用 XOR 位掩码反转位

输入 1 0 1 0 0 1 0 1 1 0 1 0
掩码 0 0 0 1 1 1 1 1 1 0 0 0
XOR 操作结果 1 0 1 1 1 0 1 0 0 0 1 0

在网络世界中,位掩码最常用于操作地址。特别是,掩码最著名的用途是在区分互联网协议(IP)地址的主机部分和子网(subnet)部分之间,这个过程称为 子网掩码(参见第十八章(Chapter 18 CONCEPTS")),其中讨论了 IP 子网地址划分))。

注意

掩码通常以十六进制或十进制表示法表示,以简化表示,如第十八章(Chapter 18 CONCEPTS"))中的 IP 子网划分摘要表所示。然而,掩码始终以二进制方式应用,如前所述。如果您想确切地看到掩码操作将如何工作,应将掩码转换为二进制

小贴士

关键概念 ORAND 布尔函数的特性使它们在需要设置(改变为 1)或清除(改变为 0)数据项的某些位时非常有用。这个过程称为 位掩码。要设置位为 1,创建一个掩码并将其与输入进行位位 OR 操作。当掩码的值为 1 时,位被强制设置为 1,而每个 0 位则保持相应的原始位不变。同样,与 AND 函数一起使用的掩码会清除某些位;掩码中的每个 1 位保持原始位不变,而每个 0 位则将输出强制设置为 0。最后,XOR 可以使用掩码来反转选定的位。

第一部分-2. 开放系统互联(OSI)参考模型

第五章

第六章

第七章

模型是有用的,因为它们帮助我们理解复杂的概念和系统。当涉及到网络时,有几个模型被用来解释各种技术所扮演的角色以及它们是如何相互作用的。在这些模型中,最流行和最常用的就是开放系统互联(OSI)参考模型。OSI 参考模型通过允许网络被视为以可预测的方式相互作用的模块化组件,而不是庞大的、复杂的单体,使得网络的分析、设计、构建和重新排列变得更加容易。

你会发现,在阅读大量关于网络的内容时,几乎不可能不遇到一些讨论,这些讨论假设至少对 OSI 参考模型的工作方式有一些了解。这就是为什么我强烈建议,如果你是 OSI 参考模型的新手,你应该仔细阅读这部分内容。虽然这所有内容都可以说是背景材料,但这些信息将为你理解网络打下基础,并使本书的其余部分更容易理解。如果你对 OSI 参考模型非常熟悉,你可能希望跳过这部分内容或只是快速浏览一下。

本部分旨在讨论网络和互联网的一般性,而不是专门针对 TCP/IP 协议套件。因此,本节中并非所有材料都与学习 TCP/IP 直接相关,尽管其中很多是。你也可以参考第一部分-3,其中讨论了 TCP/IP 和 OSI 模型之间的比较。

在这部分,我详细描述了 OSI 参考模型。我首先讨论了一些与 OSI 参考模型和网络模型总体相关的一般概念。然后,我描述了 OSI 参考模型的七个层次。最后,我通过一个有用的类比来总结,帮助你理解参考模型是如何在多个层面上解释网络交互的。那一章还提供了一个层次及其相应功能的参考表。

第五章. 一般 OSI 参考模型问题和概念

无标题图片

OSI 参考模型背后的理念是为设计网络系统和解释它们的工作提供框架。当你阅读有关网络的内容时,你经常会发现对 OSI 参考模型的各个级别或层次的引用。然而,在我能够正确讨论实际的 OSI 模型层次之前,你需要理解整个模型。

在本章中,我介绍了 OSI 参考模型,并提供了一些有用的背景信息,以帮助您理解它。我首先简要回顾了该模型的历史,包括其发展和目标。然后,我以一般术语介绍了网络模型,描述了它们的好处以及如何最好地使用它们。本章的大部分内容包含重要的 OSI 模型概念,这将帮助您真正理解模型的工作方式,描述它的术语以及它如何有助于解释网络技术的操作。

OSI 参考模型的历史

查看 OSI 参考模型的起源,将我们带回到第三章中讨论的与标准和标准组织相关的几个问题。创建网络标准的理念是为了定义广泛接受的设置网络和连接网络的方式。OSI 参考模型代表了早期尝试让所有各种硬件和软件制造商就开发各种网络技术框架达成一致的努力。

在 20 世纪 70 年代末,两个项目独立开始,目标相同:为网络系统的架构定义一个统一的标准。一个是国际标准化组织(ISO)管理的,另一个是由国际电报电话咨询委员会(CCITT)或简称CCITT(该缩写来自法语名称)承担的。这两个国际标准机构各自开发了一份定义类似网络模型的文件。

到 1983 年,这两份文件合并形成了一个名为开放系统互连基本参考模型的标准。这个名字听起来很复杂,所以这个标准通常被称为开放系统互连参考模型OSI 参考模型,甚至简称为OSI 模型。它于 1984 年由 ISO 作为 ISO 7498 标准以及更名为 CCITT(现在称为国际电信联盟的电信标准化部门ITU-T)作为 X.200 标准发布。(顺便说一句,CCITT 的新名字不是比旧名字有趣得多吗?听起来是不是顺耳多了?)

OSI 参考模型的历史中一个有趣的方面是,其原始目标并不是为了创建一个主要用于教育目的的模型,尽管今天许多人认为这是事实。它的目的是作为建立一个广泛采用的协议套件的基石,这些协议将被国际互联网使用——基本上,这就是互联网成为的样子。这被称为 OSI 协议套件,毫不奇怪。

然而,事情并没有按计划进行。互联网的普及及其 TCP/IP 协议与 OSI 协议套件正面相遇,简而言之,TCP/IP 取得了胜利。一些 OSI 协议得到了实施,但当互联网开始增长时,OSI 协议整体上输给了 TCP/IP。

然而,OSI 模型本身找到了一个家,作为一个解释不仅 OSI 协议,而且网络总体运作的设备。它被广泛用作教育工具——就像我本人使用它一样——并且也被用来帮助描述其他协议套件组件和甚至硬件设备之间的交互。尽管大多数技术并非专门为满足 OSI 模型的要求而设计,但许多都是根据它们如何适应其层级来描述的。这包括网络协议、软件应用,甚至不同类型的硬件设备,如交换机和路由器。该模型对开发软件和硬件产品的那些人也非常有用,因为它阐明了网络系统中每个组件所执行的角色。

小贴士

关键概念 开放系统互联参考模型OSI 参考模型OSI 模型)最初被创建作为设计一套通用协议的基础,这套协议被称为OSI 协议套件。这个套件从未取得广泛的成功,但该模型成为了一个非常有用的工具,既适用于教育,也适用于开发。该模型定义了一系列层级及其使用概念,使得理解网络变得更加容易。

一般参考模型问题

让我们讨论一些与参考模型相关的基本问题。部分原因是我想要解释为什么我对 OSI 模型如此重视,甚至将本书的大部分组织结构都围绕这个模型及其层级构建。我还希望您理解这个模型的重要性,以及它在现实中对网络的好处。

在接下来的主题中,我以一般性的方式描述了与参考模型相关的一些问题,当然,特别是与 OSI 参考模型相关。我首先概述了为什么网络模型是有益的,以及为什么了解 OSI 模型的工作原理对您来说很重要。然后,我讨论了如何最好地使用该模型,并将其与一些“现实世界”的网络架构和协议栈进行对比。

网络模型的好处

网络很复杂,必须特别努力来尝试简化它。网络技术变得更容易理解的一种方式是将它分解成各个部分,每个部分都扮演特定的角色或负责特定的任务或功能。

然而,如果要做这件事,你必须有一种确保这些不同部分可以互操作的方法;也就是说,每个部分都必须知道对其的期望以及它可以从其他部分期望什么。这是网络模型的一个重要角色。它们将实现现代网络所需的大量任务分解为更小的块,这些块可以更容易地管理。同样重要的是,它们在这些部分之间建立“墙壁”以及跨越这些墙壁传递信息的规则。

一个网络模型的良好类比是制造商的装配线。没有公司试图让一个人构建一辆完整的汽车;即使公司这样做,也不会期望这个人能够一次性学会如何完成所有工作。劳动分工为构建复杂产品(如汽车)的公司提供了几个优势。一般来说,这些包括以下内容:

培训和文档 通过将构建复杂系统的过程分解为更小的部分,解释如何构建系统会更容易。可以为特定的工作进行培训,而不需要每个人都了解其他所有工作的运作方式。

专业化 如果每个人都负责做每一项工作,没有人会积累足够经验成为任何领域的专家。通过专业化,某些个人会在特定工作中发展出专业知识。

更易进行设计和改进 通过将汽车分解为系统以及构建这些系统所需的特定工作,你可以在未来更容易地进行更改。如果没有这样的划分,确定更改可能产生的影响将会非常困难,这会抑制创新。

模块化 这与前面提到的每一项都有关。如果汽车的系统和生产步骤根据合理的架构或模型分解,那么在车辆之间交换零件和程序就会变得更容易。这节省了时间和金钱。

网络模型为网络世界带来了非常相似的好处。它们代表了一个框架,通过将工作分割为不同的级别或来划分实现网络所需的任务。运行在每个层上的硬件和软件负责与其他设备上运行的同层硬件和软件进行交互。每个硬件或软件元素的责任部分是通过在层之间划分特定的界限来定义的。

因此,你将获得前面列出的所有好处:更容易的培训、每一层的专用功能、改进的修改能力以及模块化。模块化尤其重要,因为它允许你交换在不同层运行的技术。虽然没有人会尝试建造一辆部分是紧凑型轿车、部分是 SUV、部分是摩托车的车辆,但在网络中,你可能想要做类似的事情。网络模型有助于实现这一点。

小贴士

关键概念 网络模型,如OSI 参考模型,提供了一个框架,将复杂的互连网络分解为更容易理解和利用的组件。该模型将网络功能定义为不是一个大而复杂的整体,而是一组分层、模块化的组件,每个组件负责特定的功能。结果是更好地理解网络操作、提高性能和功能、更容易的设计和开发,以及以最适合网络需求的方式组合不同组件的能力。

为什么理解 OSI 参考模型对你很重要

许多网络书籍和其他资源都忽略了 OSI 参考模型,或者将其放在难以找到的附录的最后一页。通常给出的原因是 OSI 模型“过于理论化”并且“不适用于现代网络协议如 TCP/IP”。

这是一个错误的观念。虽然确实如此,OSI 模型主要是理论性的,而且网络协议并不总是严格地设计在它们的层内,但 OSI 模型对现实世界的适用性很小这一说法是不正确的。事实上,现在很难阅读关于网络技术的文章而不看到对 OSI 模型及其层的引用,因为该模型的结构有助于构建对协议的讨论和对比各种技术。

例如,OSI 参考模型为理解像以太网和 HomePNA 这样的技术如何相似提供了基础;它解释了 PC 如何使用几组不同的协议进行通信,甚至可以同时使用;它是理解诸如中继器、集线器、网桥、交换机和路由器等互连设备之间差异的重要组成部分;它还解释了许多广域网技术如何互操作。

OSI 模型层远非过时,现在在技术讨论中出现的频率比以往任何时候都要高。事实上,一些协议甚至被特别命名,以反映它们在 OSI 参考模型中的位置!例如,考虑第二层隧道协议。此外,交换机现在通常被分类为第 2 层、第 3 层,甚至更高层的交换机。

在理论讨论中,OSI 参考模型帮助你理解网络和网络协议在现实世界中的运作方式。它还帮助你确定哪些协议和设备可以相互交互。因此,我鼓励你继续阅读。这是值得花费的时间。

小贴士

关键概念 当许多人嘲笑研究 OSI 参考模型这一概念时,理解它对于理解网络协议和技术非常有帮助。该模型是理论性的,但其概念经常被用来描述现实世界中网络的运作。

如何使用 OSI 参考模型

尽管有些人过分贬低 OSI 模型,但其他人则走向另一个极端。他们过度使用它,过度分析,并试图以从未打算的方式使用它。

最常见的错误是在尝试将“一切”都“适应”到 OSI 模型的分层结构中时犯下的。我必须承认,有时我也会陷入这个陷阱。当我最初开始安排这本书的结构时,我希望根据 OSI 模型层的位置来组织所有内容。我很快发现,这就像试图将各种形状的钉子放入只有圆形孔的板上。我不得不改变我的方法。最终,我根据它对 OSI 层的合理性来组织,在不合理的地方则采用不同的结构。

从我的经验中学习。一个简单的经验法则是这样的:如果参考 OSI 参考模型能帮助你理解技术及其工作原理,那么就使用它;如果它使事情变得更复杂,那么就不要使用它。特别是,请记住以下几点:

  • 确定某些技术在该模型中的位置可能非常困难。许多协议在设计时并未考虑 OSI 模型,它们可能无法整齐地归入某一层。有些协议可能跨越两层或多层;其他协议集可能有两个协议共享同一层。

  • 上层(会话、表示和应用)之间的界限尤其模糊。有些协议显然是为适应这些层之一而设计的,而其他协议可能重叠所有三个层。这也是为什么我不按层对高级协议进行分类的原因之一。(OSI 参考模型是为了解释区分这些层可能没有意义而设计的。)

  • OSI 参考模型主要是为了考虑局域网(LANs)而设计的。广域网(WAN)技术往往很难适应该模型,存在大量重叠和部分层覆盖。然而,在大多数情况下,从 OSI 模型的大致适应角度来考虑这些协议仍然是有用的,因为 WAN 技术的某些部分有时可以互换。

  • 设计产品的人们通常不会担心确保他们的最新发明只实现模型的具体层级。因此,有时新产品会违反规则,在多个层级上实现功能,这在以前是由多个设备在各个层级上完成的。这通常被视为进步——一件好事!

最后,一个观察:我注意到学习网络知识的人——尤其是那些试图记住简单答案以应对难题以便通过考试的人——经常问:“这块硬件在哪个层级运行?”这里的问题不在于答案,而在于问题本身过于简单。除了简单的物理设备,如连接器和电缆之外,几乎所有网络设备都在多个层级上运行。例如,虽然路由器通常与第 3 层相关联,但它有两个或更多设备接口,实现了第 2 层和第 1 层。一个更好的问题是,设备在哪个最高层级上运行?

重要的是要记住,OSI 参考模型是一个工具。如果你明智地使用它,它可以对你非常有帮助。只需记住不要在应用它时过于僵化,你就会没事的。

小贴士

关键概念 过分重视 OSI 参考模型和过分轻视模型一样都是错误。虽然该模型定义了理解网络的一个框架,但并非所有网络组件、协议和技术都必然符合模型严格的分层架构。有些情况下,试图使用该模型来描述某些概念可能会导致理解更加模糊,而不是更加清晰。你应该记住,OSI 模型是一个工具,应该相应地使用。

其他网络架构和协议栈

OSI 参考模型不是唯一用于描述网络结构的模型;还有其他几个模型和系统被用来描述各种协同工作的网络技术集合。这些通常不是描述理论模型,而是实际网络中积极使用的协议分组。因此,它们更常被称为网络架构协议套件,而不是模型。

正如你所看到的,许多技术和协议并不很好地适应 OSI 模型中使用的特定层级。同样,在现实世界中使用的多数协议套件也不完全符合 OSI 模型。当然,这是因为它们是在独立于 OSI 模型的情况下开发的。尽管如此,这些架构和套件仍然使用层级——只是与 OSI 模型使用的层级不同。

由于 OSI 模型经常被引用,它对于理解其他架构甚至比较它们非常有帮助。无论各个层和技术被称为什么,网络协议套件都试图在实现网络时达到相同的目标。因此,尽管层不相同,但它们通常是可以比较的。

在 TCP/IP 的情况下,通常在讨论套件时使用一个特殊的模型,称为国防部(DoD)模型或 TCP/IP 模型(参见第八章[Chapter 8. TCP/IP PROTOCOL SUITE AND ARCHITECTURE])。这个模型与 OSI 模型有许多相似之处,但也有一些重要的区别。在网络领域的其他领域,还使用其他模型,例如 IEEE 802 网络架构模型。这些模型在某些方面与 OSI 模型相似,但它们也有自己独特的特点。

即使在某些特定技术的范围内,你也能看到相关协议的分层结构。有些技术通常被认为实现了 OSI 模型的一个级别,尽管它们实际上有部分重叠多个 OSI 层;例如,以太网和异步传输模式(ATM)。事实上,一些协议甚至有子协议,这些子协议在 OSI 认为的单个层内分层。一个很好的例子是 TCP/IP 点对点协议(PPP),尽管名称如此,但它不是一个单独的协议,而是一个自身就是协议套件的协议(参见[Part II-1. TCP/IP 网络接口层协议]Part II-1)。

OSI 参考模型的关键概念

OSI 参考模型作为解释网络如何工作以及描述不同网络技术和协议之间关系的工具非常有价值。为了实现这一目标,模型依赖于许多重要的概念和术语,我将在以下章节中进行讨论。

我将从讨论模型如何使用层开始。这可能是所有模型概念中最重要的一个。然后,我将谈论一些你可能在模型的一般讨论中看到的符号和术语。我在模型背景下更详细地定义了接口协议的含义。接着,我解释了数据封装的重要概念以及用于指代 OSI 参考模型中消息的术语:协议数据单元(PDUs)和服务数据单元(SDUs)。最后,我通过描述各个层如何从理论上处理消息的路由来连接前面讨论的大部分问题。

OSI 参考模型网络层、子层和层分组

OSI 参考模型最重要的概念是网络的概念。说层实际上是 OSI 模型的核心并不过分——整个模型的目的就是将网络分离成不同级别上操作的独立功能。每一层都负责执行特定的任务或一系列任务,并处理其上下的层。

OSI 参考模型由七个概念层组成,每个层都被分配了一个从 1 到 7 的数字。层号代表层在整个模型中的位置,并表明层与实现网络的实际硬件的接近程度。第一层也是最低层是物理层,这是低级信号和硬件实现的地方。第七层也是最高层是应用层,它处理用户使用的高级应用:既包括最终用户也包括操作系统软件。

你可以看到,当你从第一层移动到第七层时,你是在向上移动层堆栈,并且在这个过程中,你的抽象级别在增加。这意味着层堆栈中层的级别越高,它就越处理逻辑概念和软件,而越少处理网络的硬件以及使其工作的细节。第一层是最具体的,因为它处理网络的实际硬件以及将比特从一台设备发送到另一台设备的特定方法。这是硬件工程师和信号专家的领域。第二层稍微抽象一些,但仍然处理信号和硬件。当你通过第三、第四和随后的层时,那些层的科技变得越来越抽象。当你到达第七层时,你不再处理硬件甚至操作系统概念,你处于用户和依赖较低级别来完成“重活”的高级程序的领域。

OSI 参考模型并没有正式地将相邻层之间的关系分配给任何组。然而,为了帮助解释层是如何工作的,通常将它们分为两种层分组

底层(第 1 层、第 2 层、第 3 层和第 4 层) 如图 5-1 所示,模型的底层——物理层、数据链路层、网络层传输层——主要关注在网络中数据的格式化、编码和传输。它们并不太关心数据是什么或者它被用于什么目的;相反,它们只想知道如何移动数据。这些层既可以用硬件实现,也可以用软件实现,从第 1 层到第 4 层的过渡是从硬件到软件的。

上层(第 5 层、第 6 层和第 7 层) 模型的上层——会话层、表示层应用层——主要关注与用户的交互以及实现通过网络运行的应用程序。在较高层运行的协议对数据如何从一个地方发送到另一个地方的低级细节不太关心;它们依赖于底层来传递数据。这些层几乎总是作为在计算机或其他硬件设备上运行的软件来实现。

有些人可能不会完全同意我对图 5-1 中层次划分的选择。特别是,可以提出合理的论点来支持将传输层包含在上层分组中,因为它通常作为软件实现并且相当抽象。我将其放在底层分组中,因为它的主要任务仍然是为上层提供数据传输的服务。实际上,第 4 层可以看作是一个过渡区域,很难归类。图 5-1 显示了第 4 层在堆栈中的特殊位置。

提示

关键概念 OSI 参考模型中最基本的概念是将网络功能划分为一组,从底部的第 1 层到顶部的第 7 层。随着你向上移动层堆栈,你将远离具体的、硬件特定的功能,转向越来越抽象的功能,直到你达到第 7 层的用户应用领域。这七层有时被分为分组:底层(1 到 3 层)和高层(4 到 7 层)。关于第 4 层是底层还是高层,存在一些争议。

OSI 参考模型层 OSI 参考模型将网络功能划分为一个由七层组成的堆栈,从底部向上编号为 1 到 7,有时分为两层分组——底层和高层。

图 5-1. OSI 参考模型层 OSI 参考模型将网络功能划分为一个由七层组成的堆栈,从底部向上编号为 1 到 7,有时分为两层分组——底层和高层。

此外,还有一些 OSI 层之间存在着自然的关系。特别是物理层和数据链路层,它们之间关系密切。例如,大多数人将以太网视为第 2 层技术,但以太网规范实际上处理了第 2 层和第 1 层。同样,第 3 层和第 4 层也经常相关;协议套件通常设计得使得第 3 层和第 4 层协议可以协同工作。TCP/IP 协议套件中的 TCP 和 IP,以及 Novell 套件中的 IPX 和 SPX 是很好的例子。

在某些领域,层与层之间的关系非常紧密,以至于它们之间的界限变得模糊不清。这尤其是在观察更高层时更为明显;许多技术实现了两层甚至三层这些层,这也是我认为它们最好被归为一组的原因之一。5 到 7 层之间的界限之所以模糊不清,一个重要原因是 TCP/IP 协议是基于 TCP/IP 模型(在第八章中介绍,第八章),该模型将 5 到 7 层的功能合并为一个单一、厚重的层。

小贴士

关键概念 OSI 模型的四层以下通常被单独讨论,因为它们之间的界限相对清晰。相比之下,会话层、表示层和应用层之间的界限则有些模糊。因此,有时协议跨越两层甚至所有这三层;这在 TCP/IP 应用协议中尤为如此,因为 TCP/IP 模型将 5 到 7 层视为一个单一的层。

最后,请注意,某些 OSI 参考模型层被进一步划分为子层,以更精确地定义这些层中协议和技术内部细节。这通常在底层进行,尤其是在物理层和数据链路层。

“N”表示法和其他 OSI 模型层术语

作为一种理论模型,OSI 参考模型附带了一套术语,用于描述它及其组成部分。这既是好消息也是坏消息。好消息是,如果你理解这些术语,它可以帮助你理解技术如何与模型相关,以及大多数关于 OSI 模型的讨论。坏消息是,这些术语也可能增加混淆——尤其是在它们并不总是被一致使用的情况下。

这里有一些术语概念,你经常会看到它们被用来指代 OSI 参考模型:

层名称和编号 OSI 参考模型的各个层可以用多种方式来指代。它们的名字可能被完整拼写,也可能被缩写。它们也经常简单地通过层编号来引用。例如,所有这些都指代同一事物:数据链路层,数据链路层,DLL,L2,第二层,和层 2。同样,你经常会看到层名称被用作形容词来描述协议和技术。例如,层 3 技术主要在网络层操作。

N 表示法 字母N常被用来泛指计算机世界中的数字。就 OSI 模型而言,在讨论与单个层相关的通用内容而不提及特定层时,经常看到这个字母被使用。你会听到像N-功能N-服务这样的术语,它们只是指特定层内提供的功能和服务的简称。作为另一个例子,你可能会听到有人说某种特定的技术“为 N+1 层提供了一种有用的服务。”这仅仅意味着它为其操作的层之上的层提供了一个功能。从概念上讲,除了第一层和第七层之外,每个层都有一个 N-1 层,一个 N+1 层,依此类推。如果你正在查看网络层(层 3),那么 N+2 层就是会话层(层 5)。

协议和接口 这些词在 OSI 模型中具有特殊含义。一个协议代表模型同一层中逻辑或物理设备之间的通信。一个接口代表同一设备相邻层之间的信息移动。因此,在 N 表示法中,协议代表一个设备上的层 N 与另一个设备上的层 N 之间的通信,而接口处理同一设备上层 N 与 N+1 或层 N 与 N-1 之间的通信。

网络栈 当你把许多层堆叠在一起时,你会得到一个。这个术语用来指代模型或技术套件中的整个层集,或者部分层集。由于每个层都与协议相关联,这有时也被称为协议栈

实体、功能、设施和服务 这些术语经常互换使用,有些模糊,它们指的是在模型中各个层执行的具体任务或工作。N 实体是一个指代在层 N 执行的特定操作或工作的术语。功能基本上是同一件事。设施服务是层为其上层提供的内容。这通常也用 N-notation 表示:N+1 层通常使用由 N 层提供的 N 组服务或 N 设施。

图 5-2 通过展示 OSI 模型层之间的关系以及在任何特定层上下文中用于指代相邻层的术语,总结了之前的信息。每一层(除了第 7 层)都为其上层提供服务;每一层(除了第 1 层)都使用其下层提供的服务。另一种说法是,每一层 N 为层 N+1 提供服务,并使用层 N-1 的服务。以第 3 层,即网络层为例,你可以看到它为第 4 层提供服务,并使用第 2 层的服务。从网络层的角度来看,传输层是层 N+1,数据链路层是 N-1。

OSI 参考模型层之间的关系和术语 每一层都与它上面的和下面的层有关联;在这里,如果网络层是层 N,它为传输层(层 N+1)提供服务,并使用数据链路层(层 N-1)的服务。

图 5-2. OSI 参考模型层之间的关系和术语 每一层都与它上面的和下面的层有关联;在这里,如果网络层是层 N,它为传输层(层 N+1)提供服务,并使用数据链路层(层 N-1)的服务。

你可能刚刚读完了所有这些内容,然后对自己说:“他们为什么要使这一切如此复杂?”这是个好问题。记住,我确实说过这里有个坏消息!现在你知道了所有这些内容,如果你遇到它,你不会感到困惑。

幸运的是,之前使用的热门词汇的使用范围有限。大多数参考文献都是针对特定的层名称或数字,特别是 N-1 和 N+1 的内容在现实技术的讨论中很少使用。然而,在解释模型本身时,这可以非常有用,正如你在阅读本章其余部分时将看到的一些术语一样。

接口:垂直(相邻层)通信

OSI 参考模型的七层被用来划分实现网络系统所需的各种功能。在任何网络设备上,不同的软件和硬件例程和设备可能同时在这些层的任何一层或所有层上运行。因为,一般来说,所有这些都应该共同工作来实现网络功能,所以在特定主机内的层之间进行垂直通信是必要的。

在 OSI 参考模型术语中,模型中相邻层之间通信的机制被称为“接口”。当然,“接口”一词在计算机和网络世界的其他环境中也被广泛使用,因为它的通用含义是指连接几乎所有“任何东西”。然而,当某人谈论 OSI 模型层之间的接口时,那个人通常指的是数据在模型层 N 和层 N-1 或层 N+1 之间传递的过程。这些关系在图 5-3 中得到了展示。例如,“层 2/3 接口”被层 2 和层 3 协议用来传递数据和控制信息;“层 3/4 接口”将层 3 和层 4 连接在一起。

垂直通信的 OSI 参考模型接口 在 OSI 模型术语中,接口是层堆栈中相邻层之间通信的通道。

图 5-3. 垂直通信的 OSI 参考模型接口 在 OSI 模型术语中,接口是层堆栈中相邻层之间通信的通道。

注意

请记住,并非所有层都可能在现实世界的每个系统或协议堆栈中得到实现。因此,一个在技术上运行在层 7 的进程可能与运行在层 5 的进程进行通信。然而,我这里讨论的是理论模型

每当在网络上发送任何东西时,都会在协议堆栈的上下方向进行垂直通信,当然,在接收任何东西时也是如此。这是因为高层被实现为软件中的逻辑功能;没有实际的物理连接。高层将数据打包并发送到低层,以便在网络中发送。在最低层,数据通过网络发送。在接收端,过程相反,数据从接收设备的高层向上传输。我稍后会讨论这种对应层之间的逻辑交互。

OSI 参考模型的一个主要目标是允许不同层实现之间的互连。因此,意图是有一定自主权的单个层,你可以混合搭配——到一定程度。使这一切得以工作的唯一方法是定义层之间连接的明确方式,这又让我回到了接口的问题。每一层必须向其上层的层提供一个一致、良好记录的接口,以便任何上层实现都能正确使用下层。

我将从 TCP/IP 世界的例子中提供一个例子来说明我的意思。TCP/IP 协议套件的核心是互联网协议(IP)。无论你使用互联网上的任何应用程序——电子邮件、网站、FTP、聊天室等等——你都是在间接使用 IP。

然而,你通常不会直接使用 IP——你一般会使用两种传输层(层 4)协议之一:传输控制协议(TCP)或用户数据报协议(UDP)(见第二部分-8). 在 TCP/IP 协议栈中,网络层和传输层之间存在一个标准接口,它定义了上层协议如何使用 IP;这使得 TCP 和 UDP 能够与之接口。同样,TCP 和 UDP 也向使用它们的数百个高层协议和应用提供了特定的接口。

实际上,层之间发生着多种不同类型的通信。控制信息被传递,以便使高层能够利用低层,并使低层能够将状态和结果信息传递回高层。数据也在接口的两侧传递。在传输过程中,它流向低层,这通常会导致数据封装。在接收过程中,过程相反,数据从低层向上层通过接口发送回来。

小贴士

关键概念 在 OSI 参考模型中,接口定义了相邻层之间垂直通信的机制。层之间存在良好定义的接口是允许高层使用任何较低层的服务,而不需要了解这些层是如何实现的。

协议:水平(对应层)通信

OSI 参考模型中的每一层都有特定的角色(或角色)——一组它负责的一般任务。在网络的每个系统上,硬件和软件都在模型的许多不同级别上运行。在机器 A 上执行特定任务的例程被设计成与在机器 B 上运行的类似或互补的例程进行通信。这种水平通信正是网络的核心所在。它是使网络浏览器和 Web 服务器能够交谈、电子邮件应用能够交换消息以及更多内容得以实现的原因。

当然,所有通信类型只有在每个人都同意使用相同的方法来完成它时才能正常工作。描述一种通信类型的每一组规则都称为“协议”。你可以把协议想象成一种语言或一组指令。网络中的每个功能或服务都有自己的语言;就像人类语言一样,有些彼此相似,而有些则非常独特。

如果你阅读过任何关于网络的内容,你可能已经多次看到“协议”这个术语。像“接口”这个词一样,“协议”这个词可以有多个含义。实际上,它对网络来说如此基础,并且以多种不同的方式使用,以至于我在第一章中专门讨论了它。

不论其他情况如何,你必须记住,OSI 参考模型旨在成为一种描述网络的正式方式。因此,在模型中,“协议”这个术语有一个正式的含义。它具体指的是一组通信规则、指令和程序,这些规则、指令和程序描述了在网络中不同机器上运行于同一层级的特定软件或硬件元素之间的通信。

让我们考虑这些对应层如何使用协议进行通信。首先,你会记得,模型中的每一层(除了底层的物理层)实际上是在计算机上运行的程序或算法。例如,一个网页浏览器和一个网页服务器无法直接连接在一起——毕竟,它们只是软件程序。相反,运行在不同层上的软件通过逻辑方式通信。也就是说,通过使用软件和程序,一个机器上第 5 层的进程可以与另一个机器上第 5 层的类似进程进行逻辑通信。

由于机器只在第 1 层进行物理连接,发送机器上的数据必须通过第 5 层和第 1 层之间的层传递,以便第 5 层的协议能够工作。然后,数据通过物理连接传输到另一台机器的第 1 层,并在接收机器的协议堆栈中向上传递到第 5 层。这就是这两台机器在第 5 层逻辑连接的方式,尽管在那个层它们没有物理连接。

因此,除了第 1 层的实际物理连接外,所有横向通信也都需要纵向通信——在一个机器上的堆栈向下,然后在另一个机器上的堆栈向上。(然而,并非每个连接都需要完全回溯到堆栈顶部,例如在“间接设备连接和信息路由”部分讨论的路由情况。这部分内容位于本章末尾。)

图 5-4 展示了水平通信的工作原理。例如,IP 被认为是一个第 3 层协议,因为每个设备都使用 IP 软件在第 3 层进行通信。实际的数据传输和接收仅发生在最低的物理层;高层协议通过向下通过接口传递数据,直到达到第 1 层,在第 1 层进行传输,然后将数据传回接收设备相应层的适当层,以逻辑方式通信。

OSI 参考模型协议:水平通信 术语协议有许多含义;在 OSI 参考模型中,它特指实现两个或更多设备上对应层之间通信的软件或硬件元素。

图 5-4. OSI 参考模型协议:水平通信 术语协议有许多含义;在 OSI 参考模型中,它特指实现两个或更多设备上对应层之间通信的软件或硬件元素。

提示

关键概念 在 OSI 参考模型中,协议特指定义网络设备上同一层运行的软件或硬件元素之间通信的一组规则或程序。物理层协议负责在第 1 层实际传输和接收数据。高层协议将数据向下传递到它们下面的层,直到第 1 层进行传输,然后穿过网络,并返回到接收设备同一层的相应实体。结果是,在两个设备中的每个设备上运行的软件过程,例如在第 4 层,可以像它们在第 4 层直接连接一样进行逻辑通信,尽管它们并没有直接连接。

数据封装、协议数据单元(PDUs)和服务数据单元(SDUs)

协议描述了控制水平通信的规则,即运行在 OSI 参考模型中对应层内的进程之间的对话。在每一层(除了第 1 层之外),这些通信最终都采取某种形式的消息,这种消息是在两个或更多设备上对应软件元素之间发送的。由于这些消息是协议之间传递信息的机制,它们通常被称为协议数据单元(PDUs)。每个 PDU 都有一种特定的格式,该格式实现了协议的功能和需求。

如前节所述,层 1 以上的层之间的通信是逻辑的;唯一的硬件连接是在物理层。因此,为了使协议能够通信,它必须将其 PDU 传递到下一层进行传输。您也已经看到,使用 OSI 术语,较低层被说成是为它们上面的层提供服务。每个层提供的每个服务之一是这项功能:处理和管理从上层接收到的数据。

在特定的层 N 中,PDU 是一个实现了该层协议的完整消息。然而,当这个层 N 的 PDU 传递到层 N-1 时,它变成了层 N-1 协议应该服务数据。因此,层 N 协议数据单元(PDU)被称为层 N-1 的服务数据单元(SDU)。层 N-1 的任务是传输这个 SDU,它通过将层 N 的 SDU 放入自己的 PDU 格式中,在 SDU 前面加上自己的头部,并在必要时添加尾部来实现。这个过程被称为数据封装,因为高层消息的全部内容都被封装为低层消息的数据负载。

层 N-1 对其 PDU 做什么?它将其传递到下一层,在那里它被视为层 N-2 SDU。层 N-2 创建一个包含层 N-1 SDU、层 N-2 的头部和尾部的层 N-2 PDU。这个过程一直持续到物理层。在理论模型中,最终你得到的是层 1 的消息,它由应用层数据组成,这些数据被层 7 到层 2 的头部和尾部封装。

图 5-5

图 5-5. OSI 参考模型数据封装 每个协议都为传输创建一个协议数据单元(PDU),每个 PDU 都包含该协议所需的头和数据要传输的数据。这些数据成为下一层的服务数据单元(SDU)。

小贴士

关键概念 在 OSI 模型术语中,用于特定协议通信信息的消息称为其协议数据单元(PDU)。该 PDU 被传递到下一较低层进行传输;由于该层提供处理该 PDU 的服务,因此称为该较低层的服务数据单元(SDU)。SDU 被封装到该层的自己的 PDU 中,然后,反过来,发送到堆栈中下一较低层,直到达到物理层。在接收设备上,这个过程是相反的。总之,层 N 的 PDU 是层 N-1 的 SDU,它是封装到层 N-1 的 PDU 中的。

“N-1,N-2”这样的东西使得这个过程看起来比实际情况更复杂,所以让我们用一个现实世界(简化)的例子来代替。TCP 在 OSI 模型的第 4 层运行。它传输称为的消息,这些消息包含从高层协议封装的数据。TCP 下面的层是第 3 层的 IP。它从 TCP 接收数据,并将其封装以进行传输。

因此,在 OSI 参考模型的正式语言中,TCP 段作为第 4 层 PDU 被创建。当传递给 IP 时,它们被视为第 3 层 SDU。IP 软件将这些 SDU 打包成称为IP 数据包IP 数据报的消息,这些是第 3 层 PDU。这些被传递到第 2 层协议,例如以太网,它将 IP 数据报视为第 2 层 SDU,并将它们打包成第 2 层 PDU(以太网帧),然后发送到第 1 层。实际上,在某些技术中,在传输之前甚至在第 1 层发生进一步的封装。

在接收设备上,封装过程是相反的。以太网软件检查第 2 层 PDU(以太网帧),从中移除第 2 层 SDU(IP 数据报),并将其作为第 3 层 PDU 传递给 IP。IP 层移除第 3 层 SDU(TCP 段),并将其作为第 4 层 PDU 传递给 TCP。TCP 继续这个过程,向上返回到协议层堆栈。

图 5-6 更详细地展示了 OSI PDU 和 SDU 的创建和封装过程。一个 TCP 段(第 4 层 PDU)变成一个第 3 层 SDU,通过添加 IP 头部封装进第 3 层的 PDU。这成为以太网帧的有效载荷,它是一个包含以太网头部、第 2 层 SDU(IP 数据报)和以太网尾部的第 2 层 PDU。接收设备从以太网头部提取 IP 数据报并将其传递到第 3 层;IP 软件提取 TCP 段并将其传递到 TCP 软件。

整个封装问题,包括在协议栈中上下传递数据,等等,可能看起来过于复杂。它也可能显得相当低效;为什么发送一个带有这么多头部和尾部的消息?然而,数据封装的概念对于创建模块化、灵活的网络至关重要。

OSI 参考模型 PDU 和 SDU 封装 OSI 模型每一层的每个 PDU 在下一层变为 SDU,并被封装进该层的 PDU 中。

图 5-6. OSI 参考模型 PDU 和 SDU 封装 OSI 模型每一层的每个 PDU 在下一层变为 SDU,并被封装进该层的 PDU 中。

术语协议数据单元或 PDU 相当正式。你会在标准中看到它的使用,有时在讨论中也会看到,但更常见的是,你会遇到如数据报这样的消息术语,正如在第一章中讨论的那样。同样,这些消息封装的数据通常不被称为服务数据单元或 SDU,而简单地称为消息体有效载荷,正如你在查看第一章中的消息格式时所看到的。然而,在某些情况下,了解 SDU 和 PDU 之间的区别对于理解技术很重要。一个例子是 IEEE 802.11 物理层——802.11 标准经常提到 SDU 和 PDU!

小贴士

相关信息 在本章前面的“网络模型的好处”部分中,可以看到 OSI 参考模型类比的一个例子,该例子将网络封装与实际非网络环境中的操作进行比较。

间接设备连接和消息路由

我在本章其他部分提供的多数解释都讨论了机器在网络中直接连接的机制。然而,网络最强大的方面之一是能够创建互连网络——网络的网络,允许设备间接连接。例如,机器 A 可能向机器 B 发送消息,而实际上甚至不知道它在网络上的位置。

如果消息是在不在同一网络中的设备之间发送,那么它必须在网络之间传递,直到达到其最终目的地。从一网络传输到另一网络的过程称为转发,从一设备到另一设备的转发过程称为路由。这些概念是所有互连网络的基础,包括互联网本身。每次你访问互联网资源,如网站时,你都在发送被路由到该站点的消息,而你收到的响应也会被路由回来。

注意

尽管从一网络移动到相邻网络的技术正确术语是转发,但随着时间的推移,路由这个术语已经被用来指代单个网络到网络的传输,以及将消息从一台设备传输到另一台设备的整体过程

在 OSI 参考模型中,路由通常发生在网络层,即第 3 层。你会记得,数据封装会在低层为高层消息添加头部和尾部。当消息被路由时,以下是会发生的事情:

  • 一台机器上的高级应用程序决定向远程计算机发送一个数据报。数据报被封装,然后通过原始机器上的协议栈垂直向下传递。每一层都按照前述章节所述封装数据。数据报被指定给最终目标设备。然而,当消息到达低层时,它并不是直接封装以直接发送到其最终目的地,而是传递给一个中间设备。这是负责将该目标网络路由的设备。消息被传递到数据链路层和物理层,以便发送到该中间设备。

  • 中间设备(通常称为路由器)在物理层接收消息。它被传递到数据链路层,在那里进行处理、检查错误等,并移除数据链路层的头部。生成的数据包被传递到网络层。在那里,中间设备确定目标机器是否在其本地网络中,或者是否需要转发到另一个中间设备。然后它重新封装消息,并将其向下传递到数据链路层,以便在旅程的下一阶段发送。

  • 在经过几个潜在的中间设备处理信息后,它最终到达目的地。在这里,它沿着协议栈向上行进,直到达到在源机器上生成信息的应用程序所在的同一层。

这段描述的关键在于,在中间设备中,消息只沿着 OSI 层向上行进到网络层。然后它被重新封装,并沿着其路径发送回去。高层只涉及源设备和目标设备。在第 3 层使用的协议必须在互联网中是通用的,但每个单独的网络可以不同。这展示了分层的一些强大功能,它使得甚至非常不同的物理网络也能够连接在一起。

图 5-7 展示了在 OSI 模型中概念上如何实现路由。中间设备连接消息发送者和接收者的网络。当发送数据时,数据被传递到中间设备的网络层,在那里它被重新封装,并沿着传输的下一阶段向下发送到栈中。请注意,中间设备实际上有两个不同的第 1 层和第 2 层实现——一个用于每个网络的接口。另外请注意,虽然第 3 层协议必须在互联网中相同,但每个网络可以在第 1 层和第 2 层使用不同的技术。

OSI 参考模型中的消息路由。在 OSI 模型中,通过连接第 3 层的网络的中间设备来实现路由。数据在一个网络中的该设备上传递到第 3 层,然后传递到另一个网络上的第 1 层。

图 5-7. OSI 参考模型中的消息路由。在 OSI 模型中,通过连接第 3 层的网络的中间设备来实现路由。数据在一个网络中的该设备上传递到第 3 层,然后传递到另一个网络上的第 1 层。

小贴士

关键概念 在 OSI 模型中,当数据不是直接从发送者发送到最终接收者,而是通过使用中间系统间接发送时,发生路由过程。该设备通常被称为路由器,连接到两个或多个物理网络,因此具有多个第 2 层接口。当它接收数据时,数据只传递到网络层,在那里它被重新封装,然后通过适当的第 2 层接口发送到旅程的下一阶段。

第六章。OSI 参考模型层

无标题图片

在本章中,我们查看 OSI 参考模型的各个单独层。OSI 模型中的每一层都有定义其自身的某些特征,以及通常与之相关的各种协议。我将描述每一层在 OSI 层堆栈中的功能,概述每一层通常负责的具体活动类型,并提供一些位于每一层的技术和协议的示例。理解每一层的细微差别将有助于您理解使用它们的全部技术。

然而,请注意,本节中的描述是通用的。要真正理解各个层及其使用的细节,请阅读本书后面各层所使用的各个协议的详细信息。

提示

相关信息 第七章 包含可能对您理解 OSI 模型层有帮助的总结信息。这包括一些用于记住层顺序的常见记忆法,以及用于快速比较层关键特征的总结图表。

物理层(层 1)

OSI 参考模型的最底层是层 1,即物理层;它通常缩写为 PHY。这一层是唯一一个在物理上通过网络接口移动数据的层。所有其他层执行创建实现各种协议的消息的功能,但这些消息必须通过协议堆栈向下传输到物理层,并最终通过网络发送出去。

首先,稍作澄清。物理层这个名字可能有点问题,因为它暗示这一层只与实际的网络硬件相关,这并不正确。虽然有些人说物理层是网络接口卡和电缆,但这实际上并不正确。物理层定义了除与硬件电缆和卡接口之外的一系列网络功能。

人们还建议所有网络硬件都属于物理层。然而,这并不完全准确。所有硬件都必须与物理层有些关系才能在网络中发送数据,但硬件设备通常除了物理层之外还实现 OSI 模型的多个层。例如,以太网网络接口卡在物理层和数据链路层都执行功能。

物理层技术处理在网络中传输的实际的 0 和 1。例如,中继器、传统集线器和收发器都在物理层操作。这些设备对消息的内容一无所知;它们只是接收输入比特并将它们作为输出发送。物理层负责以下内容:

硬件规格定义 电缆、连接器、无线收发器、网络接口卡和其他硬件设备的操作细节通常是物理层的功能(尽管也部分属于数据链路层,层 2)。

编码与信号 物理层负责各种编码和信号功能,这些功能将计算机或其他设备内的比特转换为可以在网络上发送的信号。

数据传输与接收 在适当编码数据后,物理层实际上负责传输数据,当然,也负责接收它。(这同样适用于有线和无线网络,即使无线网络中没有可见的电缆。)

拓扑与物理网络设计 物理层也被认为是许多与硬件相关的网络设计问题的领域,例如局域网(LAN)和广域网(WAN)拓扑。

尽管网络物理层主要定义了它所使用的硬件,但它也与数据链路层密切相关。因此,通常无法独立于数据链路层所使用的特定技术来定义物理层的硬件。例如,以太网是一种描述特定类型电缆和网络硬件的技术,但以太网的物理层只能在一定程度上与其数据链路层方面分离。尽管以太网电缆是物理层,但电缆的最大长度与数据链路层存在的消息格式规则密切相关。

此外,一些技术还在物理层执行通常与数据链路层更紧密相关的功能。例如,物理层通常负责对数据链路层帧进行低级(比特级)重新封装以进行传输。在某些情况下,错误检测和纠正也可能在层 1 进行,尽管大多数人会认为这些是层 2 的功能。

在许多技术中,可以使用多个物理层与数据链路层一起使用。经典的例子是以太网,它有数十种不同的物理层实现。每种实现都使用相同的数据链路层(可能略有变化)。

提示

关键概念 OSI 参考模型中的最低层是物理层。它是网络硬件规格的领域,是数据编码、信号、传输和接收功能所在的地方。物理层与数据链路层密切相关。

许多技术进一步将物理层细分为子层,以便不同的网络媒体能够由相同的技术支持,同时在物理层共享各种媒体之间常见的其他功能。一个很好的例子是用于快速以太网、千兆以太网和 10 千兆以太网的物理层架构。

注意

在某些情况下,用于在网络或通信线路中传输比特的物理层技术被称为传输方法(不要与 OSI 传输层,层 4 混淆)

数据链路层(层 2)

OSI 参考模型堆栈中第二低层(层 2)是 数据链路层,通常简称为 链路层,或缩写为 DLL。数据链路层是许多有线和无线局域网技术主要功能的地方。例如,以太网、令牌环、FDDI 和 802.11(无线以太网或 Wi-Fi)有时被称为数据链路层技术。连接在数据链路层的设备集合通常被认为是一个简单网络(与在层 3 连接的集合网络即互联网相对)。

数据链路层通常在概念上分为两个子层:逻辑链路控制(LLC)媒体访问控制(MAC)。这种划分基于 IEEE 802 项目所采用的架构,该架构是负责创建定义许多网络技术标准的 IEEE 工作组。通过分离 LLC 和 MAC 功能,不同网络技术的互操作性变得更容易,如第五章中关于网络模型讨论所述。

以下是在数据链路层执行的关键任务:

逻辑链路控制(LLC) 逻辑链路控制指的是在网络上建立和控制本地设备之间逻辑连接所需的功能。这通常被认为是一个子层;它为上层的网络层提供服务,并隐藏数据链路层其余的细节,从而使不同的技术能够与高层无缝工作。大多数局域网技术使用 IEEE 802.2 LLC 协议来实现数据链路层的这部分功能。

媒体访问控制(MAC) 这指的是设备用于控制对网络介质访问的规程。由于许多网络使用共享介质(如单根网络电缆,或一系列电缆通过电气连接形成一个单一虚拟介质),因此有必要制定管理介质以避免冲突的规则。例如,以太网使用 CSMA/CD 媒体访问控制方法,而令牌环使用令牌传递。

数据帧 数据链路层负责数据帧,这是将高级消息最终封装成在物理层发送的

寻址 数据链路层是 OSI 模型中关注寻址的最低层。它用特定的目的地位置标记信息。网络上的每个设备都有一个唯一编号,该编号由数据链路层协议使用,以确保针对特定机器的数据能够正确到达。这通常被称为硬件地址(因为它与底层硬件密切相关)或MAC 地址(根据前面描述的 MAC 功能命名)。

错误检测和处理 数据链路层处理网络堆栈较低层发生的错误。例如,循环冗余检查(CRC)字段通常基于帧的内容计算,然后包含在其中。这可以用来允许接收数据的站检测它是否被正确接收。

物理层标准 物理层和数据链路层非常紧密相关。网络物理层的要求通常是描述特定技术的数据链路层标准的一部分。某些物理层硬件和编码方面由所使用的数据链路层技术指定。最好的例子是以太网标准 IEEE 802.3,它不仅指定了以太网在数据链路层的工作方式,还指定了其各种物理层。

提示

关键概念 第二个 OSI 参考模型层是数据链路层。这是大多数局域网和无线局域网技术被定义的地方。层 2 负责逻辑链路控制(LLC)、媒体访问控制(MAC)、硬件寻址、错误检测和处理以及定义物理层标准。它通常根据使用该架构的 IEEE 802 项目被分为 LLC 和 MAC 子层。

许多类型的硬件都与数据链路层相关联。网络接口卡通常实现特定的数据链路层技术,因此它们通常被称为以太网卡、令牌环卡等。还有一些网络互连设备,它们在整体或部分上被认为在层 2 运行,因为它们通过查看数据链路层帧来决定对接收到的数据采取什么行动。这些设备包括大多数桥接器、交换机和桥接路由器,尽管后两者还包含由层 3 执行的功能。

与层 2 一般相关的一些最流行的技术和协议包括以太网、令牌环、FDDI(加上 CDDI)、HomePNA、IEEE 802.11、异步传输模式(ATM)、TCP/IP 的串行线路接口协议(SLIP)和 TCP/IP 的点对点协议(PPP)。

网络层(层 3)

OSI 参考模型中的第三低层是网络层。如果数据链路层定义了被认为是网络的范围,那么网络层就定义了互联网(互联网络)如何工作。网络层是 OSI 模型中唯一一个真正关注将数据从一台计算机传输到另一台计算机的层,即使它们位于远程网络中;相比之下,数据链路层只处理彼此相邻的设备。

虽然第 2 层到第 6 层都充当了它们上下层之间的屏障,但网络层在区分高层和低层功能方面尤为重要。在这里,从更高层的更抽象功能——不太关注数据传输——到将数据传输到目的地的具体任务的实际转变真正开始。(随着您向上移动 OSI 协议栈,传输层继续这种抽象转变。)

网络层通常执行的一些具体工作包括以下内容:

逻辑寻址每个通过网络进行通信的设备都与一个逻辑地址相关联,该地址无论其特定位置如何都能识别该设备。这有时被称为第 3 层地址。例如,在互联网上,互联网协议(IP)是网络层协议,每台机器都有一个 IP 地址。逻辑地址独立于特定硬件,并且在整个互联网中必须是唯一的。

注意

地址分配也在数据链路层进行,但这些地址指的是本地物理设备

路由网络层的定义功能是路由——在一系列互联网络中移动数据。网络层上运行的设备和软件例程负责处理来自各种来源的传入数据包,确定它们的最终目的地,然后找出它们需要发送到何处才能到达目的地。(您可以在第五章中关于间接设备连接的部分找到 OSI 模型中关于路由的更完整讨论。第五章。)

数据报封装网络层通常通过将它们放入带有网络层头部(前一章讨论了封装)的数据报(也称为数据包)来封装从高层接收到的消息。

分片与重组 网络层必须将消息发送到数据链路层进行传输。某些数据链路层技术限制了可以发送的任何消息的长度。如果网络层想要发送的数据包太大,网络层必须将数据包分割(分片),将每个部分发送到数据链路层,然后在目标机器的网络层到达后重新组装这些部分。IP 是执行这些功能的最知名协议;请参阅第二十二章以了解 IP 数据报分片的讨论。

错误处理和诊断 网络层使用特殊的协议来允许逻辑上连接的设备(或尝试路由流量)交换有关网络中主机状态或设备本身状态的信息。

网络层协议提供面向连接或无连接的服务来在网络中传输数据包。在网络层,无连接的服务更为常见。在许多协议集中,网络层协议是无连接的,而面向连接的服务由传输层提供。例如,在 TCP/IP 中,IP 是无连接的,而第 4 层的传输控制协议(TCP)是面向连接的。面向连接和无连接协议在第一章中进行了详细讨论。

最常见的网络层协议是 IP,这也是我之前提到过几次的原因。IP 是互联网的骨干,也是整个 TCP/IP 协议集的基础。还有一些与 IP 直接相关的协议在网络层与之协同工作,例如 IPsec、IP NAT 和移动 IP。互联网控制消息协议(ICMP)是与 IP 一起使用的错误处理和控制协议的主要协议。TCP/IP 世界之外的一个值得注意的网络层协议是 Novell Internetworking Packet Exchange (IPX)协议。

小贴士

关键概念 OSI 参考模型的第三层是网络层。这是模型中最重要的层之一;它负责将单个网络链接成互联网的任务。网络层功能包括互联网级寻址、路由、数据报封装、分片与重组以及某些类型的错误处理和诊断。网络层和传输层彼此紧密相关。

在网络层运行的网际互联设备通常被称为路由器。它们负责我提到的路由功能,因为它们在路由的每一段“跳跃”中接收数据包,并将它们发送到旅程的下一阶段。它们通过路由协议相互通信,以确定发送流量的最佳路由。所谓的桥接路由器也至少部分地位于网络层,就像名称明显为第三层的交换机一样。

传输层(第 4 层)

OSI 参考模型协议栈的第四层是传输层,也称为中间层。在 OSI 模型中,传输层在某种程度上是下层和上层层组的一部分。它更常与下层相关联,因为它关注数据的传输,但它的功能也有些高级,因此它与第 5 层到第 7 层也有相当多的共同之处。

你会记得,第 1 层到第 3 层关注的是数据的实际打包、寻址、路由和交付。物理层处理比特,数据链路层处理本地网络,网络层处理网络之间的路由。相比之下,传输层足够概念化,不再关注这些基础问题。它依赖于下层在设备之间移动数据。

传输层在较高层的抽象应用世界和第 1 层到第 3 层的具体功能之间充当某种联络员。它的总体任务是提供必要的功能,以实现不同计算机上软件应用进程之间的通信,这包括许多不同但相关的职责。

由于现代计算机是多任务的,许多不同的软件应用可能在任何给定时刻都试图向同一台机器发送和接收数据。传输层负责提供一种方式,使这些应用都可以使用相同的下层协议实现发送和接收数据。因此,有时人们说它负责端到端主机到主机的传输(实际上,TCP/IP 模型中相当层的名称是主机到主机传输层)。

为了实现进程之间的这种通信,传输层必须执行几个不同但相关的任务。对于传输,它必须跟踪每个应用的数据,然后将其组合成单一的数据流发送到下层。接收信息的设备必须执行相反的操作,将数据分段,并将其引导到适当的接收进程。传输层还负责定义将潜在的大量应用数据分段进行传输的方式。

传输层还负责为在其之上运行的协议和应用程序提供连接服务。这些可以分为面向连接的服务和无连接的服务,每种都有其用途。虽然面向连接的服务可以在网络层处理,但在现实世界中它们更常见于传输层。(一些协议套件,如 TCP/IP,提供面向连接和无连接的传输层协议,以满足不同应用程序的需求。)

传输层也是通常包含添加端到端数据传输功能的地方。而网络层协议通常只关注“尽力而为”的通信,不保证交付,传输层协议则通过算法赋予智能,确保设备之间可靠且高效的通信。这种智能包括几个相关任务,包括丢失传输的检测和处理,以及管理数据发送速率,以确保接收设备不会被淹没。

传输质量——确保传输被接收时与发送时相同——非常重要,以至于一些网络书籍根据可靠性和流量控制功能来定义传输层。然而,并非所有传输层协议都提供这些服务。正如协议套件可能既有面向连接的传输层协议也有无连接的传输层协议一样,它也可能有一个提供可靠性和数据管理服务的传输层协议,以及一个不提供这些服务的协议。再次强调,TCP/IP 就是这种情况:有一个主要的传输层协议 TCP,它包括可靠性和流量控制功能,还有一个第二层协议用户数据报协议(UDP),它不提供这些功能。

让我们更详细地看看传输层通常执行的具体功能:

进程级寻址 传输层寻址用于区分不同的软件程序。这是许多不同的软件程序能够同时使用网络层协议的部分原因。传输层进程级寻址的最佳例子是 TCP/IP 中使用的 TCP 和 UDP 端口号机制,它允许在任意 TCP/IP 设备上对应用程序进行单独引用。

复用和解复用 使用进程级地址,发送设备上的传输层协议会将从多个应用程序接收到的数据进行复用,将它们组合成一个要发送的单个数据流。相同的协议接收数据,然后从进入的数据报流中解复用,并将每个数据报直接导向相应的接收应用程序进程。

分段、封装和重组 传输层将发送到网络的大量数据在网络源机器上分段成更小的块,然后在目标机器上重新组装。这个功能类似于网络层的分片功能。就像网络层将消息分片以适应数据链路层的限制一样,传输层将消息分片以满足底层网络层的要求。

连接建立、管理和终止 传输层面向连接的协议负责建立连接所需的一系列通信,包括在数据通过它发送时维护连接,并在不再需要时终止连接。

确认和重传 如前所述,传输层是实现许多保证数据可靠交付的协议的地方。这是通过多种技术实现的,最常见的是通过结合确认重传计时器。发送设备在每次发送数据时启动一个计时器;如果数据被接收,接收方会向发送方发送一个确认,以指示传输成功。如果在计时器到期之前没有收到确认,数据将被重新发送。通常还需要其他算法和技术来支持这个基本过程。

流量控制 提供可靠交付的传输层协议通常也实现了流量控制功能。这些功能允许通信中的一个设备向另一个设备指定它必须降低发送数据的速率。这将防止接收器被数据拖累。这些功能允许检测和处理发送方和接收方之间的速度不匹配。

提示

关键概念 第四层和中间的 OSI 参考模型层是传输层。这一层代表了处理数据交付问题的底层和与应用程序软件一起工作的更高层之间的过渡点。传输层负责在应用程序进程之间实现端到端通信,部分是通过使用进程级寻址和复用或解复用来实现的。传输层协议负责将应用程序数据分段以便传输,可以是面向连接的或无连接的。此层的协议也经常提供数据交付管理服务,例如可靠性和流量控制。

理论上,传输层和网络层是不同的,但在实践中,它们通常彼此非常紧密相关。您只需查看常见协议栈的名称就可以轻松看到这一点。它们通常以套件中第 3 层和第 4 层协议命名,从而暗示了它们之间的紧密关系。例如,TCP/IP 这个名字来自套件中最常用的传输层协议(TCP)和网络层协议(IP)。同样,Novell NetWare 套件通常被称为 IPX/SPX,因为它有第 3 层(IPX)和第 4 层(顺序包交换,或 SPX)协议。

通常,特定的传输层协议使用同一家族的网络层。您不太可能找到一个使用一个套件中的传输层协议和另一个套件中的网络层协议的网络。在 TCP/IP 套件中,最常用的传输层协议是 TCP 和 UDP,在 NetWare 协议套件中是 SPX,在 NetBIOS/NetBEUI/NBF 套件中是 NetBEUI(尽管 NetBEUI 更难归类)。

会话层(第 5 层)

OSI 参考模型中的第五层是会话层。随着您从 OSI 层堆栈的底部向上移动,会话层是第一个基本上将所有与寻址、封装和交付数据相关的实际事务留在了后面的层;它们是第 4 层及以下层的功能。会话层是三个上层层中最低的,作为一个整体,它们主要关注软件应用问题,而不是网络和互联网实现的细节。

会话层的名字说明了其设计目的:它旨在允许设备建立和管理会话。一般而言,会话是两个软件应用进程之间持久的逻辑连接,允许它们在一段时间内交换数据。在某些讨论中,这些会话被称为对话,实际上,它们大致相当于两个人之间的电话通话。

会话层协议主要提供设置、管理和结束会话所需的必要手段。实际上,在某些方面,会话层软件产品更像是工具集而不是特定的协议。这些会话层工具通常通过通常称为应用程序程序接口API的命令集提供给高层协议。

常见的 API 包括 NetBIOS、TCP/IP 套接字和远程过程调用(RPCs)。API 允许应用程序通过使用一组标准化的服务,轻松地在网络上完成某些高级通信。这些会话层工具主要对应用软件的开发者感兴趣。程序员使用 API 编写能够使用 TCP/IP 进行通信的软件,而无需开发者了解 TCP/IP 如何工作的实现细节。

例如,套接字接口在概念上位于第 5 层,并被 TCP/IP 应用程序程序员用于在 UNIX 操作系统上创建互联网上软件程序之间的会话。Windows 套接字同样允许程序员创建能够上网的 Windows 软件,并且能够轻松与其他使用该接口的软件交互。(严格来说,套接字不是一个协议,而是一种编程方法。)

注意

层与层之间的界限一旦达到会话层就开始变得模糊。这使得很难确定哪些内容确切地属于第 5 层,有些技术实际上跨越了第 5 层到第 7 层。在 TCP/IP 的世界中,特别是不常见能识别出专门针对 OSI 会话层的协议

小贴士

关键概念 OSI 参考模型中的第五层是会话层。正如其名称所暗示的,它是旨在为软件进程之间建立和管理会话提供功能的层。会话层技术通常作为一组称为应用程序编程接口(API)的软件工具集来实现,这些工具集提供了一套一致的服务,使程序员能够在不担心传输、寻址和交付的底层细节的情况下开发网络应用程序。

注意

“会话”这个术语有些模糊,这意味着有时会对属于会话层的具体功能或某些协议是否属于会话层存在分歧。更不用说区分连接与会话的问题了。连接通常属于第 4 层和第 3 层,但例如 TCP 连接可以持续很长时间。TCP 连接的持久性使得它们难以与会话区分开来(有些人甚至认为 TCP/IP 的主机到主机传输层实际上跨越了 OSI 的第 4 层和第 5 层)

表示层(第 6 层)

表示层是 OSI 参考模型协议堆栈的第六层,也是从顶部数第二层。它在两个关键方面与其他层不同。首先,它的功能和作用范围比其他层要有限和具体得多。其次,它比其他层使用得少,并且不是许多类型通信所必需的。

这一层处理数据的表示。更具体地说,它负责处理当从一系统发送的数据需要以不同的方式由接收系统查看时可能出现的任何问题。表示层还处理从应用程序尝试发送数据到数据通过网络发送这段时间内必须进行的任何特殊处理。

下面是表示层处理的一些具体的数据处理问题类型:

翻译 在同一个网络中可能存在多种不同类型的计算机,例如 PC、Mac、UNIX 系统、AS/400 服务器和大型机。每种计算机都有许多独特的特性,并以不同的方式表示数据(例如,使用不同的字符集)。表示层隐藏了机器之间的差异。

压缩 压缩(和解压缩)可以在表示层进行,以提高数据的吞吐量。

加密 在表示层执行某些类型的加密(和解密)操作,以确保数据在协议栈中传输时的安全性。例如,与表示层通常相关联的最流行的加密方案之一是安全套接字层(SSL)协议。(在 IPsec 等技术中,某些加密操作在协议栈的较低层进行。)

表示层并不总是在网络通信中使用,因为这些提到的功能并不总是需要的。压缩和加密通常被认为是可选的,并且仅在特定情况下需要翻译功能。此外,表示层的功能可能由应用层执行。

注意事项

由于翻译工作并不总是需要,因此表示层通常在实际协议栈实现中被省略;在这些实现中,第 7 层的协议可以直接与第 5 层的协议进行通信。这也是为什么第 5 层到第 7 层的所有功能可能都包含在同一个软件包中的原因,如前一章中关于层和层分组的概述所述

小贴士

关键概念 OSI 模型的第 6 层是表示层。该层的协议负责执行将数据从一种表示形式转换为另一种表示形式的操作任务,例如翻译、压缩和加密。在许多情况下,特定的网络栈中可能不需要此类功能;如果是这样,第 6 层可能没有活跃的协议,因此第 7 层可能直接处理第 5 层。

应用层(第 7 层)

在 OSI 参考模型层堆栈的最顶层,您会发现第 7 层,即应用层。继续您在层 5 和层 6 中看到的趋势,这一层的命名也非常恰当。应用层是网络应用程序使用的层。这些程序实际上实现了用户在网络中完成各种任务时执行的功能。

重要的是要理解 OSI 模型所说的应用层与您通常所想的应用层并不完全相同。在 OSI 模型中,应用层为用户应用提供服务。

例如,当你使用你的网页浏览器时,那个实际的软件是在你的 PC 上运行的应用程序。它并不真正位于应用层。相反,它利用了在应用层运行的协议提供的服务,这个协议被称为超文本传输协议(HTTP)。浏览器和 HTTP 之间的区别微妙但很重要。

并非所有用户应用程序都以相同的方式使用网络的网络应用层。当然,你的网页浏览器、电子邮件客户端和 Usenet 新闻阅读器都是这样,但如果你使用文本编辑器通过网络打开一个文件,那个编辑器并没有使用应用层——它只是看到了一个被映射到某处网络的文件名。操作系统将编辑器的操作重定向到网络上。

同样,并非所有应用层的用途都是通过应用程序实现的。操作系统本身可以(并且确实)直接在应用层使用服务。

不考虑这个警告,在正常情况下,每次你与电脑上专门为网络使用而设计的程序交互时,你都是在直接处理应用层。例如,发送电子邮件、启动网页浏览器和使用聊天程序都涉及到位于应用层的协议。

注意

有数十种不同的应用层协议。其中一些最受欢迎的包括 HTTP、FTP、SMTP、DHCP、NFS、Telnet、SNMP、POP3、NNTP 和 IRC。我在第三部分中描述了所有这些以及更多内容

作为堆栈的顶层,应用层是唯一一个不对堆栈中其上层的层提供任何服务的层——没有这样的层!相反,它为想要使用网络的程序以及用户你提供服务。因此,这一层的责任仅仅是实现网络用户所需的函数,并发出适当的命令以利用下层提供的服务。

提示

关键概念 应用层是 OSI 参考模型的第七层和最高层。在这一层定义了实现特定用户应用程序和其他高级功能的协议。由于它们位于堆栈的顶部,应用协议是唯一不向更高层提供服务的协议;它们使用下层提供的服务。

正如你所看到的,OSI 模型中最上面三层之间的区别并不非常明显。在 TCP/IP 的情况下,这种区别由于决定不将会话层、表示层和应用层功能分开而加剧。前面提到的所有协议都属于 TCP/IP 协议族,其中一些可能覆盖了 OSI 模型中最上面的三层、两层或一层;在 TCP/IP 模型中,它们都被视为应用层。

第七章:OSI 参考模型总结

无标题图片

许多网络学的学生发现 OSI 参考模型很难处理。主要原因之一是这个模型有些抽象,使得理解起来很困难,甚至更难将其应用于实际的网络环境中。因此,我在本章中包含了一套我希望能帮助你更好地理解和记住 OSI 参考模型及其概念的三个工具:一个类比、一组记忆法和一个 OSI 模型层的总结表。

理解 OSI 模型:一个类比

我在讨论 OSI 参考模型时,尽可能地提供尽可能多的平实的英语解释,说明它是如何工作的。然而,在某些情况下,一个好的类比可以完成许多描述都无法做到的事情。所以,我将通过一个现实生活中的类比来阐述关键 OSI 模型概念。你可以判断这个类比是否是一个好的类比。只需记住,没有任何类比是完美的!

我们的场景似乎相对简单且常见:一家《财富》500 强公司的首席执行官需要给另一家公司的首席执行官发送一封信。简单,对吧?就像打开你的网络浏览器并连接到你最喜欢的网站一样简单。然而,在这两种情况下,幕后都有很多工作要做,以确保通信能够发生。在表 7-1 中展示的类比中,我比较了这些现实世界和虚拟世界中的通信。

表 7-1. OSI 参考模型现实世界类比

阶段 OSI 层 CEO 信件 网站连接(简化版)
传输 7 凤凰城一家公司的首席执行官决定需要给阿尔巴尼的一个同行发送一封信。他将信件口述给他的行政助理。 你决定想要连接到 IP 地址 10.0.12.34 的网络服务器,该地址位于你的组织内但不在你的本地网络中。你将地址输入到你的浏览器中。
6 行政助理将口述记录成文字。 使用网站连接,这里通常不会发生任何事情。在某些情况下可能需要进行格式转换。
5 行政助理将信件放入信封并交给邮件室。助理实际上不知道信件将如何发送,但知道它很紧急,所以他说:“请尽快将这封信送到目的地。” 请求通过调用 API 发送,该 API 发出必要的命令以联系该地址的服务器。
4 邮件室必须决定如何将信件送到目的地。由于是加急件,邮件室的人决定将信封交给快递公司发送。 使用 TCP 创建一个将被发送到 IP 地址 10.0.12.34 的段。
3 快递公司收到信封,但需要添加自己的处理信息,因此将较小的信封放入快递信封(封装)。然后快递员查阅其飞机路线信息,确定要将此信封运送到阿尔巴尼,必须通过其在芝加哥的枢纽。他将此信封交给负责装载飞机包裹的工人。 您的计算机创建了一个封装了之前创建的 TCP 数据报的 IP 数据报。然后它将数据包地址设置为 10.0.12.34,但发现它不在其本地网络中。相反,它意识到需要将消息发送到其 IP 地址为 10.0.43.21 的指定路由设备。它将数据包交给您的以太网卡驱动程序(与以太网硬件接口的软件)。
路由 2 工作人员拿起快递信封,并在上面贴上芝加哥的代码标签。然后他们将其放入处理箱中,并装载到飞往芝加哥的飞机上。 以太网卡驱动程序形成一个包含 IP 数据报的帧,并准备通过网络发送。它包装消息,并将地址 10.0.43.21(用于路由器)放入帧中。
1 飞机飞往芝加哥。 帧通过连接您本地网络的 twisted-pair 电缆发送。(在此处我忽略了开销、冲突等,但那时我也忽略了与飞机发生冲突的可能性。)
2 在芝加哥,箱子被卸下,快递信封从箱子中取出,并交给在芝加哥处理路由的人员。 具有 IP 地址 10.0.43.21 的机器上的以太网卡接收帧,移除帧头部,并将其向上传递到网络层。
3 从快递信封的外面移除标记为“芝加哥”的标签。然后信封被交还给飞机工作人员,以便发送到阿尔巴尼。 IP 数据报由路由器处理,路由器意识到目的地(10.0.12.34)可以直接到达。它将数据报向下传递到以太网驱动程序。
2 信封被贴上新的标签,带有阿尔巴尼的代码,放入另一个箱子中,并装载到飞往阿尔巴尼的飞机上。 以太网驱动程序创建一个新的帧,并准备将其发送到使用 IP 地址 10.0.12.34 的设备。
1 飞机飞往阿尔巴尼。 帧通过网络发送。
2 箱子被卸下,快递信封从箱子中取出,并交给阿尔巴尼的路由办公室。 具有 IP 地址 10.0.12.34 的设备的以太网卡接收帧,移除头部,并将其向上传递到堆栈。
接收 3 阿尔巴尼的快递公司看到目的地是阿尔巴尼,就将信封递送到目的地 CEO 的公司。 从数据报中移除了 IP 头,并将 TCP 段传递给 TCP。
4 邮件室从快递信封中取出内层信封并将其交付给目的地 CEO 的助手。 TCP 移除其头部并将数据交给目标机器上的驱动程序。
5 助手从信封中取出信件。 请求被发送到网络服务器软件进行处理。
6 助手阅读信件并决定是否将信件交给 CEO,将其转录成电子邮件,给 CEO 打电话或做其他事情。 再次,在这个例子中,在表示层可能没有发生任何事情。
7 第二位 CEO 接收第一位 CEO 发送的消息。 网络服务器接收并处理请求。

如你所见,这些过程有很多共同之处。垂直通信和封装相当明显,路由也是如此。还隐含的是逻辑上的横向通信——两位 CEO 似乎“连接”在一起,尽管发生了所有这些事情才能实现这一点。同样,从某种意义上说,两位助手也是逻辑上连接的,尽管他们从未真正交谈过。当然,这个例子在几乎所有方面都被高度简化了,所以请不要用它来尝试了解 TCP/IP 的工作方式——或者快递服务,等等!

记忆 OSI 模型层:一些助记符

如果你花任何时间处理网络设计或实施问题,或者学习各种协议的工作方式,各种层的名称和数字最终会变得自然而然。

许多人,然而,尤其是那些刚开始学习网络的人,发现很难回忆起所有层的名称,尤其是它们的准确顺序。对于这些人,已经创造了许多助记符作为记忆辅助工具。你可能还记得小学时的助记符。这些是包含每个单词都以 OSI 模型层首字母开头的可爱短语,并按正确的顺序排列。其中一些按层号升序排列,而另一些则按相反方向排列。

这两个从物理层到应用层:

  • 请勿丢弃史蒂夫的香肠披萨

  • 请勿触摸史蒂夫的宠物鳄鱼

而这些则是从应用层到物理层的相反方向:

  • 所有人似乎都需要数据处理(一个流行的例子)

  • 所有人完全赤身裸体站立都不会出汗(嗯,这很有趣!)

为了您的方便,我已经在图 7-1 中说明了这四个。

OSI 参考模型助记符 这些助记符可能有助于你记住 OSI 参考模型层的顺序。

图 7-1. OSI 参考模型助记符 这些助记符可能有助于你记住 OSI 参考模型层的顺序。

或者尝试我的自创:所有人都应该每天教授网络知识。

总结 OSI 模型层:摘要图表

为了帮助您快速比较 OSI 参考模型的层,并了解它们之间的不同之处以及它们是如何相互关联的,我为您提供了一张摘要图表,如图表 7-2 所示。它显示了每一层的名称和编号,描述了其关键职责,讨论了在每一层通常处理的数据类型,并大致描述了每一层的范围。我还展示了与每一层相关的一些更常见的协议。

本表仍适用标准免责声明。也就是说,层与层之间并不总是严格划分;我没有列出每一个单独的协议,因此有些可能实际上适合多个层,等等。特别是请注意,列在数据链路层中的许多技术之所以在那里,是因为它们的主要功能位于该层。实际上,这些技术中的大多数都包含在其他层中的组件,尤其是物理层。

表 7-2. OSI 参考模型层摘要

# 层名称 主要职责 处理的数据类型 范围 常见协议和技术
下层 1 物理层 编码和信号;物理数据传输;硬件规范;拓扑和设计 比特 本地设备之间发送的电气或光信号 列出的大部分数据链路层技术的物理层
2 数据链路 逻辑链路控制;媒体访问控制;数据帧;寻址;错误检测和处理;定义物理层的要求 本地设备之间的低级数据消息 IEEE 802.2 LLC、以太网系列;令牌环;FDDI 和 CDDI;IEEE 802.11(WLAN、Wi-Fi);HomePNA;HomeRF;ATM;SLIP 和 PPP
3 网络 逻辑寻址;路由;数据报封装;分片和重组;错误处理和诊断 数据报/包 本地或远程设备之间的消息 IP;IPv6;IP NAT;IPsec;移动 IP;ICMP;IPX;DLC;PLP;如 RIP 和 BGP 的路由协议
4 传输 进程级寻址;复用/解复用;连接;分段和重组;确认和重传;流量控制 数据报/段 软件进程之间的通信 TCP 和 UDP;SPX;NetBEUI/NBF
上层 5 会话 会话建立、管理和终止 会话 本地或远程设备之间的会话 NetBIOS、套接字、命名管道、RPC
6 表示层 数据转换;压缩和加密 编码的用户数据 应用数据表示 SSL;外壳和重定向器;MIME
7 应用 用户应用服务 用户数据 应用数据 DNS; NFS; BOOTP; DHCP; SNMP; RMON; FTP; TFTP; SMTP; POP3; IMAP; NNTP; HTTP; Telnet

第一部分-3. TCP/IP 协议套件和架构

第八章

在本节“TCP/IP 概述和背景信息”的前两部分中,我已经为理解网络在一般意义上的工作原理奠定了基础。现在我们可以开始关注本书的主要主题:TCP/IP。正如以太网在局域网(LAN)技术中占据主导地位,IEEE 802.11 是无线局域网(WLAN)世界的领导者,TCP/IP 在现代互联网,包括互联网的世界中占据主导地位,甚至定义了这一领域。

由于 TCP/IP 是本书的主题,你可能想知道为什么这一部分如此之小,只包含一个章节。原因是它只提供了 TCP/IP 协议套件的高级概述。TCP/IP 是一系列几十个构成协议和技术。这些在本书的下两个部分中描述,分别涵盖底层和应用协议。这些协议在随后的 TCP/IP 简介章节中进行了总结,该章节还简要介绍了 TCP/IP 的历史,并描述了其服务和模型。

第八章。TCP/IP 协议套件和架构

无标题图片

以其两个关键协议命名,TCP/IP 协议套件已经持续使用和开发大约三十年。在这段时间里,它已经从一种用于连接少量研究计算机的实验性技术,演变为历史上最大、最复杂的计算机网络——全球互联网的强大动力:连接数百万网络和终端设备。

在本章中,我们开始了一次神奇的旅行,简要回顾了 TCP/IP 的有趣历史,并对其进行了概述。我讨论了 TCP/IP 网络提供的服务,然后解释了 TCP/IP 下使用的架构模型。接着,我简要描述了本书余下部分讨论的每个最重要的 TCP/IP 协议。

TCP/IP 概述和历史

对 TCP/IP 进行考察的最佳起点可能就是其名称本身。事实上,TCP/IP 由数十种不同的协议组成,其中两种通常被认为是最重要的。互联网协议(IP)是 OSI 模型网络层(第 3 层)的主要协议,它提供了寻址、数据报路由和其他互联网中的功能。传输控制协议(TCP)是传输层(第 4 层)的主要协议,负责连接建立和管理,以及设备上软件进程之间的可靠数据传输。由于这两个协议如此重要,它们的缩写已经代表整个套件:TCP/IP。

IP 和 TCP 之所以重要,是因为 TCP/IP 的许多关键功能都是在第 3 层和第 4 层实现的,这些协议就存在于这些层。然而,TCP/IP 不仅仅是 TCP 和 IP。整个协议套件需要许多不同协议和技术的工作,才能构建一个能够为用户提供所需应用的正常工作的网络。

TCP/IP 使用它自己的四层架构(这大致对应于 OSI 参考模型),为组成它的各种协议提供框架。它还包括许多高级应用,其中一些对互联网用户来说很熟悉,他们可能没有意识到它们是 TCP/IP 的一部分,例如超文本传输协议(HTTP,它是万维网的动力)和文件传输协议(FTP)。在即将进行的关于 TCP/IP 架构和协议的讨论中,我们将探讨大多数重要的 TCP/IP 协议以及它们是如何协同工作的。

TCP/IP 历史与发展

互联网的历史和 TCP/IP 的历史密切相关,以至于很难讨论一个而不提及另一个。它们是共同发展的,TCP/IP 为互联网的实现提供了机制。多年来,TCP/IP 一直在不断进化,以满足互联网以及使用该技术的较小、私有网络的需求。我们在这里简要回顾一下这一历史。

TCP/IP 协议最初是美国国防高级研究计划署DARPAARPA)开发的研究网络的一部分。最初,这个名为 ARPAnet 的网络是一个新兴网络,设计用于使用从现有技术中改编的一系列协议。然而,它们在概念或实际应用方面(例如在 ARPAnet 上使用时的容量)都存在缺陷或限制。新网络的开发者认识到,试图使用这些现有协议可能会随着 ARPAnet 规模的扩大和适应新的用途和应用而最终导致问题。

1973 年,为 ARPAnet 开发一套完整的互联网络协议系统的工作开始了。有趣的是,该技术的早期版本只包括一个核心协议:TCP。实际上,这些字母甚至不表示它们今天所做的事情;它们代表的是传输控制程序。现代 TCP 的前身——这个程序的第一个版本是在 1973 年编写的,然后在 1974 年 12 月发布的 RFC 675 中进行了修订和正式文档化,该文档名为《互联网传输控制程序规范》。

注意

互联网标准是在称为请求评论(RFCs)的文档中定义的。这些文档以及创建它们的过程在第三章中有所描述

TCP 的测试和开发持续了几年。1977 年 3 月,TCP 的第二个版本被记录下来。1977 年 8 月,TCP/IP 的发展迎来了一个重要的转折点。Jon Postel,互联网和 TCP/IP 最重要的先驱之一,发布了一系列关于 TCP 状态的评论。在这份文件(被称为互联网工程笔记第 2 号,或IEN 2)中,他提供了一个极好的例子,说明了参考模型和层不仅仅是教科书中的内容:

我们在设计互联网协议时违反了分层原则,这是我们的错误。具体来说,我们试图让 TCP 做两件事:作为主机级别的端到端协议,以及作为互联网封装和路由协议。这两件事应该以分层和模块化的方式提供。我建议需要一个全新的、独立的互联网协议,并且 TCP 应该严格用作主机级别的端到端协议。

—Jon Postel,IEN 2,1977

Postel 基本上是在说,1970 年代中期创建的 TCP 版本试图做太多。具体来说,它包含了 OSI 层 3 和层 4 的活动。他的愿景是预言性的,因为我们现在知道,让 TCP 处理所有这些活动确实会导致未来的问题。

Postel 的观察导致了 TCP/IP 架构的定义,以及将 TCP 拆分为传输层的 TCP 和网络层的 IP。将 TCP 拆分为两部分的进程始于 1978 年的 TCP 版本 3。用于现代网络中使用的 IP 和 TCP 版本(版本 4)的第一个正式标准是在 1980 年创建的。

TCP/IP 很快成为了运行 ARPAnet 的标准协议集。在 20 世纪 80 年代,越来越多的机器和网络通过 TCP/IP 协议连接到不断发展的 ARPAnet,从而诞生了 TCP/IP 互联网。

提示

关键概念 TCP/IP 最初在 20 世纪 70 年代作为定义一组操作新兴互联网技术的努力的一部分而开发。TCP/IP 这个名字是在原始的传输控制程序(TCP)被拆分为传输控制协议(TCP)互联网协议(IP)时出现的。这两个关键协议的第一个现代版本分别在 1980 年作为 TCP 版本 4 和 IP 版本 4 被记录下来。

TCP/IP 成功的重要因素

TCP/IP 曾经只是许多可以用来提供网络层和传输层功能的不同协议集之一。今天,仍然有其他互联网协议选项,例如 Novell 的 IPX/SPX,但 TCP/IP 是全球公认的世界标准。

TCP/IP 的普及增长归因于许多重要因素。其中一些是历史的,例如它与前面描述的互联网紧密相连,而其他一些则与协议套件的自身特性有关。

集成寻址系统 TCP/IP(主要是作为 IP 的一部分)包含一个用于识别和寻址小型和大型网络中设备的系统。寻址系统被设计成允许设备被寻址,而不管构成每个网络的底层细节如何。随着时间的推移,TCP/IP 中寻址的机制得到了改进,以满足不断增长的网络的需求,特别是互联网。寻址系统还包括一个集中管理的功能,以确保每个设备都有一个唯一的地址。

设计用于路由 TCP/IP 是专门设计来简化在任意复杂网络中信息路由的。实际上,TCP/IP 在概念上更关注连接网络而不是连接设备。TCP/IP 路由器通过将数据一步一步地从网络移动到下一个网络,使不同网络上的设备之间能够传递数据。TCP/IP 中的一些支持协议被设计用来允许路由器交换关键信息,并管理从网络到网络的效率信息流。

底层网络独立性 TCP/IP 主要在层 3 及以上操作,并包含允许其在几乎任何底层技术(包括局域网(LAN)、无线局域网和多种类型的广域网(WAN))上运行的条款。这种灵活性意味着您可以混合和匹配各种不同的底层网络,并使用 TCP/IP 将它们全部连接起来。

可扩展性 TCP/IP 最令人惊叹的特性之一是其协议的可扩展性。几十年来,它已经证明了自己在互联网从小型网络发展到拥有数百万台主机的巨大互联网的过程中具有强大的实力。虽然为了支持这种增长,定期需要进行一些更改,但这些更改都是作为 TCP/IP 开发过程的一部分进行的,而且 TCP/IP 的核心基本上与 25 年前相同。

开放标准和开发过程 TCP/IP 标准不是专有的,而是开放的,对公众免费提供。此外,用于开发 TCP/IP 标准的过程也是完全开放的。TCP/IP 标准和协议是通过独特的、民主的请求评论(RFC)过程(在第三章中描述,Chapter 3)开发和修改的,所有感兴趣的相关方都被邀请参与。这确保了任何对 TCP/IP 协议感兴趣的人都有机会对其发展提供反馈,同时也确保了协议套件的全球接受度。

通用性 每个人都使用 TCP/IP,因为每个人都在使用它!这个最后一点,也许有些讽刺,可能是最重要的。TCP/IP 不仅互联网的底层语言,而且今天在大多数私有网络中也使用 TCP/IP 来传输流量。

小贴士

关键概念 虽然 TCP/IP 不是唯一的网络互联协议套件,但它无疑是其中最重要的一个。它的无与伦比的成功归因于许多因素。这些包括其技术特性,如路由友好设计、可扩展性,它在互联网协议套件中的历史角色,以及其开放标准和开发过程,这些都降低了 TCP/IP 协议的接受障碍。

TCP/IP 服务

TCP/IP 通常是通过其基于层的架构和在不同层提供的协议来研究的。然而,这些协议代表了 TCP/IP 如何工作的技术细节。对我们这些技术学习者来说,这些细节是有趣的,但对于不需要看到 TCP/IP 内部结构的用户来说,这些细节通常是隐藏的。在深入这些细节之前,让我们先从更宏观的角度来看一下 TCP/IP 是做什么的。

在讨论 OSI 参考模型概念(在第五章第五章. 一般 OSI 参考模型问题和概念)。

正如客户端/服务器网络适用于硬件一样,TCP/IP 协议和软件应用的设计也基于同样的概念,如图 8-1 所示(ch08s03.html#tcpip_clientserver_operation_most_tcpip_ "图 8-1. TCP/IP 客户端/服务器操作 大多数 TCP/IP 协议涉及两个设备之间的通信,通常是客户端和服务器,例如通过互联网进行的这种网页(HTTP)事务。")。

TCP/IP 协议并非设置成两个想要通信的机器使用相同的软件。相反,人们有意识地决定使用匹配的、互补的客户端和服务器软件对来实现通信功能。客户端通过向服务器发送请求以获取数据或其他信息来启动通信。然后服务器向客户端回复,提供客户端请求的内容,或者以其他方式回复,例如错误消息或关于其他可能找到数据的地方的信息。大多数(但不是所有)TCP/IP 功能都以这种方式工作。

TCP/IP 客户端/服务器操作 大多数 TCP/IP 协议涉及两个设备之间的通信,通常是客户端和服务器,例如通过互联网进行的这种网页(HTTP)事务。

图 8-1. TCP/IP 客户端/服务器操作 大多数 TCP/IP 协议涉及两个设备之间的通信,通常是客户端和服务器之间的通信,例如通过互联网进行的这种网页(HTTP)事务。

图 8-1 是一个简化的示意图,展示了常见的例子——使用 HTTP 的网页事务。网页浏览器是 HTTP 客户端,通过向网站发送请求文件或其他资源来启动通信,该网站是 HTTP 服务器。服务器向客户端提供请求的信息。(服务器通常同时响应多个客户端。)

在 TCP/IP 中,客户端/服务器操作有许多优点。正如客户端硬件和服务器硬件可以根据其非常不同的工作定制一样,客户端软件和服务器软件也可以优化以尽可能高效地执行其工作。例如,要从网络获取信息,网页客户端软件(通常称为 浏览器)向网页服务器发送请求。然后,网页服务器响应请求的内容。(当然,这不仅仅是那样,但对用户来说就是这样。)在众多功能中,网页浏览器允许用户与网页服务器通信;网页服务器软件旨在接收并响应请求。

在 TCP/IP 中,客户端服务器 这些术语可能会令人困惑,因为它们被用于多种不同的方式,有时甚至同时使用。

小贴士

关键概念 TCP/IP 协议套件围绕 客户端/服务器 网络通信的概念构建。并非所有设备和协议软件元素都设计为对等体,而是构建为匹配的集合。客户端通常通过发送请求来启动通信,服务器响应这些请求,向客户端提供所需的数据或信息性回复。

硬件和软件角色

客户端服务器 这些术语通常指的是网络硬件扮演的主要角色。客户端计算机通常是个人使用的 PC 或 Macintosh,它主要通过发送请求来启动对话。服务器 通常是一台高性能机器,专门用于响应客户端请求,位于某个计算机室中,除了其管理员外,没有人会看到。

如前所述,TCP/IP 使用不同的软件来实现许多协议的客户端和服务器角色。例如,网页浏览器是一块客户端软件,而网页服务器软件则完全不同。客户端软件通常位于客户端硬件上,服务器软件位于服务器硬件上,但某些设备可能同时运行客户端和服务器软件。

事务角色

在任何信息交换中,客户端通常是启动通信或发送查询的设备,然后服务器响应,通常是通过提供信息。再次强调,客户端设备上的客户端软件通常启动事务。

在典型的组织中,会有许多较小的个人计算机被指定为客户端,以及少数较大的服务器。服务器通常运行服务器软件,而客户端运行客户端软件。但服务器也可以配置客户端软件,客户端也可以配置服务器软件。

例如,假设你是一名管理员,在服务器 1 的计算机室工作,需要将文件传输到服务器 2。你启动 FTP 会话,以与服务器 2 开始文件传输。在这个事务中,服务器 1 充当客户端,因为它正在发起通信。理论上,你甚至可以从服务器 1 开始向特定客户端的 FTP 传输,如果该客户端有 FTP 服务器软件来响应服务器的请求。(这不太常见,因为服务器软件通常不会安装在客户端计算机上。)

当某些协议中的服务器之间发生通信时,事务角色就会发挥作用。例如,当两个简单邮件传输协议(SMTP)服务器通信以交换电子邮件(尽管它们都是运行在服务器硬件上的服务器程序)时,在任何事务中,一个设备充当客户端,而另一个设备充当服务器。在某些情况下,设备甚至可以在会话中途交换客户端和服务器角色。

小贴士

关键概念 在 TCP/IP 中理解客户端/服务器计算概念变得更加复杂,因为客户端和服务器这两个术语在不同的上下文中可能有非常不同的含义。这两个术语可以指代硬件角色——根据硬件设备通常作为客户端还是服务器来命名的标识。这些术语也可以指代软件角色,即协议软件组件是否作为客户端或服务器运行。它们还可以指代事务角色,即设备在数据交换中的任何特定情况下是否作为客户端或服务器。

注意

我讨论的客户端和服务器角色是传统的角色。强大个人电脑的兴起和互联网的普及(尤其是始终在线的宽带连接)导致了客户端和服务器硬件和软件的显著模糊化。许多客户端计算机现在都包括服务器软件,允许它们,例如,响应来自其他客户端的万维网查询。此外,许多文件共享程序允许客户端使用对等结构模型进行通信。然而,大多数 TCP/IP 通信仍然是客户端/服务器性质,因此牢记这些角色很重要

TCP/IP 架构和 TCP/IP 模型

OSI 参考模型的七层将实现网络所需的任务进行了划分,正如本书第 I-2 部分 Part I-2 所描述。然而,这并非唯一的模型。实际上,TCP/IP 协议套件是在 OSI 参考模型之前开发的;因此,其发明者没有使用 OSI 模型来解释 TCP/IP 架构(尽管今天在 TCP/IP 讨论中经常使用 OSI 模型)。TCP/IP 的开发者创建了自己的架构模型,该模型有不同的名称,包括TCP/IP 模型DARPA 模型(以主要负责开发 TCP/IP 的机构命名)和DoD 模型(以美国国防部命名)。大多数人称之为 TCP/IP 模型。

无论你使用哪种模型来表示网络的功能,该模型的功能基本上是相同的。TCP/IP 模型和 OSI 模型实际上非常相似,即使它们在划分网络功能的方式上并不完全相同。

由于 OSI 模型被广泛使用,因此在解释 TCP/IP 架构时,通常会同时从 TCP/IP 层和相应的 OSI 层来阐述。图 8-2 展示了这两个模型之间的关系。TCP/IP 模型没有涉及物理层,即硬件设备所在层。接下来的三个层——网络接口、互联网主机到主机传输——对应 OSI 模型的第 2、3 和 4 层。TCP/IP 的应用层在概念上模糊了 OSI 模型的上三层。请注意,有些人认为 OSI 会话层的一些方面是 TCP/IP 主机到主机传输层的一部分。

如图 8-2 所示,TCP/IP 模型使用四层,逻辑上跨越了 OSI 模型顶部六层的等价部分。(物理层未由 TCP/IP 模型涵盖,因为数据链路层被认为是 TCP/IP 堆栈与底层网络硬件之间接口发生的点。)从底部开始,以下各节将描述 TCP/IP 层。

网络接口层

如其名所示,网络接口层是更高层的 TCP/IP 协议与本地网络接口的地方。这一层有些有争议,因为有些人甚至不认为它是 TCP/IP 的合法部分,通常是因为核心 IP 协议没有在这一层运行。尽管如此,网络接口层是架构的一部分。它相当于 OSI 参考模型中的数据链路层(第 2 层),有时也称为链路层。你也许还会看到使用网络接入层这个名字。

OSI 参考模型和 TCP/IP 模型层 TCP/IP 架构模型有四层,大致对应 OSI 参考模型的七层中的六层。

图 8-2. OSI 参考模型和 TCP/IP 模型层 TCP/IP 架构模型有四层,大致对应 OSI 参考模型的七层中的六层。

在许多 TCP/IP 网络上,这一层根本就没有运行 TCP/IP 协议,因为这根本不是必需的。例如,如果你在以太网上运行 TCP/IP,那么以太网就处理了第 2 层(以及第 1 层)的功能。然而,TCP/IP 标准确实定义了没有自己的第 2 层实现的 TCP/IP 网络协议。这些协议,即串行线路互联网协议(SLIP)和点对点协议(PPP),填补了网络层和物理层之间的空白。它们通常用于促进通过直接串行线路连接(如拨号电话网络)和其他直接在物理层运行的技术上的 TCP/IP。

互联网层

互联网层对应于 OSI 参考模型中的网络层(因此即使在 TCP/IP 模型讨论中,有时也称之为网络层)。它负责典型的第 3 层工作,例如逻辑设备寻址、数据封装、处理和传输,以及路由。在这一层,你可以找到 IP,这可以说是 TCP/IP 的核心,以及支持协议,如互联网控制消息协议(ICMP)和路由协议(RIP、OSFP、BGP 等)。下一代 IP,即 IPv6,也位于这一层。

主机到主机传输层

主机到主机传输层的主要任务是促进在互联网上端到端的通信。它负责允许在设备之间建立逻辑连接,以便数据可以无保证地(没有任何保证它会被送达)或可靠地(协议跟踪发送和接收的数据,以确保其到达,并在必要时重新发送)发送。这里还完成了特定源和目的应用进程的识别。

这个层的正式名称通常被简称为传输层。本层的核心 TCP/IP 协议是 TCP 和 UDP。TCP/IP 传输层对应于 OSI 模型中同名层(第 4 层),但包括某些可以说是 OSI 会话层的一部分的元素。例如,TCP 建立一个可以持续很长时间的连接,这使一些人认为 TCP 连接更像是一个会话。

应用层

应用层是 TCP/IP 模型的最高层。这是一个相当广泛的层,涵盖了 OSI 模型中的第 5 层到第 7 层。虽然与 OSI 模型相比这似乎丢失了一些细节,但这可能是一件好事。TCP/IP 模型更好地反映了 OSI 模型中高层功能之间划分的某种模糊性,这在实际应用中往往显得相当任意。实际上,很难根据它们包含的第 5、6 或 7 层的哪些部分来区分某些协议。

许多协议位于应用层。这些包括提供终端用户服务的应用协议,如 HTTP、FTP 和 SMTP,以及管理协议,如简单网络管理协议(SNMP)、动态主机配置协议(DHCP)和域名系统(DNS)。

注意

互联网和主机到主机的传输层通常被认为是 TCP/IP 架构的核心,因为它们包含了实现 TCP/IP 互连网络的大多数关键协议

在下一节中,我将简要介绍本书详细介绍的每个 TCP/IP 协议,并更详细地说明它们在 TCP/IP 架构中的位置。我还将讨论几个有趣的事实,即这些协议实际上并不很好地适应 TCP/IP 层模型。

提示

关键概念 TCP/IP 协议套件的架构通常用一种称为TCP/IP 模型、DARPA 模型DoD 模型的分层参考模型来描述。TCP/IP 模型包括四个层:网络接口层(负责将套件与它运行的物理硬件接口),互联网层(在这里进行设备寻址、基本数据报通信和路由),主机到主机传输层(在这里管理连接并确保可靠通信),以及应用层(在这里驻留终端用户应用程序和服务)。前三个层分别对应 OSI 参考模型的第 2 层到第 4 层;应用层相当于 OSI 的第 5 层到第 7 层。

TCP/IP 协议

由于 TCP/IP 是一个协议套件,它通常按其组成的协议来讨论。每个协议都位于我刚才讨论的 TCP/IP 架构模型的特定层级,并负责执行实现 TCP/IP 网络或应用所需的总功能的一部分。这些协议共同工作,使 TCP/IP 作为一个整体能够运行。

注意

有时你会听到 TCP/IP 只被称为一个协议而不是协议套件。这是一个简化,虽然技术上不正确,但被广泛使用。我相信这很大程度上是由于微软在它的操作系统中将协议套件称为协议而引起的。我在第一章中更详细地讨论了这个问题

如前所述,一些 TCP/IP 协议通常被称为套件的内核,因为它们负责其基本操作。在这个核心中,大多数人会将互联网和传输层的主要协议包括在内:IP、TCP 和 UDP。这些核心协议支持许多其他协议,以便在每个 TCP/IP 模型层执行各种功能。

注意

总的来说,有数百个 TCP/IP 协议和应用,我无法在本书中涵盖每一个。我确实包括了一些章节,其中我讨论了几十个我认为出于某种原因很重要的协议。这些协议的全面覆盖(以不同详细程度)可以在本书的第二部分和第三部分找到

表 8-1 包含了本书中讨论的每个 TCP/IP 协议的摘要。我已经按照层级组织它们,并为每个协议讨论的章节提供了交叉引用。TCP/IP 协议套中的协议组织也可以通过图 8-3 一目了然。我还在网络接口层展示了 TCP/IP 硬件驱动程序的概念位置;这些驱动程序在 TCP/IP 在 LAN 或 WAN 技术上实现时用于第 2 层,而不是使用 SLIP 或 PPP。

表 8-1. TCP/IP 协议

TCP/IP 层级 协议名称 协议缩写 描述
网络接口(第 2 层) 串行线路互联网协议 SLIP 通过在两个设备之间通过串行线路创建第 2 层连接,提供基本的 TCP/IP 功能。参见第九章。
点对点协议 PPP 提供类似于 SLIP 的第 2 层连接,但更加复杂和强大。PPP 本身是一套协议(如果你愿意称之为子协议),允许进行诸如身份验证、数据封装、加密和聚合等功能,从而促进 TCP/IP 在 WAN 链路上的操作。参见第九章和点对点协议(PPP)概述和基础")至第十二章。
网络接口/互联网(第 2/3 层) 地址解析协议 ARP 用于将第 3 层 IP 地址映射到第 2 层物理网络地址。参见第十三章")。
反向地址解析协议 RARP 从机器的第 2 层地址确定其第 3 层地址。现在主要被 BOOTP 和 DHCP 取代。参见第十四章")。
网络层(第 3 层) 互联网协议,互联网协议版本 6 IP, IPv6 在 TCP/IP 网络上提供传输层消息的封装和无连接交付。还负责寻址和路由功能。参见第二部分-3")和第二部分-4")。
IP 网络地址转换 IP NAT 允许私有网络上的地址自动转换为公共网络上的不同地址,从而提供地址共享和安全优势。(请注意,有些人不认为 IP NAT 在严格意义上是一个协议。)参见第二十八章协议")。
IP 安全 IPsec 一组与 IP 相关的协议,提高了 IP 传输的安全性。参见第二十九章协议")。
互联网协议移动支持 Mobile IP 解决与移动设备相关的某些 IP 问题。参见第三十章")。
互联网控制消息协议 ICMP/ICMPv4, ICMPv6 一种支持 IP 和 IPv6 的协议,为主机提供错误报告和信息请求-响应功能。参见第二部分-6。
邻居发现协议 NDP 一种新的 IPv6 支持协议,包括由传统 IP 中的 ARP 和 ICMP 执行的一些功能。参见第三十六章协议")。
路由信息协议、开放最短路径优先、网关到网关协议、HELLO 协议、内部网关路由协议、增强内部网关路由协议、边界网关协议、外部网关协议 RIP、OSPF、GGP、HELLO、IGRP、EIGRP、BGP、EGP 用于支持 IP 数据报的路由和路由信息交换的协议。参见第二部分-7。
主机到主机传输层(第 4 层) 传输控制协议 TCP TCP/IP 的主要传输层协议。在设备之间建立和管理连接,并确保使用 IP 进行可靠和流量控制的可靠数据传输。参见第二部分-8。
用户数据报协议 UDP 一种可以被认为是 TCP 严重简化版本的传输协议。它用于在应用进程之间以简单的方式发送数据,没有 TCP 的许多可靠性和流量管理功能,但通常效率更高。参见第四十四章。
应用层(第 5/6/7 层) 域名系统 DNS 允许使用名称而不是仅使用数值 IP 地址来引用 IP 设备。允许机器将这些名称解析为其相应的 IP 地址。参见第三部分-1。
网络文件系统 NFS 允许在 TCP/IP 网络上无缝共享文件。参见第五十八章。
引导协议 BOOTP 开发用于解决 RARP 的一些问题,并以类似的方式使用:允许在启动时配置 TCP/IP 设备。通常被 DHCP 取代。参见第六十章。
动态主机配置协议 DHCP 一种用于配置 TCP/IP 设备和管理 IP 地址的完整协议。它是 RARP 和 BOOTP 的后继者,包括许多功能和能力。参见第三部分-3。
简单网络管理协议 SNMP 一种用于网络和设备远程管理的全功能协议。参见第三部分-4。
远程监控 RMON 一种用于远程监控网络设备的诊断“协议”(实际上是 SNMP 的一部分)。参见第六十九章。
文件传输协议,简单文件传输协议 FTP, TFTP 设计允许将所有类型的文件从一个设备传输到另一个设备的协议。见第三部分-6。
RFC 822,多用途互联网邮件扩展,简单邮件传输协议,邮局协议,互联网消息访问协议 RFC 822,MIME,SMTP,POP,IMAP 定义在 TCP/IP 网络上电子邮件消息格式、投递和存储的协议。见第三部分-7。
网络新闻传输协议 NNTP 通过在主机之间传输 Usenet 新闻消息来启用 Usenet 在线社区的操作。见第八十五章。
超文本传输协议 HTTP 在主机之间传输超文本文档;实现了万维网。见第三部分-8。
Gopher 协议 Gopher 一种较老的文档检索协议,现在主要由万维网取代。见第八十六章。
Telnet 协议 Telnet 允许一台机器上的用户在另一台机器上建立远程终端会话。见第八十七章。
Berkeley "r"命令 允许在一台机器上执行另一台机器上的命令和操作。见第八十七章。
Internet 中继聊天 IRC 允许 TCP/IP 用户之间的实时聊天。见第八十七章。
管理和故障排除工具和协议 一组软件工具,允许管理员管理、配置和故障排除 TCP/IP 互连网络。见第八十八章。

TCP/IP 协议 此图展示了本书涵盖的所有 TCP/IP 协议,按 TCP/IP 和 OSI 参考模型层排列(除管理工具外)

图 8-3. TCP/IP 协议 此图展示了本书涵盖的所有 TCP/IP 协议,按 TCP/IP 和 OSI 参考模型层排列(除管理工具外)。

你可以在前一个表格和图中看到,ARP 和 RARP 是异类。在某些方面,它们属于第 2 层和第 3 层,而在其他方面,它们不属于任何一层。它们实际上是为了连接网络接口层和互联网层。因此,我认为它们位于这两层之间,并将它们称为“层连接”协议。参见第第十三章")和第十四章")了解更多相关信息。

第二部分-1. TCP/IP 网络接口层协议

TCP/IP 底层核心协议

TCP/IP 协议套件在很大程度上是通过其构成的协议来定义的,本书涵盖了数十个协议。套件中的大多数关键协议都位于 OSI 参考模型的底层(在第一部分-2 参考模型")中介绍):第 2 层、第 3 层和第 4 层,这对应于 TCP/IP 模型架构中的网络接口、互联网和传输层(在第一部分-3 中描述)。这里包括至关重要的第 3 层互联网协议(IP)和第 4 层的传输控制协议(TCP),它们共同构成了 TCP/IP 的名称。

由于这些和其他 TCP/IP 协议在底层的重要性,这是本书三个部分中最大的一个。它包含八个部分。第一部分描述了位于网络接口层(OSI 参考模型的第 2 层)的两个 TCP/IP 协议:点对点协议(PPP)和串行线路接口协议(SLIP)。第二部分描述了位于第 2 层和第 3 层之间架构上的几个特殊协议:地址解析协议(ARP)和反向地址解析协议(RARP)。第三和第四部分描述了 IP 版本 4 和 6(IPv4 和 IPv6)。第五和第六部分讨论与 IP 相关的功能和支持协议,第七部分描述 IP 路由协议。最后,第八部分涵盖了两个 TCP/IP 传输层协议:传输控制协议(TCP)和用户数据报协议(UDP),以及相关的主题,例如 TCP/IP 端口的使用。

第九章 和点对点协议 (PPP) 概述和基础")

第十章

第十二章

OSI 参考模型的最底层是物理层,它负责在网络上从一处传输信息到另一处的细节。物理层之上的层是 数据链路层,在 TCP/IP 架构模型中被称为 网络接口层,或简称为 链路层。其主要任务是实施本地网络,并在以硬件为导向的物理层和更抽象的、以软件为导向的网络层及其以上各层之间进行接口。

在 TCP/IP 的情况下,互联网协议(IP)是第 3 层的核心协议,它是整个 TCP/IP 协议套件的基础。IP 被设计成可以建立在任何数量的第 2 层技术之上。然而,某些类型的连接不包括 IP 可以运行的第 2 层协议。为了使 TCP/IP 能够在这些类型的链路上运行,有两种特殊的 TCP/IP 协议在网络接口层运行,将 IP 连接到下面的物理层。

在本部分,我提供了关于 TCP/IP 协议套件中位于数据链路或网络接口层的两个协议的描述。这些是较旧的简单串行线路接口协议(SLIP)和较新的、功能更强大的点对点协议(PPP)。我首先用一个章节简要概述 SLIP 和 PPP,展示它们如何融入整个 TCP/IP 协议套件,并以一般术语描述它们。

本部分其余部分包含三个章节,详细描述了两个协议中更为重要的 PPP 协议。这三个章节中的第一个解释了负责设置 PPP 链路和基本操作的核心理议。第二个章节涵盖了用于实现 PPP 中各种特殊功能的协议,例如压缩和加密。PPP 的最后一章提供了关于 PPP 协议使用的各种帧格式的详细信息。

第九章:TCP/IP 串行线路互联网协议(SLIP)和点对点协议(PPP)概述和基础

无标题图片

TCP/IP 的核心协议在 OSI 模型的第 3 层和第 4 层运行,对应于 TCP/IP 架构模型中的互联网层和主机到主机的传输层(在第八章中介绍)。该模型还定义了网络接口层,对应于数据链路层。然而,在大多数网络实现中,TCP/IP 没有定义在这一层运行的任何协议。相反,TCP/IP 假设第 2 层功能由广域网(WAN)或局域网(LAN)技术,如以太网、令牌环或 IEEE 802.11 提供。这些技术负责经典的第 2 层功能:物理层寻址、媒体访问控制,特别是,从第 3 层接收的数据报的第 2 层帧格式。

假设互联网协议(IP)可以建立在现有的第 2 层协议之上是有问题的,因为有时并不存在这样的协议。某些技术,如两个设备之间简单的串行连接,仅在物理层建立基本、低级的连接。当然,一种串行连接仍然非常流行:串行拨号网络。当你通过拨号调制解调器连接到你的 ISP 时,调制解调器协商的连接在架构上仅存在于物理层。

由于 IP 假设某些服务将在第 2 层提供,因此无法使其直接在串行线或其他物理层连接上运行。至少,最重要的第 2 层功能是需要某种机制来对 IP 数据报进行封装以进行传输;也就是说,提供必要的数据封装机制,以便数据报能够在物理层网络上传输。没有这个机制,IP 数据报就无法在链路上发送。

SLIP 与 PPP 的比较

为了填补第 3 层的 IP 和第 1 层的物理连接之间的差距,有两个协议在第 2 层运行并提供 IP 运行所需的服务。一个协议是串行线互联网协议(SLIP),一个非常简单的第 2 层协议,只为 IP 提供基本的封装。另一个是点对点协议(PPP),一个更复杂、功能更全面的链路层协议,提供封装以及许多其他改进安全和性能的功能。

SLIP 非常简单且易于实现,但缺乏 PPP(如认证、压缩和错误检测)的一些功能,而 PPP 功能全面但更复杂。为了进行类比,SLIP 就像一辆结实、十年级的紧凑型轿车,而 PPP 则像一辆闪亮的、全新的豪华 SUV。两者都能让你从这里到奶奶家,但 SUV 将更安全、更舒适,并能更好地处理路上可能出现的问题。如果它们购买和运营成本相同,你可能会选择 SUV。SLIP 和 PPP 的成本大致相同,而且与 SUV 不同,PPP 不会造成空气污染,也不会大量消耗汽油。因此,PPP 是今天大多数串行线连接的选择,几乎取代了 SLIP。

提示

关键概念 SLIPPPP 为直接在物理层链路上运行而没有第 2 层技术的 TCP/IP 实现提供第 2 层连接。虽然 SLIP 更简单,但由于其许多功能和能力,PPP 更受欢迎。

SLIP 和 PPP 都是为了连接仅两个设备而设计的;因此,称为点对点协议。由于只有两个设备,A 和 B,通信是直接的:A 发送给 B,B 发送给 A,由于它们只处理简单的两设备连接,因此它们不需要像以太网等技术那样管理媒体访问控制、冲突和独特的寻址方案等复杂性。

注意

有些人不认为 SLIP 和 PPP 是真正的 TCP/IP 协议套件的一部分。他们认为 TCP/IP 在 OSI 模型的第 3 层及以上被定义,IP 是 TCP/IP 在第 3 层的基础,而 SLIP 和 PPP 只是可以在 TCP/IP 下使用的额外协议。为了支持他们的论点,他们指出 PPP 可以用于除了 IP 之外的协议,这是事实

串行线互联网协议(SLIP)

在 TCP/IP 的开发早期就确定了需要一个数据链路层协议,以便 IP 能够在串行链路上运行。在 IP 上工作的工程师需要一种方法来通过串行链路发送 IP 数据报。为了解决这个问题,他们创建了一个非常简单的协议 SLIP,用于在串行线上传输 IP 消息的帧。

与大多数 TCP/IP 协议不同,SLIP 从未被定义为正式标准。它是在 20 世纪 80 年代初非正式创建的,在它被描述在请求评论(RFC)之前就已经成为事实上的标准。当它在 1988 年发布(RFC 1055,“在串行线上传输 IP 数据报的非标准:SLIP”)时,决定将其指定为“非标准协议”。

SLIP 被指定为非标准,因为它被开发为一个非常原始的临时措施,以在需要时提供第 2 层帧。SLIP 非常简单,以至于实际上没有什么可以标准化的。此外,它有太多的缺陷,以至于互联网工程任务组(IETF)显然不想将其正式化为标准。RFC 1055 特别提到了 SLIP 的各种问题(我将在本章后面讨论),以及已经开始定义 PPP 作为 SLIP 更强大的继任者的工作。

小贴士

关键概念 SLIP 为 IP 数据报提供第 2 层帧服务,但没有其他功能或能力。

SLIP 数据帧方法及一般操作

SLIP 只执行一个功能:为传输数据帧。以下是 SLIP 帧的工作方式。一个 IP 数据报被传递到 SLIP,它将其分解成字节,并将这些字节逐个发送到链路上。在发送完数据报文的最后一个字节后,发送一个特殊的字节值,告诉接收设备数据报文已经结束。这被称为 SLIP 的END 字符,其十进制值为 192(十六进制为 C0,二进制为 11000000)。这就是 SLIP 帧的精髓:将整个数据报文发送,一次发送一个字节,然后发送字节 192 来界定数据报文的结束。

对 SLIP 基本操作的一个小改进是在数据报文前也加上一个END字符,从而清楚地分隔数据报文的开始和它之前的内容。为了理解为什么可能需要这样做,你可以想象在某个特定时间你只有一个数据报文要发送:数据报文 1。你发送 1,然后发送END字符来界定它。现在,假设在下一个数据报文出现之前有一个暂停。在这段时间里,你没有传输,但如果有线噪声,另一台设备可能会在这里和那里接收到虚假的字节。如果你后来收到数据报文 2 并且开始发送它,接收设备可能会认为噪声字节是数据报文 2 的一部分。

从数据报 2 开始使用END字符告诉接收方,在此END字符和前一个END字符之间接收到的任何内容都是单独的数据报。如果这只是噪音,那么这个“噪音数据报”只是无意义的文本,将在 IP 层被拒绝。同时,它不会破坏你希望发送的真实数据报。如果在数据报之间的线路上没有发生噪音,那么接收方将只看到数据报 2 开始处的END字符,紧随数据报 1 结束处的END字符之后,并忽略两者之间的“空数据报”。

但如果END字符的十进制值为 192;如果数据报本身出现字节值 192,会发生什么?按原样传输它会让接收方误以为数据报提前结束。为了避免这种情况,定义了一个转义字符 (ESC),其十进制值为 219(十六进制 DB,二进制 11011011)。这个符号意味着“这个字节和下一个字节是特殊的。”当数据报中出现 192 的值时,发送设备将其替换为 ESC 字符后跟十进制值 220。因此,单个 192 变为 219 220(或十六进制的 DB DC)。接收方将 219 220 转换回 192。

注意

SLIP ESC 字符与 ASCII ESC *字符不同。它们都执行一个“转义”操作,但除此之外没有其他关联。如果 ESC 字符本身就在原始数据报中——也就是说,如果 IP 数据报中要发送的字节值为 219——则设备使用 219 221 而不是仅仅使用 219。

总结来说,SLIP 执行以下操作:

  • 将 IP 数据报拆分为字节

  • 在数据报的最后一个字节之后发送END字符(值为 192);在更好的实现中,它还在第一个字节之前发送END字符

  • 将数据报中要发送的任何字节值为 192 的字节替换为 219 220

  • 将要发送的任何字节值为 219 的字节替换为 219 221

图 9-1 的操作。SLIP 的唯一功能是通过在数据报周围添加 END 字符并替换所需的特殊字符来封装来自第 3 层(通常是 IP 数据报)的数据。")展示了如何使用示例 IP 数据报来完成这一操作。IP 数据报在第二层(这里显示的是一个简化的版本,只有五个字节)传递到 SLIP 软件。在那里,它们被封装,通过在它们周围添加END字符(十六进制值 C0h,以斜线阴影显示)。具有十六进制值 DBh 和 C0h 的特殊字符被替换为双字节序列。请注意,括号END字符的存在迫使接收设备将噪音字节(03h,黑色)视为单独的 IP 数据报,而不是真实数据报的一部分。当它被传递到 IP 层时将被拒绝。

SLIP 的问题和局限性

SLIP 的简单性并非没有代价。SLIP 简单地没有提供你在现代串行链路上真正需要的许多功能和能力。SLIP 在以下方面最缺乏:

标准化的数据报大小规范 SLIP 支持的最大数据报大小没有标准化,并且取决于每个实现。通常的默认值是 1,006 字节,这成为链路的最大传输单元(MTU)(见第二十七章

图 9-1. 串行线路互联网协议(SLIP)的操作 SLIP 的唯一功能是通过围绕它们放置 END 字符并根据需要替换特殊字符来封装来自第三层(通常是 IP 数据报)的数据。

错误检测和纠正机制 SLIP 不提供任何检测或纠正传输中错误的方法。虽然通过 IP 头部校验和等机制在高层提供了这样的保护,但这项工作传统上也在第二层完成。原因是依赖于那些高层意味着错误只有在整个数据报发送并返回到接收方的堆栈后才会被检测到。错误纠正只能通过重新发送任何损坏的数据报来实现。这效率低下,尤其是在串行链路通常比普通局域网链路慢得多的情况下。

控制信息 SLIP 没有提供两种设备之间通信可能需要的管理链路控制信息的方法。

类型识别 由于 SLIP 没有自己的头部信息,因此无法识别正在使用 SLIP。虽然它是为 IP 设计的,但没有理由其他第三层协议不能使用 SLIP(如果你在高层运行多个互连网络协议)。然而,没有类型识别,就没有办法在同一个链路上混合来自两个或更多第三层协议的数据报。

地址发现方法 在第二层不需要寻址,因为在点对点连接中只有两个设备,所以每个设备显然只向另一个设备发送数据。然而,设备确实需要某种方式来学习彼此的 IP 地址以在第三层进行路由。SLIP 没有提供这种方法。

压缩支持 压缩可以提高与其他技术相比本来较慢的串行线路的性能。SLIP 没有提供压缩功能。(然而,请注意,调制解调器通常在第一层支持使用它们的串行连接的压缩。)在 20 世纪 80 年代末,创建了一个名为压缩 SLIPCSLIP的 SLIP 变体,但它并没有像常规 SLIP 那样得到广泛部署。

安全特性 SLIP 缺乏甚至基本的安全特性,没有认证连接或加密数据的方法。

SLIP 的许多缺点导致大多数实现从 SLIP 迁移到 PPP,PPP 是一个更丰富的数据链路协议,用于直接连接,解决了 SLIP 的问题。SLIP 现在已经过时。尽管如此,SLIP 仍然在许多地方被使用。简单性很有吸引力,人们以其惯性而闻名:如果某事物被实施并且运行良好,许多人会拒绝改变,除非他们被迫这样做。

点对点协议(PPP)概述和基础

即使 SLIP 正在被记录,关于一种新协议的工作也在进行中,该协议将在成对的设备之间的直接链路上提供全功能的 IP 传输。结果是PPP,它定义了使用串行线路或其他物理层设备之间稳健数据链路连接的完整方法。它包括许多功能和特性,包括错误检测、压缩、认证和加密。

串行链路的激增,尤其是对于拨号互联网接入,导致了 PPP 的广泛应用。PPP 现在是网络世界中最受欢迎的第 2 层广域网技术之一,并已取代 SLIP,成为除了旧实现之外所有串行连接的标准。虽然 PPP 通常与拨号调制解调器的使用相关联,但它可以跨越任何类似类型的物理层链路运行。例如,它通常用于在综合业务数字网络(ISDN)上提供第 2 层功能。

注意

尽管 PPP 被称为协议,通常被认为是 TCP/IP 的一部分,但它实际上更像是一个协议套件,因为它的操作基于许多单个协议中定义的程序。或者,其组件可以被视为 PPP 内的子协议,尽管在标准中通常不这样称呼它们

开发和标准化

与 SLIP 不同,PPP 的开发是为了成为一个完整的协议套件,它将能够支持完全功能的第 2 层连接,不仅支持 IP,还支持其他网络层协议的传输。

PPP 的历史可以追溯到 20 世纪 80 年代末,当时 SLIP 是串行 IP 实现的既定标准。与 PPP 相关的第一个正式的 IETF 文档是 RFC 1134(1989 年)。这个 RFC 本身并不是标准,而是一个提案,最终被定义为第一个主要 PPP 标准 RFC 1171(1990 年)。RFC 1171 经过多次修订,并添加了几个其他文档来定义构成整个 PPP 套件的各个协议。

与其从头开始开发 PPP,IETF 决定基于 IBM 最初开发的 ISO 高级数据链路控制(HDLC)协议,该协议是同步数据链路控制(SDLC)协议的衍生品。PPP 的开发者从 HDLC 中采用了其帧结构及其一些通用操作

功能和架构

PPP 是一种面向连接的协议,它能够在各种不同的物理层连接上建立第 2 层链路。它支持同步和异步线路,可以在半双工或全双工模式下操作。它被设计用来携带 IP 流量,但足够通用,允许任何类型的网络层数据报通过 PPP 连接发送。正如其名称所暗示的,PPP 是为两个设备之间的点对点连接而设计的,并且它假定帧是按照相同的顺序发送和接收的。

PPP 在网络接口层(链路层)中与 TCP/IP 相匹配,如图图 9-2 所示。PPP 的操作遵循一个特定的顺序,包括一个可能包含可选认证的多步骤链路建立阶段。

PPP 在 TCP/IP 架构中的位置 PPP 是 IP 与物理链路(如串行线或拨号网络连接)之间的接口。这对应于 OSI 参考模型中的第 2 层。

图 9-2. PPP 在 TCP/IP 架构中的位置 PPP 是 IP 与物理链路(如串行线或拨号网络连接)之间的接口。这对应于 OSI 参考模型中的第 2 层。

优点和好处

PPP 的优点列表在很大程度上类似于 SLIP 的弱点列表,如本章前面所述。PPP 的一些具体好处包括以下内容:

  • 与 SLIP 中的单个END字符相比,更全面的帧机制

  • 封装协议的规范,以允许多个第 3 层协议在单个链路上复用

  • 通过在每个帧的帧头中使用循环冗余检查(CRC)代码来检测每个传输帧的错误

  • 一种强大的协商链路参数的机制,包括允许的最大帧大小

  • 在数据报传输之前测试链路的方法以及监控链路质量的方法

  • 支持使用多个认证协议对连接进行认证

  • 支持额外的可选功能,包括压缩、加密和链路聚合(允许两个设备使用多个物理链路,就像它们是一个单一的高性能链路一样)

串行链路的激增,尤其是对于拨号互联网访问,导致了 PPP 的广泛应用。现在,它是网络世界中最受欢迎的第 2 层广域网技术之一,并且已经取代了 SLIP,成为除了旧实现之外所有串行连接的标准。虽然 PPP 通常与拨号调制解调器的使用相关联,但它可以运行在任何类似的物理层链路上。例如,它通常用于在 ISDN 上提供第 2 层功能。

小贴士

关键概念 PPP 是为使用 TCP/IP 的设备提供的完整的链路层协议套件。它提供了帧定界、封装、认证、质量监控和其他功能,这些功能使得 TCP/IP 能够在各种物理层连接上稳健运行。

PPP 的一个关键优势是它具有可扩展性。多年来,为了提供额外的功能或能力,已经向该套件中添加了新的协议。例如,PPP 设计为不仅仅使用单个认证协议,而是允许选择。

PPP 的成功甚至导致了派生协议的发展,如以太网上的 PPP(PPPoE)和 ATM 上的 PPP(PPPoA)。这些派生协议实际上是在现有的数据链路层技术之上叠加 PPP,这证明了 PPP 功能的价值。即使已经使用了第 2 层技术,也可以在顶部应用 PPP,为数字用户线路(DSL)等服务提供认证和管理优势。

PPP 主要组件

在最高级别,PPP 的功能可以分为几个组件。每个组件都包含 PPP 功能的一般类别,并由套件中的一个协议或一组协议表示。PPP 标准描述了 PPP 的三个主要组件:

PPP 封装方法 PPP 的主要任务是取更高层的消息,例如 IP 数据报,并将它们封装以通过底层物理层链路进行传输。为此,PPP 定义了一种特殊的帧格式,用于封装数据以进行传输,该格式基于 HDLC 中使用的帧定界。PPP 帧被设计得小巧,只包含简单的字段,以最大限度地提高带宽效率和处理速度。

链路控制协议(LCP) LCP 负责设置、维护和终止设备之间的链路。它是一种灵活、可扩展的协议,允许交换许多配置参数,以确保两个设备就如何使用链路达成一致。

网络控制协议 (NCPs) PPP 支持封装多种不同的第三层数据报类型。其中一些在激活链路之前需要额外的设置。一旦使用 LCP 完成了一般的链路设置,控制权就传递给特定于 PPP 链路上传输的第三层协议的 NCP。例如,当 IP 通过 PPP 传输时,使用的 NCP 是 PPP 互联网协议控制协议 (IPCP)。其他 NCPs 定义用于支持互联网包交换 (IPX) 协议、NetBIOS 数据包 (NBF) 协议等。

PPP 封装方法和 LCP 定义在主要的 PPP 标准和一些支持标准中;NCPs 在单独的标准文档中描述,每个 NCP 一个文档。

PPP 功能组

虽然 PPP 的主要组件构成了总包的大部分,但我还会添加两个额外的功能组。这些代表了随着时间的推移添加到套件中的许多额外协议,以支持或增强其基本操作:

LCP 支持协议 PPP 套件中的几个协议在链路协商过程中使用,用于管理或配置选项。例如,挑战握手认证协议 (CHAP) 和密码认证协议 (PAP) 是在可选的认证阶段由 LCP 使用的认证协议。这些内容在第十章中有讨论。

LCP 可选功能协议多年来,许多协议被添加到基本的 PPP 套件中,以增强链路设置后和设备之间传输数据报的操作。例如,PPP 压缩控制协议 (CCP) 允许压缩 PPP 数据;PPP 加密控制协议 (ECP) 允许对数据报进行加密以提高安全性;PPP 多链路协议 (PPP MP) 允许单个 PPP 链路在多个物理链路上运行。这些协议通常在链路协商期间也需要额外的设置,因此许多它们定义了扩展(例如额外的配置选项),这些扩展作为 LCP 协商的一部分。

注意

每个可选协议都由一个特定的标准文档定义,正如你将在本章后面看到的那样

一般操作

虽然 PPP 套件包括数十个协议,但其一般操作实际上非常简单。基本上,PPP 涉及以下三个基本步骤(参见图 9-3):

  1. 链路设置和配置 在两个设备可以交换信息之前,它们必须相互联系并设置它们之间的链路。在链路设置过程中,设备就管理链路操作所需的所有参数达成一致。LCP 开始这个过程,并在需要时调用支持协议,例如身份验证。一旦链路建立,为了完成链路设置,将调用适当的 NCP 来处理链路上传输的任何第三层技术。

  2. 链路操作 设备使用链路发送数据报。每个设备通过封装第三层数据报并将其发送到第 1 层进行传输来传输。每个设备通过从自己的物理层接收发送上来的 PPP 帧,移除 PPP 头部并将数据报传递到第 3 层来接收。在适当的情况下,使用可选协议提供如压缩(CCP)等功能。

  3. 链路终止 当任一设备决定不再想要通信时,它会终止链路。

PPP 操作的概述 以最简单的术语来说,PPP 只包含三个基本步骤:链路设置、链路操作和链路终止。

图 9-3. PPP 操作的概述 以最简单的术语来说,PPP 只包含三个基本步骤:链路设置、链路操作和链路终止。

链路设置是这些一般步骤中最复杂的,因为它涉及几个子步骤,用于协商链路参数和选项。

PPP 链路设置和阶段

在 PPP 连接上交换数据之前,必须在两个设备之间建立链路。作为此设置任务的一部分,进行配置过程,其中设备配置链路并就数据如何在他们之间传输的参数达成一致。只有完成这一步骤后,帧才能实际通过链路传输。

LCP 通常负责设置和维护 PPP 链路。当 PPP 配置为使用身份验证时,LCP 可能会调用一个身份验证协议(PAP 或 CHAP)。一旦 LCP 链路已打开,PPP 将调用一个或多个 NCP 来处理链路上传输的第三层协议。这些 NCP 执行在链路能够携带特定网络层协议之前所需的任何网络层特定配置。

PPP 链路的操作可以描述为具有一定的生命周期:PPP 链路建立、配置、使用,最终终止。设置、使用和关闭 PPP 链路的过程在 PPP 标准中被描述为一系列阶段状态。这是一种有限状态机(FSM),它是用来解释协议操作的工具。有限状态机背后的基本概念在讨论传输控制协议(TCP)的有限状态机的章节中描述,见第四十七章。

为了更好地理解 PPP 是如何工作的,让我们看看这些阶段,以及链路生命周期中从一个阶段过渡到下一个阶段是如何进行的。为了清晰起见,这个描述基于一个例子,其中设备 A 是通过拨号网络连接到远程主机 B 的 PC(参见图 9-4)。

注意

当我们总体上谈论 PPP 链路时,我们是在谈论两个设备之间的 LCP 连接状态。一旦打开了一个 LCP 链路,链路上的每个 NCP 都可以独立于整体的 PPP(LCP)链路打开或关闭。你很快就会看到这是如何工作的

链路死亡阶段

设计上,PPP 链路始终从链路死亡阶段开始和结束。这个阶段表示两个设备之间没有建立物理层链路的情况。链路将保持在这个阶段,直到物理层链路建立,此时它将进入链路建立阶段。

在这个例子中,当设备 A 首次开启时,它与设备 B 之间没有物理层连接(调制解调器连接)。一旦建立连接,链路就可以进入第 2 阶段。

注意

在直接连接中,例如通过串行电缆连接两个 PC,链路可能只保持在链路死亡阶段几秒钟,直到检测到物理层连接

链路建立阶段

物理层现在已连接,LCP 执行链路的基本设置。设备 A 通过物理链路向设备 B 发送一个 LCP 配置请求消息,指定它希望使用的参数。如果设备 B 同意,它将回复一个确认。如果设备 B 不同意,它将返回一个否定确认或拒绝,告诉设备 A 它不接受什么。然后设备 A 可以尝试使用设备 B 可能接受的新的参数的不同配置请求。(这个过程在第十章中有更详细的描述。)

如果设备 A 和设备 B 最终达成一致,链路状态被认为是LCP 打开,并将进入认证阶段。如果它们无法达成一致,物理链路将被终止,并返回到链路死亡阶段。

认证阶段

在许多情况下,设备可能需要在允许另一个设备连接之前进行认证。(这通常是在使用 PPP 进行拨号时的情况。)然而,在 PPP 中认证不是强制的。当使用时,将采用适当的认证协议(CHAP 或 PAP)。

在认证成功后,链路将进入网络层协议阶段。如果认证不成功,链路将失败并过渡到链路终止阶段。

网络层协议阶段

一旦基本链路配置完成并且认证完成,LCP 链路的一般设置就完成了。现在,通过调用适当的 NCP,如 IPCP、IPXCP 等,执行适当的网络层协议的具体配置。

每个成功配置了 NCP 的特定网络层协议被认为在 LCP 链路上是开启的。一个 PPP 链路上可以开启多个 NCP,并且当不再需要时,每个都可以独立关闭。一旦所有必要的 NCP 都已被调用,链路将进入链路开启状态,即使没有任何 NCP 成功开启。

注意

某些 PPP 特性需要在两个设备之间协商额外的选项,这些设备在网络层协议阶段可能会执行自己的链路建立过程。PPP 压缩控制协议(CCP)以这种方式设置数据压缩

链路开启阶段

在链路开启状态下,LCP 链路和一个或多个 NCP 链路是开启并操作的。对于每个成功设置的 NCP,都可以传递数据。

链路可以因各种原因在任何时间由任一设备终止。这些原因可能包括用户请求(当你想要断开拨号会话时,你点击断开连接);链路质量问题(由于线路噪音,调制解调器挂断);或其它原因(你在洗手间花费了太多时间,你的 ISP 的闲置计时器将你登出)。当这些情况中的任何一种发生时,LCP 链路被中断,链路进入链路终止阶段。

链路终止阶段

终止链路的设备发送一个特殊的 LCP 终止帧,另一个设备确认它。然后链路返回到链路死亡阶段。如果终止是请求的,并且物理层连接仍然活跃,PPP 实现应该特别向物理层发出信号以终止第 1 层连接。

你应该记住,基本链路是由 LCP 建立的,NCP 链路是在 LCP 链路内设置的。关闭 NCP 链路不会导致 LCP 链路关闭。即使所有 NCP 都关闭,LCP 链路仍然保持开启状态。(当然,在适当的 NCP 链路重新建立之前,无法传递数据;需要设备丢弃包含任何没有开启 NCP 的第 3 层协议的帧。)要终止 PPP 连接,只需要在链路终止阶段终止 LCP 链路;NCP 不需要显式关闭。

图 9-4 展示了 PPP 阶段及其之间转换发生的情况。两个设备之间的 PPP 连接从链接失效状态开始,经过三个中间阶段,直到链接完全开启。它保持在稳定的链接开启阶段,直到终止。较浅的框显示了在阶段之间转换时 PPP 链接状态的相应变化。

PPP 阶段 一个 PPP 连接遵循从链接失效阶段通过链接开启阶段的主要线性转换序列。

图 9-4. PPP 阶段 一个 PPP 连接遵循从链接失效阶段通过链接开启阶段的主要线性转换序列。

表 9-1 总结了 PPP 阶段;LCP 链接状态和 NCP 链接状态列显示了阶段开始时链接的状态。

PPP 标准

虽然 PPP 的不同部分由不同的标准覆盖是有意义的,但这确实使得学习 PPP 的工作原理变得更加困难。此外,确实有数十个 RFC 涵盖了 PPP 的主要操作、其各种协议和其他相关问题。您可以通过查阅 RFC 的主列表并搜索字符串“PPP”来找到它们,但您将按数字顺序(RFC 编号)找到它们,这在协议的使用方面意义不大。您还必须区分当前的和过时的 RFC。

表 9-1. PPP 阶段

阶段/状态 阶段摘要 进入阶段时的 LCP 链接状态 进入阶段时的 NCP 链接状态 转换要求 转换到阶段
链接失效 默认状态;物理层未连接。 关闭 关闭 成功的物理层连接 链接建立
链接建立 物理层已连接,链路的基本配置由 LCP 执行。 关闭 关闭 成功协商 认证
未成功的谈判 链接失效
认证 基本链接现在已开启,并执行设备可选认证。 开启 关闭 成功认证或无需认证 网络层协议
认证失败 链接终止
网络层协议 一个或多个 NCP 在 LCP 链接内打开 NCP 链接。 开启 关闭 所有 NCP 已开启 链接开启
链接开启 链接开启并正常运行。 开启 开启 链接故障或关闭请求 链接终止
链接终止 LCP 链接关闭。 开启 开启 链接失效

表 9-2 列出了最重要的和有趣的 PPP 相关 RFC。为了更容易地了解 RFC 的内容,我已经将它们组织成五个组,如下所示:

核心 这些是 PPP 的主要文档。它们涵盖了 PPP 的基本操作,包括 PPP LCP 和数据报封装。

LCP 支持 这些协议支持 LCP 的基本操作。我只包括在链路启动期间提供认证服务的那些协议。

NCPs 这些协议协商 PPP 承载的各种第 3 层协议的特定参数。

功能 这些协议定义了与 PPP 一起使用的可选功能,例如压缩和加密。

应用和杂项 这些是描述 PPP 如何适应在特定类型的链路上运行或实际上不适合任何前述组的协议。

在每个组内,RFC 按数字顺序列出,也就是日期顺序。只列出最新的 RFC,不包括已被废弃的较早的 RFC(除了 RFC 1334,尽管已被废弃,但仍然很重要)。

表 9-2. PPP 标准

RFC 编号 标准名称 描述
核心 1570 PPP LCP 扩展 定义了两个 LCP 功能,允许设备相互识别,并让每个设备告诉对方当前会话剩余多少时间。
1661 点对点协议(PPP) PPP 的基本标准。描述了 PPP 架构、一般操作(包括链路建立、维护和终止的过程)以及 LCP 的详细信息。
1662 类似于 HDLC 的 PPP 帧 定义了 PPP 帧的具体帧格式,基于在 HDLC 中使用的格式。这个标准可以被认为是主要 PPP 标准 RFC 1661 的补充。
LCP 支持 1334 PPP 认证协议 定义了两个 PPP 认证协议:PAP 和 CHAP。请注意,RFC 1994 废弃了 RFC 1334,但没有讨论 PAP。(这表明 IETF 对 PAP 的看法不高;有关更多信息,请参阅第十章。)
1994 PPP 挑战握手认证协议(CHAP) 更新了 RFC 1334 中提供的 CHAP 信息。
NCPs 1332 PPP 互联网协议控制协议(IPCP) IP 的 NCP。
1377 PPP OSI 网络层控制协议(OSINLCP) OSI 协议套件网络层协议(如 CNLP、ES-IS 和 IS-IS)的 NCP。
1378 PPP AppleTalk 控制协议(ATCP) AppleTalk 协议的 NCP。
1552 PPP 互连包交换控制协议(IPXCP) Novell IPX 协议的 NCP。
2043 PPP SNA 控制协议(SNACP) IBM 系统网络架构(SNA)的 NCP。
2097 PPP NetBIOS 帧控制协议(NBFCP) NetBIOS 帧(NBF,也常称为 NetBEUI)的 NCP。
2472 PPP 上的 IPv6 版本 IPv6 的 NCP:IPv6 控制协议(IPv6CP)。
功能 1962 PPP 压缩控制协议(CCP) 定义了一种压缩通过 PPP 链路发送的数据的机制,以提高性能。本标准描述了如何在 PPP 链路上的两个设备之间协商压缩。它与几个实际执行数据压缩的压缩算法一起使用。
1968 PPP 加密控制协议(ECP) 定义了一种加密通过 PPP 链路发送的数据的机制,以提高性能。本标准描述了如何在两个设备之间协商加密。它与几个加密算法一起使用。
1989 PPP 链路质量监控 定义了一种协议,允许 PPP 设备相互生成关于链路质量的报告。
1990 PPP 多链路协议(MP) 定义了在一系列聚合链路上运行 PPP 的方法,从而允许两个设备将多个低带宽链路作为一个单一的高带宽虚拟链路使用。
2125 PPP 带宽分配协议(BAP)/PPP 带宽分配控制协议(BACP) 定义了两个支持协议,用于管理使用 PPP MP 聚合的链路上的带宽分配。
应用和杂项 1618 PPP over ISDN 描述了在 ISDN 链路上运行 PPP 的应用特定细节。
1973 PPP 在帧中继上 描述了如何修改 PPP 以在第二层上通过帧中继运行。
2290 PPP IPCP 的移动 IPv4 配置选项 定义了对 PPP 互联网协议控制协议(IPCP)的更改,以支持移动 IP。
2364 PPP over AAL5 定义了一种在 AAL5(ATM)上发送 PPP 帧的方法,通常称为 PPPoA。
2516 通过以太网(PPPoE)传输 PPP 的方法 定义了一种封装 PPP 帧通过以太网(PPPoE)的技术。
2615 PPP over SONET/SDH 讨论了如何在 SONET/SDH 链路上封装 PPP 帧。

第十章. PPP 核心协议:链路控制、网络控制和认证

无标题图片

本章描述了负责 PPP 链路设置和基本操作的协议,包括链路控制协议(LCP)和用于配置 PPP 以适应不同第 3 层协议的网络控制协议(NCPs)。我还讨论了两个 PPP 认证协议,密码认证协议(PAP)和挑战握手认证协议(CHAP),它们用于在链路设置期间提供认证。

链路控制协议(LCP)

在所有 PPP 套件协议中,LCP 是最重要的。它负责 PPP 的整体成功运行,并在每个 PPP 链路阶段(配置、维护和终止,如第九章所述)中发挥关键作用(第九章)。链路配置在初始链路建立阶段执行;链路维护在链路开启期间进行;链路终止发生在链路终止阶段。

图 10-1 概述了 LCP 在 PPP 连接的不同阶段执行的大多数消息交换。链路配置在此显示为简单的配置请求和配置确认的交换。在随后的交换中使用其他 PPP 协议进行身份验证和配置一个或多个 NCP 之后,链路进入链路开启阶段。在此示例中,首先使用 Echo-Request 和 Echo-Reply 消息来测试链路,然后是两个设备发送和接收数据。显示了一个数据消息因代码字段无效而被拒绝。最后,使用终止请求和终止确认消息终止链路。

PPP 链路控制协议(LCP)消息交换 此图显示了 LCP 在链路配置、维护和终止期间执行的不同消息交换

图 10-1。PPP 链路控制协议(LCP)消息交换 此图显示了 LCP 在链路配置、维护和终止期间执行的不同消息交换

LCP 数据包

设备使用 LCP 通过在它们之间的物理链路上发送 LCP 消息来控制 PPP 链路。这些消息被称为LCP 数据包LCP 帧。尽管标准使用数据包,但术语更受欢迎,因为第 2 层消息通常被称为帧。主要 PPP 文档定义了 11 种不同的 LCP 帧,这些帧分为三个组,分别对应三个链路阶段。四种 LCP 帧类型用于链路配置,五种用于维护,两种用于终止。

在下一节中,我将讨论 LCP 的三个主要功能以及在每个功能中如何使用帧。(第十二章描述了数据包本身的帧格式。)

LCP 链路配置

链路配置可以说是 LCP 在 PPP 中最重要的工作。在链路建立阶段,两个物理连接的设备交换 LCP 帧,以帮助它们协商链路将运行的条件。图 10-2 显示了整个过程。

此过程从发起设备(设备 A)创建一个包含它希望设置在链路上的配置选项的可变数量的配置请求帧开始。这基本上是设备 A 的“愿望清单”,说明了它希望如何创建链路。

PPP LCP 链路配置过程 LCP 配置链路所进行的协商过程。此过程从 PPP 链路进入链路建立阶段开始。配置成功后,连接过渡到认证阶段。

图 10-2。PPP LCP 链路配置过程 LCP 配置链路所进行的协商过程。此过程从 PPP 链路进入链路建立阶段开始。配置成功后,连接过渡到认证阶段。

RFC 1661,主要的 PPP 文档,定义了发起者可以在该请求中指定的多个不同配置选项。这些选项中的任何一个都可以包含在内,如果包含,则用与设备 A 对该选项所希望值相对应的值填写。如果不存在,则设备 A 不请求该选项。这六个选项如下:

最大接收单元 (MRU) 允许设备 A 指定它希望链路能够携带的最大数据报大小。

认证协议 设备 A 可以指示它希望使用的认证协议类型(如果有的话)。

质量协议 如果设备 A 希望在链路上启用质量监控,则应使用哪种质量监控协议(尽管目前只定义了一种:LQR)。

魔法数字 用于检测回环链接或其他连接中的异常。

协议字段压缩 允许设备 A 指定它希望使用“压缩”的(8 位)协议字段,而不是 PPP 数据帧中的正常 16 位协议字段。这为每个 PPP 帧提供了一小(一个字节)但免费的节省。(注意,这与压缩控制协议(CCP)提供的压缩功能无关;有关此功能的更多信息,请参阅第十二章中 PPP 通用帧格式的讨论。)

地址和控制字段压缩(ACFC) 与协议字段压缩相同,但用于压缩地址和控制字段以节省少量带宽。(有关更多信息,请参阅第十二章 AND POINT-TO-POINT PROTOCOL (PPP) OVERVIEW AND FUNDAMENTALS"))。

对于每种常见的网络层技术,都在单独的 RFC 中为其定义了一个 PPP NCP。"PPP 互联网协议控制协议(IPCP)"、"PPP 互连包交换控制协议(IPXCP)"和"PPP NetBIOS 帧控制协议(NBFCP)"分别是 IP、IPX 和 NBF(也称为 NetBEUI)的 NCP。还定义了一个单独的 NCP 用于 IP 版本 6,即"PPP IP 版本 6 控制协议(IPv6CP)"。

NCP 的操作

每个 NCP 的操作非常类似于 LCP 的一个轻量级版本,正如您可以在图 10-3 中看到的那样。(为了看到相似之处,您应该将图 10-3 与图 10-1 进行比较,后者显示了 LCP 的消息。)像 LCP 一样,每个 NCP 执行链路设置、维护和终止的功能,但它只处理其特定的 NCP 链接,而不是整个 LCP 链接。每个 NCP 使用 LCP 中定义的以下七个消息类型的一个子集,其方式与 LCP 使用相同名称的消息类型非常相似,正如在每个主要链路活动中的示例所示:

链路配置 一旦建立了 LCP 链接,就会使用配置请求、配置确认、配置否定和配置拒绝消息来设置和协商特定 NCP 链接的参数(如 LCP 中讨论的那样)(但这些都是针对每个 NCP 特定的)。配置选项是正在协商的网络层协议参数。

链路维护 可以发送代码拒绝消息来指示无效的代码值(NCP 帧类型)。

链路终止 可以使用终止请求和终止确认消息来终止 NCP 链接。但请记住,NCP 链接是在 LCP 链接内设置的,并且可以打开多个 NCP 链接。关闭 NCP 链接不会终止 LCP 链接。(当终止 LCP 链接时,不需要关闭 NCP 链接。)

图 10-3 展示了 NCP(如 IPCP)的整体操作与 LCP 非常相似。一旦 LCP 配置(包括认证)完成,就会使用配置请求和配置确认消息来建立 IPCP 链接。然后可以通过该链接发送 IP 数据。如果不再需要 IPCP 连接,它可以被终止,之后 LCP 链接仍然保持开启状态,以便传输其他类型的数据。然而,在终止 LCP 连接之前,没有必要明确终止 IPCP 链接。

PPP IP 控制协议(IPCP)消息交换 配置和终止 IPCP 所执行的消息交换与用于 LCP 的相当相似。

图 10-3. PPP IP 控制协议(IPCP)消息交换 配置和终止 IPCP 所执行的消息交换与用于 LCP 的相当相似。

小贴士

关键概念 一旦使用 LCP 建立了主要的 PPP 链路,每个要携带通过链路的网络层协议都需要建立适当的 NCP 链路。其中最重要的是PPP 互联网协议控制协议(IPCP),它允许 IP 数据报通过 PPP 传输。

互联网协议控制协议(IPCP):一个示例 NCP

让我们看看 IP 的 NCP:IPCP。当 PPP 被设置为携带 IP 数据报时,IPCP 在网络层协议阶段被调用,以在两个设备之间建立 IP NCP 链路。设置是通过使用四个配置消息来完成的。对于 IP,可以在 IPCP 配置请求消息中指定两个配置选项:

IP 压缩协议 允许设备协商使用 Van Jacobson TCP/IP 头部压缩,这缩小了 TCP 和 IP 头部的大小以节省带宽。在概念上,这与 LCP 中的协议字段压缩和 ACFC 选项类似。

IP 地址 允许发送配置请求消息的设备指定它想要用于通过 PPP 链路路由 IP 的 IP 地址,或者请求另一台设备提供 IP 地址。这通常用于拨号网络链路。

一旦配置完成,就可以发送对应于协商的 NCP 的第三层协议的数据。这通过在包含该第三层数据的 PPP 数据帧中使用适当的协议字段值来指示。

PPP 认证协议:PAP 和 CHAP

PPP 被设计为在各种串行链路和其他物理层技术上提供第二层连接性,其中一些比其他技术引入了更多的安全担忧。例如,假设你用串行电缆连接办公室中的两台机器,并想在它们之间运行 PPP。当其中一台机器与另一台机器建立 PPP 链路时,你实际上不需要担心是谁在打电话。另一方面,考虑一个使用 PPP 为远程拨入用户提供服务的互联网服务提供商(ISP)。他们通常只想允许他们的客户连接。

PPP 协议集允许在设备协商基本链路设置时使用可选的认证协议。PPP 套件最初定义了两个这样的协议:PAP 和 CHAP。一旦在两个设备之间建立 LCP 链路,就使用这些协议发送一系列认证消息来验证发起链路的设备的身份。只有认证成功,链路配置才能继续。

PAP

PAP 是一个非常直接的认证方案,只包含两个基本步骤,如图 图 10-4 所示。

认证请求 发起设备发送一个包含用户名和密码的 Authenticate-Request 消息。

认证回复 响应设备查看用户名和密码,并决定是否接受发起设备并继续设置链路。如果是这样,它将发送一个 Authenticate-Ack 消息。否则,它将发送一个 Authenticate-Nak 消息。

PAP 是一个例子,它过于简单,以至于不利于自身。其主要缺陷之一是它在链路中明文传输用户名和密码。这是一个大忌,因为窃听者可以获取密码。

PAP 也不能提供针对各种安全攻击的保护。例如,未经授权的用户可能会尝试不同的密码,直到发现正确的密码。PAP 还将认证控制完全放在发起设备(通常是客户端机器)的肩上,这通常不被认为是理想的,因为这是管理员更喜欢管理的服务器功能。

PAP 认证 PAP 使用包含用户名和密码信息的请求以及指示认证是否成功的回复的简单交换。

图 10-4. PAP 认证 PAP 使用包含用户名和密码信息的请求以及指示认证是否成功的回复的简单交换。

CHAP

PAP 和 CHAP 之间最重要的区别在于 CHAP 不会在链路中传输密码。当使用 PAP 时,发起者(调用客户端)向认证者(通常是决定是否授予认证的服务器)发送一条消息,其大意是:“这是我知道的密码;看看它是否与你的匹配。”每个设备使用密码执行加密计算,然后检查是否得到相同的结果。如果是这样,它们就知道它们有相同的密码。

在 CHAP 中,首先在发起者和认证者之间建立一个基本的 LCP 链路。然后,认证者负责认证过程,使用一种称为“三次握手”的技术。

注意

三次握手是一种相当常见的通用认证程序。例如,在 IEEE 802.11 无线网络中的共享密钥认证中也使用了相同的基本技术

三路握手步骤如下(参见图 10-5 认证 CHAP 使用一个三路握手,从认证设备发出的挑战开始。此消息被加密并返回给认证设备,认证设备检查尝试进行认证的设备是否使用了正确的密码(或其他共享秘密)"))):

挑战 认证器生成一个称为挑战的帧并发送给发起者。此帧包含一个简单的文本消息(有时称为挑战文本)。消息没有固有的特殊含义,所以如果有人拦截它,也没有关系。重要的是在收到挑战后,两个设备都有相同的挑战消息。

响应 发起者使用其密码(或认证者也知道的其他共享秘密)来加密挑战文本。然后,它将加密的挑战文本作为响应发送回认证器。

成功或失败 认证器对挑战文本执行与发起者相同的加密操作。如果认证器收到与发起者在响应中发送的相同结果,它就知道发起者在进行加密时拥有正确的密码,因此认证器返回一个成功消息。否则,它发送一个失败消息。

PPP 挑战握手认证协议 (CHAP) 认证 CHAP 使用一个三路握手,从认证设备发出的挑战开始。此消息被加密并返回给认证设备,认证设备检查尝试进行认证的设备是否使用了正确的密码(或其他共享秘密)

图 10-5. PPP 挑战握手认证协议 (CHAP) 认证 CHAP 使用一个三路握手,从认证设备发出的挑战开始。此消息被加密并返回给认证设备,认证设备检查尝试进行认证的设备是否使用了正确的密码(或其他共享秘密)。

这的好处在于它验证了两个设备具有相同的共享秘密,但不需要它们通过链路发送秘密。响应是根据密码计算的,但响应的内容被加密,因此从响应中推导密码要困难得多。CHAP 还提供了对重放攻击的保护,其中未经授权的用户捕获一条消息并试图稍后再次发送。这是通过在每个消息中更改一个标识符并改变挑战文本来实现的。此外,在 CHAP 中,服务器控制认证过程,而不是发起链路的客户端。

小贴士

关键概念 PPP 支持两种认证协议:PAPCHAP。PAP 是一种简单的请求和回复认证协议,因为它以明文形式发送用户名和密码,并且对许多安全问题的保护很少,所以普遍被认为是不够的。CHAP 使用三次握手过程,在大多数实现中比 PAP 更受欢迎。

CHAP 并不完美,但比 PAP 好得多。事实上,IETF 在修订描述 PAP 和 CHAP 的原始 RFC 时,对此做出了相当强烈的声明,将新标准中仅包括 CHAP。尽管如此,PAP 仍然在一些应用中使用,因为它很简单。在安全不是大问题的情况下,PAP 就足够了,但 CHAP 是一个更好的选择。

注意

顺便说一下,除了 PAP 和 CHAP,还可能使用专有认证方案。这需要将适当的配置选项值编程到 LCP 中,以便放置在认证协议配置选项中

第十一章。PPP 功能协议

无标题图片

点对点协议(PPP)是串行链路上的数据链路层连接标准,因为其核心协议提供了一个坚实的基础操作基础,正如你在 第十章 中所看到的。然而,PPP 的流行并不仅仅基于其高度强大的链路建立和管理功能,它还拥有许多非常有用的功能,为网络用户提供了重要的安全和性能优势。

在本章中,我描述了实现 PPP 中一些最常见额外功能的协议。我首先讨论 PPP 链路质量监控。我描述了用于配置和实现数据压缩和数据加密的协议集。然后,我讨论 PPP 多链接协议(MP,MLPPP),它允许 PPP 将多个低速链路捆绑成一个高速链路。我还涵盖了 带宽分配协议(BAP)带宽分配控制协议(BACP),它们用于管理 MLPPP 的操作。

PPP 链路质量监控和报告(LQM,LQR)

PPP 包括可选认证,以适应 PPP 可能运行的许多不同类型链路的不同的 安全 需求。这些链路在 质量 方面也有很大的差异。正如你不需要过多担心认证,当两台机器通过短电缆连接时,你同样可以相当有信心地认为它们之间发送的数据将会完整到达。现在,将这一点与通过长途电话建立的 PPP 会话进行对比。至于使用模拟蜂窝电话拨号连接的 PPP 会话呢?

PPP 在其基本包中包括检测发送帧中错误的规定,而像 TCP 这样的高层协议也包含在嘈杂线路上提供鲁棒性的方法。这些技术允许链路容忍问题,但提供了很少有关链路状态的有用信息。在某些情况下,设备可能希望能够跟踪链路的工作情况,并可能采取行动。例如,在拨号连接上遇到太多错误的设备可能想要切断并重试新的呼叫。在某些情况下,如果当前物理链路工作不佳,设备可能希望尝试另一种连接方法。

认识到这一需求,PPP 套件包括一个功能,允许设备分析它们之间链路的质量。这被称为 PPP 链路质量监控LQM。PPP 以通用方式设置,以允许使用任意数量的不同监控功能,但目前在现有情况下,只有一个,称为 链路质量报告 (LQR)。LQR 允许设备请求其对等方(链路上的另一台设备)跟踪有关链路的统计信息,并定期发送关于它们的报告。

LQR 设置

在可以使用 LQR 之前,必须设置它,这是通过 LCP 在链路建立阶段协商基本链路参数时完成的(参见 第十章中如何工作的内容,这应该看起来很熟悉):

链路配置 与 NCPs 一样,压缩配置是在 CCP 达到网络层协议阶段时完成的。设置压缩和协商参数的过程是通过使用配置请求、配置确认、配置拒绝和配置拒绝消息来完成的,就像 LCP 一样,只是配置选项是针对 CCP 特定的。

链路维护 可以发送 Code-Reject 消息来指示 CCP 帧中的无效代码值。两种新的消息类型是 Reset-Request 和 Reset-Ack,它们用于在检测到解压缩失败时重置压缩(CCP 链路)。

链路终止 可以使用 Terminate-Request 和 Terminate-Ack 来终止 CCP 链路。再次提醒,与 NCP 链路一样,CCP 链路是在 LCP 链路内设置的,关闭它不会终止控制 PPP 总体的 LCP 链路。

CCP 配置选项和压缩算法

CCP 配置选项仅用于协商两个设备将使用的压缩类型,以及获取该算法如何使用的具体细节。发起协商的设备会发送一个包含它支持的每个压缩算法的一个选项的 Configure-Request。另一个设备会将此选项列表与它理解的算法进行比较。它还会检查与选项相关的任何特定细节,以查看是否同意如何使用该算法。然后,它会发送适当的回复(Ack, Nak 或 Reject),并开始协商,直到两个设备找到一个双方都理解的共同算法。如果是这样,则启用压缩;否则,不启用。

CCP 配置选项以类型值开始,该值指示压缩算法。当类型值为 0 时,这表示该选项包含有关特殊、专有压缩算法的信息,该算法不受任何 RFC 标准的覆盖。如果两个设备都理解它,则可以使用此信息。从 1 到 254 的值表示为 CCP 使用而定义的压缩算法。表 11-1 压缩算法") 显示了类型字段的最常见值,包括每个类型值对应的压缩算法以及定义它的 RFC 编号。

表 11-1. PPP 压缩控制协议 (CCP) 压缩算法

CCP 选项类型值 定义 RFC 压缩算法(如 RFC 标题所示)
0 专有
1 和 2 1978 PPP 预测器压缩协议
17 1974 PPP Stac LZS 压缩协议
18 2118 微软点对点压缩 (MPPC) 协议
19 1993 PPP Gandalf FZA 压缩协议
21 1977 PPP BSD 压缩协议
23 1967 PPP LZS-DCP 压缩协议 (LZS-DCP)
26 1979 PPP Deflate 协议

压缩算法操作:压缩和解压缩数据

一旦成功协商了算法,压缩算法就会在传输前压缩数据,并在接收后解压缩数据。为了压缩,发送设备会取通常放在未压缩 PPP 帧信息字段中的数据,并通过压缩算法进行处理。为了指示一个帧已被压缩,特殊的值 0x00FD(十六进制)被放置在 PPP 协议字段中。当与多个链路一起使用压缩,并且链路独立压缩时,使用不同的值:0x00FB。

你会记得,在一个常规未压缩帧中,协议字段指示数据来自哪个第 3 层协议。由于你仍然需要知道这一点,原始的协议值实际上是在压缩之前附加到数据之前的。当数据解压缩时,这个值被用来恢复原始的协议字段,以便接收设备知道数据属于哪个高层。

例如,如果你使用 IPCP 在 PPP 中封装 IP 数据,未压缩帧的协议字段将具有 0x8021 的值。这个值(0x8021)将被放置在要压缩的数据的开始处。压缩数据将被放入一个协议值为 0x00FD 的 PPP 帧中。接收设备会在协议字段看到 0x00FD 的值,识别帧为压缩帧,解压缩它,并恢复原始帧,其中协议值为 0x8021。第十二章中关于 PPP 通用帧格式的讨论更详细地介绍了这一点。

理论上,压缩算法可以将多个 PPP 数据帧放入一个压缩 PPP 数据帧中。尽管如此,许多,如果不是大多数算法,保持一对一的对应关系,将每个 PPP 数据帧放入一个压缩帧中。请注意,LCP 帧不压缩,也不用于其他协议的控制帧。例如,携带 IP 流量的数据帧会被压缩,但用于 IPCP(IP 的 NCP)的控制帧则不会。

压缩可以与加密结合使用。在这种情况下,压缩是在加密之前进行的。

注意

CCP 执行的压缩与可以作为 LCP 一部分协商的头部压缩选项无关。这种类型的压缩不涉及使用压缩算法压缩数据流,而是一种在链路两端同意这样做时简化头部空间占用的一种简单方法

PPP 加密控制协议(ECP)和加密算法

PPP 认证协议密码认证协议(PAP)和挑战握手认证协议(CHAP)可用于确保只有授权设备才能建立 PPP 连接。一旦完成,PPP 通常不会为传输的数据提供其他安全措施。特别是,所有数据通常都是明文(未加密)发送的,这使得拦截它的人很容易阅读。

对于必须保持安全的重要数据,传输前的加密是一个好主意。这可以在更高层使用类似 IPsec 的方法来完成,但 PPP 也提供了一个可选功能,允许在数据链路层本身使用两个协议组件来加密和解密数据:

PPP 加密控制协议 (ECP) 该协议负责协商和管理 PPP 链路上的加密使用。

PPP 加密算法 是一组执行实际数据加密和解密的加密算法。其中一些在 RFCs 中定义,如果两个设备想要使用未由公共标准定义的加密方法,它们也可以协商一个专有加密方法。

小贴士

关键概念 PPP 包含一个可选的加密功能,为通过 PPP 传输的数据提供隐私。支持多种加密算法。要启用加密,PPP 链路上的两个设备都使用 PPP 加密控制协议 (ECP) 来协商使用哪种算法。然后使用选定的算法来加密和解密 PPP 数据帧。

ECP 操作:加密设置

当讨论 PPP 中的加密时,通常只提到 ECP 的这一部分,但实际上它只用于配置和控制加密的使用;算法做实际的工作。这种技术允许每个实现选择它希望使用的加密类型。

原始的 ECP 只定义了一种加密方法,后来又增加了一些。像 CCP 一样,ECP 类似于 NCPs,它们协商特定于在链路上发送的网络层协议的参数,但它处理的是设备如何加密数据,而不是如何传输第 3 层流量。这也意味着,像 NCPs 一样,ECP 是 LCP 的轻量级版本,并以相同的基本方式工作。一旦协商了 ECP 链路,设备就可以相互发送加密帧。当不再需要时,可以终止 ECP 链路。

ECP 使用与 NCPs 相同的七个 LCP 消息类型的子集,并增加了两个。以下是对 ECP 链路每个生命阶段使用这些消息的说明:

链路配置 与 NCPs(当然,也像 CCP 一样),加密配置是在 ECP 达到 网络层协议 阶段时完成的。设置加密和协商参数的过程是通过使用 Configure-Request、Configure-Ack、Configure-Nak 和 Configure-Reject 消息来完成的,正如我在 第十章 中对 LCP 的描述中解释的那样,除了配置选项是特定于 ECP 的。

链路维护 可以发送 Code-Reject 消息来指示 ECP 帧中的无效代码值。两种新的消息类型是 Reset-Request 和 Reset-Ack,它们用于在检测到解密失败时重置加密(ECP 链路)。

链路终止 使用 Terminate-Request 和 Terminate-Ack 可以终止 ECP 链路。再次提醒,与 NCP 链路一样,ECP 链路是在 LCP 链路内设置的,因此关闭它不会终止 LCP 链路。

ECP 配置选项和加密算法

ECP 配置选项仅用于协商两个设备将使用的加密算法类型以及该算法的具体应用方式。发起协商的设备会发送一个包含它支持的每个加密算法的一个选项的 Configure-Request。另一个设备会将此选项列表与它理解的算法进行比较。它还会检查与选项相关的任何细节,以查看是否同意如何使用该算法。然后,它会发送适当的回复(Ack, Nak 或 Reject),并开始协商,直到两个设备找到一个它们都理解的共同算法。如果找到了,则启用加密;否则,关闭加密。

ECP 配置选项以一个表示加密算法的类型值开始。当类型值为 0 时,这表示选项包含有关特殊专有加密方法的信息,该方法不受任何 RFC 标准的覆盖,如果两个设备都理解它,则可以使用。范围从 1 到 254 的值表示为 ECP 定义了用于加密的加密算法;目前,只定义了两个。表 11-2 压缩算法") 显示了类型字段的值,包括每个类型值对应的加密算法以及定义它的 RFC 编号。

表 11-2. PPP 加密控制协议 (ECP) 压缩算法

ECP 选项类型值 定义 RFC 加密算法(如 RFC 标题中所示)
0 专有
2 2420 PPP 三重 DES 加密协议 (3DESE)
3 2419 PPP DES 加密协议,版本 2 (DESE-bis)

注意

类型值 1 用于原始 DES 算法,该算法在 RFC 1969 中定义。它已被 RFC 2419 中的 DES 版本 2 取代

加密算法操作:加密和解密数据

一旦成功协商了加密算法,它就会用于在传输前加密数据以及解密接收到的数据。为了加密,发送设备会将通常放入未加密 PPP 数据帧信息字段中的数据通过加密算法处理。为了指示帧已被加密,将特殊值 0x0053(十六进制)放入 PPP 协议字段。当使用多个链路进行加密且链路独立加密时,使用不同的值:0x0055。

你会记得,在一个常规未加密的帧中,协议字段指示数据来自哪个第 3 层协议。由于你仍然需要知道这一点,原始的协议值实际上是在加密之前附加到数据之前的。当数据被解密时,这个值被用来恢复原始的协议字段,这样接收设备就知道数据属于哪个高层。

例如,如果你使用 IPCP 将 IP 数据封装在 PPP 中,未加密的帧在协议字段中的值为 0x8021(十六进制)。这个值(0x8021)将被放置在要加密的数据的开始处。加密的数据将被放入一个协议值为 0x0053 的 PPP 帧中。接收设备会在协议字段中看到 0x0053 的值,将其识别为加密帧,解密它,并恢复原始帧,其协议值为 0x8021。第十二章中关于 PPP 通用帧格式的讨论更全面地涵盖了这一点。

每个加密的 PPP 数据帧恰好携带一个 PPP 数据帧。请注意,与你在压缩中看到的不同,LCP 帧以及用于其他协议的控制帧可以被加密。压缩可以与加密结合使用;在这种情况下,压缩是在加密之前进行的。

PPP 多链路协议(MP,MLP,MLPPP)

大多数情况下,两个设备之间只有一个物理层链路。然而,有些情况下,实际上可能存在两个层 1 连接在同一对设备之间。这看起来可能有些奇怪。为什么任何一对机器之间会有多个链路?

有许多情况下可能会发生这种情况。一个常见的情况是在一对设备之间故意放置两个链路。这通常是为了通过扩大两个设备之间的管道来提高性能,而不必采用更新、更昂贵的技术。例如,如果两台机器通过一个速度太慢的常规模拟调制解调器相互连接,一个相对简单的解决方案是使用两个模拟调制解调器对来连接机器,以加倍带宽。

当多路复用在两个设备之间创建相当于几个物理层通道时,会出现一种稍微不同的情况,即使它们之间只有一个硬件链路。以 ISDN 为例。ISDN 服务最常见的形式(ISDN 基本速率接口或 BRI)在两个设备之间创建两个 64,000 bps 的B 通道。这些 B 通道是时分复用,并携带在单一对铜线上,但对于设备来说,它们看起来就像有两条物理层链路,每条链路都携带 64 Kbps 的数据。而 ISDN 主速率接口(PRI)实际上创建了 23 个或更多的通道,所有这些通道都在同一对硬件设备之间。

在你有多个链路的情况下,你可以在每个连接上独立建立 PPP。然而,这远非一个理想的解决方案,因为你将不得不手动在连接它们的两个(或更多)通道或链路上分配流量。如果你想连接到互联网,你需要建立单独的连接,然后选择每个动作使用哪一个。这并不 exactly 是一件有趣的事情,更糟糕的是,你永远无法将所有带宽用于单一目的,例如下载最新的 100 MB 微软安全补丁。

你真正想要的是一个能够让你结合多个链路并将它们用作一个高性能链路的解决方案。一些硬件设备实际上允许在硬件级别本身执行此操作。在 ISDN 中,当在第一层执行时,这项技术有时被称为bonding。对于那些不提供此功能的硬件单元,PPP 通过 PPP 多链路协议(MP)的形式提供这项功能。该协议最初在 RFC 1717 中描述,并在 RFC 1990 中进行了更新。

注意

PPP 多链路协议正确缩写为 MP,但经常看到许多其他缩写被用来指代它。其中许多实际上是从将名称中的单词顺序改变为 Multilink PPP 中派生出来的,所以你经常会看到它被称为 ML PPP、MLPPP、MPPP、MLP 等等。这些在技术上是不正确的,但被广泛使用,尤其是 MLPPP。我在这本书中使用正确的缩写

PPP 多链路协议架构

MP 是 PPP 的一个可选特性,因此它必须被设计成能够无缝地集成到常规 PPP 操作中。为了实现这一点,MP 被实现为 PPP 内部的一个新的架构子层。本质上,一个 MP 子层被插入到常规 PPP 机制和任何使用 PPP 的网络层协议之间,如图图 11-1 所示。这使得 MP 能够将所有要发送到 PPP 链路上的网络层数据分散到多个物理连接上,而不会导致常规 PPP 机制或网络层协议接口与 PPP 之间的中断。

图 11-1 左边的列显示了带有相应 OSI 参考模型层号的 TCP/IP 模型架构。中间的列显示了正常的 PPP 层架构。当使用 MP 时,有两个或更多物理链路上的单独 PPP 实现。MP 在架构上位于这些链路和将通过这些链路传输的任何网络层协议之间。(在此图中,只显示了 IP,因为它最常见,但 MP 可以与多个网络层协议一起工作,每个协议都通过每个物理链路发送。)

多链路 PPP 架构 当多链路 PPP 用于组合两个或更多物理链路时,它位于架构上位于每个物理链路上运行的 PPP 层之上。

图 11-1. 多链路 PPP 架构 当使用多链路 PPP 来组合两个或更多物理链路时,它在架构上位于每个物理链路上运行的 PPP 层之上。

提示

关键概念PPP 多链路协议(MP)允许 PPP 将多个物理链路捆绑在一起,并像使用单个高容量链路一样使用它们。在链路配置期间必须启用它。一旦运行,它通过分割整个 PPP 帧并将碎片通过不同的物理链路发送来工作。

PPP 多链路协议设置和配置

要使用 MP,两个设备都必须将其作为 PPP 软件的一部分实现,并且必须协商其使用。这是通过 LCP 作为链路建立阶段中基本链路参数协商的一部分来完成的(就像本章前面描述的 LQR 一样)。定义了三个新的配置选项,用于协商以启用 MP:

多链路最大接收重构单元提供了基本指示,表明开始协商的设备支持 MP 并希望使用它。该选项包含一个指定它支持的 PPP 帧最大大小的值。如果接收此选项的设备不支持 MP,则必须以 Configure-Reject LCP 消息响应。

多链路短序列号头部格式允许设备协商使用较短的序列号字段来提高 MP 帧的效率。(有关 MP 帧的完整讨论,请参阅第十二章。)

端点区分器唯一地标识系统。它用于允许设备确定哪些链路连接到哪些其他设备。

在可以使用 MP 之前,必须在两个设备之间的每个链路上进行至少 Multilink 最大接收重建单元选项的成功协商。一旦完成,并且每个物理链路都存在一个 LCP 链路,就会从 LCP 链路制作一个虚拟 ,并启用 MP。

PPP 多链路协议操作

如前所述,MP 基本上位于网络层和常规 PPP 链路之间,充当中间人。以下是它在通信每个方向上所做的工作:

传输 MP 接受通过适当的 NCP 配置的网络层协议接收到的数据报。它首先将它们封装成修改后的常规 PPP 帧,然后决定如何通过多个物理链路传输该帧。通常,这是通过将帧分成均匀分布在链路集合上的 片段 来实现的。然后,这些片段被封装并通过物理链路发送。然而,你也可以实现一种替代策略,例如在链路之间交替发送完整大小的帧。此外,通常较小的帧不会被分段,控制帧(如用于链路配置的帧)也不会。

接收 MP 接收来自所有物理链路的片段,并将它们重新组装成原始的 PPP 帧。然后,该帧就像任何 PPP 帧一样被处理,通过查看其协议字段并将其传递到适当的网络层协议。

MP 中使用的片段在概念上类似于 IP 片段,但当然这些是运行在不同层的不同协议。对于 PPP 或 MP 来说,一个 IP 片段就像任何其他 IP 数据报一样。

MP 中数据分片引入了协议必须处理的许多复杂性。例如,由于片段大致是并发发送的,你需要用序列号来标识它们以方便重新组装。你还需要一些控制信息来标识第一个和最后一个片段。MP 片段使用特殊的帧格式来携带这些额外信息。我在 第十二章 中描述了这一点,该章还包含了更多关于如何实现分片的信息,以及一个演示其工作原理的插图。

PPP 带宽分配协议(BAP)和带宽分配控制协议(BACP)

PPP MP 允许一对设备之间(无论是物理的还是虚拟通道的形式)的多个链路组合成一个宽管道(高容量通道)。这对许多 PPP 用户来说提供了巨大的优势,因为它让他们能够充分利用所有带宽,特别是对于互联网连接等应用。因此,MP 成为 PPP 最受欢迎的功能之一,也就不足为奇了。

定义 MP 的原标准基本上假设多个链路将组合成一个单一的束。例如,如果您有两个调制解调器链路,它们都会连接并合并,或者 ISDN 链路中的两个 B 通道会合并。在 MP 设置之后,束将可供任何设备完全使用。

这个系统的缺点之一是:粗管道始终处于启用状态,在许多情况下,始终设置这种配置是昂贵的。连接两个或更多层 1 链路通常比单个链路更昂贵,而且并不总是需要。例如,一些 ISDN 服务对 B 通道的通话按分钟收费。在调制解调器拨号的情况下,世界上某些地区的通话也按分钟收费。即使在常规电话免费的地方,也存在占用电话线的成本。考虑到在许多应用中,所需的带宽量会随时间变化。

如果您能设置 MP,使其能够在需要时动态地将链路添加到束中(例如,当您决定下载一些大文件时),然后在不再需要时自动删除它们,那就更好了。这种对基本 MP 包的增强是以 RFC 2125 中描述的一对新的协议的形式提供的:

带宽分配协议(BAP) 描述了一种机制,其中在层 1 链路束中通信的任一设备都可以请求将链路添加到束中或从其中删除。

带宽分配控制协议(BACP) 允许设备配置它们想要如何使用 BAP。

提示

关键概念 BAPBACP 用于提供对 PPP MP 功能的动态控制。

BACP 操作:配置 BAP 的使用

让我们从 BACP 开始,因为它是用于该功能初始设置的协议。从概念上讲,BACP 与其他所有名称中带有“控制”(Control)的 PPP 协议非常相似,例如 LCP、NCP 家族、CCP 和 ECP,但实际上它更加简单。它仅在链路配置期间使用,用于设置 BAP。这是通过使用配置请求(Configure-Request)、配置确认(Configure-Ack)、配置拒绝(Configure-Nak)和配置拒绝(Configure-Reject)消息来完成的,正如在 LCP 主题中所描述的那样。

在 BACP 中协商的唯一配置选项是称为“首选对等方”(Favored-Peer)的选项,它用于确保当链路上的两个设备同时尝试发送相同的请求时不会出现问题。如果两个设备都支持 BAP,那么 BACP 协商将成功,并将激活 BAP。

BAP 操作:添加和删除链路

BAP 定义了一组可以在设备之间发送的消息,用于向当前 PPP 束中添加或删除链路。BAP 特别有趣的是,它包括在需要更多带宽时实际启动不同类型的物理层连接(例如,为捆绑的模拟链路拨打电话调制解调器或启用额外的 ISDN 通道)所需的工具。然后,当不再需要时,它们会关闭这些连接。

这里是 BAP 消息类型的简要描述:

呼叫请求和呼叫响应 当链路上的一个设备想要将链路添加到捆绑中并自己启动新的物理层链路时,它向另一台设备发送一个呼叫请求帧来告知,该设备则以呼叫响应进行回复。

回调请求和回调响应 这些与前面两种消息类型类似,但它们是在设备想要其对等方(链路上的另一台设备)发起调用以添加新链路时使用的。所以,如果设备 A 说,“我需要更多的带宽,但我想让你打电话给我,而不是我打电话给你,”它就会向设备 B 发送一个回调请求。

呼叫状态指示和呼叫状态响应 在设备尝试向捆绑中添加新链路(在发送呼叫请求或接收回调请求后)后,它使用呼叫状态指示帧报告新链路的状态。然后,另一台设备以呼叫状态响应进行回复。

链路删除查询请求和链路删除查询响应 一台设备使用这些消息请求删除链路,而另一台设备则使用它们来响应这个请求。

注意,何时添加或删除链路的决定不是由这些协议做出的。这取决于特定的实现。

第十二章。PPP 协议帧格式

无标题图片

点对点协议(PPP)协议套件包括许多不同的协议,用于以不同的方式发送数据和控制信息。每个协议都将信息打包成称为的消息,每个帧都遵循特定的帧格式。PPP 从一个通用帧格式开始,涵盖链路上发送的所有帧,然后包括用于不同目的的更具体格式。理解这些格式不仅使诊断 PPP 问题更容易,而且有助于更清楚地了解关键 PPP 协议的功能。

在本章中,我展示了用于在 PPP 上发送数据和控制信息的最常见帧格式。我首先解释了用于所有 PPP 帧的整体格式。我还描述了用于各种控制协议的一般格式以及它们大多数使用的选项格式。(PPP 的一个优点是,许多协议使用具有共同格式的控制帧。)

我随后具体列出了用于链路控制协议(LCP)和身份验证协议(PAP 和 CHAP)的帧。我还描述了 PPP 多链路协议(MP)用于在捆绑链路上传输数据片段的特殊格式。

注意

由于 PPP(点对点协议)中有大量不同的协议(数十种)以及许多协议都有其独特的选项,我无法在此详细描述每个协议的所有特定帧格式和选项格式。请参阅相应的 RFC(列于第九章以获取更多详细信息)。

PPP 通用帧格式

使用 PPP 发送的所有消息都可以被认为是数据控制信息。单词数据描述了你在第二层尝试传输的更高层数据报。这是我们“客户”给我们发送的内容。控制信息用于管理 PPP 内部的各种协议的操作。尽管 PPP 套件中的不同协议使用许多类型的帧,但在最高层,它们都符合一个单一的、通用的帧格式。

你会记得,PPP 套件的基本操作基于 ISO 高级数据链路控制(HDLC)协议。当你查看 PPP 帧的整体结构时,这一点变得非常明显——它们使用与 HDLC 相同的基本格式,甚至包括某些对于 PPP 本身并非严格必要的字段。唯一的重大变化是添加了一个新字段来指定封装数据的协议。PPP 帧的一般结构在 RFC 1662 中定义,它是 PPP 主要标准 RFC 1661 的配套文件。

PPP 的通用帧格式,展示了如何将 HDLC 帧格式应用于 PPP,在表 12-1 中描述,并在图 12-1 中展示。

表 12-1. PPP 通用帧格式

字段名称 大小(字节) 描述
标志 1 表示 PPP 帧的开始。始终具有二进制值 01111110(十六进制 0x7E,或十进制 126)。
地址 1 在 HDLC 中,这是帧的目标地址。但在 PPP 中,你处理的是两个设备之间的直接连接,因此该字段没有实际意义。因此,它始终设置为 11111111(十六进制 0xFF 或十进制 255),这相当于广播(意味着“所有站”)。
控制 1 此字段在 HDLC 中用于各种控制目的,但在 PPP 中设置为 00000011(十进制 3)。
协议 2 识别帧信息字段中封装的数据报的协议。有关协议字段更多信息,请参阅“协议字段范围”部分。
信息 可变 包含数据或控制信息的零个或多个负载字节,具体取决于帧类型。对于常规 PPP 数据帧,网络层数据报封装在这里。对于控制帧,控制信息字段放置在这里。
填充 可变 在某些情况下,可能需要添加额外的空字节来填充 PPP 帧的大小。
帧校验序列 2 (或 4) 对帧进行校验和计算,以提供对传输错误的基本保护。这是一个类似于在以太网中使用的其他层 2 协议错误保护方案(如)的 CRC。它可以是 16 位或 32 位大小(默认为 16 位)。FCS 是在地址、控制、协议、信息和填充字段上计算的。
标志 1 表示 PPP 帧的结束。始终具有二进制值 01111110(十六进制 0x7E,或十进制 126)。

PPP 通用帧格式

图 12-1. PPP 通用帧格式

协议字段范围

协议字段是接收帧的设备的主要帧类型指示器。对于数据帧,这通常是创建数据报的网络层协议;对于控制帧,通常是创建控制消息的 PPP 协议。在修改数据(如前一章中解释的压缩(CCP)或加密(ECP))的情况下,此字段标识数据是压缩的还是加密的,并在信息字段解压缩/解密后提取原始协议值。

所有 PPP 帧都是基于图 12-1 中所示的一般格式构建的。前三个字节是固定的,后面跟着一个两字节的协议字段,表示帧类型。可变长度的信息字段根据 PPP 帧类型以多种方式格式化。可以对帧应用填充,以一个两字节或四字节的 FCS 字段(此处显示为两字节)和一个尾随的标志值 0x7E 结束。(参见图 12-2 了解此格式如何应用。)

网络层协议和 PPP 控制协议有数十种,相应地,协议值也有大量。主要 PPP 标准定义了四个范围来组织这些值,如表 12-2 所示。

标准还规定,协议值必须分配,以便第一个字节是偶数,第二个字节是奇数。例如,0x0021 是一个有效值,但 0x0121 和 0x0120 则不是。(原因将在稍后变得明显。)还有一些特定的块是保留的,不使用。

图 12-2 展示了 PPP 通用帧格式的常见应用之一:携带数据。协议字段中的值 0x0021 标识这是一个 IPv4 数据报。此示例有 1 字节填充和 2 字节帧校验序列(FCS)。(显然,真实的 IP 数据报比这里显示的 23 字节要长!这些字节是任意的,并不代表一个真实的数据报。)请参阅 图 12-12 以了解如何格式化和分片此相同的数据帧,以便通过多个链路进行传输。

表 12-2. PPP 协议字段范围

协议字段范围(十六进制) 描述
0000–3FFF 与 NCP(见 第十章)关联的封装网络层数据报。在这种情况下,对应 NCP 的控制帧使用通过将网络层协议值的第一字节加 8 计算出的协议字段值。例如,对于 IP,协议值是 0021,而 IP 控制协议(IPCP)的控制帧使用协议值 8021。此范围还包括用于特殊处理封装数据报的几个值,例如在采用压缩或加密时。
4000–7FFF 来自“低流量”协议的封装数据报。这些是没有关联 NCP 的协议。
8000–BFFF 与 0000–3FFF 范围内的网络层协议值相对应的 NCP 控制帧。
C000–FFFF LCP 和 LCP 支持的协议(如 PAP 和 CHAP)使用的控制帧。这里也包括了一些杂项协议值。

样本 PPP 数据帧 包含缩略 23 字节 IP 数据报的 PPP 数据帧。

图 12-2. 样本 PPP 数据帧 包含缩略 23 字节 IP 数据报的 PPP 数据帧。

协议字段值

PPP 协议值的完整列表由互联网数字分配机构(IANA)维护,包括所有其他用于互联网标准的保留数字。 表 12-3 展示了一些更常见的值。

表 12-3. 在 PPP 帧中携带的常见协议及其协议字段值

协议类型 协议字段值(十六进制) 协议
封装的网络层数据报 0021 Internet 协议版本 4 (IPv4)
0023 OSI 网络层
0029 AppleTalk
002B Novell 互连网络数据包交换 (IPX)
003D PPP 多链接协议 (MP) 片段
003F NetBIOS 帧(NBF/NetBEUI)
004D IBM 系统网络架构 (SNA)
0053 使用 ECP 和 PPP 加密算法的加密数据
0055 PPP 多链接下的单个链路加密数据
0057 互联网协议版本 6 (IPv6)
00FB PPP 多链接下的单个链路压缩数据
00FD 使用 CCP 和 PPP 压缩算法的压缩数据
低流量封装协议 4003 CDPD 移动网络注册协议
4025 光纤通道
网络控制协议 (NCP) 控制帧 8021 PPP 互联网协议控制协议
8023 PPP OSI 网络层控制协议
8029 PPP AppleTalk 控制协议
802B PPP IPX 控制协议
803F PPP NetBIOS 帧控制协议
804D PPP SNA 控制协议
8057 PPP IPv6 控制协议
LCP 和其他控制帧 C021 PPP 链路控制协议 (LCP)
C023 PPP 密码认证协议 (PAP)
C025 PPP 链路质量报告 (LQR)
C02B PPP 带宽分配控制协议 (BACP)
C02D PPP 带宽分配协议 (BAP)
C223 PPP 挑战握手认证协议 (CHAP)

PPP 字段压缩

PPP 使用 HDLC 基本帧结构,该结构包括两个在 HDLC 中需要但在 PPP 中不需要的字段,因为 PPP 的操作方式。这些字段是地址和控制字段。为什么要在每个帧中发送两个具有相同值的字节,而这些字节又没有用于任何目的?最初,它们是为了兼容性而保留的,但这降低了效率。

为了避免在每个帧中浪费两个字节,在初始链路设置期间可以使用链路控制协议 (LCP) 通过该名称相同的 LCP 选项协商一个称为 地址和控制字段压缩 (ACFC) 的功能。启用此功能后,它将简单地导致这些两个字段不发送在大多数 PPP 帧中(但不包括 LCP 控制帧)。实际上,这个功能最好命名为 地址和控制字段抑制,因为字段只是被抑制并压缩到无。

即使设备同意使用字段压缩,它们仍然必须能够接收压缩和非压缩的帧。它们通过查看初始标志字段之后的第一个字节来区分这两种帧。如果它们包含值 0xFF03,则它们必须是地址和控制字段;否则,这些字段被抑制。(值 0xFF03 不是一个有效的协议字段值,因此不存在歧义的机会。)

同样,链路上的两个设备也可以协商对协议字段的压缩,使其只占用一个字节而不是两个字节。这通常是通过丢弃第一个字节(如果它是零)来完成的,这个过程称为协议字段压缩(PFC)。回想一下,第一个字节必须是偶数,第二个字节是奇数。因此,接收设备检查每个帧中协议字段的第一个字节的偶数性。如果它是奇数,这意味着协议字段中前导零字节已被抑制,因为完整的两个字节协议值的第一个字节必须是偶数。

注意

此字段压缩(实际上是抑制)与 PPP 压缩控制协议(CCP)和压缩算法进行的数据压缩无关。

PPP 通用控制协议帧格式和选项格式

你刚才看到的通用帧格式用于 PPP 协议集中定义的所有许多帧类型。在该格式中,信息字段携带封装的第三层用户数据或封装的控制消息。这些控制消息包含用于配置、管理和断开 PPP 链路以及实现 PPP 所包含的各种特性的特定信息。

存在许多不同的 PPP 控制协议,通常可以通过其名称中出现的单词控制来区分。这些包括主要的 PPP 链路控制协议(LCP);一系列网络控制协议(NCPs),如 IPCP、IPXCP 等;以及实现特性的控制协议,如压缩控制协议(CCP)和加密控制协议(ECP)。密码认证协议(PAP)和挑战握手认证协议(CHAP)名称中缺少控制,但也属于这一类别。

每个控制协议都以略微不同的方式使用控制消息,但消息之间也存在许多共性。这是因为,正如我在 PPP 协议讨论中解释的那样,大多数控制协议——如 NCP 家族、CCP 和 ECP——都是作为 LCP 功能子集实现的。它们执行许多相同的功能,因此 PPP 设计者明智地采用了 LCP 消息系统来适应这些其他控制协议。

这意味着控制协议帧具有一个共同的格式,该格式适合 PPP 中的整体通用帧格式。即使像 PAP 和 CHAP 这样的协议不是基于 LCP,也使用这种通用控制帧格式,该格式在表 12-4 中描述。

表 12-4. PPP 控制消息格式

字段名称 大小(字节) 描述
Code (类型) 1 一个单字节值,指示此控制帧中控制消息的类型。在某些 PPP 标准中,有时也称为类型。
标识符 1 这是一个标签字段,用于将请求与回复匹配。当发送请求时,会生成一个新的标识符。当创建回复时,使用请求中标识符字段的值作为回复的标识符字段。
长度 2 指定控制帧的长度。这是必需的,因为数据字段长度是可变的。长度字段以字节为单位指定,包括控制帧中的所有字段,包括代码、标识符、长度和数据字段。
数据 可变 包含特定于消息类型的信息。此字段的不同用途将在本章后面进行描述。

整个结构成为 PPP 帧的有效负载,这意味着它适合 PPP 帧的信息字段,如图 图 12-3 所示。PPP 控制消息格式的四个字段适合 PPP 通用帧格式的信息字段。数据字段随后填充与控制消息类型特定的数据。因此,长度字段的大小等于 PPP 帧中信息字段的大小。控制帧的协议字段设置为与生成控制帧的协议匹配。例如,对于 LCP 帧将是 0xC021。

PPP 控制消息格式

图 12-3. PPP 控制消息格式

PPP 控制消息和代码值

代码字段指示特定控制协议中的控制帧类型。某些协议有一组独特的代码,仅由该特定协议使用;例如,身份验证协议(PAP 和 CHAP)和带宽分配协议(BAP)。由于 NCPs 和许多功能控制协议(如 CCP 和 ECP)基于 LCP,它们使用一组通用的消息代码和类型。表 12-5 显示了这些通用消息代码,并指出了哪些控制协议使用它们。

表 12-5. PPP 控制消息、代码值和 PPP 协议使用

代码值 控制消息 LCP NCPs CCP 和 ECP
1 配置请求
2 配置确认
3 配置拒绝
4 配置拒绝
5 终止请求
6 终止确认
7 代码拒绝
8 协议拒绝
9 回显请求
10 回显回复
11 丢弃请求
12 识别
13 剩余时间
14 重置请求
15 重置确认

注意

我在第十章和第十一章中描述了这些帧类型在 LCP、NCP、CCP 和 ECP 各个独立主题中的具体使用方式。

数据字段的内容完全取决于控制消息的类型。在某些情况下,可能根本不需要发送额外数据,这种情况下可以省略数据字段。在其他控制消息中,它携带与消息类型相关的信息。例如,代码拒绝消息在数据字段中包含被拒绝的帧的副本。

PPP 控制消息选项格式

不同的配置消息用于在 LCP 和其他控制协议中协商配置选项。在它们的数据字段中,它们携带一个或多个选项,这些选项再次是特定于使用它们的协议的。例如,LCP 使用一组配置选项来配置整个链路,CCP 使用选项来协商压缩算法,MP 使用它来设置多链路捆绑,等等。图 12-4 显示了这些选项(其长度可能不同)如何放置在 PPP 控制消息的数据字段中(该字段嵌套在一般的 PPP 帧格式中)。此图显示了在数据字段中携带选项的示例 PPP 控制消息。可以根据消息的需求包含任意数量的选项,并与其他数据混合。

PPP 控制消息携带选项

图 12-4。PPP 控制消息携带选项

再次,这里也有共性。虽然每个选项都不同,但它们都使用相同的基本格式。任何出现在众多 PPP 控制消息类型中的选项都由类型、长度和数据的三元组组成,如表 12-6 所示,并在图 12-5 中说明。

表 12-6。PPP 控制消息选项格式

字段名称 大小(字节) 描述
类型 1 指示选项类型的类型值。类型值的集合对每个协议是唯一的。例如,LCP 有一组与配置选项对应的类型值,每个 NCP 有不同的类型值,CCP 有自己的类型值,等等。
长度 1 指定选项的长度(字节)。
数据 可变 包含配置选项的特定数据。

配置选项在各个协议主题中简要描述。我没有展示每个选项的具体内容,因为它们的数量实在太多。这些内容在 RFC 中。

PPP 控制消息选项格式

图 12-5. PPP 控制消息选项格式

PPP 控制消息格式总结

我的意图是向您展示不同控制协议使用的通用格式,因为它们非常相似,我没有时间或空间逐一描述每个协议的帧。以下是一个简要总结:

  • PPP 的通用帧格式用于所有帧,包括所有控制帧。其信息字段包含有效载荷,对于控制帧,它携带了整个控制消息。

  • 控制帧的结构是使用我在本主题开头给出的通用格式构建的。代码值表示每个控制协议的控制帧类型。数据字段长度可变,包含该控制帧的数据,在某些情况下可能包括一个或多个配置选项。

  • 对于像配置请求配置确认这样的配置控制帧,数据字段包含使用本主题第二表中通用结构封装的选项集。每个选项都有自己的数据子字段,包含特定于该选项的数据。

为了使这一点更加清晰,接下来的两个部分提供了 LCP 和认证协议的帧格式的更具体示例。

PPP 链路控制协议(LCP)帧格式

您刚刚探索了 PPP 协议中用于交换控制消息的各种协议所使用的通用格式。在 PPP 的众多控制协议中,LCP(链路控制协议)是最重要的,因为它负责基本的 PPP 链路设置和操作。它也是用作许多其他控制协议模板的协议。

由于它在 PPP 中如此核心,并且许多其他协议使用类似的消息系统,让我们通过展示用于每个 LCP 控制帧的具体帧格式来使一般的帧格式(如图 12-5 所示)更加具体。表 12-7 显示了 13 种 LCP 帧类型中每个字段的含义和内容。

注意

LCP 帧类型 5、6、9、10、11、12 和 13 允许在数据字段中包含额外的数据量,其方式不是严格由协议描述的。PPP 标准表示可能有零个或多个字节“包含由发送方使用的未解释数据”并且“可能由任何二进制值组成”(RFC 1661)。包含这些未解释数据的选择留给了实现者。

所有 LCP 控制帧都通过将帧结构放入其信息字段中封装到 PPP 帧中,正如你之前所看到的。协议字段设置为 0xC021 以表示 LCP。(有关帧的使用说明,请参阅第十章中 LCP 的操作描述 Chapter 10。)

表 12-7. PPP 链路控制协议(LCP)帧类型和字段

帧类型 代码字段 标识符字段 长度字段 数据字段
Configure-Request 1 为每个帧生成的新值 4 + 所有包含的配置选项的长度 两个对等体在链路上协商的配置选项。(本章前面的部分描述了配置选项的一般格式。)
Configure-Ack 2 从对应 Configure-Ack 回复的 Configure-Request 帧的标识符字段复制而来 4 + 所有包含的配置选项的长度 被积极确认的配置选项(在链路协商期间接受)。
Configure-Nak 3 从对应 Configure-Nak 回复的 Configure-Request 帧的标识符字段复制而来 4 + 所有包含的配置选项的长度 被否定确认的配置选项(请求重新协商)。
Configure-Reject 4 从对应 Configure-Reject 回复的 Configure-Request 帧的标识符字段复制而来 4 + 所有包含的配置选项的长度 被拒绝的配置选项(因为设备无法协商它们)。
Terminate-Request 5 为每个帧生成的新值 4(如果包含额外数据,则更多) 不需要。请参阅本表之前的说明。
Terminate-Ack 6 从匹配的 Terminate-Request 帧的标识符字段复制而来 4(如果包含额外数据,则更多) 不需要。请参阅本表之前的说明。
Code-Reject 7 为每个帧生成的新值 4 + 被拒绝帧的长度 被拒绝的 LCP 帧的副本。这不是完整的 PPP 帧,只是从其信息字段中的 LCP 控制部分。
Protocol-Reject 8 为每个帧生成的新值 6 + 被拒绝帧的长度 前两个字节包含被拒绝帧的协议值。其余部分包含被拒绝帧的信息字段的副本。
Echo-Request 9 为每个帧生成的新值 8(如果包含额外数据,则更多) 包含一个用于检测回环链路的四字节“魔术数字”,如果已协商适当的配置选项;否则,设置为 0。也可能包含其他未解释的数据;请参阅本表之前的说明。
回显回复 10 从匹配的回显请求的标识符字段复制 8(或更多,如果包含额外数据) 包含一个四字节的“魔法数字”,用于检测已协商适当配置选项的回环链路;否则,设置为 0。也可能包含其他未解释的数据;请参阅此表之前的说明。
丢弃请求 11 为每个帧生成的新值 8(或更多,如果包含额外数据) 包含一个四字节的“魔法数字”,用于检测已协商适当配置选项的回环链路;否则,设置为 0。也可能包含其他未解释的数据;请参阅此表之前的说明。
标识 12 为每个帧生成的新值 8(或更多,如果包含额外数据) 包含一个四字节的“魔法数字”,用于检测已协商适当配置选项的回环链路;否则,设置为 0。也可能包含其他未解释的数据;请参阅此表之前的说明。
剩余时间 13 为每个帧生成的新值 12(或更多,如果包含额外数据) 包含一个四字节的“魔法数字”,用于检测已协商适当配置选项的回环链路;否则,设置为 0。还包含一个四字节的值,表示当前会话剩余的秒数。此字段中全为 1 的值表示永远,意味着会话不会过期。也可能包含其他未解释的数据;请参阅此表之前的说明。

PAP 和 CHAP 帧格式

对于安全重要的链路,PPP 提供了两种可选的认证协议,即 PAP 和 CHAP。这些协议在 LCP 进行初始链路设置时使用,以拒绝未经授权的设备建立 PPP 连接。

PAP 和 CHAP 是控制协议,因此使用本节前面描述的相同基本控制协议帧格式。然而,由于它们与 LCP 和其他许多控制协议的目的非常不同,它们使用一组独特的帧,并具有自己独特的代码值集。PAP 使用三种不同的控制帧类型,而 CHAP 使用四种。让我们看看 PAP 和 CHAP 帧是如何构建的。

PPP PAP 控制帧格式

PAP 的三个控制帧的构建方式如表表 12-8 帧格式")和表 12-9 所示。认证请求使用一种格式,如图图 12-6 所示,而其他两种帧类型使用不同的格式,如图图 12-7 所示。

表 12-8. PPP 密码认证协议(PAP)帧格式

帧类型 代码字段 标识符字段 长度字段 数据字段
Authenticate-Request 1 每个帧生成的新值 6 + Peer-ID 长度 + 密码长度 包含用于认证的用户名和密码。这包含在四个子字段中,并按表 12-9 中所示排列。
Authenticate-Ack 2 从 Authenticate-Request 帧的标识符字段复制而来,作为回复 5 + 包含消息的长度 包含一个指定其后消息子字段长度的单字节 Msg-Length 子字段。消息子字段包含任意字符串数据,其用途取决于实现。它可以用来向用户指示认证成功或失败。如果没有使用,Msg-Length 字段仍然包含,但其值设置为零。
Authenticate-Nak 3

PPP PAP Authenticate-Request 帧格式

图 12-6. PPP PAP Authenticate-Request 帧格式

PPP PAP Authenticate-Ack 和 Authenticate-Nak 帧格式

图 12-7. PPP PAP Authenticate-Ack 和 Authenticate-Nak 帧格式

表 12-9. PPP PAP Authenticate-Request 帧子字段

子字段名称 大小(字节) 描述
Peer-ID 长度 1 Peer-ID 字段的长度,以字节为单位
Peer-ID 可变 要认证的设备名称;在概念上等同于用户名
Passwd-Length 1 密码字段的长度,以字节为单位
Password 可变 与正在认证的名称对应的密码

PPP CHAP 控制帧格式

四种 CHAP 帧类型格式如表表 12-10 和表 12-11 所示。挑战和响应帧使用一种消息格式,如图图 12-8 所示,而成功和失败帧使用不同的格式,如图图 12-9 所示。

表 12-10. PPP 挑战握手认证协议(CHAP)格式

帧类型 代码字段 标识符字段 长度字段 数据字段
挑战 1 每个帧生成的新值 5 + 挑战文本的长度 + 名称的长度 载有挑战文本或响应文本和系统标识符。此信息在表 12-11 中所示的三个子字段中传输。
响应 2 从此响应的挑战帧的标识符字段复制 5 + 值的长度 + 名称的长度
成功 3 从此响应的响应帧的标识符字段复制 4(或更多,如果包含额外数据) 可能包含一个任意、实现相关的消息字段,以指示用户身份验证是否成功或失败。
失败 4

表 12-11。CHAP 挑战和响应帧子字段

子字段名称 大小(字节) 描述
值大小 1 后续值子字段的长度,以字节为单位
变量 对于挑战帧,包含初始挑战中使用的挑战文本;对于响应帧,包含返回给验证器的加密挑战文本
名称 可变 用来标识发送帧的设备的文本字节

PPP CHAP 挑战和响应帧格式

图 12-8。PPP CHAP 挑战和响应帧格式

PPP CHAP 成功和失败帧格式

图 12-9。PPP CHAP 成功和失败帧格式

PPP 多链路协议(MP)帧格式

一些设备不是通过单个物理层链路连接,而是通过两个或更多。这些可能是多个物理连接,例如两个连接的调制解调器对,或者像 ISDN B 通道这样的复用虚拟层 1 连接。在任一情况下,PPP MP 都可以用来聚合这些物理链路的带宽,创建一个单一的、高速的捆绑。我在第十一章中描述了如何实现这一点。

在 MP 配置并开始工作后,它通过在组成 MP 捆绑的许多单个物理链路之间分配常规 PPP 帧的策略来运行。这通常是通过将 PPP 帧切割成称为片段的块,并将它们分散在物理链路上来实现的。这允许物理链路上的流量容易平衡。

PPP MP 帧分片过程

要完成此分片过程,设备必须遵循以下三个步骤:

  1. 原始 PPP 帧创建 要发送的数据或其他信息首先被格式化为一个完整的 PPP 帧,但将以修改后的形式,正如我们马上将看到的。

  2. 分片 MP 将完整大小的 PPP 帧切割成片段。

  3. 封装 每个分片都封装在新的 PPP MP 分片帧的信息字段中,以及允许接收方重新组装分片的控制信息。

如果该帧将被分割并放置到其他 PPP MP 帧中,则通常出现在整个 PPP 帧中的几个字段就不需要了,因此当进行分片时,为了提高效率,在构建原始 PPP 帧时会省略这些字段。这些是在使用 MP 时未使用的字段:

  • 起始和结束处的标志字段仅用于传输的帧定界,在逻辑分片帧中不需要。

  • FCS 字段不需要,因为每个分片都有自己的 FCS 字段。

  • 对于任何 PPP 帧可能使用的特殊压缩选项,在创建此原始帧时都会使用——即地址和控制字段压缩(APCP)和协议字段压缩(PFC)。这意味着帧中不包含地址或控制字段,而协议字段的大小仅为一个字节。请注意,这本质上限制了分片只能携带某些类型的信息。

小贴士

关键概念 PPP 多链路协议(MP)通常通过创建一个移除不必要的头部的原始 PPP 帧,并在物理链路之间分配数据,然后将它分成分片帧。每个分片包含特殊的头部,允许接收设备重新组装原始帧。

这些更改在每个将被分片的 PPP 帧上节省了完整的八个字节。因此,原始 PPP 帧具有一个非常小的头部,仅由一个字节的协议字段组成。每个分片的协议值设置为 0x003D,以指示一个 MP 分片,而原始帧的协议字段变为第一个分片中的数据的第一字节。

PPP MP 分片帧格式

每个分片的信息字段使用一个包含四个字段MP 头部以及原始 PPP 帧的一个分片的子结构,如表 12-12 所示。

表 12-12. PPP 多链路协议分片帧格式

字段名称 大小(字节) 描述
B 1/8 (1 bit) 开始分片标志:当设置为 1 时,将该分片标记为拆分 PPP 帧的第一个分片。对于其他分片,设置为 0。
E 1/8 (1 bit) 结束分片标志:当设置为 1 时,将该分片标记为拆分 PPP 帧的最后一个分片。对于其他分片,设置为 0。
保留 2/8 (2 bits) 或 6/8 (6 bits) 未使用;设置为 0。
序列号 1 1/2 (12 bits) 或 3 (24 bits) 当一个帧被拆分时,分片被赋予连续的序列号,以便接收设备可以正确地重新组装它们。
分片数据 可变 原始 PPP 帧的实际分片。

如您所见,MP 帧格式有两种版本:长格式使用四个字节的头,而短格式只需要四个字节。默认的 MP 头格式使用 24 位序列号和 6 个保留位,如图 12-10 所示。当设置 MP 时,设备可以协商 Multilink Short Sequence Number Header Format 配置选项。如果成功完成,则使用较短的 12 位序列号。还有四个保留位被截断,每个帧节省两个字节,如图 12-11 所示。(考虑到 12 位仍然允许每个 PPP 帧有超过 4000 个片段,这通常已经足够了!)

PPP MP 长片段帧格式 PPP MP 的长帧格式使用一个完整的字节用于标志位和一个 24 位的序列号。

图 12-10. PPP MP 长片段帧格式 PPP MP 的长帧格式使用一个完整的字节用于标志位和一个 24 位的序列号。

PPP MP 短片段帧格式 PPP MP 格式的简版使用 4 位用于标志位和一个 12 位的序列号。

图 12-11. PPP MP 短片段帧格式 PPP MP 格式的简版使用 4 位用于标志位和一个 12 位的序列号。

片段数据字段包含要发送的实际片段。由于原始 PPP 头(包括协议字段)位于原始 PPP 帧的开始处,因此它将出现在第一个片段的开始处。其余的片段将包含原始 PPP 帧信息字段的片段。最后一个片段将以原始 PPP 帧的最后几个字节结束。

接收设备将收集每个 PPP 帧的所有片段,并从每个片段中提取片段数据和 MP 头。它将使用序列号重新组装片段,然后处理生成的 PPP 帧。

PPP MP 分片演示

图 12-12 展示了 PPP 数据帧分片的演示。顶部是本章前面图 12-2 中显示的相同 PPP 数据帧。

这八个被灰显的字节是在帧需要分片时未使用的字节。因此,用于 MP 的 PPP 帧长度为 24 字节。此帧被分割成 8 字节的块,每个块都包含在 MP 分片的片段数据字段中。注意片段帧中的连续序列号值。另外,请注意,开始片段字段仅对第一个片段进行设置,而结束片段仅对最后一个进行设置。

PPP MP 分片 此图展示了单个 PPP 帧如何被分成三个更小的帧。

图 12-12. PPP MP 分片 此图展示了单个 PPP 帧如何被分成三个更小的帧。

第二部分-2. TCP/IP 网络接口/互联网层连接协议

第十三章

第十四章

OSI 参考模型的第二层是数据链路层;它对应于 TCP/IP 的网络接口层。在这一层,定义了大多数局域网(LAN)、广域网(WAN)和无线局域网(WLAN)技术,如以太网和 IEEE 802.11。

OSI 参考模型的第三层是网络层,在 TCP/IP 模型中也称为互联网层。在这一层,定义了互联网协议,其中最著名的是互联网协议(IP)。

第二层和第三层密切相关,因为网络层发送的消息必须在数据链路层通过单个物理网络传输。它们执行不同的任务,但作为协议栈中的邻居,它们必须相互协作。

一组协议承担着将这两层连接起来并使它们协同工作的重任。问题是决定这些协议应该放在哪里。它们在网络世界中有点像“黑羊”。没有人否认它们的重要性,但他们总是认为它们属于“别人的”层。例如,由于这些协议在层 2 网络上传递数据,处理层 2 技术的那些人认为这些协议属于层 3。但那些与层 3 协议工作的人认为这些低级协议为层 3 提供服务,因此将它们视为层 2 的一部分。

那么,这些协议去哪里呢?在一定程度上,这并不真的重要。我认为它们有些特别,所以我为它们提供了一个自己的家。欢迎来到网络层混沌之地,也称为 OSI 模型 2.5 层。这就是我将一些作为数据链路层和网络层之间粘合剂的协议放在一起的地方。这里的主要工作是地址解析,或者提供层 2 和层 3 地址之间的映射。这种解析可以是双向的,在本部分中描述的两个 TCP/IP 协议中得到了体现:地址解析协议(ARP)和反向地址解析协议(RARP),尽管它们有相似之处,但用于相当不同的目的。

我建议在继续之前熟悉层 2 和层 3 的基础知识(在第 I-2 部分和 I-3 部分中描述),特别是对 IP 地址的某些理解有帮助,尽管不是严格必要的。

第十三章。地址解析与 TCP/IP 地址解析协议(ARP)

无标题图片

在互联网上的通信是通过在第 3 层使用网络层地址发送数据来完成的,但实际上数据的传输是在第 2 层使用数据链路层地址进行的。这意味着每个具有完全指定的网络协议栈的设备都将拥有第 2 层和第 3 层的地址。有必要定义一种方法来将这些地址联系起来。通常,这是通过获取网络层地址并确定与之相对应的数据链路层地址来实现的。这个过程被称为地址解析

在本章中,我从概念和实际层面探讨了地址解析的问题,当然,重点是它在 TCP/IP 协议套件中的实现方式。我首先概述了地址解析的一般概念,它描述了过程中涉及的问题。然后,我详细描述了 TCP/IP 地址解析协议(ARP),这可能是最知名和最常用的地址解析技术。然后,我简要地探讨了在互联网协议(IP)中如何进行多播地址的地址解析,最后,介绍了新 IP 版本 6(IPv6)中使用的方法。

地址解析的概念和问题

由于 TCP/IP 在网络领域的突出地位,大多数关于地址解析的讨论都直接跳到了 TCP/IP 的 ARP。这个协议确实很重要,我们将在本章后面讨论它。然而,地址解析的基本问题并不特定于任何处理它的特定实现,如 ARP。为了更好地理解数据链路层和网络层之间解析地址的问题,并支持我们对 ARP 的考察,我们将首先从更一般的角度来探讨这个问题。

我首先从一般意义上讨论地址解析的需求。然后描述了解决地址解析问题的两种主要方法:直接映射和动态解析。我还探讨了实际动态地址解析中的一些效率问题,重点关注缓存的重要性。

地址解析的需求

有些人可能对地址解析的概念以及执行此功能的协议的需求感到犹豫。在第五章中关于 OSI 参考模型的讨论中,我详细地谈到了拥有概念层的目的在于分离逻辑功能,并允许高层协议隐藏于底层细节之外。鉴于这一点,为什么你需要将协议和层联系起来的地址解析协议呢?

这是真的。然而,OSI 参考模型正是这样一个模型。常常会出现一些需要解决方案的实际情况,这些解决方案并不严格符合层模型。当模型不符合现实时,模型必须让步。因此,在处理地址解析问题时也是如此。

第 2 层和第 3 层的地址解析

当你考虑 OSI 参考模型的七层时,有两层与寻址有关:数据链路层和网络层。物理层根本不严格涉及寻址,而是仅在位级别上进行发送。网络层以上的所有层都使用网络层地址。

但为什么要在两个不同的层级上进行寻址呢?答案是它们是用于不同目的的非常不同类型的地址。第 2 层地址(如 IEEE 802 MAC 地址)用于在可以直接通信的硬件设备之间进行本地传输。它们用于实现基本局域网(LAN)、无线局域网(WLAN)和广域网(WAN)技术。相比之下,第 3 层地址(最常见的是 IP 地址)用于互联网互连,以在网络层创建一个庞大的虚拟网络。

这些类型地址之间最重要的区别在于第 2 层和第 3 层:第 2 层处理直接连接的设备(在同一网络中),而第 3 层处理间接连接的设备(以及直接连接的设备)。比如说,你想连接到www.tcpipguide.com上的 Web 服务器。这是一个运行在服务器上的网站,该服务器内置了以太网卡,用于连接到其互联网服务提供商站点。然而,即使你知道它的 MAC 地址,你也不能使用它通过你家用 PC 中的以太网卡直接与该服务器通信,因为设备位于不同的网络中——实际上,它们可能位于不同的洲!

相反,你在第 3 层进行通信,使用 IP 和更高层协议,如传输控制协议(TCP)和超文本传输协议(HTTP)。你的请求从你的家用机器出发,通过一系列路由器到达“TCP/IP 指南”服务器,响应信息再返回给你。从逻辑上讲,通信是在第 3 层及以上进行的;你发送请求不是直接到服务器的网络卡的 MAC 地址,而是发送到服务器的 IP 地址。

然而,尽管你可以在第 3 层虚拟地连接设备,但这些连接实际上只是概念上的。当你使用 IP 发送请求时,请求是逐个发送的,从一个物理网络到下一个。在每个这样的跳中,物理和数据链路层都会发生实际传输。当你的请求发送到第 3 层的本地路由器时,实际的请求会封装在一个使用你物理连接到路由器的任何方法创建的帧中,然后通过路由器的数据链路层地址传递给路由器。后续的每个步骤都会发生同样的情况,直到最终,离目的地最近的路由器使用其数据链路(MAC)地址将数据发送到目的地。这如图图 13-1 所示。

为什么地址解析是必要的 尽管在概念上客户端和服务器在第 3 层直接连接,但实际上它们之间的信息传递要经过多个第 2 层链路。在这个例子中,本地网络上的一个客户端正在访问互联网上的某个服务器。逻辑上,这种连接可以直接在客户端和服务器之间建立,但实际上,它是一系列第 2 层的物理链路。在这种情况下,有六个这样的链路,其中大多数位于客户端和服务器之间的路由器之间。在每一步,数据发送的决定是基于第 3 层地址,但实际上必须使用路由路径中下一个预期接收者的第 2 层地址进行传输。

图 13-1. 为什么地址解析是必要的 虽然在概念上客户端和服务器在第三层直接连接,但在现实中,它们之间传递的信息要经过多个第二层链接。在这个例子中,本地网络上的一个客户端正在访问互联网上的某个服务器。在逻辑上,这个连接可以直接在客户端和服务器之间建立,但在现实中,它是一系列第二层的物理链接。在这种情况下,有六个这样的链接,其中大多数位于客户端和服务器之间的路由器之间。在每一步,决定将数据发送到哪里的决策是基于第三层地址,但实际的传输必须使用路由中下一个预期接收者的第二层地址来执行。

基本问题是,IP 地址对于网络上的物理硬件来说层级太高,它们不理解它们是什么。当你的请求到达连接到《TCP/IP 指南》的路由器时,它可以看到www.tcpipguide.com服务器的 IP 地址,但这并没有帮助:它需要发送到服务器的MAC 地址

即使是在局域网内的设备之间进行通信,也存在相同的问题。即使 Web 服务器和客户端坐在同一张桌子上,通信在逻辑上是 IP 层,但必须在数据链路层完成。这意味着你需要一种在两个层之间转换地址的方法。这个过程被称为地址解析

小贴士

关键概念 地址解析是必需的,因为互联网设备使用第三层地址进行逻辑通信,但设备之间的实际传输使用的是第二层(硬件)地址。

通用地址解析方法

实际上,你不仅需要有一种进行这种转换的方法,还需要关注它是如何进行的。由于这种转换发生在通过互联网发送的每个数据报的每个跳转中,因此这个过程的高效性非常重要。你不想使用占用大量网络资源的解析方法。

地址解析可以通过两种基本方式实现:直接映射和动态解析。

注意

由于必须性,不可能有一个完全通用的自动地址解析方法。因为它涉及到将数据链路层地址与网络层地址链接起来,所以实现必须针对这些层中每个层所使用的特定技术。唯一可以考虑为通用方法的是使用静态、手动更新的表格,例如,将这个第 3 层地址链接到这个第 2 层地址。"当然,这并不是自动的,并带来了手动配置的所有局限性

通过直接映射进行地址解析

在每个数据报穿越互联网的过程中,网络层地址必须多次解析为数据链路层地址。因此,你希望这个过程尽可能简单和高效。实现这一点的最简单方法是在这两种类型的地址之间进行直接映射

直接映射是如何工作的

在直接映射技术中,使用一个公式将高层地址映射到低层地址。这是一种更简单、更有效的方法,但它有一些局限性,尤其是在数据链路层地址和网络层地址的大小比较方面。

直接映射背后的基本思想是选择一种第 2 层和第 3 层地址的方案,以便你可以使用简单的算法从其中一个确定另一个。这使得你可以通过简短的程序将第 3 层地址转换为第 2 层地址。本质上,只要你有了第 3 层地址,你就已经有了第 2 层地址。

直接映射的最简单例子可能是,如果你为数据链路层和网络层地址使用了相同的结构和语义。这通常是不切实际的,因为这两种类型的地址服务于不同的目的,因此基于不兼容的标准。然而,如果你有足够的灵活性来创建足够大的第 3 层地址,以便在其中编码完整的链路层地址,你仍然可以进行直接映射。然后确定第 2 层地址就变成了简单地从第 3 层地址中选择一定部分的问题。

以一个简单的局域网技术,如 ARCNet 为例。它使用一个短的 8 位数据链路层地址,有效值为 1 到 255,可以由管理员分配。你可以在这样的 LAN 上轻松设置一个 IP 网络,通过使用 ARCNet 数据链路层作为最后一个八位字节来从类 C 网络中获取。因此,如果网络是,例如,222.101.33.0,你可以将 IP 地址 222.101.33.1 分配给具有 ARCNet 地址#1 的设备,将 IP 地址 222.101.33.29 分配给具有 ARCNet 地址#29 的设备,依此类推,如图 13-2 所示。在一个小的硬件地址大小下,你可以轻松地将每个硬件地址映射到一个第 3 层地址。如图所示,当硬件地址较小时,定义一个直接对应于第 3 层地址一部分的映射是很容易的。在这个例子中,一个 8 位的 MAC 地址,如 ARCNet 所使用的,被映射到设备的 IP 地址的最后字节,从而使地址解析变得微不足道。

通过直接映射进行地址解析 由于硬件地址尺寸较小,你可以轻松地将每个硬件地址映射到第 3 层地址。如图所示,当硬件地址较小时,定义一个直接对应于第 3 层地址一部分的映射非常容易。在这个例子中,一个 8 位的 MAC 地址,例如用于 ARCNet 的地址,被映射到设备的 IP 地址的最后字节,从而使地址解析变得非常简单。

图 13-2. 通过直接映射进行地址解析 由于硬件地址尺寸较小,你可以轻松地将每个硬件地址映射到第 3 层地址。如图所示,当硬件地址较小时,定义一个直接对应于第 3 层地址一部分的映射非常容易。在这个例子中,一个 8 位的 MAC 地址,例如用于 ARCNet 的地址,被映射到设备的 IP 地址的最后字节,从而使地址解析变得非常简单。

这个系统的吸引力是显而易见的。从概念上讲,理解起来非常简单——要获取设备的硬件地址,你只需使用 IP 地址的最后八位即可。编程设备执行操作也非常简单,效率极高,根本不需要在网络上交换数据。

小贴士

关键概念 当第 2 层地址小于第 3 层地址时,可以在它们之间定义一个直接映射,以便可以直接从网络层地址确定硬件地址。这使得地址解析变得极其简单,但减少了地址分配的灵活性。

直接映射的问题

不幸的是,直接映射仅在数据链路层地址可以表示为网络层地址的函数时才有效。考虑一下相同的 IP 地址,222.101.33.29,它在以太网网络上运行。在这里,数据链路层地址是硬编码在硬件本身中的(有时可以覆盖,但通常不这样做)。更重要的是,MAC 地址是 48 位宽,而不是 8 位。这意味着第 2 层地址比第 3 层地址大,无法进行直接映射,如图 13-3 所示。如图所示,当第 2 层地址的尺寸大于第 3 层地址时,无法定义一个用于地址解析的映射。

大硬件地址尺寸的地址解析问题 当第 2 层地址的尺寸大于第 3 层地址时,直接映射是不可能的。

图 13-3. 使用大硬件地址大小的地址解析问题 当第 2 层地址的大小大于第 3 层地址时,直接映射是不可能的。

注意

当硬件地址大小超过网络层地址大小时,你可以进行部分映射。例如,你可以使用 IP 地址来获取部分的 MAC 地址,并希望你在未使用的位上没有重复。这种方法不适合常规传输,但用于在 IPv4 中解析多播地址到以太网地址。你将在本章末尾看到这是如何完成的

因此,一般来说,当第 3 层地址小于第 2 层地址时,直接映射是不可能的。考虑到以太网是第 2 层最流行的技术,使用 48 位地址,而 IP 是第 3 层最流行的技术,使用 32 位地址。这就是为什么直接映射是一种不太广泛使用的技术的原因。

那下一代 IP 呢?IPv6 支持大量的 128 位地址(见第二十五章)。此外,常规(单播)地址甚至是通过一种方法定义的,该方法使用特殊映射从数据链路层地址创建它们。在理论上,这将允许 IPv6 使用直接映射进行地址解析。

然而,决定让 IPv6 使用与 IPv4 一样动态解析。一个可能的原因是历史原因,因为 IPv4 使用动态解析。然而,更大的原因可能是直接映射的缺点:它的不灵活性。动态解析是一个更通用的解决方案,因为它允许数据链路层和网络层地址独立,并且其缺点可以通过仔细的实现大部分得到中和,正如你将看到的。

实际上,这种证据可以在 IP 的动态解析定义在 ARCNet 的事实中看到,我刚才提到的例子。你可以在那里进行直接映射,但它限制了你使用一定模式的 IP 地址,这减少了灵活性。

动态地址解析

你刚才看到,直接映射提供了一种简单且非常高效的将网络层地址解析为数据链路层地址的方法。不幸的是,这是一种在大多数情况下你既不能使用也不应该使用的技术。当数据链路层地址的大小大于网络层地址的大小时,你不能使用它。当你需要灵活性时,你不应该使用它,因为直接映射要求你使第 3 层和第 2 层地址相对应。

直接映射的替代方法是称为 动态地址解析 的技术。这使用一种特殊的协议,允许只有 IP 地址的设备确定对应的数据链路层地址,即使这两种地址类型完全不同。这通常是通过查询本地网络中的一个或多个其他设备来确定与给定 IP 地址相对应的数据链路层地址来完成的。这比直接映射更复杂、效率更低,但更灵活。

动态寻址的工作原理

要了解动态寻址是如何工作的,你可以考虑一个简单的类比。我敢肯定你见过在机场等待接人的豪华轿车司机。(嗯,你在电影里见过,不是吗?)这与这里的问题类似:司机知道将被运输的人的名字,但不知道那个人的面孔(从某种意义上说,这是一种“本地地址”!)。为了找到那个人,司机举起了写有那个人名字的卡片。除了那个人之外的其他人都忽略了这张卡片,但被点名的人应该认出它并走向司机。

在网络中,动态地址解析做的是同样的事情。假设设备 A 想要向设备 B 发送数据,但只知道设备 B 的网络层地址(它的“名字”),而不是它的数据链路层地址(它的“面孔”)。它广播一个包含设备 B 的第三层地址的层 2 帧——这就像拿着写有某人名字的卡片一样。除了设备 B 之外的其他设备不识别这个第三层地址,并忽略它。然而,设备 B 知道自己的网络层地址。它在广播帧中识别出这一点,并直接向设备 A 发送响应。这告诉设备 A 设备 B 的层 2 地址,解析完成。图 13-4 展示了这个过程。

小贴士

关键概念 动态地址解析 通常是通过一种特殊的协议来实现的。一个只知道另一个设备的网络层地址的设备可以使用此协议来请求该设备的硬件地址。

动态地址解析 该设备想要发送数据,广播一个请求,要求从另一设备获取响应的硬件地址。设备 A 需要向设备 B 发送数据,但只知道其 IP 地址(IPB),而不知道其硬件地址。设备 A 广播一个请求,要求使用 IP 地址 IPB 发送该设备的硬件地址。设备 B 直接向设备 A 响应,提供硬件地址。

图 13-4. 动态地址解析 想要发送数据的设备广播一个请求,要求从另一设备获取响应的硬件地址。设备 A 需要向设备 B 发送数据,但只知道其 IP 地址(IPB),而不知道其硬件地址。设备 A 广播一个请求,要求使用 IP 地址 IPB 发送该设备的硬件地址。设备 B 直接向设备 A 响应,提供硬件地址。

虽然直接映射非常简单,但正如你所见,动态解析也不完全是火箭科学!它是一种简单易行且易于实现的技术。此外,它消除了与直接映射相关的限制。网络层地址和数据链路层地址之间不需要任何特定的关系;它们可以具有完全不同的结构和大小。

尽管直接映射涉及快速计算,但动态解析并不完全是火箭科学!它是一种简单易行的技术,可以消除与直接映射相关的限制。网络层地址和数据链路层地址之间不需要任何特定的关系;它们可以具有完全不同的结构和大小。

动态地址解析与效率问题

你现在已经看到了动态地址解析如何消除了你在直接映射中看到的限制,从而允许你轻松地关联任何大小或结构的 2 层和 3 层地址。它的唯一问题是,每个地址解析都需要你发送一条额外的消息,这在直接映射中是不必要的。更糟糕的是,由于你不知道接收者的 2 层身份,你必须使用广播消息(或者至少是多播),这意味着本地网络上的许多设备必须消耗资源来检查数据帧并确定正在解析哪个 IP 地址。

当然,发送一条额外的消息可能看起来不是什么大问题,因为帧不需要非常大,因为它只包含网络层地址和一些控制信息。然而,当你必须为每个数据报传输的每个跳步都这样做时,开销真的会累积起来。因此,尽管基本的动态地址解析简单且功能性强,但通常不足以满足需求。你必须向地址解析的实现中添加一些智能,以减少对持续地址解析性能的影响。

考虑到局域网上的大多数设备只向少数几个物理设备发送数据,并且往往反复这样做。这种现象被称为引用局部性,它在计算领域的许多不同领域都有观察到。如果你从你的办公 PC 向互联网网站发送请求,它首先需要到达你的公司网络本地路由器,因此你需要解析路由器的层 2 地址。如果你稍后点击该网站上的链接,该请求也需要发送到路由器。实际上,你几乎在本地网络之外所做的一切可能首先都会发送到同一个路由器(通常称为默认网关)。每次都必须进行新的解析将是愚蠢的。这就像每次你想给最好的朋友打电话说你好时,都必须查找他们的电话号码一样。

为了避免被指责设计出愚蠢的地址解析协议,设计者通常会包括一个缓存机制。当一个设备的网络层地址解析为数据链路层地址后,这两个地址之间的连接会在设备内存中保持一段时间。当它下次需要层 2 地址时,设备只需在其缓存中进行快速查找。这意味着,你不需要在每一个数据报上执行广播,而只需在整个数据报序列中执行一次。

缓存是动态解析中最重要的性能提升工具。它将原本可能非常浪费的过程转变为在大多数情况下与直接映射一样高效的过程。然而,它确实增加了复杂性。缓存表条目必须得到维护。还有一个问题,表中的信息可能会随着时间的推移而变得过时。如果你更改了设备的网络层地址或数据链路层地址会发生什么?因此,缓存条目必须定期过期。本章后面关于 TCP/IP 的 ARP 中缓存的讨论展示了如何处理这些问题的某些细节。

动态解析的其他增强

基本动态解析方案也可以进行其他增强。让我们再次考虑我们的例子,即向互联网发送请求。你发送一个需要发送到本地路由器的请求,因此你解析其地址并发送请求。片刻之后,回复返回到路由器,以便发送给你,因此路由器需要你的地址。因此,即使你刚刚交换了帧,它也必须对你进行动态解析。这同样是愚蠢的。相反,你可以通过交叉解析来提高效率;当设备 A 解析设备 B 的地址时,设备 B 也会将其条目添加到自己的缓存中。

还可以进行其他改进。如果你这么想,局域网中的设备将会相当频繁地相互通信,即使它们现在没有聊天。如果设备 A 正在解析设备 B 的网络层地址,它将广播一个所有设备 C、D、E 等都能看到的帧。为什么不让它们也更新它们的缓存表,以备将来使用解析信息呢?

这些以及其他增强功能都是为了减少动态地址解析的效率问题。它们结合起来使得动态解析在整体能力上接近直接映射,因此没有很好的理由不使用它。再次强调,你可以在描述 ARP 缓存功能的章节中看到更多关于这方面的细节。

顺便提一下,在这次讨论中,有时还会提出一个提高性能的想法:为什么不直接广播数据报,而不是先进行额外的广播步骤来解析地址呢?实际上你可以这样做,如果数据报足够小,这将更有效率。然而,通常情况下,数据报很大,而解析帧可以相当紧凑;进行小范围的广播然后进行大范围的单播是有意义的,而不是进行大范围的广播。此外,假设你广播了这个数据报。下一个数据报和再下一个数据报怎么办?这些数据报也需要广播。当你使用缓存进行解析时,你只需要偶尔广播一次,而不是持续不断地广播。

TCP/IP 地址解析协议 (ARP)

ARP 是一个功能齐全的动态解析协议,用于将 IP 地址与底层的数据链路层地址匹配。最初是为以太网开发的,但现在已被推广,允许 IP 在多种 2 层技术上进行操作。

注意

这里描述的地址解析协议用于解析互联网协议第 4 版(IPv4)中的单播地址。IPv4 中的多播地址使用直接映射方法,而 IPv6 使用新的邻居发现(ND)协议而不是 ARP。这两种方法都在本章末尾进行讨论

小贴士

相关信息 有关具有移动 IP 设备的网络中 ARP 相关问题的讨论,请参阅第三十章

小贴士

相关信息 用于在主机上管理 TCP/IP ARP 实现的软件应用arp,在第八十八章中有详细说明

物理网络在 OSI 参考模型的第 1 层和第 2 层运行,并使用数据链路层地址。相比之下,互联网协议在第三层运行,将这些物理网络互联起来,创建一个可能非常大的设备互联网,这些设备使用网络层地址指定。地址解析是将网络层地址解析为数据链路层地址的过程。这允许数据在互联网中逐跳发送。

地址解析问题在 TCP/IP 协议套件的开发一开始就很明显。IP 的早期开发大部分是在当时新兴的以太网局域网技术上进行的;这甚至是在以太网被正式标准化为 IEEE 802.3 之前。有必要定义一种将 IP 地址映射到以太网地址的方法,以便在以太网网络上进行通信。

正如我们在本章中已经看到的,关联 IP 和以太网地址有两种基本方法:直接映射或动态解析。然而,以太网地址是 48 位长,而 IP 地址只有 32 位,这立即排除了直接映射。此外,IP 的设计者希望使用动态解析模型带来的灵活性。为此,他们开发了 TCP/IP 地址解析协议(ARP)。该协议在互联网 RFCs 中描述,这些 RFC 是最早的,现在仍在普遍使用:RFC 826,“一个以太网地址解析协议”,于 1982 年发布。

从名称上可以看出,ARP 最初是为以太网开发的。因此,它代表了最流行的第 2 层局域网协议和最流行的第 3 层互联网协议之间的一个枢纽。即使二十年后,这一点仍然是正确的。然而,从一开始就很明显,尽管以太网是传输 IP 的一种非常常见的方式,但它不会是唯一的方式。因此,ARP 被设计成一个通用协议,能够从 IP 解析到以太网以及其他多种数据链路层技术。

ARP 的基本操作涉及在广播消息中编码目标接收者的 IP 地址。它被发送到本地网络,以便 IP 数据报的目标接收者能够用其数据链路层地址对源进行响应。这是通过简单的请求和回复方法完成的。ARP 消息使用特殊格式,这些消息被传递到本地数据链路层进行传输。

小贴士

关键概念 ARP(地址解析协议)是为了促进 IP 和以太网之间的动态地址解析而开发的,现在也可以用于其他第 2 层技术。它通过允许 IP 设备在本地网络发送广播,并从同一本地网络上的另一设备请求一个硬件地址来工作。

这种基本操作通过提高性能的方法得到了补充。由于从一开始就知道必须对每个数据报使用广播进行解析是荒谬的低效,因此 ARP 始终使用一个缓存,在该缓存中它保留本地网络中 IP 地址和数据链路层地址之间的绑定。随着时间的推移,已经开发出各种技术来改进用于维护缓存条目的方法。在过去的几年中,还定义了改进和附加功能,例如支持设备对之间的交叉解析以及代理 ARP,并将这些功能添加到基本的 ARP 功能集中。

ARP 地址规范和一般操作

当 IP 网络上的源设备有一个要发送的 IP 数据报时,ARP 事务就开始了。它必须首先决定目标设备是在本地网络还是远程网络。如果是前者,它将直接发送到目标;如果是后者,它将数据报发送到物理网络上的一个路由器以进行转发。无论哪种方式,它都将确定本地网络上需要成为其 IP 数据报直接目标设备的 IP 地址。在封装数据报后,它将将其传递给其 ARP 软件进行地址解析。

ARP 的基本操作是在本地网络上进行的一对请求和响应传输。源(需要发送 IP 数据报的一方)广播包含有关目标(数据报的预期接收者)的信息。然后目标通过单播向源响应,告诉源目标的硬件地址。

ARP 消息类型和地址指定

目标这两个术语在整个事务中适用于相同的设备。然而,在 ARP 中发送了两种不同的消息:一种是从源到目标的消息,另一种是从目标到源的消息。对于每个 ARP 消息,发送者是正在传输消息的一方,而目标是接收它的一方。因此,发送者和目标的身份在每个消息中都会改变。以下是请求和回复中发送者和目标身份的工作方式:

请求 对于初始请求,发送者是源(要发送 IP 数据报的设备),目标是目标。

回复 对于 ARP 请求的回复,发送者是目标。它向源回复,源成为目标。

任何消息中的双方都有两个地址(二层和三层)需要关注,因此每个消息都涉及以下四个不同的地址:

发送者硬件地址 ARP 消息的发送者的二层地址。

发送者协议地址 ARP 消息的发送者的三层(IP)地址。

目标硬件地址 ARP 消息的目标的二层地址。

目标协议地址 目标的三层(IP)地址。

这些地址在 ARP 消息格式中都有位置,我们将在稍后进行考察。

ARP 通用操作

在有了这个背景之后,让我们看看在 ARP 事务中发生的步骤。(这些步骤也在 图 13-5 事务处理过程 ARP 通过源设备广播一个请求以查找目标,目标使用回复消息进行响应。ARP 缓存也会被咨询并更新。") 中的插图中有图形展示。)此图显示了典型 ARP 事务中发生的步骤序列,以及源设备和目标设备之间的消息交换,以及缓存检查和更新功能。(顺便说一句,那些小堆栈是硬盘,而不是汤罐头!)

  1. 源设备检查缓存 源设备首先会检查其缓存以确定是否已经解析了目标设备。如果是这样,它可以直接跳到步骤 9。

  2. 源设备生成 ARP 请求消息 源设备生成一个 ARP 请求消息。它将自己的数据链路层地址作为发送者硬件地址,自己的 IP 地址作为发送者协议地址。它填写目标设备的 IP 地址作为目标协议地址。(它必须将目标硬件地址留空,因为它正在尝试确定这个地址!)

  3. 源设备广播 ARP 请求消息 源设备在本地网络上广播 ARP 请求消息。

    地址解析协议 (ARP) 事务处理过程 ARP 通过源设备广播一个请求以查找目标,目标使用回复消息进行响应。ARP 缓存也会被咨询并更新。

    图 13-5. 地址解析协议 (ARP) 事务处理过程 ARP 通过源设备广播一个请求以查找目标,目标使用回复消息进行响应。当需要时,ARP 缓存也会被咨询并更新。

  4. 本地设备处理 ARP 请求消息 消息被本地网络上的每个设备接收。它被处理,每个设备都会寻找与目标协议地址匹配的匹配项。那些不匹配的将丢弃消息并采取进一步行动。

  5. 目标设备生成 ARP 回复消息 那个 IP 地址与消息中的目标协议地址内容匹配的设备将生成一个 ARP 回复消息。它从 ARP 请求消息中获取发送者硬件地址和发送者协议地址字段,并使用这些值作为回复的目标硬件地址和目标协议地址。然后它填写自己的第 2 层地址作为发送者硬件地址,自己的 IP 地址作为发送者协议地址。其他字段按以下章节中 ARP 消息格式描述的解释进行填写。

  6. 目标设备更新 ARP 缓存 如果源设备现在需要向目标发送 IP 数据报,那么目标设备可能很快需要向源设备发送响应是有意义的。(毕竟,网络上的大多数通信都是双向的。)接下来,作为一个优化,目标设备将在其 ARP 缓存中添加一个条目,包含发送 ARP 请求的源的硬件和 IP 地址。这可以节省目标设备在以后不需要进行不必要的解析周期。

  7. 目标设备发送 ARP 回复消息 目标设备发送 ARP 回复消息。然而,这个回复是单播发送给源设备的,因为不需要广播。

  8. 源设备处理 ARP 回复消息 源设备处理来自目标的回复。它将发送者硬件地址作为目标层的 2 层地址存储,并使用该地址发送其 IP 数据报。

  9. 源设备更新 ARP 缓存 源设备使用发送者协议地址和发送者硬件地址来更新其 ARP 缓存,以便在将来向该设备传输时使用。

小贴士

关键概念 ARP 是一种相对简单的请求-回复协议。源设备广播一个 ARP 请求,根据设备的 IP 地址寻找特定的设备。该设备通过 ARP 回复消息回复其硬件地址。

注意,这个描述超出了地址解析的基本步骤,因为提到了两个增强功能。一个是缓存,你很快就会了解。另一个是交叉解析(在本章关于动态解析缓存问题的概述中描述),这是过程的第 6 步。这就是为什么源设备在请求中包含其 IP 地址的原因。实际上并不需要其他原因,所以你可以看到这个功能是从 ARP 一开始就被构建在内的。

ARP 消息格式

你刚刚看到了如何在 ARP 中通过源设备寻求解析和响应它的目标设备之间的消息交换来完成地址解析。与其他协议一样,使用特殊的消息格式来包含解析过程中每一步所需的信息。

ARP 消息使用相对简单的格式。它包括一个字段,描述消息的类型(其操作码opcode)以及关于第 2 层和第 3 层地址的信息。为了支持可能具有不同长度的地址,格式指定了第 2 层和第 3 层使用的协议类型,以及在这些层中使用的地址长度。然后包括空间以容纳本章前面描述的所有四种地址组合:发送者硬件地址、发送者协议地址、目标硬件地址和目标协议地址。

ARP 消息的格式在 表 13-1 中描述。 图 13-6 展示了 ARP 消息格式是如何设计以适应各种大小的层 2 和层 3 地址的。此图显示了最常用的实现,它使用 32 位用于层 3("协议")地址,48 位用于层 2 硬件地址。这些数字对应于以太网使用的 IPv4 和 IEEE 802 MAC 地址的大小。

表 13-1. ARP 消息格式

字段名称 大小(字节) 描述
HRD 2 硬件类型:此字段指定用于传输 ARP 消息的本地网络的硬件类型;因此,它也标识了使用的寻址类型。此字段最常见的值显示在 表 13-2 字段值") 中。
PRO 2 协议类型:此字段是硬件类型字段的补码,指定消息中使用的层 3 地址的类型。对于 IPv4 地址,此值是 2048(十六进制 0800),对应于 IP 的 EtherType 代码。
HLN 1 硬件地址长度:指定此消息中硬件地址的长度。对于以太网或其他使用 IEEE 802 MAC 地址的网络,此值是 6。
PLN 1 协议地址长度:同样,是前一个字段的补码;指定此消息中协议(层 3)地址的长度。对于 IPv4 地址,此值是 4。
OP 2 操作码:此字段指定发送的 ARP 消息的性质。前两个值(1 和 2)用于常规 ARP。还定义了多个其他值以支持使用 ARP 帧格式的其他协议,如 RARP,如 表 13-3 字段值") 所示。某些协议比其他协议更广泛使用。
SHA 变量,等于 HLN 字段中的值 发送者硬件地址:发送此消息的设备的硬件(层 2)地址,在请求中是 IP 数据报源设备,在回复中是 IP 数据报目标。
SPA 变量,等于 PLN 字段中的值 发送者协议地址:发送此消息的设备的 IP 地址。
THA 变量,等于 HLN 字段中的值 目标硬件地址:此消息要发送到的设备的硬件(层 2)地址。在请求中这是 IP 数据报目标设备,在回复中是 IP 数据报源。
TPA 变量,等于 PLN 字段中的值 目标协议地址:此消息要发送到的设备的 IP 地址。

表 13-2. ARP 硬件类型 (HRD) 字段值

硬件类型 (HRD) 值 硬件类型
1 以太网(10 Mb)
6 IEEE 802 网络
7 ARCNeT
15 帧中继
16 异步传输模式 (ATM)
17 高级数据链路控制 (HDLC)
18 光纤通道
19 异步传输模式 (ATM)
20 串行线路

表 13-3. ARP 操作码(OP)字段值

操作码 ARP 消息类型
1 ARP 请求
2 ARP 回复
3 RARP 请求
4 RARP 回复
5 DRARP 请求
6 DRARP 回复
7 DRARP 错误
8 InARP 请求
9 ARP 回复

ARP 消息格式

图 13-6. ARP 消息格式

一旦 ARP 消息被组成,它就会被传递到数据链路层进行传输。ARP 消息的整个内容成为实际在网络中发送的消息的有效负载,例如在以太网 LAN 上的以太网帧。请注意,ARP 消息的总大小是可变的,因为地址字段长度是可变的。然而,通常这些消息相当小。例如,它们在携带 IPv4 数据报的 IEEE 802 MAC 地址网络上只有 28 字节。

ARP 缓存

ARP 是一种动态解析协议,这意味着每次解析都需要在网络上交换消息。每次设备发送 ARP 消息时,都会占用本地网络,消耗无法用于其他流量的网络带宽。ARP 消息并不大,但需要为每个 IP 数据报的每个跳步发送它们,这将对网络性能造成不可接受的负面影响。与简单的直接映射解析方法相比,这也浪费了时间。此外,ARP 请求消息是广播的,这意味着本地网络上的每个设备都必须花费 CPU 时间检查每个消息的内容。

动态解析效率问题的通用解决方案是采用 缓存。除了减少网络流量外,缓存还确保常用地址的解析速度快,从而使整体性能与直接映射相当。因此,缓存功能从一开始就被集成到 ARP 中。

静态和动态 ARP 缓存条目

ARP 缓存以包含匹配的硬件和 IP 地址对的表格形式存在。网络上的每个设备都管理自己的 ARP 缓存表。缓存条目可以以两种不同的方式放入 ARP 缓存:

静态 ARP 缓存条目 这些是手动添加到设备缓存表的地址解析,并且永久保留在缓存中。静态条目通常使用如 arp 软件工具(见第八十八章)等工具进行管理。

动态 ARP 缓存条目 这些是软件根据过去成功完成的 ARP 解析添加到缓存的硬件和 IP 地址对。它们只在缓存中保留一段时间,然后被删除。

设备的 ARP 缓存可以包含静态和动态条目,每个条目都有其优缺点。然而,动态条目使用得最频繁,因为它们是自动的,不需要管理员干预。

静态 ARP 条目最适合用于需要定期与之通信的设备。例如,工作站可能为其本地路由器和文件服务器设置静态 ARP 条目。由于条目是静态的,它总是在 ARP 事务过程的第 1 步中找到,并且不需要为该条目中的目标发送解析消息。缺点是这些条目必须手动添加,如果条目中任何硬件的硬件或 IP 地址发生变化,它们也必须更改。此外,每个静态条目都会占用 ARP 缓存的空间,因此你不希望过度使用静态条目。例如,为网络上的每个设备设置静态条目可能不是个好主意。

缓存条目过期

动态条目根据需要自动添加到缓存中,因此它们代表设备正在积极使用的宿主机和路由器的映射。它们不需要手动添加或维护。然而,重要的是要认识到,动态条目不能永久留在缓存中——长时间留在原地的动态条目可能会变得过时。

考虑设备 A 的 ARP 缓存,其中包含对设备 B 的动态映射,设备 B 是网络上的另一个主机。如果动态条目永远留在缓存中,可能会出现以下情况。

设备硬件更改 设备 B 可能会遇到需要更换其网络接口卡的硬件故障。由于条目中的硬件地址不再在网络上,设备 A 的缓存中的映射将变得无效。

设备 IP 地址更改 类似地,如果设备 B 的 IP 地址更改,设备 A 的缓存中的映射也会变得无效。

设备移除 假设设备 B 从本地网络中移除。设备 A 将永远不会在数据链路层再次向它发送数据,但映射将保留在设备 A 的缓存中,浪费空间,并可能占用搜索时间。

为了避免这些问题,动态缓存条目必须设置为在一段时间后自动过期。这由 ARP 实现自动处理,典型的超时值是 10 或 20 分钟。在特定条目超时后,它将从缓存中删除。下次需要地址映射时,将执行新的解析以更新缓存。这比静态条目稍微低效一点,但每 10 或 20 分钟发送两个 28 字节的消息并不是什么大问题。

如 ARP 操作概述中所述,动态缓存条目不仅在设备启动解析时添加,当它是目标设备时也会添加。这是另一个减少不必要的地址解析流量的增强功能。

其他缓存功能

根据实现方式,通常还会实施其他增强功能。标准 ARP 要求,如果设备 A 通过广播启动解析,网络上的每个设备都应该更新自己的设备 A 的缓存条目,即使它们不是设备 A 试图到达的设备。然而,在这些情况下,“第三方”设备不需要为设备 A 创建新的缓存条目。

这里的问题是一个权衡。创建一个新的缓存条目将使这些设备中的任何一个在未来不需要解析设备 A 的地址。然而,这也意味着网络上的每个设备都会很快将 ARP 缓存表填满,其中包含网络上大多数其他设备的地址。这在较大的网络中可能不是所希望的。即使在较小的网络中,这种模式可能也不合理,因为现代计算本质上是客户端/服务器模式,局域网上的对等设备可能不会经常直接通信。一些设备可能会选择创建这样的缓存条目,但它们可能会将它们设置为在非常短的时间内过期,以避免填满缓存。

每个 ARP 实现还负责维护缓存所需的所有其他家务工作。例如,如果一个设备在一个有大量主机的本地网络上,并且其缓存表太小,那么可能有必要删除较旧、使用频率较低的条目,为新条目腾出空间。理想情况下,缓存应该足够大,可以容纳设备在网络上定期通信的所有其他设备,以及一些偶尔与之通信的设备的空间。

代理 ARP

ARP 被设计为供直接连接在本地网络上的设备使用。网络上的每个设备都应该能够直接向彼此发送单播和广播传输。通常,如果设备 A 和设备 B 通过路由器分离,它们就不会被认为是彼此的本地设备。设备 A 不会直接向设备 B 发送,反之亦然;它们会在第二层向路由器发送,并在第三层被认为是两个跳数之隔。

然而,在某些网络情况下,可能会有两个物理网络段位于同一 IP 网络或子网络中,并通过路由器连接。换句话说,设备 A 和设备 B 可能在数据链路层级别位于不同的网络,但在同一 IP 网络或子网中。当这种情况发生时,设备 A 和设备 B 在尝试发送 IP 数据报时,都会认为对方位于本地网络中。

在这种情况下,假设设备 A 想要向设备 B 发送数据报。它没有在缓存中找到设备 B 的硬件地址,因此开始地址解析。然而,当它广播 ARP 请求消息以获取设备 B 的硬件地址时,它将很快遇到一个问题:设备 B 不在设备 A 的本地网络中。它们之间的路由器不会将设备 A 的广播传递到设备 B 的网络部分,因为路由器不会传递硬件层的广播。设备 B 永远不会收到请求,因此设备 A 将不会收到包含设备 B 硬件地址的回复。

这种情况下的解决方案被称为ARP 代理代理 ARP。在这种技术中,位于本地网络之间的路由器被配置为代表设备 B 响应设备 A 的广播。它不会将设备 B 的硬件地址发送回设备 A。由于它们不在同一个网络中,设备 A 无论如何也无法直接向设备 B 发送数据。相反,路由器将发送设备 A 自己的硬件地址。然后设备 A 将消息发送给路由器,路由器将消息转发到另一个网络中的设备 B。当然,路由器也会代表设备 A 为设备 B 做同样的事情,以及为两个网络上的其他每个设备做同样的事情,当发送的广播消息的目标设备不在与解析发起者相同的实际物理网络上时。这如图图 13-7 所示。

代理 ARP 为那些主机实际上不在同一个物理网络上,但被配置为在网络层上的网络提供了灵活性。它可以用于在其他特殊情况下提供支持,在这些情况下,设备无法直接响应 ARP 消息广播。当防火墙出于安全目的配置时,可能会使用它。在移动 IP 中,也使用一种代理类型来解决移动设备离开其本地网络时地址解析的问题。

小贴士

关键概念 由于 ARP 依赖于广播进行地址解析,而广播不会在物理网络之外传播,因此 ARP 不能在位于不同物理网络上的设备之间工作。当需要此类操作时,可以将设备(如路由器)配置为 ARP 代理,代表不同网络上的设备响应 ARP 请求。

ARP 代理操作 这些示例展示了作为 ARP 代理的路由器如何响应一个设备对另一网络地址的请求,返回其自己的硬件地址。在这个所示的小型互联网中,一个路由器连接了位于同一 IP 网络或子网上的两个局域网。该路由器不会传递 ARP 广播,但已被配置为作为 ARP 代理。在这个例子中,设备 A 和设备 D 都试图向对方发送 IP 数据报,因此每个都广播了一个 ARP 请求。路由器响应设备 A 发送的请求,就像它是设备 D 一样,向设备 A 提供其自己的硬件地址(而不传播设备 A 的广播)。它将设备 A 发送给设备 D 的消息转发到设备 D 的网络。同样,它以设备 A 的身份响应设备 D,提供自己的地址,然后将设备 D 发送给它的消息转发到设备 A 所在的网络。

图 13-7. ARP 代理操作 这两个示例展示了作为 ARP 代理的路由器如何响应一个设备对另一网络地址的请求,返回其自己的硬件地址。在这个所示的小型互联网中,一个路由器连接了位于同一 IP 网络或子网上的两个局域网。该路由器不会传递 ARP 广播,但已被配置为作为 ARP 代理。在这个例子中,设备 A 和设备 D 都试图向对方发送 IP 数据报,因此每个都广播了一个 ARP 请求。路由器响应设备 A 发送的请求,就像它是设备 D 一样,向设备 A 提供其自己的硬件地址(而不传播设备 A 的广播)。它将设备 A 发送给设备 D 的消息转发到设备 D 的网络。同样,它以设备 A 的身份响应设备 D,提供自己的地址,然后将设备 D 发送给它的消息转发到设备 A 所在的网络。

代理的主要优势是它对不同物理网络段上的主机是透明的。然而,这项技术也有一些缺点。首先,它引入了额外的复杂性。其次,如果多个路由器使用相同的网络 ID 连接两个物理网络,可能会出现问题。第三,它引入了潜在的安全风险;因为它本质上意味着路由器通过充当代理来冒充设备,因此设备冒充另一个设备的可能性是真实的。出于这些原因,如果可能的话,最好重新设计网络,以便在由路由器分隔的物理网络之间进行路由。

TCP/IP 地址解析用于 IP 组播地址

与大多数关于地址解析的讨论一样,到目前为止,本章的大部分内容都集中在单播通信上,其中数据报从一个源设备发送到单个目标设备。无论使用直接映射还是动态解析来解析网络层地址,当只有一个预期的数据报接收者时,解析地址相对简单。正如你所看到的,TCP/IP 使用 ARP 进行其动态解析方案,该方案仅设计用于单播解析。

然而,IP 也支持数据报的 组播,正如我在第二十三章(第二十三章。IP 路由和组播)和第十七章(第十七章。类地址(传统)寻址)中关于 IP 组播和 IP 组播地址的章节中解释的那样。在这种情况下,数据报必须发送到多个接收者,这大大增加了复杂性。您需要在 IP 组播组地址和数据链路层设备的地址之间建立某种关系。您可以通过在数据链路层将 IP 组播数据报转换为单个单播传输来实现这一点,每个都使用 ARP 进行解析,但这将非常低效。

当可能时,IP 利用底层网络的组播寻址和交付能力,在物理网络上交付组播数据报。也许令人惊讶的是,尽管 ARP 使用动态解析,但组播地址解析是使用直接映射技术的一种版本。通过定义 IP 组播组和数据链路层组播组之间的 映射,您使物理设备知道何时关注组播数据报。

最常用的具有组播功能的数据链路层寻址方案是 IEEE 802 寻址系统,它最著名的用途是在以太网网络中。这些数据链路层地址有 48 位,分为两个 24 位的块。高 24 位被组织成一个称为 组织唯一标识符 (OUI) 的块,不同的值分配给各个组织;然后低 24 位用于特定设备。

互联网分配号码权威机构 (IANA) 本身有一个用于将组播地址映射到 IEEE 802 地址的 OUI。这个 OUI 是 01:00:5E。为了形成以太网的映射,使用 24 位用于这个 OUI,第 25 位(48 位中的第 25 位)始终为零。这留下了原始 48 位中的 23 位来编码组播地址。为了进行映射,组播地址的低位 23 位被用作以太网地址的最后 23 位,以 01:00:5E 开头发送组播消息。

图 13-8

提示

关键概念 IP 多播地址通过使用 23 位 IP 多播组地址的直接映射技术解析为 IEEE 802(以太网)MAC 地址。

当然,IP 多播地址中有 28 个独特的比特位,所以这有点问题!这意味着 IP 多播地址和以太网多播地址之间没有唯一的映射关系。由于多播组的 28 位中的 5 位无法编码到以太网地址中,因此 32 个(2⁵)不同的 IP 多播地址映射到每个可能的以太网多播地址。在理论上,这可能会成为一个问题,但在实践中,它并不是。在单个网络中,任何两个 IP 多播地址同时映射到相同的以太网多播地址的概率相当小。

多播 IP 地址映射到 IEEE 802 多播 MAC 地址的图示 多播 IP 地址通过复制 IANA 多播 OUI 值(01-00-5E)到最高 24 位,将第 25 位设置为 0,并将多播地址的最低 23 位复制到剩余的 23 位来映射到 IEEE 802 多播 MAC 地址。为了创建一个 48 位的多播 IEEE 802(以太网)地址,最高 24 位填充了 IANA 的多播 OUI,01-00-5E。第 25 位是 0,多播组的最低 23 位放入 MAC 地址的最低 23 位。这留下了 5 位(如图中阴影所示)没有映射到 MAC 地址,这意味着 32 个不同的 IP 地址可能有相同的多播 MAC 地址。

图 13-8. 多播 IP 地址到 IEEE 802 多播 MAC 地址的映射 多播 IP 地址通过复制 IANA 多播 OUI 值(01-00-5E)到最高 24 位,将第 25 位设置为零,并将多播地址的最低 23 位复制到剩余的 23 位,映射到 IEEE 802 多播 MAC 地址。为了创建一个 48 位的多播 IEEE 802(以太网)地址,最高 24 位填充了 IANA 的多播 OUI,01-00-5E。第 25 位为零,多播组的最低 23 位放入 MAC 地址的最低 23 位。这留下了 5 位(以虚线表示)没有映射到 MAC 地址,这意味着 32 个不同的 IP 地址可能有相同的多播 MAC 地址映射。

尽管如此,可能存在两个 IP 多播组在同一物理网络上使用,并映射到相同的数据链路层多播地址的情况。因此,设备不能假设它们接收到的所有多播消息都是为它们的组设计的;它们必须将消息传递到 IP 层以检查完整的 IP 多播地址,以确保它们确实应该接收它们接收到的多播数据报。如果它们意外地收到一个旨在为它们不是成员的多播组设计的消息,它们将丢弃它。这种情况很少发生,因此相对缺乏效率不是一个大问题。

TCP/IP 地址解析针对 IP 版本 6

TCP/IP ARP 是一个相当通用的协议,用于动态地将网络层地址解析为数据链路层地址。尽管它是为 IPv4 设计的,但消息格式允许硬件和网络层使用可变长度的地址。这种灵活性意味着理论上可以使用它来处理 IP 的新版本,IPv6。可能需要一些小的改动,但技术可能大致相同。

然而,IPv6 的设计者选择不这样做。改变 IP 是一项庞大的工作,已经进行了多年,提供了改变 TCP/IP 各个方面的罕见机会。互联网工程任务组(IETF)决定利用 IPv6 的变化来彻底改革 IP 本身,以及支持或协助它的许多协议。在 IPv6 中,ARP 的地址解析任务与原始 TCP/IP 套件中由互联网控制消息协议(ICMP)执行的一些功能相结合,补充了额外的功能,并定义为新的邻居发现(ND)协议。

IPv6 中的术语 邻居 简单地指的是本地网络上的设备,正如其名所示,ND 负责与邻居(以及其他事物)之间通信信息的相关任务。我在 第三十六章 协议") 中简要介绍了 ND,包括讨论它执行的各种任务。在这里,我特别关注 ND 如何执行地址解析。

IPv6 ND 中地址解析的基本概念与 IPv4 ARP 中的概念并没有太大的不同。解析仍然是动态的,并且基于使用一个缓存表来维护 IPv6 地址和硬件地址的配对。物理网络上的每个设备都会跟踪其邻居的这些信息。当一个源设备需要向本地网络邻居发送 IPv6 数据报,但没有其硬件地址时,它将启动解析过程。为了在文本中清晰起见,让我们说,像往常一样,设备 A 正在尝试向设备 B 发送数据。

相比于发送 ARP 请求消息,设备 A 创建了一个 ND 邻居请求消息。现在,从这里我们可以看到从 ARP 的第一个重大变化。如果底层数据链路协议支持多播,就像以太网一样,邻居请求消息就不会广播。相反,它被发送到要解析的 IPv6 地址的设备的请求节点地址。所以设备 A 不会广播消息,但它会将消息多播到设备 B 的请求节点多播地址。

请求节点多播地址是从每个多播能力网络设备的多播地址创建的特殊映射;它在第二十五章(第二十五章。IPv6 寻址)中关于 IPv6 多播地址的讨论中描述。请求节点地址对于每个 IPv6 地址并不是唯一的,但在给定网络上任何两个邻居具有相同地址的概率很小。每个接收到多播邻居请求的设备仍然需要检查以确保它就是源设备试图解析的设备。

如果设备仍然需要检查每条消息,为什么还要这样做呢?多播最多只会影响少数设备。使用广播,本地网络上的每个设备都会接收到消息,而使用请求节点地址意味着最多只有几台设备需要处理它。其他设备甚至不需要麻烦检查邻居请求消息。

设备 B 将接收邻居请求并回应对设备 A 的邻居通告。这类似于 ARP 回复,并告诉设备 A 设备 B 的物理地址。然后设备 A 将设备 B 的信息添加到其邻居缓存中。为了提高效率,支持跨解析,就像 IPv4 地址解析一样。这是通过设备 A 在邻居请求中包含其自己的第 2 层地址来实现的,假设它知道这个地址。设备 B 将记录这个地址以及设备 A 的 IP 地址到设备 B 的邻居缓存中。

小贴士

关键概念 IPv6 中的地址解析使用新的邻居发现(ND)协议而不是地址解析协议(ARP)。试图发送 IPv6 数据报的设备会发送一个邻居请求消息以获取另一个设备的地址,该设备会响应一个邻居广告。当可能时,为了提高效率,请求会使用一种特殊的组播地址而不是广播发送。

这实际上是对 IPv6 中解析工作原理的相对简化解释,因为邻居发现(ND)相当复杂。邻居请求和广告也用于其他功能,例如测试节点的可达性以及确定是否有重复地址在使用。ND 还处理许多特殊情况问题,以确保在地址解析过程中不会出现任何问题。ND 还支持代理地址解析。

注意

尽管我把这次讨论放在了接近其他地址解析讨论的位置,但 ND 实际上并不是一个像 ARP 那样的层连接或底层协议。它在角色和功能上与 ICMP (第三十一章)相似,并且实际上使用了 ICMP(v6)消息。这种架构变化的一个优点是减少了对外部网络特性的依赖,因此解析是以更类似于其他网络支持活动的方式完成的。因此,可以利用适用于所有 IP 数据报传输的设施,例如 IP 安全特性。第三十六章包含更多关于这个主题的信息

第十四章。反向地址解析和 TCP/IP 反向地址解析协议(RARP)

无标题图片

在第十三章中,你探讨了 TCP/IP 地址解析协议(ARP)的操作。当设备需要确定其他设备的第 2 层(硬件)地址但只知道其第 3 层(网络,IP)地址时,会使用 ARP。它会广播一个硬件层请求,目标设备会响应一个与已知 IP 地址匹配的硬件地址。

理论上,也可以以相反的方式使用 ARP。如果你知道设备的硬件地址但不知道其 IP 地址,你可以广播一个包含硬件地址的请求,并得到一个包含 IP 地址的响应。在本章中,你将简要探讨这种反向地址解析的概念。

显然,首先的问题是你为什么要做这件事?既然你正在处理基于互联网协议(IP)的通信,你总是知道你需要发送的数据报的 IP 地址——它就在数据报本身中。你也知道自己的 IP 地址。或者你不知道?

在传统的 TCP/IP 网络中,网络上的每个普通主机都知道自己的 IP 地址,因为它的 IP 地址存储在机器的某个地方。当你打开你的 PC 时,TCP/IP 软件会从文件中读取 IP 地址,这使得你的 PC 能够学习和开始使用它的 IP 地址。然而,有些设备,如无盘工作站,没有任何存储 IP 地址的手段,以便可以轻松检索。当这些单元启动时,它们只知道自己的物理地址(因为它是通过硬件连接的),但不知道自己的 IP 地址。

你需要解决的问题在计算机行业中通常被称为引导。这指的是从零状态开始某事的概念;它类似于“自己拉起自己的靴带”。这似乎是不可能的,就像使用 TCP/IP 来配置 TCP/IP 通信所需的 IP 地址一样似乎矛盾。然而,通过使用广播,即使不知道目标地址,也可以实现这一点,这是可能的。

反向地址解析协议(RARP)

解决 TCP/IP 启动问题所采用的第一种方法是反向使用 ARP,这在上一章中已有描述。这种技术被正式化在 1984 年发布的 RFC 903,“反向地址解析协议(RARP)”。ARP 允许设备 A 说:“我是设备 A,我拥有设备 B 的 IP 地址。设备 B,请告诉我你的硬件地址。”RARP 由设备 A 用来表示:“我是设备 A,我正在使用我的硬件地址发送这个广播;请有人告诉我我的 IP 地址?”

RARP 的兩步操作如图 14-1 所示。正如其名称所暗示的,RARP 的工作方式与 ARP 相反,这就是为什么这个图与图 13-4 相似。

那么接下来的问题是,如果设备 A 不知道,谁知道设备 A 的 IP 地址?答案是必须配置一个特殊的RARP 服务器来监听 RARP 请求,然后对它们做出响应。每个使用 RARP 的物理网络都必须至少在一台机器上运行 RARP 软件。

RARP 不仅与 ARP 非常相似,实际上它基本上就是 ARP。RFC 903 并没有从头定义一个全新的协议;它只是描述了一种使用 ARP 来执行其正常功能相反的新方法。RARP 使用与 ARP 相同的格式(在第十三章中描述)的 ARP 消息,但使用不同的操作码来完成其反向功能。与 ARP 一样,在交换中使用了请求和回复。地址字段的意义也是相同的:发送者是传输消息的设备,而目标是接收它的设备。

小贴士

关键概念 反向地址解析协议(RARP) 是最早且最简单的协议,旨在允许设备在 TCP/IP 网络上获取 IP 地址。它直接基于 ARP,基本上以相同的方式工作,但相反:设备发送包含其硬件地址的请求,而设置为 RARP 服务器的设备则响应并提供设备的分配 IP 地址。

反向地址解析协议 (RARP) 操作 RARP 与 ARP 类似,但方向相反;设备广播其硬件地址,RARP 服务器以其 IP 地址响应。在这里,不是设备 A 提供另一个设备的 IP 地址并请求其硬件地址,而是提供自己的硬件地址并请求可以使用的 IP 地址。在这种情况下,答案是设备 D 提供的,它作为该网络的 RARP 服务器。

图 14-1. 反向地址解析协议 (RARP) 操作 RARP 与 ARP 类似,但方向相反;设备广播其硬件地址,RARP 服务器以其 IP 地址响应。在这里,不是设备 A 提供另一个设备的 IP 地址并请求其硬件地址,而是提供自己的硬件地址并请求可以使用的 IP 地址。在这种情况下,答案是设备 D 提供的,它作为该网络的 RARP 服务器。

RARP 通用操作

图 14-2 操作 RARP 包括一个广播请求消息和一个单播回复消息的交换。") 展示了 RARP 事务中遵循的步骤。如您所见,RARP 使用简单的请求和回复交换,允许设备获取 IP 地址。

反向地址解析协议 (RARP) 操作 RARP 包括一个广播请求消息和一个单播回复消息的交换。

图 14-2. 反向地址解析协议 (RARP) 操作 RARP 包括一个广播请求消息和一个单播回复消息的交换。

这里是每个步骤发生的情况:

  1. 源设备生成 RARP 请求消息 源设备生成一个 RARP 请求消息。因此,它在消息中使用值 3 作为 opcode。它将自己的数据链路层地址作为发送者硬件地址和目标硬件地址。它将发送者协议地址和目标协议地址留空,因为它不知道这些信息。

  2. 源设备广播 RARP 请求消息 源设备在本地网络上广播 ARP 请求消息。

  3. 本地设备处理 RARP 请求消息 该消息被本地网络上的每个设备接收并处理。未配置为作为 RARP 服务器的设备会忽略该消息。

  4. RARP 服务器生成 RARP 响应消息 网络上任何设置为充当 RARP 服务器的设备都会对源设备的广播做出响应。它使用操作码值为 4 生成一个 RARP 响应。它将发送者硬件地址和发送者协议地址设置为它自己的硬件和 IP 地址,因为它是对话的发送者。然后,它将目标硬件地址设置为原始源设备的硬件地址。它在表中查找源设备的硬件地址,确定该设备的 IP 地址分配,并将其放入目标协议地址字段。

  5. RARP 服务器发送 RARP 响应消息 RARP 服务器将 RARP 响应消息单播发送给正在尝试配置的设备。

  6. 源设备处理 RARP 响应消息 源设备处理来自 RARP 服务器的响应。然后,它使用 RARP 服务器提供的目标协议地址中的 IP 地址来配置自己。

注意

如果任何本地网络上配置了两个或更多的 RARP 服务器,则可能有多于一个的 RARP 服务器响应请求。源设备通常会使用第一个响应并丢弃其他响应

RARP 的局限性

RARP 是我所说的主机配置协议类别中最早且最基础的协议之一,我在第五十九章中以一般术语描述了这些协议。作为这些协议中的第一个,RARP 在 20 世纪 80 年代初对 TCP/IP 来说是一个有用的补充,但它有几个缺点,其中最重要的是以下这些:

低级硬件导向 RARP 使用硬件广播工作。这意味着如果你有一个由许多物理网络组成的大型互连网络,你需要在每个网络段上都有一个 RARP 服务器。更糟糕的是,如果你需要可靠性来确保 RARP 即使在某个 RARP 服务器宕机的情况下也能继续运行,你需要在每个物理网络上配置两个RARP 服务器。这使得 IP 地址的集中管理变得困难。

手动分配 RARP 允许主机自动配置自己,但 RARP 服务器仍需手动设置硬件与 IP 地址之间的绑定表。这些绑定表需要为每个服务器维护,这又给管理员带来了大量工作。

有限信息 RARP 只为主机提供其 IP 地址。它无法提供其他所需信息,例如,例如,子网掩码或默认网关。

自 20 世纪 80 年代初以来,主机配置的重要性显著增加。许多组织甚至为具有磁盘存储的主机动态分配 IP 地址,因为这种做法在管理和地址空间的高效使用上提供了许多优势。因此,RARP 已被两种更高级的技术所取代,这些技术运行在 TCP/IP 协议栈的更高层:BOOTP 和 DHCP。它们在主机配置协议的应用层部分中进行了讨论,从第第六十章")到第第六十四章。

第二部分-3. 互联网协议版本 4 (IP/IPV4)

第十五章

第十六章

第十七章 寻址")

第十八章 概念")

第十九章

第二十章/超网")

第二十一章

第二十二章

第二十三章

如果考虑到网络中任何一种协议比其他协议更重要,那么这种想法似乎有点没有意义。协议和技术作为一个团队工作,以实现网络通信的目标。就像任何团队一样,无论成员多么优秀,没有单个成员能够独立完成任务。尽管如此,如果我们试图在网络世界中挑选一个“最有价值球员”,那么可以说我们找到了 TCP/IP 的 互联网协议 (IP)

即使在 TCP/IP 协议套件的名称中它排在第二位,IP 协议仍然是 TCP/IP 的主力。它实现了关键的网络层功能,包括寻址、数据报处理和路由,并且是其他 TCP/IP 协议建立的基础。即使是 TCP/IP 架构中较低层的协议,如地址解析协议 (ARP) 和点对点协议 (PPP),在了解 IP 协议的工作原理后也更容易理解。

本部分包括九个章节,对 IP 协议进行了相当全面的介绍。第一章对 IP 协议的整体进行了概述,包括对其版本的讨论,而其余章节则专注于当前最受欢迎的协议版本——IP 版本 4 (IPv4) 的操作细节。

第二至第六章详细讨论了 IP 寻址的概念和实践。第二章提供了 IPv4 寻址概念和问题的概述。第三章讨论了原始的基于类别的 (类别) IP 寻址方案以及不同类别的工作方式。第四和第五章致力于 IP 子网和子网寻址。它们讨论了子网划分的概念,并包括了一个实际步骤的子网划分示例。第六章描述了新的无类别寻址系统,有时也称为 超网

第七章到第九章讨论了与 IPv4 数据报创建和处理相关的重要实际问题。你将在第七章中找到 IPv4 消息格式和选项的完整描述;第八章中解释了 IP 数据报的大小、分片和重组;第九章涵盖了路由和多播。

如本部分标题所示,这里的覆盖范围仅限于 IPv4。为了简单起见,在本部分中,我使用更简单的标识符IP而不是IPv4,除非需要清晰地区分版本号。IPv6(IP 版本 6)在其单独的部分(第二部分-4"))中介绍,以及与 IP 相关的协议。尽管如此,这里的一些原则也将以有限的方式适用于 IPv6,以及 IP 网络地址转换(NAT)、IPsec 和移动 IP(第二部分-4"))。

第十五章:互联网协议版本、概念和概述

无标题图片

互联网协议(IP)是互联网互连中非常重要的一个协议。可以说,没有对 IP 的良好理解,你实际上是无法真正理解现代网络的。不幸的是,IP 可能有些难以理解。多年来,大量复杂性与之相关联,这使得它能够满足所面临的众多需求。

在深入探讨 IP 的工作原理之前,我们将先了解 IP 的基本概念。在本章中,我将用基本术语解释 IP 的工作原理以及它完成工作的最重要的方面。我们将探讨其主要功能、历史以及它是如何催生多个与 IP 相关的协议的发展。

IP 概述和关键操作特性

IP 是 TCP/IP 协议族的核心,也是网络层的主要协议。网络层主要关注在不同网络之间传输数据,这些网络以任意方式相互连接。换句话说,就是一个互联网。IP 是通过这种机制在 TCP/IP 网络上发送数据(当然,也需要网络层其他协议的帮助)。

让我们来看看 TCP/IP 层模型,并从架构的角度考虑 IP 的功能。作为第 3 层协议,它为 TCP/IP 堆栈的第 4 层提供服务,主要由传输控制协议(TCP)和用户数据报协议(UDP)代表(见第二部分-8)。IP 接收由 TCP 或 UDP 打包的数据,根据需要对其进行操作,并将其发送出去(见图 15-1)。

这种服务有时被称为互联网数据报传输。有许多细节解释了这项服务是如何完成的,但简而言之,IP 通过连接的网络互联网从 A 点发送数据到 B 点。

IP 的主要功能:互联网数据报传输 IP 的整体责任是在未连接的网络设备之间传输数据。此图展示了 IP 如何在互联网中从一个设备向另一个设备传输数据报;在这种情况下,远程客户端和服务器通过在一系列互联网络中传递 IP 数据报来相互通信。

图 15-1. IP 的主要功能:互联网数据报传输 IP 的整体责任是在未连接的网络设备之间传输数据。此图展示了 IP 如何在互联网中从一个设备向另一个设备传输数据报;在这种情况下,远程客户端和服务器通过在一系列互联网络中传递 IP 数据报来相互通信。

提示

关键概念 虽然互联网协议有许多功能和特性,但它可以归结为一个主要目的:在连接的网络互联网中传输数据报。

当然,有许多方法可以实现 IP 来完成这项任务。为了了解 TCP/IP 的设计者是如何让 IP 工作的,让我们来看看描述 IP 的关键特性以及它的一般操作方式:

通用寻址 为了从 A 点发送数据到 B 点,必须确保设备知道如何识别 B 点。IP 定义了网络的寻址机制,并使用这些地址进行传输目的。

底层协议无关 IP 被设计成允许数据跨越任何类型的底层网络传输,这些网络被设计成与 TCP/IP 堆栈一起工作。它包括允许其适应各种底层协议(如以太网或 IEEE 802.11)要求的条款。IP 还可以在为它专门创建的特殊数据链路协议上运行,例如串行线路接口协议(SLIP)和点对点协议(PPP)(请参阅第二部分第一章到第二十章/超网")中进行了全面探讨。

数据封装和格式化/包装 作为 TCP/IP 网络层协议,IP 从传输层协议 UDP 和 TCP 接收数据。然后,它使用一种特殊格式在传输之前将此数据封装成 IP 数据报。

分片和重组 IP 数据报被传递到数据链路层,以便在本地网络上进行传输。然而,使用 IP 的每个物理和数据链路网络的最大帧大小可能不同。因此,IP 包括将 IP 数据报分成片段的能力,这样它们就可以分别携带到本地网络。接收设备使用重组功能来重新创建整个 IP 数据报。尽管很明显它们是互补的,但有些人将分片和重组视为不同的功能,而我将它们视为同一工作的组成部分。

路由和间接投递 当一个 IP 数据报必须发送到同一本地网络上的目的地时,你可以通过使用网络的底层局域网(LAN)、无线局域网(WLAN)或广域网(WAN)协议,以所谓的直接投递方式轻松完成。然而,在许多(如果不是大多数情况下),最终目的地是在一个与源不直接相连的远程网络上。在这种情况下,数据报必须间接投递。这是通过将数据报通过中间设备(路由器)进行路由来实现的。IP 与包括互联网控制消息协议(ICMP)和 TCP/IP 网关/路由协议(如路由信息协议 RIP 和边界网关协议 BGP)在内的其他协议的支持下完成这一任务。

IP 的历史、标准、版本和密切相关协议

由于 IP 实际上是整个 TCP/IP 协议套件的架构基础,你可能预计它是最先被创建的,其他协议都是建立在它之上的。毕竟,这是构建结构的方式!然而,IP 的历史要复杂得多。它的功能在协议诞生时就已经定义,但在定义协议套件的最初几年里,IP 本身并不存在。

我在第八章中探讨了 TCP/IP 的早期阶段,该章提供了整个套件的概述。IP 发展的一个显著特点是,它的功能最初是 TCP 的一部分。作为一个正式的协议,IP 是在 20 世纪 70 年代为现代互联网的前身开发的一个早期版本的 TCP 中,当它在第 4 层分割成 TCP,在第 3 层分割成 IP 时诞生的。IP 发展的关键里程碑是 1981 年 9 月发布的 RFC 791,“互联网协议”。这个标准是前一年类似 RFC 760 的修订版,定义了在过去二十年里广泛使用的 IP 版本的核心功能和特性。

IP 版本和版本号

在 RFC 791 中定义的 IP 是第一个广泛使用的 IP 版本。然而,有趣的是,这并不是 IP 的第 1 版,而是第 4 版!这当然意味着在某个时候,该协议有更早的版本。然而,实际上并没有。IP 是在其功能从早期版本的 TCP 中分离出来时创建的,该 TCP 结合了 TCP 和 IP 的功能。TCP 通过三个更早的版本演变,并在第 4 版时被分割成 TCP 和 IP。这个版本号被应用于 TCP 和 IP 以保持一致性。

小贴士

关键概念 第 4 版的互联网协议(IP)实际上是第一个广泛部署的版本,目前仍在广泛使用。

因此,当你今天使用 IP 时,你使用的是 IP 版本 4,通常简称为 IPv4。除非另有说明,否则可以安全地假设IP指的是 IP 版本 4——至少在未来几年内是这样。(这个版本号包含在所有 IP 数据报的适当字段中,如第二十一章中讨论的 IP 数据报格式所述。)

考虑到它最初是为一个比我们当前互联网小得多的互连网设计的,IPv4 已经证明了自己具有非凡的能力。随着时间的推移,对 IP 的使用方式进行了各种补充和变更,尤其是在地址方面,但核心协议基本上与 20 世纪 80 年代初相同。这有很好的理由。改变像 IP 这样基本的东西需要大量的开发工作,并且在过渡期间也会引入复杂性。

IPv4 为我们服务得很好,但人们理解,由于各种原因,最终将需要一个新的 IP 版本。由于进行如此重要变更的困难,这个新版本的 IP 开发实际上从 20 世纪 90 年代中期就开始了。这个新版本的 IP 正式称为互联网协议版本 6(IPv6),有时也被称为IP 下一代IPng。我在本书的第二部分-4")中详细讨论了 IPv6 的开发原因以及它与 IPv4 的不同之处。

在这个阶段,一个自然的问题就是,“IP 的第五版发生了什么?”答案是它根本不存在。虽然这可能会让人感到困惑,但第五版实际上是有意跳过的,以避免混淆,或者至少是纠正它。第五版的问题与一个名为互联网流协议,版本 2的实验性 TCP/IP 协议有关,最初在 RFC 1190 中定义。这个协议最初被一些人视为 TCP/IP 架构中互联网层 IP 的同等协议,在其标准版本中,这些数据包被分配了 IP 版本 5,以区分它们与正常的 IP 数据包(版本 4)。这个协议显然并没有走得太远,但为了绝对确保不会有混淆,版本 5 被跳过,转而使用版本 6。

与 IP 相关的协议

除了旧的和新的 IP 版本之外,还有一些与 IP 相关的协议。这些协议是为了在特殊情况下增强或扩展 IP 功能,但它们不是 IP 本身的一部分。具体如下:

IP 网络地址转换(IP NAT 或 NAT) 该协议提供了 IP 地址转换功能,允许以灵活的方式将私有网络连接到公共网络。它允许共享公共 IP 地址,并通过使公共网络上的主机更难未经授权访问主机来提高安全性。它通常被称为NAT。本协议在第二十八章中进行了讨论。

IP 安全(IPsec) IPsec 定义了一组子协议,提供了一种使用 IP 安全传输数据的机制。作为能够启用虚拟专用网络的安全协议,它正迅速增长其受欢迎程度。本协议在第二十九章中进行了讨论。

移动 IP 这是一个协议,用于解决在使用 IP 时,频繁在不同网络间移动的计算机所遇到的一些困难。它提供了一种机制,允许数据自动路由到移动主机(如笔记本电脑),而无需不断重新配置设备的 IP 地址。本协议在第三十章中进行了讨论。

第十六章。IPV4 寻址概念和问题

无标题图片

互联网协议(IP)的主要任务是传递设备之间的消息,就像任何优秀的递送服务一样,如果不知道收件人的位置,它就无法很好地完成其工作。显然,IP 最重要的功能之一就是寻址。IP 寻址不仅用于唯一标识 IP 地址,而且还用于在互联网中路由 IP 数据报。IP 地址在 TCP/IP 网络中被广泛使用和提及。

尽管原始的 IP 寻址方案相对简单,但随着对其进行的修改以适应各种寻址需求,它已经变得复杂。更高级的 IP 寻址风格,如子网划分和无类别寻址,是现代网络中最常用的。然而,它们可能有点难以理解。为了帮助理解它们,我们必须从讨论 IP 寻址的基本原理开始。

在本章中,我通过解释 IP 地址背后的关键概念和问题,开始对 IP 地址分配进行更深入的研究。我首先概述 IP 地址分配,并讨论其内容。我描述了 IP 地址的大小、其地址空间的概念以及通常用于 IP 地址的表示法。我提供了关于 IP 地址结构的基本信息以及它是如何分为网络标识符和主机标识符的。然后,我描述了不同类型的 IP 地址以及通常伴随 IP 地址出现在大型网络中的附加信息,如子网掩码和默认网关。我简要描述了有时将多个地址分配给单个设备的原因。最后,我描述了公共 IP 地址的注册和管理过程,以及执行这项工作的组织。

小贴士

背景信息 如果你不熟悉至少二进制数的基本工作原理,以及如何将二进制数和十进制数相互转换,我建议你在继续阅读之前阅读第四章,该章节提供了关于数据表示和计算数学的一些背景信息

IP 地址分配概述和基础知识

IP 地址分配非常重要,因为它促进了 IP 的主要功能:在互联网中传递数据报。当你更详细地检查这一点时,你会发现 IP 地址实际上有两个不同的功能,如下所示:

网络接口标识 就像街道地址一样,IP 地址为设备与网络之间的接口提供了唯一的标识。这是确保数据报被交付给正确收件人的必要条件。

路由 当 IP 数据报的源和目标不在同一网络时,必须通过中间系统间接交付数据报。这个过程称为 路由。IP 地址是用于路由数据报的系统的基本组成部分。

你可能已经注意到了这个简短列表中的几个问题。一个是我说 IP 地址标识的是 网络接口,而不是标识 设备 本身。这种区别很重要,因为它强调了 IP 是围绕连接到大型、虚拟网络的概念,该网络位于第 3 层,可以跨越多个物理网络。一些设备,如路由器,将拥有多个网络连接,这是必要的,以便从一个网络中提取数据报并将它们路由到另一个网络。这意味着它们也将拥有多个 IP 地址——每个连接一个。

你可能也会觉得奇怪,我之前说 IP 地址有助于路由。它是如何做到这一点的呢?答案是,这个地址系统是设计成具有一种结构,可以解释为允许路由器根据地址中的值来确定对数据报的处理方式。与 IP 地址相关的数字,如使用子网划分时的子网掩码,支持这一功能。

让我们一般性地探讨一些与 IP 地址相关的重要问题和特性。

每个设备的 IP 地址数量

任何在网络层发送数据给它的设备至少有一个 IP 地址:每个网络接口一个。这意味着像计算机和网络打印机这样的普通主机通常只有一个 IP 地址,而路由器则拥有多个 IP 地址。如果某些特殊主机是多宿主的——连接到多个网络——它们可能拥有多个 IP 地址。

较低级别的网络互联设备,如中继器、网桥和交换机,不需要 IP 地址,因为它们根据第二层(数据链路层)地址传递流量。通过网桥和交换机连接的网络段形成一个单一的广播域,并且任何连接到它们的设备都可以直接发送数据给对方,而无需路由。对于 IP 来说,这些设备基本上是看不见的;它们的重要性不比连接设备的电线大(有几个例外)。然而,这些设备可能为了管理目的而选择性地拥有一个 IP 地址。在这方面,它们表现得就像网络上的普通主机。

图 16-1 展示了几个常见局域网设备的 IP 接口,以小圆圈表示。每个正常主机有一个接口,而服务于这个局域网的路由器有三个,因为它连接到三个不同的网络。请注意,局域网交换机没有 IP 接口;它在第二层连接主机和路由器。(也参见图 16-5,它展示了更复杂配置中设备的 IP 接口。)

常见网络设备的 IP 接口 正常主机有一个接口;路由器通常有多个;而交换机没有(因为它们在第二层操作)。

图 16-1.常见网络设备的 IP 接口常规主机有一个接口;路由器通常有多个;而交换机没有(因为它们在层 2 操作)。

地址唯一性和网络特定性

单个互联网上的每个 IP 地址都必须是唯一的。(这似乎非常明显,尽管在 IPv6 中存在例外,形式为特殊的任播地址,如第二十五章第二十五章。IPv6 寻址中所述。)

由于 IP 地址代表网络接口并用于路由,因此 IP 地址特定于连接的网络。如果设备移动到新的网络,IP 地址通常也必须更改。关于这一点的完整原因,请参阅本章后面关于基本 IP 地址结构的讨论。这个问题是创建移动 IP(在第三十章第三十章。互联网协议移动支持(移动 IP)")中介绍)的主要动机之一。

对比 IP 地址和链路层地址

IP 地址用于在互联网中跨网络层的数据传输。这使得 IP 地址与设备的链路层地址(如其以太网 MAC 地址)有很大不同。(在 TCP/IP 术语中,这些有时被称为物理地址硬件地址。)

在网络层,一个数据报可以从设备 A 发送到设备 B。然而,如果设备 A 和设备 B 不在同一网络中,实际的数据报交付可能需要它通过十几个或更多的物理设备。

还需要提供一个将 IP 地址和链路层地址之间进行映射的功能。在 TCP/IP 中,这是地址解析协议(ARP)的工作(见第十三章第十三章。地址解析和 TCP/IP 地址解析协议(ARP)"))。

在一个物理网络(如以太网)中,MAC 地址是发送设备之间数据所需的所有信息。相比之下,IP 地址仅代表数据报的最终交付点。所采取的路径取决于源设备和目标设备之间网络路径的特性。甚至可能不存在任何两个设备之间的路由,这意味着即使它们知道彼此的地址,两个设备也无法交换数据!

私有和公共 IP 网络地址

使用 IP 地址设置网络有两种不同的方式。在私有网络中,单个组织控制所有设备的地址分配;他们在选择数字方面几乎有绝对的自由,只要每个地址都是唯一的。

相比之下,在公共网络上,需要一个机制来确保组织不会使用重叠的地址,并且能够有效地在组织之间路由数据。最著名的例子是互联网,为了解决这个问题,已经创建了公共 IP 注册和管理设施。现在还有一些高级技术,如 IP 网络地址转换(NAT),允许使用私有地址的网络与公共 TCP/IP 网络接口。

IP 地址配置和寻址类型

IP 地址可以设置为静态或动态配置。在静态配置设置中,每个设备都会手动配置一个不会改变的 IP 地址。这对于小型网络来说是可以的,但在大型网络中,当需要更改时,这会迅速变成一个管理噩梦。另一种选择,动态配置,允许在软件控制下分配和更改 IP 地址。为了填补这一后者的功能,创建了两种主机配置协议,即 BOOTP 和 DHCP(参见第三部分-3)。

此外,IP 寻址方案还包括所有三种基本寻址类型:单播、多播和广播。

小贴士

关键概念 IP 地址具有设备标识和路由的双重功能。每个网络接口需要一个 IP 地址,这是网络特定的。IP 地址可以是静态或动态分配的,并且有单播、多播和广播形式。

IP 地址的大小、地址空间和表示法

现在您已经了解了与 IP 地址相关的一般问题和特征,是时候超越介绍,深入探讨 IP 地址的“实质”讨论了。让我们首先看看 IP 地址的物理结构和大小,以及它是如何被引用和使用的。

IP 地址大小和二进制表示法

在最简单的情况下,IP 地址只是一个 32 位的二进制数:一组 32 个 1 或 0。在最低级别,计算机总是以二进制形式工作,这同样适用于网络硬件和软件。虽然地址中的不同位被赋予了不同的含义,但地址本身只是一个 32 位的二进制数。

人们不太擅长处理二进制数,因为它们很长且复杂,仅使用两个数字使得它们难以区分。(快,以下哪个更大:11100011010100101001100110110001 还是 11100011010100101001101110110001?)因此,当使用 IP 地址时,除非绝对必要,否则不会以二进制形式处理它们。

人们自然会对一长串比特进行的第一件事就是将其分成四个八位字节(或者字节,尽管这两个词在技术上并不完全相同;参见第四章),以便更容易管理。所以 11100011010100101001101110110001 将变成 11100011 - 01010010 - 10011101 - 10110001。然后你可以将每个字节转换成一个更易管理的两位十六进制数,得到以下结果:E3 - 52 - 9D - B1。实际上,这是 IEEE 802 MAC 地址所使用的表示法,只是它们是 48 位长的,所以它们有六个两位的十六进制数,并且通常用冒号而不是破折号分隔,就像我这里所做的那样。

(顺便提一下,第二个二进制数是较大的那个。)

IP 地址点分十进制表示法

大多数人仍然觉得十六进制数有点难以处理。因此,IP 地址通常以每个八位字节转换为十进制数,并且字节之间用点()分隔来表示。因此,前面的例子将变成 227.82.157.177,如图 16-2 所示。这通常被称为点分十进制表示法,原因相当明显。IP 地址中的每个八位字节可以取从 0 到 255 的值,因此最低值理论上为 0.0.0.0,最高值为 255.255.255.255。

小贴士

关键概念 IP 地址是 32 位的二进制数,可以用二进制、十六进制或十进制形式表示。最常见的是,它们通过将 32 位分成四个字节并将每个字节转换为十进制来表示,然后用点分隔这些数字以创建点分十进制表示法。

IP 地址的二进制、十六进制和点分十进制表示形式。IP 地址的二进制、十六进制和十进制表示都是等效的

图 16-2. IP 地址的二进制、十六进制和点分十进制表示形式。IP 地址的二进制、十六进制和十进制表示都是等效的

点分十进制表示法为人们在通信中处理 IP 地址提供了一个方便的方法。永远不要忘记,对于计算机来说,IP 地址始终是一个 32 位的二进制数;当你查看下一个主题中 IP 地址的逻辑组成部分时,以及当你检查操作 IP 地址的技术,如子网划分时,你会理解这一点的重要性。

IP 地址空间

由于 IP 地址是 32 位宽,这提供了理论上的地址空间为 2³²,或 4,294,967,296 个地址。这似乎有很多地址,从某些方面来看确实是这样的。然而,正如您将看到的,由于 IP 地址的结构和分配方式,并非所有这些地址都可以实际使用。

IP 最初是在一个相当小的互联网上创建的,这一事实的一个不幸遗产是,所做的决定浪费了大部分地址空间。例如,所有以 127 开头的第一个八位字节中的 IP 地址都保留用于环回功能。仅此一项决定就使得总地址的 1/256,即 16,277,216 个地址不再可用。还有其他一些方式没有保存 IP 地址空间。随着互联网规模的扩大,这造成了困难。(您将在第十七章中了解更多关于这一点,该章涵盖了类别地址。)

提示

关键概念 由于 IP 地址是 32 位长,因此 IPv4 的总地址空间为 2³²或 4,294,967,296 个地址。然而,由于各种原因,并非所有这些地址都可以使用。

这个 IP 地址空间决定了每个 IP 互联网中可寻址接口数量的限制。因此,如果您有一个私有网络,从理论上讲,您可以拥有超过四十亿的地址。然而,在像互联网这样的公共网络中,所有设备必须共享可用的地址空间。设计诸如无类别域间路由(CIDR)、超网技术或 NAT 等技术部分是为了更有效地利用现有的互联网 IP 地址空间。IPv6 将 IP 地址的大小从 32 位扩展到 128 位,地址空间增加到极其庞大的数字,使得整个地址空间大小的问题变得无关紧要。

IP 基本地址结构和主要组件

正如我在 IP 地址概述中提到的,IP 地址被用来促进 IP 互联网中数据报的路由。这是由于 IP 地址的结构以及网络路由器如何解释这种结构而成为可能。

网络 ID 和主机 ID

正如您刚才看到的,每个 IPv4 地址都是 32 位长。当您引用 IP 地址时,您使用点分十进制表示法,而计算机将其转换为二进制。然而,尽管这些 32 位的集合被视为一个单一实体,但它们包含两个组成部分的内部结构:

网络标识符(网络 ID) 从最左边的位开始的一定数量的位用于标识主机或其他网络接口所在的网络。这有时也被称为网络前缀,甚至只是前缀

主机标识符(主机 ID) 剩余的位用于标识网络上的主机。

注意

按照惯例,为了简便起见,IP 设备通常被称为主机,正如我在本书中一直所做的那样。尽管每个主机通常只有一个 IP 地址,但你应该记住,IP 地址严格关联于网络层的网络接口,而不是物理设备,因此一个设备可能拥有多个 IP 地址(尤其是路由器或多宿主主机)。

如您在图 16-3 中可以看到,这实际上是一个相当简单的概念。IP 地址位的根本划分是网络 ID 和主机 ID。在此图中,网络 ID 长度为 8 位,主机 ID 长度为 24 位。这与北美电话号码的结构相似。电话号码(401)555-7777 是一个十位数的号码,通常被称为一个单独的电话号码。然而,它有一个结构。特别是,它有一个区号(401)和一个本地号码(555-7777)。

网络 ID 包含在 IP 地址中,这在地址已知时部分促进了 IP 数据报的路由。路由器查看 IP 地址的网络部分,首先确定目标 IP 地址是否与主机 IP 地址在同一网络上。然后根据路由器保留的有关各种网络位置的信息做出路由决策。再次强调,这与电话网络中相当于路由器的实体使用区号切换电话呼叫的概念上是相似的。地址的主机部分由网络本地部分的设备使用。

基本 IP 地址划分:网络 ID 和主机 ID 此图展示了将 IP 地址划分为网络 ID 和主机 ID 的多种方法之一。

图 16-3. 基本 IP 地址划分:网络 ID 和主机 ID 此图展示了将 IP 地址划分为网络 ID 和主机 ID 的多种方法之一。

网络 ID 和主机 ID 之间的划分位置

IP 地址和电话号码之间的一个区别是,用于标识网络和标识主机的位之间的划分点不是固定的。它取决于地址的性质、所使用的寻址类型和其他因素。

以先前的例子 227.82.157.177 为例(见图 16-2)。可以将其划分为网络 ID 227.82 和主机 ID 157.177。或者,网络 ID 可能是 227,而网络内的主机 ID 可能是 82.157.177。

为了将网络 ID 和主机 ID 表示为 32 位地址,你需要添加零来替换缺失的部分。以网络 ID 为 227 和主机 ID 为 82.157.177 为例,网络地址变为 227.0.0.0,主机地址为 0.82.157.177。(在实践中,这种类型的网络地址通常会看到添加的零;网络 ID 以这种方式以 32 位形式出现的频率不高。)

不要认为从这些例子中可以得出分割必须总是在整个八位字节之间进行的结论,你应该知道它也可以在八位字节的中部进行分割。例如,你可以将 IP 地址 227.82.157.177 分割,使得网络 ID 有 20 位,主机 ID 有 12 位。过程是相同的,但确定点分十进制 ID 值更为复杂,因为在这里,157 被分割成两个二进制数。结果是网络 ID 为 227.82.144.0,主机 ID 为 0.0.0.13.177,如图 16-4 所示。图 16-4。

由于 IP 地址通常表示为四个点分十进制数字,教育资源通常会显示网络 ID 和主机 ID 在八位字节边界上的分割。然而,必须记住,分割点通常出现在这些八位数字的中间。在图 16-4 中,网络 ID 为 20 位,主机 ID 为 12 位。这导致原始 IP 地址的第三个数字 157 被分割成 144 和 13。

为了让像路由器这样的设备知道如何解释地址,必须知道网络 ID 和主机 ID 之间的分割位置。这个信息要么隐含地传达,要么明确地传达,具体取决于使用的 IP 地址类型,正如我接下来要讨论的。

中八位字节 IP 地址分割 IP 地址不需要在八位字节边界上分割网络 ID 和主机 ID。这里的分割是一个 20 位网络 ID 和一个 12 位主机 ID。

图 16-4. 中八位字节 IP 地址分割 IP 地址不需要在八位字节边界上分割网络 ID 和主机 ID。这里的分割是一个 20 位网络 ID 和一个 12 位主机 ID。

提示

关键概念 IP 地址的基本结构由两个部分组成:网络 ID 和主机 ID。32 位地址的分割点不是固定的,而是取决于多个因素,并且可能出现在各种位置,包括点分十进制八位字节的中部。

由于 IP 地址可以被分成网络 ID 和主机 ID 组件,因此根据上下文,也可以单独使用其中一个或另一个。这些地址被赋予了特殊的意义。例如,如果使用全 1 作为主机 ID 的网络 ID,这表示向整个网络广播。同样,如果主机 ID 单独使用,网络 ID 为全 0,这表示发送到本地网络中该 ID 主机的 IP 地址,无论该主机是什么。这将在第十七章中详细解释。

正是网络 ID 包含在每个网络上的每个主机的 IP 地址中,才使得 IP 地址具有网络特定的性质。如果你将设备从一个网络移动到另一个网络,网络 ID 必须更改为新网络的网络 ID。因此,IP 地址也必须更改。这是一个不幸的缺点,在处理移动设备时最常见;请参阅第三十章。

IP 寻址类别和 IP 寻址辅助

我们刚刚探讨了 IP 地址中的 32 位是如何在本质上分为网络 ID 和主机 ID 的。网络 ID 用于路由目的,而主机 ID 唯一标识网络上的每个网络接口。为了设备能够知道如何在网络上使用 IP 地址,它们必须能够判断哪些位用于每个 ID。然而,这条分界线并不是预先定义的。它取决于网络中使用的寻址类型。

了解这些 ID 如何确定,使我们进入了对 IP 寻址方案三个主要类别的更广泛讨论:分类、子网化和无类。每个都使用稍微不同的系统来指示主机 ID 在 IP 地址中的位置。

传统的(分类)寻址

原始的 IP 寻址方案被设置为仅在少数几个位置之一发生分界:在八位字节边界上。根据用于网络 ID 和主机 ID 的八位字节数,区分了三个主要类别的地址——A、B 和 C。例如,C 类地址将 24 位用于网络 ID,8 位用于主机 ID。这种寻址方式现在通常被称为虚构的词 classful,以区分较新的无类方案。

这种最基本的寻址类型使用最简单的方法来划分网络 ID 和主机 ID:将类别及其分界点编码到每个地址的前几位中。路由器可以通过这些位判断哪些八位字节属于哪个标识符。

子网化分类寻址

在子网寻址系统中,通过从类别 A、B 或 C 的主机 ID 中取出一些位,并将它们用于一个子网标识符(子网 ID),将 IP 地址的网络和主机部分从两层系统扩展为三层系统。网络 ID 保持不变。子网 ID 用于在构成整个网络的各个子网络之间进行路由,从而为管理员提供额外的灵活性。例如,考虑一个通常使用前 24 位作为网络 ID 和剩余 8 位作为主机 ID 的类别 C 地址。主机 ID 可以被分成,比如说,3 位用于子网 ID 和 5 位用于主机 ID。

该系统基于原始的类别方案,因此网络 ID 和完整主机 ID 之间的分割线仍然基于地址的前几位,就像之前一样。子网 ID 和“子主机”ID 之间的分割线由一个称为子网掩码的 32 位数字表示。在先前的例子中,子网掩码将是 27 个 1 位后面跟着 5 个 0 位——0 位表示地址的哪一部分是主机。以点分十进制表示,这将表示为 255.255.255.224。

无类别寻址

在无类别系统中,原始 IP 寻址方案中的类别被摒弃。网络 ID 和主机 ID 的分割可以发生在任意点,而不仅仅是类别方案中的八位边界。

通过在地址后放置用于网络 ID 的位数,即所谓的前缀长度,来指示分割点。(回想一下,网络 ID 位有时也被称为网络前缀,因此网络 ID 的大小就是前缀长度。)例如,如果 227.82.157.177 是使用前 27 位作为网络 ID 的网络的一部分,那么该网络将被指定为 227.82.157.160/27。/27 在概念上等同于 255.255.255.224 子网掩码,因为它有 27 个 1 位后面跟着 5 个 0 位。

小贴士

关键概念 决定一个 IP 地址如何被解释的一个基本因素是它所使用的寻址方案。这三种方法按照年龄、复杂性和灵活性的递增顺序排列,分别是类别寻址、子网类别寻址和无类别寻址。

这篇关于类别寻址、子网寻址和无类别寻址概念的介绍旨在展示它们如何影响 IP 地址的解释方式。我在这里大大简化了重要概念。所有三种方法都在各自的章节中进行了详细解释。

子网掩码和默认网关

在原始的类别划分方案中,网络 ID 和主机 ID 之间的划分是隐含的。然而,如果使用子网划分或无类别寻址,则需要子网掩码(或斜杠号,两者等价)来完全指定地址。这些数字被视为 IP 地址的补充,通常与地址一起提及,因为没有它们,就无法知道网络 ID 在哪里结束,主机 ID 在哪里开始。

与设备 IP 地址一起经常指定的另一个数字是默认网关标识符。简单来说,这是为特定设备提供默认路由功能的路由器的 IP 地址。当一个 IP 网络上的设备想要向其本地 IP 网络上看不到的设备发送数据报时,它会将其发送到默认网关,该网关负责路由功能。没有这个,每个 IP 设备都需要了解路由功能和路由,这将是不高效的。参见第二十三章,其中讨论了 IP 路由概念,以及从第三十七章到 41 章,这些章节涵盖了 TCP/IP 路由协议,以获取更多信息。

IP 地址数量和多宿主

在 IP 互联网上的每个网络接口都有一个独立的 IP 地址。在一个经典网络中,每台常规计算机,通常称为主机,只连接到网络的一个地方,因此它只有一个 IP 地址。这是我们使用 IP 网络时最熟悉的情况(这也是为什么大多数人使用术语主机而不是网络接口的原因)。

如果一个设备与互联网有多个接口,它将拥有多个 IP 地址。最明显的例子是路由器,它们连接不同的网络,因此必须为每个接口分配一个 IP 地址。然而,主机也可能拥有多个 IP 地址。这样的设备有时被称为多宿主

主机可以多宿主有两种方式:

同一网络上的两个或更多接口 服务器或高性能工作站等设备可能出于性能和可靠性原因配备了连接到同一网络的两个物理接口。它们将在同一网络上有两个具有相同网络 ID 的 IP 地址。

连接到两个或更多不同网络的接口 设备可能具有连接到不同网络的多个接口。IP 地址通常包含不同的网络 ID。

图 16-5 展示了这两种类型的多宿主设备的示例。当然,这些可以组合,一个主机可以有一个连接到一个网络,另一个连接到另一个网络。还有一些其他特殊情况,例如一个具有单个网络连接的主机有多个 IP 地址别名。

注意

当使用子网划分时,可以在同一子网或不同子网的多宿主之间做出相同的区分

现在,让我们考虑第二种情况。如果一个主机连接到两个或更多不同的网络,它能否在这两个网络之间传递 IP 数据报?是的,如果它在上面运行了正确的软件。那么这不会使主机变成一种路由器吗?实际上,这正是这种情况。一个具有连接到两个网络的接口的多宿主主机可以使用软件作为路由器。这有时被称为软件路由

与硬件路由器相比,使用主机作为路由器具有某些优点和缺点。一个多宿主的服务器可以执行路由功能,同时,嗯,充当服务器。专门设计的硬件路由器是为了路由任务而设计的,通常会比在主机上运行的软件程序更有效率。

小贴士

关键概念 拥有多个 IP 网络接口的主机被称为多宿主。一个多宿主设备可以连接到同一网络、不同网络或两者。一个连接到两个网络的主机可以被配置为作为路由器。

多宿主曾经被认为是一种相当晦涩的应用,但近年来变得更加普遍。这在软件路由用途的多宿主不同网络方面也是正确的。实际上,你可能在家里做着这样的事情而自己并没有意识到。

假设你有两台联网的 PC 和一个电话线路来连接到互联网。一台计算机拨号连接到你的互联网服务提供商(ISP),并运行如微软的互联网连接共享(ICS)软件,以便另一台计算机可以访问互联网。每天有成千上万的人这样做——他们有一个多宿主系统(连接到互联网和另一台 PC),其中 ICS 充当软件路由器的角色(尽管 ICS 和真正的路由器之间当然有一些技术差异)。

IP 地址管理、分配方法和权限

如果你告诉某人你住在 34 号橡树街,当他驶入你的道路时,发现四栋房子上都有 34 号,会发生什么?他可能最终会找到你的地方,但不会太高兴。你和你家的信使也不会高兴。而且你们都比计算机聪明得多。就像街道地址一样,IP 地址也必须是唯一的,才能发挥作用。

IP 互联网上的多宿主设备 该互联网由两个局域网 A(上方)和 B(下方)组成。局域网 A 有一个多宿主工作站,用两个 IP 网络接口“圆圈”表示。两个局域网通过一个配置为在它们之间路由流量的多宿主共享服务器连接在一起。请注意,该服务器还处理所有在局域网 B 和互联网之间传递的流量(因为互联网连接仅在局域网 A 中)

图 16-5. IP 互联网上的多宿主设备 该互联网由两个局域网 A(上方)和 B(下方)组成。局域网 A 有一个多宿主工作站,用两个 IP 网络接口“圆圈”表示。两个局域网通过一个配置为在它们之间路由流量的多宿主共享服务器连接在一起。请注意,该服务器还处理所有在局域网 B 和互联网之间传递的流量(因为互联网连接仅在局域网 A 中)。

由于 IP 数据报只发送在 IP 互联网的范围内,它们必须在每个互联网内是唯一的。如果你是一家拥有自己的私有互联网的公司,这并不是一个大问题。负责维护互联网的人会保留一个列表,记录哪些数字在哪里被使用,并确保没有两个设备被分配相同的地址。然而,在公共网络中,有多个不同的组织会发生什么?在这里,确保 IP 地址空间在组织间得到管理,以确保它们使用不同的地址是至关重要的。让每个组织与其他组织协调其活动是不切实际的。因此,需要某种形式的集中式管理机构

在你需要有人确保地址分配没有冲突的同时,你不想让网络的用户每次需要更改他们的网络时都要去这个中央机构。根据他们想要连接到网络的设备数量,由该机构分配块或块状数字更有意义。组织可以根据自己的需要管理这些块,而权威机构的任务也因为处理的是块而不是数十亿个单独的地址和机器而变得更容易。

互联网作为大的 IP 互联网,需要为全球数百万组织执行这项协调任务。最初,管理互联网上 IP 地址分配的工作由一个组织执行:互联网分配号码权威机构 (IANA)。IANA 负责分配 IP 地址,以及管理其他重要的集中式协调功能,例如管理用于 TCP/IP 协议的通用参数。在 1990 年代末,一个新的组织——互联网名称和数字地址分配公司 (ICANN) 被创建。ICANN 现在负责监督 IANA 的 IP 地址分配任务,以及管理其他任务,如域名系统 (DNS) 名称注册(参见第五十四章)。

IP 地址最初是直接分配给组织的。原始的 IP 地址方案基于类别,因此 IANA 会分配 A 类、B 类和 C 类块中的地址。今天,地址是无类的,使用 CIDR 的分层地址方案。IANA 不直接分配地址,而是将它们委派给区域互联网注册机构 (RIRs)。这些是 APNIC、ARIN、LACNIC 和 RIPE NCC。每个 RIR 可以反过来将地址块委派给低级注册机构,如国家互联网注册机构 (NIRs) 和本地互联网注册机构 (LIRs)。

最终,地址块由 ISP 获取,用于分配给最终用户组织。一些 ISP 的客户是最终用户组织,但其他的是(较小的)ISP 本身。他们可以反过来使用或委派他们块中的地址。这可以以分层的方式继续进行几个阶段。这种安排有助于确保 IP 地址以最有效的方式分配和使用。有关如何工作的更多信息,请参阅第二十章/超网"),其中讨论了 CIDR。

IANA、ICANN 和 RIRs 负责的不仅仅是 IP 地址分配,尽管我这里主要关注 IP 地址,这是显而易见的原因。有关 IANA、ICANN、APNIC、ARIN、LACNIC 和 RIPE NCC 的更一般信息,可以尝试一罐字母汤——或者查看第三章,其中提供了互联网注册机构的概述。

第十七章。类地址(传统)地址

无标题图片

原始的 IP 地址地址方法将 IP 地址空间划分为五个不同大小的块,称为 类别,并根据组织的大小和需求从这些类别中分配地址块。在这个分类地址方案中,每个类别都保留用于特定目的,主要地址类别根据用于网络标识符(网络 ID)的八位组数量以及用于主机标识符(主机 ID)的八位组数量来区分。

在本章中,我描述了分类 IP 地址。我首先概述了该概念和不同类别的通用描述。我讨论了与不同类别相关的网络标识符和主机标识符以及地址范围。我讨论了常用类别的容量,即每个类别包含多少网络以及每个网络可以包含多少主机。我讨论了分配给某些 IP 地址模式的特殊含义以及为私有 IP 地址、环回功能和多播保留的特殊范围。我最后讨论了这种地址类型的问题,这些问题导致了它被弃用,转而采用子网划分,最终实现了 IP 地址空间的非分类分配。

注意

分类地址方案已被第二十章中描述的无类别地址系统所取代(ch20.html "第二十章. IP 无类别地址——无类别域间路由(CIDR)/超网”)。然而,我认为了解这个原始系统是如何运作的仍然很重要,因为它构成了更复杂地址机制的基础。

IP 地址分类概述及地址类别

互联网协议(IP)的开发者认识到,组织的大小各不相同,因此需要在互联网上使用不同数量的 IP 地址。他们设计了一个系统来将 IP 地址空间划分为 类别,每个类别包含总地址的一部分,并专门用于特定用途。一些类别将用于互联网上的大型网络,而其他类别则保留给较小的组织或特殊用途。

这个原始系统没有名称;它只是“IP 地址系统”。今天,它被称为 分类地址方案,以区分较新的无类别方案。

IP 地址类别

在分类系统中,有五个类别,分别用字母 A 到 E 表示。表 17-1 提供了有关类别、其旨在用途和其特性的某些一般信息。

表 17-1. IP 地址类别及其特性与用途

IP 地址类别 总 IP 地址空间的比例 网络标识符位数 主机标识符位数 旨在用途
类别 A 1/2 8 24 用于连接到互联网的非常大型组织,拥有数十万或数百万个主机
类别 B 1/4 16 16 用于连接到互联网的中等到大型组织,拥有数百到数千个主机
类别 C 1/8 24 8 用于连接到互联网的小型组织,不超过约 250 个主机
类别 D 1/16 n/a n/a IP 多播
类别 E 1/16 n/a n/a 保留用于实验用途

通过查看这张表格(以及图 17-1),您可以看到类别 A、B 和 C 占据了大部分的总地址空间(七分之八)。这些类别用于 单播 IP 地址和发送到单个网络接口的消息。(这些块还包括这些网络的关联广播地址。)这就是我通常认为的正常 IP 地址。

IPv4 地址空间的类别划分

图 17-1. IPv4 地址空间的类别划分

您可以将类别 A、B 和 C 视为传统 IP 地址中的大熊爸爸、大熊妈妈和小熊宝宝。它们允许互联网为少量非常大的网络、中等数量的中等规模组织和大量的小公司提供地址。这大致反映了现实世界中组织规模的分布,尽管每个地址类别允许的最大主机数量之间的巨大差距导致了一定的不灵活性,我将在本章后面讨论这一点。

如您所见,类别之间的区别在于它们在地址的网络 ID 和主机 ID 部分之间划定的界限。然而,在每种情况下,划分都是在八位字节边界上进行的。在类别地址中,划分不会在八位字节内部发生。

类别 D 和 E 是特殊的——以至于许多人甚至没有意识到它们的存在。类别 D 用于 IP 多播,而类别 E 保留用于实验用途(由互联网的设计师)。我在本章后面讨论 IP 多播地址。

小贴士

关键概念 类别 IP 地址方案将 IP 地址空间划分为五个不同大小的类别,从 A 到 E。类别 A、B 和 C 是最重要的,指定用于传统单播地址,占据了地址空间的七分之八。类别 D 保留用于 IP 多播,类别 E 保留用于实验用途。

类别地址划分的原理

虽然今天经常讨论类别寻址方案的缺点(您将在本章后面看到),但了解在开发此系统时互联网的大小是很重要的。当时互联网很小,与创造者多年后预想的机器数量相比,32 位地址空间似乎巨大无比。公平地说,也应该记住 25 年前开发的类别寻址系统的以下优点:

简单明了 可供选择的类别只有几个,理解地址如何划分非常简单。类别的区别清晰且明显。A、B 和 C 类中网络 ID 和主机 ID 之间的划分在八位字节边界上,这使得确定任何地址的网络 ID 变得容易。

合理的灵活性 三种粒度级别与大型、中型和小型组织的规模相当匹配。原始系统提供了足够的容量来处理当时互联网预期的增长速度。

路由便捷性 如您很快就会看到的,地址类别被编码到地址中,以便路由器知道任何地址的哪一部分是网络 ID,哪一部分是主机 ID。不需要附加信息,如子网掩码。

保留地址 某些地址被保留用于特殊目的。这不仅包括 D 类和 E 类,还包括用于私有寻址的特殊保留地址范围。

当然,后来发现原始 IP 寻址方案中的一些决策是令人遗憾的——但这正是事后诸葛亮的益处。我相信我们都会希望收回为 E 类保留的约 2.68 亿个地址。虽然现在看来为实验用途保留地址空间的三分之一似乎有些浪费,但请记住,即使在 10 年前,也从未预料到互联网的当前规模,更不用说 25 年前了。此外,为任何稀缺资源预留一部分以备将来使用是良好的实践。

IP 类别寻址网络和主机标识及地址范围

类别 IP 寻址方案将整个 IP 地址空间划分为 A 到 E 五个类别。相对简单的类别寻址方案的一个好处是,关于类别的信息直接编码到 IP 地址中。这意味着你可以事先确定哪些地址范围属于每个类别。这也意味着相反的情况是可能的:你只需检查地址的一小部分就能确定与任何地址关联的类别。这种后者的好处是类别寻址系统最初创建的主要动机之一。

类别寻址类别确定算法

当 TCP/IP 最初创建时,计算机技术还处于起步阶段。路由器需要能够快速做出关于如何移动 IP 数据报的决定。IP 地址空间被划分为类别,使得通过查看任何 IP 地址的前几个比特,路由器可以轻松地判断如何选择网络 ID 和主机 ID,从而确定对数据报的处理方式。

路由器需要查看的位数可能从 1 位到 4 位不等,这取决于它开始查找时发现的内容。用于确定类别的算法对应于用于划分地址空间的系统,如图 17-2 所示。

类别确定算法用于类别 IP 地址 类别 IP 地址的简单性可以从用于确定地址类别的非常简单的算法中看出。

图 17-2. 类别确定算法用于类别 IP 地址 类别 IP 地址的简单性可以从用于确定地址类别的非常简单的算法中看出。

这里是算法中的四个非常基本的步骤:

  1. 如果第一个比特是 0,则这是一个 A 类地址,任务完成。(地址空间的一半以 0 作为第一个比特,这就是为什么 A 类占据一半地址空间的原因。)如果它是 1,继续到步骤 2。

  2. 如果第二位是 0,则这是一个 B 类地址,任务完成。(剩余的非 A 类地址的一半,或者总量的四分之一。)如果它是 1,继续到步骤 3。

  3. 如果第三位是 0,则这是一个 C 类地址,任务完成。(剩余部分再减半,或者总量的八分之一。)如果它是 1,继续到步骤 4。

  4. 如果第四位是 0,则这是一个 D 类地址。(剩余部分的一半,或者地址空间的十六分之一。)如果它是 1,则是一个 E 类地址。(另一半,十六分之一。)

大概就是这样。

从第一个八位字节位模式确定地址类别

当然,作为人类,我们通常使用点分十进制地址而不是二进制地址来工作,但很容易看出与类别相对应的范围。例如,考虑 B 类。第一个八位字节的头两位是 10。剩余的位可以是任意组合的 1 和 0。这通常表示为 10xx xxxx(为了可读性,显示为两组四个)。因此,第一个八位字节的二进制范围可以从1000 0000 到1011 1111(十进制中的 128 到 191)。因此,在类别方案中,任何第一个八位字节在 128 到 191(含)之间的 IP 地址都是 B 类地址。

表 17-2 显示了每个五个类别的位模式以及如何计算第一个八位字节的范围。第一列显示了 IP 地址第一个八位字节的格式;x可以是零或一。接下来是每个类别的最低和最高值列(固定的几个位以粗体字打印,以便您可以看到它们在变化时保持不变),然后是第一个八位字节的对应范围,以十进制表示。

表 17-2. IP 地址类别位模式、第一个八位字节范围和地址范围

IP 地址类别 IP 地址的第一个八位字节 第一个八位字节的最低值(二进制) 第一个八位字节的最大值(二进制) 第一个八位字节的值范围(十进制) 网络 ID/主机 ID 的八位字节 理论上的 IP 地址范围
A 类 0xxx xxxx 0000 0001 0111 1110 1 to 126 1 / 3 1.0.0.0 to 126.255.255.255
B 类 10xx xxxx 1000 0000 1011 1111 128 to 191 2 / 2 128.0.0.0 to 191.255.255.255
C 类 110x xxxx 1100 0000 1101 1111 192 to 223 3 / 1 192.0.0.0 to 223.255.255.255
D 类 1110 xxxx 1110 0000 1110 1111 224 to 239 224.0.0.0 to 239.255.255.255
E 类 1111 xxxx 1111 0000 1111 1111 240 to 255 240.0.0.0 to 255.255.255.255

此表还显示了每个类别的理论最低和最高 IP 地址范围。这意味着它们是取每个类别中可能的完整二进制数范围的结果。实际上,某些值可能无法用于常规使用。例如,尽管 192.0.0.0 到 192.0.0.255 的范围在技术上属于 C 类,但它被保留,并且实际上并未被互联网上的主机使用。

此外,某些 IP 地址不能使用,因为它们具有特殊含义。例如,255.255.255.255 是一个保留的广播地址。类似地,请注意,A 类的范围是从 1 到 126,而不是您可能预期的 0 到 127。这是因为 A 类网络中的 0 和 127 是保留的;127 是包含 IP 环回地址的网络。这些特殊和保留的地址将在本章后面讨论。

回想一下,类别 A、B 和 C 在网络 ID 和主机 ID 之间的分割线是不同的:类别 A 为网络 1 位,主机 3 位;类别 B 为每个 2 位;类别 C 为网络 3 位,主机 1 位。基于这种分割,我在 表 17-2 中突出了每个类别 A、B 和 C 的 IP 地址范围中的网络 ID 部分。纯文本对应于每个允许的网络 ID 的主机 ID 范围。图 17-3 以图形方式展示了每个类别中位的使用情况。

IP 地址类别位分配和网络/主机 ID 大小 此图示展示了 IP 地址的 32 位是如何分配给五个 IP 地址类别的。类别 A、B 和 C 是用于常规单播地址的正常类别;每个类别在网络 ID 和主机 ID 之间都有不同的分割点。类别 D 和 E 是特殊的,并且不以这种方式分割。

图 17-3. IP 地址类别位分配和网络/主机 ID 大小 此图示展示了 IP 地址的 32 位是如何分配给五个 IP 地址类别的。类别 A、B 和 C 是用于常规单播地址的正常类别;每个类别在网络 ID 和主机 ID 之间都有不同的分割点。类别 D 和 E 是特殊的,并且不以这种方式分割。

小贴士

关键概念 在类别 IP 地址方案中,IP 地址的类别是通过查看地址的第一位、两位、三位或四位来确定的。这既可以通过处理这些地址的人类完成,也可以通过做出路由决策的路由器完成。使用这些位模式意味着不同类别的 IP 地址落入特定的地址范围,通过查看其点分十进制地址的第一字节即可确定地址的类别。

例如,考虑类别 C。最低的 IP 地址是 192.0.0.0,最高的 IP 地址是 223.255.255.255。前三个八位字节是网络 ID,其范围从 192.0.0223.255.255。对于该范围内的每个网络 ID,主机 ID 的范围从 0 到 255。

注意

通常人们会看到资源将类别地址的网络 ID 仅指包括重要的位;也就是说,只有那些不属于该类别所有网络的位。例如,你可能会看到一个类别 B 网络 ID 在图中显示为 14 位,其中起始所有此类网络的 10 位被单独显示,好像它不是网络 ID 的一部分。记住,网络 ID 也包括这些位;对于类别 A 是 8 个完整的位,对于类别 B 是 16 位,对于类别 C 是 24 位。在类别 D 地址的情况下,所有的 32 位都是地址的一部分,但只有低位的 28 位是组播组地址的一部分;有关更多内容,请参阅本章后面的多播地址主题

IP 地址类别 A、B 和 C 的网络和主机容量

到目前为止,我已经介绍了 IP 地址类别的概念,并展示了类别如何与 IP 地址的范围相关联。在五个类别中,D 和 E 类别是专门用于特殊目的的,所以我现在将暂时不讨论这些。类别 A、B 和 C 是实际分配用于在 IP 互联网上执行正常(单播)地址目的的类别,因此它们是我们持续关注的重点。

正如你所见,类别之间的区别在于用于网络 ID 的位数(和八位字节)与用于主机 ID 的位数。每个类别可能的不同网络数量是分配给网络 ID 的位数的一个函数,同样,每个网络可能的主机数量取决于为主机 ID 提供的位数。你还必须考虑到,IP 地址中的 1、2 或 3 位被用来指示类别本身,因此实际上这些位被排除在用于确定网络数量的计算之外(尽管它仍然是网络 ID 的一部分)。

根据这些信息,你可以计算出每个类别的网络数量,以及每个类别的每个网络的主机 ID 数量。表 17-3 显示了计算结果。

表 17-3. IP 地址类别网络和主机容量

IP 地址类别 网络 ID/主机 ID 的总位数 IP 地址的第一个八位字节 用于识别类别的网络 ID 位数 可用的网络 ID 位数 可能的网络 ID 数量 每个网络 ID 的主机 ID 数量
类别 A 8/24 0xxx xxxx 1 8-1 = 7 2⁷-2 = 126 2²⁴-2 = 16,277,214
类别 B 16/16 10xx xxxx 2 16-2 = 14 2¹⁴ = 16,384 2¹⁶-2 = 65,534
类别 C 24/8 110x xxxx 3 24-3 = 21 2²¹ = 2,097,152 2⁸-2 = 254

让我们来看一下这个表格中的一行,以便您了解它是如何工作的,以 B 类为例。基本的划分是 16 位用于网络 ID,16 位用于主机 ID。然而,所有 B 类地址的前两位必须是 10,这样就只剩下 14 位来唯一标识网络 ID。这给我们提供了总共 2¹⁴ 或 16,384 个 B 类网络 ID。对于这些中的每一个,您都有 2¹⁶ 个主机 ID,减去两个,总共为 65,534。

为什么减去两个?对于每个网络 ID,有两个主机 ID 不能使用:全零的主机 ID 和全一的主机 ID。这些地址具有特殊含义,如下一节所述。同时请注意,从 A 类网络 ID 的数量中减去两个。这是因为两个 A 类网络 ID(0 和 127)被保留。

在这里展示的三个类中,都预留了几个其他的地址范围。它们将在本章后面的“IP 保留、私有和环回地址”部分列出。

小贴士

关键概念 在按类 IP 编址方案中,一个 A 类网络包含大约 1600 万个网络接口的地址;一个 B 类网络包含大约 65,000 个;一个 C 类网络包含 254 个。

如您所见,在这些类中,每个网络可用的主机数量差异很大。如果一个组织需要 1,000 个 IP 地址,它必须使用四个 C 类或者一个 B 类(这样做会浪费 B 类网络中超过 90%的可能地址)。请记住,全球只有大约 16,000 个 B 类网络 ID 可用,您开始理解按类编址的一个大问题。

具有特殊含义的 IP 地址

一些 IP 地址并不直接指向特定的硬件设备;相反,它们被用来间接地指向一个或多个设备。为了与语言进行类比,大多数 IP 地址指的是专有名词,如“John”或“角落里的那张红桌子。”然而,有些被用来更类似于您使用代词的方式,如“这个”或“那边的那组。”我把这些具有特殊含义的 IP 地址称为特殊 IP 地址。

这些特殊地址是通过在 IP 地址中将正常的网络 ID 或主机 ID(或两者)替换为两种特殊模式之一来构建的:

全零 当网络 ID 或主机 ID 位被一组全零位替换时,特殊含义等同于代词这个,指代被替换的内容。它也可以解释为默认当前。例如,如果您用全零替换网络 ID,但保留主机 ID 不变,那么得到的地址意味着“具有给定主机 ID 的设备,在这个网络上,”或“具有指定主机 ID 的设备,在默认网络当前网络上。”

全一 当网络 ID 或主机 ID 位被全部为一的集合替换时,这具有“所有”的特殊含义,意味着 IP 地址指的是网络上的所有主机。这通常用作广播地址,向所有人发送消息。

小贴士

关键概念 当 IP 地址的网络 ID 或主机 ID 被全部为一的图案替换时,结果是具有特殊含义的地址。此类地址的示例包括“所有主机”广播地址和指向特定主机或整个网络的地址。

存在许多特殊地址。其中一小部分适用于整个 TCP/IP 网络,而其他则存在于每个网络或主机 ID。由于两个特殊模式可以应用于网络 ID、主机 ID 或两者,因此有六种可能的组合,每种组合都有其自己的含义。其中五种被使用。

表 17-4 描述了这些特殊含义,并包括 A、B、C 类中的示例。注意,每个常见类别的 IP 地址如何修改以具有特殊含义形式。 (第一行显示了它们的正常形式,供参考。)

表 17-4. 特殊含义的 IP 地址模式

网络 ID 主机 ID A 类示例 B 类示例 C 类示例 特殊含义和描述
网络 ID 主机 ID 77.91.215.5 154.3.99.6 227.82.157.160 正常含义: 指的是特定的设备。
网络 ID 全零 77.0.0.0 154.3.0.0 227.82.157.0 指定的网络: 这种表示法,地址末尾有一个 0,指的是整个网络。
全零 主机 ID 0.91.215.5 0.0.99.6 0.0.0.160 指定网络上的主机: 当网络 ID 未知或不需要明确指出时,此地址指向当前或默认网络上的主机。
全零 全零 0.0.0.0 : 当设备不知道自己的 IP 地址时,用于指代自身。(或者“此主机”、“当前/默认主机”)。最常见的用法是当设备尝试使用如 DHCP 之类的主机配置协议确定其地址时。也可以用来表示多宿主机的任何地址都可以使用。
网络 ID 全一 77.255.255.255 154.3.255.255 227.82.157.255 指定网络上的所有主机: 用于向本地网络上的所有主机广播。
全一 全一 255.255.255.255 网络上的所有主机: 指定向直接连接的网络上的所有主机进行全局广播。请注意,没有地址可以暗示向全球互联网上的所有主机发送,因为这会非常低效且成本高昂。

备注

*表 17-4 中缺失的组合是网络 ID 全为 1 而主机 ID 正常的情况。从语义上讲,这将指代“所有网络上的特定 ID 的主机”,这在实践中并没有什么实际意义,所以它没有被使用。注意,从理论上讲,一个特殊地址,其中网络 ID 全为零而主机 ID 全为 1,将具有与全一有限广播地址相同的含义。然而,后者被使用,因为它更通用,不需要知道网络 ID 和主机 ID 之间的划分在哪里。

由于全零和全一的模式被保留用于这些特殊含义,因此它们不能用于常规 IP 地址。这就是为什么,当你查看每个类别的网络中每台主机的数量时,你必须从理论上的最大值中减去两个:一个用于全零的情况,一个用于全一的情况。

同样,网络 ID 也不能全为零。然而,这不需要特定的排除,因为第一个八位字节中包含 0 的整个地址块(0.x.x.x)是保留的 IP 地址集合之一。这些在下一节中描述的保留地址,进一步限制了某些地址在 IP 地址空间中的常规使用。

IP 保留地址、私有地址和环回地址

除了刚才讨论的具有特殊含义的不可用数字外,还有几组 IP 地址有特殊用途,因此它们不可用于常规地址分配。这些通常分为三类:保留地址、私有地址和环回地址。

保留地址

几个地址块被指定为保留,但没有给出它们被保留的具体用途。也许它们是为未来的实验或为在互联网内部使用而预留的。(一般来说,为未预见的需要预留任何有限资源的一部分是个好主意。)

这些块在每个主要类别(A、B 和 C)的开始和结束处都出现。 (由于 D 类和 E 类不用于常规寻址,所以它们也是保留的。)

私有、未注册、不可路由地址

你会记得,在第十六章的 IP 地址概述中,我对比了私有和公共 IP 地址。IP 网络上的每个 IP 地址都必须是唯一的。在公共 IP 网络的情况下,地址由中央机构分配,以确保没有重叠。相比之下,在私有网络中,你可以使用你想要的任何地址。

那为什么不随便选择任何 A 类、B 类或 C 类地址块来为你的私有网络使用呢?你可以这样做,有些人确实这样做了。例如,如果你没有连接到互联网,你可以使用互联网上预留给麻省理工学院(MIT)的 A 类网络 18.x.x.x。由于你没有连接到 MIT,你可能认为这不会有什么影响。

然而,随着互联网的发展,那些独立的私有网络最终需要连接到公共互联网,然后它们就产生了冲突。如果它们使用 18.x.x.x 地址,它们就必须重新分配所有设备的地址,以避免引起一大群计算机极客的愤怒。(实际上,有些公司不小心将属于其他公司的 IP 地址空间中的机器连接到互联网上,在这个过程中造成了一些混乱。)

RFC 1918(取代 RFC 1597)提供了解决方案。它定义了一组专为私有地址而设的不可路由的特殊地址块。这些地址在公共互联网上根本不存在。因此,它们不像其他公共地址那样注册;有时被称为未注册的。任何人都可以使用它们,但它们不能连接到互联网,因为路由器没有编程来转发这些地址范围内的流量到本地组织之外。RFC 1918 的发布是为了鼓励使用这些私有块,以减少公共互联网上不需要公开访问的设备数量。这是对节约公共地址空间需求的回应。

注意

为了将使用私有地址的网络连接到公共互联网,需要使用额外的硬件和软件。可以使用网关机器作为公共网络和私有网络之间的接口。网络地址转换(NAT;见第二十八章 Chapter 28. IP 网络地址转换(NAT)协议)等技术通常与私有 IP 地址一起使用,以允许这些主机在公共 IP 网络上进行通信

小贴士

关键概念 私有地址块是为了允许使用不会与公共 IP 地址冲突的地址来创建私有 IP 互联网而创建的。它们通常用于未连接到全球互联网的互联网中;使用它们的设备也可以通过使用 NAT 来访问全球互联网。

回环地址

通常,当一个 TCP/IP 应用程序想要发送信息时,该信息会沿着协议层向下传输到 IP 层,在那里它被封装在一个 IP 数据报中。然后该数据报会传递到设备的物理网络的数据链路层,以便在前往 IP 目标的过程中传输到下一个跳点。

然而,有一组特殊的地址范围,从 127.0.0.0 到 127.255.255.255,被预留用于环回功能。主机发送到 127.x.x.x 环回地址的 IP 数据报不会传递到数据链路层进行传输;相反,它们在 IP 层回环到源设备。本质上,这绕过了正常的协议栈;数据由设备的第 3 层 IP 实现发送,然后立即被它接收。

这个环回范围用于在主机上测试 TCP/IP 协议的实现。由于底层被短路,向环回地址发送允许你隔离并测试高层(IP 及以上)而不会受到底层干扰。127.0.0.1 是最常用的测试地址。

小贴士

关键概念 IP 地址空间的部分被预留用于预留、私有和环回地址。

预留、私有和环回地址块

表 17-5 显示了从正常的 IP 地址空间中预留的所有特殊块,按数字顺序排列,并简要说明了每个块的使用方法。它列出了表示每个块的类地址和无类地址表示,因为现在互联网使用无类地址,并且因为一些私有块不对应于单个 A、B 或 C 类网络。

特别注意从 192.168.0.0 到 192.168.255.255 的私有地址块。这是一个 B 类网络的大小,但在类地址方案中不是 B 类,因为 192 的第一个八位字节将其放在地址空间的 C 类部分。它实际上是 256 个连续的 C 类网络。

你也可能注意到特殊的 B 类(/16)块 169.254.x.x。这是为自动私有 IP 地址分配(APIPA)预留的,在第六十四章中讨论。配置为使用此功能的系统将自动从该块分配系统地址,以便它们即使在找不到服务器进行适当的 IP 地址分配(使用动态主机控制协议 DHCP)的情况下也能进行通信。

表 17-5. 预留、私有和环回 IP 地址

范围起始地址 范围结束地址 类地址等效 无类地址等效 描述
0.0.0.0 0.255.255.255 A 类网络 0.x.x.x 0/8 预留
10.0.0.0 10.255.255.255 A 类网络 10.x.x.x 10/8 A 类私有地址块
127.0.0.0 127.255.255.255 A 类网络 127.x.x.x 127/8 环回地址块
128.0.0.0 128.0.255.255 B 类网络 128.0.x.x 128.0/16 预留
169.254.0.0 169.254.255.255 Class B 网络 169.254.x.x 169.254/16 保留,用于自动私有地址分配(有关详细信息,请参阅第六十四章)
172.16.0.0 172.31.255.255 从 172.16.x.x 到 172.31.x.x 的 16 个连续的 Class B 网络 172.16/12 Class B 私有地址块
191.255.0.0 191.255.255.255 Class B 网络 191.255.x.x 191.255/16 保留
192.0.0.0 192.0.0.255 Class C 网络 192.0.0.x 192.0.0/24 保留
192.168.0.0 192.168.255.255 从 192.168.0.x 到 192.168.255.x 的 256 个连续的 Class C 网络 192.168/16 Class C 私有地址块
223.255.255.0 223.255.255.255 Class C 网络 223.255.255.x 223.255.255/24 保留

IP 多播寻址

IP 互联网上的绝大多数流量是单播,即一个源设备向一个目的设备发送。IP 还支持多播,即源设备向一组设备发送。尽管在当今的互联网上多播使用不多,主要是因为缺乏广泛的硬件支持,但在某些情况下它很有用,尤其是在作为广播的更有效替代方案时。

类别 IP 寻址方案将地址空间的六分之一留作多播地址,作为 D 类。多播地址通过前四位中的模式 1110 来识别,这对应于第一个八位字节为 224 到 239。因此,多播地址的全范围是从 224.0.0.0 到 239.255.255.255。

由于多播地址代表一组 IP 设备(有时称为主机组),它们只能作为数据报的目的地使用,而不能作为源地址。

多播地址类型和范围

IP 地址中的其他 28 位定义了多播组地址。因此,D 类多播地址空间的大小是 2²⁸,即 268,435,456 个多播组。这 28 位没有子结构定义其用途,也没有像 A、B 和 C 类中那样的网络 ID 和主机 ID 的具体概念。然而,地址空间的一部分被留作特定用途。表 17-6 和图 17-4 显示了 D 类地址空间的一般分配。

表 17-6。IP 多播地址范围和用途

范围起始地址 范围结束地址 描述
224.0.0.0 224.0.0.255 保留用于特殊知名多播地址
224.0.1.0 238.255.255.255 全局范围(互联网范围)多播地址。
239.0.0.0 239.255.255.255 管理范围(本地)多播地址

注意

与其他 IP 地址类一样,地址的整个 32 位始终被使用。只有最低的 28 位是有趣的,因为最高 4 位永远不会改变

IP 多播地址范围和用途 所有多播地址以 1110 开头。知名组的多播组地址的前 20 位为零,有 8 位可用于定义 255 个特殊的多播地址。以 1110 1111 开头的多播地址是本地范围的;所有其他地址都是全局范围的(这包括以 1110 0000 开头但不是 255 个知名地址的地址)

图 17-4。IP 多播地址范围和用途 所有多播地址以 1110 开头。知名组的多播组地址的前 20 位为零,有 8 位可用于定义 255 个特殊的多播地址。以 1110 1111 开头的多播地址是本地范围的;所有其他地址都是全局范围的(这包括以 1110 0000 开头但不是 255 个知名地址的地址)。

小贴士

相关信息 多播地址范围的概念在 IPv6 中得到了更完整的定义,我在第二十五章中对其进行了更详细的讨论

地址空间的大部分在中段多播范围内。这些是正常的多播地址,就像 A 类、B 类和 C 类单播地址一样,它们可以被分配给各种组。

最后的地址范围是用于管理范围的多播组。这是一个用于私人组织内部的多播组的术语。这个块代表了总多播地址空间的六分之一,与本章前面看到的私有地址相当。它进一步细分为站点本地多播地址、组织本地地址等。

知名多播地址

第一块 256 个地址用于定义特殊、知名的多播地址块(表 17-7 有选择性列表)。这些地址不代表任意设备组,也不能以这种方式分配。相反,它们具有特殊含义,允许源向预定义的组发送消息。

表 17-7。知名 IP 多播地址

范围起始地址 描述
224.0.0.0 保留;未使用
224.0.0.1 子网上的所有设备
224.0.0.2 子网上的所有路由器
224.0.0.3 保留
224.0.0.4 使用 DVMRP 的所有路由器
224.0.0.5 使用 OSPF 的所有路由器
224.0.0.6 使用 OSPF 指定的路由器
224.0.0.9 使用 RIP-2 指定的路由器
224.0.0.11 移动代理(用于移动 IP)
224.0.0.12 DHCP 服务器/中继代理

由于存在多个接收者,IP 多播流量的传输比单播流量更复杂。不是通过用于单播数据报的地址解析协议(ARP)的正常解析方法,而是将 IP 多播组和硬件多播组进行映射。

分类 IP 寻址的问题

分类寻址系统是第一个尝试定义大型 IP 互联网通用寻址方法的重大尝试。正如我在分类方案概述中提到的,该系统有一个合理的理论基础,并且鉴于它是几十年前为规模有限的网络开发的,它在长时间内出色地完成了任务。

没有人曾预料到互联网会发展到如今这样的规模。随着互联网的发展,分类的 IP 寻址机制出现了一些问题。

分类寻址的三个主要问题如下:

内部地址灵活性不足 大型组织被分配了大型、单一的地址块,这与它们底层内部网络的架构并不匹配。

地址空间使用效率低下 只存在三种块大小(A 类、B 类和 C 类)会导致有限的 IP 地址空间浪费。

路由器表条目激增 随着互联网的增长,路由器需要更多的条目来路由 IP 数据报。这导致路由器性能问题。试图减少低效的地址空间分配会导致更多的路由器表条目。

第一个问题主要源于分类系统中,大型公司被分配了相当大的(B 类)或真正巨大的(A 类)地址块。它们被互联网路由器视为一个单一的网络,具有一个网络 ID。现在想象一下,你正在经营一个中等至大型公司,拥有 5,000 台计算机,并且你的网络被分配了一个 B 类地址。你真的有 5,000 台计算机都连接到一个单一的网络中吗?我肯定希望你不是!然而,你将被迫在原始的分类方法中将所有这些设备都放入一个 IP 网络中。无法创建地址的内部层次结构。

第二个和第三个问题都源于这样一个事实,即类地址系统中的粒度太低,在大规模互联网中不实用;可用的网络大小选择太少。原则上,三种大小看起来是合适的,但大小之间的差距巨大,而且大小与现实世界中组织的分布不太匹配。考虑 C 类和 B 类网络之间的大小差异——从 254 个主机直接跳到超过 65,000 个!有许许多多的公司需要的 IP 地址数量超过 254 个,但远少于 65,000 个。那么 A 类呢?有多少公司需要 1600 万个 IP 地址,即使是真正的大型公司?如果你这么想,可能没有,但那占了 IP 地址空间的一半。

拥有 5000 台计算机的公司应该使用哪种网络类别?如图 17-5 所示,类地址方案无法满足这家公司的需求。如果它被分配了一个 B 类地址,那么超过 90%的 IP 地址将会被浪费。

浪费所有这些 IP 地址的替代方案是给这家虚构的公司分配一大堆 C 类地址而不是一个 B 类地址;但它们需要 20 个这样的地址。虽然这样做会使地址空间的使用效率更高,但它导致了第三个问题:互联网上的每个路由器都必须将单个 B 类路由表条目替换为 20 个 C 类路由表条目。将这个数字乘以几千家中等规模的公司,你就会发现这种方法会极大地增加路由表的大小。这些表越大,路由器做出路由决策所需的时间就越长。

类地址的主要问题 在这个比例图中,每个方块代表 50 个可用的地址。由于 C 类地址只有 254 个地址,而 B 类包含 65,534 个地址,拥有 5000 个主机的组织处于中间位置。它只能选择浪费 B 类地址的 90%或者使用 20 个不同的 C 类网络。

图 17-5. 类地址的主要问题 在这个比例图中,每个方块代表 50 个可用的地址。由于 C 类地址只有 254 个地址,而 B 类包含 65,534 个地址,拥有 5000 个主机的组织处于中间位置。它只能选择浪费 B 类地址的 90%或者使用 20 个不同的 C 类网络。

类寻址的问题通过三个增强得到了解决,您将在后面的章节中看到。第一个,主要解决第一个问题,是子网划分的发展。第二个是转向无类寻址和路由,用具有更高粒度的新方法替换了类寻址系统。这通过根据实际组织需求分配地址来解决第二个和第三个问题,而不需要为每个组织创建大量的路由表条目。第三个改进是新的 IP 版本 6(IPv6),它最终摒弃了拥挤的 32 位 IP 地址空间,转而采用巨大的 128 位地址空间。

其他支持技术,如 NAT,通过允许多个设备共享公共地址,帮助延长了 IPv4 的生命周期。这本身就让 IPv4 寻址系统的寿命增加了数年。

第十八章. IP 子网寻址(子网划分)概念

无标题图片

在上一章中,我们探讨了原始的类 IP 寻址方案,从概念上讲,它将大型互联网划分为一个简单的两级层次结构,包括许多不同大小的网络,每个网络包含一定数量的主机。该系统对于可能将所有机器连接到单个网络的小型组织来说效果很好。然而,对于通常有许多子网络或子网的大型组织来说,它缺乏灵活性。为了更好地满足大型组织的行政和技术需求,通过称为子网寻址或更简单的子网划分的技术增强了类 IP 寻址系统。

在本章中,我描述了与 IP 子网寻址相关的概念和一般技术。我首先概述了子网划分,包括对该系统动机及其优点的讨论。我讨论了传统的两级 IP 地址划分方法如何变为三级子网划分。我谈论了子网掩码及其在寻址和路由计算中的应用。我讨论了在子网环境中用于表示类 A、B 和 C 网络的默认子网掩码,然后讨论了如何为这些类别使用自定义子网掩码。然后我讨论了子网标识符以及在子网环境中确定子网和主机地址的一般概念。我提供了子网划分 A 类、B 类和 C 类网络的总结表格。我最后简要讨论了可变长度子网掩码(VLSM),这是对传统子网划分的增强,进一步提高了其灵活性。

注意

我详细介绍了子网划分,因为理解它是了解 IP 地址如何工作以及 TCP/IP 如何工作的重要部分。然而,这项技术今天主要被认为是历史的,因为它基于类地址。子网和子网掩码的概念当然没有消失,但被分配一个 A 类、B 类或 C 类互联网地址块然后明确划分它的想法已经不再相关了

小贴士

相关信息 这是两章中关于 IP 地址子网划分的第一章。第十九章描述了使用示例的子网划分的逐步过程。如果你在阅读了这一概念部分后仍然不太理解子网划分,可以尝试阅读基于示例的部分,可能会发现这有助于使一切变得清晰。另一方面,如果你已经对子网划分有些了解,你可能发现可以跳过这一概念部分,直接进入逐步示例。你将在那一章中找到关于子网掩码、子网地址和主机地址计算的更多详细信息。将实际细节放在那里,使得这一部分可以专注于概念,而不至于过于陷入数字

小贴士

背景信息 理解子网划分需要熟悉二进制数及其操作方式。这包括使用布尔运算符,如 AND *来“屏蔽”二进制位。如果你读到最后一句话感到困惑,我强烈建议你在继续之前先复习一下计算数学的背景部分(第四章"))进行更改,以处理子网和子网掩码。

小贴士

关键概念 子网地址通过将组织的 IP 网络划分为子网,为 IP 地址的解释增加了另一个层次化级别。这使得每个组织都能将其地址空间结构化以匹配其内部物理网络,而不是被迫将它们视为平面块。这解决了原始类地址方案中的许多问题,但需要改变地址和路由的工作方式,以及修改几个 TCP/IP 协议。

虽然有趣,但与较旧的地址方案相比,子网划分的主要缺点更多地与理解子网划分的工作原理有关,而不是与这项技术本身有关。在子网环境中处理地址和路由需要更多的努力,管理员必须学习如何将他们的网络划分为子网,并正确分配地址。这对子网划分的新手来说可能有点令人困惑。然而,今天这项技术已经相当成熟,所以这并不是一个大问题。

IP 子网划分:三级层次化 IP 子网地址

如我之前所述,子网划分在 IP 地址使用的结构层次中增加了一个额外的层次。为了支持这一点,IP 地址必须被分成三个元素而不是两个。这是通过保持网络 ID 不变,并将主机 ID 划分为子网 ID 和主机 ID 来实现的。这些子网 ID 位用于识别网络中的每个子网。主机以对网络最有意义的方式分配到子网中。

有趣的是,之前对电话号码的类比在子网划分的世界中仍然适用,并展示了子网划分如何改变对 IP 地址的解释方式。例如,像(401) 555-7777 这样的电话号码有一个区号(401)和一个本地号码(555-7777)。然而,本地号码本身可以分解为两部分:交换机(555)和本地分机(7777)。这意味着电话号码实际上由三个层次化的组件组成,就像子网划分中的 IP 地址一样。

当然,IP 地址中的位数是固定的,为 32 位。这意味着在将主机 ID 划分为子网 ID 和主机 ID 时,你减小了地址中主机 ID 部分的尺寸。本质上,你是在从主机 ID 中窃取位数来用于子网 ID。A 类网络有 24 位可以分配给子网 ID 和主机 ID;B 类网络有 16 位;C 类网络只有 8 位。

提示

关键概念 类地址通过将主机 ID 部分进行划分来进行子网划分,保留一些位用于主机 ID,而将其他位分配给新的子网 ID。这些位随后用于识别网络中的各个子网,主机被分配到这些子网中。

现在记住,当我们查看上一章中每个主要类的大小的时候,我们看到了对于每个类,网络的数量和每个网络的主机数是每个类使用的位数的函数。同样适用于主机 ID 的划分。由于我们处理的是二进制数,子网的数量是子网 ID 字段大小的 2 的幂。同样,每个子网的主机数是主机 ID 字段大小的 2 的幂(减去两个排除的特殊情况)。

让我们通过一个简短的例子来看看这是如何工作的。想象一下,你从一个 B 类网络 154.71.0.0 开始,网络 ID(154.71)有 16 位,主机 ID 也有 16 位。在常规的类地址中,没有子网,总共有 65,534 个主机。为了划分这个网络,你可以决定如何划分那 16 位,以最好地满足网络的需求:1 位用于子网 ID 和 15 位用于主机 ID,或者 2 和 14,3 和 13,等等。只要总数是 16,大多数任何组合都是可行的;我在图 18-1 中使用了 5 和 11。从主机 ID 中为子网 ID 窃取的位数越多,你可以拥有的子网就越多,但每个子网的主机数就越少。

子网划分 B 类网络 我们从 B 类网络 154.71.0.0 开始,该网络在其主机 ID 块中有 16 位。然后我们通过将主机 ID 划分为子网 ID 和主机 ID 来划分这个网络。在这种情况下,5 位被分配给了子网 ID,剩下 11 位用于主机 ID。

图 18-1. 子网划分 B 类网络 我们从 B 类网络 154.71.0.0 开始,该网络在其主机 ID 块中有 16 位。然后我们通过将主机 ID 划分为子网 ID 和主机 ID 来划分这个网络。在这种情况下,5 位被分配给了子网 ID,剩下 11 位用于主机 ID。

在设置子网 IP 网络时,如何将主机 ID 分割成子网位和主机位是设计时最重要的考虑因素之一。子网的数量通常基于整个组织网络中物理子网的数量来确定,并且每个子网中的主机数量不能超过你所选择的特定子网划分允许的最大值。如何将原始的主机 ID 位分割成子网 ID 位和主机 ID 位有时被称为自定义子网划分,本章后面将更详细地描述。

IP 子网掩码、表示法和子网计算

子网划分将组织的网络划分为一个完全内部且对互联网上所有其他组织隐藏的两级结构:子网和主机。其许多优点之一是每个组织都可以根据自己的选择来划分类别的主机 ID 为子网 ID 和主机 ID。

在非子网划分的类环境,路由器使用 IP 地址的第一个八位字节来确定地址的类别,并据此知道哪些位是网络 ID,哪些位是主机 ID。当你使用子网划分时,这些路由器也需要知道如何将主机 ID 划分为子网 ID 和主机 ID。然而,这种划分对每个网络来说是任意的。此外,仅通过查看 IP 地址就无法判断属于每个类别的位数。

在子网划分环境中,关于哪些位是子网 ID 位和哪些位是主机 ID 位的信息必须传达给解释 IP 地址的设备。这些信息以一个 32 位的二进制数的形式给出,称为子网掩码。术语掩码来自二进制数学概念中的位掩码。这是一种技术,可以使用特殊的 1 和 0 的模式与布尔函数(如 AND 和 OR)结合使用,以选择或清除数字中的某些位。(我在关于二进制数和数学的背景部分中解释了位掩码,在第四章中。)

子网掩码的功能

子网掩码似乎让人感到不安,尤其是如果他们对二进制数不熟悉的话。然而,其背后的理念非常简单。掩码是一个 32 位的数字,就像 IP 地址也是一个 32 位的数字一样。子网掩码中的每一个 32 位对应于 IP 地址中相同位置的位。任何给定子网中掩码的位被选择,使得用于网络 ID 或子网 ID 的位是 1,而用于主机 ID 的位是 0。

小贴士

关键概念 子网掩码是一个 32 位二进制数,与 IP 地址一起使用。它是这样创建的,即对于 IP 地址中属于其网络 ID 或子网 ID 的每个对应位都有一个 1 位,而对于 IP 地址的主机 ID 的每个位都有一个 0 位。因此,掩码告诉 TCP/IP 设备哪些位属于网络 ID 和子网 ID,哪些位是主机 ID 的一部分。

为什么要用 32 位二进制数来做这件事呢?答案是布尔逻辑的魔力。你通过将布尔 AND 函数应用于子网掩码和 IP 地址来使用子网掩码。对于 IP 地址和子网掩码中的每个 32 个“位对”,你使用 AND 函数,其输出只有当两个位都是 1 时才为 1。这在实际意义上的含义如下,对于每个 32 位:

子网位为 1 在这种情况下,你正在将 IP 地址中的 0 或 1 与 1 进行 AND 操作。如果 IP 地址位是 0,AND 操作的结果将是 0;如果是 1,AND 操作将是 1。换句话说,当子网位为 1 时,IP 地址保持不变

子网位为 0 在这种情况下,你正在与 0 进行 AND 操作,所以结果总是 0,无论 IP 地址是什么。因此,当子网位为 0 时,IP 地址位总是被清除为零

因此,当你在 IP 地址上使用子网掩码时,网络 ID 和子网 ID 中的位保持不变,而主机 ID 位被移除。就像一个只遮挡你面部一部分但让其他部分露出的面具一样,子网掩码遮挡了地址的一部分位(主机位),而其他位保持不变(网络和子网位)。执行此功能的路由器将保留子网的地址。由于它知道从网络类别中哪个部分是网络 ID,它也知道地址位于哪个子网。

小贴士

关键概念 要使用子网掩码,设备会在子网掩码的每一位与 IP 地址的对应位之间执行布尔 AND 操作。结果 32 位数字仅包含地址的网络 ID 和子网 ID,主机 ID 被清除为零。

子网掩码表示法

就像 IP 地址一样,子网掩码在计算机中总是以 32 位二进制数的形式使用。并且,就像 IP 地址一样,将它们作为 32 位二进制数使用对人类来说很困难。因此,它们通常被转换为点分十进制表示法以便于使用,就像 IP 地址一样。

例如,假设你决定使用 5 位作为子网 ID 和 11 位作为主机 ID 来子网化 B 类网络 154.71.0.0(参见图 18-2)。在这种情况下,子网掩码将有 16 个 1 用于网络部分(因为这是 B 类),然后是 5 个 1 用于子网 ID,接着是 11 个 0 用于主机 ID。这在二进制中表示为 11111111 11111111 11111000 00000000,其中对应子网 ID 的位被突出显示。在点分十进制中,子网掩码将是 255.255.248.0。

确定子网掩码的子网化网络 示例图 在此图中,显示的是从顶部开始的 B 类网络,其中 5 位分配给了子网 ID,剩下 11 位用于主机 ID。要创建子网掩码,你需要将一个 32 位的数字填充为每个网络 ID 和子网 ID 位为 1,每个主机 ID 位为 0。然后你可以将其转换为点分十进制。

图 18-2. 确定子网化网络的子网掩码。图 18-1 中的 B 类网络从顶部开始,分配了 5 位给子网 ID,剩下 11 位用于主机 ID。要创建子网掩码,你需要将一个 32 位的数字填充为每个网络 ID 和子网 ID 位为 1,每个主机 ID 位为 0。然后你可以将其转换为点分十进制。

应用子网掩码:示例

现在,让我们看看子网掩码可能如何被使用。假设你在这个网络上有主机,其 IP 地址为 154.71.150.42,而路由器需要确定这个地址所在的子网。为此,它执行了表 18-1 和图 18-3 中显示的掩码操作。

表 18-1. 通过子网掩码确定 IP 地址的子网 ID

组件 八位字节 1 八位字节 2 八位字节 3 八位字节 4
IP 地址 10011010 (154) 01000111 (71) 10010110 (150) 00101010 (42)
子网掩码 11111111 (255) 11111111 (255) 11111000 (248) 00000000 (0)
AND 掩码结果 10011010 (154) 01000111(71) 10010000 (144) 00000000 (0)

通过子网掩码确定 IP 地址的子网 ID 子网掩码涉及在子网掩码和 IP 地址的每个对应位之间执行布尔 AND 操作。子网掩码可以比作物理掩码;其中的每个 1 都允许 IP 地址的对应位显示出来,而每个 0 则阻止 IP 地址的对应位。这样,地址的主机 ID 位就被剥离,以便设备可以确定地址所属的子网。

图 18-3. 通过子网掩码确定 IP 地址的子网 ID 子网掩码涉及在子网掩码和 IP 地址的每个对应位之间执行布尔 AND 操作。子网掩码可以比作物理掩码;其中的每个 1 都允许 IP 地址的对应位显示出来,而每个 0 则阻止 IP 地址的对应位。这样,地址的主机 ID 位就被剥离,以便设备可以确定地址所属的子网。

这个结果,154.71.144.0,是 154.71.150.42 所属子网的 IP 地址。由于你仍在使用类别地址,因此没有必要明确区分网络 ID 位和子网 ID 位。任何路由器都可以看到,由于地址的前两位是 10,这是一个 B 类地址。因此,网络 ID 是 16 位,这意味着子网 ID 必须是从左边数起的第 17 到 21 位。在这里,子网是之前突出显示的部分:10010,或子网 18。(我将在本章后面的“IP 自定义子网掩码”部分更好地解释这一点。)

小贴士

关键概念 子网掩码通常以点分十进制表示法表示,以便于使用,但计算机将其用作二进制数,通常必须以二进制形式表示,以便理解掩码的工作原理以及它所代表的子网 ID 位数。

子网掩码表示法的理由

从实际的角度来看,子网掩码实际上只传达一条信息:子网 ID 和主机 ID 之间的界限。那么为什么还要费心使用一个大的 32 位二进制数,而不是只指定发生分割的位数呢?为什么不在 21 位之后直接分割 IP 地址?即使设备想要执行掩码操作,它们不能按需创建掩码吗?

这是一个非常好的问题。有两个历史原因:效率考虑和对非连续掩码的支持。子网掩码表达式是高效的,因为它允许路由器快速执行掩码操作以确定子网地址。(考虑到今天机器的速度,这实际上并不是一个问题。)

当将主机 ID 中的位分割为子网 ID 和主机 ID 时,RFC 950 指定它们可以在多个地方分割。在先前的例子中,你不仅可以把 16 位分割成 5 位作为子网 ID 和 11 位作为主机 ID,还可以将其分割为 2 位作为子网 ID,然后 4 位作为主机 ID,接着再分割 3 位作为子网 ID,最后再分割 7 位作为主机 ID。对于这 16 位,子网掩码模式将是 11000011 10000000(紧随网络 ID 的 16 个 1 之后)。当然,以这种方式进行子网划分会使得分配地址变得极其混乱。因此,虽然技术上合法,但非连续子网掩码不被推荐,并且在实践中也不这样做。

由于非连续掩码不再使用,并且今天的计算机速度更快,现在经常使用仅用一个数字来表示掩码的替代方法。与其写“IP 地址为 154.71.150.42,子网掩码为 255.255.248.0”,你只需简单地写“154.71.150.42/21”。这有时被称为斜线表示法无类别域间路由(CIDR)表示法。虽然这在可变长度子网掩码(VLSM)环境中更为常见,并且在 CIDR 地址方案下指定无类别地址是标准(见第二十章 总结了每个类别的默认子网掩码。它们也以图形方式显示在图 18-4 中。

表 18-2. Class A、Class B 和 Class C 网络的默认子网掩码

IP 地址类别 网络 ID/主机 ID 的总位数 默认子网掩码
第一字节
--- --- ---
Class A 8/24 11111111 (255)
Class B 16/16 11111111 (255)
Class C 24/8 11111111 (255)

Class A、Class B 和 Class C 网络的默认子网掩码

图 18-4. Class A、Class B 和 Class C 网络的默认子网掩码

因此,三个默认子网掩码分别是 Class A 的 255.0.0.0,Class B 的 255.255.0.0,以及 Class C 的 255.255.255.0。

虽然所有默认子网掩码都只使用 255 和 0,但并非所有包含 255 和 0 的子网掩码都是默认的。还有一些自定义子网在八位边界上划分,如下所示:

255.255.0.0 这是 Class B 的默认掩码,但也可以是使用 8 位子网 ID(为主机 ID 留下 16 位)来划分 Class A 网络的自定义子网掩码。

255.255.255.0 这是 Class C 的默认子网掩码,但可以是具有 16 位子网 ID 的自定义 Class A 或具有 8 位子网 ID 的 Class B。

提示

关键概念 每个三个 IP 单播和广播地址类别,A、B 和 C,都有一个 默认子网掩码 定义,该掩码在每个类别的网络 ID 的位上有一个 1,在其主机 ID 的位上有一个 0,并且没有子网 ID 位。三个默认子网掩码分别是 Class A 的 255.0.0.0,Class B 的 255.255.0.0,以及 Class C 的 255.255.255.0。

IP 自定义子网掩码

默认子网掩码实际上并不代表子网划分,因为您正在将零位分配给子网 ID。要进行真正的子网划分,您必须将 presubnetted 主机 ID 的至少一位位分配给子网 ID。

由于你可以选择子网 ID 和主机 ID 之间的分隔点以适应网络,这有时被称为定制子网划分。在创建定制子网时使用的子网掩码,反过来,被称为定制子网掩码。定制子网掩码由网络硬件用于确定如何在网络中将子网 ID 从主机 ID 中划分。

决定使用多少子网位

定制子网划分中的关键决策是从 IP 地址的主机 ID 部分取出多少位放入子网 ID。你会记得,网络中可能的子网数量是用于表示子网 ID 的位的数量的 2 的幂,每个子网可能的主机数量是主机 ID 中剩余位的 2 的幂(减去两个,如我在本节后面解释的那样)。

因此,决定为每个子网 ID 和主机 ID 使用多少位代表了子网寻址中的一个基本权衡:

  • 从主机 ID 中取出的每个位用于子网 ID,都会使网络中可能的子网数量加倍。

  • 从主机 ID 中取出的每个位用于子网 ID(大约)将网络中每个子网内可能的主机数量减半。

例如,假设你从一个 B 类网络开始,网络地址为 154.71.0.0。由于这是 B 类,16 位用于网络 ID(154.71)和 16 位用于主机 ID。在默认情况下,没有子网,总共有 65,534 个主机。要划分这个网络,你可以使用以下方法:

  • 子网 ID 使用 1 位,主机 ID 使用 15 位。如果你这样做,子网总数将是 2¹,即 2。第一个子网是 0,第二个是 1。每个子网可用的主机数量是 2¹⁵–2,即 32,766。

  • 子网 ID 使用 2 位,主机 ID 使用 14 位。在这种情况下,子网数量加倍。现在你有 2²,即 4 个子网:00、01、10 和 11(子网 0、1、2 和 3)。但主机数量现在只有 2¹⁴–2,即 16,382。

  • 任何位组合,只要总和为 16,并且每个子网至少有 2 个主机:4 和 12,5 和 11 等等。

你决定如何将类 C 主机 ID 划分为子网 ID 和主机 ID 位是子网划分中的关键设计决策。你的选择基于网络中的子网数量,以及网络中每个子网需要分配的最大主机数量。例如,如果你有 10 个总子网用于你的 B 类网络,你需要 4 位来表示这一点,因为 2⁴是 16,而 2³只是 8。这留下了 12 位用于主机 ID,每个子网最多有 4,094 个主机。

然而,假设你有 20 个子网。如果是这样,子网 ID 的 4 位将不足以使用;你需要 5 位(2⁵=32)。这意味着你现在只有 11 位用于主机 ID,每个子网最多有 2,046 个主机。(第十九章中的实际子网划分示例的第二步详细讨论了这些决策。)

现在你有 20 个子网,并且每个子网最多需要 3,000 个主机,你遇到了问题。你需要 5 位来表示 20 个不同的子网,但你需要 12 位来表示主机的 ID 号。这是 17 位——太多了。解决方案是什么?你可能能够重新排列你的物理网络,使得你只有 16 个。如果不能,你需要第二个 B 类网络。

小贴士

关键概念 子网划分的基本权衡是,每个子网 ID 位(因此,从主机 ID 中减去该位)的增加都会使子网数量翻倍,并且大约将每个子网中的主机数量减半。从子网 ID 中减去位(并将该位加到主机 ID 上)会做相反的事情。

确定自定义子网掩码

一旦你确定了分配给子网和主机 ID 的位数,你就可以确定子网掩码。你从网络适当类别的默认子网掩码的二进制形式开始。你从该掩码中最左边的零开始,将你分配给子网 ID 的位数改为一,此时你可以用点分十进制形式表示子网掩码。图 18-5 显示了如何为 Class C 网络的每个子网划分选项确定自定义子网掩码,既以二进制形式又以十进制形式。

考虑图 18-5 中的 Class C 网络 200.13.94.0。原始主机 ID 中有 8 位,这为你提供了六种不同的子网划分选项(你无法使用七位或八位作为子网 ID,原因我将在稍后讨论)。假设你使用其中的三位作为子网 ID,剩下五位作为主机 ID。为了确定自定义子网掩码,你从 Class C 默认子网掩码开始:

11111111 11111111 11111111 00000000
然后你将前三个零改为一,以获得自定义子网掩码:
11111111 11111111 11111111 11100000
以点分十进制格式,这表示为 255.255.255.224.

注意

一旦你选择了子网划分的方法,你就可以通过从网络的默认子网掩码开始,将每个子网 ID 位从零改为一来确定自定义子网掩码

注意

在常规子网划分中,用于子网 ID 的位数在整个网络中是固定的。你不能有不同大小的子网——它们必须相同。因此,最大子网中的主机数将决定你需要多少位用于主机 ID。这意味着在先前的例子中,如果你有一个奇怪的配置,其中 19 个子网每个只有 100 个主机,但第 20 个子网有 3,000 个,你将遇到问题。如果这种情况发生,你可以通过将那个超大的子网分成两个或更多较小的子网来轻松解决这个问题。子网划分的一个增强功能,称为可变长度子网掩码(VLSM),在很大程度上是为了消除这一限制。VLSM 将在本章后面进行描述

C 类网络的自定义子网掩码 由于 C 类网络地址中有主机 ID 位,因此网络可以有六种不同的子网划分方式。每种方式对应一个不同的自定义子网掩码,这是通过将分配的子网 ID 位从零改为一来创建的。

图 18-5. C 类网络的自定义子网掩码 由于 C 类网络地址中有主机 ID 位,因此网络可以有六种不同的子网划分方式。每种方式对应一个不同的自定义子网掩码,这是通过将分配的子网 ID 位从零改为一来创建的。

从每个子网的主机数中减去两个,以及(可能)从每个网络中的子网数中减去两个

你已经看到了在常规的类地址中,你必须从每个网络允许的主机数中减去两个。这是必要的,因为每个子网中有两个主机 ID 有特殊含义:全零的主机 ID(表示“此网络”)和全一的主机 ID(表示向网络上的所有主机广播)。这些限制也适用于子网划分下的每个子网,这就是为什么你必须继续从每个子网的主机数中减去两个的原因。(这也是为什么将 C 类网络的八个主机 ID 位分为七个用于子网 ID 和一个用于主机 ID 是没有意义的:它留下了 2¹–2 = 0 个主机每个子网,这并不特别有用。)

子网 ID 也存在类似的问题。当最初在 RFC 950 中定义子网划分时,标准明确排除了使用全零和全一的子网。这是由于担心路由器可能会被这些情况弄混淆。后来的标准 RFC 1812,“IP 版本 4 路由器的要求”,在 1995 年移除了这一限制。因此,现代硬件现在对全零或全一的子网没有问题,但一些非常旧的硬件可能仍然会对此表示抗拒。

提示

关键概念 每个子网允许的主机数是子网划分后剩余的主机 ID 位数的二进制幂减去二。减去两个是因为每个子网内的全零和全一主机 ID 被保留用于两个特殊意义地址:指代子网本身和指代其本地广播地址。在某些实现中,子网的数量也减少了两个,因为最初不允许使用全零和全一的子网 ID。

因此,有时你会看到排除这些情况的子网划分讨论。当这样做时,你会失去两个潜在的子网:全零和全一的子网。如果你这样做,那么选择一个位作为子网 ID 就不再有效,因为它会产生 2¹–2=0 个子网。如果你需要两个子网,你必须选择两个位。

注意

在这本书中,我假设你正在处理现代硬件,不排除全零和全一的子网,但我确实会在相关的地方明确指出这一点。本章后面的总结表格显示了 A、B 和 C 类每个子网划分的权衡,以及每个选择的子网掩码

IP 子网标识符、子网地址和主机地址

与子网相比,传统的不使用子网的类属地址的主要优势是简单性。例如,尽管在单个 B 类网络中管理数千个设备可能会有问题,但在网络内分配地址是简单的:它们都被合并在一起,所以可以在主机 ID 中使用任何位组合(除了全零和全一)。

当你进行子网划分时,然而,你会在类属主机 ID 内部创建一个两级结构:子网 ID 和主机 ID。这意味着你必须更仔细地选择设备的 IP 地址。从理论上讲,你正在选择子网以对应组织内的物理网络,因此你希望以与物理网络结构一致的方式分配 IP 地址。

子网标识符

一旦你决定将有多少个子网,你需要识别子网并确定它们的地址。你从子网标识符开始,即我们网络中任何子网的子网 ID。子网从零开始编号,增加到小于最大子网数,这是子网 ID 中位数数的函数。(如果排除全零和全一的子网 ID,如 RFC 950 中指定,则第一个子网 ID 为 1。)

当然,你可能不需要定义的所有子网。例如,如果你有 20 个子网,你需要五个位作为子网标识符,这允许理论上的最大 32 个子网。你将只使用子网 0 到 19;20 到 31 将被保留供将来使用。这些子网可以用十进制形式(0,1,2……直到 19)或二进制形式(00000,00001,00010,等等,直到 10011)表示。

子网地址

对于每个子网,你也可以确定其子网地址。为此,你需要从整个网络的 IP 地址开始,该地址在类别的主机 ID 字段中所有位都是零(8 位、16 位或 24 位)。然后,你将特定子网的子网 ID 插入指定的子网位中。

例如,要子网化图 18-2 中显示的 154.71.0.0 的 B 类网络,其中你使用五个子网 ID 位,你从以下带有高亮显示的子网 ID 位的网络 IP 地址开始:

10011010 01000111 00000000 00000000

要找到例如子网 11 的地址,你需要将这些位替换为 01011,保留主机 ID 位为零,如下所示:

10011010 01000111 01011000 00000000

然后,你可以将其从二进制形式转换为点分十进制,得到子网地址为 154.71.88.0。

小贴士

关键概念 子网的标识符就是其子网 ID。子网的子网地址是通过将子网 ID 替换到整个网络地址的子网位中确定的。

当你查看子网寻址时,尤其是在按顺序替换子网 ID 时,一个模式会立即变得明显。第一个子网地址总是整个网络的地址,因为子网 ID 全部为零。然后,通过向一个八位字节添加一个特定的二倍数来找到十进制形式的第二个子网地址。然后,通过将这个相同的数字添加到第二个地址来找到第三个地址,依此类推。

事实上,每个子网地址的十进制值可以表示为一个公式,基于原始网络的类别和用于子网 ID 的位数。例如,考虑一个具有整体地址 x.y.0.0 的 B 类网络(对于这些目的,x 和 y 是什么并不重要)。现在假设你使用两个位作为子网 ID。这里有四个子网地址:

  • 子网 0 的地址将与网络地址相同:x.y.0.0。

  • 子网 1 的地址是通过将 01 替换为第三个八位字节的前两位来找到的。这产生了一个地址为 x.y.01000000.0000000,或者说是 x.y.64.0 的纯十进制形式。

  • 子网 2 的地址是通过将 10 替换为子网 ID 位来找到的,因此它是 x.y.10000000.0000000,或者说是 x.y.128.0 的纯十进制形式。

  • 子网 3 的地址将是 x.y.192.0。

因此,在这种情况下,子网N的公式是 x.y.N^64.0. 如果您为子网使用五个比特,公式是 x.y.N^8.0. 正如您之前看到的,网络 154.71.0.0 中子网 11 的子网地址是 154.71.88.0. 我已经在子网划分总结表中(表 Table 18-3,Table 18-4,和 Table 18-5)展示了所有子网 ID 和主机 ID 大小组合的公式。一旦您对子网划分更加熟悉,这些公式可以真正节省时间。

每个子网内的主机地址

一旦您知道了特定子网的子网地址,您就可以通过将值插入剩余的主机 ID 比特中来分配 IP 地址。您跳过全零值,因此子网中的第一个主机的主机 ID 除了最右边的比特位置为 1 之外都是零。然后下一个主机除了末尾的"10"(十进制中的 2)之外都是零。您可以一直做到全一的值之前的一个值。同样,然后您将每个 IP 地址从二进制转换为十进制。

注意

您可以在第十九章实际子网划分的覆盖中找到这些详细信息

A 类、B 类和 C 类网络的 IP 子网划分总结表

由于 A 类、B 类和 C 类网络的子网划分选项有限,我在总结表 Table 18-3 到 Table 18-5 中列出了每个类别的选项。这些表格可以帮助您快速决定子网 ID 和主机 ID 应使用多少比特,以及选择它们的子网掩码是什么。它们还很好地总结了本章到目前为止我所讨论的内容。

每个表格的每一行显示了该类的一个可能的子网划分选项,包括子网 ID 和主机 ID 的比特数,以及基于比特数的子网和主机数量。然后我展示了子网掩码的二进制和十进制形式,以及 CIDR 表示法(在第二十章无类别 IP 地址——无类别域间路由(CIDR)/超网中介绍)。最后,我包括了每个选项下计算每个子网地址的公式。

关于这些表格,有一些额外的解释性说明是必要的:

  • 每个网络中子网数目的值假设允许全零和全一子网。如果不允许,则必须从这些数字中减去两个。这也意味着仅使用一个比特位用于子网 ID 的选项变得无效,子网地址公式也不再按所示工作。

  • 每个子网的主机数不包括全零和全一的情况,因此是主机 ID 比特数的 2 的幂次,减去 2。

  • 每个表格的第一行显示了默认情况,其中子网位数为零,因此子网掩码是类默认子网掩码。

  • 在所有选项的子网掩码中,除了默认选项外,我都突出了对应于子网 ID 的子网掩码部分,以增强清晰度。这已经针对二进制掩码的每个单独比特位以及掩码的点分十进制表示中的每个八位字节(其中包含子网 ID 的一部分)进行了操作。

  • 在查看这些表格时,你会发现并非所有的划分在现实世界中都有很大的意义,尽管你可能感到惊讶。例如,乍一看,认为你可能想要将类 B 主机 ID 的 14 位分配给子网 ID,并留下 2 位用于主机 ID 似乎很荒谬——什么样的真实网络会有 16,384 个子网,每个子网有两个主机?然而,一些大型互联网服务公司确实在设置路由器之间的连接或其核心网络与客户之间的连接时可能需要成千上万的微小子网。

  • 每个表格最后一列的子网地址公式显示了子网N(从零开始编号,到最大子网数减一)的地址。请参阅逐步子网划分讨论的步骤 4 的结尾(第十九章** | 24 | 1 | 16,277,214 | 11111111.00000000.00000000.00000000255.0.0.0 | /8 | — |
    | 1 | 23 | 2 | 8,388,606 | 11111111.10000000.00000000.00000000255.128.0.0 | /9 | x.N128.0.0 |
    | 2 | 22 | 4 | 4,194,302 | 11111111.111000000.00000000.00000000255.192.0.0 | /10 | x.N
    64.0.0 |
    | 3 | 21 | 8 | 2,097,150 | 11111111.11100000.00000000.00000000255.224.0.0 | /11 | x.N32.0.0 |
    | 4 | 20 | 16 | 1,048,574 | 11111111.11110000.00000000.00000000255.240.0.0 | /12 | x.N
    16.0.0 |
    | 5 | 19 | 32 | 524,286 | 11111111.11111000.00000000.00000000255.248.0.0 | /13 | x.N8.0.0 |
    | 6 | 18 | 64 | 262,142 | 11111111.11111100.00000000.00000000255.252.0.0 | /14 | x.N
    4.0.0 |
    | 7 | 17 | 128 | 131,070 | 11111111.11111110.00000000.00000000255.254.0.0 | /15 | x.N*2.0.0 |
    | 8 | 16 | 256 | 65,534 | 11111111.11111111.00000000.00000000255.
    255.0.0 | /16 | x.N.0.0 |
    | 9 | 15 | 512 | 32,766 | 11111111.11111111.10000000.00000000255.
    255.128.0 | /17 | x.N/2.(N%2)*128.0 |
    | 10 | 14 | 1,024 | 16,382 | 11111111.11111111.11000000.00000000255.
    255.192.0 | /18 | x.N/4.(N%4)*64.0 |
    | 11 | 13 | 2,048 | 8,190 | 11111111.11111111.11100000.00000000255.
    255.224.0 | /19 | x.N/8.(N%8)*32.0 |
    | 12 | 12 | 4,096 | 4,094 | 11111111.11111111.
    11110000.00000000255.255.240.0 | /20 | x.N/16.(N%16)*16.0 |
    | 13 | 11 | 8,192 | 2,046 | 11111111.11111111.
    11111000.00000000255.255.248.0 | /21 | x.N/32.(N%32)*8.0 |
    | 14 | 10 | 16,384 | 1,022 | 11111111.11111111.
    11111100.00000000255.255.252.0 | /22 | x.N/64.(N%64)*4.0 |
    | 15 | 9 | 32,768 | 510 | 11111111.11111111.
    11111110.00000000255.255.254.0 | /23 | x.N/128.(N%128)*2.0 |
    | 16 | 8 | 65,536 | 254 | 11111111.11111111.
    11111111.00000000255.255.255.0 | /24 | x.N/256.N%256.0 |
    | 17 | 7 | 131,072 | 126 | 11111111.11111111.
    11111111.10000000255.255.255.128** | /25 | x.N/512.(N/2)%256.(N%2)128 |
    | 18 | 6 | 262,144 | 62 | 11111111.11111111.11111111.11000000255.255.255.192 | /26 | x.N/1024.(N/4)%256.(N%4)
    64 |
    | 19 | 5 | 524,288 | 30 | 11111111.11111111.11111111.11100000255.255.255.224 | /27 | x.N/2048.(N/8)%256.(N%8)32 |
    | 20 | 4 | 1,048,576 | 14 | 11111111.11111111.11111111.11110000255.255.255.240 | /28 | x.N/4096.(N/16)%256.(N%16)
    16 |
    | 21 | 3 | 2,097,152 | 6 | 11111111.11111111.11111111.11111000255.255.255.248 | /29 | x.N/8192.(N/32)%256.(N%32)8 |
    | 22 | 2 | 4,194,304 | 2 | 11111111.11111111.11111111.11111100255.255.255.252 | /30 | x.N/16384.(N/64)%256.(N%64)
    4 |

Table 18-4. 子网划分汇总表,适用于 B 类网络

子网 ID 位数 主机 ID 位数 每个网络中的子网数量 每个子网中的主机数量 子网掩码(二进制/点分十进制) 子网掩码(斜杠/ CIDR 表示法) 子网地址#N 公式(N=0, 1, 子网数量-1)
0 (默认) 16 1 65,534 11111111.11111111.00000000.00000000255.255.0.0 /16 -
1 15 2 32,766 11111111.11111111.10000000.00000000255.255.128.0 /17 x.y.N*128.0
2 14 4 16,382 11111111.11111111.11000000.00000000255.255.192.0 /18 x.y.N*64.0
3 13 8 8,190 11111111.11111111.11100000.00000000255.255.224.0 /19 x.y.N*32.0
4 12 16 4,094 11111111.11111111.11110000.00000000255.255.240.0 /20 x.y.N*16.0
5 11 32 2,046 11111111.11111111.11111000.00000000255.255.248.0 /21 x.y.N*8.0
6 10 64 1,022 11111111.11111111.11111100.00000000255.255.252.0 /22 x.y.N*4.0
7 9 128 510 11111111.11111111.11111110.00000000255.255.254.0 /23 x.y.N*2.0
8 8 256 254 11111111.11111111.11111111.00000000255.255.255.0 /24 x.y.N.0
9 7 512 126 11111111.11111111.11111111.10000000255.255.255.128 /25 x.y.N/2.(N%2)*128
10 6 1,024 62 11111111.11111111.11111111.11000000255.255.255.192 /26 x.y.N/4.(N%4)*64
11 5 2,048 30 11111111.11111111.11111111.11100000255.255.255.224 /27 x.x.N/8.(N%8)*32
12 4 4,096 14 11111111.11111111.11111111.11110000255.255.255.240 /28 x.y.N/16.(N%16)*16
13 3 8,192 6 11111111.11111111.11111111.11111000255.255.255.248 /29 x.y.N/32.(N%32)*8
14 2 16,384 2 11111111.11111111.11111111.11111100255.255.255.252 /30 x.y.N/64.(N%64)*4

表 18-5. C 类网络的子网划分汇总表

子网 ID 位数 主机 ID 位数 每个网络中的子网数 每个子网中的主机数 子网掩码(二进制/点分十进制) 子网掩码(斜杠/ CIDR 表示法) 子网地址#N 公式(N=0, 1, 子网数-1)
0 (默认) 8 1 254 11111111.11111111.11111111.00000000255.255.255.0 /24
1 7 2 126 11111111.11111111.11111111.10000000255.255.255.128 /25 x.y.z.N*128
2 6 4 62 11111111.11111111 .11111111.11000000255.255.255.192 /26 x.y.z.N*64
3 5 8 30 11111111.11111111.11111111.11100000255.255.255.224 /27 x.y.z.N*32
4 4 16 14 11111111.11111111.11111111.11110000255.255.255.240 /28 x.y.z.N*16
5 3 32 6 11111111.11111111.11111111.11111000255.255.255.248 /29 x.y.z.N*8
6 2 64 2 11111111.11111111.11111111.11111100255.255.255.252 /30 x.y.z.N*4

IP 可变长度子网掩码(VLSM)

传统子网划分的主要弱点在于子网 ID 仅代表 IP 地址解释和使用路由中的一个额外的层次级别。

看起来贪婪地看待子网划分并说,“什么,只有一个额外的级别?”然而,在大型网络中,将整个网络仅划分为一个级别的子网并不代表 IP 地址块的最佳使用。

此外,您已经看到,由于子网 ID 在整个网络中长度相同,如果您有子网数量差异很大的子网,可能会出现问题。子网 ID 必须根据具有最大主机数的子网来选择,即使大多数子网的主机数要少得多。即使在小型网络中,这也可能是不高效的,并且可能导致需要使用额外的地址块,同时浪费每个块中的许多地址。

例如,考虑一个相对较小的公司,拥有一个 C 类网络,201.45.222.0/24。管理员在其网络中有六个子网。前四个子网(S1、S2、S3 和 S4)相对较小,每个子网只包含 10 个主机。然而,其中一个(S5)是为他们的生产线而设,有 50 个主机,最后一个(S6)是他们的开发和工程团队,有 100 个主机。因此,所需的总主机数为 196。

在没有子网划分的情况下,公司在其 C 类网络中有足够的主机来处理它们。然而,当他们尝试进行子网划分时,他们会遇到一个大问题。为了拥有六个子网,他们需要使用三个位来表示子网 ID。这仅留下五个位用于主机 ID,这意味着每个子网都有相同的容量,即 30 个主机,如图 18-6 所示。这对于较小的子网来说是足够的,但对于较大的子网来说则不够。除了重新排列物理子网之外,使用传统子网划分的唯一解决方案是为两个大子网获取另一个 C 类地址块,并使用原始的地址块来处理四个小子网。但这很昂贵,意味着浪费了数百个 IP 地址!

C 类(/24)网络划分为八个传统子网。使用传统子网划分,所有子网必须具有相同的大小,当某些子网的大小远大于其他子网时,这会引发问题。与此相对比。

图 18-6。C 类(/24)网络划分为八个传统子网。使用传统子网划分,所有子网必须具有相同的大小,当某些子网的大小远大于其他子网时,这会引发问题。与此相对比图 18-7。

解决方案:可变长度子网掩码

解决方案是对基本子网寻址方案的一种增强,称为可变长度子网掩码(VLSM)。其理念是,你首先对网络进行子网划分,然后对子网进行子网划分,就像你最初对网络进行子网划分一样。实际上,你可以多次这样做,创建子网中的子网网段,次数取决于你的地址块中主机 ID 的位数。

可以选择将这种多级分割仅应用于某些子网,从而允许您有选择地切割 IP 地址块,使得一些块比其他块大。这意味着在先前的例子中,公司可以创建六个子网来满足其网络的需求,如图图 18-7 网络进行分割。使用 VLSM,一个组织可以多次将其 IP 网络分割成与其实际网络大小要求更匹配的子网。与图 18-6 进行比较。")所示。

C 类(/24)网络使用 VLSM 进行分割。使用 VLSM,一个组织可以多次将其 IP 网络分割成与其实际网络大小要求更匹配的子网。与进行比较。

图 18-7. 使用 VLSM 对 C 类(/24)网络进行分割。使用 VLSM,一个组织可以多次将其 IP 网络分割成与其实际网络大小要求更匹配的子网。与图 18-6 网络分割成八个传统子网。在传统子网划分中,所有子网必须具有相同的大小,当某些子网比其他子网大得多时,这会引发问题。与图 18-7 进行比较。")。

小贴士

关键概念 可变长度子网掩码(VLSM) 是一种技术,通过迭代多次进行子网划分,允许网络被划分为大小不同的子网层次结构。这使得组织能够更好地匹配其子网的大小以满足其网络的需求。

使用 VLSM 进行多级子网划分

VLSM 子网划分与常规子网划分的方式相同;它只是涉及额外的子网划分层次级别。要实现它,您首先将网络划分为大型子网,然后根据需要进一步分解一个或多个子网。您为每个次子网和次次子网添加位到子网掩码,以反映它们较小的尺寸。

在 VLSM 中,通常使用无类别地址的斜线表示法而不是二进制子网掩码(它的工作方式非常类似于 CIDR),因此我将使用这种方法。

注意

如果您对子网划分的工作方式感到有些不舒服,在继续进行下面的 VLSM 示例之前,请考虑阅读关于实际子网划分的章节(第十九章)

例如,考虑 C 类网络,201.45.222.0/24。您按照以下方式执行三次子网划分(参见图 18-8 以展示过程)。

VLSM 示例 此图展示了文本中描述的示例,即一个使用三个分层级别划分的 C 类(/24)网络。它首先被划分为两个子网;其中一个子网被划分为两个二级子网;而一个二级子网被划分为四个三级子网。结果显示的六个子网,用粗黑边框表示,最大容量分别为 126、62、14、14、14 和 14 个主机。

图 18-8. VLSM 示例 此图展示了文本中描述的示例,即一个使用三个分层级别划分的 C 类(/24)网络。它首先被划分为两个子网;其中一个子网被划分为两个二级子网;而一个二级子网被划分为四个三级子网。结果显示的六个子网,用粗黑边框表示,最大容量分别为 126、62、14、14、14 和 14 个主机。

  • 您首先使用一个位作为子网 ID 进行初始子网划分,留下七个位用于主机 ID 和两个子网:201.45.222.0/25 和 201.45.222.128/25。每个子网最多可以容纳 126 个主机。您将这些中的第一个留作子网 S6 及其 100 个主机。

  • 您选择第二个子网,201.45.222.128/25,并从主机 ID 中剩余的七个位中取出一个位,这为您提供了两个二级子网:201.45.222.128/26 和 201.45.222.192/26,每个子网可以容纳 62 个主机。您将这些中的第一个留作子网 S5 及其 50 个主机。

  • 您选择第二个二级子网,201.45.222.192/26,并将其进一步划分为四个三级子网。您从主机 ID 中剩余的六个位中取出两个位,这为您提供了四个三级子网,每个子网最多可以容纳 14 个主机。这些用于 S1、S2、S3 和 S4。

虽然我选择了这些数字以确保它们完美匹配,但您应该已经明白了。VLSM 大大提高了子网划分的灵活性和效率。

注意

为了使用 VLSM,必须使用支持 VLSM 路由协议的路由器。VLSM 还要求在构建路由表时更加小心,以确保对网络中地址的解释没有歧义

如我之前所述,VLSM(可变长度子网掩码)在概念上与 CIDR(无类别域间路由)的执行方式相似。VLSM 与 CIDR 之间的主要区别在于关注的焦点不同。VLSM 处理的是私有组织内单个网络的子网。CIDR 将你在 VLSM 中看到的理念扩展到整个互联网,通过改变组织网络的分配方式,用多层层次结构取代了单层类别的层次结构。

第十九章。IP 子网划分 实践子网设计和地址确定示例

无标题图片

当教育工作者询问学生他们认为在了解网络时最令人困惑的方面是什么时,许多人说那是 IP 地址子网划分。虽然子网划分在概念上并不那么困难,但它可能会让人感到有些令人困惑,部分原因是因为需要操作二进制数。许多人理解子网划分背后的理念,但发现难以跟随实际的网络子网划分步骤。

因此,尽管我在上一章详细解释了子网划分的概念,但我认为再有一个提供逐步查看如何执行自定义子网划分的章节将非常有价值。本章将子网划分分为五个相对简单的阶段,包括确定需求;决定用于子网 ID 和主机 ID 的位数;然后确定诸如子网掩码、子网地址和主机地址等重要数字。

我在这里的重点是展示子网划分的实用“如何做”。这些主题通过使用 B 类和 C 类示例网络进行两个示例来说明子网划分是如何进行的,并且我在展示如何计算一切时是明确的。这意味着本节数字较多。此外,我尽量不重复前节中涵盖的概念问题,尽管确实存在一定程度的重叠。总的来说,如果你对子网划分的工作方式完全不熟悉,你将首先想要阅读上一章。我在适当的地方引用了那一章的内容,特别是总结表。顺便说一下,我只在这里介绍传统的子网划分,而不是可变长度子网掩码(VLSM)。

本节可能对已经熟悉基础知识但只想回顾子网划分步骤的人来说是一个有用的复习或总结。再次提醒,子网划分基于较旧的类别 IP 地址方案,而今天的互联网是无类别的,使用无类别域间路由(CIDR;见第二十章)。

注意

如果在阅读本章时,你发现自己想要进行二进制到十进制的转换或二进制数学运算,请记住,大多数版本的 Windows(以及许多其他操作系统)都有一个包含科学功能的计算器程序

IP 子网划分步骤 1:分析需求

当你作为一个整体构建或升级网络时,第一步不是购买硬件,也不是确定协议,甚至不是设计。而是需求分析,即确定网络需要做什么的过程。没有这个基础,你可能会实施一个与你的设计完美匹配的网络,但无法满足你组织的需求。同样的规则也适用于子网划分。在你查看主机地址和子网掩码的详细信息之前,你必须决定如何划分网络。为了做到这一点,你必须了解网络的需求。

分析网络划分的需求并不困难,因为只有几个问题需要考虑。由于需求分析通常是通过提问来完成的,以下是在分析子网划分需求时最重要的问题列表:

  • IP 地址块属于哪一类?

  • 现在网络上有多少物理子网络?(一个物理子网络通常指的是 LAN 上的广播域——由路由器界定的物理网络上的主机集合。)

  • 你预计在不久的将来会添加任何更多的物理网络吗?如果是这样,那么会有多少?

  • 你现在最大的子网络中有多少主机?

  • 你预计在不久的将来最大的子网络中会有多少主机?

小贴士

关键概念 要成功划分网络,你必须首先了解网络的需求。最重要的参数是确定所需的子网数量和每个子网络所需的最大主机数。数字不应仅基于当前需求,还应考虑近期预期的需求。

第一个问题很重要,因为子网划分中的所有内容都是围绕划分 A 类、B 类或 C 类网络进行的,所以你需要知道你正在处理哪一类。如果你正在从头开始设计网络,还没有 A 类、B 类或 C 类块,那么你将根据组织的近似规模来确定你需要哪一类。

之后,你需要确定两个关键数字:你有多少物理子网络,以及每个子网络的最大主机数。你需要了解这些数字不仅是为了现在的网络,也是为了近期未来。这两个数字的当前值代表了网络今天应该如何设计。然而,只为现在设计并不是一个好主意。

假设你现在网络中恰好有四个子网络。从理论上讲,你只需要两个比特位来表示子网 ID,因为 2 的平方等于 4。然而,如果公司正在快速发展,这将是一个糟糕的选择。当你需要添加第五个子网络时,你会遇到问题!

类似地,考虑子网中主机数量的增长。如果当前最大的子网有 60 个主机,你不想为主机 ID 分配六个比特位,因为这会限制你只能有 62 个主机。你可以将大型子网划分为更小的子网,但这可能只是意味着不必要的额外工作。

那么,“近期”是什么意思呢?这个术语必然是模糊的,因为它取决于组织想要展望多远的未来。一方面,如果你有足够的 IP 地址,规划几年的增长是有意义的。另一方面,你不想规划得太远,因为短期内可能的变化可能会让你不得不完全重新设计你的网络。

IP 子网划分步骤 2:划分网络地址主机位

在完成简短的需求分析后,你应该知道你必须有两个关键参数才能对网络进行子网划分:网络所需的子网数量和每个子网的最大主机数量。在使用这些数字来设计子网化网络时,你将面临子网划分的关键设计决策:如何将类地址的主机 ID 中的 8、16 或 24 比特位划分为子网 ID 和主机 ID。

换句话说,你需要决定从主机 ID 中窃取多少比特位用于子网 ID。正如我在上一章关于自定义子网掩码的部分所解释的,选择这个数字的基本权衡如下:

  • 从主机 ID 中为子网 ID 取出的每个比特位将网络中可能的子网数量翻倍。

  • 从主机 ID 中为子网 ID 取出的每个比特位(大约)将网络中每个子网可能的主机数量减半。

对于 C 类网络,有六种可能的决策方式,如图 19-1 所示。图 19-1

C 类网络的子网设计权衡图。这幅图显示了 C 类网络子网化的选项。随着主机 ID 比特位的增加,子网的数量增加,但每个子网的大小减少。

图 19-1. C 类网络的子网设计权衡图。这幅图显示了 C 类网络子网化的选项。随着主机 ID 比特位的增加,子网的数量增加,但每个子网的大小减少。

比特位与子网数量和主机数量的关系如下:

  • 网络中允许的子网数量是子网 ID 比特位数量的 2 的幂。

  • 每个子网允许的主机数量是主机 ID 比特位数量的 2 的幂,减去 2。

你需要从每个子网的主机数中减去两个,以排除主机 ID 全零或全一的具有特殊意义的案例。正如我在上一章中解释的,这种排除最初也应用于子网 ID,但在较新的系统中不再如此。

要选择用于子网的位数,你可以使用试错法。我的意思是,你可以先尝试使用一个位作为子网 ID,其余位留给主机 ID 来计算子网和主机的数量。然后你可以尝试使用两个位作为子网 ID,接着是三个位,以此类推。然而,这样做会很愚蠢;它既耗时又难以让你选择最佳选项。有一个更简单的方法:你可以使用上一章中介绍的子网划分总结表。它们让你可以看到所有选项,你通常可以立即看到最适合你的选项。

C 类子网划分设计示例

让我们举一个例子。假设你有一个 C 类网络,基本地址为 211.77.20.0,总共需要七个子网。每个子网的最大主机数是 25。查看 C 类子网划分总结表(第十八章中的表 18-5),答案立刻清晰:你需要三个位用于子网 ID。为什么?这允许你拥有八个子网,每个子网有 30 个主机。如果你尝试选择两个位,你无法定义足够多的子网(只有四个)。正如图 19-2 所示,如果你选择四个位作为子网 ID,那么每个子网就只能有 14 个主机。

C 类子网划分示例

图 19-2. C 类子网划分示例 在这个特定的例子中,需要七个子网,最大的子网需要 25 个主机,只有一个子网 ID 大小的选择符合要求。这是一个简单的决定!

B 类子网划分设计示例

在某些情况下,尤其是对于较大的网络,你可能有多重选择。以一个更有趣的例子来说明,更大的 B 类网络 166.113.0.0,其中总共有 15 个子网,最大的子网有 450 个主机。查看 B 类网络的子网汇总表(表 18-4,位于第十八章)表明有四种可接受的选择,如图图 19-3

图 19-3. B 类子网划分示例 这个 B 类网络至少需要 15 个子网,并且必须允许每个子网最多 450 个主机。三个子网 ID 位太少,而八个位意味着每个子网只有 254 个主机,这不够。这留下了四个可接受的选择,所以你必须明智地选择。

小贴士

关键概念 如果有多个子网 ID 和主机 ID 大小的组合可以满足要求,尽量选择一个折中的选项,以最好地预测未来的增长需求。如果没有组合满足要求,则必须更改要求!

IP 子网划分步骤 3:确定自定义子网掩码

一旦你决定了用于子网 ID 的位数以及用于主机 ID 的位数,你就可以确定网络的自定义子网掩码。现在,不要因为我而躲起来。很多人一提到子网掩码就会眼花缭乱,但一旦你完成了在第 2 步中做出的设计决策的作业,它实际上是非常简单的。事实上,有两种方法来做这件事;一种比另一种工作量小,但它们都很简单。我本来想称它们为“难方法”和“易方法”,但相反,我将称它们为“简单”和“更简单”。

计算自定义子网掩码

让我们从简单方法开始,即根据你已有的关于网络的信息,以二进制形式计算子网掩码,然后将掩码转换为十进制。为了刷新你的记忆并指导这个过程,请记住这一点:子网掩码是一个 32 位的二进制数,其中一位代表网络 ID 或子网 ID 的一部分,而零代表主机 ID 的一部分。

C 类自定义子网掩码计算示例

参考上一节中的 C 类示例(图 19-2):

  1. 确定默认子网掩码 对于 B 类,子网掩码是 255.255.0.0。在二进制中,它是这样的:

    11111111 11111111 00000000 00000000
  2. 将最左边的零位转换为子网位的一 如果你使用五个位作为子网 ID,你将五个最左边的零位从 0 转换为 1,如粗体所示,以得到二进制自定义子网掩码,如下所示:

    11111111 11111111 11111000 00000000

    确定 C 类网络的自定义子网掩码

    图 19-4. 确定 C 类网络的自定义子网掩码

  3. 将子网掩码转换为点分十进制表示 你将子网掩码中的每个八位字节转换为十进制,以得到 255.255.248.0 的自定义子网掩码。

  4. 以斜杠表示法表达子网掩码 你可以将子网掩码 255.255.248.0 表示为/21,因为它有 21 个 1 后面跟着 11 个 0。换句话说,它的前缀长度是 21。

确定 B 类网络的自定义子网掩码

图 19-5. 确定 B 类网络的自定义子网掩码

使用子网划分表确定自定义子网掩码

现在,还有什么比这更容易的吗?嗯,你可以简单地参考第十八章中提供的子网划分摘要表第十八章。找到适合的类别的表格,然后找到你在上一步中选择的行,该行与你想使用的子网 ID 位数相匹配。你可以在那里看到匹配的子网掩码。

(嘿,知道如何自己做到这一点是很好的!你可能并不总是有表格可以参考!)

IP 子网划分步骤 4:确定子网标识符和子网地址

分配给网络的网络 ID 适用于整个网络。这包括所有子网以及所有子网中的所有主机。然而,每个子网都需要一个唯一的子网标识符子网 ID,以便可以将其与网络中的其他子网区分开来。这就是你在子网划分中从主机 ID 位中提取的子网 ID 位的目的。在你识别了每个子网之后,你需要确定每个子网的地址,以便可以在分配主机特定 IP 地址时使用。

这是子网划分中的一个步骤,实际上并不难理解或执行。理解如何确定子网 ID 和子网地址的关键是始终以二进制形式工作,然后稍后转换为十进制。你还将查看一个直接确定十进制地址的捷径,这更快,但概念上不太简单。

注意

我假设在这个描述中,你将使用全零和全一的子网号。在原始 RFC 950 子网划分系统中,这两个子网没有被使用,这改变了以下大多数计算。参见第十八章以获取解释

你从 0 开始编号子网,然后是 1,2,3,依此类推,直到你需要的高个子网 ID。你确定子网 ID 和地址如下:

子网 ID 这只是子网号,它可以以二进制或十进制形式表示。

子网地址 这是通过将整个网络的地址替换为(二进制)子网 ID 来形成的地址。你需要以二进制形式这样做,但只针对有子网 ID 位的八位字节;那些只有网络 ID 位或只有主机 ID 位的字节保持不变。

看起来很复杂?让我们回到例子,你会发现这实际上并不复杂。

C 类子网 ID 和地址确定示例

你会记得 C 类示例网络,211.77.20.0。该网络的二进制地址如下:

11010011 01001101 00010100 00000000

你使用三个位作为子网 ID 进行子网划分,剩下五位用于主机 ID。现在让我们看看带有粗体子网位的网络地址:

11010011 01001101 00010100 00000000

这些是你可以用子网 ID 替换的位。注意,由于前三个八位字节包含网络 ID 位,并且每个子网的网络 ID 都是相同的,所以它们永远不会改变。尽管如此,你实际上并不需要查看它们的二进制形式,但为了清晰起见,你将在这里这样做。

这就是确定子网 ID 和地址的方法,再次强调,从 0 开始(见图 19-6)):

子网 0 这个子网的子网 ID 是 0,或二进制的 000。要找到地址,你从二进制的网络地址开始,用 000 替换子网 ID 位。哎呀,这些位已经都是零了!这意味着子网 0 的地址与整个网络的地址相同:211.77.20.0。这始终是这种情况:子网 0 始终与网络的地址相同。

子网 1 这个子网的子网 ID 是十进制的 1 或二进制的 001。要找到地址,你需要用 001 替换子网 ID 位,得到以下结果:

11010011 01001101 00010100 00100000
转换为十进制,得到 211.77.20.32。

子网 2 这个子网的子网 ID 是 2,或二进制的 010。要找到它的地址,你需要用 010 替换子网 ID 位,得到以下结果:

11010011 01001101 00010100 01000000
这在二进制中是 211.77.20.64。

子网 3 这个子网的子网 ID 是 011。正如你所看到的,地址的前三个八位组总是 211.77.20。这里的最后一个八位组是01100000,在十进制中是 96,所以整个地址是 211.77.20.96。

你开始看到模式了吗?是的,任何子网的地址都可以通过将前一个子网的最后一个八位组加 32 来找到。这个模式适用于所有子网划分选择;增量取决于你为子网 ID 使用的位数。在这里,增量是 32,即 2⁵;5 是在你取了三个子网 ID 位之后剩下的主机 ID 位的数量。

子网 4 这个子网的子网 ID 是 100。它的地址是 211.77.20.128。

子网 5 这个子网的子网 ID 是 101。它的地址是 211.77.20.160。

子网 6 这个子网的子网 ID 是 110。它的地址是 211.77.20.192。

子网 7 这个子网的子网 ID 是 111。它的地址是 211.77.20.224。

确定 C 类网络的子网地址 此图显示了在 C 类网络中使用三个位作为子网 ID 时创建的八个可能的子网。二进制的子网 ID 简单地替换了子网位,得到的 32 位数字被转换为点分十进制形式。

图 19-6. 确定 C 类网络的子网地址 此图显示了在 C 类网络中使用三个位作为子网 ID 时创建的八个可能的子网。二进制的子网 ID 简单地替换了子网位,得到的 32 位数字被转换为点分十进制形式。

提示

关键概念 在子网化网络中,子网地址总是以数值均匀分布,间隔取决于子网 ID 位的数量。

这个例子只需要七个子网,从 0 到 6。子网 7 将是备用。注意,最后一个子网与网络的子网掩码具有相同的最后一个八位字节?这是因为我在子网掩码计算中用 111 替换了子网 ID 位。

B 类子网 ID 和地址确定示例

让我们看看另一个例子,B 类网络 166.113.0.0。在二进制中,它如下所示:

0100110 01110001 00000000 00000000

你正在使用五个位作为子网 ID,剩下 11 个主机 ID 位。具有突出显示的子网 ID 位的网络地址如下:

0100110 01110001 00000000 00000000

在这里,只有第三个八位字节会因不同的子网而改变。前两个始终是 166.113,最后一个八位字节始终是 0。共有 32 个可能的子网;我将列出前几个,以便你可以看到模式(参见图 19-7):

子网 0 这具有子网 ID 00000。这意味着地址将是 166.113.0.0,正如你所期望的那样,这是网络地址。

子网 1 这具有子网 ID 00001。地址变为

10100110 01110001 00001000 00000000
这是以十进制表示的 116.113.8.0。

子网 2 这具有子网 ID 00010,地址为 116.113.00010000.0 或 116.113.16.0。

子网 3 这具有子网 ID 00011 和子网地址 116.113.24.0。

确定 B 类网络的子网地址 这与相同,但针对具有五个子网 ID 位的 B 类网络(出于明显的原因,我没有显示所有 32 个子网)

图 19-7。确定 B 类网络的子网地址 这与图 19-6 相同,但针对具有五个子网 ID 位的 B 类网络(出于明显的原因,我没有显示所有 32 个子网)。

再次,这里的模式很明显:你将第三个八位字节加八以获得连续的地址。这里的最后一个子网是 31,其子网地址为 116.113.248.0,其第三个和第四个八位字节与子网掩码 255.255.248.0 相同。

使用子网地址公式计算子网地址

由于子网地址形成一种模式,而这种模式取决于子网 ID 位的数量,因此可以使用单个公式来表示每个子网选项的子网地址。我在第十八章的子网划分总结表中展示了 A、B 和 C 类每个类的公式。这些公式可以直接计算子网N的地址,其中N从 0 开始编号,直到少于总子网数,正如我之前所做的那样。

在这些公式中,网络 ID 位以 x.、x.y.或 x.y.z.的形式表示三个类别。这仅仅意味着子网地址具有与网络地址中相应八位相同的数字。在示例中,x.y 对于 B 类网络将是 166.113,而 x.y.z 对于 C 类网络将是 211.77.20。

当子网位数为大于八位时,一些八位的形式是N除以一个整数,例如N/8。这是一个整数除法,意味着将N除以 8,保留整数部分,并丢弃小数部分或余数。其他八位基于N的模数计算,表示为N%8。这是完全相反的:这意味着将N除以 8,丢弃整数,并保留余数。例如,在整数数学中 33/5 是 6(6 余 3,丢弃余数,或者换句话说,6.6,丢弃小数),而 33%5 是 3(6 余 3,丢弃 6,保留余数)。

在具有三个子网 ID 位的 C 类网络中,表中的公式是 x.y.z.N**32. 对于这个网络,所有子网都采用 211.77.20.N32 的形式,其中N从零到七。因此,子网 5 是 211.77.20.(532),即 211.77.20.160,正如你之前看到的。同样,在具有五个子网 ID 位的 B 类网络中,公式是 x.y.N8.0. 在这种情况下,x.y 是 166.113. 子网 26 将具有地址 166.113.(26*8).0,或者 166.113.208.0。

这相当简单,这使得公式成为快速确定子网地址的好方法,尤其是在有多个子网的情况下。它们也可以用在电子表格中。

使用公式时唯一需要小心的地方是当子网位数为九位或更多时。这意味着子网标识符跨越了八位边界,这导致公式变得更加复杂。

当子网位数为八位或更少时,公式相对简单,只需计算一个八位,例如N**4 或N**32 的乘法。这通常是这种情况,因为子网的数量通常少于 256,这两个示例都是这种情况。

让我们以 B 类网络为例,假设出于某种奇怪的原因,你决定使用 10 位作为子网 ID 而不是 5 位。在这种情况下,公式是 x.y.N/4.(N%4)64。在这种情况下,子网 23 的地址将是 166.113.23/4.(23%4)64。23 除以 4 等于 5(小数点后的.75 被省略)。23 模 4 等于 3,乘以 64 得到 192。因此,子网地址是 166.113.5.192。子网 709 将是 116.113.709/4.(709%4)*64,即 116.113.177.64。

好吧,现在让我们进入真正的乐趣!如果你使用超过 16 位用于子网 ID 的 Class A 地址进行子网划分,你将跨越两个八位字节边界,公式变得非常……有趣,涉及到整数除法和模数。假设你负责 Class A 地址 21.0.0.0,并决定对其进行子网划分。然而,你在办公室的节日派对上喝了几杯烈酒之后才开始做这件事,所以你的判断有点受损。你决定选择 21 位作为子网 ID 是一个很好的主意,因为你喜欢数字 21。这给你带来了几百万个子网。

在这种情况下,子网地址的公式相当长且复杂:x.N/8192.(N/32)%256.(N%32)8。哎呀。这有点复杂——复杂到可能更容易直接取一个子网号,用二进制的方式来做。但让我们用一个例子来看看它对子网 987654 是如何工作的。第一个八位字节是 21。第二个八位字节是 987654/8192,整数除法。这是 120。第三个八位字节是(987654/32)%256。除法的结果是 30864(省略小数部分)。然后你取 30864%256,得到余数 144。第四个八位字节是(987654%32)8。这是 6*8 或 48。因此,子网地址 987654 是 21.120.144.48。

(不要酒后驾车。也不要酒后子网划分。)

IP 子网划分步骤 5:确定每个子网的主机地址

一旦你知道了网络中每个子网地址,你就可以将这些地址作为分配给每个子网中各个主机 IP 地址的基础。你首先将每个物理网络与一个子网基本地址关联起来(因为至少在理论上,子网对应于物理网络)。然后,你按顺序在子网内为各个主机分配特定的 IP 地址(或者如果你愿意的话,用不同的方式!)。

一旦你知道了子网地址,确定主机地址实际上非常简单。你所做的就是用数字 1、2、3 等替换子网地址中的主机 ID 位。你必须用二进制来做这件事,然后转换成十进制形式。再次提醒,一旦出现了如何分配地址的相当明显的模式,你就可以采取一些捷径。你将在本章的末尾看到这些。

C 类主机地址确定示例

让我们再次从 Class C 示例开始,211.77.20.0,你使用三个子网位将其划分为八个子网。以下是带有子网位(粗体)和主机 ID 位(斜体)显示的地址:

11010011 01001101 00010100 00000000

第一个子网是子网 0,这些子网位全部为零,因此与整个网络的地址相同:211.77.20.0。你用 1、2、3 等数字替换斜体位以获得主机 ID。记住,这里你不从零开始,因为对于主机 ID,全零和全一的二进制模式有特殊含义。所以它如下所示:

第一个主机地址的主机 ID 为 1,或者二进制表示为 00001。因此,它如下所示:

11010011 01001101 00010100 00000001

在十进制中,这是 211.77.20.1。

第二个主机地址的主机 ID 为 2,或者二进制表示为 00010。它的二进制值如下所示:

11010011 01001101 00010100 00000010

在十进制中,这是 211.77.20.2。

我相信你已经明白了;第三个主机将是 211.77.20.3,第四个是 211.77.20.4,以此类推。每个子网最多有 30 个主机,正如你之前看到的。因此,这个子网的最后一个主机将通过将 30(二进制中的 11110)替换为主机 ID 位来找到,结果是一个十进制地址 211.77.20.30。

你可以为其他每个子网做同样的事情;唯一改变的是子网 ID 位中的值。以子网 6 为例。它的子网位是 110,而不是 000。因此,它的子网基本地址是 211.77.20.192,或者

11010011 01001101 00010100 11000000

你可以通过替换主机 ID 位中的 00001、然后 00010、然后 00011 来分配主机到这个子网,如前所述。让我们逐个考虑主机:

第一个主机地址如下所示:

11010011 01001101 00010100 11000001

或者 211.77.20.193。

第二个主机地址是

11010011 01001101 00010100 11000010

或者 211.77.20.194。

以此类推,直到子网的最后一个主机,即 211.77.20.222。图 19-8 显示了如何计算此示例网络的子网和主机地址。

你可能还想计算的是子网的广播地址。这是一个特殊情况,如第十八章第十八章中讨论的那样,通过将所有位替换为主机 ID 来找到。对于子网 0,这将是在 211.77.20.31。对于子网 6,它将是 211.77.20.223。这就是全部内容。

确定 C 类网络的宿主地址 此图展示了通过两步过程确定子网地址和宿主地址的方法。子网地址是通过将子网 ID 值(粗体显示)替换网络子网 ID 位来找到的。然后,对于任何给定的子网地址,你可以通过在该子网内将一个宿主号(粗体和斜体显示)替换宿主 ID 位来确定一个宿主地址。例如,子网 6 中的宿主 2 具有 110 作为子网 ID 和 00010 作为宿主 ID,最终八位字节值为 11000010,或 194。

图 19-8. 确定 C 类网络的宿主地址 此图展示了通过两步过程确定子网地址和宿主地址的方法。子网地址是通过将子网 ID 值(粗体显示)替换网络子网 ID 位来找到的。然后,对于任何给定的子网地址,你可以通过在该子网内将一个宿主号(粗体和斜体显示)替换宿主 ID 位来确定一个宿主地址。例如,子网 6 中的宿主 2 具有 110 作为子网 ID 和 00010 作为宿主 ID,最终八位字节值为 11000010,或 194。

B 类宿主地址确定示例

你当然也可以为 B 类网络做同样的事情。该网络的地址是 166.113.0.0。现在假设你想定义要放入子网 13 的宿主。你将 13 的二进制(01101)替换为子网 ID 位,得到以下子网地址,子网 ID 位用粗体显示,宿主 ID 位用斜体显示:

10100110 01110001 01101000 00000000

这是子网地址 166.113.104.0。现在你有 11 位宿主 ID,所以你可以有最多 2046 个宿主。第一个是通过将 000 00000001 替换为宿主 ID 位来找到的,这给出了地址 166.113.104.1。第二个宿主是 166.113.104.2,以此类推。最后一个是通过将 111 11111110 替换,这给出了地址 166.113.111.254。注意,由于宿主 ID 位跨越了两个八位字节,当你增加宿主 ID 时,两个八位字节都会改变,这与 C 类示例不同。广播地址是 166.113.111.255。

小贴士

关键概念 在子网化网络中,子网号S内宿主 H 的地址是通过将S的二进制值插入网络的子网 ID 位,将H的二进制值插入子网的宿主 ID 位来找到的。

计算宿主地址的快捷方式

如你所见,定义主机 ID 实际上非常直接。如果你能替换位并转换为十进制,你就知道所有你需要知道的信息了。你还可以看到,正如定义子网地址的情况一样,在定义主机 ID 和理解它们如何工作方面,你可以使用一些模式。这些通常定义了你可以通过直接在十进制中工作而不是烦恼二进制替换来更快地确定某些主机地址的方法。这个概念上稍微复杂一些,所以只有当你感到有点勇敢时才继续。

在确定子网环境中的主机 IP 地址时,你可以使用以下一些快捷方式:

第一个主机地址 第一个主机地址总是子网地址,最后八位加 1。所以在 C 类示例中,子网 3 的基本地址是 211.77.20.96。因此,子网 3 的第一个主机地址是 211.77.20.97。

后续主机地址 找到第一个主机地址后,要获取下一个地址,你只需将前一个地址的最后八位加 1。如果这使得最后八位为 256(这只有在有超过八位的主机 ID 位时才会发生),你“回绕”到零并增加第三八位。

直接计算主机地址 如果主机 ID 的位数是八位或更少,你可以通过将 N 加到最后八位的十进制值来找到主机N的地址。例如,在 C 类示例中,子网 3 的基本地址是 211.77.20.96。因此,这个子网中的主机 23 的地址是 211.77.20.119。如果有超过八位的主机 ID 位,这仅适用于前 255 个主机,之后你需要回绕并增加第三八位的值。再次考虑 B 类示例中的子网 13,其基本地址为 166.113.104.0。这个子网上的主机 214 的地址是 166.113.104.0,但主机 314 不是 166.113.104.314。它是 166.113.105.58(主机 255 是 166.113.104.255,然后主机 256 是 166.113.105.0,你再数 58 个(314-256)以得到 314,166.113.105.58)。

主机地址范围 对于任何子网的主机范围,第一个地址是子网的基本地址,最后八位加 1。最后一个地址是此子网之后下一个子网的基本地址,最后八位减 2(这可能需要将最后八位中的 0 改为 254,并将第三八位的值减少 1)。例如,考虑 B 类示例中的子网 17。其子网地址是 166.113.136.0。子网 18 的地址是 166.113.144.0。因此,子网 17 的主机地址范围是 166.113.136.1 到 166.113.143.254。

广播地址 子网的广播地址总是比下一个子网的基本地址少 1。或者,也可以说是比子网的最后一个实际主机地址多 1。所以在 B 类示例中的子网 17,广播地址是 166.113.143.255。

我是不是让你困惑了?好吧,记住这些只是捷径,有时当你走捷径时,你可能会迷失方向。开个玩笑;一旦你玩得多了,其实并不难。

在结束之前,当在子网环境中处理 IP 地址时,请记住以下快速总结:

  • 网络 ID 对于所有子网中的所有主机以及网络中的所有子网都是相同的。

  • 子网 ID 对于每个子网中的所有主机都是相同的,但在网络中每个子网是唯一的。

  • 主机 ID 在每个子网内是唯一的。每个子网都有相同的主机 ID 集合。

  • 子网编址很有趣!(好吧,好吧,对不起……)

第二十章。IP 无类编址—无类域间路由(CIDR)/超网

无标题图片

随着互联网的急剧增长,在前面章节中描述的原有按类编址方案出现了三个主要问题。这些问题部分通过子网编址得到解决,这为互联网上各个网络的管理员提供了更多的灵活性。然而,子网编址并没有真正从一般意义上解决这些问题。由于使用了类别,一些问题仍然存在。

虽然在 20 世纪 90 年代中期开始开发互联网协议(IPv6;参见第二部分-4)及其宽敞的 128 位编址系统,但开发者认识到,在 IPv6 得到广泛部署之前还需要许多年。为了在新的版本完成之前延长 IPv4 的生命周期,有必要采取一种新的方法来编址 IPv4 设备。这个新系统要求完全消除地址类别的概念,创建一个新的无类编址方案,有时称为无类域间路由(CIDR)

在本章中,我描述了现代的无类 IP 编址。我首先概述了无类编址背后的概念和超网背后的想法,包括为什么它被创建以及它的优缺点。然后我定义了 CIDR,并更详细地描述了该系统的工作原理,包括用于地址块的符号。我列出了每个 CIDR 地址块的大小,并展示了它们如何与较老的 A 类、B 类和 C 类网络相关联。最后,我给出了一个 CIDR 编址示例,它与第十九章中的示例类似,但这个示例专注于 CIDR,并且更加简洁。

无类 IP 编址和超网概述

子网地址划分是 IP 地址划分演变过程中的一个重要发展,因为它解决了传统两级基于类别的地址方案的一些重要问题。子网划分对 IP 地址划分灵活性的贡献是允许每个网络拥有自己的两级层次结构,从而为每个网络管理员提供了相当于互联网内部的互联网。

当你在第十八章中看到子网划分的优势时,你会发现子网划分在每个组织内部是局部的,对其他组织来说是不可见的。这是一个优势,因为它允许每个组织根据需要定制其网络,而无需其他团体担心如何操作的细节。不幸的是,这种不可见性也代表了子网化类地址划分的一个关键缺点:它不能纠正与那种类型地址划分相关的根本低效,因为组织仍然根据类别分配地址块。

类地址划分的主要问题

子网划分系统的关键弱点是其粒度低。一个 B 类地址块包含一个非常大的地址数量(65,534),但一个 C 类地址块只有相对较小的数量(254)。有成千上万的组织中等的组织需要超过 254 个 IP 地址,但其中只有一小部分需要 65,534 个或任何接近这个数量的地址。(图 17-5 说明了在第十七章中中等规模组织与 5,000 个主机匹配不良的问题。)当这些公司和团体设置他们的网络时,他们往往会请求 B 类地址块而不是 C 类地址块,因为他们需要超过 254 个主机,而不考虑他们实际上会使用 65,000 多个地址中的多少。

由于旧系统中的类别设计方式,有超过两百万个 C 类地址块,但只有 16,384 个 B 类网络。乍一看,16,384 似乎很多,但世界上有成千上万的组织和公司。B 类分配正在迅速消耗,而较小的 C 类网络相对未被使用。

分配互联网地址的人们需要一种更好的方式来利用地址空间,以便在过渡到 IPv6 之前不会耗尽。子网划分在这方面并没有太大的帮助。为什么?因为它只适用于类别地址块内部。如果一个需要 2,000 个 IP 地址的组织请求一个 B 类块,他们可以使用子网划分来更有效地管理他们的块。然而,子网划分对这样一个事实无能为力:这个组织永远不会使用其块中超过 62,000 个地址——大约 97%的分配地址空间。

解决这个问题的唯一方法就是说服——在最坏的情况下,强迫——公司使用许多较小的 C 类块而不是浪费 B 类分配的大部分。许多组织由于涉及到的复杂性而抵制这种做法,这导致了另一个主要问题,即子网划分没有解决的问题:互联网路由表的增长。用一个 B 类网络替换 10 个 C 类网络意味着路由器需要维护的条目数量增加了十倍。

解决方案:消除地址类别

很明显,只要网络只有三种大小,分配效率问题就永远无法得到妥善解决。解决方案是完全取消类别,转而采用无类别分配方案。这个系统将解决类别地址的主要两个问题:地址空间使用效率低下和路由表指数级增长。

这个系统是在 20 世纪 90 年代初开发的,并在 1993 年的 RFC 1517、1518、1519 和 1520 中正式化。这项技术被称为无类别域间路由(CIDR)。尽管这个名字如此,但该方案处理了地址和路由问题,因为它们是密不可分的。

CIDR 背后的想法是将单个网络的子网划分概念应用到整个互联网上。本质上,无类别地址意味着你不需要将特定网络划分为子网,而是可以将网络聚合到更大的“超网”中。正因为如此,CIDR 有时被称为超网划分:它将子网划分的原则应用到更大的网络上。正是这种将网络聚合到超网中的做法,使得 CIDR 能够解决互联网路由表增长的问题。

当然,如果你打算将子网划分的概念应用到整个互联网上,你需要能够拥有不同大小的子网。毕竟,消除类别的一个主要目标就是实现这一点。因此,更准确地说,CIDR 不仅是在整个互联网上应用了一级子网划分,还包括了在第十八章所示。或者换一种方式思考,一个 B 类网络的等效地址可以由需要 8,190 个或更少 IP 地址的八家公司共享。

消除类别不平衡 没有更多 A 类、B 类和 C 类网络,因此不存在某些地址空间部分被广泛使用而其他部分被忽视的问题。

高效的路由条目 CIDR 的多级分层结构允许少量路由条目代表大量网络。网络描述可以被聚合并由单个条目表示。由于 CIDR 是分层的,因此可以隐藏低级别、较小网络的详细信息,这些信息对于在大型网络组之间移动流量的路由器来说是隐藏的。这一点在第二十三章中有更详细的讨论,该章节涵盖了 IP 路由问题。

无需单独的子网划分方法 CIDR 在互联网本身中实现了子网划分的概念。一个组织可以使用在互联网上使用的相同方法将其内部网络划分为任意复杂性的子网,而无需单独的子网划分机制。

无类别编址(CIDR)解决了粒度问题,如图所示类别编址的主要问题:B 类和 C 类网络大小之间的巨大差距。CIDR 通过允许使用任意数量的位来表示网络 ID 来解决此问题。对于一个拥有 5,000 个主机的组织,可以分配一个/19 网络,该网络有 8,190 个主机。这减少了此类组织地址空间的浪费,大约减少了 95%。

图 20-1. 无类地址(CIDR)解决了粒度问题图 17-5 在第十七章中说明了类别地址的主要问题:B 类和 C 类网络大小之间的巨大差距。CIDR 通过允许使用任意数量的位来表示网络 ID 来解决这一问题。对于一个拥有 5,000 个主机的组织,可以分配一个/19 网络,包含 8,190 个主机。这减少了此类组织地址空间的浪费,大约 95%。

由于类别地址的主要优点是其简单性,因此 CIDR 的主要缺点是其复杂性增加也就不足为奇了。一个问题是通过查看第一个八位字节,现在无法确定 IP 地址中有多少位代表网络 ID,有多少位代表主机 ID。在设置路由器时也需要更加小心,以确保正确完成路由。

IP 超网:CIDR 分层地址和表示法

当你第一次在第十七章中查看 IP 地址时,你看到 IP 地址被设计成分为网络标识符(网络 ID)和主机标识符(主机 ID)。然后,当引入子网时,你从主机 ID“偷取”位来创建子网 ID,使 IP 地址具有总共三个层次。使用 VLSM,你进一步对子网进行子网划分,从主机 ID 中取出更多位,从而得到一个多级层次结构,包括子子网、子子子网等等。

在无类环境中,你通过应用 VLSM 概念,不仅针对一个网络,而是针对整个互联网,完全改变了看待 IP 地址的方式。本质上,互联网变成了一个巨大的网络,被划分为多个大型块。其中一些大型块随后被划分为更小的块,这些块又可以进一步划分。这种划分可以多次发生,允许你将互联网地址的“饼”分割成许多不同大小的片,以满足组织的需要。

如其名所示,无类别寻址完全消除了之前的类别概念。不再有 A 类、B 类和 C 类块,它们由地址的前几位来划分。在 CIDR 下,所有互联网块都可以是任意大小。你不必让所有网络都使用 8 位(A 类)、16 位(B 类)或 24 位(C 类)作为网络 ID,你可以有大型网络,例如,使用 13 位作为网络 ID(留下 19 位用于主机 ID),或者非常小的网络,使用 28 位作为网络 ID(只有 4 位用于主机 ID)。网络的大小仍然基于主机 ID 位数的二进制幂。

CIDR(斜线)表示法

你会记得,当你使用子网划分时,你遇到了一个问题:子网划分可以通过取任意数量的可用主机 ID 位来完成,那么设备如何知道子网 ID 和主机 ID 之间的界限在哪里?在 CIDR 下也会出现同样的问题。没有类别,所以通过查看 IP 地址的前几位无法得知任何信息。由于地址的主机 ID 和网络 ID 之间的分隔点可以出现在任何位置,因此你需要额外的信息来正确解释 IP 地址。在 CIDR 下,这不仅影响组织内的地址,还影响整个互联网的地址,因为不存在类别,每个网络都可以是不同的大小。

因此,正如子网划分需要使用子网掩码来显示哪些位属于网络 ID 或子网 ID,哪些位属于主机 ID 一样,CIDR 也使用子网掩码来显示主机 ID 和网络 ID 之间的界限在哪里。然而,为了简化,在 CIDR 下,你通常不使用 32 位的二进制子网掩码。相反,你使用斜线表示法,更准确地称为CIDR 表示法。这种表示法通过在 IP 地址后跟一个整数来显示网络的大小,有时称为前缀长度,这个整数告诉你用于网络 ID(前缀)的位数。

小贴士

关键概念 由于 CIDR 中没有地址类别,你不能仅从地址本身判断网络 ID 的大小。在 CIDR 中,前缀(网络 ID)的长度通过在地址后跟一个斜线来表示。这被称为CIDR 表示法,或斜线表示法

例如,考虑网络规范 184.13.152.0/22。这里的 22 表示这个网络有 22 位用于网络 ID,10 位用于主机 ID。这相当于指定一个地址为 184.13.152.0,子网掩码为 255.255.252.0 的网络,正如你可以在图 20-2 中看到的那样。这个示例网络总共提供了 1,022 个主机(2¹⁰-2)。下一节中的表格显示了在 CIDR 下可以配置的所有不同可能的网络大小。

CIDR(斜杠)表示法及其子网掩码等效图

图 20-2. CIDR(斜杠)表示法及其子网掩码等效图。无类别网络通常在 CIDR 或斜杠表示法中指定,例如这个示例:184.13.152.0/22。这里,/22 表示地址的前 22 位是网络 ID。等效的子网掩码可以通过创建一个 32 位数字,其中前 22 位是 1,后面跟着 10 位是 0 来计算。

注意

你可能还记得,在类别子网划分中,用于子网 ID 的位不需要连续。尽管这种能力几乎从未被用来避免混淆,但非连续的子网 ID 位是可能的。在 CIDR 中,对连续子网 ID 位的要求已经正式化——否则你不能使用斜杠表示法

超网划分:互联网的子网划分

理论上,CIDR 所做的是为中央地址分配权威机构提供灵活性,根据组织的需求分配不同大小的地址块。然而,当 CIDR 被开发时,公共 IP 地址分配的方法发生了变化。让世界上每个人都试图从一个组织获取地址并不是最好的方法。在类别子网划分方案下这是必要的,因为层次结构只有两层深。互联网数字分配机构(IANA)向每个人分配网络 ID,然后他们分配主机 ID(或进行子网划分)。

在 CIDR 下,你有许多分层级别:你将大块分割成小块,然后再将小块分割成更小的块,依此类推。以类似分层的方式管理块是有意义的。所以,实际上,IANA/ICANN 将地址划分为大块,并将其分配给四个区域互联网注册机构(RIRs):APNIC、ARIN、LACNIC 和 RIPE NCC。然后,它们进一步将地址块分割并分配给下一级的国家互联网注册机构(NIRs)、本地互联网注册机构(LIRs)和/或个人组织,例如互联网服务提供商(ISPs)。这一切都在第三章中关于互联网权威机构和注册机构的背景讨论中解释。

然后,ISP 可以将这些块分割成更小的块,并将它们分配给客户。这些客户有时本身就是较小的 ISP,它们会重复这个过程。他们将块分割成不同大小的块,并将它们分配给客户,其中一些客户甚至是更小的 ISP,还有一些是最终用户。这种分割可以发生的次数仅限于原始块中的地址数量。

值得注意的是,尽管 CIDR 基于子网划分的概念,但子网划分本身并不用于 CIDR——至少,不是在类地址方式下使用的那种方式。CIDR 中没有使用子网 ID 进行显式子网划分。所有 IP 地址仅被解释为具有网络 ID 和主机 ID。组织通过使用与 ISP 相同的一般方法将其自己的网络划分为子网,这相当于子网划分。这可能会有些令人困惑。在本章的后面部分,我将提供一个详细的分层地址块分配示例以及 CIDR 下的分割是如何工作的。

类地址和无类地址的共同特点

在“类地址”方案下定义的一些地址方面在 CIDR 下并没有改变:

私有地址块 某些地址块仍然保留用于私有网络地址。这些地址不能直接在互联网上路由,但可以与网络地址转换(NAT;参见第二十八章)结合使用,以允许没有公共地址的 IP 主机访问互联网。

具有特殊含义的地址 某些网络 ID 和主机 ID 模式所赋予的特殊含义与之前相同。这也是为什么你仍然必须从每个网络的主机数中减去两个的原因。这些代表整个网络的全部零地址和用于广播的全一地址。

环回地址 网络 127.0.0.0 仍然保留用于环回功能。(在 CIDR 中,它被表示为 127.0.0.0/8。)

最后,请注意,使用无类地址需要设计用于处理它的硬件和软件。如果硬件和软件仍然假设它们在类环境中运行,它们将无法正确解释地址。由于 CIDR 现在已经存在十多年了,这在现代系统中通常不是问题。

无类地址块大小和类网络等效

由于 CIDR 允许你根据任何位边界将 IP 地址划分为网络 ID 和主机 ID,因此它可以创建数十种不同大小的网络。与子网划分一样,网络的大小是网络 ID 位数和主机 ID 位数之间的权衡。与传统的子网划分不同,在传统的子网划分中,所有子网都做出单一的选择,而 CIDR 允许对互联网进行多级分层划分,因此存在许多不同大小的网络。较大的网络被创建并进一步划分为较小的网络。

由于许多人习惯于根据它们的类大小查看 IP 地址块,因此通常用它们的类等效来表示 CIDR 地址块。首先,在这个阶段,应该很容易看出 CIDR /8 网络的大小与 A 类网络相等,/16 与 B 类网络等效,/24 与 C 类网络等效。这是因为 A 类网络使用 8 位作为网络 ID,B 类网络使用 16 位,C 类网络使用 24 位。然而,请记住,这些 CIDR 等效不需要像类方案那样有特定的第一个八位字节范围。

每次你减少前缀长度,你都在定义一个大约是前一个具有更高数字的网络大小两倍的网络,因为你已经通过增加主机 ID 中的一个位数。因此,/15 网络的大小等于两个/16 网络。

表 20-1 显示了在 CIDR 下将 IP 地址的 32 位划分为网络 ID 和主机 ID 位数的所有可能的理论方法。对于每一种方法,我都展示了每个网络中的主机数量,以及每种大小的网络在斜杠表示法和传统子网掩码中的表示方式。我还展示了每个的 A 类、B 类和 C 类网络的等效数量。

在查看此表时,请记住以下几点:

  • 显示的一些条目比实际更理论化,仅为了完整性而包含。这尤其适用于较大的网络。例如,我怀疑没有人真正使用过/1 或/2 CIDR 网络;前者只有两个,后者有四个,涵盖了整个 IP 地址空间!大多数时候,你将处理较小的网络,/16 以下。

  • 在正常情况下,您不能有/31 或/32 CIDR 网络,因为它将没有有效的主机 ID。(有一个特殊情况:/31 网络可以用于点对点链路,在这种情况下,每个传输的预期接收者很明显,并且不需要广播。这已在 RFC 3021 中描述。)

  • 在显示等效 A、B 和 C 类网络数量的列中,为了简化,我只显示了 1/256 到 256 范围内的数字。显然,/6 网络除了与四个 A 类网络大小相等外,还等于 1,024 个 B 类网络和 262,144 个 C 类网络,但很少有人会费心将/6 网络称为 262,144 个 C 类网络。

表 20-1. CIDR 地址块和类地址等效

网络 ID 位数 主机 ID 位数 每个网络的主机数 斜杠表示法中的前缀长度 等效子网掩码 等效类地址网络数
A 类
--- --- --- --- --- ---
1 31 2,147,483,646 /1 128.0.0.0 128
2 30 1,073,741,822 /2 192.0.0.0 64
3 29 536,870,910 /3 224.0.0.0 32
4 28 268,435,454 /4 240.0.0.0 16
5 27 134,217,726 /5 248.0.0.0 8
6 26 67,108,862 /6 252.0.0.0 4
7 25 33,554,430 /7 254.0.0.0 2
8 24 16,777,214 /8 255.0.0.0 1
9 23 8,388,606 /9 255.128.0.0 1/2
10 22 4,194,302 /10 255.192.0.0 1/4
11 21 2,097,150 /11 255.224.0.0 1/8
12 20 1,048,574 /12 255.240.0.0 1/16
13 19 524,286 /13 255.248.0.0 1/32
14 18 262,142 /14 255.252.0.0 1/64
15 17 131,070 /15 255.254.0.0 1/128
16 16 65,534 /16 255.255.0.0 1/256
17 15 32,766 /17 255.255.128.0
18 14 16,382 /18 255.255.192.0
19 13 8,190 /19 255.255.224.0
20 12 4,094 /20 255.255.240.0
21 11 2,046 /21 255.255.248.0
22 10 1,022 /22 255.255.252.0
23 9 510 /23 255.255.254.0
24 8 254 /24 255.255.255.0
25 7 126 /25 255.255.255.128
26 6 62 /26 255.255.255.192
27 5 30 /27 255.255.255.224
28 4 14 /28 255.255.255.240
29 3 6 /29 255.255.255.248
30 2 2 /30 255.255.255.252

IP CIDR 地址示例

CIDR 的多个分层级别使这项技术看起来相当复杂。然而,如果你已经知道如何进行子网划分,理解 CIDR 的工作原理实际上并不困难。特别是,如果你知道 VLSM 的功能,你基本上已经知道了 CIDR 的工作原理,因为它们基本上是同一件事。它们的不同之处仅在于网络分层划分的实现方式和术语。

为了展示 CIDR 如何更好地工作,让我们举一个例子,这个例子将说明无类别地址的强大功能:它能够选择性地将一个大块地址细分为适合各种组织需求的小块。由于 CIDR 中的地址分配通常从较大的 ISP 拥有的较大块开始,因此我们也从这里开始。

假设你有一个刚刚起步的 ISP。它不是一个主要 ISP,而是一个规模适中的 ISP,只有少数客户,因此它只需要相对较小的分配。它从 71.94.0.0/15 这个块开始。块地址末尾的/15 告诉你,这是一个地址块,其中前 15 位是网络 ID,后 17 位是宿主 ID。这个块是从一个更大的 ISP 那里获得的,由该 ISP 从一个更大的地址块中切割而来。例如,71.94.0.0/15 等于 71.92.0.0/14 地址块的一半,71.88.0.0/13 块的四分之一,等等。

该 ISP 的地址块大小等于两个 B 类网络的大小,总共有 131,070 个可能的宿主地址。这个 ISP 可以选择以各种方式划分这个地址块,这取决于其客户的需求以及其自身的内部使用。然而,这个 ISP 刚刚起步,甚至还不确定其最终需求是什么。假设它预计将大约一半的地址空间转售给其他 ISP,但还不确定他们需要多大的地址空间。在剩下的另一半中,它计划将其分成四种不同大小的块,以适应不同规模组织的需要。

为了想象 ISP 如何划分其地址空间,你可以考虑将一块饼切开的类比。ISP 首先将饼切成两半,保留一半给未来的 ISP 客户。然后,它将另一半切成一些大块和一些小块。这如图图 20-3 所示。(好吧,我知道它是一个方形的饼。我想按比例展示单独的小块。)

实际的划分过程可能遵循以下章节中描述的进展,并在 图 20-4 中展示。

第一层划分

“饼”最初是通过使用单个最左边的宿主 ID 位作为额外的网络位来切成两半的。以下是网络地址块,71.94.0.0/15 的二进制表示,其中最左边的宿主 ID 位以粗体显示:

01000111 01011110 00000000 00000000

/15 CIDR 地址块的分层划分示例 此图展示了 ISP 如何将相对较大的 /15 地址块(131,070 个主机)进行分层划分的一种方法。在这种情况下,它首先被分成两个 /16 块。其中一个被保留,而另一个被分成四个 /18 块。这些块被进一步划分为不同大小的块,以便分配给需要 62、126、254 或 510 个主机的组织。

图 20-3. /15 CIDR 地址块的分层划分示例 此图展示了 ISP 如何将相对较大的 /15 地址块(131,070 个主机)进行分层划分的一种方法。在这种情况下,它首先被分成两个 /16 块。其中一个被保留,而另一个被分成四个 /18 块。这些块被进一步划分为不同大小的块,以便分配给需要 62、126、254 或 510 个主机的组织。

要进行划分,你将一个网络设置为具有高亮显示的位保持为零的该二进制网络地址,另一个网络则将其改为一位。这创建了两个子网络——不是在类 B 意义上的子网,而是原始网络的部分——我根据将替代新网络 ID 位的数值进行编号,如下所示:

子网络 0: 01000111 01011110 00000000 00000000
子网络 1: 01000111 01011111 00000000 00000000

因为第 16 位现在也是网络地址的一部分,这些是 /16 网络,相当于一个类 B 网络的大小。因此,子网络如下:

子网络 0: 71.94.0.0/16
子网络 1: 71.95.0.0/16

你会注意到子网络 0 与它所来自的较大网络的 IP 地址相同;在网络的子网络 0 中,这始终是正确的。

使用 CIDR 进行分层地址划分

图 20-4. 使用 CIDR 进行分层地址划分

第二层划分

假设你之前为未来的 ISP 分配保留了子网络 0。然后你选择将第二个子网络分成四份。然后你将进一步将这些子网络划分为不同的大小以满足客户的需求。要将它们分成四组,你需要从子网络 1 的主机 ID 中再借用两个位,如下所示,粗体和下划线显示在原始子网位旁边:

01000111 01011111 00000000 00000000

这两个位被替换为模式 00、01、10 和 11,以获得四个子子子网络。它们将是/18 网络,因为您从/16 的主机 ID 中提取了两个额外的位,如下所示:

子子子网络 1-0: 01000111 01011111 00000000 00000000 (71.95.0.0/18)
子子子网络 1-1: 01000111 01011111 01000000 00000000 00000000 (71.95.64.0/18)
子子子网络 1-2: 01000111 01011111 10000000 00000000 (71.95.128.0/18)
子子子网络 1-3: 01000111 01011111 11000000 00000000 (71.95.192.0/18)

每个都有 16382 个地址。

第三级划分

现在,您将每个四个/18 网络进一步细分。您希望每个都包含不同大小的块,以对应潜在的客户。一种方法如下:

大型组织 需要最多 510 个地址的客户需要/23 网络。您通过从主机 ID 字段中提取五个位来分割子子子网络 1-0,71.95.0.0/18:

01000111 01011111 00000000 00000000

您将这些五位替换为 00000、00001、00010 等,从而在这个块中提供 32 个不同的/23 网络,每个网络包含九位用于主机 ID,共 510 个主机。第一个将是子子子子网络 1-0-0,71.95.0.0/23;第二个是子子子子网络 1-0-1,71.95.2.0/23;最后一个将是子子子子网络 1-0-31:71.95.62.0/23。

中型组织 对于需要最多 254 个地址的客户,您可以通过从主机 ID 字段中提取六个位来分割子子子网络 1-1,71.95.64.0/18:

01000111 01011111 01000000 00000000

这为您提供了 64 个不同的/24 网络。第一个将是子子子子网络 1-1-0,71.95.64.0/24,第二个是子子子网络 1-1-1,71.95.65.0/24,依此类推。

小型组织 对于拥有最多 126 个主机的客户,您可以通过从主机 ID 字段中提取七个位来分割子子子网络 1-2,71.95.128.0/18,如下所示:

01000111 01011111 10000000 00000000

七位允许在/18 块内包含 128 个这些/25 网络。第一个将是 71.95.128.0/25,第二个是 71.95.128.128/25,第三个是 71.95.129.0/25,依此类推。

微型组织 对于拥有最多 60 个主机的客户,您可以通过从主机 ID 字段中提取八个位来分割子子子网络 1-3,71.95.192.0/18:

01000111 01011111 11000000 00000000

这在/18 块内为您提供了 256 个不同的/26 网络。第一个将是 71.95.192.0/26,第二个是 71.95.192.64/26,依此类推。

此示例仅显示了分割这个蛋糕的许多不同方法之一。ISP 可能会决定预先创建四种不同大小的客户网络不是正确的做法。它可能会选择将蛋糕分成两半,然后再分成两半,依此类推,直到创建出正确大小的块。或者,如果大多数客户需要的主机数量大约是 50、100、200 或 500,那么前面的例子可能是最容易管理的。

如果 ISP 需要这样做,他们仍然可以将任何较小的块进一步分割。例如,他们可以将一个/26 子子子网络分割成四个/28 子子子子网络,以适应非常小的客户。同样,这个 ISP 的个别客户也可以做同样的事情,将其自己的块分割以适应其网络的内部结构。

第二十一章. 互联网协议数据报封装和格式

无标题图片

互联网协议(IP)的主要任务是将在互联网中不同设备之间传输的数据。在互联网中两个主机之间的旅程中,这些数据可能穿越许多物理网络。为了确保数据被正确发送和接收,它被封装在一个称为IP 数据报的消息中。这个数据报包含几个字段,有助于管理 IP 的操作并确保数据到达它需要去的地方。

在本章中,我探讨了 IP 协议如何从上层接收数据并将其打包以进行传输。我首先对 IP 数据报和封装进行了概述性讨论。然后,我描述了 IP 数据报的一般格式,包括 IP 头部中使用的字段及其解释方式。我还简要讨论了 IP 数据报选项及其用途。

提示

背景信息 本章假定至少对 IP 寻址概念有基本的了解,这些概念在第十六章–第二十章/超网")中概述。它还参考了关于数据报分片和重组的章节(第二十二章)

注意

IP 数据报有时被称为 IP 数据包。数据报数据包哪个是首选术语似乎取决于你问的是谁;甚至标准也不使用一个术语。另一方面,我见过 IP 数据报被称为IP 帧,这绝对是错误的!第一章更完整地描述了这些术语*。

IP 数据报封装

在第五章中,我描述了 OSI 参考模型的概念,我探讨了网络协议栈中各层协议之间相互交互的几种方式。在协议间操作中最重要的概念之一就是封装。大多数数据都起源于 OSI 模型的高层。这些层的协议将数据向下传递到较低层进行传输,通常是以离散消息的形式。在接收时,每个较低层的协议都会接收到的整个消息内容,并将其封装成自己的消息格式,可能还会添加一个头部和可能的尾部,这些头部和尾部包含重要的控制信息。

你可能会把封装想象成类似于将一封信装入信封的过程。你写一封信,放入一个带有名字和地址的信封中,但如果你要通过快递员进行隔夜送达;快递员会取走那个信封,并将其放入一个更大的快递信封中。以类似的方式,在网络协议栈中,较高层的消息会被封装在较低层的消息中,而这些较低层的消息又可以进一步封装。

由于 TCP/IP 的突出地位,IP 是现代网络中数据封装发生的重要位置之一。数据通常从两个主要的传输层协议之一传递给 IP:传输控制协议(TCP)或用户数据报协议(UDP)。这些数据已经以 TCP 或 UDP 消息的形式存在,带有 TCP 或 UDP 头部。然后这些数据被封装进 IP 消息的主体中,通常称为IP 数据报IP 数据包。IP 数据报的封装和格式化有时也被称为包装——再次强调,信封是一个明显的类比。

图 21-1 展示了整个过程,这个过程看起来与 OSI 参考模型的整体绘制非常相似,如图 5-5 在第五章中所示。正如您所看到的,上层消息被封装成 TCP 或 UDP 消息。然后它成为 IP 数据报的有效负载,这里只显示了一个头部(事情可能比这复杂一些)。然后 IP 数据报被传递到第 2 层,在那里它被封装成某种局域网(LAN)、广域网(WAN)或无线局域网(WLAN)帧,然后转换为比特并在物理层传输。

如果要传输的消息太大,无法通过底层网络传输,它可能首先被分片。这类似于将一个大件拆分成多个较小的信封或盒子。在这种情况下,每个 IP 数据报只携带高层消息的一部分。接收设备必须从 IP 数据报中重新组装消息。

IP 数据报封装上层消息被封装成 TCP 或 UDP 消息,这成为 IP 数据报的有效负载。然后 IP 数据报被传递到第 2 层,在那里它被封装在 LAN、WAN 或 WLAN 帧中。随后它被转换为比特并在物理层传输。

图 21-1. IP 数据报封装上层消息被封装成 TCP 或 UDP 消息,这成为 IP 数据报的有效负载。然后 IP 数据报被传递到第 2 层,在那里它被封装在 LAN、WAN 或 WLAN 帧中。随后它被转换为比特并在物理层传输。

在概念上,IP 数据报与以太网或其他数据链路层使用的帧有些相似,但 IP 数据报的设计是为了促进跨互联网的传输,而数据链路层帧仅用于物理网络内的直接交付。IP 头部中包含的字段用于管理互联网数据报的交付。这包括交付的关键信息,如目标设备的地址、帧类型的标识和控制位。头部遵循您将很快要检查的格式。

一旦数据被封装进 IP 数据报,它就会被传递到数据链路层,以便在互联网的当前“跳”中进行传输。在那里,它被进一步封装,包括 IP 头部,进入一个数据链路层帧,例如以太网帧。IP 数据报可能被封装进许多这样的数据链路层帧,因为它在互联网中路由;在每次跳转中,IP 数据报从数据链路层帧中移除,然后重新封装成一个新的帧,以便进行下一跳。然而,IP 数据报在到达最终目的地之前不会改变(除了某些控制字段)。

IP 数据报通用格式

使用 IP 在互联网上传输的数据被包含在称为IP 数据报的消息中。与所有网络协议消息一样,IP 为其数据报使用特定的格式。在这里,我将讨论 IP 版本 4(IPv4)数据报格式,该格式在 RFC 791 中定义,与 IPv4 的其他部分一起。

IPv4 数据报在概念上分为两部分:头部有效载荷。头部包含寻址和控制字段,而有效载荷携带要发送到互联网的实际数据。与某些消息格式不同,IP 数据报在有效载荷之后没有跟随着尾部。

尽管 IP 是一个相对简单、无连接和不可靠的协议,但 IPv4 头部携带了相当多的信息,这使得它相当大。它至少有 20 字节长,带有选项时可以更长。IP 数据报格式在表表 21-1 数据报格式")、表 21-2 和表 21-3 中描述,并在图 21-2 中展示。

表 21-1. 互联网协议版本 4(IPv4)数据报格式

字段名称 大小(字节) 描述
版本 1/2(4 位) 识别用于生成数据报的 IP 版本。对于 IPv4,这个数字是 4。该字段确保了可能运行不同 IP 版本设备之间的兼容性。一般来说,运行较旧 IP 版本设备将拒绝由较新实现创建的数据报,假设较旧版本可能无法正确解释较新的数据报。
IHL 1/2 (4 bits) 指定 IP 头部长度,以 32 位字为单位。这包括任何选项字段和填充的长度。当不使用选项时,此字段的正常值为 5(5 个 32 位字 = 5*4 = 20 字节)。与表中较长的总长度字段进行对比。
TOS 1 这是一个设计用来携带信息以提供服务质量功能的字段,例如为 IP 数据报提供优先级交付。这并没有像最初定义的那样被广泛使用,并且其含义已被重新定义为使用称为区分服务(DS)的技术,如本章“IP 数据报服务类型(TOS)字段”部分所述。
TL 2 指定 IP 数据报的总长度,以字节为单位。由于此字段为 16 位宽,IP 数据报的最大长度为 65,535 字节,尽管大多数数据报的长度要小得多。
Identification 2 此字段包含一个 16 位值,该值属于特定消息的每个分片;对于原本未分片发送的数据报,此字段仍然填写,以便在数据报在传输过程中必须由路由器分片时使用。接收方使用此字段重新组装消息,而不会意外地将来自不同消息的分片混合在一起。这是必要的,因为分片可能来自多个混合在一起的消息,因为 IP 数据报可以从任何设备无序接收。(有关 IP 消息分片的讨论,请参见第二十二章。)
Flags 3/8 (3 bits) 三个控制标志,其中两个用于管理分片(如分片主题中所述),另一个保留。参见表 21-2。
Fragment Offset 1 5/8 (13 bits) 当发生消息分片时,此字段指定偏移量或位置,即此分片中的数据在消息中的位置,以 8 字节(64 位)为单位。第一个分片的偏移量为 0。(有关该字段的使用方法,请参见第二十七章中的分片讨论。)
TTL 1 这指定数据报在网络中允许存活的时间,以路由器跳数为单位。每个路由器在传输之前都会递减 TTL 字段的值(减一)。如果 TTL 字段降至零,则假定数据报已采取过长的路由,并将其丢弃。(有关更多信息,请参见本章后面的“IP 数据报生存时间(TTL)字段”部分。)
协议 1 识别数据报中携带的更高层协议(通常是传输层协议或封装的网络层协议)。表 21-3 显示了此字段的协议值,这些值最初由 IETF“分配号码”标准 RFC 1700 定义,现在由互联网分配号码权威机构(IANA)维护。
头部校验和 2 对头部进行校验和计算,以提供对传输中损坏的基本保护。这不是数据链路层技术(如以太网)通常使用的更复杂的循环冗余检查(CRC)代码;它只是一个 16 位的校验和。它是通过将头部字节分成字(一个字是两个字节)然后将它们相加来计算的。只有头部被校验和;不是数据。在每个跳转点,接收数据报的设备执行相同的校验和计算,如果存在不匹配,它将丢弃数据报作为损坏的数据报。
源地址 4 这是数据报发起者的 32 位 IP 地址。请注意,尽管中间设备如路由器可能处理数据报,但它们通常不会将它们的地址放入此字段——地址始终是最初发送数据报的设备的地址。
目标地址 4 这是数据报预期接收者的 32 位 IP 地址。尽管路由器等设备可能是数据报的中间目标,但此字段始终用于指定最终目的地。
选项 可变 在某些 IP 数据报的标准头部之后,可以包含几种类型的选项之一,如本章后面“IP 数据报选项和选项格式”部分所述。
填充 可变 如果包含一个或多个选项,并且用于它们的位数不是 32 的倍数,则需要添加足够的 0 位来填充头部,使其成为 32 位的倍数(四个字节)。
数据 可变 这是将在数据报中传输的数据。它可以是整个高层消息或其一部分。

表 21-2. IPv4 标志子字段

子字段名称 大小(字节) 描述
保留 1/8(1 位) 未使用。
DF 1/8(1 位) 当设置为 1 时,这意味着数据报不应该被分段。由于分段过程通常对高层来说是不可见的,大多数协议都不关心这一点,也不设置此标志。然而,它用于测试链路的最大传输单元(MTU)。
MF 1/8 (1 位) 当设置为 0 时,表示消息中的最后一个分段;当设置为 1 时,表示在分段消息中还有更多分段尚未到来。如果消息未使用分段,则只有一个分段(整个消息),此标志为 0。如果使用分段,除了最后一个分段之外的所有分段都将此标志设置为 1,以便接收者知道何时已发送所有分段。

表 21-3. IPv4 协议子字段

十六进制值 十进制值 协议
00 0 保留
01 1 ICMP
02 2 IGMP
03 3 GGP
04 4 IP-in-IP 封装
06 6 TCP
08 8 EGP
11 17 UDP
32 50 封装安全载荷(ESP)扩展头部
33 51 认证头部(AH)扩展头部

备注

表 21-3 的最后两个条目用于在数据报中插入额外的头部:AH 或 ESP 头部。更多信息请参见第二十九章

IPv4 数据报格式 此图显示了至关重要的 IPv4 数据报格式。前 20 个字节是固定的 IP 头部,后面是可选的选项部分,以及可变长度的数据区域。注意,服务类型字段显示的是 IPv4 标准中最初定义的形式。

图 21-2. IPv4 数据报格式 此图显示了至关重要的 IPv4 数据报格式。前 20 个字节是固定的 IP 头部,后面是可选的选项部分,以及可变长度的数据区域。注意,服务类型字段显示的是 IPv4 标准中最初定义的形式。

IP 数据报生存时间(TTL)字段

让我们看看生存时间(TTL)字段。由于 IP 数据报在穿越互联网时作为路由器到路由器的传输,一个数据报可能会从路由器 A 传递到路由器 B,再到路由器 C,然后又回到路由器 A。这被称为路由器循环,这是我们不想发生的事情。

为了确保数据报不会无限循环,TTL 字段被设计为包含一个时间值(以秒为单位),在数据报最初发送时填充。路由器会定期减少时间值,如果时间值达到零,则销毁数据报。TTL 字段也被设计用来确保时间敏感的数据报不会过时或错过其到期日期。

在实践中,这个字段并不是以这种方式使用的。今天的路由器速度很快,通常在不到一秒的时间内就可以转发一个数据报,这使得测量数据报存活时间变得不切实际。相反,这个字段被用作数据报的最大跳数。每次路由器处理一个数据报时,它都会将 TTL 字段的值减一。如果这样做导致字段为零,则称数据报已过期,此时它将被丢弃,并且通常会发送一个 Internet 控制消息协议(ICMP)超时消息,通知消息的发送者该消息已过期。TTL 字段是网络保护免受路由器环路的主要机制之一。(有关 TTL 如何帮助 IP 处理路由器环路的更多内容,请参阅第三十二章中 ICMP 超时消息的描述。)

IP 数据报服务类型(TOS)字段

服务类型(TOS)字段是一个一字节的字段,最初旨在为 IP 数据报的交付提供某些服务质量(QoS)特性。它允许 IP 数据报被标记上信息,不仅表明它们的优先级,而且还表明它们应该以何种方式交付。它被划分为多个子字段,如表 21-4 和图 21-2 所示。

长久以来,缺乏服务质量(QoS)特性一直被认为是 IP 的一个弱点。但正如你在表 21-4 中可以看到的,这些特性从一开始就被构建到 IP 中。事实上,尽管这个字段在 20 世纪 80 年代初的标准中就已经定义,但它并没有被硬件和软件广泛使用。多年来,它只是以所有位都为零的形式传递,大部分时间都被忽略了。

互联网工程任务组(IETF)看到这个字段未被使用,试图复兴其使用。1998 年,RFC 2474 重新定义了 TOS 字段的前六位,以支持一种称为区分服务(DS)的技术。在 DS 下,TOS 字段中的值被称为代码点,并与不同的服务级别相关联。(有关所有详细信息,请参阅 RFC 2474。)

小贴士

相关信息 务必阅读本章剩余部分以获取有关如何在数据报中使用 IP 选项的更多信息,并在第二十二章中了解有关使用与分片相关的字段(如标识符、分片偏移和更多分片)的更多背景信息

表 21-4. IPv4 服务类型(TOS)字段的原始定义

子字段名称 大小(字节) 描述
优先级 3/8 (3 bits) 表示数据报优先级的字段。定义了八个值,从最低到最高优先级:000:常规 001:优先 010:立即 011:闪光 100:闪光优先 101:CRITIC/ECP110:互联网控制 111:网络控制
D 1/8 (1 bit) 设置为 0 以请求正常交付延迟;如果请求低延迟交付,则设置为 1。
T 1/8 (1 bit) 设置为 0 以请求正常交付吞吐量;如果请求更高的吞吐量交付,则设置为 1。
R 1/8 (1 bit) 设置为 0 以请求正常交付可靠性;如果请求更高的可靠性交付,则设置为 1。
保留 2/8 (2 bits) 未使用。

IP 数据报选项和选项格式

所有 IP 数据报都必须包含包含数据报源和目的地址、分片控制参数、长度信息等关键信息的标准 20 字节报头。除了这些固定字段外,IPv4 的创建者还包括了添加选项的能力,这些选项为 IP 处理数据报提供了额外的灵活性。当然,使用这些选项是可选的。然而,所有处理 IP 数据报的设备都必须能够正确读取和处理它们。

IP 数据报可能包含零个、一个或多个选项,因此 IP 头中选项字段的长度是可变的。每个选项可以是单个字节或多个字节,具体取决于选项需要传达多少信息。当包含多个选项时,它们被连接起来作为一个整体放入选项字段中。由于 IP 头必须是 32 位的倍数,如果所有选项中的位数不是 32 位的倍数,则包括一个填充字段。

每个 IP 选项都有自己的子字段格式,通常结构如表 21-5 和表 21-6 所示,并在图 21-3 中说明。对于大多数选项,都使用所有三个子字段:选项类型、选项长度和选项数据。然而,对于一些简单的选项,这种复杂的子结构是不必要的。在这些情况下,选项类型本身就包含了所需的所有信息,因此只出现选项类型字段,省略了选项长度和选项数据子字段。

表 21-5. IPv4 选项格式

子字段名称 大小(字节) 描述
选项类型 1 选项类型子字段分为三个子子字段,如表 21-6 所示。
选项长度 0 或 1 对于可变长度选项,指示整个选项的大小,包括此处显示的所有三个子字段,以字节为单位。
选项数据 0 或可变 对于可变长度选项,包含作为选项一部分发送的数据。

表 21-6. IPv4 选项:选项类型子字段

子子字段名称 大小(字节) 描述
复制标志 1/8 (1 位) 如果选项旨在在数据报分片时复制到所有分片中,则此位设置为 1;如果选项不应复制到分片中,则清除为 0。
选项类别 2/8 (2 位) 指定选项所属的四个潜在值之一,表示选项的一般类别。实际上,只使用了其中的两个值:0 用于控制选项,2 用于调试和测量。
选项编号 5/8 (5 位) 指定选项的类型。对于两个选项类别中的每一个,可以指定 32 个不同的值。其中,一些值更常用。有关特定选项的更多信息,请参阅表 21-7。

表 21-7 列出了最常见的 IPv4 选项,显示了每个选项的选项类别、选项编号和长度(长度为 1 表示选项仅由选项类型字段组成)。该表还提供了每个选项的简要使用说明。

IPv4 选项字段格式 此图显示了 IPv4 选项的完整字段格式。请注意,一些简单的选项可能仅包含选项类型子字段,省略了选项长度和选项数据子字段。

图 21-3. IPv4 选项字段格式 此图显示了 IPv4 选项的完整字段格式。请注意,一些简单的选项可能仅包含选项类型子字段,省略了选项长度和选项数据子字段。

表 21-7. 常见 IPv4 选项

选项类 选项号 长度(字节) 选项名称 描述
0 0 1 选项列表结束 包含单个零字节的选项,用于标记选项列表的结束。
0 1 1 无操作 一种“虚拟选项”,用作内部填充,以便在需要时将某些选项对齐到 32 位边界。
0 2 11 安全 为军事部门提供的一个选项,用于指示 IP 数据报的安全分类。
0 3 可变 松散源路由 IP 数据报源路由的两种选项之一。
0 7 可变 记录路由 允许将数据报使用的路由记录在数据报本身的头部中。如果源设备发送包含此选项的数据报,则处理数据报的每个路由器都会将其 IP 地址添加到此选项中。接收者可以提取 IP 地址列表,以查看数据报所经过的路由。请注意,此选项的长度由源设备设置。在数据报路由过程中不能扩大,如果它在到达目的地之前填满,则只能记录部分路由。
0 9 可变 严格源路由 IP 数据报源路由的两种选项之一。
2 4 可变 时间戳 与记录路由选项类似,但每个设备都会放入一个时间戳,因此接收者可以看到数据报在路由器之间传输所需的时间。与记录路由选项一样,此选项的长度由源设备设置,中间设备不能扩大。
2 18 12 跟踪路由 用于跟踪路由实用程序的增强实现,如 RFC 1393 所述。另见第三十三章,其中讨论了 ICMP 跟踪路由消息。

提示

关键概念 每个 IPv4 数据报包含一个 20 字节的强制头,并且可能包含一个或多个选项。每个选项都有自己的字段格式,并且大多数的大小是可变的。

通常,IP 数据报在没有任何特定指令的情况下被路由,这些指令说明数据报应从源到目的地采取的路径。这是路由器的任务,使用路由协议并找出这些细节。然而,在某些情况下,让数据报的源指定数据报在网络中采取的路径可能是有利的。这个过程被称为源路由

有两种 IP 选项支持源路由。在每个选项中,选项包括一个 IP 地址列表,指定了必须使用的路由器以到达目的地。当使用严格源路由时,选项中指定的路径必须完全、按顺序使用,不允许其他路由器处理数据报。相比之下,宽松源路由指定了一个必须按顺序遵循的 IP 地址列表,但它允许列表中设备之间的中间跳数。(有关每种选项类型使用的确切结构的完整详细信息,请参阅 RFC 791。)

第二十二章。IP 数据报大小、分片和重组

无标题图片

互联网协议(IP)的主要责任是在互连设备之间传输数据。正如你在上一章中看到的,这要求从高层接收到的数据必须封装成 IP 数据报进行传输。然后,这些数据报被传递到数据链路层,在那里它们通过物理网络链路发送。为了使这个过程正常工作,每个数据报必须足够小,以便能够适应底层技术的帧格式。如果消息比底层网络的帧大小最大值还要大,可能需要将消息分片。然后,这些数据报单独发送,并重新组装成原始消息。

IP 被设计用来管理数据报大小,并使分片和重组无缝。本章探讨了与 IP 数据报大小管理相关的问题。我从对数据报大小问题的概述和网络的传输单元(MTU)这一重要概念进行讨论开始,讨论为什么分片是必要的。然后,我描述了消息如何由源设备分片,以及可能由路径上的路由器分片,以及它们如何被接收者重新组装。

小贴士

背景信息 理解分片和重组需要一些关于 IP 数据报基本格式及其包含的一些字段的知识。如果你还没有阅读描述第二十一章中 IP 数据报通用格式的章节第二十一章,你可能希望在继续之前先复习一下。

IP 数据报大小、MTU 和分片概述

作为 TCP/IP 协议套件的核心网络层协议,IP 被设计用来实现可能非常大的设备互联网。当我们使用 IP 时,我们习惯了主机能够相互发送信息,尽管这些主机可能相隔甚远。尽管我们通常可以将 TCP/IP 互联网视为一个大型、抽象的虚拟设备网络,但我们必须始终记住,在网络层之下,数据总是穿越一个或多个物理网络。IP 的实现必须考虑到这一现实。

为了使用 IP 发送消息,我们将高层数据封装成 IP 数据报。然后,这些数据报必须发送到数据链路层,在那里它们被进一步封装成用于物理传输的帧格式,无论是直接发送到目的地还是间接发送到旅程中的下一个中间步骤。数据链路层实现将整个 IP 数据报放入其帧格式的数据部分(有效载荷),就像 IP 将传输层消息——包括传输头——放入其 IP 数据字段一样。这立即向我们提出了一个潜在问题:匹配 IP 数据报的大小与底层数据链路层帧大小。

IP 数据报大小和底层网络帧大小

设备用于连接其他设备的底层网络可能是局域网(LAN)连接(如以太网或令牌环),无线局域网(WLAN)链路(如 802.11),拨号连接,数字用户线路(DSL)连接,T1 链路,或其他广域网(WAN)连接。每个物理网络通常使用自己的帧格式,每种格式都有限制,即单帧可以发送多少数据。如果 IP 数据报太大,无法适应数据链路层帧格式的有效载荷部分,我们就遇到了问题!

例如,考虑一个光纤分布式数据接口(FDDI)网络。FDDI 数据字段的最大大小约为 4,470 字节。这意味着 FDDI 可以处理最大为 4,470 字节的 IP 数据报。相比之下,常规以太网帧使用一个帧格式,限制了其发送的有效载荷大小为 1,500 字节。这意味着以太网无法处理大于 1,500 字节的 IP 数据报。

现在,请记住,在发送数据报跨互联网时,它可能穿过多个物理网络。例如,为了访问互联网上的一个站点,我们通常通过我们的本地路由器发送请求,然后该路由器连接到其他路由器,最终将请求转发到互联网站点。数据报在转发过程中每跳可能使用不同的物理网络,具有不同的最大帧大小。

网络层协议背后的整个想法是实现这个虚拟网络的概念,在这个网络中,设备可以在很远的距离上通信。这意味着高层不需要担心底层数据链路层技术的尺寸限制等细节。这项任务由 IP 层负责。

MTU 和数据报分片

IP 互联网上的每个设备都必须知道其与其它设备直接数据链路层连接的容量。这个容量被称为网络的最大传输单元(MTU),也称为最大传输单元

如果 IP 层收到一个需要通过互联网发送的消息,它会查看消息的大小,然后计算在添加 20 个或更多字节(用于 IP 头部)后,IP 数据报的大小。如果总长度超过底层网络的 MTU(最大传输单元),IP 层将把消息分成多个 IP 片段。因此,如果一个主机通过以太网局域网连接到其本地网络,它可能为 IP 数据报使用 1,500 字节的 MTU,并且它会将任何更大的数据报进行分片。

图 22-1 展示了不同 MTU 和分片的例子。

提示

关键概念 可以通过物理网络传输的最大 IP 数据报的大小被称为该网络的最大传输单元(MTU)。如果一个数据报从一个 MTU 较高的网络传递到 MTU 较低的网络,它必须被分片以适应另一个网络较小的 MTU。

由于设备之间的路径上的一些物理网络可能具有比其他网络更小的 MTU,可能需要多次分片数据报。例如,假设源设备想要发送一个 12,000 字节长的 IP 消息。它的本地连接 MTU 为 3,300 字节。它需要将这个消息分成四个片段进行传输:三个大约 3,300 字节长,一个剩余大约 2,100 字节长。(我在简化过程中忽略了额外的头部;本章后面的“IP 消息分片过程”部分包括了分片过程的全部细节。)

IP 最大传输单元(MTU)和分片 在这个简单的例子中,设备 A 通过一个由一个路由器和两个物理链路组成的小型互联网向设备 B 发送数据。从设备 A 到路由器的链路 MTU 为 3,300 字节,但从路由器到设备 B,它只有 1,300 字节。因此,任何大于 1,300 字节的 IP 数据报都需要进行分片。

图 22-1. IP 最大传输单元 (MTU) 和分片 在这个简单的例子中,设备 A 通过一个由一个路由器和两个物理链路组成的小型互联网向设备 B 发送数据。从设备 A 到路由器的链路 MTU 为 3,300 字节,但从路由器到设备 B,仅为 1,300 字节。因此,任何大于 1,300 字节的 IP 数据报都需要进行分片。

多阶段分片

当 IP 分片在传输过程中,它们可能需要通过一个物理网络 MTU 只有 1,300 字节的两个路由器之间的跳。在这种情况下,每个分片又需要再次分片。3,300 字节的分片最终将分成三块(两块大约 1,300 字节和一块大约 700 字节),最后的 2,100 字节分片将变成一个 1,300 字节和一个 800 字节的分片。因此,我们最终将得到 11 个分片(33+12),如图 图 22-2 所示。

IPv4 数据报分片。本例说明了大型 IP 数据报的两步分片过程。方框代表数据报或数据报片段,并按比例显示。原始数据报为 12,000 字节,由大灰框表示。为了通过第一个本地链路传输这些数据,设备 A 将其分成四个片段,如图左侧所示。第一个路由器必须将这些每个分片进一步分割成更小的片段,以便通过 1,300 字节 MTU 链路发送,如图底部所示。请注意,第二个路由器不会重新组装 1,300 字节的数据报片段,尽管其与设备 B 的链路 MTU 为 3,300 字节。(本章后面的“IP 分片过程”部分描述了创建本例中片段的过程。)

图 22-2. IPv4 数据报分片。此示例说明了大型 IP 数据报的两步分片。方框代表数据报或数据报片段,并按比例显示。原始数据报为 12,000 字节,由大灰框表示。为了通过第一个本地链路传输这些数据,设备 A 将其分成四个片段,如图左侧所示。第一个路由器必须将这些每个分片进一步分割成更小的片段,以便通过 1,300 字节的 MTU 链路发送,如图底部所示。请注意,第二个路由器不会重新组装 1,300 字节的片段,尽管其连接到设备 B 的链路的 MTU 为 3,300 字节。(本章后面的“IP 分片过程”部分将描述创建此示例中片段的过程。)

互联网最小 MTU:576 字节

路由器需要处理至少 576 字节的 MTU(最大传输单元)。这个值在 RFC 791 中指定;它被选择以允许至少 512 字节的数据块,以及标准 IP 头和选项的空间。由于这是 IP 标准中指定的最小尺寸,576 字节已成为用于 IP 数据报的常见默认 MTU 值。即使主机通过大于 576 字节的 MTU 的本地网络连接,它也可能选择使用 576 字节的 MTU 值,以确保中间路由器不需要进一步分片。

注意

虽然中间路由器可能会进一步分片已经分片的 IP 消息,但它们不会重新组装片段。重新组装仅由接收设备完成。这有一些优点和缺点,我们将在本章后面的“IP 消息重新组装”部分检查重新组装过程时看到。

MTU 路径发现

当我们试图发送大量数据时,消息传输的效率变得很重要。我们发送的 IP 数据报越大,用于开销(如头部字段)的字节浪费百分比就越小。这意味着,理想情况下,我们希望使用尽可能大的 MTU,而无需对其进行传输分片。

要确定两个设备之间路由的最佳 MTU,我们需要知道该路由上每个链路的 MTU——这是连接端点所没有的信息。然而,连接端点可以通过使用MTU 路径发现来确定整个路由的 MTU,该机制使用 TCP/IP 互联网控制消息协议(ICMP)中内置的错误报告机制。

在 ICMP 版本 4(ICMPv4)中定义的消息类型之一是目标不可达消息(见第三十二章),在 IP 数据报无法交付的各种情况下返回。这些情况之一是当数据报太大,无法通过物理链路上的路由器转发,但该数据报的“不要分片”(DF)标志被设置为防止分片。在这种情况下,必须丢弃数据报并向源发送目标不可达消息。设备可以通过使用不同大小的数据报测试路径来利用这种功能,以查看它们必须有多大才会被拒绝。

源节点通常发送一个具有其本地物理链路 MTU 的数据报,因为这代表从该设备到任何路径的上限。如果这个数据报没有错误地通过,设备就知道它可以使用这个值来发送到该目的地的未来数据报。如果它收到任何“目标不可达 - 需要分片和 DF 设置”消息,它就知道它和目的地之间的链路有一个更小的 MTU。它再次尝试使用更小的数据报大小,并继续直到它找到路径上可以使用的最大 MTU。

IP 消息分片过程

如前所述,当一个 IP 数据报对于用于其旅程下一阶段的底层数据链路层技术的 MTU 太大时,它必须在发送到网络之前进行分片。要传输的较高层消息不是在一个单独的 IP 数据报中发送,而是分解成单独发送的片段。在某些情况下,这些片段本身可能还需要进一步分片。

分片是实现独立于底层细节的网络层互连的关键,但它给 IP 带来了显著复杂性。记住,IP 是一个不可靠的无连接协议。IP 数据报可以从源到目的地的任何路径中选择,有些甚至可能根本无法到达目的地。当消息被分片时,这会将单个数据报转换为多个,从而引入几个新的问题:

序列化和放置 片段通常按照从消息开始到结束的顺序发送,但它们不一定按照发送的顺序出现。接收设备必须能够确定片段的顺序,以便按正确顺序重新组装它们。实际上,某些实现首先发送最后一个片段,这样接收设备就会立即知道原始完整数据报的大小。这使得跟踪段顺序变得更加重要。

碎片化消息的分离 源设备可能需要一次发送多个碎片化消息,或者它可能发送在途中被碎片化的多个数据报。这意味着目标设备可能正在接收多组碎片,这些碎片需要重新组合。想象一个包含来自两个、三个或更多拼图碎片的大盒子,你就理解这个问题了。

完成 目标设备必须能够判断它是否已经收到了所有碎片,以便知道何时开始重组(或者如果它没有收到所有碎片,何时放弃)。

为了解决这些担忧并允许正确重组碎片化的消息,IP 协议在 IP 格式头部中包含几个字段,这些字段从源地址传递到目标地址有关碎片的信息。其中一些字段包含消息所有碎片的公共值;而其他字段则对每个碎片不同。

IP 碎片化过程

执行碎片化的设备遵循一个特定的算法将消息分成用于传输的碎片。碎片化过程的精确实现取决于设备。例如,考虑一个宽度为 12,000 字节(包括 20 字节 IP 头部)的 IP 消息,需要通过一个 MTU 为 3,300 字节的链路发送。图 22-3 描述了执行这种碎片化的一种典型方法。

IPv4 数据报碎片化过程 在此图中,每个碎片的 MF 和碎片偏移字段以供参考。数据字段按比例显示(每个的长度与碎片中的字节数成正比)

图 22-3. IPv4 数据报碎片化过程 在此图中,每个碎片的 MF 和碎片偏移字段以供参考。数据字段按比例显示(每个的长度与碎片中的字节数成正比)

图 22-3 中显示的四个碎片创建如下:

  • 第一个碎片是通过取 12,000 字节 IP 数据报的前 3,300 字节创建的。这包括原始头部,它成为第一个碎片的 IP 头部(某些字段已更改,如下一节所述)。因此,第一个碎片中有 3,280 字节的数据。这留下了 8,700 字节(11,980-3,280)需要封装。

  • 接下来的 3,280 个字节的数据是从第一个分片构建后剩余的 8,700 字节中提取的,并与一个新的头部配对以创建第二个分片。这留下了 5,420 个字节。

  • 第三段是从接下来的 3,280 个字节的数据中创建的,包含一个 20 字节的头部。这留下了 2,140 个字节的数据。

  • 剩余的 2,140 个字节被放入第四个分片,包含一个 20 字节的头部。

这里有两个重要的点。首先,IP 分片并不是通过将原始 IP 消息完全封装到分片的数据字段中来工作的。如果是这样的话,第一个分片数据字段的头 20 个字节将包含原始 IP 头部。(这种技术被一些其他协议使用,例如第九章中讨论的 PPP 多链路协议。)原始 IP 头部被转换成第一个分片的 IP 头部。

其次,请注意,传输的字节总数增加了:我们现在发送 12,060 字节(3,300*3+2,160),而不是 12,000 字节。额外的 60 字节来自第二、第三和第四分片中的附加头部。(如果头部包含选项,理论上大小增加可能会更大。)

分片相关 IP 数据报头部字段

当一个发送设备或路由器对数据报进行分片时,它必须提供信息,以便接收设备能够识别分片并将它们重新组装成原始数据报。这些信息由分片设备在 IP 数据报头部的一些字段中记录:

总长度 分片后,总长度字段表示每个分片的长度,而不是整个消息的长度。通常,分片大小被选择以匹配字节的 MTU 值。然而,分片必须具有是 8 的倍数的长度,以便正确指定偏移量(由分片偏移量字段处理)。最后一个分片通常会比其他分片短,因为它将包含剩余的部分,除非消息长度恰好是分片大小的整数倍。

标识 为了解决同一盒子里多个拼图碎片的问题,为每个正在分片的消息分配一个唯一的标识符。这就像在将拼图碎片扔进盒子之前,在每个拼图碎片底部写上不同的数字。这个值放在每个发送的分片 IP 头部的标识字段中。标识字段是 16 位宽,因此总共可以使用 65,536 个不同的标识符。显然,我们想确保每个正在分片以供传输的消息都有一个不同的标识符。源可以决定如何生成唯一的标识符。这可能通过某种简单的方法实现,比如每次创建一个新的分片集时,计数器就会增加。

更多分片 更多分片标志对所有分片都设置为 1,除了最后一个分片,它的设置为 0。当看到更多分片标志值为 0 的分片时,目标设备就知道它已经收到了消息的最后一个分片。

分片偏移 分片偏移字段通过指示接收设备在每个整体消息中每个特定分片应该放置的位置来解决分片排序的问题。该字段宽度为 13 位,因此偏移量可以从 0 到 8,191。分片以 8 字节为单位指定,这就是为什么分片长度必须是 8 的倍数。巧合的是,8,191 乘以 8 等于 65,528,这几乎是 IP 数据报允许的最大大小。在图 22-3 中所示示例中,第一个分片的分片偏移为 0,第二个分片的偏移为 410(3,280/8),第三个分片的偏移为 820(6,560/8),第四个分片的偏移为 1,230。

一个 IP 数据报还有一些与分片相关的其他字段。首先,如果一个包含选项的数据报必须进行分片,那么一些选项可能会被复制到每个分片中。这是通过每个选项字段中的复制标志来控制的。

其次,在 IP 头部中,有一个称为“不要分片”的标志。这个字段可以被发送设备设置为 1,以指定数据报在传输过程中不应该被分片。这可能在某些情况下使用,例如,由于某种原因整个消息必须完整地交付。如果目标设备具有有限的 IP 实现,无法重新组装分片,也可以使用它,并且它也用于测试链路的 MTU。然而,通常设备不会关心分片,这个字段保留为 0。

如果一个路由器遇到一个太大而无法通过下一个物理网络传输的数据报,但“不要分片”位设置为 1,它不能分片数据报,也不能将其传递下去,因此它就卡住了。它通常会丢弃数据报,并返回一个 ICMP 目标不可达错误消息:“需要分片,但设置了不要分片位。”这用于 MTU 路径发现,如本章前面所述。

小贴士

关键概念 当 MTU(最大传输单元)要求迫使数据报被分片时,它会被分割成几个较小的 IP 数据报,每个数据报都包含原始数据报的一部分。原始数据报的头部被改变为第一个分片的头部,并为其他分片创建新的头部。每个分片的标识值被设置为相同的值,以标记它们是同一原始数据报的一部分。每个分片的分片偏移量被设置为分片在原始数据报中的位置。除了最后一个分片外,所有分片的更多分片字段都被设置为 1,以便让接收方知道何时已收到所有分片。

IP 消息重组

当数据报被分片时,它变成了多个分片数据报。整体消息的目的地必须收集这些分片并将它们重新组装成原始消息。

虽然重组是分片的补充,但这两个过程并不对称。两者之间的主要区别在于,中间路由器可以分片单个数据报或进一步分片已经分片的数据报,但中间设备不执行重组;重组仅在消息的最终目的地发生。因此,如果一个在具有 1,300 字节 MTU 的物理网络一侧的中间路由器上的数据报导致 3,300 字节数据报的分片,那么该 1,300 MTU 链路另一端的路由器不会将 3,300 字节的数据报恢复到其原始状态。它将发送所有 1,300 字节的分片,如图 22-2

互联网协议(IP)数据报封装和寻址的基本功能有时可以比作将一封信放入信封,然后在上面写上收件人的地址。一旦我们的 IP 数据报“信封”被填写并贴上标签,它就准备出发了,但它仍然放在我们的桌子上。IP 的最后一个主要功能是将信封送到预期的收件人那里。这是数据报的投递过程。当收件人不在我们本地网络时,这种投递需要将数据报从我们的网络路由到目的地所在的网络。

本章通过讨论 IPv4(互联网协议版本 4)在互联网上路由数据报的一些具体细节来结束我们对 IPv4 的探讨。我首先概述了这个过程,并对比了设备之间直接和间接的数据传输。我讨论了在互联网上路由数据报的主要方法,并简要解释了 IP 路由表是如何构建和维护的。我还描述了从类别到无类别寻址的迁移,即使用无类别域间路由(CIDR)对路由的影响。

我最后简要地看了看与 IP 多播相关的问题。多播实际上并不是路由的一部分,但多播中的许多问题都与数据报的投递和路由有关。

小贴士

相关信息 本章重点介绍与 IP 工作方式直接相关的路由问题。路由是网络中的一个复杂且重要的话题,你可以在第第三十七章到第四十一章中找到更多关于它的信息

IP 数据报交付

IP 的整体任务是将在更高层协议中传输的消息通过设备互联网传输。这些消息必须被封装和标记地址,如果需要,还要进行分片,然后它们必须被交付。交付过程可以是简单的也可以是复杂的,这取决于源设备和目标设备之间的距离。我们可以将所有 IP 数据报交付分为两种一般类型:直接交付和间接交付。图 23-1 展示了 IP 数据报交付类型的示例。

IP 数据报的直接和间接(路由)交付 此图展示了 IP 数据报交付的三个示例。第一个传输(#1,深色箭头)显示了本地网络中两个设备之间的直接交付。第二个(#2,浅色箭头)显示了本地网络内的间接交付,客户端和服务器之间由路由器隔开。第三个(#3,中等箭头)显示了更远的间接交付,本地网络中的客户端和互联网上的服务器之间。

图 23-1. IP 数据报的直接和间接(路由)交付 此图展示了 IP 数据报交付的三个示例。第一个传输(#1,深色箭头)显示了本地网络中两个设备之间的直接交付。第二个(#2,浅色箭头)显示了本地网络内的间接交付,客户端和服务器之间由路由器隔开。第三个(#3,中等箭头)显示了更远的间接交付,本地网络中的客户端和互联网上的服务器之间。

直接数据报交付

当数据报在相同物理网络上的两个设备之间发送时,数据报可以直接从源发送到目标。例如,如果你想给你的街上的邻居送信,你可能会直接在信封上写上她的名字,然后直接放入她的邮箱。

直接投递显然是一种简单的投递方法。源端只需将 IP 数据报发送到其数据链路层实现。数据链路层将数据报封装在帧中,并通过物理网络直接发送到接收者的数据链路层,该层再将数据报向上传递到 IP 层。

间接数据报投递(路由)

当两个设备不在同一物理网络中时,从一个设备到另一个设备的数据报投递是 间接的。由于源设备在其本地网络中看不到目的地,它必须通过一个或多个中间设备发送数据报以进行投递。间接投递就像给不同城市的友人寄信一样。你不会亲自投递;你使用邮政系统。信件通过邮政系统旅行,可能经过几个中间步骤,最终到达你的友人的街区,那里的邮递员将其放入他的邮箱。

间接投递要复杂得多,因为我们不能直接将数据发送给接收者。实际上,我们通常甚至不知道接收者的确切位置。当然,我们有它的地址,但我们可能不知道它所在的网络,或者该网络相对于我们自己的网络的位置。(如果我告诉你我的地址,你就会知道它在佛蒙特州的贝宁顿,但你能找到它吗?)就像我们必须在信封类比中依赖邮政系统一样,我们必须依赖互联网本身来间接投递数据报。而且就像邮政系统一样,IP 不要求你知道如何将消息送到接收者;你只需将其放入系统。

实现这种间接投递魔法的设备通常被称为 路由器,而间接投递更常见地被称为 路由。就像将一封信托付给当地的邮递员或邮箱一样,需要将消息发送到远程设备的宿主机通常会将数据报发送到其本地路由器。路由器连接到一个或多个其他路由器,并且它们各自维护有关如何发送数据报以到达最终目的地的信息。

与远程设备(如互联网或广域网(WAN)链接上的设备)通信时,几乎总是需要间接投递。然而,即使要发送的消息是给办公室隔壁的设备,如果该设备在第二层没有直接连接到你的设备,也可能需要间接投递。

注意

在过去,路由器通常被称为网关。今天,这个术语更普遍地可以指代以各种方式连接网络的设备。你有时仍会听到路由器被称为网关,尤其是在默认网关等术语的上下文中,但由于其含糊不清,更倾向于使用路由器这个术语

数据报路由与寻址之间的关系

每次发送数据报时,发送者必须首先确定是否可以直接交付,或者是否需要路由。IP 编址允许设备快速确定它是否与其预期接收者位于同一网络。以下是有三种主要编址类别(请参阅第十六章):

传统按类编址 通过查看地址的前几位,我们可以知道每个地址的类别。这告诉我们地址中哪些位是网络 ID。如果目标地址的网络 ID 与我们的相同,则接收者位于同一网络;否则,它不在。有关按类编址的更多信息,请参阅第十七章。

子网划分的按类编址 我们使用子网掩码来确定我们的网络 ID 和子网 ID 以及目标地址的网络 ID 和子网 ID。如果网络 ID 和子网相同,则接收者位于同一子网。如果只有网络 ID 相同,则接收者位于同一网络的不同子网。如果网络 ID 不同,则目标位于完全不同的网络。请参阅第十八章以了解子网划分的全面讨论。

无类编址 与子网划分的按类编址使用相同的基本技术,只是没有子网。我们使用斜杠数字来确定地址的哪一部分是网络 ID,并像以前一样比较源地址和目标地址;请参阅第二十章。(然而,这里有一些复杂性,将在本章后面的“子网或无类编址(CIDR)环境中的 IP 路由”部分讨论。)

小贴士

关键概念 IP 数据报的交付分为两类:直接间接。当两个设备位于同一物理网络时,可以进行直接交付。当它们不在同一网络时,需要间接交付,通常称为路由,才能将数据报从源传输到目标。设备可以通过查看目标 IP 地址以及补充信息(如子网掩码)来确定需要哪种类型的交付,这些补充信息告诉设备它位于哪个网络或子网。

确定需要哪种类型的交付是源决定将数据报发送到何处的第一步。如果它意识到目的地在同一本地网络,它将在数据链路层直接将数据报地址发送给接收者。否则,它将数据报发送到它连接的一个路由器的数据链路层地址。数据报的 IP 地址仍然是最终目的地的地址。IP 地址与数据链路层地址之间的映射是通过使用 TCP/IP 地址解析协议(ARP)完成的,该协议在第十三章中讨论(ch13.html "第十三章。地址解析和 TCP/IP 地址解析协议(ARP)")。

路由是通过间接交付来完成的,以便将数据报发送到接收者的本地网络。一旦数据报被路由到接收者的物理网络,它就会通过接收者的本地路由器发送给接收者。因此,可以说间接交付包括直接交付作为其最终步骤。

注意

严格来说,任何在源设备和目的地设备之间的交付过程都可以被认为是路由,即使这些设备在同一网络中。然而,通常将路由过程更具体地指代为间接交付

IP 路由概念和下一跳路由过程

IP 路由信息的能力使我们能够使用它来创建一个跨越可能成千上万个物理网络的虚拟互联网,即使设备位于地球两端也能进行通信。让我们简要地看一下关键的 IP 路由概念。

继续使用我们的邮政系统类比,我可以从我在美国的家中给印度某地的人寄一封信,两个国家的邮政系统都会工作(或者应该工作)以将信件送到目的地。然而,当我把信件投入邮箱时,并不是有人出现,拿起信件,然后亲手将其送到印度的正确地址。信件从邮箱运送到我的本地邮局。从那里,它可能被送到一个区域配送中心,然后从那里送到国际邮件枢纽。它可能通过一个中间国家运往印度。当它到达印度时,印度邮政系统使用其自己的办公室和设施网络将信件路由到目的地。信封从一个地点跳到另一个地点,直到到达目的地。

IP 路由以非常相似的方式工作。尽管 IP 允许设备通过间接交付连接到互联网,但所有数据报的实际通信都是通过物理网络使用路由器进行的。我们不知道目标设备网络的确切位置,当然也没有任何方法直接连接到那里成千上万的网络。相反,我们依赖于这些中间设备——路由器,它们以各种方式相互物理连接,形成一个包含数百万网络之间路径的网状结构。数据报从一个路由器传递到下一个,直到到达目标设备物理网络。这个过程称为下一跳路由,如图图 23-2 所示。

这是 IP 工作方式中的一个关键概念:路由是逐步进行的,一次跳一步。当我们决定向远程网络上的设备发送数据报时,我们不知道数据报将采取的确切路径;我们只有足够的信息将其发送到我们连接的正确路由器。然后,该路由器查看目标 IP 地址并决定数据报应该跳转到下一个位置。这个过程会一直持续到数据报到达目标主机的网络。

起初,下一跳路由可能看起来像是一种在互联网中发送数据报的奇怪方式。实际上,它是使 IP 如此强大的部分原因之一。在前往任何其他主机的每一步中,路由器只需要知道数据报的下一步在哪里。如果没有这个概念,每个设备和路由器都需要知道如何到达互联网上每个其他主机的路径,这将非常不切实际。

小贴士

关键概念 使用称为下一跳路由的过程来实现 IP 数据报的间接交付,其中每个消息从一个路由器传递到下一个,直到到达目标网络的网络。这种方式的主要优势是每个路由器只需要知道哪个相邻路由器应该是给定数据报的下一个接收者,而不是需要知道到达每个目标网络的精确路由。

IP 数据报下一跳路由 此图与图所示相同,但它明确显示了三个样本传输的跳转。第一次传输的直接交付只有一个跳转(记住交换机不计入,因为在第 3 层它是不可见的)。本地间接交付通过一个路由器,因此有两个跳转。互联网交付有六个跳转。(实际的互联网路由可以更长。)

图 23-2. IP 数据报下一跳路由 这与图所示相同,但它明确显示了三个样本传输的跳转。第一次传输的直接交付只有一个跳转(记住交换机不计入,因为在第 3 层它是不可见的)。本地间接交付通过一个路由器,因此有两个跳转。互联网交付有六个跳转。(实际的互联网路由可以更长。)

与下一跳路由原则相关的另一个关键概念是,路由器而不是主机被设计用来完成路由任务。大多数主机仅通过一个路由器连接到互联网的其余部分(或互联网)。如果需要给每个主机提供智能以知道如何路由到其他每个主机,那将是一场维护噩梦。相反,主机只需决定它们是发送到自己的本地网络还是另一个网络。如果目的地是另一个网络,主机只需将数据报发送到其路由器,并说:“这里,来处理这个。”如果一个主机连接到多个路由器,它只需知道为某些远程网络集使用哪个路由器。

再次强调,每个跳转都包括物理网络的遍历。一旦源主机将其数据报发送到其本地路由器,路由器上的数据链路层将数据报向上传递到路由器的 IP 层。在那里,检查数据报的报头,路由器决定哪个设备应该接收下一个数据报。然后,它将数据报向下传递到数据链路层,通过路由器的物理网络链路发送,通常是发送到另一个路由器。路由器将记录其连接的路由器的物理地址,或者它将使用 ARP 来确定这些地址。

IP 路由和路由表

如前所述,路由器负责在 IP 互联网上转发流量。每个路由器从各种来源接收数据报,检查目的地的 IP 地址,并决定数据报需要采取的下一个跃点,以便更接近其最终目的地。但是,路由器如何知道将不同数据报发送到何处?

每个路由器维护一组信息,这些信息提供了不同网络 ID 与其连接的其他路由器之间的映射。这些信息包含在一个通常称为 路由表 的数据结构中。表中的每个条目,称为 路由条目,提供有关一个网络(或子网络或主机)的信息。它基本上说,“如果这个数据报的目的地在这个网络中,你应该采取的下一步是到以下设备。”每次接收到数据报时,路由器都会将其目的 IP 地址与其表中的路由条目进行比较,以决定将数据报发送到何处,然后将其发送到下一个跃点。

小贴士

关键概念 路由器通过其内部 路由表 来决定如何路由数据报。该表包含条目,指定数据报应发送到哪个路由器,以便到达特定的网络。

显然,表中条目越少,路由器决定如何处理数据报的速度就越快。(这是无类别寻址动机的一部分,它将路由聚合到超网络中,以减少路由表的大小,如下一节所述。)一些路由器只连接到两个其他设备,因此它们没有太多决策要做。通常,路由器将简单地从其接口接收数据报,如果需要,通过另一个接口发送它们。例如,考虑一个小公司的路由器作为三个主机网络与互联网之间的接口。从这个网络的主机发送到路由器的任何数据报都需要通过路由器与互联网服务提供商(ISP)的路由器连接。

当路由器连接到两个以上的设备时,事情会变得相当复杂。使用特定的连接,某个远程网络可能更容易到达。路由表不仅包含有关直接连接到路由器的网络的信息,还包含路由器关于更远程网络的信息。

图 23-3展示了包含四个路由器的示例。路由器 R1、R2 和 R3 以三角形的形式连接,这样每个路由器都可以直接向其他路由器发送数据,以及向其自己的本地网络发送。R1 的本地网络是 11.0.0.0/8,R2 的是 12.0.0.0/8,R3 的是 13.0.0.0/8。R1 知道任何以 11 开头的八位字节的数据报都在其本地网络中。它还将有一个路由条目,说明任何以 12 开头的 IP 地址应发送到 R2,任何以 13 开头的 IP 地址应发送到 R3。R1 还连接到路由器 R4,其本地网络为 14.0.0.0/8。R1 将有一个关于这个本地网络的条目,但 R2 和 R3 也需要知道如何到达 14.0.0.0/8,即使它们没有直接连接到其路由器。很可能会有一个条目说明,任何针对 14.0.0.0/8 的数据报应发送到 R1。然后 R1 将它们转发到 R4。同样,R4 将任何针对 12.0.0.0/8 或 13.0.0.0/8 的流量通过 R1 发送。

IP 路由和路由表 此图显示了一个由四个局域网组成的小型、简单的互联网,每个局域网都由一个路由器提供服务。每个路由表列出了应将每个目标网络的报文发送到哪个路由器。注意,由于三角形的结构,R1、R2 和 R3 可以相互发送数据。然而,R2 和 R3 必须通过 R1 来将数据发送到 R4,而 R4 必须使用 R1 来到达其中的任何一个。

图 23-3. IP 路由和路由表 此图显示了一个由四个局域网组成的小型、简单的互联网,每个局域网都由一个路由器提供服务。每个路由表列出了应将每个目标网络的报文发送到哪个路由器。注意,由于三角形的结构,R1、R2 和 R3 可以相互发送数据。然而,R2 和 R3 必须通过 R1 来将数据发送到 R4,而 R4 必须使用 R1 来到达其中的任何一个。

现在,想象这个过程被扩展以处理成千上万的网络和路由器。路由器不仅需要知道它们为每个网络使用哪个本地连接,而且如果可能的话,它们还想知道每个网络的最佳连接是什么。由于路由器以网状形式相互连接,通常任何两个设备之间都有多条路由,但我们希望尽可能选择最佳路由。这可能是最短的路由,最不拥挤的路由,或者基于其他标准被认为是最佳的路由。

确定我们应该为不同的网络使用哪些路由是一项重要但非常复杂的工作。路由器通过使用 IP 路由协议来规划路由并交换有关路由和网络的信息。R2 和 R3 使用这些协议来找出 14.0.0.0/8 的存在以及它是通过 R1 连接到它们的。(我在第三十七章到第四十一章中讨论了这些支持协议。)

注意

可路由协议和路由协议之间是有区别的。IP 是一个可路由协议,这意味着它的消息(数据报)可以被路由。路由协议的例子有路由信息协议(RIP)和边界网关协议(BGP),它们用于在路由器之间交换路由信息(见第三十八章")和第四十章"))

子网或无类别地址(CIDR)环境中的 IP 路由

如前几章所述,IP 寻址主要有三种类型:类别寻址、子网类别寻址和无类别寻址。确定是否需要直接或间接交付数据报的方法因寻址类型而异。网络中使用的寻址类型也会影响路由器在互联网中转发流量的决策。

传统基于类别的寻址方案被创造出来的主要原因是它使得寻址和路由相对简单。记住,IPv4 是在 20 世纪 70 年代末开发的,当时我们今天视为理所当然的廉价且强大的计算机硬件仍然是科幻。为了使互联网能够正常工作,路由器需要能够查看 IP 地址并快速决定如何处理它。

类别寻址旨在实现这一点。整个互联网只有两级层次结构:网络 ID 和主机 ID。路由器可以通过查看 IP 地址的前四个比特来判断任何 IP 地址中的哪些比特是网络 ID,哪些是主机 ID。然后他们只需要查阅他们的路由表来找到网络 ID 并查看哪个路由器提供了到达该网络的最佳路由。

在传统寻址中添加子网并没有真正改变互联网主要路由器的情况,因为子网是组织内部的。处理互联网上大量流量的主要路由器根本不查看子网。子网所代表的额外层次结构仅存在于选择使用子网的组织内部的路由器中。这些路由器在决定如何处理组织网络内的数据报时,需要提取不仅包括 IP 地址的网络 ID,还包括子网 ID。这告诉它们哪个内部物理网络应该接收数据报。

无类别寻址正式称为无类别域间路由(CIDR)。名字中包含路由但不包含寻址的事实表明,CIDR 在很大程度上是为了提高路由效率而引入的。这种改进发生是因为无类别网络使用多级层次结构。每个网络都可以分解成子网络、次子网络等等。这意味着当我们决定在 CIDR 环境中如何路由时,我们也可以以层次化的方式描述路由。许多较小的网络可以使用单个高级网络描述来描述,该描述代表它们在互联网其他路由器中的所有信息。这种技术有时被称为路由聚合,可以减少路由表的大小。

让我们回顾一下我在第二十章中提供的详细示例。一个 ISP 从 71.94.0.0/15 块开始,多次细分以为自己和客户创建更小的块。对于这个块的客户和用户来说,这些较小的块必须区分开来;ISP 显然需要知道如何将流量路由到正确的客户。然而,对于互联网上的其他人来说,这些细节在决定如何将数据报路由到该 ISP 块中的任何人的时候并不重要。

例如,假设我正在使用一个 IP 地址为 211.42.113.5 的主机,我需要向 71.94.1.43 发送消息。我的本地路由器和互联网上的主要路由器不知道该地址在 71.94.0.0/15 块中的哪个位置,而且它们不需要知道。它们只知道任何前 15 位包含 71.94 的二进制等效值的地址都发送到处理 71.94.0.0/15 的聚合地址的路由器。他们是整个块的聚合地址。他们让 ISP 的路由器确定其构成子网络中包含 71.94.1.43 的是哪一个。

将此与类别环境进行对比。在这里,这个 ISP 的每个客户可能都有一个或多个 C 类地址块,每个块都需要一个单独的路由条目,并且这些块需要为互联网上的所有路由器所知。因此,而不是只有一个 71.94.0.0/15 条目,每个客户网络都会有数十个甚至数百个条目。在无类别方案中,只有一个条目存在,即为父 ISP。

CIDR 为路由提供了好处,但也增加了其复杂性。在 CIDR 下,我们不能仅从 IP 地址中确定哪些位是网络 ID,哪些位是主机 ID。更糟糕的是,我们可以有网络、子网络、次子网络等等,它们都具有相同的基址!

在我们的例子中,71.94.0.0/15 是完整网络,子网络 0 是 71.94.0.0/16。它们有不同的前缀长度(网络 ID 位的数量),但相同的基址。如果一个路由器以这种方式对网络 ID 有多个匹配项,它必须首先使用具有最长网络标识符的匹配项,因为它代表了一个更具体的网络描述。

IP 多播

TCP/IP 通信的大部分都使用 IP 将消息从一台源设备发送到一台接收设备,这个过程被称为单播通信。这是我们通常使用 TCP/IP 进行消息传递的类型,因此当你使用互联网时,你实际上几乎在所有情况下都在使用单播。

然而,IP 也支持一个设备向一组接收者发送消息的能力。这被称为多播。IP 多播自 IPv4 首次定义以来就已经得到官方支持,但多年来并没有得到广泛的应用,这主要归因于许多硬件设备对多播的支持不足。近年来,对多播的兴趣有所增加,并且多播支持已成为下一代 IP 版本 6(IPv6)协议的标准部分。在这里,我们将简要地看看多播,这是一个庞大而复杂的话题。

IP 多播背后的想法是允许 IP 互联网上的一个设备向任意集合的其他设备发送数据报,而不仅仅是向一个接收者发送。IP 多播是模仿在数据链路层使用类似功能,允许单个硬件设备向组内的多个成员发送数据。在数据链路层,多播相对容易,因为所有设备都可以直接通信。相比之下,在网络层,我们正在连接可能相隔甚远的设备,必须在不同的网络之间路由数据报。这必然会使使用 IP 进行的多播变得复杂(除非在特殊情况下,我们只在同一数据链路层网络上的设备之间使用 IP 多播)。

实现 IP 多播必须执行三个主要功能:寻址、组管理和数据报处理/路由。

多播寻址

多播必须使用特殊的寻址方式。一个多播地址标识的不是单个设备,而是一个多播组的设备,这些设备会监听发送给它们的特定数据报。在 IPv4 中,整个地址空间中有一六分之一被留给了多播地址:原始的类地址方案中的 D 类块。使用各种技术来定义该块中地址的含义,以及定义 IP 多播地址与数据链路层多播地址之间的映射。(参见第十七章关于 IP 多播地址的讨论 Chapter 17 ADDRESSING");第十三章讨论了 IP 多播地址到硬件层多播地址的映射 Chapter 13")。)

多播组管理

组管理包括设置设备组所需的所有活动。设备必须能够动态地加入和离开组,并且关于组的信息必须在 IP 互联网中传播。为了支持这些活动,需要额外的技术。互联网组管理协议(IGMP)是用于此目的的主要工具。它定义了一种消息格式,允许在互联网上的设备和路由器之间发送有关组和组成员的信息。

多播数据报处理和路由

在多播环境中处理和路由数据报可能是最复杂的函数。这里有几个问题:

  • 由于我们是将数据从一台设备发送到多台,因此实际上需要为交付创建多个数据报副本,这与单播情况中使用的单个数据报不同。路由器必须能够判断何时需要创建这些副本。

  • 路由器必须使用特殊的算法来确定如何转发多播数据报。由于每个数据报都可能导致发送到各个地方的多份副本,因此效率很重要,以避免产生不必要的流量。

  • 即使源不是组成员,路由器也必须能够处理发送到多播组的数据报。

在多播环境中进行路由需要路由硬件具备显著更多的智能。一些特殊的协议,例如距离矢量多播路由协议(DVMRP)和开放最短路径优先(OSPF)的多播版本,被用来使路由器能够有效地转发多播流量。这些算法必须在确保组内每个设备都能接收到为该组设计的所有数据报的同时,防止不必要的流量在互联网中传输。

小贴士

关键概念 IP 多播允许开发特殊的应用程序,其中一个设备可以向多个设备发送信息,这些设备位于私有互联网或全球互联网中。与传统的单播 IP 相比,它更为复杂,需要特别注意,尤其是在地址和路由方面。

本概述只是对 IP 多播的表面进行了探讨。处理组和将消息转发到多播组所涉及到的复杂性是支持该功能相当不均匀的一个原因,因此,它并没有被广泛使用。另一个问题是多播的苛刻性:它需要大量的网络带宽来复制消息,同时也要求已经忙碌的路由器做更多的工作。

第二部分-4. 互联网协议版本 6 (IPV6)

第二十四章

第二十五章

第二十六章

第二十七章

自 1981 年以来,TCP/IP 一直建立在互联网协议 (IPv4) 的第 4 版上,在前一部分中进行了详细讨论。IPv4 是在如今我们视为理所当然的全球互联网只是一个小型实验性网络的时候被创建的。考虑到互联网在二十年的时间里经历了多大的增长和变化,IPv4 已经出色地完成了它的任务。同时,多年来,很明显,如果不对这个受人尊敬的协议中的某些限制进行解决,它们将阻碍互联网未来的增长。

由于 IP 扮演着关键角色,改变它是项艰巨的任务。这意味着对 TCP/IP 中几乎所有操作方式的重大修改。然而,尽管我们发现改变很难,但我们大多数人知道这是必要的。在过去几年里,IP 的新版本的开发一直在进行中,官方称为 互联网协议版本 6 (IPv6),有时也称为 IP 下一个世代IPng。IPv6 准备取代 IPv4,并将成为未来互联网的基础。

在本部分,我提供了 IPv6 的详细描述。由于 IPv6 仍然是 IP,就像 IPv4 一样,它执行相同的函数:寻址、封装、分片和重组,以及数据报交付和路由。因此,关于 IPv6 的讨论模仿了关于 IPv4 的讨论。共有四章:第一章涵盖 IPv6 概念和问题;第二章讨论 IPv6 寻址;第三章讨论 IPv6 封装和格式;第四章讨论 IPv6 数据报分片、重组和路由。

由于 IPv6 代表了 IP 的演变,许多操作概念都是建立在 IPv4 中引入的概念之上的。为了避免在本部分中不必要的重复,我假设您熟悉 IPv4 的操作,特别是地址以及数据报是如何封装和交付的。如果您还没有阅读第二部分-3"), 首先复习它将是明智的,因为 IPv6 的描述重点在于它如何与当前的 IP 版本不同。

您还可以参考第二部分-6, 其中涵盖了互联网控制消息协议 (ICMP),其中一部分是 ICMP 版本 6——IPv6 的 ICMP,以及 IPv6 邻居发现 (ND) 协议,因为这些是 IPv6 的伴侣。

第二十四章. IPV6 概述、变更和过渡

无标题图片

互联网协议版本 6(IPv6)注定将成为 IP 的未来,由于 IP 的关键重要性,它将构成 TCP/IP 和互联网未来的基础。事实上,它自上上个十年中期以来一直在开发中,并且已经使用了多年的真实 IPv6 互连网络进行测试。尽管如此,许多人对于 IPv6 的了解并不多,除了它是一个 IP 的新版本之外。有些人甚至从未听说过它!当然,我将纠正这一点——但在深入探讨 IPv6 地址、封装、分片和其他功能的重要变化之前,让我们先从 IPv6 的鸟瞰图开始。

在本章中,我提供了一个关于 IPv6 的简要高级概述,包括从一般意义上看它与 IP 版本 4(IPv4)的不同之处。我首先简要概述了 IPv6 及其创建的原因。我列出了 IPv6 中做出的主要更改和协议的新增内容。我还解释了一些与从 IPv4 过渡到 IPv6 相关的困难。

IPv6 动机和概述

“如果它没有坏,就别修它。”这是我非常喜欢的一句民间智慧。我通常喜欢坚持使用有效的方法,大多数人也是如此。IPv4 运行得相当不错。它已经存在了几十年,并且随着互联网从小型研究网络发展到全球性的强大力量而幸存下来。所以,就像一辆你成功驾驶多年的可靠老车一样,如果它还能完成任务,为什么还要更换它呢?

就像那辆老车一样,你可以在可预见的未来继续使用 IPv4。问题是:这要付出什么代价?如果你愿意投入时间和金钱来维护和保养它,一辆老车可以保持良好的工作状态。然而,它的一些功能将受到限制。它的可靠性可能会受到怀疑。它不会有最新的功能。除了那些喜欢把汽车修理作为爱好的人之外,最终继续修复一辆老车是没有意义的。

在某些方面,这并不是一个很好的类比。我们的高速公路与 20 世纪 70 年代相比并没有太大的不同,而且与驾驶汽车相关的其他大多数问题在过去 25 年里也没有发生太大的变化。是否更新车辆的选择更多是基于实际考虑而非必要性。

相比之下,看看在过去 25 年里计算机和网络世界发生了什么!今天的便携式电脑的功能比当时最强大的服务器还要多。网络技术速度提高了 100 倍甚至 1000 倍。连接到全球互联网的人数增加了更大的倍数。在许多情况下,计算机的通信方式也发生了巨大的变化。

在某些方面,IPv4 可以被认为是一辆经过精心维护和修复的老车。它完成了工作,但它的年龄开始显现。IPv4 的主要问题是其相对较小的地址空间,这是仅使用 32 位 IP 地址的决定的遗留问题。在原始的类地址分配方案下,我们可能已经用完了 IPv4 地址。迁移到无类地址分配有助于推迟这个问题,像 IP 网络地址转换(NAT)这样的技术也起到了作用,它允许私有地址的主机访问互联网。

然而,最终,这些只是修补工作和不完美的修复,目的是为了保持老化的 IPv4 汽车在路上行驶。核心问题,即 32 位地址空间对于当前和未来互联网规模来说太小,只能通过迁移到更大的地址空间来解决。这是创建下一个版本 IP,即IPv6的主要推动因素。

注意

IPv4 的继任者版本是 6 而不是 5 的原因是因为版本号 5 被用来指代一个名为互联网流协议的实验性协议,该协议从未被广泛部署。有关 IP 历史和版本的完整讨论,请参见第十五章

IPv6 标准

IPv6 代表了自 1981 年 IPv4 正式化以来 IP 的第一个重大变化。多年来,其核心操作在 1998 年发布的一系列 RFC 中定义:RFC 2460 至 RFC 2467。其中最值得注意的是主要的 IPv6 标准 RFC 2460,“互联网协议,版本 6(IPv6)规范”,以及描述 IPv6 的两个辅助协议的文档:RFC 2461,描述了 IPv6 邻居发现协议(ND),和 RFC 2463,描述了 IPv6 的互联网控制消息协议版本(ICMPv6)。

此外,1998 年还编写了两份文档。它们讨论了更多关于 IP 地址的内容:RFC 2373,“IP 版本 6 地址架构”和 RFC 2374,“IPv6 可聚合全局单播地址格式”。由于 IPv6 地址实现方式的变化,这些文档在 2003 年由 RFC 3513,“互联网协议版本 6(IPv6)地址架构”和 RFC 3587,“IPv6 全局单播地址格式”进行了更新。

许多其他 RFC 定义了 IPv6 如何工作的更多具体细节,许多也描述了 IPv6 兼容的其他 TCP/IP 协议版本,如域名系统(DNS;见第五十二章*。它是为了纠正 IPv4 的一些重大问题而创建的,特别是 IPv4 地址空间即将出现的不足,以提高整个协议的操作,并将 TCP/IP 带入未来。

在 IPv6 旨在解决这些问题以及许多其他传统 IP 问题的同时,其变化仍然是渐进的,而不是革命性的。在 20 世纪 90 年代互联网工程任务组(IETF)的许多讨论中,有些人说,当我们更新 IP 时,也许我们应该对一种全新的、未经证实的互联网互连协议进行彻底、根本的改变。最终的决定不是这样做,而是定义一个更强大的 IP 版本,这是我们一直在使用的。

原因很简单:IP,就像我们信任的旧车一样,工作得很好。IPv6 代表了一个更新,它努力增加 IPv4 的最佳特性,而不是让每个人都从头开始使用一些新事物。这种设计确保了从 IPv4 到 IPv6 的任何变化带来的痛苦都可以得到管理,并且希望最小化。

IPv6 中的主要变化和新增功能

在前面的概述中,我解释了创建新的 IP 版本的主要动机是为了解决 IPv4 地址分配中的问题。但正如您所看到的,新协议也存在许多其他设计目标。一旦决定采取创建一个像 IP 一样重要的协议新版本的这一重大步骤,就有必要利用这个机会尽可能地进行改进。

当然,我们还需要担心改变带来的痛苦,因此 IPv6 中的每个潜在变化或新增功能都需要有超过其成本的益处。最终的设计在提供有用优势的同时,保持了原始 IP 的大部分核心。以下是 IPv4 和 IPv6 之间的一些最重要的变化,它们展示了 IPv6 团队如何满足新协议的设计目标:

更大的地址空间 IPv6 地址长度为 128 位,而不是 32 位。这把地址空间从大约 40 亿个地址扩展到了,嗯,天文数字(超过 300 万亿万亿万亿个地址)。

分层地址空间 IPv6 地址大小之所以扩大这么多,一个原因是为了允许它进行分层划分,从而提供大量不同类别的地址。

单播地址的分层分配 创建了一种特殊的全局单播地址格式,以便在整个互联网上轻松分配地址。它允许在互联网服务提供商(ISP)和组织级别上实现多级网络和子网层次结构。它还允许根据底层硬件接口设备 ID(如以太网 MAC 地址)生成 IP 地址。

对非单播寻址的支持得到改善 多播支持得到改进,并增加了对一种新型寻址方式的支持,即任播寻址。这种新型的寻址方式基本上意味着,“将此消息发送到这个群体中最容易到达的成员”,并可能启用新的消息功能。

自动配置和重新编号 包含了一项规定,允许在需要时更容易地自动配置主机以及重新编号网络和子网络中的 IP 地址。同时,也存在一种重新编号路由器地址的技术。

新的数据报格式 IP 数据报格式已被重新定义并赋予了新的功能。每个 IP 数据报的主要头部已被简化,并增加了对数据报扩展头部的支持,以便于扩展需要更多控制信息的头部。

对服务质量(QoS)的支持 IPv6 数据报包括 QoS 特性,这有助于更好地支持多媒体和其他需要 QoS 的应用。

安全支持 在 IPv6 中,通过使用认证和加密扩展头以及其他特性,设计进了安全支持。

更新的分片和重组过程 在 IPv6 中,数据报的分片和重组工作方式已经改变。改进的路由效率更好地反映了当今网络的实际情况。

现代化的路由支持 IPv6 被设计成支持现代化的路由系统,并允许随着互联网的增长而进行扩展。

过渡能力 由于从一开始就认识到从 IPv4 过渡到 IPv6 是一个重大的转变,因此在多个领域提供了 IPv4/IPv6 过渡的支持。这包括 IPv4 和 IPv6 网络互操作的计划、IPv4 和 IPv6 地址之间的映射以及其他过渡支持。

对其他协议的更改 随着 IPv6 的引入,一些与 IP 密切相关的其他 TCP/IP 协议也必须进行更新。其中之一是 ICMP,它是 IPv4 最重要的支持协议,通过创建 ICMPv6 来对 IPv6 进行修订。TCP/IP 的补充是 ND 协议,它执行了 IPv6 中由版本 4 的地址解析协议(ARP)和 ICMP 执行的多个功能。

以下关于 IPv6 的章节提供了更多关于这些变化和 IP 新增功能的具体细节。你会注意到,其中大部分都与寻址相关,因为 IPv6 中最重要的变化就是在寻址方面。当然,路由和寻址是紧密相关的,寻址的变化也对路由产生了重大影响。

从 IPv4 到 IPv6 的过渡

IP 是 TCP/IP 协议套件和互联网的基础,因此在结构重要性方面与房子的基础有些类似。鉴于这一点,改变 IP 就像对房子的基础进行重大修改一样。由于 IP 用于连接许多设备,这就意味着不仅仅是改变你的房子,而是改变世界上每一座房子!

你如何改变房子的基础?非常小心。在实施 IPv6 时也需要同样的谨慎。虽然大多数人认为 IPv6 是件新鲜事,但实际情况是 IPv6 的计划和开发已经进行了近十年,如果我们从头开始,这个协议多年前就已经可以投入使用。然而,IPv4 的硬件和软件安装基础非常庞大。这意味着开发 TCP/IP 的人们不能只是打开一个开关,让所有人都转向使用 IPv6。相反,必须计划从 IPv4 向 IPv6 的过渡。

转型已经开始,尽管大多数人还不知道这一点。正如我所说,IPv6 本身的发展几乎已经完成,尽管仍在继续完善协议以及开发其他协议的 IPv6 兼容版本。IPv6 的实施始于创建开发网络以测试 IPv6 的运行。这些网络相互连接,形成了一个名为6BONE(该名称是IPv6 骨干的缩写)的实验性 IPv6 互联网。这个互联网已经运行了好几年。

IPv4 到 IPv6 的过渡:意见分歧

实验性网络是很好的,但大问题是将互联网过渡到 IPv6,在这里,意见分歧相当快。一方面有公司、组织和个人。所有这些群体都迫切希望快速过渡到 IPv6,以获得它在寻址、路由和安全领域承诺的许多好处。另一方面的人则采取了一种更加谨慎的方法,指出 1990 年代中期对 IPv4 即将灭亡的悲观预测并没有成真,并认为我们应该花时间确保 IPv6 能够在大规模上运行。

这两组人将在接下来的几年里继续进行拔河比赛,但看起来现在潮流正在转向那些希望加快现在已持续多年的过渡的人。将 IPv6 作为生产协议的采用正在由多个团体和组织领导。IPv6 在除美国以外的许多地区都得到了很多支持,这些地区由于相对于其规模的小额分配而 IPv4 地址短缺。亚洲就是这样一片地区,拥有数十亿人口,互联网使用快速增长,IPv4 地址短缺。

在美国,由于互联网在这里开发,拥有大部分 IPv4 地址(因为互联网在这里开发),对于快速部署 IPv6 似乎有点不太热情。然而,即使在这里,IPv6 在 2003 年 7 月也获得了重大推动,当时美国国防部(DoD)宣布,从那年 10 月开始,它将只购买包含 IPv6 兼容性的网络产品。DoD(最初负责互联网的发展)希望到 2008 年完全过渡到 IPv6。这可能会对其他美国政府和私营组织的计划产生重大影响。

IPv6 的创造者从一开始就知道,过渡将是新协议的一个重要问题。IPv6 与 IPv4 不兼容,因为地址系统和数据报格式不同。然而,IPv6 的设计者知道,由于过渡将需要很多年,他们必须提供一种方法,使 IPv4 和 IPv6 宿主机能够互操作。考虑到在任何过渡中,总会有一些落后者。就像角落里那个你偶尔还需要使用的旧 Windows 3.11 PC 一样,一些设备将保持使用 IPv4,即使大部分互联网都是 IPv6,因为它们从未升级。

小贴士

关键概念 由于 IPv4 和 IPv6 之间存在许多差异,以及 IP 对 TCP/IP 的基本重要性,因此已经计划在多年内从 IPv4 到 IPv6 进行有序过渡。

IPv4 到 IPv6 过渡方法

IETF 一直在制定具体规定,以允许从 IPv4 到 IPv6 的平稳过渡,以及硬件和软件互操作性解决方案,以便新的 IPv6 设备能够访问 IPv4 宿主机。IPv6 中包含了一种技术,允许管理员在 IPv6 地址中嵌入 IPv4 地址。定义了特殊方法来处理互操作性,包括以下内容:

双栈设备 路由器和其他一些设备可能被编程为同时支持 IPv4 和 IPv6 的实现,以便它们能够与这两种类型的宿主机进行通信。

IPv4/IPv6 转换 双栈设备可能被设计为接受来自 IPv6 宿主机的请求,将它们转换为 IPv4 数据报,然后将数据报发送到 IPv4 目的地,并类似地处理返回的数据报。

IPv6 的 IPv4 隧道 没有完全由支持 IPv6 的路由器组成的路径的 IPv6 设备可能能够通过封装 IPv6 数据报在 IPv4 中来进行通信。本质上,它们将使用 IPv6 在 IPv4 之上;也就是说,两个网络层。封装的 IPv4 数据报将穿越传统的 IPv4 路由器。

请记住,这些解决方案通常仅解决向后兼容性问题,以允许 IPv6 设备与 IPv4 硬件通信。IPv4 和 IPv6 之间的向前兼容性是不可能的,因为 IPv4 主机无法与 IPv6 主机通信;它们缺乏了解 IPv6 如何工作的知识。可能某些特殊的适应性可能会被创建,以允许 IPv4 主机访问 IPv6 主机。但最终,所有重要的 IPv4 设备都将希望迁移到 IPv6。

互联网工程任务组 (IETF) 在过去在引入新技术方面做得很好,并且在 IPv6 转型方面投入了大量的努力,因此我对 IPv6 转型能够顺利实施,几乎没有问题,非常有信心。关于转型的一个好处是,IPv4 在目前仍然能够完成任务,因此没有必要急于转向 IPv6。虽然像 CIDR 和 NAT 这样的技术就像是 IPv4 的创可贴,但它们在延长这个老协议的有效寿命方面非常成功。

第二十五章。IPv6 寻址

无标题图片

创建互联网协议版本 6 (IPv6) 的主要动机是为了纠正版本 4 (IPv4) 中的寻址问题。除了获取更多地址外,IPv6 设计者还希望找到一种方式,以更符合现代互联网的方式解释、分配和使用地址。因此,IPv6 中许多变化都与 IP 寻址相关。IPv6 寻址方案在概念上与 IPv4 寻址方案相似,但已经完全重新设计,以创建一个能够支持未来可预见的互联网扩展和新应用的寻址系统。

本章描述了与 IPv6 寻址相关的概念和方法。我首先回顾了 IPv6 中的一些寻址一般性内容,包括寻址模型、地址类型的大小和地址空间。我讨论了用于 IPv6 地址和前缀的独特和有时令人困惑的表示法和符号。然后,我探讨了地址是如何安排和分配到不同类型的,从整体上查看地址空间组成开始,然后是全局单播地址格式。我描述了用于将 IP 地址映射到底层物理网络地址的新方法。然后,我描述了特殊的 IPv6 寻址问题,包括保留地址和私有地址、IPv4 地址嵌入、任播和多播地址,以及地址的自动配置和重新编号。

IPv6 地址分配在主要的 IPv6 RFC 2460 中进行了概述,即“互联网协议,版本 6(IPv6)规范”。然而,IPv6 地址的大部分细节包含在其他两个标准中:RFC 3513,“互联网协议版本 6(IPv6)地址架构”和 RFC 3587,“IPv6 全局单播地址格式”。这些标准取代了 1998 年的 RFC 2373,“IP 版本 6 地址架构”和 RFC 2374,“IPv6 可聚合全局单播地址格式”。

小贴士

背景信息 与其他本书中的 IPv6 章节一样,我对地址分配的探讨在一定程度上是基于与 IPv4 地址分配方式的对比。我强烈建议在继续阅读之前,对 IPv4 地址分配有一个全面的理解,包括使用无类域间路由(CIDR)的无类地址分配,如第第十六章至第二十三章所述。与 IPv4 地址分配部分一样,了解二进制数的工作原理以及二进制与十进制数之间的转换也是很好的主意。第四章提供了关于数据表示和计算数学的一些背景信息,可能在这方面有所帮助

IPv6 地址概述:地址模型、地址类型和地址大小

正如你在上一章中看到的,IPv6 对 IP 协议进行了重大更新,但其修改和新增内容并未改变 IP 工作的核心本质。地址分配是 IPv4 和 IPv6 之间大部分差异体现的地方,但这些变化主要在于地址的实现和使用方式。IPv6 中用于 IP 地址分配的整体模型与 IPv4 中的非常相似;一些方面完全没有变化,而其他方面则只有轻微的变化。

IPv6 地址模型特性

以下是一些 IPv6 地址模型的一般特性,这些特性基本上与 IPv4 相同:

地址的核心功能 地址的两个主要功能仍然是网络接口标识和路由。路由通过互联网上地址的结构来实现。

网络层地址 IPv6 地址仍然是与 TCP/IP 网络中的网络层相关联的地址,并且与数据链路层(有时也称为物理层)地址不同。

每台设备的 IP 地址数量 地址仍然分配给网络接口,因此像 PC 这样的普通主机通常只有一个(单播)地址,而路由器将为其连接的每个物理网络分配多个地址。

地址解释和前缀表示 IPv6 地址与无类 IPv4 地址类似,它们被解释为具有网络标识符部分和主机标识符部分(网络 ID 和主机 ID),但这种划分并没有编码到地址本身中。使用类似 CIDR 的表示法,一个前缀长度数字用来指示网络 ID 的长度(前缀长度)。

私有地址和公有地址 在 IPv6 中,这两种类型的地址都存在,尽管它们的定义和使用方式有所不同。

IPv6 支持地址类型

IPv6 寻址模型中的一个重要变化是支持的地址类型。IPv4 支持三种地址类型:单播、多播和广播。在这些类型中,绝大多数实际流量是单播。IP 多播支持直到互联网建立多年后才得到广泛部署,并且由于各种问题而继续受到阻碍。出于性能原因,IP 中的广播使用必须受到严格限制(我们不希望任何设备能够在整个互联网上广播!)。

IPv6 也支持三种地址类型,但有以下变化:

单播地址 这些是 IPv4 中的标准单播地址,每个主机接口一个。

多播地址 这些是代表各种 IP 设备组的地址。发送到多播地址的消息将发送到组中的所有设备。IPv6 包括比 IPv4 更好的多播功能和更多的多播地址。由于 IPv4 下的多播在很大程度上受到许多硬件设备不支持该特性的阻碍,因此多播支持是 IPv6 的一个必需部分,而不是一个可选部分。

任播地址 任播寻址用于必须将消息发送到组中的任何一个成员,但不需要发送给所有成员的情况。通常,最容易到达的组成员将接收该消息。任播寻址的一个常见例子是在组织中的一组路由器之间进行负载均衡。

在 IPv6 中,作为独立寻址方法的广播寻址已经消失。广播功能是通过多播寻址到设备组来实现的。例如,一个所有节点都属于的多播组可以用于网络中的广播。

提示

关键概念 IPv6 像 IPv4 一样具有单播和多播地址。然而,IPv6 中并没有广播地址的独立概念。为了允许消息发送到设备组中的任何一个成员,增加了一种新的地址类型,即任播地址。

任播地址的创建的一个重要含义是消除了 IP 地址的严格唯一性要求。任播是通过将相同的 IP 地址分配给多个设备来实现的。这些设备还必须明确告知它们正在共享一个任播地址,但地址本身的结构与单播地址相同。

本章的剩余部分主要关注单播地址,因为它是迄今为止最重要的类型。多播和任播地址将在本章后面的单独部分中给予特别关注。

IPv6 地址大小和地址空间

在 IPv6 引入的所有变化中,最容易引起关注的是 IP 地址大小的增加,这导致了地址空间大小的相应大幅增加。与 IPv4 相比,这些大小增加并不令人惊讶——因为多年来我们都知道 IPv4 地址空间太小,无法支持互联网的未来。令人印象深刻的是增加的程度以及这对互联网地址使用的影响。

在 IPv4 中,IP 地址长度为 32 位;这些地址通常被分为 4 个 8 位的八位字节。理论上的 IPv4 地址空间是 2³²,即 4,294,967,296 个地址。为了增加这个地址空间,我们只需增加地址的大小;我们给地址大小增加的每一个额外位都会使地址空间翻倍。基于这一点,有些人预计 IPv6 地址大小将从 32 位增加到 48 位,或者可能是 64 位。这两个数字中的任何一个都会给出一个非常大的地址数量。

然而,IPv6 地址使用的是这两个数字中的任何一个。相反,IP 地址大小直接跳到 128 位,即 16 个 8 位的八位字节/字节。IPv6 地址空间的大小实际上是天文数字。就像描述星系中星星数量或最远脉冲星距离的数字一样,IPv6 可以支持的地址数量令人难以置信。参见图 25-1 来了解我所说的“天文数字”是什么意思。

由于 IPv6 地址长度为 128 位,如果所有地址都被使用,理论上的地址空间是 2¹²⁸个地址。这个数字展开后是 340,282,366,920,938,463,463,374,607,431,768,211,456,通常用科学记数法表示为大约 3.410³⁸个地址。哇!这大约是 340 万亿,万亿万亿*个地址。正如我所说,很难理解这个数字有多大。考虑以下比较:

  • 这些地址足够多,可以为地球上每一个人类分配数十亿个地址。

  • 地球大约有 45 亿年的历史。如果你从地球形成的那一刻起,以每秒 10 亿个地址的速度分配 IPv6 地址,到目前为止,你使用的地址空间还不到万亿分之一。

  • 地球表面积大约为 510 万亿平方米。如果一台典型的计算机占地面积约为 0.1 平方米,你需要堆叠 1000 亿台计算机——覆盖整个地球表面——才能耗尽同样的万亿分之一地址空间。

好的,我想你已经明白了。很明显,决定使用 128 位地址的一个目标是为了确保我们永远不会再次耗尽地址空间,而且这似乎是非常可能的。

相对 IPv4 和 IPv6 地址空间大小的(较差)表示我想制作一个酷炫的图形来展示 IPv4 和 IPv6 地址空间的相对大小。你知道,我会把 IPv6 地址空间展示为一个大的盒子,而 IPv4 地址空间展示为一个小的盒子。问题是 IPv6 地址空间比 IPv4 空间大得多,以至于无法按比例展示!为了使这个图按比例展示,想象一下上面的 1.6 英寸平方是 IPv4 地址空间。在这种情况下,IPv6 地址空间将用一个代表太阳系的平方来表示!

图 25-1. 相对 IPv4 和 IPv6 地址空间大小的(较差)表示我想制作一个酷炫的图形来展示 IPv4 和 IPv6 地址空间的相对大小。你知道,我会把 IPv6 地址空间展示为一个大的盒子,而 IPv4 地址空间展示为一个小的盒子。问题是 IPv6 地址空间比 IPv4 空间大得多,以至于无法按比例展示!为了使这个图按比例展示,想象一下上面的 1.6 英寸平方是 IPv4 地址空间。在这种情况下,IPv6 地址空间将用一个代表太阳系的平方来表示!

拥有如此巨大的地址空间也有其缺点。考虑一下,即使使用 64 位地址,我们也会有一个非常大的地址空间;2⁶⁴ 等于 18,446,744,073,709,551,616,或者说大约 18 亿万亿。这些地址可能仍然比互联网需要的地址多。然而,通过使用 128 位,这使得处理 IP 地址变得难以管理(你将在下一节中看到)。这也增加了开销,因为每个数据报头或其他引用 IP 地址的地方都必须使用 16 个字节来表示每个地址,而不是 IPv4 中所需的 4 个字节,或者 64 位地址可能需要的 8 个字节。

小贴士

关键概念 IPv6 地址空间真的非常大!

那么为什么需要过度到 128 位呢?主要原因在于灵活性。尽管如果我们逐个分配,我们可以拥有数亿个地址,但这使得分配变得困难。开发者移除了 IPv4 中的基于类别的地址分配,因为它浪费了地址空间。然而,现实是,能够浪费地址空间是一种有用的奢侈。

使用 128 位允许我们将地址空间分割,并为不同的位范围分配不同的用途,同时仍然不必担心空间不足。在本章的后续部分,在描述 IPv6 全局单播地址格式的部分,你会看到这些 128 位是如何得到良好应用的:它们允许你创建一个网络层次结构,同时仍然为主机 ID 保留 64 位。这种层次结构有其自身的优势。

IPv6 地址、地址表示法和前缀表示法

将 IP 地址的大小从 32 位增加到 128 位,将地址空间扩展到一个巨大的规模,从而确保我们永远不会再次耗尽 IP 地址,并允许在分配和使用它们时具有灵活性。不幸的是,这种方法有一些缺点,其中之一是 128 位数字非常大。其大小使得它们使用起来很尴尬且困难。

计算机以二进制方式工作,它们处理一长串的 1 和 0 没有问题,但人类发现它们很令人困惑。即使是 IPv4 的 32 位地址对我们来说也很繁琐,这就是为什么我们通常使用点分十进制表示法来表示它们,除非我们需要在二进制下工作(如子网划分)。然而,IPv6 地址比 IPv4 地址大得多,使用点分十进制表示法会变得很成问题。为了使用这种表示法,我们需要将 128 位分成 16 个八位字节,并用 0 到 255 之间的十进制数来表示每个字节。然而,我们最终得到的不是 4 个这样的数字,而是16个。按照这种表示法,一个典型的 IPv6 地址可能如下所示:

128.91.45.157.220.40.0.0.0.0.252.87.212.200.31.255

该地址的二元和点分十进制表示法显示在图 25-2 的顶部附近。在任何情况下,"优雅"这个词都不太可能立刻出现在你的脑海中。

IPv6 地址的二进制、十进制和十六进制表示。最上面两行显示了 IPv6 地址的二进制和点分十进制表示;这两种表示法都不常用(除了计算机本身之外!)。下表的最上面一行显示了完整的十六进制表示,而接下来的两行说明了零抑制和压缩。最后一行显示了混合表示法,其中 IPv6 地址的最后 32 位以点分十进制表示(212.200.31.255)。这最常用于嵌入式 IPv4 地址。

图 25-2. IPv6 地址的二进制、十进制和十六进制表示。最上面两行显示了 IPv6 地址的二进制和点分十进制表示;这两种表示法都不常用(除了计算机本身之外!)。下表的最上面一行显示了完整的十六进制表示,而接下来的两行说明了零抑制和压缩。最后一行显示了混合表示法,其中 IPv6 地址的最后 32 位以点分十进制表示(212.200.31.255)。这最常用于嵌入式 IPv4 地址。

IPv6 地址十六进制表示法

为了使地址更短,IPv6 中决定将表示地址的主要方法从十进制改为十六进制。这样做的好处是表示地址所需的字符更少,而且从十六进制到二进制以及反过来转换比从二进制到十进制或反过来转换要容易得多。缺点是许多人发现十六进制难以理解和处理,尤其是由于每个数字中包含 16 个值的概念有点奇怪。

用于 IPv6 地址的十六进制表示法与用于 IEEE 802 MAC 地址以及类似以太网等技术的相同方法相似。在这些 MAC 地址中,48 位由 6 个八位字节表示,每个八位字节是一个从 0 到 FF 的十六进制数,由破折号或冒号分隔,如下所示:

0A-A7-94-07-CB-D0

由于 IPv6 地址更大,它们被分成八个 16 位 单词,并用冒号分隔,从而形成了有时被称为 冒号十六进制表示法 的格式,如图 25-2 所示。因此,前面例子中的 IPv6 地址可以这样表示:

805B:2D9D:DC28:0000:0000:FC57:D4C8:1FFF

为了减小地址的大小,可以在表示法中省略前导零,这样你可以立即将其简化为以下形式:

805B:2D9D:DC28:0:0:FC57:D4C8:1FFF

好吧,这确实比点分十进制表示法短,但仍然相当长。当你处理这么大的数字时,你能做的只有这么多。这也是为什么在 IPv6 下使用域名系统(DNS)名称来表示主机比在 IPv4 下更为重要的部分:谁会记得那么长的十六进制地址呢?

IPv6 地址中的零压缩

幸运的是,有一种快捷方式可以进一步缩短某些地址。这种技术有时被称为零压缩。这种方法允许将 IPv6 地址中的一个连续的零字符串替换为双冒号。例如,前面的地址可以这样表示:

805B:2D9D:DC28::FC57:D4C8:1FFF

你知道有多少零被两个冒号(::)替换,因为你可以看到地址中有多少完全表示(未压缩)的十六进制词。在这种情况下,有六个,所以::代表两个零词。为了避免歧义,双冒号在任何 IP 地址中只能出现一次,因为如果出现多次,你将无法确定每个实例中替换了多少零。所以,如果示例地址是 805B:2D9D:DC28:0:0:FC57:0:0,你可以替换第一对零或第二对,但不能同时替换。

零压缩并没有使示例变得更短,但由于 IPv6 地址的结构,长串的零是常见的。例如,考虑以下地址:

FF00:4501:0:0:0:0:0:32

使用压缩,它可以缩短为以下形式:

FF00:4501::32

这种技术在特殊地址上效果更好。完整的 IPv6 回环地址写法如下:

0:0:0:0:0:0:0:1

使用压缩,回环地址看起来是这样的:

::1

为了更有趣,考虑特别奇怪的 IPv6 未指定地址,如下所示:

0:0:0:0:0:0:0:0

对一个全为零的地址应用零压缩,你会得到什么?

::

没有任何数字!当然,将::视为地址确实需要一些习惯。

小贴士

关键概念 为了简洁起见,IPv6 地址使用八组四位十六进制数字表示,这种形式称为冒号十六进制表示法。此外,还使用称为零省略零压缩的技术,通过从地址的表示中删除不必要的零来进一步减小显示地址的大小。

IPv6 混合表示法

在某些情况下,也使用了一种替代表示法,特别是用于表示嵌入 IPv4 地址的 IPv6 地址(本章后面将讨论)。对于这些地址,显示地址的 IPv4 部分以较旧的点分十进制表示法是有用的,因为这是你用于 IPv4 的表示法。由于嵌入使用最后 32 位作为 IPv4 地址,因此表示法具有以冒号十六进制表示法显示的前 96 位和以点分十进制显示的最后 32 位。因此,再次以先前的例子为例,在 混合表示法 中,它将如下所示:

805B:2D9D:DC28::FC57:212.200.31.255

这并不是混合表示法的很好例子,因为嵌入通常涉及长串零后面跟着 IPv4 地址。因此,零压缩在这里非常有用。你不会看到如下这样的内容:

0:0:0:0:0:0:212.200.31.255

你通常会看到这样的:

::212.200.31.255

乍一看,这似乎是一个 IPv4 地址。你必须密切关注 IPv6 中的那些冒号!

提示

关键概念 对于最后 32 位包含嵌入的 IPv4 地址的 IPv6 地址,定义了一种特殊的混合表示法。在这种表示法中,前 96 位以常规的冒号十六进制表示法显示,而最后 32 位以 IPv4 风格的点分十进制表示法显示。

IPv6 地址前缀长度表示

与 IPv4 无类地址一样,IPv6 地址在本质上被分成若干个网络 ID 位,后面跟着若干个主机 ID 位。网络标识符被称为 前缀,使用的位数是 前缀长度。这个前缀通过在地址后添加斜杠,然后在斜杠后放置前缀长度来表示。这是用于 CIDR 的无类 IPv4 地址的相同方法。例如,如果样本地址的前 48 位是网络 ID(前缀),那么我们将表示为 805B:2D9D:DC28::FC57:D4C8:1FFF/48。

提示

关键概念 在 IPv6 中,地址前缀的大小由跟在地址后面的前缀长度指示,用斜杠分隔,就像在 IPv4 无类地址中做的那样。

与 IPv4 类似,整个网络的指定符通常以长串零结尾。这些可以用双冒号(::)替换,使用零压缩。例如,前一个示例的 48 位网络 ID 是 805B:2D9D:DC28:0:0:0:0:0/48,或 805B:2D9D:DC28::/48。如果你替换了尾随的零,必须 包含 "::"。

IPv6 地址空间分配

经过多年处理非常小的 IPv4 地址空间之后,IPv6 中巨大的地址数量一定让互联网工程任务组(IETF)的工程师们感觉像是在糖果店里的孩子。然而,他们都是好孩子,并没有乱跑,抓取他们能找到的所有糖果并吞下去。他们非常仔细地考虑了如何为各种用途划分地址空间。当然,当你有这么多糖果时,分享变得相当容易。

与 IPv4 一样,在决定如何划分 IPv6 地址空间时,有两个主要问题:地址分配和路由。IPv6 的设计者希望结构化地址空间,使得将地址分配给互联网服务提供商(ISP)、组织和个人尽可能容易。

起初,也许具有讽刺意味的是,这使 IPv6 的创造者回到了使用特定比特序列来识别不同类型地址的老路,就像旧的类地址方案一样。地址类型由地址开头的一组比特表示,称为格式前缀(FP)。格式前缀在概念上与 IPv4 类地址中用于表示地址类的 1 到 4 比特相同,但长度是可变的,范围从 3 到 10 比特。格式前缀在 RFC 2373 中进行了描述。

在 RFC 2373 发布后的几年里,管理互联网的大师们对地址块应该如何考虑有了新的看法。他们仍然希望将 IPv6 地址空间划分为不同大小的块以供不同目的使用。然而,他们意识到许多人开始认为使用格式前缀与旧的基于类的 IPv4 系统相当。他们主要担心的是,实施者可能会在 IPv6 硬件逻辑中编程,仅根据地址的前几个比特进行路由决策。这特别不是IPv6 应该工作的方式;一方面,分配是可能改变的。

因此,RFC 3513 中做出的修改之一是改变有关 IPv6 地址分配的语言,特别是从标准中删除了术语格式前缀。地址空间的各个部分的分配仍然基于地址的前三到十个比特的特定模式,以便某些类别比其他类别拥有更多的地址。消除表示这一点的特定术语是为了传达这些比特不应给予特殊关注。

表 25-1 显示了 IPv6 地址空间的分配以及每个分配占总地址空间的多少。

表 25-1. IPv6 地址空间分配

前导比特 IPv6 地址空间总量的比例 分配
0000 0000 1/256 未分配(包括特殊地址,如未指定地址和环回地址)
0000 0001 1/256 未分配
0000 001 1/128 保留用于 NSAP 地址分配
0000 01 1/64 未分配
0000 1 1/32 未分配
0001 1/16 未分配
001 1/8 全球单播地址
010 1/8 未分配
011 1/8 未分配
100 1/8 未分配
101 1/8 未分配
110 1/8 未分配
1110 1/16 未分配
1111 0 1/32 未分配
1111 10 1/64 未分配
1111 110 1/128 未分配
1111 1110 0 1/512 未分配
1111 1110 10 1/1024 链路本地单播地址
1111 1110 11 1/1024 站点本地单播地址
1111 1111 1/256 组播地址

这比 IPv4 的类地址方案更复杂,因为类别更多,大小差异很大,即使大多数目前尚未分配。

要更好地理解这个表格,可以考虑将 IPv6 地址空间划分为八分之一。在这八个组中,一个(001)已被保留用于单播地址;第二个(000)被用来划分更小的保留块,第三个(111)被用来为本地和组播地址的子块。其余五个完全未分配。

你可以看到,IPv6 的设计者非常小心地只为每种地址类型分配了地址空间中他们认为需要的“八分之一”部分。例如,以 111 开头的地址空间部分只使用了很小的一部分,大部分留空。总的来说,目前只分配了地址空间的 71/512,大约 14%,其余的 86%尚未分配,留作将来使用。(记住,即使是 IPv6 地址空间的 1/1024 也是巨大的——它代表了数万亿的地址。)

本章后面的部分提供了关于这些地址块中几个地址块更多的信息。请注意,0000 0000 保留块用于几种特殊地址类型,包括环回地址、未指定地址和 IPv4 地址嵌入。1111 1111 格式前缀标识组播地址;这个字符串在十六进制中是 FF,所以任何以 FF 开头的地址在 IPv6 中都是组播地址。

IPv6 全局单播地址格式

预计在 IPv6 下,单播地址将被用于绝大多数互联网流量,就像在 IPv4 中一样。正因为如此,分配给 IPv6 地址空间的最大块被用于单播地址。整个地址空间的八分之一被分配给单播地址,这由地址前三位中的 001 表示。问题是:我们如何使用宽敞的 IP 地址中剩余的 125 位?

结构化单播地址块的理由

当 IPv4 最初被创建时,互联网相对较小,地址块的分配模式基于一个中央协调者:互联网数字分配机构(IANA)。任何想要地址块的人都会直接前往中央权威机构。随着互联网的发展,这种模式变得不切实际。如今,IPv4 的无类别地址方案允许可变长度的网络 ID 和地址块的分层分配。大型 ISP 从中央权威机构获得大块地址,然后将其细分并分配给客户,等等。这由今天的 ISP 管理,但在地址空间中没有帮助管理分配过程的东西。反过来,每个组织都有能力进一步细分其地址分配,以满足其内部需求。

IPv6 的设计者受益于这一经验,并意识到将单播地址结构设计成反映互联网整体拓扑结构将带来巨大的优势。以下是一些包括的内容:

  • 在互联网拓扑层次结构的各个级别上更容易分配地址块。

  • IP 网络地址能够自动反映路由器在互联网中传输信息时所采用的层次结构,从而使得路由可以轻松聚合,实现更有效的路由。

  • 为像 ISP 这样的组织提供灵活性,以便将地址块细分以供客户使用。

  • 为终端用户组织提供灵活性,以便将地址块细分以匹配内部网络,就像 IPv4 中的子网划分一样。

  • IP 地址具有更大的意义。不再是 128 位无结构的字符串,而是可以查看地址并了解其某些信息。

单播地址空间的通用划分

将单播地址空间的 128 位最通用地划分为三个部分,如图表 25-2 所示。

表 25-2. 通用 IPv6 全局单播地址格式

字段名称 大小(位) 描述
前缀 n 全局路由前缀:地址的网络 ID 或前缀,用于路由。
子网 ID m 子网标识符:一个数字,用于标识站点内的子网。
接口 ID 128-n-m 接口标识符:特定接口(主机或其他设备)的唯一标识符。它在特定的前缀和子网内是唯一的。

全局路由前缀子网标识符代表了地址需要按层次结构构建的两个基本级别:即全球和特定站点。路由前缀由一定数量的位组成,可以根据互联网注册机构和 ISP 的需求进一步细分。这种细分反映了整个互联网的地形。子网 ID 为站点管理员提供了一定数量的位,以便创建适合每个管理员需求的内部网络结构。

IPv6 单播地址空间实现

在理论上,可以使用任何大小的nm(参见表 25-2 所示,并在图 25-3 中说明。

表 25-3. IPv6 全局单播地址格式

字段名称 大小(位) 描述
前缀 48 全局路由前缀:用于路由的地址的网络 ID 或前缀。前三位是 001,表示单播地址。
子网 ID 16 子网标识符:一个标识站点内子网的数字。
接口 ID 64 接口 ID:特定接口(主机或其他设备)的唯一标识符。它在特定的前缀和子网内是唯一的。

IPv6 全局单播地址格式

图 25-3. IPv6 全局单播地址格式

提示

关键概念 IPv6 地址空间中为单播地址预留的部分被组织成一个地址格式,其中使用前 48 位作为路由前缀(类似于网络 ID),接下来的 16 位作为子网 ID,最后的 64 位作为接口 ID(类似于主机 ID)。

由于这种结构,大多数终端站点(与 ISP 相比,是普通公司和组织)将被分配具有 48 位前缀的 IPv6 网络。在常见的说法中,这些网络标识符现在被称为48s/48s

子网 ID 的 16 位允许每个站点在创建反映站点网络结构的子网时有相当大的灵活性。以下是一些 16 位的使用示例:

  • 较小的组织可以将子网 ID 中的所有位都设置为 0,并拥有一个扁平的内部结构。

  • 一个中等规模的组织可以使用子网 ID 中的所有位来执行 IPv4 下的直接子网划分,从而为每个子网分配不同的子网 ID。这里有 16 位,这允许有 65,536 个子网!

  • 一个较大的组织可以使用这些位来创建多个级别的子网层次结构,就像 IPv4 的可变长度子网掩码(VLSM)一样。例如,公司可以使用两个位来创建四个子网。然后,它可以使用接下来的三个位在四个子网中的某些或全部子网中创建八个子子网。还有 11 个位可以用来创建更下一级的子子子网,以此类推。

全球路由前缀的原有划分:聚合器

全球路由前缀被类似地划分为一个层次结构,但这是一个为整个互联网使用而设计的层次结构,就像 CIDR。这里有 45 位可用(48 位减去固定的前三位 001)。这相当多。当 RFC 2374 首次详细说明单播地址结构时,该文件描述了基于互联网注册机构和提供商的两级层次拓扑结构的具体 45 位划分。这些组织被描述如下:

顶级聚合器(TLAs) 这些指的是最大的互联网组织,它们将从注册机构那里分配大量的 IPv6 地址。

下一级聚合器(NLAs) 这些组织将从顶级聚合器(TLAs)那里获得地址块,并将它们分配给最终用户组织(站点)。

45 位在这两个用途之间分配,中间保留了一些位,以便在需要时扩展任一字段。因此,RFC 2374 结构中的 45 位看起来就像表 25-4 中列出的一样。

表 25-4. 历史 IPv6 单播路由前缀结构

字段名称 大小(位) 描述
TLA ID 13 顶级聚合(TLA)标识符:顶级聚合器的全局唯一标识符。有 13 位,因此允许的最大 TLA 数量为 8,192 个。
RES 8 保留:这 8 位被保留供将来使用,并设置为 0。通过在 TLA ID 和 NLA ID 之间留出这 8 位未使用,它们可以在需要时扩展 TLA ID 或 NLA ID 字段。
NLA ID 24 下一级聚合(NLA)标识符:每个 TLA 都被分配了这个 24 位字段,用于为其客户分配地址块。NLA ID 对于每个 TLA ID 是唯一的。24 位的使用由 TLA 组织自行决定。

你会注意到我在描述 TLA/NLA 结构时使用了过去时态,而且那个表头也是一个很大的提示。2003 年 8 月,RFC 3587 被发布,简而言之就是,“嗯,关于所有那些 TLA/NLA 的事情就别管了。”决定将这种结构硬编码到互联网标准中是不灵活的,让区域互联网注册机构(APNIC、ARIN、LACNIC 和 RIPE)自己决定如何使用这 45 位似乎更有意义。

注意

TLA/NLA 结构的淘汰是在人们习惯了多年之后发生的,所以在未来一段时间内,你仍然会经常在 IPv6 描述中看到这些术语。这就是为什么我在这里讨论了它们。)

全球路由前缀分层划分的示例

在全球单播层次结构中,没有单一的结构来确定 48 位路由前缀如何划分。例如,它可能被划分为三个层次,如表 25-5 所示,并在图 25-4

图 25-4. IPv6 单播路由前缀结构示例。最上面一行显示了全局 IPv6 单播地址格式。第二行展示了将全局路由前缀分别使用 10、12 和 23 位划分为三个级别的示例。第三行展示了如何使用前 10 位来创建 210,即 1,024 个不同级别的 1 号块。下一行说明了对于这些 13 位前缀中的每一个,你可以有 212,即 4,096 个级别的 2 号块。然后,在每个 25 位的级别 2 ID 中,你有 23 位,即 8,388,608 个级别的 3 号块。在最下面,一个级别 3 或/48 将被分配给一个单独的组织。

这只是/48 网络地址中位分配的一种可能的理论方式。正如你所见,有这么多位,有很大的灵活性。在之前的方案中,你可以拥有超过四百万个级别 2 的组织,每个组织可以分配八百万个/48 地址。而且每个组织的大小相当于一个 IPv4 类 B 地址(超过 65,000 个主机)!

移除 RFC 2374 中全局路由前缀的固定结构与 IPv6 开发团队强调的位字段和结构仅用于地址分配而不用于路由目的的努力是一致的。一旦创建,地址本身不会根据这种格式在网络互连中的硬件上进行解释。对于路由器来说,唯一重要的是由 IP 地址后面的前缀长度给出的网络 ID 和主机 ID 之间的划分,这种划分可以在任何位边界发生。这些硬件设备只看到 IP 地址的 128 位,并使用它,而不了解层次地址划分或级别。

顺便说一下,获得可聚合单播地址格式分配好处的关键在于 IPv6 下我们可用的位非常多。在仍然允许 64 位用于接口标识符的同时拥有这些层次级别是 IPv6 设计者从 32 位到 128 位地址大小的主要原因之一。通过创建这种结构,我们保持了灵活性,同时避免了在 128 位内尝试分配许多不同网络大小的潜在混乱。

注意,任播地址的结构与单播地址相同,因此它们根据相同的模型分配。(多播地址不是。)

IPv6 接口标识符和物理地址映射

在 IPv4 中,IP 地址与底层数据链路层网络技术使用的地址没有关系。一个使用以太网网络接口卡(NIC)连接到 TCP/IP 网络的宿主具有一个以太网 MAC 地址和一个 IP 地址,但这两个数字是不同的,并且以任何方式都不相关。IP 地址是由管理员手动分配的,不考虑底层物理地址。

随着 IPv6 地址系统的全面更新,出现了一个机会,可以创建一种更好的方法来映射 IP 单播地址和物理网络地址。实施这种高级映射技术是 IPv6 地址被设计得如此大的原因之一。总共有 128 位,即使有 45 位被保留用于网络前缀和 16 位用于站点子网,我们仍然有 64 位可用于接口标识符(接口 ID),这在 IPv4 中类似于主机 ID。

拥有如此多的位给我们带来了极大的灵活性。我们不再需要为宿主使用任意编造的标识符,只要底层数据链路层硬件地址的长度不超过 64 位,我们就可以基于该地址创建接口 ID。由于几乎所有设备都使用 64 位或更短的第二层地址,因此将这些地址用于 IP 地址中的接口 ID 没有问题。这提供了一个直接的好处:它使得网络管理变得更加容易,因为我们不需要为每个宿主记录两个任意数字。IP 地址可以从 MAC 地址和网络 ID 中推导出来。这也意味着我们可以从 MAC 地址和 IP 地址中区分开来,反之亦然。

实际上,从数据链路层地址映射到 IP 接口 ID 取决于特定的技术。当然,同一网络上的所有设备使用相同的映射技术是至关重要的。到目前为止,网络中最常见的第二层地址是 IEEE 802 MAC 地址,这些地址被以太网和其他 IEEE 802 项目网络技术所使用。这些地址有 48 位,分为两个 24 位的块。上面的 24 位被组织成一个称为组织唯一标识符(OUI)的块,不同的值分配给各个组织。下面的 24 位用于每个特定设备的标识符。

IEEE 还定义了一种称为64 位扩展唯一标识符的格式,简称EUI-64。它与 48 位的 MAC 格式相似,除了 OUI 保持为 24 位外,设备标识符变为 40 位而不是 24 位。这给每个制造商提供了 65,536 倍的设备地址空间在其 OUI 内。

这种格式的形式,称为修改后的 EUI-64,已被采用作为 IPv6 接口 ID。要获取设备的修改后的 EUI-64 接口 ID,你只需将 EUI-64 地址并将第七位(通用/本地,或 U/L,位)从 0 改为 1。

当然,大多数设备仍然使用旧的 48 位 MAC 地址格式。这些可以转换为 EUI-64,然后修改为 EUI-64 形式以创建 IPv6 接口 ID。过程如下:

  1. 将 24 位的 OUI 部分,即以太网地址的最左边 24 位,放入接口 ID 的最左边 24 位。将 24 位的本地部分(以太网地址的最右边 24 位)放入接口 ID 的最右边 24 位。

  2. 在接口 ID 中间的剩余 16 位中,放入值 11111111 11111110,即十六进制的 FF FE。

  3. 现在地址处于 EUI-64 形式。将通用/本地位(从左数第七位,在图 25-5 中用粗体表示)从 0 改为 1。这给出了修改后的 EUI-64 接口 ID。

提示

关键概念 IPv6 单播地址的最后 64 位用于接口 ID,这些接口 ID 以称为修改后的 EUI-64的特殊格式创建。可以使用一个简单的流程从类似以太网网络接口卡的 48 位 MAC 地址中确定接口 ID。然后,可以将网络前缀(路由前缀和子网 ID)与之结合,以确定设备的相应 IPv6 地址。

以 39-A7-94-07-CB-D0 的以太网地址为例。以下是转换步骤(在图 25-5 中说明):

  1. 将标识符的前 24 位 39-A7-94 放入地址的第一个(最左边的)24 位。07-CB-D0 的本地部分成为标识符的最后 24 位。

  2. 中间的 16 位赋予值 FF-FE。

  3. 将第七位从 0 改为 1,这将第一个八位字节从 39 改为 3B。

因此,标识符变为 3B-A7-94-FF-FE-07-CB-D0,或者用 IPv6 冒号十六进制表示法,3BA7:94FF:FE07:CBD0。设备地址的前 64 位使用全局单播地址格式提供。

这种技术的唯一缺点是,如果物理硬件发生变化,IPv6 地址也会发生变化。

IPv6 特殊地址:保留、私有、未指定和环回

正如某些 IPv4 地址范围被指定用于保留、私有和其他不寻常的地址一样,IPv6 的巨大地址空间中的一部分也被预留用于特殊地址。这些地址和地址块的目的在于为 IPv6 网络中的特殊需求和私有用途提供地址。由于即使是相对较小的 IPv6 地址空间也非常巨大,因此为特定用途预留地址空间的 0.1% 通常会产生比任何人需要的都多的地址。

将 IEEE 802 MAC 地址转换为 IPv6 修改后的 EUI-64 标识符

图 25-5. 将 IEEE 802 MAC 地址转换为 IPv6 修改后的 EUI-64 标识符

特殊地址类型

IPv6 有四种基本类型的特殊地址:

保留地址 地址空间的一部分被预留,供 IETF 现在和未来的各种用途使用。与地址空间中分散的多个小保留块不同,IPv6 中的保留块位于地址空间的“顶部”,从 0000 0000(或第一个十六进制八位字节为 00)开始。这代表了总地址空间的 1/256。你很快就会看到的一些特殊地址就来自这个块。IPv4 地址嵌入也在此保留地址区域内进行。

注意

保留地址与未分配地址不同。后者仅指尚未确定用途的块

私有/未注册/不可路由地址 与 IPv4 类似,预留了一块地址用于私有地址,但与 IPv6 中的所有事物一样,IPv6 中的私有地址块要大得多。这些私有地址仅限于特定的链路或站点本地,因此永远不会被路由到特定公司的网络之外。私有地址通过地址的前九位为“1111 1110 1”来表示。因此,私有地址的十六进制第一个八位字节值为 FE,下一个十六进制数字为 8 到 F。这些地址根据它们的范围进一步分为两种类型:站点本地和链路本地,如稍后所述。

环回地址 与 IPv4 类似,已经为测试目的预留了一个特殊的环回地址;发送到该地址的数据报文会“回环”到发送设备。然而,在 IPv6 中,只有一个这样的地址,而不是一个整个块(最初也从未需要过)。环回地址是 0:0:0:0:0:0:0:1,通常使用零压缩表示为 ::1。

未指定地址 在 IPv4 中,全零的 IP 地址具有特殊含义:它指的是主机本身,当设备不知道自己的地址时使用。在 IPv6 中,这个概念已经被正式化,全零地址(0:0:0:0:0:0:0:0)被称为未指定地址。它通常用于设备发送的报文源字段中,以配置其 IP 地址。可以对这个地址应用零压缩;由于它是全零,地址就变成了::。(我个人认为这很令人困惑。我认为像 0::0 这样的表示法既清晰又简洁。)

提示

关键概念 在 IPv6 中,一个特殊的环回地址,0:0:0:0:0:0:0:1(压缩形式为::1)被预留用于测试目的。未指定地址,0:0:0:0:0:0:0:0(压缩形式为::)用于表示未知地址。定义了一个私有本地地址块。这个块是所有以 1111 1110 1 作为前九位开始的地址集合。

IPv6 私有地址类型范围

现在我们来更详细地看看私有地址。在 IPv6 中,这些被称为本地使用地址,名称清楚地说明了它们的作用。它们有时也被称为链路层地址。你会记得,在无法为所有设备获取公共地址时,IPv4 私有地址通常被使用,有时与网络地址转换(NAT)等技术结合使用。在 IPv6 中,不需要像 NAT 这样的技巧。相反,本地使用地址旨在用于仅设计为发送到本地设备的通信。例如,使用 IPv6 邻居发现(ND)协议的邻居发现功能采用本地使用地址。

本地地址的范围显然是本地网络,而不是公共互联网地址的全局范围。IPv6 中的本地地址进一步分为两种类型,反映了本地范围的划分:

站点本地地址 这些地址的范围是整个站点或组织。它们允许在组织内部进行寻址,而无需使用公共前缀。路由器将在站点内使用站点本地地址转发数据报,但不会将站点外的地址转发到公共互联网。站点本地地址通过在所有私有 IPv6 地址共有的九位起始地址之后有一个 1 位来与链路本地地址区分。因此,它们以 1111 1110 11 开始。以十六进制表示,站点本地地址以 FE 开始,然后是第三位的 C 到 F。因此,这些地址以 FEC、FED、FEE 或 FEF 开始。

链路本地地址 这些地址的范围比站点本地地址小;它们仅指特定的物理链路(物理网络)。路由器不会转发使用链路本地地址的数据报,甚至不在组织内部转发。这些地址仅用于特定物理网络段上的本地通信。它们可用于地址配置或用于 ND 功能,如地址解析和 ND。链路本地地址通过在所有私有 IPv6 地址共有的前九位地址之后跟一个 0 位来区分站点本地地址:1111 1110 1。因此,站点本地地址以 FE 开头,然后是第三十六进制位的 8 到 B。因此,这些地址以 FE8、FE9、FEA 或 FEB 开头。

小贴士

关键概念 IPv6 站点本地地址只允许数据发送到站点或组织内的设备。它们以十六进制的 FEC、FED、FEE 或 FEF 开头。IPv6 链路本地地址仅在特定的本地链路(物理网络)上使用,通常用于特殊目的,如地址解析或邻居发现(ND)。它们以 FE8、FE9、FEA 或 FEB 开头。

注意,站点本地 IPv6 地址相当于 IPv4 私有地址,因为它们在整个组织中路由。链路本地范围的概念在 IPv6 中是新的。

IPv6/IPv4 地址嵌入

由于 IP 的重要性以及 IPv6 中做出的变更的重要性,新版本的协议的部署不会一次性完成。需要从 IPv4 向 IPv6 的过渡。这次过渡需要周密的规划。正如我之前提到的,预计从 IPv4 到 IPv6 的迁移将需要很多年。

如果使用特殊技术,IPv6 与 IPv4 向后兼容。例如,为了在通过 IPv4 网络连接的 IPv6 设备岛屿之间启用通信,您可能需要使用隧道。为了支持 IPv4/IPv6 兼容性,开发了一种方案,允许 IPv4 地址嵌入到 IPv6 地址结构中。这种方法将常规 IPv4 地址放入特殊的 IPv6 格式中,以便某些 IPv6 设备将其识别为 IPv4 地址。

由于 IPv6 地址空间比 IPv4 大得多,将后者嵌入前者很容易——就像将紧凑型轿车塞进货轮的货舱一样!嵌入地址空间是地址块的一部分,其地址以八个 0 位开始,但它只是相对较小的一部分。使用两种不同的嵌入格式来指示使用嵌入地址的设备的性能:

IPv4 兼容的 IPv6 地址 这些是分配给 IPv6 兼容设备的特殊地址,例如同时使用 IPv4 和 IPv6 的 双栈 设备。它们中间的 16 位都是零;因此,它们以一串 96 个零位开始,后面跟着 IPv4 地址。这种地址的一个例子是混合表示法中的 0:0:0:0:0:0:101.45.75.219,或者更简洁地,::101.45.75.219。图 25-6 展示了 IPv4 兼容的 IPv6 表示。

IPv4 映射 IPv6 地址 这些是已映射到 IPv6 地址空间的常规 IPv4 地址。它们用于仅具有 IPv4 功能的设备。它们在初始的 80 个零位之后有一组 16 个一,然后是 IPv4 地址。所以如果一个 IPv4 设备具有地址 222.1.41.90,例如图 25-7 中显示的设备,它将被表示为 0:0:0:0:0:FFFF:222.1.41.90,或者 ::FFFF:222.1.41.90。

IPv4 兼容的嵌入式 IPv6 地址表示

图 25-6. IPv4 兼容的嵌入式 IPv6 地址表示

这两者之间的区别微妙但很重要。它们地址的前 80 位都是零,并将嵌入的 IPv4 地址放入 IPv6 地址格式的最后 32 位。它们在中间的 16 位(从左数第 81 位到第 96 位)的值不同。IPv4 兼容的 IPv6 地址仅用于实际具有 IPv6 意识的设备;IPv4 兼容的地址是其传统 IPv6 地址的补充。相比之下,如果在初始的 80 位之后看到 FFFF,这表示一个传统的 IPv4 设备,其 IPv4 地址已被映射到 IPv6 格式。它不是一个具有 IPv6 功能的设备。

IPv4 映射的嵌入式 IPv6 地址表示

图 25-7. IPv4 映射的嵌入式 IPv6 地址表示

提示

关键概念 IPv4 地址嵌入 用于在 IPv4 地址和 IPv6 地址之间建立关系,以帮助您从 IPv4 过渡到 IPv6。一种类型,即 IPv4 兼容的 IPv6 地址,用于同时兼容 IPv4 和 IPv6 的设备;它以 96 个零位开始。另一种,即 IPv4 映射地址,用于将不兼容 IPv6 的 IPv4 设备映射到 IPv6 地址空间;它以 80 个零位开始,然后是 16 个一。

IPv6 多播和任播寻址

在 IPv6 的通用寻址模型中,最显著的修改之一是对基本地址类型及其使用方式的改变。单播地址仍然像在 IPv4 中一样,是绝大多数通信的选择,但在 IPv6 中,“批量”寻址方法有所不同。作为特定寻址类型的广播已被消除。相反,对多播寻址的支持得到了扩展,并成为协议的必要部分,并实现了一种称为任播的新类型地址。

IPv6 多播地址

让我们从 IPv6 下的多播开始看起。多播允许单个设备向一组接收者发送数据报。IPv4 支持使用无类别寻址方案中的 D 类地址块进行多播寻址(见第十七章中解释,并在图 25-8 中展示。

IPv6 多播地址格式

图 25-8. IPv6 多播地址格式

表 25-6. IPv6 多播地址格式

字段名称 大小(位) 描述
(指示符) 8 前八位始终是 1111 1111,这表示一个多播地址。在术语被取消之前,这被称为格式前缀(如本章前面关于 IPv6 地址空间分配的章节中所述)。该字段现在没有名称。
标志 4 四位保留用于可以用来指示某些多播地址性质的标志。目前,这其中的前三个是未使用的,设置为 0。第四个是 T(瞬态)标志。如果保持为 0,则将多播地址标记为永久分配的、众所周知的多播地址,正如你将很快看到的。如果设置为 1,这意味着这是一个瞬态多播地址,意味着它不是永久分配的。
范围 ID 4 这四个位用于定义多播地址的范围;从 0 到 15 的 16 个不同值是可能的。该字段允许创建全局多播地址,或限制在更小的范围,如特定组织、站点或链路。当前定义的值(十进制)如下:0 = 保留 1 = 节点本地范围 2 = 链路本地范围 5 = 站点本地范围 8 = 组织本地范围 14 = 全局范围 15 = 保留
群组 ID 112 定义每个范围级别内的特定组。

多播范围

显式定义多播地址的范围的概念非常重要。全局范围的多播地址在整个互联网中必须是唯一的,但本地范围地址仅在组织内部是唯一的。这提供了极大的灵活性,因为每种类型的多播地址实际上都有几个版本:一个只在节点内部多播的版本,一个在本地链路(本地网络)上多播的版本,一个在本地站点上多播的版本,等等。范围还允许路由器立即确定它们应该将多播数据报传播得多广,以提高效率并消除将流量发送到预期范围之外的问题。图 25-9 以图形方式说明了多播范围的概念。

小贴士

关键概念 多播地址用于向互联网上的多个设备同时发送数据。在 IPv6 中,每个多播地址可以指定为各种不同的范围,从而允许将传输针对广泛的或狭窄的接收设备受众。

IPv6 多播范围 此图展示了范围的概念如何使 IPv6 多播限制在特定的影响范围内。最紧密的范围是节点本地范围,其范围 ID 值为 1。随着范围 ID 值的增加,范围扩展以覆盖本地网络、站点、组织,最终涵盖整个互联网。

图 25-9. IPv6 多播范围 此图展示了范围的概念如何使 IPv6 多播限制在特定的影响范围内。最紧密的范围是节点本地范围,其范围 ID 值为 1。随着范围 ID 值的增加,范围扩展以覆盖本地网络、站点、组织,最终涵盖整个互联网。

常见多播地址

临时标志允许显式确定哪些多播地址可用于正常使用,与哪些保留为已知地址。通过保留用于多个范围 ID 值的一定数量的组 ID 来定义几个已知的多播地址。 表 25-7 显示了这些值;多播地址模式中的x是多位范围 ID 字段对应的十六进制数字。|

所有节点和所有路由器的多播地址实现了 IPv4 中广播所执行的功能的等效功能。同样,在这种类型的多播中,范围的概念非常重要,因为我们不希望尝试向全球互联网上的所有节点发送消息,例如。因此,当使用具有范围值 2 的全路由器地址时,意味着“本地链路上的所有路由器。”如果使用值为 5,则意味着“本站点的所有路由器。”

请求节点多播地址

除了常规的多播地址外,每个单播地址还有一个特殊的多播地址,称为其请求节点地址。此地址通过从设备的单播地址进行特殊映射创建。请求节点地址由 IPv6 ND 协议(参见第三十六章协议"))使用,以提供比 IPv4 中使用的地址解析协议(ARP;参见第十三章"))技术更有效的地址解析。

表 25-7. 重要 IPv6 已知多播地址

多播地址模式 有效范围值(十进制) 标识 描述
FF0x:0:0:0:0:0:0 0 到 15 保留 所有 112 位组 ID 为零的多播地址都是保留的。
FF0x:0:0:0:0:0:1 1, 2 所有节点 当组 ID 恰好等于 1 时,这表示向所有节点进行多播。既可以是节点本地(FF01:0:0:0:0:0:1)也可以是链路本地(FF02:0:0:0:0:0:1)的所有节点多播地址。
FF0x:0:0:0:0:0:2 1, 2, 5 所有路由器 当组 ID 恰好等于 2 时,这指定了特定范围内的所有路由器作为接收者。有效的范围值包括节点本地、链路本地和站点本地。

所有请求节点地址的 T 标志都设置为 0,并且具有范围 ID 2,因此它们以 FF02 开头。112 位的组 ID 如下分解(参见图 25-10

图 25-10. IPv6 solicited-node address calculation The solicited-node multicast address is calculated from a unicast address by taking the last 24 bits of the address and prepending them with the IPv6 partial address FF02:0:0:0:0:1:FF. This shows the example address from Figure 25-2. The top row of the lower table shows the full hexadecimal representation, while the next two rows illustrate zero suppression and compression. The last row shows mixed notation, with the final 32 bits of an IPv6 address shown in dotted decimal notation (212.200.31.255). This is most commonly used for embedded IPv4 addresses.") 转换为其 solicited-node 地址,FF02::1:FFC8:1FFF。

小贴士

关键概念 每个单播地址都有一个等效的 solicited-node multicast address,它是由单播地址创建的,并在其他设备需要在本地网络上访问它时使用。

IPv6 Anycast Addresses

Anycast addresses are a unique type of address that is new to IP in IPv6. The IPv6 implementation is based on the material in RFC 1546, "Host Anycasting Service." Anycast addresses can be considered a conceptual cross between unicast and multicast addressing. Where unicast says, "Send this to one address," and multicast says, "Send this to every member of this group," anycast says, "Send this to any one member of this group." Naturally, in choosing which member to send to, we would, for efficiency, normally send to the closest one—that is, the closest in routing terms. So, we can normally also consider anycast to mean, "Send this to the closest member of this group."

Anycast 背后的想法是使 TCP/IP 中以前难以实现的功能成为可能。Anycast 特别旨在在需要由多个不同服务器或路由器提供的服务的情况下提供灵活性,而我们并不关心哪个提供它。在路由方面,Anycast 允许数据报被发送到一组等效路由器中最近的任何一个路由器,并允许在路由器之间进行负载均衡,如果某些路由器停止服务,还可以提供动态灵活性。发送到 Anycast 地址的数据报将自动交付到最易到达的设备。

毫不奇怪,没有特殊的 Anycast 寻址方案。Anycast 地址与单播地址相同。当单播地址分配给多个接口时,Anycast 地址会自动创建。

小贴士

关键概念 Anycast 地址是 IPv6 中的新功能,可以用来设置一组设备,其中任何一个都可以对发送到单个 IP 地址的请求做出响应。

与多播一样,Anycast 为路由器增加了更多的工作量,因为它的复杂性比单播寻址更高。特别是,共享 Anycast 地址的设备距离越远,复杂性就越高。在全球互联网上进行 Anycasting 可能难以实现,IPv6 Anycasting 是为彼此靠近的设备设计的,通常在同一网络内。此外,目前由于互联网社区对 Anycast 的相对不熟悉,只有路由器,而不是单个主机,使用 Anycast 地址。

IPv6 自动配置和重新编号

在 IPv6 中实现的最有趣和可能最有价值的寻址功能之一是允许 IPv6 网络上的设备独立配置自己的功能。在 IPv4 中,主机最初是手动配置的。后来,如动态主机配置协议(DHCP;见第六十一章。

  1. 路由器方向 路由器向节点提供有关如何进行自动配置的指示。它可能告诉节点在这个网络中正在使用有状态自动配置,并可能提供要使用的 DHCP 服务器的地址。或者,它将告诉主机如何确定其全球互联网地址。

  2. 全局地址配置 假设网络中正在使用无状态自动配置,主机将使用其全局唯一的互联网地址进行配置。该地址通常由路由器提供给主机的网络前缀形成。前缀与设备标识符相结合,该标识符在第 1 步中生成。

显然,这种方法在手动和基于服务器的配置方法之上具有许多优势。它在支持 IP 设备的移动性方面尤其有用,因为它们可以移动到新的网络并获得有效的地址,而无需了解本地服务器或网络前缀。同时,如果需要,它仍然允许使用(IPv6 兼容的)DHCP 版本来管理 IP 地址。本地网络上的路由器通常会通过在 Internet 控制消息协议第 6 版(ICMPv6)路由器通告消息中的特殊标志来告诉主机支持哪种类型的自动配置(参见第三十五章)。

小贴士

关键概念 IPv6 包含一个有趣的功能,称为“无状态地址自动配置”,它允许主机通过遵循一个特殊程序,从其第 2 层地址确定自己的 IPv6 地址。

IPv6 设备重编号

设备重编号是与自动配置相关的方法。像主机配置一样,它可以通过使用像 DHCP 这样的协议,通过使用在一段时间后到期的 IP 地址租约来实现。在 IPv6 中,网络可以通过在自动配置时让路由器指定网络前缀的过期间隔来重编号。稍后,它们可以发送一个新的前缀来告诉设备重新生成它们的 IP 地址。设备实际上可以保持旧的不推荐地址一段时间,然后迁移到新地址。

RFC 2894 定义了一种用于重编号路由器地址的类似技术。它使用特殊的 ICMPv6 消息,并在第三十五章中描述。

第二十六章。IPv6 数据报封装和格式

无标题图片

在 Internet 协议版本 6(IPv6)互联网中传输数据是通过将高层数据封装到 IPv6 数据报中实现的。这些在 IPv6 中起到与 IPv4 数据报在旧版协议中相同的一般作用。然而,它们作为 IPv6 所代表的整体变化的组成部分进行了重新设计。IPv6 数据报具有灵活的结构,其格式更好地满足当前 IP 网络的需求。

在本章中,我将探讨 IPv6 数据报使用的格式。我首先概述 IPv6 数据报的一般结构,描述主要变更,并展示主头部和扩展头部在数据报中的排列方式。然后,我描述主头部的格式,定义并描述各种扩展头部类型。最后,我简要解释 IPv6 选项及其实现方式。

提示

背景信息 本章假设读者对 IPv6 地址概念有基本理解(参见上一章)并且对 IPv4 数据报格式有一般了解(在第二十一章中描述)

IPv6 数据报概述和一般结构

IPv6 封装从高层协议接收的数据以在互联网中传输的方法基本上与 IPv4 使用的方法相同。从传输或更高层接收的数据被作为 IPv6 数据报的有效负载,该数据报有一个或多个头部,用于控制消息的传递。这些头部向路由器提供信息,以便它们能够将数据报移动到网络中。它们还向主机提供信息,以便它们可以知道哪些数据报是针对它们的。

虽然自 IPv4 以来数据报的基本使用没有改变,但在创建 IPv6 时对其结构和格式进行了许多修改。这主要是出于必要性:IPv6 地址与 IPv4 地址不同,IP 地址位于数据报头部。IP 地址从 32 位增加到 128 位,在头部中增加了惊人的额外 192 位,即 24 字节的信息。这导致了一个努力,以移除那些并非绝对必要的字段,以补偿必要的尺寸增加。然而,对 IPv6 数据报的变更也包括添加功能以及使它们更好地满足现代互联网的需求。

以下是对 IPv6 中数据报最显著的总体变更列表:

多重头部结构 与包含所有字段(可能包括选项)的单个头部不同,IPv6 数据报支持一个主头部,并在需要时支持扩展头部以提供附加信息。

精简头部格式 已从主头部中删除了几个字段,以减小其大小并提高效率。只有真正对几乎所有数据报都必需的字段保留在主头部中;其他字段被放入扩展头部中,并在需要时使用。一些字段被删除,因为它们不再需要,例如互联网头部长度字段。IPv6 头部长度是固定的。我将在稍后更详细地检查这一点。

重命名字段 一些字段已被重命名,以更好地反映它们在现代网络中的实际用途。

更大的灵活性 扩展头允许在需要时伴随数据报传输大量额外信息。IPv6 也支持选项。

消除校验和计算 在 IPv6 中,不再在头部计算校验和。这节省了每个封装 IP 数据报的设备(主机和路由器)的计算时间,以及校验和字段在 IPv4 头部所占用的空间。

改进的服务质量支持 定义了一个新的字段,即流标签,以帮助支持流量的优先级。

提示

关键概念 IPv6 数据报使用一种通用结构,它以一个长度为 40 字节的强制主头开始,后面跟着可选的扩展头,然后是可变长度的数据区域。这种结构是为了使主头更加精简,同时允许设备在需要时向数据报添加额外信息。

如我之前所述,IPv6 数据报现在包括一个主头部格式(在标准中没有官方名称;它只是“头部”)和零个或多个扩展头部。IPv6 数据报的整体结构在 表 26-1 中显示,并在 图 26-1 中说明。

表 26-1. IPv6 通用数据报结构

组件 每个数据报的组件数量 大小(字节) 描述
主头 1 40 包含源地址和目的地址,以及每个数据报所需的重要信息。
扩展头部 0 或更多 可变 每个头部包含一种支持各种功能(包括分片、源路由、安全和选项)的额外信息。
数据 1 变量 将在数据报中传输的上层有效载荷。

IPv6 通用数据报结构

图 26-1. IPv6 通用数据报结构

注意,与 IPv4 一样,在封装之前可能会对大型有效载荷进行分片,以确保数据报的总大小不超过底层网络允许的最大大小。然而,IPv6 中的分片细节与 IPv4 不同,如第二十七章所述(第二十七章)。

IPv6 数据报主头部格式

IPv6 数据报使用一种包括常规头和可选的一个或多个扩展头的结构。这个常规头类似于 IPv4 数据报的头部,尽管它的格式不同,您将在下面看到。标准没有给这个头部命名;它只是“IPv6 头部”。为了区分 IPv6 扩展头部,我称之为“主头部”。

IPv6 的主要报头对于每个数据报都是必需的。它包含用于管理数据报处理和路由的地址和控制信息。IPv6 数据报的主要报头格式在表 26-2 中描述,并在图 26-2 中展示。

表 26-2. IPv6 主要报头格式

字段名称 大小(字节) 描述
版本 1/2 (4 位) 此字段标识用于生成数据报的 IP 版本。此字段的使用方式与 IPv4 相同,只是它携带的值是 6(二进制 0110)。
流类别 1 此字段替换了 IPv4 头中的服务类型(TOS)字段。它不是按照 TOS 字段最初定义的方式(使用优先级、D、T 和 R 位)使用,而是使用 RFC 2474 中定义的新区分服务(DS)方法。实际上,该 RFC 规定了 IPv4 和 IPv6 的质量服务(QoS)技术;有关更多信息,请参阅 IPv4 格式描述(第二十一章)。
流标签 2 1/2 (20 位) 这个大字段是为了提供对实时数据报交付和 QoS 功能的额外支持而创建的。在 RFC 2460 中将流定义为从源设备发送到一个或多个目标设备的数据报序列。使用唯一的流标签来标识特定流中的所有数据报,以便源设备和目标设备之间的所有路由器都以相同的方式处理它们。这有助于确保流中数据报的交付一致性。例如,如果视频流正在通过 IP 互联网发送,包含流的那些数据报可以通过流标签来识别,以确保它们以最小的延迟交付。并非所有设备和路由器都支持流标签处理,并且源设备使用该字段完全是可选的。此外,该字段仍然有些实验性,并且可能随着时间的推移而改进。
有效载荷长度 2 此字段替换了 IPv4 头中的总长度字段,但其使用方式不同。它不是测量整个数据报的长度,而是只包含有效载荷的字节数。然而,如果包含扩展头,它们的长度也在此处计算。简单来说,此字段测量数据报的长度,减去主要头本身的 40 个字节。
下一个头部 1 此字段代替了协议字段,有两个用途。当一个数据报有扩展头部时,此字段指定第一个扩展头部的标识符,它是数据报中的下一个头部。当一个数据报只有这个“主要”头部而没有扩展头部时,它具有与旧 IPv4 协议字段相同的作用,并且具有相同的值,尽管 IPv6 版本中常用协议使用的新数字。在这种情况下,“下一个头部”是 IPv6 数据报携带的更高层消息的头部。我将在本章稍后更详细地讨论这一点。
跳数限制 1 这代替了 IPv4 头部中的生存时间(TTL)字段;其名称更好地反映了现代网络中 TTL 的使用方式(因为 TTL 实际上用于计算跳数,而不是时间)。
源地址 16 数据报发送者的 128 位 IP 地址。与 IPv4 一样,这始终是最初发送数据报的设备。
目标地址 16 数据报预期接收者的 128 位 IP 地址:单播、任播或多播。同样,尽管路由器等设备可能是数据报的中间目标,但此字段始终用于最终目的地。

IPv6 主要头部格式

图 26-2. IPv6 主要头部格式

IPv6 下一个头部字段

下一个头部字段是 IPv6 数据报格式中最重要的新增功能之一。当 IPv6 数据报使用扩展头部时,此字段包含第一个扩展头部的标识符,该标识符反过来使用自己的下一个头部字段来指向下一个头部,依此类推。最后一个扩展头部随后引用封装的更高层协议。因为更高层协议的头部出现在 IPv6 数据字段的开头,所以它就像是接收数据报的设备眼中的“下一个头部”。对于一些人来说,这在概念上可能有点难以理解;你可以在本章后面的“使用下一个头部字段进行 IPv6 头部链接”部分找到更多关于该字段如何工作的细节(包括一个有用的插图,图 26-3)。

IPv6 中下一个头部字段的一些最常见值显示在表 26-3 中。

表 26-3. 常见 IPv6 下一个头部值

值(十六进制) 值(十进制) 协议/扩展头部
00 0 跳到跳选项扩展头部(请注意,在 IPv4 中此值是“保留”的)
01 1 互联网控制消息协议版本 4(ICMPv4)
02 2 互联网组管理协议版本 4(IGMPv4)
04 4 IP-in-IP 封装
06 6 传输控制协议(TCP)
08 8 外部网关协议(EGP)
11 17 用户数据报协议(UDP)
29 41 IPv6
2B 43 路由扩展头部
2C 44 分段扩展头部
2E 46 资源预留协议(RSVP)
32 50 加密安全有效载荷(ESP)扩展头部
33 51 认证头部(AH)扩展头部
3A 58 ICMPv6
3B 59 无下一个头部
3C 60 目的选项扩展头部

IPv6 主要头部格式的总长度为 40 字节。这是没有选项的 IPv4 头部大小的两倍,这主要是因为需要额外的 24 字节来容纳庞大的 IPv6 地址。IPv6 主要头部中只有 8 字节的非地址头部字段,而 IPv4 头部中有 12 个。

IPv4 和 IPv6 之间主要头部的关键变化

总结来说,IPv6 的主要头部与 IPv4 头部相比如下:

未更改字段 三个字段以相同的方式使用,并且保留了相同的名称(尽管它们的内容和/或大小不同):版本、源地址和目的地址。

重命名字段 两个字段以相同的方式使用,但被重新命名:流量类别和跳数限制。

修改字段 两个字段以类似的方式使用,但它们的意义略有不同,并且也被重新命名:有效载荷长度和下一个头部。

新增字段 有一个新字段:流标签。

移除字段 为了减少头部长度和不需要的工作,从 IPv6 头部中移除了五个 IPv4 头部字段:

  • 互联网头部长度字段不再需要,因为 IPv6 的主要头部长度固定为 40 字节。

  • 标识符、标志分段偏移量字段用于分段,在 IPv6 中比 IPv4 少用,因此这些字段现在仅在需要时出现在分段扩展头部中。

  • 头部校验和字段不再需要,因为决定在 IPv6 中消除头部校验计算。这被视为与高层错误检查和数据链路层 CRC 计算冗余。这为路由器节省了处理时间,并在数据报头部中节省了 2 个字节。

此外,虽然 IPv4 中选项曾经被认为是主要头部的一部分,但在 IPv6 中它们是分开的。

IPv6 数据报扩展头部

在 IPv6 数据报的强制主标题之后,可能有一或多个扩展标题出现在封装的有效载荷之前。这些标题是在尝试提供在创建 IPv6 数据报时的灵活性和效率而创建的。所有仅用于特殊目的的字段都被放入扩展标题中,并在需要时放入数据报。这使得主数据报标题的大小可以做得小而紧凑,只包含那些确实必须始终存在的字段。

关于扩展标题的作用经常存在混淆,尤其是在与数据报选项比较时。IPv4 数据报只有一个标题,但它包括了一个选项的条款,IPv6 也有选项,那么为什么还要麻烦扩展标题呢?

本来可以使用选项完成所有事情。然而,被认为更好的设计是为某些需要用于常见功能(如分段)的信息集使用扩展标题。确实,IPv6 仍然支持选项;它们通过提供可变长度的字段来提供更多的灵活性,这些字段可用于任何目的。它们本身是使用扩展标题定义的,正如你很快就会看到的。

当扩展标题包含在 IPv6 数据报中时,它们会依次出现在主标题之后。每种扩展标题类型都有自己的字段内部结构。

使用下一个标题字段进行 IPv6 标题链式连接

所有扩展标题类型共有的唯一字段是下一个标题字段,它实际上出现在 ESP 标题类型的末尾。8 位的下一个标题字段用于逻辑链接 IPv6 数据报中的所有标题,如下所示:

  • 主标题中的下一个标题字段包含第一个扩展标题类型的参考编号。

  • 第一个扩展标题中的下一个标题字段包含第二个扩展标题类型的编号,如果有第二个的话。如果有第三个,第二个标题的下一个标题指向它,依此类推。

  • 最后一个扩展标题的下一个标题字段包含封装的更高层协议的协议号。本质上,此字段指向有效载荷内的“下一个标题”。

例如,假设一个封装 TCP 的数据报有一个跳-跳选项扩展标题和一个分段扩展标题。那么,这些标题的下一个标题字段将包含以下值:

  • 主要标题的下一个标题值将是 0,表示跳-跳选项标题。

  • 跳-跳选项标题的下一个标题值将是 44(十进制),这是分段扩展标题的值。

  • 分段标题的下一个标题值将是 6。

这在 图 26-3 中进行了说明。

使用下一个头部字段链接 IPv6 扩展头部 IPv6 下一个头部字段允许设备更容易地处理接收到的 IPv6 数据报中的头部。当数据报没有扩展头部时,“下一个头部”实际上是 IP 数据字段开始的头部,在这种情况下,是一个值为 6 的 TCP 头部。这与 IPv4 中使用协议字段的方式相同。当出现扩展头部时,每个头部的下一个头部值包含一个表示数据报中后续头部类型的数字,因此它们逻辑上链接在一起。

图 26-3. 使用下一个头部字段链接 IPv6 扩展头部 IPv6 下一个头部字段允许设备更容易地处理接收到的 IPv6 数据报中的头部。当数据报没有扩展头部时,“下一个头部”实际上是 IP 数据字段开始的头部,在这种情况下,是一个值为 6 的 TCP 头部。这与 IPv4 中使用协议字段的方式相同。当出现扩展头部时,每个头部的下一个头部值包含一个表示数据报中后续头部类型的数字,因此它们逻辑上链接在一起。

提示

关键概念 IPv6 下一个头部字段用于将 IPv6 数据报中的头部链接在一起。主头部中的下一个头部字段包含第一个扩展头部的编号;其下一个头部包含第二个的编号,依此类推。数据报中的最后一个头部包含开始数据字段的封装协议的编号。

IPv6 扩展头信息摘要

表 26-4 列出了不同的扩展头部,显示了每个扩展头部的下一个头部值、长度、定义的 RFC 以及其简要使用说明。

表 26-4. IPv6 扩展头部

下一个头部值(十进制) 扩展头部名称 长度(字节) 描述 定义 RFC
0 跳到跳选项 可变 定义一组任意选项,这些选项旨在由从源设备到目的地设备(们)路径上的所有设备检查。这是用于定义可变格式选项的两个扩展头之一。 2460
43 路由 可变 定义一种允许源设备指定数据报路由的方法。此头部类型实际上允许定义多种路由类型。IPv6 标准定义了类型 0 路由扩展头,它等同于 IPv4 中的“宽松”源路由选项。它以类似的方式使用。请参阅本章的“IPv6 路由扩展头”部分,了解此扩展头的格式。 2460
44 分片 8 当数据报只包含原始消息的一部分时,包含从主头部移除的片段偏移量、标识符和更多片段字段。请参阅本章的“IPv6 分片扩展头”部分,了解此扩展头的格式,以及关于分片和重组的专题(第二十七章),了解字段的使用细节。 2460
50 封装安全载荷 (ESP) 可变 用于承载加密数据以实现安全通信。此头部在第二十九章中有详细描述,该章节涵盖了 IPsec。 2406
51 认证头 (AH) 可变 包含用于验证加密数据真实性的信息。此头部在第二十九章中有详细描述。 2402
60 目的选项 可变 定义一组任意选项,这些选项仅由数据报的目的地(们)检查。这是用于定义可变格式选项的两个扩展头之一。 2460

注意,IPv6 主头部的下一个头部值为 41;IPv4 头部的值为 4(其协议号)。还有一个名为“无下一个头部”的“虚拟”扩展头,其值为 59。这是一个占位符,当在下一个头部字段中找到时,表示该扩展头部之后没有其他内容。

如表 26-4 中所述,几个头部格式的提供在其他本书的部分。然而,我将在这里描述其中两个:路由扩展头和分片扩展头。

IPv6 路由扩展头

路由扩展头用于在 IPv6 中执行源路由。它在表 26-5 中描述,并在图 26-4 中展示。

表 26-5. IPv6 路由扩展头格式

字段名称 大小(字节) 描述
下一个头部 1 包含路由头部之后下一个头部的协议号。用于将头部链接在一起,如本章前面所述。
Hdr Ext Len 1 用于头部扩展长度,指定路由头在 8 字节单位中的长度,不包括头部的前 8 字节。对于路由类型字段为 0 的情况,此值是头部中嵌入的地址数的两倍。
路由类型 1 允许多个路由类型被定义;目前,唯一使用的值是 0。
Segments Left 1 指定在到达目的地之前路由中剩余的显式命名的节点数。
保留 4 未使用;设置为 0。
Address1…AddressN 可变(16 的倍数) 一组 IPv6 地址,指定要使用的路由。

IPv6 路由扩展头部格式

图 26-4. IPv6 路由扩展头部格式

IPv6 分片扩展头部

片扩展头部包含在分片数据报中,以提供允许分片重新组装所需的信息。它描述在表 26-6 中,并在图 26-5 中展示。

表 26-6. IPv6 分片扩展头部格式

字段名称 大小(字节) 描述
下一个头部 1 包含分片头部之后下一个头部的协议号。用于将头部链接在一起,如本章前面所述。
保留 1 未使用;设置为 0。
分片偏移 13/8 (13 位) 指定此分片中的数据在整体消息中的偏移量或位置。它以 8 字节(64 位)为单位指定,其使用方式与 IPv4 头部中同名字段非常相似。
Res 1/4 (2 位) 未使用;设置为 0。
M 标志 1/8 (1 位) 更多分片标志,与 IPv4 头部中同名标志相同。当设置为 0 时,表示消息中的最后一个分片;当设置为 1 时,表示在分片消息中还有更多分片尚未到来。
标识 4 与 IPv4 头部中同名字段相同,但扩展到 32 位。它包含一个特定值,该值属于特定消息的每个分片。这确保了来自不同分片消息的片段不会混合在一起。

IPv6 分片扩展头部格式

图 26-5. IPv6 分片扩展头部格式

IPv6 扩展头部顺序

每个扩展标题在任何数据报中只出现一次(有一个例外,你很快就会看到)。此外,只有数据报的最终接收者会检查扩展标题,而不是中间设备(也有一个例外,你马上就会看到)。

RFC 2460 规定,当出现多个标题时,它们应该在 IPv6 数据报有效载荷中的主标题之后、高层封装标题之前按照以下顺序出现:

  1. 跳-跳选项

  2. 目的选项(用于由目的地以及路由标题中指定的设备处理的选项)

  3. 路由

  4. 分片

  5. 认证标题

  6. 封装安全有效载荷

  7. 目的选项(仅由最终目的地处理的选项)

现在让我们来看看那些例外情况。唯一可能出现两次的标题是“目的选项”。通常,它作为最后一个标题出现。然而,数据报也可能包含一个“目的选项”标题,其中包含必须由源路由中指定的一组设备检查的选项,除了目的地之外。在这种情况下,这些选项的“目的选项”标题被放置在“路由”标题之前。还可能有一个包含仅针对最终目的地的选项的第二个此类标题。

提示

关键概念 每个扩展标题在 IPv6 数据报中只能出现一次,并且每个都必须按照固定顺序出现。例外的是“目的选项”标题,它可以出现两次:在数据报的开始处,用于处理前往目的地的设备的选项,以及在扩展标题的末尾,用于仅针对最终目的地的选项。

通常所有中间设备都会检查的唯一标题是“跳-跳选项”扩展标题。它专门用于将管理信息传达给路由中的所有路由器。如果存在,则“跳-跳选项”扩展标题必须作为第一个扩展标题出现。由于它是每个路由器都必须读取的(这代表了路由器的性能损耗),因此它被赋予最高的优先级,以便更容易、更快地找到和处理。

最后,请注意,所有扩展标题的长度必须是八的倍数,以便对齐。此外,请记住,特定扩展标题的“下一个标题”值出现在前一个标题的“下一个标题”字段中,而不是标题本身。

IPv6 数据报选项

在 IPv4 中,为各种目的所需的所有额外信息都以选项的形式放入数据报中,这些选项出现在 IPv4 标题中。在 IPv6 中,引入了新的扩展标题概念,正如你刚才看到的。这些标题取代了许多预定义的 IPv4 选项。然而,选项的概念在 IPv6 中仍然保持,但目的略有不同。

选项允许 IPv6 数据报补充任意集合的信息,这些信息在常规扩展头部中没有定义。它们提供了最大的灵活性,从而允许基本 IPv6 协议以设计者未曾预料的方式扩展,目的是减少协议在未来变得过时的可能性。

我说 IPv6 选项补充扩展头部;实际上,它们实际上作为扩展头部实现。用于编码选项有两种不同的头部。这两个头部在处理它们包含的选项方面有所不同;否则,它们的格式相同,并且以相同的方式使用。

两种扩展头部类型如下:

目标选项 包含仅针对数据报最终目的地(如果存在,还包括路由头中的一组路由器)的选项。

跳-跳选项 包含携带源和目的地之间每个设备(路由器)信息的选项。

这些头部类型每个都有一个一字节的下一个头部字段和一个一字节的头部扩展长度字段,用于指示头部的总长度。头部的其余部分有一个或多个选项字段。

图 26-6 展示了这两个头部的整体格式。每个选项的格式与 IPv4 选项类似,如表 26-7 和表 26-8 所示。

IPv6 跳-跳选项和目标选项头格式 这些扩展头每个都以两个固定字段开始,即下一个头部和头部扩展长度。头部的其余部分由一系列可变长度的选项组成。每个选项都有一个由类型/长度/值三元组组成的结构,如图所示。

图 26-6. IPv6 跳-跳选项和目标选项头格式。这些扩展头每个都以两个固定字段开始,即下一个头部和头部扩展长度。头部的其余部分由一系列可变长度的选项组成。每个选项都有一个由类型/长度/值三元组组成的结构,如图表 26-7 所示。

表 26-7. IPv6 选项格式

子字段名称 大小(字节) 描述
选项类型 1 此字段指示选项的类型。位根据子子字段“结构”进行解释,如表 26-8 中所述。
选项数据长度 1 指定选项数据子字段长度。注意,这与 IPv4 中的语义不同,在 IPv4 中,长度字段指示整个选项的大小;在 IPv6 中,选项类型和选项数据长度字段的长度不包括在内。
选项数据 可变 作为选项的一部分要发送的数据,这取决于选项类型。有时也称为选项值。

表 26-8. IPv6 选项类型子字段

子子字段名称 大小(字节) 描述
未知选项操作 2/8 (2 位) 这两个位指定如果处理选项的设备不识别选项类型时应该采取什么操作。四个值如下:00: 跳过选项;处理其余的头部。0: 丢弃数据报;不做其他操作。10: 丢弃数据报并发送一个带有代码 2 的 ICMP 参数问题消息回数据报源。11: 丢弃数据报并发送与值 10 相同的 ICMP 消息,仅当目标不是多播地址时。
选项更改允许标志 1/8 (1 位) 如果选项数据在数据报传输过程中可以更改,则设置为 1;如果不可更改,则保留为 0。
选项类型剩余部分 5/8 (5 位) 五个剩余的位允许为前三个位的每个组合指定 32 种不同的组合。

注意

在解释方式上,选项类型子字段有点奇怪。尽管它有一个包含三个子子字段的子结构(如表 26-8 所示),但这个结构是非正式的——这个字段的 8 位被视为一个整体。尽管最高三位有特殊含义,但整个字段被称为选项类型,而不仅仅是最后五位,整个字段从 0 到 255 用作单个值。实际上,子子字段名称甚至没有在标准中指定;是我自己编造的。 |

由于每个选项都有一个类型、长度和值(数据)的子字段,因此有时说选项是 TLV 编码的。如果有多个选项,它们将按顺序放置在头部中。在所有选项的末尾,在跳步选项或目标选项扩展头中,设备可以放置填充以确保头部长度是 8 的倍数。 |

提示

关键概念 两种 IPv6 扩展头类型,跳步选项和目标选项,用于在 IPv6 数据报中携带任意可选信息。每个都由一组使用三个子字段定义的可变长度选项组成,这些子字段指示选项的类型、长度和值。

第二十七章. IPv6 数据报大小、分片、重组和路由

无标题图片

互联网协议版本 6(IPv6)改变了 IP 的许多操作细节,但大多数基本原理是相同的。特别是,设备仍然需要在可能使用不同底层网络技术的互联网上传递数据报。这意味着我们必须关注这里,就像在 IPv4 中一样,数据报的大小、处理分片和重组以及处理与路由相关的问题的机制。

在本章中,我通过检查这些问题来完成 IPv6 的讨论,目的是对比它们在 IPv6 中的工作方式。这包括查看 IPv6 数据报的大小、最大传输单元(MTU)的变化以及分片和重组。我还简要讨论了 IPv6 路由与 IPv4 相同以及路由发生变化的地方。

IPv6 数据报大小和分片概述

IP 的工作是在连接的网络之间传递消息。当在不同网络的主机之间发送数据报时,它们通过路由器逐跳传输,跨越许多物理网络链路。在旅途中每一步,数据报都会被编码在数据链路层帧中以便传输。

为了使数据报能够成功沿路由传输,其大小必须足够小,以便在每一步都能适应低层帧。术语最大传输单元(MTU)描述了任何给定物理网络的大小限制。如果一个数据报太大,无法适应网络的 MTU,它必须被分成几块——这个过程称为分片——然后这些块在目标设备上重新组装。这自从 IPv4 以来一直是必需的,我在相关的 IPv4 讨论中详细解释了与数据报大小、MTU、分片和重组相关的概念和问题,在第二十二章。

所有这些问题在发送 IPv6 数据报时与 IPv4 一样适用。然而,正如协议的其他领域一样,关于分片和重组的一些重要细节已经发生了变化。这些变化是为了提高路由过程的效率,并反映当前网络技术的现实:大多数可以处理平均 IP 数据报而不需要分片。

关于数据报大小、MTU 和分片与重组,IPv4 和 IPv6 之间最重要的区别如下:

增加默认 MTU 在 IPv4 中,路由器和物理链路必须处理的最低 MTU 是 576 字节。在 IPv6 中,所有链路都必须处理至少 1280 字节的数据报大小。这种大小的增加通过增加最大有效载荷与头部长度的比率来提高效率,并减少了需要分片的情况。

消除途中分片 在 IPv4 中,数据报可以在传输过程中由源设备或路由器进行分片。在 IPv6 中,只有源节点可以进行分片;路由器不行。在传输之前,源必须将分片的大小设置为路由上最小的 MTU。这将带来优点和缺点,您将看到。重组仍然只由目的地执行,就像在 IPv4 中一样。

MTU 大小错误反馈 由于路由器不能分片数据报,如果它们被迫尝试在物理链路上发送过大的数据报,它们必须丢弃它们。使用互联网控制消息协议版本 6(ICMPv6;见第三十一章),已经定义了一个反馈过程,允许路由器告诉源设备它们正在使用对于路由来说太大的数据报。

路径 MTU 发现 由于源设备必须决定分片的大小,如果它们有一个机制来确定这应该是什么,那就很有帮助。这种能力是通过一种称为路径 MTU 发现的特殊技术提供的,最初是为 IPv4 定义的,但后来为 IPv6 进行了改进。

分片头字段移动 为了反映 IPv4 中分片的重要性降低,与该过程相关的永久字段已经从 IPv4 头部分离出来,并仅在需要时包含在分片扩展头中。

IPv6 仅源分片规则的影响

我发现分片和重组过程中的变化很有趣。虽然 IPv6 中的许多其他变化代表了从主机设备到路由器的功能责任转移,但这一变化却是相反的。在 IPv4 中,源节点可以发送其本地链路可以处理的任何大小的数据报,并让路由器根据需要对其进行分片。这似乎是一个合理的模型;节点在一个大型、虚拟的网络中通信,而根据物理链路需要拆分消息的细节则被无形地处理。

这个问题的缺点是它代表了路由性能的拖累。路由器转发一个完整的数据报比花费时间对其进行分片要快得多。在某些情况下,分片可能需要在数据报传输过程中多次发生,而且记住,这必须发生在路由上的每个数据报上。源一开始就发送正确大小的数据报要高效得多。

当然,这里有一个问题:源如何知道应该使用什么大小?源对路由数据报将要使用的物理网络没有任何了解;实际上,它甚至不知道路由是什么!因此,它根本不知道 MTU 的最佳大小。它有两个选择:

使用默认 MTU 第一个选项是简单地使用默认的 1280 字节 MTU,所有物理网络都必须能够处理这个大小。这是一个不错的选择,尤其是对于短通信或发送少量数据时。

使用路径 MTU 发现 另一个选择是利用本章后面描述的路径 MTU 发现功能。该功能在 RFC 1981 中定义,定义了一种方法,即节点通过路由发送消息以确定路径的整体最小 MTU。这是一种与 IPv4 中讨论的方法非常相似的技术。第二十二章。

由于路由器在 IPv6 中不能分片,如果一个源发送的数据报太大而无法通过路由器,它必须丢弃该数据报。然后,它将向源发送关于这一事件的反馈,形式为 ICMPv6“数据包太大”消息。这告诉源它的数据报已被丢弃,并且它必须分片(或减小其分片的大小)。

这种反馈机制也用于发现路径 MTU。源节点发送一个包含其本地物理链路 MTU 的数据报,因为那代表了路径 MTU 的上限。如果这个数据报无错误地通过,它就知道可以使用这个值来发送未来的数据报。如果它收到任何“数据包太大”的消息,它将尝试使用更小的数据报大小。与默认的 1280 字节相比,这种方法的优点是它可能允许使用更高的 MTU 进行大量通信,从而提高性能。

小贴士

关键概念 在 IPv6 中,分片仅由发送数据报的设备执行,而不是由路由器执行。如果一个路由器遇到一个太大而无法通过具有小 MTU 的物理网络发送的数据报,路由器将向数据报的源发送一个 ICMPv6“数据包太大”消息。这可以作为称为“路径 MTU 发现”的过程的一部分来使用,以确定整个路由的最小 MTU。

仅在源节点进行分片的决定有一个缺点,那就是如果设备之间存在多条路由或路由发生变化,可能会引入潜在的问题。在 IPv4 中,分片是动态和自动的;它自行发生,并随着路由的变化而调整。路径 MTU 发现是一个很好的特性,但它却是静态的。它要求主机跟踪不同路由的 MTU 并定期更新。IPv6 通过在节点收到之前已执行路径 MTU 发现的路由上的“数据包太大”消息时重新执行路径 MTU 发现来实现这一点。然而,这需要时间。

IPv6 分片过程

IPv6 中分片的实际机制与 IPv4 中的类似,但增加了处理扩展头部的复杂性。为了分片,IPv6 数据报被分成以下两个部分:

不可分部分 这包括原始数据报的主报头,以及任何需要存在于每个分片中的扩展报头。这意味着主报头,以及以下任何存在的报头:跳数选项、目的选项(对于需要在路由上的设备处理的选项),以及路由。

可分部分 这包括数据报的数据部分,以及如果存在的话,其他扩展报头——认证报头、封装安全载荷和/或目的选项(对于仅由最终目的地处理的选项)。

不可分部分必须存在于每个分片中,而可分部分则在分片中分割。因此,为了分片一个数据报,设备会创建一组分片数据报,每个数据报按顺序包含以下内容:

  1. 不可分部分 原始数据报的完整不可分部分,其有效载荷长度已更改为分片数据报的长度。

  2. 分片报头 一个分片报头,其中片段偏移、标识和 M 标志的设置方式与 IPv4 中使用的相同。

  3. 分片 原始数据报的可分部分的分片。请注意,每个分片必须具有长度为 8 字节的倍数,因为片段偏移字段中的值是以 8 字节为单位的倍数。

提示

关键概念 在 IPv6 中,分片的方式与 IPv4 类似,但扩展报头必须特别处理。某些扩展报头被认为是不可分片的,并出现在每个分片中;其他则与数据一起分片。

让我们用一个例子来说明 IPv6 分段是如何工作的。假设你有一个正好 320 字节的 IPv6 数据报,由一个 40 字节的 IP 头,四个 30 字节的扩展头和 160 字节的数据组成。其中两个扩展头是不可分的,而另外两个是可分的。(在实际中,你永远不会需要分段如此小的数据报,但我试图保持数字简单。)假设你需要通过一个只有 230 字节 MTU 的链路发送这个数据报。实际上你需要三个片段,而不是你可能预期的两个,因为需要将两个 30 字节的不可分扩展头放入每个片段中,并且每个片段的长度必须是 8 的倍数。以下是片段的结构(参见图 27-1):

  1. 第一片段 第一个片段将包括 100 字节的不可分部分,随后是一个 30 字节的片段头和原始数据报文可分部分的第一个 96 字节。这将包含两个可分扩展头和前 36 字节的数据。这将留下 124 字节的数据需要发送。

  2. 第二片段 这将包含 100 字节的不可分部分,随后是一个片段头,以及 96 字节的数据(字节 36 到 131)。这将留下 28 字节的数据未发送。

  3. 第三片段 最后一个片段将包含 100 字节的不可分部分,一个片段头和最后的 28 字节数据。

IPv6 数据报分段 在这个图中,一个 320 字节的 IPv6 数据报,包含四个 30 字节的扩展头,被分成三个片段。字段的大小按比例显示。不可分部分,在左侧以较浅的阴影显示,在每个片段的开始,随后是片段头。然后,可分部分的各个部分按顺序放入每个片段中。认证和目标选项扩展头是可分部分的一部分,因此它们看起来像是第一个片段的一部分。

图 27-1。IPv6 数据报分片 在这个示例中,一个包含四个 30 字节扩展头的 320 字节 IPv6 数据报被分成三个分片。字段的大小按比例显示。不可分部分,在左侧以较浅的阴影显示,开始于每个分片,然后是分片头部。然后,将可分部分的各个部分按顺序放入每个分片中。认证和目标选项扩展头部是可分部分的一部分,因此它们看起来像是第一部分的一部分。

在前两个分片中,M(更多分片)标志会被设置为 1,在第三个分片中设置为 0,并且分片偏移值会被适当地设置。有关这些字段如何使用的更多信息,请参阅第二十二章,它涵盖了 IPv4 的分片。

接收设备通过从第一个分片获取不可分部分,然后按顺序组装每个分片的分片数据来重新组装。

IPv6 数据报交付和路由

IP 功能,如寻址、数据报封装,以及在必要时分片和重组,所有这些最终都指向协议的最终目标:将数据报从源设备实际交付到一台或多台目标设备。与 IPv6 中数据报交付相关的多数概念与 IPv4 中的相同:

  • 当源节点和目标节点位于同一网络时,数据报直接交付。当它们位于不同的网络时,交付是间接的,使用路由到目标网络的路径,然后直接到目标。

  • 路由器查看 IP 地址,并确定哪一部分是网络标识符(网络 ID),哪一部分是主机标识符(主机 ID)。IPv6 以与无类 IPv4 相同的基本方式执行此操作,尽管 IPv6 单播地址是使用特殊分层格式分配的。

  • 路由仍然基于下一跳进行,源通常不知道数据报是如何从 A 点到 B 点的。

  • 路由是由称为路由器的设备执行的,这些设备维护着路由表,告诉它们将数据报转发到不同的目标网络。

  • 路由协议用于允许路由器交换有关路由和网络的信息。

IPv6 中路由的大部分变化都与协议其他领域的更改直接相关,如前几章所述。与 IPv6 中的路由和路由器相关的一些主要问题包括以下内容:

分层路由和聚合 用于组织单播地址的结构的目标之一是改进路由。单播地址格式旨在提供更好的地址与互联网拓扑之间的匹配,并便于路由聚合。在 IPv4 中使用 CIDR 的无类地址是一种改进,但它缺乏创建可扩展层次结构的正式机制。

作用域本地地址 IPv6 中定义了本地使用地址,包括站点本地地址和链路本地地址,路由器必须能够识别它们。在适当的时候,它们必须路由这些地址或路由这些地址。多播地址也有各种作用域级别。

多播和任播路由 多播在 IPv6 中是标准配置,不是像 IPv4 那样的可选配置,因此路由器必须支持它。任播寻址是 IPv6 中的一种新型寻址方式。

更多支持功能 路由器必须增加功能以支持 IPv6 中的新特性。例如,在新的 IPv6 分片方案中,路由器在无需服务器帮助的情况下实现自动配置和路径 MTU 发现中发挥着关键作用。

新的路由协议 路由协议,如 RIP,必须更新以支持 IPv6。

过渡问题 最后,但同样重要的是,路由器在支持从 IPv4 到 IPv6 的过渡中扮演着重要角色。它们将负责连接 IPv6“岛屿”并执行翻译,以便在多年向新协议迁移的过程中,IPv4 和 IPv6 设备能够相互通信。

第二部分第五部分。与 IP 相关的功能协议

第二十八章

第二十九章

第三十章

前两部分彻底探讨了互联网协议(IP)的第四版和第六版。IP 是一个非常强大的协议,它提供了在 TCP/IP 互联网上寻址、打包和传递信息所需的功能。然而,IP 被有意设计得非常简单,没有很多花哨的功能。为了处理特殊需求,已经创建了许多其他协议来增强或扩展 IP 的功能。我称这些为与 IP 相关的功能协议

本部分包含三个章节,提供了对三个更重要与 IP 相关的功能协议的完整解释。第一章描述了IP 网络地址转换(IP NAT 或 NAT),它允许私有网络在互联网上访问并共享 IP 地址。第二章探讨了IP 安全(IPsec),这是一组子协议,允许对 IP 数据报进行认证和/或加密。第三章涵盖了移动 IP协议,它纠正了使用 TCP/IP 与移动主机相关的一些问题。

本部分假设您已经很好地理解了 IP 的操作,这在第二部分的第三部分和第四部分中进行了讨论。

第二十八章。IP 网络地址转换(NAT)协议

无标题图片

为了在开发并部署新的 IPv6 协议的同时延长 IPv4 地址方案的寿命,已经开发了一些其他技术。其中最重要的之一是IP 网络地址转换(NAT)。这项技术允许少量公网 IP 地址被大量使用私有地址的主机共享。这个基本的工作方案使得全球互联网实际上能够支持比其地址空间通常支持的更多主机。同时,它通过使主机更难以被公网上的外国机器直接寻址,提供了一些安全优势。

在本章中,我提供了 IP NAT 背后的概念描述和对 IP NAT 类型的操作解释。我首先概述了该协议及其优缺点,然后描述了您需要了解的地址术语,以便理解 NAT 的功能以及各种转换技术之间的差异。我解释了地址映射的执行方式以及静态和动态地址映射之间的区别。

然后我解释了四种主要类型的 NAT 的操作:单向、双向、基于端口的和重叠的。我最后简要介绍了与 NAT 相关的兼容性问题。

NAT(网络地址转换)主要是为了解决 IPv4 地址短缺问题而开发的,因此它与 IPv4 相关联并一起使用。虽然可以实现 IPv6 兼容版本的 NAT,但在 IPv6 中,地址转换并不像 IPv4 那样重要,因为 IPv6 的设计目的是为每个 TCP/IP 设备分配其唯一的地址。因此,在本章中,我主要关注 NAT 与 IPv4 的使用。

注意

顺便说一下,大多数人只是称这种技术为网络地址转换,而不带IP然而,在我看来这听起来相当通用,而且由于我这里讨论的是特定于 IP 的版本,我更喜欢明确指出这是一个 IP 特性。话虽如此,为了简便起见,我也经常只说“NAT”,因为这样更简洁。我还应该指出,相当多的人并不认为 NAT 在严格意义上是一个协议*。

IP NAT 概述

将 IP 地址长度设置为 32 位作为 IP 原始设计的一部分,导致当互联网的普及程度超出任何人的预期时出现了一个严重问题:地址空间的耗尽。无类别寻址有助于更好地利用地址空间,IPv6 的创建确保我们永远不会再次耗尽地址。然而,无类别寻址仅减缓了 IPv4 地址空间的消耗,IPv6 的开发需要数年,部署也需要数年。

如果不实施某种解决方案直到 IPv6 过渡完成,IP 地址的短缺预计将在 20 世纪 90 年代末变得至关重要。互联网工程任务组(IETF)上的创新工程师们接受了这一挑战。他们创造了一种技术,不仅能够延缓地址空间的耗尽,还可以用于解决 20 世纪 90 年代中期到后期出现的以下两个其他日益增长的问题:

IP 地址成本增加 任何资源变得稀缺时,其成本就会增加。即使 IP 地址可用,从服务提供商那里获取大量地址的成本也比获取少量地址的成本高。不仅为了整个互联网的缘故,而且为了节省金钱,都有必要节约它们。

对安全的担忧日益增加 20 世纪 90 年代,随着互联网的使用增加,更多的坏人开始使用网络。公司直接连接到互联网的机器越多,它们面临的安全风险就越大。

解决这些问题的方法之一是建立一个系统,其中公司的网络不是直接连接到互联网,而是间接连接。由于以下重要特性,这种方式的网络设置是可能的,即大多数组织如何使用互联网:

大多数主机是客户端设备 互联网是基于客户端/服务器的,大多数主机是客户端。客户端设备通常不需要公开访问。例如,当使用你的本地 PC 访问万维网时,你向服务器发出请求,它们会做出回应,但服务器没有理由试图与你建立联系。客户端,而不是服务器,根据定义开始大多数通信。

很少的主机同时访问互联网 当你在同一网络上连接了大量的主机时,通常只有少数主机在任何给定时间试图访问互联网。没有必要假设他们都会同时需要访问服务器。即使你在积极浏览网页时,你也会时不时地停下来阅读信息;你只访问网络服务器进行交易所需的时间。

互联网通信是路由的 组织的网络与互联网之间的通信通过路由器进行,它充当流量流量的控制点。

最好的方式来解释为什么这些属性很重要,是通过类比组织如何使用电话来解释,因为许多相同的属性也适用于那里。在典型的组织中,大多数电话都是用来让员工打电话出去的。通常没有必要有直接调用员工的方式;相反,一个系统或一个人可以处理所有来电。在任何给定时间,只有少数员工会打电话给外部世界。所有电话都通过一个管理电话系统的中心点进行路由。

由于这些原因,为了节省金钱,组织不会为每个员工的办公桌运行独立的公共电话线路。相反,它们设置了一个电话系统,其中每个员工都得到一个分机,这基本上是一个只在组织内部有效的本地电话号码。一小部分外部线路以池的形式提供给员工共享,电话系统根据需要将内部分机与外部线路匹配。语音邮件系统和人工接待员处理来电的组织路由。是的,当然有些公司会在分机号码和真实电话号码之间进行直接映射。)

可以使用一个非常类似的技术来连接组织的计算机到互联网。在 TCP/IP 网络中,这项技术最初在 1994 年 5 月通过的 RFC 1631,“IP 网络地址转换器(NAT)”中得到了正式化。单词转换器指的是实现 NAT 的设备(路由器)。更常见的是,这项技术整体被称为IP 网络地址转换IP NATNAT)。

注意

RFC 1631 的文档状态为信息性。这意味着,技术上讲,IP NAT 不是一个官方的互联网标准

NAT 的基本实现涉及使用为本地 IP 网络预留的私有地址范围之一来设置组织的内部网络。组织还会分配一个或多个公共(互联网)地址,并在本地网络和公共互联网之间安装一个或多个具有 NAT 功能的路由器。公共 IP 地址就像电话系统中的外线,而私有地址就像内部分机。

NAT 路由器扮演着电话系统计算机和接待员的角色。它根据需要将内部分机映射到外线,并在需要时处理“来电”。它通过不仅路由 IP 数据报,而且在需要时修改它们来实现这一点,从而将数据报中的地址从私有网络转换为用于在互联网上传输的公共地址,然后再转换回来。

小贴士

关键概念 IP 网络地址转换 (IP NATNAT) 是一种技术,允许组织使用私有地址建立网络,同时仍然允许在公共互联网上进行通信。具有 NAT 功能的路由器根据需要将私有地址转换为公共地址,反之亦然。这允许少量公共 IP 地址在大量设备之间共享,并提供其他好处,但也存在一些缺点。

随着时间的推移,也创建了 NAT 的新版本。它们解决了其他问题或提供了额外的功能。基于端口的 NAT 通过让两个或多个设备每次共享一个 IP 地址,允许在有限的 IP 地址上共享更多的主机。所谓的双重 NAT 通过在传入和传出数据报中转换源地址和目标地址,有助于虚拟专用网络(VPN)的实施。

IP NAT 的优点

NAT 是那些具有长串优缺点列表的技术之一。这意味着它在各种场景中可能极其有用,但在其他情况下也可能有问题。主要优点如下:

公共 IP 地址共享 大量主机可以共享少量公共 IP 地址。这不仅可以节省费用,还可以节约 IP 地址空间。

更容易扩展 由于本地网络设备使用私有地址,并且不需要为每个设备分配公共 IP 地址,因此很容易将新客户端添加到本地网络。

更大的本地控制 管理员可以获得与私有网络相关的所有控制好处,但仍可以连接到互联网。

在互联网服务提供商(ISP)服务方面的更大灵活性 更改组织的 ISP 更容易,因为只有公共地址会改变。不需要重新编号网络上的所有客户端计算机。

增强安全性 NAT 转换代表了一种间接层次。因此,它自动在组织的网络和公共互联网之间创建了一种防火墙。由于客户端没有公开的 IP 地址,恶意用户直接访问任何客户端设备变得更加困难。

(大部分)透明 NAT 实现主要是透明的,因为更改发生在一个或几个路由器上。成百上千的主机本身不需要更改。

IP NAT 的缺点

列出的先前优点都是使用 NAT 的好理由,但这项技术也有其缺点:

复杂性 NAT 在设置和管理网络方面代表了一种额外的复杂性。它还由于地址替换而使得故障排除更加复杂。

由于缺乏公网地址的问题 由于客户端主机机器缺乏真实的 IP 地址,某些功能可能无法正常工作。

与某些应用的兼容性问题 我之前提到 NAT 只是大部分透明。实际上,由于 NAT 在数据报中的 IP 头部字段中而不是在应用数据中篡改,某些应用存在兼容性问题。这意味着像文件传输协议(FTP;见第七十二章"))这样的工具,在命令中传递 IP 地址和端口号,必须特别处理,并且某些应用可能无法工作。

与安全协议的问题 如 IPsec 这样的协议旨在检测头部修改,并且通常对 NAT 所做的更改表示反对,因为它们无法区分这些更改和恶意数据报黑客行为。仍然可以将 NAT 和 IPsec 结合起来,但这变得更加复杂。

对客户端访问的支持不足 每个客户端缺乏公网 IP 地址是一把双刃剑;它保护了主机免受黑客尝试访问,但同时也使得对本地网络中客户端的合法访问变得困难。对等应用(P2P)的设置更加困难,而像组织网站(作为整体从互联网访问)通常需要在没有 NAT 的情况下设置。

性能降低 每次数据报在私有网络和互联网之间转换时,都需要进行地址转换。此外,还需要执行其他工作,例如重新计算头部校验和。每次单独的转换需要很少的努力,但当你加起来时,你正在放弃一些性能。

其中一些可能会抵消前述列表中某些项目的某些好处。然而,许多组织认为其优点超过了缺点,特别是如果他们主要以客户端/服务器模式使用互联网,就像大多数人一样。因此,NAT 已经变得非常流行。然而,请记住,导致 NAT 的主要问题是地址空间不足。IPv6 解决了这个问题,而 NAT 只是找到了一个巧妙的解决方案。因此,许多人认为 NAT 是一种 kludge。一旦部署 IPv6,它将不再需要,有些人甚至不喜欢它用于 IPv4。另一方面,有些人认为它的其他好处使其即使在 IPv6 中也有考虑的价值。

注意

A kludge ( kluge) *是一种以不优雅的方式解决问题的方法,就像用可调扳手的侧面敲钉子一样。

IP NAT 地址术语

如其名称明显所示,IP NAT 完全是关于 IP 地址的转换。当数据报在组织的私有网络和公共互联网之间传递时,NAT 路由器会更改这些数据报中的一个或多个地址。这种转换意味着在 NAT 环境中,每笔交易不仅涉及源地址和目的地址,还可能涉及源和目的地的多个地址。

为了更清楚地解释 NAT 的工作原理,已经开发了一些特殊名称来指代在使用 NAT 时可以在 IP 数据报中找到的不同类型的地址。不幸的是,NAT 中使用的地址术语可能会令人困惑,因为很难想象(通常听起来相似)名称之间的区别。然而,如果不了解这些地址的含义,就无法正确理解 NAT 的操作。

地址区分的第一种方式是基于设备在网络中的位置,如下所示:

内部地址 组织私有网络中任何使用 NAT 的设备都被称为内部网络。因此,任何以任何形式指向本地网络设备的地址都称为内部地址

外部地址 公共互联网——即本地网络之外的一切——被认为是外部网络。任何指向公共互联网设备的地址都是外部地址

提示

关键概念 在 NAT 中,术语内部外部用于识别设备的位置。内部地址指的是组织私有网络中的设备。外部地址指的是公共互联网上的设备。

内部设备始终具有内部地址;外部设备始终具有外部地址。然而,根据地址在数据报中出现的网络部分,有两种不同的方式来指定内部或外部设备:

本地地址 这个术语描述的是出现在内部网络数据报上的地址,无论它是指内部地址还是外部地址

全局地址 这个术语描述的是出现在外部网络数据报上的地址,再次强调,无论它是指内部地址还是外部地址。

小贴士

关键概念 在 NAT 中,术语本地全局用来指示特定地址出现在哪个网络中。本地地址用于组织的私有网络中(无论是引用内部设备还是外部设备)。全局地址用于公共互联网上(再次强调,无论是引用内部设备还是外部设备)。

这有点令人困惑,所以我将尝试进一步解释。NAT 转换路由器负责连接内部网络与外部网络(互联网)。内部设备需要能够与外部设备通信,反之亦然,但内部设备只能使用与本地网络寻址方案一致的地址。同样,外部设备不能使用本地地址。因此,内部和外部设备都可以用本地或全局地址版本来引用。这产生了四种不同的特定地址类型:

内部本地地址 使用其正常的本地设备表示法表示的本地网络设备地址。例如,如果你有一个使用 10.0.0.0 私有地址块并分配地址 10.0.0.207 的客户端,这将是其内部本地地址。

全局地址 这是一个全局的、可公开路由的 IP 地址,用于在内部设备与外部世界之间进行表示。在 NAT 配置中,内部全局地址是指分配给组织并由 NAT 路由器使用的实际 IP 地址。假设设备 10.0.0.207 想要向位于地址 204.51.16.12 的互联网服务器发送一个 HTTP 请求。它使用 10.0.0.207 作为源地址来形成数据报。然而,如果这个数据报以原样发送到互联网,服务器无法回复,因为 10.0.0.207 不是一个公开可路由的 IP 地址。因此,NAT 路由器将数据报中的 10.0.0.207 转换成组织注册的 IP 地址之一,比如 194.54.21.10。这是与 10.0.0.207 相对应的内部全局地址。当服务器发送其 HTTP 响应时,它将用作目标地址。请注意,在某些情况下,内部本地地址和外部本地地址可能是相同的。

外部全局地址 这是外部(公共互联网)设备在全局互联网上的引用地址。这基本上是互联网上设备的常规、公开注册的地址。在先前的例子中,204.51.16.12 是一个公共服务器的外部全局地址。

外部本地地址 外部设备在本地网络设备中引用的地址。在某些情况下,这可能与该外部设备的外部全局地址相同。

呼吸一下,这仍然很困惑,不是吗?让我们尝试另一种看待这个问题的方式。在这四个地址中,两种类型是内部或外部设备本地产生的地址,而另外两种是转换地址。以下是一个总结:

内部设备标识 对于内部设备,其内部本地地址是其正常或本地地址。其内部全局地址是一个用于在必要时在外部网络上表示内部设备的转换地址。

外部设备标识 对于外部设备,其外部全局地址是其正常或本地地址。其外部本地地址是一个用于在必要时在内部网络上表示外部设备的转换地址。

因此,NAT 所做的是将内部或外部设备的标识从本地表示转换为全局表示,反之亦然。地址如何更改以及具体类型取决于所使用的 NAT 类型。例如,在传统 NAT 中,内部设备使用它们的正确(全局)表示来引用外部设备,因此这些外部设备的全局外部和本地外部地址是相同的。

小贴士

关键概念 NAT 路由器将本地地址转换为全局地址,反之亦然。因此,一个内部本地地址被转换为内部全局地址(反之亦然),一个外部本地地址被转换为外部全局地址(反之亦然)。

经过所有这些之后,仍然很困惑!一个很大的问题是,“内部”和“本地”这两个词在某种程度上是同义的,同样,“外部”和“全局”也是,但在 NAT 中它们的意思却不同。在试图解释网络概念时,典型的悖论再次显现:我想定义这些地址来使描述 NAT 操作更容易,但发现自己需要用 NAT 操作的例子来澄清地址的使用方式。

即使写完这些材料后,我发现这些术语仍然令人困惑,所以我创建了图 28-1 术语。希望这个图表能帮助你更好地理解整个“内部/外部/本地/全局”的概念。"),它以图形形式展示了这些术语,可能有所帮助。该图表也用作本章其余部分不同类型 NAT 插图模板。在阅读关于 NAT 操作的内容时,如果你想要再次检查地址类型,请回到这里。如果需要几次才能弄清楚地址,不要气馁。

IP 网络地址转换(NAT)术语 希望这个图表能帮助你更好地理解整个“内部/外部/本地/全局”的概念。

图 28-1. IP 网络地址转换(NAT)术语。希望这个图表能帮助你更好地理解整个“内部/外部/本地/全局”的概念。

IP NAT 静态和动态地址映射

NAT 允许你通过在连接两个网络的路由器中实现地址转换算法,将私有(内部)网络连接到公共(外部)网络,如互联网。每次 NAT 路由器遇到跨越两个网络边界的 IP 数据报时,它都必须适当地转换地址。但它如何知道要转换什么以及使用什么作为转换地址呢?

路由器中的 NAT 软件必须维护一个转换表,以告知其如何操作。转换表包含将内部设备(它们的常规地址)的内部本地地址映射到内部全局地址表示(用于外部通信的特殊公共地址)的信息。如果适当,它还可能包含外部全局地址和外部本地地址之间的映射,用于入站交易。

向 NAT 转换表中添加条目的两种基本方式是:静态或动态。

静态映射

静态映射表示在全局本地地址表示之间定义的永久、固定关系,无论是内部还是外部设备的地址。例如,如果你想使具有内部本地地址 10.0.0.207 的内部设备始终使用内部全局地址 194.54.21.10,你可以使用静态转换。每当 10.0.0.027 与互联网发起交易时,NAT 路由器都会将此地址替换为 194.54.21.10。

动态映射

在动态映射中,全局本地地址表示由 NAT 路由器自动生成,按需使用后即丢弃。这种用法最常见的方式是允许一个内部全局地址池被大量内部设备共享。

例如,假设你正在使用动态映射,并且有一个从 194.54.21.1 到 194.54.21.20 的内部全局地址池。当 10.0.0.207 向互联网发送请求时,它的源地址不会自动被替换为 194.54.21.10。NAT 路由器会从池中的 20 个地址中选择一个。然后,路由器会监视使用该地址返回的回复,并将它们转换回 10.0.0.207。当会话完成后,它会丢弃条目,将内部全局地址返回到池中。

在静态和动态映射之间进行选择

静态和动态 NAT 映射之间的权衡与静态和动态之间的选择时几乎总是相同的。例如,在地址解析协议(ARP)缓存中也会出现相同的问题;参见第十三章。

静态映射是永久的,因此非常适合需要在外部网络上始终以相同的公共地址表示的设备。它们也可以用来允许特定设备的入站流量;也就是说,它们可以用于在公共网络上发起的交易,这些交易发送到内部网络上的特殊服务器。然而,它们需要手动设置和维护,并且不允许在内部网络上共享 IP 地址。

动态映射通常用于常规客户端,以便促进公共 IP 地址的共享——这是大多数 NAT 实现的主要目标。它比静态映射更复杂,但一旦设置好,就会自动进行。

当然,可以在同一系统上混合动态和静态映射。你可以指定某些静态映射的设备,其余的则使用动态映射。你只需确保静态映射不会与用于动态分配的池重叠。

顺便提一下,你还可以通过使用域名系统(DNS;参见第五十二章)进行域名解析来执行全局和本地地址的动态映射。这在外部设备使用双向 NAT(入站事务)访问内部主机时尤其常见。由于公共互联网上的主机对组织的私有网络一无所知,它们会发出请求以获取他们想要访问的设备的 DNS 名称。这会导致生成一个 NAT 转换条目,将主机的内部本地公共地址映射到内部全局地址,以便网络外部的用户使用。关于双向 NAT 的工作原理的更多细节,请参见本章后面的描述。

IP NAT 单向(传统/出站)操作

现在是时候深入了解它是如何工作的了。NAT 有许多不同的版本,本章涵盖了四种常见的版本。从 RFC 1631 中描述的原始 NAT 版本开始看是有意义的。这是最简单的 NAT 方法,因此也是最容易解释的。

NAT 被设计为允许私有网络上的主机在访问互联网时共享公网 IP 地址。由于大多数主机是发起事务的客户端,NAT 是在假设客户端/服务器请求/响应通信将以从内部网络发送到外部的数据报开始的情况下设计的。因此,这种 NAT 类型有时被称为单向出站NAT。由于它是最古老的版本,现在也被称为传统NAT,以区分较新的类型。

为了展示单向 NAT 的工作原理,我将使用一个例子。假设内部网络有 250 个主机,它们使用 10.0.0.0/8 地址范围内的私有(内部本地)地址(我选择这个范围是因为数字较小!)。这些主机使用动态 NAT,共享从 194.54.21.1 到 194.54.21.20 的 20 个内部全局地址。

在这个例子中,设备 10.0.0.207 想要访问公网地址 204.51.16.12 上的万维网服务器。表 28-1 展示了在这个(简化)事务中涉及的四个基本步骤。我将其以表格形式呈现,以便明确展示请求数据报(步骤 1 和 2)和响应数据报(步骤 3 和 4)中的地址发生了什么变化。我还为了清晰起见,突出了翻译后的地址值,并提供了图 28-2,它以图形方式展示了这个过程。

表 28-1. 单向(传统/出站)NAT 的操作

步骤编号 描述 数据报类型 数据报源地址 数据报目的地址
1 内部客户端生成请求并发送到 NAT 路由器:设备 10.0.0.207 生成一个 HTTP 请求,最终传递到 IP 层并封装在 IP 数据报中。源地址是自身,10.0.0.207,目的地是 204.51.16.12。数据报被发送到能够连接组织内部网络到互联网的 NAT 路由器。 请求(从内部客户端到外部服务器) 10.0.0.207(内部本地) 204.51.16.12(外部本地)
2 NAT 路由器转换源地址并发送到外部服务器:NAT 路由器意识到 10.0.0.207 是一个 内部本地 地址,并且知道它必须替换一个 内部全局 地址,以便让公共互联网目标做出响应。它查阅其地址池并看到下一个可用的地址是 194.54.21.11。它将数据报中的源地址从 10.0.0.207 更改为 194.54.21.11。在传统 NAT 中,目标地址不会被转换。换句话说,外部本地 地址和 外部全局 地址是相同的。NAT 路由器将其从 10.0.0.207 到 194.54.21.11 的映射放入其转换表中。它发送修改后的数据报,该数据报最终被路由到 204.51.16.12 的服务器。 194.54.21.11 (内部全局) 204.51.16.12 (外部全局)
3 外部服务器生成响应并发送回 NAT 路由器:204.51.16.12 的服务器生成一个 HTTP 响应。它不知道 NAT 是否被涉及;它看到发送给它的请求中包含 194.54.21.11,因此它将响应发送到那里。然后它被路由回原始客户端的 NAT 路由器。 响应(从外部服务器到内部客户端) 204.51.16.12 (外部全局) 194.54.21.11 (内部全局)
4 NAT 路由器转换目标地址并将数据报发送到内部客户端:NAT 路由器看到从互联网到达的响应中包含 194.54.21.11。它查阅其转换表并知道这个数据报是针对 10.0.0.207 的。这次,目标地址改变了,但源地址没有变。然后它将数据报发送回原始客户端。 204.51.16.12 (外部本地) 10.0.0.207 (内部本地)

单向(传统/出站)NAT 操作图。您可以通过按顺时针顺序遵循这些步骤来查看此过程中的四个步骤。已转换的地址以粗体显示。有关四种地址类型的解释,请参阅和。

图 28-2. 单向(传统/出站)NAT 操作图。您可以通过按顺时针顺序遵循这些步骤来查看此过程中的四个步骤。已转换的地址以粗体显示。有关四种地址类型的解释,请参阅 表 28-1 和 图 28-1 术语。希望这个图表能帮助您更好地理解整个“内部/外部/本地/全局”的概念。")。

如您所见,这其实并不是什么火箭科学,一旦您习惯了术语和概念,理解正在发生的事情就相当容易。在单向 NAT 中,源地址在出站数据报中被转换,而目的地址在入站数据报中被转换。传统 NAT 仅支持这种类型的出站事务,这种事务是由内部网络中的设备启动的。它无法处理向公共互联网上的私有地址发送请求的设备。

小贴士

关键概念单向(传统)NAT 中,NAT 路由器将出站请求的源地址从内部本地转换为内部全局形式。然后它将响应的目的地址从内部全局转换为内部本地。在请求和回复中,外部本地和外部全局地址是相同的。

还要注意,尽管我主要关注 NAT 路由器对地址所做的更改,但它也必须对数据报进行其他更改。更改 IP 头中的任何字段意味着需要重新计算 IP 头校验和字段。用户数据报协议(UDP)和传输控制协议(TCP)校验和也需要重新计算,并且根据数据报中数据的特点,可能还需要进行其他更改。我将在本章末尾关于 NAT 兼容性问题的部分中讨论这些问题。

顺便提一下,这个简化的示例假设在私有网络和公共网络之间只有一个路由器。在这些网络之间可能有多个路由器。但是,如果使用这种配置,则它们必须使用相同的转换表。否则,如果路由器 R1 处理请求,但路由器 R2 收到响应,路由器 R2 将不知道如何转换入站数据报上的目的地址。这使得动态映射变得极其困难:路由器必须协调它们的地址映射。

IP NAT 双向(双向/入站)操作

传统 NAT 设计用于处理仅出站事务;本地网络上的客户端发起请求,互联网上的设备发送响应。然而,在某些情况下,我们可能希望反方向进行。也就是说,我们可能希望外部网络上的设备与内部网络上的设备发起事务。为了允许这样做,我们需要比传统版本更强大的 NAT 类型。这种增强有多种名称,最常见的是双向 NAT、双向 NAT 和入站 NAT。所有这些名称都传达了这种 NAT 允许您在前面主题中看到的类型的事务,以及从外部网络发起的事务。

在入站事务上进行 NAT 比传统的出站 NAT 更困难。要理解为什么,请记住使用 NAT 时的网络配置本质上是不对称的:内部网络通常知道外部设备的 IP 地址,因为它们是公开的,但外部网络不知道内部网络的私有地址。即使它们知道这些地址,它们也无法作为从外部发起的 IP 数据报的目标,因为它们是不可路由的——没有方法将它们发送到私有网络的本地路由器。

这有什么关系呢?好吧,考虑一下内部网络中设备 A 向外部网络中设备 B 进行 NAT 的情况。本地客户端 A 总是首先开始事务,因此设备 A 的 NAT 路由器能够在请求期间创建一个映射,将设备 A 的内部本地地址和内部全局地址关联起来。设备 B 是已翻译数据报的接收者,所以设备 A 使用 NAT 的事实被隐藏了。设备 B 进行响应,NAT 路由器进行反向翻译,而设备 B 甚至不知道为设备 A 使用了 NAT。

现在让我们看看入站的情况。在这里,设备 B 试图向使用 NAT 的设备 A 发送数据。设备 B 不能直接发送到设备 A 的私有(内部本地)地址。它需要设备 A 的内部全局地址来开始这个过程。然而,设备 A 的 NAT 路由器并不在设备 B 附近。实际上,设备 B 甚至可能不知道设备 A 的 NAT 路由器的身份!

这就只剩下两种方法。一种是为需要从外部访问的内部网络中的设备(如服务器)使用静态映射。当使用静态映射时,使用静态映射的设备的全局地址将是公开的,这解决了“我该向哪里发送请求”的问题。

另一个解决方案是利用 DNS。正如在 DNS 部分详细解释的那样(见第三部分-1),该协议允许请求以名称而不是 IP 地址的形式发送。DNS 服务器将这些名称转换为相应的地址。可以将 DNS 和 NAT 集成在一起,使它们协同工作。这个过程在 RFC 2694,“DNS 对网络地址转换器的扩展(DNS_ALG)”中有描述。

在这种技术中,外部设备可以利用动态映射。基本过程(高度简化)如下:

  1. 外部设备使用它想要到达的内部网络设备的名称发送 DNS 请求。例如,它可能是www.ilikenat.com

  2. 内部网络的 DNS 服务器将www.ilikenat.com名称解析为对应此 DNS 条目的设备的内部本地地址。

  3. 内部本地 地址被传递给 NAT,并用于在从外部访问的服务器的 内部本地 地址和 内部全局 地址之间创建动态映射。此映射被放入 NAT 路由器的转换表中。

  4. 当 DNS 服务器发送回名称解析时,它告诉外部设备之前步骤中映射的 内部全局(公共)地址,而不是正在寻找的服务器的 内部本地(私有)地址。

一旦外部设备知道内部网络中设备的内部全局地址,交易就可以开始了。让我们使用上一节中的相同示例,但这次我们将其反转,以便外部设备 204.51.16.12 发起请求(因此现在它是 客户端),向内部设备 10.0.0.207(它是 服务器)发起请求。假设已经使用了静态映射或 DNS,以便外部设备知道 10.0.0.207 的内部全局地址实际上是 194.54.21.6。表 28-2 详细描述了交易过程,并在图 28-3 中进行了说明。

双向(双向/入站)NAT 的操作 此图与  相似,但交易方向相反,因此从右上角开始,逆时针方向。翻译后的地址以粗体显示。 包含了四个步骤的完整解释。有关地址类型的解释,请参阅 。

图 28-3. 双向(双向/入站)NAT 操作此图与图 28-2 非常相似,除了事务是反向的,因此从右上角开始,逆时针进行。已转换的地址以粗体显示。表 28-2 包含对四个步骤的完整解释。请参阅图 28-1 以了解地址类型的解释。

表 28-2. 双向(双向/入站)NAT 操作

步骤 # 描述 数据报类型 数据报源地址 数据报目的地址
1 外部客户端生成请求并发送到 NAT 路由器:设备 204.51.16.12 向内部服务器生成请求。它使用内部全局地址 194.54.21.6 作为目的地址。数据报将被路由到该地址的本地路由器,即服务位于内部网络的 NAT 路由器。 请求(从外部客户端到内部服务器) 204.51.16.12(外部全局) 194.54.21.6(内部全局)
2 NAT 路由器转换目的地址并发送到内部服务器:NAT 路由器已经从内部全局地址映射到服务器的内部本地地址。它将 194.54.21.6 目的地址替换为 10.0.0.207,并根据需要执行校验和重新计算和其他工作。源地址不进行转换。然后路由器将修改后的数据报发送到位于 10.0.0.207 的内部服务器。 204.51.16.12(外部本地) 10.0.0.207(内部本地)
3 内部服务器生成响应并发送回 NAT 路由器:位于 10.0.0.207 的服务器生成响应,将其地址设置为 204.51.16.12,因为这是向它发送请求的来源。然后将其路由到服务器的 NAT 路由器。 响应(从内部服务器到外部客户端) 10.0.0.207(内部本地) 204.51.16.12(外部本地)
4 NAT 路由器转换源地址并将数据报路由到外部客户端:NAT 路由器在响应中看到私有地址 10.0.0.207,并将其替换为 194.54.21.6。然后它将此路由回外部网络上的原始客户端。 194.54.21.6(内部全局) 204.51.16.12(外部全局)

如您所见,一旦外部设备知道内部设备的 内部全局 地址,您会发现入站 NAT 与出站 NAT 非常相似。它只是执行相反的转换。而不是修改出站请求的源地址和入站响应的目的地址,路由器更改入站请求的目的地址和出站回复的源地址。

小贴士

关键概念 在传统的 NAT 中,交易必须从本地网络上的客户端请求开始,但在 双向(双向/入站)NAT 中,公共互联网上的设备可以访问本地网络服务器。这需要使用静态映射或 DNS 向外部客户端提供内部网络上服务器的地址。然后,NAT 交易基本上与单向情况相同,只是方向相反:传入请求的目的地址从 内部全局 更改为 内部本地;响应的源地址从 内部本地 更改为 内部全局

IP NAT 基于端口的操作(过载)

传统的 NAT 和双向 NAT 都是通过根据需要交换内部网络和外部网络地址来工作的,以便允许私有网络访问公共网络。对于每次交易,私有网络中设备上的 内部本地 地址与代表它在公共网络上出现的 内部全局 地址之间有一个一对一的映射。我们可以使用动态地址分配,允许大量私有主机共享少量已注册的公共地址。

然而,这里有一个潜在的陷阱。考虑之前的 NAT 示例,其中 250 个主机共享 20 个内部全局(公共)地址。如果已经有 20 个主机正在进行交易,那么当第 21 个尝试访问互联网时会发生什么?没有可用的 内部全局 地址供其使用,因此它将无法访问。

幸运的是,TCP/IP 已经内置了一种机制,可以帮助我们缓解这种情况。TCP/IP 传输层协议中的两个协议,TCP 和 UDP,都使用了额外的寻址组件,称为 端口。TCP 或 UDP 消息中的端口号有助于识别两个地址之间的单个连接。它用于允许 TCP/IP 客户端和服务器上的许多不同应用程序同时进行通信,而不会相互干扰。例如,当你打开多个浏览器窗口以同时访问同一网站上的多个网页时,你使用这种能力。这种在许多连接之间共享 IP 地址的行为称为 复用。第四十三章,它描述了 TCP 和 UDP 端口,对此进行了更详细的说明。

现在让我们回到 NAT(网络地址转换)。在我们发送数据报文在互联网的公共部分和私有部分之间时,我们已经在转换 IP 地址了。如果我们还能转换端口号呢?嗯,我们可以!地址和端口的组合唯一地标识了一个连接。当数据报文从私有网络传递到公共网络时,我们不仅可以更改 IP 地址,还可以更改 TCP 或 UDP 头中的端口号。数据报文将以不同的源地址和端口号发送出去。响应将返回到这个相同的地址和端口号组合(称为套接字)并可以再次进行转换。

这种方法有不同的名称。由于它是一种可以使多个内部本地地址共享单个内部全局地址的技术,因此被称为内部全局地址的 过载,或者简单地称为过载 NAT。更优雅的名称能更好地说明该技术的工作方式,包括基于端口的 NAT、网络地址端口转换(NAPT)端口地址转换(PAT)

小贴士

关键概念 基于端口的 或过载 NAT 是常规 NAT 的增强,它允许私有网络上的大量设备通过更改 TCP 和 UDP 消息中使用的端口号,同时共享一个单一的内部全局地址。

无论其名称如何,在转换中使用端口号具有巨大的优势。它可以允许私有网络上的所有 250 台主机只使用 20 个 IP 地址——甚至可能更少。理论上,甚至可以一次性让所有 250 台共享一个单一的公共 IP 地址!你不希望共享太多的本地主机以至于用完端口号,但可供选择的端口号有数千个。

基于端口的 NAT 需要一台被编程来在传输数据报文时在网络上进行适当的地址和端口映射的路由器。这种方法的不利之处包括更大的复杂性,以及更多兼容性问题(例如与 FTP 等应用程序),因为你现在必须在高层监视端口号,而不仅仅是 IP 地址。

NAPT/PAT 的操作与常规 NAT 的工作方式非常相似,只是端口也会被转换。对于传统的出站事务,源端口号码在修改源地址的同时在请求上更改;响应中的目标端口号码与目标地址一起修改。

让我们再次考虑你在传统 NAT 主题中查看的示例,但这次是在 PAT 环境中。设备 10.0.0.207 是私有网络上的 250 个主机之一,它访问了位于 204.51.16.12 的万维网服务器。假设由于使用了 PAT,为了节省费用,所有 250 个主机都在共享一个单一的内部全局地址,194.54.21.7,而不是一个 20 个地址的池。事务将按照表 28-3 中描述并在表 28-3 中展示的方式进行。

提示

关键概念 在基于端口的 NAT 中,NAT 路由器将内部本地请求的源地址和端口号转换为内部全局形式。然后,它将响应的目的地址和端口号从内部全局转换为内部本地。在外部本地和外部全局地址在请求和回复中是相同的。

与 NAPT/PAT 相关的一个其他问题也值得提及:它假设所有流量在传输层都使用 UDP 或 TCP。尽管这通常是情况,但它可能并不总是如此。如果没有端口号,则无法进行端口转换,该方法将无法工作。

基于端口的(过载)NAT 操作 此图与非常相似,除了显示了源和目的端口号,因为它们在这种类型的 NAT 中使用。已翻译的地址和端口以粗体显示。包含基于端口 NAT 的四个步骤的完整解释。请参考来解释地址类型。

图 28-4. 基于端口的(过载)NAT 操作 此图与表 28-3 非常相似,除了显示了源和目的端口号,因为它们在这种类型的 NAT 中使用。已翻译的地址和端口以粗体显示。表 28-3 包含了基于端口 NAT 的四个步骤的完整解释。请参考图 28-1 来解释地址类型。

表 28-3. 基于端口的(过载)NAT 操作

步骤编号 描述 数据包类型 数据包源地址:端口 数据包目的地址:端口
1 内部客户端生成请求并发送至 NAT 路由器:设备 10.0.0.207 向服务器 204.51.16.12 生成一个 HTTP 请求。WWW 的标准服务器端口是 80,所以请求的目标端口是 80;假设客户端的源端口是 7000。数据报被发送到连接组织内部网络到互联网的 NAT 兼容路由器。 请求(从内部客户端到外部服务器) 10.0.0.207:7000 (内部本地) 204.51.16.12:80 (外部本地)
2 NAT 路由器转换源地址和端口并发送到外部服务器:NAT 路由器意识到 10.0.0.207 是一个 内部本地 地址,并且知道它必须替换为一个 内部全局 地址。然而,这里有多个主机共享单个 内部全局 地址 194.54.21.7。假设端口 7000 已经被另一个私有主机连接使用。路由器替换了 内部全局 地址,并为这个请求选择了一个新的源端口号,比如 7224。目标地址和端口没有变化。NAT 路由器将地址和端口映射放入其转换表中。它发送修改后的数据报出去,该数据报到达服务器 204.51.16.12。 194.54.21.7:7224 (内部全局) 204.51.16.12 (外部全局)
3 外部服务器生成响应并发送回 NAT 路由器:服务器在 204.51.16.12 生成一个 HTTP 响应。它不知道 NAT 是否被涉及;它看到发送给它的请求中有一个地址 194.54.21.7 和端口 7224,因此它将响应发送回那个地址和端口。 响应(从外部服务器到内部客户端) 204.51.16.12:80 (外部全局) 194.54.21.7:7224 (内部全局)
4 NAT 路由器转换目标地址和端口并将数据报发送到内部客户端:NAT 路由器看到从互联网到达的响应中包含的地址 94.54.21.7 和端口 7224。它查阅其转换表并知道这个数据报是针对 10.0.0.207,端口 7000 的。这次,目标地址和端口发生了变化,但源地址没有变。然后路由器将数据报发送回原始客户端。 204.51.16.12:80 (外部本地) 10.0.0.207:7000 (内部本地)

IP NAT 重叠/双重 NAT 操作

到目前为止讨论的所有三种 NAT 版本——传统、双向和基于端口的 NAT——通常用于将使用私有、不可路由地址的网络连接到使用唯一、已注册、可路由地址的公共互联网。使用这些类型的 NAT,内部和外部网络的地址空间通常不会有重叠,因为前者是私有的,后者是公共的。这使得 NAT 路由器能够仅通过查看地址就能立即区分内部地址和外部地址。

在你迄今为止看到的例子中,内部地址都是从 RFC 1918 块 10.0.0.0 来的。这些不能是公共互联网地址,所以 NAT 路由器知道在这个范围内由内部网络内的请求引用的任何地址都是内部网络内的本地引用。同样,任何在这个范围之外的地址都很容易识别为属于外部世界。

然而,在某些情况下,内部网络使用的地址和外部网络部分使用的地址之间可能确实存在重叠。考虑以下情况:

私有网络到私有网络连接 使用 10.0.0.0 块地址的示例网络可能希望连接到另一个使用相同方法的网络。这种情况可能发生在两家公司合并并恰好使用相同的寻址方案(而且私有 IP 块并不多,所以这种情况并不罕见)。

将公共地址空间无效分配给私有网络 一些网络可能不是通过使用指定的私有地址块来设置的,而是使用包含有效互联网地址的块。例如,假设一位管理员决定他正在设置的整个网络永远不会连接到互联网(哈哈!),并使用麻省理工学院(MIT)的 18.0.0.0 地址来编号整个网络,这些地址属于麻省理工学院。然后,当这个网络确实需要连接到互联网时,这位管理员的短视将会适得其反。

过时的公共地址分配 公司 A 可能多年来一直在使用某个特定的地址块,但由于某种原因被重新分配或重新分配给了公司 B。公司 A 可能不想麻烦重新编号其网络,因此会保留其地址,即使公司 B 开始在互联网上使用它们。

这些情况都有一个共同点,那就是私有网络中使用的内部地址与公共网络上的地址重叠。当从本地网络发送数据报时,NAT 路由器无法判断目标是在内部网络还是外部网络。例如,如果你想在私有网络中将主机 10.0.0.207 连接到另一个网络中的主机 10.0.0.199,并将 10.0.0.199 放在数据报的目标中并发送它,那么路由器如何知道你是想连接到你的本地网络上的 10.0.0.199 还是远程网络上的 10.0.0.199?至于发送到另一个私有网络中的 10.0.0.207 的请求,你的自己的地址!以使用 MIT 地址块编号的网络为例。路由器如何知道数据报是实际发送到 MIT 还是私有网络上的另一个设备?

解决这个困境的方法是使用更复杂的 NAT 形式。你之前看到的版本总是转换数据包从内部网络到外部网络或相反方向时的源地址或目的地址。为了处理重叠地址,我们必须在每个从内部到外部或相反方向的转换中同时转换源地址和目的地址。这种技术被称为重叠 NAT,以解决它所解决的问题,或者称为Twice NAT,因为它解决问题的方法。(顺便说一下,尽管有后者的名称,常规 NAT 并不被称为 Once NAT。)

Twice NAT 通过创建一组映射,不仅为 NAT 路由器服务的私有网络,还包括与内部网络地址空间冲突的重叠网络(或多个网络)。为了实现这一点,Twice NAT 依赖于 DNS 的使用,就像双向 NAT 一样。这使得内部网络能够以唯一标识的方式向重叠网络发送请求。否则,路由器无法确定我们的内部网络试图联系哪个重叠网络。

让我们尝试一个新的例子。假设网络被错误地编号,因此它不在 10.0.0.0 私有块中,而是在 MIT 使用的 18.0.0.0 块中。我们私有网络上的一个客户端,18.0.0.18,想要向服务器www.twicenat.mit.edu发送请求,该服务器在 MIT 的地址是 18.1.2.3。客户端不能直接使用 18.1.2.3 作为目的地址并发送数据包,因为路由器会认为它在本地网络中,不会进行路由。相反,18.0.0.18 使用 DNS 和 NAT 的组合来获取外部设备地址,如下所示:

  1. 本地网络上的客户端(18.0.0.18)发送一个 DNS 请求以获取www.twicenat.mit.edu的地址。

  2. 为本地网络服务的(与 Twice-NAT 兼容)NAT 路由器拦截这个 DNS 请求。然后它查阅其表格以找到这个外部设备的特殊映射。假设它被编程为将www.twicenat.mit.edu转换为地址 172.16.44.55。这是一个私有、不可路由的 RFC 1918 地址。

  3. NAT 路由器将这个值,172.16.44.55,返回给源客户端,客户端使用它作为目的地址。

一旦客户端获得了转换后的地址,它就像以前一样启动一个事务。现在 NAT 将执行内部设备和外部设备的转换。外部设备地址必须进行转换,因为内部设备正在使用 172.16.44.55,这不是它试图到达的服务器的有效地址。内部设备地址仍然需要像常规 NAT 那样进行转换,因为 18.0.0.18 不是有效的公共地址。它可能指向 MIT 中的一台真实机器,而且你不应该在互联网上使用它!

假设你仍在使用从 194.54.21.1 到 194.54.21.20 的内部全局地址池作为内部地址,并且进一步假设 NAT 路由器为这次特定的交换选择了 194.54.21.12。事务序列大致如表 28-4 所述,并在图 28-5 中所示。

重叠 NAT 用于源地址和目的地址都是私有地址或无法在公共互联网上常规使用的场合。在这种情况下,与其它类型的 NAT 不同,NAT 路由器将传入和传出数据报的源地址和目的地址都进行翻译。在传出消息中,内部本地地址被更改为内部全局外部本地地址被更改为外部全局;在传入消息中,内部全局地址被更改为内部本地外部全局地址被更改为外部本地

表 28-4. Overlapping NAT/Twice NAT 的操作

步骤编号 描述 数据报类型 数据报源地址 数据报目的地址
1 内部客户端生成请求并发送至 NAT 路由器:设备 18.0.0.18 使用从(NAT 拦截的)DNS 查询得到的www.twicenat.mit.edu的目的地址 172.16.44.55 生成一个请求。数据报被发送到本地网络的 NAT 路由器。 请求(从内部客户端到外部服务器) 18.0.0.18(内部本地) 172.16.44.55(外部本地)
2 NAT 路由器翻译源地址和目的地址并发送至外部服务器:NAT 路由器进行两次翻译。首先,它将 18.0.0.18 地址替换为公开注册的地址,在这个例子中是 194.54.21.12。然后,它将虚假的 172.16.44.55 地址翻译回真实的 MIT 地址www.twicenat.mit.edu。它将数据报路由到外部服务器。 194.54.21.12(内部全局) 18.1.2.3(外部全局)
3 外部服务器生成响应并发送回 NAT 路由器:位于 18.1.2.3 的 MIT 服务器生成一个响应并将其发送回 194.54.21.12,这导致它返回到 NAT 路由器。 响应(从外部服务器到内部客户端) 18.1.2.3(外部全局) 194.54.21.12(内部全局)
4 NAT 路由器翻译源地址和目的地址并将数据报传递给内部客户端:NAT 路由器将目的地址翻译回实际用于内部客户端的地址,就像常规 NAT 一样。它还替换回它用作www.twicenat.mit.edu真实地址替代的 172.16.44.55 值。 172.16.44.55(外部本地) 18.0.0.18(内部本地)

如您所见,在这个例子中,外部本地外部全局的地址是不同的,与前面的 NAT 例子不同。双 NAT 也可以通过监视从互联网进入的与本地网络使用的地址重叠的数据报来处理入站事务,并根据需要执行双重替换。

IP NAT 兼容性问题及特殊处理要求

在一个完美的世界中,NAT 可以使其对使用它的设备透明。我们希望 NAT 路由器能够在数据报离开网络时更改 IP 地址,并在返回的响应中更改它们,并且没有任何主机会察觉到。不幸的是,这不是一个完美的世界。

重叠 NAT/双 NAT 的操作 此图与非常相似,但如您所见,NAT 路由器每次都翻译源地址和目的地址(以粗体显示)。包含重叠 NAT 四个步骤的完整解释。有关地址类型的解释,请参阅。

图 28-5. 重叠 NAT/双 NAT 的操作 此图与图 28-2 非常相似,但如您所见,NAT 路由器每次都翻译源地址和目的地址(以粗体显示)。表 28-4 包含重叠 NAT 四个步骤的完整解释。有关地址类型的解释,请参阅图 28-1。

NAT 不可能对其使用的设备完全透明。如果 NAT 不执行某些功能,可能会出现潜在的兼容性问题。这些功能不仅涉及在 IP 头部中简单地交换 IP 地址和可能端口号,还涉及更多。主要问题是尽管 IP 地址被认为是 IP 的领域,但它们实际上也被其他协议使用,无论是在网络层还是在更高层。当 NAT 更改 IP 数据报中的 IP 地址时,它通常还必须更改其他地方地址,以确保各种头部和负载中的地址仍然匹配。

这些兼容性问题要求尽管 NAT 在理论上应在网络层的 IP 级别工作,但在实际应用中,NAT 路由器必须了解许多更多协议并根据需要执行特殊操作。其中一些是所有转换数据报所需的;其他则仅适用于某些数据报而不适用于其他数据报。即使在 NAT 路由器中添加了这些技术,某些事情在 NAT 环境中仍然可能无法正常工作。

让我们来看看一些主要问题和要求:

TCP 和 UDP 校验和重新计算 在 IP 头部更改 IP 地址意味着必须计算 IP 头部校验和。由于 UDP 和 TCP 也有校验和,并且这些校验和是在包含 IP 源地址和目标地址的伪头部上计算的,因此它们也必须在每次转换时重新计算。

ICMP 操作 由于 NAT 与 IP 头部紧密协作,并且由于 IP 与其“助手”协议互联网控制消息协议(ICMP;见第三十一章

原始互联网协议(IP)的一个弱点是,它在数据通过互联网传输时缺乏任何通用机制来确保数据的真实性和隐私。由于 IP 数据报通常需要在两个设备之间通过未知网络进行路由,因此其中的任何信息都可能被截获,甚至可能被更改。随着互联网在关键应用中的使用增加,IP 需要增强安全性。为此,开发了一套称为IP 安全IPsec的协议。

在本章中,我简要介绍了 IPsec 的概念和协议。我首先概述了 IPsec,包括对这项技术历史的讨论和标准的定义。我描述了 IPsec 套件的主要组件和协议,以及其实施的不同架构和方法。然后,我转向实际讨论 IPsec 的工作原理,从对两种 IPsec 模式(传输和隧道)及其差异的描述开始。我描述了安全关联和相关结构,如安全参数索引(SPI)。最后三个主题涵盖了三个主要的 IPsec 协议:IPsec 认证头(AH)、IPsec 封装安全载荷(ESP)和 IPsec 互联网密钥交换(IKE)。

注意

IPsec 最初是为了 IPv6 而开发的,但已被设计为为 IPv4 和 IPv6 网络提供安全,且两种版本的操作相似。AH 和 ESP 使用的数据报格式有所不同。这些差异取决于你在 IPv4 还是 IPv6 中使用 IPsec,因为两个版本有不同的数据报格式和寻址方式。我在适当的地方突出了这些差异。

IPsec 概述、历史和标准

原始 IP 版本(IPv4)的大问题是其地址空间的即将耗尽。这种情况是由于 IPv4 开发时,互联网的快速扩张超出了任何人的预期。IPv4 创建时互联网的状态与现在的状态之间的这种不匹配,导致了 IP 的另一个主要问题:缺乏确保 IP 互联网安全的确切手段。

安全问题产生的原因是,25 年前,互联网很小且相对私密。如今,它变得巨大且真正公开。随着互联网的增长,对安全的需求也随之增长。考虑一下,TCP/IP 和早期互联网先驱是在美国国防部高级研究计划局(DARPA 或 ARPA)的研究人员使用的小型网络中开发的。那些知名人士通常会有安全许可,控制着所有硬件。在这样的网络中,你不需要在协议中构建安全——你将其构建在建筑中!使用锁和守卫来确保安全比使用复杂的加密要容易。防止某人窃听或篡改网络上的数据的最佳方式就是简单地拒绝他们访问连接到网络的宿主。

在最初只有几十台机器在互联网上时,这种方法运行良好。即使互联网最初开始增长时,它也主要用于连接研究人员和其他网络专业人士。最初,新网站缓慢地被添加到网络中,而且至少有人知道每个新添加到不断增长的网络中的网站的身份。然而,随着互联网的持续增长并最终向公众开放,维护整个网络的安全性变得不可能。如今,“广大无知的群众”都在互联网上。许多路由器——由“谁知道”拥有并由“谁知道”管理——介于你和其他你想要连接的设备之间。你不能假设你发送或接收的数据是安全的。

随着时间的推移,已经发展出多种方法来满足对安全性的需求。其中大多数都集中在 OSI 协议栈的高层,以弥补 IP 安全性的不足。这些解决方案在某些情况下很有价值,但它们不能轻易推广,因为它们针对的是各种不同的应用。例如,我们可以使用安全套接字层(SSL)来处理某些应用,如万维网访问或文件传输协议(FTP),但还有数十种应用这种类型的网络安全从未打算与之配合。

真正需要的是一种允许在 IP 层实现安全性的解决方案,以便 TCP/IP 的所有高层协议都能从中受益。当决定开发新的 IP 版本(IPv6)时,这是解决不仅包括旧 IPv4 的寻址问题,还包括安全不足的黄金机会。针对 IPv6 开发的新安全技术,但由于 IPv6 的开发和部署耗时多年,而安全需求现在就存在,因此解决方案被设计成可以用于 IPv4 和 IPv6。

将安全通信带给 IP 的技术被称为IP 安全,通常缩写为IPsec. 这个缩写的首字母大小写是可变的,所以你会看到 IPSec 和 IPSEC。

IPsec 服务和功能的概述

IPsec 不是一个单独的协议,而是一组服务和协议,为 IP 网络提供完整的解决方案。这些服务和协议结合在一起提供各种类型的保护。由于 IPsec 在 IP 层工作,它可以提供这些保护,而无需额外的安全方法,这对于任何高层 TCP/IP 应用或协议来说是一个主要优势。IPsec 提供的一些保护服务包括以下内容:

  • 加密用户数据以保护隐私

  • 验证消息的完整性以确保它在传输过程中未被更改

  • 防止某些类型的网络安全攻击,例如重放攻击

  • 设备协商满足其安全需求所需的安全算法和密钥的能力

  • 两种安全模式,隧道和传输,以满足不同的网络需求

小贴士

关键概念 IPsecIP 安全 的缩写,它由一系列提供 IP 网络安全的服务和协议组成。它由一系列互联网标准定义。

IPsec 标准

由于 IPsec 实际上是一系列技术和协议的集合,它不是由一个单一互联网标准定义的。相反,一系列 RFC 定义了 IPsec 的架构、服务和使用的特定协议。其中一些最重要的如下所示表 29-1,所有这些都是在 1998 年 11 月发布的。

表 29-1. 重要的 IP 安全(IPsec)标准

RFC 编号 名称 描述
2401 互联网协议的安全架构 主要的 IPsec 文档,描述了该技术的架构和通用操作,并展示了不同组件如何相互配合。
2402 IP 认证头 定义了 IPsec 认证头(AH)协议,该协议用于确保数据完整性和来源验证。
2403 HMAC-MD5-96 在 ESP 和 AH 中的使用 描述了用于 AH 和封装安全载荷(ESP)协议的特定加密算法,称为消息摘要 5(MD5),HMAC 变体。
2404 HMAC-SHA-1-96 在 ESP 和 AH 中的使用 描述了用于 AH 和 ESP 的特定加密算法,称为安全哈希算法 1(SHA-1),HMAC 变体。
2406 IP 封装安全载荷(ESP) 描述了 IPsec ESP 协议,该协议提供数据加密以实现机密性。
2408 互联网安全关联和密钥管理协议(ISAKMP) 定义了交换密钥和协商安全关联的方法。
2409 互联网密钥交换(IKE) 描述了 IKE 协议,用于在设备之间协商安全关联和交换密钥以实现安全通信。基于 ISAKMP 和 OAKLEY。
2412 OAKLEY 密钥确定协议 描述了一种通用的密钥交换协议。

IPsec 的部署仅在最近几年真正开始起飞。该技术的重大用途在于实现虚拟专用网络(VPN)。似乎 IPsec 的未来光明,因为越来越多的个人和公司决定他们需要利用互联网的力量,同时保护他们通过它传输的数据的安全性。

IPsec 通用操作、组件和协议

IPsec 并不是这本书中唯一困难的主题,但它无疑是令许多人困惑的主题。大多数关于它的讨论都直接跳到描述机制和协议,而没有提供关于它做什么以及各个部分如何组合的一般描述。好吧,我认识到 IPsec 的重要性,并且我不回避挑战。因此,这是我尝试为理解 IPsec 的各种片段提供一个框架的尝试。

那么,IPsec 究竟做了什么,又是如何做到的?从一般意义上讲,它为其他 TCP/IP 协议和应用提供了 IP 层的安全服务。这意味着 IPsec 提供了 TCP/IP 网络上的设备在安全通信时所需的工具。当两个设备(无论是终端用户主机还是中间设备,如路由器或防火墙)想要进行安全通信时,它们需要在彼此之间建立一个安全路径,这个路径可能跨越许多不安全的中间系统。为了实现这一点,它们必须执行(至少)以下任务:

  • 他们必须就使用的一组安全协议达成一致,以便每个设备都能以对方能理解的方式发送数据。

  • 他们必须决定在编码数据时使用特定的加密算法。

  • 他们必须交换用于“解锁”加密数据的密钥。

  • 一旦完成这项背景工作,每个设备都必须使用之前商定的协议、方法和密钥来编码数据并将其发送到网络上。

IPsec 核心协议

为了支持这些活动,许多不同的组件共同构成了被称为 IPsec 的总套件,如图图 29-1 所示。其中两个主要部分是一对有时被称为 IPsec 的核心协议的技术,实际上负责将信息编码以确保安全:

IPsec 认证头(AH) 此协议为 IPsec 提供认证服务。它允许消息的接收者验证消息的所谓发送者实际上是发送者本人。它还允许接收者验证途中经过的中间设备没有更改数据报文中的任何数据。它还提供了针对所谓的重放攻击的保护,即一个消息被未经授权的用户捕获并重新发送。

封装安全载荷(ESP) AH 确保数据报文的完整性,但不保证其隐私性。当数据报文中的信息“仅供你一人知晓”时,可以使用 ESP 进一步保护,ESP 会加密 IP 数据报文的负载。

IPsec 协议和组件概述 IPsec 由两个核心协议 AH 和 ESP 以及三个支持组件组成。

图 29-1. IPsec 协议和组件概述 IPsec 包含两个核心协议,AH 和 ESP,以及三个支持组件。

IPsec 支持组件

AH 和 ESP 通常被称为 协议,尽管这又是一个这个术语使用有争议的例子。它们实际上并不是独立的协议,而是作为插入到 IP 数据报中的头部来实现,正如你将看到的。因此,它们完成了 IPsec 的“基础工作”,可以一起使用以提供认证和隐私。然而,它们不能独立运行。为了正常工作,它们需要其他几个协议和服务的支持(参见 图 29-1* 和 安全哈希算法 1 (SHA-1)。这些算法也被称为 哈希 算法,因为它们通过基于输入数据和密钥计算一个称为 哈希 的公式来工作。

安全策略、安全关联和管理方法 由于 IPsec 允许不同的设备决定如何实现安全策略,因此它们需要一些方法来跟踪它们之间的安全关系。在 IPsec 中,这是通过称为 安全策略安全关联 的结构来实现的,并提供交换安全关联信息的方式。

密钥交换框架和机制 为了两个设备能够交换加密信息,它们需要能够共享用于解密密钥。它们还需要一种交换安全关联信息的方式。在 IPsec 中,一个名为 互联网密钥交换 (IKE) 的协议提供了这些功能。

提示

关键概念 IPsec 包含多个不同的组件,它们协同工作以提供安全服务。其中两个主要组件是名为 认证头 (AH)封装安全载荷 (ESP) 的协议,它们通过在 IP 数据报中添加特殊头部的方式,为 IP 数据提供真实性和隐私性。

好吧,这至少为理解 IPsec 的概念以及各个部分如何协同工作提供了一个框架。随着你继续阅读本章,你将更详细地研究这些组件和协议。

IPsec 架构与实现方法

IPsec 之所以如此强大,主要原因是它为 IP 提供了安全保护,而 IP 是所有其他 TCP/IP 协议的基础。在保护 IP 的同时,你也在保护 TCP/IP 中的几乎所有其他内容。因此,一个重要的问题是,你如何将 IPsec 精确地集成到 IP 中?部署 IPsec 有几种实现方法。这些方法代表了 IPsec 可能修改 TCP/IP 整体层架构的不同方式。

RFC 2401 中为 IPsec 定义了三种不同的实现架构。你使用哪一种取决于多种因素,包括使用的 IP 版本(IPv4 或 IPv6)、应用的需求以及其他因素。这些因素又基于一个主要实现决策:IPsec 应该被编程到网络上的所有主机中,还是仅编程到某些路由器或其他中间设备中?这是一个必须基于网络需求的设计决策:

端点主机实现 将 IPsec 集成到所有主机设备中提供了最大的灵活性和安全性。它使得网络中任何两个设备之间都能实现端到端的安全。然而,典型网络上有许多主机,这意味着这比仅在路由器中实现 IPsec 的工作量要大得多。

路由器实现 这个选项工作量要小得多,因为它意味着你只需对少数几个路由器进行更改,而不是数百或数千个客户端。它只提供实现 IPsec 的路由器对之间的保护,但这可能对于某些应用,如 VPN,已经足够了。路由器可以用来仅保护数据报在组织外部路由的部分,从而使得路由器和本地主机之间的连接保持未加密(或者可能通过其他方式加密)。

定义了三种不同的架构,描述了将 IPsec 集成到 TCP/IP 协议栈中的方法:集成架构、栈中凸起(BITS)架构和线中凸起(Bump in the Wire)。

集成架构

在理想情况下,我们会将 IPsec 的协议和能力直接集成到 IP 本身中。这是最优雅的解决方案,因为它允许像常规 IP 一样轻松地提供所有 IPsec 安全模式和功能。不需要额外的硬件或架构层。

IPv6 被设计用来支持 IPsec。因此,它对于主机或路由器来说是一个可行的选项。对于 IPv4,集成需要修改每个设备上的 IP 实现,这在很大程度上是不切实际的(至少可以说)。

栈中凸起(BITS)架构

在堆栈中断(BITS)技术中,IPsec 被作为一个独立的架构层置于 IP 和数据链路层之间。这个可爱的名字指的是 IPsec 是网络协议堆栈中的一个额外元素,正如您可以在图 29-2 中看到的那样。IPsec 在数据报通过协议堆栈传递时拦截它们,提供安全保护,并将它们传递到数据链路层。

IPsec 堆栈中断(BITS)架构 在这种类型的 IPsec 实现中,IPsec 成为了 TCP/IP 堆栈中的一个独立层。它作为位于 IP 之下的软件实现,并为 IP 层创建的数据报提供安全保护。

图 29-2. IPsec 堆栈中断(BITS)架构 在这种类型的 IPsec 实现中,IPsec 成为了 TCP/IP 堆栈中的一个独立层。它作为位于 IP 之下的软件实现,并为 IP 层创建的数据报提供安全保护。

这种技术的优点是,由于 IPsec 功能与 IP 分离,因此可以将其回接到任何 IP 设备。缺点是与集成架构相比,存在工作重复的问题。BITS 通常用于 IPv4 主机。

线中断(BITW)架构

在线中断(BITW)方法中,我们添加一个提供 IPsec 服务的硬件设备。例如,假设我们有一家公司有两个站点。每个站点都有一个网络,通过一个不具备 IPsec 功能的路由器连接到互联网。我们可以在两个站点的路由器和互联网之间插入一个特殊的 IPsec 设备,如图图 29-3 所示。这些设备将拦截发出的数据报,为它们添加 IPsec 保护,并从传入的数据报中移除。

IPsec 线中断(BITW)架构 在这种 IPsec 架构中,IPsec 实际上是部署在希望安全通信的设备之间的独立设备中。这些设备将不安全的 IP 数据报重新封装,以便在公共互联网上传输。

图 29-3. IPsec 线中的凸起(BITW)架构 在此 IPsec 架构中,IPsec 实际上是在位于希望安全通信的设备之间的独立设备中实现的。这些设备重新封装不安全的 IP 数据报,以便在公共互联网上传输。

正如 BITS 允许你将 IPsec 添加到旧主机一样,BITW 可以对非 IPsec 路由器进行改造,以提供安全优势。缺点是复杂性和成本。

提示

关键概念 为 IPsec 定义了三种不同的架构或实现模型。最好的是集成架构,其中 IPsec 直接构建到设备的 IP 层中。其他两种是 堆栈中的凸起(BITS)线中的凸起(BITW),它们是使用软件和硬件解决方案在常规 IP 下方分层 IPsec 的方法。

正如你将在下一节中看到的,架构的选择对可以使用哪两种 IPsec 模式有重要影响。顺便说一下,尽管 BITS 和 BITW 看起来相当不同,但它们实际上做的是同一件事。在 BITS 的情况下,我们有一个额外的软件层,它向现有的 IP 数据报添加安全性;在 BITW 中,专门的硬件设备执行这项相同的任务。在这两种情况下,结果都是相同的,并且对 IPsec 模式选择的影响也是相同的。

IPsec 模式:传输和隧道

你刚刚看到,可以使用三种不同的基本实现架构来为 TCP/IP 网络提供 IPsec 功能。你使用的实现选择,以及你是否在端主机或路由器中实现,会影响 IPsec 的具体工作方式。为与这些架构相关的两种特定操作模式定义了 IPsec。它们被称为 传输模式隧道模式

IPsec 模式与两个核心协议 AH 和 ESP 的功能密切相关。这两个协议通过向数据报添加包含安全信息的头部(以及可能的其他字段)来提供保护。模式的选择不影响每个协议生成其头部的方法,而是改变 IP 数据报的哪些特定部分受到保护以及如何安排头部以实现这一点。本质上,模式实际上描述了而不是规定了 AH 或 ESP 如何工作。它被用作定义其他结构,如安全关联(SAs)的基础。

传输模式

正如其名称所暗示的,在传输模式下,协议保护从传输层传递给 IP 的消息。该消息由 AH 和/或 ESP 处理,并在传输(UDP 或 TCP)头部之前添加适当的头部。然后,IP 头部由 IP 添加到前面。

另一种看待这个问题的方式如下:通常,传输层将数据打包以进行传输,并将其发送到 IP。从 IP 的角度来看,这个传输层消息是 IP 数据报的有效负载。当 IPsec 在传输模式下使用时,IPsec 头部仅应用于这个 IP 有效负载,而不是 IP 头部。AH 和 ESP 头部出现在原始的单个 IP 头部和 IP 有效负载之间。这如图图 29-4 所示。

隧道模式

在隧道模式下,IPsec 用于在 IP 头部已经应用于 IP 数据报之后,保护一个完全封装的 IP 数据报。IPsec 头部出现在原始 IP 头部之前,然后在新 IP 头部之前添加一个新 IP 头部。也就是说,整个原始 IP 数据报被加密,然后封装在另一个 IP 数据报中。这如图图 29-5 所示。

比较传输模式和隧道模式

理解两种 IPsec 模式之间差异的底线是:隧道模式保护整个原始 IP 数据报,包括头部,而传输模式则不保护。因此,总的来说,头部的顺序如下:

传输模式 IP 头部,IPsec 头部(AH 和/或 ESP),IP 有效负载(包括传输头部)

隧道模式 新 IP 头部,IPsec 头部(AH 和/或 ESP),旧 IP 头部,IP 有效负载

IPsec 传输模式操作 当 IPsec 在传输模式下运行时,它与 IP 集成并用于直接传输上层(TCP/UDP)消息。处理完毕后,数据报只有一个包含 AH 和 ESP IPsec 头部的 IP 头部。与图 29-5 中的隧道模式相比。

图 29-4. IPsec 传输模式操作 当 IPsec 在传输模式下运行时,它与 IP 集成并用于直接传输上层(TCP/UDP)消息。处理后,数据报只有一个包含 AH 和 ESP IPsec 头部的 IP 头部。与隧道模式相比,隧道模式在图 29-5 中展示。

再次强调,这是对 IPsec 数据报构建过程的简化视图;实际情况要复杂得多。在传输和隧道模式下,IPsec 数据报中头部的排列方式取决于所使用的 IP 版本。IPv6 在使用 IPsec 时必须以特定方式排列扩展头部。头部放置还取决于所使用的 IPsec 协议,AH 或 ESP。请注意,也可以将 AH 和 ESP 同时应用于同一个数据报;如果是这样,AH 头部总是出现在 ESP 头部之前。

因此,有三个变量和八种基本模式组合(隧道或传输)、IP 版本(IPv4 或 IPv6)和协议(AH 或 ESP)。接下来对 AH 和 ESP 的讨论将描述适用于每个协议的传输/隧道模式和 IPv4/IPv6 的四种格式组合。请注意,ESP 还包括一个 ESP 尾随数据保护后的数据。

通过阅读这些描述,您可能已经能够了解这两种模式如何与您之前查看的 IPsec 架构选择相关联。传输模式要求 IPsec 集成到 IP 中,因为 AH/ESP 必须在传输层消息的原 IP 封装过程中应用。这对于需要端到端安全且直接运行 IPsec 的主机实现通常是选择。

IPsec 隧道模式操作 IPsec 隧道模式之所以得名,是因为它代表了一个完整 IP 数据报的封装,从而在 IPsec 设备之间形成一个虚拟隧道。IP 数据报传递给 IPsec,在那里创建一个新的 IP 头部,并添加 AH 和 ESP IPsec 头部。与传输模式相比,请参见图 29-4。

图 29-5. IPsec 隧道模式操作 IPsec 隧道模式之所以得名,是因为它代表了对完整 IP 数据报的封装,从而在具有 IPsec 功能的设备之间形成一个虚拟隧道。IP 数据报被传递给 IPsec,在那里创建一个新的 IP 头部,并添加了 AH 和 ESP IPsec 头部。这与传输模式形成对比,传输模式在图 29-4 中展示。

隧道模式代表了 IP 在 IP 加上 IPsec 组合中的封装。因此,它与 BITS 和 BITW 实现相对应,在这些实现中,IPsec 在 IP 处理了高层消息并已添加其头部之后应用。隧道模式是 VPN 实现的一个常见选择,这些实现基于通过不安全的网络(如互联网)隧道传输 IP 数据报。

小贴士

关键概念 IPsec 有两种基本的工作模式。在传输模式中,IPsec AH 和 ESP 头部在创建原始 IP 数据报时添加。传输模式与集成 IPsec 架构相关联。在隧道模式中,原始 IP 数据报按正常方式创建,然后整个数据报被封装到一个新的 IP 数据报中,该数据报包含 AH/ESP IPsec 头部。隧道模式最常与bump in the stack (BITS)bump in the wire (BITW)实现一起使用。

IPsec 安全构造

重要 IPsec 安全构造包括安全关联、安全关联数据库、安全策略、安全策略数据库、选择器和安全参数索引。这些项目都密切相关,并且在开始查看核心 IPsec 协议之前是必不可少的。这些构造用于以一般方式指导 IPsec 的操作,特别是指导设备之间的交换。这些构造控制 IPsec 的工作方式,并确保每个进入或离开具有 IPsec 功能的设备的数据报都得到适当的处理。

安全策略、安全关联和相关数据库

让我们先考虑如何在处理许多不同数据报交换的设备上应用安全性的问题。提供安全性涉及开销,因此你不想为每个进出消息都这样做。某些类型的消息可能需要更多的安全性;其他可能需要较少。此外,与某些设备的交换可能需要与其他设备不同的处理。

为了管理所有这些复杂性,IPsec 配备了一种灵活、强大的方式来指定不同类型的数据报应该如何处理。要了解这是如何工作的,你必须首先定义以下两个重要的逻辑概念:

安全策略和安全策略数据库(SPD) 安全策略是编程到 IPsec 实现中的规则。它告诉实现如何处理设备接收到的不同数据报。例如,安全策略决定特定的数据包是否需要由 IPsec 处理。AH 和 ESP 完全绕过那些不需要处理的数据包。如果需要安全,安全策略提供了一般性指南,说明如何提供安全,并在必要时提供更具体细节的链接。设备的安全策略存储在设备的安全策略数据库(SPD)中。

安全关联(SA)和安全关联数据库(SAD) 安全关联(SA)是一组安全信息,描述了设备之间特定类型的安全连接。你可以将其视为一份合同,它指定了用于两个设备之间安全通信的特定安全机制。设备的安全关联包含在其安全关联数据库(SAD)中。

通常很难区分 SPD 和 SAD,因为它们在概念上相似。它们之间的主要区别是,安全策略是通用的,而安全关联更具体。为了确定如何处理特定的数据报,设备首先检查 SPD。SPD 中的安全策略可能引用 SAD 中的特定 SA。如果是这样,设备将查找该 SA 并使用它来处理数据报。

选择器

我还没有涉及的一个问题是设备如何确定为特定的数据报使用哪些安全策略或安全关联(SA)。同样在这里,IPsec 定义了一个非常灵活的系统,允许每个安全关联定义一组规则,用于选择 SA 应用到的数据报。这些规则集被称为选择器。例如,你可能定义一个选择器,它表示数据报源地址中特定范围的值,结合目标地址中的另一个值,意味着必须为该数据报使用特定的 SA。

安全关联三元组和安全参数索引(SPI)

设备与另一个设备进行的每次安全通信都需要建立 SA。SA 是单向的,因此每个 SA 只处理特定设备的入站或出站流量。这使得从设备 A 到设备 B 的流量安全级别可以不同于从设备 B 到设备 A 的流量安全级别。在这种双向通信中,设备 A 和设备 B 都会有两个 SA;设备 A 会有可以称为 SAdeviceBin 和 SAdeviceBout 的 SA。设备 B 会有 SAdeviceAin 和 SAdeviceAout。

然而,SA 实际上并没有名称。它们由一组三个参数定义,称为三元组

安全参数索引 (SPI) 一个 32 位的数字,用于唯一标识任何已连接设备上的特定安全关联 (SA)。SPI 被放置在 AH 或 ESP 数据报中,从而将每个安全数据报与安全关联链接起来。它被传输的接收者使用,以便知道哪个 SA 管理该数据报。

IP 目标地址 建立 SA 的设备的地址。

安全协议标识符 指定此关联是用于 AH 还是 ESP。如果这两种协议都与此设备一起使用,它们有独立的 SA。

正如你所见,两个安全协议 AH 和 ESP 依赖于 SA、安全策略以及控制这些 SA 和政策操作的各个数据库。管理这些数据库非常重要,但这完全是另一个复杂的话题。通常,SA 可以手动设置(这当然需要额外的工作)或者你可以部署一个使用 IKE(在本章末尾讨论)等协议的自动化系统。

感到困惑?我不怪你,尽管我尽了最大努力,并且记住,这一切都被高度简化了。欢迎来到网络安全的奇妙世界。如果你曾经被失眠困扰,我强烈推荐阅读 RFC 2401!

IPsec 认证头 (AH)

如我在本章前面提到的,AH 是 IPsec 中的两个核心安全协议之一。这是另一个名称选择得很好的协议。它通过添加基于数据报中值的计算出的头部,提供对数据报全部或部分内容的认证。用于计算的部分以及头部的放置取决于模式(隧道或传输)和 IP 版本(IPv4 或 IPv6)。

AH 的操作出奇地简单,尤其是对于任何与网络安全有关的协议来说。这种简单性类似于用于计算校验和或执行循环冗余(CRC)检查以检测错误的算法。在这些情况下,发送者使用标准算法根据消息内容计算校验和或 CRC 代码。这个计算结果与原始数据一起传输到目的地,目的地重复计算,如果发现其计算与源的计算有任何不一致,则丢弃该消息。

这与 AH 的理念相同,只是它使用的是一种特殊的哈希算法和只有源和目的地知道的特定密钥,而不是众所周知的简单算法。两个设备之间的 SA 指定了这些细节,这样源和目的地就知道如何执行计算,但其他人则无法知道。在源设备上,AH 执行计算并将结果(称为 完整性校验值ICV)放入一个带有其他传输字段的特殊头部中。目标设备使用两个设备共享的密钥执行相同的计算。这使得设备能够立即看到原始数据报中的任何字段是否被修改(无论是由于错误还是恶意)。

正如校验和不会改变原始数据一样,ICV 计算也不会改变原始数据。AH 头部的存在使我们能够验证消息的完整性,但它不会加密它。因此,AH 提供了 认证 但不提供 隐私(这是 ESP 的作用)。

AH 数据报放置和链接

IPv4 和 IPv6 的 AH 计算方式相似。一个不同之处在于将头部放入数据报以及将头部链接在一起的确切机制。我将首先描述 IPv6,因为它更简单,而且 AH 实际上是为了适应其机制而设计的。

IPv6 AH 放置和链接

在 IPv6 中,AH 作为扩展头部插入到 IP 数据报中,遵循正常的 IPv6 扩展头部链接规则。它通过前一个头部(扩展或主)进行链接,将 AH 头部的分配值(51)放入其 Next Header 字段。然后 AH 头部通过其 Next Header 字段链接到下一个扩展头部或传输层头部。

在传输模式下,AH 放入主 IP 头部,出现在任何包含旨在最终目的地的选项的 Destination Options 头部之前,如果存在 ESP 头部,则出现在任何其他扩展头部之后。在隧道模式下,它作为封装原始数据报的新 IP 数据报的扩展头部出现。这在 图 29-6 这是一个使用标准 IPv6 机制(参见第二十六章中的图 26-3)链接两个扩展头部的 IPv6 数据报的示例。当在传输模式下应用 AH 时,它简单地作为一个新的扩展头部添加(如深色阴影所示),位于路由扩展头部和目的地选项头部之间。在隧道模式下,整个原始数据报被封装到一个新的 IPv6 数据报中,该数据报包含 AH 头部。在这两种情况下,Next Header 字段都用于将每个头部链接到下一个。注意隧道模式中使用的 Next Header 值 41,这是封装的 IPv6 数据报的值。") 中有图形表示。

带有 IPsec 认证头(AH)的 IPv6 数据报格式,这是一个 IPv6 数据报的示例,它包含两个通过标准 IPv6 机制链接的扩展头(参见)。当 AH 在传输模式下应用时,它简单地作为一个新的扩展头(如图中深色阴影所示)添加,位于路由扩展头和目标选项头之间。在隧道模式下,整个原始数据报被封装到一个新的 IPv6 数据报中,该数据报包含 AH 头。在这两种情况下,Next Header 字段都用于将每个头链接到下一个头。注意隧道模式中 Next Header 值的使用,该值为封装的 IPv6 数据报的值。

图 29-6. 带有 IPsec 认证头(AH)的 IPv6 数据报格式 这是一个 IPv6 数据报的示例,它包含两个通过标准 IPv6 机制链接的扩展头(参见图 26-3)。当 AH 在传输模式下应用时,它简单地作为一个新的扩展头(如图中深色阴影所示)添加,位于路由扩展头和目标选项头之间。在隧道模式下,整个原始数据报被封装到一个新的 IPv6 数据报中,该数据报包含 AH 头。在这两种情况下,Next Header 字段都用于将每个头链接到下一个头。注意隧道模式中 Next Header 值的使用,该值为封装的 IPv6 数据报的值。

IPv4 AH 放置和链接

在 IPv4 中,采用了一种类似于 IPv6 头链接技术的方法。在 IPv4 数据报中,协议字段指示数据报中携带的更高层协议(通常是 TCP 或 UDP)的身份。因此,该字段指向下一个头,即 IP 有效载荷的前端。AH 采用这个值并将其放入其 Next Header 字段,然后将 AH 本身的协议值(点分十进制中的 51)放入 IP 协议字段。这使得 IP 头指向 AH,然后 AH 指向 IP 数据报之前指向的内容。

再次强调,在传输模式下,AH 头部添加到原始数据报的主要 IP 头部之后;在隧道模式下,它添加到封装原始数据报的新 IP 头部之后。这如图 图 29-7 所示。

带有 IPsec AH 的 IPv4 数据报格式 这里是一个 IPv4 数据报的示例;它可能包含或不包含 IPv4 选项(与 IPv6 中的情况不同,它们不是独立的实体)。在传输模式下,AH 头部添加到 IP 头部和 IP 数据之间;IP 头部的协议字段指向它,而其下一个头部字段包含 IP 头部的前一个协议值(在这种情况下为 6,表示 TCP)。在隧道模式下,IPv4 数据报封装到一个新的 IPv4 数据报中,该数据报包含 AH 头部。请注意,在隧道模式下,AH 头部在其下一个头部字段中使用值 4(表示 IPv4)

图 29-7. 带有 IPsec AH 的 IPv4 数据报格式 这里是一个 IPv4 数据报的示例;它可能包含或不包含 IPv4 选项(与 IPv6 中的情况不同,它们不是独立的实体)。在传输模式下,AH 头部添加到 IP 头部和 IP 数据之间;IP 头部的协议字段指向它,而其下一个头部字段包含 IP 头部的前一个协议值(在这种情况下为 6,表示 TCP)。在隧道模式下,IPv4 数据报封装到一个新的 IPv4 数据报中,该数据报包含 AH 头部。请注意,在隧道模式下,AH 头部在其下一个头部字段中使用值 4(表示 IPv4)。

小贴士

关键概念 IPsec 认证头 (AH) 协议允许接收方验证数据报的真实性。它作为头部添加到包含 完整性校验值 (ICV) 的 IP 数据报中,该值基于数据报中字段的值计算得出。接收方可以使用此值来确保数据在传输过程中未被更改。AH 不加密数据,因此不保证传输的隐私性。

AH 格式

AH 格式在 表 29-2 格式") 中描述,并在 图 29-8 格式") 中展示。

表 29-2. IPsec 认证头(AH)格式

字段名称 大小(字节) 描述
下一个头部 1 包含 AH 之后的下一个头部的协议号。用于将头部链接在一起。
有效载荷长度 1 尽管其名称,此字段测量的是认证头本身的长度,而不是有效载荷的长度。(我想知道其背后的历史是什么!)它以 32 位为单位进行测量,为了与 IPv6 中通常计算头部长度的方法保持一致,减去 2。
保留 2 未使用;设置为 0。
SPI 4 一个 32 位值,当与目的地址和安全协议类型(在这里显然是 AH)结合时,可以识别出将用于此数据报的安全关联(SA)。(SAs 在本章前面已有讨论。)
序列号 4 当两个设备之间形成 SA 时,该计数器字段被初始化为 0,然后为使用该 SA 发送的每个数据报递增。这唯一地标识了 SA 上的每个数据报,并用于通过防止捕获的数据报的重传来提供对重放攻击的保护。
认证数据 可变 包含 AH 协议执行的哈希算法的结果,称为完整性校验值(ICV)。

IPsec 认证头(AH)格式

图 29-8. IPsec 认证头(AH)格式

认证数据字段的大小是可变的,以支持不同的数据报长度和哈希算法。其总长度必须是 32 位的倍数。此外,整个头部必须是 32 位(对于 IPv4)或 64 位(对于 IPv6)的倍数,因此如果需要,可以在认证数据字段中添加额外的填充。

你也可能注意到,在头部没有出现任何 IP 地址,这是它对 IPv4 和 IPv6 都相同的前提条件。

IPsec 封装安全载荷(ESP)

IPsec AH 为具有 IPsec 功能的设备提供完整性认证服务,以便它们可以验证从其他设备接收到的消息是否完整。然而,对于许多应用来说,这仅仅是谜题的一部分。我们不仅希望防止中间设备更改数据报,还希望防止它们检查其内容。对于这种级别的私密通信,AH 是不够的;我们需要使用 ESP 协议。

ESP 的主要任务是通过对数据报进行加密来提供我们所需的 IP 数据报的隐私。加密算法将数据报中的数据与密钥结合,将其转换为加密形式。然后使用你很快就会看到的特殊格式重新封装,然后传输到目的地,目的地使用相同的算法进行解密。ESP 还拥有自己的认证方案,类似于 AH 中使用的方案,或者它可以与 AH 一起使用。

ESP 字段

ESP 有几个字段与 AH 中使用的字段相同,但它以非常不同的方式打包其字段。它不仅仅有一个标题,而是将其字段分为三个部分:

ESP 标题 这包含两个字段,SPI 和序列号,位于加密数据之前。其位置取决于 ESP 是否在传输模式或隧道模式中使用,如本章前面所述。

ESP 尾迹 此部分放置在加密数据之后。它包含用于通过填充和填充长度字段对齐加密数据的填充。有趣的是,它还包含 ESP 的 Next Header 字段。

ESP 认证数据 此字段包含一个 ICV,其计算方式类似于 AH 协议的工作方式。当 ESP 使用可选的认证功能时,使用此字段。

将这些字段拆分成这样的原因有两个。第一个原因是某些加密算法要求加密的数据具有特定的块大小,因此必须在数据之后而不是之前添加填充。这就是为什么填充出现在 ESP 尾迹字段中的原因。第二个原因是 ESP 认证数据单独出现,因为它用于在加密之后对加密数据报的其余部分进行认证。这意味着它不能出现在 ESP 标题或 ESP 尾迹中。

ESP 操作和字段使用

这仍然有点令人困惑,所以我将尝试通过考虑 ESP 执行的三步基本步骤来按程序解释:计算标题,然后是尾迹,然后是认证字段。

标题计算和放置

首先要考虑的是 ESP 标题的放置。这与 AH 的工作方式类似,并取决于 IP 版本,如下所示:

IPv6 ESP 标题字段作为扩展标题插入到 IP 数据报中,遵循正常的 IPv6 扩展标题链接规则。在传输模式下,它出现在包含最终目的地选项的标题之前,但在任何其他扩展标题之后(如果有)。在隧道模式下,它作为封装原始数据报的新 IP 数据报的扩展标题出现。这如图图 29-9 所示。

IPv4 与 AH 类似,ESP 头部字段放置在正常的 IPv4 头部之后。在传输模式下,它出现在原始数据报的 IP 头部之后;在隧道模式下,它出现在封装原始数据报的新 IP 数据报的 IP 头部之后。您可以在图 29-10 中看到这一点。

拖车计算和放置

ESP 拖车字段被附加到将要加密的数据上。ESP 随后执行加密操作。有效载荷(TCP/UDP 消息或封装的 IP 数据报)以及 ESP 拖车都被加密,但 ESP 头部不被加密。再次提醒,任何出现在 ESP 头部和有效载荷之间的其他 IP 头部也会被加密。在 IPv6 中,这可以包括目标选项扩展头部。

通常,下一个头部字段会出现在 ESP 报头中,并用于将 ESP 报头与其后的报头链接起来。然而,ESP 中的下一个头部字段出现在尾部而不是头部,这使得 ESP 中的链接看起来有点奇怪。该方法基本上与 AH 以及 IPv6 中的方法相同,使用下一个头部和协议字段将一切联系起来。然而,在 ESP 中,下一个头部字段出现在加密数据之后,因此它指向以下之一:一个存在的目标选项扩展报头(如果存在)、TCP/UDP 报头(在传输模式下),或 IPv4/IPv6 报头(在隧道模式下)。这也在图 图 29-9 和 图 29-10 中展示。

ESP 认证字段计算和放置

如果使用可选的 ESP 认证功能,它是在整个 ESP 数据报上计算的(当然,不包括认证数据字段本身)。这包括 ESP 报头、有效载荷和尾部。

小贴士

关键概念 IPsec ESP 协议允许对数据报的内容进行加密,从而确保只有预期的接收者才能看到数据。ESP 通过三个组件实现:一个添加到受保护数据报前面的 ESP 报头,一个跟随受保护数据的 ESP 尾部,以及一个可选的 ESP 认证 数据字段,它提供类似于 AH 提供的认证服务。

带 IPsec ESP 的 IPv6 数据报格式这是您在之前看到的相同示例 IPv6 数据报,具有两个扩展头部。当 ESP 在传输模式下应用时,ESP 头部字段被添加到现有数据报中,就像 AH 一样,ESP 尾部和 ESP 认证数据字段放置在末尾。在隧道模式下,ESP 头部和尾部字段包围整个封装的 IPv6 数据报。注意每种情况下的加密和认证范围,以及 Next Header 字段如何回指到数据报,因为它出现在 ESP 尾部。

图 29-9. 带 IPsec ESP 的 IPv6 数据报格式这是您在图 29-6 的 IPv6 数据报格式这是一个带有两个扩展头部的 IPv6 数据报示例,这些扩展头部使用标准的 IPv6 机制链接(参见第二十六章的图 26-3)。当 AH 在传输模式下应用时,它简单地作为一个新的扩展头部添加(如深色阴影所示),位于路由扩展头部和目标选项头部之间。在隧道模式下,整个原始数据报封装到一个新的 IPv6 数据报中,该数据报包含 AH 头部。在这两种情况下,Next Header 字段都用于将每个头部链接到下一个。注意隧道模式中使用的 Next Header 值 41,这是封装的 IPv6 数据报的值。")中看到的相同示例 IPv6 数据报,具有两个扩展头部。当 ESP 在传输模式下应用时,ESP 头部字段被添加到现有数据报中,就像 AH 一样,ESP 尾部和 ESP 认证数据字段放置在末尾。在隧道模式下,ESP 头部和尾部字段包围整个封装的 IPv6 数据报。注意每种情况下的加密和认证范围,以及 Next Header 字段如何回指到数据报,因为它出现在 ESP 尾部。

IPv4 数据报格式与 IPsec ESP这是您在之前看到的相同样本 IPv4 数据报。当 ESP 在传输模式下处理此数据报时,ESP 头部字段位于 IPv4 头部和数据之间,ESP 尾部和 ESP 认证数据字段随后。在隧道模式下,整个原始 IPv4 数据报被这些 ESP 组件包围,而不仅仅是 IPv4 数据。同样,请注意加密和认证范围,以及 Next Header 字段如何回指以指定加密数据或数据报的身份。

图 29-10. 带有 IPsec ESP 的 IPv4 数据报格式 这里是您在 图 29-7。)。当 ESP 在传输模式下处理此数据报时,ESP 头部字段被放置在 IPv4 头部和数据之间,ESP 尾部和 ESP 认证数据字段随后。在隧道模式下,整个原始 IPv4 数据报被这些 ESP 组件包围,而不仅仅是 IPv4 数据。再次强调,正如在 图 29-9, 注意加密和认证覆盖,以及 Next Header 字段如何指向数据报内部以指定加密数据或数据报的身份。

ESP 格式

ESP 部分 和 字段的格式在 表 29-3 格式") 中描述,并在 图 29-11 中展示。在这张图和表中,我都明确显示了字段的加密和认证覆盖,以阐明其工作原理。

表 29-3. IPsec 封装安全载荷 (ESP) 格式

部分 字段名称 大小(字节) 描述 加密覆盖 认证覆盖
ESP 头部 SPI 4 一个 32 位值,与目标地址和安全协议类型结合使用,以标识将用于此数据报的安全关联(SAs)。(SAs 在本章前面已讨论。)
序列号 4 当两个设备之间形成安全关联(SA)时,计数器字段初始化为零,然后为使用该 SA 发送的每个数据报递增。这用于提供防止重放攻击的保护。
有效载荷 有效载荷数据 可变 加密的有效载荷数据,由高层消息或封装的 IP 数据报组成。它还可以包括支持信息,例如某些加密方法所需的初始化向量。
ESP 尾部 填充 可变(0 到 255) 根据需要包含额外的填充字节,用于加密或对齐。
填充长度 1 前一个填充字段中的字节数。
下一个头部 1 包含数据报中下一个头部的协议号。用于链接头部。
ESP 认证数据 可变 包含由可选的 ESP 认证算法应用产生的 ICV。

IPsec ESP 格式 注意,此格式中的大多数字段和部分都是可变长度的。例外的是 SPI 和序列号字段,它们都是 4 个字节长,填充长度和下一个头部字段各为 1 个字节。

图 29-11. IPsec ESP 格式 注意,此格式中的大多数字段和部分都是可变长度的。例外的是 SPI 和序列号字段,它们都是 4 个字节长,填充长度和下一个头部字段各为 1 个字节。

填充字段在加密算法需要时使用。填充还用于确保 ESP 尾部字段以 32 位边界结束。也就是说,ESP 头部字段的大小加上有效载荷字段,再加上 ESP 尾部字段的大小必须是 32 位的倍数。ESP 认证数据字段也必须是 32 位的倍数。

IPsec 互联网密钥交换(IKE)

IPsec,就像许多安全网络协议集一样,基于共享密钥的概念。两个想要安全发送信息的设备使用只有它们知道的信息进行编码和解码。任何不知道这个秘密的人都能拦截信息,但被阻止读取它(如果使用 ESP 加密有效载荷),或者不被察觉地篡改它(如果使用 AH)。然而,在 AH 或 ESP 可以使用之前,两个设备必须交换安全协议本身将使用的密钥。在 IPsec 中,用于此目的的主要支持协议被称为互联网密钥交换(IKE)

IKE 定义在 RFC 2409 中,它是 IPsec 协议中较难理解的一个。实际上,如果没有在密码学方面的深厚背景,真正理解其操作的真实简化几乎是不可能的。我并没有密码学背景,而且我必须假设我的读者也没有。因此,为了避免在这个主题中充斥着令人困惑的缩写和未解释的概念,我将只提供一个 IKE 的简要概述以及它是如何被使用的。

IKE 概述

IKE 的目的是允许设备交换用于安全通信所需的信息。正如标题所暗示的,这包括用于编码认证信息和执行有效载荷加密的加密密钥。IKE 通过允许 IPsec 兼容设备交换 SA 来工作,这些 SA 填充了它们的 SAD。然后,这些 SAD 被用于使用 AH 和 ESP 协议实际交换受保护的数据报。

IKE 被认为是混合协议,因为它结合(并补充)了三个其他协议的功能。首先是 互联网安全关联和密钥管理协议(ISAKMP)。该协议提供了一个交换加密密钥和安全关联信息的框架。它通过允许通过一系列阶段协商安全关联来运行。

ISAKMP 是一个支持许多不同密钥交换方法的通用协议。在 IKE 中,ISAKMP 框架被用作结合两个密钥交换协议特性的特定密钥交换方法的基础:

OAKLEY 描述了一种通过定义各种密钥交换模式来交换密钥的特定机制。IKE 的密钥交换过程的大部分基于 OAKLEY。

SKEME 描述了一种不同于 OAKLEY 的密钥交换机制。IKE 使用了 SKEME 的某些特性,包括其公钥加密方法和快速重新密钥功能。

IKE 操作

IKE 并不严格实现 OAKLEY 或 SKEME,而是从每个协议中取其精华,形成自己使用 ISAKMP 的方法。我知道这听起来很混乱。因为 IKE 在 ISAKMP 框架内运行,其操作基于 ISAKMP 分阶段协商过程。有两个阶段,如下所示:

ISAKMP Phase 1 第一阶段是一个设置阶段,其中两个设备就如何安全地交换更多信息达成一致。这两个单元之间的协商创建了一个 ISAKMP 自身的 SA:一个 ISAKMP SA。然后,这个安全关联在第二阶段用于安全地交换更详细的信息。

ISAKMP Phase 2 在这个阶段,第一阶段建立的 ISAKMP SA 用于为其他安全协议创建 SAs。通常,这就是协商 AH 和 ESP 协议“真实”SA 参数的地方。

一个明显的问题是为什么 IKE 要费心采用这种两阶段方法。为什么不一开始就协商 AH 或 ESP 的安全关联(SA)呢?嗯,尽管额外的阶段增加了开销,但一旦完成第一阶段,就可以进行多个第二阶段的协商,从而分摊两阶段方法的额外成本。一旦在第一阶段建立了 ISAKMP SA,也可以使用更简单的交换方法进行第二阶段的协商。

第一阶段协商的 ISAKMP SA 包括后续协商中使用的以下属性:

  • 一种加密算法,例如 数据加密标准 (DES)

  • 一种哈希算法(MD5 或 SHA,如 AH 或 ESP 所用)

  • 一种认证方法,例如使用先前共享的密钥进行认证

  • 一个 Diffie-Hellman 群组

注意

Diffie 和 Hellman 是行业中的两位先驱,他们发明了公钥加密。在这种方法中,不是使用相同的密钥进行加密和解密,而是使用任何人都可以知道的公钥进行加密,并使用保密的私钥进行解密。Diffie-Hellman 群组定义了执行此类加密的属性。IKE 中指定了从 OAKLEY 衍生的四个预定义群组,并允许定义新的群组

注意,尽管安全关联(SA)通常是单向的,但 ISAKMP SA 是双向建立的。一旦第一阶段完成,任何设备都可以使用 ISAKMP SA 设置后续的 AH 或 ESP 安全关联。

第三十章. 互联网协议移动支持(移动 IP)

无标题图片

互联网协议(IP)是计算中最成功的网络层协议,因为它具有许多优点,但它也有一些弱点,其中许多随着网络的演变而变得更加重要。无类别寻址和网络地址转换(NAT)等技术对抗了 IP 版本 4(IPv4)地址空间的耗尽,而 IPsec 为其提供了所缺少的安全通信。IP 的另一个弱点是它没有考虑到移动计算机。

尽管移动设备当然可以使用 IP,但设备寻址和数据报路由的方式在它们从一个网络移动到另一个网络时会导致问题。在 IP 开发的时候,计算机体积庞大且很少移动。今天,我们有数百万台笔记本电脑和更小的设备,其中一些甚至使用无线网络连接到有线网络。为这些移动设备提供完整的 IP 功能的重要性已经大幅增长。为了在移动环境中支持 IP,开发了一种新的协议,称为 IP 移动支持,或更简单地,移动 IP

在本章中,我描述了为克服移动计算机连接到 IP 互联网的问题而开发的特殊协议。我首先概述了移动 IP 及其创建的原因。我讨论了定义移动 IP 及其一般操作模式的重要概念。然后,我转向移动 IP 工作的一些具体细节。这包括对特殊移动 IP 寻址方案的描述,解释移动设备如何发现代理,讨论与设备的主代理注册的过程,以及最后解释数据是如何封装和路由的。我讨论了移动 IP 对 TCP/IP 地址解析协议(ARP)操作的影响。我通过检查使用移动 IP 时出现的效率和安全性问题来结束本章。

注意

本节专门描述了 IPv4 网络如何提供 IP 移动性支持。它不涉及 IPv6 中移动性实现的更具体细节

提示

背景信息 如果您不熟悉 IP 寻址和路由的基础知识,我强烈建议在阅读有关移动 IP 的内容之前,至少阅读第第十六章和第二十三章

移动 IP 概述、历史和动机

过去几年中,移动计算因其小型化技术的进步而大大增加了其受欢迎程度。如今,我们可以在笔记本电脑或甚至手持计算机中获得曾经需要庞大机器才能提供的强大功能。我们还拥有无线局域网(WLAN)技术,它能够轻松地让设备从一个地方移动到另一个地方,并在数据链路层保持网络连接。不幸的是,IP 是在巨无霸时代开发的,它并没有设计成优雅地处理移动的计算机。要了解为什么 IP 在移动环境中表现不佳,你必须回顾 IP 寻址和路由是如何工作的。

TCP/IP 中移动节点的难题

如果您阅读过本书中关于 IP 寻址的任何材料——我当然希望您已经阅读过——您知道 IP 地址在本质上分为两部分:网络标识符(网络 ID)和主机标识符(主机 ID)。网络 ID 指定主机所在的网络,而主机 ID 唯一地指定网络内的主机。这种结构是数据报路由的基础,因为设备使用数据报目的地址的网络 ID 部分来确定接收者是在本地网络还是远程网络,而路由器则使用它来确定如何路由数据报。

这是一个很好的系统,但它有一个关键的缺陷:IP 地址与设备所在网络紧密绑定。大多数设备永远不会(或者至少很少)更改它们的网络连接点,因此这对它们来说不是问题,但对于移动设备来说确实是一个问题。当移动设备离开其本地位置时,基于 IP 地址的路由系统就会崩溃。这如图图 30-1 所示。

网络 ID 和主机 IP 地址的紧密绑定意味着,当移动设备从一个网络移动到另一个网络时,在传统的 IP 环境下,只有两种实际的选择:

更改 IP 地址 我们可以将主机的 IP 地址更改为一个新的地址,该地址包含它要移动到的网络的网络 ID。

解耦 IP 路由与地址 我们可以改变设备路由的方式,使得路由器不再根据设备的网络 ID 发送数据包到设备,而是根据其整个地址进行路由。

移动设备在 IP 互联网上的主要问题 在这个例子中,一个移动设备(笔记本电脑)已经从其在伦敦的本地网络移动到东京的另一个网络。一个远程客户端(左上角)决定向移动设备发送一个数据包。然而,它并不知道设备已经移动。由于它使用移动节点的本地地址 71.13.204.20 发送,其请求被路由到负责该网络的路由器,该路由器位于伦敦。移动设备不在那里,所以路由器无法将其交付。移动 IP 通过赋予移动设备和路由器将数据包从一处转发到另一处的功能来解决此问题。

图 30-1. IP 互联网中移动设备的主要问题 在这个例子中,一个移动设备(笔记本电脑)已从其在伦敦的本地网络移动到另一个在东京的网络。一个远程客户端(左上角)决定向移动设备发送数据报。然而,它不知道设备已经移动。由于它使用移动节点的本地地址 71.13.204.20 发送,其请求被路由到负责该网络的路由器,该路由器位于伦敦。移动设备不在那里,因此路由器无法将其传递。移动 IP 通过使移动设备和路由器能够将数据报从一个位置转发到另一个位置来解决此问题。

这些看起来似乎都是可行的选择,如果只有少数设备尝试它们,它们可能有效。不幸的是,它们都效率低下,通常不实用,并且由于以下原因,它们都不具有可扩展性(当数千或数百万个设备尝试时是实用的):

  • 每次设备移动时更改 IP 地址既费时又通常需要人工干预。此外,整个 TCP/IP 堆栈都需要重新启动,从而中断任何现有的连接。

  • 如果我们更改移动设备的 IP 地址,我们如何将地址更改通知互联网上的其他设备?这些设备将只有移动节点的原始本地地址,这意味着即使我们给它一个与其新位置匹配的新地址,它们也无法找到它。

  • 基于主机完整地址的路由意味着整个互联网将被每个移动计算机的路由信息淹没。考虑到为了减少路由表条目而投入了大量精力开发诸如无类别寻址等技术,显然这是一个潘多拉的盒子,没有人愿意触碰。

小贴士

关键概念 在 IP 互联网中支持移动设备的基本问题是使用 IP 地址进行路由。这意味着设备的 IP 地址与其所在网络绑定。如果设备更改网络,发送到其旧地址的数据无法通过常规方式传递。传统的解决方案,如通过完整 IP 地址进行路由或手动更改 IP 地址,通常会产生更多问题。

解决方案:移动 IP

解决这些困难的方法是定义一个新的协议,专门用于支持移动设备,该协议增加了原始 IP 的功能。这个协议被称为IPv4 的 IP 移动性支持,最初在 RFC 2002 中定义,在 RFC 3220 中更新,现在在 RFC 3344 中描述。该文档标题中给出的正式名称相当长;这项技术更常见地被称为移动 IP,不仅在 RFC 本身中,而且在网络专业人士中也如此。

为了确保其成功,移动 IP 的设计者必须达到一系列重要的目标。由此产生的协议具有以下关键属性和特性:

使用现有设备地址实现无缝设备移动 移动设备可以在继续使用其现有 IP 地址的同时更改其物理网络连接方法和位置。

无需新的寻址或路由要求 与常规 IP 一样,寻址和路由的整体方案得到保持。IP 地址仍然按照每个设备所有者的传统方式分配。不对互联网施加新的路由要求,例如主机特定的路由。

互操作性 移动 IP 设备仍然可以向不知道如何使用移动 IP 的现有 IP 设备发送和接收数据,反之亦然。

层透明性 移动 IP 所做的更改仅限于网络层。传输层和更高层的协议和应用程序能够像在常规 IPv4 中一样运行,并且现有的连接甚至可以在移动过程中保持。

有限的硬件更改 需要修改移动设备的软件以及移动设备直接使用的路由器。然而,其他设备不需要更改,包括家庭网络和访问网络之间的路由器。

可扩展性 移动 IP 允许设备从任何网络更改为任何其他网络,并支持任意数量的设备这样做。连接更改的范围可以是全球性的;例如,您可以从伦敦的办公室断开一台笔记本电脑并将其移动到澳大利亚或巴西,它的工作方式将与您将其带到隔壁办公室时相同。

安全性 移动 IP 通过重定向消息来工作,并包括认证程序以防止未经授权的设备引起问题。

移动 IP 通过为移动设备实现一个转发系统来实现这些目标。当移动单元在其家庭网络中时,它正常工作。当它移动到不同的网络时,数据报从其家庭网络发送到其新位置。这使得不知道移动 IP 的正常主机和路由器可以继续像移动设备没有移动一样操作。需要特殊支持服务来实现移动 IP;这些服务允许诸如让移动设备确定其位置、告诉家庭网络将消息转发到何处等活动。

提示

关键概念 移动 IP 通过建立一个系统来解决与设备更改网络位置相关的问题,该系统使得发送到移动节点家庭位置的数据报无论其位于何处都会被转发给它。它特别适用于无线设备,但也可以用于任何定期在网络上移动的设备。

移动 IP 通常与无线网络相关联,因为使用 WLAN 技术的设备可以轻松地从一个网络移动到另一个网络。然而,它并不是专门为无线网络设计的。它同样适用于从一个建筑物的以太网网络移动到另一个建筑、城市或国家的网络。移动 IP 对于许多旅行销售人员、访问客户场所的顾问、在校园中四处走动解决问题的管理员等众多应用来说,可以带来极大的好处。

移动 IP 的局限性

重要的是要认识到,移动 IP 在无线环境中的有用性存在某些局限性。它被设计来处理设备的移动性,但只有相对较少的移动性。这是由于每次更改所涉及的工作。当你每周、每天甚至每小时移动一次计算机时,这种开销并不是什么大问题。对于“实时”移动性,如无线网络中的漫游,数据链路层的手交功能可能更适合。移动 IP 是在特定的假设下设计的,即连接点不会每秒更改超过一次。

移动 IP 旨在与保持静态 IP 配置的设备一起使用。由于设备需要能够始终知道其主网络和正常 IP 地址的身份,因此在使用动态获取 IP 地址的设备(如动态主机配置协议 DHCP)时,它要困难得多。

移动 IP 概念和通用操作

我喜欢类比,因为它们提供了一种方式,用你可以理解的语言来解释通常枯燥的技术概念。移动设备在 IP 互联网中的问题可以很容易地与现实生活中移动和信息传输问题相比较:为那些旅行的人的邮件投递。

假设你是一名为大型公司工作的顾问,该公司拥有许多办事处。你的家办公室位于英国伦敦,你大约有一半的时间在那里。其余时间被分配给其他办事处,比如罗马、东京、纽约市和多伦多。你偶尔还会访问客户场所,这些场所可能遍布世界各地。你可能会在这些偏远地点待上几周的时间。

问题是如何安排事情,以便无论你在哪里都能收到你的邮件?你面临的问题与常规 IP 在移动设备上遇到的问题相同,而且如果不采取特殊措施,你有两种不令人满意的选择来解决它:更改地址或解除地址与路由的耦合。你不能每次搬家时都更改你的地址,因为你需要不断地修改它;等你告诉每个人你的新地址时,它可能又变了。而且你当然不能“解除”邮件路由与你的地址的耦合,除非你想建立自己的邮政系统!

解决这个困境的方法是邮件转寄。假设你离开伦敦去东京几个月。你告诉伦敦邮局(PO),你将在东京。他们会拦截寄往你正常伦敦地址的邮件,重新标记,并将其转发到东京。根据你停留的地方,这封邮件可能会直接转寄到东京的新地址,或者转寄到东京邮局,你可以在那里取件。如果你离开东京去另一个城市,你只需给伦敦邮局打电话,告诉他们你的新位置。当你回家时,你取消转寄,像往常一样取回你的邮件。(是的,我假设伦敦和东京每个地方只有一个邮局。)

这个系统的优点很多。它相对简单易懂且易于实施。对于给你发送邮件的每个人来说,它也是透明的;他们仍然会将邮件发送到伦敦,而邮件会到达它需要去的地方。转寄机制的处理仅由伦敦邮局(PO)以及你目前所在地的邮局进行;邮政系统的其他部分甚至不知道有任何异常情况发生。

当然,也有一些缺点。伦敦邮局可能会免费提供偶尔的转寄服务,但如果你定期这样做,可能会向你收费。你可能在旅行的城市也需要特别的安排。每次搬家时,你都需要与你的家乡邮局保持沟通。而且,每一封信件都必须通过系统发送两次——首先发送到伦敦,然后发送到你所在的地方——这非常低效。

移动 IP 的工作方式与我刚才描述的邮件转寄系统非常相似。移动顾问是那些在网络之间移动的设备。每个网络可以被视为一个不同的城市,路由器之间的互联网就像邮政系统。连接任何网络到互联网的路由器就像该网络的邮局,从 IP 的角度来看。

移动节点通常驻留在其本地网络上,这是由其 IP 地址中的网络 ID 指示的。互联网上的设备始终使用此地址进行路由,因此“邮件”(数据报)始终到达设备的“家”中的路由器。当设备前往另一个网络时,本地路由器(“邮局”)拦截这些数据报并将它们转发到设备的当前地址。它可以直接使用一个新的临时地址将它们发送到设备,或者将它们发送到设备当前网络上的路由器(在我们的类比中是“另一个邮局”或东京)以进行最终交付。您可以在图 30-2 中查看移动 IP 操作的概述。

移动 IP 的通用操作 此图与类似,但显示了移动 IP 的实现。移动节点的本地路由器充当本地代理,而东京的路由器充当外地代理。移动节点在东京期间被分配了一个临时的“照顾”地址来使用(在这种情况下是一个与本地节点共位的照顾地址,意味着它直接分配给移动节点。展示了使用另一种类型的照顾地址的相同示例)。在步骤 1 中,远程客户端使用其本地地址向移动节点发送数据报,就像正常的 TCP/IP 一样。它像往常一样到达伦敦。在步骤 2 中,本地代理将那个数据报封装在一个新的数据报中,并将其发送到东京的移动节点。

图 30-2. 移动 IP 的一般操作 这个图与 图 30-1, 除了它展示了移动 IP 的实现。移动节点的本地路由器作为本地代理,东京的路由器作为外地代理。移动设备在东京期间被分配了一个临时的“照顾”地址来使用(在这种情况下是一个与本地节点共位的照顾地址,这意味着它直接分配给移动节点。图 30-3 展示了使用另一种类型的照顾地址的相同示例)。在步骤 1 中,远程客户端使用其本地地址向移动设备发送一个数据报,就像正常的 TCP/IP 一样。它像往常一样到达伦敦。在步骤 2 中,本地代理将那个数据报封装在一个新的数据报中,并将其发送到东京的移动节点。

移动 IP 设备角色

正如你所见,正如邮件转发需要来自一个或多个邮局的支持一样,移动 IP 需要两个路由器的帮助。以下特殊名称被赋予实现该协议的三个主要参与者(也显示在图 30-2

图 30-3. 使用国外代理的“照顾”地址的移动 IP 操作 此图与 图 30-2 类似,但不同的是,移动节点没有位于同一地点(不同)的 IP 地址,这里移动节点正在使用国外代理的照顾地址。这意味着节点的照顾地址实际上是国外代理自己的地址。步骤 1 与 图 30-2 相同,但在步骤 2 中,本地代理不是直接转发到移动节点,而是转发到国外代理(因为那个路由器是移动节点正在使用的 IP 地址所属的路由器)。在步骤 3 中,国外代理移除本地代理的包装,并将原始数据报交付给移动节点。这通常使用连接移动节点和国外代理的任何第 2 层(局域网或无线局域网)技术来完成。

在顾问类比中,此类照顾地址就像从伦敦邮政局转发到东京邮政局。伦敦人员会取走寄给约翰·史密斯的信件,并重新包装以交付给东京的约翰·史密斯,由东京邮政局照顾。东京邮政局(或约翰·史密斯本人)需要担心最后一段的交付。

同地照顾地址

本地转交地址是直接使用移动 IP 之外的手段分配给移动节点的。例如,它可能在外国网络上手动分配,或者可能通过 DHCP 自动分配。在这种情况下,转交地址用于将来自本地代理的流量直接转发到移动节点。这种类型的地址在前面图 30-2 中进行了描述。

由于与常规路由器发现的相似性,将代理发现作为现有过程的修改而不是建立全新的系统来实现是有意义的。代理发现过程中使用的消息如下:

代理广告 这是一个由作为移动 IP 代理的网关定期传输的消息。它由一个或多个添加了包含移动节点特定信息的扩展的常规路由器广告消息组成。

代理请求 这个消息可以被移动 IP 设备发送,以促使本地代理发送代理广告消息。

这些消息的使用在移动 IP 标准中进行了详细描述,并且不出所料,与常规路由器广告和路由器请求消息的使用非常相似。代理通常配置为定期发送代理广告,速率设置为确保与移动节点快速联系而不消耗过多的网络带宽。它们必须通过发送广告来响应它们收到的任何代理请求消息。可能某些代理被配置为仅在收到请求时发送广告。

移动节点需要接受和处理代理通告。它们通过查看消息的大小来区分这些通告和常规路由器通告。然后它们解析扩展(s)以了解本地代理的能力。它们确定自己是在本地网络还是外国网络,以及在外国代理的情况下,如何使用代理。移动节点需要使用代理通告来检测它们何时移动,使用标准中定义的两个算法之一。移动节点还需要检测在旅行后何时返回到本地网络。最后,如果它们在一段时间后没有收到代理通告,它们还需要能够发送代理请求消息。然而,它们被限制只在不经常发送这些消息,以保持流量可管理。

现在我们来看看这两种消息类型的格式。

代理请求消息格式

代理请求消息很简单。实际上,根本为这个消息定义了新的消息格式;它与路由器请求消息的格式完全相同(见第三十三章)。

在这里不需要新的消息类型的原因是,请求消息非常简单:“嘿,如果这里有任何路由器,请告诉我你是谁以及你能做什么。”不需要发送额外的移动 IP 信息。当一个常规 IP 路由器接收到路由器请求时,它会发送路由器通告,但当一个移动 IP 路由器在收到任何请求(无论来自移动 IP 节点还是常规 IP 设备)时,它会自动发送更长的代理通告。

代理通告消息格式

代理通告以 ICMP 路由器通告消息的正常字段开始(见第三十三章)。如果本地网络支持多播,则消息的目标是“所有设备”多播地址(224.0.0.1),否则是广播地址(255.255.255.255)。路由器地址字段用代理的地址(们)填充。

注意

一个设备可能希望宣传其处理移动 IP 消息的能力,但又不希望作为常规路由器。在这种情况下,它将路由器通告消息头中的正常代码字段从 0 更改为 16

在常规字段之后,添加了一个或多个扩展:

移动代理广告扩展 这是主要用于向本地网络上的移动节点传达代理的移动 IP 功能的主要扩展。该字段在表表 30-1 和表 30-2 中描述,并在图 30-4 中说明。

前缀长度扩展 这是一个可选扩展,它告诉移动节点包含在代理广告消息常规部分中的路由器地址的前缀长度(s);即消息常规路由器广告部分的路由器地址字段。前缀长度是地址中网络 ID 位数的另一个术语,因此它指定了路由器地址中的网络 ID。该字段在表 30-3 中描述,并在图 30-5 中说明。

单字节填充扩展 一些实现要求 ICMP 消息的字节数为偶数,因此需要一个填充字节。该字段仅包含一个全零字节。

提示

关键概念 移动 IP 代理发现 是移动节点确定其位置并与本地或外地代理建立联系的过程。为了表明其能力,可以作为代理的路由器会定期发送代理广告消息,这些消息是常规路由器广告的修改版本。为了请求发送广告,移动节点也可以发送代理请求,它与常规路由器请求相同。

我应该指出,移动 IP 不包含对代理广告代理请求消息进行认证的任何规定。如果已实现,它们可以使用 IPsec 进行认证。

移动 IP 移动代理广告扩展格式 此扩展出现在路由器广告消息的正常字段之后,如图所示。

图 30-4. 移动 IP 移动代理广告扩展格式 此扩展出现在路由器广告消息的正常字段之后,如图第三十三章中所示。

表 30-1. 移动 IP 移动代理广告扩展格式

字段名称 大小(字节) 描述
类型 1 识别代理广告扩展类型。对于移动性代理广告扩展,它设置为 16。
长度 1 扩展的长度(字节),不包括类型和长度字段。因此,它等于 6 加上消息中每个代管地址的 4 个字节。
序列号 2 当路由器初始化时,设置一个顺序计数器为零,然后为发送出的每个广告递增。
注册生存时间 2 代理愿意接受注册请求的最大时间长度,以秒为单位。65,535(全为 1)表示无限。请注意,此字段仅用于注册,与消息常规路由器广告部分的常规生存时间字段无关。
标志 1 一个包含多个信息标志的字节字段,这些标志传达有关代理能力和状态的具体信息。有七个单比特标志,当设置时,传达表 30-2 中所示的含义。
保留 1 作为零发送并由接收者忽略。
代管地址 可变(每个地址 4 个) 由外国代理提供的零个或多个地址,供移动节点作为外国代理代管地址使用。外国代理必须在它的广告中提供至少一个地址。不能作为外国代理的路由器通常会省略此字段。

表 30-2. 移动 IP 移动代理广告扩展标志

子字段名称 大小(字节) 描述
R 1/8(1 位) 注册要求:即使使用本地代管地址,移动节点也必须通过外国代理进行注册。
B 1/8(1 位) 忙碌:代理目前太忙,无法接受来自移动节点的进一步注册。
H 1/8(1 位) 家庭代理:代理愿意在此链路上作为家庭代理运行(它将转发数据报等)。请注意,设备可以作为家庭代理和外国代理同时提供服务。
F 1/8(1 位) 外国代理:代理愿意作为外国代理运行。同样,设备可以同时作为家庭代理和外国代理。
M 1/8(1 位) 最小封装:代理可以使用最小封装接收隧道数据报。
G 1/8(1 位) GRE 封装:代理可以使用 GRE 封装接收隧道数据报。
r 1/8(1 位) 保留:未使用;发送为零。
T 1/8(1 位) 反向隧道:代理支持反向隧道。

表 30-3. 移动 IP 前缀长度扩展格式

字段名称 大小(字节) 描述
类型 1 识别代理通告扩展类型。对于前缀长度扩展,它设置为 19。
长度 1 扩展的长度(以字节为单位),不包括类型和长度字段。因此,它等于前缀长度的数量(因为每个长度占用 1 个字节)。
前缀长度 可变(每个长度 1 个) 每个路由器地址在代理通告的常规路由通告部分中对应一个前缀长度数字。

移动 IP 前缀长度扩展格式 此扩展出现在路由通告消息的正常字段之后,如图所示。

图 30-5. 移动 IP 前缀长度扩展格式 此扩展出现在路由通告消息的正常字段之后,如图第三十三章所示。

在本章后面的移动 IP 封装部分中,请参阅有关最小和通用路由封装(GRE)封装以及反向隧道详情。

移动 IP 家园代理注册和注册消息

一旦移动节点完成了代理发现,它就知道自己是在家园网络还是外网。如果它在家园网络,它就像一个常规 IP 设备一样进行通信,但如果它在外网,它必须激活移动 IP。这需要它与家园代理通信,以便两者之间可以交换信息和指令。这个过程称为 家园代理注册,或者更简单地说,就是 注册

注册的主要目的是实际上启动移动 IP 工作。移动节点必须联系家园代理,并告知它已进入外网,并请求开启数据报文转发。它还必须让家园代理知道其处理地址,以便家园代理知道将转发数据报文发送到何处。在执行注册时,家园代理需要将各种类型的信息反馈给移动节点。请注意,外网代理实际上并不参与注册,除非可能用于中继消息。

移动节点注册事件

成功的注册在标准中建立了一个称为 移动绑定 的家园代理和移动节点之间的绑定。在注册期间,移动节点的常规家园地址与其当前的处理地址绑定,家园代理将封装并转发指向家园地址的数据报文到处理地址。移动节点应通过以下操作来管理其注册和处理各种事件:

注册 当移动节点首次检测到它已从家园网络移动到外网时,它将启动一个 注册

注销 当移动节点返回家园时,它应该通知家园代理取消转发——这个过程称为 注销

重新注册 如果移动节点从一个外国网络移动到另一个网络,或者其 care-of 地址发生变化,它必须更新其与本地代理的注册。即使它停留在外国网络上的一个位置,如果当前的注册即将到期,它也必须这样做。

每个注册仅针对特定的时间长度,这就是为什么无论设备是否移动,都需要定期重新注册。注册的时间限制确保它们不会过时。例如,如果一个节点忘记在返回时注销,当注册到期时,数据报转发最终会停止。

注册请求和注册回复消息

为了执行注册,在移动 IP 中定义了两种新的消息类型:注册请求注册回复。每个都按照其名称所暗示的执行操作。有趣的是,这些不是像代理发现中使用的 ICMP 消息,而是用户数据报协议(UDP)消息。因此,从技术上讲,注册是在比移动 IP 通信的其他部分更高的层次上执行的。代理在众所周知的 UDP 端口 434 上监听注册请求,并使用节点发送消息时使用的任何临时端口回应移动节点。

注册过程

根据移动节点使用的 care-of 地址类型以及其他我将简要说明的特定情况,定义了两种不同的注册程序。第一种是直接注册方法,它只有两个步骤:

  1. 移动节点向本地代理发送注册请求。

  2. 本地代理将注册回复发送回移动节点。

然而,在某些情况下,需要稍微复杂一些的过程,其中外国代理在本地代理和移动节点之间传递消息。在这种情况下,该过程有四个步骤:

  1. 移动节点向外国代理发送注册请求。

  2. 外国代理处理注册请求并将其转发给本地代理。

  3. 本地代理向外国代理发送注册回复。

  4. 外国代理处理注册回复并将其发送回移动节点。

当一个移动节点使用本地地址时,通常使用第一种、更简单的方法。在这种情况下,节点可以轻松地直接与本地代理通信,并且移动节点也被设置为直接接收来自本地代理的信息和数据报。当没有外国代理时,这显然是唯一可用的方法。当移动节点返回本地网络后注销其本地代理时,这也是显然的唯一方法。

当移动节点使用外国代理的 care-of 地址时,需要第二种方法。你会记得在这种情况下,移动节点根本没有任何唯一的 IP 地址;它正在使用外国代理给它的共享地址,这阻止了节点与本地代理之间的直接通信。此外,如果移动节点收到设置了 R 标志的代理广告,即使它有一个协同定位的 care-of 地址,它也应该通过外国代理进行。

注意,外国代理实际上只是一个中间人;交换仍然是在本地代理和移动节点之间进行的。然而,如果请求违反了外国网络使用的规则,外国代理可以拒绝注册。这就是为什么一些外国代理可能要求即使移动节点有一个协同定位的 care-of 地址,它们也必须是注册的渠道。当然,如果外国代理无法联系到本地代理,注册将无法进行。

提示

关键概念 移动 IP 的本地代理注册是指创建一个在本地代理和移动节点之间的移动绑定的过程,以便执行数据报文的转发。发送注册请求消息的移动节点执行注册,本地代理返回注册回复。外国代理可能需要充当中间人以便促进交易,但除此之外并不参与。

之前的描述实际上是对注册基本原理的高度简化解释。移动 IP 标准详细说明了代理和节点如何执行注册的许多细节,包括请求和回复发送的具体时间、如何处理各种特殊条件(如无效请求)、本地代理维护移动绑定表的规则以及更多内容。该标准涵盖了支持认证的常规注册消息的扩展定义,认证对于安全通信是必需的(有关安全问题的更多详细信息,请参阅本章后面的相关部分)。它还包括在需要时,移动节点可以维护多个并发绑定的能力。

注册请求消息格式

注册请求消息的格式如表格表 30-4 和表 30-5 所示,并在图 30-6 消息的有效负载中,其头部未显示")中说明。关于移动 IP 封装的详细信息,请参阅本章后面的相关部分。

表 30-4. 移动 IP 注册请求消息格式

字段名称 大小(字节) 描述
Type 1 识别注册消息类型。对于请求,此字段为 1。
Flags 1 包含多个信息标志的一个字节字段,这些标志传达了移动节点向家庭代理提出的特定请求。当设置时,标志传达的含义如表 30-5 所示。
Lifetime 2 移动节点从家庭代理请求此注册的时间长度,单位为秒。
Home Address 4 移动节点在其本地网络上的家庭(正常)IP 地址。无论请求如何传达给家庭代理,都能唯一标识设备。
Home Agent 4 作为移动节点家庭代理的设备 IP 地址。
Care-Of Address 4 移动节点正在使用的作为其协同地址的 IP 地址。
Identification 8 一个 64 位数字,唯一标识注册请求,并用于将请求与回复匹配。它还提供了防止重放攻击的保护;有关更多信息,请参阅本章后面的移动 IP 安全问题部分。
Extensions 可变 包括扩展字段以对请求进行身份验证。还可以包括其他扩展。

表 30-5. 注册请求标志

子字段名称 大小(字节) 描述
S 1/8 (1 bit) 同时绑定:移动节点请求保留先前的移动绑定,除了当前请求中的一个。
B 1/8 (1 bit) 广播数据报:移动节点请求将家庭网络上的广播转发给它。
D 1/8 (1 bit) 移动节点解封装:移动节点告诉家庭代理它将自行解封装封装的数据报,而不是使用外地代理。换句话说,当此字段为 1 时,移动节点正在使用本地协同地址;当为 0 时,它正在使用外地代理的协同地址。
M 1/8 (1 bit) 最小封装:移动节点请求家庭代理使用最小封装转发数据报。
G 1/8 (1 bit) GRE 封装:移动节点请求家庭代理使用 GRE 封装转发数据报。
r 1/8 (1 bit) 保留:未使用;发送为零。
T 1/8 (1 bit) 反向隧道:移动节点请求家庭代理使用反向隧道。
x 1/8 (1 bit) 保留:未使用;发送为零。

移动 IP 注册请求消息格式 此消息承载在用户数据报协议(UDP)消息的有效负载中,其头部未显示。

图 30-6. 移动 IP 注册请求消息格式 此消息包含在用户数据报协议(UDP)消息的有效负载中,其头部未显示。

注册回复消息格式

注册回复消息的格式如表 30-6 所示,并在图 30-7 中说明。

表 30-6. 移动 IP 注册回复消息格式

字段名称 大小(字节) 描述
类型 1 识别注册消息类型。对于回复,此字段为 3。
代码 1 表示注册请求的结果。如果注册被接受,则此字段设置为 0;如果注册被接受但请求了同时绑定且不支持,则设置为 1。如果注册被拒绝,将提供不同的原因代码,以指示拒绝的原因,以及是家庭代理还是外国代理拒绝的。
寿命 2 如果注册被接受,这表示注册到期前的秒数。这可能与移动节点请求的值不同。
家庭地址 4 当移动节点处于其家庭网络时,该移动节点的家庭(正常)IP 地址。无论请求如何传达给家庭代理,都能唯一标识设备,以便在同一个外国代理为多个移动节点提供服务时,可以将消息发送到它。
家庭代理 4 作为移动节点家庭代理的设备的 IP 地址。
识别 8 一个 64 位数字,唯一标识注册回复,并与触发它的请求的识别字段相匹配。
扩展 可变 包含在此处的扩展字段用于回复的认证。也可能包含其他扩展。

移动 IP 注册回复消息格式 此消息包含在 UDP 消息的有效负载中,其头部未显示

图 30-7. 移动 IP 注册回复消息格式 此消息包含在 UDP 消息的有效负载中,其头部未显示。

移动 IP 数据封装和隧道

一旦外国网络上的移动节点与其家庭代理完成成功的注册,本章前面描述的移动 IP 数据报转发过程将被完全“激活”。家庭代理将拦截路由到其家庭网络的移动节点意图的数据报,并将它们转发到移动节点。通过封装数据报,然后发送到节点的 care-of 地址来实现这一点。

封装是必需的,因为您拦截并转发的每个数据报文都需要通过网络重新发送到设备的 care-of 地址。理论上,设计者可能通过仅仅让归属代理更改目标地址并将其重新发送到网络上来实现这一点,但存在各种复杂因素使得这种方法不切实际。在重新传输之前将整个数据报文包裹在一组新的头中更为合理。在我的邮件转发类比中,这相当于将收到的旅行顾问的信件放入一个新的信封中以便转发,而不是仅仅划掉原始地址并写上新地址。

在移动 IP 中使用的默认封装过程称为IP 内部封装,正如它在 RFC 2003 中定义的那样。它通常简称为IP-in-IP。这是一个相对简单的方法,描述了如何将 IP 数据报文作为另一个 IP 数据报文的负载。在移动 IP 中,新的头指定如何将封装数据报文发送到移动节点的 care-of 地址。

除了 IP-in-IP 之外,还可以选择使用以下两种封装方法:IP 内部最小封装,它在 RFC 2004 中定义,以及通用路由封装(GRE),它在 RFC 1701 中定义。要使用这些方法之一,移动节点必须在它的注册请求中请求适当的方法,并且归属代理必须同意使用它。如果使用外地代理 care-of 地址,外地代理也必须支持所需的方法。

移动 IP 传统隧道

封装过程在封装设备和解封装设备之间创建了一个名为tunnel的逻辑结构。这与在虚拟专用网络(VPNs)、IPsec 隧道模式或用于安全性的各种其他隧道协议讨论中使用的隧道概念相同。隧道代表了一个数据报文可以在任意互联网上转发的中继,封装数据报文的细节(即原始 IP 头)暂时被隐藏。

在移动 IP 中,隧道的起始点是归属代理,它负责封装。隧道的终点取决于使用的是两种类型的 care-of 地址中的哪一种:

外地代理 care-of 地址 外地代理是隧道的终点。它从归属代理接收封装的消息,移除外部 IP 头,然后将数据报文递送到移动节点。这通常使用第二层来完成,因为移动节点和外地代理位于同一本地网络中,并且移动节点在该网络上没有自己的 IP 地址,因为它正在使用外地代理的地址。

本地化 care-of 地址 移动节点本身是隧道的终点,并移除外部头。

通常,之前描述的隧道仅用于已发送到移动节点并被本地代理捕获的数据报。当移动节点想要发送数据报时,它不会将其隧道化回本地代理;这将是不必要的低效。相反,它只需直接使用当前网络中可以找到的任何路由器发送数据报,这可能或可能不是外部代理。当它这样做时,它使用自己的本地地址作为发送请求的源地址。因此,对这些请求的任何响应都将返回到本地网络。这为这些类型的交易设置了一个由三个传输组成的三角形(如图图 30-8 所示):

  1. 移动节点从外部网络向互联网上某个第三方设备发送请求。

  2. 第三方设备向移动节点回复。然而,这会将回复发送回移动节点在其本地网络上的本地地址。

  3. 本地代理在本地网络中拦截响应并将其隧道化回移动节点。

移动 IP 封装和隧道化 此示例说明了在移动 IP 中典型的请求/回复消息交换如何导致通信的三角形。在第 1 步中,移动节点向互联网上的某个远程服务器发送请求。它使用自己的本地地址作为请求的源地址,因此在第 2 步中,回复返回到本地代理。第 3 步包括本地代理将回复隧道化回移动节点。

图 30-8. 移动 IP 封装和隧道化 此示例说明了在移动 IP 中典型的请求/回复消息交换如何导致通信的三角形。在第 1 步中,移动节点向互联网上的某个远程服务器发送请求。它使用自己的本地地址作为请求的源地址,因此在第 2 步中,回复返回到本地代理。第 3 步包括本地代理将回复隧道化回移动节点。

反向交易基本上是相同的,只是顺序相反。在这种情况下,第三方(互联网)设备会向移动节点发送请求,该请求会被本地代理接收并转发。移动节点会直接向互联网主机回复。

提示

关键概念 一旦移动 IP 设置并运行,它通过本地代理封装隧道接收到的数据报到移动节点来工作。移动设备通常直接将数据报发送到互联网主机,这些主机响应移动的本地代理,该代理将数据报转发到移动节点。这意味着请求/回复通信需要三次传输。

移动 IP 反向隧道

可能存在某些情况下,使用外国网络上的路由器直接将数据报发送到互联网是不可行或不受欢迎的,正如你刚才看到的。在这种情况下,如果移动节点、本地代理(如果相关的话,还有外国代理)支持,可以部署一个可选功能,称为反向隧道。当这样做时,根据 care-of 地址类型,在移动节点和本地代理之间,或者在外国代理和本地代理之间设置一个补充正常隧道的反向隧道。所有来自移动节点的传输都会通过隧道返回到本地网络,本地代理在那里通过互联网传输它们,从而实现比刚才描述的三角形更对称的操作。这基本上就是我之前描述的效率低下的原因,因为它意味着每次通信需要四个步骤。因此,它仅在必要时使用。

需要反向隧道的一种情况是,如果移动节点所在的网络实施了某些安全措施,禁止节点使用其正常的 IP 地址发送数据报。特别是,网络可能被设置为不允许带有与其网络前缀不匹配的源地址的出站数据报。这通常是为了防止欺骗(冒充他人的 IP 地址)。

小贴士

关键概念 在某些情况下,可以使用一个称为反向隧道的可选功能,例如当网络不允许带有外国源 IP 地址的出站数据报时。启用后,而不是直接发送数据报,移动节点将所有传输通过隧道返回到本地代理,该代理将它们发送到互联网。

注意,我刚才讨论的一切都适用于正常——即单播——数据报,这些数据报是发送到和从移动节点发送的。在本地网络上的广播数据报,如果移动节点在本地,通常会被发送到移动节点,除非节点在注册期间明确请求此服务,否则不会转发。在外国网络上的多播操作也得到支持,但移动节点需要做额外的工作来设置它。

移动 IP 和 TCP/IP 地址解析协议(ARP)操作

移动 IP 是一种协议,它很好地实现了困难的函数:它透明地允许 IP 设备移动到不同的网络。不幸的是,任何试图改变 IP 工作方式的协议都会遇到特殊情况的难题。家庭代理拦截数据报并将其隧道传输到移动节点在一般意义上是有效的,但有些情况下需要额外的工作。其中之一是使用 ARP,除非我们采取特殊措施,否则它会在移动 IP 下失效。

小贴士

背景信息 在本主题中假定对 ARP 在一般意义上的工作原理有所了解。这包括 ARP 代理,这在第十三章中有描述。

要了解 ARP 的问题是什么,考虑一个位于外国网络并已成功注册到其家庭代理的移动节点。家庭代理将拦截进入家庭网络的所有数据报,特别是那些旨在发送给移动节点的数据报,然后封装并转发它们。然而,为了实现这一点,家庭代理(家庭路由器)必须看到数据报。这通常只在数据报从外部进入家庭网络并由路由器处理时才会发生。

当家庭网络上的本地设备本身想要向已经旅行到其他地方的移动节点传输数据时会发生什么?记住,这个设备本身可能不是移动的,并且可能对移动 IP 一无所知。它将遵循标准流程来决定如何处理它需要发送的数据报,正如第二十三章中解释的那样。它将比较其网络 ID 与移动节点的网络 ID,并意识到它不需要路由其数据报;它可以直接将其发送到移动节点。

本地主机将尝试使用 ARP 来查找移动节点的数据链路层地址,以便它能直接向其发送数据报。主机将首先检查其 ARP 缓存,如果在那里找到节点的数据链路层地址,它将使用它来在第二层发送。移动节点不再位于本地网络段上,因此消息将不会被接收。如果没有 ARP 缓存条目,家庭网络上的主机将尝试向移动节点发送 ARP 请求以确定其第二层地址。同样,移动节点已经离开,所以这个请求将无人响应。

解决这个问题需要,正如你所猜到的,家庭代理的介入。它必须执行两个任务才能使本地主机能够向移动节点发送数据:

ARP 代理 家庭代理必须监听任何由当前注册到它的任何移动节点所在同一网络上的节点发送的 ARP 请求。当它听到一个请求时,它会代表移动节点进行回复,并指定自己的数据链路层地址作为移动节点 IP 地址的绑定。这将导致家庭网络上的主机将任何打算发送给移动节点的数据报发送到家庭代理,在那里它们可以被转发。这个过程在图 30-9 中进行了说明。

无用的 ARP 代理有助于处理 ARP 请求,但对于已经为移动节点缓存了条目的设备怎么办?一旦移动节点离开网络,这些条目就会自动过时。为了纠正它们,家庭代理发送所谓的“无用的”ARP 消息,告诉本地网络上的设备将移动节点的 IP 地址与家庭代理的数据链路层地址关联起来。术语“无用的”指的是设备不是发送消息以执行实际的地址解析,而是仅仅为了更新缓存。它可能发送多次,以确保每个设备都能收到消息。

移动 IP 家庭代理的 ARP 代理 家庭代理必须采取特殊措施来处理来自本地网络设备的传输。在这个例子中(为了简单起见,使用简短的硬件地址),移动节点的硬件地址是 48,家庭代理是 63。家庭网络上的一个本地客户端,其硬件地址为 97,发送一个 ARP 请求以找出移动节点的硬件地址。家庭代理代表移动节点进行回复,指定不是硬件地址 48,而是自己的地址:63。因此,客户端会发送到家庭代理,然后家庭代理可以将数据转发到外国网络上的移动节点。

图 30-9. 移动 IP 本地代理的 ARP 代理。本地代理必须采取特殊步骤来处理来自本地网络设备的传输。在这个例子中(为了简单起见,使用简短的硬件地址),移动节点的硬件地址是 48,本地代理是 63。本地网络上的一个客户端硬件地址为 97,发送一个 ARP 请求以找出移动节点的硬件地址。本地代理代表移动节点响应,指定不是硬件地址 48,而是它自己的地址:63。因此,客户端将数据发送到本地代理,然后本地代理可以将数据转发到外国网络上的移动节点。

小贴士

关键概念 在理论上,移动节点本地网络上的主机可能会遇到问题,它们试图在第二层向主机发送数据报。为了解决这些问题,需要本地代理使用代理 ARP 来指导这些设备向本地代理发送,以便它们可以被转发。它还必须使用 无用的 ARP 来更新任何现有的 ARP 缓存以实现这一点。

一旦完成这些步骤,ARP 应该在本地链路上正常工作。当移动设备返回本地网络时,必须反转这个过程。在向本地代理注销后,移动设备将停止为移动节点代理。移动节点和本地代理还将发送无用的 ARP 广播,以更新本地设备缓存。这将再次将移动节点的 IP 地址与其自己的第 2 层地址关联起来,而不是本地代理的第 2 层地址。

移动 IP 效率问题

让本地代理将所有数据报转发到移动节点,无论它在何处,这是一个方便的移动解决方案,但也是一个相当低效的解决方案。由于设备必须首先将每个数据报发送到本地网络,然后再转发到移动节点,因此数据报将不得不在互联网的某个部分上往返两次。转发所表示的不效率程度可能非常显著,并可能导致某些应用程序出现问题。

要了解问题所在,让我们考虑一个移动的节点 M 和一个想要向其发送数据的常规设备,设备 A。移动 IP 的不效率程度是设备 A 与节点 M 的本地网络之间的互联网距离与设备 A 与节点 M 的当前网络之间的互联网距离的函数。这里的“距离”是指用于确定互联网上路由的术语。当两个设备之间通信所需的时间和跳数更少时,它们更接近;当需要更多的跳数时,它们更远。(在以下示例中,我使用地理距离来表示这个概念,但请记住,地理距离只是互联网距离的一个因素。)

让我们考虑移动节点 M 在外国网络上,且距离家乡相当远的情况,设备 A 想使用节点 M 的本地 IP 地址发送数据报。假设本地网络在伦敦,设备再次在东京。让我们看看移动 IP 与移动节点在外国网络上仅获取新的临时 IP 地址而不使用移动 IP 的替代方案的效率比较。以下示例按效率递增的顺序排列:

在本地网络上的发送设备 在这种情况下,设备 A 将发送一个数据报,该数据报立即被本地网络上的本地代理截获并转发到移动节点。实际上这里根本不存在任何低效(除了封装等开销),因为即使设备 A 直接将数据报发送到移动节点并使用新的外国地址,数据报可能仍然会通过本地代理路由器。

接近本地网络的网络上的发送设备 假设巴黎的设备想向移动节点发送数据。数据报从巴黎到伦敦,然后到东京。这还不是太糟糕。

接近外国网络的网络上的发送设备 现在假设发送设备位于台湾台北。在这种情况下,移动 IP 变得非常低效。数据报必须从台北发送到伦敦,然后再发送回东京。

在外国网络上的发送设备 当发送设备实际上位于移动节点访问的外国网络时,效率最低。如果设备 A 位于东京的移动节点当前网络,它必须一直发送到伦敦,然后将结果再次转发回东京。如果没有移动 IP,你只需要使用 ARP,然后在第二层直接交付,而不需要任何路由!这种情况在图 30-10 中进行了说明。

不幸的是,发送设备在外国网络上的最坏情况是经常发生的情况。移动设备通常连接到外国网络,以便与该网络上的主机进行特定通信。

移动 IP 效率最坏情况示意图 此图显示了移动 IP 效率最坏的情况。当位于移动设备所在外国网络上的设备试图向移动设备发送数据时。这里的发送者,210.4.79.11,使用移动节点的本地地址,因此传输必须一路路由回伦敦,然后再转发回东京,尽管这两个设备可能就坐在同一张桌子上!

图 30-10. 移动 IP 效率最坏情况示意图 此图显示了移动 IP 效率最坏的情况。当位于移动设备所在外国网络上的设备试图向移动设备发送数据时。这里的发送者,210.4.79.11,使用移动节点的本地地址,因此传输必须一路路由回伦敦,然后再转发回东京,尽管这两个设备可能就坐在同一张桌子上!

更糟糕的是,考虑一下如果使用反向隧道会发生什么!在这里,隧道不仅用于发送到移动节点的数据报,也用于从设备发送的数据报。在最坏的情况示例中,从移动节点到外国网络上另一设备的请求/回复对需要从东京到伦敦并返回的两个完整往返。显然,这远非理想。

小贴士

关键概念 由于数据报是发送到移动 IP 的本地地址,因此发送到移动设备的每个数据报必须首先返回其本地网络,然后转发到其当前位置。由此产生的效率低下程度取决于发送者与移动设备本地网络的距离。最坏的情况实际上发生在发送者和移动设备位于同一外国网络时,在这种情况下,每次传输都必须往返于移动设备的本地网络。

在移动 IP 内部实际上并没有解决这个问题;这只是协议工作方式的自然结果。真正改善事情的唯一方法是通过“黑客”方式引入一个解决方案,这个解决方案最终归结为我们在 IP 无移动支持时始终拥有的两种选择之一:要么在外国网络上给移动设备分配一个临时的真实 IP 地址,要么在移动设备位于外国网络时使用针对主机的特定路由。

你已经看到,这些方法都有问题,这也是移动 IP 最初被创建的原因。然而,可能存在效率比移动 IP 提供的透明可移植性更重要的情况。对于在远离本地网络的国外网络上长期部署,或者对于效率至关重要的应用,采用这些技术之一可能是合理的。例如,一个在多个城市有少量办公室且通过互联网连接的公司可能会设置特殊的路由。这将允许来自其他城市的移动设备直接与网络的外部部分的本地区域节点通信,而无需通过互联网进行路由。

移动 IP 安全注意事项

在当今的任何互联网环境中,安全性始终是一个关注点,但在使用移动 IP 时尤其重要。这有几个原因。这些原因既与协议的使用方式有关,也与实现该协议的具体机制有关。

在使用方面,由于移动设备通常使用无线网络技术,因此在移动 IP 的开发过程中始终考虑到了安全性。无线通信本质上比有线通信不安全,因为传输是在公开环境中进行的,可以被截获。恶意用户也更容易干扰无线设备的操作。

在操作方面,由于移动 IP 使用注册系统并在一个未加密的互联网上转发数据报,因此存在许多风险。恶意设备可能会干扰注册过程,从而使得原本打算发送给移动设备的数据报被重定向。一个恶意用户也可能通过封装一个虚假的数据报来干扰数据转发过程,诱使移动节点认为它收到了它从未收到的东西。

由于这些原因,移动 IP 标准包括了一些明确的条款,以防范各种安全风险。有一项安全措施被认为非常重要,因此它被直接集成到移动 IP 标准中:注册请求和注册回复消息的认证。这个过程以一种与 IPsec 认证头(AH)操作类似的方式进行,如第二十九章所述。其目标是防止未经授权的设备通过诱使代理不正确地设置、续订或取消注册来拦截流量。

所有移动 IP 设备都必须支持身份验证。节点必须用它来请求,代理必须用它来回复。由于没有自动化的安全密钥分发系统,密钥必须手动分配。默认的身份验证方法使用HMAC-MD5(在 RFC 2403 中指定),这是 IPsec 使用的两种哈希算法之一。

另一个关注点是称为重放攻击的安全问题。在这种攻击中,第三方截获一个数据报,保留它,然后稍后重新发送。这似乎相当无害,但考虑一下时间的重要性。想象一个注册了其家乡代理的移动节点,然后后来返回家中并注销。如果一个恶意设备捕获了原始注册请求的副本并重新发送,家乡代理可能会被欺骗,认为节点已经离开了家,而实际上并没有。它随后可能会截获转发的数据报。

在注册请求和注册回复消息中使用的标识字段是为了防止重放攻击设计的。由于每个请求都有一个不同的标识号,节点和代理可以匹配请求和回复,并拒绝他们收到的任何重复的已经见过的数据报。移动 IP 标准还指定了防止重放攻击的替代方法。

虽然移动 IP 包括对注册消息的认证措施,但它不对其他类型的消息进行认证。它也没有指定从家乡代理转发到移动节点的封装数据报的认证。加密也没有提供以保护控制消息或转发数据报的隐私。当需要更强的隐私或真实性保证时,明显的解决方案是使用 IPsec AH 和/或封装安全载荷(ESP)协议(在第二十九章第二十九章。IP 安全性(IPSEC)协议中描述)。

第二部分-6. IP 支持协议

第三十一章

第三十二章

第三十三章

第三十四章

第三十五章

第三十六章 协议")

互联网协议 (IP) 是实现 TCP/IP 协议套件的关键网络层协议。由于 IP 是提供在设备之间传递数据报机制的协议,因此它被设计得相对简单。例如,它缺乏允许错误报告回发送设备以及完成测试和特殊任务的方法。然而,这些辅助功能对于互联网的操作是必要的,因此 TCP/IP 包括 支持协议 来帮助 IP 执行这些任务。本部分探讨了两个主要的 IP 支持协议:互联网控制消息协议 (ICMP)邻居发现 (ND) 协议。

本部分的大部分内容详细描述了 ICMP,它最初是为了作为原始 IP 版本 4 (IPv4) 的配套而开发的。随着 IP 版本 6 (IPv6) 的创建,一个新的 ICMP 版本也被创建,称为 ICMP 版本 6 (ICMPv6)。原始的 ICMP 现在有时被称为 ICMPv4 以区分它,就像原始的 IP 现在通常被称为 IPv4 一样。

ICMP 的两个版本在具体方面有一些差异,但它们在总体操作上非常相似。因此,我将本部分的两个版本的 ICMP 的一般操作描述整合到了第一章。ICMPv4 和 ICMPv6 最不同的地方在于特定的消息类型和格式,因此这些内容在第二到第五章中分别进行了描述。这些章节描述了每个版本中的错误消息和信息消息。

最后一章描述了 ND,它专门创建来协助 IPv6 的操作,并且与 ICMPv6 密切相关。

由于 ICMP 与 IP 之间的紧密关系,本部分假设您熟悉基本的 IP 概念,包括 IP 地址、IP 数据报的一般格式以及它们的路由方式(在第 II-3 部分[pt06.html "第 II-3 部分. 互联网协议版本 4 (IP/IPV4)"]中介绍)。为了更好地理解 ICMPv6 的细节,您可能还需要参考 IPv6 地址和数据报封装信息(在第 II-4 部分[pt07.html "第 II-4 部分. 互联网协议版本 6 (IPV6)"]中介绍)。

第三十一章. ICMP 概念和一般操作

无标题图片

互联网控制消息协议(ICMP)是网络世界中未被充分重视的“工蜂”之一。每个人都清楚关键协议如互联网协议(IP)对 TCP/IP 的重要性,但很少有人意识到整个套件依赖于 ICMP 提供的许多功能。最初创建是为了允许报告一小组错误条件,ICMP 消息现在被用来实现广泛的错误报告、反馈和测试功能。虽然每种消息类型都是独特的,但它们都是使用通用消息格式实现的,然后根据相对简单的协议规则发送和接收。这使得 ICMP 成为最容易理解的 TCP/IP 协议之一。(是的,我在这本书中确实说过一些事情是容易的!)

在本章中,我提供了 ICMP 的一般描述。我首先概述 ICMP,讨论其目的、历史以及定义它的版本和标准。我描述了 ICMP 的一般操作方法,并讨论了如何以及何时创建和处理的规则。然后,我概述了协议第 4 版和第 6 版(ICMPv4 和 ICMPv6)中使用的 ICMP 消息的常见格式,以及它们在一般术语中如何封装数据。最后,我讨论了 ICMP 消息的分类,并总结了 ICMPv4 和 ICMPv6 的不同消息类型和代码。

ICMP 概述、历史、版本和标准

IP 是 TCP/IP 协议套件的基础,因为它负责交付数据报的机制。描述 IP 数据报交付方法的三个主要特征是无连接的不可靠的无确认的。这意味着数据报只是在互联网上发送,没有建立先前的连接,没有保证它们会出现,也没有向发送者发送确认它们已到达的确认。表面上,这似乎会导致一个难以使用且无法依赖的协议,因此不适合设计协议套件。然而,尽管 IP 没有保证,它仍然工作得非常好,因为大多数时候,IP 互联网足够健壮,消息能够到达它们需要去的地方。

即使是最精心设计的系统仍然会遇到问题,这是当然的。偶尔会发送错误的包,硬件设备出现问题,找到无效的路由,等等。IP 设备也需要共享特定信息以便引导它们的操作,并且它们需要执行测试和诊断。然而,IP 本身并没有提供允许设备交换低级控制消息的条款。相反,这些功能以 IP 的伴随协议的形式提供,称为互联网控制消息协议(ICMP)

IP 和 ICMP 之间关系的良好类比是考虑一个高功率执行者和她经验丰富的行政助理之间的关系。执行者很忙,她的时间是极其宝贵的。她被雇佣来做一项具体的工作,并且要做好这项工作,而不是花时间在行政工作上。然而,如果没有人在做这些工作,执行者就无法正确地完成她的工作。行政助理做重要的支持工作,使得执行者能够专注于她的工作。他们之间的工作关系非常重要;一个好的搭档会像一个团结的团队一样一起工作,甚至预见彼此的需求。

在 TCP/IP 中,IP 是执行者,而 ICMP 是其行政助理。IP 专注于其核心活动,如寻址、数据报封装和路由。ICMP 通过提供允许 IP 设备之间进行不同类型通信的ICMP 消息来为 IP 提供关键支持。这些消息使用一个通用的通用格式,并封装在 IP 数据报中进行传输。它们被分为不同的类别,每种类型都有特定的用途和内部字段格式。

正如行政助理在组织结构图上通常有一个特殊的位置,并且通常用虚线直接连接到她所协助的执行者一样,ICMP 在 TCP/IP 协议架构中占据一个独特的位置(见第八章)。技术上,你可能认为 ICMP 属于第 4 层,因为它创建的消息封装在 IP 数据报中,并使用第 3 层的 IP 发送。然而,在最初定义它的标准中,ICMP 被明确声明不仅属于网络层,而且,正如 RFC 792 中所述,它是“IP 的真正组成部分,[必须]由每个 IP 模块实现。”这是 ICMP 的初始定义标准,标题简单地称为“互联网控制消息协议”。它与 IP 的标准同时发布,即 RFC 791。这进一步表明 IP 和 ICMP 确实是一对搭档。

由于两者之间关系密切,当 1990 年代中期开发新的互联网协议第 6 版(IPv6)时,有必要定义一个新的 ICMP 版本。这当然被称为“互联网控制消息协议(ICMPv6)用于互联网协议第 6 版(IPv6)规范”。它最初于 1995 年作为 RFC 1885 发布,并在 1998 年作为 RFC 2463 进行了修订。正如原始 IP 现在通常称为 IPv4 以区分 IPv6 一样,原始的 ICMP 现在也称为ICMPv4

小贴士

关键概念 在 TCP/IP 中,互联网层中的诊断、测试和错误报告功能由互联网控制消息协议(ICMP)执行,它类似于 IP 的“行政助理”。原始版本,现在称为 ICMPv4,与 IPv4 一起使用,而较新的 ICMPv6 与 IPv6 一起使用。

这两个 RFC,792 和 2463,分别定义了 ICMPv4 和 ICMPv6 的基本操作,并描述了每种协议版本所支持的 ICMP 消息类型。ICMPv4 和 ICMPv6 在大多数方面非常相似,尽管它们有一些差异,这些差异大多是由于对 IP 本身的直接更改而产生的。另一份文档 RFC 1122,“互联网主机需求——通信层”,包含了关于如何使用 ICMPv4 的规则,正如你将在本章后面关于 ICMP 消息创建和处理惯例的部分中看到的。RFC 1812,“IP 版本 4 路由器需求”也是相关的。

该协议的两个版本都定义了一个通用消息系统,该系统被设计为可扩展的。这意味着除了在 ICMP 标准本身中定义的消息之外,其他协议也可以定义在 ICMP 中使用的消息类型。其中一些更重要的是在表 31-1 中展示的。

表 31-1. 定义 ICMP 消息的非 ICMP 互联网标准

ICMP 版本定义的消息类型 RFC 编号 名称 ICMP 消息类型定义
950 互联网标准子网划分过程 地址掩码请求,地址掩码回复
1256 ICMP 路由器发现消息 路由器通告,路由器请求
ICMPv4 1393 使用 IP 选项进行 Traceroute Traceroute
1812 IP 版本 4 路由器需求 定义了目的地不可达消息的三个新代码(子类型)。
ICMPv6 2461 IP 版本 6(IPv6)的邻居发现 路由器通告,路由器请求,邻居通告,邻居请求,重定向
2894 IPv6 路由器重新编号 路由器重新编号

本章包括本书中涵盖的 ICMPv4 和 ICMPv6 消息类型的完整列表以及定义每个消息类型的标准。

ICMP 通用操作

ICMP 是 TCP/IP 协议套中最简单的协议之一。大多数协议实现特定类型的功能,以促进网络栈的一部分或应用程序的基本操作。为此,它们包括许多特定的算法和任务,这些定义了协议,这也是大多数复杂性的来源。相比之下,ICMP 正是其名称所暗示的:一个定义控制消息的协议。因此,ICMP 的大部分内容都是提供一种机制,使任何 IP 设备都能向另一设备发送控制消息。

ICMP 消息传递服务

ICMP 定义了各种消息类型,允许交换不同类型的信息。这些通常是为了报告错误或交换保持 IP 平稳运行所需的不同类型的重要信息而生成的。ICMP 本身并不定义所有不同 ICMP 消息的使用方式;这是由使用这些消息的协议来完成的。以这种方式,ICMP 为其他协议描述了一个简单的消息传递服务。

小贴士

关键概念 ICMP 与其他大多数 TCP/IP 协议不同,它不执行特定任务。它定义了一种机制,通过该机制可以传输和接收各种控制消息以实现各种功能。

如前所述,尽管 ICMP 使用 IP 发送其消息,但它被认为是 IP 的一个组成部分。通常,ICMP 的操作涉及机器上 TCP/IP 协议软件的一部分检测到导致其生成 ICMP 消息的条件。这通常是 IP 层本身,尽管也可能是软件的另一个部分。然后,消息被封装并像任何其他 TCP/IP 消息一样传输,与其他 IP 数据报相比没有特殊处理。消息通过网络发送到接收设备的 IP 层,如图图 31-1 所示。

再次强调,由于许多 ICMP 消息实际上是为了向设备的 IP 软件传达信息,因此一旦接收方收到该消息,IP 层本身可能就是 ICMP 消息的最终目的地。在其他情况下,最终目的地可能是 TCP/IP 协议软件的另一个部分,这取决于接收到的消息类型。ICMP 不使用端口,如用户数据报协议(UDP)或传输控制协议(TCP)来将消息定向到主机上的不同应用程序。软件识别消息类型,并在软件内部相应地引导它。

ICMP 最初的设计理念是大多数消息将由路由器发送,但它们也可以由路由器和普通主机发送,具体取决于消息类型。有些显然只由路由器发送,例如重定向消息;而其他可能由路由器或主机发送。许多 ICMP 消息都是成对使用的,尤其是在各种请求和回复消息以及广告和请求消息中。

ICMP 通用操作 AICMP 的典型用途是在发送 IP 消息时提供反馈机制。在这个例子中,设备 A 试图向设备 B 发送一个 IP 数据报。然而,当它到达路由器 R3 时,检测到某种问题导致数据报被丢弃。路由器 R3 向设备 A 发送一个 ICMP 消息,告知它发生了某些事情,希望提供足够的信息让设备 A 纠正问题,如果可能的话。路由器 R3 只能将 ICMP 消息发送回设备 A,而不能发送给路由器 R2 或 R1。

图 31-1. ICMP 通用操作 AICMP 的典型用途是在发送 IP 消息时提供反馈机制。在这个例子中,设备 A 试图向设备 B 发送一个 IP 数据报。然而,当它到达路由器 R3 时,检测到某种问题导致数据报被丢弃。路由器 R3 向设备 A 发送一个 ICMP 消息,告知它发生了某些事情,希望提供足够的信息让设备 A 纠正问题,如果可能的话。路由器 R3 只能将 ICMP 消息发送回设备 A,而不能发送给路由器 R2 或 R1。

ICMP 错误报告限于数据报源

ICMP 操作的一个有趣的一般特征是,当检测到错误时,可以使用 ICMP 报告错误,但只能报告给数据报的原始源。这实际上是 ICMP 工作方式的一个重大缺点。请参阅图 31-1 并再次考虑客户端主机 A 向服务器主机 B 发送消息,由路由器 R3 检测到数据报中的问题。即使路由器 R3 怀疑问题是由处理消息的前一个路由器(如路由器 R2)引起的,它也不能向路由器 R2 发送问题报告。它只能将 ICMP 消息发送回主机 A。

这种限制是 IP 工作方式的产物。你可能还记得查看 IP 数据报格式时,唯一的地址字段是用于数据报的原始源地址和最终目的地址。(唯一的例外是如果使用了 IP 记录路由选项,但设备不能依赖这一点。)当路由器 R3 从路由器 R2 接收数据报,而路由器 R2 又从路由器 R1(以及在那之前,从设备 A)接收数据报时,数据报中只有设备 A 的地址。因此,路由器 R3必须将问题报告发送回设备 A,而设备 A 必须决定如何处理它。设备 A 可能决定更改它使用的路由,或者生成一个管理员可以用来调试路由器 R2 的错误报告。

除了这个基本限制之外,还制定了一些特殊的规则和惯例来规范 ICMP 消息生成、发送和处理的条件。我将在本章后面讨论这些内容。

小贴士

关键概念 在响应在 IP 数据报中看到的某个问题时发送的 ICMP 错误报告消息只能发送回原始设备。中间设备不能成为 ICMP 消息的接收者,因为它们的地址通常不在 IP 数据报的头部中携带。

ICMP 消息类别、类型和代码

ICMP 消息用于允许在互联网中的 IP 设备之间通信不同类型的信息。这些消息本身用于广泛的目的,并且它们被组织成一般类别以及许多特定类型和子类型。

ICMP 消息类别

在最高级别上,ICMP 消息分为两大类:

错误消息 这些消息用于向源设备提供有关已发生错误的反馈。它们通常专门针对某种操作生成,通常是数据报的传输,如图 31-1 所示。错误通常与数据报的结构或内容有关,或者与在数据报路由过程中在互联网中遇到的问题情况有关。

信息性(或查询)消息 这些是用于让设备交换信息、实现某些 IP 相关功能以及执行测试的消息。它们不指示错误,并且通常不会在常规数据报传输的响应中发送。它们是在应用程序的指示下生成或在常规基础上定期生成,以向其他设备提供信息。信息性 ICMP 消息也可能在响应另一个信息性 ICMP 消息时发送,因为它们通常出现在请求/响应或请求/公告功能对中。

小贴士

关键概念 ICMP 消息分为两大类:错误消息,用于报告问题条件,以及信息性消息,用于诊断、测试和其他目的。

ICMP 消息类型

ICMP 中的每种独立消息类型都分配了一个唯一的类型值,该值放入 ICMP 公共消息格式中同名字段。该字段宽度为 8 位,因此可以定义的理论最大消息类型数为 256。为 ICMPv4 和 ICMPv6 的每个版本维护一组单独的类型值。

在 ICMPv4 中,类型值是按照先来先服务的原则(某种程度上)连续分配给错误和信息性消息的,所以我们不能仅通过类型值来判断每种消息的类型。ICMPv6 中的一项微小改进是将消息类型分开。在 IPv6 中,错误消息的类型值为 0 到 127,信息性消息的类型值为 128 到 255。目前只定义了部分类型值。

小贴士

关键概念 对于 ICMPv4 和 ICMPv6,可以定义总共 256 种不同的可能消息类型。每个消息的头部中出现的类型字段指定了 ICMP 消息的类型。在 ICMPv4 中,类型值与消息类型之间没有关系。在 ICMPv6 中,错误消息的类型值为 0 到 127,信息性消息的类型值为 128 到 255。

ICMP 消息代码

消息类型指示每种 ICMP 消息的一般用途。ICMP 还在每个消息类型内部提供了一种额外的详细级别,形式为一个代码字段,该字段也是 8 位。您可以将此字段视为消息子类型。因此,每种消息类型可以有最多 256 个子类型,这些子类型是消息整体功能的更详细细分。一个很好的例子是目标不可达消息,当数据报无法投递时会产生此消息。在此消息类型中,代码值提供了关于为什么投递不可能的具体信息。

ICMP 消息类别和类型摘要

书的下一章描述了 ICMPv4 和 ICMPv6 的所有主要 ICMP 消息类型。为了方便,我已经将这些消息类型总结在表 31-2 中,该表显示了本书涵盖的每个消息的类型值、每个消息的名称、其目的的非常简短的摘要以及定义它的 RFC。为了使表格不至于过大,我没有显示每个类型值的每个代码值;这些可以在单独的消息类型描述中找到。该表按与描述 ICMP 消息类型的四个章节相对应的节组织,但此表在每个类别内按类型值升序排序,以便于参考。

表 31-2. ICMP 消息类别、类型和代码

消息类别 类型值 消息名称 消息类型摘要描述 定义 RFC 编号
3 目标不可达 表示数据报无法送达其目标。代码值提供了关于错误性质更多信息的详细信息。 792
ICMPv4 错误消息 4 源抑制 允许拥塞的 IP 设备告诉发送数据报的设备减慢发送数据报的速度。 792
5 重定向 允许路由器通知主机使用更好的路由发送数据报。 792
11 时间超限 发送时,由于生存时间字段已过期,数据报在交付前被丢弃。 792
12 参数问题 表示在交付数据报时出现的一些问题(由代码值指定)。 792
0 回声响应 作为对回声(请求)消息的回复发送;用于测试连通性。 792
8 回声(请求) 由设备发送,以测试与互联网上另一设备的连通性。消息名称中有时会出现“请求”一词。 792
9 路由器通告 由路由器用于告知主机其存在和能力。 1256
ICMPv4 信息消息(第一部分,共 2 部分) 10 路由器请求 由主机使用,以提示任何监听路由器发送路由器通告。 1256
13 时间戳(请求) 由设备发送,请求另一设备发送时间戳值以进行传播时间计算和时钟同步。消息名称中有时会出现“请求”一词。 792
14 时间戳响应 作为对时间戳(请求)的响应发送,以提供时间计算和时钟同步信息。 792
15 信息请求 最初用于从其他设备请求配置信息。现在已过时。 792
16 信息响应 最初用于在信息请求消息的响应中提供配置信息。现在已过时。 792
ICMPv4 信息性消息(第二部分,共 2 部分) 17 地址掩码请求 用于请求设备发送子网掩码。 950
18 地址掩码回复 包含在回复地址掩码请求时发送的子网掩码。 950
30 跟踪路由 用于实现实验性的增强型跟踪路由实用程序。 1393
1 目的地不可达 表示数据报无法递送到其目的地。代码值提供有关错误性质的更多信息。 2463
ICMPv6 错误消息 2 数据包过大 当数据报因为对于路由中下一跳的最大传输单元(MTU)来说太大而无法转发时发送。此消息在 IPv6 中是必需的,而在 IPv4 中不是,因为在 IPv4 中,路由器可以分片过大的消息,但在 IPv6 中它们不能。 2463
3 时间超出 当数据报在交付前被丢弃,因为跳数限制字段减少到零时发送。 2463
4 参数问题 表示在递送数据报时出现了一些问题(由代码值指定)。 2463
128 回显请求 由设备发送以测试与互联网上另一设备的连通性。 2463
129 回显应答 作为对回显(请求)消息的回复发送;用于测试连通性。 2463
133 路由器请求 促使路由器发送路由器通告。 2461
ICMPv6 信息性消息 134 路由器通告 由路由器发送,告知本地网络上的主机路由器存在。它还描述了其功能。 2461
135 邻居请求 由设备发送以请求另一设备的第 2 层地址,同时提供自己的地址。 2461
136 邻居通告 向网络上的其他设备提供有关主机的信息。 2461
137 重定向 将传输从主机重定向到网络上的直接邻居或路由器。 2461
138 路由器重新编号 传达路由器重新编号的信息。 2894

你可以看到,在 ICMPv4 和 ICMPv6 中,许多消息类型相当相似,但也有一些细微的差异。一个明显的差异是,在 ICMPv4 中,重定向被视为错误消息,但在 ICMPv6 中它是信息性消息。消息的使用方式也经常不同。在 IPv6 中,许多 ICMP 信息性消息的使用在邻居发现(ND)协议中有描述,这是 IPv6 中新的(见第三十六章)。

注意,信息请求和信息回复消息最初是为了允许设备确定 IP 地址以及可能的其他配置信息而创建的。这个功能后来通过主机配置协议如反向地址解析协议(RARP;参见第十四章"))、引导协议(BOOTP;参见第六十章"))和动态主机配置协议(DHCP,在第第六十一章至第六十四章中讨论)来实现。这些消息类型现在已过时。

ICMP 消息创建和处理约定和规则

在本章前面关于 ICMP 的概述中,我把 IP 和 ICMP 之间的关系比作行政主管和行政助理之间的关系。许多主管在优秀的助理身上看重的特点之一是助理能够独立工作,不会造成不必要的干扰。一个好的助理应该节省主管的时间,而不是浪费她的时间。

作为 IP 的助手,ICMP 必须同样帮助 IP 正常工作,同时不占用太多资源。在这里,所节约的资源不是时间,而是带宽。ICMP 消息很重要,但必须被视为运行网络的开销的一部分。它们不携带用户数据,因此每一条都代表着网络中整体最终用户带宽的小损失。因此,我们只想在必要时发送它们,并且要仔细控制它们生成的条件。

行政助理相对于网络协议有一些明显的优势:常识和经验。他们通常知道帮助和阻碍之间的界限在哪里;计算机则不知道。为了部分弥补这一点,ICMP 的操作由一套关于如何创建和处理消息的约定规则来指导。对于 ICMPv4,这些约定部分地描述在定义 RFC 792 中,但在 RFC 1122,“对互联网主机的要求——通信层”中描述得更多,该文档提供了在主机设备中实现 TCP/IP 的具体信息。在 ICMPv6 中,RFC 1122 中出现的与 ICMP 实现相关的信息已被大量纳入定义 ICMPv6 的主要文档 RFC 2463 中。

与消息生成相关的大部分问题都与错误消息有关,而不是信息消息。后一类消息通常不会引起问题,因为它们是根据使用它们的协议中已经建立的特定规则生成的。例如,路由器定期发送路由器通告消息,并且确保这是不频繁的。它们也是响应主机偶尔发送的路由器请求消息而发送的,只要主机不出现混乱并开始发送大量的请求,就不会有问题。即使在这种情况下,你也可以给路由器足够的智能,使其不会太频繁地发送路由器通告。

ICMP 消息响应的限制

问题出现在错误消息上,特别是因为它们是针对许多情况发送的。潜在地,它们甚至可能相互响应。如果没有特别的注意,可能会发生循环或消息生成级联。例如,考虑这样一种情况:设备 A 遇到错误并向设备 B 发送错误报告。设备 B 发现设备 A 的消息中存在错误,并向设备 A 发送错误报告。这可能导致数十亿条消息在设备之间来回发送,从而阻塞网络,直到有人发现出了什么问题并修复它。

为了防止出现此类问题,在以下任何情况下都不应生成 ICMP 错误消息 必须不

一个 ICMP 错误消息 这防止了前面提到的循环。然而,请注意,ICMP 错误消息 可以 在响应 ICMP 信息消息时生成。

一个广播或多播数据报 如果一个数据报被广播到 5,000 个主机,并且每个主机都发现其中的错误并尝试向源发送报告,会发生什么?结果可能很糟糕!

除了第一个数据报片段之外 在许多情况下,可能导致设备对某个片段生成错误的情况也会影响到后续的每个片段,从而造成不必要的 ICMP 流量。因此,当一个数据报被分片时,设备可能只在第一个片段出现问题时发送错误消息。

非单播源地址的数据报 如果一个数据报的源地址没有定义一个唯一的单播设备地址,则无法向该源发送错误消息。这防止了 ICMP 消息被广播、单播或发送到非路由的特殊地址,例如回环地址。

小贴士

关键概念 为了防止网络上发送过多的 ICMP 消息,有一套特殊的规则来规定何时以及如何创建它们。其中大部分都是为了消除在特定事件发生时会产生大量 ICMP 错误消息的情况。

这些规则适用于 ICMPv4 和 ICMPv6,但在 ICMPv6 中存在一些特殊情况。在特定情况下,ICMPv6 数据包太大消息可能被发送到多播地址,因为这是路径 MTU 发现(在第二十七章中描述)正常工作所必需的。第二十七章。某些参数问题消息也可能被发送到多播或广播地址。最后,除了上述规则外,IPv6 实现还特别指示要限制发送 ICMPv6 消息的整体速率。

ICMP 消息处理约定

消息处理通常按照在 ICMP 一般操作部分中较早描述的方式进行,ICMP 消息根据需要交付给 IP 软件或其他协议软件实现。对消息的处理通常取决于其类型。一些消息仅针对 IP 软件本身,但许多消息旨在针对生成导致错误的分组的上层协议。在下一节中,您将看到 ICMP 错误消息包含允许上层协议被提取的信息,以便将消息传递到适当的软件层。

在 IPv6 中,可以通过类型值确定消息类别(错误或信息)。然后可以使用此知识来指导处理具有未知类型值的 ICMP 消息。规则是,具有未知类型值的 ICMP 错误消息必须传递给适当的上层协议。具有未知类型值的信息消息将被丢弃,而不采取任何行动。

除了这些一般规则外,还制定了特定规则来指导处理某些消息类型。我在讨论单个 ICMP 消息的章节中描述了这些约定。

一个重要的最终观点是,ICMP 消息,尤其是错误消息,并不被认为对处理它们的设备具有约束力。继续使用办公室类比,它们在办公室中的地位相当于仅相当于一个信息备忘录,而不是一项任务。通常情况下,设备在处理 ICMP 消息后应该采取行动,但设备并不需要这样做。例外情况再次是当信息消息用于特定目的时。例如,大多数成对出现的消息都是设计成请求导致匹配的回复,而请求则产生广告。

小贴士

关键概念 接收 ICMP 消息的设备不需要采取行动,除非使用消息类型的协议指定了对特定消息类型的特定响应。特别是,当接收 ICMP 错误消息时,设备不需要执行任何特定任务。

ICMP 通用消息格式和数据封装

如本章中迄今为止所看到的,ICMP 与其说是一个执行特定功能的协议,不如说是一个交换错误报告和信息的基础框架。由于每种消息类型都用于不同的目的,它们包含的信息类型不同。这意味着每个 ICMP 消息都有略微不同的格式。然而,同时,ICMP 消息类型也有一定程度的共性——每种消息类型之间有部分内容是共同的。

ICMP 通用消息格式

你可以将 ICMP 消息的结构想象成一个通用部分和一个独特部分。通用部分由三个字段组成,这些字段在所有 ICMP 消息中具有相同的大小和相同的含义(尽管每个 ICMP 消息类型字段中的值并不相同)。独特部分包含特定于每种消息类型的字段。

有趣的是,通用消息格式对于 ICMPv4 和 ICMPv6 基本上是相同的。它在表 31-3 中描述,并在图 31-2 中展示。

表 31-3. ICMP 通用消息格式

字段名称 大小(字节) 描述
类型 1 识别 ICMP 消息类型。对于 ICMPv6,0 到 127 的值是错误消息,128 到 255 的值是信息消息。该字段的常见值在表 31-2 中给出。
代码 1 识别每个 ICMP 消息类型值内的消息子类型。因此,可以为每种消息类型定义多达 256 个子类型。该字段的值将在以下章节中关于单个 ICMP 消息类型的章节中展示。
校验和 2 一个 16 位的校验和字段,其计算方式类似于 IPv4 中的 IP 头校验和。它为整个 ICMP 消息提供错误检测覆盖。注意,在 ICMPv6 中,为校验和计算预先附加了 IPv6 头字段的一个伪头;这与在 TCP 中执行的方式相似。
消息体/数据 可变 包含用于实现每种消息类型的特定字段。这是消息的独特部分。

ICMP 通用消息格式 这个通用的整体消息格式用于 ICMPv4 和 ICMPv6 消息类型。

图 31-2. ICMP 通用消息格式 这个通用的整体消息格式用于 ICMPv4 和 ICMPv6 消息类型。

在 ICMP 错误消息中包含原始数据报

消息体通常包含一个或多个字段,这些字段携带与每种特定类型 ICMP 消息相关的信息。所有 ICMP 错误消息都包括导致生成 ICMP 错误消息的原始 IP 数据报的一部分。这有助于通过允许将错误传达给高层来诊断导致生成 ICMP 消息的问题。

对于两种 ICMP 版本,包含原始 IP 数据报信息的方式不同:

ICMPv4 错误消息 每个错误消息都包括完整的 IP 报头和有效负载的前 8 个字节。由于有效负载的开始将包含封装的更高层报头,因此 ICMP 消息还携带完整的 UDP 报头或 TCP 报头的前 8 个字节。在两种情况下,源端口和目的端口号码都是包含的部分。如果原始报头是一个没有选项的标准 IP 报头,则消息体长度为 28 字节;如果有选项,则长度更大。

ICMPv6 错误消息 每个错误消息都包括尽可能多的 IPv6 数据报,而不会导致 ICMPv6 错误消息(包括其 IP 报头封装)的大小超过最小 IPv6 最大传输单元大小,即 1280 字节。与 ICMPv4 相比,这为诊断提供了额外的信息,同时确保没有 ICMPv6 错误消息会太大,以至于无法在任何物理网络段中传输。包含数据的较大大小允许在错误消息中包含 IPv6 扩展报头,因为错误可能出现在这些扩展报头之一中。

注意

记住,在 IPv6 中,路由器不能分片 IP 数据报;任何超出底层物理网络大小的数据报都会被丢弃。因此,ICMPv6 被设计成通过不创建超过通用 IPv6 MTU 大小(1280 字节)的 ICMPv6 数据报来确保这一点

小贴士

关键概念 每种 ICMP 消息都包含该消息类型独有的数据,但所有消息都根据通用的 ICMP 消息格式进行结构化。ICMP 错误消息在其消息体字段中始终包含导致生成错误的部分原始 IP 数据报。

ICMP 数据封装

在将 ICMP 消息格式化后,它就像任何其他 IP 消息一样封装在 IP 数据报中。这就是为什么有些人认为 ICMP 在架构上比 IP 层次更高,尽管如我之前讨论的,它实际上更像是一个特殊情况。你还可以看到,当生成 ICMP 错误消息时,我们最终会得到原始 IP 报头和部分或全部的有效负载,这些都被封装在 ICMP 消息中,而该消息反过来又封装在一个新的 IP 报头中,该报头将作为错误报告发送回去,通常发送给发送原始 IP 消息的设备。

第三十二章. ICMPV4 错误消息类型和格式

无标题图片

路由器和主机使用互联网控制消息协议(ICMP)错误消息来告知发送数据报的设备在投递过程中遇到的问题。原始的 ICMP 版本 4(ICMPv4)定义了五种不同的错误消息,这些消息都在原始 ICMP 标准 RFC 792 中进行了描述。这些是最重要的 ICMP 消息之一。它们提供了关于错误条件的关键反馈,并可能帮助发送设备采取纠正措施,以确保可靠和高效的数据报投递。

在这四章关于特定 ICMP 类型的章节中,我首先探讨 ICMPv4 错误消息。我从目的地不可达消息开始,这些消息是由于数据报投递失败而发送的,以及源端抑制消息,这些消息用于告诉设备减慢发送数据报的速度。接下来,我描述了超时消息,这些消息是在数据报在网络中传输时间过长或从片段重新组装所需时间过长时发送的,以及重定向消息,这些消息允许路由器向主机提供关于更好路由的反馈。最后,我讨论了参数问题消息,这些是用于其他 ICMP 错误消息未涵盖的问题的通用消息。

ICMPv4 目的地不可达消息

由于互联网协议(IP)是一个不可靠的协议,因此无法保证一个设备发送给另一个设备的数据报最终会到达。主机和路由器的互联网将尽力投递数据报,但由于各种原因,它可能无法到达目的地。IP 网络上的设备理解这一点,并且相应地设计。IP 软件从不假设其数据报总是会收到,而像传输控制协议(TCP)这样的高层协议负责为需要这些功能的程序提供可靠性和接收数据的确认。

这种设置,由高层处理失败投递,在某些情况下是足够的。例如,假设设备 A 试图向设备 B 发送数据,但设备 B 附近的路由器过载,因此它丢弃了数据报。在这种情况下,问题可能是间歇性的,因此设备 A 可以重传并最终到达设备 B。但是,如果设备试图向一个不存在的 IP 地址发送数据,或者存在不易纠正的路由问题,该怎么办呢?在这种情况下,让源端不断重试至少是不高效的。

IP 协议设计为允许 IP 数据报投递失败,我们应该认真对待任何此类失败。我们真正需要的是一个反馈机制,能够告诉源设备发生了不适当的事情以及原因。在 IP 版本 4(IPv4)中,这项服务是通过传输目标不可达ICMP 消息来提供的。当一个源节点收到这些消息之一时,它知道发送数据报出现了问题,然后可以决定是否采取任何行动。像所有 ICMP 错误消息一样,目标不可达消息包含无法投递的数据报的一部分,这有助于错误接收者找出问题所在。

ICMPv4 目标不可达消息格式

表 32-1 和图 32-1

图 32-1. ICMPv4 目标不可达消息格式

ICMPv4 目标不可达消息子类型

有许多不同的原因可能导致数据报无法到达其目的地。其中一些可能是因为错误的参数(如前面提到的无效 IP 地址示例)。路由器可能因为任何原因无法到达特定的网络。也可能存在其他更奇特的原因,这些原因与数据报无法投递有关。

因此,ICMPv4 目标不可达消息类型可以被视为一类相关的错误消息。收到目标不可达消息告诉设备它发送的数据报无法交付,并且 ICMP 头部中的代码字段指示了非交付的原因。表 32-2 显示了不同的代码值、相应的消息子类型以及每个的简要说明。

表 32-2. ICMPv4 目标不可达消息子类型

代码值 消息子类型 描述
0 网络不可达 数据报无法发送到 IP 地址网络 ID 部分指定的网络。这通常意味着存在路由问题,但也可能是由于地址错误引起的。
1 主机不可达 数据报被发送到 IP 地址的网络 ID 部分指定的网络,但无法发送到地址中指定的特定主机。同样,这通常意味着存在路由问题。
2 协议不可达 传输数据报的主机中指定的协议在协议字段中无效。
3 端口不可达 UDP 或 TCP 头部指定的目标端口无效。
4 需要分片且设置了 DF 标志 这是那些晦涩难懂的代码之一。通常,如果 IPv4 路由器接收到的数据报太大,无法适应下一个物理网络链路的最大传输单元(MTU),则会自动分片数据报。然而,如果 IP 头部中的 DF(不要分片)标志被设置,这意味着数据报的发送者不希望数据报被分片。这使路由器处于两难境地,它将被迫丢弃数据报并使用此代码发送错误消息。这种消息类型通常被巧妙地用于故意发送越来越大尺寸的消息,以发现链路可以处理的最大传输单元(MTU)大小。这个过程被称为路径 MTU 发现(在第二十七章中描述,第二十七章)。
5 源路由失败 如果在数据报的选项中指定了源路由,但路由器无法将数据报转发到路由中的下一个步骤,则会生成此错误。
6 目标网络未知 未使用;使用代码 0 代替。
7 目标主机未知 指定的主机未知。这通常由目标主机本地的路由器生成,通常意味着地址错误。
8 源主机隔离 已过时,不再使用。
9 与目标网络的通信被管理员禁止 源设备不允许向目标设备所在的网络发送数据。
10 与目标主机通信被管理员禁止 源设备允许发送到目标设备所在的网络,但不能发送到该特定设备。
11 由于服务类型无法到达目标网络 由于无法提供数据报头部服务类型字段中指定的服务,无法到达 IP 地址中指定的网络。
12 由于服务类型无法到达目标主机 由于无法提供数据报服务类型字段中指定的服务,无法到达 IP 地址中指定的目标主机。
13 管理性禁止通信 由于基于内容过滤阻止消息的过滤导致数据报无法转发。
14 主机优先级违规 当服务类型字段中的优先级值不被允许时,由第一个路由器(处理发送数据报的第一个路由器)发送。
15 优先级截止生效 当路由器收到一个优先级值(优先级)低于当时网络允许的最小值的数据报时发送。

如您在表 32-2 中看到的,目前并不是所有这些代码都在积极使用。例如,代码 8 已过时,代码 0 代替了 6。此外,一些与服务类型字段相关的较高数字没有积极使用,因为服务类型没有被积极使用。

小贴士

关键概念 ICMPv4 目的地不可达 消息用于通知发送设备 IP 数据报交付失败。消息的代码字段提供了关于交付问题性质的信息。

目的地不可达消息的解释

需要记住的是,就像 IP 是尽力而为一样,使用 ICMP 报告不可达目的地也是尽力而为。意识到这些 ICMP 消息本身是在 IP 数据报中传输的。更重要的是,记住可能存在阻止路由器检测 ICMP 消息交付失败的问题,例如低级硬件问题。理论上,即使检测到交付失败,路由器也可能被阻止发送 ICMP 消息。

因此,应将发送目的地不可达消息视为补充。不能保证发送数据报的每个问题都会导致相应的 ICMP 消息。没有任何设备应该期望在失败交付时收到 ICMP 目的地不可达消息,就像它最初期望交付一样。这就是为什么在讨论开始时提到的上层机制仍然很重要的原因。

ICMPv4 源抑制消息

当源设备发送数据报时,它将穿越互联网,最终到达其预期的目的地(至少,这是我们希望发生的事情)。在那个时刻,目标设备负责通过检查它并确定要将数据报交给哪个高层软件进程来处理数据报。

如果目标设备以相对较慢的速度接收数据报,它可能能够在接收的同时即时处理每个数据报。然而,在典型的互联网中,数据报的接收可能会不均匀或突发,流量速率交替上升和下降。为了允许数据报到达速度超过其处理速度的时间,每个设备都有一个缓冲区,它可以暂时存储它已经接收到的数据报,直到它有机会处理它们。

然而,这个缓冲区本身的大小是有限的。假设设备已经得到适当的设计,缓冲区通常足以在大多数时候平滑处理高流量和低流量时段。仍然可能发生某些情况,其中流量接收速度如此之快,以至于缓冲区完全填满。以下是一些可能发生这种情况的场景示例:

  • 单个目标设备被来自许多源的数据报淹没,例如,一个流行的网站被 HTTP 请求淹没。

  • 设备 A 和设备 B 正在交换信息,但设备 A 比设备 B 快得多,可以比设备 B 更快地生成出站数据报和处理入站数据报。

  • 路由器通过高速链路接收大量需要通过低速链路转发的数据报;它们在等待通过慢速链路发送时开始堆积。

  • 硬件故障或其他情况导致数据报在设备上停留,无法被处理。

当设备没有更多缓冲区空间时,它被迫丢弃数据报,并被说成是拥塞的。由于 IP 本身是不可靠的且未确认的,因此,虽然简单地允许高层协议检测丢弃的数据报并生成替代品是可能的,但让拥塞设备通过告诉源它已过载来向源提供反馈要合理得多。

在 IPv4 中,由于拥塞而被迫丢弃数据报的设备会通过向其发送 ICMPv4 源抑制消息向使其过载的源提供反馈。正如你用水来扑灭火焰一样,源抑制消息是一个试图抑制发送速度过快的源设备的信号。换句话说,这是一种礼貌的方式,让一个 IP 设备告诉另一个设备,“慢一点!”当一个设备收到这样的消息时,它知道它需要降低向发送它的设备发送数据报的速度。

ICMPv4 源抑制消息格式

表 32-3 和 图 32-2 展示了 ICMPv4 源抑制消息的具体格式。

表 32-3. ICMPv4 源抑制消息格式

字段名称 大小(字节) 描述
类型 1 识别 ICMP 消息类型;对于源抑制消息,此值设置为 4。
代码 1 识别正在通信的错误子类型。对于源抑制消息,此字段未使用,并设置为 0。
校验和 2 ICMP 头的 16 位校验和字段(见第三十一章

图 32-2. ICMPv4 源抑制消息格式

源抑制消息的问题

源抑制格式的有趣之处在于它基本上是一个空消息。它告诉源目标已拥塞,但并未提供关于该情况的具体信息,也没有指定目标确切希望源如何减少其传输速率。也没有方法让目标向源发出信号,表明它不再拥塞,源应恢复其先前的发送速率。这意味着源抑制消息的响应留给接收它的设备。通常,设备会减少其传输速率,直到不再收到这些消息,然后它可能尝试缓慢地再次增加速率。

以类似的方式,关于何时以及如何生成源抑制消息没有规则。一个常见的约定是,对于每个被丢弃的数据报生成一条消息。然而,更智能的算法可能在高端路由器上被采用,以预测设备缓冲区何时会满,并预先抑制发送速度过快的某些源。设备还可以决定在变得繁忙时是否抑制所有源,或者只抑制某些源。与其他 ICMP 错误消息一样,设备不能指望在繁忙设备丢弃其数据报时发送源抑制消息。

源抑制消息中传达的信息不足,使它们成为管理拥塞的相当原始的工具。一般来说,在两个设备之间调节消息发送的过程称为 流量控制,这通常是传输层的功能。TCP 实际上有一个流量控制机制(在第四十九章 49 中讨论),它比使用 ICMP 源抑制消息的使用要优越得多。

源抑制消息的另一个问题是它们可能会被滥用。恶意用户发送这些消息可能会导致主机在没有合理原因的情况下变慢。这个问题与 TCP 流量控制方法的优越性相结合,导致源抑制消息的使用在很大程度上不再受欢迎。

小贴士

关键概念 ICMPv4 的 源抑制 消息是由设备发送的,以请求另一个设备降低发送数据报的速度。与 TCP 提供的更强大机制相比,这些消息是一种相当原始的流量控制方法。

ICMPv4 时间超限消息

大型 IP 互联网可以拥有成千上万的互联路由器,它们在各个网络之间的设备之间传递数据报。在大互联网中,路由器之间的连接拓扑可能变得复杂,这使得路由更加困难。路由协议通常允许路由器在网络上找到最佳路由,但在某些情况下,可能会选择一个低效的路由。在最坏的情况下,可能会发生 路由环路。这种情况的一个例子是,路由器 A 认为发往网络 X 的数据报应该发送到路由器 B,而路由器 B 认为它们应该发送到路由器 C,而路由器 C 认为它们需要发送回路由器 A。(有关路由环路说明的示例,请参阅第三十四章中的 ICMPv6 时间超限消息描述。)

如果发生这样的环路,进入该互联网部分的网络 X 的数据报将永远循环,消耗带宽,最终导致网络无法使用。为了防止这种情况发生,每个 IP 数据报在其报头中都包含一个生存时间(TTL)字段。该字段最初旨在限制数据报在互联网上存在的最大时间(以秒为单位),但现在通过限制数据报从一个设备传递到下一个设备的次数来限制数据报的生命周期。TTL 由源设备设置,表示它希望数据报经过的最大跳数。每个路由器都会递减该值;如果它达到零,则称数据报已 过期 并被丢弃。

当数据报因 TTL 字段过期而被丢弃时,丢弃数据报的设备将通过发送一个 ICMPv4 时间超限 消息来通知源设备这一事件,如图图 32-3 所示。收到此消息表明,原始发送设备在向该特定目的地发送时存在路由问题,或者最初设置的 TTL 字段值太低。与所有 ICMP 消息一样,接收该消息的设备必须决定是否以及如何对此消息做出响应。例如,它可能首先尝试以更高的 TTL 值重新发送数据报。

IP 数据报过期和时间超限消息生成示例 在本例中,设备 A 向设备 B 发送一个 IP 数据报,设备 B 的生存时间(TTL)字段值仅为 4(可能没有意识到设备 B 距离有七个跳数)。在第四跳时,数据报到达路由器 R4,其将 TTL 字段减至 0,然后因过期而丢弃。路由器 R4 随后向设备 A 发送一个 ICMP 时间超限消息。

图 32-3. IP 数据报过期和时间超限消息生成示例 在本例中,设备 A 向设备 B 发送一个 IP 数据报,设备 B 的生存时间(TTL)字段值仅为 4(可能没有意识到设备 B 距离有七个跳数)。在第四跳时,数据报到达路由器 R4,其将 TTL 字段减至 0,然后因过期而丢弃。路由器 R4 随后向设备 A 发送一个 ICMP 时间超限消息。

还有一种时间超限情况,ICMP 时间超限消息被使用。当一个 IP 消息被分成片段时,目标设备负责将它们重新组装成原始消息。一个或多个片段可能无法到达目的地,因此为了防止设备无限期地等待,当第一个片段到达时,它设置了一个计时器。如果这个计时器在收到其他片段之前到期,设备将放弃此消息。片段被丢弃,并生成一个时间超限消息。

ICMPv4 时间超限消息格式

表 32-4 和 图 32-4 展示了 ICMPv4 时间超限消息的具体格式。

表 32-4. ICMPv4 时间超限消息格式

字段名称 大小(字节) 描述
类型 1 识别 ICMP 消息类型;对于超时消息,此值设置为 11。
代码 1 识别正在通信的错误子类型。值为 0 表示 IP TTL 字段的过期;值为 1 表示分段重组时间已超过。
校验和 2 ICMP 头部的 16 位校验和字段(见第三十一章)。
未使用 4 留白且未使用的 4 个字节。
原始数据报部分 可变 由于 TTL 字段过期或重组定时器到期而被丢弃的数据报的完整 IP 头和负载的前 8 个字节。

ICMPv4 超时消息格式

图 32-4. ICMPv4 超时消息格式

超时消息的应用

ICMP 超时消息通常是对表 32-4 中描述的两个条件之一的响应:TTL 或重组定时器到期。通常,路由器在尝试路由数据报时生成 TTL 过期消息,而端主机指示重组违规。然而,实际上这些消息有一个非常巧妙的用途,这与报告错误毫无关系。

TCP/IP 的traceroute(或tracert)实用程序用于显示数据报在源和目的地之间特定路由上传递的设备序列。traceroute 实用程序还显示了数据报到达该路由中每个跳所需的时间。该实用程序最初是通过发送具有递增 TTL 值的数据报并使用超时消息实现的。

首先,发送一个 TTL 值为 1 的虚拟数据报,导致路由中的第一个跳丢弃数据报并发送一个 ICMP 超时消息;然后可以测量这个过程中的时间。然后,发送一个 TTL 值为 2 的数据报。这会导致路由中的第二个设备报告一个超时消息,依此类推。通过继续增加 TTL 值,你可以从路由中的每个跳获取报告。参见第八十八章了解更多关于 traceroute 操作细节。

小贴士

关键概念 ICMPv4 的超时消息在两种不同的时间相关情况下发送。第一种情况是,如果数据报的生存时间(TTL)字段减少到零,导致其过期并丢弃数据报。第二种情况是,在接收方的重组定时器到期之前,未接收到分段消息的所有片段。

ICMPv4 重定向消息

在互联网中,每个设备都需要能够向其他所有设备发送数据。如果主机负责确定每个可能目的地的路由,那么每个主机都需要维护一个庞大的路由信息集。由于互联网上有如此多的主机,这将是一个非常耗时且维护密集的情况。

相反,IP 互联网的设计基于一个基本的设计决策:路由器负责确定路由并维护路由信息。主机只确定何时需要将数据报路由,然后将数据报交给本地路由器发送到所需的位置。我在对 IP 路由概念的概述中详细讨论了这一点(见第二十三章)。

由于大多数主机不维护路由信息,它们必须依赖路由器来了解路由以及将数据报发送到不同目的地的情况。通常,一个 IP 网络上的主机最初会拥有一个基本的路由表,告诉它将本地网络之外的所有内容发送到单个默认路由器,然后该路由器将确定如何处理它。显然,如果网络中只有一个路由器,主机将使用该路由器作为所有非本地流量的默认路由器。然而,如果有两个或更多路由器,将所有数据报发送到单个路由器可能没有意义。可能手动配置主机以知道为哪些目的地使用哪个路由器,但 IP 中的一种机制可以允许主机自动学习这一点。

考虑一个包含多个主机(H1、H2 等)和两个路由器 R1 和 R2 的网络 N1。主机 H1 已被配置为将所有数据报发送到路由器 R1,作为其默认路由器。假设它想向网络 N2 上的设备发送数据报。然而,网络 N2 最直接地通过路由器 R2 而不是 R1 连接到网络 N1。数据报首先会被发送到路由器 R1,R1 将查看其路由表,并看到网络 N2 的数据报需要通过路由器 R2 发送。“但是等等,”R1 说。“R2 在本地网络中,H1 也在本地网络中——那么我作为中间人有什么用?H1 应该直接将 N2 的数据报发送到 R2,而不用我。”

在这种情况下,路由器 R1 将向主机 H1 发送一个 ICMPv4 重定向 消息,告诉它将来应直接将此类数据报发送到路由器 R2。这种情况在 图 32-5 中显示。路由器 R1 还会将数据报转发到路由器 R2 以进行投递,因为没有理由丢弃数据报。因此,尽管通常与真正的 ICMP 错误消息一起分组,但重定向消息实际上根本不是错误消息。它们代表只存在低效,而不是明显的错误。实际上,在 ICMPv6 中,它们已被重新分类。

ICMPv4 重定向消息格式

表 32-5 和 图 32-6 展示了 ICMPv4 重定向消息的具体格式。

使用 ICMP 重定向消息进行主机重定向 在本例中,主机 H1 向路由器 R1 发送一个目的地为网络 N2 的数据报。然而,路由器 R1 注意到路由器 R2 在同一网络中,并且是到达网络 N2 的更直接路由。它将数据报转发到路由器 R2,同时也向主机 H1 发送一个 ICMP 重定向消息,告诉它下次使用路由器 R2。

图 32-5. 使用 ICMP 重定向消息进行主机重定向 在本例中,主机 H1 向路由器 R1 发送一个目的地为网络 N2 的数据报。然而,路由器 R1 注意到路由器 R2 在同一网络中,并且是到达网络 N2 的更直接路由。它将数据报转发到路由器 R2,同时也向主机 H1 发送一个 ICMP 重定向消息,告诉它下次使用路由器 R2。

表 32-5. ICMPv4 重定向消息格式

字段名称 大小(字节) 描述
类型 1 识别 ICMP 消息类型;对于重定向消息,此值为 5。
代码 1 识别重定向消息的意义或范围。有关此字段在重定向消息中如何使用的说明,请参阅 表 32-6

图 32-6. ICMPv4 重定向消息格式

重定向消息解释代码

当设备接收到重定向消息时,它会检查原始数据报包含的部分。由于这包含重定向目标设备的原始目标地址,这告诉原始发送者哪些地址应在未来进行重定向。互联网地址字段告诉它应使用哪个路由器进行后续数据报。代码字段告诉发送者如何广泛地解释重定向。有四个不同的代码值,如表 32-6 所示。

表 32-6. ICMP 重定向消息解释代码

代码值 消息子类型 含义
0 为网络(或子网)重定向数据报 重定向所有未来发送到导致此重定向的设备地址的数据报,以及该设备所在网络(或子网)上的所有其他设备。(此代码现已过时;请参阅此表后面的注释。)
1 为主机重定向数据报 仅针对原始数据报发送的特定设备地址重定向所有未来数据报。
2 为服务类型(TOS)和网络(或子网)重定向数据报 与代码值 0 相同,但仅针对与原始数据报具有相同 TOS 值的前瞻数据报。(此代码现已过时;请参阅此表后面的注释。)
3 为 TOS 和主机重定向数据报 对于代码值 1,但仅针对与原始数据报具有相同 TOS 值的未来数据报。

注意

对于整个网络的重定向存在一个问题,即在网络划分或无类别寻址的环境中,网络规范可能是不明确的。因此,RFC 1812 禁止使用代码值 0 和 2;在现代互联网上,这些值被认为是过时的

显然,路由器通常生成重定向消息并将它们发送到主机;主机通常不会创建它们。重定向消息何时创建的具体规则可能相当复杂,因为可能存在许多条件阻止这些消息被发送。特别是,当路由器可能重定向整个网络(或子网)而不是单个主机时,存在特殊的规则。此外,请记住,TOS 字段是可选的,通常不使用,因此代码值为 2 或 3 的重定向比代码值为 0 和 1 的重定向更不常见。

重定向消息的限制

请记住,ICMP 重定向消息不是实现 IP 中一般路由过程的机制;它们只是一个辅助功能。它们是主机通过本地路由器获得路由信息的一种方便方式,但不用于在路由器之间通信路由信息。

这意味着重定向消息可以告诉主机使用一个更高效的第一个跳转路由器,但不能告诉路由器使用一个更高效的第二个跳转路由器。在先前的例子(如图 32-5 所示链接 和 图 32-7 展示了 ICMPv4 参数问题消息的特定格式。

ICMPv4 参数问题消息格式

图 32-7. ICMPv4 参数问题消息格式

表 32-7. ICMPv4 参数问题消息格式

字段名称 大小(字节) 描述
类型 1 识别 ICMP 消息类型;对于参数问题消息,此值为 12。
代码 1 识别正在通信的问题子类型。有关此字段与参数问题消息相关的更多信息,请参阅 表 32-8 展示了三个代码值,并对每个代码值进行了简要说明。

表 32-8. ICMPv4 参数问题消息解释代码

代码值 消息子类型 描述
0 指针指示错误 这是参数问题消息的正常用途。当使用此代码值时,指针字段指示问题的位置。
1 缺少必需的选项 IP 数据报需要包含一个缺失的选项。由于选项缺失,无法指向它。
2 错误长度 数据报的总长度不正确,表明整个消息存在一般性问题。同样,指针字段在这里没有意义。

提示

关键概念 ICMPv4 参数问题 消息是一个通用的万能工具,可以用来传达 IP 数据报中任何类型的错误。通常使用一个特殊的指针字段来指示消息接收者,问题出在原始数据报的哪个位置。

注意,指针字段只有八位宽,但由于这允许值高达 256,因此足以允许它指向 IP 头部内的任何位置。指针字段可以指向 IP 选项内的一个字段。

第三十三章。ICMPV4 信息消息类型和格式

无标题图片

在上一章中我们检查的五个互联网控制消息协议 (ICMP) 错误消息类型,在互联网协议 (IP) 内部网络操作过程中遇到错误或问题条件时,传达了重要的信息。相比之下,另一类 ICMP 消息包含那些消息,它们是 信息性的。它们不是对常规 IP 数据报中某个问题的响应,而是用于实现 IP 的各种支持功能。信息性消息用于测试和诊断目的,以及允许设备共享它们正常工作所需的临界信息。

在本章中,我描述了九种不同的 ICMP 版本 4(ICMPv4)信息消息。由于许多这些消息用于功能集,因此相关消息的对一起描述。我首先讨论了用于网络测试的回声(请求)和回声应答消息,以及用于时钟同步的时间戳(请求)和时间戳应答消息。我解释了路由器通告和路由器请求消息的使用和格式,这些消息允许主机发现本地路由器的身份并了解它们的重要信息。我还描述了用于通信子网掩码信息的地址掩码请求和地址掩码应答消息。最后,我审视了 Traceroute 消息,它实现了 traceroute 实用程序的更复杂版本。

注意

原始的 ICMP 标准还定义了两种更多的信息消息类型:信息请求和信息应答。这些消息旨在允许设备确定 IP 地址以及可能的其他配置信息。这个功能后来通过主机配置协议如反向地址解析协议(RARP)、引导协议(BOOTP)和动态主机配置协议(DHCP)来实现。这些消息类型现在已过时;因此,它们在本章中未讨论

ICMPv4 回声(请求)和回声应答消息

ICMP 信息消息的主要目的之一是启用测试和诊断,以帮助识别和纠正互联网中的问题。两个设备之间可以进行的最基本的测试就是简单地检查它们是否能够互相发送数据报。通常的做法是让一个设备向第二个设备发送测试消息,第二个设备接收消息并回复告诉第一个设备它已收到消息。

ICMPv4 包括一对专门用于连接测试的消息。假设设备 A 想看看它是否能到达设备 B。设备 A 通过向设备 B 发送 ICMPv4 Echo 消息来开始测试过程。当设备 B 接收到回声时,它会向设备 A 发送一个Echo 应答消息。当设备 A 接收到这条消息时,它就知道它能够与设备 B 成功通信(发送和接收)。

注意

该对中第一条消息的名称通常被称为回声请求。虽然这确实传达了回声和回声应答消息的配对性质,但标准中使用的正式名称只是一个回声消息

ICMPv4 回声和回声应答消息格式

表 33-1 和 图 33-1 展示了 ICMPv4 回显和回显应答消息的格式。

表 33-1. ICMPv4 回显和回显应答消息格式

字段名称 大小(字节) 描述
类型 1 识别 ICMP 消息类型。对于回显消息,值为 8;对于回显应答消息,值为 0。
代码 1 不用于回显和回显应答消息;设置为 0。
校验和 2 ICMP 头部的一个 16 位校验和字段(见第三十一章

图 33-1. ICMPv4 Echo 和 Echo Reply 消息格式 这些消息的格式中使用了两个特殊字段。它们允许设备将 Echo 和 Echo Reply 消息配对,并交换一系列消息。标识符字段原本设想为用作高级标签,如会话标识符,而序列号被视为用于识别一系列中的单个测试消息。然而,这些字段的使用取决于特定的实现。在某些情况下,标识符字段被填充为使用 Echo 或 Echo Reply 消息的应用程序进程号,以便多个用户可以使用 ping 等工具而不会相互干扰。

Echo 和 Echo Reply 消息的应用

你最可能使用 Echo 和 Echo Reply 消息的方式是通过流行的实用工具ping,它用于测试主机可达性。虽然基本测试只是简单地发送一个 Echo 消息并等待 Echo Reply 消息,但 ping 的现代版本相当复杂。它们允许用户指定许多参数,包括发送的 Echo 消息数量、发送频率、传输的消息大小等等。它们还提供了大量有关连接的信息,包括接收到的 Echo Reply 消息数量、交换这对消息所花费的时间以及更多。有关 ping 的完整说明,请参阅第八十八章。

小贴士

关键概念 ICMPv4 的Echo (请求)Echo Reply消息用于促进网络可达性测试。一个设备可以通过发送 Echo 消息并等待另一个设备返回 Echo Reply 消息来测试其与另一个设备进行基本通信的能力。ping 实用工具是 TCP/IP 因特网中广泛使用的诊断工具,它利用了这些消息。

ICMPv4 时间戳(请求)和时间戳回复消息

因特网上的所有主机和路由器都是相互独立运行的。这种自主性的一个方面是每个设备都维护一个独立的系统时钟。然而,有一个问题:即使是非常精确的时钟,在保持时间的准确性以及启动时初始化的时间上也有细微的差异。这意味着在正常情况下,因特网上的任何两个设备都不保证具有完全相同的时间。

TCP/IP 的创造者认识到,如果一对设备之间的系统时钟差异太大,某些应用程序可能无法正常工作。为了支持这一需求,他们创建了一对 ICMP 消息,允许设备交换系统时间信息。发起设备创建一个时间戳消息并将其发送给它希望同步的设备。该设备以时间戳回复消息的形式进行响应。这些消息中的时间戳字段用于标记消息发送和接收的时间,以便同步设备的时钟。

注意

与上一节中描述的回显消息一样,时间戳消息有时被视为时间戳请求,尽管其正式名称中并没有出现“请求”一词

ICMPv4 时间戳和时间戳回复消息格式

ICMPv4 的时间戳时间戳回复消息具有相同的格式。发起设备填写一些字段,而响应设备填写其他字段。格式如表 33-2 和图 33-2 所示。

表 33-2. ICMPv4 时间戳和时间戳回复消息格式

字段名称 大小(字节) 描述
类型 1 识别 ICMP 消息类型。对于时间戳消息,值为 13;对于时间戳回复消息,值为 14。
代码 1 对于时间戳和时间戳回复消息未使用;设置为 0。
校验和 2 ICMP 头部(见第三十一章

图 33-2. ICMPv4 时间戳和时间戳回复消息格式

所有三个时间戳都表示自午夜以来的毫秒数,世界时 (UT)(也称为格林威治平均时间GMT)。之所以有三个时间戳而不是你通常期望的两个,是因为响应设备在接收到时间戳消息和生成时间戳回复时记录了单独的时间戳。当回复消息被原始设备接收时,它就有了时间戳和时间戳回复消息发送的时间。这使得原始设备能够区分在网络中传输数据报所需的时间和另一设备处理时间戳消息并将其转换为时间戳回复消息所需的时间。

使用时间戳和时间戳回复消息的问题

实际上,即使有这三个时间戳字段,在互联网(尤其是像互联网这样的大型互联网)上协调系统时钟也很困难。主要问题是发送数据报所需的时间因数据报而异。再次强调,由于 IP 不可靠,数据报接收的时间可能是无限的。事实上,它可能被路由器丢失或丢弃。

这意味着简单的交换时间戳和时间戳回复消息并不是一个足够可靠的保证,以确保在典型的 IP 互联网上两个设备同步。因此,现代设备通常使用更复杂的方法进行时间同步,例如网络时间协议(NTP)。

注意,与许多其他 ICMP 消息类型不同,对时间戳和时间戳回复消息的支持是可选的,对于主机和路由器都是如此。

ICMPv4 路由器通告和路由器请求消息

在第二十三章中,我讨论了 IP 互联网设计的关键方面:路由器与主机在路由方面的角色差异。路由器负责路由数据报,因此需要知道路由并交换路由信息。主机通常对路由了解不多;它们依赖路由器来传递发往本地网络外目的地的数据报。

这种依赖性意味着在主机真正参与互联网之前,它需要知道本地网络中至少一个路由器的身份。确保这一点的一种方法是为每个主机手动配置本地路由器的地址作为其默认路由器。这种方法很简单,但具有与手动过程相关的典型缺点:设置耗时,维护困难,缺乏灵活性。

路由器发现过程

如果有一种方法可以让宿主机自动发现本地路由器的身份并了解它们的重要信息,那就更好了。在 IP 中,这个过程称为路由器发现,最初在 RFC 1256,“ICMP 路由器发现消息”中定义。RFC 标题中引用的消息是 ICMP 路由器广告消息和路由器请求消息。它们被添加到在较早标准(如 RFC 792)中定义的 ICMP 消息类型中。

路由器负责发送路由器广告消息。这些消息告诉监听设备路由器存在,并提供有关路由器的重要信息,例如其地址(或地址,如果它有多个地址)以及宿主机应保留关于路由器信息的时间。常规路由器广告消息定期发送,管理员可以配置消息之间的时间(通常在七到十分钟之间)。宿主机监听这些消息;当收到广告时,宿主机会处理它并将有关路由器的信息添加到其路由表中。

一台没有手动配置路由信息的宿主机在首次开机时将没有任何关于路由器的知识。让它坐等数分钟以寻找常规的路由器广告消息是不高效的。而不是等待,宿主机可以在其本地网络(s)上发送一个路由器请求消息。这将促使任何听到它的路由器立即向该宿主机发送额外的路由器广告消息。

ICMPv4 路由器广告消息格式

ICMPv4 路由器广告消息格式在表 33-3 和图 33-3 中显示。

表 33-3. ICMPv4 路由器广告消息格式

字段名称 大小(字节) 描述
类型 1 识别 ICMP 消息类型。对于路由器广告消息,值为 9。
Code 1 通常设置为 0。当一个移动 IP 代理发送带有代理广告扩展的路由器广告时,只有当设备是移动代理且不打算处理正常流量时,它才可以将值设置为 16。有关移动 IP 代理发现的讨论,请参阅第三十章的详细信息。
校验和 2 ICMP 头部的一个 16 位校验和字段(见第三十一章)。
地址数量 1 包含在此广告中的与此路由器关联的地址数量。
地址条目大小 1 地址条目大小——每个地址包含的信息的 32 位字数。由于在此消息格式中,每个路由器地址都有一个 32 位的地址和一个 32 位的优先级级别,因此此值固定为 2。
生存时间 2 主机应认为此消息中的信息有效的秒数。
路由器地址条目 Num Addrs 字段值 * 8 路由器地址条目数量等于 Num Addrs 字段值。每个条目为 8 字节,包含两个子字段,每个子字段大小为 4 字节。路由器地址子字段是发送此消息的路由器接口的有效地址。优先级级别子字段是该地址的优先级级别。当广告中包含多个地址时,此字段指示路由器希望主机使用的地址。值越大表示优先级越高。

ICMPv4 路由器通告消息格式

图 33-3. ICMPv4 路由器通告消息格式

ICMPv4 路由器请求消息格式

ICMPv4 路由器请求消息非常简单,因为它们只需要传达以下单一信息:“如果你是路由器并且可以听到这个,请向我发送路由器通告。”因此,格式只是表 33-4 中显示的平凡字段集,并在图 33-4 中说明。

表 33-4. ICMPv4 路由器请求消息格式

字段名称 大小(字节) 描述
类型 1 识别 ICMP 消息类型。对于路由器请求消息,值为 10。
代码 1 未使用;值设置为 0。
校验和 2 ICMP 头部(见第三十一章

图 33-4. ICMPv4 路由器请求消息格式

路由器通告和路由器请求消息的寻址和使用

如果可能,路由器通告和路由器请求消息都作为多播发送以提高效率。路由器通告使用“所有设备”多播地址(224.0.0.1),因为它们是针对主机接收的。路由器请求消息使用“所有路由器”多播地址(224.0.0.2)。如果本地网络不支持多播,则消息将通过广播(发送到地址 255.255.255.255)发送。

重要的是要记住,就像 ICMP 重定向消息一样,路由器通告消息不是交换路由信息的通用方法。它们仅是一个支持机制,用于通知主机关于路由器的存在。路由器之间使用路由协议(如路由信息协议(RIP)和开放最短路径优先(OSPF))来交换关于路由的详细信息。

虽然路由器发现是手动配置主机默认路由器的一种替代方案,但还有其他替代方案。例如,像动态主机配置协议(DHCP)这样的主机配置协议可以使主机学习到本地网络中默认路由器的地址。

最后,请注意,当实现移动 IP 时,路由器通告消息被用作移动 IP 意识路由器发送代理通告的基础。在常规路由器通告格式中添加了一个或多个特殊扩展来创建代理通告。这在第三十一章(第三十一章. ICMP 概念和一般操作)中关于移动 IP 代理发现的章节中进行了详细讨论。

提示

关键概念 ICMP 路由器通告 消息由 IP 路由器定期发送,以通知主机其存在和特性。这样,主机就知道使用它们将数据报文发送到远程主机。一个新加入网络并希望立即了解现有路由器的主机可以发送一个 路由器请求 消息,这将促使监听路由器发送路由器通告消息。

ICMPv4 地址掩码请求和回复消息

当 IP 首次开发时,IP 地址基于简单的两级结构,包括网络标识符(网络 ID)和主机标识符(主机 ID)。为了提供更多灵活性,很快开发了一种称为 子网划分 的技术。子网划分将寻址方案扩展为三级结构,每个地址包含网络 ID、子网标识符和主机 ID。子网掩码 是一个 32 位数字,告诉设备(和用户)哪些位是子网标识符的一部分,与主机 ID 相比。所有这些都在 IP 寻址部分(第二部分-3"))中进行了详细描述。

为了在子网环境中正常工作,每个主机都必须知道与其分配的每个地址相对应的子网掩码。没有掩码,它无法正确解释 IP 地址。正如在确定本地路由器身份时,主机可以通过手动或自动方式得知本地网络的子网掩码。手动方法是将子网掩码手动分配给每个主机。自动方法利用了一对用于确定子网掩码的 ICMP 消息,这些消息在 RFC 950 中定义,该标准本身也定义了子网划分。

要使用此方法,主机在本地网络上发送一个地址掩码请求消息,通常是为了从路由器获取响应。如果它知道本地路由器的地址,它可以直接发送请求(单播);否则,主机将广播请求到任何监听的路由器。本地路由器(或其他设备)将接收此消息,并回复一个包含本地网络子网掩码的地址掩码回复消息。这个过程与主机用于请求路由器响应路由器通告消息的机制类似,但路由器不会定期发送子网掩码信息——该信息必须被请求。

ICMPv4 地址掩码请求和地址掩码回复消息格式

地址掩码请求和地址掩码回复,就像其他一些请求和回复对一样,具有相同的基本格式。主机创建请求时,除了子网掩码值本身外,所有字段都已填写,路由器提供掩码并发送回复回主机。格式在表 33-5 中描述,并在图 33-5 中展示。

表 33-5. ICMPv4 地址掩码请求和地址掩码回复消息格式

字段名称 大小(字节) 描述
类型 1 识别 ICMP 消息类型。对于地址掩码请求消息,值为 17;对于地址掩码回复消息,值为 18。
代码 1 不用于任何消息类型;设置为 0。
校验和 2 用于 ICMP 头的 16 位校验和字段(见第三十一章

图 33-5. ICMPv4 地址掩码请求和地址掩码回复消息格式

标识符和序列号字段可以用来匹配请求和回复,因为它们用于回声和回声回复消息。然而,主机通常不会像发送用于测试的回声消息那样发送多个地址掩码请求。因此,标识符和序列号字段可能被某些实现忽略。

使用地址掩码请求和地址掩码回复消息

注意,使用地址掩码请求和地址掩码应答消息是可选的,就像上一节中描述的路由器发现一样。除了这些消息或手动配置之外,还可以使用其他方法来告诉主机使用哪个子网掩码。同样,对于这种情况,ICMP 的一个常见替代方案是使用主机配置协议,如 DHCP。路由器确实需要能够对选择发送地址掩码请求的主机的地址掩码请求做出响应。

ICMPv4 Traceroute 消息

在本章前面看到的回声和回声应答消息用于在两个设备之间进行的最基本的测试:检查它们是否可以通信。还可以进行更复杂的测试,不仅可以看到设备是否能够通信,还可以发现用于在它们之间移动数据报的确切路由器序列。在 TCP/IP 中,这种诊断是通过 traceroute(或 tracert)实用程序来执行的。

traceroute的第一个实现使用了一种巧妙的时间超限错误消息的应用,如前一章所述。通过首先向目的地发送一个 TTL 值为 1 的测试消息,然后是 2,然后是 3,依此类推,源和目的地之间的每个路由器都会依次丢弃测试消息并发送回时间超限消息。然后每个路由器会显示两个主机之间的路由器序列。这种小技巧在一般意义上效果很好,但在几个方面都不是最优的。例如,它要求源设备为路径中的每个路由器发送一个测试消息,而不是只发送一个测试消息。它也没有考虑到两个设备之间的路径在测试期间可能发生变化的可能性。

认识到这些限制后,1993 年开发了一个新的实验性标准,定义了进行 traceroute 的更有效的方法:RFC 1393,“使用 IP 选项的 traceroute”。正如标题所暗示的,这种进行 traceroute 的方法是通过源设备向目的地发送包含特殊 Traceroute IP 选项的单个数据报来实现的。在测试消息沿路由进行的过程中,每个看到该选项的路由器都会向原始源发送 ICMP Traceroute 消息,该消息也在 RFC 1393 中定义。

ICMPv4 Traceroute 消息格式

由于Traceroute消息是专门为 traceroute 实用程序设计的,因此可以在其中包含额外的信息,以便路由追踪的主机可以使用。消息格式如表 33-6 和图 33-6 所示。

表 33-6. ICMPv4 Traceroute 消息格式

字段名称 大小(字节) 描述
类型 1 识别 ICMP 消息类型;在这种情况下,为 30。
状态码 1 如果源设备发送的数据报成功发送到下一个路由器,则设置为 0,或者设置为 1 以指示数据报被丢弃(意味着 traceroute 失败)。
校验和 2 ICMP 头部的一个 16 位校验和字段(见第三十一章)。
ID 号 2 一个标识字段,用于将此 Traceroute 消息与源端发送的原始消息(包含 Traceroute IP 选项的消息)匹配。
未使用 2 未使用,设置为 0。
输出跳数 2 原始消息已经经过的路由器数量。
返回跳数 2 返回消息经过的路由器数量。
输出链路速度 4 Traceroute 消息正在发送的链路速度,以每秒字节数表示。
输出链路 MTU 4 Traceroute 消息正在发送的链路的最大传输单元(MTU),以字节为单位。

ICMPv4 Traceroute 消息格式

图 33-6. ICMPv4 Traceroute 消息格式

Traceroute 消息的使用

尽管这种实现 traceroute 的方法比旧的 Time Exceeded 消息方法有优势,但它也存在一个关键缺陷:它需要修改主机和路由器以支持新的 IP 选项和 Traceroute ICMP 消息。人们并不热衷于改变,尤其是当涉及到 IP 的基本操作时。因此,RFC 1393 从未超出实验状态,大多数 IP 设备仍然使用旧的 traceroute 实现方法。然而,你可能会遇到 ICMP Traceroute 消息,所以了解它们的存在是好的。

提示

关键概念 ICMP Traceroute消息被设计为提供一种更强大的实现 traceroute(tracert)工具的方法。然而,大多数 TCP/IP 实现仍然使用 ICMP Time Exceeded 消息来完成这项任务。

第三十四章. ICMPV6 错误消息类型和格式

无标题图片

为互联网协议第四版(IPv4)定义的原始互联网控制消息协议(ICMP)包含多个错误消息,允许在互联网内部进行问题通信。当开发 IP 版本 6(IPv6)时,IPv4 和 IPv6 之间的差异足够大,以至于还需要一个新的 ICMP 版本:版本 6 (ICMPv6),它目前由 RFC 2463 指定。与 ICMPv4 一样,ICMPv6 定义了多个错误消息,用于通知源端出现了一些问题。

在本章中,我描述了 RFC 2463 中定义的四个 ICMPv6 错误消息。我首先讨论 ICMPv6 目的地不可达消息,这些消息用于告知设备它发送的数据报由于各种原因无法交付。我描述了数据包过大错误消息,当数据报因为太大而无法通过它需要穿越的底层网络时,会发送这些消息。我解释了时间超时消息的使用,这些消息表明完成传输花费了太多时间。最后,我审视了参数问题消息,这些消息提供了一种通用的方式来报告前述任何 ICMPv6 错误消息类型未描述的错误。

注意

四个 ICMPv6 错误消息中的三个(除了数据包过大之外的所有消息)与具有相同名称的 ICMPv4 错误消息等效。然而,为了使本章能够独立存在,我详细描述了每一个,并指出了 ICMPv4 和 ICMPv6 消息版本之间的任何重大差异

ICMPv6 目的地不可达消息

IPv6 在较旧版本 4 上包含一些重要增强,但两种协议的基本操作仍然本质上是相同的。与 IPv4 一样,IPv6 是一个不可靠的网络协议,它尽力交付数据报,但并不保证它们总能到达。正如它们在 IPv4 中所做的那样,IPv6 网络上的设备不能假设发送到目的地的数据报总会被接收。

当数据报无法交付时,从这种状态中恢复通常落在传输控制协议(TCP)等高层协议上,这些协议将检测到通信错误并重新发送丢失的数据报。在某些情况下,例如由于路由器拥塞而丢弃的数据报,这可能足够了,但在其他情况下,数据报可能因为发送方式本身存在固有问题而无法交付。例如,源可能指定了一个无效的目的地址,这意味着即使重发多次,数据报也永远不会到达预期的接收者。

通常,如果源只知道重新发送未交付的数据报而不知道它们丢失的原因,这是低效的。更好的是有一个反馈机制,可以告知源设备关于无法交付的数据报,并提供一些关于数据报交付失败原因的信息。与 ICMPv4 一样,在 ICMPv6 中,这是通过目的地不可达消息来完成的。每个消息都包含一个代码,指示导致数据报无法交付的基本问题性质,以及未交付的数据报的全部或部分,以帮助源设备诊断问题。

ICMPv6 目的地不可达消息格式

表 34-1 和图 34-1 显示了 ICMPv6 目的地不可达消息的具体格式。

ICMPv6 目的地不可达消息格式

图 34-1. ICMPv6 目的地不可达消息格式

表 34-1. ICMPv6 目的地不可达消息格式

字段名称 大小(字节) 描述
Type 1 标识 ICMPv6 消息类型;对于目的地不可达消息,此值设置为 1。
Code 1 标识正在通信的不可达错误子类型。请参阅表 32-2 以获取完整代码列表及其含义。
校验和 2 ICMP 头部的 16 位校验和字段(见第三十一章显示了不同的代码值、相应的消息子类型以及每个子类型的简要说明。

表 34-2. ICMPv6 目的地不可达消息子类型

代码值 消息子类型 描述
0 无路由到目的地 数据报无法投递,因为它无法路由到目的地。由于这意味着数据报无法发送到目的地设备的本地网络,这基本上等同于 ICMPv4 中的网络不可达消息子类型。
1 由于基于内容过滤而禁止与目的地通信 由于基于内容过滤而阻止消息转发。等同于 ICMPv4 中具有相同名称(和 Code 值 13)的消息子类型。
3 地址不可达 尝试将数据报交付到目标地址中指定的主机时出现了问题。此代码等同于 ICMPv4 主机不可达代码,通常意味着目标地址不正确或解析成层 2 地址时存在问题。
4 端口不可达 UDP 或 TCP 报头中指定的目标端口无效或不存在于目标主机上。

注意,代码值 2 未使用。此外,仅在交付特定数据报存在基本问题时才会发送目标不可达消息;当数据报因路由器拥塞而丢弃时,不会发送这些消息。

处理目标不可达消息

ICMPv6 目标不可达消息的接收者需要决定如何处理它。然而,就像原始数据报可能无法到达其目的地一样,目标不可达消息也可能如此。因此,设备不能依赖于接收这些错误消息中的任何一个来通知它每个交付问题。考虑到可能存在一些不可达的目标问题无法检测到,这一点尤其正确。

小贴士

关键概念 ICMPv6 的 目标不可达 消息与 ICMPv4 的目标不可达消息以相同的方式使用:用于通知发送设备无法交付 IP 数据报。消息的代码字段提供了有关交付问题性质的信息(尽管代码值与 ICMPv4 中的不同)。

ICMPv6 数据包过大消息

在版本 6 中对 IP 操作所做的最有趣的变化之一与数据报分片和重组过程有关。在 IPv4 中,主机可以发送任何允许的 IP 规范大小的数据报到互联网。如果路由器需要通过最大传输单元(MTU)大小小于数据报大小的物理链路发送数据报,它将自动分片数据报并单独发送这些片段,以便它们可以适应。目标设备将接收这些片段并将它们重新组装。我在 第二十二章 中解释了这一过程的基本原理。

尽管主机能够依赖路由器自动根据需要分片消息很方便,但路由器花费时间做这件事是不高效的。因此,在 IPv6 中,开发者决定不允许路由器分片数据报。这把责任放在了每个主机上,以确保它们发送的数据报足够小,可以适应它们与任何目的地之间的每个物理网络。这是通过使用 IPv6 默认最小 MTU 1280 实现的,每个物理链路都必须支持,或者通过一个特殊的路径 MTU 发现过程来确定一对设备之间的最小 MTU。再次强调,详细内容请参阅第二十二章。

如果 IPv6 路由器不允许分片一个太大而无法适应下一个物理链路的数据报,它应该怎么办?数据报无法转发,因此路由器别无选择,只能丢弃它。当这种情况发生时,路由器必须使用 ICMPv6 数据包过大消息向最初发送数据报的设备报告这一事件。源设备将知道它需要分片数据报,以便它能够成功到达目的地。

注意

回想一下,数据包是数据报的同义词,所以你可以把它看作是“数据报过大”消息

ICMPv6 数据包过大消息格式

表 34-3 和图 34-2 显示了 ICMPv6 数据包过大消息的格式。

表 34-3. ICMPv6 数据包过大消息格式

字段名称 大小(字节) 描述
类型 1 识别 ICMPv6 消息类型;对于数据包过大的消息,此值设置为 2。
Code 1 此消息类型未使用;设置为 0。
校验和 2 ICMP 头部(见第三十一章

图 34-2. ICMPv6 数据包过大消息格式

提示

关键概念 在 IPv6 中,路由器不允许将太大而无法通过它们连接的物理链路发送的数据报进行分段。过大的数据报将被丢弃,并向数据报的原始发送者发送一个 ICMPv6 数据包过大消息,通知它这一情况。

“数据包过大”消息的应用

虽然“数据包过大”显然是一个错误消息,但它还有另一个用途:路径 MTU 发现的实现。这个过程在 RFC 1981 中描述,定义了一种设备确定到达目的地路径的最小 MTU 的方法。为了执行路径 MTU 发现,源设备发送一系列测试消息,逐渐减小数据报的大小,直到它不再收到对其测试的“数据包过大”消息为止。有关此过程的更多详细信息,请参阅第二十七章。

注意

“数据包过大”消息是 ICMPv6 中新的。然而,它的使用方式与 ICMP4 目标不可达消息类型中的“需要分段”和“DF 设置”版本的使用方式有些相似,后者作为 IPv4 路径 MTU 发现功能的一部分使用

顺便提一下,“数据包过大”是 ICMP 消息仅在响应单播数据报时发送的规则的一个例外;它可能是在响应一个过大的多播数据报时发送的。如果发生这种情况,重要的是要意识到,一些多播的预期目标仍然可能已经收到了它,如果多播到达它们的路径没有经过导致错误的具有小 MTU 的链路。

ICMPv6 超时消息

首先设计 IP 的工程师意识到,由于互联网中路由工作的性质,总有可能数据报在系统中丢失,花费太多时间从一个路由器传递到另一个路由器。他们在 IPv4 数据报中包含了一个名为生存时间(TTL)的字段,该字段旨在由发送数据报的设备设置时间值,并用作计时器,如果数据报到达目的地花费时间过长,则丢弃数据报。

最终,这个字段的含义发生了变化,因此它代表的是数据报允许穿越的跳数数量,而不是秒数。在 IPv6 中,当这个字段被重命名为跳数限制时,其新的含义得到了正式化。无论其名称如何,该字段仍然具有相同的基本目的:通过限制路由器转发数据报的次数,它限制了数据报在互联网上存在的时间。这是特别设计来防止大型或配置不当的互联网中可能出现的路由器循环。这种情况的一个例子是,路由器 A 认为发往网络 X 的数据报应该下个路由到路由器 B,而路由器 B 认为它们应该路由到路由器 C,路由器 C 又认为它们需要路由回路由器 A。如果没有跳数限制,这样的数据报将永远循环,堵塞网络,永远不会完成任何有用的任务。图 34-3 说明了路由器循环问题。

每当路由器传递一个 IPv6 数据报时,它会减少跳数限制字段。如果该值达到零,数据报就会过期并被丢弃。当这种情况发生时,丢弃数据报的路由器会向数据报的发送者发送一个 ICMPv6 超时消息,通知它数据报已被丢弃。这基本上与 ICMPv4 的超时消息相同。与 ICMPv4 的情况一样,接收消息的设备必须决定是否以及如何响应消息的接收。例如,由于使用跳数限制过低的设备可能引起错误,设备可能会在得出存在路由问题并放弃之前,尝试使用更高的值重新发送数据报。(第三十二章说明了 TTL 过期的工作原理。)

就像 ICMPv4 的等效物一样,也存在另一种时间超时情况,其中使用 ICMPv6 超时消息。当一个 IP 消息被分割成独立发送的片段时,目标设备负责将这些片段重新组装成原始消息。然而,一个或多个片段可能无法到达目的地。为了防止设备永远等待,当第一个片段到达时,它设置了一个计时器。如果这个计时器在所有其他片段都收到之前到期,设备将放弃这个消息。这些片段将被丢弃,并生成一个超时消息。

路由环路的一个示例 此图显示了一个由四个网络组成的简单互联网,每个网络都由一个路由器提供服务。这是对 的改编,但在这个情况下,路由表设置不正确。路由器 R1 认为它需要将任何旨在发送到网络 N4 的流量路由到路由器 R3,而 R3 认为它应该发送到路由器 R2,而 R2 认为它应该返回到路由器 R1。这意味着当任何设备尝试发送到网络 N4 时,数据包将在这个三角形中循环,直到其跳数限制达到,此时将生成一个 ICMPv6 超时消息。

图 34-3. 路由环路的一个示例 此图显示了一个由四个网络组成的简单互联网,每个网络都由一个路由器提供服务。这是对图 23-3 的改编,但在这个情况下,路由表设置不正确。路由器 R1 认为它需要将任何旨在发送到网络 N4 的流量路由到路由器 R3,而 R3 认为它应该发送到路由器 R2,而 R2 认为它应该返回到路由器 R1。这意味着当任何设备尝试发送到网络 N4 时,数据包将在这个三角形中循环,直到其跳数限制达到,此时将生成一个 ICMPv6 超时消息。

ICMPv6 超时消息格式

表 32-4 和图 34-4 显示了 ICMPv6 超时消息的格式。

表 34-4. ICMPv6 超时消息格式

字段名称 大小(字节) 描述
类型 1 识别 ICMPv6 消息类型;对于超时消息,此值设置为 3。
代码 1 识别正在通信的时间错误的子类型。值为 0 表示跳转限制字段的过期;值为 1 表示分段重组时间已超过。
校验和 2 ICMP 头部的一个 16 位校验和字段(见第三十一章

图 34-4. ICMPv6 时间超限消息格式

小贴士

关键概念 与它们的 ICMPv4 同名者一样,ICMPv6 时间超限消息在两种不同的时间相关情况下发送。第一种情况是如果数据报的 跳转限制 字段减少到零,从而使其过期并丢弃数据报。第二种情况是在接收者的重组定时器过期之前,没有接收到分段消息的所有部分。

时间超限消息的应用

在 IPv4 中,ICMP 时间超限消息既用作错误消息,又巧妙地应用于实现 TCP/IP 的 traceroute 命令。这是通过首先发送一个具有 TTL 值为 1 的虚拟数据报来完成的,从而使得路由中的第一个跳点丢弃数据报并发送回一个 ICMP 时间超限消息。然后向同一目的地发送第二个数据报,其 TTL 值为 2,从而使得路由中的第二个设备报告一个时间超限消息,依此类推。

有一个 IPv6 版本的 traceroute,有时被称为 traceroute6。由于 IPv6 及其协议和应用仍在开发中,我还没有能够确定 traceroute6 是否使用前面描述的方式通过 ICMPv6 时间超限消息实现,但我相信这是可能的(这确实是有意义的)。有关 traceroute 的更多信息,请参阅第八十八章。

ICMPv6 参数问题消息

前一节中描述的 ICMPv6 目标不可达、数据包过大和时间超限消息用于向数据报的原始发送者指示特定的错误条件。认识到路由器或主机在处理数据报时可能会遇到这些问题,而这些问题没有被上述任何消息类型所涵盖,ICMPv6 包括了一个通用的错误消息类型,就像 ICMPv4 一样。这被称为 ICMPv6 参数问题消息。

如其名所示,参数问题消息表示设备在尝试通过 IPv6 数据报的头部(或多个头部)时发现了一个参数(数据报字段的一个别名)问题。此消息仅在遇到严重错误,设备无法理解数据报并不得不丢弃它时才会生成。因此,如果发现一个设备能够从中恢复的错误(不需要丢弃数据报),则不会创建参数问题消息。

与此消息的 ICMPv4 版本一样,ICMPv6 消息被设计为通用,因此它可以指示原始数据报中基本上任何字段中的错误。使用了一个特殊的指针字段,该字段指向数据报中遇到错误的位置。通过查看原始消息的结构(如您所记得,它包含在 ICMP 消息格式中,直到一定大小),原始设备可以确定哪个字段包含问题。代码值也用于传达有关问题性质的附加一般信息。

ICMPv6 参数问题消息格式

表 34-5 和 图 34-5 展示了 ICMPv6 参数问题消息的格式。

表 34-5. ICMPv6 参数问题消息格式

字段名称 大小(字节) 描述
类型 1 识别 ICMPv6 消息类型;对于参数问题消息,此值设置为 4。
代码 1 识别参数问题的通用类别。有关更多信息,请参阅 表 34-6。
校验和 2 ICMP 头部的 16 位校验和字段(见 第三十一章)。
指针 4 一个偏移量,指向原始数据报中导致生成参数问题消息的字节位置。接收 ICMP 消息的设备可以使用此值来了解原始消息中哪个字段存在问题。
原始数据报部分 可变 在不导致 ICMPv6 错误消息(包括其自己的 IP 头部)大小超过最小 IPv6 MTU 1280 字节的情况下,IPv6 数据报中可以容纳的部分。

ICMPv6 参数问题消息格式

图 34-5. ICMPv6 参数问题消息格式

参数问题消息解释代码和指针字段

Pointer 字段在 ICMPv4 中只有 8 位宽,在 ICMPv6 中已扩展到 32 位,以便在隔离错误时提供更大的灵活性。Code 值在 ICMPv6 中的使用方式与在 ICMPv4 版本的此消息类型中有所不同。在 ICMPv4 中,只有在 Code 字段为 0 时才使用 Pointer,其他代码值表示其他问题类别,对于这些类别,Pointer 字段没有意义。在 ICMPv6 中,Pointer 字段与所有 Code 类型一起使用,以指示问题的总体性质。这意味着 Pointer 字段告诉消息接收者问题发生在消息的哪个位置,而 Code 字段告诉它问题的性质。表 34-6 显示了三个 Code 值,并对每个值进行了简要说明。

表 34-6. ICMPv6 参数问题消息解释代码

代码值 消息子类型 描述
0 遇到错误的头部字段 指针字段指向一个包含错误或无法处理的头部的头部。
1 遇到未识别的下一个头部类型 如第二十六章所述,在 IPv6 中,一个数据报可以包含多个头部,每个头部都包含一个指向数据报中下一个头部的 Next Header 字段。此代码表示指针字段指向一个包含未识别值的 Next Header 字段。
2 遇到未识别的 IPv6 选项 指针字段指向一个处理设备未识别的 IPv6 选项。

小贴士

关键概念 ICMPv6 参数问题消息是一个通用错误消息,可以用来传达 IP 数据报中任何类型的错误。Pointer 字段用于向消息接收者指示问题在原始数据报中的位置。

第三十五章. ICMPv6 信息性消息类型和格式

无标题图片

在上一章中,我们探讨了多种互联网控制消息协议第 6 版(ICMPv6)错误消息。当原始发送者检测到错误,使得错误无法被传递时,这些错误消息会被发送回 IPv6 数据报的原始发送者。与原始的 ICMP(ICMPv4)版本一样,ICMPv6 还定义了另一个消息类别:信息性消息。这些 ICMPv6 消息不是用来报告错误的,而是用来共享实施各种测试、诊断和支持功能所需的信息,这些功能对于 IPv6 的运行至关重要。

在本章中,我描述了八个不同的 ICMPv6 信息消息,分为五个主题(其中六个消息是成对使用的,这些对一起描述)。我首先描述了 ICMPv6 回显请求和回显应答消息,这些消息用于网络连通性测试。我解释了路由器通告和路由器请求消息的格式,这些消息用于让主机发现本地路由器并从它们那里学习必要的参数。然后,我描述了 ICMPv6 邻居通告和邻居请求消息,这些消息用于本地网络中主机之间的各种通信,包括 IPv6 地址解析。我还讨论了 IPv6 重定向消息,这些消息让路由器通知主机更好的下一跳路由器,以及 IPv6 路由器重新编号消息。

一些 ICMPv6 信息消息包括额外的信息,这些信息根据生成消息的环境是可选的、推荐的或强制性的。其中一些在消息类型之间共享,因此它们在章节末尾的单独主题中进行了描述。

在 IPv4 中,许多 ICMP 信息消息的使用在各种不同的标准中进行了描述。在 IPv6 中,许多使用信息消息的功能已经汇集在一起,并在 IPv6 邻居发现(ND)协议中正式化。本地路由器和相邻主机的请求和通告,以及重定向信息的通信都是 ND 负责的活动示例。实际上,本章中描述的五个 ICMP 消息实际上是在 ND 标准 RFC 2461 中定义的。

小贴士

相关信息 邻居发现(ND)和 ICMPv6 显然密切相关,因为 ND 描述了几个 ICMP 消息的使用:路由器通告、路由器请求、邻居通告、邻居请求和重定向。因此,就像 ICMPv4 是 IPv4 的重要助手一样,ICMPv6 和 ND 都是 IPv6 的重要助手。在这本书中,我提供了关于这些消息如何使用的描述,这些描述将在下一章中讨论 ND。在这一章中,我主要提供这些消息使用的简要总结,同时主要关注消息格式以及该格式中每个字段的含义

ICMPv6 回显请求和回显应答消息

IP 是一个相对简单的协议,它不包含任何在设备之间执行测试的方法,以帮助诊断互联网问题。这意味着这项工作,就像其他支持任务一样,落到了 ICMP 头上。当使用 TCP/IP 出现问题时,通常进行的 simplest 测试通常是检查一对设备能否互相发送数据报。这通常是通过一个发起设备向第二个设备发送测试消息来完成的,第二个设备接收它并回复告诉第一个设备它已经收到了消息。

与 ICMPv4 一样,ICMPv6 包含了一对专门用于连接测试的消息。要使用它们,设备 A 通过向设备 B 发送 ICMPv4 回显请求消息来开始测试过程,设备 B 会以回显响应消息的形式回应设备 A。当设备 A 接收到此消息时,它知道它可以成功与设备 B 进行通信(发送和接收)。

注意

在 ICMPv4 中,第一个消息类型仅被命名为回显,但通常被称为回显请求在 ICMPv6 中请求*是正式消息名称的一部分——这是一个既谦虚又实用的改进,从清晰度的角度来看。|

ICMPv6 回显和回显响应消息格式

ICMPv6 回显请求和回显响应消息的格式与 ICMPv4 版本非常相似,如表 35-1 和图 35-1 所示。

表 35-1. ICMPv6 回显请求和回显响应消息格式

字段名称 大小(字节) 描述
类型 1 识别 ICMPv6 消息类型;对于回显请求消息,值为 128,对于回显响应消息,值为 129。(在 ICMPv6 中,信息消息始终具有 128 或更高的类型值。)
1 未使用;设置为 0。
校验和 2 用于 ICMP 头部的一个 16 位校验和字段(见第三十一章

图 35-1. ICMPv6 回显请求和回显响应消息格式

经常需要将回显响应消息与导致其生成的回显请求消息进行匹配。这些消息的格式中使用了两个特殊字段,以便将回显请求和回显响应消息匹配在一起,并允许交换一系列消息。标识符字段提供了一种方法,可以识别特定的测试会话,而序列号字段允许对会话中的测试进行编号。这两个字段的使用是可选的。

回显和回显响应消息的应用

ICMPv6 回显请求和回显响应消息通过 IPv6 版本的 IP ping 工具使用,通常称为 ping6。像它的 IPv4 前身一样,这个工具允许管理员配置多个测试选项,以执行一对设备之间简单或严格的连接测试。参见 第八十八章 以获得完整说明。

提示

关键概念 ICMPv6 的 回显请求回显响应 消息用于促进网络可达性测试。一个设备通过发送回显请求消息并等待相应的回显响应来测试其与另一个设备通信的能力。ping 工具,作为 TCP/IP 互联网中广泛使用的诊断工具,利用了这些消息。

ICMPv6 路由器通告和路由器请求消息

在最高层面上,我们可以将 IP 设备分为两组:主机和路由器。两者都参与互联网的使用,但它们有不同的角色。与这种划分相关的一个重要 IP 原则是,路由器负责路由——在网络上移动数据——而主机通常不需要担心这项工作。主机依赖于它们本地网络中的路由器,以便与其他所有主机(除了本地网络上的主机)进行通信。

这的后果是明显的:一个主机在知道至少一个本地路由器的身份以及如何使用该路由器的方法之前,实际上无法真正使用互联网。在 IPv4 中,发明了一种称为 路由器发现 的技术,它提供了一种主机可以定位路由器并学习与本地网络操作相关的重要参数的方法。IPv6 中的路由器发现以非常相似的方式工作,通过路由器定期发送 路由器通告 消息,并在主机使用 路由器请求 消息提示时响应。路由器发现功能已被纳入 ND 协议,它是更大类工具的一部分,我将其称为 主机-路由器发现 功能。

ICMPv6 路由器通告消息格式

ICMPv6 路由器通告和路由器请求消息与 ICMPv4 的对应消息相当相似。主要区别在于所传递的参数。由于在 IPv6 中,路由器比在 IPv4 中负责更多的功能,因此 ICMPv6 的路由器通告消息比旧版本多了几个字段。

ICMPv6 路由器通告消息的格式在 表 35-2 中描述,并在 图 35-2 中展示。

ICMPv6 路由器通告消息格式

图 35-2. ICMPv6 路由器通告消息格式

表 35-2. ICMPv6 路由器通告消息格式

字段名称 大小(字节) 描述
类型 1 识别 ICMPv6 消息类型;对于路由器通告消息,值为 134。
代码 1 未使用;设置为 0。
校验和 2 ICMP 头部的一个 16 位校验和字段(请参阅第三十一章
保留 6/8 (6 位) 保留供将来使用;发送为零。

ICMPv6 路由器请求消息格式

ICMPv6 路由器请求消息的格式显示在表 35-4 和图 35-3 中。

表 35-4. ICMPv6 路由器请求消息格式

字段名称 大小(字节) 描述
类型 1 识别 ICMPv6 消息类型;对于路由器请求消息,值为 133。
代码 1 未使用;设置为 0。
校验和 2 用于 ICMP 头部的 16 位校验和字段(见第三十一章

图 35-3. ICMPv6 路由器请求消息格式

路由器通告和路由器请求消息的寻址

路由器请求消息通常发送到 IPv6 的“所有路由器”多播地址;这是最有效的方法,因为路由器需要订阅此多播地址,而主机将忽略它。一个常规(非请求)的路由器通告消息发送到使用本地网络“所有节点”多播地址的所有设备。响应路由器请求消息发送的路由器通告消息以单播形式返回到发送请求的设备。

提示

关键概念 ICMPv6 路由器通告 消息由 IPv6 路由器定期发送,以通知主机其存在和特性,并为主机提供它们在本地网络中正常工作所需的参数。想要立即了解哪些路由器存在的宿主机可以发送一个 路由器请求 消息,这将促使监听的路由器发送路由器通告。

ICMPv6 邻居通告和邻居请求消息

前一节描述了路由器通告和路由器请求消息,这些消息用于协助主机-路由器发现功能,作为 IPv6 ND 协议的一部分。ND 负责的另一组主要任务是处理同一网络上的相邻主机之间的信息交换。我称这些为 主机-主机通信主机-主机发现 功能。

不可否认,ND 协议最重要的补充是那些形式化参数交换的功能以及确定相邻主机存在的方法。这些任务包括 IPv6 中新的地址解析方法,以及下一跳确定和邻居不可达检测的过程。它们需要使用两个 ICMPv6 消息:邻居请求消息邻居通告消息

邻居请求消息允许设备检查邻居是否存在且可到达,并允许设备启动地址解析。邻居通告消息确认主机或路由器的存在,并在需要时提供层 2 地址信息。正如您所看到的,这两条消息与路由器通告和路由器请求消息类似,但它们的使用方式不同,并且包含不同的参数。

ICMPv6 邻居通告消息格式

邻居通告消息的格式显示在表 35-5 和图 35-4 中。

表 35-5. ICMPv6 邻居通告消息格式

字段名称 大小(字节) 描述
类型 1 识别 ICMPv6 消息类型;对于邻居通告消息,值为 136。
代码 1 未使用;设置为 0。
校验和 2 ICMP 头部的 16 位校验和字段(见第三十一章中所述。
目标地址 16 如果邻居通告是响应邻居请求而发送的,则此值与请求中的目标地址字段相同。此字段通常包含设备的 IPv6 地址,从而发送邻居通告,但并非所有情况都是如此。例如,如果设备作为邻居请求目标的代理进行响应,则目标地址字段包含目标地址,而不是发送响应的设备地址。(有关地址解析代理的详细信息,请参阅第十三章"))。如果邻居通告是无请求发送的,则这是发送它的设备的 IPv6 地址。
选项 可变 当作为对多播邻居请求的响应发送时,邻居通告消息必须包含一个目标链路层地址选项,该选项携带发送消息的设备的链路层地址。这是一个实际上并非“可选”的选项的例子。当邻居通告作为对单播邻居请求的响应发送时,此选项在技术上不是必需的(因为请求的发送者必须已经拥有目标链路层地址才能发送单播)。尽管如此,它通常仍然被包含,以确保目标链路层地址在发送邻居请求的设备的缓存中得到更新。

ICMPv6 邻居通告消息格式

图 35-4. ICMPv6 邻居通告消息格式

表 35-6. ICMPv6 邻居通告消息标志

子字段名称 大小(字节) 描述
R 1/8(1 位) 路由器标志:当路由器发送邻居通告时设置,当主机发送时清除。这标识了发送数据报的设备类型,并用于作为邻居不可达性检测的一部分,以检测设备从充当路由器变为作为常规主机时的变化。
S 1/8(1 位) 请求标志:当设置时,表示此消息是在响应邻居请求消息时发送的。对于非请求的邻居通告清除。
O 1/8(1 位) 覆盖标志:当设置时,告诉接收方,此消息中的信息应覆盖该设备链路层地址的任何现有缓存条目。此位通常在非请求的邻居通告中设置,因为这些消息是在主机需要强制更改其邻居缓存中的信息时发送的。
保留 3 5/8(29 位) 一组大的保留位。

ICMPv6 邻居请求消息格式

邻居请求消息的格式非常简单,如表 35-7 和图 35-5 所示。

表 35-7. ICMPv6 邻居请求消息格式

字段名称 大小(字节) 描述
类型 1 标识 ICMPv6 消息类型;对于邻居请求消息,值为 135。
代码 1 未使用;设置为 0。
校验和 2 ICMP 头部(见第三十一章中关于 IPv6 地址解析的讨论。)

ICMPv6 邻居请求消息格式

图 35-5. ICMPv6 邻居请求消息格式

邻居通告和邻居请求消息的寻址

邻居请求消息要么是单播发送到目标设备的地址,要么发送到目标设备的请求节点多播地址。后者是一种特殊类型,允许设备发送一个多播,该多播将被尝试解析地址的目标设备听到,但不会被大多数其他设备听到;这已在第二十五章中解释,该章节描述了 IPv6 地址解析。

当响应邻居请求消息生成邻居通告消息时,它将单播发送回发送请求消息的设备,除非该消息是从未指定地址发送的,在这种情况下,它将多播发送到“所有节点”多播地址。如果邻居通告消息是非请求发送的(例如,由希望通知他人链路层地址变化的设备发送),它将发送到“所有节点”多播地址。

小贴士

关键概念 ICMPv6 邻居通告邻居请求 消息在许多方面与路由器通告和路由器请求消息相似。然而,它们不是用来从路由器向主机传递参数,而是用于物理网络中主机之间的各种通信,例如地址解析、下一跳确定和邻居不可达检测。

ICMPv6 重定向消息

由于在 IPv6 互联网中路由器和主机扮演着不同的角色,因此主机不需要了解太多的路由信息。它们直接将目的地为本地网络的数据报发送出去,而对于其他网络的数据报,则发送给本地的路由器,让它们“驾驶”,换句话说。

如果一个本地网络只有一个路由器,它将所有此类非本地流量发送到该路由器。如果有多个本地路由器,那么主机必须决定为哪种流量使用哪个路由器。一般来说,主机不会知道为它可能需要发送的每种数据报选择最有效路由器的方法。实际上,许多节点最初都有一个有限的路由表,指示将所有流量发送到单个默认路由器,即使网络上有多个路由器。

当路由器接收到指向某些网络的数据报时,它可能会意识到如果本地网络上不同路由器上的主机发送此类流量会更有效率。如果是这样,它将通过向发送原始数据报的设备发送 ICMPv6 重定向 消息来调用重定向功能。这是 IPv6 中 ND 协议执行的最后一个功能,并在第三十六章 协议")中解释。

备注

在 ICMPv6 中,重定向消息是信息性的,不再被视为错误消息,就像在 ICMPv4 中那样

ICMPv6 重定向消息格式

ICMPv6 重定向消息的格式显示在表 35-8 和图 35-6 中。

表 35-8. ICMPv6 重定向消息格式

字段名称 大小(字节) 描述
类型 1 标识 ICMPv6 消息类型;对于重定向消息,值为 137。
代码 1 未使用;设置为 0。
校验和 2 ICMP 头部的 16 位校验和字段(见第三十一章

图 35-6. ICMPv6 重定向消息格式

重定向消息始终以单播方式发送到最初发送原始数据报并创建重定向消息的设备的地址。

重定向消息的应用

重定向消息一直有点儿另类。在 ICMPv4 中,它被视为错误消息,但这使其与其他错误消息不同。首先,它实际上并不是错误,因为它并不代表交付失败,而只是交付过程中的低效。因此,在 ICMPv6 中,它被移动到了信息消息类型集合中。在这里,它也并不真正与其他消息相匹配,因为它是对常规 IP 消息的反应,并且它还包含(部分)产生它的数据报的副本,就像错误消息一样。

小贴士

关键概念 ICMPv6 重定向消息由路由器用来通知主机一个更好的路由器,用于将来发送到特定主机或网络的报文。然而,它们并不用于更改路由器之间的路由。

ICMPv6 路由器重新编号消息

在 IPv6 中做出的更有趣的决定之一是选择了一个非常大的 128 位地址大小。这提供了一个远远超过人类可能需要的地址空间,实际上可能比 IPv6 严格来说所需的还要大。这些比特的丰富性提供了为地址结构中的不同比特分配含义的灵活性。这反过来又为诸如 IPv6 地址的自动配置和自动重新编号等重要特性奠定了基础。

IPv6 路由器重新编号

IPv6 中的重新编号功能对网络管理员来说特别有趣,因为它有可能使大型网络迁移和合并变得更加简单。2000 年 8 月,IETF 发布了 RFC 2894,“IPv6 路由器重新编号”,它描述了一种类似的技术,允许自治系统中的路由器通过给它们新的前缀(网络标识符)来进行重新编号。

路由器重新编号实际上是一个相当简单的过程,特别是如果我们避免那些血腥的细节,这正是我的意图。网络管理员使用互联网上的设备生成一个或多个路由器重新编号命令消息。这些消息提供了一个要重新编号的路由器前缀列表。每个路由器处理这些消息,以查看它们接口上的地址是否与指定的前缀匹配。如果是这样,它们将匹配的前缀更改为消息中指定的新前缀。路由器重新编号命令消息中还包含其他信息,以控制重新编号如何以及何时进行。

如果请求,每个处理命令消息的路由器将响应一个路由器重新编号结果消息。这作为对命令消息发起者的反馈,表明重新编号是否成功,以及是否进行了任何更改。

路由重编号标准还定义了一些重要的管理功能。其中许多反映了大规模重编号路由器的强大功能,因此,它们代表了这种权力被滥用的潜在可能性。命令消息可以在测试模式下发送,此时它们会被处理,但实际的重编号并不会执行。消息包括一个序列号以防止重放攻击,并且可以使用特殊的序列号重置消息来重置之前发送的序列号信息。为了增加安全性,标准规定消息必须经过身份验证,并检查其身份。

ICMPv6 路由重编号消息格式

路由重编号消息的格式显示在表 35-9 和图 35-7 中。

ICMPv6 路由重编号消息格式

图 35-7. ICMPv6 路由重编号消息格式

表 35-9. ICMPv6 路由重编号消息格式

字段名称 大小(字节) 描述
类型 1 识别 ICMPv6 消息类型;对于路由重编号消息,该值为 138。
代码 1 指示路由重编号消息的子类型:0 = 路由重编号命令 1 = 路由重编号结果 255 = 序列号重置
校验和 2 ICMP 头部的一个 16 位校验和字段(见第三十一章中所述。
最大延迟 2 告知接收消息的路由,在发送回复之前允许的最大延迟时间(以毫秒为单位)。
保留 4 4 个保留字节。
消息体 可变 对于路由器重新编号命令,消息体包含两套信息。第一套是正在重新编号的前缀的匹配前缀部分。第二套是描述每个匹配的新前缀的一个或多个使用前缀部分。接收命令的路由器检查其自己的接口地址,如果它们与匹配前缀部分匹配,则使用使用前缀部分数据来完成重新编号。对于路由器重新编号结果,消息体包含零个或多个匹配结果条目,描述路由器从路由器重新编号命令中匹配的每个前缀。每个条目都提供有关前缀重新编号是否成功的信息。

表 35-10 显示了路由器重新编号消息标志。前四个标志(T、R、A 和 S)控制命令消息的操作。它们只是从导致结果消息创建的命令消息中逐字复制到结果消息中。P 标志仅在结果消息中使用(命令消息中为 0)。

表 35-10. ICMPv6 路由重新编号消息标志

子字段名称 大小(字节) 描述
T 1/8(1 位) 测试命令标志:当设置为 1 时,此标志将此命令消息标记为测试消息。这告诉接收者仅模拟处理重新编号,而不要实际执行。
R 1/8(1 位) 请求结果标志:当设置为 1 时,请求在处理命令消息后发送结果消息。当设置为 0 时,表示不发送。
A 1/8(1 位) 所有接口标志:当此标志清除(0)时,命令消息不应用于任何已由管理员关闭的路由器接口。当为 1 时,它应用于所有接口。
S 1/8(1 位) 站点特定标志:当路由器将其接口视为属于不同站点时,此标志才有意义。如果是这样,值为 1 表示仅将命令消息应用于与接收命令消息的接口相同的站点的接口。值为 0 表示应用于所有接口,无论站点如何。
P 1/8(1 位) 之前已处理标志:此标志通常为 0,表示命令消息之前未见过,结果消息包含处理它的报告。当为 1 时,这表示命令消息的接收者认为它之前已经见过,并且不会处理它。(测试命令不包括在评估命令消息之前是否已见过。)
保留 3/8(3 位) 保留用于未来标志的 3 位。

路由器重新编号消息的寻址

由于路由器重新编号消息旨在发送到站点的所有路由器,它们通常发送到“所有路由器”多播地址,使用链路本地或站点本地范围。它们也可以发送到本地单播地址。

ICMPv6 信息消息选项

协议定义并使用的五种 ICMPv6 信息消息类型中,每种类型都有一个选项字段,可以插入一个或多个选项。这些数据集可能不是最好的名称,因为它们在某些情况下是可选的。实际上,在某些情况下,选项实际上是消息的全部目的。例如,包含地址解析链路层地址的邻居通告消息将其包含在选项字段中,但如果没有它,消息将没有太大用处!

每个选项都有其自己的子字段结构,基于在许多消息格式中使用的经典类型、长度和值三元组。类型子字段指示选项类型,长度字段指示其长度,这样处理选项的设备就可以确定其结束位置。值可能包含在一个或多个字段中,这些字段包含选项所使用的实际信息。

一些选项仅用于一种类型的 ICMPv6 消息;而另一些则用于多种类型。因此,它们最好被视为根据需要在不同类型消息中使用的模块化组件。我在以下各节中描述了这些五个选项的格式。

源链路层地址选项格式

源链路层地址选项携带发送 ICMPv6 消息的设备的链路层地址,如表 35-11 和图 35-8 所示。它在路由器通告、路由器请求和邻居请求消息中使用。

表 35-11. ICMPv6 源链路层地址选项格式

字段名称 大小(字节) 描述
类型 1 识别 ICMPv6 选项类型。对于源链路层地址选项,其值为 1。
长度 1 整个选项(包括类型和长度字段)的长度,以 8 个八位字节(64 位)为单位。
源链路层地址 可变 发送 ICMPv6 消息的设备的链路层(第 2 层)地址。

ICMPv6 源链路层地址选项格式

图 35-8. ICMPv6 源链路层地址选项格式

目标链路层地址选项格式

目标链路层地址选项携带与邻居通告和重定向消息中的目标地址字段相对应的链路层地址。其格式如表 35-12 和图 35-9 所示。

表 35-12. ICMPv6 目标链路层地址选项格式

字段名称 大小(字节) 描述
类型 1 识别 ICMPv6 选项类型。对于目标链路层地址选项,值为 2。
长度 1 整个选项的长度(包括类型和长度字段),以 8 个八位字节(64 位)为单位表示。
目标链路层地址 可变 目标设备的链路层(第 2 层)地址。

ICMPv6 目标链路层地址选项格式

图 35-9. ICMPv6 目标链路层地址选项格式

前缀信息选项格式

前缀信息选项在路由器通告消息中提供前缀和相关信息。这是选项中最长且最复杂的,如表 35-13 和图 35-10 所示。

表 35-13. ICMPv6 Prefix Information Option Format

字段名称 大小(字节) 描述
类型 1 识别 ICMPv6 选项类型。对于前缀信息选项,值为 3。
长度 1 整个选项的长度(包括类型和长度字段),以 8 个八位字节(64 位)为单位表示。前缀信息选项的大小固定为 32 字节,因此长度字段的值为 4。
前缀长度 1 前缀字段中作为网络标识符一部分的位数(其余用于主机标识符并被忽略)。有关前缀长度的详细信息,请参阅第二十五章。
标志 1 一对标志,传达有关前缀的信息,如表 35-14 中所述。
有效期限 4 消息接收者应考虑此选项前缀在链路确定目的上有效的秒数(参见表 35-14 中 L 标志的描述)。全为 1 的值表示无限(永远)。
推荐寿命 4 当前缀的接收者使用它来自动生成地址时,这指定了此类地址保持首选(即有效且可自由使用)的秒数。全为 1 的值表示无限(永远)。
保留 4 发送为零的 4 个未使用字节。
前缀 16 在路由器通告消息中从路由器发送到主机的正在通信的前缀。前缀长度字段指示该字段中多少个 128 位是有效的(网络 ID 的一部分)。只有这些位被放置在前缀字段中;其余位被清除为零。

ICMPv6 前缀信息选项格式

图 35-10. ICMPv6 前缀信息选项格式

表 35-14. ICMPv6 前缀信息选项标志

子字段名称 大小(字节) 描述
L 1/8 (1 位) 链接标志:当设置为 1 时,告诉选项的接收者此前缀可用于链路确定。这意味着前缀可用于决定地址是否在链路上(在接收者的本地网络中)。当为 0 时,发送者没有关于是否可以使用此前缀的声明。
A 1/8 (1 位) 自动地址配置标志:当设置为 1 时,指定此前缀可用于 IPv6 地址自动配置。(有关 IPv6 自动配置的详细信息,请参阅第二十五章

重定向头部选项格式

在重定向消息中,重定向头部选项提供了导致生成重定向消息的原始消息(或其一部分)的副本。此选项的格式显示在表 35-15 和图 35-11 中。

表 35-15. ICMPv6 重定向头部选项格式

字段名称 大小(字节) 描述
类型 1 识别 ICMPv6 选项类型。对于重定向头部选项,值为 4。
长度 1 整个选项的长度(包括类型和长度字段),以 8 个八位字节(64 位)为单位表示。
保留 6 以零的形式发送的 6 个保留字节。
IP 头部 + 数据 可变 在不导致 ICMPv6 错误消息(包括其自身的 IP 头部)的大小超过最小 IPv6 MTU 1280 字节的情况下,尽可能多的原始 IPv6 数据报。

ICMPv6 重定向头部选项格式

图 35-11. ICMPv6 重定向头部选项格式

MTU 选项格式

MTU选项允许路由器在路由器通告消息中传达推荐的 MTU 值。其格式显示在表 35-16 和图 35-12 中。

表 35-16. ICMPv6 MTU 选项格式

字段名称 大小(字节) 描述
类型 1 识别 ICMPv6 选项类型。对于 MTU 选项,其值为 5。
长度 1 整个选项的长度(包括类型和长度字段),以 8 个八位字节(64 位)为单位表示。MTU 选项的长度固定为 8 字节,因此此字段的值为 1。
保留 2 发送为零的 2 个保留字节。
MTU 4 路由器推荐用于本地链路上的 MTU 值,以字节为单位。

ICMPv6 MTU 选项格式

图 35-12. ICMPv6 MTU 选项格式

第三十六章. IPV6 邻居发现 (ND) 协议

无标题图片

新的互联网协议版本 6 (IPv6) 是对久经考验的 IP 的演进。它保持了与 IPv4 相同的基本操作原则,但在地址领域进行了一些重要的修改。实际上,IPv6 中的一些更显著的变化实际上并不在 IP 本身,而是在支持 IP 的协议中。其中最有趣的一个是为 IPv6 创建了一个全新的支持协议。它结合了 IPv4 中其他协议以前执行的一些任务,添加了一些新功能,并对整个包进行了许多改进。这个新标准被称为 IPv6 邻居发现 (ND) 协议。

在本章中,我描述了 IPv6 中使用的新 ND 协议。我首先概述了该协议,讨论了其历史、创建动机以及定义它的标准。然后以一般术语描述其操作,列出 ND 执行的基本功能,这些功能分为三个组,以及用于执行这些功能的 Internet 控制消息协议版本 6 (ICMPv6) 消息类型。我描述了 ND 与 IPv4 中执行其功能的方式之间的关键区别。然后提供了关于 ND 中的三个功能组的更多信息:涉及从路由器发现重要互联网信息的功能组,涉及主机之间地址解析和邻居通信的功能组,以及涉及路由器重定向的功能组。

小贴士

背景信息 *本章假设对 IPv6 有基本理解,而这反过来又需要理解 IPv4。ND 使用 ICMPv6 消息,因此我参考了第 第三十一章 到 第三十五章,这些章节讨论了它们。最后,由于 ICMP 执行了 IPv4 中地址解析协议 (ARP) 执行的一些功能,如果您不熟悉 ARP 的操作,可能需要参考 第十三章")。|

IPv6 ND 概述

网络层协议如 IP 的目的在于提供一种将单个本地网络连接起来以创建更大互联网的手段。对于高层协议和用户来说,这个互联网在大多数方面表现得就像一个单一的大型网络,因为低层隐藏了将各个网络连接在一起的细节。任何设备都可以向任何其他设备发送信息,无论其位置如何,就像魔法一样,它将工作——至少在大多数时候。

互联网的存在意味着设备可以将所有其他设备视为对等体,至少从高层协议和应用的视角来看是这样。然而,从低层角度来看,位于主机本地网络上的设备和位于其他地方的网络设备之间存在一个非常重要的区别。在一般意义上,大多数设备与其本地网络上的设备的关系比与其远端设备的关系更为重要。设备必须特别与其他本地网络上的设备执行的一些最明显的任务包括以下内容:

直接数据报传输 设备直接将其数据传输到其本地网络上的其他设备,而前往远程设备的数据必须间接传输(路由)。

层 2 寻址 为了便于直接传输,设备需要知道本地网络上其他设备的层 2 地址;对于非本地设备,它们不需要知道这些地址。

路由器识别 为了间接传输,设备需要在其本地网络上找到一个可以与之通信的路由器。

路由器通信 本地路由器必须将其信息传达给使用它的每个本地主机,以便主机知道如何最好地使用它。

配置 主机通常会寻求本地设备提供的信息,以便它们执行配置任务,例如确定自己的 IP 地址。

为了支持这些和其他要求,与原始 IP(版本 4)一起开发了几个特殊的协议和功能。IP 寻址方案让设备能够区分本地地址和远程地址。地址解析协议(ARP)让设备能够从层 3 地址确定层 2 地址。ICMP 提供了一种消息系统,以支持本地设备之间的各种通信需求,包括主机找到本地路由器以及路由器向本地主机提供信息的能力。

这些特性在 IPv4 中都正常工作,但它们是以一种临时的方式开发的。它们不是定义在一个地方,而是在各种不同的互联网标准中定义的。这些本地设备功能的实现方式也存在一些局限性。

正式化本地网络功能:邻居概念

IPv6 代表了数十年来对 IP 本身以及整个 TCP/IP 套件的重大变化。因此,它为正式化和整合与本地设备间通信相关的许多不同功能和任务提供了理想的机会。结果是创建了一个新的协议:IPv6 版本的邻居发现,也通常称为 IPv6 邻居发现 协议。由于这个协议在 IPv6 中是新的,因此没有 IPv4 版本,所以这个名字通常只被看作是没有任何进一步说明的 ND 协议;它的使用与 IPv6 是隐含的。

“邻居”这个术语多年来在各种网络标准和技术中被用来指代彼此相邻的设备。在当前讨论的上下文中,如果两个设备位于同一本地网络中,它们就是“邻居”,这意味着它们可以直接向对方发送信息。这个术语可以指代一个普通的主机或一个路由器。我认为这与人类称呼附近居住或工作的人的方式相似。就像我们中的大多数人都会与邻居有特殊的关系,并且比与远方的人交流更多一样,IP 设备也是如此。

由于邻居是本地设备,ND 协议的名称似乎表明 ND 主要关于邻居如何发现彼此的存在。然而,在这个协议的上下文中,“发现”这个术语有更广泛的意义:它不仅指发现谁是邻居,还指发现关于它们的重要信息。除了让设备识别它们的邻居外,ND 还促进了前面列出的所有任务,包括地址解析、参数通信、自动配置等功能,您将在本章中看到。

小贴士

关键概念 新的 IPv6 邻居发现 (ND) 协议为 IPv6 正式定义了一系列与本地网络中设备间通信相关的功能,这些功能在 IPv4 中由 ARP 和 ICMP 等协议执行。ND 被视为 IPv6 的另一个辅助协议,并且与 ICMPv6 密切相关。

邻居发现标准

ND 协议最初在 1996 年 8 月发布的 RFC 1970 中定义,并在 1998 年 12 月发布的当前定义标准 RFC 2461 中进行了修订。ND 协议的大部分功能都是通过一组五个特殊的 ICMPv6 控制消息实现的,这些消息在上一章中已有讨论。因此,从某种程度上说,ND 的操作部分由 ICMPv6 标准,RFC 2463 所描述。ICMPv4 可以被认为是 IPv4 的“行政助理”,而 IPv6 实际上有两个这样的助理紧密协作:ICMPv6 和 ND。我在本章后面将讨论 IPv4 和 IPv6 实现 ND 功能之间的更多差异。

IPv6 ND 通用操作概述

正如我刚才提到的,ND 协议的名称实际上并不能真正体现其价值。该协议不仅促进了邻近设备的发现,还涉及大量与本地网络连接、数据报路由和配置相关的功能。在 IPv6 环境中,无论是常规主机还是路由器,都依赖于 ND 协议来促进对正确互联网操作至关重要的信息交换。

ND 协议与 ICMP 有许多相似之处。其中之一是,像 ICMP 一样,ND 是一种 消息 协议。它不实现单一特定的功能,而是通过消息交换执行一系列活动。这意味着我无法通过具体描述 ND 做了什么来解释 ND 的操作,而必须通过 ND 提供的消息列表及其具体使用方式来定义其操作。

互联网上的任何本地网络都将包含常规主机和路由器,术语 邻居 可以指代任一。当然,主机和路由器在网络中扮演不同的角色,因此 ND 在每个网络中都非常不同。ND 标准描述了协议执行的九个具体功能。为了更好地理解这些功能及其相互关系,我们可以根据通信类型和涉及的设备类型将它们分为三个功能组,如图 36-1 所示。

邻居发现(ND)协议功能组和功能

图 36-1. 邻居发现(ND)协议功能组和功能

ND 中的主要功能分为两组:处理路由器发现和处理主机间通信的功能。第三组功能仅包括重定向功能。

主机-路由器发现功能

ND 主机-路由器发现功能是指促进本地路由器发现以及路由器和主机之间信息交换的功能。这包括以下四个具体功能:

路由器发现(RD) RD 是该组的核心功能。它是主机在其本地网络上定位路由器的方法。

前缀发现 与 RD 过程密切相关的是前缀发现。回想一下,术语 前缀 指的是 IP 地址的网络标识符部分。主机使用此功能来确定它们所在的网络,这反过来又告诉他们如何区分本地和远程目的地,以及是否尝试直接或间接交付数据报。

参数发现 也与 RD 密切相关,这是主机学习有关本地网络和/或路由器的重要参数的方法,例如本地链路的最大传输单元(MTU)。

地址自动配置 IPv6 中的主机被设计成能够自动配置自己,但这需要由路由器提供的信息。

主机-主机通信功能

另一个主要的功能组与信息确定和节点之间的直接通信有关,通常涉及主机。其中一些功能可以在主机和路由器之间执行,但这个组并不专门与 RD 相关。主机-主机通信功能包括以下内容:

地址解析 设备通过该设备的第 3 层(IP)地址确定本地网络上另一个设备的第 2 层地址的过程。这是 IPv4 中 ARP 执行的任务。

下一跳确定 查看 IP 数据报的目的地址并确定它应该发送到哪里的方法。

邻居不可达性检测 确定邻居设备是否可以直接联系的过程。

重复地址检测 确定设备希望使用的地址是否已经在网络上存在。

重定向功能

最后一个功能组只包含一个功能:重定向。这是一种路由器通知主机使用更好的下一跳节点来路由特定目的地的技术。

小贴士

关键概念 ND 包含九个独立的功能,其中许多相互关联。它们被组织成三个功能组:主机-路由器发现功能、主机-主机通信功能和重定向功能

功能之间的关系

将 ND 的整体功能划分为三个组中的九个任务在一定程度上是任意的,但为理解协议的功能提供了一个良好的参考框架。不同组中的某些功能是相关的;下一跳确定使用参数发现获得的信息。重定向功能也是路由器-主机通信的一种形式,但与 RD 不同。

ND 使用的 ICMPv6 消息

正如 ND 在操作上与 ICMP 相似,这两个协议在另一个方面也有关系:它们执行消息的方式。ND 实际上使用 ICMPv6 消息来实现其功能。ND 标准中描述了五种消息类型:

路由器通告消息 路由器定期发送,告知主机它们的存在,并向它们提供重要的前缀和参数信息。

路由器请求消息 由主机发送,请求任何本地路由器发送路由器通告消息,这样它们就不必等待下一个常规通告消息。

邻居通告消息 由主机发送,以表明主机存在并提供有关该主机的信息。

邻居请求消息 发送到验证另一个主机存在并请求它传输邻居通告消息。

重定向消息 由路由器发送,告知主机一种更好的路由数据到特定目的地的方案。

我们将在本章后面讨论这些消息类型的使用方法。参见第三十五章,了解 ND 使用的这五种 ICMPv6 消息类型的结构。

IPv6 ND 功能与等效 IPv4 功能的比较

IPv6 ND 协议的独特之处在于它是作为 IPv6 核心部分创建的唯一真正新的协议;没有 ND 的先前版本。当然,ND 提供给 IPv6 的大多数服务在 IPv4 中也是必需的。它们只是被提供在一系列相当多样化的协议和标准中,而 ND 协议将这些标准化、集成并改进。

这意味着虽然 ND 是新的,但它所做的工作与 IPv4 中其他几个协议执行的任务相当。具体来说,ND 的大部分功能对应于以下 IPv4 中的标准、特性和消息类型集:

ICMPv4 路由发现 ND 中与识别和从路由器获取信息相关的许多功能都是基于 RFC 1256 中定义的 ICMPv4 路由器通告和路由器请求消息的使用。

地址解析协议 ND 提供了增强的地址解析功能,这与 IPv4 中 ARP 提供的功能类似。

ICMPv4 重定向 ND 的重定向功能和重定向消息基于 IPv4 和 ICMPv4 中定义的类似功能。

ND 还有其他一些方面与 IPv4 中的工作方式只有一定程度的关联。与这些 IPv4 功能相比,也有一些改进或新功能。其中一些是由于 IPv6 本身与 IPv4 相比的操作方式的不同。例如,ND 中的前缀发现与 ICMPv4 中的地址掩码请求和地址掩码回复消息有关。

总体而言,ND 与 IPv4 中完成其工作的方式相比,有显著的改进。像 IPv6 本身一样,ND 通常更适合现代网络的需求,而不是较老的协议。与 IPv4 中完成其工作的方式相比,ND 在以下方面做出了一些更重要且具体的改进:

路由发现的形式化 在 IPv4 中,RD 和请求的过程可以说是事后才考虑的。ND 形式化了这个过程,并将其作为 TCP/IP 协议套件核心的一部分。

地址解析的形式化 以类似的方式,ND 在地址解析方面以更优越的方式处理,它位于第 3 层,与 IP 紧密相连,就像 ICMP 一样。不再需要像 ARP 这样的模糊分层协议,其实现很大程度上依赖于底层物理和数据链路层。

安全执行功能 ND 在网络层运行,因此可以利用 IPsec 的认证和加密功能来执行地址解析和 RD 等任务。

自动配置 与 IPv6 内建的功能结合使用,ND 允许许多设备自动配置自己,无需像动态主机配置协议(DHCP)服务器这样的东西(尽管 DHCPv6 也存在)。

动态路由器选择 设备使用 ND 来检测邻居是否可达。如果一个设备正在使用一个不再可达的路由器,它将检测到这一点,并自动切换到另一个路由器。

基于多播的地址解析 地址解析使用特殊的组播地址而不是广播,从而在需要发送解析消息时减少对“无辜旁观者”不必要的干扰。

更好的重定向 生成和使用重定向消息的方法已经得到了改进。

IPv6 ND 主机-路由器发现功能

将单个网络连接在一起创建互连网络。负责这种网络连接的设备是路由器,它们将数据从一个网络发送到下一个网络。主机必须依赖路由器将传输转发到本地网络以外的所有设备。因此,在主机能够正确使用互连网络之前,它需要找到一个本地路由器,并了解关于路由器和网络本身的重要信息。启用这种信息交换是 IPv6 ND 协议最重要的任务之一。

在本地网络上描述主机和路由器之间大部分 ND 通信的一般术语是发现。正如我在本章前面提到的,这个术语不仅包括路由器的发现,还包括重要参数的通信。大部分这种通信都是从路由器流向主机的,因为路由器控制每个网络的使用方式。它们向主机提供信息,以便主机知道如何最佳地操作。

与主机-路由器通信相关的各种发现功能都是由两种不同的 ICMPv6 消息类型的相同交换所促进的。路由通告消息仅由路由器发送,并包含关于路由器及其所在网络的信息。路由请求消息是可选的,当主机想要找到一个本地路由器时,会发送这些消息。这些消息的格式在第三十五章中进行了描述。

注意,路由通告(Router Advertisement)和路由请求(Router Solicitation)消息都可能包含发送消息的设备的可选二层地址。这用于更新地址解析缓存,以便在需要地址解析时节省时间。

使用这些消息的机制实际上并不复杂。要了解发现过程的整体工作方式,最好的方法是查看在 ND 中路由器和主机执行的具体任务。让我们首先看看路由器执行的功能。

路由器执行的主机-路由器发现功能

路由器负责以下功能:

常规通告 路由器在 ND 中的主要任务是定期传输路由器通告消息。每个路由器都维护一个计时器,控制广告发送的频率。在出现任何特殊情况下也会发送广告。例如,如果路由器的重要信息发生变化,如其在本地网络上的地址,则会发送消息。路由器通告消息包括关于路由器和网络的关键信息。有关路由器通告消息格式的完整描述,请参阅第三十五章。

参数维护 路由器负责维护有关本地网络的关键参数,以便它们可以在广告中发送。这些包括网络上的主机应使用的默认跳数限制字段值、网络的默认 MTU 值以及用于主机首次路由和自动配置的网络前缀等信息。有关这些的更多详细信息,请参阅第三十五章。

请求处理 路由器监听路由器请求消息。当接收到请求时,它们将立即向请求的主机发送路由器通告。

主机执行的主机-路由器发现功能

对于它们的部分,主机负责三个主要功能:

广告处理 主机监听其本地网络上的广告并进行处理。然后,它们根据这些消息中的信息设置适当的参数。这包括维护各种数据结构,例如前缀列表和路由器列表,这些结构会随着新广告信息的到来而定期更新。

生成请求 在某些条件下,主机将生成路由器请求并将其发送到本地网络。这个非常简单的消息只是请求任何听到它的本地路由器立即向请求该消息的设备发送路由器通告消息。这通常在主机首次开启时进行,这样它就不必等待下一次常规通告。

自动配置 当需要时,如果网络支持该功能,主机将使用来自本地路由器的信息来自动配置自己,包括 IP 地址和其他参数。

提示

关键概念 ND 的两个主要功能组之一是主机-路由器发现功能集。它们允许本地网络上的主机发现本地路由器的身份,并学习有关如何使用网络的重要参数。主机-路由器发现操作是通过使用 ICMPv6 路由器通告和路由器请求消息来执行的。

IPv6 ND 主机-主机通信功能

在 IP 中,数据报的交付可以分为两种方法:直接和间接。间接数据报交付需要路由器为主机提供帮助,这导致了前一小节中描述的主机-路由器发现功能。数据报的直接交付是在同一网络上的一个主机到另一个主机之间进行的。这不需要使用路由器,但需要其他涉及本地主机之间直接通信的 IPv6 ND 协议功能。这些包括下一个跳数确定、地址解析、邻居不可达检测和重复地址检测。

下一个跳数确定

任何主机在想要发送数据报时必须执行的第一项任务是下一个跳数确定。这是通过检查数据报中的目标地址,并决定是否需要直接或间接交付的过程。在早期的 IPv4 中,这是通过查看地址类别来完成的,后来则通过使用子网掩码。在 IPv6 中,从本地路由器获得的前缀信息与数据报的目标地址进行比较,以确定目标设备是本地还是远程。如果是本地,下一个跳数与目标地址相同;如果不是本地,则从设备的本地路由器列表中选择下一个跳数(这些路由器是通过手动配置或使用 ND 的主机-路由器发现功能确定的)。

为了提高效率,主机不会为每个数据报都执行下一个跳数确定。它们维护一个包含有关最近发送数据报的主机的下一个跳数信息的缓存。每次为特定目标执行下一个跳数确定时,该确定的信息将被输入到缓存中,以便在下一次向该设备发送数据报时使用。

地址解析

如果主机确定数据报的目标是本地,那么它将需要将数据报发送到该设备。实际的传输将使用实现本地网络的物理层和数据链路层技术来完成。这要求主机知道目标的主机 2 层地址,尽管它通常只有数据报中的第 3 层地址。从第 3 层地址到第 2 层地址的转换被称为地址解析问题。

在 IPv6 中,ND 协议负责地址解析。当一台主机想要获取数据报目的地的第 2 层地址时,它会发送一个包含目标设备 IP 地址的 ICMPv6 邻居请求消息,该地址是它希望确定其第 2 层地址的设备。该设备会以包含其第 2 层地址的邻居通告消息作为回应。为了避免使用广播干扰本地网络上的每个设备,请求是通过一个特殊的组播发送到目标设备的请求节点地址。有关 IPv6 中地址解析的更多信息,请参阅第第十三章和第二十五章。

注意,尽管这次讨论主要集中在主机之间的通信上,但在主机需要向本地路由器发送数据报且其目标缓存中没有该路由器的条目时,也可能进行地址解析。在地址解析的上下文中,目标设备只是一个邻居。它是一个主机还是路由器,只有在数据报发送和接收之后发生的事情中才有意义。换句话说,这些主机到主机的功能之所以这样命名,仅仅是因为它们不像上一节中的任务那样特定于主机和路由器之间的通信。

使用邻居通告消息更新邻居

设备不会像路由器发送路由通告消息那样定期发送邻居通告消息。实际上,这并不是必需的:邻居地址在一段时间内变化不大,随着设备之间发送数据报,解析会自然发生。此外,让网络上这么多设备定期发送通告将是浪费的。

然而,在某些条件下,主机可能会发送一个未经请求的邻居通告消息,在这种情况下,它认为有必要立即向本地网络上的其他邻居提供更新的信息。一个很好的例子是硬件故障——特别是网络接口卡的故障。当卡被更换时,设备的第 2 层(MAC)地址将改变。假设设备的 IP 层能够检测到这一点,它就可以发送一个未经请求的邻居通告消息,告诉其他设备使用新的 MAC 地址更新它们的解析缓存。

邻居不可达检测和邻居缓存

邻居请求和邻居通告消息通常与地址解析相关联,但它们也有其他用途。其中之一是邻居不可达性检测。每个设备都维护有关其每个邻居的信息,并根据网络条件的变化动态更新这些信息。这些信息保留在本地网络上的主机和路由器设备中。知道一个设备已变得不可达很重要,因为主机可以相应地调整其行为。在不可达主机的案例中,设备可能在尝试向不可达主机发送数据报之前等待一段时间,而不是在网络中重复尝试发送到主机。另一方面,不可达的路由器是设备需要找到新路由器来使用的信号,如果可用的话。

每个主机维护一个包含关于邻居设备信息的邻居缓存。每次主机从邻居接收数据报时,它知道邻居在那一刻是可达的,因此设备在缓存中为邻居创建一个条目以指示这一点。当然,从邻居接收数据报仅意味着邻居现在可达;自上次接收到数据报以来经过的时间越长,邻居不再可达的可能性就越大。

因此,邻居可达性信息必须被视为临时的。每次将一个邻居添加到缓存中作为可达时,都会启动一个计时器。当计时器到期时,该邻居的可达性信息被认为是过时的,不再假设该邻居可达。当从该邻居接收到新的数据报时,计时器重置,并将缓存再次设置为指示该设备可达。主机在过期之前应认为邻居可达的时间量是通过本地路由器使用路由器通告消息中的一个字段来通信的。

如果主机需要知道其可达性状态,它也可以动态地寻找邻居。它向设备发送邻居请求消息并等待响应的邻居通告消息。然后根据需要更新缓存。

地址冲突检测

我们一直在讨论的这两个消息的最后一个用途是用于地址冲突检测。当主机使用 IPv6 自动配置功能时,该过程的一个步骤是确保它试图使用的地址在网络中尚未存在。这是通过向设备希望使用的地址发送邻居请求消息来完成的。如果收到响应的邻居通告消息,则该地址已被使用。

小贴士

关键概念 ND 的两个主要功能组中的第二个是 主机-主机通信 功能集。定义了两种 ICMPv6 消息,即邻居通告和邻居请求。它们使得在本地网络中相邻主机之间进行各种类型的必要通信成为可能。这包括地址解析、确定数据报应发送的下一跳,以及评估邻居设备的可达性。

IPv6 ND 重定向功能

IPv6 ND 协议的最后一个主要责任是 重定向 功能。该功能由路由器用于通知主机,对于已发送到特定目的地的数据报,应使用更好的路由。可以争辩说,重定向功能应该是主机-路由器组的一部分,因为它代表了路由器与普通主机之间的一种通信形式。然而,它与其他发现功能略有不同,因此标准将其单独处理。

路由器负责检测本地网络中某个主机在首次路由决策上做出了低效的选择,并尝试进行纠正。例如,考虑一个网络上有两个路由器,R1 和 R2。主机 H1 想要将数据报发送到另一个网络上的设备 X2,该网络通过路由器 R2 连接到主机 H1 的网络。如果主机 H1 将数据报发送到路由器 R1,那么该路由器将知道它必须通过路由器 R2,并将其发送到那里。看到路由器 R2 也在本地网络中,因此路由器 R1 知道主机 H1 做了一个糟糕的初始路由决策:数据报应该直接发送到路由器 R2,而不是路由器 R1。如果这听起来非常类似于 ICMPv4 的重定向功能,那是因为它就是!

作为回应,路由器 R1 将创建一个特殊的 ICMPv6 重定向消息。此消息将告诉主机 H1,对于任何后续发送到设备 X2 的数据报,应首先发送到路由器 R2,而不是路由器 R1。也有可能路由器会确定其他情况下特定主机的第一跳应该不同,并使用重定向消息建议主机。这如图 图 36-2 所示。

只有路由器会发送重定向消息,而不是主机。主机负责寻找这些重定向消息并处理它们。接收到此类消息的主机将检查其中哪个目的地的数据报导致了重定向通知,以及路由器表示主机未来应为此目的地使用的新第一个跳。在这个例子中,主机 H1 将看到路由器 R1 表示,任何发往设备 X2 的进一步数据报都应该发送到路由器 R2 而不是路由器 R1。主机 H1 将相应地更新其设备 X2 的目标缓存。

使用 ICMPv6 重定向消息进行 ND 主机重定向。主机 H1 向路由器 R1 发送一个目的地为网络 N2 上设备的 IPv6 数据报。然而,路由器 R1 注意到路由器 R2 与源设备位于同一网络,并且是到达网络 N2 的更直接路径。它将数据报转发到路由器 R2,同时也向主机 H1 发送一个 ICMPv6 重定向消息,告知它下次使用路由器 R2。

图 36-2. 使用 ICMPv6 重定向消息进行 ND 主机重定向。主机 H1 向路由器 R1 发送一个目的地为网络 N2 上设备的 IPv6 数据报。然而,路由器 R1 注意到路由器 R2 与源设备位于同一网络,并且是到达网络 N2 的更直接路径。它将数据报转发到路由器 R2,同时也向主机 H1 发送一个 ICMPv6 重定向消息,告知它下次使用路由器 R2。

提示

关键概念 ND 重定向 功能允许路由器告诉主机在未来的传输中为特定目的地使用不同的路由器。它与 IPv4 重定向功能类似,并使用 ICMPv6 重定向消息实现。

当路由器发送重定向消息时,它还可能在消息中包含它要重定向到的目的地的数据链路层地址。如果需要,该地址由主机用于更新其地址解析缓存。这可能会在未来节省带宽,通过消除地址解析周期,当重定向主机尝试向新的重定向位置发送时。在这个例子中,路由器 R1 可能会在重定向消息中包含路由器 R2 的自身层 2 地址。这可以在主机 H1 下次有发往设备 X2 的数据报时使用。

IPv6 还支持对重定向消息进行身份验证,以防止未经授权的设备通过发送不适当的重定向消息造成混乱。主机可能被配置为丢弃未经适当身份验证的重定向消息。

第二部分-7. TCP/IP 路由协议(网关协议)

第三十七章

第三十八章")

第三十九章")

第四十章")

第四十一章

路由不仅仅是网络层发生的最重要的活动之一;它还是真正定义OSI 参考模型第 3 层的功能。路由是使小型本地网络能够连接起来形成可能巨大的互联网的功能,这些互联网可以跨越城市、国家,甚至整个地球。路由的工作由称为路由器的特殊设备完成,它们将数据报从网络转发到网络,允许任何设备向任何其他设备发送信息,即使源设备不知道目的地在哪里。

严格来说,可以争论一些路由协议不属于第 3 层。例如,许多这些协议在第四层使用传输控制协议(TCP)或用户数据报协议(UDP)发送消息。尽管如此,路由本质上是一种第 3 层活动,因此,传统上认为路由协议是第 3 层的一部分。

路由是一个复杂的话题。简而言之,这个过程是路由器根据数据报的目的地址来决定如何转发数据报,这个地址与路由器在特殊路由表中保存的信息进行比较。这些表包含了路由器所知的每个网络条目,告诉路由器数据报应该发送到哪个相邻路由器,以便最终到达目的地。

如你所想,路由表对于路由过程至关重要。这些表可以由网络管理员手动维护,但这既繁琐又耗时,而且不允许路由器处理互联网中的变化或问题。相反,大多数现代路由器都设计有功能,允许它们与其他路由器共享路由信息,从而使它们能够自动更新其路由表。这种信息交换是通过使用路由协议来完成的。

这一部分包含五章,描述了在 TCP/IP 中使用的最常见路由(或网关)协议。第一章提供了各种重要概念的概述,这些概念对于理解路由协议的工作方式至关重要,包括对内部和外部路由协议之间差异的解释。这为后续章节奠定了基础。

在第二和第三章中,我详细解释了 TCP/IP 中最常用的两种内部路由协议:路由信息协议(RIP)和开放最短路径优先(OSPF)协议。在第四章中,我描述了边界网关协议(BGP),这是今天互联网上使用的外部路由协议。第五章简要讨论了五种历史、专有或较少使用的路由协议。

您可能会注意到,这一部分的标题同时提到了路由协议网关协议。这两个术语可以互换使用,而且网关这个词出现在几个协议的名称中。这是由于在早期的 TCP/IP 标准中,网关一词的历史用法是指我们现在称之为路由器的设备。今天,网关一词通常不指路由器,而是指不同类型的网络互连设备,这可能会特别令人困惑。现在更倾向于使用路由协议这个术语,这也是我使用的术语。

就像所有与路由相关的主题一样,路由协议通常相当复杂。我在这里详细介绍了主要的路由协议,比大多数一般性的网络参考资料都要详细,但即便如此,我也只是触及了表面,尤其是像 OSPF 这样的更复杂的协议。如果您想了解更多细节,可以查看所引用的互联网标准(RFC)。此外,请注意,这里没有涵盖 IP 网络上使用的某些路由协议,例如 IS-IS(实际上是一个 OSI 协议,并不是 TCP/IP 的正式部分)。

第三十七章:概述关键路由协议概念

无标题图片

路由协议在互联网的路由整体过程中扮演着重要的角色。因此,在讨论路由的总体框架中理解它们是最容易的。在没有一些关于路由协议如何工作的背景信息的情况下,很难描述单个 TCP/IP 路由协议。因此,我认为简要地查看一些关键的路由协议概念是有价值的,这样您在理解下一章中描述的路由协议时就会更有运气。

在本章中,我将概述路由协议架构、协议类型、算法和度量标准。

路由协议架构

让我们从路由协议架构开始探讨。在这个语境中,架构一词指的是互联网的结构方式。一旦您有一些想要连接起来的网络和路由器,您有无数种方法可以做到这一点。您选择的架构基于路由器之间的连接方式,这会影响路由的执行方式和路由协议的操作。

核心架构

TCP/IP 和互联网是同时开发的,因此 TCP/IP 路由协议随着互联网本身的发展而发展。互联网的早期架构由少量包含关于互联网的全面信息的核心路由器组成。当互联网非常小的时候,向这个核心添加更多路由器可以扩展它。然而,每次核心扩展时,需要维护的路由信息量都会增加。

最终,核心变得太大,因此形成了一个两级层次结构,以允许进一步扩展。非核心路由器位于核心的边缘,只包含部分路由信息;它们依赖于核心路由器进行跨互联网的传输。在互联网的核心内部使用了名为网关到网关协议(GGP)的特殊路由协议,而在非核心路由器和核心路由器之间使用了另一个名为外部网关协议(EGP)的协议。非核心路由器有时是单个独立路由器,将单个网络连接到核心,或者它们可以是组织的一组路由器。

这种架构在一段时间内有效,但随着互联网的增长,它并没有很好地扩展。问题主要在于该架构只有一个级别:核心中的每个路由器都必须与其他每个路由器通信。即使外围路由器被保持在核心之外,核心中的流量量仍在不断增加。

自治系统(AS)架构

为了解决缩放问题,创建了一种新的架构,该架构从核心集中式概念转向更适合更大和不断增长的互联网架构。这种去中心化架构将互联网视为一组独立的组,每个组被称为自治系统(AS)。一个 AS 由一组由特定组织或管理实体控制的路由器和网络组成,该实体使用单一一致的政策进行内部路由。

该系统的优势在于,整个互联网上的路由发生在 AS 之间,而不是单个路由器之间。信息在 AS 中的每个路由器之间共享,而不是每个 AS 中的每个路由器。AS 内部的路由细节也隐藏在互联网的其他部分。这既为每个 AS 提供了灵活性,使其能够根据需要执行路由(因此得名自治),又为整体互联网提供了效率。每个 AS 都有自己的编号,这些编号在全球范围内管理,以确保它们在互联网(如互联网)中是唯一的。

小贴士

关键概念 大型现代 TCP/IP 互联网可以包含数千个路由器。为了更好地管理这种环境中的路由,路由器被分组到称为自治系统(ASes)的结构中,每个自治系统由特定组织或实体独立管理的一组路由器组成。

现代协议类型:内部和外部路由协议

AS 内部和 AS 之间的路由性质的不同可以从以下事实中看出:每种类型都使用以下不同的 TCP/IP 路由协议集:

内部路由协议 这些协议用于在 AS 内部的路由器之间交换路由信息。内部路由协议不用于 AS 之间。

外部路由协议 这些协议用于在 AS 之间交换路由信息。在某些情况下,它们也可能用于 AS 内部的路由器之间,但它们主要处理在 AS 之间交换信息。

小贴士

关键概念 内部路由协议用于在自治系统内部共享路由信息;由于系统是自主的,因此每个 AS 可能使用不同的内部路由协议。外部路由协议在 AS 之间传递路由数据;每个 AS 必须使用相同的协议来确保其能够通信。

由于 AS(自治系统)只是一组路由器的集合,你通过将一个 AS 中的路由器连接到另一个 AS 中的路由器来连接 AS。在架构上,一个 AS 由一组具有两种不同连接类型的路由器组成:

内部路由器 AS 中的某些路由器仅连接到同一 AS 中的其他路由器。这些运行内部路由协议。

边界路由器 AS 中的某些路由器既连接到 AS 内部的路由器,也连接到一个或多个其他 AS 中的路由器。这些设备负责在 AS 和互联网的其余部分之间传递流量。它们运行内部和外部路由协议。

由于其优势,AS 架构(例如,图 37-1

图 37-1. TCP/IP 自治系统(AS)路由架构 此图显示了由三个 AS 组成的简化互联网,每个 AS 都独立于其他 AS 进行管理。每个 AS 内的通信使用该 AS 管理员选择的内部路由协议(细线)。AS 之间的通信必须使用通用的外部路由协议(粗线)。内部路由器以浅色文字显示,边界路由器以黑色文字显示。

路由协议算法和度量

路由协议的另一个关键区别在于它们所使用的算法度量。算法指的是协议用于确定任意一对网络之间最佳路由以及路由器之间共享路由信息的方法。度量是一种衡量“成本”的指标,用于评估特定路由的效率。由于互联网可能非常复杂,因此协议的算法和度量非常重要,它们可能是决定一个协议优于另一个协议的决定性因素。

最常见的两种路由协议算法是距离矢量算法和链路状态算法。还有一些协议结合了这些方法或其他方法。

距离矢量(Bellman-Ford)路由协议算法

一种距离矢量路由算法,也称为以两位发明者命名的Bellman-Ford算法,是根据网络之间的距离来选择路由的。距离度量很简单——通常是它们之间的跳数或路由器的数量。

使用此类协议的路由器在表中维护有关所有已知网络的距离信息。它们会定期将此表发送给它们直接连接的每个路由器(它们的邻居对等方)。然后这些路由器更新它们的表并将这些表发送给它们的邻居。这导致距离信息在互联网中传播,因此最终每个路由器都能获得互联网上所有网络的距离信息。

距离矢量路由协议在选择最佳路由方面能力有限。它们在操作中也存在某些问题,必须通过添加特殊启发式和功能来解决。它们的主要优点是简单性和历史(它们已经使用了很长时间)。

链路状态(最短路径优先)路由协议算法

链路状态算法根据任何两个网络之间最短路径的动态评估来选择路由。因此,它也被称为最短路径优先方法。

使用这种方法,每个路由器都维护一张描述互联网当前拓扑结构的地图。这张地图通过测试互联网不同部分的可达性,以及与其他路由器交换链路状态信息来定期更新。最佳路由(或最短路径)的确定可以根据多种指标进行,这些指标表示通过特定路由发送数据报的真实成本。

链路状态算法比距离矢量算法更强大。它们可以动态适应互联网条件的变化,并且还允许根据比网络间跳数更现实的成本指标来选择路由。然而,它们设置和使用起来更复杂,比距离矢量算法消耗更多的计算机处理资源,并且还没有那么成熟。

混合路由协议算法

此外,还有一些混合协议结合了两种算法的特征,以及其他使用完全不同算法的协议。例如,边界网关协议(BGP)是一种路径矢量算法,它在某种程度上类似于距离矢量算法,但交换的路线信息更加详细。它包含了一些距离矢量和链路状态协议的属性,但不仅仅是两者的组合。

静态和动态路由协议

最后,你也可能偶尔看到将路由协议按类型分为静态动态。这个术语有些误导。

静态路由这个术语仅仅是指路由表是手动设置的,因此保持静态。相比之下,动态路由是使用路由协议动态更新路由表。因此,所有路由协议都是动态的。不存在静态路由协议(除非你将编辑路由表的网络管理员视为协议)。

第三十八章. 路由信息协议(RIP、RIP-2 和 RIPNG)

无标题图片

TCP/IP 内部路由协议中最受欢迎的是路由信息协议(RIP)。名称的简单性符合协议的简单性。在所有路由协议中,RIP 是最容易配置的之一,对资源的需求也最少。它的流行既归因于这种简单性,也归因于其悠久的历史。事实上,RIP 的支持已经集成到操作系统中,与 TCP/IP 本身存在的时间一样长。

RIP 有三个版本:RIP 版本 1 和 2 用于 IP 版本 4(IPv4),以及 RIPng 用于 IP 版本 6(IPv6)。这三个版本的基本操作大致相同,但它们之间也有一些明显的差异,尤其是在发送消息的格式方面。

RIP 是 TCP/IP 中最早使用的内部路由协议之一。20 多年后,它仍然被广泛使用。尽管 RIP 存在重要的局限性,但它至今在 TCP/IP 路由中仍然占有重要位置。RIP 有未来的证据可以在创建协议的 IPv6 版本 RIPng 中看到。

我将以对 RIP 特性的整体描述和它在一般意义上的工作原理来开启 RIP 的考试。我首先概述了该协议的历史,包括对其不同版本和定义它们的标准的简要讨论。我描述了 RIP 用来确定路由的方法以及用于评估路由成本的度量标准。我还描述了该协议的一般操作,包括消息类型和发送时间。然后,我描述了 RIP 最重要的局限性和问题,以及为解决基本 RIP 算法中的几个问题而添加到协议中的特殊功能。最后,我更详细地查看每个版本,展示每个版本使用的消息格式,并讨论版本特定的功能。

RIP 概述

多年来,RIP 一直是 TCP/IP 协议套件中最受欢迎的内部路由协议。该协议的历史以及它是如何获得显著地位的是一个相当有趣的故事。与 TCP/IP 套件中的许多其他重要协议不同,RIP 并不是首先通过 RFC 标准化过程正式开发的(参见第三章)。相反,它作为一个事实上的行业标准而演变,后来成为互联网标准。

RIP 的历史与另一个网络巨头——以太网——有着某种共同之处。就像那个强大的局域网技术一样,RIP 的根源可以追溯到那个计算先驱——施乐帕洛阿托研究中心(PARC)。在以太网被开发用于连接局域网的同时,PARC 创建了一个在以太网上运行的更高层协议,称为施乐帕洛阿托通用协议(PUP)。PUP 需要一个路由协议,因此施乐创建了一个名为网关信息协议(GWINFO)的协议。后来,该协议被更名为路由信息协议,并作为施乐网络系统(XNS)协议套件的一部分使用。

当加州大学伯克利分校的开发者将其用于 UNIX 操作系统的伯克利标准分布(BSD)时,RIP 进入了主流。RIP 首次出现在 1982 年的 BSD 版本 4.2 中,当时它被实现为 UNIX 程序routed(发音为"route-dee",不是"rout-ed"—其中的"d"代表"daemon",是 UNIX 中用于服务器进程的常见术语)。

BSD 曾经(并且现在仍然是)一个非常流行的操作系统,尤其是对于连接到早期互联网的机器。因此,RIP 被广泛部署,并成为了内部路由协议的行业标准。它被用于 TCP/IP 和其他协议套件。实际上,许多其他路由协议,如 AppleTalk 套件中的 RTP 协议,都是基于这种早期的 RIP 版本。

RIP 标准化

一段时间内,BSD 实现的 routed 实际上被认为是该协议的标准。然而,这并不是一个正式定义的标准,这意味着没有正式的定义来确切说明它是如何工作的。这导致了该协议在不同实现之间的细微差异。为了解决实现之间的潜在互操作性问题,互联网工程任务组(IETF)在 1988 年 6 月发布的互联网标准 RFC 1058,“路由信息协议”(Routing Information Protocol)中正式指定了 RIP。这个 RFC 直接基于 BSD 的 routed 程序。这个原始版本的 RIP 现在有时也被称为 RIP 版本 1 或 RIP-1,以区分后来的版本。

RIP 的流行很大程度上归因于它被包含在 BSD 中,而它之所以被包含在 BSD 中,是因为该协议相对简单。

RIP 操作概述、优势与局限性

RIP 使用距离矢量算法来确定路由,如第三十七章所述。每个路由器维护一个路由表,包含互联网中各种网络或主机的条目。每个条目包含两个主要信息:网络或主机的地址以及到它的距离,以跳数衡量,这仅仅是数据报必须通过的路由器的数量以到达其目的地。

定期地,互联网中的每个路由器都会在其连接的每个网络上发送一个特殊消息,其中包含其路由表,使用的是用户数据报协议(UDP)。其他路由器接收这些表,并使用它们来更新自己的表。这是通过将它们接收到的每个路由增加一个额外的跳数来完成的。例如,如果路由器 A 从路由器 B 收到指示,表示网络 N1 距离四跳,由于路由器 A 和路由器 B 是相邻的,因此从路由器 A 到网络 N1 的距离是五跳。在路由器更新其表后,它会将此信息发送到其本地网络上的其他路由器。随着时间的推移,所有网络的路由距离信息在整个互联网中传播。

RIP 在操作上简单明了,易于实现,对路由器处理能力的要求不高,这使得它在较小的自治系统 (AS) 中特别有吸引力。然而,由于协议的简单性,也出现了一些重要的限制。首先,跳数往往不是选择路由的最佳度量标准。还有许多与算法本身相关的问题。这些问题包括收敛缓慢(所有路由器就相同的路由信息达成一致时的延迟)以及处理网络链路故障的问题。RIP 包含了几个特殊功能来解决这些问题中的某些问题,但其他问题是协议的固有限制。例如,RIP 只支持目的地之间最多 15 跳,这使得它不适用于非常大的 AS,并且这一点无法更改。

在首次创建二十多年后,RIP 仍然是一种流行的内部路由协议。其限制导致许多互联网专家希望该协议最终会被技术上更优越的新协议,如开放式最短路径优先 (OSPF) 所取代。有些人甚至讽刺地建议,也许 RIP R. I. P. 会是最好的。然而,一旦一个协议变得流行,就很难抵挡其势头,RIP 很可能在未来许多年里继续被使用。

小贴士

关键概念 路由信息协议 (RIP) 是最古老且最受欢迎的内部路由协议之一。每个路由器使用距离矢量算法来维护一个表,该表指示如何到达 AS 中的各种网络以及到达该网络的跳数。RIP 流行是因为它已经建立并且简单,但它有许多重要的限制。

RIP 版本 2 (RIP-2) 和 RIPng for IPv6 的开发

由于该协议是在 20 世纪 80 年代初期开发的,当时 TCP/IP 还处于初级阶段,RIP 出现了一些其他问题。随着时间的推移,随着 TCP/IP 协议的使用发生变化,RIP 变得过时。作为回应,在 20 世纪 90 年代初期创建了 RIP 版本 2RIP-2

RIP-2 为 RIP 定义了新的消息格式,并包括许多新特性,包括对无类别寻址、身份验证以及使用多播而非广播的支持,这些特性提高了网络性能。它首次在 1993 年 1 月发布的 RFC 1388,“RIP 版本 2 带有附加信息”中被定义。该 RFC 在 RFC 1723 中进行了修订,并在 1998 年 11 月发布的 RFC 2453,“RIP 版本 2”中最终确定。

为了确保 RIP 能够与 TCP/IP 在未来一起工作,有必要定义一个与 IPv6 兼容的版本。1997 年,发布了 RFC 2080,标题为“RIPng for IPv6”。ng 代表 下一代;你可能会记得 IPv6 也被称为 IPng

RIPng不仅仅是一个新的 RIP 版本,就像 RIP-2 一样,但它被定义为一个新的独立协议。然而,它却紧密基于原始的 RIP 和 RIP-2 标准。由于 IPv4 和 IPv6 之间的变化,需要一个独立的协议(而不是原始协议的修订),尽管 RIP 和 RIPng 以相同的基本方式工作。RIPng 有时也被称为RIPv6

小贴士

关键概念 原始版本的 RIP 功能最少,现在被称为RIP-1RIP-2是为了添加对无类别寻址和其他功能的支持而创建的。RIPng是为与 IPv6 兼容而创建的版本。

RIP 路由确定算法和度量

正如我在上一章提到的,任何路由协议的一个定义特征就是它用于确定路由的算法。RIP 属于使用距离矢量或贝尔曼-福特路由算法的协议类别。为了帮助您理解 RIP 如何确定路由,本节将介绍 RIP 算法的具体实现并提供一个示例。

注意,这里提供的描述是 RIP 使用的基算法。这个算法在特定情况下会进行一些修改,以解决由于算法工作方式而产生的某些问题。在本章的后面部分,我们将探讨这些问题以及 RIP 包含的用于解决这些问题的特殊功能。

RIP 路由信息与路由距离度量

RIP 的任务,就像任何路由协议一样,是提供一个机制来交换路由信息,以便路由器可以保持它们的路由表是最新的。RIP 互联网中的每个路由器都在其路由表中跟踪互联网中的所有网络(以及可能个别的主机)。对于每个网络或主机,设备包括各种信息,其中以下信息是最重要的:

  • 网络或主机的地址

  • 从该路由器到网络或主机的距离

  • 路由的第一个跳:数据报必须首先发送到的设备,以便最终到达网络或主机

理论上,距离度量可以是任何成本评估,但在 RIP 中,距离是以跳数来衡量的。您可能已经知道,在 TCP/IP 术语中,数据报通过路由器时进行一次。因此,RIP 中路由器与网络之间的距离衡量的是数据报必须通过多少个路由器才能到达网络。如果一个路由器直接连接到网络,那么距离是 1 跳。如果它通过一个路由器,距离是 2 跳,依此类推。在 RIP 中,任何网络或主机的最大跳数限制为 15 跳。值 16 被定义为无穷大,所以其中包含 16 的条目意味着“此网络或主机不可达。”

RIP 路由确定算法

定期地,每个运行 RIP 的路由器都会发送其路由表条目,以向其他路由器提供有关它知道如何到达的网络和主机的信息。与发送此信息的同一网络上的任何路由器都能够根据接收到的信息更新自己的表。

任何从同一网络上的另一个路由器收到消息,表明它可以以 N 的成本到达网络 X 的路由器都知道,通过向它收到消息的路由器发送,它可以以 N+1 的成本到达网络 X。

RIP 路由确定和信息传播

让我们通过一个具体的例子来帮助你理解路由是如何确定的,以及如何使用 RIP 传播路由信息。考虑一个相对简单的互联网,包含四个单独的网络,如下所示连接:

  • 路由器 RA 将网络 N1 连接到网络 N2。

  • 路由器 RB 和路由器 RC 将网络 N2 连接到网络 N3。

  • 路由器 RD 将网络 N3 连接到网络 N4。

此示例 AS 在 图 38-1 中说明。

示例 RIP AS 这是一个包含四个物理网络和四个路由器的简单 AS 的示例。

图 38-1. 示例 RIP AS 这是一个包含四个物理网络和四个路由器的简单 AS 的示例。

现在假设我们刚刚开启了路由器 RA。它看到它直接连接到网络 N1 和网络 N2,因此在其路由表中将有一个条目,表明它可以以 1 的成本到达网络 N1,我们可以将其表示为 {N1,1}。关于网络 N1 的信息将通过以下步骤(如图 38-2 所示)在互联网中传播(这些步骤在 图 38-2

图 38-2。使用 RIP 传播网络路由信息。此复合图说明了从路由器 RA 传播关于网络 N1 路由信息的五个步骤。在第 1 步,信息从路由器 RA 发送到其连接的两个网络。在第 2 步,它到达路由器 RB 和 RC,然后它们知道它们可以通过路由器 RA 以额外跳数 1 到达网络 N1。在第 3 步,这两个路由器将此信息发送到它们的网络,在第 4 步,它到达路由器 RD。在第 5 步,路由器 RD 发送出信息,但没有其他路由器在附近接收它。

这种网络路由信息的传播是定期发生的,也发生在网络结构发生变化(由于地形的有意变化或链路或路由器的故障)时。当这种情况发生时,更改信息将通过互联网传播,以便最终更新所有路由器。例如,假设从路由器 RC 到网络 N1 添加了一个连接。如果路由器 RD 之前有{N1,RB,3}条目,它最终会将其更改为{N1,RC,2},因为它现在可以通过路由器 RC 更快地到达网络 N1。

默认路由

在某些情况下,对于大型互联网中的每个网络或主机来说,使用自己的路由条目进行完全指定可能不方便。那么,为网络指定一个默认路由,以便在它们没有信息的情况下访问主机或网络,可能是有益的。最常见的例子是当一个自治系统(AS)通过单个路由器连接到公共互联网时。除了那个路由器之外,本地网络的其他部分不需要知道如何访问互联网。

在 RIP 中,默认路由的信息是通过打算处理此类流量的路由器发送关于一个地址为 0.0.0.0 的“虚拟”网络的信息来传递的。当在互联网上使用 RIP 消息传播路由信息时,这被视为一个常规网络,但其他设备识别这个特殊地址并理解它意味着默认路由。

悼念通用操作、消息和定时器

RIP 是一种交换路由信息的协议,因此其操作最好用用于交换这些信息的消息以及发送消息的规则来描述。每个路由器中的 RIP 软件在响应某些事件以及由计时器触发的触发器时,都会发送消息并采取其他行动。计时器还用于确定当路由信息未更新时应该丢弃路由信息的时间。

RIP 消息和基本消息类型

在互联网中路由器上的 RIP 软件元素之间的通信是通过使用 RIP 消息 完成的。这些消息使用 UDP 发送,UDP 端口号 520 保留给 RIP-1 和 RIP-2,521 保留给 RIPng。因此,尽管 RIP 被视为与其他路由协议一样属于第 3 层,但在发送消息方面它更像是一个应用程序。消息的确切格式取决于版本,本章后面将详细描述所有三种格式(RIP、RIP-2 和 RIPng)。RIP 消息可以发送到特定设备,也可以发送给多个设备接收。如果指向一个设备,它们是单播发送;否则,它们在 RIP 中是广播,在 RIP-2 和 RIPng 中是组播。

对于 RIP 的所有三个版本,只有两种基本消息类型:

RIP 请求 路由器发送给另一个路由器的消息,要求它发送其路由表的全部或部分。

RIP 响应 包含路由器路由表全部或部分的消息。请注意,尽管名称如此,此消息并非仅作为对 RIP 请求消息的响应发送,正如您将看到的。

注意

原始的 RIP 还定义了几种其他消息类型:Traceon、Traceoff 和为 Sun Microsystems 保留的特殊消息类型。这些已经过时,不再使用。它们已被从 RIP-2 和 RIPng 标准中删除

RIP 更新消息和 30 秒计时器

当路由器需要立即提供路由信息时,会在特殊情况下发送 RIP 请求消息。最常见的例子是当路由器首次开机时。初始化后,路由器通常会在其连接的网络中发送一个 RIP 请求消息,以请求从任何相邻路由器获取的最新路由信息。RIP 请求消息也可以用于诊断目的。

接收到 RIP 请求消息的路由器将处理该消息,并发送一个 RIP 响应消息,其中包含其路由表的全部或仅请求的消息条目,根据情况而定。然而,在正常情况下,路由器通常不会发送特定的 RIP 请求消息来请求路由信息。相反,每个 RIP 路由器都有一个特殊的计时器,每 30 秒触发一次。(在 RIP 标准中,此计时器没有特定的名称;它只是 30 秒的计时器。)

每当计时器到期时,都会发出一个包含路由器整个路由表的 RIP 响应消息的无请求(未请求)广播或多播。然后重置计时器,30 秒后再次启动,导致发送另一个常规的 RIP 响应消息。这个过程确保路由信息定期在互联网上发送,因此路由器始终能够了解路由信息。

小贴士

关键概念 RIP 使用两种基本消息类型:RIP 请求和 RIP 响应。两者都使用用户数据报协议(UDP)发送。尽管名为 RIP 响应消息,但它们既用于常规周期性路由表更新,也用于响应 RIP 请求消息。请求仅在特殊情况下发送,例如当路由器首次加入网络时。

防止过时信息:超时计时器

当路由器接收到路由信息并将其输入其路由表时,该信息不能无限期地被认为是有效的。在“RIP 路由确定和信息传播”部分前面给出的示例中,假设在路由器 RB 通过路由器 RA 安装到网络 N1 的路由后,路由器 RA 和网络 N2 之间的链路失败。一旦发生这种情况,网络 N1 就无法从路由器 RB 访问,但路由器 RB 有一个指示它可以访问网络 N1 的路由。

为了防止这个问题,路由仅在路由表中保留有限的时间。每当在路由表中安装路由时,就会启动一个特殊的超时计时器。每当路由器收到包含该路由信息的另一个 RIP 响应消息时,该路由被认为是刷新的,并且其超时计时器被重置。只要路由继续刷新,计时器就不会到期。

然而,如果包含该路由的 RIP 响应消息停止到达,计时器最终会到期。当发生这种情况时,通过将路由的距离设置为 16(你可能记得这是 RIP 无穷大,表示不可达的网络)来标记路由为删除。超时计时器的默认值通常是 180 秒。这允许在路由器得出路由不可达的结论之前,错过几个路由的周期性更新。

移除过时信息:垃圾收集计时器

当一个路由被标记为删除时,也会启动一个新的垃圾收集计时器。“垃圾收集”是计算机行业术语,指查找已删除或无效信息并将其清理的任务。因此,这是一个在从表中实际删除新无效路由之前计算秒数的计时器。此计时器的默认值为 120 秒。

使用这种两阶段删除方法的原因是给声明了不再可达的路由的路由器一个机会,让它将此信息传播给其他路由器。在垃圾收集计时器到期之前,该路由器将包括该路由,其不可达度量值为 16 跳,在其自己的 RIP 响应消息中,以便将该路由的问题传达给其他路由器。当计时器到期时,该路由被删除。如果在垃圾收集期间收到该路由的新 RIP 响应消息,则删除过程被中止。在这种情况下,垃圾收集计时器被清除,该路由再次标记为有效,并启动一个新的超时计时器。

触发更新

除了已经描述的两种情况下发送 RIP 响应——回复 RIP 请求消息和在 30 秒计时器到期时——当路由发生变化时,也会发送 RIP 响应消息。

这个动作,对基本 RIP 操作的一种增强,称为触发更新,旨在确保路由变化的信息尽可能快地在互联网中传播。这将有助于减少 RIP 中的缓慢汇聚问题。例如,在路由超时和垃圾收集计时器启动的情况下,会立即发送关于现在无效路由的触发更新。这将在本章后面的“RIP 解决 RIP 算法问题的特殊功能”部分中更详细地描述。

RIP 问题及其解决方案

RIP 的简单性经常被列为它受欢迎的主要原因。简单性大多数时候都是好的,但在很多情况下,简单性的不幸代价是问题会出现,通常是在不寻常的情况或特殊情况下,RIP 也是如此。直接的距离矢量算法和操作机制在大多数情况下工作得很好,但它们有一些重要的弱点。我们需要检查这些问题,以了解 RIP 的限制以及为解决这些问题而添加到协议中的一些复杂性。

RIP 算法的问题

我们在 RIP 中遇到严重问题的最重要领域是本节前面描述的基本距离矢量算法的基本功能以及用于实现它的消息的使用方式,如以下各节所述。

汇聚缓慢

距离矢量算法被设计成所有路由器定期共享它们的所有路由信息。随着时间的推移,所有路由器最终都会拥有关于网络位置和到达它们最佳路由的相同信息。这被称为汇聚。不幸的是,基本的 RIP 算法在实现汇聚方面相当慢。所有路由器获取相同信息需要很长时间,特别是拓扑变化信息传播需要很长时间。

考虑两个由 15 个路由器分隔的网络的最坏情况。由于路由器通常每 30 秒才发送一次 RIP 响应消息,因此这对网络中一个网络的变化可能要过好几分钟才会被另一个网络最近的路由器看到——在网络术语中这是一个漫长的等待。

当涉及到路由故障的传播时,收敛缓慢的问题更为明显。路由故障的检测仅通过 180 秒超时计时器的到期来完成,这导致在收敛甚至开始之前还要额外增加三分钟的延迟。

路由环路

当路由器 A 有一个条目指示它将网络 1 的数据报发送到路由器 B,而路由器 B 有一个条目表示网络 1 的数据报应该发送到路由器 A 时,就会发生路由环路。更大的环路也可能存在:路由器 A 指示发送到 B,B 指示发送到 C,C 又指示发送到 A。在正常情况下,这些环路不应该发生,但在特殊情况下它们可能会发生。

RIP 没有包括任何特定的机制来检测或防止路由环路。它所能做的最好的事情就是试图避免它们。

无限计数

收敛缓慢的特殊情况可能导致路由环路情况,其中一个路由器向另一个路由器传递错误信息,该路由器又向另一个路由器发送更多错误信息,如此循环。这种情况有时被描述为协议不稳定。这个问题被称为无限计数,原因你很快就会看到。

要理解这是如何发生的,让我们修改“RIP 路由确定和信息传播”部分中前面提到的示例,如图图 38-3

图 38-3. RIP 计数到无穷大问题 这个复合图展示了之前在图 38-1 中提到的 AS 的一部分。顶部面板(1)显示了网络的正常状态,其中路由器 RB 能够以 2 的成本通过路由器 RA 到达网络 N1。在面板 2 中,路由器 RA 和网络 N1 之间的链路中断。路由器 RA 将其到达网络 N1 的成本更改为 16(RIP 无穷大)。在面板 3 中,在路由器 RA 可以将此更新发送给路由器 RB 之前,它收到了来自路由器 RB 的常规 RIP 消息,表明可以通过 2 的成本到达网络 N1。然后,路由器 RA 被误导,认为它可以使用路由器 RB 作为到达网络 N1 的备用路由,尽管路由器 RB 的信息最初是从路由器 RA 那里来的。在面板 4 中,路由器 RA 随后发送了这条虚假信息,该信息在面板 5 中被路由器 RB 接收。然后,路由器 RB 将其成本增加到 4,在其下一个周期将发送此信息给路由器 RA,路由器 RA 的成本将增加到 5,依此类推。这个周期将持续下去,两个路由器都将“计数到无穷大”(成本为 16)。

现在假设路由器 RB 的常规 30 秒计时器在路由器 RA 的下次广播之前触发。路由器 RB 将发送其正常的路由表,其中包含一条到网络 N1 的路由,成本为 2。路由器 RA 会看到这一点,并说:“嘿,看,路由器 RB 有一条到网络 N1 的路由,成本为 2!这意味着我可以以 3 的成本到达那里,这肯定比我目前的 16 成本低。让我们使用它!”因此,路由器 RA 安装了这条路由并取消了其超时计时器。当然,这是虚假信息——路由器 RA 没有意识到路由器 RB 能够到达网络 N1 的声明是基于来自路由器 RA 自己的旧信息!

从那里开始,情况变得更糟。当路由器 RA 的常规路由表更新时间到来时,它将广播一条到网络 N1 的路由,成本为 3。现在路由器 RB 会看到这一点,并说:“嗯,我的到网络 N1 的路由是通过路由器 RA 的。路由器 RA 之前说它的成本是 1;但现在它说成本是 3。这意味着我必须将我的成本改为 4。”

路由器 RB 稍后会发送回路由器 RA,他们就这样来回发送,每次增加 2 的成本。这不会停止,直到无限大成本的 16 值被触及——因此得名“无限计数”。在这种情况下,两个路由器最终会同意网络 N1 不可达,但如您所见,这需要很长时间才能发生。

小无限

使用相对较小的无限大成本值限制了缓慢收敛问题。即使在计数到无限大的情况下,经过的总时间也是至少可以管理的。(想象一下,如果无限大被定义为比如说 1,000!)不幸的是,这种做法的缺点是限制了可以使用 RIP 的互联网的大小。

许多人对 RIP 中 15 个路由器的跨度限制感到犹豫,但说实话,我认为这不过是小题大做,好吧,如果不是无关紧要的话,那么就是无关紧要的。15 个值并不是你总共可以使用路由器的数量限制,而是任何两个网络之间路由器的数量限制。考虑到大多数互联网都是按层次结构设置的。即使你有一个相当复杂的四级层次结构,你也不会接近 15 个路由器的限制。实际上,你可以创建一个拥有数千个路由器的大型自治系统,而任何两个设备之间都不会超过 15 个路由器。因此,这只是一个针对非常大 AS 的限制。

另一方面,RIP 每小时需要多次发送其整个路由表,这使得它无论无限大=16 的问题如何,都可能是一个大型互联网的潜在较差选择。在一个拥有许多路由器的互联网中,RIP 产生的流量可能会变得过多。

小提示

关键概念 RIP 操作中存在的一个最重要问题是收敛速度慢,这描述了网络变化信息在路由器之间传播可能需要很长时间的事实。这个问题的一个具体实例是无限计数问题,其中过时的信息导致许多虚假的 RIP 消息在路由器之间关于不可达网络的交换。

公平地说,这些问题主要是针对距离矢量路由算法的,而不是针对 RIP 本身。其中一些问题通过在算法或 RIP 消息发送的规则下实施具体更改得到纠正,如下一节所述。根据 RFC 2453,实际上有一个提议将 RIP 的无限成本增加到 16 以上的一个数字,但这会导致与旧设备(将任何度量值为 16 或更高的路由视为不可达)的兼容性问题,因此被拒绝了。

RIP 度量的问题

除了对算法本身的这些担忧之外,RIP 还经常因其度量选择而受到批评。这里的首要问题是 RIP 使用跳数作为距离度量。简单来说,跳数是发送数据报文在两个网络之间成本的一个糟糕度量。我相信 RIP 中将跳数作为度量部分是由于对简单性的渴望(当跳数是所有路由器需要考虑的时,使协议工作变得容易)。但使用跳数也是 RIP 存在超过 20 年的部分原因。

几十年前,计算机速度慢,所以每次数据报通过路由器时,可能都会有一个显著的延迟。即使在那时,跳数也不是一个完美的度量,但我认为它比现在更符合数据报在互联网中传输所需的时间。

现代路由器非常快速,使得跳数成为衡量网络距离的一个有缺陷的方法。跳数的数量通常与实际在路由上传输数据所需的时间没有关联。为了举一个极端的例子,考虑两个通过 56K 调制解调器直接拨号电话网络连接连接的网络。假设它们还通过使用高速 DS-3 线路的三个路由器序列连接。RIP 会认为 56K 链路是一个更好的路由,因为它有更少的跳数,尽管它显然要慢得多。

另一个问题是没有支持 RIP 的动态(实时)度量。即使 RIP 使用比跳数更有意义的度量,算法也要求每个链路的度量应该是固定的。没有方法让 RIP 像 OSPF 这样的协议那样根据各种链路的实时数据计算最佳路由(见第三十九章)。

大多数这些问题都内置在 RIP 中,无法解决。有趣的是,一些 RIP 实现似乎允许管理员“调整”某些路由,以补偿跳数度量指标的局限性。例如,前面提到的 56K 链路两端的路由器可以被配置为将 56K 链路视为跳数为十而不是一。这将导致使用该链路的任何路由都比 DS-3 路径更昂贵。这是聪明的,但几乎不是一个优雅或通用的解决方案。

注意,除了我提到的相当长的问题列表之外,RIP 的第一个版本还有一些具体问题。其中一些更重要的问题包括不支持无类别域间路由(CIDR)、缺乏认证以及由于使用广播进行消息传递而导致的性能下降。这些问题大部分通过 RIP-2 的扩展得到了解决。

解决 RIP 算法问题的 RIP 特殊特性

RIP 的简单性是其最吸引人的特性,但正如你所看到的,这导致了它在操作上的一些问题。这些限制中的大多数都与用于确定路由的基本算法以及实现该算法的消息传递方法有关。为了使 RIP 成为一个有用的协议,需要解决这些问题,形式上是对我们在本节 earlier 探讨的基本 RIP 算法和操作方案的改变。

由于 RIP 过于简单而产生的问题的解决方案是添加复杂性,以特征的形式增加 RIP 操作方式的智能。在接下来的几节中,我们将探讨其中的四个:分割水平分割水平带毒反转触发更新保持状态

注意,虽然我把这些描述为“特性”,但至少其中一些是确保 RIP 正确功能所必需的。因此,它们通常被认为是 RIP 的标准部分,甚至在最早的 RIP 文档中就有描述。然而,有时当使用这些技术时,尤其是在组合使用时,可能会出现性能或稳定性问题。因此,不同的 RIP 实现可能会省略一些特性。例如,保持状态会减慢路由恢复,当使用其他特性如分割水平时可能就不需要了。像往常一样,必须小心确保所有路由器都使用相同的特性,否则可能会出现更大的问题。

此外,请参阅本章后面的 RIP-2 特定特性的即将到来的部分,以了解下一跳特性的描述,该特性有助于在 RIP 使用时减少收敛和路由问题。

分割水平

无限计数问题是基本 RIP 算法中最严重的问题之一。在前一个部分的例子中,问题的原因立即很明显:在 N1 网络失败并且路由器 RA 注意到它失败后,路由器 RB 通过向路由器 RA 发送到 N1 的路由广告来“欺骗”路由器 RA,让它认为它有一个到达 N1 的替代路径。

如果你仔细想想,在任何情况下,让路由器 RB 向路由器 RA 发送关于一个只能通过路由器 RA 访问的网络的路由广告,这实际上在任何情况下都没有意义。在路由失败的情况下,这会导致这个问题,这显然是一个很好的理由不这么做。但是即使路由是可操作的,路由器 RB 告诉路由器 RA 这个路由有什么意义呢?路由器 RA 已经有一个到网络的更短连接,因此它无论如何都不会将意图发送到网络 N1 的流量发送到路由器 RB。

显然,最好的解决方案是让路由器 RB 在其发送给路由器 RA 的任何 RIP 响应消息中不提及到网络 N1 的路由。我们可以通过向 RIP 操作添加一条新规则来概括这一点:当路由器在它连接的任何网络上发送 RIP 响应消息时,它省略了从该网络最初学习到的任何路由信息。这个功能被称为分割水平,因为路由器实际上分割了其对互联网的看法,在某些链路上发送的信息与在其他链路上发送的信息不同。

使用这个新规则,让我们考虑路由器 RB 的行为。它有一个连接到网络 N2 的接口,它与路由器 RA 共享。因此,当它在网络 N2 上发送时,它将不会包含从路由器 RA 那里最初获得的路由信息。这将防止你在前一个部分中看到的无限计数循环。同样,因为路由器 RD 在网络 N3 上,路由器 RB 在发送到网络 N3 时,不会发送从路由器 RD 那里获得的任何路由信息。

然而,需要注意的是,分割水平(split horizon)并不总是能解决无限计数问题,尤其是在多个路由器间接连接的情况下。一个经典的例子是三个路由器配置成三角形。在这种情况下,由于任何两个路由器之间传播的数据是双向的,可能会出现问题。在这种情况下,稍后描述的保持下降(hold down)功能可能会有所帮助。

分割水平与中毒反转

添加“中毒反转”(poisoned reverse)增强了基本的分割水平功能。在发送 RIP 响应消息时,不是从特定接口省略从该接口学习到的路由,而是包括这些路由,但将它们的度量设置为 RIP 无穷大,即 16。所以,在先前的例子中,路由器 RB 会在其发送到网络 N2 的传输中包含到网络 N1 的路由,但它会说到达网络 N1 的成本是 16,而不是其实际成本(即 2)。

“中毒反转”指的是我们正在中毒那些我们想要确保接口上的路由器不使用的路由。路由器 RA 将看到路由器 RB 通告网络 N1,但成本为 16,这作为对路由器 RA 的一个明确信息:“你绝对不可能通过路由器 RB 到达网络 N1。”这比常规的分割水平特性提供了更多的保险,因为如果路由器 RA 到网络 N1 的链路中断,路由器 RA 将确定它不能尝试通过路由器 RB 获取新的路由。图 38-4 展示了分割水平与中毒反转是如何工作的。

这种技术也在正常情况下(意味着没有像网络链路中断这样的问题)有效。在这种情况下,路由器 RA 将定期从路由器 RB 接收成本为 16 的更新,但路由器 RA 永远不会尝试通过路由器 RB 到达网络 N1,因为它直接连接到网络 N1(成本为 1)。

触发更新

在本章前面我们讨论的路由环路问题发生,是因为路由器 RB 向路由器 RA 通告了路由器 RA 的路由。这个问题还有一个重要的方面:当路由器 RA 发现连接到网络 N1 的链路失败后,它必须等待多达 30 秒,直到下一个预定传输时间才能通知其他路由器关于链路失败的情况。

为了使 RIP 工作良好,当发生重大事件时,我们希望立即通知互联网上的其他路由器。因此,应该向基本的 RIP 路由器操作中添加一条新规则:每当路由器更改其路由的度量值时,它必须(几乎)立即发送一个 RIP 响应消息,通知其直接相邻的路由器关于更改的情况。如果这些路由器看到这个更改,它们将更新它们的路由信息,然后它们反过来必须发送更新。因此,任何网络路由信息的变化都会导致整个互联网上发送级联更新,显著减少缓慢收敛问题。请注意,这包括由于超时定时器的到期而删除路由的情况,因为删除路由的第一步是将路由的度量值设置为 16,这会触发一个更新。

RIP 问题解决使用带毒回溯的分割视域 The 图表的上面板(1)显示了与图中的相同示例。在面板 2 中,与之前一样,RA 路由器与网络 N1 之间的链路已断开,正如 RB 路由器准备发送其常规更新。然而,分割视域带毒回溯功能意味着它在两个链路上发送不同的消息。在连接到 RA 路由器的网络上,它发送一个成本为 16 的路由通告。在面板 3 中,RA 路由器收到这个通告,它将丢弃这个通告,确保不会出现无限计数问题。在 RA 路由器的下一个周期,它将更新 RB 路由器,告诉它网络 N1 不再可达。

图 38-4. 使用带毒回溯的分割视域解决 RIP 问题 图表的上面板(1)显示了与图 38-3。在面板 2 中,与之前一样,RA 路由器与网络 N1 之间的链路已断开,正如 RB 路由器准备发送其常规更新。然而,分割视域带毒回溯功能意味着它在两个链路上发送不同的消息。在连接到 RA 路由器的网络上,它发送一个成本为 16 的路由通告。在面板 3 中,RA 路由器收到这个通告,它将丢弃这个通告,确保不会出现无限计数问题。在 RA 路由器的下一个周期,它将更新 RB 路由器,告诉它网络 N1 不再可达。](httpatomoreillycomsourcenostarchimages288035.png.jpg)

你可能已经注意到我说触发的更新是“几乎”立即发送的。事实上,在发送触发更新之前,路由等待一个随机的时长,从 1 到 5 秒。这样做是为了减少由许多路由器几乎同时发送更新消息而对互联网造成的负载。

按住

分隔水平尝试通过抑制关于失败路由的无效信息传输来解决计数到无限问题。为了额外的保险,我们可以实现一个功能,该功能在收到失败路由信息时改变接收路由信息处理方式。保持功能通过让每个路由器在首次收到关于不可达网络的信息时启动计时器来实现。在计时器到期之前,路由器将丢弃任何后续的路由消息,这些消息表明该路由实际上是可达的。典型的保持计时器运行时间为 60 或 120 秒。

这种技术的优点是,路由器不会因为收到关于路由可访问的虚假信息而困惑,因为它刚刚被告知该路由不再有效。它提供了一个时间段,让过时的信息从系统中清除,这在复杂的互联网中尤其有价值。将保持功能添加到分隔水平也可以帮助在仅分隔水平不足以防止计数到无限的情况下的情况,例如,当三个路由器以三角形的形式相互连接时,如前所述。

保持的主要缺点是它迫使路由器在路由修复后延迟响应。假设由于某种原因,路由仅关闭了五秒钟。当网络再次上线后,路由器将再次想要了解这一点。然而,保持计时器必须到期,路由器才会再次尝试使用该网络。这使得使用保持功能的互联网响应修正路由相对较慢,并且可能导致间歇性失败的网络的访问延迟。

小贴士

关键概念 四个特殊功能代表了 RIP 操作的变化,这些变化改善了或消除了基本协议操作中的问题。分隔水平分隔水平带毒反转防止路由器将其从最初学习路由的路由器发送无效的路由信息。触发更新通过立即传播更改后的路由信息来减少缓慢收敛问题。最后,保持功能可以在收到失败路由信息时提供鲁棒性。

RIP 版本特定的消息格式和功能

正如我之前提到的,RIP 已经广泛使用超过二十年了。在这段时间里,互联网和互联网技术已经发生了变化。为了跟上时代的步伐,RIP 也进行了演变,如今有三个不同的版本。这三个版本的基本操作相当相似,这在前面的章节中已经描述过。正如你所预期的,版本之间也有一些差异。其中之一是每个版本中 RIP 消息的格式,以及该格式中字段的含义和使用。

现在是时候查看 RIP 三个版本各自使用的消息格式,以及某些并非所有版本都有的特定功能了。我首先介绍原始的 RIP,现在也被称为RIP 版本 1。然后,我描述 RIP 的更新版本,称为RIP 版本 2RIP-2。最后,我讨论RIPng,有时也称为RIPv6;这是用于 IPv6 的 RIP 版本。(注意,这并不是原始 RIP 的新版本,而是一个基于早期 RIP 版本的新协议。)

RIP 版本 1(RIP-1)消息格式和功能

RIP 作为一个行业标准而发展起来,并通过其包含在伯克利标准分布的 UNIX(BSD UNIX)中而普及。RIP 的第一个版本(现在有时称为 RIP-1,以区分后续版本)最终在 RFC 1058 中标准化。作为该标准的一部分,定义了原始的 RIP-1 消息格式,当然这服务于RIP-1本身,也是后续版本格式的基础。

RIP-1 消息

如前几节中关于 RIP 操作的通用讨论所述,RIP 通过发送两种不同类型的 RIP 消息来交换路由信息:RIP 请求和 RIP 响应。这些消息作为常规 TCP/IP 消息通过 UDP 传输,UDP 使用保留的端口号 520。该端口号的使用如下:

  • RIP 请求消息发送到 UDP 目标端口 520。它们可能具有源端口 520 或可能使用一个临时端口号(有关临时端口号的解释,请参阅第四十三章)。

  • 作为对 RIP 请求的回复发送的 RIP 响应消息使用源端口 520 和与 RIP 请求使用的源端口相等的目标端口。

  • 无请求的 RIP 响应消息(定期发送,而不是响应请求)使用源端口和目标端口,这两个端口都设置为 520。

RIP-1 消息格式

RIP-1 的基本消息格式在表 38-1 中描述,并在图 38-5 中展示。

表 38-1. RIP-1 消息格式

字段名称 大小(字节) 描述
命令 1 命令类型:标识发送的 RIP 消息类型。值为 1 表示 RIP 请求,而 2 表示 RIP 响应。最初,还定义了三种其他值和命令:3 和 4 用于 Traceon 和 Traceoff 命令,5 为 Sun Microsystems 保留。这些已过时,不再使用。
版本 1 版本号:对于 RIP 版本 1 设置为 1。
必须为零 2 字段保留;值必须设置为全零。
RIP 条目 20 至 500,以 20 为增量 RIP 消息的主体由 1 至 25 组 RIP 条目组成。这些条目包含消息传达的实际路由信息。每个条目长 20 字节,并具有表 38-2 中显示的子字段。

表 38-2. RIP-1 RIP 条目

子字段名称 大小(字节) 描述
地址族标识符 2 这是一个用于标识条目中地址类型的字段的别称。路由器使用 IP 地址,该字段的值为 2。
必须为零 2 字段保留;值必须设置为全零。
IP 地址 4 路由器发送信息关于的路由地址。在 RIP 中,不对不同类型设备的地址进行区分,因此地址可以是网络、子网或单个主机。也可以发送全零的地址,这被解释为网络中其他设备用于到达没有指定路由条目的路由的默认路由。这通常用于允许网络访问互联网。
必须为零 4 字段保留;值必须设置为全零。
必须为零 4 字段保留;值必须设置为全零。(是的,连续两个都是。)
度量值 4 由 IP 地址字段中指示的网络的距离。1 到 15 的值表示到达网络的跳数,而 16 的值表示无穷大(不可达的目的地)。有关度量值的使用,请参阅本章前面关于 RIP 算法的一般讨论。

RIP-1 消息格式 The RIP-1 message format can contain up to 25 RIP entries. Here, RIP entry 1 is shown with each of its constituent subfields.

图 38-5. RIP-1 消息格式 RIP-1 消息格式可以包含多达 25 个 RIP 条目。在此,展示了 RIP 条目 1 及其所有构成子字段。

如果你像我一样,看到这个消息格式后首先想到的是:所有这些额外的空间是干什么的?我的意思是,我们有四个不同的保留字段(必须为零),甚至大多数其他字段都比所需的要大(一个 1 到 16 的度量值只需要 4 位,而不是 32 位)。如果不需要,命令类型和版本号也可以很容易地只占用 4 位,甚至更少。而且,既然我们只处理 IP 地址,为什么还要有一个 2 字节的字段来标识地址类型呢?

这种看似浪费的做法实际上是原始 RIP 设计通用性的产物。该协议旨在能够支持各种不同互连协议的路由,而不仅仅是互联网协议(IP)。记住,它最初甚至没有考虑到 IP。因此,地址族标识符被包括在内以指定地址类型,并且 RIP 条目被设计得足够大,可以处理大型地址。IP 只需要每个地址 4 个字节,所以一些空间没有被使用。

RIP-1 版本特定功能

由于 RIP-1 是协议的第一个版本,其特性构成了未来 RIP 版本的基础;它实际上并没有任何版本特定功能。RIP-1 所具有的是一些限制,例如不支持指定无类别地址以及没有认证手段。RIP-2 的创建是为了解决 RIP-1 的一些不足。正如你将在下一节中看到的那样,RIP-2 的功能充分利用了 RIP-1 格式中的“必须为零”字节!

小贴士

关键概念 RIP-1 是 RIP 的第一个版本,在操作和功能方面是最简单的。一个 RIP-1 消息的大部分由一组 RIP 条目组成,这些条目指定路由地址和到达该路由的跳数。

RIP 版本 2(RIP-2)消息格式和功能

原始的 RIP(RIP-1)存在许多问题和限制。随着 TCP/IP 协议套件的演变和变化,RIP-1 的问题由于变得有些过时而加剧。它无法处理新的 IP 功能。有些人认为,存在更新、更好的内部路由协议意味着最好是完全放弃 RIP,转而使用类似 OSPF 的协议。

然而,RIP 的吸引力从未在于其技术优势,而在于其简单性和在行业中的普遍性。到 20 世纪 90 年代初,RIP 已经在成千上万的网络中使用。对于那些喜欢 RIP 的人来说,迁移到一个新版本,该版本解决了 RIP-1 的一些不足,比转向一个完全不同的协议更有意义。为此,开发了一个新的协议版本,即 RIP-2。它最初于 1993 年在 RFC 1388 中发布。现在,它在 1998 年 11 月发布的 RFC 2453,“RIP 版本 2”中定义。

RIP-2 版本特定功能

RIP-2 对基本的 RIP 进行了非常小的改动。RIP-2 与 RIP-1 以相同的基本方式工作。实际上,RIP-2 中引入的新特性被描述为对基本协议的扩展,从而传达了它们是建立在常规 RIP-1 功能之上的这一事实。五个关键的 RIP-2 扩展如下:

无类别地址支持及子网掩码指定 当 RIP-1 开发时,IP 中的子网使用(如 RFC 950 中所述)尚未正式定义。仍然可以通过使用启发式方法来确定目的地是网络、子网还是主机来使用 RIP-1 与子网。然而,使用 RIP-1 消息无法明确指定地址的子网掩码。RIP-2 通过允许每个网络地址的路由条目中包含子网掩码来显式支持子网。它还提供了对可变长度子网掩码(VLSM;见第十八章)和 CIDR 的支持。

下一跳指定 在 RIP-2 中,每个 RIP 条目都包含一个空间,可以输入一个显式的 IP 地址作为该条目网络的数据报的下一跳路由器。这个特性可以通过消除发送到某些目的地的数据报的不必要额外跳数来帮助提高路由效率。这个字段的常见用途是当到达网络的最有效路由是通过不运行 RIP 的路由器时。这样的路由器不会交换 RIP 消息,因此通常不会被 RIP 路由器选为任何网络的下一跳。显式的下一跳字段允许路由器在这种情况下被选为下一跳。

认证 RIP-1 没有包含认证机制,这是一个问题,因为它可能允许恶意主机通过发送虚假的 RIP 消息来攻击互联网。RIP-2 提供了一个基本的认证方案,允许路由器在它接受来自该路由器的 RIP 消息之前确定该路由器的身份。

路由标记 每个 RIP-2 条目都包含一个路由标记字段,可以存储关于路由的附加信息。这些信息会随着路由的其他数据一起在互联网中传播,当 RIP 条目在互联网中发送时。这个字段的常见用途是在从不同的 AS 学习路由时,以便识别获取路由的 AS。

多播的使用 为了帮助减少网络负载,RIP-2 允许路由器配置为使用多播而不是广播来发送未经请求的 RIP 响应消息。这些数据报使用特殊的保留多播地址 224.0.0.9 发送。如果要让这正常工作,互联网上的所有路由器都必须使用多播。

正如你所见,许多这些扩展都需要在每个广告路由中包含更多信息。这就是 RIP-1 路由条目消息格式中所有额外空间派上用场的地方,你很快就会看到。

小贴士

关键概念 RIP-2 是 IPv4 中使用的最新版本的 RIP。它包括对原始 RIP-1 的许多改进,包括对子网掩码和无类别寻址的支持、显式下一跳指定、路由标记、身份验证和组播。为了兼容性,它使用与 RIP-1 相同的消息格式,将所需的新功能信息放入 RIP-1 消息格式的某些未使用字段中。

RIP-2 消息传递

RIP-2 消息的交换使用与 RIP-1 消息相同的基本机制。存在两种不同的消息类型:RIP 请求和 RIP 响应。它们使用 UDP 发送,UDP 使用保留端口号 520。此端口的用法语义与 RIP-1 相同。为了方便,我在此处重复描述:

  • RIP 请求消息发送到 UDP 目的端口 520。它们可能具有源端口 520 或可能使用一个临时端口号。

  • 响应 RIP 请求消息的 RIP 响应消息的源端口为 520,目的端口等于 RIP 请求消息使用的源端口。

  • 非请求的 RIP 响应消息(定期发送,而不是响应请求)的源端口和目的端口都设置为 520。

RIP-2 消息格式

RIP-2 的基本消息格式与 RIP-1 基本相同,版本字段设置为 2,以便清楚地识别该消息为 RIP-2。表 38-3 和图 38-6 说明了 RIP-2 的消息格式。真正的区别在于单个 RIP 条目,如表 38-4 所示。

表 38-3. RIP-2 消息格式

字段名称 大小(字节) 描述
命令 1 命令类型:标识发送的 RIP 消息类型。值为 1 表示 RIP 请求,而 2 表示 RIP 响应。
版本 1 版本号:设置为 2 表示 RIP 版本 2。
必须为零 2 字段保留;值必须设置为全零。
路由表条目(RTEs) 20 至 500,以 20 为增量 与 RIP-1 一样,RIP-2 消息的主体由 1 至 25 组路由信息组成。在 RIP-2 中,这些被标记为路由表条目,或 RTEs。每个 RTE 长度为 20 字节,并具有表 38-4 中显示的子字段(其他字段已汇总以节省空间)。

表 38-4. RIP-2 路由表条目(RTEs)

子字段名称 大小(字节) 描述
地址族标识符 2 与 RIP-1 相同,值为 2 用于标识 IP 地址。
路由标记 2 需要与此路由一起携带的附加信息。
IP 地址 4 与 RIP-1 相同:路由器发送信息关于的路由地址。在 RIP 中不区分不同类型设备的地址,因此地址可以是网络、子网或单个主机。也可以发送全零地址,这被解释为默认路由,如在 RIP-1 中。
子网掩码 4 与此地址关联的子网掩码。
下一个跃点 4 作为此条目中广告的网络的下一个跃点的设备地址。
距离度量 4 由 IP 地址指示的网络距离,如在 RIP-1 中。值 1 到 15 表示到达网络所需的跳数(如本章前面关于 RIP 算法的讨论所述),而值为 16 表示无穷大(不可达的目的地)。

如您所见,未使用的字段允许在不改变 RIP 条目基本结构的情况下实现新的 RIP-2 功能。这允许 RIP-1 和 RIP-2 消息和设备在同一网络中共存。一个 RIP-2 设备可以处理 RIP-1 和 RIP-2 消息,并且会查看版本号以确定消息的版本。一个 RIP-1 设备应以相同的方式处理 RIP-2 和 RIP-1 消息,简单地忽略它不理解的多余的 RIP-2 字段。

注意

如果使用身份验证,其中一个 RTE 包含身份验证信息,因此将消息限制为 24 个“真实”RTE

RIP-2 消息格式 The RIP entries of RIP-1 are called Route Table Entries (RTEs) in RIP-2; the message format can contain up to 25. The format of RTE 1 is shown here with each of its subfields (the others are summarized to save space).

图 38-6. RIP-2 消息格式 RIP-1 中的 RIP 条目在 RIP-2 中称为路由表条目(RTEs);消息格式可以包含多达 25 个。这里显示了 RTE 1 的格式,以及它的各个子字段(其他字段为了节省空间进行了总结)。

RIPng(RIPv6)消息格式和功能

TCP/IP 的未来是 IPv6,这给 IP 带来了非常重要的变化,特别是在地址方面。由于 IPv6 地址与 IPv4 地址不同,与 IP 地址一起工作的所有内容都必须更改才能在 IPv6 下运行。这包括路由协议,它们交换地址信息。

为了确保 RIP 的未来,必须开发一个与 IPv6 兼容的新版本。这个新版本于 1997 年在 RFC 2080 中发布,名为RIPng for IPv6,其中ng代表下一代(IPv6 有时也称为IP next generation)。

由于显而易见的原因,RIPng 有时也被称为 RIPv6,它被设计成尽可能类似于当前版本的 IPv4 RIP,即 RIP-2。实际上,RFC 2080 将 RIPng 描述为对 RIP 进行最小更改,以便使其能够在 IPv6 上工作。尽管做出了这些努力,但无法将 RIPng 定义为仅是较老 RIP 的新版本,就像 RIP-2 一样。RIPng 是一种新的协议,这是由于 IPv4 和 IPv6 之间变化的重大意义所必需的——特别是 IPv6 中从 32 位到 128 位的地址变化,这需要新的消息格式。

RIPng 版本特定功能

尽管 RIPng 是一种新的协议,但仍然做出了特定的努力使其类似于其前辈。其基本操作几乎完全相同,它使用与本章前面看到的相同的整体算法和操作。与 RIP-2 相比,RIPng 也没有引入任何特定的新功能,除了在 IPv6 上实现 RIP 所必需的功能。

RIPng 保留了 RIP-2 中引入的大多数增强功能;一些按 RIP-2 中的方式实现,而其他则以修改后的形式出现。以下是 RIP-2 中的五个扩展如何在 RIPng 中实现的具体说明:

无类别地址支持和子网掩码指定 在 IPv6 中,所有地址都是无类别的,并使用地址和前缀长度指定,而不是子网掩码。因此,为每个条目提供了一个前缀长度字段,而不是子网掩码字段。

下一跳指定 该功能在 RIPng 中得到保留,但实现方式不同。由于 IPv6 地址的长度较大,如果在 RIPng 格式中包含下一跳字段,RTEs 的每个条目的大小几乎会翻倍。由于下一跳是一个可选功能,这将是一种浪费。相反,当需要下一跳时,它将在单独的路由条目中指定。

认证 RIPng 不包括自己的认证机制。假设如果需要认证和/或加密,它们将通过标准 IPsec 功能提供,这些功能在 IPv6 的 IP 层中定义。这比让像 RIPng 这样的单个协议执行认证更有效。

路由标记 该字段与 RIP-2 中的实现方式相同。

多播的使用 RIPng 使用多播进行传输,具体使用保留的 IPv6 多播地址 FF02::9。

RIPng 消息

RIPng 有两种基本的消息类型,即 RIP 请求和 RIP 响应,它们使用 UDP 进行交换,就像 RIP-1 和 RIP-2 一样。由于 RIPng 是一种新的协议,它不能使用与 RIP-1/RIP-2 相同的保留 UDP 端口号 520,该端口号用于 RIP-1/RIP-2。相反,RIPng 使用已知的端口号 521。该端口号的使用语义与 RIP-1 和 RIP-2 中使用的端口号 520 的语义相同。为了方便,这里再次列出规则:

  • RIP 请求消息发送到 UDP 目的端口 521。它们可能具有源端口 521 或可能使用一个临时端口号。

  • 响应 RIP 请求消息发送的 RIP 响应消息使用源端口 521,目的端口等于 RIP 请求消息使用的源端口。

  • 无请求的 RIP 响应消息(定期发送,而不是响应请求)的源端口和目的端口都设置为 521。

RIPng 消息格式

RIPng 的消息格式与 RIP-1 和 RIP-2 类似,除了 RTEs 的格式。它显示在表 38-5 中,并在图 38-7 中说明。

表 38-5. RIPng 消息格式

字段名称 大小(字节) 描述
Command 1 命令类型:标识发送的 RIPng 消息类型。值为 1 表示 RIPng 请求,而值为 2 表示 RIPng 响应。
版本 1 版本号:设置为 1(不是 6,因为这是新协议 RIPng 的第一个版本)。
必须为零 2 保留字段;值必须设置为全零。
路由表条目(RTEs) 可变 RIPng 消息的主体由一个可变数量的路由表条目(RTEs)组成,这些条目包含有关路由的信息。每个条目长度为 20 字节,并具有表 38-6 中显示的子字段。

表 38-6. RIPng RTEs

子字段名称 大小(字节) 描述
IPv6 前缀 16 包含在此 RTE 中的网络信息的 128 位 IPv6 地址。
Route Tag 2 与此路由一起携带的附加信息,如 RIP-2 中定义。
前缀长度 1 IPv6 地址中网络部分(其余为主机部分)的位数。这是在指定 IPv6 网络地址时通常出现在斜杠后面的数字。它类似于 IPv4 子网掩码。有关 IPv6 前缀记法的更多详细信息,请参阅第二十五章中的描述。
Metric 1 由 IP 地址指示的网络距离,如 RIP-1 中所述。值为 1 到 15 表示到达网络的路由跳数(如本章前面关于 RIP 算法的一般讨论中所述),而值为 16 表示无穷大(不可达的目的地)。

RIPng 消息格式 RIPng 保留了 RIP-2 中 RTEs 的使用,但它们的格式已更改以适应更大的 IPv6 地址大小。每条消息的条目限制也已取消。

图 38-7。RIPng 消息格式 RIPng 保留了 RIP-2 中使用的 RTEs,但它们的格式已经改变,以适应更大的 IPv6 地址大小。每条消息的条目限制也已被消除。

RIPng 中的 RTE 最大数量不受 RIP-1 和 RIP-2 中 25 个的限制。它仅受发送消息的网络最大传输单元(MTU)的限制。

小贴士

关键概念 RIPng 是为在 IPv6 互联网上使用而开发的 RIP 版本。从技术上讲,它与 RIP-1 和 RIP-2 是不同的协议,但与两者非常相似。它保留了 RIP-2 中对 RIP 所做的增强,并在需要与 IPv6 兼容的地方对这些特性和 RIP 消息格式进行了修改。

当需要指定下一跳字段时,会包含一个特殊的路由条目(RTE),正如我之前提到的。这个 RTE 包含在所有它适用的 RTE 之前。它具有与表 38-6 中显示的常规 RTE 相同的基本结构,IPv6 前缀子字段包含下一跳地址,路由标记和前缀长度字段设置为 0,度量字段设置为 255(0xFF)。

第三十九章。开放最短路径优先(OSPF)

无标题图片

使用距离矢量路由算法的内部路由协议,例如我们在上一章中探讨的路由信息协议(RIP),有着悠久的历史,在小型路由器组中运行良好。然而,它们在可扩展性和性能方面也存在一些严重的限制,这使得它们不适合较大的自治系统(AS)或具有特定性能问题的系统。许多最初使用 RIP 的组织很快就会发现自己遇到的限制和问题使其远非理想。

为了解决这个问题,在 20 世纪 80 年代末开发了一种新的路由协议。这个协议被称为开放最短路径优先(OSPF),它使用更强大(也更复杂)的链路状态或最短路径优先路由算法。它解决了 RIP 的许多问题,并允许根据网络当前状态动态选择路由,而不仅仅是静态的连接图。它还具有许多高级功能,包括支持分层拓扑和路由之间的自动负载均衡。然而,它是一个复杂的协议,这意味着除非真的需要,否则通常不会使用。这使得它成为 RIP 的补充,也是它们两者都在 TCP/IP 路由协议谱系中有位置的原因。

在本章中,我提供了对 OSPF 背后概念和操作的浓缩解释。像往常一样,我首先概述了该协议,讨论了其发展、版本以及定义它们的标准。我描述了 OSPF 背后的概念,包括基本拓扑和链路状态数据库。然后,我讨论了更复杂的可选分层拓扑以及在此拓扑下路由器扮演的角色。我简要解释了在 OSPF 中确定路由的方法,以及该协议中使用的通用操作和消息,包括对五种 OSPF 消息类型的描述。最后,我描述了用于 OSPF 消息的格式。

注意

网络技术的难点在于,有如此多的协议和技术如此复杂,每个都值得一本自己的书。OSPF 本身就是一个很好的例子,它足够复杂,以至于定义 OSPF 版本 2 的 RFC 文档有超过 240 页!因此,尽管本章相当全面,但只是对 OSPF 的高层次描述

OSPF 概述

在 TCP/IP 的早期,RIP 几乎默认成为了自治系统(AS)内部路由的标准协议。RIP 有两个很大的优势:它简单易用,并且从 1982 年开始就被包含在流行的伯克利标准分布(BSD)UNIX 中。大多数使用 TCP/IP 的组织最初使用的是相对较小的网络,并且能够以某种程度成功使用 RIP。

然而,正如我在第三十八章")中讨论的那样,该协议存在一些严重的技术问题,并且在 RIP 在较大的自治系统(AS)中使用时这些问题会加剧。RIP 的许多问题都源于它是一个距离矢量协议,因为该算法本身仅仅限制了 RIP 选择最佳路由和适应网络变化的能力。RIP 的其他问题基于其实现,例如选择 16 作为无穷大的成本值,这使得在设备之间可能发生超过 15 跳的情况下无法使用 RIP。RIP 版本 2 解决了诸如不支持无类别寻址等问题,但作为整体协议的基本困难仍然存在。

OSPF 的发展和标准化

互联网工程任务组(IETF)认识到,仅凭 RIP 本身无法满足互联网上所有 AS 的需求。它在 1988 年成立了一个工作组,以开发一种基于更强大的链路状态算法的新路由协议,也称为最短路径优先(SPF)。对这类协议的研究早在 20 世纪 70 年代就已经开始,其中一些研究是在互联网的前身 ARPAnet 上进行的,TCP/IP 的大部分内容都是在那里开发的。

这个新协议的名称传达了其两个最重要的特性。第一个词指的是该协议,像所有 TCP/IP 标准,是使用开放和公共的 RFC 流程开发的,因此它不是专有的,并且不需要许可证来使用它。名称中的 SPF 部分指的是它使用的算法类型,该算法旨在允许路由器动态确定任何两个网络之间的最短路径。

OSPF 的第一个版本在 1989 年 10 月发布的 RFC 1131 中进行了描述。这很快被 1991 年 7 月发布的 OSPF 版本 2 所取代,该版本在 RFC 1247 中进行了描述。从那时起,OSPF 版本 2 标准已经进行了几次修订,包括 RFC 1583、2178 和 2328,其中最后一个是现在的标准。OSPF 版本 2 是今天使用的唯一版本,因此当人们(包括我自己)提到 OSPF 时,通常是指这个版本。

OSPF 运作概述

OSPF 背后的基本概念是一个称为 链路状态数据库 (LSDB) 的数据结构。一个自治系统 (AS) 中的每个路由器都维护这个数据库的一个副本,其中包含以有向图形式的信息,描述了 AS 的当前状态。每个网络或另一个路由器的链路都由数据库中的一个条目表示,并且每个条目都有一个相关的成本(或度量)。度量可以包括许多不同的路由性能方面,而不仅仅是像 RIP 中使用的简单跳数。

关于 AS 的信息以 链路状态通告 (LSA) 的形式在 AS 中传播,这些是让每个路由器告诉其他路由器它目前对 AS 状态了解的消息。随着时间的推移,每个路由器关于 AS 的信息与其他路由器收敛,并且它们都有相同的数据。当互联网状态发生变化时,路由器发送更新以确保所有路由器都保持最新。

为了确定实际路由,每个路由器使用其 LSDB 构建一个最短路径树。这棵树显示了从路由器到每个其他路由器和网络的链路,并允许确定到任何位置的最低成本路由。当关于互联网状态的新信息到达时,这棵树可以重新计算,因此根据网络条件动态调整最佳路由。当存在多个具有相同成本的路径时,流量可以在这些路径之间共享。

OSPF 特点和缺点

除了链路状态算法的明显好处之外,OSPF 还包括其他一些有价值的特性,特别是对大型组织来说。它支持用于安全性的身份验证和所有三种主要的 IP 地址类型(类别、子网类别和类别无类)。对于非常大的 AS,OSPF 还允许将路由器分组并安排成层次拓扑。这有助于更好的组织和通过减少 LSA 流量来提高性能。

自然地,OSPF 的优越功能和许多特性并非没有代价。在这种情况下,主要的代价是复杂性。与 RIP 简单易用相比,OSPF 需要更多的工作和专业知识来正确配置和维护。这意味着尽管 OSPF 通常被认为比 RIP 更好,但从技术上讲,它并不适合每个人。OSPF 的明显角色是作为大型或高性能 AS 的路由协议,而将 RIP 留给覆盖较小和较简单的互联网。

小贴士

关键概念 开放最短路径优先(OSPF)是在 20 世纪 80 年代末开发的,旨在为那些 RIP 服务不佳的大型或更复杂的 AS 提供更强大的内部路由协议。它使用动态最短路径优先或链路状态路由算法,每个路由器维护一个包含关于互联网状态和拓扑信息的数据库。随着互联网的变化,路由器会发送更新的状态信息,这使得每个路由器可以动态地计算出在任何时间点到达任何网络的最佳路由。OSPF 是 RIP 的补充,因为 RIP 简单但有限,而 OSPF 功能更强大但更复杂。

OSPF 基本拓扑和链路状态数据库(LSDB)

OSPF 旨在促进较小和较大 AS 的路由。为此,该协议支持两种拓扑。当只有少量路由器时,整个 AS 被视为一个单一实体。这没有特定的名称,但我将其称为OSPF 基本拓扑,以传达拓扑的简单性,并与下一节中将要探索的分层拓扑进行对比。

当使用 OSPF 基本拓扑时,AS 中的所有路由器都作为对等体工作。每个路由器与其他每个路由器通信路由信息,并且每个路由器都维护一个关键 OSPF 数据结构的副本:链路状态数据库(LSDB),这本质上是对 AS 拓扑的计算机化表示。它是路由器查看 AS 中链路状态的方法——因此得名链路状态数据库(并且就 OSPF 而言,整个链路状态算法类别的名称,其中 OSPF 是其中之一)。

链路状态数据库(LSDB)有点难以可视化,但最好将其视为一组数据,相当于一个图形化图片,展示了 AS 的拓扑结构。在这样的图中,我们通常将路由器和网络作为节点显示,将路由器与网络之间的连接作为连接它们的线条。OSPF 链路状态数据库将那些信息放入表中,以便路由器可以维护 AS 中所有路由器与网络之间连接的虚拟图像。

因此,链路状态数据库(LSDB)指示哪些路由器可以直接到达哪些其他路由器,以及每个路由器可以到达哪些网络。此外,它为这些链接中的每一个存储一个到达网络的成本。这个成本是一个任意度量,可以根据管理员认为重要的任何标准设置。OSPF 不限于在 RIP 中使用的过于简单的跳数度量。

OSPF 基本拓扑

例如,让我们考虑你在第三十八章中检查的 RIP 路由确定算法相同的 AS。这个互联网有四个独立网络,如下所示连接:

  • 路由器 RA 将网络 N1 连接到网络 N2。

  • 路由器 RB 和 RC 将网络 N2 连接到网络 N3。

  • 路由器 RD 将网络 N3 连接到网络 N4。

为了使这个例子更有趣,我在路由器 RB 和 RC 之间添加了一个直接链接。

结果的 AS 如 图 39-1 所示。表 39-1”) 显示了该 AS 的 LSDB 可能看起来是什么样子。

示例 OSPF AS 这是你在第三十八章中查看的相同 AS,但增加了路由器 RB 和 RC 之间的链接

图 39-1. 示例 OSPF AS 这是你在第三十八章中查看的相同 AS,但增加了路由器 RB 和 RC 之间的链接(如图 38-1 所示)。

表 39-1. 示例 OSPF 链路状态数据库(LSDB)

到路由器/网络 从路由器 从网络
RA RB
--- --- ---
RA
RB
RC
RD
N1
N2
N3
N4

在实践中,表 39-1") 中的每个项目符号(•)将被一个表示从特定路由器发送数据报文到另一个路由器或网络的成本的度量值所取代。请注意,图表是对称的,因为如果路由器 RB 可以到达路由器 RC,那么路由器 RC 也可以到达路由器 RB。然而,成本 不一定是对称的。可能存在路由器 RB 到路由器 RC 的度量值高于路由器 RC 到路由器 RB 的情况。

还要注意,从网络 到达 路由器没有成本。这确保了路由器在网络上发送到另一个路由器时只应用一个成本。成本是从路由器到达网络。这很有意义,因为每个路由器都是其连接的网络的一个成员。

LSDB 信息存储和传播

关于 LSDB 的重要事项是,尽管每个路由器都维护它,但数据库并不是从单个路由器的视角构建的。一个路由器的 LSDB 代表整个 AS 的拓扑结构,包括与它可能相当遥远的路由器之间的链路。因此,例如,路由器 RA 会将其存储区域中的整个数据库保持在其存储区域中,包括关于路由器 RC 和路由器 RD 的信息,而它与这些路由器没有直接连接。

由于在基本拓扑中,所有路由器都是对等的,并维护整个 AS 的信息,在理论上,它们应该具有完全相同的 LSDB 内容。当路由器首次启动时,它可能与其邻居有不同的 LSDB 信息,但将通过包含 LSA 的更新消息的交换来纠正这一点。最终,所有路由器都应该收敛到相同的信息。你将在本章后面的关于 OSPF 消息传递的部分中看到这是如何工作的。

OSPF 作为一种内部路由协议,仅在 AS 内部使用。在大多数情况下,AS 将通过其一个或多个路由器连接到其他 AS。连接 AS 到其他 AS 的路由器通常被称为 边界路由器。这些设备将使用 OSPF 在 AS 内部进行通信,并使用外部路由协议(通常是 BGP)与 AS 外部的路由器进行通信。其名称中的 边界 一词指的是这些设备通常位于 AS 的外围。

小贴士

关键概念 在基本的 OSPF 拓扑中,运行 OSPF 的每个路由器都被视为其他路由器的对等体。每个路由器维护一个 链路状态数据库 (LSDB),其中包含整个 AS 的拓扑信息。每个路由器与网络或两个路由器之间的链路都由 LSDB 中的一个条目表示,该条目指示通过链路发送数据的成本。LSDB 通过交换 OSPF 链路状态通告 (LSA) 定期更新。

OSPF 分层拓扑

当一个 AS 中的路由器数量相对较少时,使用之前描述的基本拓扑结构效果良好。每个路由器都维护一个网络拓扑的公共视图,形式为一个相同的链路状态数据库(LSDB)。路由器使用链路状态通告(LSA)作为对等体进行通信。尽管 AS 中的变化可能导致路由器暂时拥有与其对等体不同的信息,但常规的数据交换将保持所有 LSDB 同步并更新,而且由于 AS 较小,不需要发送太多信息。

这种更简单的拓扑结构可以合理地扩展,并且可以支持许多较小的甚至中等规模的 AS。然而,随着路由器数量的增加,更新链路状态数据库(LSDB)所需的通信量也会增加。在一个拥有数十个甚至数百个路由器的非常大的互联网中,使用基本拓扑结构让所有路由器都成为 OSPF 对等体可能会导致性能下降。这个问题是由于需要传递的巨大路由信息量以及每个路由器都需要维护一个包含整个 AS 中每个路由器和网络的庞大 LSDB 而产生的。

OSPF 区域

为了更好地支持这些大型互联网,OSPF 支持使用更高级、分层的拓扑结构。在这种技术中,自治系统(AS)不再被视为一个由相互连接的路由器组成的单一、扁平的结构,其中所有路由器都是对等体。相反,构建了一个两级分层拓扑结构。AS 被划分为称为 区域 的结构,每个区域包含一定数量的连续路由器和网络。这些区域被编号,并由其内部的路由器独立管理,因此每个区域几乎就像是一个独立的 AS。这些区域通过相互连接,以便在整个 AS 中共享区域间的路由信息。

理解这种分层拓扑的最简单方法是将每个区域视为 AS 整体中的子 AS。任何区域内的路由器维护一个包含该区域内部路由器和网络信息的 LSDB。位于多个区域内的路由器维护关于它们所属的每个区域的 LSDB,并且它们还连接这些区域以在它们之间共享路由信息。

小贴士

关键概念 为了更好地控制和管理大型互联网,OSPF 允许将大型 AS 结构化为分层形式。连续的路由器和网络被分组到区域中,这些区域通过逻辑骨干连接在一起。这些区域在较大的 AS 中充当较小 AS 的等效体,从而提供与 AS 为大型组织间互联网提供本地化控制和流量管理相同的益处。

OSPF 分层拓扑中的路由器角色

描述的拓扑结构是分层的,因为 AS 中的路由器不再是单个组中的所有对等体。两级层次结构包括包含单个区域的较低级别,以及将它们连接在一起的高级别,这被称为骨干,并指定为 Area 0。路由器根据它们的位置和连接方式扮演不同的角色。在此配置中,对路由器应用了三个不同的标签:

内部路由器 这些是只连接到单个区域内的其他路由器或网络的路由器。它们只为该区域维护一个 LSDB,并且不知道其他区域的拓扑结构。

区域边界路由器 这些是连接到多个区域内的路由器或网络的路由器。它们为它们所参与的每个区域维护一个 LSDB。它们还参与骨干。

骨干路由器 这些是 OSPF 骨干的一部分。根据定义,这些包括所有区域边界路由器,因为那些路由器在区域之间传递路由信息。然而,骨干路由器也可能是一个只连接到其他骨干(或区域边界)路由器的路由器,因此它不属于任何区域(除了 Area 0)。

总结来说,区域边界路由器也总是骨干路由器,但骨干路由器不一定是区域边界路由器。

注意

我刚才提到的分类与将路由器指定为上一节中描述的边界路由器的指定无关。边界路由器是那些与 AS 外部的路由器或网络通信的路由器。边界路由器也经常是区域边界路由器或骨干路由器,但这并不一定。边界路由器可能是一个区域内的内部路由器

所有这些的目的与最初使用 AS 架构的目的相同。每个区域的拓扑结构只对那个区域内的设备有意义。这意味着该拓扑结构的变化只需要在该区域内传播。这也意味着 Area 1 内部的内部路由器不需要了解 Area 2 内部发生的事情,也不需要维护关于任何其他区域的信息。只有骨干路由器(每个区域至少包含一个区域边界路由器)需要了解整个 AS 的详细信息。这些骨干路由器将区域的信息压缩,以便只在骨干上发布每个区域拓扑的摘要。

在分层拓扑结构的 AS 中执行路由的方式有两种,这取决于设备的位置:

  • 如果源和目的地在同一区域,则路由仅在該区域的网络和路由器上发生。

  • 如果源和目标在不同的区域,数据报将从源区域的路由器边界路由器路由,经过骨干到目标区域的路由器边界路由器,然后最终交付给目标。

再次强调,这与在大图景互联网中 AS 之间的路由工作方式类似。

让我们通过一个例子来帮助使事情更加具体。我们可以使用前面例子中的 AS。这个 AS 足够小,以至于我们不太可能使用分层拓扑,但为了说明目的,它还是足够的。让我们将这个 AS 分为两个区域,如下(参见图 39-2):

  • 区域 1 包含网络 N1、路由器 RA、网络 N2、路由器 RB 和路由器 RC。

  • 区域 2 包含路由器 RB、路由器 RC、网络 N3、路由器 RD 和网络 N4。

示例 OSPF 分层拓扑 AS 这是你在中看到的相同的 AS,但它被组织成 OSPF 分层拓扑。AS 已经被均匀地分为区域 1 和区域 2。区域 0 包含路由器 RB 和 RC,它们是本例中区域 1 和区域 2 的区域边界路由器。

图 39-2. 示例 OSPF 分层拓扑 AS 这是你在图 39-1,但它被组织成 OSPF 分层拓扑。AS 已经被均匀地分为区域 1 和区域 2。区域 0 包含路由器 RB 和 RC,它们是本例中区域 1 和区域 2 的区域边界路由器。")

在这个例子中,路由器 RA 和路由器 RD 是内部路由器。路由器 RB 和 RC 是构成互联网骨干(区域 0)的区域边界路由器。RA、RB 和 RC 路由器将维护描述区域 1 的 LSDB,而 RB、RC 和 RD 路由器将维护描述区域 2 的 LSDB。RB 和 RC 路由器维护一个独立的 LSDB 用于骨干。除了区域边界路由器 RB 和 RC 之外,没有其他骨干路由器。然而,假设我们有一个只有直接连接到路由器 RB 和 RC 的路由器 RE。这将是一个仅作为骨干的路由器。

这个例子说明了本章前面提到的分层拓扑的主要缺点:复杂性。然而,对于大型 AS 来说,与将每个路由器都视为对等体相比,它具有显著的优势。同时,由于需要非常仔细的设计,特别是骨干的设计,概念复杂性变得更糟。如果层次结构设置不当,路由器之间链路的单个故障可能会破坏骨干并隔离一个或多个区域(包括该区域内所有网络上的所有设备!)。

使用 SPF 树进行 OSPF 路由确定

每个 OSPF AS 中的路由器维护的关键数据结构是 LSDB,它包含整个 AS(在基本拓扑中)或单个区域(在分层拓扑中)的拓扑表示。正如你所看到的,AS 或区域中的每个路由器都有相同的 LSDB,因此它代表了路由器与网络之间连接的中立视图。

SPF 树

每个路由器需要参与保持 LSDB 更新,但它也有自己的关注点。它需要能够确定它应该使用哪些路由来处理从其连接的网络接收到的数据报——毕竟,这就是路由协议的全部目的。为了找到最佳路由,它必须确定自己与 AS 或区域中每个路由器或网络之间的最短路径。为此,它需要的不是对互联网的中立视图,而是从其自身视角的视图。

路由器通过将 LSDB 中的信息转换为SPF 树来创建这种视角。术语指的是一个具有根节点,从根节点延伸出分支指向其他节点,这些节点也有分支的数据结构。整体结构看起来像一棵倒置的树。在这种情况下,SPF 树显示了 AS 或区域的拓扑信息,其中构建树的路由器位于顶部。每个直接连接的路由器或网络在树中向下一步;然后连接到这些第一级路由器或网络的每个路由器或网络,依此类推,直到整个 AS 或区域都被表示。

再次强调,路由器并不真正制造树;它只是路由器内部计算机执行的一种算法计算。然而,一旦完成这个计算,这个逻辑结构就可以用来计算该路由器到达 AS(或区域)中任何路由器或网络的成本。在某些情况下,到达路由器或网络可能有多种方式,因此树被构建来显示到达网络的唯一最短(最低成本)路径。

每个路由器只负责在其旅程的下一阶段发送数据报,而不负责整个旅程的任何情况。一旦创建了 SPF 树,路由器将创建一个路由表,其中包含每个网络的条目,显示到达该网络的成本,以及用于到达该网络的下一条路由器。

SPF 树是根据 LSDB 的当前状态动态创建的。如果 LSDB 发生变化,则重新计算 SPF 树和路由信息。

小贴士

关键概念 要确定它应该使用哪些路由来到达其 AS 中的网络,路由器从其 LSDB 生成一个 最短路径优先树(SPF 树)。此树包含与 LSDB 相同的基本信息,但以进行计算的路由器的视角呈现,这样路由器就可以看到到达不同网络的各个路径的成本。

OSPF 路由确定

我几乎能看到你的眼睛开始发直,所以我们回到本章中一直在使用的例子。为了简单起见,我们假设我们正在查看基本拓扑中的整个 AS。表 39-2 重复了之前在表 39-1 中显示的此 AS 的 LSDB,但我已经自由地将项目符号替换为成本度量;这些在图 39-3 中也有显示。再次提醒,从网络到达路由器没有成本,所以这些链接只有从路由器到网络的方向才有非零成本。

表 39-2. 带成本的样本 OSPF LSDB

| 到路由器/网络 | 从路由器 | 从网络 |
| --- | --- | --- | --- | --- | --- | --- | --- | --- |

RA RB RC RD N1 N2 N3 N4
RA 0 0
RB 5 0 0
RC 5 0 0
RD --- --- --- --- --- 0 0
N1 2
N2 3 4 3
N3 5 6 1
N4 4

带成本的样本 OSPF AS 这是图 39-1 中显示的相同样本 AS,但为路由器和网络之间的每个连接分配了成本。路由器和网络之间的成本仅在从路由器到网络的方向上应用。

图 39-3. 带成本的样本 OSPF AS 这与图 39-1,是相同的样本 AS,但为路由器和网络之间的每个连接分配了成本。路由器和网络之间的成本仅在从路由器到网络的方向上应用。

现在我们来构建 RC 的 SPF 树。我们可以通过迭代来完成,如下所示(参见图 39-4)。

使用 SPF 算法确定 OSPF 路由 此图图形化地展示了路由器(在本例中为路由器 RC)如何确定到达各种网络的最佳路径。这里的箭头表示的不是数据的传输,而是从路由器到其他路由器或网络的链路检查。在面板 1 中,路由器 RC 检查其链路状态数据库(LSDB),并确定其直接连接的每个设备的成本。在面板 2 中,通过将这些数字与面板 1 中找到的路由器/网络连接的所有路由器/网络的成本相加,构建了 SPF 树的第二级。(黑色箭头表示在先前步骤中返回的方向,我们不继续追踪。)在面板 3 中,过程继续进行,最终确定路由器 RC 到达网络 N1 的成本为 5,到达网络 N4 的成本为 10。

图 39-4. 使用 SPF 算法确定 OSPF 路由 此图图形化地展示了路由器(在本例中为路由器 RC)如何确定到达各种网络的最佳路径。这里的箭头表示的不是数据的传输,而是从路由器到其他路由器或网络的链路检查。在面板 1 中,路由器 RC 检查其链路状态数据库(LSDB),并确定其直接连接的每个设备的成本。在面板 2 中,通过将这些数字与面板 1 中找到的路由器/网络连接的所有路由器/网络的成本相加,构建了 SPF 树的第二级。(黑色箭头表示在先前步骤中返回的方向,我们不继续追踪。)在面板 3 中,过程继续进行,最终确定路由器 RC 到达网络 N1 的成本为 5,到达网络 N4 的成本为 10。

第一级

要构建树的第一个级别,我们寻找所有路由器 RC 可以直接到达的设备。我们找到了以下设备:

  • 路由器 RB,成本为 5

  • 网络 N2,成本为 3

  • 网络 N3,成本为 6

第二级

要构建第二级,我们寻找第一级可以直接到达的所有设备。然后我们将到达第一级每个设备的成本加到第二级每个设备的成本上。

RB: 路由器 RB 的成本为 5,可以到达以下:

  • 路由器 RC,成本为 5,总成本为 10

  • 网络 N2,成本为 4,总成本为 9

  • 网络 N3,成本为 5,总成本为 10

N2: 网络 N2 的成本为 3,可以到达以下:

  • 路由器 RA,成本为 0,总成本为 3

  • 路由器 RB,成本为 0,总成本为 3

  • 路由器 RC,成本为 0,总成本为 3

N3: 网络 N3 的成本为 6,可以到达以下:

  • 路由器 RB,成本为 0,总成本为 6

  • 路由器 RC,成本为 0,总成本为 6

  • 路由器 RD,成本为 0,总成本为 6

你可能立即就能看出,我们最终得到了到达相同设备或网络的不同路径的数量,其中一些路径没有意义。例如,我们并不关心任何通往路由器 RC 的路径,因为我们就是路由器 RC!同样,我们可以立即排除某些路径,因为我们已经找到了到达它们的更短路径。当我们可以在第一级直接以 6 的成本到达时,通过路由器 RB 到网络 N3 的路径成本为 10 是没有意义的。因此,在分离出杂质后,我们在第二级得到了以下谷物:

  • 网络 N2 到路由器 RA,成本为 3

  • 网络 N3 到路由器 RD,成本为 6

第三级

我们通过寻找连接到我们在第二级找到的已筛选设备(这次我只显示有意义的设备)来继续这个过程:

RA: 路由器 RA 连接到网络 N1,成本为 2,总成本为 5。

RD: 路由器 RD 连接到网络 N4,成本为 4,总成本为 10。

在这个简单的例子中,我们只需要三个级别来构建路由器 RC 的树。(对于路由器 RA 或 RD,我们可能需要更多级别。)最终结果将是图 39-5 中显示的树,以及 RC 到四个网络的路由信息,如表 39-3 所示。

OSPF 计算的 SPF 树 这是图 中的 SPF 树的图形表示,仅显示计算过程的最终结果

图 39-5. OSPF 计算的 SPF 树 这是对 图 39-4 |
| N3 | 6 | (本地) |
| N4 | 10 | RD |

在这个非常简单的例子中,这正是你所期望的。请注意,没有为其他路由器指定特定的条目,因为它们是到达网络的手段。然而,如果其他路由器是连接 AS 和外部世界的边界路由器,那么将会有连接到这些网络的条目,这样路由器 RC 就知道将那些网络的流量发送到该边界路由器。

OSPF 通用操作

作为一种路由协议,OSPF 的主要任务是促进路由器之间路由信息的交换。在一个运行 OSPF 软件的 OSPF AS 中,每个路由器都负责各种任务,例如设置计时器来控制必须定期发生的某些活动,以及维护重要的数据结构,如链路状态数据库 (LSDB)。最重要的是,每个 OSPF 路由器都必须生成并响应 OSPF 消息。正是这种消息系统使得重要的路由信息能够在 AS 或区域内共享,这使得理解 OSPF 的工作方式变得至关重要。因此,通过查看消息类型及其使用方式来讨论 OSPF 的操作是值得的。

OSPF 消息类型

与 RIP 不同,OSPF 不使用用户数据报协议 (UDP) 来发送其信息。相反,OSPF 直接形成 IP 数据报,使用协议号 89 对 IP 协议字段进行打包。OSPF 定义了五种不同的消息类型,用于各种类型的通信:

Hello 如其名所示,这些消息用作问候的形式,允许路由器发现其本地链路和网络上的其他相邻路由器。这些消息在相邻设备(称为邻接)之间建立关系,并传达有关如何在 AS 或区域中使用 OSPF 的关键参数。

数据库描述 这些消息包含 AS 或区域的拓扑描述;也就是说,它们将 AS 或区域的 LSDB 内容从一台路由器传递到另一台路由器。由于 LSDB 可能很大,可能需要发送多个消息;这是通过指定发送设备为主设备并按顺序发送消息来实现的,从设备(LSDB 信息的接收者)则以确认的方式响应。

链路状态请求 这些消息由一台路由器用于从另一台路由器请求 LSDB 某部分的更新信息。该消息指定了请求设备希望获取更多当前信息的链路。

链路状态更新 这些消息包含关于 LSDB 中某些链路状态的更新信息。它们作为对链路状态请求消息的响应发送,并且路由器会定期广播或组播这些消息。它们的内含用于更新接收它们的路由器的 LSDB 中的信息。

链路状态确认 这些消息通过明确确认接收链路状态更新消息来为链路状态交换过程提供可靠性。

OSPF 消息

这些消息的使用方法大致如下。当路由器首次启动时,它会发送一个 Hello 消息以查看是否有运行 OSPF 的相邻路由器,并且它还会定期发送这些消息以发现可能出现的任何新邻居。当与一个新路由器建立邻接关系时,随后会发送数据库描述消息以初始化路由器的 LSDB。

已初始化的路由器进入稳定状态模式。它们将例行地向本地网络中洪泛链路状态更新消息,以通告其链路的状态。当它们检测到需要通告的拓扑结构变化时,它们也会发送更新。它们将接收来自其他设备的链路状态更新消息,并相应地发送链路状态确认。路由器还可以使用链路状态请求消息请求更新。

当使用分层拓扑时,内部路由器维护单个 LSDB,并在一个区域内执行消息传递。区域边界路由器有多个 LSDB,并在多个区域内执行消息传递。它们以及任何其他 OSPF 骨干路由器,还在骨干上交换消息信息,包括它们边界的区域摘要链路状态信息。

再次强调,这一切都高度简化了;OSPF 标准包含大量详细规则和程序,规定了发送和接收消息的确切时间。

小贴士

关键概念 OSPF 的操作涉及五种消息类型。Hello 消息在路由器之间建立联系。数据库描述消息初始化路由器的 LSDB。通过链路状态更新消息发送常规 LSDB 更新,并使用链路状态确认进行确认。设备还可以使用链路状态请求消息请求特定的更新。

OSPF 消息认证

OSPF 标准规定,所有 OSPF 消息都必须进行身份验证以确保安全。然而,这有点误导,因为支持的认证方法之一是空认证,这意味着不使用任何认证。使用可选的简单密码认证方法可以提供更多的安全性,而使用加密认证则可以获得最高的安全性。这些方法在 RFC 2328 的附录 D 中进行了描述。

注意

OSPF 中使用的 Hello 消息有时也被称为 Hello 协议。这是一个特别糟糕的术语,因为实际上有一个名为 HELLO 协议的实际路由协议。这两个协议没有关系。然而,我怀疑 OSPF 的 Hello 消息可能被这样命名是因为它们与独立 HELLO 协议中使用的消息具有类似的作用*。

OSPF 消息格式

如前所述,OSPF 使用五种不同类型的消息在 AS 或区域内的路由器之间通信链路状态和一般信息。为了帮助说明如何使用 OSPF 消息,查看这些消息的格式是值得的。

OSPF 通用头部格式

自然地,每种类型的 OSPF 消息都包含一组略有不同的信息;否则,就不会有不同类型的消息。然而,所有消息类型都共享一个类似的消息结构,从共享的 24 字节头部开始。这个通用头部允许以一致的方式传达某些标准信息,例如生成消息的 OSPF 版本号。它还允许接收 OSPF 消息的设备快速确定它接收到的消息类型,从而知道是否需要检查消息的其余部分。表 39-4 和图 39-6 显示了常见的 OSPF 头部格式。

表 39-4. OSPF 通用头部格式

字段名称 大小(字节) 描述
版本号 1 设置为 2 表示 OSPF 版本 2。
类型 1 表示 OSPF 消息的类型:1 = Hello2 = 数据库描述 3 = 链路状态请求 4 = 链路状态更新 5 = 链路状态确认
数据包长度 2 消息的长度,以字节为单位,包括此头部的 24 字节。
路由器 ID 4 生成此消息的路由器 ID(通常是发送消息的接口上的 IP 地址)。
区域 ID 4 当使用区域时,此消息所属的 OSPF 区域的标识。
校验和 2 以类似于标准 IP 校验和的方式计算的一个 16 位校验和。整个消息包含在计算中,除了认证字段之外。
认证类型 2 指示用于此消息的认证类型:0 = 无认证 1 = 简单密码认证 2 = 密码学认证
认证 8 用于消息认证的 64 位字段,如有需要。

OSPF 通用头部格式

图 39-6. OSPF 通用头部格式 在此头部之后,消息体包括一个可变数量的字段,这些字段取决于消息类型。每种消息格式都在 RFC 2328 中详细描述。由于有些相当长,所以我将只简要描述它们的字段。

OSPF Hello 消息格式

Hello 消息的头部 Type 值为 1,消息体中的字段结构如表 39-5 和图 39-7 所示。

表 39-5. OSPF Hello 消息格式

字段名称 大小(字节) 描述
网络掩码 4 路由器发送到的网络的子网掩码。
Hello 间隔 2 路由器在发送 Hello 消息之间等待的秒数。
选项 1 指示路由器支持哪些可选的 OSPF 功能。
路由器优先级 1 在选择备用指定路由器时,指示路由器的优先级。
路由器死亡间隔 4 路由器在被认为是失败之前可以沉默的秒数。
指定路由器 4 在某些网络中指定用于特定特殊功能的路由器的地址。如果没有指定路由器,则设置为全零。
备用指定路由器地址 4 备用指定路由器的地址。如果没有备用指定路由器,则设置为全零。
邻居 4 的倍数 从最近接收到的 Hello 消息的每个路由器的地址。

OSPF Hello 消息格式

图 39-7. OSPF Hello 消息格式

OSPF 数据库描述消息格式

数据库描述消息在头部中的类型值为 2,其体结构如图表 39-6 和图 39-8 所示。

表表 39-6

字段名称 大小(字节) 描述
接口 MTU 2 在此路由器接口上可以发送的最大 IP 消息的大小,无需分片。
选项 1 指示路由器支持几个可选的 OSPF 功能中的哪一个。
标志 1 特殊标志,用于指示数据库描述消息交换的信息,如图表 39-7 所示。
数据库描述序列号 4 用于对数据库描述消息进行编号,以便保持它们的顺序。
LSA 头部 可变 包含 LSA 头部,它们携带有关 LSDB 的信息。请参阅本章后面的“OSPF 链路状态广告和 LSA 头部格式”部分以获取有关 LSA 的更多信息。请添加正确的交叉引用信息。

表表 39-7

子字段名称 大小(字节) 描述
保留 5/8 (5 位) 保留:发送和接收时均为零。
I 1/8 (1 位) I 位:设置为 1 以指示这是数据库描述消息序列中的第一个(初始)消息。
M 1/8 (1 位) M 位:设置为 1 以指示在此消息之后还有更多的数据库描述消息。
MS 1/8 (1 位) MS 位:如果发送此消息的路由器是通信中的主设备,则设置为 1;如果是从设备,则设置为 0。

OSPF 数据库描述消息格式

图图 39-8

OSPF 链路状态请求消息格式

链路状态请求消息在头部中的类型值为 3。在头部之后,跟随一个或多个由三个字段组成的集合,每个字段都标识一个路由器请求更新的 LSA,如图图 39-9 所示。每个 LSA 标识的格式在表 39-8 中描述。

表表 39-8

字段名称 大小(字节) 描述
LS 类型 4 正在寻找的 LSA 的类型。
链路状态 ID 4 LSA 的标识符,通常是路由器或网络链接的 IP 地址。
广播路由器 4 创建正在寻找更新的 LSA 的路由器的 ID。

OSPF 链路状态请求消息格式

图 39-9. OSPF 链路状态请求消息格式

OSPF 链路状态更新消息格式

链路状态更新消息在头部有一个类型值为 4,以及 表 39-9 和 图 39-10 中展示的字段。

表 39-9. OSPF 链路状态更新消息格式

字段名称 大小 (字节) 描述
# LSAs 4 此消息中包含的 LSA 数量。
LSAs 可变 包含一个或多个 LSA。有关更多详细信息,请参阅本章后面的“OSPF 链路状态通告和 LSA 头部格式”部分。

OSPF 链路状态更新消息格式

图 39-10. OSPF 链路状态更新消息格式

OSPF 链路状态确认消息格式

链路状态确认消息在头部有一个类型值为 5。然后,它们包含一个与被确认的 LSA 对应的 LSA 头部列表,如 表 39-10 和 图 39-11 所示。

表 39-10. OSPF 链路状态确认消息格式

字段名称 大小 (字节) 描述
LSA 头部 可变 包含标识被确认的 LSA 的 LSA 头部。

OSPF 链路状态确认消息格式

图 39-11. OSPF 链路状态确认消息格式

OSPF 链路状态通告和 LSA 头部格式

前几个消息类型包括 LSA,这些字段实际上携带了关于 LSDB 的拓扑信息。有几种类型的 LSA,用于传达有关不同类型链路的信息。与 OSPF 消息本身一样,每个 LSA 都有一个 20 字节的通用头部,然后是一系列描述链路的附加字段。

LSA 头部包含足够的信息来识别链路。它使用 表 39-11 和 图 39-12 中所示的子字段结构。

表 39-11. OSPF 链路状态通告头部格式

子字段名称 大小 (字节) 描述
LS 年龄 2 自 LSA 创建以来经过的秒数。
选项 1 指示路由器支持几种可选的 OSPF 功能之一。
LS 类型 1 指示此 LSA 描述的链接类型,如 表 39-12 所示。
链路状态 ID 4 识别链接。这通常是路由器或该链接所代表的网络的 IP 地址。
广告路由器 4 发起 LSA 的路由器 ID。
LS 序列号 4 用于检测旧或重复 LSA 的序列号。
LS 校验和 2 用于数据损坏保护的 LSA 校验和。
长度 2 LSA 的长度,包括头部的 20 个字节。

表 39-12. OSPF 链路状态通告头部 LS 类型

链接类型 描述
1 路由器-LSA 连接到路由器的链路。
2 网络-LSA 连接到网络的链路。
3 摘要-LSA (IP 网络) 当使用区域时,会生成关于网络的摘要信息。
4 摘要-LSA (ASBR) 当使用区域时,会生成关于连接到 AS 边界路由器的链路摘要信息。
5 AS-外部-LSA AS 外部的链路。

OSPF 链路状态通告头部格式

图 39-12. OSPF 链路状态通告头部格式

在 LSA 头部之后是 LSA 的主体。主体中的特定字段取决于 LS 类型字段的值(参见 表 39-12)。以下是摘要:

  • 对于到路由器的普通链接,LSA 包含了路由器的标识和到达它的度量,以及有关路由器的详细信息,例如它是否是边界或区域边界路由器。

  • 网络链路状态通告包括子网掩码以及关于网络中其他路由器的信息。

  • 摘要 LSA 包含度量、汇总地址以及子网掩码。

  • 外部链路状态通告包含一些额外的字段,允许外部路由器进行通信。

如果您想了解 LSA 主体中字段的详细信息,请参阅 RFC 2328 的附录 A。

第四十章. 边界网关协议 (BGP/BGP-4)

无标题图片

现代 TCP/IP 互连网络由独立运行的自治系统(AS)组成。每个自治系统可能使用内部路由协议,如路由信息协议(RIP)、开放最短路径优先(OSPF)、内部网关路由协议(IGRP)或增强型内部网关路由协议(EIGRP)来选择 AS 内网络之间的路由。为了形成更大的互连网络,特别是“所有互连网络之母”——互联网,这些自治系统必须连接在一起。这需要使用所有自治系统都能达成一致的统一外部路由协议,在今天的 TCP/IP 中,该协议就是 边界网关协议(BGP)

如果你要求普通互联网用户,甚至典型的网络管理员列出十个最重要的 TCP/IP 协议,BGP 可能不会频繁出现。路由协议是 TCP/IP 协议套件的工蜂,它们并不非常吸引人。然而,现实情况是,BGP 对于大型互联网和互联网本身的运行至关重要。它是将较小的互联网(AS)粘合在一起的东西,并确保每个组织都能共享路由信息。正是这个功能使我们能够将不同的网络和互联网连接起来,并从任何主机找到到任何其他主机的有效路由,无论位置如何。

在本章中,我描述了 BGP(边界网关协议)的特点、一般操作和详细操作。我像往常一样,首先概述了该协议,并讨论了其历史、标准和版本,包括对其关键特性和特性的讨论。然后,我涵盖了基本操作概念,包括拓扑、BGP 发言人概念和邻居关系。我讨论了 BGP 流量类型以及如何使用策略来控制互联网上的流量。我解释了 BGP 路由器如何存储和通告路由以及路由信息库如何工作。我描述了 BGP 使用的算法以及路径属性如何描述路由。我提供了 BGP 路由选择过程操作的总结。然后,我给出了 BGP 操作的一般描述及其对各种消息的高级使用。最后,我更详细地分析了不同消息类型、它们的使用方式和格式。

BGP 是庞大的一组协议和技术中的一个,其复杂性如此之大,以至于需要数十章才能公正地描述。因此,我在这里包含了一个相当标准的免责声明,你将在本章中只看到 BGP 的相对高级概述。如果你需要更多细节,你需要参考 BGP 标准(在 BGP 标准和版本部分描述)。

注意

当前 BGP 的版本是版本 4,也称为 BGP-4。这是今天广泛使用的唯一版本,所以除非另有说明,否则在你看到 BGP 的地方,假设我在谈论 BGP-4。*

BGP 概述

正如我在第三十七章中简要描述的路由协议概念概述中所述,早期互联网中路由器之间的连接方式与今天大不相同。早期的互联网有一组作为核心自治系统(AS)的集中式路由器。这些路由器在 AS 内部使用网关到网关协议(GGP)进行通信,并使用恰如其分的称为外部网关协议(EGP)与核心外的路由器通信。GGP 和 EGP 在第四十一章中讨论。

当互联网增长并转向 AS 架构时,EGP 仍然能够作为互联网的外部路由协议运行。然而,随着互联网中 AS 数量的增加,它们之间通信的重要性也随之增长。EGP 虽然功能齐全,但存在一些弱点,随着互联网的扩展,这些弱点变得更加突出。有必要定义一个新的外部路由协议,该协议将为日益增长的互联网提供增强的功能。

1989 年 6 月,本新路由协议的第一个版本通过发布 RFC 1105,“一个边界网关协议(BGP)”而正式化。BGP 标准的这个初始版本定义了协议背后的大多数概念,以及关键的基本要素,如消息、消息格式以及设备在一般意义上的操作。它确立了 BGP 作为互联网未来外部路由协议的地位。

BGP 版本和定义标准

由于跨越互联网的协议的重要性,在最初标准发布后,对 BGP 的工作持续了许多年。BGP 的开发者需要纠正初始协议的问题,细化 BGP 的操作,提高效率,并添加功能。还必须进行调整,以使 BGP 能够跟上 TCP/IP 协议套件中的其他变化,例如无类别地址和路由的发明。

这项持续工作的结果是,BGP 经历了几个版本和标准的演变。这些有时被称为 BGP-N,其中N是版本号。表 40-1 显示了 BGP 标准的历史,提供了 RFC 编号和名称,以及每个版本所做的简要更改。

表 40-1. 边界网关协议(BGP)版本和定义标准

RFC 编号 日期 名称 BGP 版本 描述
1105 1989 年 6 月 一个边界网关协议(BGP) BGP-1 BGP 的初始定义。
1163 1990 年 6 月 一个边界网关协议(BGP) BGP-2 这个版本的 BGP 清理了 BGP-1 中的几个问题,并细化了某些消息类型的意义和使用。它还增加了重要的路径属性概念,用于传递有关路由的信息。BGP-1 是基于方向拓扑的概念设计的,某些路由器相对于彼此是上升、下降或水平;BGP-2 去除了这个概念,使 BGP 更适合任意 AS 拓扑。(注意,RFC 标题没有打字错误;他们没有在标题中放入“版本 2”。)
1267 十月 1991 边界网关协议 3 (BGP-3) BGP-3 此版本优化并简化了路由信息交换,向用于建立 BGP 通信的消息中添加了标识能力,并纳入了其他一些改进和修正。(出于某种原因,他们从标题中省略了 "A" 字母。)
1654 七月 1994 边界网关协议 4 (BGP-4) BGP-4 BGP-4 的初始标准,在 RFC 1771 中进行了修订。
1771 三月 1995 边界网关协议 4 (BGP-4) BGP-4 BGP-4 的当前标准。BGP-4 的主要变化是支持无类别域间路由 (CIDR)。该协议被修改,允许指定表示一组聚合网络的前缀。还对协议进行了其他一些小的改进。

如你所想,更改像 BGP 这样的协议版本并不是一项容易的任务。对协议的任何修改都需要许多不同组织的协调。互联网规模越大,这越困难。因此,尽管在 20 世纪 90 年代初期频繁进行版本更改,但 BGP-4 仍然是当前的标准版本,并且是广泛使用的版本。除非另有说明,本书中提到的任何 BGP 都指的是 BGP-4。

补充 RFC 1771 的还有三个连续编号的 RFC,它们与 RFC 1771 同时发布,提供了关于 BGP 功能和使用的支持信息,如 表 40-2 所示。

表 40-2. BGP-4 的附加定义标准

RFC 编号 名称 描述
1772 互联网中边界网关协议的应用 提供了关于 BGP 运作以及如何在互联网上应用和使用的额外概念信息。这份文档有时被认为是 RFC 1771 的配套文件,两者共同定义了 BGP-4。
1773 BGP-4 协议的经验 描述了测试和使用 BGP-4 的人的经验,并提供了证明其作为标准被接受的信息。
1774 BGP-4 协议分析 提供了关于 BGP-4 运作的更详细的技术信息。

提示

关键概念 现代 TCP/IP 互联网中使用的边界路由协议是 边界网关协议 (BGP)。BGP 最初在 20 世纪 80 年代末期开发,作为外部网关协议 (EGP) 的继任者,BGP 已多次修订;当前版本是 4,因此 BGP 也常被称为 BGP-4。BGP 的主要功能是在自治系统 (AS) 之间交换网络可达性信息,以便互联网上的每个 AS 都能高效地向其他 AS 发送消息。

BGP 功能和特性概述

如果我要用一个短语来总结 BGP 的工作,那将是交换 AS(自治系统)之间的网络可达性信息,并从这个信息中确定到达网络的路径。在一个典型的互联网(以及因特网)中,每个 AS 指定一个或多个运行 BGP 软件的路由器。每个 AS 中的 BGP 路由器与一个或多个其他 AS 中的路由器相连。每个 BGP 路由器在一系列路由信息库(RIBs)中存储有关网络及其路径的信息。这种路由信息在 BGP 路由器之间交换,并在整个互联网中传播,使得每个 AS 能够找到到达其他 AS 的路径,从而在整个互联网中实现路由。

BGP 支持任意拓扑结构的 AS,这意味着它们可以以任何方式连接。一个 AS 至少必须有一个运行 BGP 的路由器,但可以有多个。也有可能使用 BGP 在同一 AS 内部的 BGP 路由器之间进行通信。

BGP 使用一个相当复杂的系统来确定路由。该协议超越了仅考虑网络下一跳的有限概念,就像 RIP 这样的距离矢量算法所做的那样。相反,BGP 路由器存储了从自身到网络的路由(AS 序列)的更完整信息。特殊的路径属性描述了路径的特性,并在路由选择过程中使用。由于其存储路径信息,BGP 有时被称为 路径向量 协议。

BGP 使用一种确定性的算法来选择路由,该算法评估路径属性并选择一条高效的路由,同时避免路由器环路和其他问题条件。BGP 路由器选择路由的过程也可以通过一组 BGP 策略来控制,这些策略可以指定,例如,AS 是否愿意承载来自其他 AS 的流量。然而,BGP 不能保证到达任何目的地的最有效路由,因为它无法知道每个 AS 内部发生的情况以及穿越每个 AS 的成本。

BGP(边界网关协议)的操作基于执行不同功能的消息交换。BGP 路由器使用 Open 消息来联系相邻路由器并建立 BGP 会话。它们通过交换 Update 消息来沟通关于可达网络的详细信息,根据需要只发送部分信息。它们还使用 Keepalive 和 Notification 消息来维护会话并通知对等体错误条件。这些消息的使用将在本章后面详细解释。

小贴士

关键概念 BGP 支持任意拓扑结构的 AS。每个使用 BGP 的 AS 分配一个或多个路由器来实现该协议。这些设备随后交换消息以相互建立联系,并通过传输控制协议(TCP)在互联网中共享关于速率的信息。BGP 使用一种复杂的路径向量路由计算算法,该算法根据描述如何到达不同网络的路径属性来确定路由。

BGP 使用传输控制协议(TCP)作为可靠的传输协议,以便可以利用该协议的许多连接设置和维护功能。这也意味着 BGP 不需要担心诸如消息排序、确认或丢失传输等问题。由于未经授权的 BGP 消息可能会对互联网的运行造成破坏,因此 BGP 包括一个用于安全性的身份验证方案。

注意

BGP 与较老的外部路由协议 EGP 保持向后兼容

BGP 拓扑

在上一节中,我将 BGP 的功能总结如下:在路由器网络的 AS 之间交换网络可达性信息,并据此确定路由。然而,BGP 实际用来完成这一任务的方法相当复杂。

BGP 最重要的特性之一是其灵活性。该协议可以使用任意拓扑连接任何 AS 的内部网络。唯一的要求是每个 AS 至少有一个能够运行 BGP 的路由器,并且该路由器至少连接到一个其他 AS 的 BGP 路由器。除此之外,“天高任鸟飞”,正如他们所说。BGP 可以处理一组以全网状拓扑(每个 AS 连接到每个其他 AS)、部分网状、AS 链(一个 AS 链接到下一个 AS)或其他任何配置连接的 AS。它还可以处理随时间可能发生的拓扑变化。

BGP 做出的另一个重要假设是它对 AS 内部发生的事情一无所知。这是 AS 自主性的一个重要前提——它有自己的内部拓扑并使用自己的选择的路由协议来确定路由。BGP 只是从 AS 接收到的信息,并将其与其他 AS 共享。

BGP 发言人、路由器角色、邻居和对等体

创建 BGP 内部网络始于在每个 AS 中指定某些路由器作为将运行该协议的路由器。在 BGP 术语中,这些被称为BGP 发言人,因为它们使用 BGP 语言。一个协议可以合理地被称为一种语言,但我还没有在其他任何协议中遇到过这种发言人的概念,所以这是一个相当有趣的术语。

一个 AS 可以包含许多以任意拓扑连接的路由器。我们可以区分 AS 中仅连接到 AS 内其他路由器的路由器与连接到其他 AS 的路由器。前者组中的路由器通常被称为内部路由器,而后者组中的路由器在 BGP(以及其他协议中的类似名称;例如,在 OSPF 中它们被称为边界路由器)中被称为边界路由器

边界这个概念是 BGP(边界网关协议)名称的基础。要实际创建 BGP 内部网,每个 AS(自治系统)边界的 BGP 发言人需要物理连接到其他 AS 中的一个或多个 BGP 发言人,无论内部网设计者指定了何种拓扑结构。当一个 AS 中的 BGP 发言人与另一个 AS 中的 BGP 发言人生成连接时,它们被认为是邻居。它们之间的直接连接使得它们能够交换关于它们所属 AS 的信息。

大多数 BGP 发言人将连接到多个其他发言人。这既提供了更多直接路径到不同网络的更高效率,也提供了冗余,以便内部网能够应对设备或连接故障。一个 BGP 发言人与其他 BGP 发言人建立邻居关系,既可能在其自己的 AS 内部,也可能在其 AS 外部。AS 内部的邻居被称为内部对等体,而 AS 外部的邻居被称为外部对等体。内部对等体之间的 BGP 有时被称为内部 BGP (IBGP);外部对等体之间协议的使用被称为外部 BGP (EBGP)。这两个协议相似,但在某些领域有所不同,尤其是在路径属性和路由选择方面。您可以在图 40-1 中看到一个 BGP 拓扑和内部与外部对等体的指定示例。

此图是第三十七章中图 37-1 的一个变体。它显示了 BGP 用于指代不同类型路由器和 AS 的名称。内部路由器以较淡的文字显示,而边界路由器以粗体显示。在一个 AS 内进行通信的 BGP 发言人是内部对等体,而在 AS 之间进行通信的是外部对等体。这个高度简化的内部网显示了两个只有连接到多宿主 AS 2 的端点 AS。BGP 发言人之间的对等连接可以是使用某种形式的第 2 层技术的直接链路,也可以是使用 TCP 的间接链路。这允许 BGP 发言人在本章后面部分看到的报文系统中建立 BGP 会话并交换路由信息。它也是实际用户流量在 AS 之间移动的手段。外部对等体通常直接连接,而内部对等体通常间接连接。

你很快就会看到 AS 连接的方式对互联网的整体功能和流量在其上的传输方式有重要影响。

样本 BGP 拓扑和命名

图 40-1. 样本 BGP 拓扑和命名

小贴士

关键概念 配置为使用 BGP 的每个路由器称为 BGP 发言人;这些设备使用 BGP 消息系统交换路由信息。仅连接到同一 AS 内其他路由器的路由器称为内部路由器,而连接到其他 AS 的路由器称为边界路由器。同一 AS 中的相邻 BGP 发言者称为内部对等体,而不同 AS 中的称为外部对等体

BGP AS 类型、流量和路由策略

当我们将自治系统(AS)连接起来形成一个互联网时,AS 边界路由器之间的路径形成了消息从一个 AS 移动到另一个 AS 的通道。仔细控制 AS 之间的消息流动非常重要。根据情况,我们可能希望限制或甚至禁止某些类型的消息进入或离开某个 AS。这些决定反过来又直接影响 BGP 路由的确定。

BGP 流量和流量类型

互联网中的消息流动有时统称为流量。这个术语提供了一个很好的类比,因为我们可以以与城市街道相同的方式考虑 BGP 互联网中的流量控制问题。你可能见过住宅街道上的标志,上面写着“禁止通过交通”或“仅限本地交通”。这些都是试图控制那些街道上交通流动的尝试。一个更极端的例子是我以前住的那个社区中的一条街道,其中在中间故意设置了一个路障,将繁忙的通过街道变成一对死胡同。再次强调,目标是交通控制。

这些措施突出了本地流量和邻域中通过流量之间的关键区别。正如这里所示,这种分类在 BGP 中同样重要:

本地流量 在 AS 内部携带的流量,要么起源于该 AS,要么打算在 AS 内部交付。这就像街道上的本地交通。

转接流量 在该 AS 外部生成并打算在 AS 外部交付的流量。这就像街道上的通过流量。

BGP AS 类型

在上一节中,我讨论了 AS 内部路由器和边界(或边界)路由器之间的区别。我们可以根据它们在整体 BGP 拓扑中的互联方式,在 AS 的不同类型之间做出类似的区分。主要有两种类型的 AS:

末端 AS 这是一个只连接到另一个 AS 的 AS。在道路类比中,它相当于一个死胡同(死胡同街道);通常,只有来自或前往该街道上房屋的车辆才会出现在那条街道上。

多宿主 AS 这是一个连接到两个或更多其他 AS 的 AS。在道路类比中,它相当于一条过境街道,因为车辆可能进入街道并穿过它,而不在任何街道房屋处停车。

在示例 BGP 内部网络 图 40-1 中,我已经将 AS 2 的边界路由器链接到 AS 1 和 AS 3。虽然 AS 2 的流量可以流向 AS 1 和 AS 3,但也可能存在 AS 1 的流量流向 AS 3 以及相反的情况。AS 2 作为这些数据报的“过境街道”。

BGP AS 路由策略

BGP 区分流量类型和 AS 类型的原因与在街道上这样做的原因相同:许多人对外来交通持保留态度。在社区中,每个人都希望能够从家中到达城市中他们需要去的地方,但他们不希望很多人使用他们的街道。同样,每个 AS 都必须至少使用另一个 AS 与远程 AS 进行通信,但许多人并不热衷于成为大量外部交通的通道。

这种犹豫在许多情况下确实是有道理的,无论是社区的情况还是 BGP 的情况。许多汽车和卡车在住宅街道上可能会带来多种问题:安全问题、道路磨损、污染等等。同样,如果一个多宿主 AS 被迫携带其他 AS 想要发送给它的所有过境交通,它可能会过载。

为了控制过境交通的携带,BGP 允许一个自治系统(AS)设置和使用路由策略。这些是一系列规则,用于规定一个 AS 如何处理过境交通。在 AS 如何处理过境交通方面存在很大的灵活性。许多选项中包括以下内容:

无过境策略 一个 AS 可以有一个策略,即完全不处理过境交通。

受限 AS 过境策略 一个 AS 可以允许处理来自某些 AS 的流量,但不允许处理其他 AS 的流量。在这种情况下,它告诉那些它将处理流量的 AS,它们可以发送流量给它,但不对其他 AS 说同样的话。

基于标准的过境策略 一个 AS 可以使用多个不同的标准来决定是否允许过境交通。例如,它可能只在特定时间或在其有足够的额外容量时允许过境交通。

注意

愿意携带过境交通的 AS 有时被称为过境 AS

以类似的方式,可以设置策略来控制一个 AS 如何由其他 AS 处理其自身的流量。一个末端 AS 将始终作为一个整体连接到互联网,使用它所连接的单个 AS。然而,一个多宿主 AS 可能有政策,通过指定在什么条件下应该使用一个 AS 而不是另一个 AS 来影响路由选择。这些政策可能基于安全(如果一个连接的 AS 被认为比另一个更安全)、性能(如果一个 AS 比另一个更快)、可靠性或其他因素。

小贴士

关键概念 在 BGP 中,一个重要的问题是处理 AS 之间的流量流动。在 BGP 互联网中的每个 AS 要么是只连接到另一个 AS 的末端 AS,要么是连接到两个或更多其他 AS 的多宿主 AS。BGP 允许多宿主 AS 的管理员建立路由策略,这些策略指定在什么条件下 AS 愿意处理中继流量(源和目的地都位于该 AS 之外的消息)。

路由策略和互联网设计问题

如果每个街道只允许本地交通,一个城市会怎样?这将非常难以出行。当然,这个问题在精心设计的城市中永远不会发生,因为交通规划者理解了在住宅区连接性和避免中继交通的双重需求。城市以某种层次结构的方式布局,因此本地交通汇集到专门用于携带非本地交通的干道。

在互联网中存在相同的基本情况。如果每个自治系统(AS)都声明它不感兴趣于携带中继流量,那么这不会运作得很好!通常,互联网的设计是为了让某些 AS 有意承担大量中继流量。这通常是高速、高容量骨干连接的功能,这些连接作为其他 AS 的客户。一个 AS 通常只会在有安排允许这样做的情况下携带另一个 AS 的流量。

BGP 路由存储和公告

BGP(边界网关协议)的职责是促进 BGP 设备之间路由信息的交换,以便每个路由器都能确定到达 IP 互联网上每个网络的效率最高的路由。这意味着路由描述是 BGP 设备处理的关键数据。每个 BGP 发言人都有责任根据 BGP 标准中确立的具体指南管理路由描述。

BGP 路由信息管理功能

从概念上讲,路由信息管理的整体活动可以被认为是包括四个主要任务:

路由存储 每个 BGP 在一系列特殊数据库中存储如何到达网络的信息。它还使用数据库来保存从其他设备接收到的路由信息。

路由更新 当 BGP 设备从其对等体之一接收到更新消息时,它必须决定如何使用这些信息。应用特殊技术来确定何时以及如何使用从对等体接收到的信息来正确更新设备对路由的了解。

路由选择 每个 BGP 使用其路由数据库中的信息来选择互联网上每个网络的良好路由。

路由通告 每个 BGP 发言人定期告诉其对等体它所了解的关于各种网络及其到达方法。这被称为路由通告,并使用 BGP 更新消息来完成。你将在本章后面了解更多关于这些消息的内容。

BGP 路由信息库(RIBs)

BGP 路由信息管理和处理系统的核心是存储路由的数据库。这个数据库统称为路由信息库(RIB),但实际上它不是一个单一的整体。它由三个独立的部分组成,这些部分被 BGP 发言人用来处理路由信息的输入和输出。其中两个部分由几个单独的部分或副本组成。

三个 RIB 部分(使用 BGP 标准给它们起的神秘名称)如下:

Adj-RIBs-In 一组输入数据库部分,包含从对等 BGP 发言人接收到的路由信息。

Loc-RIB 本地 RIB。这是核心数据库,存储了由该 BGP 设备选定的路由,并被认为是有效的。

Adj-RIBs-Out 一组输出数据库部分,包含有关该 BGP 设备选定要传播给其对等体的路由的信息。

因此,根据你的视角,RIB 可以被视为一个单独的数据库或一系列相关数据库。(之前的划分是概念性的;整个 RIB 可以作为一个具有表示不同组件的内部结构的单一数据库实现,或者作为单独的数据库实现。)

RIB 是一个相当复杂的数据结构,不仅因为这种多部分结构,还因为 BGP 设备存储了比简单路由协议更多的路由信息。在 BGP 中,路由也称为路径,它们的详细描述以特殊 BGP 路径属性的形式存储,我们将在稍后进行考察。

RIB 的三个部分是 BGP 发言人管理信息流的方式。从对等 BGP 发言人通过更新消息传输的数据被保存在 Adj-RIBs-In 中,每个 Adj-RIB-In 保存来自一个对等体的输入。然后分析这些数据,并从中选择适当的部分来更新 Loc-RIB,这是该 BGP 发言人正在使用的路由的主要数据库。定期地,Loc-RIB 中的信息被放入 Adj-RIBs-Out 中,通过更新消息发送给其他对等体。这种信息流是通过称为 BGP 决策过程的系统的一部分来完成的,即路由更新、选择和广告,我将在本章后面的“BGP 路由确定和 BGP 决策过程”部分中讨论。

小贴士

关键概念 BGP 的常规操作需要 BGP 发言人存储、更新、选择和广告路由信息。用于此目的的中心数据结构是BGP 路由信息库(RIB)。实际上,RIB 由三个部分组成:一组输入数据库(Adj-RIBs-In),它保存从对等体接收到的路由信息;一个本地数据库(Loc-RIB),它包含路由器的当前路由;以及一组输出数据库(Adj-RIBs-Out),路由器使用这些数据库将其路由信息发送到其他路由器。

BGP 路径属性和算法概述

使用距离矢量算法的路由协议,如 RIP,在很大一部分上相对简单,因为每个设备存储的关于每条路由的信息本身很简单。每个路由器只知道它可以通过特定的下一跳路由器以特定的成本到达一个网络。它没有关于数据报将如何到达这些网络的任何路由知识。这种知识水平对于像 BGP 这样的协议的需求来说是不够的。

为了处理在 AS 的任意拓扑中计算有效、无环路由的计算,我们需要知道的不只是我们必须将网络 N7 发送到路由器 R4,还包括从我们到网络 N7 的整个路径的特性。通过存储这些附加信息,我们可以根据路由器与网络之间的整个路径的知识来做出关于如何计算和更改路由的决定。因此,BGP 设备不是以目的地和到达该目的地的距离来广告网络,而是广告网络作为目的地地址和到达这些目的地的路径描述。这意味着 BGP 使用的是路径矢量算法,而不是距离矢量算法。

可达网络的每次通信都提供了关于到达目的地的整个路由器序列的大量信息。由于包含拓扑信息,路径向量协议有时被描述为距离向量算法和链路状态算法的组合。然而,这并不真正公正,因为它们并不像这两种算法类型那样工作。(如果你对路径向量算法的更多信息感兴趣,可以在 RFC 1322,“跨域路由的统一方法”中找到一些信息。(警告:在操作重型机械之前不要阅读。)

到每个路由的路径信息以 BGP 路径属性的形式存储在每个 BGP 发言人的 RIB 中。这些属性用于在 BGP 设备发送更新消息时向网络宣传路由。路径属性的存储、处理、发送和接收是路由器决定如何创建路由的方法,因此理解它们显然非常重要。

存在几种不同的路径属性,每种属性都描述了路由的特定特征。根据其重要性和特定的管理规则,属性被分为不同的类别。最重要的路径属性被称为已知属性;每个 BGP 发言人都必须识别和处理这些属性,但只有一些需要在每个路由中发送。其他属性是可选的,可能或不实现。这些属性进一步根据它们在由不识别它们的设备接收时的处理方式来区分。

BGP 路径属性类别

路径属性的四种正式分类如下:

已知强制性 这些是最重要的路径属性。它们必须包含在更新消息中的每个路由描述中,并且必须由接收它们的每个 BGP 设备进行处理。

已知任意性 如果收到,BGP 设备必须识别这些路径属性,但它们可能包含在更新消息中,也可能不包含。因此,对于信息发送者来说,它们是可选的,但对于信息接收者来说,它们是必须处理的。

可选传递性 这些路径属性可能被 BGP 路由器识别,并可能包含在更新消息中。在宣传路由时,即使由不识别该属性的设备接收,也必须传递给其他 BGP 发言者。

可选非传递性 可选属性可能被 BGP 设备识别,并可能包含在更新消息中。如果被不识别该属性的设备接收,则会被丢弃,不会传递给下一个路由器。

小贴士

关键概念 与仅存储有限关于如何到达网络信息的简单路由协议不同,BGP 存储了关于到达各种网络的完整路由的详细信息。这些信息以路径属性的形式存在,描述了通过连接路由器到目的网络连接的 AS 的各种特征。

注意

正如你可能想象的那样,所有已知的属性在定义上都是传递性的——它们必须从一台 BGP 发言人传递到下一台

BGP 路径属性特征

表 40-3 提供了描述到目的地路由的每个最常见 BGP 路径属性的特征摘要。它还提供了分配给 BGP 更新消息中每个特征的属性类型代码的摘要。

表 40-3. BGP 路径属性摘要

BGP 路径属性 分类 属性类型 值 描述
起源 已知强制 1 指定路径信息的来源。此属性指示路径最初是否来自内部路由协议、较老的外部路由协议或其他来源。
AS 路径 已知强制 2 描述通过该路由描述已通过的 AS 序列的 AS 号码列表。这是一个至关重要的属性,因为它包含到达网络的实际 AS 路径。它用于计算路由和检测路由循环。
下一个跃点 已知强制 3 用于到达此目的地的下一个跃点路由器。
多出口度量(MED) 可选非传递 4 当路径包含多个进入或离开 AS 的出口或入口点时,此值可以用作区分它们的度量(即,选择一个出口或入口点而不是其他)。
本地优先级 已知任意 5 用于同一 AS 内 BGP 发言人间通信,以指示对特定路由的优先级水平。
原子聚合 已知任意 6 在某些情况下,BGP 发言人可能会接收到一组重叠的路由,其中一个是比另一个更具体的。例如,考虑一个到网络 34.15.67.0/24 和网络 34.15.67.0/26 的路由。后者是前者的子集,使其更具体。如果 BGP 发言人使用较不具体的路由(在这种情况下,34.15.67.0/24),它将此路径属性设置为 1,以指示已这样做。
聚合器 可选传递 7 包含执行路由聚合的路由器的 AS 号码和 BGP ID;用于故障排除。

这些路径属性中的一些是直接的;其他则是相当晦涩难懂,可能令人困惑。深入探讨路径属性将引导我们进入详细描述跨 AS 路由计算的全面描述。我们将在下一节中在一定程度上探讨这一点。

BGP 路由确定和 BGP 决策过程

你现在已经了解了 BGP 设备如何存储和管理网络路由信息的基本原理。这包括了对 BGP 发言人执行的四个路由信息管理活动的概述:路由存储、更新、选择和公告。路由存储是每个 BGP 发言人的 RIB 的功能。路径属性是 BGP 存储关于路由的详细信息并描述这些细节给 BGP 对等体的机制。

BGP 决策过程阶段

正如你所见,RIB 还包含用于存储从 BGP 对等体接收到的输入信息的部分,以及用于存储每个 BGP 设备想要发送给这些对等体的输出信息。路由更新、选择和公告的功能涉及分析这些输入信息。它们还决定在本地数据库中包含什么,更新该数据库,然后从其中选择要发送给对等设备的路由。在 BGP 中,一个称为决策过程的机制负责这些任务。它包括三个总体阶段:

第一阶段 从相邻 AS 中的 BGP 发言人所接收到的每个路由都会被分析并分配一个优先级。然后,根据优先级对这些路由进行排序,并选择每个 AS 内向其他 BGP 发言人公告的最佳路由。

第二阶段 根据优先级从传入数据中选择每个目的地的最佳路由,并使用它来更新本地路由信息库(Loc-RIB)。

第三阶段 从 Loc-RIB 中选择路由发送到其他 AS 中的相邻 BGP 发言人。

分配路由优先级的标准

显然,如果 BGP 发言人只知道一个网络的单一路由,它将安装并使用该路由(假设没有问题)。当 BGP 发言人收到特定网络的多条路由时,分配路由优先级才变得重要。优先级可以根据许多不同的标准确定。以下是一些典型的标准:

  • 路由器与网络之间的 AS 数量(通常越少越好)。

  • 存在某些可能使某些路由不可用的策略;例如,一个路由可能穿过一个 BGP 发言人不愿意与其数据信任的 AS。

  • 路径的起源——即它从何而来。

在一组到达同一网络的路由都被计算为具有相同优先级的情况下,将使用一种决断方案从中选择。额外的逻辑用于处理特殊情况,例如重叠网络的情况(例如,在表 40-3 中对 Atomic_Aggregate 路径属性的描述中可以看到这种情况的例子)。

在第 3 阶段向其他路由器传播路由的选择基于一个相当复杂的算法,我无法在这里充分解释。路由公告受到我在本章前面讨论的路由策略的指导。与外部对等体相比,用于向内部对等体公告路由的规则不同。

小贴士

关键概念 BGP 发言人用来确定从其对等体接受哪些新路由以及向其公告哪些路由的方法被称为BGP 决策过程。这是一个涉及基于现有路径信息和传入路径信息计算最佳路由的复杂算法,分为三个阶段。

BGP 选择高效路由的能力的限制

在考虑路由选择时,非常重要的一点是要记住 BGP 是一种在 AS(自治系统)之间运行的路由协议。因此,路由是在 AS 之间选择的,而不是在 AS 内部单个路由器级别上选择的。所以,例如,当 BGP 存储关于到达某个网络的路径信息时,它将其存储为一系列 AS,而不是一系列特定的路由器。

BGP 无法处理 AS 内的单个路由器,因为根据定义,AS 内部发生的事情的细节应该对外界保密。它不知道其自身之外 AS 的结构。这对 BGP 选择路由有重要影响:BGP 不能保证它会为每个网络选择最快、成本最低的路由。它可以选择一个最小化其与特定网络之间 AS 数量的路由,但当然,AS 并不都是一样的。一些 AS 很大,由许多慢速链路组成;而另一些 AS 则较小且速度快。选择通过两种后一种类型的 AS 的路由将比选择通过前一种类型的 AS 的路由更好,但 BGP 无法知道这一点。可以使用策略在一定程度上影响 AS 选择,但总的来说,由于 BGP 不知道 AS 内部发生的事情,它不能保证路由的整体效率。(顺便说一句,这也是为什么 BGP 中没有一般成本或距离路径属性的原因。)

小贴士

关键概念 作为一种外部路由协议,BGP 在 AS 级别运行。它的路由是基于 AS 之间的路径计算的,而不是单个路由器。由于 BGP,根据定义,不知道 AS 内路由器的内部结构,因此它不能确定在给定的 AS 中发送数据报的成本。这意味着 BGP 不能总是保证它将选择任何两个网络之间的绝对最低成本的路径。

发起新的路由和撤回不可达的路由

自然地,存在一种设施,允许 BGP 发言人发起到达网络的新的路由。BGP 发言人可以从直接连接的 AS 上的内部路由协议中获得有关新路由的知识,然后它可以选择与其他 AS 共享此信息。它将为该网络创建一个新的条目并将其发送给其他 BGP 对等体。

BGP 还包括一种机制来宣传它无法到达的路由。这些被称为不可行或撤回的路由,并在 Update 消息中提及,以表明路由器无法再到达特定的网络。

BGP 的一般操作和消息

在前面的章节中,您已经看到了 BGP 如何存储有关路由的信息,以及它是如何使用这些信息来确定到达各种网络的路径。现在,让我们从一般的角度来了解一下 BGP 的操作。像本书中介绍的其他许多协议一样,BGP 的操作主要可以通过消息的形式来描述。消息的使用是 BGP 对等体之间传递路由信息的手段。这最终使得如何到达网络的知识在整个互联网中传播开来。

演讲者指定和连接建立

在开始消息之前,BGP 发言人必须被指定并连接在一起。BGP 标准没有指定如何确定相邻发言人;这必须在协议之外完成。一旦完成,AS 就被连接到一个启用了 BGP 的互联网中。拓扑链接提供了物理连接和使数据报在 AS 之间流动的手段。此时,舞池已经准备好了,但没有人跳舞;BGP 可以工作,但尚未开始运行。

BGP 的操作从 BGP 对等体形成传输协议连接开始。BGP 使用 TCP 作为其可靠的传输层,因此两个 BGP 发言人建立了一个在后续消息交换过程中保持的 TCP 会话。当这样做之后,每个 BGP 发言人发送一个 BGP Open 消息。这个消息就像一个舞会邀请,它开始了在设备之间设置 BGP 链接的过程。在这个消息中,每个路由器都标识了自己及其 AS,并告诉其对等体它希望用于链接的参数。这包括认证参数的交换。假设每个设备都认为其对等体的 Open 消息内容是可以接受的,它将通过 Keepalive 消息进行确认,然后 BGP 会话开始。

在正常情况下,大多数 BGP 发言者将与多个其他 BGP 发言者保持同时会话,这些会话既在发言者自己的 AS 内,也在其 AS 外。AS 之间的链接使得 BGP 路由器能够学习如何在互联网中路由。AS 内部的链接对于确保 AS 中的每个 BGP 发言者保持一致的信息非常重要。

路由信息交换

假设链路已初始化,两个对等体开始一个持续的过程,告诉对方他们所了解的网络以及如何到达这些网络。每个 BGP 发言者将其 RIB 中的信息编码成 BGP 更新消息。这些消息包含已知网络地址列表,以及关于到达各种网络路径的信息,正如您已经看到的,这些信息以路径属性的形式描述。然后,这些信息被用于路由确定,如前所述。

当两个对等体之间首次建立连接时,这些对等体会通过交换它们的完整路由表来确保每个路由器持有完整的信息。随后,会发送更新消息。这些消息只包含关于已更改路由的增量更新。根据需要仅交换更新信息可以减少网络上的不必要带宽,从而使 BGP 比如果它定期发送完整的路由表信息更有效率。

连通性维护

BGP 之间的 TCP 会话可以保持很长时间开放。只有当路由发生变化时才需要发送更新消息,这些变化通常很少发生。这意味着更新消息的传输之间可能经过许多秒。

为了确保对等体之间保持联系,当它们没有其他信息要发送时,它们都会定期发送 Keepalive 消息。这些是空消息,不包含数据,只是告诉对等设备“我还在这里。”这些消息发送得不太频繁——不超过每秒一次——但足够规律,以至于对等体不会认为会话被中断。

错误报告

最后一种 BGP 消息是 BGP 通知消息。这是一个错误消息;它告诉对等体发生了问题,并描述了错误条件的性质。在发送 BGP 通知消息后,发送该消息的设备将终止对等体之间的 BGP 连接。然后需要协商一个新的连接,可能是在导致通知消息的问题得到纠正之后。

小贴士

关键概念 BGP 通过 BGP 发言人之间交换四种不同的消息类型来实现。BGP 会话从两个路由器之间建立 TCP 连接并相互发送 Open 消息开始。BGP 更新消息是设备之间交换路由信息的主要机制。小的 BGP 保活消息用于在需要交换信息期间保持设备之间的通信。最后,通知消息用于问题报告。

BGP 详细消息、操作和消息格式

到目前为止,我已经讨论了 BGP 的概念和一般操作。为了更好地理解 BGP 的确切工作方式,详细查看其四种不同的消息类型——Open(打开)、Update(更新)、Keepalive(保活)和 Notification(通知)——以及它们的使用方法是非常有帮助的。在这个过程中,我们可以检查每种消息类型中的字段,以便你不仅能理解消息是如何完成的,还能理解路由数据是如何实际传递的。让我们从描述 BGP 消息生成和传输的常见属性以及所有 BGP 消息使用的通用格式开始。

BGP 消息生成和传输

每个运行 BGP 的路由器都会生成消息以实现协议的各种功能。其中一些消息在 BGP 软件的正常操作过程中定期创建。这些通常由设置和倒计时的计时器控制,以使它们被发送。其他消息是在接收到来自 BGP 对等体的消息后发送的,可能是在处理步骤之后。

与大多数其他路由协议不同,BGP 从一开始就被设计为使用可靠的消息传递方法。TCP 存在于每个互联网协议(IP)路由器的软件中,因此在 TCP/IP 互联网中进行可靠的数据通信时,它显然是最佳选择,这也是 BGP 所使用的。路由协议通常被认为是第 3 层的一部分,但这个协议是在第 4 层协议上运行的,因此 BGP 是架构模型最好仅作为指南的绝佳例子。

TCP 通过处理会话设置和管理的大部分细节,为 BGP 提供了众多优势,从而使得 BGP 能够专注于需要发送的数据。TCP 负责会话设置和协商、流量控制、拥塞处理以及丢失消息的必要重传,从而确保消息被接收并确认。BGP 使用众所周知的 TCP 端口 179 进行连接。

BGP 通用消息格式

TCP 的使用也对 BGP 消息的结构方式产生了有趣的影响。当你查看 BGP 消息格式(你很快就会看到)时,一个突出的问题是 BGP 消息可以具有奇数个字节。大多数路由协议以 4 或 8 字节为单位进行尺寸划分,但由于 TCP 以八位组流的形式发送数据,因此 BGP 消息不需要在 32 位或 64 位边界上断开。另一个影响是需要一个特殊的标记字段来帮助确保 BGP 消息可以在 TCP 流中区分开来(稍后将有更多关于这个问题的讨论)。

与大多数消息协议一样,BGP 为其四种消息类型中的每一种都使用一个通用的消息格式。每个 BGP 消息在概念上分为一个头部和一个主体(在 BGP 标准中称为 数据部分)。头部有三个字段,长度固定为 19 字节。主体长度可变,在 Keepalive 消息中完全省略,因为它们不需要它。

所有 BGP 消息类型的通用格式显示在 表 40-4 中,并在 图 40-2 中说明。

表 40-4. BGP 通用消息格式

字段名称 大小(字节) 描述
标记 16 每条 BGP 消息开始处的这个大字段用于同步和认证。
长度 2 消息的总长度(以字节为单位),包括头部字段。此字段的最低值为 19(用于 Keepalive 消息);可能高达 4096。
类型 1 表示 BGP 消息类型:1 = Open2 = Update3 = Notification4 = Keepalive
消息体/数据部分 可变 包含用于实现每种消息类型(Open、Update 和 Notification)的具体字段。

BGP 通用消息格式

图 40-2. BGP 通用消息格式

标记字段是 BGP 消息格式中最有趣的一个。它用于同步和认证。BGP 使用单个 TCP 会话连续发送多个消息。TCP 是一种面向流的传输协议,它发送字节穿越链路,而不了解这些字节代表什么。这意味着使用 TCP 的协议负责决定数据单元之间的界限在哪里——在这种情况下,BGP 消息。

通常,长度字段告诉每个 BGP 设备在哪里划分一条线,从一条消息的结束到下一条消息的开始。然而,由于各种条件,设备可能会失去对消息边界的跟踪。标记字段填充了一个可识别的模式,清楚地标记了每条消息的开始;BGP 对等体通过寻找这个模式来保持同步。

在建立 BGP 连接之前,标记字段被填充为全 1。因此,这是 Open 消息使用的模式。一旦协商了 BGP 会话,如果两台设备之间就认证方法达成一致,标记字段将承担额外的认证角色。BGP 设备不再寻找包含全 1 的标记字段,而是寻找使用约定的认证方法生成的模式。检测到这个模式同时同步设备并确保消息是真实的。

在极端情况下,BGP 对等体可能无法保持同步,如果是这样,将生成一个通知消息并关闭会话。如果启用认证时标记字段包含错误数据,也会发生这种情况。

小贴士

关键概念 所有四种 BGP 消息类型都使用一种通用的消息格式,该格式包含三个固定头部字段——标记、长度和类型——以及用于不同消息类型的不同消息体的空间。大的标记字段用于表示新 BGP 消息的开始,并且它还用于简化 BGP 认证方法。

BGP 连接建立:Open 消息

在可以使用 BGP 会话交换路由信息之前,必须在 BGP 对等体之间建立连接。这个过程从设备之间创建 TCP 连接开始。一旦完成,BGP 设备将通过交换 BGP Open 消息来尝试创建 BGP 会话。

BGP 开放消息功能

Open 消息有两个主要目的。第一个是识别和初始化两个设备之间的连接;它允许一个对等体告诉另一个,“我是一个名为 X 的 BGP 说话人,在 AS Y 上,我想与你开始交换 BGP 信息。”第二个是协商会话参数。这些是 BGP 会话将如何进行的条款。使用 Open 消息协商的一个重要参数是每个设备想要用于认证的方法。BGP 的重要性意味着为了防止不良信息或恶意人员破坏路由,认证是必不可少的。

每个接收 Open 消息的 BGP 都会处理它。如果消息的内容是可以接受的,包括其他设备想要使用的参数,它将以确认消息的形式响应。每个对等体必须发送一个 Open 消息并接收一个 Keepalive 确认消息,以便初始化 BGP 连接。如果任一对等体不愿意接受 Open 消息的条款,则不会建立连接。在这种情况下,可能会发送一个通知消息来传达问题的性质。

BGP 开放消息格式

BGP Open 消息的具体格式显示在表 40-5 和图 40-3 中。

表 40-5. BGP 开放消息格式

Field Name Size (Bytes) 描述
Marker 16 每个 BGP 消息开头的这个大字段用于同步和认证。
Length 2 消息的总长度(以字节为单位),包括头部字段。Open 消息的长度是可变的。
Type 1 BGP 消息类型;值为 1 表示 Open 消息。
Version 1 表示发送 Open 消息的发送者使用的 BGP 版本。此字段允许设备拒绝与使用它们可能无法理解的版本的设备建立连接。当前值为 4,用于 BGP-4,并被大多数,如果不是所有,当前的 BGP 实现所使用。
My Autonomous System 2 识别发送 Open 消息的发送者的 AS 号。AS 号在互联网上以类似于 IP 地址管理的方式集中管理。
Hold Time 2 此设备提议用于 BGP 保持计时器的秒数,该计时器指定 BGP 对等体允许在接收到 BGP 消息后连接保持沉默的时间。如果 BGP 设备不喜欢其对等体建议的值,它可能会拒绝连接;然而,通常两个设备会同意使用每个设备建议的值中的较小者。该值必须至少为 3 秒,或 0。如果为 0,则指定不使用保持计时器。有关保持计时器的更多使用信息,请参阅本章后面的 Keepalive 消息讨论。
BGP Identifier 4 识别特定的 BGP 说话者。您会记得,IP 地址与接口相关联,而不是与设备相关联,因此每个路由器至少有两个 IP 地址。通常,BGP 标识符被选择为这些地址之一。一旦选择,此标识符就用于与 BGP 对等体的所有 BGP 通信。这包括从选择标识符的接口上的 BGP 对等体,以及其他接口上的 BGP 对等体。因此,如果一个具有两个接口的 BGP 说话者有 IP1 和 IP2 地址,它将选择其中一个作为其标识符,并在其两个接口上使用它。
Opt Parm Len 1 用于可选参数的字节数(见下一条记录)。如果为 0,则此消息中没有可选参数。
Optional Parameters 可变 允许 Open 消息在 BGP 会话设置期间通信任意数量的额外参数。每个参数都使用一个相当标准的类型/长度/值三元组进行编码,如表 40-6 所示。

表 40-6. BGP Open 消息可选参数

Subfield Name Size (Bytes) 描述
Parm Type 1 参数类型:可选参数的类型。目前只定义了一个值,1,用于认证信息。
Parm Length 1 参数长度:指定参数值子字段的长度(因此,此值是整个参数的长度减去 2)。
参数值 可变 参数值:正在通信的参数的值。

BGP 开放消息目前仅使用一个可选参数:认证信息。其参数值子字段包含一个字节的认证代码子子字段,指定设备希望使用的认证类型。随后是一个可变长度的认证数据子子字段。认证代码指定了如何执行认证,包括认证数据字段的含义,以及如何计算标记字段。

提示

关键概念 BGP 会话从连接中的每个对等体向另一个发送 BGP 开放消息开始。此消息的目的是在设备之间建立联系,识别消息的发送者和其 AS,并协商重要的参数,这些参数决定了会话的进行方式。

BGP 路由信息交换:更新消息

一旦 BGP 说话者建立了联系并使用开放消息建立了链接,设备就开始实际交换路由信息的过程。每个 BGP 路由器使用本章前面描述的 BGP 决策过程来选择某些要通告给其对等体的路由。然后,这些信息被放入 BGP 更新消息中,这些消息被发送到已建立会话的每个 BGP 设备。这些消息是网络可达性知识在互联网中传播的方式。

BGP 开放消息格式

图 40-3. BGP 开放消息格式

BGP 更新消息内容

每个更新消息包含以下一个或两个:

路由通告 单个路由的特性。

路由撤销 一系列不再可达的网络。

更新消息中只能通告一个路由,但可以撤销多个。这是因为撤销路由很简单;只需要移除路由的网络地址。相比之下,路由通告需要描述一组相当复杂的路径属性,这需要占用相当大的空间。(注意,更新消息可以仅指定撤销的路由,而不通告任何路由。)

BGP 更新消息格式

由于它包含的信息量及其复杂性,BGP 更新消息使用 TCP/IP 中最复杂的结构之一。消息的基本结构在表 40-7 中描述,并在图 40-4 中说明。正如您可以从表中看到的,几个字段有自己的子结构。路径属性字段具有复杂的子结构,我在其他表中单独展示了它。

表 40-7. BGP 更新消息格式

字段名称 大小(字节) 描述
标记 16 每个 BGP 消息开头的这个大字段用于同步和认证。
长度 2 消息的总长度,以字节为单位,包括头部字段。更新消息的长度是可变的。
类型 1 BGP 消息类型;值为 2 表示更新消息。
不可行路由长度 2 退回路由字段长度,以字节为单位。如果为 0,则没有路由被退回,并且退回路由字段被省略。
退回路由 可变 指定正在从使用中退回路由的网络地址。每个地址使用两个子字段指定。1 字节长度的长度字段是 IP 地址前缀子字段中有效的位数。可变长度的前缀子字段是正在退回路由的网络的前缀 IP 地址。如果前缀中的位数不是 8 的倍数,则此字段用零填充,以便落在字节边界上。如果前一个长度字段为 8 或更少,则此字段长度为 1 字节;如果为 9 到 16,则长度为 2 字节;如果为 17 到 24,则长度为 3 字节;如果为 25 或更大,则长度为 4 字节。
总路径属性长度 2 路径属性字段的长度,以字节为单位。如果为 0,表示在此消息中没有广告路由,因此省略路径属性和网络层可达性信息。
路径属性 可变 描述广告路由的路径属性。由于某些属性需要比其他属性更多的信息,因此使用灵活的结构来描述属性,以最小化与使用固定字段相比的消息大小,而固定字段通常为空。不幸的是,这也使得字段结构变得复杂。每个属性都有表 40-8 中显示的子字段。
网络层可达信息 (NLRI) 可变 包含正在宣布的路由的 IP 地址前缀列表。每个地址都使用与用于撤回路由相同的通用结构进行指定。1 字节长度子字段是前缀子字段中有效位数的数量。可变长度前缀子字段是正在宣布路由的网络的前缀 IP 地址。如果前缀中的位数不是 8 的倍数,则在此字段中填充零,以便它落在字节边界上。如果前面的长度字段为 8 或更少,则此字段长度为 1 字节;如果为 9 到 16,则长度为 2 字节;如果为 17 到 24,则长度为 3 字节;如果为 25 或更大,则长度为 4 字节。与更新消息中的大多数其他字段不同,NLRI 字段的长度不是明确声明的。它是从整体消息长度字段中减去其他明确指定的字段长度计算得出的。

表 40-8. BGP 更新消息路径属性

子字段名称 大小(字节) 描述
属性类型 2 定义属性类型并对其进行描述。此子字段本身具有两级子结构,包括属性类型标志和属性类型代码,因此甚至无法在这里全部展示!请参阅表格 表 40-9 和 表 40-10 以获取详细信息。
属性长度 1 或 2 属性的字节数。此字段通常为 1 字节,因此允许字段长度最多为 255 字节。对于更长的属性,设置扩展长度标志(见 表 40-9),表示此属性长度字段为 2 字节,对于长度最多为 65,535 字节的属性。
属性值 可变 属性的值。此字段的大小和含义取决于路径属性的类型。例如,对于起源属性,它是一个表示路由起源的单个整数值;对于 AS_Path 属性,此字段包含到达网络的路径中 AS 的可变长度列表。

BGP 更新消息格式 此图显示了完整的 BGP 更新消息格式,包括一组撤回路由、路径属性和 NLRI 条目。分解视图显示了路径属性中属性类型子字段的子结构,如表格和 . 中所述。

图 40-4. BGP 更新消息格式此图显示了完整的 BGP 更新消息格式,包括一组已撤销的路由、路径属性和 NLRI 条目。分解视图显示了路径属性字段属性类型子字段的子结构,如表 40-9 和表 40-10 中所述。

表 40-9 显示了路径属性字段属性类型子字段的属性标志子子字段的结构。此子字段包含一组标志,用于描述属性的性质以及如何处理它。您可能需要参考本章前面“BGP 路径属性和算法概述”部分中的路径属性描述来理解这些标志。

表 40-9. BGP 更新消息属性标志

子子子字段名称 大小(字节) 描述
可选 1/8 (1 bit) 对于可选属性设置为 1;对于已知属性设置为 0。
传递 1/8 (1 bit) 对于可选传递属性设置为 1;对于可选非传递属性设置为 0。对于已知属性始终设置为 1。
部分信息 1/8 (1 bit) 当为 1 时,表示有关可选传递属性的信息是部分信息。这意味着由于它是可选的且传递的,所以经过路径的其中一个或多个路由器没有实现该属性,但被迫传递它,因此关于它的信息可能缺失(未由未识别它的路由器提供,但只是传递)。如果为 0,则表示信息是完整的。此位仅对可选传递属性有意义;对于已知或非传递属性,它为 0。
扩展长度 1/8 (1 bit) 对于长属性设置为 1,以指示属性长度字段大小为 2 字节。通常为 0,表示属性长度字段为单字节。
保留 4/8 (4 bits) 设置为 0 并忽略。

路径属性字段属性类型子字段的属性类型子子字段包含一个数字,用于标识属性类型。表 40-10 显示了当前值。

表 40-10. BGP 更新消息属性类型代码

属性类型
1 Origin
2 AS_Path
3 Next_Hop
4 Multi_Exit_Disc (MED)
5 Local_Pref
6 Atomic_Aggregate
7 Aggregator

虽然我之前说过更新消息只广告一条路由,但似乎在网络层可达信息(NLRI)字段中可以有多于一个前缀,这可能会让人感到困惑。实际上,这里并没有不一致之处。单条路由可能关联多个网络;换句话说,多个网络可能有相同的路径和路径属性。在这种情况下,在同一个更新消息中指定多个网络前缀比为每个网络生成一个新的更有效。

小贴士

关键概念 BGP 中最重要的消息类型是更新消息,它用于发送 BGP 设备之间路由的详细信息。它使用一种复杂的结构,允许 BGP 说话者有效地指定新路由、更新现有路由以及撤回不再有效的路由。每条消息可能包括一条现有路由的完整描述,也可能撤回多条路由的使用。

BGP 连通性维护:保活消息

一旦使用 Open 消息建立 BGP 连接,BGP 对等体最初将使用更新消息相互发送大量路由信息。然后,它们将进入一个常规流程,维护 BGP 会话,但仅在需要时发送更新消息。由于这些更新对应于路由变化,而路由变化通常是很少发生的,这意味着在连续的更新消息之间可能经过许多秒。

BGP 保活消息间隔

保持计时器和当 BGP 对等体等待接收下一个更新消息时,它就像是被电话中的某人挂起一样。现在对我们来说,几秒钟可能不算什么,但对计算机来说,它们是非常长的时间。就像你一样,被挂起太久的 BGP 说话者可能会变得不耐烦,并开始怀疑对方是否挂断了电话。计算机不会因为被挂起而生气,但它们可能会怀疑是否出现了导致连接中断的问题。

为了跟踪已保持多长时间,每个 BGP 设备维护一个特殊的 保持计时器。每次其对等体发送 BGP 消息时,都会将其设置为初始值。计时器随后倒计时,直到收到下一个消息,然后重置。如果保持计时器过期,则假定连接已被中断,BGP 会话被终止。

保持计时器的长度作为会话设置的一部分通过 Open 消息协商。它必须至少为三秒长,或者可以协商为零的值。如果为零,则不使用保持计时器;这意味着设备有无限的耐心,不关心消息之间经过多少时间。

为了确保计时器不会在长时间内不需要发送更新消息的情况下超时,每个对等方会定期发送 BGP Keepalive 消息。正如其名所示:该消息只是保持 BGP 连接活跃。Keepalive 消息的发送速率取决于实现方式,但标准建议它们以保持计时器值的三分之一为间隔发送。因此,如果保持计时器的值为三秒,则每个对等方每秒发送一个 Keepalive 消息(除非在该秒需要发送其他类型的消息)。为了防止过度使用带宽,Keepalive 消息必须每秒发送一次,因此这是最小间隔,即使保持计时器的值小于三秒。

BGP Keepalive 消息格式

Keepalive 消息的重点是消息本身;没有要传达的数据。实际上,我们希望消息简短明了。因此,它实际上是一个只包含 BGP 头部(在那么长的更新消息格式之后是一种很好的变化)的虚拟消息。Keepalive 消息的格式在表 40-11 和图 40-5 中显示。

表 40-11. BGP Keepalive 消息格式

字段名称 大小(字节) 描述
标记 16 每个 BGP 消息开头的这个大字段用于同步和认证。
Length 2 消息的总长度(字节),包括头部字段。Keepalive 消息的长度固定为 19 字节。
类型 1 BGP 消息类型;对于 Keepalive 消息,值为 4。

BGP Keepalive 消息格式

图 40-5. BGP Keepalive 消息格式

Keepalive 消息也有特殊用途:它们确认在初始 BGP 会话设置期间收到了有效的 Open 消息。

小贴士

关键概念 BGP Keepalive 消息在空闲期间定期发送,在这些期间不需要在连接的 BGP 发言人之间发送实际信息。它们仅用于保持会话活跃,因此只包含 BGP 头部而没有数据。

BGP 错误报告:通知消息

一旦建立,BGP 会话将保持开启状态一段时间,允许设备之间定期交换路由信息。在操作过程中,可能会出现某些错误条件,可能会干扰 BGP 对等方之间的正常通信。

BGP 通知消息功能

出现的一些错误条件足够严重,以至于必须终止 BGP 会话。当这种情况发生时,检测到错误的设备将通过发送 BGP 通知消息来告知其对等方的错误性质,然后关闭连接。

当然,有人告诉你“我发现了一个错误,所以我退出了”并没有太大的价值。因此,BGP 通知消息包含多个字段,提供有关导致消息发送的错误性质的信息。这包括一组主要错误代码以及一些错误代码中的子代码。根据错误的性质,还可能包含一个额外的数据字段,以帮助诊断问题。

除了使用通知消息来传达错误的发生之外,此消息类型还用于其他目的。例如,如果两个设备无法就如何协商会话达成一致,这严格来说并不是错误。通知消息还用于允许设备出于与错误无关的原因终止 BGP 会话。

BGP 通知消息格式

BGP 通知消息的格式在表 40-12 中详细说明,并在图 40-6 中展示。 |

表 40-12. BGP 通知消息格式

字段名称 大小(字节) 描述
标记 16 每个 BGP 消息开头的这个大字段用于同步和认证。
长度 2 消息的总长度(字节),包括头部字段。通知消息的长度是可变的。
类型 1 BGP 消息类型;对于通知消息,值为 3。
错误代码 1 指定错误的通用类别。表 40-13 显示了可能的错误类型及其简要描述。
错误子代码 1 为三个错误代码值提供对错误原因的更具体指示。此字段对于每个错误代码值的可能值显示在表 40-14 中。
数据 变量 包含帮助诊断错误的附加信息。其含义取决于错误代码和错误子代码字段中指定的错误类型。在大多数情况下,此字段填充了导致错误发生的任何不良值。例如,对于“消息头错误/错误消息类型”错误,错误的类型字段值被放置在这里。

BGP 通知消息格式

图 40-6. BGP 通知消息格式

表表 40-13 和表 40-14 显示了错误代码和错误子代码字段允许的值,从而提供了通知消息可以报告的错误类型的良好总结。它们还展示了消息类型的其他非错误用途。

表 40-13. BGP 通知消息错误代码

错误代码值 代码名称 描述
1 消息头错误 检测到 BGP 头的内容或长度存在问题。错误子代码字段提供了关于问题性质的更多详细信息。
2 开启消息错误 在开启消息体中发现了问题。错误子代码字段详细描述了问题。注意,认证失败或无法就保持时间等参数达成一致的情况也包括在内。
3 更新消息错误 在更新消息体中发现了问题。同样,错误子代码字段提供了更多信息。许多属于此代码的问题都与更新消息中检测到的路由数据或路径属性问题相关,因此这些消息向发送错误数据的设备提供了有关此类问题的反馈。
4 保持计时器超时 在保持时间到期之前没有收到消息。有关此计时器的详细信息,请参阅本章前面关于保持消息的描述。
5 有限状态机错误 BGP 有限状态机指的是对等体上的 BGP 软件根据事件(有关此概念的一些背景信息,请参阅第四十七章中关于 TCP 有限状态机的描述)从一个操作状态移动到另一个操作状态的机制。如果发生对当前状态的对等体来说意外的事件,它将生成此错误。
6 停止 当 BGP 设备因与错误代码中描述的其他错误条件无关的原因想要断开与对等体的连接时使用。

表 40-14. BGP 通知消息错误子代码

错误类型 错误子代码值 子代码名称 描述
消息头错误(错误代码 1) 1 连接未同步 标记字段中的预期值未找到,表明连接已不同步。请参阅 BGP 通知消息格式中标记字段的描述。
2 消息长度错误 消息长度小于 19 字节,大于 4096 字节,或者与预期消息类型不一致。
3 消息类型错误 消息的类型字段包含一个无效的值。
打开消息错误(错误代码 2) 1 不支持版本号 设备不支持其对等方试图使用的版本号。
2 错误的 Peer AS 路由器不识别对等方的 AS 号或不愿意与其通信。
3 错误的 BGP 标识符 BGP 标识符字段无效。
4 不支持的可选参数 消息中的可选参数是接收者不理解的。
5 认证失败 认证信息可选参数中的数据无法进行认证。
6 不可接受的保持时间 路由器拒绝打开会话,因为其对等方在其 Open 消息中指定的提议保持时间不可接受。
更新消息错误(错误代码 3) 1 属性列表格式错误 消息路径属性的总体结构不正确,或者属性出现了两次。
2 不可识别的已知属性 必须的已知属性之一未被识别。
3 缺少的已知属性 必须的已知属性之一未指定。
4 属性标志错误 一个属性有一个设置为与属性类型代码冲突的标志。
5 属性长度错误 属性的长度不正确。
6 无效的起源属性 Origin 属性具有未定义的值。
7 AS 路由环路 检测到路由环路。
8 无效的 Next_Hop 属性 Next_Hop 属性无效。
9 可选属性错误 在可选属性中检测到错误。
10 无效的网络字段 网络层可达信息字段不正确。
11 AS_PATH 格式错误 AS_Path 属性不正确。

注意,可能具有讽刺意味的是,没有机制可以报告通知消息本身的错误。这可能是由于在发送此类消息后,通常终止了连接。

提示

关键概念 BGP 通知消息用于 BGP 对等体之间的错误报告。每个消息都包含一个错误代码字段,指示发生了哪种类型的问题。对于某些错误代码字段,错误子代码字段提供了有关问题具体性质的额外详细信息。尽管这些字段名称如此,通知消息也用于其他类型的特殊非错误通信,例如终止 BGP 连接。

第四十一章。其他路由协议

无标题图片

路由信息协议(RIP)、开放最短路径优先(OSPF)和边界网关协议(BGP)——如前几章所述——是 TCP/IP 协议族中最著名的三个路由协议。但还有几个其他的 TCP/IP 路由协议,它们可以分为两大类。一些协议现在不再使用,但从历史角度来看仍然有趣。其他是一些专有的 RIP 和 OSPF 替代品,你可能在今天的网络世界中偶尔会遇到。

在本章中,我简要介绍了五种额外的 TCP/IP 路由协议。我首先回顾了两个在早期互联网中扮演重要角色的过时内部路由协议:网关到网关协议(GGP)和 HELLO 协议。然后,我描述了两个内部路由协议(由思科系统开发),这些协议有时在业界被视为 RIP 和 OSPF 的替代品:内部网关路由协议(IGRP)和增强型内部网关路由协议(EIGRP)。最后,我讨论了外部网关协议(EGP),这是在 BGP 之前的外部路由协议。

TCP/IP 网关到网关协议(GGP)

在第三十七章中,我描述了 TCP/IP 路由架构的演变。现代互联网基于独立自治系统(AS)的概念,这些系统在其内部运行内部路由协议,在其之间运行外部路由协议。然而,早期的互联网相对简单。它由相对较少的核心路由器组成,这些路由器携带有关整个互联网的详细信息,以及非核心路由器,它们只知道整个互联网的部分信息,并位于核心周围。

这些核心路由器使用一种特殊的路由协议进行通信,称为网关到网关协议(GGP)。Bolt、Beranek 和 Newman 是互联网和 TCP/IP 的先驱之一,他们在 20 世纪 80 年代初最初开发了 GGP。该协议在 1982 年 9 月发布的 RFC 823,“DARPA 互联网网关”中进行了记录。这个协议现在已经过时,但它通过引入开发者在后来的路由协议中使用的某些概念,在早期互联网中发挥了重要作用。

GGP 在一般操作上与 RIP(在第三十八章中描述)相似,因为它使用距离矢量算法来确定设备之间的最佳路由。像 RIP 一样,度量是一个简单的跳数计数,所以 GGP 会选择跳数最少的路由。尽管你看到在 RIP 中跳数并不总是路由器成本的最佳度量标准,但当时它实际上是一个相当好的路由确定方法。这是因为早期的互联网使用了当时被认为是极其缓慢的计算机和链路,因此与现代路由相比,每个跳数在发送数据所需的时间上相当昂贵。

使用 GGP 的路由器最初处于空状态。然后,它通过查看是否可以在网络上发送和接收消息来测试其本地网络的状态。每 15 秒,路由器向其每个邻居发送一个 GGP 回显消息。如果邻居收到消息,它会用一个 GGP 回显应答消息进行响应。发送回显消息的路由器如果收到一定比例(默认为 50%)的消息回复,就会认为邻居是可达的。

注意

这些消息在功能上与互联网控制消息协议版本 4(ICMPv4)的回显和回显应答消息(在第三十三章中描述)类似,但并不相同。

实际的路由信息是通过发送 GGP 路由更新消息来传递的。这些消息在本质上类似于 RIP 中使用的 RIP 响应消息。每个路由更新消息都包含了发送路由器的路由表信息,它指定了路由器可以到达的网络以及每个网络的成本(以跳数表示)。

接收到路由更新消息的路由器知道它可以到达发送更新的路由器。因此,它可以以额外跳数的成本到达其他路由器可达的所有网络。路由器使用这些信息来更新其内部的目的地表和度量表,然后在自己的连接网络上发送自己的路由更新。这样,它可以在自己的网络上传播从其他路由器获得的信息。这个过程会一直持续,直到最终,GGP 路由器的路由信息在整个互联网中传播开来,就像 RIP 中的这个过程一样。

GGP 与 RIP 之间一个有趣的不同之处在于,在 GGP 网络中,网络和成本不是成对发送的。相反,GGP 路由器以组的形式发送其路由表。如果它可以直接与三个网络通信,成本为 1,它就会将这些网络以距离值为 1 的组发送。接下来,如果 GGP 路由器可以以成本 2 到达一些网络,它就会将这些网络以距离值为 2 的组发送,依此类推。

另一个不同之处在于 GGP 路由更新消息会被确认。每个路由更新消息都会附带一个序列号,这确保了过时信息不会被传播。如果收到路由更新并且它有一个新的序列号(表示它包含最新信息),处理该路由更新的路由器会向发送者返回一个 GGP 确认消息。如果序列号表明消息已过时,则会发送一个否定确认,并丢弃该消息。

作为使用跳数作为度量标准距离矢量算法,GGP 与 RIP 共享了大部分相同的优缺点。它在简单性方面占优势,但存在许多问题,如收敛速度慢和无限计数问题。然而,GGP 比 RIP 更原始,并且不包括 RIP 中用于处理此类问题的许多功能,例如分割水平。由于 GGP 的年代久远,它也仅限于未子网化的类网络。

当互联网架构转向使用自治系统(AS)时,GGP 被淘汰。虽然它是 TCP/IP 历史的重要组成部分,但今天它并不正式被认为是 TCP/IP 协议套件的一部分。

小贴士

关键概念 网关到网关协议(GGP)曾用于在早期互联网的核心路由器之间通信路由信息。它是一种距离矢量协议,其操作方式与 RIP 非常相似。每个路由器定期向相邻路由器发送其路由表,以便每个路由器都能学习到达 AS 中每个网络的跳数成本。GGP 现在被认为是一个历史协议,不再是 TCP/IP 的一部分。

HELLO 协议(HELLO)

我们今天所知道的 TCP/IP 互联网是在几十年的时间里逐步演变的。它始于由美国国防部高级研究计划局(DARPA 或 ARPA)发起的一个实验性研究项目。该项目被称为 ARPAnet,通过添加其他网络(如国家科学基金会(NSF)开发的重要 NSFnet)而逐渐发展壮大。NSFnet 骨干网在多年的时间里不断扩展,对于最终创建现代互联网起到了关键作用。

原始的 NSFnet 骨干网由六台位于美国各地的数字设备公司(多年前被康柏公司收购)LSI-11 计算机组成。这些计算机运行了被俗称为“fuzzball”的特殊软件。这种软件使计算机能够作为路由器运行。这些 fuzzball 路由器将各种网络连接到 NSFnet 和 ARPAnet。

六个 NSFnet 路由器作为一个 AS 工作,就像任何 AS 一样,使用内部路由协议来交换路由信息。这些早期路由器使用的路由协议被称为HELLO 协议。在 20 世纪 80 年代初开发,它记录在 1983 年 12 月发布的 RFC 891,“DCN Local-Network Protocols”中。HELLO这个名字首字母大写,但它不是一个缩写;它仅仅指的是单词hello,因为该协议使用的是类似于路由器相互问候的消息。

注意

OSPF 路由协议有一个名为 Hello 的消息类型。这些消息的使用有时被称为 Hello 协议。OSPF 与本章中描述的 HELLO 协议没有直接关系,除了一个自治系统(AS)可以使用这两个协议进行路由的事实。OSPF 可能从 HELLO 协议那里借用了 Hello 这个名字

HELLO 协议使用距离矢量算法,就像 RIP 和 GGP 一样。然而,有趣的是,与 RIP 和 GGP 不同,HELLO 不使用跳数作为度量值。相反,它试图通过评估网络延迟并选择延迟最短的路径来选择最佳路由。

使用 HELLO 的路由器的一项关键任务是计算向其邻居发送和接收数据报所需的时间延迟。定期地,路由器交换包含时钟和时间戳信息的 HELLO 消息。通过使用特殊的算法来比较消息中的时钟值和时间戳与其自己的时钟,接收设备可以计算发送数据报通过链路所需时间的估计值。

就像 RIP 和 GGP 消息一样,HELLO 消息也包含以目的地和度量值对的形式的路由信息。这些表示发送路由器能够到达的地方以及与每个地方通信的成本。然而,在 HELLO 中,度量值是每个目的地的往返延迟成本的估计。这些信息被添加到接收路由器接收消息的链路的计算往返延迟时间中,并用于更新接收路由器自己的路由表。

这看起来有点令人困惑,但实际上与像 RIP 这样的跳数距离矢量协议的工作方式非常相似。路由器 A 使用 RIP 从路由器 B 接收 RIP 响应消息,知道它可以到达路由器 B 可以到达的每个目的地,但代价是额外一跳(从路由器 A 到路由器 B 的跳数)。同样,路由器 A 收到来自路由器 B 的 HELLO 消息,知道它可以到达路由器 B 可以到达的每个目的地,但代价是计算路由器 A 和路由器 B 之间链路的延迟。

在理论上,使用延迟计算应该比简单地使用跳数算法选择路由更高效,但这会增加复杂性。这使得 HELLO 协议确实非常有趣,尤其是对于一个超过 20 年的协议来说。然而,由于链路的延迟通常与其带宽无关,使用时间延迟作为链路度量可能会导致虚假的结果。

此外,任何链路上的延迟随时间变化是正常的;例如,如果两条路由的成本相似,每条路由的延迟波动可能会导致路由之间快速切换(这种现象有时被称为路由波动)。需要对 HELLO 协议的基本操作概述进行调整,以避免这类问题。

就像其他早期的路由协议一样,HELLO 协议不包括像认证这样的复杂功能。在互联网的早期,当互联网互连规模小且容易控制时,这些功能是不需要的。随着互联网的发展,像 RIP 这样的新路由协议最终取代了 HELLO。现在它被认为是一个历史性的协议(换句话说,已经过时),并且不再被使用。

小贴士

关键概念 HELLO 协议在互联网的早期路由器及其前身上用于交换路由信息。它是一个距离矢量协议,类似于 RIP 和 GGP,但它不同之处在于它使用计算出的延迟而不是跳数作为度量。就像 GGP 一样,它现在被认为是一个历史性协议,不再是 TCP/IP 的一部分。

内部网关路由协议(IGRP)

我非常偏好通用的开放标准而不是专有标准。我在第三章中解释了原因,该章节讨论了网络标准。我并不孤单在这个观点上,说 TCP/IP 和互联网的大部分成功与它们都是通过开放的 RFC 过程开发和仍在开发的事实紧密相关,并不夸张。

话虽如此,在特定情况下,如果以下两个因素中的至少一个是真的,专有协议可以带来好处,甚至可以取得相当大的成功:

  • 现有的开放协议在功能覆盖上存在不足或空白,这为专有协议的成功提供了机会。

  • 专有协议必须由行业中的大玩家发起或大力支持。这有助于确保其他公司会注意到并给这个协议一个成为标准的机会。

这种情况在 20 世纪 80 年代的路由协议世界中出现。当时,最受欢迎的内部路由协议是 RIP,它基本上做得很好,但存在一些固有的限制和问题,这些问题是协议本身的,并且不容易解决。在 20 世纪 80 年代中期,像 OSPF 这样的开放替代品尚未存在;即使存在,OSPF 也比 RIP 复杂得多,因此有时不是 RIP 的好替代品。

思科系统——无疑是网络、互连和路由领域的知名企业——决定开发一种新的路由协议,该协议将与 RIP 相似,但将提供更强大的功能并解决 RIP 的一些固有问题。该协议被称为内部网关路由协议(IGRP),其名称中方便地使用了网关路由这两个词,说明了这两个词在互连标准中可以互换使用。思科将其设计为 RIP 的替代品。它在许多方面都很相似,并保留了 RIP 的简单性,这是其关键优势之一。同时,IGRP 克服了 RIP 的两个关键限制:将跳数单纯作为路由度量以及 15 个跳数的限制。

与 RIP 一样,IGRP 是一种距离矢量路由协议,专为与自治系统(AS)一起使用而设计,因此使用相同的机制来确定路由。每个路由器定期在每个连接的本地网络上发送一条消息,该消息包含其路由表的一个副本。此消息包含可达网络及其到达每个网络的成本(度量标准)的成对信息。接收此消息的路由器知道只要它能到达发送消息的路由器,它就可以到达消息中的所有网络。它通过将到达发送消息的路由器的成本加到网络的成本上来计算到达这些网络的成本。路由器相应地更新它们的表,并在下一次常规更新中发送此信息。最终,AS 中的每个路由器都将了解到达其内部每个网络的成本。

然而,RIP 和 IGRP 之间存在一个重要的区别。RIP 只允许以跳数来表示到达网络的成本;IGRP 提供了一个更为复杂的度量标准。在 IGRP 中,到达网络的总体成本是基于多个个别度量标准计算的,包括网络延迟、带宽、可靠性和负载。管理员可以通过设置反映该自治系统优先级的组件度量标准的相对权重来自定义成本的计算。因此,如果某个管理员认为强调可靠性而不是带宽将最好地最小化路由成本,他可以这样做。这样的系统在 RIP 的僵化跳数系统中提供了巨大的灵活性。与 RIP 不同,IGRP 在网络之间也没有固有的 15 跳限制。

在这个基本算法的基础上,IGRP 增加了一个名为多路径路由的功能。这允许自动使用多个路由之间的路径,并在这之间共享流量。流量可以均匀共享,也可以根据每条路径的相对成本度量不均匀分配。这提供了改进的性能和灵活性。

由于 IGRP 与 RIP 一样是一个距离矢量协议,因此它共享许多 RIP 的算法问题。不出所料,因此 IGRP 必须包含与 RIP 相同的许多稳定性功能,包括使用分割水平、分割水平带毒反转(在特定情况下)以及使用保持时间计时器。与 RIP 一样,IGRP 也使用计时器来控制更新发送的频率、路由器保持时间以及路由在路由表中过期之前保持的时间。

思科最初为互联网协议(IP)网络开发了 IGRP,由于 IP 在行业中占主导地位,因此这些网络是最常看到 IGRP 的地方。然而,IGRP 并不仅限于 IP,如果为它们实现,也可以与其他互连网络协议一起使用。正如您将看到的,思科还使用 IGRP 作为改进路由协议 EIGRP 的基础,该协议是在原始协议几年后开发的。

小贴士

关键概念 在 20 世纪 80 年代,思科系统公司创建了内部网关路由协议(IGRP),作为对行业标准协议 RIP 的改进。与 RIP 一样,IGRP 是一个距离矢量协议,但它包括几个增强功能。最重要的是,它消除了路由器之间的 15 跳限制,并提供了使用除跳数之外的其他度量来确定最佳路由的能力。

增强型内部网关路由协议(EIGRP)

如前所述,IGRP 在 RIP 之上代表了一个重大的改进,但像任何成功的公司一样,思科并不满足于安于现状。思科的开发者知道 IGRP 有很大的改进空间,因此他们在 20 世纪 90 年代初着手创建一个更好的 IGRP 版本。结果是增强型内部网关路由协议(EIGRP)

与原始协议相比,EIGRP 更像是一种演变而不是革命。EIGRP 仍然是一个距离矢量协议,但它比 IGRP 或 RIP 等其他距离矢量协议更复杂,并且包括一些更常与链路状态路由协议(如 OSPF)而不是距离矢量算法相关的功能。此外,由于思科开发者意识到许多决定使用 EIGRP 的组织将是从 IGRP 迁移过来,因此他们采取了特殊措施确保两者之间的兼容性。

IGRP 和 EIGRP 之间的主要区别不在于它们做什么,而在于它们是如何做的。为了提高路由收敛的效率和速度(即提高互联网中不同路由器之间的协议一致性),EIGRP 改变了路由计算的方式。EIGRP 基于一种新的路由计算算法,称为扩散更新算法(DUAL),由 SRI 国际的 J. J. Garcia-Luna-Aceves 博士开发。

DUAL 与典型的距离矢量算法的主要区别在于,它维护比 RIP 或 IGRP 更多的互联网拓扑信息。它使用这些信息自动选择网络之间的最低成本、无环路由。EIGRP 使用一个度量值,该度量值结合了对链路带宽的评估以及通过该链路发送的总延迟。(其他度量值也可以配置,尽管不推荐。)当相邻路由器发送更改后的度量信息时,路由将被重新计算,并按需发送更新。如果需要(例如,如果现有路由失败),DUAL 将查询相邻路由器以获取可达性信息。

这种“按需”的操作特性突出了 EIGRP 相对于 IGRP 在性能提升方面的一个重要方式。EIGRP 不会发送常规的路由更新,而是根据需要只发送部分更新,从而减少了路由器之间产生的流量。此外,这些更新被设计成只有需要更新信息的路由器才会接收它们。

为了构建计算路由所需的信息表,EIGRP 要求路由器与其本地网络中的其他路由器建立并保持联系。为此,EIGRP 集成了邻居发现和恢复过程。该系统涉及交换小的 Hello 消息,让路由器发现本地网络中的其他路由器,并定期检查它们是否可达。这与 OSPF 中同名 Hello 消息的使用方式非常相似(如第三十九章所述),因为消息很小且发送频率低,所以对带宽的使用影响很小。

IGRP 中的一些特性延续到了其继任者中,例如使用带有中毒反转的分割水平以增强稳定性。除了算法本身带来的基本效率提升和路由收敛改进外,EIGRP 还包括一些其他特性。这些特性包括对可变长度子网掩码(VLSM)的支持以及支持多个网络层协议。这意味着 EIGRP 可以被配置在运行 IP 协议以及另一个第 3 层协议的网络中工作。

小贴士

关键概念 20 世纪 90 年代开发的增强型内部网关路由协议(EIGRP)是 Cisco 的 IGRP 的改进版本。它在许多方面与 IGRP 相似,但它使用了一种更复杂的路由计算方法,称为扩散更新算法(DUAL)。EIGRP 还包括一些使它在计算路由方面更加智能化的特性;它借鉴了链路状态路由协议的概念,并使用更有效的部分更新,而不是发送整个路由表。

TCP/IP 外部网关协议(EGP)

在早期互联网时代,一小部分集中式核心路由器维护有关网络可达性的完整信息,负责路由。这些核心路由器使用我们在本章前面考察的历史内部路由协议 GGP 交换信息。其他位于核心外围的非核心路由器,无论是独立的还是成组的,都使用第一个 TCP/IP 外部路由协议:外部网关协议(EGP)与核心路由器交换网络可达性信息。

互联网先驱 Bolt、Beranek 和 Newman 在 20 世纪 80 年代初开发了 EGP。它首次在 1982 年 10 月发布的互联网标准 RFC 827,“外部网关协议(EGP)”中正式描述,该文件后来被 1984 年 4 月发布的 RFC 904,“外部网关协议正式规范”所取代。像 GGP 一样,EGP 现在被认为是过时的,因为它已被 BGP 所取代。然而,像 GGP 一样,它是 TCP/IP 路由历史的一个重要部分,因此简要考察它是值得的。

注意

正如我在第三十七章中解释的那样,路由器在过去常常被称为网关。因此,外部路由协议被称为外部网关协议。这里讨论的 EGP 协议是外部网关协议(也称为 EGP)的一个具体实例。因此,你有时可能会看到 BGP 也被称作外部网关协议EGP,这是该术语的通用用法

EGP 负责在可能或可能不在不同 AS 中的相邻路由器之间通信网络可达性信息。EGP 的操作与 BGP(在第四十章中讨论)的操作有些相似。每个 EGP 路由器维护一个关于它可以到达哪些网络以及如何到达它们的数据库。它定期将此信息发送给它直接连接的每个路由器。路由器接收这些消息并更新它们的路由表,然后使用这些新信息更新其他路由器。关于如何到达每个网络的信息在整个互联网中传播。

交换路由信息的实际过程涉及几个步骤,这些步骤用于发现邻居并设置和维护通信。步骤如下:

  1. 邻居获取 每个路由器通过发送邻居获取请求消息来尝试与每个相邻路由器建立连接。当一个邻居听到请求时,它可以回复一个邻居获取确认消息,表示它已识别请求并希望连接。它也可以通过回复一个邻居获取拒绝消息来拒绝获取。为了在两个邻居之间建立 EGP 连接,每个消息必须首先通过确认消息成功获取对方。

  2. 邻居可达性 在获取一个邻居之后,路由器会定期检查以确保邻居可达并且正常工作。这是通过向已建立连接的每个邻居发送 EGP 问候消息来完成的。邻居会回复一个我听到了你(IHU)消息。这些消息在某种程度上类似于 BGP 保持活动状态消息,但它们是成对使用的。

  3. 网络可达性更新 路由器定期向其每个邻居发送轮询消息。邻居会回复一个更新消息,其中包含它能够到达的网络详情。这些信息用于更新发送轮询消息的设备的路由表。

一个邻居可以通过发送停止消息(称为邻居去获取)来决定终止一个连接;邻居会回复一个停止-确认(确认)消息。

定义了一个错误消息,它在角色和结构上类似于 BGP 通知消息(见第四十章"))。邻居可能会在收到 EGP 消息时发送此消息作为响应,无论是消息本身存在问题(例如消息长度不良或字段中的数据不可识别)还是表示消息使用方式存在问题(例如以被认为过高的速率接收问候或轮询消息)。与 BGP 通知消息不同,EGP 路由器在发送错误消息时并不一定关闭连接。

提示

关键概念 外部网关协议(EGP) 是第一个 TCP/IP 外部路由协议,在早期互联网上与 GGP 一起使用。它以类似于 BGP 的方式工作。例如,EGP 路由器会与相邻路由器建立联系并与之交换路由信息。还提供了一个机制来维护会话并报告错误。EGP 在功能上比 BGP 有限,现在被认为是一个历史协议。

早期的互联网设计是为了将边缘路由器或路由器组连接到互联网核心。因此,它是在假设互联网以层次树状结构连接的情况下设计的,核心作为根节点。EGP 就是基于这种树状结构的假设设计的,因此,它无法处理像 BGP 那样的任意拓扑结构的 AS。同样,如果相邻路由器之间的互联中存在路由循环,它也无法保证不存在路由循环。这也是为什么随着互联网向更任意的 AS 连接结构发展,BGP 需要被开发出来,在这种结构中,如果不采取措施避免,循环是可能出现的。

第二部分-8. TCP/IP 传输层协议

第四十二章

第四十三章

第四十四章")

第四十五章

第四十六章基础和一般操作")

第四十七章

第四十八章

第四十九章

OSI 参考模型的前三层——物理层、数据链路层和网络层——对于理解网络如何工作非常重要。物理层在电线上移动比特;数据链路层在网络中移动帧;网络层在互联网中移动数据报。作为一个整体,它们是协议堆栈的组成部分,负责将数据从一地传输到另一地。

在这三层之上立即是 OSI 参考模型的第四层:传输层,在 TCP/IP 模型中称为主机到主机的传输层。这一层很有趣,因为它位于模型的非常核心的架构中。因此,它代表了在下面的硬件相关层(执行基础工作)和上面的更软件导向和抽象的层之间的重要过渡点。

在传输层运行的协议负责提供几个重要的服务,以使高层软件应用能够在互联网上工作。它们通常负责在可能位于远程机器上的软件服务之间建立和维护连接。许多高层应用需要以可靠的方式发送数据,而无需担心错误纠正、丢失数据或流量管理。然而,网络层协议通常是不可靠的且未确认的。传输层协议通常与直接位于其下的网络层协议非常紧密地绑定,并专门设计来处理那些协议未处理的功能。

本部分描述了 TCP/IP 协议集中使用的传输层协议和相关技术。在这一层有两个主要的协议:传输控制协议(TCP)和用户数据报协议(UDP)。UDP 比 TCP 简单,解释起来也不需要花费太多时间。相比之下,TCP 是一个相当复杂的协议,也是 TCP/IP 协议集中的非常重要的部分,因此需要更多的解释。

本部分的第一章简要概述了这两个协议在 TCP/IP 协议族中的作用,讨论了它们为何都如此重要,并总结了它们的关键属性。第二章描述了这两个协议用于寻址的方法,即使用传输层端口和套接字。第三章讨论了 UDP。

剩下的五章涵盖了 TCP 的概念、特性和功能的全面描述。本部分第四章概述了 TCP,描述了其历史、功能以及工作原理。第五章涵盖了理解 TCP 操作所需的一些重要背景信息,解释了诸如流和段、滑动窗口以及 TCP 端口和连接等关键概念。第六章描述了 TCP 建立、维持和终止会话的过程。第七章描述了 TCP 消息及其格式化和传输方式。最后,本部分最后一章展示了 TCP 如何提供可靠性以及其他重要的传输层功能,如流量控制、丢失数据的重传和拥塞避免。

由于 TCP 建立在互联网协议(IP)之上,在描述 TCP 时,我假设您至少对 IP 有基本的了解(在第二部分-3"); 特别是,参见第十五章(ch15.html "第十五章. 互联网协议版本、概念和概述")和第十六章(ch16.html "第十六章. IPv4 寻址概念和问题"),其中描述了基本 IP 概念))。

第四十二章:TCP 和 UDP 的概述与比较

无标题图片

TCP/IP 是世界上最重要的互联网协议族。它是互联网的基础,也是世界上绝大多数联网计算机所使用的“语言”。TCP/IP 包括一组在网络层及其以上层运行的协议。整个套件以互联网协议(IP)为基础,许多人都认为这是网络世界中最重要的单一协议。

当然,网络层和在其之上运行的层中的应用程序之间存在一定的架构距离。IP 是执行使互联网工作所需的大部分功能的协议,但它不包括许多应用程序需要的某些功能。在 TCP/IP 中,运行在传输层的两个协议执行这些任务。这些协议是传输控制协议(TCP)用户数据报协议(UDP)

在这两个协议中,TCP 受到了最多的关注。它是与 TCP/IP 最常相关联的传输层协议。它也是许多互联网上最受欢迎的应用程序使用的传输协议。

另一方面,UDP 排在第二位。然而,UDP 和 TCP 实际上是同等级别的,在 TCP/IP 中扮演着相同的作用。它们功能非常不同,为使用它们的应用程序提供不同的优势和劣势。但它们对整个协议套件来说都很重要。本章介绍了 TCP 和 UDP 的功能,并突出了它们之间的相似之处和不同之处。

TCP/IP 传输层需求的两项协议

在协议套件中,传输层负责一组特定的功能。因此,你可能期望 TCP/IP 套件会有一个单一的、主要的传输协议来执行这些功能,就像它在网络层有 IP 作为核心协议一样。但有两个不同的广泛使用的 TCP/IP 传输层协议,这种安排可能是协议分层力量的最佳例子之一(表明学习理解第五章到第七章中令人烦恼的 OSI 参考模型所花费的所有时间是值得的)。

让我们从回顾第 3 层开始。在我的第十五章中关于 IP 的关键操作特性的概述中,我描述了 IP 的几个限制。最重要的限制是 IP 是无连接的不可靠的无确认的。使用尽力而为的范式,数据在没有首先建立连接的情况下被发送到 IP 互联网。消息通常会到达它们需要去的地方,但没有保证,发送者通常甚至不知道数据是否到达了目的地。

这些特性给软件带来了严重的问题。许多,如果不是大多数,应用程序都需要能够依赖它们发送的数据能够无损失或无错误地到达目的地。应用程序还希望两个设备之间的连接能够自动管理,如拥塞和流量控制等问题能够按需解决。除非在较低层提供某种机制,否则每个应用程序都需要执行这些任务,这将造成巨大的重复劳动。

事实上,你可能会争辩说,建立连接、提供可靠性、处理重传、缓冲和数据流都是足够重要的,可能最好直接将这些能力构建到 IP 中。有趣的是,TCP/IP 的早期阶段正是如此。最初只有一个名为 TCP 的协议。它结合了 IP 的任务以及我刚才提到的可靠性和会话管理功能。然而,这有一个大问题:建立连接、提供可靠性机制、管理流量控制、管理确认和管理重传都会带来时间和带宽的开销。将这些能力构建到一个跨越层 3 和 4 的单一协议中意味着所有应用程序都会获得可靠性的好处,但也会承担相应的成本。虽然这种方法对许多应用程序来说都是可行的,但还有一些应用程序要么不需要可靠性,要么无法承担提供可靠性所需的开销。

解决方案很简单:让网络层(IP)负责在互联网上处理基本的数据移动,并在传输层定义两个协议。一个协议将为需要该功能的应用程序提供丰富的服务集,并且在使用此协议时,理解到需要一些开销。另一个协议会更简单,在经典层 4 功能方面提供很少的服务,但它会更快、更易于使用。因此,结果是两个 TCP/IP 传输层协议:

传输控制协议 (TCP) TCP 是一个功能齐全、面向连接、可靠的 TCP/IP 应用传输协议。它提供了传输层寻址,允许多个软件应用程序同时使用单个 IP 地址,并允许一对设备建立虚拟连接,然后双向传递数据。传输使用特殊的 滑动窗口 系统进行管理,未确认的传输会被检测到并自动重传。额外的功能允许管理设备间的数据流,并解决特殊情况。

用户数据报协议 (UDP) 相比之下,UDP 是一个非常简单的传输协议,它提供了类似于 TCP 的传输层寻址,但除此之外几乎没有其他功能。UDP 仅仅是一个包装协议,为应用程序提供访问 IP 的方式。没有建立连接,传输不可靠,数据可能会丢失。

小贴士

关键概念 许多 TCP/IP 应用需要不同的传输需求,因此需要两个 TCP/IP 传输层协议。传输控制协议(TCP)是一个功能齐全、面向连接的协议,在管理流量和处理诸如拥塞和传输丢失等问题时,提供数据的确认交付。相比之下,用户数据报协议(UDP)是一个更简单的协议,它只专注于交付数据,以便在不需要 TCP 的功能时最大化通信速度。

TCP 和 UDP 的应用

用一个类比来说,TCP 就像一辆配备司机和卫星跟踪/导航系统的全负荷豪华性能轿车。它提供了很多奢华、舒适和性能。它几乎保证你能够无任何问题地到达目的地,并且任何出现的问题都可以得到纠正。相比之下,UDP 就像一辆简化的赛车。它的目标是简单和速度;其他一切都是次要的。你可能能够到达目的地,但可能会遇到赛车难以保持运行的问题。

拥有如此互补的优缺点两个传输层协议,为网络软件的创造者提供了相当大的灵活性。

TCP 应用

大多数典型应用都需要 TCP 提供的可靠性和其他服务,而大多数应用并不介意因为 TCP 的开销要求而损失一小部分性能。例如,大多数在机器之间传输文件或重要数据的应用都使用 TCP,因为文件任何部分的丢失都会使数据变得无用。例如,包括以下知名应用在内的例子:超文本传输协议(HTTP),它是万维网(WWW)使用的;文件传输协议(FTP);以及简单邮件传输协议(SMTP)。我在第三章中更详细地描述了 TCP 应用。

UDP 应用

有什么样的应用不关心其数据是否到达,为什么有人会想使用这种不可靠的应用?你可能感到惊讶。许多 TCP/IP 协议使用 UDP。当应用本身不介意一些数据丢失时,它是一个很好的匹配,例如在流式传输视频或多媒体时。应用不会注意到丢失的一个字节的数据。当应用本身选择提供其他机制来弥补 UDP 功能不足时,UDP 也是一个很好的匹配。

发送非常少量数据的应用通常使用 UDP,并假设如果发送请求但没有收到回复,客户端稍后会发送新的请求。这提供了足够的可靠性,而没有 TCP 连接的开销。我在第四十四章")中讨论了一些常见的 UDP 应用。

小贴士

关键概念 大多数典型应用程序,尤其是发送文件或消息的应用程序,都需要数据可靠传输,因此使用 TCP 进行传输。对于使用 UDP 或使用自己特定的应用程序程序处理潜在交付问题的应用程序来说,少量数据的丢失通常不是问题。

注意,尽管 TCP 通常被描述为比 UDP 慢,但这是一种相对测量。TCP 是一个非常优秀的协议,能够进行高度有效的数据传输。它之所以慢,只是因为建立和管理连接的开销。这种差异可能是显著的,但不是巨大的。

顺便说一句,如果您想了解为什么同时拥有 UDP 和 TCP 有价值,可以考虑域名系统(DNS)中的消息传输。如第五十七章所述,DNS 实际上使用 UDP 进行某些类型的通信,而使用 TCP 进行其他类型的通信。

UDP 和 TCP 的总结比较

在接下来的几章中,我们将更详细地探讨 UDP 和 TCP。我将帮助你更好地理解这两种协议的优缺点。虽然这些章节信息丰富,但阅读起来耗时较长。因此,为了您的方便,我包括了表 42-1,它描述了这两种协议最重要的属性以及它们之间的对比。

表 42-1. UDP 和 TCP 的总结比较

特征/描述 UDP TCP
一般描述 简单、高速、功能低下的包装器,将应用程序与网络层接口,但做不了其他事情 功能齐全的协议,允许应用程序可靠地发送数据,无需担心网络层问题
协议连接设置 无连接;数据发送无需设置 有连接;传输前必须建立连接
数据与应用程序的接口 基于消息;应用程序以离散的数据包发送数据 基于流;应用程序发送无特定结构的数据
可靠性和确认 不可靠,尽力交付,不进行确认 消息可靠交付;所有数据都得到确认
重传 不执行;应用程序必须检测丢失的数据并在需要时重新传输 所有数据的交付都得到管理,丢失的数据会自动重传
管理数据流的功能 使用滑动窗口进行流量控制;窗口大小调整启发式算法;拥塞避免算法
开销 非常低 低,但高于 UDP
传输速度 非常高 高,但不如 UDP
数据量适用性 小到中等的数据量(多达几百字节) 小到非常大的数据量(多达几个吉字节)
使用该协议的应用类型 数据传输速度比完整性更重要,发送数据量较小,或使用组播/广播的应用 必须可靠接收的数据传输协议,包括大多数文件和消息传输协议
已知应用和协议 多媒体应用、DNS、BOOTP、DHCP、TFTP、SNMP、RIP、NFS(早期版本) FTP、Telnet、SMTP、DNS、HTTP、POP、NNTP、IMAP、BGP、IRC、NFS(后期版本)

第四十三章:TCP 和 UDP 寻址:端口和套接字

无标题图片

互联网协议(IP)地址是 TCP/IP 网络中使用的最主要寻址形式。这些网络层地址唯一标识每个网络接口,因此,它们作为数据在互联网上正确路由到特定网络,然后到达该网络正确设备的机制。

但在 TCP/IP 协议栈的传输层,存在一个额外的寻址层级,这位于 IP 地址之上。TCP/IP 传输协议中的两个协议——传输控制协议(TCP)和用户数据报协议(UDP)——都使用端口套接字的概念来进行虚拟软件寻址。端口和套接字使得许多应用程序能够在 IP 设备上同时运行。

在本章中,我描述了 TCP 和 UDP 寻址的特殊机制。我首先讨论 TCP/IP 应用程序进程,包括通信的客户端/服务器特性,这为解释端口和套接字的使用提供了背景。然后,我概述了端口的概念以及它们如何使数据在 IP 地址上复用。我描述了端口号码如何按范围分类并分配给常见应用程序的服务器进程。我解释了用于客户端的短暂端口号码的概念。然后,我讨论了套接字及其在连接识别方面的使用,包括多个设备如何与另一设备上的单个端口通信的手段。接着,我提供了最常见的已注册端口号码的总结表。

TCP/IP 进程、复用和客户端/服务器应用角色

了解 TCP/IP 协议套件如何工作的最合理起点是检查 IP 本身,以及在网络层与之协同工作的支持协议。IP 是 TCP/IP 其余部分的基础。它是数据在 TCP/IP 互联网中打包和路由的机制。

因此,当我们从 IP 的角度检查 TCP/IP 的操作时,我们非常笼统地谈论发送和接收数据报。对于发送和接收 IP 数据报的 IP 层软件来说,数据报来自哪个高级应用程序以及数据报去向哪个高级应用程序实际上并不重要。对 IP 来说,一个数据报就是一个数据报。所有数据报都以相同的方式打包和路由,IP 主要关注以高效方式在设备之间移动它们的基础层面。然而,重要的是要记住,这实际上是为了描述第三层操作而进行的抽象。它没有考虑数据报在第三层以上是如何真正生成和使用的。

第四层代表了 OSI 模型中硬件相关层(1、2 和 3)与软件相关层(5 到 7)之间的一个过渡点。这意味着 TCP/IP 传输层协议,TCP 和 UDP,需要关注软件使用 TCP/IP 的方式,即使 IP 实际上并不需要这样做。

最终,拥有网络、互联网和像 TCP/IP 这样的协议套件的全部目的,是为了使网络应用程序能够运行。大多数互联网用户每天都在使用这些应用程序。事实上,我们中的大多数人同时运行许多不同的应用程序。例如,你可能使用网页浏览器来查看新闻,使用文件传输程序(FTP)客户端上传一些图片与家人分享,或者使用互联网中继聊天(IRC)程序与朋友或同事讨论某事。实际上,拥有多个单个应用程序的实例是很常见的。最常见的例子是同时打开多个网页浏览器窗口(我有时发现自己一次有 30 个窗口在运行!)。

多路复用和解复用

TCP/IP 中的大多数通信都是以一个设备上运行的程序与另一个设备上运行的匹配程序之间交换信息的形式进行的。每个应用程序实例代表该应用程序软件的一个副本,需要发送和接收信息。这些应用程序实例通常被称为进程。TCP/IP 应用程序进程是指使用 TCP/IP 协议套件发送和接收信息的任何网络软件。这包括前面描述的经典终端用户应用程序,以及当它们发送消息时表现得像应用程序的支持协议。后者的例子包括像简单网络管理协议(SNMP;见第第六十五章至第六十九章"))这样的网络管理协议,甚至发送消息的方式与应用程序相同的路由协议边界网关协议(BGP;见第四十章"))。

因此,一个典型的 TCP/IP 主机有多个进程,每个进程都需要发送和接收数据报。然而,所有这些数据报都必须使用相同的接口发送到互联网,使用 IP 层。这意味着所有应用的数据(可能有一些例外)最初都会被引导到传输层,在那里 TCP 或 UDP 处理它们。从那里,消息传递到设备的 IP 层,在那里它们被封装成 IP 数据报并发送到互联网上的不同目的地。这个技术的术语是复用。这个术语简单意味着组合,这里的用法是软件上的复用方式(例如,如何将单个电话通话封装)的类比。

一种互补机制负责接收数据报。在 IP 层将数据报复用到多个应用进程以发送的同时,它也接收许多旨在发送到不同进程的数据报。IP 层必须处理这一系列无关的数据报,并将它们传递给正确的进程(通过其上的传输层协议)。这是分解复用,与复用相反。

您可以在图 43-1 中看到 TCP/IP 进程复用和分解复用概念的解释。

小贴士

关键概念 TCP/IP 被设计成允许许多不同的应用在同一台设备上使用相同的 IP 软件同时发送和接收数据。为了实现这一点,必须将来自许多源的数据在传递到 IP 层时进行复用。在接收到一系列 IP 数据报的同时,它们会被分解复用,并将适当的数据传递给接收主机上的每个应用软件实例。

TCP/IP 客户端进程和服务器进程

TCP/IP 软件通常是非对称的。这意味着当一个计算机上的 TCP/IP 应用进程试图与另一台计算机上的应用进程通信时,这两个进程通常并不完全相同。相反,它们是彼此的补充,设计成一起作为一个团队工作。

正如我在第八章中对 TCP/IP 的概述描述中解释的那样,大多数网络应用都使用客户端/服务器模型进行操作。这个术语可以用来指代计算机的角色,其中服务器是一个相对强大的机器,为大量由用户操作客户端提供服务。它也适用于软件。在软件环境中,客户端进程通常运行在客户端机器上,并启动联系以执行某种功能。服务器进程通常运行在硬件服务器上,监听来自客户端的请求,并对它们进行响应。

这种客户端/服务器操作的典型例子是万维网(WWW)。网络使用超文本传输协议(HTTP;见第八十章),这是一个应用协议的好例子。网络浏览器是 HTTP 客户端,通常运行在最终用户客户端机器上。它通过向网络(HTTP)服务器发送请求来启动 HTTP(网络)数据的交换。该网络服务器上的服务器进程听到请求后,要么回复请求的项目(网页或其他数据),要么回复错误信息。服务器通常专门设计来处理大量的客户端请求,在许多情况下,没有其他用途。

为什么我要在本来应该解释 TCP 和 UDP 端口的章节中讲述这些内容?我之所以从这里开始,是因为许多应用进程是同时运行的,并且它们的数据被复用进行传输。应用进程的并发性和数据的复用是为什么在 TCP/IP 中高级寻址成为必要性的推动力。TCP/IP 使用的客户端/服务器配置对端口的使用方式和端口分配的机制有重要影响。接下来的两个章节将更全面地探讨这些概念。

TCP/IP 中的进程复用和解复用过程在一个典型的运行 TCP/IP 的机器中,同时运行着许多不同的协议和应用。这个例子展示了四个不同的应用在客户端和服务器机器之间进行通信。所有四个应用都使用相同的 IP 软件和物理连接进行复用传输;接收到的数据被解复用并传递到相应的应用。IP、TCP 和 UDP 提供了一种方法,以确保每个应用的数据都是独立的。

图 43-1. TCP/IP 中的进程复用和解复用在一个典型的运行 TCP/IP 的机器上,同时运行着许多不同的协议和应用。此示例显示了四个不同的应用在客户端和服务器机器之间进行通信。所有四个都使用相同的 IP 软件和物理连接进行复用传输;接收到的数据被解复用并传递到适当的应用。IP、TCP 和 UDP 提供了一种方法,以保持每个应用的数据独立。

TCP/IP 端口:TCP/UDP 寻址

在 TCP/IP 互联网中,一个典型主机上同时运行着许多不同的软件应用进程。每个进程生成数据,并将其发送到 TCP 或 UDP,然后由 IP 层进行传输。IP 层将这个复用数据报流发送到不同的目的地。同时,每个设备的 IP 层正在接收来自其他主机上多个应用进程的数据报。这些数据报需要被解复用,以便它们最终到达接收它们的设备上的正确进程。

使用端口进行复用和解复用

问题是,我们如何解复用一系列需要发送到许多不同应用进程的 IP 数据报?让我们考虑一个具有单个网络接口并带有 IP 地址 24.156.79.20 的主机。通常,IP 层接收到的每个数据报都将在此 IP 目标地址字段中包含此值。IP 层接收到的连续数据报可能包含您使用网络浏览器下载的文件的一部分,您兄弟发给您的电子邮件,以及一个在 IRC 聊天频道中写下的朋友的一行文本。如果它们都具有相同的 IP 地址,IP 层如何知道哪些数据报该去哪里?

答案的第一部分在于每个 IP 数据报头部中包含的协议字段。该字段携带一个代码,用于标识将数据报中的数据发送到 IP 的协议。由于大多数最终用户应用在传输层使用 TCP 或 UDP,因此接收到的数据报中的协议字段告诉 IP 根据需要将数据传递给 TCP 或 UDP。当然,这仅仅是将问题推迟到了传输层。

许多应用同时使用 TCP 和 UDP。这意味着 TCP 或 UDP 必须确定将数据发送到哪个进程。为了实现这一点,需要额外的寻址元素。此地址允许在特定的 IP 地址内识别一个更具体的地址——一个软件进程。在 TCP/IP 中,这个传输层地址被称为端口

源端口和目标端口号码

在 UDP 和 TCP 消息中,出现了两个地址字段:一个源端口和一个目的端口。这些字段与 IP 层上的源地址和目的地址字段类似,但更详细。它们标识了源机器上的发起进程和目标机器上的目标进程。TCP 或 UDP 软件在传输之前填充这些字段,并将数据引导到目标设备上的正确进程。

注意

“端口”这个词除了在 TCP/IP 中的这个含义之外,还有许多其他含义。例如,网络设备中的物理出口通常被称为端口。 通常,你可以从上下文中判断所讨论的端口是指硬件端口还是软件端口。

TCP 和 UDP 端口号的长度为 16 位。有效的端口号理论上可以取从 0 到 65,535 的值。你将在下一节中看到,这些值被划分为不同的范围,用于不同的目的,某些端口被保留用于特定的用途。

有时候可能会有些令人困惑的一个事实是,UDP 和 TCP 都使用相同的端口号范围,但它们是独立的。从理论上讲,UDP 端口号 77 可以指代一个应用程序进程,而 TCP 端口号 77 可以指代一个完全不同的进程。至少对于计算机来说,这没有歧义,因为如前所述,每个 IP 数据报都包含一个协议字段,用于指定它携带的是 TCP 消息还是 UDP 消息。IP 将数据报传递给 TCP 或 UDP,然后使用 TCP 或 UDP 头中的端口号将消息发送到正确的进程。这一机制在图 43-2 中得到了说明。

TCP/IP 进程复用/解复用使用 TCP/UDP 端口,这是图 43-1 的一个更具体的版本,展示了 TCP 和 UDP 端口如何实现软件复用和解复用。再次有四个不同的 TCP/IP 应用程序在进行通信,但这次我只展示了从客户端到服务器的流量。其中两个应用程序使用 TCP,另外两个使用 UDP。客户端上的每个应用程序都使用特定的 TCP 或 UDP 端口号发送消息。服务器上的 UDP 或 TCP 软件使用这些端口号将数据报传递给适当的应用程序进程。

图 43-2. 使用 TCP/UDP 端口的 TCP/IP 进程多路复用/解复用 本图是图 43-1 的一个更具体版本,展示了 TCP 和 UDP 端口如何实现软件多路复用和解复用。再次,有四个不同的 TCP/IP 应用程序在进行通信,但这次我只展示了从客户端到服务器的流量。其中两个应用程序使用 TCP,另外两个使用 UDP。客户端上的每个应用程序都使用特定的 TCP 或 UDP 端口号发送消息。服务器上的 UDP 或 TCP 软件使用这些端口号将数据报传递给适当的应用程序进程。

在实践中,TCP 和 UDP 使用不同的端口号可能会造成混淆,尤其是对于常用应用程序使用的保留端口号。为了避免混淆,按照惯例,大多数保留端口号都为 TCP 和 UDP 保留。例如,端口 80 为 HTTP 保留,用于 TCP 和 UDP,尽管 HTTP 只使用 TCP。我们将在下一节中更详细地探讨这一点。

小贴士

关键概念 TCP/IP 传输层地址是通过使用 TCP 和 UDP 端口 来实现的。特定 IP 设备内的每个端口号标识一个特定的软件进程。

数据报传输和接收端口使用总结

下面是如何在 TCP 和 UDP 中实现传输层地址(端口地址)的:

发送数据报 应用程序指定它希望用于通信的源端口和目标端口。端口号被编码到 TCP 或 UDP 头部,具体取决于应用程序使用的传输层协议。当 TCP 或 UDP 将数据传递给 IP 时,IP 在 IP 数据报的协议字段中指示适用于 TCP 或 UDP 的协议类型。源端口和目标端口作为 TCP 或 UDP 消息的一部分封装在 IP 数据报的数据区域中。

接收数据报 IP 软件接收数据报,检查协议字段,并决定数据报属于哪个协议(在这种情况下,是 TCP 或 UDP)。TCP 或 UDP 接收数据报,并根据目标端口号将其内容传递给适当的过程。

小贴士

关键概念 TCP/IP 中应用程序进程的多路复用和解复用是通过 IP 协议字段以及 UDP/TCP 源端口和目标端口字段实现的。在传输过程中,协议字段被赋予一个数字来指示是否使用了 TCP 或 UDP,端口数字被填充以指示发送和接收的软件进程。接收数据报的设备使用协议字段来确定是否使用了 TCP 或 UDP,然后将数据传递给目标端口号指示的软件进程。

TCP/IP 应用程序分配和服务器端口号范围

我刚才讨论的端口号提供了一种传输层寻址方法,允许许多应用程序同时使用 TCP 和 UDP。通过指定适当的目标端口号,发送数据的程序可以确保目标设备上的正确进程将接收消息。不幸的是,仍然有一个问题需要解决。

让我们回到使用万维网。你打开一个网页浏览器,这是一个客户端软件,它使用 HTTP 发送请求。你需要知道你想要访问的网站的 IP 地址,或者你可能让域名系统(DNS)自动为你提供 IP 地址。一旦你有了地址,网页浏览器就可以生成一个 HTTP 消息并将其发送到网站的 IP 地址。

这个 HTTP 消息是为了发送到你试图访问的网站上的 Web 服务器进程。问题是网页浏览器(客户端进程)如何知道分配给网站服务器进程的端口号?端口号的范围从 0 到 65535,这意味着有很多选择。而且,从理论上讲,每个网站都可以为其 Web 服务器进程分配不同的端口号。

有几种不同的方法可以解决这个问题。TCP/IP 采取了可能是最简单的方法:它为特定应用程序保留了某些端口号。

保留端口号

监听该应用程序请求并对其做出响应的服务器进程为每个常见应用程序分配一个特定的端口号。为了避免混乱,实现特定服务器进程的软件通常在每台 IP 设备上使用相同的保留端口号,以便客户端可以轻松找到它。

在使用网页浏览器访问网站的例子中,HTTP 保留的端口号是 80。每个网页浏览器都知道,网页设计者设计网站是为了监听发送到端口 80 的请求。因此,网页浏览器将使用这个值在请求中,以确保网页浏览器的 IP 和 TCP 软件将 HTTP 消息直接导向 Web 服务器软件。虽然特定的 Web 服务器可以使用不同的端口号,但在此情况下,Web 服务器必须以某种方式通知用户这个数字,并且必须明确告诉网页浏览器使用它而不是默认端口号(80)。

小贴士

关键概念 为了使客户端设备更容易建立到 TCP/IP 服务器的连接,常见应用程序的服务器进程使用通用服务器端口号。客户端预先编程,默认使用这些端口号。

为了使这个系统运行良好,对端口号分配的普遍同意是必不可少的。因此,这又是一个需要中央权威机构来管理大家使用的端口号分配列表的情况。对于 TCP/IP 来说,负责分配和协调其他集中管理数字的同一权威机构负责这项工作,包括 IP 地址、IP 协议号等:互联网数字分配机构(IANA;见第三章)。

TCP/UDP 端口号范围

正如你所见,有 65,536 个端口号可用于进程。但也有相当多的 TCP/IP 应用程序,并且这个列表每年都在增长。IANA 需要仔细管理端口号地址空间,以确保端口号不会被浪费在不会广泛使用的协议上。同时,IANA 还需要为必须使用不为人知的组织提供灵活性。为此,TCP 和 UDP 的全部端口号范围被划分为三个范围:

已知(特权)端口号(0 到 1023) IANA 管理这些端口号,并将它们仅保留给最通用的 TCP/IP 应用程序。IANA 只将这些端口号分配给使用 TCP/IP RFC 流程标准化的协议,正在标准化过程中的协议,或预计未来可能标准化的协议。在大多数计算机上,只有由系统管理员或特权用户运行的服务器进程使用这些端口号。这些进程通常对应于实现关键 IP 应用程序的进程,例如 Web 服务器、FTP 服务器等。因此,这些进程有时被称为 系统端口号

已注册(用户)端口号(1024 到 49151) 许多需要使用 TCP/IP 的应用程序没有在 RFC 中指定,或者不像其他应用程序那样被普遍使用,因此它们不配拥有全球知名的端口号。为了确保这些不同的应用程序之间不会相互冲突,IANA 使用了大部分端口号范围作为已注册端口号。任何创建可行的 TCP/IP 服务器应用程序的人都可以请求预留这些端口号之一,如果请求得到批准,IANA 将注册该端口号并将其分配给该应用程序。系统上的任何用户通常都可以访问已注册端口号;因此,它们有时被称为 用户端口号

私有/动态端口号(49152 到 65535) IANA 既不保留也不维护这些端口。任何人都可以在不注册的情况下用于任何目的,因此它们适用于仅由特定组织使用的私有协议。

小贴士

关键概念 IANA 管理端口号分配以确保全球互联网的通用兼容性。这些数字分为三个范围:用于最常见应用的知名端口号,用于其他应用的注册端口号,以及无需 IANA 注册即可使用的私有/动态端口号。

使用这些范围确保了在如何访问最常见 TCP/IP 协议的服务器进程方面将达成全球共识。它们还允许特殊应用有灵活性。大多数 TCP/IP 应用和应用协议使用知名端口号范围中的数字作为其服务器的端口号。这些端口号通常不用于客户端进程,但也有一些例外。例如,端口号 68 保留用于使用引导协议(BOOTP)或动态主机配置协议(DHCP)的客户端。

TCP/IP 客户端(短暂)端口和客户端/服务器应用端口使用

在详细检查端口号的使用时,TCP/IP 中客户端和服务器之间的不对称性变得明显。由于客户端使用 TCP 和 UDP 来初始化应用数据传输,因此它们需要知道服务器进程的端口号。因此,服务器需要使用普遍知晓的端口号。因此,知名和注册的端口号用于标识服务器进程。发送请求的客户端使用知名或注册的端口号作为目标端口号。

相比之下,服务器响应客户端;它们不会主动与他们接触。因此,客户端不需要使用保留端口号。实际上,这真的是一种低估。服务器不应该使用知名或注册的端口号来向客户端发送响应,因为有可能同一台机器上运行着同一协议的客户端和服务器软件。如果服务器在其机器的 80 端口上收到 HTTP 请求,并将回复发送回客户端机器的 80 端口,那么服务器就会将回复发送到客户端机器上的 HTTP 服务器进程(如果存在),而不是发送给发送初始请求的客户端进程。

为了知道将回复发送到哪里,服务器必须知道客户端正在使用的端口号。客户端在请求中将端口号作为源端口号提供,然后服务器使用源端口号作为目标端口号来发送回复。客户端进程不使用知名或注册端口。相反,每个客户端进程都会为其分配一个临时端口号供其使用。这通常被称为短暂端口号

注意

今日 10 词: 临时:"短暂存在的;仅存在或持续很短的时间。" ——韦伯斯特修订版无删节词典

临时端口号分配

TCP/IP 软件根据需要将临时端口号分配给进程。显然,每个同时运行的客户端进程都需要使用一个唯一的临时端口号,因此 TCP 和 UDP 层必须跟踪哪些端口号正在使用中。TCP/IP 软件通常以伪随机方式从预留的数字池中分配这些端口号。我之所以说伪随机,是因为分配给进程的临时端口号没有特定的意义,因此 TCP/IP 软件可以为每个客户端进程选择一个随机的端口号。然而,由于需要随着时间的推移重复使用这个池中的端口号,许多实现使用一套规则来最小化由于重复使用而造成的混淆。

考虑一个仅使用临时端口号 4121 发送请求的客户端进程。客户端进程收到回复后终止。假设你立即将 4121 重新分配给其他进程。然而,先前使用端口号 4121 的用户访问服务器,由于某种原因,服务器发送了额外的回复。这个回复将发送到新的进程,从而造成混淆。为了避免这种情况,最好尽可能等待一段时间后再将端口号 4121 重新用于另一个客户端进程。因此,一些实现会循环使用端口号,以确保在连续使用相同的临时端口号之间有尽可能长的时间间隔。

小贴士

关键概念 对于服务器进程来说,需要已知的和注册的端口号,因为客户端必须知道服务器的端口号才能发起联系。另一方面,客户端进程可以使用任何端口号。每次客户端进程发起 UDP 或 TCP 通信时,TCP/IP 软件都会为其分配一个临时或临时端口号,用于那次对话。TCP/IP 软件以伪随机方式分配这些端口号,因为软件使用的确切数字并不重要,只要每个进程有不同的数字即可。

临时端口号范围

TCP/IP 软件在设备上用于临时端口号的端口号范围也取决于实现。伯克利标准分布(BSD)UNIX 中的 TCP/IP 实现确立了经典的临时端口号范围。BSD UNIX 将其定义为 1024 到 4999,从而提供了 3,976 个临时端口号。这似乎是一个非常大的数字,实际上通常对于典型的客户端来说已经足够了。然而,这个数字的大小可能会误导。许多应用程序使用多个进程,理论上在非常繁忙的 IP 设备上可能会耗尽临时端口号。因此,大多数情况下,临时端口号的范围可以更改。默认范围可能因其他操作系统而异。

就像众所周知并注册的端口号用于服务器进程一样,临时端口号仅用于客户端进程。这意味着从 1024 到 4999 的地址范围的使用不会与该范围用于注册端口号的使用发生冲突。我在上一节“临时端口号分配”中讨论了这一点。

客户端/服务器交换期间的端口号使用

现在让我们回到客户端/服务器应用程序消息交换的问题。一旦客户端分配了一个临时端口号,该端口号就用作客户端请求 TCP/UDP 消息中的源端口。服务器接收请求并生成一个回复。在形成这个响应消息时,服务器交换源端口号和目标端口号,就像它交换源和目标 IP 地址一样。因此,服务器的回复是从服务器进程的已知或注册端口号发送回客户端机器上的临时端口号。

现在回到网页浏览器的例子。具有 IP 地址 177.41.72.6 的网页浏览器想要向 IP 地址为 41.199.222.3 的特定网站发送 HTTP 请求。TCP/IP 软件使用目标端口号 80(为 HTTP 服务器保留的端口)发送 HTTP 请求。TCP/IP 软件从临时端口池中分配源端口号;假设它是端口 3022。当 HTTP 请求到达 Web 服务器时,它被传递到端口 80,HTTP 服务器接收它。这个过程生成一个回复并发送回 IP 地址 177.41.72.6,使用目标端口3022 和源端口80。每当 TCP/IP 软件交换源端口号和目标端口号以及源和目标 IP 地址时,这两个进程就可以来回交换信息。这个例子在图 43-3 中有说明。

TCP/IP 客户端/服务器应用程序端口机制 这个高度简化的例子展示了客户端和服务器如何使用端口号进行请求/回复交换。客户端正在发送 HTTP 请求,并将其发送到 HTTP 的已知端口 80。它的这个交换的端口号是伪随机选择的端口 3022。服务器将其回复发送回该端口号,它从请求中读取该端口号。

图 43-3. TCP/IP 客户端/服务器应用程序端口机制 这个高度简化的例子展示了客户端和服务器如何使用端口号进行请求/回复交换。客户端正在发送一个 HTTP 请求,并将其发送到 HTTP 的已知端口号 80。此交换的端口号是伪随机选择的 3022。服务器将其回复发送回该端口号,该端口号是从请求中读取的。

提示

关键概念 在大多数 TCP/IP 客户端/服务器通信中,客户端使用一个随机的临时端口号,并向服务器 IP 地址上的适当保留端口号发送请求。服务器将其回复发送回请求源端口号字段中找到的任何端口号。

TCP/IP 套接字和套接字对:进程和连接标识

在本章中,我讨论了在 IP 层和应用进程层面地址之间的关键区别。总结来说,在第 3 层,IP 地址对于在 IP 设备之间正确传输数据来说至关重要。相比之下,应用协议必须关注分配给每个应用程序实例的端口号,以便协议可以正确使用 TCP 或 UDP。

因此,一个应用程序过程的整体标识实际上使用的是它在运行的宿主机的 IP 地址——或者更精确地说,是它所使用的网络接口——以及分配给它的端口号的组合。这个组合地址被称为套接字。套接字使用< IP 地址>:< 端口号>的表示法指定。例如,如果你有一个运行在 IP 地址 41.199.222.3 上的网站,该网站对应的 HTTP 服务器套接字将是41.199.222.3:80

提示

关键概念 设备上 TCP/IP 应用程序过程的整体标识符是其 IP 地址和端口号的组合,这被称为套接字

你有时也会看到使用主机名而不是 IP 地址来指定套接字,如下所示:< 主机名>:< 端口号>。要使用此描述符,网络浏览器必须首先使用 DNS 将名称解析为 IP 地址。例如,你可能找到一个网站 URL,如www.thisisagreatsite.com:8080。这告诉网络浏览器首先使用 DNS 将名称www.thisisagreatsite.com解析为 IP 地址。然后它告诉浏览器使用非标准服务器端口号 8080 向该地址发送请求,浏览器偶尔会使用端口号 8080 而不是端口号 80。(有关更多信息,请参阅第七十章中关于使用 URL 进行应用层地址讨论的内容。)

套接字是 TCP/IP 应用程序操作的基本概念。实际上,它是与同名的 TCP/IP 应用程序程序接口(API)的基础:套接字。Windows 上的这个 API 版本被称为Windows 套接字Winsock,您可能之前听说过。这些 API 允许应用程序程序轻松地使用 TCP/IP 进行通信。

因此,一对设备之间的数据交换由从一台设备的套接字发送到另一台设备的套接字的一系列消息组成。每个设备通常会有多个同时进行的对话。在 TCP 的情况下,每个设备对在通信会话期间都会建立一个连接。这些连接必须被管理,并且需要它们具有唯一标识。这是通过连接的两个设备的套接字标识来完成的。

小贴士

关键概念 每个设备在任何给定时间都可能有多条 TCP 连接处于活动状态。每个连接都通过客户端套接字和服务器套接字的组合唯一标识,这些套接字又包含四个元素:客户端 IP 地址和端口号,以及服务器 IP 地址和端口号。

让我们回到图 43-3 中的例子。您正在从客户端 177.41.72.6 向网站 41.199.222.3 发送 HTTP 请求。该网站的服务器将使用已知的端口号 80,因此它的套接字是 41.199.222.3:80,正如您之前所看到的。您为网络浏览器分配了临时的端口号 3022,因此客户端套接字是 177.41.72.6:3022。这些设备之间的整体连接可以使用这个套接字对来描述:(41.199.222.3:80, 177.41.72.6:3022)。

要了解更多关于 TCP 如何识别连接的信息,请参阅第四十六章中关于 TCP 端口和连接识别的主题。

与 TCP 不同,UDP 是一种无连接协议,因此它显然不使用连接。发送和接收设备上的套接字对仍然可以用来识别正在交换数据的两个进程,但由于没有连接,套接字对在 TCP 中的重要性并不相同。

常见的 TCP/IP 应用程序和已知及注册的端口号

TCP/IP 协议套件的巨大普及导致了成千上万种不同应用程序和协议的发展。其中大多数都使用了我在本章前面讨论过的客户端/服务器操作模型。特定应用程序的服务器进程被设计为使用特定的保留端口号,而客户端使用一个短暂的(临时)端口号来与服务器建立连接。为了确保每个人都同意每个服务器应用程序应该为每个应用程序使用哪个端口号,端口号由 IANA 集中管理。

最初,IANA 将已知和注册的端口号列表保存在一个冗长的文本文档中,其中还包含了 IANA 负责的许多其他参数(如 IP 协议字段编号、ICMP 的类型和代码字段值等)。这些端口号定期在名为“分配号码”的互联网(RFC)标准文档中发布。这种系统在互联网的早期阶段运行良好,但到了 20 世纪 90 年代中期,这些值变化得太快,使用 RFC 流程已不可行。发布它们的工作量太大,而且 RFC 发布后实际上就过时了。

最后的“分配号码”标准是 RFC 1700,该标准于 1994 年 10 月发布。在那之后,IANA 转向使用一组包含他们管理的参数的万维网文档。这使得 IANA 能够不断更新列表,并使 TCP/IP 用户能够获取更准确的信息。RFC 1700 于 2002 年被正式废除。

您可以在www.iana.org/numbers.html找到 IANA 维护的所有参数的完整信息。包含 TCP/UDP 端口分配的文件的 URL 是www.iana.org/assignments/port-numbers

本文档是所有已知和注册的 TCP 和 UDP 端口分配的最终列表。每个端口号都分配了一个简短的关键字,以及使用该协议的简要描述。这份文档有两个问题。首先,它非常长;包含超过 10,000 行文本。其中提到的绝大多数协议都是用于晦涩的应用程序,你可能以前从未听说过(我肯定大多数都没听说过!)。这使得很难轻松地看到最常用协议的端口分配。

这份文档的另一个问题是,它显示同一个端口号既为 TCP 又为 UDP 的应用程序所保留。正如我之前提到的,TCP 和 UDP 端口号实际上是独立的,因此,从理论上讲,一个端口号可以分配 TCP 端口 80 给一种服务器应用程序类型,而将 UDP 端口 80 分配给另一种。人们认为这会导致混淆,因此,除了极少数例外,同一应用程序的 TCP 和 UDP 列表中显示的端口号是相同的。尽管如此,在列表中显示这一点也有一个缺点:您无法知道应用程序实际使用的是哪种协议,以及哪种只是为了保持一致性而保留的。

考虑到所有这些,我决定包括几个总结表格,显示最常见 TCP/IP 应用程序的已知和注册端口号。我指出了协议是否使用 TCP、UDP 或两者都使用。表 43-1 列出了最常见 TCP/IP 应用协议的已知端口号。

表 43-1. 常见 TCP/IP 已知端口号和应用

端口号 TCP/UDP 关键词 协议缩写 应用或协议名称/注释
7 TCP + UDP echo 回声协议
9 TCP + UDP discard 丢弃协议
11 TCP + UDP systat 活跃用户协议
13 TCP + UDP daytime 白天协议
17 TCP + UDP qotd QOTD 每日名言协议
19 TCP + UDP chargen 字符发生器协议
20 TCP ftp-data FTP(数据) 文件传输协议(默认数据端口)
21 TCP ftp FTP(控制) 文件传输协议(控制/命令)
23 TCP telnet Telnet 协议
25 TCP smtp SMTP 简单邮件传输协议
37 TCP + UDP time 时间协议
43 TCP nicname Whois 协议(也称为 Nicname)
53 TCP + UDP domain DNS 域名服务器(域名系统)
67 UDP bootps BOOTP/DHCP 引导协议/动态主机配置协议(服务器)
68 UDP bootpc BOOTP/DHCP 引导协议/动态主机配置协议(客户端)
69 UDP tftp TFTP 简单文件传输协议
70 TCP gopher Gopher 协议
79 TCP finger Finger 用户信息协议
80 TCP http HTTP 超文本传输协议(万维网)
110 TCP pop3 POP 邮政协议(第 3 版)
119 TCP nntp NNTP 网络新闻传输协议
123 UDP ntp NTP 网络时间协议
137 TCP + UDP netbios-ns NetBIOS(名称服务)
138 UDP netbios-dgm NetBIOS(数据报服务)
139 TCP netbios-ssn NetBIOS(会话服务)
143 TCP imap IMAP 互联网消息访问协议
161 UDP snmp SNMP 简单网络管理协议
162 UDP snmptrap SNMP 简单网络管理协议(陷阱)
179 TCP bgp BGP 边界网关协议
194 TCP irc IRC 互联网中继聊天
443 TCP https HTTP over SSL 超文本传输协议安全套接字层
500 UDP isakmp IKE IPsec 互联网密钥交换
520 UDP router RIP 路由信息协议(RIP-1 和 RIP-2)
521 UDP ripng RIPng 路由信息协议 - 新一代

注册端口号按照定义是用于未使用 RFC 过程标准化的协议,因此它们大多是神秘的应用程序,我认为没有必要列出所有这些。表 43-2 展示了其中一些我认为特别有趣的应用。

表 43-2. 常见 TCP/IP 注册端口号和应用

端口号 TCP/UDP 关键词 协议缩写 应用或协议名称/注释
1512 TCP + UDP wins WINS 微软 Windows 互联网命名服务
1701 UDP l2tp L2TP 层 2 隧道协议
1723 TCP pptp PPTP 点对点隧道协议
2049 TCP + UDP nfs NFS 网络文件系统
6000–6063 TCP x11 X11 X 窗口系统

第四十四章:TCP/IP 用户数据报协议(UDP)

无标题图片

TCP/IP 协议套件以互联网协议(IP)和传输控制协议(TCP)的名字命名,这本身就暗示了这两个是套件中的两个关键协议。IP 位于网络层,而 TCP 位于传输层。难怪很多人甚至没有意识到 TCP/IP 中还有一个第二层传输层协议。

就像害羞的小弟弟一样,用户数据报协议(UDP)在阴影中坐着,而 TCP 却得到了荣耀。这个更花哨的兄弟确实应该得到很多这样的关注,因为 TCP 可以说是两者中更重要的一方。然而,UDP 在 TCP/IP 协议套件中填补了一个关键的角色,因为它允许许多应用程序在使用 TCP 时达到最佳状态。

在本章中,我讨论了 UDP,这是一种更简单、不太为人所知的 TCP/IP 传输协议。我首先概述了该协议,并描述了其历史和标准。我概述了 UDP 的工作方式,并解释了 UDP 消息使用的格式。最后,我讨论了使用 UDP 的应用类型以及分配给它们的知名或注册端口号。

UDP 概述、历史和标准

我想,我在本节引言中提到的兄弟姐妹竞争的比喻可能有点愚蠢。我高度怀疑协议会在夜晚醒来担心我们使用它们的程度。然而,考虑到与 TCP 相比得到的关注如此之少,发现 UDP 实际上有多么重要是非常有趣的。事实上,在真正的哥哥,抢风头的风格中,你甚至无法真正理解 UDP 的历史,除非首先讨论 TCP。

在第八章中,我描述了 TCP/IP 的历史,我解释说,在协议套件的早期开发阶段,只有一个协议处理 IP 和 TCP 执行的功能。这个协议被称为 TCP,它提供了类似于 IP 的网络层连接性,并建立了连接,提供了可靠性,并处理了与现代 TCP 相关联的典型传输层质量要求,例如流量控制和重传处理。

在开发初期的联合 TCP 协议的开发者很快意识到,将这些功能混合在一起是一个错误。虽然大多数传统应用需要经典的传输层可靠性功能,但有些则不需要。这些特性引入了开销,无论应用是否真的需要可靠性功能,都会增加这种开销。更糟糕的是,对于某些应用来说,这些特性不仅没有价值,反而有害,因为即使是由于开销导致的微小性能损失也会成为一个问题。

解决方案是将原始协议分离成 IP 和 TCP。IP 将执行基本互连,而 TCP 将执行可靠性功能。这为创建一个替代传输层协议——UDP——铺平了道路,该协议适用于不需要或不需要 TCP 提供的功能的应用。

与 UDP 相关联的两个主要属性始终是简单和快速。UDP 是一个简单的协议,它使用一个非常直接的消息结构,这与许多其他 TCP/IP 协议使用的消息格式相似(与 TCP 使用的更复杂的数据结构——流和段相对比)。实际上,当你把它简化到极致,UDP 的唯一真正目标是作为在更高层运行的网络应用进程之间的接口,以及 IP 的互连能力。

与 TCP 类似,UDP 通过使用 UDP 端口号在 IP 之上叠加了一种传输层寻址方法(因此,进程标识)。UDP 包括一个可选的校验和功能用于错误检测,但几乎不添加其他功能。

要看到 UDP 的简单性,最好的办法是查看定义它的标准。或者,我应该说标准(单数形式),因为只有一个。UDP 在 1980 年的 RFC 768,“用户数据报协议”中被定义。这份文件长度为三页,而且没有人需要修订它。

UDP 是一种快速协议,这正是因为它没有 TCP 的所有花哨功能。这使得它对于许多,如果不是大多数典型的网络应用来说,都不适合使用。但对于某些应用来说,这种速度正是它们从传输层协议中想要的,即一种能够快速将应用数据打乱并迅速将其下放到 IP 层,而无需太多麻烦的东西。选择使用 UDP,应用程序编写者自己承担起处理诸如可靠性、重传等问题,如果需要的话。这可能是成功或失败的因素,取决于应用以及编写者如何仔细使用 UDP。

小贴士

关键概念 用户数据报协议(UDP)是为那些在传输层不需要可靠性、确认或流量控制功能的应用协议而开发的。它被设计成简单快捷。它只提供传输层寻址(以 UDP 端口号的形式),可选的校验和功能,以及很少的其他功能。

UDP 操作

UDP 非常简单,以至于我无法详细说明它是如何工作的。它被设计成尽可能少地做事情。

UDP 做什么

UDP 的唯一真正任务是接收来自高层协议的数据并将其放置在 UDP 消息中,然后将其传递给 IP 进行传输。使用 UDP 进行传输的基本步骤如下:

  1. 高层数据传输 应用程序向 UDP 软件发送消息。

  2. UDP 消息封装 高层消息被封装在 UDP 消息的数据字段中。UDP 消息的头部被填写,包括发送数据的源端口号和目标端口号。校验和值也可能被计算。

  3. 将消息传递给 IP UDP 消息被传递给 IP 进行传输。

就是这样。当然,当目标设备接收到消息时,这个简短的过程会被反转。

UDP 不做什么

UDP 非常简单,其操作通常用它不做什么来描述,而不是它做什么。作为一个传输协议,UDP 不执行以下操作:

  • 在发送数据之前建立连接。它只是打包数据并发送。

  • 提供确认以显示数据已被接收。

  • 提供任何保证其消息将到达。

  • 检测丢失的消息并重新传输它们。

  • 确保数据以发送的相同顺序接收。

  • 提供任何机制来处理拥塞或管理设备之间的数据流。

小贴士

关键概念 UDP 可能是 TCP/IP 中所有协议中最简单的一个。它接收传递给它的应用层数据,将其封装在简化的消息格式中,然后将其发送给 IP 进行传输。

如果这些限制听起来与 IP 的限制相似,那么你注意到了。UDP 基本上是带有传输层端口地址的 IP。(因此,UDP 有时被称为包装协议,因为它所做的只是将应用数据包装在其简单的消息格式中,并将其发送到 IP。)

然而,尽管有前面的列表,UDP 中确实存在一些有限的反馈和错误检查机制。一个是可选的校验和功能,它可以允许检测传输中的错误或 UDP 消息被错误地发送到错误位置的情况(参见下一节“UDP 消息格式”的详细信息)。另一个是互联网控制消息协议(ICMP)错误报告(参见第三十一章和图 44-1 显示了 UDP 消息的格式。

UDP 校验和字段是协议中有点令人困惑的一个区域。校验和的概念本身并不新颖;校验和在网络协议中被广泛使用,以提供对错误的保护。有点奇怪的是,这个计算校验和的概念不仅适用于常规数据报,还适用于伪头部。因此,UDP 软件不是只计算 UDP 数据报中的字段校验和,而是首先构建一个包含以下字段的假附加头部:

  • IP 源地址字段

  • IP 目标地址字段

  • IP 协议字段

  • UDP 长度字段

UDP 消息格式

图 44-1. UDP 消息格式

表 44-1. UDP 消息格式

字段名称 大小(字节) 描述
源端口 2 在源设备上发起 UDP 消息的进程的 16 位端口号。这通常是一个客户端(临时)端口号,客户端向服务器发送请求,或者是一个已知/已注册(服务器)端口号,服务器向客户端发送回复。(有关详细信息,请参见第四十三章)。
长度 2 整个 UDP 数据报的长度,包括头部和数据字段。
校验和 2 可选的 16 位校验和,计算整个 UDP 数据报加上特殊字段伪头部。有关更多信息,请参阅下文。
数据 可变 将要发送的封装的高层消息。

UDP 伪头部格式在图 44-2 中展示。

UDP 伪头部格式

图 44-2. UDP 伪头部格式

这个伪头部的总长度是 11 字节。它通过一个字节的零填充到 12 字节,然后附加到真实的 UDP 消息前。然后计算伪头部和真实 UDP 消息的组合校验和,并将值放入校验和字段。伪头部仅用于此计算,然后被丢弃;它实际上并不传输。目标设备中的 UDP 软件在计算其校验和时创建相同的伪头部,以便与 UDP 头部中传输的进行比较。

在常规 UDP 字段上计算校验和可以保护 UDP 消息免受位错误的影响。添加伪头部允许校验和也保护 UDP 消息免受其他类型的问题,最值得注意的是意外将消息发送到错误的目的地。UDP 中的校验和计算,包括使用伪头部,与 TCP 中使用的方法完全相同(除了 TCP 中的长度字段不同)。有关伪头部为什么重要的完整描述以及使用 IP 字段在传输层数据报计算中的有趣影响的详细信息,请参阅第四十八章。

提示

关键概念 UDP 将应用层数据打包成一个非常简单的消息格式,该格式仅包含四个头部字段。其中一个是可选的校验和字段。当使用校验和字段时,校验和是在真实头部和来自 UDP 和 IP 头部的字段的一个特殊伪头部上计算的,其方式与 TCP 校验和计算非常相似。

注意,在 UDP 中,使用校验和字段是可选的。如果 UDP 不使用校验和字段,它将将其设置为全零的值。然而,这可能会引起混淆,因为当 UDP 使用校验和时,计算有时会导致零值。为了避免让目的地认为在这种情况下 UDP 没有使用校验和,UDP 将这个零值表示为全一的值(十进制的 65,535)。

UDP 常见应用程序和服务器端口分配

正如你所看到的,UDP 包含的功能非常少。除了 UDP 端口代表的重要寻址能力之外,使用 UDP 在很大程度上类似于使用 IP。这意味着 UDP 具有与 IP 相同的许多缺点。它不会在设备之间建立持久的连接;它不会确认接收到的数据或重传丢失的消息;并且它当然不关心诸如流量控制和拥塞管理之类的奥秘。

这些功能的缺失使得 UDP 对于大多数经典网络应用来说根本不适用。这些应用程序通常需要建立连接,以便两个设备可以交换数据。许多应用程序还必须具备偶尔或定期发送大量数据的能力,这些数据必须完整接收才有价值。例如,考虑一个像超文本传输协议(HTTP)这样的消息传输协议。如果只有网页的一部分从服务器传回网页浏览器,那么它是无用的。HTTP 和其他类似的文件和消息传输协议需要 TCP 的功能。

为什么一些 TCP/IP 应用程序使用 UDP

那么,哪些应用程序使用 UDP 呢?UDP 的经典限制是,因为它不提供可靠性功能,所以使用 UDP 的应用程序需要负责这些功能。实际上,如果一个应用程序需要 TCP 提供的功能,但不包括 UDP 提供的功能,那么允许应用程序实现这些功能是不高效的,除非在特殊情况下。如果应用程序需要 TCP 提供的东西,它应该直接使用 TCP!然而,仅需要 TCP 实现部分功能的应用程序有时使用 UDP 并在应用层实现这一有限功能集会更好。

因此,在 UDP 上运行的应用程序通常是那些不需要 TCP 所具有的所有或大多数功能的应用程序。这些应用程序可以从避免与 TCP 相关的设置和开销带来的效率提升中受益。通常(但不总是)这些应用程序符合这一描述,因为它们发送的数据属于以下两个类别之一:

性能比完整性更重要的数据 这个类别的经典例子是多媒体应用程序。对于在互联网上流式传输视频片段,最重要的功能是流开始快速流动并保持流动。人类只注意到这类信息流动中的重大中断,因此由于丢失的数据报而丢失的几个字节并不是大问题。此外,即使有人使用 TCP 进行类似操作并注意到并重传丢失的数据报,这将是无用的,因为丢失的数据报将属于剪辑中很久以前的部分——在该重传中花费的时间可能会使当前部分的视频片段迟到。显然,UDP 最适合这种情况。

“简短而甜蜜”的数据交换 在许多 TCP/IP 应用程序中,底层协议仅由非常简单的请求/回复交换组成。客户端向服务器发送简短请求消息,然后服务器将简短回复消息发送回客户端。在这种情况下,实际上没有必要像 TCP 那样建立连接。此外,如果客户端只发送一条简短消息,单个 IP 数据报就可以携带该消息。这意味着没有必要担心数据到达顺序、设备间的流量控制等问题。那么请求或回复的丢失怎么办?这些可以在应用层使用计时器简单地处理。如果客户端发送请求而服务器没有收到,服务器将不会回复,客户端最终会发送替换请求。如果服务器发送的响应从未到达,同样的逻辑也适用。

这些是最常见的 UDP 使用情况,但还有其他原因。例如,如果一个应用程序需要多播或广播数据,它必须使用 UDP,因为 TCP 仅支持两个设备之间的单播通信。

小贴士

关键概念 协议在两种情况下使用 UDP 而不是 TCP。第一种情况是当应用程序更重视及时交付而非可靠交付,并且当 TCP 重传丢失的数据价值有限或甚至没有价值时。第二种情况是当简单的协议可以在应用层使用计时器/重传策略来处理 IP 数据报本身的潜在丢失,并且当 TCP 的其他特性不是必需时。需要多播或广播传输的应用程序也使用 UDP,因为 TCP 仅支持两个设备之间的单播通信。

顺便提一下,我阅读过关于过去在 UDP 应用程序中发生的问题。有时,程序员没有意识到 UDP 做得有多少,它如何让应用程序负责处理互联网环境中的所有潜在的不确定性。编写基于 UDP 的应用程序的人必须始终牢记,没有人可以假设目标是否会接收任何消息。测试不足可能导致在更大互联网环境中的最坏情况下的灾难,尤其是互联网。

常见 UDP 应用程序和服务器端口使用

表 44-2 展示了一些使用 UDP 的更有趣的协议以及每个协议用于其服务器进程的知名和注册端口号。它还简要说明了为什么这些协议使用 UDP 而不是 TCP。

同时使用 UDP 和 TCP 的应用程序

有些协议同时使用 TCP/IP 传输层协议。这通常发生在设计为接受两种传输层协议连接的实用协议中,或者在某些情况下需要 TCP 的好处,而在其他情况下则不需要。

后者的经典例子是 TCP/IP 域名系统 (DNS),它通常使用 UDP 端口 53 进行简单的请求和回复,这些请求通常较短。需要可靠交付的较大消息,如区域传输,则使用 TCP 端口 53。请注意,在 表 44-2 中,我省略了一些不太重要的协议,例如用于诊断目的的协议(回声、丢弃、字符生成等)。有关所有常见应用程序的完整列表,请参阅 第四十三章。

表 44-2. 常见 UDP 应用程序和服务器端口分配

端口号 关键词 协议 备注
53 域名 域名系统 (DNS) 使用简单的请求/回复消息系统进行大多数交换(但也会使用 TCP 进行较长的交换)。
67 和 68 bootps/bootpc 引导协议 (BOOTP) 和动态主机配置协议 (DHCP) 由简短的请求和回复交换组成的宿主配置协议。
69 tftp 简单文件传输协议 (TFTP) TFTP 是一个专门为 UDP 设计的协议的绝佳例子,尤其是与常规 FTP 相比。后者使用 TCP 在两个设备之间建立会话,然后利用其庞大的命令集和 TCP 的特性,以确保可能非常大的文件的可靠传输。相比之下,TFTP 是为快速轻松地传输小文件而设计的。为了避免文件损坏,TFTP 包含了 TCP 的一些简单版本的功能,例如确认。
161 和 162 snmp 简单网络管理协议 一种使用相对较短消息的行政协议。
520 和 521 router/ripng 路由信息协议 (RIP-1, RIP-2, RIPng) 与像 BGP 这样更复杂的路由协议不同,RIP 使用简单的请求/回复消息系统,不需要连接,并且确实需要多播/广播。这使得它成为 UDP 的一个自然选择。如果由于请求而发送的路由更新丢失,可以通过发送新的请求来替换。在下一个周期中,丢失的常规(非请求)更新将被替换。
2049 nfs 网络文件系统 NFS 是一个有趣的案例。由于它是一个文件共享协议,您可能会认为它应该使用 TCP 而不是 UDP,但最初它是为了性能原因而设计为使用 UDP。许多人认为这不是最佳的设计决策,后来的版本转向使用 TCP。最新的 NFS 版本仅使用 TCP。

第四十五章。TCP 概述、功能和特性

无标题图片

正如我在第四十二章中提到的,传输控制协议(TCP)是 TCP/IP 协议套件中的一个关键部分。它也是一个相当复杂的协议,包含许多重要的概念和机制,您需要理解。老笑话说“吃象最好的方法是每次咬一口。”同样,在这里,您可以通过逐步理解这个复杂的协议,从对其高层次的观察开始,了解其来源和作用,来最好地理解其操作。

在本章中,我首先向您介绍 TCP。我首先提供 TCP 的概述和历史,然后描述定义它的标准。然后,通过列出其功能和解释 TCP 的工作原理,即描述其最重要的特性,来展示 TCP 实际上做什么。这将让您对 TCP 有一个大致的了解,并为后续章节中更复杂的技术讨论奠定基础。

TCP 概述、历史和标准

在 OSI 参考模型中,第 3 层和第 4 层代表网络软件(需要通过网络移动数据的应用程序)和网络硬件(在网络中传输数据的设备)之间的接口。任何协议套件都必须有一个或一组协议来处理这些第 3 层和第 4 层功能。

TCP/IP 协议套件是以提供这些功能的两个主要协议命名的。TCP 和互联网协议(IP)都允许软件在互连网络上运行。IP 处理互连网络数据报的交付和路由,而 TCP 处理连接并提供可靠性。然而,有趣的是,在协议套件的早期阶段,实际上根本不存在 TCP/IP。

TCP 历史

由于 TCP 在网络历史中扮演着突出的角色,不回顾协议套件的早期阶段就无法描述 TCP。在 20 世纪 70 年代初,我们今天所知道的全球互联网是一个名为ARPAnet的小型研究型互连网络,这个名字来源于美国国防高级研究计划局(DARPA 或 ARPA)。这个网络使用了一种名为网络控制协议(NCP)的技术,它允许主机相互连接。NCP 大致完成了今天 TCP 和 IP 一起完成的相同工作。

由于 NCP 的限制,开始开发一个新的协议,该协议更适合不断增长的互连网络。这个新协议首次在 RFC 675 中正式化,被称为互联网传输控制程序(TCP)。像其前身 NCP 一样,TCP 负责实现应用程序在互连网络上运行所需的所有基本功能。因此,最初 TCP 既是 TCP 也是 IP。

正如我在第八章中详细解释的那样,在调整和修订 TCP 的过程中花费了几年时间,该协议的第二个版本于 1977 年进行了记录。虽然 TCP 的功能稳步提升,但协议背后的基本概念存在问题。让 TCP 处理数据报传输、路由(第 3 层功能)、连接、可靠性和数据流管理(第 4 层功能)意味着 TCP 违反了协议分层和模块化的关键概念。TCP 迫使所有应用程序使用第 4 层功能才能使用第 3 层功能。这使得 TCP 缺乏灵活性,不适合仅需要低层功能而不需要高层功能的应用程序的需求。

因此,决定将 TCP 分为两部分:保留了第 4 层的功能,将 TCP 更名为传输控制协议(与传输控制程序相对)。第 3 层的功能变成了互联网协议。这种分割在 TCP 的第 4 个版本中得到最终确定,因此第一个 IP 也被赋予了“版本 4”的名称,以保持一致性。1981 年 9 月发布的 RFC 793,“传输控制协议”,定义了 TCP 版本 4,并且至今仍然是标准的当前版本。

尽管它已经超过 20 年历史,并且是大多数人首次使用的第一个版本,但版本 4 是经过多年工作和在早期互联网上测试的许多早期 TCP 版本的结果。因此,对于其年龄来说,这是一个非常成熟的协议。可以说是一个早熟的协议。(为了公平起见,其他标准已经描述了许多对 TCP 的附加功能和修改,而不是升级主要文档。)

TCP 操作概述

TCP 是一个功能齐全的传输层协议,它提供了典型应用程序在任意互联网上可靠传输数据所需的所有功能。它以 TCP 端口的形式为应用程序进程提供传输层寻址,允许机器使用这些端口来建立它们之间的连接。一旦设备相互连接,它们就可以在它们之间双向传递数据。应用程序可以将数据作为简单的字节流发送到 TCP,而 TCP 负责将数据打包并发送为 TCP 打包成 IP 数据报的段。接收设备的 TCP 实现会逆转这个过程,将设备最初发送的数据流传递给应用程序。

TCP 包含了一套广泛的机制。这些机制确保数据能够可靠、一致且及时地从源传输到目的地。其操作的关键在于滑动窗口确认系统,它允许每个设备跟踪其已发送的字节数据,并确认从连接的另一台设备接收到的数据。未确认的数据最终会自动重传,并且系统的参数可以根据设备和连接的需求进行调整。这个相同的系统还提供了设备之间的缓冲和流量控制能力。这些能力处理不均匀的数据传输速率和其他问题。

小贴士

关键概念 TCP/IP 协议套件中的主要传输层协议是 传输控制协议 (TCP)。TCP 是一种面向连接、确认、可靠的、功能齐全的协议,旨在为应用程序提供一种可靠的方式来使用不可靠的互联网协议 (IP) 发送数据。它允许应用程序以字节流的形式发送数据字节,并自动将它们打包成适当大小的段进行传输。它使用特殊的滑动 窗口确认系统 来确保其接收者收到所有数据,处理必要的重传,并提供流量控制,以便连接中的每个设备可以管理其他设备向其发送数据的速率。

由于 TCP 具有许多功能,因此该协议很可能满足几乎所有需要可靠、面向连接的数据传输的应用程序。TCP 的一个主要目标是可靠的数据传输,这意味着高层应用程序不需要提供 TCP 的常见功能。因为大多数传统的消息传递应用程序都使用它,所以 TCP/IP 传输协议是最广泛使用的传输协议。

TCP 标准

RFC 793 是 TCP 的定义性标准,但它并没有包括现代 TCP 运行的所有细节。其他几个标准包括关于协议如何工作的附加信息,并描述了多年来开发的基本 TCP 机制的一些增强。其中一些相当晦涩,但它们对于获得对 TCP 的更完整理解是有用的。我在表 45-1 中列出了一些。

表 45-1. 补充 TCP 标准

RFC # Name Description
813 TCP 中的窗口和确认策略 讨论了 TCP 滑动窗口确认系统,描述了可能与之相关的问题,并提供了纠正这些问题的方法。
879 TCP 最大段大小及相关主题 讨论了控制 TCP 消息大小的关键最大段大小 (MSS) 参数,并将其与 IP 数据报大小相关联。
896 IP/TCP 互连网络中的拥塞控制 讨论了拥塞问题以及如何使用 TCP 来处理这些问题。注意正常的协议套件名称的有趣反转:IP/TCP。
1122 互联网主机要求 — 通信层 描述了 TCP 应在主机上实现的重要细节。
1146 TCP 替代校验和选项 指定了一种机制,允许 TCP 设备使用替代的校验和生成方法。
1323 TCP 高性能扩展 定义了用于高速链路和新 TCP 选项的 TCP 扩展。
2018 TCP 选择性确认选项 一种增强基本 TCP 功能的方法,允许 TCP 设备选择性地指定特定段进行重传。
2581 TCP 阻塞控制 描述了在 TCP 网络中用于阻塞控制的四种算法:慢启动、拥塞避免、快速重传和快速恢复。
2988 计算 TCP 的重传计时器 讨论了与设置 TCP 重传计时器相关的问题,该计时器控制设备在重传发送的数据之前等待确认的时间长度。

有数百种高层应用协议使用 TCP,因此它们的定义标准至少对它有简要的提及。

TCP 是设计用来使用 IP 的,因为它们是共同开发的,正如您所看到的,它们甚至曾经是同一规范的一部分。后来,为了尊重架构分层原则,它们被拆分了。因此,TCP 尽量对其运行的底层协议做出尽可能少的假设。它并不像您想象的那么严格地绑定到 IP 的使用,您甚至可以将其适应用于其他网络层协议。然而,就我们的目的而言,这应该主要被视为一个有趣的旁白。

TCP 功能

您现在已经看到了 TCP 的来源以及描述它的标准。正如我在本章引言中所说,TCP 是一个复杂的协议,因此解释它是如何工作的需要一些时间。在这里,我将描述 TCP 做了什么以及它没有做什么。

TCP 执行的功能

尽管 TCP 很复杂,但我可以通过描述其主要功能来简化其基本操作。以下是我认为 TCP 执行的五个主要任务:

寻址/多路复用 许多不同的应用使用 TCP 作为传输协议。因此,就像它的简单兄弟用户数据报协议(UDP)一样,将 TCP 从这些不同进程接收到的数据多路复用,以便可以使用底层网络层协议发送数据,对于 TCP 来说是一项重要的工作。同时,这些高层应用进程使用 TCP 端口进行标识。第四十三章 包含了大量关于这种寻址如何工作的详细信息。

建立、管理和终止连接 TCP 提供了一套设备可以遵循的流程,以便在数据可以传输的 TCP 连接上进行协商和建立。一旦连接打开,TCP 包括管理连接和处理可能由此产生的连接问题的逻辑。当设备完成 TCP 连接时,会遵循一个特殊的过程来终止它。

处理和打包数据 TCP 定义了一种机制,使得应用能够从高层向 TCP 发送数据。然后,这些数据被打包成消息,这些消息将被发送到目标 TCP 软件。目标软件解包数据并将其交给目标机器上的应用。

传输数据 从概念上讲,发送设备上的 TCP 实现负责将打包的数据传输到另一设备上的 TCP 进程。遵循分层原则,这种传输是通过发送机器上的 TCP 软件将数据包传递给底层网络层协议来完成的,这通常意味着 IP。

提供可靠性和传输质量服务 TCP 包含一系列服务和功能,允许应用程序将协议视为发送数据的可靠手段。这意味着通常 TCP 应用程序不需要担心数据发送后从未出现或以错误顺序到达。这也意味着如果直接使用 IP,可能会出现的其他常见问题得到了避免。

提供流量控制和拥塞避免功能 TCP 允许控制和管理两个设备之间的数据流。它还包括处理设备在相互通信过程中可能遇到的拥塞问题的功能。

TCP 不执行的功能

显然,TCP 负责了相当数量的关键功能。前一部分列出的项目可能看起来并不那么令人印象深刻,但这只是对协议的高层次概述。当你详细查看这些功能时,你会发现每个功能实际上都涉及到 TCP 需要完成的大量工作。

相反,有时 TCP 被描述为执行应用程序使用互联网所需的所有操作。然而,该协议并不是万能的。它有局限性,并且某些领域是其设计者明确没有涉及的。以下是一些 TCP 不执行的重要功能:

指定应用程序使用 TCP 定义了传输协议。它并不具体说明应用程序应该如何使用 TCP。这取决于应用程序协议。

提供安全性 TCP 不提供任何确保它传输的数据的真实性或隐私性的机制。如果应用程序认为真实性和隐私性很重要,它们必须使用其他方式来实现,例如使用 IPsec。

维护消息边界 TCP 以连续流的形式发送数据,而不是离散的消息。指定一个消息在哪里结束,下一个消息在哪里开始的责任在于应用程序。

保证通信 等一下;TCP 不是应该保证数据能够到达目的地吗?嗯,是的,也不是。TCP 会检测未确认的传输,并在需要时重新发送。然而,如果某种问题阻止了可靠的通信,TCP 唯一能做的就是不断尝试。它不能做出任何保证,因为有许多事情超出了它的控制范围。同样,它可以尝试管理数据流,但不能解决每个问题。

这个最后一点可能听起来有点繁琐,但这一点很重要,尤其是许多人倾向于认为 TCP 是坚不可摧的。通信的整体成功完全取决于底层互联网及其构成的各个网络。链条的强度取决于最薄弱的环节,如果底层存在问题,TCP 能做的任何事都无法保证数据传输的成功。

提示

关键概念 TCP 通过检测失败的传输并重新发送它们来提供可靠的通信。它不能保证任何特定的传输,因为它依赖于不可靠的 IP。它所能做的就是如果初始交付尝试失败,就不断尝试。

TCP 特性

在许多方面,研究 TCP 如何完成其工作比研究其功能更有趣。通过检查 TCP 及其操作的最重要属性,你可以更好地了解 TCP 的工作方式。你还可以看到它与其更简单的传输层兄弟 UDP 相比的许多不同之处。

TCP 具有以下特性,使其能够执行其功能:

面向连接的 TCP 要求设备在发送数据之前首先相互建立连接。这种连接在单元之间创建了一个相当于电路的连接;它类似于电话通话。发生一个协商过程,这个过程建立了连接,从而确保两个设备都同意他们如何交换数据。

双向 一旦建立了连接,TCP 设备就双向发送数据。连接上的两个设备都可以发送和接收,无论哪个设备启动了连接。

多连接和端点识别 用于连接的两个设备使用的套接字对标识了 TCP 连接的端点。这种识别方法允许每个设备打开多个连接,无论是到同一个 IP 设备还是不同的 IP 设备,并且可以独立处理每个连接,而不会发生冲突。

可靠 使用 TCP 的通信被认为是可靠的,因为 TCP 跟踪已发送和接收的数据,以确保所有数据都到达目的地。正如你在前面的部分中看到的,TCP 实际上不能保证数据总是会被接收。然而,它可以保证所有发送的数据都会被检查接收情况,检查数据完整性,并在需要时重新传输。

确认 提供可靠性的关键是 TCP 层确认所有传输。此外,TCP 不能保证远程应用程序会接收到所有这些传输。接收方必须告诉发送方,“是的,我收到了”每份数据传输。这与典型的消息协议形成鲜明对比,在典型的消息协议中,发送者永远不知道其传输发生了什么。正如你将看到的,这种确认是 TCP 整体操作的基础。

面向流 大多数底层协议被设计成,为了使用它们,高层协议必须以块的形式发送数据。IP 是这方面的最佳例子;你发送一个要格式化的消息给 IP,IP 将其放入数据报。UDP 也是这样工作的。相比之下,TCP 允许应用程序发送连续的数据流进行传输。应用程序不需要担心将这个流分成块进行传输;TCP 会处理这一点。

无结构数据 TCP 的流导向特性的重要后果是,在应用程序的数据流中,数据元素之间没有自然的分隔。当通过 TCP 发送多个消息时,应用程序必须提供一种方法来区分一条消息(数据元素、记录等)与下一条消息。

管理数据流 TCP 不仅仅是将数据打包并发送得尽可能快。TCP 连接被管理以确保数据均匀、平滑地流动,并且该连接包括处理沿途出现问题的能力。

你会注意到我没有把“慢”列为 TCP 的特性之一。确实,当应用程序出于性能原因不想处理 TCP 为连接和可靠性所包含的额外开销时,它们会使用 UDP。然而,这并不意味着 TCP 非常慢。实际上,它非常高效——如果不是这样,它可能永远不会得到如此广泛的应用。

小贴士

关键概念 为了总结 TCP 的关键特性,我们可以这样说:它是面向连接的、双向的、多连接的、可靠的、确认的、面向流的,并且管理流量。

鲁棒性原则

TCP 标准指出,TCP 遵循鲁棒性原则,其描述如下:“在做什么方面要保守;在从别人那里接受什么方面要宽容。”这条规则意味着每个 TCP 实现都试图避免做任何可能给其他设备的 TCP 层造成问题的任何事情。同时,每个 TCP 实现也在尝试预测其他 TCP 可能引起的问题,并试图优雅地处理这些问题。

这个原则代表了一种“双重保险”的方法,有助于在 TCP 操作中提供额外的保护,以应对异常情况。实际上,这个一般原则被应用于 TCP/IP 协议套件中的许多其他协议,这也是它多年来证明如此强大的部分原因。这个原则允许 TCP 和其他协议处理在大规模互联网(如互联网)的困难环境中可能出现的不预期问题。

第四十六章. 传输控制协议(TCP)基础和一般操作

无标题图片

许多人很难理解传输控制协议(TCP)的工作原理。在花费了数十个小时撰写了近 100 页关于该协议的文档后,我深感同情!我认为困难的主要原因在于,许多关于该协议的描述过于迅速地从简短的介绍跳到了 TCP 操作的令人困惑的细节。问题是 TCP 以一种非常特殊的方式工作。其操作建立在几个非常重要的基本原理之上,你绝对必须理解这些原理,否则 TCP 操作细节将难以理解。

在本章中,我描述了 TCP 的一些关键操作原理。我首先讨论了 TCP 如何处理数据,并介绍了流、段和序列的概念。然后,我描述了非常重要的 TCP 滑动窗口系统,该系统用于确认、可靠性和数据流控制。我还讨论了 TCP 如何使用端口以及如何识别连接。我还描述了使用 TCP 的最重要应用以及它们用于服务器应用所使用的端口。

TCP 数据处理和处理

在 OSI 参考模型上层中大多数协议的操作中,一个既定的事实是,这些协议是围绕消息的使用而构建的。这些消息类似于一个包含特定信息的信件,放在一个信封里。它们从高层传递到低层,在那里它们被封装在低层头部(就像放入另一个信封一样),然后继续向下传递,直到它们在物理层实际发送出去。

你可以通过查看用户数据报协议(UDP),TCP 的传输层对等协议,来看到一个很好的例子。要使用 UDP,应用程序将其一个独特的、通常相当短的数据块传递给它。该块被封装成一个 UDP 消息,然后发送到互联网协议(IP)。IP 将消息打包成一个 IP 数据报,最终将其传递给第二层协议,如以太网。在那里,IP 将其放入一个帧中,然后发送到第一层进行传输。

提高应用程序数据处理灵活性:TCP 的流导向

使用离散消息的使用相当简单,并且显然工作得很好,因为大多数协议都使用了它。然而,它本质上是有局限性的,因为它迫使应用程序创建离散的数据块以进行通信。有许多应用程序需要连续发送信息,这种方式不适合创建“数据块”。其他应用程序需要发送的数据块如此之大,以至于应用程序根本无法在较低层作为单个消息发送它们。

要使用像 UDP 这样的协议,许多应用程序将被迫人为地将它们的数据分成没有固有意义的消息大小。这会立即引入新的问题,需要应用程序做更多的工作。应用程序必须跟踪哪些数据在哪个消息中,并替换任何丢失的数据。它需要确保消息可以被正确顺序地重新组装,因为 IP 可能会以错误的顺序交付它们。

当然,你可以编写应用程序来执行此操作,但这几乎没有意义,因为这些功能已经是 TCP 负责处理的功能。相反,TCP 的设计者采取了非常聪明的通用化 TCP 的方法,使其能够接受任何大小和结构的应用程序数据,而无需要求数据是离散的部分。更具体地说,TCP 将来自应用程序的数据视为——因此,TCP 被描述为面向流的。每个应用程序将希望传输的数据作为稳定的字节流(字节)发送。应用程序不需要将数据分割成块或担心如何将长流传输到互联网。它只需“向 TCP 泵字节”。

TCP 数据打包:段

TCP 必须从应用程序接收字节,并使用网络层协议发送它们,在这种情况下是 IP。IP 是一个面向消息的协议;它不是面向流的。因此,我们只是“推卸责任”给了 TCP,它必须从应用程序接收流并将其分割成离散的消息供 IP 使用。这些消息被称为TCP 段

注意

是网络世界中最为混乱的数据结构名称之一。从词典定义的角度来看,将流的一部分称为是有意义的,但大多数与网络打交道的人并不认为消息是一个段。在行业中,该术语还指代电缆的长度或局域网(LAN)的一部分,等等,所以要注意这一点

IP 将 TCP 段视为所有其他离散消息进行传输。IP 将它们放入 IP 数据报中,并将它们传输到目标设备。接收方解包段并将它们传递给 TCP,TCP 将它们转换回字节流以便发送到应用程序。这个过程在图 46-1 中说明。

提示

关键概念 TCP 被设计为让应用程序以字节流的形式向它发送数据,而不是要求使用固定大小的消息。这为各种用途提供了最大的灵活性,因为应用程序不需要担心数据打包,可以发送任何大小的文件或消息。TCP 负责将这些字节打包成称为的消息。

设备上的 TCP 层会累积从应用程序进程流接收到的数据。在常规间隔内,TCP 层会形成它将通过 IP 传输的段。有两个主要因素控制段的大小。首先,有一个段大小的整体限制,这是为了防止在 IP 层发生不必要的分段。一个称为最大段大小(MSS)的参数控制这个大小限制。MSS 在连接建立期间确定。其次,TCP 被设计成一旦建立连接,每个设备都会告诉对方它随时准备接受多少数据。如果数据量低于 MSS 值,设备必须发送更小的段。这是本章稍后描述的滑动窗口系统的一部分。

TCP 数据标识:序列号

TCP 将来自应用程序的数据视为字节流的事实,对协议的操作有几个非常重大的影响。第一个与数据标识相关。由于 TCP 是可靠的,它需要跟踪从应用程序接收到的所有数据,以确保目标接收所有数据。此外,TCP 必须确保目标以应用程序发送数据的顺序接收数据,并且目标必须重新传输任何丢失的数据。

如果一个设备以块状消息的形式将数据传递给 TCP,那么通过给每个消息添加一个标识符来跟踪数据将相对简单。然而,由于 TCP 是面向流的,这种标识必须对每个数据字节进行!这可能会让人感到惊讶,但实际上这正是 TCP 通过使用序列号来实现的。每个数据字节都被分配一个序列号,用于在传输、接收和确认过程中跟踪它(尽管在实践中,使用块的开头和结尾的字节序列号来管理多个字节的块)。这些序列号用于确保发送应用程序传输并重新组装分段数据成为原始数据流。序列号是实施滑动窗口系统所必需的,这使 TCP 能够提供可靠性和数据流控制。

TCP 数据流处理和分段封装 TCP 与大多数协议不同,因为它不需要使用它的应用程序以消息的形式向它发送数据。一旦建立 TCP 连接,应用程序协议就可以向 TCP 发送一个稳定的字节流,这些字节不需要遵循任何特定的结构。TCP 将这些字节打包成基于多个不同参数大小的段。这些段被传递给 IP,在那里它们被封装成 IP 数据报并传输。接收设备会逆转这个过程:从 IP 数据报中移除段,然后从段中取出字节,并将它们作为字节流传递到适当的接收应用程序协议。

图 46-1. TCP 数据流处理和分段封装 TCP 与大多数协议不同,因为它不需要使用它的应用程序以消息的形式向它发送数据。一旦建立 TCP 连接,应用程序协议就可以向 TCP 发送一个稳定的字节流,这些字节不需要遵循任何特定的结构。TCP 将这些字节打包成基于多个不同参数大小的段。这些段被传递给 IP,在那里它们被封装成 IP 数据报并传输。接收设备会逆转这个过程:从 IP 数据报中移除段,然后从段中取出字节,并将它们作为字节流传递到适当的接收应用程序协议。

提示

关键概念 由于 TCP 与单个数据字节而不是离散消息一起工作,它必须使用在字节级别上工作的标识方案来实现其数据传输和跟踪系统。这是通过为 TCP 处理的每个字节分配一个序列号来实现的。

应用数据定界的需求

当 TCP 将传入数据视为流时,使用 TCP 的应用程序接收到的数据被称为非结构化。在传输过程中,数据流进入发送设备上的 TCP,在接收过程中,数据流返回接收设备上的应用程序。尽管 TCP 将流分解成段进行传输,但这些段是 TCP 级别的细节,对应用程序来说是隐藏的。当设备想要发送多个数据块时,TCP 不提供指示这些数据块之间分隔线的机制,因为 TCP 不检查数据的含义。应用程序必须提供一种方法来做这件事。

以一个发送数据库记录的应用程序为例。它需要传输来自 Employees 数据库表的记录 579,然后是记录 581 和记录 611。它将这些记录发送给 TCP,TCP 将它们作为一个字节流整体处理。TCP 会将这些字节打包成段,但以应用程序无法预测的方式。每个字节最终可能出现在不同的段中,但更有可能它们都在一个段中,或者每个记录的一部分最终出现在不同的段中,这取决于它们的长度。记录必须有一些明确的标记,以便接收设备可以知道一个记录在哪里结束,下一个在哪里开始。

小贴士

关键概念 由于应用程序将数据作为字节流而不是预包装的消息发送给 TCP,因此每个应用程序都必须使用自己的方案来确定一个应用程序数据元素在哪里结束,下一个在哪里开始。

TCP 滑动窗口确认系统

与像 UDP 这样的简单传输协议相比,TCP 与设备之间发送数据的方式的质量不同。TCP 不会只是将数据放入消息中,然后说“出发”,而是仔细跟踪它发送的数据。这种数据管理对于满足协议的两个关键要求是必要的:

可靠性 确保发送的数据实际上到达了目的地,如果没有到达,检测到这一点并重新发送。

数据流控制 管理发送数据的速率,以确保它不会使接收设备超载。

为了完成这些任务,整个协议的操作都是围绕所谓的滑动窗口确认系统进行的。说理解滑动窗口的工作方式对于理解 TCP 中的几乎所有其他内容至关重要,这并不夸张。不幸的是,如果你试图一次性掌握它,这可能会有些难以理解。我想确保我详细解释了机制,而不假设你已经理解了它。因此,我将从解释滑动窗口背后的概念开始,特别是这项技术是如何工作的以及为什么它如此强大。

不可靠协议的问题:缺乏反馈

一个简单的“发送后即忘”协议,如 IP,是不可靠的,并且没有流量控制,主要原因在于它是一个开环系统,其中发送者无法从接收者那里获得反馈。(在此讨论中,我忽略了使用 ICMP 等方式发送的错误报告。)发送了一个数据报,它可能到达也可能不到达,但发送者将永远无法知道,因为没有反馈机制。这一概念在图 46-2 中得到了说明。

不可靠协议的运行图 46-2. 在一个像 IP 所使用的系统,如果一条消息成功到达目的地,那当然很好;否则,没有人会知道发生了什么。需要某种外部机制来处理丢失的消息,除非协议根本不在乎其消息流中是否缺少一些比特和片段。

图 46-2. 不可靠协议的运行在一个像 IP 所使用的系统,如果一条消息成功到达目的地,那当然很好;否则,没有人会知道发生了什么。需要某种外部机制来处理丢失的消息,除非协议根本不在乎其消息流中是否缺少一些比特和片段。

使用带有重传的正确认认(PAR)提供基本可靠性

在像 IP 这样的不可靠协议上运行的协议中的基本可靠性可以通过关闭循环来实现,使接收者向发送者提供反馈。这最简单的方法是使用一个简单的确认系统。设备 A 向设备 B 发送数据,设备 B 接收数据并发送一个确认信息说:“设备 A,我已收到你的消息。”然后设备 A 就知道它的传输是成功的。

但是,由于 IP 是不可靠的,那条消息实际上可能永远无法到达目的地。设备 A 会坐等确认,但永远不会收到。相反,也有可能设备 B 从设备 A 那里收到了消息,但确认信息本身却神秘消失了。在两种情况下,我们都不希望设备 A 永远等待一个永远不会到达的确认。

为了防止这种情况发生,设备 A 在首次向设备 B 发送消息时启动一个计时器,这允许足够的时间让消息到达设备 B,确认消息返回,以及一些合理的时间来应对可能的延迟。如果在收到确认消息之前计时器已经到期,设备 A 会假设存在问题并重新传输其原始消息。由于这种方法涉及肯定确认(“是的,我收到了你的消息”)以及在需要时进行重传的功能,它通常被称为带重传的肯定确认(PAR),如图 46-3 所示。

基本可靠性:带重传的肯定确认(PAR)此图展示了确保可靠性最常见和简单的方法之一。每次设备 A 发送消息时,它都会启动一个计时器。设备 B 在接收到消息后,会向设备 A 发送一个确认消息,这样设备 A 就知道消息已成功传输。如果消息丢失,计时器会超时,设备 A 会重新传输数据。请注意,任何时候只能有一个消息处于待处理状态,这使得该系统相当慢。

图 46-3. 基本可靠性:带重传的肯定确认(PAR)此图展示了确保可靠性最常见和简单的方法之一。每次设备 A 发送消息时,它都会启动一个计时器。设备 B 在接收到消息后,会向设备 A 发送一个确认消息,这样设备 A 就知道消息已成功传输。如果消息丢失,计时器会超时,设备 A 会重新传输数据。请注意,任何时候只能有一个消息处于待处理状态,这使得该系统相当慢。

小贴士

关键概念 确保通信可靠性的基本技术使用一条规则,要求设备在每次成功接收传输后发送一个确认。如果设备在一段时间后没有确认传输,其发送者会重新传输确认。这种系统被称为带重传的肯定确认(PAR)。这种基本方案的一个缺点是,在第一个设备确认第一个消息之前,发送者不能发送第二个消息。

PAR 是一种在计算机网络和通信中广泛使用的协议技术,用于交换相对较小的数据量或交换数据频率较低的协议。基本方法是功能性的,但并不适合像 TCP 这样的协议。一个主要原因是它效率低下。设备 A 发送一条消息,然后等待确认。设备 A 在收到设备 B 确认它已收到原始消息之前不能向设备 B 发送另一条消息,这是非常浪费的,会使协议变得极其缓慢。

改进 PAR

我们可以对 PAR 系统进行的第一个改进是为发送的消息以及确认提供一些识别手段。例如,我们可以在消息头中添加一个消息 ID 字段。发送消息的设备将唯一标识它,接收方将使用这个标识符在确认中。例如,设备 A 可能通过消息 ID 1 发送一块数据。设备 B 将接收这条消息,然后向设备 A 发送自己的消息,说:“设备 A,我已收到你的消息 1。”这个系统的优点是设备 A 可以一次发送多条消息。它必须跟踪它发送的每一条消息,以及设备 B 是否发送了确认。每个设备还需要一个单独的计时器,但这不是什么大问题。

当然,我们还需要从设备 B 的角度考虑这种交换。以前,设备 B 一次只能处理来自设备 A 的一条消息。现在,它可能一次会有几条消息同时出现。如果设备 B 已经忙于处理来自其他设备(或十个设备)的传输怎么办?我们需要一种机制让设备 B 能够说:“我一次只能处理你发来的以下数量消息。”我们可以通过让确认消息包含一个字段,例如发送限制,来指定设备 A 一次允许发送给设备 B 的最大未确认消息数量。

设备 A 将使用这个发送限制字段来限制它向设备 B 发送消息的速率。设备 B 可以根据其当前负载和其他因素调整这个字段,以最大化与设备 A 的通信性能。因此,这个增强的系统将提供可靠性、效率和基本的数据流控制,如图图 46-4 所示。

小贴士

关键概念 通过标识要发送的每个消息,可以增强基本的 PAR 可靠性方案,这样一次可以有多个消息在传输中。发送限制的使用允许机制提供流量控制能力,通过允许每个设备控制其他设备向其发送数据的速率。

TCP 的面向流的滑动窗口确认系统

那么 TCP 是否使用这种 PAR 的变体呢?当然不是!那会太简单了。从概念上讲,TCP 滑动窗口系统与这种方法非常相似,这就是为什么理解它很重要。然而,它需要进行一些调整。主要原因与 TCP 处理数据的方式有关:与本章前面讨论的消息导向相比,这是流导向的问题。我概述的技术涉及对消息的显式确认和(如果需要)重传。因此,它非常适合交换相对较大消息且频率较低的协议。

另一方面,TCP 将数据字节视为一个流来处理。逐个字节发送并逐个确认显然是荒谬的。这将需要太多的工作,即使是在重叠传输的情况下(即,在发送下一份数据之前不等待确认),结果也会非常慢。

增强的 PAR 此图显示了从...的基本 PAR 方案的两个增强。首先,现在每个消息都有一个标识号;每个消息都可以单独确认,因此可以在给定时间内有多个消息在传输中。其次,设备 B 定期向设备 A 发送一个发送限制参数,该参数限制设备 A 一次可以有多少个待处理消息。设备 B 可以调整此参数以控制从设备 A 流向的数据流。

图 46-4. 增强的 PAR 此图显示了从图 46-3 此图显示了确保可靠性最常见和简单的方法之一。每次设备 A 发送消息时,它都会启动一个计时器。设备 B 在接收到消息后向设备 A 发送确认,这样设备 A 就知道它成功传输了消息。如果消息丢失,计时器就会响起,设备 A 会重新传输数据。请注意,任何时候只能有一个消息处于待处理状态,这使得该系统相当慢。")的基本 PAR 方案的两个增强。首先,现在每个消息都有一个标识号;每个消息都可以单独确认,因此可以在给定时间内有多个消息在传输中。其次,设备 B 定期向设备 A 发送一个发送限制参数,该参数限制设备 A 一次可以有多少个待处理消息。设备 B 可以调整此参数以控制从设备 A 流向的数据流。

这种延迟是为什么 TCP 不会单独发送字节,而是将它们分成段的原因。一个段中的所有字节都是一起发送和接收的,并且因此一起被确认。TCP 使用了我之前描述的方法的变体,其中我之前讨论的序列号用于标识发送和确认的数据。我们不是通过使用类似消息 ID 字段的东西来确认使用,而是使用段中最后一个数据字节的序列号来确认数据。因此,我们正在处理每个情况下的字节范围,而这个范围代表了段中所有字节的序列号。

TCP 传输流分类的概念性划分

想象一下设备 A 和设备 B 之间新建立的 TCP 连接。设备 A 有一个长的字节流要传输,但设备 B 不能一次接受所有这些字节,因此它限制设备 A 一次只能发送特定数量的字节,直到已发送的段中的字节被确认。然后设备 A 被允许发送更多字节。每个设备都跟踪哪些字节已被发送和哪些尚未发送,以及哪些已被确认。

在任何时刻,我们都可以对这个过程进行“快照”。如果我们这样做,我们可以从以下四个类别概念性地划分发送 TCP 缓冲区中的字节,并将它们视为时间线(参见图 46-5):

  1. 已发送并确认的字节 流中最早的字节已经发送并被确认。这些字节基本上是从发送数据设备的视角来看待的。在图 46-5 的例子中,已有 31 个字节数据被发送并确认。这些将属于类别 1。

  2. 已发送但尚未确认的字节 这些是设备已发送但尚未收到确认的字节。发送方在收到确认之前不能认为这些字节已被处理。在图 46-5 中,这里有 14 个字节,属于类别 2。

  3. 尚未发送但接收方已准备好的字节 这些是设备尚未发送,但根据其最近与发送方的通信(关于它一次愿意处理多少字节)而留有空间的字节。发送方将尝试立即发送这些字节(受某些算法限制,你将在后面探索)。在图 46-5 中,类别 3 中有 6 个字节。

  4. 尚未发送且接收方尚未准备好的字节 这些是流中更下面的字节,发送方尚未被允许发送,因为接收方尚未准备好。在图 46-5 中,类别 4 中有 44 个字节。

TCP 传输流的概念划分

图 46-5. TCP 传输流的概念划分

注意

我在这里使用非常小的数字来简化示例,并使图表更容易构建!出于效率原因,TCP 通常不会发送大量字节

接收设备使用类似的系统来区分已接收并被确认的数据、尚未接收但准备接收的数据,以及尚未接收且尚未准备好接收的数据。实际上,两个设备都维护一组独立的变量来跟踪它们发送的流中字节所属的类别,以及它们接收的流。这将在第四十八章(ch48.html "第四十八章. TCP 消息格式和数据传输")的“TCP 滑动窗口数据传输和确认机制”部分中进一步探讨,该部分描述了详细的滑动窗口数据传输过程。

提示

关键概念 TCP 滑动窗口系统是对增强型 PAR 系统的一种变体,对系统进行了修改以支持 TCP 的流方向。每个设备都会跟踪它需要发送的字节流的状态。设备通过将字节流划分为四个概念类别来跟踪状态:已发送并被确认的字节、已发送但尚未被确认的字节、尚未发送但可以立即发送的字节,以及尚未发送且在接收方表示准备好接收之前不能发送的字节。

序列号分配和同步

发送方和接收方必须就它们将分配给流中字节的序列号达成一致。这被称为同步,并在 TCP 连接建立时完成。为了简单起见,让我们假设第一个字节是用序列号 1 发送的(这通常不是情况)。因此,在图 46-5 中显示的示例中,四个类别的字节范围如下:

  1. 发送并被确认的字节是第 1 到第 31 字节。

  2. 已发送但尚未被确认的字节是第 32 到第 45 字节。

  3. 接收方已准备好接收但尚未发送的字节是第 46 到第 51 字节。

  4. 接收方尚未准备好接收的字节是第 52 到第 95 字节。

发送窗口和可用窗口

整个过程操作的关键是接收者允许发送者在一次时间内未确认的字节数。这被称为发送窗口,或者通常简称为窗口。窗口决定了发送者允许传输的字节数,等于类别 2 和类别 3 中字节数的总和。因此,最后两个类别(接收者已准备好接收的字节和接收者尚未准备好的字节)之间的分界线是由将窗口加到流中第一个未确认字节的字节数来确定的。在图 46-5 所示的示例中,第一个未确认的字节是 32。总窗口大小为 20。

术语可用窗口定义为在给定未确认数据量的情况下,发送器仍允许发送的数据量。因此,它正好等于类别 3 的大小。你也许还会经常听到窗口的边缘被提及。左侧边缘标记窗口中的第一个字节(字节 32)。右侧边缘标记窗口中的最后一个字节(字节 51)。参见图 46-6 以了解这些概念。

小贴士

关键概念 发送窗口是整个 TCP 滑动窗口系统的关键。它表示设备一次允许未确认的字节数的最大值。可用窗口是发送窗口中发送者仍允许在任何时间点发送的数据量;它等于发送窗口的大小减去已传输的未确认字节数。

TCP 传输流类别和发送窗口术语 此图显示了与图中的相同类别,但同时也显示了发送窗口。黑色框表示整体发送窗口(类别 2 和 3 的组合);浅灰色框表示已发送的字节(类别 2),深灰色框表示可用窗口(类别 3)

图 46-6. TCP 传输流类别和发送窗口术语 此图显示了与 图 46-5 中相同的类别,但同时也显示了发送窗口。黑色方框代表整体发送窗口(类别 2 和 3 合并);浅灰色方框表示已发送的字节(类别 2),深灰色方框是可用窗口(类别 3)。

发送可用窗口字节后的 TCP 类别和窗口大小更改

现在假设在 图 46-6 所示的示例中,没有任何阻止发送者立即传输类别 3(可用窗口)中的 6 个字节。当发送者传输这些字节时,这 6 个字节将从类别 3 移动到类别 2。字节范围现在如下(参见 图 46-7

图 46-7. 发送可用窗口字节数后的 TCP 流类别和窗口 此图显示了设备发送其可用窗口内允许传输的所有字节的后果。它与图 46-6 相同,除了类别 3 中的所有字节都移动到了类别 2 中。现在可用窗口为零,并且将保持如此,直到它收到类别 2 中字节的确认。

处理确认和滑动发送窗口

在一段时间之后,目标设备向发送方发送一条消息并提供确认。目标设备不会具体列出它已确认的字节,因为正如我之前所说的,列出字节将是不高效的。相反,目标设备将确认一个字节范围,这代表了它自上次确认的字节以来接收到的最长连续字节序列。

例如,假设示例开始时已发送但尚未确认的字节(32 到 45)被传输在四个不同的段中。这些段分别携带字节 32 到 34、35 到 36、37 到 41 和 42 到 45。第一、第二和第四个段到达了,但第三个没有到达。接收方只会对字节 32 到 36(32 到 34 和 35 到 36)发送确认。接收方将保留字节 42 到 45 但不会确认它们,因为这会意味着接收方已经接收了字节 37 到 41,而这些字节尚未出现。这是必要的,因为 TCP 是一个累积确认系统,它只能使用一个数字来确认数据。这个数字是流中成功接收到的最后一个连续字节的编号。让我们也假设目标设备保持窗口大小不变,为 20 字节。

注意

一个名为选择性确认的可选功能允许确认非连续的数据块。这将在第四十九章的“TCP 非连续确认处理和选择性确认(SACK)”部分中解释;我们现在将忽略这个复杂性

当发送设备收到此确认时,它将能够将一些类别 2 中的字节转移到类别 1,因为它们现在已被确认。当它这样做时,会发生一些有趣的事情。由于已确认 5 个字节,而窗口大小没有变化,发送方被允许发送 5 个额外的字节。实际上,窗口在时间轴上向右移动或滑动。同时,5 个字节从类别 2 移动到类别 1,5 个字节从类别 4 移动到类别 3,为后续传输创建了一个新的可用窗口。因此,在组收到确认后,它们将看起来像你在图 46-8 中看到的那样。字节范围如下:

  1. 已发送并确认的字节是 1 到 36。

  2. 尚未发送且尚未确认的字节是 37 到 51。

  3. 已准备好发送但尚未发送的字节是 52 到 56。

  4. 尚未发送且接收方尚未准备好的字节是 57 到 95。

滑动 TCP 发送窗口 在收到字节 32 到 36 的确认后,字节从类别 2 移动到类别 1(以深色阴影显示)。图 46-7 中显示的发送窗口向右滑动 5 个字节;将 5 个字节从类别 4 移动到类别 3,并打开一个新的可用窗口。

图 46-8. 滑动 TCP 发送窗口 在收到字节 32 到 36 的确认后,字节从类别 2 移动到类别 1(以深色阴影显示)。图 46-7 中显示的发送窗口向右滑动 5 个字节;将 5 个字节从类别 4 移动到类别 3,并打开一个新的可用窗口。

每次收到确认时,都会发生此过程,从而使得窗口在整个流中滑动以进行传输。因此,女士们先生们,你们有了 TCP 滑动窗口确认系统!

这是一个非常强大的技术,允许 TCP 使用单个确认号轻松地确认任意数量的字节。它为面向字节的协议提供了可靠性,而不需要在过多的确认上浪费时间。为了简单起见,我这里使用的示例保留了窗口大小不变,但在现实中,它可以调整以允许接收者控制数据发送的速度,从而实现流量控制和拥塞处理。

小贴士

关键概念 当设备收到一个字节范围的确认时,它知道目标设备已成功接收了它们。它将它们从“已发送但未确认”类别移动到“已发送且已确认”类别。这导致发送窗口向右滑动,允许设备发送更多数据。

处理丢失的确认

但在图 46-8 中给出的示例中,字节 42 到 45 又是怎么回事呢?直到包含字节 37 到 41 的段 3 出现,接收设备才不会为这些字节发送确认,也不会为之后出现的任何其他字节发送确认。发送设备将能够发送添加到类别 3 的新字节,即字节 52 到 56。然后发送设备将停止,窗口将停留在字节 37 到 41 上。

小贴士

关键概念 TCP 确认是累积的,并告知发送器接收设备已成功接收了确认中指示的序列号所表示的所有字节。因此,如果接收设备接收到顺序错误的字节,设备必须等到所有前面的字节都接收完毕后才能确认它们。

与 PAR 系统一样,TCP 包括一个用于定时传输和重传的系统。最终,TCP 设备将重新发送丢失的段。不幸的是,TCP 的一个缺点是,由于它不单独确认段,它可能需要重新传输接收者实际上已接收的其他段(例如字节 42 到 45 的段)。正如我在第四十九章中讨论 TCP 重传主题时所说的,这开始变得非常复杂。

关于 TCP 滑动窗口的更多信息

尽管这个解释的篇幅较长,但前面的内容只是滑动窗口整体操作的简要描述。本章并未包括现代 TCP 中使用的所有修改!正如你所见,滑动窗口机制是 TCP 整体操作的核心。在描述分段和讨论数据传输的章节中,你将更详细地了解 TCP 发送者如何决定何时以及如何创建用于传输的分段。第四十九章提供了更多关于滑动窗口如何使设备在 TCP 连接上管理数据流的信息。它还讨论了如果窗口大小没有仔细管理可能会出现的特殊问题,以及如何通过对本节中描述的基本滑动窗口机制进行关键更改来避免 TCP 实现中的拥塞等问题。

TCP 端口、连接和连接识别

两个 TCP/IP 传输层协议,TCP 和 UDP,在协议套件中扮演相同的架构角色,但实现方式却大相径庭。实际上,这两个协议共同拥有的少数功能之一是它们都提供了一种传输层寻址和复用方法。通过使用端口,这两个协议都允许来自许多不同应用进程的数据被聚合并通过 IP 层发送,然后返回到目标设备上的正确应用进程。我在第四十三章中详细解释了 TCP 端口。

尽管存在这种共性,TCP 和 UDP 在处理进程方面还是有所区别。UDP 是一种无连接协议,这意味着在发送数据之前,设备不需要建立正式的连接。UDP 不需要使用滑动窗口或跟踪 UDP 发送传输的时间长短等。当设备上的 UDP 层接收到数据时,它只需将其发送到目标端口指示的进程,然后任务完成。UDP 可以无缝地处理发送给它消息的任何数量的进程,因为 UDP 以相同的方式处理它们。

相比之下,由于 TCP 是面向连接的,它承担着更多的责任。每个 TCP 软件层都需要能够同时支持与其他多个 TCP 的连接。每个连接的操作都是独立的,TCP 软件必须独立管理每个操作。TCP 必须确保它不仅将数据路由到正确的进程,而且还要在每个连接上管理传输的数据,确保没有重叠或混淆。

这种情况的第一后果是 TCP 必须唯一标识每个连接。它是通过使用对应于连接两端端点的套接字标识符对来实现的,其中套接字简单地是每个进程的 IP 地址和端口号的组合。这意味着套接字对包含四条信息:源地址、源端口、目的地址和目的端口。因此,TCP 连接有时被称为由这个地址四元组来描述。

我在第四十三章中介绍了这个概念,其中我给出了一个客户端向位于 177.41.72.6 的网站发送的 HTTP 请求的例子,该网站位于 41.199.222.3。该网站的服务器将使用众所周知的端口号 80,因此服务器的套接字是 41.199.222.3:80。如果服务器为网络浏览器分配一个临时端口号 3022,则客户端套接字是 177.41.72.6:3022。这些设备之间的整体连接可以使用这个套接字对来描述:(41.199.222.3:80, 177.41.72.6:3022)。

使用客户端和服务器套接字来标识连接,这为我们提供了在互联网上可能视为理所当然的设备之间进行多个连接的灵活性。例如,繁忙的应用程序服务器进程(如 Web 服务器)必须能够处理来自多个客户端的连接;否则,网络几乎无法使用。由于客户端和服务器套接字标识连接,因此这不成问题。在 Web 服务器维护连接的同时,它可以轻松地与另一个连接,比如 IP 地址 219.31.0.44 的端口号 2199,建立连接。表示这个连接的标识符如下:(41.199.222.3:80, 219.31.0.44:2199)。

实际上,你可以从同一个客户端到同一个服务器建立多个连接。每个客户端进程将被分配一个不同的临时端口号,所以即使它们都试图访问同一个服务器进程(如位于 41.199.222.3:80 的 Web 服务器进程),它们也将拥有不同的客户端套接字,并代表唯一的连接。这种差异使得你能够从你的计算机向同一个网站发出多个并发请求。

再次强调,TCP 独立跟踪每个这些连接,所以每个连接都不了解其他连接。TCP 可以处理数百甚至数千个并发连接。唯一的限制是运行 TCP 的计算机的容量以及连接到它的物理连接的带宽——同时运行的连接越多,每个连接就必须共享的资源就越有限。

小贴士

关键概念 每个设备可以处理到一台或多台设备上多个不同进程的 TCP 连接。连接中设备的套接字编号,称为连接的端点,标识每个连接。每个端点由设备的 IP 地址和端口号组成,因此客户端 IP 地址和端口号与服务器 IP 地址和端口号之间的四次通信标识了每个连接。

TCP 常见应用和服务器端口分配

在第四十五章中 TCP 的概述中,你看到该协议最初包括了现代 TCP 和 IP 的功能。TCP 被分割成 TCP 和 IP,以便不需要 TCP 复杂性的应用程序可以绕过它,使用更简单的 UDP 作为传输层协议。这个绕过是 TCP/IP 协议套件发展中的一个重要步骤,因为有几个重要的协议 UDP 非常适合,甚至有些对于 TCP 来说更多的是麻烦而不是好处。

然而,UDP 通常仅在特殊情况下使用。我在第四十四章")中描述了两种可能比 TCP 更适合 UDP 的应用类型:那些速度比可靠性更重要,以及那些不经常发送短消息的应用。大多数 TCP/IP 应用都不属于这些类别。因此,尽管 TCP 和 IP 的分层意味着大多数协议不需要使用 TCP,但它们大多数仍然这样做。使用 TCP 的大多数协议都使用其提供的所有或至少大多数功能。对于许多交互式协议,如 Telnet,以及发送命令和状态回复的协议,如 HTTP,建立持久连接是必要的。对于像文件传输协议(FTP)或电子邮件协议这样的协议,它们发送大文件,可靠性和流量控制是必不可少的。

表 46-1 显示了在 TCP 上运行的一些更重要的应用协议。对于每个协议,我都显示了为该协议的服务器进程保留的已知或注册的端口号(客户端使用临时端口,而不是表中的端口号)。我还为每个端口分配显示了特殊的关键字快捷方式,并提供了关于为什么该协议非常适合 TCP 的简要说明。

表 46-1。常见的 TCP 应用和服务器端口分配

端口号 关键字 协议 备注
20 和 21 ftp-data/ftp 文件传输协议(FTP,数据和控制) 用于发送大文件,因此非常适合 TCP。
23 telnet Telnet 协议 基于交互式会话的协议。需要 TCP 的连接特性。
25 smtp 简单邮件传输协议(SMTP) 使用命令交换,并在设备之间发送可能很大的文件。
53 domain 域名服务器(DNS) 使用 UDP 和 TCP 的协议的示例。对于简单的请求和回复,DNS 使用 UDP。对于较大的消息,特别是区域传输,DNS 使用 TCP。
70 gopher Gopher 协议 一种已被万维网 largely 取代的消息协议。
80 http 超文本传输协议(HTTP/万维网) TCP 基于消息协议的经典示例。
110 pop3 邮局协议(POP 版本 3) 使用 TCP 交换命令和数据来检索电子邮件消息的协议。
119 nntp 网络新闻传输协议(NNTP) 用于传输 NetNews(Usenet)消息,这些消息可能很长。
139 netbios-ssn NetBIOS 会话服务 一种会话协议,显然比 UDP 更适合 TCP。
143 imap 互联网消息访问协议(IMAP) 另一种电子邮件消息检索协议。
179 bgp 边界网关协议(BGP) 虽然内部路由协议如 RIP 和 OSPF 使用 UDP 或 IP 直接,但 BGP 在 TCP 上运行。这允许 BGP 在发送数据时即使是在可能的长距离上也能假设可靠的通信。
194 irc 互联网中继聊天(IRC) IRC 与 Telnet 类似,它是一种基于客户端和服务器之间持久连接的交互式协议。
2049 nfs 网络文件系统(NFS) 由于性能原因,NFS 最初使用 UDP 实现。鉴于它负责大量文件传输,以及 UDP 的不可靠性,NFS 可能不是最佳选择,因此开发人员创建了 TCP 版本。NFS 的最新版本仅使用 TCP。
6000–6063 TCP x11 用于 X Window 图形系统。多个端口被分配以允许多个会话。

表 46-1 中的某些协议同时使用 TCP 和 UDP,以便兼得两者之长。UDP 可以发送简短、简单的消息,而 TCP 可以传输较大的文件。实际上,许多同时使用 TCP 和 UDP 的协议实际上是实用程序/诊断协议(如回声、丢弃和时间协议)。这些是特殊情况,因为开发人员特别设计了它们以使用 UDP 和 TCP,以便在两种协议上都可以用于诊断。|

我没有在 表 46-1 中包含 TCP 应用程序的详尽列表。请参阅 第四十二章 了解常见的 TCP/IP 应用程序和端口号,以及已知和注册的 TCP 服务器端口的完整(庞大的)列表。

第四十七章。TCP 基本操作:连接建立、管理和终止

无标题图片

虽然我已经将传输控制协议 (TCP) 描述为面向连接的,但这个术语不仅仅是 TCP 的某个老特性。整个协议的整体操作可以用 TCP 软件如何准备、协商、建立、管理和终止连接来描述。TCP 实现确实不仅仅是处理连接,但它们执行的另一个主要任务,如数据处理和提供可靠性和流量控制,只能在稳定的连接上发生。这种稳定性使得连接成为探索 TCP 工作细节的逻辑起点。

在本章中,我将从始至终描述 TCP 连接。我首先通过提供正式定义连接阶段的有限状态机的摘要来概述 TCP 的操作。当你在标准中阅读它们时,状态机可能会让你感到有些令人困惑,但一个简化的、解释过的版本提供了对连接生命周期的优秀高级视图,因此这是一个很好的起点。

从那里,我将继续提供有关 TCP 处理连接的详细信息。我描述了如何准备和设置连接以及传输控制块 (TCBs),并解释了被动套接字打开和主动套接字打开之间的区别。我解释了你可以用来创建连接的三次握手,以及参数交换和序列号同步的方法。我讨论了如何管理已建立的连接,包括 TCP 处理问题条件和在必要时重置连接的方法。最后,我描述了当不再需要连接时如何终止连接。

小贴士

背景信息 以下详细章节假设你已经熟悉上一章中的概念,特别是序列数的概念

TCP 操作概述和 TCP 有限状态机 (FSM)

所有实现网络协议的设备都必须以一致的方式进行。否则,一个设备可能会以其他设备无法预期的行为运行。自然,这种不一致性正是存在描述每个协议操作标准的原因。像 TCP 这样的协议问题在于它执行了如此多的任务,以至于很难简洁地指定协议所有方面的确切操作。

计算机科学家描述复杂协议工作方式的一种方法是使用一种称为有限状态机 (FSM) 的理论工具。有限状态机试图通过将其视为一个虚拟机来描述协议或算法,该虚拟机根据各种事件响应,依次通过一系列操作阶段。

基本有限状态机概念

为了理解有限状态机的工作原理,你需要了解以下四个基本概念:

状态 描述机器在特定时间点上协议软件的特定情况或状态。

转换 从一个状态移动到另一个状态的行为。

事件 导致状态之间发生转换的事情。

动作 在设备转换到另一个状态之前对事件做出的响应。

有限状态机通过解释协议可以处于的所有不同状态、每个状态中可能发生的事件、对事件采取的动作以及由此产生的转换来描述协议。协议通常在首次运行时从特定的 初始状态 开始。然后它遵循一系列步骤进入常规操作状态,并响应特定类型的输入或其他情况移动到其他状态。状态机被称为 有限 的,因为状态的数量是有限的。

简化的 TCP FSM

在 TCP 的情况下,有限状态机(FSM)描述了连接的生命周期。每个 TCP 设备之间的连接都是从无连接的空状态开始的,然后通过一系列状态直到建立连接。连接保持在该状态,直到发生某些事情导致连接再次关闭,此时它将通过另一系列转换状态并返回到关闭状态。

提示

关键概念 许多计算机科学家使用 有限状态机(FSM) 来描述协议或算法的操作。有限状态机通过定义有限数量的操作 状态、可以导致状态之间 转换事件 以及对事件采取的 动作 来描述软件随时间采取的不同动作。

TCP 连接中状态、事件和转换的完整描述既冗长又复杂。这并不奇怪,因为这三个元素将涵盖整个 TCP 标准的大部分内容。这样的细节可能会很好地治疗失眠,但不会带来太多其他好处。然而,对 TCP FSM 的简化观察将有助于您对 TCP 建立连接以及连接创建后的功能有一个良好的整体感觉。

表 47-1 状态、事件和转换") 简要解释了 TCP 连接中的每个 TCP 状态、每个状态中发生的主要事件以及由此产生的动作和转换。为了简洁起见,使用了三个缩写来表示控制状态之间转换的三种类型的信息,这些缩写对应于设置为指示消息执行该功能的 TCP 报头标志。具体如下:

SYN 一个 同步 消息;用于发起和建立连接。之所以这样命名,是因为它的一个功能是在设备之间同步序列号。

FIN 一个结束消息,这是一个设置了 FIN 位的 TCP 段;它表示设备想要终止连接。

ACK 一个确认消息;表示已收到像 SYN 或 FIN 这样的消息。

再次强调,我没有展示所有可能的转换,只是展示了在连接生命周期中通常遵循的转换。错误条件也会引起转换,但包括这些转换会使我们远远超出简化的状态机。FSM(包括状态转换如何发生)在图 47-1 中进行了说明。

重要的是要记住,这个状态机适用于每个连接。这意味着,在任何给定时间,TCP 可能在一个连接到套接字X时处于一个状态,而在另一个连接到套接字Y时处于另一个状态。此外,特定连接中两个进程之间在状态之间的典型移动不是对称的,因为设备的作用不是对称的。例如,一个设备发起连接,另一个设备响应;一个设备开始终止,另一个设备回复。如果两个设备同时发起连接和终止(这不太常见,但可能发生),也会采取替代路径。这通过图 47-1 中的阴影部分来表示。

表 47-1. TCP 有限状态机(FSM)状态、事件和转换

状态 状态描述 事件和转换
CLOSED 每个连接在建立过程开始之前都处于的默认状态。在标准中,该状态被称为“虚构的”,因为此状态表示设备之间没有连接的情况。它要么尚未创建,要么刚刚被销毁(如果这样有意义)。 被动打开:服务器通过在 TCP 端口上进行被动打开开始连接设置过程。同时,它设置它需要以管理连接所需的数据结构(传输控制块,或 TCB)。然后它过渡到 LISTEN 状态。
激活打开,发送 SYN:客户端通过发送一个 SYN 消息开始连接设置,并为该连接设置一个 TCB。然后它过渡到 SYN-SENT 状态。
LISTEN 设备(通常是服务器)正在等待从客户端接收一个 SYN 消息。它尚未发送自己的 SYN 消息。 接收客户端 SYN,发送 SYN+ACK:服务器设备收到来自客户端的 SYN。它发送一个包含自己的 SYN 并确认它收到的消息。服务器移动到 SYN-RECEIVED 状态。
SYN-SENT 设备(通常是客户端)已发送一个 SYN 消息并正在等待来自另一设备的匹配 SYN(通常来自服务器)。 接收 SYN,发送 ACK:如果发送了 SYN 消息的设备收到了来自另一设备的 SYN 但没有对其自己的 SYN 的 ACK,它将确认收到的 SYN,然后过渡到 SYN-RECEIVED 状态以等待对其自己的 SYN 的确认。
接收 SYN+ACK,发送 ACK:如果发送了 SYN 的设备收到了对其 SYN 的确认和来自另一设备的 SYN,它将确认收到的 SYN,然后直接移动到 ESTABLISHED 状态。
SYN-RECEIVED 设备已从其伙伴那里收到一个 SYN(连接请求)并发送了自己的 SYN。现在它正在等待对它的 SYN 的 ACK 以完成连接设置。 接收 ACK:当设备收到它发送的 SYN 的 ACK 时,它过渡到 ESTABLISHED 状态。
ESTABLISHED 开放 TCP 连接的稳定状态。一旦连接中的两个设备都进入此状态,它们就可以自由交换数据。这将继续,直到它们关闭连接。 关闭,发送 FIN:设备可以通过发送带有 FIN 位设置的消息来关闭连接,然后它可以过渡到 FIN-WAIT-1 状态。
接收 FIN:设备可能从其连接伙伴那里收到一个请求关闭连接的 FIN 消息。它将确认此消息并过渡到 CLOSE-WAIT 状态。
CLOSE-WAIT 设备已从另一设备收到一个关闭请求(FIN)。它现在必须等待本地设备上的应用程序确认此请求并生成一个匹配的请求。 关闭,发送 FIN:使用 TCP 的应用程序在被告知另一进程想要关闭后,向其运行的机器上的 TCP 层发送一个关闭请求。然后 TCP 向已请求终止连接的远程设备发送一个 FIN。此设备现在过渡到 LAST-ACK。
LAST-ACK 已经收到关闭请求并确认的设备已发送自己的 FIN 并正在等待对此请求的 ACK。 接收 FIN 的 ACK:设备收到了其关闭请求的确认。我们现在已发送我们的 FIN 并得到了确认,收到了另一设备的 FIN 并对其进行了确认,所以我们直接过渡到 CLOSED 状态。
FIN-WAIT-1 处于此状态的设备正在等待对它发送的 FIN 的 ACK,或者正在等待来自另一设备的连接终止请求。 接收 FIN 的 ACK:设备收到了其关闭请求的确认。它过渡到 FIN-WAIT-2 状态。
接收 FIN,发送 ACK:设备没有收到自己 FIN 的 ACK,但收到了来自另一设备的 FIN。它确认了它,然后移动到 CLOSING 状态。
FIN-WAIT-2 处于此状态的设备已收到其终止连接请求的 ACK,并现在正在等待来自另一设备的匹配 FIN。 接收 FIN,发送 ACK:设备收到来自另一设备的 FIN。它确认了它,然后移动到 TIME-WAIT 状态。
CLOSING 设备已从另一设备收到一个 FIN 并对其发送了 ACK,但尚未收到对自己 FIN 消息的 ACK。 接收 FIN 的 ACK:设备收到了其关闭请求的确认。它过渡到 TIME-WAIT 状态。
TIME-WAIT 设备已从另一设备收到一个 FIN 并确认了它,并发送了自己的 FIN 并收到了对其的 ACK。我们已经完成,除了等待确保收到 ACK 以及防止与新的连接发生潜在的重叠。(有关此状态的更多详细信息,请参阅本章后面的“TCP 连接终止”部分。) 计时器超时:在指定等待期后,设备过渡到 CLOSED 状态。

因此,例如,在连接建立的开始,两个设备将采取不同的路径到达 ESTABLISHED 状态。一个设备(通常是服务器)将通过 LISTEN 状态,而另一个(客户端)将通过 SYN-SENT 状态。同样,一个设备将发起连接终止,并通过 FIN-WAIT-1 状态路径返回 CLOSED 状态;另一个将经过 CLOSE-WAIT 和 LAST-ACK 状态。然而,如果两者同时尝试打开,它们将分别通过 SYN-SENT 和 SYN-RECEIVED 状态,如果两者同时尝试关闭,它们将大致同时通过 FIN-WAIT-1、CLOSING 和 TIME-WAIT 状态。

虽然 FSM 一开始可能有些令人畏惧,但如果你花几分钟时间了解它,你就可以很好地掌握 TCP 的工作原理。FSM 将在理解本章后面讨论的连接建立和终止过程中非常有用,阅读这些部分将帮助你理解 FSM。

小贴士

关键概念 TCP 有限状态机(FSM)描述了在 TCP 会话中,两个设备在建立、管理和关闭连接时采取的步骤序列。每个设备可能通过不同的状态路径,因为在正常情况下,协议的操作不是对称的——一个设备发起连接建立或终止,另一个设备响应。

TCP 有限状态机(FSM)此图说明了简化的 TCP FSM。阴影部分不是 FSM 定义的官方部分;我添加它们是为了更清楚地显示两个设备打开和关闭连接的序列。对于建立和终止,有一个常规序列,其中发起和响应设备通过不同的状态,以及一个同时序列,其中每个设备使用相同的序列。

图 47-1. TCP 有限状态机(FSM)此图说明了简化的 TCP FSM。阴影部分不是 FSM 定义的官方部分;我添加它们是为了更清楚地显示两个设备打开和关闭连接的序列。对于建立和终止,有一个常规序列,其中发起和响应设备通过不同的状态,以及一个同时序列,其中每个设备使用相同的序列。

TCP 连接准备

在第四十三章中,我提出了一个关于 TCP 操作的重要观点,特别是它必须能够同时处理多个连接。因此,我们必须使用每个连接上两个设备的套接字标识符(IP 地址和端口号)的四元组来唯一标识每个连接。为每个连接设置、管理和终止连接的过程是独立进行的。

存储连接数据:传输控制块 (TCB)

由于每个连接都是独特的,我们必须分别维护每个连接的数据。TCP 使用一个特殊的数据结构来此目的,称为 传输控制块 (TCB)。TCB 包含有关连接的所有重要信息,例如标识它的两个套接字编号以及指向包含传入和传出数据的缓冲区的指针。TCB 还实现了滑动窗口机制。它包含跟踪接收和确认的字节数、接收但尚未确认的字节数、当前窗口大小等变量的变量。每个设备都维护自己的连接 TCB。

在设置 TCP 连接的过程开始之前,每个端点的设备必须执行一些“准备工作”。为了准备连接,所需的任务之一是设置将用于存储有关连接信息的 TCB。这是在连接建立过程的开始时进行的,当时每个设备从关闭状态过渡出来。

主动和被动打开

TCP/IP 基于客户端/服务器模型进行操作,TCP 连接设置也是基于这些角色的存在。客户端和服务器各自通过执行一个 打开 操作来准备连接。然而,存在两种不同的打开操作:

主动打开 使用 TCP 的客户端进程扮演主动角色,通过发送一个 TCP 消息来启动连接(一个 SYN 消息)来初始化连接。

被动打开 设计用于使用 TCP 的服务器进程采取了一种更“放松”的方法。它通过联系 TCP 并说,“我在这里,我在等待可能想和我交谈的客户端通过以下端口号发送给我消息”来执行一个 被动打开。这个打开被称为 被动,因为除了表明进程正在监听外,服务器进程不做任何事情。被动打开可以指定服务器正在等待来自特定客户端的主动打开,尽管并非所有 TCP/IP API 都支持这种功能。更常见的是,服务器进程愿意接受所有来者的连接。这种被动打开被称为 未指定

提示

关键概念 客户端进程通过执行一个主动的 打开 操作,向服务器发送一个 SYN 消息来初始化一个 TCP 连接。使用 TCP 的服务器进程通过执行一个 被动打开 操作来准备接收进入的连接请求。对于每个 TCP 会话,两个设备都会创建一个数据结构,称为 传输控制块 (TCB),用于存储与连接相关的重要数据。

连接准备

客户端和服务器在执行打开操作时都会为连接创建 TCB。客户端已经知道它试图连接的客户端进程和服务器进程的 IP 地址和端口号,因此可以使用这些信息来唯一标识连接及其相关的 TCB。

对于服务器来说,在这个游戏阶段,TCB 的概念要复杂一些。如果服务器正在等待特定的客户端,它可以使用自己的套接字和它正在等待的客户端的套接字来识别连接。然而,通常情况下,服务器不知道哪个客户端正在尝试连接它。实际上,可能有多个客户端几乎同时联系它。

在这种情况下,服务器创建了一个具有未指定(零)客户端套接字号的 TCB,并等待接收一个活跃的 Open。然后,它将客户端的套接字号绑定到 TCB,作为连接过程的一部分进行被动打开。为了允许服务器处理多个传入连接,服务器进程可能同时执行多个未指定的被动打开。

连接的 TCB 在整个连接过程中保持,并在连接完全终止时销毁,设备返回到 CLOSED 状态。TCP 确实包括处理两个设备同时执行主动打开的情况的进程,正如我在下一节讨论的那样。

TCP 连接建立过程:三次握手

在 TCP 可以用于任何实际有用的目的——即发送数据之前——必须在希望通信的两个设备之间建立连接。这个过程通常称为连接建立,涉及交换消息,将两个设备从它们的初始连接状态(CLOSED)转换到正常操作状态(ESTABLISHED)。

连接建立功能

连接建立过程实际上在创建一个适合数据交换的连接时完成了以下任务:

联系和通信 客户端和服务器通过相互发送消息来建立联系并建立通信。在此点之前,服务器通常甚至不知道它将和哪个客户端交谈,因此它会在连接建立过程中发现这一点。

序列号同步 每个设备让对方知道它希望用于第一次传输的初始序列号。

参数交换 两个设备交换控制 TCP 连接操作的某些参数。

我将在本章后面的“TCP 连接建立序列号同步和参数交换”部分讨论序列号同步和参数交换任务。

用于连接建立的控制消息:SYN 和 ACK

TCP 使用控制消息来管理联系和通信的过程。然而,并没有任何特殊的 TCP 控制消息类型;所有 TCP 消息都使用相同的段格式。TCP 头部的一组控制标志指示一个段是否用于控制目的还是仅用于携带数据。正如我在本章前面关于 TCP FSM 的讨论中提到的,在连接设置中使用了两种控制消息类型,这些类型通过设置以下两个标志来指定:

SYN 表示该段用于初始化连接。SYN 代表同步,指的是连接建立过程中的序列号同步任务。

ACK 表示发送段落的设备正在传达对已接收消息(如 SYN)的确认。

还有其他控制位(FINRSTPSHURG),它们对于连接建立并不重要,因此我将在其他主题中讨论它们。在常见的 TCP 术语中,设置控制位的消息通常以该位命名。例如,如果设置了 SYN 控制位,该段通常被称为 SYN 消息。同样,设置了 ACK 位的段是 ACK 消息,甚至只是 ACK。

正常连接建立:三次握手

要建立连接,每个设备都必须发送一个 SYN 消息并从另一个设备接收对该消息的 ACK 消息。因此,从概念上讲,我们需要在设备之间传递四个控制消息。然而,当可以同时通信时,将 SYN 和 ACK 分别发送在单独的消息中是不高效的。因此,在连接建立过程中的正常事件顺序中,其中一个 SYN 和一个 ACK 通过设置相关位(有时称为SYN+ACK的消息)一起发送。这使得总共只有三条消息,因此连接过程被称为三次握手

小贴士

关键概念 TCP 客户端和服务器之间建立连接的正常过程涉及以下三个步骤:客户端发送一个SYN消息。服务器发送一个消息,该消息包含对客户端SYNACK以及服务器的 SYN。然后客户端对服务器的 SYN 发送 ACK。这被称为TCP 三次握手

表 47-2 详细描述了三次握手是如何工作的(包括对上一节中讨论的准备的总结)。它改编自描述 TCP 有限状态机(FSM)的表格(表 47-1 状态、事件和转换")),但显示了服务器和客户端随时间发生的情况。每一行显示了设备开始时的状态,在该状态下采取的动作,以及转换到的状态。握手过程的三个步骤中的发送和接收部分也显示了出来。同样的过程也在 47-2 中进行了说明。

表 47-2. TCP 三次握手连接建立过程

客户端 服务器
开始状态 动作
--- ---
CLOSED The client cannot do anything until the server has performed a passive Open and is ready to accept a connection.
CLOSED Step 1 Transmit: The client performs an active Open, creating a TCB) for the connection and sending a SYN message to the server.
SYN-SENT The client waits to receive an ACK to the SYN that it has sent, as well as the server's SYN.
SYN-SENT Step 2 Receive, Step 3 Transmit: The client receives from the server the SYN+ACK containing the ACK to the client's SYN, and the SYN from the server. It sends the server an ACK for the server's SYN. The client is now finished with the connection establishment.
ESTABLISHED The client is waiting for the server to finish connection establishment so they can operate normally.
ESTABLISHED The client is ready for normal data transfer operations.

TCP 三次握手连接建立过程 此图展示了客户端和服务器如何建立传统连接。它显示了在过程中发送的三个消息以及每个设备如何从关闭状态通过中间状态过渡到已建立的会话状态。

图 47-2. TCP 三次握手连接建立过程 此图展示了客户端和服务器如何建立传统连接。它显示了在过程中发送的三个消息以及每个设备如何从关闭状态通过中间状态过渡到已建立的会话状态。

同步打开连接建立

TCP 也被设置为处理两种设备都执行主动打开而不是一个执行被动打开的情况。这种情况可能发生在两个客户端试图互相连接而不是客户端和服务器之间。然而,这种情况并不常见,并且仅在特定情况下发生。同时建立连接也仅当其中一个设备使用一个知名端口作为其源端口时才会发生。

在同时打开连接建立的情况下,对于两个设备,步骤是不同的。每个客户端将执行主动打开,然后通过 SYN-SENT 和 SYN-RECEIVED 状态,直到客户端相互确认对方的 SYN。这意味着没有三次握手;相反,有类似两个同时双向握手的操作。每个客户端发送一个 SYN,接收对方的 SYN,通过发送一个 ACK 来确认对方的 SYN,然后等待自身的 ACK。

我以简化的方式描述了同时建立打开连接的交易,并在表 47-3 中进行了说明,并在图 47-3 中进行了说明。为了限制表格大小,我显示了两个设备同时进行的操作(在同一行)。实际上,这些动作不需要在完全相同的时间发生,可能也不会。为了遵循同时过程,必须发生的事情是每个设备在收到对自身 SYN 的 ACK 之前都收到一个 SYN,如图 47-3 所示。

表 47-3. TCP 同时打开连接建立过程

客户端 A 客户端 B
开始状态 动作
--- ---
关闭 客户端 A 第一步发送:客户端 A 执行主动打开,创建一个 TCB 并向服务器发送一个 SYN。
SYN-SENT 客户端 B 第一步接收并第二步发送:客户端 A 接收到客户端 B 的 SYN 并向其发送一个 ACK。它仍在等待对自身 SYN 的 ACK。
SYN-RECEIVED 客户端 A 第二步接收:客户端 A 收到客户端 B 对其 SYN 的 ACK,完成连接建立。

TCP 同时打开连接建立过程 此图显示了当两个设备同时尝试相互打开连接时会发生什么。在这种情况下,而不是三次握手,每个设备都发送一个 SYN 并接收一个 ACK。它们遵循相同的序列状态,这与正常的三次握手的两个序列都不同。

图 47-3. TCP 同时打开连接建立过程 此图显示了当两个设备同时尝试相互打开连接时会发生什么。在这种情况下,而不是三次握手,每个设备都发送一个 SYN 并接收一个 ACK。它们遵循相同的序列状态,这与正常的三次握手的两个序列都不同。

提示

关键概念 如果一个设备在确认其 SYN 之前向另一个设备发送了一个 SYN,并且收到了来自另一个设备的 SYN,那么这两个设备将执行一个同时打开操作,这包括交换两个独立的 SYN 和 ACK 消息集。最终结果是与传统的三次握手相同,但达到 ESTABLISHED 状态的过程是不同的。

TCP 连接建立序列号同步和参数交换

TCP 三次握手描述了消息交换机制,允许一对 TCP 设备从关闭状态移动到就绪状态,即已建立的连接。连接建立不仅仅是设备之间传递消息以建立通信,设备上的 TCP 层还必须交换每个设备想要用于其第一次数据传输的序列号信息。层还必须交换关于将控制连接操作参数的信息。序列号交换通常称为序列号同步,它是连接建立如此重要的部分,以至于每个设备发送以启动连接的消息被称为SYN(同步)消息。

您可能还记得,从第四十六章中的 TCP 基础知识讨论中,TCP 对每个数据字节进行单独引用,并使用序列号来跟踪哪些字节已被发送和接收。由于每个字节都有一个序列号,我们可以确认每个字节,或者更有效地,使用一个单一的数字来确认接收到的字节范围。

在我在第四十六章中给出的例子中,我假设每个设备都会通过给它们之间发送的第一个数据字节分配序列号 1 来启动一个连接。一个合理的问题是,为什么我们不会总是通过发送序列号为 1 的第一个数据字节来启动每个 TCP 连接?毕竟,序列号是任意的,这是最简单的方法。在一个理想的世界里,这可能会起作用,但我们并不生活在一个理想的世界里。

以序列号 1 开始每个连接的问题在于,它引入了不同连接的段可能混淆的可能性。假设我们建立了一个 TCP 连接并发送了一个包含字节 1 到 30 的段。然而,由于互联网的问题,这个段出现了延迟,最终 TCP 连接本身被终止。然后我们启动了一个新的连接,并再次使用了起始序列号 1。然而,当这个新连接开始时,旧的包含字节 1 到 30 的段出现了。其他设备会错误地认为这些字节是连接的一部分。

这只是可能出现的几个类似问题之一。为了避免这些问题,每个 TCP 设备在建立连接时,都会为该连接选择一个 32 位的初始序列号(ISN)。每个设备都有自己的 ISN,而且这些 ISN 通常不会相同。

初始序列号选择

传统上,每个设备通过使用一个定时计数器来选择 ISN,就像某种时钟,每 4 微秒增加一次。TCP 在启动时初始化计数器,然后计数器的值每 4 微秒增加 1,直到达到可能的 32 位最大值(4,294,967,295),此时它回绕到 0 并继续增加。每次建立新的连接时,ISN 都是从计时器的当前值中取出的。由于以每增加 4 微秒计数,从 0 到 4,294,967,295 需要超过 4 小时,这几乎确保了每个连接都不会与之前的任何连接冲突。

这种方法的一个问题是它使得 ISN 可预测。恶意的人可以编写代码来分析 ISN,然后根据之前使用的 ISN 预测后续 TCP 连接的 ISN。恶意黑客过去已经利用了这种安全风险(例如著名的米特尼克攻击)。为了击败恶意黑客,现在的实现现在在 ISN 选择过程中使用随机数。

TCP 序列号同步

一旦每个设备选择其 ISN,它就会在设备的初始 SYN 消息的序列号字段中将 ISN 值发送给另一个设备。接收 SYN 的设备会以一个确认 ACK 消息响应,确认 SYN(该消息可能还包含其自己的 SYN,如三次握手的第二步)。在 ACK 消息中,确认号字段设置为从另一个设备接收到的 ISN 的值加一。这代表设备期望从其对等方接收的下一个序列号;ISN 实际上代表已接收的最后字节的序列号(在这种情况下是虚构的,因为连接是新的,还没有收到任何东西)。

提示

关键概念 作为连接建立过程的一部分,TCP 连接中的两个设备中的每一个都会告知对方它计划用于其第一次数据传输的序列号。每个设备通过在其 SYN 消息的序列号字段中放置前一个序列号来告知对方。对方通过增加该值并将其放入其 ACK 消息的确认号字段中来确认这一点,告诉对方这是它期望用于第一次数据传输的序列号。这个过程被称为序列号同步

这里是一个简化了的三次握手步骤的例子(见图 47-4). 我选择了小的 ISN 以提高可读性,但请记住,ISN 可以是任何 32 位数字。

  1. 客户端的连接请求 客户端为其传输选择了一个 ISN 为 4,567。它发送一个 SYN,其序列号字段设置为 4,567。

  2. 服务器的确认和连接请求 服务器为其传输选择了一个 ISN 为 12,998。它接收到了客户端的 SYN。它发送一个 SYN+ACK,其确认号字段值为 4,568(比客户端的 ISN 多一个)。此消息的序列号字段值为 12,998。

  3. 客户端的确认 客户端发送一个 ACK,其确认号字段设置为 12,999。

连接现在建立后,客户端将发送数据,其第一个字节的序列号将为 4,568。服务器的第一个数据字节的序列号将为 12,999。

TCP 序列号同步 此图说明了我在图 47-2 中介绍的相同的三次握手连接建立过程,但这次我展示了每个消息中的序列号和确认号字段,以便你可以看到两个设备如何使用它们来为数据交换建立初始序列号。

图 47-4. TCP 序列号同步 此图说明了我在图 47-2 中介绍的相同的三次握手连接建立过程,但这次我展示了每个消息中的序列号和确认号字段,以便你可以看到两个设备如何使用它们来为数据交换建立初始序列号。

TCP 参数交换

除了初始序列号之外,SYN 消息还旨在传达有关连接应如何操作的重要参数。TCP 包括一种灵活的方案来携带这些参数,以 TCP 段格式中的可变长度 选项 字段的形式,该字段可以扩展以携带多个参数。在 RFC 793 中,仅定义了一个参数在连接设置期间进行交换:最大分段大小(MSS)。我在第四十八章中讨论 TCP 数据传输时解释了此参数的重要性。

每个设备都会发送它想要用于连接的 MSS;也就是说,如果设备希望使用非默认值。当收到 SYN 时,服务器记录客户端发送的 MSS 值,并且它永远不会向客户端发送大于该值的段。客户端也会对服务器做同样的事情。客户端和服务器 MSS 值是独立的,因此它们可以建立一种连接,其中客户端可以接收比服务器更大的段,反之亦然。

后续的 RFCs 定义了在连接设置期间可能交换的附加参数。以下是一些包括的内容:

窗口缩放因子 允许一对设备指定比通常情况下由 TCP 窗口字段的 16 位大小所允许的更大的窗口大小。

允许选择确认 允许一对设备使用可选的选择确认功能,仅允许某些丢失的数据段被重传。

交替校验和法 允许设备指定一种不同于标准 TCP 校验和机制的校验和计算方法。

TCP 连接管理及问题处理

一旦 TCP 连接中的两个设备完成连接设置并进入 ESTABLISHED 状态,TCP 软件就处于其正常操作模式。TCP 软件将使用第四十八章中描述的机制将数据字节打包成段进行传输。TCP 将使用滑动窗口方案来控制段大小,并提供流量控制、拥塞处理和必要的重传。

一旦进入滑动窗口模式,两个设备可以无限期地保持在该模式。一些 TCP 连接可以非常持久——实际上,一些用户可能会连续数小时甚至数天保持某些连接,如 Telnet 会话。以下两种情况可能导致连接从 ESTABLISHED 状态移出:

连接终止 任何一个设备都可以决定终止连接。这涉及到一个特定的程序,我将在本章后面的“TCP 连接终止”部分进行介绍。

连接中断 发生某种问题并中断了连接。

TCP 重置功能

为了使其能够胜任作为一个可靠和健壮协议的职责,TCP 包括智能功能,使其能够检测和响应在建立连接期间可能发生的各种问题。其中最常见的是半开连接。这种情况发生在由于某种问题,一个设备关闭或终止连接,而另一个设备并不知道这一点。这意味着一个设备处于 ESTABLISHED 状态,而另一个可能处于 CLOSED 状态(无连接)或某种其他短暂状态。例如,如果一个设备发生软件崩溃,有人在连接中间重新启动它,或者某种类型的故障导致两个设备的状态变得不同步,就可能出现这种情况。

为了处理半开连接和其他问题情况,TCP 包括一个特殊的重置功能重置是 TCP 发送的带有RST标志设置为 1 的 TCP 段。一般来说,TCP 软件在发生意外情况时生成重置。以下是一些 TCP 软件生成重置的最常见情况:

  • 接收到来自任何设备的 TCP 段,而接收该段的设备目前没有与该设备建立连接(除了请求新连接的 SYN)

  • 接收到一个包含无效或错误的序列号或确认号字段的报文,表明该报文可能属于先前的连接或以某种方式是虚假的

  • 在没有进程监听连接的端口上接收到 SYN 消息

处理重置段

当设备收到带有 RST 位的段时,它会告诉另一个设备重置连接,以便设备可以重新建立连接。像所有段一样,重置本身必须进行检查以确保它是有效的(通过查看其序列号字段值)。这项检查防止了虚假的重置关闭连接。假设重置是有效的,消息的处理取决于接收该消息的设备状态,如下所示:

  • 如果设备处于 LISTEN 状态,它会忽略重置并保持在该状态。

  • 如果设备处于 SYN-RECEIVED 状态但之前处于 LISTEN 状态(这是服务器建立新连接的正常事件流程),它会返回到 LISTEN 状态。

  • 在任何其他情况下,重置会导致设备终止连接,并返回到该连接的 CLOSED 状态。设备将通知使用 TCP 的高层进程它已关闭连接。

小贴士

关键概念 TCP 包含一个特殊的 连接重置功能,允许设备处理问题情况,例如 半开连接 或接收到的意外消息类型。要使用此功能,检测到问题的设备会发送一个带有 RST(重置)标志设置为 1 的 TCP 段。接收设备要么在连接建立过程中返回 LISTEN 状态,要么关闭连接并返回 CLOSED 状态,等待新的会话协商。

空闲连接管理及保活消息

TCP 中最后一个连接管理问题是如何处理空闲连接;也就是说,一个活跃但长时间没有设备传输数据的 TCP 会话。TCP 标准规定在这种情况下应采取的适当行动是不采取任何行动。原因是,严格来说,在 TCP 中没有必要做任何事情来维护空闲连接。该协议完全愿意允许两个设备长时间停止传输。然后它简单地允许每个设备在它们有数据要发送时恢复数据段和确认段的传输。

然而,就像人们在电话通话中长时间听不到任何声音时会变得焦躁不安一样,一些 TCP 实现者担心空闲的 TCP 连接可能意味着连接出了问题。

因此,TCP 软件通常包括一个非官方功能,允许具有 TCP 链接的设备定期向连接上的对等设备发送一个空段,该段不包含数据。如果连接仍然有效,另一台设备会以包含确认的段进行响应;如果它无效,另一台设备将像前面描述的那样以连接重置段进行回复。这些段有时被称为 TCP 心跳消息,或简称为心跳。它们类似于边界网关协议(BGP)的心跳消息(在第四十章中描述)。

使用这些消息的使用相当有争议,因此并不普遍。那些反对使用它们的人认为它们并不是真正必要的,发送它们代表了互联网带宽的浪费,以及在计费链路上的可能额外成本(那些按每个数据报计费的网络)。他们的关键点是,如果连接目前没有被使用,那么它是否仍然有效并不重要;一旦连接再次被使用,如果它在同时已经中断,TCP 可以使用前面提到的重置功能来处理。

从理论上讲,发送一个心跳消息可能会不必要地中断一个良好的 TCP 会话。这可能会发生在客户端和服务器之间存在间歇性故障的时候。否则,在发送下一块实际数据之前,故障可能会自行纠正。此外,一些 TCP 实现可能无法正确处理这些段落的接收。

赞成使用心跳的人指出,每个 TCP 连接都会消耗一定量的资源,这可能会成为一个问题,尤其是对于繁忙的服务器。如果许多客户端连接到这样的服务器并且没有正确地终止 TCP 连接,服务器可能会长时间保持空闲连接,使用系统内存和其他它本可以用于其他地方的资源。

由于对使用此功能没有广泛接受,实现此功能的设备包括一种在必要时禁用它的方法。设备也被编程,以便它们不会仅仅因为没有收到单个心跳消息的响应就终止连接。如果它们在一段时间内发送了多次此类消息后仍未收到回复,它们可能会终止连接。

TCP 连接终止

正如俗话所说,所有美好的事物都有结束的时候,TCP 连接也不例外。在没有任何问题迫使设备终止连接的情况下,一对设备之间的连接可以保持开启状态一段时间。然而,最终,连接中的一方或双方将没有数据可以发送,并将关闭 TCP 会话,或者用户将指示设备关闭。

连接终止的要求和问题

正如 TCP 遵循一系列有序的操作来建立连接一样,它也包括一个特定的连接终止程序。与连接建立一样,每个设备都从一个状态移动到下一个状态以终止连接。这个过程比你想象的要复杂。实际上,对 TCP 状态机(FSM)的检查表明,在关闭连接中涉及的不同状态比在设置连接时更多。

连接终止之所以复杂,是因为在正常操作期间,两个设备同时发送和接收数据。通常,连接终止从一个设备向 TCP 指示它想要关闭连接开始。另一设备上的匹配过程可能根本不知道其对等方想要结束连接。需要几个步骤来确保两个设备都能优雅地关闭连接,并且在过程中不会丢失任何数据。

最终,关闭 TCP 连接需要连接两端的进程都认识到“连接的终结即将到来”,并且它们应该停止发送数据。因此,连接终止的实现是让每个设备分别终止其连接的末端。一个设备关闭连接的行为意味着该设备将不再发送数据,但可以继续接收数据,直到另一设备决定停止发送。这允许在连接结束之前,双方通信中所有待发送的数据都被刷新。

正常连接终止

在正常情况下,每一端通过发送一个设置了 FIN(完成)位的特殊消息来终止其连接的末端。FIN 消息作为连接终止请求发送给另一设备,同时可能携带像常规段一样的数据。接收 FIN 消息的设备会以一个确认响应,表明它已收到确认。直到双方都发送了 FIN 并收到了 ACK,双方才认为连接已终止,从而完成关闭过程。

因此,终止过程不是像建立连接那样的三次握手。它是一对双向握手。在正常连接关闭过程中,连接中的两个设备所经历的状态不同,因为启动关闭的设备必须与接收终止请求的设备有不同的行为。特别是,接收初始终止请求的设备上的 TCP 必须通知其应用进程,并等待一个信号,表明进程已准备好继续进行。启动设备不需要这样做,因为应用进程首先开始了这个过程。

小贴士

关键概念 TCP 连接通过一种特殊的过程终止,该过程允许每一方独立关闭其连接的端点。连接通常从应用程序进程向其 TCP 层发出信号开始,表示会话不再需要。该设备发送一个 FIN 消息告诉另一设备它想要结束连接,另一设备会进行确认。当响应设备准备好时,它也会发送一个 FIN,另一设备会进行确认;在等待一段时间以接收设备的 ACK 后,设备关闭会话。

表 47-4 详细描述了连接终止过程是如何工作的。您还可以在图 47-5 中看到状态和交换的消息的进展。表格是从表 47-1 状态、事件和转换")改编的,它描述了 TCP FSM,但显示了在连接关闭期间服务器和客户端随时间发生的情况。任何设备都可以启动连接终止;在这个例子中,我假设客户端这样做。每一行显示了每个设备开始的状态,它在该状态下采取的动作,以及它转变到的状态。我还展示了客户端和服务器关闭操作的每一步的发送和接收阶段。

表 47-4. TCP 连接终止过程

客户端 服务器
起始状态 动作
--- ---
ESTABLISHED 客户端关闭步骤 1:传输:使用 TCP 的应用程序表示连接不再需要。客户端 TCP 发送一个设置了 FIN 位的段,请求关闭连接。
FIN-WAIT-1 客户端发送了 FIN 后,正在等待设备确认,并等待服务器发送其自己的 FIN。在此状态下,客户端仍然可以接收来自服务器的数据,但将不再接受来自其本地应用程序的数据发送到服务器。
FIN-WAIT-1 客户端关闭步骤 2 接收:客户端接收其 FIN 的 ACK。它现在必须等待服务器关闭。
FIN-WAIT-2 客户端正在等待服务器的 FIN。
FIN-WAIT-2 服务器关闭步骤 1 接收和步骤 2 发送:客户端接收服务器的 FIN 并发送回 ACK。
TIME-WAIT 客户端等待一个等于最大段生存时间(MSL)双倍的时间段;这个等待确保它发送的 ACK 已被接收。
TIME-WAIT 定时器在双倍的最大段生存时间(MSL)时间后到期。
CLOSED 连接已关闭。

TCP 连接终止过程 此图展示了 TCP 会话的传统终止过程,其中一个设备发起终止,另一个设备响应。在这种情况下,客户端发起;它发送一个 FIN,服务器进行确认。服务器等待服务器进程准备好关闭,然后发送其 FIN,客户端进行确认。客户端等待一段时间以确保设备收到其 ACK,然后进入 CLOSED 状态。

图 47-5. TCP 连接终止过程 此图展示了 TCP 会话的传统终止过程,其中一个设备发起终止,另一个设备响应。在这种情况下,客户端发起;它发送一个 FIN,服务器进行确认。服务器等待服务器进程准备好关闭,然后发送其 FIN,客户端进行确认。客户端等待一段时间以确保设备收到其 ACK,然后进入 CLOSED 状态。

接收初始 FIN 的设备可能需要在 CLOSE-WAIT 状态中等待相当长的时间(从网络术语来说),以便为其所服务的应用程序指示它已准备好关闭。TCP 无法对这需要多长时间做出任何假设。在这段时间内,前一个示例中的服务器可能会继续发送数据,客户端将接收这些数据。然而,客户端不会向服务器发送数据。

最终,第二个设备(例如示例中的服务器)将发送一个 FIN 来关闭其连接的一端。最初发起关闭的设备(客户端)将为这个 FIN 发送一个 ACK。然而,客户端在发送 ACK 后不能立即进入 CLOSED 状态,因为它必须允许 ACK 到达服务器的时间。通常情况下,这会很快,但延迟可能会稍微减慢这个过程。

TIME-WAIT 状态

TIME-WAIT 状态需要两个主要原因:

  • 为了确保另一设备收到 ACK,并在它丢失时重新传输

  • 为了在这条连接的结束和任何后续连接之间提供一个缓冲期。如果没有这个时间段,不同连接的包可能会混合,从而造成混乱。

该标准规定,客户端应在关闭连接之前等待两倍于特定时间长度的时段,这个时长被称为最大分段生存时间(MSL)。TCP 标准将 MSL 定义为 120 秒(2 分钟)。在现代网络中,这几乎是一个永恒的时间,因此 TCP 允许实现选择一个更低的值,如果它认为这将导致更好的操作。

同时连接终止

正如如果两个设备决定相互主动打开连接,可以改变正常的连接建立过程一样,两个设备也可以尝试同时终止一个连接。这个术语“同时”并不意味着它们会同时决定关闭——网络延迟的差异意味着在任何互联网环境中都不可能真正同时发生。这仅仅意味着,在前面的例子中,客户端决定关闭并发送一个 FIN,但服务器在客户端的 FIN 出现在服务器之前就发送了自己的 FIN。在这种情况下,会遵循不同的程序,如表 47-5 中所述,并在图 47-6 中所示。

在某些情况下,两个设备可能会同时决定终止一个连接,或者几乎是同时。在这种情况下,每个设备都会发送一个 FIN,在收到对该 FIN 的 ACK 之前,会接收到另一个设备的 FIN。每个设备都会确认对方的 FIN,并在关闭连接之前等待一段时间。注意通过 CLOSING 状态的转换,该状态仅作为同时终止的一部分使用。

图 47-6. TCP 同时连接终止过程在某些情况下,两个设备可能会同时决定终止一个连接,或者几乎是同时。在这种情况下,每个设备都会发送一个 FIN,在收到对该 FIN 的 ACK 之前,会接收到另一个设备的 FIN。每个设备都会确认对方的 FIN,并在关闭连接之前等待一段时间。注意通过 CLOSING 状态的转换,该状态仅作为同时终止的一部分使用。

表 47-5. TCP 同时连接终止过程

客户端 服务器
起始状态 动作
--- ---
建立连接 客户端关闭步骤 1 传输:使用 TCP 的应用程序表示连接不再需要。客户端的 TCP 发送下一个段,并将 FIN 位设置为 1,表示请求关闭连接。
FIN-WAIT-1 服务器关闭步骤 1 接收和步骤 2 传输:客户端已发送一个 FIN 并正在等待其被确认。相反,它接收到了服务器发送的 FIN。它用 ACK 确认服务器的关闭请求,并继续等待自己的 ACK。
关闭中 客户端关闭步骤 2 接收:客户端接收其 FIN 的 ACK。
TIME-WAIT 客户端等待的时间是两倍的 MSL 时间。这为确保它发送给服务器的 ACK 被接收提供了足够的时间。
TIME-WAIT 定时器在两倍的 MSL 时间后到期。
关闭 连接已关闭。

如您所见,在这种情况下,过程具有更高的对称性,两个设备都通过相同的状态进行转换。在任何情况下,最终结果都是相同的,即连接处于关闭状态——意味着没有连接。每个 TCP 都会确保所有未发送的数据被发送到应用程序,有时这被称为隐含的 推送(有关此术语的解释,请参阅第四十八章中的推送功能描述)。当连接关闭时,两个设备上建立的 TCB 被销毁。

提示

关键概念 正如两个设备可以同时打开一个 TCP 会话一样,它们也可以同时终止它。在这种情况下,遵循不同的状态序列,每个设备对其接收到的对方的 FIN 响应以 ACK,然后等待接收自己的 ACK,并暂停一段时间以确保对方在结束连接之前收到了它的 ACK。

第四十八章。TCP 消息格式和数据传输

无标题图片

上一章描述了使用传输控制协议(TCP)的两个设备如何建立 TCP 连接,以及如何管理和最终终止该连接。虽然连接是 TCP 工作方式的关键部分,但它们实际上只是协议最终目标的手段:发送数据。通过使用 TCP 滑动窗口机制、特殊的段格式和几个功能,TCP 设备能够打包并发送数据,从而使得应用程序能够进行通信。

本章描述了 TCP 消息格式化的实际机制以及设备之间数据传输的过程。我首先查看重要的TCP 段格式,它描述了每个 TCP 消息中的字段以及它们的使用方式。接下来,我提供了计算 TCP(以及 UDP)消息校验和的方法的描述,并解释了为什么使用特殊的伪头部。然后,我讨论了最大段大小(MSS)参数及其重要性。随后,我详细说明了滑动窗口机制是如何用于传输和确认数据的。最后,我描述了两种特殊的数据传输特性:用于立即数据传输的推送功能,以及用于优先数据传输的紧急功能。

背景信息本章假设你已经熟悉 TCP 概念,如序列号、段和 TCP 滑动窗口机制的基本原理。如果你不熟悉,请在继续阅读本章之前先阅读第四十六章。

TCP 消息(段)格式

在第四十五章的 TCP 概述中,我描述了 TCP 执行的最有趣的任务之一:它允许应用程序以无结构的字节序列发送数据,透明地将这些数据打包成由 TCP 使用的底层协议(通常是 IP)所需的不同消息。TCP 消息被称为,这个名字指的是每个段都是设备之间整体数据流的一部分。

TCP 段非常类似于“万能的”信息——它们灵活且服务于多种目的。所有段都使用单一的字段格式,其中包含多个头部字段,以实现 TCP 所负责的众多功能和特性。TCP 段最显著的特点之一是它们被设计为可以同时携带控制信息和数据。这减少了发送的段的数量,因为一个段可以执行多个功能。

例如,在 TCP 中不需要发送单独的确认,因为每个 TCP 消息都包含一个确认字节号的字段。同样,可以在发送数据的同时请求关闭连接。每个 TCP 段的特点通过使用几个特殊控制位来指示。可以发送多个位以允许一个段执行多个功能,例如,当一位用于指定初始序列号(ISN)并确认接收了另一个这样的段时。

为了这种灵活性,我们付出的代价是 TCP 头很大:常规段为 20 字节,携带选项的段则更多。这也是为什么一些协议在不需要 TCP 功能时更倾向于使用用户数据报协议(UDP)的原因之一。TCP 头字段用于以下一般目的:

进程寻址 源设备和目标设备上的进程使用端口号进行标识。

实现滑动窗口系统 序列号、确认号和窗口大小字段实现了 TCP 滑动窗口系统(在本章后面的“TCP 滑动窗口数据传输和确认机制”部分中讨论)。

设置控制位和字段 这些是执行各种控制功能以及携带指针和其他所需数据的特殊位。

携带数据 数据字段携带设备之间发送的实际数据字节。

执行其他功能 这包括数据保护用的校验和以及用于连接设置的选项。

TCP 消息(段)的格式在表 表 48-1 到 表 48-3 中进行了详细描述,并在 图 48-1 中进行了说明。

表 48-1. TCP 段格式

字段名称 大小(字节) 描述
源端口 2 这是源设备上发起 TCP 段的进程的 16 位端口号。这通常是一个客户端的临时(客户端)端口号,用于客户端向服务器发送请求,或者是一个已知/已注册(服务器)端口号,用于服务器向客户端发送回复。
目标端口 2 这是目标设备上消息最终预期接收者的 16 位端口号。这通常是一个客户端请求的已知/已注册(服务器)端口号,或者是一个服务器回复的临时(客户端)端口号。
序列号 4 对于正常传输,这是此段中数据第一个字节的序列号。在连接请求(SYN)消息中,此字段携带源 TCP 的 ISN。数据的第一字节将赋予此字段内容之后的下一个序列号,如第四十七章中所述。
确认号 4 当 ACK 位被设置时,此段作为确认(除其他可能的职责外),并且此字段包含源端期望目的地发送的下一个序列号。有关详细信息,请参阅本章后面的“TCP 滑动窗口数据传输和确认机制”部分。
数据偏移 1/2 (4 bits) 这指定了 TCP 头部中的 32 位字节数。换句话说,此值乘以四等于头部的字节数,这必须始终是 4 的倍数。它被称为数据偏移,因为它指示数据开始相对于 TCP 段开始的 32 位字数。
保留 3/4 (6 bits) 此字段为 6 位保留,供将来使用;发送时作为零。
控制位 3/4 (6 bits) TCP 不使用单独的控制消息格式。相反,某些位被设置为指示控制信息的通信。这 6 位在表 48-2 中描述。
窗口 2 这表示发送此段的发送者愿意一次从接收者那里接受多少个八位字节的数据。这通常对应于为接受此连接分配的当前缓冲区大小。换句话说,此字段是发送此段的设备的当前接收窗口大小,也是段接收者的发送窗口。有关详细信息,请参阅本章后面的“TCP 滑动窗口数据传输和确认机制”部分。
校验和 2 这是一个用于数据完整性保护的 16 位校验和,计算整个 TCP 数据报,以及一个特殊的伪头部字段。它用于保护整个 TCP 段免受传输错误和交付错误的侵害。也支持可选的替代校验和方法。
紧急指针 2 此字段与 URG 控制位一起用于优先数据传输(见表 48-2)。此字段包含紧急数据的最后一个字节的序列号。有关详细信息,请参阅本章后面的“TCP 优先数据传输:紧急功能”部分。
选项 可变 TCP 包含一个通用机制,用于在 TCP 段中包含一个或多个可选数据集。每个选项可以是 1 个字节长或可变长。第一个字节是选项-类型子字段,其值指定了选项类型,进而指示选项是单个字节还是多个字节。多个字节的选项由三个字段组成,这些字段在表 48-3
ACK 1/8 (1 位) 确认位:当设置为 1 时,表示此段携带确认信息,确认号字段的有效值表示从该段的接收方期望的下一个序列号。
PSH 1/8 (1 位) 推送位:此段发送方正在使用 TCP 推送功能,请求将此段中的数据立即推送到接收设备上的应用程序。
RST 1/8 (1 位) 重置位:发送方遇到问题并希望重置连接。
SYN 1/8 (1 位) 同步位:此段是请求同步序列号并建立连接的请求;序列号字段(见表 48-1

TCP 段格式

图 48-1. TCP 段格式

表 48-3. TCP 段选项子字段

子字段名称 大小(字节) 描述
选项-类型 1 这指定了选项类型。
选项-长度 1 这是整个选项的长度(以字节为单位),包括选项-类型和选项-长度字段。
选项-数据 可变 此字段包含选项数据本身。在至少一个异常情况下,此字段被省略(使选项长度等于 2)。

表 48-4 显示了当前为 TCP 定义的主要选项

表 48-4. 一些 TCP 选项

选项-类型 选项-长度 选项-数据 描述
0 选项列表结束:一个单字节选项,用于标记包含在此分段中的所有选项的结束。仅在选项的结束与 TCP 头部结束不一致时需要包含。
1 无操作:一个“填充符”,可以在选项之间包含,以便在需要时将后续选项对齐到 32 位边界。
2 4 最大分段大小值 最大分段大小:传达发送方希望接收的最大分段大小。仅在连接请求(SYN)消息中使用。
3 3 窗口大小位移位 窗口缩放:实现了可选窗口缩放功能,允许设备指定比正常窗口字段可能的大得多的窗口大小。Option-Data 中的值指定了窗口字段应该乘以的 2 的幂,以获得选项发送方实际使用的真实窗口大小。例如,如果 Option-Data 的值为 3,这意味着窗口字段中的值应该乘以 8,前提是两个设备都同意使用此功能。这允许在高性能链路上在需要时宣布非常大的窗口。有关详细信息,请参阅本章后面的“TCP 滑动窗口数据传输和确认机制”部分。
4 2 允许选择性确认:指定此设备支持选择性确认(SACK)功能。这作为一个 2 字节选项实现,没有 Option-Data 字段,而不是像选项列表结束或无操作那样的单字节选项。这是必要的,因为它是在原始 TCP 规范之后定义的,因此需要一个显式的选项长度来指示向后兼容性。
5 可变 选择性确认数据块 选择性确认:允许支持可选选择性确认功能的设备指定已接收的非连续数据块,这样在中间分段未出现且需要重传时,它们不会被重传。
14 3 交替校验算法 交替校验请求:允许设备请求使用除标准 TCP 算法之外的校验生成算法来处理此连接。两个设备必须同意使用该算法。
15 可变 交替校验 交替校验:如果实现交替校验所需的校验值太大,无法放入标准的 16 位校验字段中,则将其放置在此选项中。

表格并未包含每个 TCP 选项;它只显示了在 RFC 793 中定义的基本选项以及一些有趣的其他选项,这些选项与本书其他部分描述的功能相对应。请注意,大多数选项仅在连接请求(SYN)段中发送。这包括最大段大小、窗口缩放、选择性确认允许和备用校验和请求选项。相比之下,选择性确认和备用校验和选项在它们被使用时出现在常规数据段中。

TCP 校验和计算与 TCP 伪头部

TCP 是设计用来在 IP 网络中一对设备之间提供可靠的数据传输。确保数据段可靠传输所需的大部分努力都集中在确保数据在传输过程中不会丢失的问题上。但还有另一个重要的关键障碍,即数据在穿越互联网过程中被引入 错误 的风险。

使用校验和检测传输错误

如果数据到达了它需要去的地方,但被破坏了,而我们没有检测到这种破坏,这在某些方面比它根本没出现还要糟糕。为了提供对传输错误的基本保护,TCP 在其头部包含一个 16 位的校验和字段。校验和背后的思想非常简单:将数据字节串相加,然后将这个总和与数据流一起发送,并让接收方检查这个总和。在 TCP 中,发送段的设备使用一个特殊的算法来计算这个校验和。然后,接收方使用相同的算法来检查它接收到的数据,并确保没有错误。

TCP 使用的校验和计算与常规校验和算法略有不同。常规校验和是在校验和旨在保护的所有字节上执行的,并且它可以检测到这些字段中的大多数位错误。TCP 的设计者想要这种位错误保护,但他们还想要对其他类型的问题进行保护。为此,对 TCP 校验和的计算方式进行了修改。这个特殊的 TCP 校验和算法最终也被用于 UDP;参见第四十四章")。

增加检测错误范围:TCP 伪头部

在计算 TCP 段的实际数据字段校验和之前,创建了一个 12 字节的 TCP 伪头。这个头包含了从 TCP 头和将要封装 TCP 段在内的互联网协议(IP)数据报中的字段中提取的重要信息(有关 IP 数据报格式的描述,请参阅第二十一章)。TCP 伪头的格式在表 48-5 中描述,并在图 48-2 中展示。

表 48-5。用于校验和计算的 TCP 伪头

字段名称 大小(字节) 描述
源地址 4 这是数据报发起者的 32 位 IP 地址,来自 IP 头。
目标地址 4 这是数据报预期接收者的 32 位 IP 地址,也来自 IP 头。
保留 1 这由 8 个零位组成。
协议 1 这是来自 IP 头的协议字段。这表示 IP 数据报中携带的更高层协议。当然,我们已经知道这个协议是 TCP。因此,这个字段通常具有值 6。
TCP 长度 2 这是 TCP 段的大小,包括头部和数据。请注意,这并不是 TCP 头中的一个特定字段;它是计算得出的。

用于校验和计算的 TCP 伪头

图 48-2。用于校验和计算的 TCP 伪头

一旦形成这个 96 位的头,它就被放置在缓冲区中,然后是 TCP 段本身。然后计算整个数据集(伪头加 TCP 段)的校验和。校验和的值放置在 TCP 头的校验和字段中,伪头被丢弃;它不是 TCP 段的实际部分,也不会被传输。这个过程在图 48-3 中展示。

注意

校验和字段本身也是 TCP 头的一部分,因此是计算校验和的字段之一,造成了一种“鸡生蛋,蛋生鸡”的情况。在计算校验和时,假设这个字段全部为零。

当 TCP 段到达其目的地时,接收 TCP 软件执行相同的计算。它形成伪头部,将其附加到实际的 TCP 段上,然后进行校验和(计算时将校验和字段设置为零,如之前所述)。如果其计算值与源设备放入校验和字段的值不匹配,这表明发生了某种错误,并且通常将段丢弃。

TCP 头部校验和计算 为了计算 TCP 段头部的校验和字段,首先构建 TCP 伪头部并将其逻辑上放置在 TCP 段之前。然后,对伪头部和 TCP 段进行校验和计算。伪头部随后被丢弃。

图 48-3. TCP 头部校验和计算 为了计算 TCP 段头部的校验和字段,首先构建 TCP 伪头部并将其逻辑上放置在 TCP 段之前。然后,对伪头部和 TCP 段进行校验和计算。伪头部随后被丢弃。

伪头部方法的优势

那么,为什么还要使用这个伪头部呢?源设备和目标设备都使用这个伪头部中的字段来计算校验和。这意味着,如果由于任何原因,两个设备在伪头部中使用的值不同,校验和将失败。当我们考虑头部中的内容时,我们发现这意味着校验和现在不仅保护 TCP 段字段中的错误,还保护以下问题:

分段交付错误 如果源指定的目标地址与接收段的目标地址不匹配,校验和将失败。如果源地址不匹配,也会发生相同的情况。

协议错误 如果由于某种原因,数据报被路由到 TCP,而实际上它属于不同的协议,这可以立即检测到。

分段长度错误 如果 TCP 段的一部分被意外省略,源设备和目标设备使用的长度将不匹配,校验和将失败。

伪头部聪明的地方在于,通过使用它进行校验和计算,我们可以提供这种保护,而实际上并不需要发送伪头部本身中的字段。这消除了在 TCP 头部中重复使用伪头部中使用的 IP 字段,这将是不必要的且浪费带宽。伪头部方法的缺点是它使得校验和计算需要更多的时间和精力(尽管这在今天并不是一个大问题)。

提示

关键概念 TCP 校验和不仅计算 TCP 分段,还包括包含 TCP 分段长度以及 IP 源地址、目的地址和协议字段的 TCP 伪头部。由于这些字段是校验和的一部分,如果分段被错误设备接收或协议字段或分段长度不正确,它将被拒绝。这种技术很巧妙,因为即使伪头部本身实际上并没有传输,校验和也能提供这种保护。

在当今现代、高速、高度可靠的网络的背景下,使用伪头部有时似乎有些过时。数据报被错误地址交付的可能性有多大?不太可能。然而,在 TCP 创建的时候,人们却对 IP 层上数据报的端到端交付检查可能不正确表示了极大的担忧。将 IP 信息包含在 TCP 校验和中被视为一种有用的额外保护层。

注意

TCP 伪头部有一个有趣的含义:它违反了 TCP 设计者在将 TCP 和 IP 分割开来时试图尊重的架构分层原则。对于校验和,TCP 必须知道它技术上不应该知道的网络信息。例如,TCP 校验和计算需要将 IP 头部的协议号从携带该分段的 IP 数据报中提供给接收设备的 TCP 层。TCP 伪头部是严格分层被实用性所取代的一个很好的例子。

TCP 还支持一种可选的方法,让两个设备就一个替代校验和算法达成一致。这必须在建立连接期间协商。

TCP 最大分段大小(MSS)

TCP 分段是携带 TCP 设备之间数据的消息。数据字段是实际传输数据被携带的地方,由于 TCP 中数据字段的长度是可变的,这引发了一个有趣的问题:我们应该在每个分段中放入多少数据?TCP 从使用它的应用程序接受一个恒定的数据流,这意味着它必须决定在每个发送的消息中放入多少字节。

决定在分段中发送多少数据的一个主要因素是接收方滑动窗口机制当前的状态。当设备 A 从设备 B 接收 TCP 分段时,它会检查窗口字段的值,以了解设备 B 允许设备 A 在其下一个分段中发送的数据量限制。(这个过程在本章后面的“TCP 滑动窗口数据传输和确认机制”部分中描述。)在选择和调整窗口大小方面也存在一些重要问题,这些问题会影响整个 TCP 系统的操作,这些问题将在第四十六章中讨论。

除了当前窗口大小的规定之外,每个 TCP 设备还与其关联一个 TCP 大小的上限——一个永远不会超过的段大小。这被称为最大段大小(MSS)。在决定将多少数据放入一个段时,TCP 连接中的每个设备都会根据当前窗口大小,结合第四十六章中描述的各种算法来选择数据量,但它永远不会大到超过它发送的设备 MSS。

注意

最大段大小的名称具有误导性。该值实际上指的是一个段可以容纳的最大数据量。它不包括 TCP 头部。因此,如果 MSS 是 100,实际的最高段大小可能是 120(对于常规 TCP 头部)或更大(如果段包含 TCP 选项)。

MSS 选择

MSS 的选择基于在 TCP/IP 网络上传输数据时需要平衡各种相互竞争的性能和实现问题。主要的 TCP 标准,RFC 793,对 MSS 没有太多说明,因此可能会对如何使用该参数产生混淆。RFC 879 在 TCP 标准发布后几年发布,以阐明该参数及其相关问题。

MSS 的一些问题相当平凡;例如,某些设备在缓冲区中用于存储 TCP 段的空间有限,因此可能希望将段大小限制在一个相对较小的值。然而,总的来说,MSS 必须在两个相互竞争的性能问题之间进行权衡:

开销管理 TCP 头部占用 20 字节的数据(或使用选项时更多);IP 头部也使用 20 或更多字节。这意味着它们之间,至少需要 40 字节用于头部,而这全部是非数据开销。如果我们设置 MSS 太低,这将导致带宽使用非常低效。例如,如果我们将其设置为 40 字节,每个段的最大50% 实际上是数据;其余的只是头部。许多段数据报在效率方面会更差。

IP 分片 TCP 段将被封装成 IP 数据报。正如你在第二十二章中看到的,数据报有自己的大小限制问题:底层网络的最大的传输单元(MTU)问题。如果一个 TCP 段太大,它将导致一个无法不进行分片发送的过大的 IP 数据报。分片降低了效率,并增加了 TCP 段的一部分丢失的可能性,导致整个段需要重新传输。

TCP 默认 MSS

解决开销管理和 IP 分段这两个相互竞争的问题的方案是,为 TCP 建立一个尽可能大的默认 MSS,同时避免大多数传输段发生分段。这是通过从 IP 网络的最低 MTU 576 字节开始计算的。所有网络都必须能够处理这个大小的 IP 数据报而不会分段。从这个数字中,我们减去 20 字节用于 TCP 头部和 20 字节用于 IP 头部,剩下 536 字节。这是 TCP 的标准 MSS。

提示

关键概念TCP 被设计为限制它发送的段的大小,以一定的最大限制,以减少在 IP 层传输时需要分段的可能性。TCP 最大分段大小(MSS) 指定了 TCP 段数据字段中的最大字节数,无论其他影响段大小的因素如何。TCP 的默认 MSS 是 536 字节,这是通过从最低 IP MTU 576 字节开始,并为 IP 和 TCP 头部各减去 20 字节计算得出的。

选择这个 MSS 值是一种折衷。这意味着大多数 TCP 段将无分段地跨越 IP 互联网发送。然而,如果使用了任何 TCP 或 IP 选项,最小 MTU 为 576 字节将被超过,并且会发生分段。尽管如此,允许一些段进行分段比使用一个远小于 MSS 的值以确保它们永远不会分段更有意义。如果我们选择,比如说,400 字节的 MSS,我们可能永远不会发生分段,但我们会降低所有段的数据/头部比率从 536:40(93%数据)到 400:40(91%数据)。

非默认 MSS 值指定

自然地,会有一些情况,默认 MSS 值并不理想。TCP 提供了一种机制,允许设备指定它想要使用的 MSS 值要么小于或大于 536 字节的默认值。设备可以通过在建立连接过程中交换参数来通知其他设备它想要使用的 MSS 值。选择这样做的设备会在其 SYN 消息中包含一个称为最大分段大小的 TCP 选项。其他设备接收到这个选项并记录连接的 MSS。每个设备都可以独立指定它希望接收的段所使用的 MSS。

注意

在设置过程中交换 MSS 值有时被称为 MSS 协商。这实际上是一个误导性的术语,因为它暗示两个设备必须就一个共同 MSS 值达成一致,而这并不是事实。每个设备使用的 MSS 值可能不同,并且根本不存在协商。

如果设备知道将要传输的段将通过的网络 MTU 大于 IP 的最小值 576 字节,它们可能会希望使用更大的 MSS。这种情况在大量数据在本地网络中发送时最为常见。正如第二十二章中所述的 MTU 路径发现过程,用于确定适当的大小。如果设备知道 TCP 段使用某个特定的可选功能,该功能会持续增加 IP 头的大小,例如当段使用 IPsec 进行安全时(参见第二十九章),它们可能会使用较小的 MSS。

小贴士

关键概念 设备可以通过在它们用于建立连接的 SYN 消息中包含最大段大小选项来指示它们希望使用与默认值不同的 MSS 值。连接中的每个设备都可能使用不同的 MSS 值。

TCP 滑动窗口数据传输和确认机制

TCP 连接建立过程是由一对设备使用的,用于在它们之间创建 TCP 连接。一旦所有设置完成——传输控制块(TCBs)已设置,参数已交换,等等——设备就准备好开始传输数据了。

在连接中,TCP 设备之间数据的发送是通过我们在第四十六章中探讨的滑动窗口系统完成的。在这里,我们将更详细地探讨滑动窗口是如何实现的,以便发送和接收数据。为了便于解释,我们假设我们的连接是在客户端和服务器之间——这比整个“设备 A/设备 B”的业务要简单。

滑动窗口发送和接收类别

连接上的两个设备都必须跟踪它们发送的数据以及从另一设备接收的数据。这是通过概念上将字节划分为类别来完成的。对于正在传输的数据,有四个发送类别:

发送类别 1 已发送并确认的字节

发送类别 2 已发送但尚未确认的字节

发送类别 3 已发送但尚未准备好接收的字节

发送类别 4 已发送但尚未准备好接收的字节

对于正在接收的数据,没有必要像发送方将其前两个类别分为“已发送并确认”和“已发送但尚未确认”那样,将其分为“已接收并确认”和“已接收但尚未确认”。原因是发送方必须等待每次传输的确认,但接收方不需要确认它已收到某些内容。因此,一个接收类别对应于传输类别 1 和 2,而另外两个分别对应于传输类别 3 和传输类别 4,总共三个接收类别。为了帮助更清楚地说明类别之间的关系,我按如下方式编号:

接收类别 1+2 已接收并确认的字节。这是接收方对传输类别 1 和 2 的补充。

接收类别 3 尚未接收但接收方已准备好的字节。这是接收方对传输类别 3 的补充。

接收类别 4 尚未接收但接收方尚未准备好的字节。这是接收方对传输类别 4 的补充。

发送(SND)和接收(RCV)指针

客户端和服务器都必须跟踪通过连接发送的两个流。这是通过一组称为指针的特殊变量来完成的,这些指针将字节流划分为上一节中描述的类别。

四个传输类别是通过三个发送(SND)指针来划分的。其中两个指针是绝对的(参考特定的序列号),另一个是添加到绝对指针之一上的偏移量,如下所示:

发送未确认(SND.UNA) 已发送但尚未确认的数据的第一个字节的序列号。这标志着传输类别 2 的第一个字节;所有之前的序列号都指的是传输类别 1 中的字节。

发送下一个字节(SND.NXT) 下一个要发送到另一设备(在这种情况下是服务器)的数据字节的序列号。这标志着传输类别 3 的第一个字节。

发送窗口(SND.WND) 发送窗口的大小。回想一下,窗口指定任何设备在任何时刻可能有的未确认的字节数量。因此,将第一个未确认字节的序列号(SND.UNA)和发送窗口(SND.WND)相加,标志着传输类别 4 的第一个字节。

另一种看待这些指针的方法是它们如何指示在任何时刻传输设备可以发送的字节数——即传输类别 3 中的字节数。传输类别 3 的开始由 SND.NXT 标记,结束由传输类别 4 的第一个字节标记,该字节由 SND.UNA+SND.WND 给出。因此,传输类别 3 中的字节数由以下公式给出:

SND.UNA + SND.WND - SND.NXT

这被称为可用窗口,因为它表示发送器在任何时刻可以使用的字节数。当数据被确认时,这会导致字节从传输类别 2 移动到传输类别 1,通过增加 SND.UNA 的值。假设发送窗口大小不变,这将导致窗口向右滑动,允许发送更多数据。图 48-4 说明了 SND 指针。

提示

关键概念 TCP 滑动窗口方案使用三个指针来跟踪四个传输类别中的每个字节的传输情况。SND.UNA 指向第一个未确认的字节,并指示传输类别 2 的开始;SND.NXT 指向下一个要发送的数据字节,并标记传输类别 3 的开始。SND.WND 包含发送窗口的大小;它被添加到 SND.NXT 上,以标记传输类别 4 的开始。将 SND.WND 添加到 SND.UNA,然后减去 SND.NXT,得到当前可用的传输窗口大小。

TCP 传输类别、发送窗口和指针 此图与()相同,但显示了 TCP 发送指针。SND.UNA 指向传输类别 2 的开始,SND.NXT 指向传输类别 3 的开始,SND.WND 是发送窗口的大小。可用窗口的大小(阴影矩形)可以通过这三个指针计算得出。

图 48-4. TCP 传输类别、发送窗口和指针 此图与图 46-6。")(在第四十六章)相同,但显示了 TCP 发送指针。SND.UNA 指向传输类别 2 的开始,SND.NXT 指向传输类别 3 的开始,SND.WND 是发送窗口的大小。可用窗口的大小(阴影矩形)可以通过这三个指针计算得出。

三种接收类别是通过两个指针来划分的:

接收下一个字节(RCV.NXT) 从其他设备期望接收的下一个字节的序列号。这标志着接收类别 3 中的第一个字节。所有之前的序列号都指的是已接收并确认的字节,在接收类别 1 和 2 中。

接收窗口(RCV.WND) 向其他设备广告的接收窗口大小。这指的是设备一次愿意从其对等方接受的字节数,这通常是为接收此连接的数据分配的缓冲区大小。当与 RCV.NXT 指针相加时,此指针标记接收类别 4 的第一个字节。

接收类别和指针在图 48-5 中说明。

SND 和 RCV 指针是互补的,就像类别一样,每个设备都管理自己的数据发送和从对等方接收数据。假设我们有一个客户端和一个服务器,这些指针之间的关系如下:

客户端 SND 指针跟踪客户端的输出数据流;RCV 指针指向从服务器传入的数据。客户端的 SND 类别对应于服务器的 RCV 类别。

服务器 SND 指针跟踪服务器的输出数据流;RCV 指针指向从客户端接收的数据。服务器的 SND 类别对应于客户端的 RCV 类别。

TCP 接收类别和指针 此图是 Figure 48-4 的补充,展示了接收设备如何设置类别。类别 1 和 2 已合并,因为“已接收未确认”和“已接收已确认”之间没有区别。此示例显示了接收设备在收到 14 个字节之前的状态,这些字节已在 Figure 48-4 中发送。

图 48-5. TCP 接收类别和指针 此图是图 48-4,展示了接收设备如何设置类别。由于“已接收未确认”和“已接收已确认”之间没有区别,因此类别 1 和 2 已经被合并。此示例显示了接收设备在收到图 48-4 中已发送的 14 个字节之前的状态。

小贴士

关键概念 每个设备都维护一组接收(RCV)指针。这些接收指针是发送(SND)指针的补充。设备的发送指针跟踪其发出的数据,而接收指针跟踪接收到的数据。两个接收指针是 RCV.NXT,它指示从另一设备期望的下一个字节的编号,以及 RCV.WND,它是该设备的接收窗口大小。一个设备的 RCV.WND 等于连接的另一设备的 SND.WND。

由于 SND 和 RCV 值是互补的,一个设备的发送窗口是另一个设备的接收窗口,反之亦然。然而,需要注意的是,两个设备上的指针值并不总是完全匹配,因为在任何给定时间,一些字节可能正在两个设备之间传输。图 48-5,例如,显示了接收者在接收到字节 32 到 45 之前的接收指针,这些字节在图 48-4 详细描述了该过程,展示了每一步中两个设备的发送和接收指针。它相当大,所以请注意。交易也以图形方式展示在图 图 48-6 和 图 48-7 中。两者都展示了相同的信息交换,使用 表 48-6 的步骤编号,但从一个设备的视角来看。图 48-6 展示了服务器的发送指针和客户端的接收指针。图 48-7 展示了客户端的发送指针和服务器的接收指针。(我本想将它们全部放在一个图中,但它们放不下!)

表 48-6. 带有发送和接收指针的 TCP 交易示例

客户端 服务器
处理步骤 SND.UNA SND.NXT SND.WND RCV.NXT RCV.WND 处理步骤 SND.UNA SND.NXT SND.WND RCV.NXT RCV.WND
--- --- --- --- --- --- --- --- --- --- --- ---
描述 描述
--- --- --- --- --- --- --- --- --- --- --- ---
(设置) 1 1 360 241 200 (设置) 241 241 200 1 360
在建立连接过程中,客户端根据设置期间交换的参数设置其指针。注意,SND.UNA 和 SND.NXT 的值相同。尚未发送任何数据,因此没有未确认的数据。RCV.NXT 是服务器期望接收的第一个字节的值。 服务器像客户端一样设置其指针。注意,其值是客户端值的补数。
1. 发送请求 1 141 360 241 200 (等待) 241 241 200 1 360
客户端向服务器发送一个请求。假设请求长度为 140 字节。它将形成一个具有该长度数据字段的数据段,并将序列号设置为 1(第一个字节的序列号)来传输它。一旦发送了这些数据,客户端的 SND.NXT 指针将增加到 141,以指示这是要发送给服务器的下一个数据。 服务器不采取任何行动,等待请求。
(等待) 1 141 360 241 200 2. 接收请求,发送确认和回复 241 321 200 141 360
此时,客户端尚未收到对其请求的确认。目前,SND.UNA+SND.WND 的值为 361,而 SND.NXT 的值为 141。这意味着当前可用的窗口为 220 字节。客户端在收到确认之前可以发送多达 220 字节的更多数据。现在,假设它没有更多要传输的数据。 服务器从客户端接收 140 字节的请求。服务器发送一个 80 字节的响应,该响应也确认了客户端的 TCP 段。序列号字段将为 241,这是服务器 80 字节数据的第一个序列号。确认号将为 141,告诉客户端这是服务器期望听到的下一个序列号,从而隐式确认接收了从第 1 个字节到第 140 个字节的数据。服务器将其 RCV.NXT 指针增加到 141,以反映接收到的 140 字节的数据。它将其 SND.NXT 指针增加 80。
3. 接收确认和回复,发送确认 141 141 360 321 200 4. 发送文件的第一部分 241 441 200 141 360
客户端接收到了服务器的响应。它看到确认号为 141,知道字节 1 到 140 已被成功接收。它将 SND.UNA 增加到 141,实际上是通过滑动发送窗口 140 个字节。客户端还接受了服务器发送的 80 字节数据,将 RCV.NXT 指针增加 80。假设它没有更多数据要发送,它发送了一个纯确认的 TCP 段,以确认服务器的响应。这个段没有数据,确认号值为 321。 当客户端接收其响应时,服务器的 TCP 被提供了一个 280 字节的文件要发送给客户端。然而,它不能在一个段中发送所有这些。当前 SND.UNA+SND.WND 的值为 441,而 SND.NXT 为 321。因此,服务器的可用窗口包含 120 字节数据。它创建了一个包含这么多数据和序列号 321 的 TCP 段。它将 SND.NXT 指针增加到 441。现在服务器已经填满了发送窗口。请注意,服务器不需要等待对步骤 2 中发送的回复的确认。这是 TCP 确保高吞吐量的关键因素之一。
5. 接收文件第一部分,发送确认 141 141 360 441 200 6. 接收回复的确认 321 441 200 141 360
客户端接收到了服务器发送的文件的前 120 字节部分。它将 RCV.NXT 指针增加到 441,并带着确认号 441 发送了一个确认。再次,如果它有其他对服务器的请求,它也可以在这里包含,但我们假设它没有。 服务器接收到了客户端对其先前 80 字节响应的确认(在步骤 2 中发送)。它将 SND.UNA 增加到 321。由于它刚刚收到了 80 字节的确认(并且客户端的窗口没有改变),服务器的可用窗口现在是 80 字节。然而,正如我们将在第四十九章中看到的,发送这样小的段可能会引起性能问题。假设服务器被编程为在有很多数据要传输时不会发送小于 100 字节的段。它决定等待。
(等待) 141 141 360 441 200 7. 接收文件第一部分的确认 441 441 200 141 360
客户端等待文件的其余部分。 服务器接收到了文件第一部分的确认。它将 SND.UNA 增加到 441。这现在恢复了完整的 200 字节窗口。
(仍在等待?) 141 141 360 441 200 8. 发送文件第二部分 441 601 200 141 360
客户端继续等待文件的其余部分。 服务器将文件中剩余的 160 字节数据在一个段中发送。它将 SND.NXT 增加 160,并使用序列号值为 441 的数据发送。
9. 接收文件第二部分,发送确认 141 141 360 601 200 (等待) 441 601 200 141 360
客户端收到文件的其余部分并确认它。它将 RCV.NXT 增加到 601,并发送一个确认号为 601 的段。 服务器目前完成。它等待文件第二部分的确认。
(完成) 141 141 360 601 200 10. 接收文件第二部分确认 601 601 200 141 360
客户端完成这次交换。 服务器收到第二个确认,并将发送窗口向前滑动 160 字节。事务现在完成。

TCP 事务示例,展示服务器的发送指针。从服务器的视角看事务。查看客户端的指针。

图 48-6. TCP 事务示例,展示服务器的发送指针。从服务器的视角看表 48-6 的事务。查看图 48-7 以查看客户端的指针。

TCP 事务示例,展示客户端的发送指针。从客户端的视角看事务。查看服务器的指针。

图 48-7. TCP 事务示例,展示客户端的发送指针。从客户端的视角看表 48-6 的事务。查看图 48-6 以查看服务器的指针。

滑动窗口机制的实际情况复杂性

我相信前一部分概述的过程看起来相当复杂,但实际上,示例被高度简化,以向您展示基本数据传输机制是如何在没有太多干扰的情况下工作的。可怕,不是吗?现实世界的连接将包括几个复杂性:

重叠传输 我故意只展示了客户端的一个请求和服务器的一个响应。在现实中,客户端和服务器可能会以快速连续的方式互相发送许多请求和响应。客户端会通过包含新请求的段来确认从服务器接收到的段,依此类推。

多个段的确认 我也没有展示一个案例,其中两个段被设备接收并使用单个确认进行确认,尽管这确实可能发生。假设在示例中,280 字节的文件的两个部分同时发送并被客户端同时接收。客户端将通过发送一个带有确认号 601 的单个段来确认这两个部分。请记住,这个字段是所有包含数据的段的累积确认,通过它前面的数字来表示,因此这将确认所有数据直到字节 600。

流量控制中的波动窗口大小 示例中的窗口大小保持不变,但在实际连接中,情况并不总是如此。一个非常繁忙的服务器可能无法像确认那样快速处理和从其缓冲区中移除数据。它可能需要缩小接收窗口以减少发送给客户端的数据量,然后在有更多空间可用时增加窗口。这就是 TCP 实现流量控制的方式,您将在下一章中看到。

丢失的传输 在实际连接中,一些传输的段会丢失并需要重传。这由 TCP 的重传方案(在第四十九章中描述)处理。

避免小窗口问题 在示例的描述中,我暗示我们并不总是想尽可能快地发送数据,以避免发送一个非常小的段。原因是这可能导致性能下降,包括称为愚蠢窗口综合征的现象。这将在下一章中探讨,我们将看到如何处理它需要我们改变迄今为止所检查的简单滑动窗口方案。

拥塞处理和避免 基本的滑动窗口机制在多年中已经改变,以避免 TCP 连接引起互联网拥塞,并在检测到拥塞时处理拥塞。正如您可能猜到的,拥塞问题将在下一章中讨论。

TCP 立即数据传输:推送功能

TCP 将来自进程的传入数据视为一个无结构的字节流,这使得它在满足大多数应用程序的需求方面具有很大的灵活性。应用程序不需要创建块或消息;它只需在准备传输时将数据发送到 TCP。至于 TCP,它对数据流中字节的含义没有任何了解或兴趣。它们只是字节,TCP 发送它们时并不真正关心它们的结构或目的。

这对应用程序的工作方式有几个有趣的影响。一个是 TCP 不提供任何关于数据分界点的自然指示,例如数据库记录或文件。应用程序必须负责这一点。TCP 字节导向的另一个结果是,TCP 不能根据数据的内文来决定何时形成段并将在设备之间发送的字节。TCP 通常会在缓冲区中累积应用程序进程发送给它的数据。它选择何时以及如何发送数据,完全基于前一小节讨论的滑动窗口系统,并结合帮助确保协议高效运行的逻辑。

这意味着虽然应用程序可以控制向 TCP 发送数据的速率和时机,但它不能本质上控制 TCP 本身在互联网上发送数据的时机。现在,如果我们发送一个大型文件,例如,这并不是一个大问题。只要我们继续发送数据,TCP 就会继续在互联网上转发它。在这种情况下,让 TCP 用数据填满其内部传输缓冲区并形成发送的段通常是没问题的。

然而,在某些情况下,让 TCP 在传输之前累积数据可能会引起严重的问题。这个经典的例子是交互式应用程序,如 Telnet 协议(见第八十七章

传输控制协议(TCP)的主要任务很简单:打包和发送数据。当然,几乎每个协议都会打包和发送数据!区分 TCP 与其他协议的是我们在上一章中探讨的滑动窗口机制,该机制控制设备之间的数据流。这个系统不仅管理基本的数据传输过程,而且还确保数据可靠地发送,并管理设备之间的数据流,以有效地传输数据,避免任何设备发送数据速度超过另一个设备接收速度的情况。

为了使 TCP 能够提供应用程序所需的功能和数据传输质量,该协议需要在前面章节中看到的简化数据传输机制之外进行增强。开发者需要给协议添加额外的“智能”来处理潜在的问题,并改变设备发送数据的基本方式,以避免可能产生的低效。

在本章中,我描述了 TCP 如何确保 TCP 连接上的设备以可靠和高效的方式进行通信。我首先解释了 TCP 检测丢失段并重新传输它们的基本方法。我讨论了与 TCP 确认方案相关的一些问题以及一个可选功能,以提高其效率。然后,我描述了 TCP 通过调整它决定一个段丢失之前将等待多长时间的系统。我讨论了如何调整窗口大小以实现流量控制以及窗口大小管理中的一些问题。这包括对臭名昭著的“愚蠢窗口综合症”问题的分析,以及针对与窗口大小相关的问题的特殊启发式方法,这些方法修改了基本的滑动窗口方案。最后,我讨论了 TCP 处理和避免拥塞的机制。

小贴士

背景信息 本节假设您已经熟悉 TCP 序列号和段,以及 TCP 滑动窗口机制的基本知识。它还假设您已经阅读了关于 TCP 消息格式和数据传输的章节。如果没有,您可能需要至少回顾第四十八章中关于 TCP 数据传输机制的章节。本章中的几个部分将扩展对 TCP 数据传输的简化讨论,以展示在非理想条件下的情况。

TCP 段重传计时器和重传队列

TCP 的基本数据传输和确认机制使用每个设备维护的一组变量来实现滑动窗口系统。这些指针跟踪每个设备发送和接收的字节数据,以及区分已确认和未确认的传输。在前一章中,我描述了这种机制,并给出了一个简化的示例,展示了客户端和服务器如何使用它进行基本数据传输。

那个示例之所以简化,是因为服务器发送的每个数据段都被客户端接收,反之亦然。如果我们可以始终依赖这种情况发生,那将是很好的,但正如我们所知,在互联网环境中,这是不现实的。由于各种条件——如硬件故障、互联网协议(IP)数据报损坏或路由器拥塞——TCP 数据段可能被发送但从未被接收。为了成为可靠的传输协议,TCP 必须能够检测丢失的数据段并重新传输它们。

使用重传队列管理重传

检测丢失的数据段并重新传输的方法在概念上是简单的。每次发送数据段时,我们都会启动一个重传计时器。这个计时器从预定的值开始,随着时间的推移而递减。如果在收到数据段的确认之前计时器到期,我们将重新传输该数据段。

TCP 使用这种基本技术,但以略微不同的方式实现。这样做的原因是需要有效地处理可能同时未确认的多个数据段,以确保在需要时它们各自在适当的时间重新传输。TCP 系统按照以下特定顺序工作。

放置在重传队列中,计时器启动 一旦传输包含数据的数据段,该数据段的副本就被放置在一个称为重传队列的数据结构中。当数据段被放置在队列中时,为该数据段启动一个重传计时器。因此,在某个时刻,每个数据段都会被放置在这个队列中。队列按照重传计时器剩余时间排序,这样 TCP 软件可以跟踪哪些计时器在到期前剩余时间最少。

确认处理 如果在计时器到期之前收到数据段的确认,则从重传队列中删除该数据段。

重传超时 如果在数据段的计时器到期之前没有收到确认,将发生重传超时,该数据段将自动重新传输。

当然,我们对于重新传输的数据段能否被接收的保证并不比原始数据段更多。因此,在重新传输数据段后,它将保留在重传队列中。重传计时器被重置,并重新开始倒计时。如果未收到重传的确认,数据段将再次重新传输,并重复此过程。

某些条件可能导致即使重复重传数据段也会失败。我们不希望 TCP 无限期地重传,因此 TCP 只会在确定存在问题并终止连接之前重传丢失的数据段一定次数。

小贴士

关键概念 为了提供发送数据的基本可靠性,每个设备的 TCP 实现都使用一个 重传队列。每个发送的数据段都会放入队列中,并为它启动一个 重传定时器。当接收到数据段中数据的确认时,它将从重传队列中移除。如果在收到确认之前定时器已经超时,该段将被重传,定时器也会重新启动。

识别数据段是否完全确认

但我们如何知道一个数据段是否已被完全确认呢?重传是在数据段的基础上处理的,但正如我们所见,TCP 确认是基于累积的,使用序列号。每当设备 A 向设备 B 发送数据段时,设备 B 会查看数据段中确认号字段的值。所有序列号低于该值的字节数据都已由设备 A 接收。因此,当设备 B 向设备 A 发送的数据段中所有发送的字节序列号都低于设备 B 向设备 A 发送的最后一个确认号时,该数据段被认为是已确认的。这是通过计算数据段最后一个序列号(使用其序列号字段中的第一个字节编号和数据段数据字段的长度)来确定的。

小贴士

关键概念 TCP 使用一个 累积确认 系统。设备接收到的数据段中的确认号字段表示,所有序列号小于该值的字节数据都已成功被另一设备接收。当一个数据段的全部字节都被确认时,该段被认为是已确认的;换句话说,当接收到一个包含比其最后一个字节的序列号更大的值的确认号时。

让我们使用图 49-1 中的示例来说明确认和重传在 TCP 中是如何工作的。假设连接中的服务器发送出四个连续的段(为了清晰起见,从 1 开始编号):

段 1 序列号字段为 1,段长度为 80。因此,段 1 中的最后一个序列号是 80。

段 2 序列号字段为 81,段长度为 120。段 2 中的最后一个序列号是 200。

段 3 序列号字段为 201,段长度为 160。段 3 中的最后一个序列号是 360。

段 4 序列号字段为 361,段长度为 140。段 4 中的最后一个序列号是 500。

再次强调,这些段可以依次发送,无需等待每个前一个传输被确认。这是 TCP 滑动窗口机制的主要优势。

现在假设客户端接收了前两个传输。它将发送一个确认,其中确认号字段值为 201。这告诉服务器,前两个段已经被客户端成功接收;它们将从重传队列中移除(并且服务器的发送窗口将向右滑动 200 字节)。段 3 将保留在重传队列中,直到接收到一个确认号字段值为 361 或更高的段;段 4 需要一个确认值至少为 501。

现在,让我们进一步假设在这个例子中,段 3 在传输过程中丢失,但段 4 被接收。客户端将段 4 存储在其接收缓冲区中,但无法确认它,因为 TCP 的累积确认系统——确认段 4 意味着也接收了段 3,而这从未出现。因此,客户端需要等待段 3。最终,服务器为段 3 启动的重传计时器将到期。服务器然后将重传段 3。客户端将接收它,然后能够向服务器确认段 3 和段 4。

然而,这里还有一个重要的问题:服务器应该如何处理第 4 个段?当客户端等待缺失的第 3 个段时,服务器没有收到任何反馈,因此它不知道第 3 个段已经丢失,也不知道第 4 个段(或任何后续传输)发生了什么。可能的情况是客户端已经收到了第 4 个段,但无法确认它。另一方面,第 4 个段也可能丢失了。一些实现可能选择只重发第 3 个段,而另一些可能选择重发第 3 个和第 4 个段。这是我们接下来要讨论的重要问题。

带重传的 TCP 事务示例 此图说明了简单的事务,并显示了服务器的发送指针和客户端的接收指针。服务器连续向客户端发送三个段,并为每个段设置重传定时器。第一部分和第二部分被接收,客户端为它们发送确认。收到此确认后,第一部分和第二部分从重传队列中移除。然而,第三部分在传输过程中丢失。当收到第四部分时,客户端无法确认它;这会暗示收到了缺失的第三部分。最终,第三部分的重传定时器到期,它被重新传输,此时第三部分和第四部分都被确认。

图 49-1. 带重传的 TCP 事务示例 此图说明了简单的事务,并显示了服务器的发送指针和客户端的接收指针。服务器连续向客户端发送三个段,并为每个段设置重传定时器。第一部分和第二部分被接收,客户端为它们发送确认。收到此确认后,第一部分和第二部分从重传队列中移除。然而,第三部分在传输过程中丢失。当收到第四部分时,客户端无法确认它;这会暗示收到了缺失的第三部分。最终,第三部分的重传定时器到期,它被重新传输,此时第三部分和第四部分都被确认。

最后一个问题是在将段放入重传队列时,我们应该使用什么值作为重传定时器。如果设置得太低,会发生过多的重传;如果设置得太高,由于重发丢失段的外部延迟,性能会降低。实际上,TCP 不能使用单个数字来表示这个值。它必须使用称为自适应重传的过程动态确定这个值,我们将在本章后面讨论这个问题。

TCP 非连续确认处理和选择性确认(SACK)

计算机科学人员有时使用优雅这个词来描述一个简单但有效的解决方案。我认为这个术语相当适用于 TCP 滑动窗口系统的一部分累积确认方法。通过一个单一的数字,在 TCP 段的确认号字段中返回,发送段的设备不仅可以确认它从连接对等方接收到的单个段,而且可能还有几个段。我们在第四十六章中讨论滑动窗口的基本原理时看到了这一点,也在之前的重传讨论中再次看到了这一点。

即使是最优雅的技术也有一定的弱点。在 TCP 确认系统的案例中,它无法有效地处理接收到的非连续TCP 段。确认号指定了发送该数字的设备已经接收了所有低于其值的序列号。如果我们收到两个非连续范围内的序列号的字节,就没有办法用一个单一的数字来指定这一点。

这可能会导致潜在的严重性能问题,尤其是在高速运行或在本质上不可靠的物理网络上运行的互联网中。为了了解问题所在,让我们回到图 49-1 中展示的例子。在那里,服务器发送了四个段,并收到了一个确认,其确认号值为 201。因此,段 1 和段 2 被认为是已确认的。它们将被从重传队列中移除,这也允许服务器的发送窗口向右滑动 80+120 字节,从而允许发送 200 更多字节的数据。

然而,让我们再次想象,从序列号 201 开始的第 3 个段在传输过程中丢失了。由于客户端从未收到这个段,它永远无法发送一个确认号高于 201 的确认。这导致滑动窗口系统卡住。服务器可以继续发送额外的段,直到填满客户端的接收窗口,但直到客户端发送另一个确认,服务器的发送窗口不会滑动。

我们看到的另一个问题是,如果第 3 个段丢失了,客户端没有方法告诉服务器它已经收到了任何后续的段。客户端完全可能已经收到了服务器的第 4 个段和后续段,直到窗口填满。但是,客户端不能发送一个值为 501 的确认来表示已收到第 4 个段,因为这暗示了已收到第 3 个段

注意

在某些情况下,客户端在收到第 4 个段后仍然可能会发送一个确认,但只包含对到第 2 个段末尾的字节的重复确认。请参阅本章后面的拥塞避免部分以获取解释。

在这里,我们可以看到 TCP 的单数值累积确认系统的缺点。我们可以想象一个最坏的情况,即服务器被告知它有一个 10,000 字节的窗口,并发送了 20 个每个 500 字节的段。第一个段丢失了,其他 19 个段被接收。但是,由于第一个段从未出现,所以其他 19 个段都无法被确认!

小贴士

关键概念 TCP 的确认系统是累积的。这意味着如果传输过程中丢失了一个段,那么在丢失的段被重传并成功接收之前,不能确认后续的段。

处理未确认段落的策略

当存在超出丢失段的后续段时,我们如何处理重传?在我们的例子中,当服务器在第 3 个段上遇到重传超时时,它必须决定对第 4 个段做什么,因为它根本不知道客户端是否收到了它。在我们的最坏情况下,我们可能有 19 个段,这些段可能在丢失的第一个段之后出现在客户端,也可能没有。

我们有两种处理这种情况的可能方法:

仅重传超时段 这是一种更为保守,或者如果你愿意,更为乐观的方法。我们只重传超时的那个段,希望其他超出它的段已经成功接收。如果超时段之后的段实际上已经出现,这种方法效果最好。如果它们没有出现,效果就不那么好了。在后一种情况下,每个段都需要单独超时并重传。想象一下,在我们最坏的情况下,所有的二十个 500 字节的段都丢失了。我们需要等待第 1 个段超时并重传。这个重传会被确认(我们希望),然后我们会陷入等待第 2 个段超时并被重传的困境。我们需要这样做很多次。

重传所有未确认的段 这是一种更为激进,或者说是悲观的方法。每当一个段超时时,我们不仅重传那个段,而且重传所有其他尚未确认的段。这种方法确保了,在任何确认出现延误的情况下,我们都会刷新所有未确认的段,给另一个设备一个额外的机会接收它们,以防它们也丢失了。在所有 20 个段都丢失的情况下,这种方法比乐观的方法节省了大量时间。问题是,这些重传可能并不必要。如果前 20 个段中的第一个丢失,而其他 19 个实际上已经接收到了,我们就会无端地重传 9500 字节的数据(包括头部)。

由于 TCP 不知道这些其他段是否出现,它无法知道哪种方法更好。它必须简单地做出决策,选择一种方法或另一种方法,并寄希望于最好的结果。在图 49-1 中所示的情况下,我演示了保守、乐观的方法:只有文件丢失的段被重新传输。图 49-2 展示了另一种积极、悲观的重传方法。

TCP 积极重传示例此示例与图 49-1 所示相同,只是在这里服务器正在采取积极的方法来重新传输丢失的段。当段 3 超时时,段 3 和段 4 都被重新传输,并且它们的重传定时器被重新启动。(在这种情况下,段 4 已经到达,所以这次额外的传输没有用。)

图 49-2. TCP 积极重传示例 此示例与图 49-1 中的示例相同,只是在这里,服务器正在采取一种“积极”的方法来重传丢失的段。当第 3 个段超时时,第 3 个段和第 4 个段都被重新传输,并且它们的重传定时器被重新启动。(在这种情况下,第 4 个段已经到达,所以这次额外的传输并没有用。)

小贴士

关键概念 在 TCP 中处理重传有两种方法。在更保守的方法中,只有定时器到期的段被重新传输。这可以节省带宽,但如果连续丢失多个段,可能会导致性能下降。另一种方法是,当一个段的重传定时器到期时,它和所有后续未确认的段都被重新传输。如果丢失多个段,这可以提供更好的性能,但可能会在不必要的情况下浪费带宽。

对非连续段缺乏了解是问题的核心。解决方案是在基本的 TCP 滑动窗口算法中增加一个可选功能,允许设备单独确认非连续段。这个功能在 RFC 1072 中引入,并在 RFC 2018 中完善,被称为 TCP 选择性确认,简称 SACK

更好的解决方案:选择性确认(SACK)

要使用 SACK,连接上的两个设备都必须支持该功能,并且必须通过在它们用来建立连接的 SYN 段中协商选择性确认允许(SACK-Permitted)选项来启用它。假设这样做,任何设备都可以在常规 TCP 段中包含一个选择性确认(SACK)选项。此选项包含一个已接收但尚未确认的数据段序列号范围列表,因为这些段是非连续的。

每个设备都会修改其重传队列,以便每个段包含一个标志,如果该段已被选择性确认——即 SACK 位,则该标志被设置为 1。设备随后使用图 49-2 选项,以标识已接收但尚未确认的非连续段。这可以节省原始发送者重新传输它们的需求。

例如,在我们的四个段的情况下,如果客户端收到了段 4 但没有收到段 3,当它发送一个带有确认号字段值为 201(用于段 1 和段 2)的段时,它可以包含一个 SACK 选项,指定“我已经收到了字节 361 到 500,但它们尚未被确认。”如果段 4 在段 1 和段 2 之后到达得很好,这也可以在第二个确认段中完成。服务器会识别这作为段 4 的字节范围,并打开段 4 的 SACK 位。当段 3 被重传时,服务器看到段 4 的 SACK 位已打开,因此不会重传它。这可以在图 49-3 中看到。

在段 3 重传后,段 4 的 SACK 位被清除。这是为了稳健性,以处理由于任何原因,客户端改变主意认为已收到段 4 的情况。客户端应该发送一个确认,其确认号为 501 或更高,正式表示已收到段 3 和段 4。如果这种情况没有发生,服务器必须接收到另一个针对段 4 的选择性确认,以将其 SACK 位重新打开。否则,它将在其定时器到期或段 3 被重新传输时自动重新发送。

使用选择性确认(SACK)的 TCP 重传 这是来自图和 的示例,改为使用可选的选择性确认功能。在收到文件的 1、2 和 4 部分后,客户端为 1 和 2 发送确认,其中包含对部分 4 的 SACK。这告诉服务器在部分 3 的定时器到期时不要重新发送部分 4。

图 49-3. 使用选择性确认(SACK)的 TCP 重传 这是来自图图 49-1 和图 49-2 的示例,改为使用可选的选择性确认功能。在收到文件的 1、2 和 4 部分后,客户端为 1 和 2 发送确认,其中包含对部分 4 的 SACK。这告诉服务器在部分 3 的定时器到期时不要重新发送部分 4。

TCP 自适应重传和重传定时器计算

每当发送一个 TCP 段时,它的一个副本也会放在重传队列中。当段被放入队列时,就会为该段启动一个重传计时器,它从一个特定的值开始并倒数到零。这个计时器控制了在发送者放弃、得出段已丢失的结论并再次发送它之前,一个段可以保持未确认的最长时间。

因此,我们用于重传计时器的时长非常重要。如果设置得太低,我们可能会开始重传一个实际上已经接收到的段,因为我们没有等待足够长的时间来等待该段的确认到达。相反,如果我们设置计时器太长,我们会浪费时间等待永远不会到达的确认,从而降低整体性能。

理想情况下,我们希望将重传计时器设置为略大于两个 TCP 设备之间往返时间(RTT)的值;也就是说,从客户端发送一个段到服务器,以及服务器将确认发送回客户端(或者当然相反)的典型时间。问题是,并没有这样一个典型的 RTT。有两个主要原因:

连接距离的差异 假设你在美国工作,在午餐时间,你使用 100 Mbps 快速以太网在你的工作站和本地服务器之间传输一个大型文件。同时,你从你姐姐的个人网站上下载你侄子的照片,该网站通过连接到秘鲁利马附近一个小镇的 ISP 的模拟调制解调器连接到互联网。你希望这两个 TCP 连接使用相同的重传计时器值吗?我当然希望不是!

瞬态延迟和可变性 由于互联网中的各种事件,任何两个设备之间发送数据所需的时间会随时间变化:流量波动、路由器负载等等。为了亲自看看这个例子,尝试从连接到互联网的 PC 的命令行中输入ping www.tcpipguide.com,你会看到报告的时间如何变化。

正是因为这些原因,TCP 不会尝试使用一个静态的单一数字作为其重传计时器的值。相反,TCP 使用一个动态的,或称自适应的重传方案。

基于 RTT 计算的自适应重传

TCP 试图确定设备之间的近似 RTT,并随着时间的推移进行调整,以补偿平均延迟的增加或减少。如何做到这一点的问题很重要,但在 TCP 的主要标准中并没有详细说明。然而,RFC 2988,“计算 TCP 的重传计时器”对此问题进行了广泛讨论。

RTT 可能会上下波动,因此我们希望为连接找到一个平均的 RTT 值。这个平均值应该对 RTT 的上下波动做出响应,而不会对几个非常慢或非常快的确认过度反应。为了实现这一点,RTT 的计算使用了一个平滑公式:

新 RTT = (α * 旧 RTT) + ((1-α) * 最新 RTT 测量值)

其中α(alpha)是介于 0 和 1 之间的平滑因子。α的值越高(越接近 1),平滑效果越好,可以避免由于一个非常快或非常慢的 RTT 测量结果而导致的突然变化。相反,这也减慢了 TCP 对 RTT 更持续变化的反应速度。α的值越低(越接近 0),RTT 对测量 RTT 的变化反应越快,但 RTT 波动剧烈时可能会引起过度反应。

确认模糊性

测量两个设备之间的 RTT 在概念上很简单:注意发送段的时刻,注意收到确认的时刻,然后相减。然而,在实际实现中,这个测量更为复杂。

主要的潜在“陷阱”之一发生在假设一个段丢失并重新传输时。重传的段没有任何可以将其与原始段区分开来的东西。当收到这个段的确认时,不清楚这是否对应于重传或原始段。尽管我们决定该段已丢失并重新传输,但该段最终可能经过很长时间才到达,或者该段快速到达但确认花费了很长时间!

这被称为确认模糊性,解决它并不简单。我们不能简单地决定假设一个确认总是与发送的段的最旧副本一起,因为这会使往返时间(RTT)看起来太高。我们也不想仅仅假设确认总是与段的最新发送一起,因为这可能会人为地降低平均 RTT。

RTT 计算和卡尔算法的改进

TCP 的解决方案基于使用一种称为卡尔算法的技术,以发明者菲尔·卡尔的名字命名。这个算法的主要变化是将平均 RTT 的计算与用于重传段计时器的值的计算分开。

在卡尔算法下进行的第一个改变是不在计算连接的整体平均 RTT 时使用任何重传段的测量 RTT。这完全消除了确认模糊性问题。

然而,仅此并不能允许由于重传而增加的延迟影响平均 RTT。为此,我们需要第二个变化:为重传段引入计时器退避方案。我们首先根据当前的平均 RTT 为每个新传输的段设置重传计时器。当一个段被重传时,计时器不会被重置为最初传输时设置的相同值。它通过乘数(通常是 2)进行“退避”,或增加,以给重传更多的时间被接收。计时器会继续增加,直到重传成功,达到一定的最大值。这防止了重传发送得太快,从而进一步增加网络拥塞。

一旦重传成功,往返时间(RTT)将保持在较长的(退避的)值,直到可以在没有重传的情况下发送并确认的段上测量到一个有效的 RTT。这允许设备对偶尔导致连接上延迟持续一段时间的情况使用较长的计时器进行响应,而当正常条件恢复时,最终将 RTT 调整回长期平均值。

小贴士

关键概念 TCP 使用一种自适应的重传方案,该方案根据设备之间发送段所需平均时间自动调整重传计时器的设置时间。这有助于避免太早或太晚重传可能丢失的段。

TCP 窗口大小调整和流量控制

我们已经看到了窗口大小的概念对 TCP 滑动窗口机制的重要性。在客户端和服务器之间的连接中,客户端告诉服务器它愿意一次从服务器接收多少字节的数据;这是客户端的接收窗口,它成为服务器的发送窗口。同样,服务器告诉客户端它愿意一次从客户端接收多少字节的数据;这是服务器的接收窗口和客户端的发送窗口

这些窗口的使用在第四十八章中得到了演示,我们讨论了 TCP 的基本数据传输和确认机制。然而,正如该章节中的示例简化了因为我没有展示丢失段的情况,还有另一种方式它并不反映实际互联网的真实情况:在通信过程中,发送和接收窗口的大小从未改变。

要理解窗口大小可能波动的原因,我们需要了解它代表什么。考虑窗口大小的最简单方式是,它表示设备特定连接的接收缓冲区的大小。也就是说,窗口大小表示设备在将数据传递给应用程序进程之前,一次可以从其对等方处理多少数据。让我们考虑第四十八章中的例子。我说服务器的窗口大小是 360。这意味着服务器一次愿意从客户端接收不超过 360 字节。

当服务器从客户端接收数据时,它将其放入此缓冲区。然后服务器必须对这份数据执行两个不同的操作:

致谢 服务器必须向客户端发送一个确认,以表明数据已被接收。

传输 服务器必须处理数据,将其传输到目标应用程序进程。

区分这两种活动至关重要。不幸的是,TCP 标准在这方面做得并不出色,这使得它们很难理解。关键点是,在基本的滑动窗口系统中,数据在接收时会被确认,但不一定立即从缓冲区中传输出来。这意味着缓冲区可能会以接收 TCP 无法清空的速度更快地填满接收到的数据。当这种情况发生时,接收设备可能需要调整窗口大小以防止缓冲区过载。

由于窗口大小可以用来以这种方式管理连接两端设备之间数据流动的速率,因此它是 TCP 实现流量控制的方法之一,这是传输层的经典任务。流量控制对 TCP 至关重要,因为它是设备相互通信状态的方法。通过减小或增加窗口大小,服务器和客户端都确保对方设备发送数据的速度与接收方处理数据的速度相匹配。

通过减小发送窗口大小来降低发送数据速率

要理解窗口大小调整,让我们回到我们之前的例子第四十八章,但做一些修改。首先,为了使事情简单,我们只需查看客户端向服务器发送的传输,而不是服务器的回复(除了确认)——这如图图 48-7 所示。与之前一样,客户端向服务器发送 140 字节。发送 140 字节后,客户端在其可用窗口中剩余 220 字节:发送窗口中的 360 字节减去它刚刚发送的 140 字节。

在某个时候之后,服务器接收到了 140 字节并将它们放入缓冲区。现在,在一个理想的世界里,140 字节进入缓冲区,它们被确认并立即从缓冲区中移除。另一种思考方式是,缓冲区是无限大小的,可以容纳客户端发送的所有数据。缓冲区的空闲空间保持 360 字节大小,因此可以再次向客户端宣传相同的窗口大小。这就是前一个示例中的简化。

只要服务器能够以与数据到达速度相同的速度处理数据,它就会保持窗口大小为 360 字节。客户端在收到 140 字节的确认和之前相同的窗口大小时,将整个 360 字节的窗口向右滑动 140 字节。由于现在没有未确认的字节,客户端现在可以再次发送 360 字节的数据。这些对应于之前在可用窗口中的 220 字节,加上刚刚确认的 140 个新字节。

然而,在现实世界中,该服务器可能正在处理数十、数百甚至数千个 TCP 连接。TCP 可能无法立即处理数据。或者,可能由于某种原因,应用程序本身可能还没有准备好处理 140 字节的数据。在任何情况下,服务器的 TCP 可能无法立即从缓冲区中移除所有 140 字节。如果是这样,当向客户端发送确认时,服务器将希望更改它向客户端宣传的窗口大小,以反映缓冲区部分已满的事实。

假设我们收到了 140 字节,但只能向应用程序发送 40 字节,留下 100 字节在缓冲区中。当我们发送 140 字节的确认时,服务器可以将发送窗口减少 100 字节,变为 260 字节。当客户端从服务器接收到这个段时,它将看到发送的 140 字节的确认,并将窗口向右滑动 140 字节。然而,在滑动这个窗口时,它将窗口大小减少到只有 260 字节。我们可以将这视为将窗口的左边缘向右滑动 140 字节,但右边缘只向右滑动 40 字节。新的、更小的窗口确保服务器从客户端接收的最大字节数为 260 字节,这将适合其接收缓冲区中剩余的 260 字节。这在上面的图 49-4 的第一次消息交换(步骤 1 至 3)中得到了说明。

TCP 窗口大小调整和流量控制 此图显示了三个消息周期,每个周期都会导致服务器减少其接收窗口。在第一个周期,服务器将其从 360 字节减少到 260 字节,因此当客户端收到服务器的确认时,其可用窗口只能增加 40 字节。在第二个和第三个周期,服务器通过接收到的数据量来减少窗口大小,这暂时冻结了客户端的发送窗口大小,阻止其发送新数据。

图 49-4. TCP 窗口大小调整和流量控制 此图显示了三个消息周期,每个周期都会导致服务器减少其接收窗口。在第一个周期中,服务器将其从 360 字节减少到 260 字节,因此当客户端收到服务器的确认时,其可用窗口只能增加 40 字节。在第二个和第三个周期中,服务器通过接收到的数据量来减少窗口大小,这暂时冻结了客户端的发送窗口大小,阻止其发送新数据。

减少发送窗口大小以停止发送新数据

如果服务器如此繁忙以至于无法处理接收到的任何字节怎么办?假设客户端的下一个传输大小为 180 字节,但服务器如此繁忙以至于无法移除任何字节。

在这种情况下,服务器可以缓冲 180 字节,并在它发送的这些字节的确认中,将窗口大小减少相同的量:从 260 字节减少到 80 字节。当客户端收到 180 字节的确认时,它会看到窗口大小也减少了 180 字节。它会将窗口滑动相同的量,就像窗口大小减少一样!这实际上就像服务器说:“我确认收到了 180 字节,但不允许你发送任何新字节来替换它们。”另一种看待方式是,窗口的左边缘滑动 180 字节,而右边缘保持固定。只要窗口的右边缘不移动,客户端就不能发送比确认接收之前更多的数据。这是图 49-4 中的中间交换(步骤 4 到 6)图 49-4。

关闭发送窗口

这个窗口调整的过程可以继续,当然,这可以通过两个设备来完成,尽管我们在这里只考虑等式中的客户端发送到服务器的一侧。如果服务器从客户端接收数据的速度超过了它可以将数据泵送到应用程序的速度,它将继续减少其接收窗口的大小。

继续我们的例子,假设在发送窗口减少到 80 字节后,客户端发送了第三个请求,这次请求长度也是 80 字节,但服务器仍然很忙。然后服务器将窗口大小降低到 0,这被称为关闭窗口。这告诉客户端服务器非常繁忙,它应该完全停止常规的数据发送,如图 49-4 底部三分之一所示。稍后,当服务器负载减轻时,它可以再次增加此连接的窗口大小,允许传输更多数据。

小贴士

关键概念 TCP 滑动窗口系统不仅用于通过确认和重传确保可靠性,它也是 TCP 流量控制机制的基础。通过增加或减少其接收窗口的大小,一个设备可以提高或降低其连接伙伴向其发送数据的速率。在设备变得极其繁忙的情况下,它甚至可以将接收窗口减少到零。这将关闭窗口并停止任何进一步的数据传输,直到窗口重新打开。

虽然从概念上讲很简单,但使用窗口大小调整进行流量控制可能会非常复杂。如果我们不仔细考虑如何更改窗口大小,我们可能会在 TCP 的操作中引入严重问题。还有一些特殊情况可能会发生,尤其是在窗口大小因设备变得繁忙而减小的情况下。接下来的两个部分将探讨窗口管理问题以及需要对这些基本滑动窗口系统进行哪些更改来解决这些问题。

TCP 窗口管理问题

TCP 连接上的两个设备中的每一个都可以调整它向另一个设备广告的窗口大小,以控制通过连接的数据流。减小窗口大小迫使另一个设备发送更少的数据;增加窗口大小允许更多数据流动。在理论上,我们应该能够让每个设备上的 TCP 软件根据数据进入缓冲区和从缓冲区移除以发送到接收应用程序的速度来按需更改窗口大小。

不幸的是,窗口大小的某些变化可能会导致不希望的结果。这些情况不仅发生在窗口大小减小的时候,也发生在窗口大小增加的时候。因此,我们需要考虑与窗口大小管理相关的一些问题。正如前几节所做的那样,我们将使用之前在第四十八章中引入的相同的客户端/服务器示例进行说明。

缩小 TCP 窗口相关的问题

一个与窗口大小管理相关的问题是与设备在变得繁忙时如何快速减小其接收窗口大小。假设服务器从 360 字节的接收窗口开始,正如上述示例中所述,并接收了 140 字节的数据,它确认了这些数据,但无法立即从缓冲区中移除。服务器可以通过减小它向客户端广告的窗口大小来响应。在无法从缓冲区中移除任何字节的情况下,窗口大小会减少 140 字节,这是添加到缓冲区中的相同字节。这冻结了客户端发送窗口的右边缘,因此当它收到确认时,无法发送任何额外的数据。

如果服务器超载到实际上需要减小缓冲区本身的大小怎么办?比如说内存不足,操作系统说:“我知道你为这个连接分配了 360 字节的接收缓冲区,但我需要释放内存,所以现在你只有 240 字节。”服务器仍然不能立即处理它接收到的 140 字节,因此它需要将发送给客户端的窗口大小从 360 字节减少到 100 字节(总缓冲区 240 字节减去已接收的 140 字节)。

实际上,这样做实际上是将客户端发送窗口的右边缘向左移动。它说:“当你收到这个确认时,不仅不能发送更多数据,而且你现在发送的数据更少。”在 TCP 术语中,这被称为缩小窗口

然而,这样做有一个非常严重的问题:当原始的 140 字节从客户端传输到服务器时,客户端仍然认为它有 360 字节的窗口大小,其中 220 字节是可用的(360 减去 140)。客户端很可能已经向服务器发送了那 220 字节数据中的一些,在它收到服务器缩小窗口的通知之前!如果是这样,并且服务器将缓冲区减少到 140 字节使用后 240 字节,当那 220 字节到达服务器时,只有 100 字节可以容纳,任何额外的字节都需要被丢弃。这将迫使客户端需要重新传输那些数据,这是低效的。图 49-5 直观地说明了这种情况会如何发展。

缩小 TCP 窗口的问题 在这个对图 49-4 例子的修改中,客户端开始时有一个 360 字节的可用窗口大小。它发送了一个 140 字节的段,然后不久之后发送了一个 180 字节的段。然而,服务器很忙,当它接收到第一次传输时,它决定将缓冲区减少到 240 字节。它保留了刚刚接收到的 140 字节,并将接收窗口减少到 100 字节。当客户端的 180 字节段到达时,服务器缓冲区中只有 100 字节的空间。当客户端收到新的窗口大小广告 100 时,它将遇到问题,因为它已经发送了 180 字节但尚未得到确认。

图 49-5. 缩小 TCP 窗口的问题 在对图 49-4,客户端的可用窗口大小从 360 字节开始。它发送了一个 140 字节的段,然后不久之后发送了一个 180 字节的段。然而,服务器很忙,当它收到第一次传输时,它决定将缓冲区减少到 240 字节。它保留了刚刚接收到的 140 字节,并将接收窗口一直减少到 100 字节。当客户端的 180 字节段到达时,服务器缓冲区中只有 100 字节的空间。当客户端收到新的窗口大小广告为 100 时,它将遇到问题,因为它已经发送了 180 字节但尚未得到确认。

减少缓冲区大小而不缩小窗口

为了防止与窗口缩小相关的问题发生,TCP 向基本的滑动窗口机制添加了一条简单规则:不允许设备缩小窗口。

注意,这里存在一个潜在的术语模糊性。在日常讨论中,缩小减少这两个词有时被同义使用。正如我们所见,减少窗口大小并没有什么问题。缩小窗口的问题仅指我们减少窗口大小到与先前的窗口广告相矛盾,通过收回发送一定数量字节的权限。

另一种看待这个问题的方式是,缩小发生在服务器发送回的窗口大小广告小于客户端认为其当时可用窗口大小的时候。在这种情况下,服务器缩小了窗口,因为在它确认 140 字节的时候,它发送回的窗口大小为 100,这小于客户端当时的 220 字节可用窗口。

当然,可能会有需要减少缓冲区的情况,那么应该如何处理呢?与缩小窗口不同,服务器必须更加耐心。在上一节中的例子中,当缓冲区需要减少到 240 字节时,服务器必须发送一个窗口大小为 220 的字节,从而冻结客户端发送窗口的右边缘。客户端仍然可以填满 360 字节的缓冲区,但不能发送超过这个量。一旦从服务器的接收缓冲区中移除 120 字节,缓冲区就可以在不丢失数据的情况下减小到 240 字节。然后服务器可以恢复正常操作,随着从接收缓冲区中取走字节,增加窗口大小。

小贴士

关键概念 当一个设备将其接收窗口减小到足以使对方设备的可用发送窗口缩小(意味着其发送窗口的右边缘向左移动)的程度时,就会发生称为 窗口缩小 的现象。由于这可能导致正在传输的数据需要被丢弃,因此设备必须更逐渐地减小其接收窗口的大小。

处理关闭的窗口和发送探测段

另一个特殊的窗口管理问题是如何处理一个设备必须将发送窗口大小减小到零的情况。如前所述,这被称为 关闭接收窗口。由于服务器的接收窗口是客户端的发送窗口,将其大小减小到零意味着客户端无法发送任何数据。这种情况将持续到客户端从服务器接收到一个包含非零窗口字段的新的确认段,从而重新打开窗口。然后客户端能够再次发送数据。

这种情况的问题在于客户端必须依赖于从服务器接收“窗口打开”段。像所有 TCP 段一样,这个段是通过 IP 传输的,这是不可靠的。记住,TCP 之所以可靠,是因为它会确认发送的数据,并在必要时重新传输丢失的数据,但它永远不能 保证 任何特定的段能够到达目的地。这意味着当服务器尝试通过包含较大窗口字段的确认段重新打开窗口时,客户端可能永远不会收到这条消息。客户端可能会得出结论,发生了问题,并终止连接。

为了防止这种情况发生,客户端可以定期向服务器发送特殊的 探测 段。这些探测的目的在于促使服务器发送包含当前窗口大小的段。探测段可以包含零个或一个字节的数据,即使窗口关闭时也是如此。探测将定期发送,直到窗口重新打开,具体的实现决定了探测生成的速率。

小贴士

关键概念 将接收窗口减少到零的设备被称为关闭了窗口。另一个设备的发送窗口因此关闭;它可能不会发送常规数据段。然而,它可以发送探测段来检查窗口的状态,从而确保在窗口重新打开时不会错过通知。

当服务器决定重新打开关闭的窗口时,还有一个潜在的风险:将窗口打开得太小。一般来说,当接收窗口太小时,这会导致生成许多小段,大大降低 TCP 的整体效率。下一节将探讨这个众所周知的问题以及它是如何通过改变基本的滑动窗口机制来解决的。

TCP 愚蠢窗口综合征

在第四十八章中描述 TCP 的最大段大小(MSS)参数时,我解释了确定 TCP 段最佳大小的权衡。如果段太大,我们可能会在 IP 层上使它们碎片化。如果它们太小,我们会因为在一个至少有 40 字节头开销的段中发送少量数据而大大降低性能。我们还消耗了处理这些小段所需的有价值的处理时间。

MSS 参数确保我们不会发送过大的段;TCP 不允许创建大于 MSS 的段。不幸的是,基本的滑动窗口机制并没有提供任何最小的段大小,可以传输。实际上,设备发送非常小、效率低下的段是可能的,而使用不受限制的窗口大小调整的最简单流量控制实现确保在重负载条件下,窗口大小会变得很小,从而导致性能显著下降!

愚蠢窗口综合征是如何发生的

为了了解愚蠢窗口综合征(SWS)是如何发生的,让我们考虑一个例子,这个例子是对本节中我们一直在使用的例子的一个变体。我们假设 MSS 是 360 字节,一个客户端/服务器对,其中服务器的初始接收窗口设置为这个相同的值,360。这意味着客户端可以向服务器发送一个完整大小的段。只要服务器能够以与客户端发送的速度一样快地从缓冲区中移除数据,我们就应该没有问题。(实际上,缓冲区的大小通常会比 MSS 大。)

现在,想象一下,如果服务器因为某种原因而变得繁忙,而客户端需要向它发送大量数据。为了简单起见,让我们假设服务器只能从缓冲区中移除每个接收到的 3 字节中的 1 字节数据。让我们还说,在下一个客户端段到达的时间内,它还从缓冲区中移除了额外的 40 字节。以下是会发生的事情:

  1. 客户端的发送窗口是 360 字节,并且它有很多数据要发送。它立即向服务器发送一个 360 字节的段。这用完了它的整个发送窗口。

  2. 当服务器收到这个段时,它会进行确认。然而,它只能删除 120 字节,因此服务器将窗口大小从 360 字节减少到 120 字节。它在确认的窗口字段中发送这个信息。

  3. 客户端收到 360 字节的确认,并看到窗口大小已减少到 120 字节。它想尽快发送数据,因此发送了一个 120 字节的段。

  4. 当 120 字节的段到达时,服务器已经从缓冲区中删除了 40 更多字节。因此,缓冲区包含 200 字节(第一个段中的 240 字节减去删除的 40 字节)。服务器能够立即处理这 120 字节中的三分之一,即 40 字节。这意味着向已经留在缓冲区中的 200 字节中添加了 80 字节,所以用掉了 280 字节。服务器必须将窗口大小减少到 80 字节。

  5. 客户端将看到这个减少的窗口大小,并发送一个 80 字节的段。

  6. 服务器最初有 280 字节,删除了 40 字节,所以剩下 240 字节。它从客户端接收 80 字节,并删除三分之一,因此向缓冲区中添加了 53 字节,缓冲区变为 293 字节。它将窗口大小减少到 67 字节(360 减去 293)。

这个过程,如图图 49-6,将会进行多轮,窗口大小会越来越小,尤其是如果服务器负载进一步增加。它清空缓冲区的速度可能会进一步降低,窗口甚至可能完全关闭。

假设这种情况发生。最终,服务器将从该缓冲区中删除一些数据。比如说,当客户端的第一个关闭窗口探测到达时,服务器已经删除了 40 字节。然后服务器将窗口重新打开到 40 字节的大小。客户端仍然急于尽可能快地发送数据,因此它生成一个 40 字节的段。就这样,很可能所有剩余的数据都以极小的段从客户端传递到服务器,直到客户端数据耗尽或服务器更快地清空缓冲区。

现在想象一下最坏的情况。这次,是服务器上的应用程序过程过载。它一次从缓冲区中提取一个字节的数据。每次它从服务器的缓冲区中移除一个字节,服务器的 TCP 就会打开一个窗口大小正好为 1 的窗口,并在对客户端的确认中将这个值放入窗口字段。然后客户端发送一个正好包含一个字节的数据段,直到应用程序提取出下一个字节,缓冲区再次被填满。

这一切并不代表滑动窗口机制的失败本身。它正在正常工作,以保持服务器的接收缓冲区充满并管理数据流。问题是滑动窗口机制只关注管理缓冲区。它没有考虑到当窗口大小以这种方式微管理时,产生的较小数据段的低效性。本质上,通过发送小窗口大小的广告,我们赢得了战斗但输掉了战争。

早期发现这一现象的 TCP/IP 研究人员将其称为愚蠢窗口综合征(SWS),这是对“滑动窗口系统”这一短语的戏谑,表达了他们对系统进入这种状态时行为的看法。

TCP 愚蠢窗口综合征(SWS)此图展示了 TCP 愚蠢窗口综合征这一现象的一个例子。客户端试图尽可能快地将数据发送到服务器,而服务器非常繁忙,无法及时清除其缓冲区。每当客户端发送数据时,服务器都会减小其接收窗口。客户端发送的消息大小会缩小,直到它只发送非常小、低效的数据段。注意,在此图中,我将服务器的缓冲区固定在位置,而不是像本章其他图中的那样向右滑动。这样,你可以更容易地看到接收窗口大小的减小。

图 49-6. TCP 愚蠢窗口综合征(SWS)此图展示了 TCP 愚蠢窗口综合征这一现象的一个例子。客户端试图尽可能快地将数据发送到服务器,而服务器非常繁忙,无法及时清除其缓冲区。每当客户端发送数据时,服务器都会减小其接收窗口。客户端发送的消息大小会缩小,直到它只发送非常小、低效的数据段。注意,在此图中,我将服务器的缓冲区固定在位置,而不是像本章其他图中的那样向右滑动。这样,你可以更容易地看到接收窗口大小的减小。

讨论中的示例展示了 SWS 是如何由接收设备广告的小窗口大小引起的。如果发送设备在生成传输段时不够小心,即使接收方的缓冲区状态如何,也可能发生 SWS。例如,假设示例中的客户端 TCP 以每次 10 字节的数据块从发送应用程序接收数据。图 49-6 此图展示了 TCP silly window syndrome 这一现象的一个例子。客户端试图尽可能快地将数据发送到服务器,服务器非常繁忙,无法及时清除其缓冲区。每次客户端发送数据时,服务器都会减小其接收窗口。客户端发送的消息大小会缩小,直到它只发送非常小、效率低下的段。注意,在此图中,我将服务器的缓冲区固定在位置,而不是像本章其他图那样向右滑动。这样,你可以更容易地看到接收窗口大小的减小。"),然而,发送 TCP 如此急切地想要将数据发送到客户端,以至于它将每个 10 字节的数据块立即打包成一个段,即使下一个 10 字节的数据块很快就会到来。这会导致不必要的、效率低下的 10 字节段的蜂拥而至。

Tip

关键概念 基本的 TCP 滑动窗口系统不对传输段设置最小大小。在特定情况下,这可能导致发送许多小、效率低下的段,而不是少量大段。亲切地称为 silly window syndrome (SWS),这一现象可能是由于接收方广告的窗口大小太小或发送方过于积极立即发送非常小的数据量而引起的。

Silly Window Syndrome Avoidance Algorithms

由于 SWS 是由基本的滑动窗口系统没有关注创建小段的决定的结果引起的,因此处理 SWS 在概念上是简单的:改变系统,使我们避免广告小窗口大小,同时,也避免发送小段。由于数据发送方和接收方都参与了 SWS,因此对两者的行为都进行了修改以避免 SWS。这些更改统称为SWS 避免算法

Receiver SWS Avoidance

让我们从接收方的 SWS 避免开始。正如我们在前面的例子中所看到的,接收方通过减小其接收窗口的大小到更小的值来对 SWS 做出了贡献。这导致发送方发送窗口的右边缘以越来越小的增量移动,从而产生越来越小的数据段。为了避免 SWS,我们简单地制定了一条规则,即接收方不得以这种方式更新其广告的接收窗口,以至于在发送方部分留下太少可用的窗口空间。换句话说,我们限制接收方通过过小的量移动窗口的右边缘。边缘可能移动的通常最小值是 MSS 参数的值或缓冲区大小的一半,取较小者。

让我们看看我们如何在图 49-6 中展示的例子中使用它。当服务器从客户端接收初始 360 字节的段并且只能处理 120 字节时,它不会将窗口大小减小到 120。它将窗口大小一直减小到零,关闭窗口。然后它将这个信息发送回客户端,客户端将停止发送小段。一旦服务器从缓冲区中移除 60 个字节,现在将有 180 个字节空闲,是缓冲区大小的一半。现在它将窗口大小增加到 180 字节,并将新的窗口大小发送给客户端。

它将继续只宣传 0 字节或 180 字节或更多字节,而不是介于两者之间的较小值。这似乎会减慢 TCP 的操作,但实际上并没有。因为服务器过载,连接整体性能的限制因素是服务器清除缓冲区的速率。我们只是在交换许多小段为几个大段。

发送方 SWS 避免和 Nagle 算法

发送方通过在传输 TCP 部分施加“限制”来避免 SWS。我们不是尽可能快地发送数据,而是等待直到我们有一个合理大小的数据段。完成此操作的具体方法被称为Nagle 算法,以发明者约翰·史密斯的名字命名。(开个玩笑,其实是约翰·Nagle。)简化地说,这个算法的工作原理如下:

  • 只要连接上没有未确认的数据,一旦应用程序想要发送数据,就可以立即发送。例如,在像 Telnet 这样的交互式应用程序的情况下,单个按键可以推送到一个段中。

  • 尽管存在未确认的数据,但所有后续要发送的数据都保留在传输缓冲区中,直到所有未确认的数据被确认,或者我们积累了足够的数据来发送一个完整大小的(MSS 大小的)段。即使用户请求了推送,这也适用。

这可能看起来很奇怪,尤其是关于即使有推送请求也要缓冲数据的那部分!你可能会认为这会导致像 Telnet 这样的应用程序崩溃。实际上,Nagle 算法是一种非常聪明的解决方案,它适合像 Telnet 这样的低数据速率交互式应用程序和高带宽文件传输应用程序的需求。

如果你使用的是像 Telnet 这样的东西,其中数据到达非常缓慢(与计算机相比,人类非常慢),初始数据(第一个按键)可以立即推送。下一个按键必须等待确认,但相对于按下下一个键所需的时间,这可能会相对较快。相比之下,生成大量数据的更传统应用程序将自动将数据积累成更大的段以提高效率。

Nagle 算法实际上比这个描述要复杂得多,但这一部分已经太长了。RFC 896 在(更多)细节中讨论了它。

小贴士

关键概念 现代 TCP 实现包含一套SWS 避免算法。在接收时,设备被编程为不宣传非常小的窗口,而是等待直到缓冲区中有足够的空间容纳一个合理大小的窗口。发送者使用Nagle 算法来确保在存在未确认的字节时不会生成小的段。

TCP 拥塞处理和拥塞避免算法

通过改变设备向 TCP 连接上的对等方宣传的窗口大小,设备可以增加或减少其对等方发送给它的数据速率。这就是 TCP 滑动窗口系统如何在两个连接设备之间实现流量控制。我们已经在本章中看到了它是如何工作的,包括对基本机制所做的更改,以确保通过减少发送的小段数量来保持性能。

流量控制是调节设备间数据传输的重要部分,但在以下方面有限制:它只考虑连接中每个设备内部发生的事情,而不是它们之间设备发生的事情。实际上,这种“自我中心”是分层架构的典型症状。由于我们处理的是第 4 层中典型服务器和客户端之间 TCP 的工作方式,所以我们不担心数据如何在它们之间传输;这是第 3 层 IP 的工作。

拥塞考虑

在实践中,第三层发生的事情可能非常重要。从抽象的角度来看,我们的服务器和客户端可能直接使用 TCP 连接,但我们发送的所有段都通过它们之间的互联网和路由器传输。这些网络和路由器也在携带来自许多其他连接和高层协议的数据。如果互联网变得非常繁忙,我们连接端点之间传输段的速率将会降低,甚至可能会被丢弃。这被称为拥塞

再次强调,在 TCP 层面,没有直接理解导致拥塞的原因或原因的方法。它只是被视为从一台设备向另一台设备传输数据时的低效,这需要某些段需要重传。然而,尽管 TCP 对互联网上发生的事情大多视而不见,但它必须足够聪明,以了解如何处理拥塞,而不是加剧它。

回想一下,每个传输的段都会放入重传队列,并设置一个重传定时器。现在,假设互联网上的拥塞急剧增加,并且没有机制来处理拥塞。段将被延迟或丢弃,这会导致它们超时并被重传。这将增加我们客户端和服务器之间互联网上的流量。此外,可能有数千个其他 TCP 连接以类似的方式行为。每个都会不断重传越来越多的段,进一步增加拥塞,形成一个恶性循环。整个互联网的性能将急剧下降,导致一种称为拥塞崩溃的状态。

消息很明确:TCP 不能仅仅忽略其连接端点之间互联网上发生的事情。为此,TCP 包含了几种特定的算法,这些算法旨在响应拥塞或从一开始就避免它。从某种意义上说,许多这些技术可以被认为是使 TCP 连接不那么自私的方法;也就是说,它试图考虑到它所操作的互联网上其他用户的存在。虽然单个连接本身无法解决整个互联网的拥塞,但所有设备共同实施这些措施可以减少由 TCP 引起的拥塞。

第一个问题是我们需要知道何时发生拥塞。根据定义,拥塞意味着中间设备——路由器——过载。路由器通过丢弃数据报来响应过载。当这些数据报包含 TCP 段时,这些段无法到达目的地,因此它们未被确认,最终会过期并被重传。这意味着当一个设备发送 TCP 段而没有收到它们的确认时,可以假设在大多数情况下,它们已被中间设备由于拥塞而丢弃。通过检测未确认发送的段的数量,TCP 设备可以推断出自身与 TCP 连接对端之间的网络拥塞程度。

TCP 拥塞处理机制

在获取有关拥塞的信息之后,我们必须决定如何处理这些信息。主要的 TCP 标准 RFC 793 包含很少关于 TCP 拥塞处理问题的信息。这是因为基于这个标准的 TCP 早期版本没有包括拥塞处理措施。这些早期实现的问题导致发现拥塞是一个重要的问题。现代设备使用的措施是在多年中开发的,并最终在 RFC 2001 中记录下来,“TCP 慢启动、拥塞避免、快速重传和快速恢复算法”。

小贴士

关键概念 TCP 流量控制是调节 TCP 设备之间流量流的一个基本部分,但它只考虑两个 TCP 端点的繁忙程度。同样重要的是要考虑任何 TCP 会话建立的网络的拥塞可能性,这可能导致通过丢弃段的不效率。为了处理拥塞并避免不必要地贡献拥塞,现代 TCP 实现包括一系列拥塞避免算法,这些算法改变了滑动窗口系统的正常操作,以确保更有效的整体操作。

RFC 2001 提到了四种算法:慢启动、拥塞避免、快速重传和快速恢复。在实践中,这些特性都是相互关联的。慢启动和拥塞避免是不同的算法,但它们使用单一机制实现,涉及定义一个拥塞窗口,该窗口限制传输的大小,其大小根据拥塞水平增加或减少。快速重传和快速恢复作为对实现慢启动和拥塞避免机制的更改来实现。

以下部分提供了这些算法工作原理的简化总结。我的目标仅仅是帮助您大致了解 TCP 中如何处理拥塞。

注意

拥塞处理是一个相当复杂的过程。如果您想了解更多,RFC 2001 包含了技术细节,展示了每个算法在每个设备中的实现方式。

慢启动

在 TCP 的原始实现中,一旦两个设备之间建立连接,它们就可以各自“尽情地”发送数据段,只要另一个设备的接收窗口还有空间。在一个繁忙的互联网中,大量新流量的突然出现可能会加剧现有的拥塞。为了缓解这种情况,现代 TCP 设备在最初发送数据段的速度上受到限制。

每个发送者在最初都限制只能发送等于一个完整数据段大小的数据量——即等于连接的 MSS 值。每次收到确认后,设备可以发送的数据量会增加另一个完整数据段的大小。因此,设备在发送数据量方面开始较慢,发送的数据量逐渐增加,直到达到完整的窗口大小或检测到链路上的拥塞。在后一种情况下,将使用下面描述的拥塞避免功能。

避免拥塞

当在 TCP 链路上检测到潜在的拥塞时,设备会通过降低发送数据段的速度来响应。使用一种特殊的算法,允许设备在发生拥塞时快速降低发送数据段的速度。然后,设备使用慢启动算法逐渐增加传输速率,以尝试在不发生拥塞的情况下最大化吞吐量。

快速重传

我们在查看 TCP 数据段重传时已经看到,当设备接收到非连续顺序的数据段时(即乱序),接收方只会确认连续接收到的那些。确认号字段将指定它期望接收的下一个字节的序列号。因此,在该节给出的示例中,数据段 1 和 2 被确认,而数据段 4 没有被确认,因为数据段 3 没有被接收。

当 TCP 设备接收到乱序数据段时,它可以简单地通过重复说明它正在等待特定的字节数来响应确认。因此,当示例中的客户端收到数据段 4 而不是数据段 3 时,它可以发送一个确认说:“我正在等待数据段 3 的第一个字节。”

现在,假设这种情况反复发生。服务器没有意识到数据段 3 已丢失,因此发送了数据段 5、6 等等。每次接收到数据段时,客户端都会发送一个确认,指定数据段 3 的第一个字节数。最终,服务器可以合理地得出结论,数据段 3 已丢失,即使其重传计时器尚未到期。

快速重传功能规定,如果收到三个或更多这样的确认,都表示“我想要从字节 N 开始的段”,那么很可能从字节 N 开始的段已经丢失,通常是因为它由于拥塞而被丢弃。在这种情况下,设备将立即重传丢失的段,而不经过正常的重传队列过程。这通过消除会暂停链路上有效数据流的延迟来提高性能。

快速恢复

当使用快速重传来重发丢失的段时,使用该功能的设备执行拥塞避免,但不会使用慢启动来再次增加传输速率。这样做的原因是,由于发送方收到了多个确认,所有这些确认都表示收到了乱序的段,这表明两个设备之间的段流中已经移除了几个段。出于效率的考虑,因此,传输速率可以比其他方式发生拥塞时更快地增加。这比在快速重传后使用常规的拥塞避免算法提高了性能。

第三部分-1. 命名系统与 TCP/IP 命名注册及名称解析

TCP/IP 应用层协议

OSI 参考模型用于描述网络协议和技术的架构,并展示它们如何相互关联。在第五章(第五章

第五十一章

第五十二章

第五十三章

第五十四章

第五十五章

第五十六章

第五十七章

人类和计算机在几十年前开始相互打交道。总的来说,人类(和女性!)与机器的关系相当不错,这反映在计算机曾经只是技术人员的领域,而现在已经成为主流的事实上。然而,有些领域人类和计算机根本无法达成共识。其中之一就是我们处理信息的方式。

计算机最适合处理数字,而大多数人更喜欢不处理数字。这种根本性的差异给网络技术的设计者带来了问题。从技术角度来看,使用简单的数字标识符设计网络和互联网的寻址方案是合理的,因为这样可以简化并提高效率。不幸的是,使用数字地址来识别计算机对人类来说很麻烦,随着网络设备数量的增加,这种情况变得更加麻烦。为了解决这个问题,技术人员开始努力工作,并为网络发明了名称系统。这些机制允许计算机继续使用简单、高效的数字地址,同时让人类指定名称来识别网络设备。

本部分包括八个章节,解释了网络名称系统背后的理论和实践。第一章描述了名称系统的动机以及它们工作背后的重要概念和技术。第二章介绍了 TCP/IP 上的名称系统,并对简单的主机表名称系统进行了简要描述。

剩余章节详细介绍了非常重要的域名系统(DNS)。第三章提供了 DNS 的概述,包括对其特性和组件的描述。第四章讨论了 DNS 命名空间和架构,第五章涵盖了 DNS 名称注册过程,包括分层权限和管理。第六章描述了 DNS 名称服务器以及它们在解析调用时如何表示、管理和提供数据。第七章描述了 DNS 客户端,称为解析器,它们如何启动解析以及解析过程中涉及的步骤。最后,第八章通过查看这些单元之间的消息交换,并描述消息、资源记录和 DNS 主文件的格式,将有关名称服务器和解析器的信息联系起来。本章还简要介绍了对 DNS 所做的更改,以支持互联网协议(IPv6)的新版本及其更长的地址。

注意,尽管缩写DNS通常代表域名系统,但你有时也会看到S代表其他单词,特别是服务服务器。此外,一些文档将这个名称系统称为the DNS。大多数人只是说DNS,不带定冠词,这也是我在这里遵循的惯例。

一组相关的 TCP/IP 实用工具,称为nslookup、hostdig,可以被管理员用来查询 DNS 名称服务器以获取信息。它们用于各种目的,包括手动确定主机的 IP 地址、检查为 DNS 名称维护的特定资源记录,以及验证名称解析功能。你可以在第三部分-10 中找到更多关于这些实用工具的信息。

第五十章 名称系统问题、概念和技术

无标题图片

可以将名称系统视为网络协议栈的使节。正如政治使节擅长使用多种语言并确保那些可能以不同方式看待世界的人之间良好沟通一样,名称系统弥合了计算机喜欢使用的数字地址和人类更偏好的简单名称之间的鸿沟。

在查看具体的名称系统之前,讨论它们的一般性是有意义的。这将帮助你理解为什么这些系统很重要,以及所有名称系统(无论其具体实现如何)背后的概念。

我以对名称系统的概述和讨论其为何被创造开始本章。然后,我讨论名称系统的三个主要功能:名称空间、名称注册和名称解析。接着,我扩展了这个功能概述,说明了名称空间和架构是如何工作的,名称注册和管理背后的问题,以及最后,名称解析技术和解析过程中的实际问题。

本章介绍了名称系统,但不讨论具体的名称系统。我喜欢用例子来解释概念,为此,有时会提到 TCP/IP 域名系统(DNS)。然而,你不需要熟悉 DNS 就能理解本章内容。

名称系统概述

人类与计算机之间几个重要差异之一是我们处理信息的方式。计算机处理数字,而很少有人喜欢这样做。当我们观察标识符或地址如何分配给网络设备时,这种区别变得尤为重要。

用于寻址的符号名称

对于计算机来说,给网络上的每个设备分配一个数字并使用这些数字来移动信息没有任何问题。如果你的电脑被分配了一个像 341,481,178,295 这样的数字,并且你网络上的所有其他机器也是如此,那么你的电脑会非常高兴。你可以发出这样的命令:“将这个文件发送到机器 56,712,489,901。”然而,大多数人不想以这种方式使用网络。这些长而神秘的数字对他们来说没有任何意义。他们希望告诉他们的机器:“将这个文件发送到乔的电脑上,”或者“在销售部门的彩色激光打印机上打印这个文件,”或者“检查 CNN 网站上最新的头条新闻。”

这种差异导致了名称系统的开发。这些技术允许网络上的计算机同时拥有一个传统的数字地址和一个更用户友好、人类可读的名称,由字母、数字和其他特殊符号组成。有时被称为“符号名称”,这可以作为设备寻址的替代形式。名称系统负责管理此系统的必要功能,包括确保名称唯一性、从名称到数字的转换以及管理名称和数字列表。

悖论:名称系统既是必需的又是非必需的

名称系统有趣的地方在于,它们对网络来说极其重要,但与此同时,它们对于网络的运行往往并不是严格必要的。这种看似矛盾的悖论再次源于人类与计算机之间的差异。计算机只需要数字寻址方案,而不需要分配给它们的名称。因此,没有名称系统,计算机和网络仍然可以工作,但人们使用它们会变得非常困难!

这种情况的例子最容易被看到,当一个问题使提供互联网命名服务的 DNS 的一部分无法运行时。技术上讲,使用互联网的大部分内容并不需要 DNS,因为所有通信都使用 IP 地址。这意味着尽管你通常可以通过www.cnn.com访问 CNN 的网站,但你也可以只使用 IP 地址 64.236.16.20。

问题在于,在阅读这篇文章之前,你可能不知道 CNN 网站的 IP 地址,对其他使用该网站的几乎每个人来说也是如此。此外,你可能还想检查的不仅仅是 CNN 网站,可能是 1、2 或 20 个其他新闻网站。记住互联网上成千上万个不同网站中的数字对即使是少数人来说也是困难的,所以每次你想访问资源时,你都需要手动查找其地址,如图图 50-1 所示。

无命名系统时的互联网访问 当没有命名系统时,用户必须知道他们想要在互联网上访问的任何设备的地址。由于我们大多数人的数字记忆有限,这意味着每次访问之前都必须进行低效、繁琐的手动地址查找。

图 50-1. 无命名系统时的互联网访问 当没有命名系统时,用户必须知道他们想要在互联网上访问的任何设备的地址。由于我们大多数人的数字记忆有限,这意味着每次访问之前都必须进行低效、繁琐的手动地址查找。

相比之下,记住资源的名称要容易得多。有了命名系统,你只需输入设备的名称,命名系统就会将其转换为地址,如图图 50-2 所示。这就是为什么即使网络技术本身不需要,命名系统仍然如此重要的原因。事实上,对像 DNS 这样的命名系统的依赖如此之大,以至于许多人甚至没有意识到他们可以在他们的网络浏览器中输入 IP 地址!

使用命名系统的互联网访问

图 50-2. 使用命名系统的互联网访问

当一个互联网配备了一个命名系统时,用户不再需要知道设备的地址来访问它。他或她输入名称,命名系统会自动将其转换为地址,就像一个计算机化的旋转索引卡,如下所示。然后命名系统将地址传递给客户端软件,该软件使用该地址来访问请求的资源,就像用户直接输入它一样。

决定命名系统必要性的因素

更普遍地说,命名系统的重要性在很大程度上取决于它所使用的网络的特征。以下是在确定命名系统需求时需要考虑的三个主要问题:

网络规模 在一个非常小的网络和只有几台计算机的情况下,让人类用户记住这些机器的数字地址至少是可行的,如果不是理想的话。例如,一个有两三台机器的小型家庭网络在理论上并不真的需要一个命名系统。然而,如果你有成千上万或数百万的设备,命名系统就变得至关重要了。

地址大小和复杂性 数字地址方案越复杂,或使用的数字越大,人类记住这些数字就越困难。这使得对于这些地址的用户来说,拥有一个命名系统变得尤为重要。

用户基础规模和技能 在网络早期,只有少数技术精湛且受过良好训练的工程师使用它们,这些人有时只是记住了他们每天使用的机器的数字。在拥有成千上万或数百万普通用户的现代网络中,期望普通人记住设备号码是不合理的。

小贴士

关键概念 网络命名系统之所以重要,是因为它们允许设备被分配有效的数字地址,同时仍然允许人类使用更容易记住的名称来访问它们。随着网络规模、地址或用户基础的增大,命名系统变得更加重要。当用户基础在技能或经验方面有限时,它们也变得更加必要。

观察这些问题,我们可以看到,当今网络的趋势都是朝着增加命名系统重要性的方向发展。我们的网络,无论是私有的还是公共的,都在不断增长,使用它们的人数也在增加,包括更多没有技术背景的人。我们也在从小的地址转向更大的地址。最好的例子是即将到来的 IP 变化。虽然 DNS 对于 IPv4 中使用的 32 位地址很重要,但它对于处理 IPv6 的巨大 128 位地址来说甚至更重要(见第二部分-4"))。

基本命名系统功能:命名空间、名称注册和名称解析

虽然数字地址和符号名称之间的差异对网络设备的用户来说非常显著,但重要的是要记住,数字和名称实际上都服务于相同的基本目的:设备识别。即使我们使用名称系统使设备更容易访问,计算机本身仍然通常需要使用底层的数字标识符。本质上,每个设备最终都会拥有(至少)两个标识符:一个数字 和一个名称

设备最终拥有多个标识符的事实使得人们和他们的机器可以使用他们偏好的识别方法。然而,这意味着必须有一种管理名称分配和它们之间转换的方法。名称系统不仅涉及在计算机上贴上名称,而必须是一个完整的 系统,允许人类使用名称,而设备继续使用数字标识符。

在最高层次上,名称系统必须处理三个基本功能:

命名空间定义 命名系统为它运行的联网系统定义了一个 命名空间。命名空间,有时也称为 命名架构,描述了命名结构和使用规则。它还定义了单个设备名称与系统中其他设备名称之间的关系,以及如何确保没有无效的名称会导致整个系统出现问题。

名称注册 为了实现名称系统,必须为网络上的每个设备分配一个名称。像任何寻址系统一样,除非系统中的每个名称都是唯一的,否则名称系统无法正常工作。我们需要某种方式来管理名称的分配,以便结果是有意义的。将特定名称与特定设备链接的过程通常称为 名称注册

名称解析 尽管人类喜欢符号名称,但计算机通常对它们用处不大。有必要定义一种机制,通过该机制可以将设备的符号名称转换为它的数字地址。这个过程通常称为 名称解析

命名空间更多的是一种描述性功能,它定义了系统中的命名是如何工作的。名称注册和解析是更主动的功能,每个名称系统都包括一个或多个特定程序,用于执行这些任务。在某种程度上,名称注册和解析是相互补充的,因此某些注册技术通常与特定的解析方法相关联。反过来,可能的注册和解析方法的类型取决于命名空间,特别是其架构。这些关系以简化的形式在图 50-3 中展示。

命名系统功能

图 50-3. 命名系统功能

此图显示了名称系统三个主要功能之间的关系。名称空间定义了名称系统的结构和创建名称的规则。名称空间用作名称注册方法的依据,该方法定义了名称和地址之间的映射。当用户想要通过名称访问设备时,使用名称解析方法来咨询名称空间,确定与名称关联的地址,然后将名称转换为地址。注册和解析的过程可能非常简单,也可能相当复杂,这取决于所使用的名称系统类型。简单的名称系统在操作上主要手动进行,易于理解,最适合用于较小的网络。较大的、更复杂的网络和互联网需要更复杂的注册和解析方法,这些方法涉及较少的管理员干预,并且随着网络中新机器的增加而更好地扩展。

虽然名称注册和名称解析在最高级别上作为功能工作,但它们可能更好地被视为功能的集合。名称注册必然与名称系统管理和维护等问题相关联,而理解解析需要我们查看效率性和可靠性领域的一些重要实现问题。本章的其余部分通过更详细地考虑这三个功能中的每一个来扩展这个概述。

提示

关键概念 名称系统由三个理论上的高级功能组成:名称空间,它描述了名称的创建和组织方式;名称注册技术,它用于建立名称和地址之间的关系;以及名称解析方法,它负责将名称转换为地址。

名称空间和名称架构

名称系统的核心思想是提供一种使用符号名称识别设备的方法。像任何识别机制一样,在可以使用之前,我们必须定义识别将如何执行的方式。数字寻址方案(如 IP 地址)有关于地址创建的规则,并将地址分配给每个设备,这些地址来自它们的地址空间。以类似的方式,名称系统中的设备从系统的名称空间中获得名称。

名称空间功能

在名称系统的三个主要组成部分中,名称空间是最抽象的。它也是系统最基本的部分,因为它实际上描述了名称是如何创建的。名称空间在名称系统中定义了几个方面:

名称大小和最大名称数量 名称空间指定了组成名称的字符(符号)数量。它还定义了系统中可以出现的最大名称数量。

名称规则和语法 名称空间指定了在名称中允许使用的字符和符号。这用于允许为所有设备选择合法的名称,同时避免非法名称。

命名架构和语义 每个命名空间使用特定的架构或结构,这描述了名称是如何构建和解释的。

名称大小和名称语法的概念相对简单。名称架构可能是名称系统最重要的区分特征。因此,命名空间有时甚至被称为名称架构。名称空间的架构决定了名称是否被分配和使用为简单的无结构符号集,或者具有更复杂的内部结构。在后一种情况下,名称空间还必须定义特定名称的元素之间是如何相互关联的。

理论上,可能存在许多不同的命名架构。在实践中,大多数可以分为两类:平面和层次。

平面命名架构(平面命名空间)

在平面命名架构中,名称被分配为一系列符号,这些符号被解释为一个单一的、整体的标签,没有任何内部结构。任何名称与其他名称之间没有明确的关系。

这种架构的一个例子是,计算机被分配无结构的名称,如工程工作站 1 或乔安妮的 PC,如图 50-4 中的示例所示。

平面命名架构(平面命名空间)此图展示了平面命名架构的一个示例。没有结构来组织名称或规定它们必须如何构建。逻辑上,每个设备都是其他每个设备的对等体。

图 50-4. 平面命名架构(平面命名空间)此图展示了平面命名架构的一个示例。没有结构来组织名称或规定它们必须如何构建。逻辑上,每个设备都是其他每个设备的对等体。

层次命名架构(结构化命名空间)

在层次命名架构或结构化命名空间中,名称是一系列符号,但这些符号使用特定的和清晰的架构进行分配。每个名称由相互关联的离散元素组成,通常通过使用层次父子语义。在许多不同环境中,有许多使用这种类型层次结构的命名架构。例如,考虑一个大公司如何设置组织结构图并命名组织中的高管和官员。一个假设的层次命名架构示例如图图 50-5 所示。

分层名称空间最著名的现实世界例子是 DNS(名称空间)的名称空间(见第五十三章),它使用由点(或)分隔的文本标签来形成内部结构。系统中的所有名称都组织成一个结构,并且可以通过查看其名称来确定特定设备在结构中的位置。例如,www.tcpipguide.com指的是TCP/IP 指南的万维网服务器,该服务器位于商业公司(.com)的伞下。

分层名称架构(结构化名称空间)

图 50-5. 分层名称架构(结构化名称空间)

此图包含与图 50-4,相同的设备,但它们是使用分层、结构化的名称架构排列的。在这种情况下,组织选择首先按设施位置来结构化其设备名称,然后按部门。每个名称都以类似 USA-Service-或 EU-Mfg-的某种东西开头。这通过提供对设备命名的本地控制而无需担心冲突,带来了直接的好处。如果有人名叫 John 被雇佣到美国销售团队,他的机器可以被命名为 USA-Sales-John,而不会与欧洲销售团队(EU-Sales-John)拥有的 John 的机器发生冲突。这种结构还使得立即知道设备在组织中的位置变得更加容易。

比较名称架构

正如您将在本章接下来的两个部分中看到的那样,名称空间的架构与名称的注册和管理方式密切相关,最终与它们的解析方式密切相关。平面名称空间需要一个某种形式的中央权威来为系统中的所有设备分配名称以确保唯一性。分层名称架构非常适合更分散的注册方案,允许许多权威机构共同参与注册和管理过程。

所有这些都意味着这些架构的优缺点并不是一个很大的谜团。平面名称空间具有简单性和创建简短且易于记忆的名称的能力,如图 50-4 所示。然而,由于确保每个名称都是唯一的困难,它们在包含数百或数千台机器的名称系统中扩展性不好。例如,如果有四个人都叫约翰,他们都试图将他们的电脑命名为约翰的 PC,会发生什么?另一个问题是集中管理这些名称所需的开销。

相比之下,分层名称空间更复杂、更灵活,因为它们允许使用逻辑结构来分配名称。我们可以使用反映我们组织结构的分层结构来命名我们的机器,例如,并授权组织的不同部分管理名称空间的一部分。只要每个部门都有独特的名称,并且这个独特的部门名称是每个机器名称的一部分,我们就不必担心在整个组织中分配的每个名称都是唯一的;它只需要在部门内部是唯一的。因此,我们可以有四台不同的机器,它们的名称由部门名称和约翰组成,如图 50-5 所示。这种灵活性的代价是需要更长的名称和在名称注册和解析中更多的复杂性。

小贴士

关键概念 最常见的两种名称架构类型是平面名称空间和分层名称空间。平面名称空间中的名称都是对等的,没有关系。在分层架构中,使用多级结构以特定方式组织名称。平面系统更简单,对于小型网络来说是令人满意的。分层名称空间更灵活、更强大,更适合大型网络和互联网。

名称注册方法、管理和权限

显然,为了实施我们的名称系统,我们需要一种方法来为将使用该系统的每个设备分配名称。正如名称系统有一个与寻址系统的地址空间相当的名字空间,它也必须实施一套规则和程序来分配名称,类似于寻址系统分配地址的方式。这被称为名称注册

名称注册功能

通常,名称注册包括以下四个概念和任务:

名称分配和唯一性保证 名称注册过程的核心任务是给设备分配名称。像所有识别方案一样,名称注册的一个关键要求是确保每个名称都是唯一的。重复的名称会导致歧义,并使得一致的名称解析变得不可能。

中央注册权威机构指定 确保名称的唯一性需要有人负责名称分配过程。这个中央注册权威机构可能是一个维护包含名称的文件的单一个人,或者是一个负责整个名称注册过程的组织。该机构还负责解决注册过程中可能出现的任何问题和冲突。

注册权威机构委派 在较小的名称系统中,中央注册权威机构可能负责所有设备的实际注册过程。在较大、分层的名称系统中,集中处理这一过程是不切实际的。相反,中央注册权威机构将名称空间划分,并将注册不同部分名称的权力委派给下属组织。这需要制定并实施委派政策。

分层结构定义 当使用分层名称空间时,中央权威机构负责定义结构的外观。这反过来又决定了如何在层次结构的各个部分注册名称,当然,这也影响了权力的委派。

名称注册过程的复杂性在很大程度上取决于整个名称系统的大小和复杂性,特别是名称空间的架构。在简单使用平面名称空间的名称系统中,注册通常通过单一权威机构完成。没有结构,通常也没有权力委派,因此注册过程相对简单。对于分层名称系统,名称注册与用于名称的层次结构紧密相关。

分层名称注册

中央权威机构定义了层次结构的结构,并决定如何将层次结构划分为可以由其他权威机构独立管理的子集。这些权威机构反过来也可能将它们名称空间的部分子集委派出去,从而创建一个灵活且可扩展的系统。

能够委派名称注册的权限是层次结构名称空间最强大的好处之一。例如,在 DNS 中,中央权威机构负责整个名称注册。这个中央权威机构负责决定哪些顶级域名——例如.com、.edu、.info 和.uk——被允许存在。管理全球层次结构中这些子集的权限随后被委派给其他组织。这些组织根据自身情况继续划分层次结构的过程。最终,每个组织都能够独立决定如何为其内部系统命名;例如,IBM 可以在 ibm.com 名称下以任何它认为合适的方式注册名称。

名称注册方法

实际注册过程通常有几种常见方法。这些包括表名注册、广播名称注册和数据库注册。每种方法都有其优势和劣势,再次强调,有些更适合扁平名称空间,而有些则更适合层次结构名称空间。

表名注册

使用表名注册,名称分配由管理员在表中维护。当需要添加、删除或更改名称时,表格会被编辑。

这种技术通常与小型、扁平名称空间名称系统相关联。它具有与扁平架构相同的优点和缺点:简单且易于实现,但扩展性不佳,不适合较大的系统。对于十几台机器,有人编辑名称注册表是可行的;但对于成千上万的机器来说,则不可行。它也不利于存在多个权威机构的层次结构系统,因为表格需要保存在一个地方。

在较大的互联网中,表格可能被用作其他更复杂注册技术的一种辅助手段。

广播名称注册

广播名称注册是一种试错技术。一个想要使用特定名称的设备会向网络上的所有其他设备发送消息,询问是否有人已经在使用它。如果是这样,它会选择一个不同的名称。如果不是,该名称就被认为是已注册的,然后可以开始使用。

这种技术比使用表格更复杂,但它仍然限于在相对较小的系统中使用。尝试向成千上万的系统广播是不切实际的,并且这种方法不能在互联网上使用,因为在互联网中无法向每个网络设备广播。

数据库注册

使用数据库注册,维护一个名称分配的数据库。要注册一个名称,必须向数据库提交请求以添加名称分配。如果名称系统的权限完全集中,则数据库将集中并由该权限机构维护。如果层次结构的一部分权限被委派,则使用分布式数据库进行注册,每个权限机构维护描述其层次结构部分的数据库部分。

这是最复杂的技巧,通常与像 DNS 这样的分层名称系统相关联。它具有几个优点,包括灵活性、可靠性和维护工作的分布。其主要缺点是复杂性。

提示

关键概念 名称注册是将名称与名称系统中的地址链接起来的过程。它包括中央注册机构授权和委派以及名称空间结构管理等活动。最常见的名称注册方法,按能力递增和复杂性递增的顺序排列,是手动表维护、广播注册和数据库注册。

名称解析技术和元素

正如我们在本章前面讨论的那样,使用名称系统为计算机创建了两个并行识别系统:机器使用的数字和人们使用的名称。名称系统的任务是整合这两个方案。名称注册允许人类指定哪些机器使用哪些名称。然而,这只是一个过程的一半;我们还需要一种方法,让机器能够将人类给它们的名称翻译成它们实际用于通信的数字地址。这被称为名称解析

名称解析,有时也称为名称翻译、映射绑定,是名称系统最知名的部分,因为它是在这里发生名称系统大部分“重活”的地方。名称空间通常只设置一次,名称注册很少发生——仅在必须创建或更改名称时发生。相比之下,名称系统的每个用户每天都会指示他们使用的机器执行名称解析,数百次甚至数千次。

名称解析方法

可以使用几种不同的技术进行名称解析。此功能的实现方式在很大程度上取决于其他两个名称系统功能:名称空间和名称注册。正如你可能想象的那样,具有简单名称注册方法的简单名称系统通常会使用简单的解析方法。具有分布式数据库的复杂分层系统在名称解析方面需要更多的复杂性。有三种常见的名称解析方法:表名称解析、广播名称解析和客户端/服务器名称解析。

基于表的名称解析

当需要执行解析时,设备会咨询用于基于表的名称注册的表。该表告诉设备如何将需要联系的主机的名称转换成地址。

这种技术显然对应于表名称注册。这是三种方法中最简单且功能最弱的一种。表名称解析仅适用于非常小的名称系统中的独立使用,但它也可以作为其他方法的补充。

广播名称解析

当设备需要解析一个名称时,它会广播一个查询,内容如下:“我需要发送到名为 X 的设备。它是谁?”名为 X 的设备回应:“我是 X,我的数字地址是 N。”

这是广播名称注册的补充。它也只能在简单系统中使用,在这些系统中每个设备都能听到广播。使用广播也会造成网络带宽的浪费。

客户端/服务器名称解析

在客户端/服务器名称解析中,服务器被编程为能够响应客户端发送的名称解析请求。这些服务器在请求中查找相关的数字标识符,并在响应中将其发送回去。

这种技术通常与数据库名称注册结合使用。这是最复杂的名称解析方法,但也是最有效率的,也是唯一能够在大型、分布式分层名称系统上真正正常工作的方法。

客户端/服务器名称解析功能元素

客户端/服务器名称解析是大多数大型、现代名称系统使用的方法。客户端/服务器请求/回复解析方法与许多其他协议的功能相似。然而,名称解析的一个独特之处在于,名称解析通常不是由客户端直接调用的。例如,用户很少会说“请解析以下名称。”我们当然也不希望用户每次想要联系设备时都需要手动将名称解析为地址,因为这会很麻烦。

相反,系统通过软件自动接受用户输入的机器名称。软件通过将其传递给 名称解析器 软件组件来解析名称。解析器在名称解析过程中充当客户端。它联系 名称服务器,该服务器响应请求。名称解析器和名称服务器构成了名称解析中的两个主要功能元素。

小贴士

关键概念名称解析可以说是名称系统的主要功能元素中最重要的,因为它是将名称转换为地址的系统部分。名称解析的两个主要组件是名称解析器,它在解析过程中充当客户端,以及名称服务器。三种主要的名称解析方法——基于表格、广播和客户端/服务器——与名称注册的表格、广播和数据库方法紧密对应。

在用于分层名称系统的分布式数据库中,可能需要多个请求,因为名称服务器只会包含某些机器的信息,而不是所有机器。解析器遵循一个特殊程序来遍历层次结构,直到找到包含所需信息的服务器。再次强调,DNS 的名称解析是这种方法的最佳例子。

效率、可靠性及其他名称解析考虑因素

如前所述,名称解析的主要功能是允许人类使用名称来识别设备,然后将这些名称转换为数字,以便计算机可以使用这些数字。这个基本任务在概念上相当简单,但在实现上可能会变得相当复杂。原因是名称解析与其他名称系统执行的任务如此不同的关键特性:它执行的频率。

名称注册很少进行,但名称解析非常频繁。如果你考虑一个有数千用户运行各种应用程序的大型互联网,每天必须解析数百万个名称。现在,考虑像互联网这样的系统,它每天必须处理数十亿客户端/服务器请求和回复!确保这些系统能够正常工作,我们需要做的不仅仅是实现一个解析过程;我们必须添加确保解析尽可能有效进行的设施。

效率考虑

名称解析的第一个主要问题是效率。名称解析会消耗系统资源,尤其是在需要发送请求和回复的解析技术中。这意味着我们希望尽可能减少解析的次数。现在,考虑许多人会频繁地重复访问相同的机器。例如,如果你第一次访问名为www.thisisasite.com的网站,你的系统将需要解析该名称。在该网站的首页加载后,如果你点击该网站上的另一个页面链接,该页面也将以相同的名称找到:www.thisisasite.com。因此,如果需要再次解析该名称将是浪费的。

为了避免这种情况,名称系统几乎总是包括某种形式的缓存能力,这允许设备记住最近的名字解析,并在一段时间内保留从名称到地址的映射。每当需要解析一个名称时,都会首先检查缓存,然后再通过正式的解析过程。缓存的使用消除了绝大多数实际名称解析请求,否则这些请求是必需的。

缓存的缺点是它需要一些自己的系统资源,并且会增加系统的复杂性。一个问题是决定在缓存中保留数据的时间长度。如果我们保留得太短,就会产生额外的、不必要的解析请求。如果我们保留得太长,如果机器的名称分配发生变化,映射可能会变得过时。这些都是一个复杂的名称系统必须处理的问题。一个典型的解决方案是允许每个名称注册指定有关该名称到地址链接的信息可以缓存多长时间。

可靠性考虑

在效率之后的主要关注点是名称解析的可靠性。正如我在本章前面所说的,对于计算机来说,拥有一个名称系统并不是严格必要的,但对于用户来说,尤其是在像互联网这样的大型网络中,它非常重要。

虽然有一个单一的中心位置维护关于名称系统的所有信息可能会使管理变得简单,但它创建了一个危险的单点故障。如果存储信息的设备发生任何问题,整个名称系统都会失败。现代名称系统采用冗余来防止整个系统依赖于任何特定设备进行解析。在客户端/服务器系统中,一个典型的方法是在不同位置(或连接到不同的网络)拥有多个服务器,这些服务器可以响应名称解析请求。

小贴士

关键概念 由于名称解析是名称系统中使用最频繁的部分,因此我们必须在这里仔细注意实现问题。最重要的两个问题是效率和可靠性。效率对于每天在大系统上执行成千上万或数百万次解析至关重要。可靠性是一个考虑因素,因为名称系统的用户很快就会依赖它,因此我们必须确保它是健壮的。

其他考虑因素

一些名称解析系统中的一个可选功能是负载均衡。当正确实现时,负载均衡允许一个名称映射到多个底层地址。这允许发送到特定虚拟设备的请求实际上被导向多个不同的实际物理设备,从而在多台机器上分散负载。这个功能的常见用途是用于经常访问的非常受欢迎的网站。

最后,虽然名称解析显然是为了允许将名称映射到地址,但在某些情况下,我们可能希望朝相反的方向进行:给定一个数字地址,找到与之对应的名称。这个过程称为反向解析,类似于拥有一个电话号码并试图找到属于该号码的个人信息或公司。正如我们无法轻易通过传统的电话簿找到匹配电话号码的名称(我们需要扫描每一页以查找号码),反向解析需要名称系统提供特殊支持。如果名称系统数据分布在多个服务器上,这一点尤为重要。

第五十一章。TCP/IP 名称系统概述和主机表名称系统

无标题图片

TCP/IP 已经足够流行,以至于许多人——甚至不是极客的人——都相当舒适地使用它的数字标识符(IP 地址)。即便如此,使用名称比使用数字要容易得多,而且名称的记忆性也更强。我们还可以考虑,当在更大的网络上使用时,名称系统变得更加重要,而 TCP/IP 被用来实现互联网,这是世界上最大的互联网。拥有一个好的名称系统对于互联网的运行至关重要,因此,已经成为 TCP/IP 整体的一个重要元素。

在本章中,我首先回顾了 TCP/IP 中主机名称的使用历史以及其名称系统的早期发展。然后,我描述了简单的主机表名称系统,这是在协议集中首次使用的。我讨论了为什么主机表被域名系统(DNS)所取代,以及即使在今天,它们也可以用来补充 DNS 功能。

小贴士

背景信息 本章假设您已经熟悉了上一章中解释的名称系统的一般概念和问题

TCP/IP 主机名称和名称系统简史

在上一章中,我描述了一个有趣的悖论:尽管名称系统对于网络系统的运行并不是严格必要的,但它们使人们使用网络变得如此容易,以至于被认为是大多数网络的一个基本组成部分。没有比在 TCP/IP 中名称系统的发展历史中更好的证据了。

开发第一个名称系统:ARPAnet 主机名称列表

TCP/IP 协议集中名称系统的发展历史实际上可以追溯到在传输控制协议(TCP)和互联网协议(IP)本身被创造之前很久。在 20 世纪 60 年代末和 70 年代初,当互联网的前身,被称为ARPAnet,正在开发时,它使用了较老的联网协议,这些协议今天与 TCP 和 IP 的功能相同。

与今天的标准相比,ARPAnet 非常小,最初只包含几台机器,被称为主机,就像 TCP/IP 机器今天通常被称为一样。地址方案也很简单,仅由每个主机的计算机号和端口号组合而成。只有少数机器名,很容易记住地址,但随着 ARPAnet 发展到几十台机器,这种方案变得不可行。

早在 1971 年,设计 ARPAnet 的工程师们就明显意识到,与数字地址相比,符号名称对每个人来说都更容易操作。他们开始为网络上的每个设备分配简单的主机名。每个站点管理自己的主机表,列出了名称到地址的映射。

自然,ARPAnet 工程师立即认识到每个站点维护可能不一致的主机名列表的危险。由于当时互联网只是一个小的“俱乐部”,他们使用请求评论(RFC)过程本身来记录标准的域名到地址映射。RFC 226,“主机助记符标准化”,是我能找到的第一个显示主机名如何分配的 RFC。它于 1971 年 9 月 20 日发布。

这个初始的命名系统几乎和手动操作一样。随着网络中添加和更改的增加,主机名列表在新的 RFC 中被更新,导致在 20 世纪 70 年代出版了一系列 RFC。每个主机管理员仍然维护自己的主机表,当新的 RFC 发布时进行更新。在这段时间里,主机名的结构仍在讨论中,并且随着新想法的探索和细化,对命名系统的几乎所有方面都进行了更改。

在主机表文件中存储主机名

在 ARPAnet 非常小的时候,这个早期的命名系统运行得很好,但随着互联网的发展,它提出了许多问题。一个问题是在对网络修改做出响应时非常缓慢,因为只有在发布新列表之后,才会将添加和更改输入到设备表中。此外,即使有集中的列表,仍然存在潜在的一致性问题,因为站点管理员可能忘记更新文件或犯打字错误。

第一个改进是将主机名分配的列表变成一个标准的“主”文本文件,该文件由中心管理,可以使用文件传输协议(FTP)等网络协议下载。该文件存储在斯坦福大学的网络信息中心(NIC)。定义和使用此文件的过程在 1973 年 12 月和 1974 年 1 月分别发布的 RFC 606 和 RFC 608 中进行了描述,这两个 RFC 的标题都是“在线主机名”。这些文件还正式指定了 TCP/IP 主机表名称系统的语法,这在本章后面将进行描述。

使用集中管理的主机表一直持续到 20 世纪 70 年代。当 TCP/IP 被开发时,系统得到了维护,并且主机名与 32 位 IP 地址之间的映射被建立。RFC 810,“DoD Internet Host Table Specification”展示了如何为主机表定义与 IP 地址一起使用。它于 1982 年 3 月发布。

超越主机表名称系统,转向 DNS

ARPAnet/Internet 的持续增长表明,简单的主机表名称系统最终将变得难以管理。随着最初几十个,然后是数百个和数千个新主机连接到互联网,一个位于中央位置的单个文本文件根本无法胜任这项任务。

将名称系统迁移到基于域名概念的分层名称系统的想法最早在 1981 年 9 月的 RFC 799,“Internet Name Domains”中提出。在 20 世纪 80 年代初,对这个概念进行了大量的讨论和发展。到 1983 年,一项计划被制定,从平面主机表名称系统迁移到新的域名系统(DNS)。这个名称系统发展的详细历史在第五十二章中概述。

TCP/IP 主机表名称系统

现代互联网的先驱们在早期 ARPAnet 创建包含机器名称和地址的简单文件时,为 TCP/IP 套件创建了第一个名称系统,正如前文所述。这个系统非常简单,最初甚至没有正式指定为名称系统本身。由于文件包含网络主机的名称,将名称与地址关联的过程简单地称为主机名机制。后来,这些文件被称为主机表,因此,这项技术通常被称为 TCP/IP 主机表名称系统

作为一种系统,它极其简单,因为它仅由网络上每台机器上维护的文本文件组成。在 UNIX 系统中,这个文件通常被称为/etc/hosts,而在 Windows 系统中被称为 HOSTS(通常位于主 Windows 目录中)。文件通常以一些注释行开始,然后列出 IP 地址和主机名的配对。一个非常简化的例子(使用现代的表结构,这与原始的主机表格式略有不同)在示例 51-1 中展示。

# Host Database
# This file should contain the addresses and aliases
# for local hosts that share this file.
#
# Each line should take the form:
# <address>              <host name>
#
127.0.0.1                localhost
209.68.14.80             www.pcguide.com
216.92.177.143           www.desktopscenes.com
198.175.98.64            ftp.intel.comHost Table Name Space

示例 51-1. TCP/IP 主机表示例

主机表名称系统的命名空间和架构在理论上来说是扁平的,每个名称都可以采取任何形式,没有任何实际结构。尽管如此,为了保持一致性,最终还是制定了一些关于名称创建的规则,如第五十三章中所述。你将在本章后面了解到,使用主机表也可以支持实现层次名称空间,这意味着名称的创建需要使用该名称空间的规则。

主机表名称解析

主机表名称系统中的名称解析非常简单。每个设备在启动时将主机表读入内存。系统用户可以通过使用名称而不是数字 IP 地址来调用各种应用程序中的名称来引用该主机表中的名称。当软件检测到名称以这种方式使用时,它会将该名称指向设备内部的解析例程,该例程在内存中的主机表中查找名称并返回其地址。不需要任何传输或联系服务器;解析完全是局部的。

主机表名称注册

现在,这里是我应该说出在主机表名称系统中的名称注册同样简单的那部分,对吧?好吧,是的,也不是。从纯粹的技术角度来看,它确实很简单。当名称和相应的 IP 地址被输入到设备的主机表中时,名称就在特定设备上注册了,就是这样。

然而,从管理角度来看,名称注册要复杂得多,这也是使用主机表的主要弱点。每个网络设备都维护自己的主机表,独立于其他设备,通常存储在其本地硬盘上的文件中。这与数据库注册系统(见第五十章中看到的示例),但这并不是一个理想的解决方案。

所有这些原因都说明了互联网的设计者最终放弃了在整个互联网上使用主机表,转而采用了更强大的 DNS。

提示

关键概念 主机表名称系统 是早期互联网上用于实现名称的原初机制。它简单地由一组表组成,包含在每个网络中的每台机器上维护的名称与地址之间的映射。当需要解析名称时,会查阅该表以确定适当的地址。这个系统非常简单,但功能有限,并且不适合大型全球互联网,这就是为什么它最终被 DNS 所取代。

现代网络中使用主机表名称系统

虽然主机表名称系统存在关键弱点,但它并未完全消失。本节中解释了两种情况下这种技术仍然有价值。

小型“岛屿”网络

如果你正在使用 TCP/IP 设置一个小型局域网(LAN),并且不需要你的设备名称被网络外的人访问,那么猜猜看:你拥有某种形式的早期互联网。在这种情况下,主机表系统对你来说就像它在 20 世纪 70 年代的互联网上一样适用。你可以在每个设备上简单地设置主机表并手动管理它们。

只要局域网足够小,定期编辑这些文件不会造成麻烦,这实际上是一个快速有效的命名系统,因为不需要交换消息进行解析。你甚至可以在一台机器上维护一个主文件,并在需要更改时使用脚本将其复制到其他机器上,以节省时间。

补充 DNS 的本地名称映射

尽管现代系统通常使用 DNS 进行大多数名称解析,但它们通常仍然支持使用主机表文件。你可以手动将常见的名称映射输入到这个文件中,即使是全球互联网上的设备也可以。然后,你的系统可以设置为在利用其分配的 DNS 服务器之前先咨询这个列表。

将 HOSTS 文件与 DNS 结合使用允许你手动指定常用网站的映射,这可能由于无需访问服务器而提供轻微的性能提升。由于 HOSTS 文件不对名称施加任何特定的结构,因此自然可以将 DNS 风格的分层名称放入文件中,就像我在示例 51-1 中展示的那样。该文件被加载到内存中,并用于覆盖其中列出的名称的正常 DNS 过程。

当然,然后你必须承受手动编辑文件可能带来的所有潜在维护问题。你必须更新这些文件,因为 DNS 系统中的主机名或地址发生变化。因此,这种将 HOSTS 文件用于由 DNS 服务的网站的第二种用途不如用于本地机器的用途受欢迎。

小贴士

关键概念 尽管主机表名称系统不是 TCP/IP 命名的首选机制,但它仍然在两种情况下使用。第一种是在小型本地 TCP/IP 互联网中实现基本命名系统。第二种是作为 DNS 的辅助工具,它允许在需要时创建手动映射来覆盖 DNS 过程。

第五十二章。域名系统(DNS)概述、功能和特性

无标题图片

创建主机表将计算机名称映射到地址大大提高了早期互联网和实现它的 TCP/IP 协议套件的可用性。不幸的是,尽管主机表名称系统在互联网规模较小的时候运行良好,但它并没有很好地扩展,随着互联网开始增长其规模和复杂性。名称系统必须保留,但必须放弃使用主机表,转而采用一个更新、更强大的系统。

在过去几年里,许多工程师致力于创建一个系统,这个系统能够满足当时 TCP/IP 互联网的需求,同时也能适应未来的需求。新的命名系统基于网络按层次划分成组和子组,名称反映了这种结构。它被设计成以分布式方式存储数据,以促进分散控制和高效运行,并包括灵活和可扩展的名称注册和解析机制。这个新的 TCP/IP 命名系统被称为域名系统(DNS)

我们将在本章中开始对 DNS 的探讨。我首先提供 DNS 的发展、历史和标准的概述,继续在 TCP/IP 名称系统的整体概述中开始的历史。我讨论了 DNS 创建者的设计目标和目的,以帮助您更好地理解设计者试图做什么。然后,我谈论 DNS 的主要组件和它执行的功能,将这些与在名称系统概述部分解释的基本功能联系起来。

DNS 概述、历史和标准

大多数人对尝试记住数字标识符的反感导致了为我们现在所说的互联网的先驱设备快速采用命名系统。在 20 世纪 60 年代和 70 年代初,机器被赋予名称,这些名称被保存在主机表中。TCP/IP 主机表名称系统(在第五十一章中描述 Chapter 51)在多年中运行良好,一个由设备管理员使用的集中维护的主列表确保了网络的一致视图。

不幸的是,这样的系统只有在设备数量较少时才能很好地工作。随着互联网的成长,主机表方法中的许多弱点变得明显,正如我在第五十一章中详细描述的那样 Chapter 51。此外,系统的问题并不是可以通过小改动轻易修复的;问题是结构性的,是主机表整体基本想法的一部分。对于如何在互联网上使用名称,需要一种全新的方法。

早期 DNS 发展和向分层域的转变

TCP/IP 工程师做出的最重要的范式转变是决定将名称系统从使用单一集中式名称列表转变为更加分散的系统。这个想法是在 1981 年 9 月发布的 RFC 799,“互联网名称域”中首次提出的,即在结构化的拓扑中组织名称为

RFC 799 实际上更多地描述了在域之间传递电子邮件消息的机制,而不是域本身。有趣的是,该标准在其讨论中假设域具有平面结构,同时提到了创建层次结构结构的可能性。正是决定采用这种层次名称空间来创建 DNS,才导致了我们今天所知道的 DNS 形式的产生。

在 20 世纪 80 年代初,发布了大量描述 DNS 不同方面发展的 RFC 文档。DNS 历史上的第一个真正里程碑可能是 1983 年 11 月发布的三个初始文档,讨论了 DNS 概念:

  • RFC 881,“域名计划与时间表”,讨论了实施新 DNS 以及如何从较旧的宿主表系统迁移的问题。

  • RFC 882,“域名:概念与设施”,相当详细地描述了 DNS 的概念和功能元素。它包括对名称空间、资源记录以及名称服务器和解析器如何工作的讨论。

  • RFC 883,"域名:实现规范",提供了 DNS 消息和操作的详细细节。

DNS 标准化和初始定义标准

1983 年 11 月发布的三个“域名”RFC 文档在接下来的几个月里被频繁讨论,基本的 DNS 机制被多次修订。随后还发布了几个后续 RFC,更新了 DNS 过渡计划和时间表。最后,在 1987 年 11 月,关于系统操作的协议最终确定,并发布了四篇新的 RFC,首次正式化了 DNS 系统:

  • RFC 1032,“域名管理员指南”,规定了运行域的管理程序和策略。

  • RFC 1033,"域名管理员操作指南",提供了关于如何操作 DNS 服务器的技术细节,包括如何维护 DNS 分布式数据库中的名称部分。

  • RFC 1034,“域名 - 概念与设施”,取代了 RFC 882,提供了 DNS 的介绍和概念描述。

  • RFC 1035,"域名 - 实现与规范",是 RFC 883 的更新,详细说明了 DNS 的工作原理,包括资源记录定义、消息类型、主文件格式以及解析器和名称服务器的实现细节。

这最后两个文档,RFC 1034 和 1035,被认为是 DNS 操作的权威原始规范。虽然它们现在已经很多年了,但它们仍然提供了 DNS 工作原理的基本描述。

随着互联网的发展,包括成千上万个网站,DNS 的重要性也随之增长。如今,大多数人几乎每次使用 TCP/IP 访问互联网时都会使用 DNS。它已经从应用程序的替代寻址形式转变为大多数用户首选的形式。它也是为 TCP/IP 开发的更完整的应用层寻址方案的一个重要组成部分:统一资源标识符(URIs)(在第七十章中描述)。

DNS 名称空间的分层性质使得互联网能够通过使名称的分配和映射变得可管理来增长。权威结构(它定义了谁负责名称空间的部分)也是分层的,这使本地管理员能够控制他们管理的设备名称,同时确保整个层次结构中的名称一致性。使用多个名称服务器和遵循标准消息协议的标准解析技术来分配数据提供了效率和可靠性。随着我们在本章后面的部分更全面地探索 DNS,这些概念将变得更加清晰。

DNS 的发展与重要附加标准

自从 1987 年以来,TCP/IP 和互联网都发生了很大的变化,当然,DNS 也必须做出相应的改变。自 1980 年代末基础文档发布以来,已经编写了许多 RFC,其中大部分进一步阐明了 DNS 的操作,扩展了其功能,或为其定义了新的特性。您可以通过在 RFC 列表中搜索“域名”或“DNS”来找到所有这些内容。这些 RFC 有数十个。以下是一些更有趣的例子:

  • RFC 1183,“新的 DNS RR 定义”,定义了几个新的实验性资源记录类型。其他后续的 RFC 也定义了新的资源记录。

  • RFC 1794,“DNS 对负载均衡的支持”,讨论了 DNS 服务器中为了提高性能的负载均衡。

  • RFC 1995,“DNS 中的增量区域传输”,指定了一个新功能,该功能允许只将区域的一部分传输到辅助名称服务器以提高效率。

  • RFC 1996,“快速通知区域更改(DNS NOTIFY)的机制”,向 DNS 添加了一种新的消息类型,允许主(权威)DNS 服务器告诉辅助服务器主数据库中的信息已更改。

  • RFC 2136,“域名系统(DNS)中的动态更新(DNS UPDATE)”,描述了一种在 DNS 数据库中动态进行资源记录更改的技术(也称为动态 DNS)。

  • RFC 2181,“DNS 规范的澄清”,讨论了在 RFC 1034 和 RFC 1035 中定义的主要 DNS 标准中存在的一些问题以及如何解决这些问题。

  • RFC 2308,“DNS 查询的负缓存(DNS NCACHE)”,指定了负缓存的操作,这是一个允许服务器更有效地维护关于不存在名称的信息的功能。

DNS 适应互联网协议第 6 版

互联网协议第 6 版(IPv6,在第 II-4 部分中介绍 Part II-4"))从 20 世纪 90 年代中期开始开发,并带来了对 DNS 操作进行更改和改进的需求。(尽管 DNS 在高层运行,但它与地址紧密相关,而地址在 IPv6 中已经改变,如第二十五章 Chapter 25 中所述。)允许 DNS 支持 IPv6 所需的修改首先在 RFC 1886,“IPv6 DNS 扩展”中定义,这是介绍 IPv6 基础的一组 RFC 的一部分。从那时起,已经发布了几个后续标准;这些标准在第五十七章中 IPv6 DNS 部分进行了讨论。

本章的其余部分通过讨论其创造者的设计目标和协议的关键特性,提供了对 DNS 及其发展的更全面概述。

DNS 设计目标、目标和假设

正如我们刚才看到的,从讨论 TCP/IP 域名系统的第一个 RFC 到发布描述 DNS 操作的官方标准,所经过的时间超过了六年。对于一个系统的发展来说,这是一个非常长的时间,但这并不令人惊讶。在创建 DNS 时,必须投入大量的思考,以确保它能够满足所有即将对其提出的众多需求。

第一个问题是 DNS 的创造者需要担心如何定义新系统以及如何从旧系统迁移。他们花费了大量时间来弄清楚如何将所有现有的主机迁移到新的 DNS 命名空间,以及如何在它们上实施交换 DNS 信息的新的协议。

DNS 的创造者知道他们正在创建一个新系统,因为旧系统扩展性并不好。他们也知道,如果当时存在的少量主机迁移已经是一个难题,那么如果他们未来需要迁移到另一个新系统,这将会更加困难。这使得 DNS 的关键挑战在于创建一个能够满足互联网需求的系统,不仅是在它被引入的那一天,或下一年,甚至是在十年或更长时间之后。

DNS 设计目标和目标

回到 20 世纪 80 年代,没有人能想到互联网会像过去十年那样增长。DNS 仍然像现在这样工作,是对其设计师技能的证明。这种成功的大部分归功于在系统设计早期所打下的基础。DNS 工程师记录了他们认为在创建过程中的一些主要设计目标,这有助于我们不仅了解 DNS 做什么,还了解为什么这样做。以下设计目标和目标如下:

创建一个全球、可扩展、一致的命名空间 命名空间需要能够跨越包含数百万台机器的大型、全球互联网。它必须提供一种一致且可预测的方法来命名设备和资源,以便它们可以轻松找到。显然,避免名称重复也是必不可少的,即使潜在的冲突可能发生在不同大陆的设备之间。

对本地资源的本地控制 互联网上整个网络和小型互联网网络的管理员需要能够控制他们自己的设备命名。对于需要通过中央权威机构为每个对象命名,或者每个管理员都需要知道其他所有人的网络和机器的名称,这都是不可接受的。

分布式设计以避免瓶颈 DNS 的设计者知道他们需要放弃集中式数据库的想法,转而采用分布式数据存储方法,以避免使用 DNS 时因多设备使用而产生的瓶颈。

应用通用性 该系统需要足够通用,以支持各种应用。例如,它需要支持主机识别、邮件投递和其他功能。

多种底层协议支持 DNS 需要能够内在地支持不同的底层协议。许多人没有意识到,例如,DNS 不仅可以支持 IP 地址,还可以支持其他类型的地址,这仅仅是因为在今天的网络中 IP 如此主导。

硬件通用性 大型和小型计算机都需要能够使用该系统。

在你学习更多关于 DNS 的知识时,请牢记这些目标,它们将帮助你更好地理解为什么选择了某些设计属性。例如,如果我们考虑列出的前两个目标,它们似乎几乎相互矛盾:如果个人管理员能够分配本地名称,我们如何能有一个具有唯一名称的全局命名空间?正如你将看到的,这正是 DNS 分层命名空间的强大之处得以体现的地方。

DNS 设计假设

设计目标告诉我们 DNS 的创造者希望确保新系统能够解决的问题。此外,参与协议实现细节的工程师需要根据某些关于其使用方式的假设做出决策:

数据库规模快速增长 到 1980 年代中期,很明显,DNS 名称数据库将从一个相对较小的规模开始,但会迅速增长。系统需要能够处理这种快速增长。

可变数据修改率 命名数据库中的大部分数据只会偶尔更改,但有些数据会比这更频繁地更改。这意味着在处理数据更改以及如何传达这些更改的信息方面需要灵活性。

可委托的组织责任 名称数据库的部分责任将主要基于组织边界进行委托。许多组织也会运行自己的硬件和软件来实施整个系统的一部分。

名称信息访问的相对重要性 假设 DNS 最重要的任务是提供可靠的名字解析,因此系统被创建得总是允许用户访问名称并确定其地址。在创建系统时的一个关键决策是,即使信息略有过时,也比没有信息要好。如果名称服务器无法提供最新数据来满足请求,它将返回它拥有的最佳信息。

处理缺失信息请求 由于名称数据将被分发,一个特定的名称服务器可能没有用户请求的信息。在这种情况下,名称服务器不应只是说,“我不知道。”它应提供对更有可能提供信息的来源的引用,或者通过发出自己的请求来寻找数据。这导致了几个 DNS 名称解析技术的创建:本地、迭代和递归。

缓存的使用以提高性能 从一开始,就假设 DNS 会大量使用缓存来避免对包含分布式名称数据库部分的服务器进行不必要的查询。

在创建这个系统时,可以说做出了很多假设,正如在开发每个系统时的情况一样。例如,DNS 需要对其数据的确切存储方式、消息传输机制、管理员的角色等做出假设。随着我们逐步了解该系统,您将了解更多关于这些内容。

DNS 组件和一般功能

为了满足其设计者设定的许多目标,DNS 需要大量的功能。它是一个真正的名称系统,强调的是系统,因此比 TCP/IP 早期使用的宿主表名称系统复杂得多。在第五十章中,我将一个功能齐全的名称系统的许多任务分为三个类别。DNS 包括所有这些类别的功能,因此使用这些类别是了解 DNS 工作方式的好方法(参见图 52-1)。

DNS 功能 DNS 由三个主要功能类别组成:名称空间、名称注册和名称服务器/解析。每个类别都包含许多具体任务和责任。

图 52-1. DNS 功能 DNS 由三个主要功能类别组成:域名空间、域名注册和域名服务器/解析。每个类别都包含一系列具体任务和责任。

DNS 域名空间

DNS 使用一个由单一、复杂、多级结构组成的层次化域名空间,系统中的所有名称都适合这个结构。域名空间从单个根开始组织,其中放置了容器(称为 域名)。每个容器可以包含单个设备名称或更具体的子容器。整体结构在某种程度上类似于计算机目录系统从一般到具体组织文件的方式,使用一种可以优化到各种需求的任意结构。使用特定的语法来定义有效名称,并使用特殊术语来描述结构的一部分和识别域名,从根到设备级别。

域名注册(包括管理和权限)

DNS 域名注册用于将单个名称输入到 DNS 分布式数据库中。DNS 使用一种层次化的权限安排,这与层次化的域名空间相辅相成。一个中央权限机构决定了域名空间的整体形状和结构,并处理最高级别的名称注册。权限随后被 委托 给不同的组织来管理域名空间的各个部分。一套通用政策控制注册过程,并处理问题和冲突。

域名解析

DNS 使用了一种强大、分布式、客户端/服务器模式的域名解析机制。这可能是 DNS 设计中需要投入最多关注的地方,以确保其能够扩展以处理每天数百万甚至数十亿次的域名解析请求。

域名解析过程是通过两个基本的软件元素来实现的,这两个元素分别扮演服务器和客户端的角色:域名服务器和域名解析器。

DNS 域名服务器是在硬件服务器上运行的特殊程序,是 DNS 的核心。这些服务器由拥有 DNS 域名空间部分管理权的组织维护。它们包含 资源记录,这些记录描述了该域名空间部分的名字、地址和其他特性。因此,服务器本身被组织成一个类似于域名空间的层次结构,尽管在结构上并不完全相同。

域名服务器的主要任务是接收域名解析请求,并响应请求,要么提供数据库中请求的数据,要么提供指向另一个将导致所需信息的域名服务器的名称。域名服务器还负责数据缓存和其他管理任务,以确保整个系统的有效运行。

名称解析器是名称解析过程中的常规客户端。当用户在网络应用程序中引用一个名称时,该名称会被传递给解析器,解析器向名称服务器发出请求。根据配置,可能需要多个请求,并且可能将几个不同的解析过程组合起来以找到所需的信息。解析器还可能使用缓存或实现其他功能。

注意

解析器和服务器之间的划分基于角色。当我们查看名称解析时,你将看到名称服务器也可能在某些数据交换中充当客户端。参见第五十六章以了解这种看似矛盾的说明

如果这听起来很像我在第五十章中给出的经典命名系统描述,那不是巧合。DNS 被认为是唯一的命名系统,通常与其他大多数命名系统进行比较。如果你理解了这些高级描述,那么你已经知道了 DNS 工作的基本原理。接下来的三章将更详细地探讨这三个功能区域,并将帮助你真正了解 DNS 是如何工作的。

小贴士

关键概念 作为完整的命名系统,DNS 提供了实现三个基本命名系统功能的各种能力。DNS 的命名空间是分层的,并使用具有特定命名规则的多级结构进行组织。DNS 的名称注册系统基于域的层次结构和负责它们的注册机构的概念。DNS 的名称解析也是分层的,它围绕名称解析器名称服务器软件组件之间的交互设计,这些组件咨询 DNS 的资源记录数据库,并使用特殊的消息协议进行通信以回答客户端查询。

第五十三章。DNS 命名空间、架构和术语

无标题图片

命名空间是任何命名系统的最基本部分,因为它定义了名称本身是如何创建的。命名空间告诉我们名称可能采取的形式,并提供了创建它们的规则。最重要的是,它指定了名称的架构——名称本身的内部结构。这反过来又对名称注册和解析的工作方式产生关键影响,使得对命名空间和架构问题的研究成为学习域名系统(DNS)细节的明显起点。

在本章中,我描述了 DNS 名称空间及其结构背后的概念。我首先概述了 DNS 名称空间及其使用的分层架构。然后,我解释了常用来指代名称空间各部分的术语。接下来,我提供了 DNS 标签的正式描述以及创建域名时的官方和非官方规则。最后,我描述了域名规范,并解释了资格的概念以及完全限定名和部分限定名的区别。

DNS 域和 DNS 分层名称架构

名称系统名称空间的最重要元素是其名称架构,它描述了名称是如何构建和解释的。DNS 的架构显然是基于一个称为的抽象概念。这显然是解释 DNS 如何工作的一个很好的起点。

DNS 名称空间中的基本概念:域

“域”这个词的词典定义通常传达了影响范围或控制或统治区域的概念。一个基本的概念是,在不同的语境中,控制或权威可以在许多不同的层面上施加。一个影响范围可能包含较小的范围,而这些较小的范围又可以包含更小的范围。这意味着这样的域自然地按层次排列。

以地缘政治域为例。我们地球上没有集中的“世界政府”,但我们有联合国,它处理全球性问题。在下一级,我们有各个国家。一些国家有州和省这样的划分。更低的级别有县、市镇、社区以及单个住宅或企业。这些“域”在组织上天生就是分层的。

DNS 使用“域”这个词的方式与这非常相似,并且它采用了一种分层结构,其工作方式与地缘政治示例非常相似。在 DNS 中,“域”被定义为单个对象或一组基于某种共同性收集在一起的对象。通常,在 DNS 中,这种共同性是它们都由同一个组织或权威机构管理,这使得名称层次紧密地与 DNS 分层权威结构(见第五十四章)的概念相关联。

注意

术语“域”在网络世界的其他语境中也被使用。最显著的例子是在微软网络中,其中“域”也用来表示一组在共同权威下集合的对象。然而,这两种类型的域在概念层面上完全不同,并且没有超出这一层面的关联

名称的 DNS 分层树结构

我们可以构建一个树状图,将联合国置于顶部,线条指向世界上的每个国家。然后,在美国内部,我们可以画出线条指向每个州。在每个州内部,我们可以画出线条指向每个县,以此类推。结果将是一个倒置的树状结构,如图图 53-1 所示。这被称为树结构

树结构在计算和网络中很常见。例如,树是用于将网络连接成局域网的一种拓扑类型。

对于理解 DNS 来说,树结构的最佳例子是用于在计算机硬盘上存储文件的目录树。根目录位于结构顶部,可能包含命名文件和/或命名目录。每个目录本身可以包含单个文件或子目录,这些子目录又可以包含它们自己的子目录,以此类推。DNS 中的域名结构在概念上以相同的方式排列,但 DNS 处理的是命名对象,通常是像互联网协议(IP)主机这样的设备。

全球分层域架构示例 此图展示了基于政治划分的分层架构示例。联合国是一个代表(在某种程度上)世界上所有国家的伞状组织。它是树的根;在其下方我们发现各个国家。每个国家随后以它选择的方式进一步细分。例如,加拿大有省和地区,而美国有各个州。这些可以以任何数量的方式进一步细分。

图 53-1. 全球分层域架构示例 此图展示了基于政治划分的分层架构示例。联合国是一个代表(在某种程度上)世界上所有国家的伞状组织。它是树的根;在其下方我们发现各个国家。每个国家随后以它选择的方式进一步细分。例如,加拿大有省和地区,而美国有各个州。这些可以以任何数量的方式进一步细分。

最高级别仍然是树的根节点。它包含多个域名,每个域名可以包含单个对象(名称)和/或低级别的域名。低级别域名反过来又可以有更低级别的域名,使得整个树可以具有任意结构。

类似于目录结构,DNS 层次结构命名架构允许从最一般到最具体的组织名称。它还具有完全的灵活性,允许我们以任何我们想要的方式安排结构。例如,我们可以创建一个与图 53-1 中显示的地理政治组织图完全平行的名称系统。我们可以让名称结构的根代表联合国,并为每个国家创建一个域名。然后,对于有州的那些国家,我们可以在那些国家域名内创建州域名。不需要这些域名的较小国家可以直接在国家域名下拥有城市域名。层次结构是灵活的,因为在每个级别,它都可以被赋予一个合适的子结构。

小贴士

关键概念 域名空间被组织成一个类似倒置树的域名层次结构。它在结构上类似于文件系统的目录结构,有一个根节点,包含多个域名,每个域名可以包含子域名以及更多。

重要的是要记住,每个独立的互联网网络都可以有自己的域名空间和独特的层次结构。很多时候,人们会将一个域名空间的概念与域名空间的概念混淆。后者指的是用于全球互联网的 DNS 层次结构,很明显,这值得极大的关注。但这只是无限多种可能结构中的一种可能安排,尽管它很重要。

注意

第五十四章提供了关于互联网 DNS 层次结构的更具体信息。正如您将看到的,地缘政治结构实际上被用来为互联网的一些计算机分配名称,但层次结构的其他部分是不同的

DNS 结构元素和术语

现在我们已经回顾了 DNS 名称空间的基本知识,让我们更详细地看看其结构。同时,我将定义许多用于指代 DNS 域名层次结构各部分的术语。

DNS 树相关术语

正如我在上一节中解释的那样,DNS 名称结构在某种程度上类似于一棵树。在计算机网络中,结构化元素与树的比较是常见的。技术与生物学的区别在于 DNS 树是从上往下生长的,而不是向天空伸展。将树作为类比自然导致在描述 DNS 名称结构时使用几个与树相关的术语,其中一些在图 53-2 中有说明。

这是 DNS 名称结构的概念性顶部。DNS 中的 域包含整个结构。根据定义,它没有名称;它是 的。

分支 一个 分支 是 DNS 层次结构中的任何连续部分。它由一个域及其内部的所有域和对象组成。所有分支都连接到根,就像在真实树木中一样。(是的,如果将根称为 树干 会更好,但显然计算机科学专业的学生没有选修植物学选修课。)

叶子 这是结构中的末端对象;也就是说,一个下面没有任何内容的域。将叶子作为一系列分支的末端的类比是恰当的。

没有特定的术语来指代不是叶子的域。这些有时被称为 内部节点,意味着它们位于结构中间。节点 是拓扑或结构中对象的通用计算机术语。因此,在 DNS 中,每个节点都是一个域,它可能是一个包含附加域和/或对象的内部节点,也可能是一个特定的、有名称的设备。因此,术语 有点含糊,因为它可以指代代表树的一个分支的对象集合,也可以指代一个特定的叶子。

DNS 域相关术语

还有几个类似域名的术语经常用来指代层次结构中不同级别的域名。这些术语也显示在图 53-2:

根域名 这是树的根。

顶级域名(TLDs) 这些是树根下面的最高级域名。它们有时也被称为一级域名

二级域名 令人惊讶的是,这些域名位于顶级域名直接下方。

子域名 在某些上下文中,这个术语仅指位于二级域名直接下方的域名。

DNS 树相关和域名相关术语 DNS 名称空间的顶部是树的根,它没有名称。在根下面可以有任意数量的顶级域名(TLDs)。在每个这些下面可以放置二级域名,然后在这些子域名下面,依此类推。这里也显示了 DNS 中使用的部分树术语。浅色阴影的部分是一个分支;较暗的区域突出显示该分支内的较小子分支。该区域内最暗的节点是该较小分支的叶子。

图 53-2. DNS 树相关和域名相关术语 DNS 名称空间的顶部是树的根,它没有名称。在根下面可以有任意数量的顶级域名(TLDs)。在每个这些下面可以放置二级域名,然后在这些子域名下面,依此类推。这里也显示了 DNS 中使用的部分树术语。浅色阴影的部分是一个分支;较暗的区域突出显示该分支内的较小子分支。该区域内最暗的节点是该较小分支的叶子。

小贴士

关键概念 DNS 名称空间的顶部是。在根下面是顶级域名,在这些顶级域名下面是二级域名,然后是子域名。理论上,可以创建任意数量的子域名级别。分支是 DNS 树中的任何连续部分。叶子是一个在结构中没有下级的域名,它通常代表一个单一设备。

术语子域也可以像这个词本身一样通用。在这种情况下,它仅仅指的是两个域之间的关系,其中子域在结构上位于另一个域之下。这意味着,例如,顶级域可以说成是根域的子域;每个二级域都是顶级域的子域,依此类推。但再次强调,有时子域特指三级或更低级的域。

DNS 相关术语

与 DNS 相关的另一组术语将树结构比作不是一棵活树,而是另一个类比:家谱。这些术语通常用来描述特定域与其周围的其他域或子域之间的关系,因此它们是相对术语。以下常见的家谱相关术语(参见图 53-3))。

父域 这是指在本层级之上的一级域。例如,根域是所有顶级域的父域。

子域 这是指在本层级之下的一级域。因此,顶级域是根域的子域

同级域 这是指在本层级与当前域相同级别且具有相同父域的域。因此,所有顶级域都是根域的同级域;特定顶级域内的所有二级域都是同级域,依此类推。

DNS 名称空间“家谱”此图类似于,但节点被标记以显示 DNS 中有时使用的面向家庭的术语。在这种情况下,名称相对于较暗的阴影所示的内部节点。位于其上方的域是其父节点。同一级别的其他节点是同级节点,而它内部的子域是该节点的子域。

图 53-3. DNS 名称空间“家谱图”此图与图 53-2,但节点被标记以显示 DNS 中有时使用的以家庭为导向的术语。在这种情况下,名称相对于较暗阴影中的内部节点。位于其上方的域名是其父节点。同一级别的其他节点是兄弟节点,而该节点内的子域名是该节点的子节点。

提示

关键概念 在 DNS 名称空间中位于给定域名之上的域名称为其父域名。在同一父节点内同一级别的域名是兄弟节点。子域名被称为该域名的子节点

就像一棵真正的树一样,DNS 名称结构在其结构上必须是一个真正的树。每个域名只能有一个父节点(除了根节点),就像树的每一枝(除了根/树干)只能连接到一个树枝一样。此外,结构中不能出现循环;你不能有一个子节点也是其父节点的域名,例如。

提示

关键概念 DNS 名称空间必须作为一个真正的拓扑树来组织。这意味着每个域名只能有一个父节点,结构中不允许有循环。

请记住,尽管名称层次结构代表了命名设备的组织方式,但它只是一种逻辑结构。它与设备的物理位置没有必然的联系。一个有 10 个子域名的域名可能代表 11 个位于 11 个不同国家的设备。我们将在下一章讨论 DNS 授权结构时进一步探讨这一点。

DNS 标签、名称和语法规则

我们已经看到 DNS 名称空间层次结构如何使我们能够将域名组织成一个虚拟树,该树反映了设备本身的组织特性。虽然使用层次名称空间在本质上比平面名称空间更复杂,但它产生了一个强大的结果:能够指定可以在本地管理的同时保持全局唯一性的名称。同时,树的复杂性带来了相对简单的名称构造的好处,这使用户标识符来实现。

DNS 标签和标签语法规则

DNS 中的命名从给 DNS 名称空间中的每个域名或节点分配一个文本标签开始。标签标识结构中的域名,并必须遵循几个语法规则:

长度 每个标签理论上可以从 0 到 63 个字符长。在实践中,长度为 1 到大约 20 个字符是最常见的,对于分配给树根的标签(如下一节所述,长度为 0 个字符)有一个特殊例外。

符号 允许使用字母、数字以及破折号字符(-)。不允许使用其他标点符号。例如,下划线(_)不能用于标签中。

大小写 标签不区分大小写。例如,Jabberwockyjabberwocky 是等效的域名标签。

每个标签必须在它的父域内是唯一的。所以,例如,如果我们有一个名为 Rocks 的顶级域,我们可以在 Rocks 内只有一个名为 Crystal 的子域。由于标签的不区分大小写,我们无法在 Rocks 内同时有 CRYSTAL 和 Crystal,因为它们被认为是相同的。

正是这种在父域内的本地唯一性概念确保了名称的整体唯一性,同时允许对命名进行本地控制。无论谁负责 Rocks 域,都可以为尽可能多的单个对象或子域分配名称,只要这些名称在域内是唯一的。其他人,比如 Glass 域的维护者,也可以在 Glass 内创建一个名为 Crystal 的子域。不会发生冲突,因为 Glass 和 Rocks 域是分开的。当然,由于所有顶级域都有相同的父级(根),所有顶级域都必须是唯一的。

小贴士

关键概念 DNS 名称空间中的每个节点都通过一个标签来标识。每个标签必须在父域内是唯一的,但不需要在整个域名空间内唯一。这允许每个域对子域的名称进行本地控制,而不会在全球层面上创建的完整域名中引起任何冲突。

域名构造

可以使用从树根开始并向下到该域的标签序列来唯一标识域名结构中的每个单独的域。在层次结构中的每个级别的标签按顺序列出,从最高级别开始,从右到左,由点分隔。结果是域名的正式定义。

名称空间的根默认被赋予一个零长度的空名称;也就是说,根的标签存在,但它是空的。这样做是因为从技术上讲,根是每个域名的一部分,所以它必须包含在每个域名中。如果它像 Root 那样很长,我们就需要在每个域名的末尾包含它。这只会使每个名称更长,而实际上并没有添加任何有用的信息——我们已知每个域名都在根之下。

考虑一个顶级域名为 Rocks 的例子,其中包含一个二级域名 Crystal。Rocks 的域名是 Rocks.,点分隔 Rocks 和空标签(空根)。在实践中,尾随的点通常被省略,因此顶级域名 Rocks 的域名可以被认为是仅仅是 Rocks。Rocks 中的子域 Crystal 的域名是 Crystal.Rocks。如果我们有一个名为 Salt 的设备位于 Crystal.Rocks 域中,它将被称为 Salt.Crystal.Rocks。这相当直接,如图 53-4 所示。

DNS 标签和域名构造 DNS 名称空间中的每个节点都有一个标签(根节点除外,其标签为空)。节点的域名通过将树顶部的标签顺序排列到单个域名,从右到左,用点(句号)分隔每个标签来简单地构造。

图 53-4. DNS 标签和域名构造 DNS 名称空间中的每个节点都有一个标签(根节点除外,其标签为空)。节点的域名通过将树顶部的标签顺序排列到单个域名,从右到左,用点(句号)分隔每个标签来简单地构造。

我们可以使用这些名称轻松地识别特定域的子域。例如,如果我们从 Salt.Crystal.Rocks 开始,很明显 Crystal.Rocks 是其父域。这也清楚地表明,Crystal.Rocks 和 Salt.Crystal.Rocks 都是 Rocks 的子域;一个比 Rocks 低一个级别,另一个低两个级别。

注意,为了实施目的,完整的域名有一个最大字符限制为 255 个字符。实际上,大多数域名都比这个限制短得多,如果我们让它们变得如此之长以至于没有人能记住它们,这将违背域名整体的目的。

小贴士

关键概念 域名是一个文本字符串,它唯一地标识了名称空间中的特定节点。节点的域名是通过将 DNS 树分支中的所有标签从树顶开始到特定节点按右到左的顺序连接起来来构造的,每个标签之间用点(句号)分隔。

最后,请注意,在许多协议中,通过在名称之后提供目录结构,可以指定域名内的特定资源。这是使用标准的 TCP/IP URL 语法完成的,其中路径是通过斜杠分隔子目录来指示的。例如,位于 Salt.Crystal.Rocks 的特定文件可能位于 Salt.Crystal.Rocks/chem/composition。虽然 DNS 名称不区分大小写,但路径中的标签是区分大小写的。因此,此示例与 Salt.Crystal.Rocks/chem/Composition 不同。有关 URL 语法的讨论,请参阅第七十章的更多详细信息。

绝对(完全限定)和相对(部分限定)域名规范

如前所述,我们可以通过从根节点开始并按顺序跟随子域的序列到所讨论的节点,列出每个级别的标签并用点分隔,来指定 DNS 名称层次结构中任何节点的域名。当我们这样做时,我们得到一个唯一标识特定设备名称的单个名称。在实践中,域名可以通过它们的完全限定名称或部分限定名称来指定。

完全限定域名

技术上,如果一个顶级域名 A 包含一个子域名 B,而 B 又包含子域名 C,那么 C 的完整域名就是 C.B.A.. 这被称为节点的完全限定域名(FQDN)。在这里,单词限定指定同义。域名 C.B.A.是完全限定的,因为它给出了整个 DNS 名称空间中特定域名所在的全局位置。

FQDN 有时也称为绝对域名。这个术语反映了这样一个事实:您可以使用 FQDN 从名称空间的任何其他部分无歧义地引用任何设备的名称。使用 FQDN 始终指示解释名称的人或软件从根开始,然后从右到左按顺序跟随域名标签的序列,在树中从上到下。

部分限定域名

在某些情况下,您可能使用不完整的名称规范来引用设备。这被称为部分限定域名(PQDN),这意味着该名称仅部分指定了设备的位置。根据定义,PQDN 是模糊的,因为它没有给出完整的域名路径。因此,您只能在已知特定父域的绝对域名的情况下使用 PQDN。

我们可以通过将部分名称附加到父域的绝对名称上来找到部分指定的域名的 FQDN。例如,如果我们有一个在 FQDN Y.X.上下文中的 PQDN Z,我们知道 Z 的 FQDN 是 Z.Y.X。

为什么要这样做呢?答案是方便。一个域的管理员可以使用 PQDN 作为缩写来引用设备或子域名,而无需重复整个全名。例如,假设你是 Widgetopia 大学计算机科学系的负责人。整个系的域名是 cs.widgetopia.edu.,而你管理的单个主机以水果命名。在你维护的 DNS 文件中,你可以每次都通过 FQDN 来引用每个设备;例如,apple.cs.widgetopia.edu.,banana.cs.widgetopia.edu.等等。但告诉软件“如果你看到一个不是完全限定的名称,假设它位于 cs.widgetopia.edu 域中”会更简单。然后你只需称这些机器为 apple、banana 等等。每当 DNS 软件看到像 kiwi 这样的 PQDN 时,它将把它视为 kiwi.cs.widgetopia.edu。

小贴士

关键概念 一个完全限定域名(FQDN)是一个完整的域名,它通过给出从树根到该节点的完整标签路径,唯一地标识 DNS 命名空间中的一个节点。它定义了域的绝对位置。相比之下,一个部分限定域名(PQDN)仅指定域名的一部分。它是一个相对名称,仅在特定上下文中才有意义。部分名称必须在该上下文中解释,才能完全识别节点。

我在本章前面提到,对于空根域的尾随点通常省略。这在日常用语中以及当用户在应用程序中指定域名时是正确的。例如,你不会在网页浏览器中使用尾随点。然而,点用于在 DNS 主文件中清楚地区分 FQDN 和 PQDN。这允许我们同时使用 FQDN 和 PQDN。在我们的例子中,apple 将指 apple.cs.widgetopia.edu.,但 apple.com.将指苹果电脑公司的 FQDN。你必须小心观察这里的点,因为 apple.com(没有尾随点)将是一个 PQDN,它将指 apple.com.cs.widgetopia.edu.,而不是苹果电脑的域。

第五十四章。DNS 域名注册、公共管理、区域和权威机构

无标题图片

前一章解释了域名系统(DNS)命名空间由一系列域名和子域名组成。从根开始,我们有一系列顶级域名,然后是它们下面的二级域名,再下面是更低级的域名。那么,显然的问题就变成了:我们如何确定命名空间的形状和结构,以及谁将管理它?更具体地说,谁将控制树的根并决定顶级域的名称?我们如何对剩余的命名空间进行细分控制?我们如何确保在域内选择兄弟子域的名称时没有冲突?

DNS 可以用于由单个组织控制的私有网络,如果是这样,那么该组织显然负责名称空间。我们将讨论私有命名,但实际上,这并不那么有趣。DNS 的大多数使用都发生在公共互联网上。在这里,我们面临着一个更大的挑战,因为我们需要构建一个跨越全球并覆盖由不同组织管理的数百万台机器的名称空间。为此,我们需要一个非常强大的名称注册过程和支撑它的管理方法。

在本章中,我将描述名称注册的过程以及如何在 DNS 中管理权限,重点关注公共互联网。我首先描述 DNS 的分层权限结构以及它与分层命名空间的关系,并讨论 DNS 分布式名称数据库背后的概念。我描述了互联网的组织和地缘政治顶级域名,以及它们是如何由不同的权限机构管理的。然后,我讨论了权限是如何委派给二级和更低级域的,以及域名公共注册的工作方式,包括如何解决公共注册的问题和问题。我解释了 DNS 名称空间是如何划分为权限管理区的,然后我简要讨论了私人 DNS 名称注册。

小贴士

相关信息 大多数 TCP/IP 实现都包含一个名为 whois 的特殊实用程序,可以用来查询 DNS 分布式名称数据库以获取域名的注册信息。这个应用程序在故障排除中非常有用。有关详细信息,请参阅讨论 whois 的第八十八章部分

DNS 分层权限结构和分布式名称数据库

在上一章中,我解释了 DNS 中命名的核心概念是基于域名的。每个域名都可以被认为类似于一个影响或控制的范围。一个域名“展开其翅膀”覆盖了它包含的所有对象和子域名。由于这种影响的概念,当我们考虑任何 DNS 名称空间时,我们会看到它是分层的,因为它反映了控制域名及其内部节点的组织层次结构。这意味着存在一个分层权限结构,它补充了 DNS 中的分层名称结构。

名称空间分层导致权限分层的主要原因是对兄弟子域名在域名内唯一性的要求。一旦我们有了唯一性的需求,我们就必须有一些形式的权限或过程来确保每个子域名或对象在该域名内选择不同的名称。这正是名称注册的全部内容。

这种分层权限结构的概念有点抽象,但如果我们检查一个示例 DNS 名称空间并讨论其中涉及的问题,就更容易理解。自然地,我们希望从名称层级的顶部开始,即根域,null。

DNS 根域中央权限机构

要开始名称空间,我们必须在根域内创建顶级域名 (TLD)。现在,每个都必须是唯一的,因此必须有一个权限机构来管理所有 TLD 的创建。这意味着控制根域的权限机构控制整个名称空间。

在互联网的情况下,这个中央权限机构最终对 DNS 中的每个名称负责。最初控制 TLD 创建的互联网中央 DNS 权限机构被称为 网络信息中心。后来,它被称为 互联网分配号码权威机构 (IANA),它还负责协议号码、IP 地址等。这些功能现在由 IANA 和 互联网名称与数字地址分配机构 (ICANN) 共享。我们将在下一章讨论互联网的具体 TLD;IANA、ICANN 和相关组织在 第三章 中的互联网注册权限机构部分进行讨论。

TLD 权限机构

在权限层级的下一级,我们在每个 TLD 内创建二级域名。每个 TLD 必须使用协调权限机构进行管理,但这不一定是运行根域(IANA)的组织。IANA 委派 一些 TLD 的权限给其他组织。

IANA 可以将每个 TLD 的控制权委派给层级中的不同权限机构。实际上,在管理二级域名的创建方面,一个 TLD 可能会有与另一个 TLD 完全不同的规则。在某些 TLD 中,存在多个权限机构共同进行名称注册。

低级别权限委派

随着我们向下移动名称空间层级,权限委派的过程继续进行。在每一级,名称空间变得更加具体。

如果我们使用组织层级,例如 .COM TLD,我们通常将每个二级域名的权限委派给代表该名称的组织。例如,IBM.COM 由 IBM 管理。由于 IBM 规模庞大,它可能进一步细分权限结构,但较小的组织可能不会这么做。

权限层级与名称层级的关系

授权层次结构与名称层次结构是互补的;它们并不完全相同。并不一定需要在层次结构的每个级别都有一个不同的授权。在许多情况下,一个单一的授权机构可以管理跨越结构多个级别的名称空间的一部分。例如,IANA 管理互联网根域名(null)和.int 顶级域,但其他顶级域由其他组织管理。名称层次结构被划分为授权区域,这些区域反映了管理名称空间部分授权的层次结构。

此外,对一个域的管辖权并不一定意味着物理控制。一个域可以包含由不同大陆上的组织管理的子域,而且一个单独的子域也可以包含位于不同大陆上的命名设备。

DNS 分布式名称数据库

当然,有了权限也就有了责任,一个授权机构对一个域的主要责任是在域内注册名称。当名称被注册时,就会为其创建一组数据,然后这些数据可以被互联网设备用来解析名称到地址或执行其他功能。

描述所有 DNS 域的所有数据集构成了 DNS 的名称数据库。正如注册权限是分布的和分层的,这个数据库也是分布的和分层的。换句话说,没有单一的地方存储所有 DNS 名称信息。相反,DNS 服务器携带资源记录(见第五十七章)。

.COM 公司和企业

.EDU 大学和其他教育机构

.GOV 政府机构

.MIL 军事组织

.NET 实施、处理或管理网络技术以及/或互联网的组织

.ORG 不适合任何先前分类的其他组织

初看这似乎是一种合理的方式来涵盖世界上的组织。然而,由于.ARPAnet 域名(其名称指的是 ARPAnet,现代互联网的前身,如第八章所述)是临时的,这为所有其他组织留下了只有六个类别。此外,TLDs 并没有像最初预期的那样被全部使用。例如,.GOV 和.MIL 域名并没有用于所有类型的政府和军事组织,而主要是用于美国联邦政府和军事。.EDU 域名最终只用于大学,同样是在美国。

这使得只有三个常见的顶级域名——.COM、.NET 和.ORG——几乎适用于所有其他希望使用组织层次结构的团体和公司。由于只有这三个顶级域名,它们很快就变得非常拥挤,尤其是.COM 域名。不久之后,又增加了一个新的第四个域名——.INT,用于国际组织。然而,它仅打算用于少数几个组织,例如国际标准机构。

当然,没有固有的理由说明通用域名应该仅限于最初创建的少数几个。

新的通用顶级域名

在过去的几年里,提出了许多关于新的通用顶级域名的建议,这些域名将扩大可能的二级域名的数量,并为不同的组织类型提供更好的分类——也就是说,使通用顶级域名不那么通用。最初对这些新名称的采用存在一些阻力,特别是因为关于应该创建哪些新顶级域名的想法有很多不同。

IANA 从很多人那里收集了意见,并遵循了一个复杂的程序来确定应该创建哪些新的顶级域名。在 2001 年和 2002 年,批准创建了几个新的顶级域名,并做出了关于管理它们的权威机构的决定。

在过去几年中批准的新顶级域名中,据我所知,没有哪一个实现了广泛的流行。人类是惰性的生物,大多数人仍然习惯于以.COM、.NET 或.ORG 结尾的名称。随着时间的推移,这可能会改变,但可能需要几年时间。

注意

有些人实际上觉得增加新的通用顶级域名是一个糟糕的想法,因为这可能会使组织更难定位(由于域名可能以各种不同的顶级域名结尾)。然而,这还是有争议的,尤其是由于现有顶级域名的地址空间耗尽,许多公司已经不得不选择不直观的域名了

表 54-1 展示了所有当前的通用顶级域名,并描述了它们的使用方式,并列出了管理每个域名的当前中央权威机构。原始顶级域名以斜体突出显示(我将 .INT 作为原始顶级域名包括在内,因为它是在“新”的之前创建的)。图 54-1 以图形形式显示了 15 个通用顶级域名。

互联网 DNS 组织(通用)顶级域名 互联网目前定义了 15 个通用顶级域名。它们按字母顺序排列在此,原始顶级域名以浅色阴影显示,而 2001/2002 年新增的顶级域名以深色阴影显示。

图 54-1. 互联网 DNS 组织(通用)顶级域名 目前为互联网定义了 15 个通用顶级域名。它们按字母顺序排列在此,原始顶级域名以浅色阴影显示,而 2001/2002 年新增的顶级域名以深色阴影显示。

表 54-1. 互联网 DNS 组织(通用)顶级域名

通用顶级域名 缩写 权威机构 描述
.AERO 航空航天 国际航空航天电信公司(SITA) 用于航空航天行业的成员,如航空公司和机场。(是的,这是法语!)
.ARPA 地址和路由参数区域 IANA/ICANN 最初定义为从较旧的宿主表系统迁移的临时域名,当然,ARPA最初代表高级研究计划署,互联网前身创造者。今天,.ARPA 域名用于内部互联网管理目的;表中显示的扩展名称,我相信是为了符合缩写。此域名最著名的用途是用于反向 DNS 查找。
.BIZ 商业 NeuLevel 公司 用于商业。旨在与.COM 竞争。
.COM 商业组织 VeriSign 公司 最初旨在为公司和其它商业利益使用,.COM 也被广泛用于其他目的,包括小型企业和甚至喜欢.COM 域名流行度的个人。
.COOP 合作协会 Dot Cooperation 公司 用于合作协会。
.EDU 教育 Educause 最初旨在为所有类型的学校组织使用,.EDU 现在仅用于在美国获得认证的学位授予高等教育机构。其他教育机构,如公立学校通常使用国家代码顶级域名。
.GOV 政府 美国总务管理局 保留供美国联邦政府使用。
.INFO 信息 Afilias 公司 一个非常通用的顶级域名,旨在用于各种类型的信息资源。它是无限制的,任何人都可以在.INFO 中注册任何类型的组织。它也被定位为.COM 的替代品。
.INT 国际 IANA .int 域名注册处 仅用于由国际条约建立的大型组织。
.MIL 军事 美国国防部网络信息中心 保留供美国军事使用。
.MUSEUM 博物馆 博物馆域名管理协会 猜猜看。查看 http://index.museum 获取使用此顶级域名的完整博物馆列表。
.NAME 名称 全球名称注册 在原始的通用层次结构中,没有为个人预留注册自己名称的地方,因此人们会创建像 jonesfamily.org 这样的域名。这并不理想,因此创建了.NAME 作为个人和家庭注册自己名称域名的场所。.NAME 还与国家代码顶级域名竞争。
.NET 网络 VeriSign, Inc. 这原本只用于互联网服务提供商(ISPs)和其他与互联网或网络紧密合作的组织。然而,由于.COM 和.ORG 中的名称空间耗尽,许多.NET 域名被注册给了其他组织。
.ORG 组织 公共利益注册局 最初是为不适合其他通用顶级域的组织设计的,.ORG 很快与专业和非营利组织相关联。然而,有盈利公司可以使用.ORG 名称。
.PRO 专业 RegistryPro 保留给有资质的专业人士,如律师和医生。

小贴士

关键概念 互联网的 DNS 名称空间被划分为两种方式之一是使用一组通用顶级域名(TLDs)。这些 TLDs 旨在为所有公司和组织提供一个基于其组织类型命名的场所。最初有六个这样的域名,但现在已经扩展到有 15 个。

DNS 地缘政治(国家代码)顶级域名和机构

理论上,通用顶级域名应该足以满足世界上所有个人、公司和团体的需求。这一点尤其正确,因为根据定义,.ORG 是一个可以包括任何人或任何事物的通用域名。因此,在一个理想的世界里,世界上每个人都能在这些简单的域名中找到一个位置。

然而,在 DNS 的早期,其创造者意识到通用顶级域名可能无法满足世界上所有人的需求,尤其是在某些情况下。这有几个原因:

通用域名的美国中心主义 我并不是在批评这一点(我是一个美国公民,热爱我的国家!)。然而,无可争议的是,美国组织和公司在通用顶级域名中占据主导地位。考虑到互联网最初是在美国开发的,这一点并不令人惊讶,但它仍然给某些群体带来问题。例如,如果美国军方控制着.MIL 域名,那么比如大不列颠的军方在名称空间中该如何定位?

语言 大多数通用域名由主要用英语进行商业活动的组织占据。然而,世界上有数百种语言,对于那些语言的说话者来说,如果他们能够更容易地找到他们能理解的资源,那就更容易了。

本地控制 世界各地的国家很少达成一致,他们当然在如何安排其国家内组织互联网存在方面存在差异。许多人希望允许国家能够为自己设置命名空间的一部分。

由于这些以及其他原因,互联网的命名空间被设置了一套与通用顶级域名平行的国家代码 TLDs,有时被称为ccTLDs。我称这些为地缘政治 TLDs,因为它们基于世界的地缘政治划分(类似于我在第五十三章中概述 DNS 命名空间时使用的例子)。在这个等级结构中,世界上每个国家都被分配了一个特定的两位字母代码作为 TLD,并指定一个特定的权威机构负责管理该域名。例如,大不列颠的 ccTLD 是 .UK,加拿大的是 .CA,日本的则是 .JP。这些代码在本地语言中往往比在英语中更有意义。例如,德国的是 .DE,瑞士的是 .CH。

国家代码指定

当我说国家很少达成一致时,我并不是在开玩笑。事实上,他们甚至不能就什么是国家达成一致!为了是否某个领土是独立还是另一个国家的组成部分而进行的真实射击战争已经发生,DNS 的创造者不想参与这种争议。正如 IANA 网站所说:“IANA 不参与决定什么是国家,什么不是国家,以及哪些代码字母适用于特定国家。”

为了保持中立,IANA 的 ccTLD 代码直接来自国际标准化组织(ISO)维护的 ISO 标准 3166-1 中的标准国家缩写。当一个国家被 ISO 认可并分配了此列表上的代码时,IANA 就将其创建为 TLD。目前有超过 200 个不同的地缘政治 TLDs。您可以在www.iana.org/cctld/cctld-whois.htm找到 IANA 国家代码 TLDs 的当前列表。

小贴士

关键概念 由于通用 TLDs 的限制,创建了一套国家代码顶级域名。这种地缘政治层次结构允许地球上每个国家根据自己的需求建立自己的命名系统,并以他们认为合适的方式管理它。根据 ISO 的官方决定,IANA 确定什么是国家。

国家代码 TLD 权威机构

每个国家都有权根据自己的选择设置其 TLD 的内部子结构;这再次显示了层次结构的权力。

一些国家在较低级别强制实施进一步的地理子结构。例如,美国的 .US 域最初被设置,以便所有二级域名都是两位字母的州缩写(这后来有所改变)。

其他国家实际上可能在它们的国代码中使用组织子域名。例如,大不列颠有 .CO.UK 用于该国的公司(就像 .COM 但仅限于英国;他们省略了 M),而 .COM.AU 是用于澳大利亚的公司的。

其他国家可能根本没有任何特定的子结构,尤其是如果它们很小的话。

国家代码域名的租赁/销售

有趣的是,一些具有可识别国家代码的小国家,尤其是对英语使用者来说,已经将它们的代码用于非常创造性的目的,包括将名称空间出售或出租给有进取心的公司。

一个很好的例子是 .TV 域名,技术上属于岛国 图瓦卢。当然,对大多数人来说,“TV”意味着完全不同的东西。有些人认为以 .TV 结尾的域名可能在英语世界很受欢迎,所以他们成立了一家名为 The .TV Corporation 的公司,并与图瓦卢政府协商使用 .TV 域名。如今,这个 TLD 的管理机构就是这家总部位于加利福尼亚的公司!类似的安排也可以在 .CC、.NU、.TO 以及其他 TLDs 中找到。

这提醒我们,名称空间是逻辑的,而不是物理的。显然,拥有 .TV 名称的许多计算机实际上并不位于南太平洋的一个偏远岛屿上。同样,如果一个网站以 .CA 结尾,例如,它可能代表一个加拿大组织,但这并不一定意味着该网站本身实际上托管在加拿大。

地缘政治 TLDs 的缺点

地缘政治域名在特定用途中非常受欢迎。国家政府和其他官方机构喜欢使用它们,这是显而易见的。输入 www.gov.xx 或 www.government.xxxx 是国家代码),很可能会把你带到大多数国家的国家政府网站。一些公司和组织使用 ccTLDs,因为它们允许他们选择在通用层次结构中已被占用的名称,或者简单地表达民族自豪感。

然而,对于许多其他公司和组织来说,通用顶级域名(TLDs)比国家代码更受欢迎。我认为最重要的原因是组织使用通用域名更容易定位。

这里有一个很好的例子来说明我的意思。在我居住的城镇附近,一家名为 Aldi 的新杂货店最近开业了。我喜欢这家商店,并想了解更多关于它的信息,所以我打开了我的网络浏览器,并寻找它的网站。是的,我可以在搜索引擎中输入它,但像大多数人一样,我很懒。直接在我的浏览器中输入 www.aldi.com 要容易得多,结果,Aldi 国际的网站就弹出来了。

现在,Aldi 实际上总部位于德国,该公司确实有一个位于 www.aldi.de 的网站。但我不知情。我通过访问 www.aldi.com 轻易地找到了他们,因为我不需要知道他们的物理位置,而且我知道大多数大公司都有 .COM 域名。当然,可查找性非常重要,尤其是对于试图开展商业活动的商业组织。

另一个很好的例子是美国,它除了主导通用 TLD 外,还有自己的国家代码 .US。负责该域名的权威机构最初选择使其遵循严格的地理层级结构,因此每个域名都必须是 organization.city.state-code.us 的形式。因此,要使用这部分命名空间,波士顿的公司必须位于 .boston.ma.us 域名下。这非常整洁且逻辑性强,但它使得名称比通用等价物更长且更难猜测。

假设你想获取金属巨头 Alcoa 的信息。如果你在行业里,你可能知道 Alcoa 位于匹兹堡,但如果你不在,哪个更容易找到:www.alcoa.pittsburgh.pa.us 还是 www.alcoa.com?这里有人知道如何拼写阿尔伯克基吗?

正因如此,.US 域名在某些社会群体中取得了成功,但在其他群体中却没有,尤其是商业实体(公司)。严格的层级结构确实有一些实际优势,例如避免命名空间冲突,但其缺点如此之多,以至于最近在 .US 域名中放宽了规则。

二级和更低级别域名的公共注册

IANA 负责决定哪些 TLD 存在于互联网名称空间中,因此,他们最终对互联网中的所有名称负责。然而,权威层级的整个目的在于 IANA 不应负责整个命名空间。因此,尽管 IANA 维护对某些 TLD(如 .INT 和 .ARPA)的控制,但管理其他 TLD 的控制权被委派给了每个 TLD 的二级权威机构。

正如 IANA 有权选择如何将权限委派给根域的子域一样,负责每个顶级域(TLD)的组织也有权决定如何在 TLD 下创建二级域。

在许多 TLD 中,尤其是通用 TLD,二级域名直接分配给个人或组织。例如,名为 XYZ Industries 的公司可能想要获得 xyzindustries.com 的域名。

在其他 TLD 中,二级域名的设置遵循特定的结构,就像 .US 域名中使用的州代码。在那里,你需要向下走更多层级,但最终你会到达公司和个人注册自己域名的点。例如,在 .US 域名中,XYZ Industries 如果总部位于凤凰城,可能会想要注册 xyz.phoenix.az.us。

这个从被授权负责部分名称空间的权威机构到希望获取名称的普通人和团体之间的过渡点很重要。必须建立一个公开注册的过程,以允许以一致和可管理的方式发生此类名称分配。当最初创建通用的顶级域名和国家代码顶级域名时,这并不难实现。当时互联网相当小,让每个顶级域名的管理机构在该顶级域名内执行注册是有意义的。这确保了在顶级域名内没有名称重复,而且没有太多麻烦。

注册管理机构

对于像.COM、.NET 和.ORG 这样非常重要的通用顶级域名,负责注册的权威机构是互联网网络信息中心(InterNIC)。InterNIC 是由美国政府管理的服务,后来将管理它的合同授予了 Network Solutions Inc.(NSI)。NSI 最终被 VeriSign 收购,后来将其作为独立的企业分离出来。(网络世界的变化真是快!)

多年来,NSI 独立执行了.COM、.NET 和.ORG 顶级域名内的所有注册。然而,原始通用顶级域名的流行导致了 20 世纪 90 年代这些域名名称注册需求的激增。有一个公司负责注册导致这成为互联网域名系统中的另一个瓶颈。还有很多人不喜欢单一垄断负责注册所带来的缺乏责任感和竞争。InterNIC 可以自行设定价格,最初每个域名每年收费 35 美元,后来增加到每年 50 美元。

在 20 世纪 90 年代末,域名注册的责任被赋予了 ICANN。注册过程被去监管化,借用一个指从发电等行业中去除垄断的术语。截至 1999 年 12 月,每个顶级域名(包括.COM、.NET 和.ORG)仍然只有一个负责整体管理的单一机构。

现在,NSI 仍然是运行.COM 和.NET 的权威机构。然而,它并不是唯一注册这些顶级域名下名称的组织。它进一步将注册管理权委托给许多其他公司,称为认证注册商。任何注册商都可以为其认证的顶级域名(s)注册名称。

注册协调

当有多个公司在顶级域名下注册名称时,自然协调变得更加重要。遵循一套特殊的技性行政程序,以确保不会出现问题,例如两个注册商同时试图抢注一个名称。

该系统运行良好,现在希望使用存在竞争的 TLDs 的公司可以选择各种注册公司。这一结果最引人注目的是最可预测的:在非监管的通用 TLDs 中注册域名的成本通常远低于最初由 InterNIC 收取的费用。

一旦公司、个人或组织注册了低级域名,他/她/它就成为了该域名的权威。域名的使用因此变得私密,但根据域名的使用方式,可能还需要进一步进行公共名称注册。有关私人注册的讨论,请参阅本章末尾,以获取更多信息。

DNS 公共注册争议和争议解决

互联网最初是一种研究网络的中介,后来发展成为连接科学家的系统,最终成为几乎每个人都使用的全球通信工具。作为这一演变的一部分,互联网也成为了世界上商业活动的重要组成部分。20 世纪 90 年代初,金钱开始进入互联网领域,仅仅几年后,它对互联网的影响就如此之大,以至于 20 世纪 90 年代末股市飙升的现象现在常被称为“互联网泡沫”。

公共注册争议

不幸的是,互联网对商业利益的重要性日益增加,与互联网技术的非商业原始设计发生了正面冲突,这在 DNS 中尤为明显。由于只有少数通用 TLDs,TLD 内的每个名称都必须是唯一的,而人类往往是好斗的生物,因此很快就出现了关于谁可以使用什么名称以及为什么的争论。当然,从那里开始,不久之后,诉讼和其他不愉快的事情就变得司空见惯了。

与公共注册域名相关的重大问题数量惊人:

公司名称冲突 .COM 域名是针对公司的,但许多公司拥有相同的名称。ACME 家具公司、ACME 餐饮用品公司以及 ACME 鞋业公司,都可能希望拥有 acme.com 域名。但在.COM 中只能有一个这样的域名。(这些都是虚构的例子;acme.com 实际上由一个名为Acme Labs的组织拥有。)

公司/个人/小型企业名称冲突 许多公司拥有与个人姓名相似甚至完全相同的名称,这可能导致潜在的冲突。例如,假设你的名字是 Wendy,你拥有一家名为 Wendy's Fabrics 的小型布料店。但你很懂互联网,并在 1993 年一听到互联网就决定注册 wendys.com。然后这家大型汉堡连锁店出现了,并对此产生了问题。

注意

据我所知,温迪公司并没有出现此类问题,但实际上有一个广为人知的案例,展示了大多数公司最近在域名命名方面是如何脱离轨道的。1994 年,《连线》杂志的一名撰稿人惊讶地发现,mcdonalds.com 这个域名尚未注册!为了展示注册过程是多么不受监管,他自己注册了这个域名,并因此引起了一些骚动。最终,金拱门的人通过友好的安排从他那里购买了该域名,他放弃了名称,他们向慈善机构捐赠了一笔钱

企业战争 当公司故意通过注册与自身公司无关的名称来试图从对方那里夺取业务时,就会发生一种特别丑陋的冲突。一个例子是,如果汉堡王试图注册 mcdonalds.com 并用来宣传汉堡王的产品。(顺便说一句,他们并没有这样做,所以请不要起诉我!)另一个例子是,公司试图使用替代顶级域名(TLD),例如注册 burgerking.org 来混淆试图找到 burgerking.com 的人。事实上,许多公司已经采取了在许多不同 TLD 上注册自己名称的措施,以防止这类事情发生。

网络域名抢注 一些雄心勃勃(用这个词来形容很合适)的个人,很早就意识到某些名称的潜在价值,注册了大量名称,希望将来转售。许多人谴责这种行为是剥削性的,因此创造了“网络域名抢注”这个术语来指代这种活动。不幸的是,通过这种方式赚了很多钱,至今仍有许多域名因为被某些人或个人无限期保留而无法使用。

误导性命名实践 另一种有点邪恶的创造力体现在那些试图利用我们中一些人拼写能力不足的人身上。例如,如果你是一家名为 Superb Transceivers Inc.的大公司的竞争对手,该公司注册了 superbtransceivers.com,你可能会注册 superbtranscievers.com,并将流量从那里重定向到你的域名。另一个例子是利用字母O和数字 0(零)之间的常见混淆。例如,一家软件公司曾经注册了 micros0ft.com,这让华盛顿州雷德蒙德的软件巨头感到非常不快。

顺便提一下,正是这些荒谬的事情部分导致了对新通用顶级域名的强烈呼声。尽管像.US 这样的顶级域使用的更复杂的方案并不受欢迎,但它们在通用域名上具有巨大的优势。由于所有这些注册都是地域性的,因此冲突要少得多。例如,ACME 家具公司可能会使用 acme.seattle.wa.us,ACME 餐饮供应公司可能拥有 acme.mendocino.ca.us,而 ACME 鞋业公司则可以选择 acme.anchorage.ak.us。只有在组织名称相同且位于同一州和城镇时,才会出现争议。你仍然可以在芝加哥有三个乔的比萨店竞争,但这不太可能成为大公司的问题。

注册争议解决方法

那么,我们如何解决这些情况呢?俗话说,这可以通过简单或困难的方式完成。以下是一些用于争议解决的方法:

域名共享有时,对立双方会同意一个富有成效的解决方案。一个特别有建设性的想法是同意共享域名。例如,三个不同的 ACME 公司可以各自创建自己的更具特定名称的域名,例如 acmefurniture.com、acmerestaurantsupply.com 和 acmefootwear.com。然后他们可能同意将 www.acme.com 注册给无人使用,通过一家公司注册但不用于任何目的。更好的是,他们可以设置一个简单的网页,说明域名是共享的,并提供到三个网站的链接。不幸的是,似乎小学生比大多数企业高管更理解共享的概念,因此这种解决方案很少见。

域名购买另一个选择是购买。如果一家大公司想要购买一个个人或小企业已经注册的域名,它通常会直接购买该域名,因为这是最容易的做法。在互联网狂热的高峰期,有些域名以数百万美元的价格出售——仅仅是使用该名称的权利!许多网络抢注者和其他投机者通过出售域名而致富。

诉讼通常,争斗者不会表现得很好,通常会发生:威胁、恐吓、诉讼等等。有时,一封律师函就足以解决争议,特别是当一些拥有网站的可怜个人受到大公司的法律行动威胁时——这种情况已经发生很多次。然而,经常有争议的各方坚持自己的立场,特别是当两家公司发生冲突,他们的律师拒绝退让时。通常,事情最终会进入法院,以某种方式解决。通常,商标侵权的主张会被挑战先前域名注册的公司使用。

统一域名争议解决政策

诉讼费用高昂且耗时,因此人们希望存在其他机制来解决这些冲突。由于每个顶级域(TLD)的权威机构控制着其内部发生的事情,因此它也有权制定自己的政策来处理这类问题。对于通用顶级域,原始注册机构 InterNIC 曾有一个争议解决政策,允许对某个名称有商标利益的人挑战域名注册。这项政策因多个原因而备受争议,其中最不重要的是,它导致一些域名在没有任何商标侵权证据的情况下被成功挑战。

当前通用顶级域的权威机构 IANA/ICANN 于 1999 年创建了一个新的统一域名争议解决政策(UDRP),以更好地处理域名冲突。这项政策规定了一个程序,即如果一个公司拥有有效的商标,并且如果该域名侵犯了商标、与商标混淆相似或被他人恶意注册,它可以挑战该域名。同时,它还列出了原始注册人可以证明注册有效并应予以维持的方法。这个新系统消除了与域名公开注册相关的大多数问题——如欺骗性命名、企业战争和域名抢注——同时不会自动允许后来者关闭合法域名。

DNS 名称空间管理层次结构分区:DNS 授权区域

我在本章前面解释过,DNS 名称空间是按层次结构排列的,并且还有一个与该层次结构名称相关的权威机构层次结构。然而,这两个层次结构并不完全相同。如果它们是相同的,我们将在树的每一级为每个域名都需要一个单独的权威机构,而这在我们结构的任何地方都是不太可能想要实现的。

在 DNS 树的最顶层,我们可能希望在结构的每一级都指定一个单独的权威机构似乎是合理的。考虑地缘政治名称层次结构;IANA/ICANN 管理根域名,但每个国家顶级域(ccTLD)都由一个独特的国家权威机构管理。

然而,当我们到达结构的较低层次时,通常不方便或根本不可能让每一级都对应一个单独的权威机构。例如,假设你负责 Googleplex 大学 IT 部门,该部门运行自己的 googleplex.edu 域名 DNS 服务器。假设这所大学只有两所学校,分别是艺术系和计算机科学系。假设计算机名称空间被分为三个子域:finearts.googleplex.edu、compsi.googleplex.edu 和 admin.googleplex.edu(包括 IT 部门在内的中央行政职能)。

很可能,你不想也不需要艺术系运行自己的 DNS 服务器。同样,对于管理机器来说,情况可能也是如此。然而,计算机科学系可能确实希望运行自己的 DNS 服务器,因为这个部门可能比其他部门拥有更多的计算机,而且员工可能会将运行 DNS 服务器作为课程的一部分。

在这种情况下,你可能希望你自己,即 googleplex.edu 的管理员,维护 finearts.googleplex.edu 和 admin.googleplex.edu 子域及其内部的一切的权限,同时将 compsci.googleplex.edu 的权限委托给计算机科学部门中指定的任何人。DNS 被特别设计为允许在名称层次结构和权限结构之间创建这些划分。

将命名空间划分为权限区域的方法

完整的 DNS 名称结构是通过在相邻节点之间进行“切割”(如 RFC 1034 所称呼的)来划分的,从而在结构中创建连续节点的组。每个组被称为“权限区域”,或者更常见的是,简单地称为“区域”。每个区域通常由区域中最高级节点的域名来标识;即,离根节点最近的那个。DNS 中的区域在定义上是“非重叠”的——每个域或子域都恰好属于一个区域。命名空间划分为区域的方式可以是任意的。在一种极端情况下,我们可以在每个节点之间放置一个切割,从而将整个命名空间划分为每个域(以及子域等)都是一个单独区域的区域。如果我们这样做,整个 DNS 树中的名称层次结构和权限层次结构确实会是相同的。在另一端,我们可能一个切割都不用,定义一个包含整个 DNS 结构的单个区域。这意味着根节点是整个树的权限。

当然,在实践中,这两种方法都不是特别有用,因为它们都没有反映现实世界中 DNS 管理的方式。相反,我们通常根据命名空间不同部分的需求,在多个地方划分名称结构。有许多情况,我们可能想要创建一个负责其自身 DNS 服务器操作的子域;也有其他情况,我们可能不希望这样做。在名称层次结构中的这种划分的意义在于,这种划分本质上代表了被划分节点相对于其上方节点的“DNS 独立声明”。

回到我们的例子,如果 googleplex.edu 负责其自己的 DNS 服务器,那么在下一个更高级别的名称空间中,将在 googleplex.edu 和.EDU 之间进行切割。这意味着.EDU 的 DNS 服务器不再负责 googleplex.edu 域的 DNS;相反,要么是大学本身,要么是雇佣的第三方必须提供 DNS 服务。在这种情况下,我们假设 Googleplex 大学的员工自己运行他们的 DNS。如果没有进行其他切割,googleplex.edu 域将是一个包含该名称以下所有内容的单个区域,包括 finearts.googleplex.edu 和 compsi.googleplex.edu。

然而,在我们的例子中,我们会在 googleplex.edu 和 compsi.googleplex.edu 之间进行另一个切割。这实际上解放了 compsi.googleplex.edu,允许其管理员负责他们自己的 DNS 服务器。这样做,我们最终得到两个不同的区域:一个包括 googleplex.edu、finearts.googleplex.edu 和 admin.googleplex.edu(以及它们下面的所有内容),另一个是 compsi.googleplex.edu(以及它下面的所有内容)。这如图图 54-2 所示。

区域对名称解析的影响:授权服务器

区域的概念对于理解 DNS 名称服务器的工作方式至关重要,因此,对于名称解析的执行方式也是如此。区域中关于子域和单个设备的所有信息都是通过在 DNS 名称服务器上存储的一组资源记录来表示的。通常,这个名称服务器与区域中最高级别的域名相关联。包含区域最终信息的名称服务器被称为该区域的授权服务器。

DNS 区域的授权切割可以在 DNS 名称树中的节点之间进行,以创建任意名称授权的层次结构。此示例显示了 googleplex.edu 的 DNS 树分支,每个区域使用不同的阴影表示。IANA/ICANN 负责根域名,一个名为 Educause 的独立机构负责.EDU。第三个区域覆盖了 googleplex.edu 的大部分,除了在 googleplex 和 compsi 之间进行了切割,以创建一个独立的 compsi.googleplex.edu 授权区域。

图 54-2. DNS 授权区域划分可以在 DNS 名称树中的节点之间进行,以创建名称权威的任意层次结构。此示例显示了 googleplex.edu 的 DNS 树分支,每个区域使用不同的阴影表示。IANA/ICANN 负责根域,一个名为 Educause 的独立权威机构负责.EDU。第三个区域覆盖了 googleplex.edu 的大部分,除了在 googleplex 和 compsci 之间进行了切割,以创建 compsci.googleplex.edu 的独立授权区域。

一个区域的权威服务器是指维护该区域官方信息的服务器,以及最终负责提供关于该区域名称解析信息的服务器。我们将在第五十六章关于 DNS 服务器和名称解析的部分中讨论这一点。

小贴士

关键概念 DNS 名称注册层次结构被划分为称为授权区域的区域。每个区域代表一个独立管理的区域,由 DNS 名称树的连续段组成。

每个 DNS 区域都有一组权威服务器,通常是一对称为主服务器(或主服务器)和辅助服务器(或从服务器)。然而,单个 DNS 名称服务器也可能对多个区域具有权威性。

如前所述,域的实际所有者并不总是需要为其提供 DNS 服务。非常常见的是,特别是对于由小型企业或个人拥有的域,DNS 服务通常由第三方提供,通常是 ISP。例如,自从 1997 年以来,我就已经将 pcguide.com 注册为一个域,但我的长期网络托管提供商 pair Networks 从一开始就为我提供了 DNS 服务。这意味着 pair 的 DNS 服务器在 pair.com 的层次结构中负责 pcguide.com。它们还负责该公司客户的其他许多域。

DNS 私有名称注册

我们现在已经审查了 DNS 名称空间的层次结构性质以及管理它的权威结构。名称注册从名称层次结构根部的通用和国家代码顶级域开始,然后继续到顶级域内的二级域,然后是那些二级域下的更低级子域。随着我们沿着名称树向下移动,我们从最一般的公共权威(IANA/ICANN,它运行所有的 DNS)通过高级顶级域权威,最终下降到个人组织、公司和个人的层面。

公共当局和私人当局之间的这种界限在名称结构中的许多不同地方都会出现。无论它出现在哪里,在该线以下,域的责任就变成了注册该域的组织。该组织可以进一步细分名称空间,将其部分授予其他组织,甚至可以转售。或者,一个组织可能决定使用名称空间来创建一个纯粹内部的结构。我称这种做法为私有名称注册,与本章前面描述的公共名称注册相对。

例如,如果一家名为 XYZ 工业的公司注册了 xyzindustries.com,那么该公司不仅成为该域名名的所有者,而且成为该公司可能选择创建的任何子域结构或命名项的所有者。这是授权委派和分层结构的美丽和强大之处。然而,该公司必须做出一个重要的决定:他们是否希望创建成为全球 DNS 名称结构一部分的名称,或者是否仅在结构内部使用名称。

使用公开可访问的私有名称

如果一个组织的管理员希望其域内的名称成为全球 DNS 名称结构的一部分,他们必须完成必要的设置和管理工作,以确保这些名称适合 DNS。最常见的例子是创建一个公共的万维网服务器。大多数公司以 www 开头命名此类服务器,因此 XYZ 工业公司可能希望将其 Web 服务器地址命名为 www.xyzindustries.com。

显然,XYZ 工业公司的所有者希望并且需要互联网上的任何人都能找到这个服务器。因此,尽管他们拥有 xyzindustries.com 域的私人控制权,并且拥有 www.xyzindustries.com 的名称,但他们必须遵循适当的程序来确保为他们的 www 子域设置 DNS 资源记录,以便互联网上的每个人都能找到它。如果他们运行自己的 DNS 服务器,他们可以自己这样做,或者可以由 ISP 或其他第三方代为完成,如前所述。

用于内部使用的私有名称

另一种选择是为仅在组织内部使用的名称创建纯粹私有的名称。例如,即使 XYZ 希望有一个公共的 Web 服务器,管理员可能也希望为仅在公司内部访问的其他许多机器命名。在这种情况下,他们不需要设置这些机器以便它们可以被公开识别。他们可以创建私有机器名称,并在自己的网络内部管理它们。

小贴士

关键概念 一旦一个组织注册了特定的域名,它就成为了该域名的所有者,并可以决定是否以及如何在该域名内创建子结构。如果一个组织希望域名内的对象可以在公共互联网上访问,它必须将其域名结构化以符合互联网 DNS 标准。或者,它可以创建一个完全私有的域名,使用它喜欢的任何结构和规则。

常见的做法之一是利用较旧的宿主表名称系统。这个系统现在对于大型互连网络来说已经过时,但由于其简单性,在较小的公司中仍然经常使用。通过将其添加到组织内每台计算机的宿主表中,一个名称就会被注册,当宿主机的操作系统在执行标准 DNS 解析方法之前检查此文件时,该名称就会被解析。在这种情况下,宿主表补充了 DNS(它实际上不是 DNS 的一部分)。这两个系统是互补的,可以一起工作,如第五十一章中所述。

在不连接到互联网的网络中使用私有名称

注意,如果你正在运行一个完全私有的网络,完全不连接到互联网,你实际上可以设置自己的完全私有的名称层次结构并自行运行 DNS。在这种情况下,你是 DNS 根的负责人,可以使用你喜欢的任何命名系统。

这种方法有时被认为很有吸引力,因为你可以然后在小型网络中使用非常简单的机器名称,而无需进行任何公共注册或使用与全球层次结构相对应的名称。例如,XYZ 工业的会计计算机可以命名为 accounting,而不是 accounting.xyzindustries.com,在内部它可以是 accounting。在访问资源时,你也可以将这些名称与真实 DNS 名称混合使用。例如,Joe 的机器可以简单地称为 joe,而 UPS 的网站当然仍然是 www.ups.com。

这种私有和公共名称混合的最常见例子是为计算机的环回地址定义私有本地名称。大多数 Windows 和 UNIX 机器将名称localhost定义为地址 127.0.0.1,这意味着在任何 TCP/IP 机器上都是“这台计算机”。

第五十五章。DNS 名称服务器概念和操作

无标题图片

在所有组合起来形成域名系统(DNS)的组件和功能元素中,名称服务器可能是最重要的。这些服务器可以是专用设备,也可以是在执行其他任务的机器上运行的软件进程。它们存储和管理有关域的信息,并响应用户的解析请求——在某些情况下,每天可能数百万次。了解它们如何执行这项最基本的工作以及它们负责的许多支持性工作对于理解 DNS 的整体运作至关重要。

在本章中,我将介绍与 DNS 名称服务器相关的概念,并解释它们是如何运作的。我首先概述 DNS 名称服务器功能和一般操作。我描述了 DNS 名称服务器数据如何存储在资源记录中以及类别的角色。我讨论了 DNS 中名称服务器的不同角色,并解释了至关重要的根名称服务器。我还讨论了 DNS 区域的管理、域名联系和区域传输的概念,以及如何使用缓存和负载均衡来提高 DNS 的效率。最后,我简要概述了几个对基本 DNS 服务器操作进行改进的增强功能,包括新的 Notify 和 Update 消息类型以及增量区域传输。

小贴士

相关信息 本节中的信息应被视为与以下章节中 DNS 解析器相关的补充信息

DNS 一般操作

命名系统的三个主要功能是创建命名空间、执行命名注册以及提供命名解析服务。前几章描述了 DNS 如何使用分层树结构来构建其命名空间(第五十三章):

RR 字段格式(二进制)表示 命名服务器需要通过在 DNS 消息中发送 RR 来响应对名称信息的查询。显然,我们希望尽可能高效地完成这项工作,因此每个 RR 都使用一种特殊的字段格式内部存储,这种格式类似于其他协议中用于消息的许多字段格式。所有 RR 都使用一种通用的字段格式来表示它们的一些字段,然后有一个特定于 RR 类型的独特部分。

主文件(文本)表示 计算机乐于交换二进制编码的字段格式,并且没有问题记住例如,RR 类型 15 对应于邮件交换(MX)记录。然而,人类管理员希望能够快速轻松地维护 DNS 信息,而无需记住难以理解的代码或处理二进制值。因此,DNS 使用主文件格式作为其用户-机器界面,这使得可以以文本形式指定 RR,以便更容易维护。

DNS RR 主文件和二进制字段格式

图 55-1. DNS RR 主文件和二进制字段格式

为了满足人类和计算机的需求,DNS 为 RR 中存储的数据使用两种表示形式。管理员在文本 DNS 主文件中输入和维护信息。这些文件由 DNS 服务器软件读取,并在内部以二进制格式存储,以回答 DNS 请求。

RRs 和主文件的使用

每个节点可能具有可变数量的记录,具体取决于节点类型和为其保留的信息。当 DNS 信息发生变化时,通过修改服务器计算机上的文本主文件的管理员添加、更改或删除 RR。然后,DNS 服务器软件将这些文件读入内存,解析(解释),并转换为二进制形式。然后它们就准备好用于解决 DNS 名称请求和其他查询。我在 第五十七章 中描述了二进制 RR 字段格式和主文件格式。

小贴士

关键概念 DNS 命名服务器以 资源记录 (RR) 的形式存储 DNS 信息。每个 RR 包含 DNS 树中节点特定类型的信息。RR 有两种表示形式:传统的二进制字段格式用于 DNS 命名服务器和解析器之间的通信,而文本 主文件 由管理员编辑以管理 DNS 区域。

常见 RR 类型

主要 DNS 标准,RFC 1034 和 1035,定义了多种 RR 类型。随着时间的推移,该列表已发生变化,新的 RR 类型在后续标准中被创建,而其他 RR 的使用方式发生了变化。与其他互联网参数一样,DNS RR 类型的列表由互联网数字分配机构 (IANA) 维护。同样,与其他互联网参数一样,DNS 中实际上定义了数十种 RR,但只有少数被广泛使用;其他现在已过时,用于特殊目的或具有实验性质。当前 DNS 资源记录列表维护在一个文件中,该文件可以在 www.iana.org/assignments/dns-parameters 找到。

表 55-1 总结了最重要的 RR 类型。对于每一种类型,我都展示了记录的数值类型值,该值用于在消息交换中识别 RR 类型,以及在主文件中使用的文本代码。

表 55-1. 常见 DNS 资源记录摘要

RR 类型值 RR 文本代码 RR 类型 描述
1 A 地址 包含一个 32 位 IP 地址。这是 DNS 的“精髓”,因为它是存储节点地址以进行名称解析的地方。
2 NS 命名服务器 指定权威于该区域的 DNS 命名服务器名称。每个区域必须至少有一个指向其主 DNS 服务器的 NS 记录,并且该名称也必须有一个有效的地址 (A) 记录。
5 CNAME 规范名称 用于定义指向节点真实名称的别名。CNAME 记录提供了此别名与节点规范(真实)名称之间的映射。它通常用于通过让外部用户使用不变的别名来隐藏内部 DNS 结构的变化,同时根据组织的需求修改内部名称。有关示例,请参阅第五十六章中关于名称解析的讨论。第五十六章。
6 SOA 权限起始 用于标记 DNS 区域的开始并提供有关该区域的重要信息。每个区域必须恰好有一个 SOA 记录,其中包含区域名称、其主(主)授权服务器名称以及技术细节,例如管理员电子邮件地址和从(辅助)名称服务器更新的参数。
12 PTR 指针 提供对名称空间中另一个位置的指针。这些记录最著名的用途是通过 IN-ADDR.ARPA 域(在第五十四章中描述)进行反向解析。
15 MX 邮件交换 指定负责处理发送到该域的电子邮件的位置(设备名称)。
16 TXT 文本字符串 允许存储与域名相关联的任意附加文本。

所有这些 RR 都以不同的方式用于定义区域及其内部的设备,然后允许进行名称解析和其他功能。您将在第五十六章(涵盖名称解析)中详细了解它们的使用方法。您还可以在第五十七章(专门介绍 RR 字段格式)中找到一些更详细的描述。第五十七章。

小贴士

相关信息 有关 IPv6 DNS 支持的特定 RR 类型,请参阅第五十七章末尾的主题。第五十七章。

RR 类别

最后,我想提及关于资源记录(RR)的一个历史性注释。当 DNS 首次创建时,其发明者希望它尽可能通用。为此,他们设计得使其能够理论上为多种底层协议提供名称服务;也就是说,DNS 可以同时支持 TCP/IP 以及其他协议。

当然,协议有不同的寻址方案,对名称解析的需求也各不相同。因此,DNS 被定义为每个协议都可以有一组独特的 RR 类型。每组 RR 类型被称为一个类别。技术上,必须使用类别标识符和 RR 类型来标识 RR。与 RR 类型一样,类别有一个数字代码和一个文本缩写。TCP/IP 的类别使用数字 1,文本代码为 IN(代表互联网)。

实际上,这种关于多个 RR 类别的概念从未流行起来。据我所知,今天 DNS 仅用于 TCP/IP。(可能有少数例外。)RFC 1035 定义了几个其他类别,并在 IANA DNS 参数列表中列出,但它们是相对不为人知的、实验性的或过时的网络类型,例如 CSNET、CHAOS 和 Hesiod。你仍然会在 DNS 消息和 RR 格式的规范中看到这个类别的概念,但今天实际上只有一个类别:IN,代表 TCP/IP。因此,在大多数情况下,可以在 DNS 相关命令和数据条目中省略类别名称,默认情况下将假设为 IN。

小贴士

关键概念 DNS 标准最初是为了允许它们与多个协议一起工作而创建的,通过指定每个 RR 的类别。今天,唯一常用的类别是 TCP/IP 的类别,称为 IN(代表互联网)。

DNS 名称服务器类型和角色

到目前为止,我们已经探讨了 DNS 服务器的功能,重点是存储名称服务器信息的重要任务。互联网上有数以千计的 DNS 服务器,并且它们并不都以相同的方式使用。每个 DNS 服务器在名称系统的整体运行中都有特定的角色。不同类型的服务器也以各种方式相互交互。

主(主)/从(辅助)服务器

每个区域至少需要一个负责该区域的 DNS 名称服务器。这些 DNS 名称服务器被称为该区域的权威服务器,因为它们包含描述该区域的完整 RR 集合。当任何互联网设备想要了解有关区域的信息时,它会咨询其权威服务器之一。

从严格的理论角度来看,每个区域或域有一个名称服务器就足以提供整个 DNS 名称结构的名称解析服务。然而,从实现的角度来看,每个名称空间部分只有一个名称服务器并不是一个明智的选择。相反,每个区域通常至少与两个名称服务器相关联:一个主控名称服务器,以及一个辅助从属名称服务器。一些区域可能有多个辅助名称服务器。

注意

在 DNS 标准中,经常使用主和从术语来指代区域两个权威服务器的角色。然而,现在主和从是首选术语,因为主和从有些含糊不清,并在其他上下文中使用。你应该准备好看到这两个术语都被使用

主域名服务器显然是最重要的服务器。该区域的 RR 主文件保存在这个域名服务器上,因此主域名服务器是关于该区域信息的最终权威。然而,有几个原因说明从服务器也很重要:

冗余 如果只有一个域名服务器并且它失败了,将没有人能够将诸如www.xyzindustries.com之类的名称解析为 IP 地址,这将是一件糟糕的事情。从域名服务器作为它们支持的主服务器的备份。冗余是在设置主从域名服务器时最重要的考虑因素。在服务器室中将两台机器并排放置,连接到相同的电源服务,都连接到互联网,使用相同的互联网服务提供商(ISP),并将一台作为主 DNS 服务器,另一台作为从服务器并不是一个明智的选择。理想情况下,主服务器和辅助服务器应该尽可能独立;它们应该在物理上相距很远,并且有独立的互联网连接。

维护 当有多个服务器时,我们可以在需要时轻松地将主服务器关闭进行维护,而不会中断域名解析服务。

负载处理 忙碌的区域可以使用多个服务器来分散域名解析请求的负载,以提高性能。

效率 在许多情况下,为了提高效率,将域名服务器放置在特定的地理位置是有利的。例如,一家公司可能在遥远的地方有一个办公室,使用低速广域网链路连接。为了减少通过该链路的域名解析流量,让该区域的信息在连接两端的域名服务器上可用是有意义的,这需要两个物理服务器。

正如“master”和“slave”这两个名称所暗示的,辅助域名服务器不是关于一个区域信息的原始来源。它们通常不是从人工编辑的主文件中获取 RR,而是从主服务器的更新中获取。这是通过一个称为“区域传输”的过程来完成的。这些传输定期执行,以确保从服务器保持最新。从服务器然后可以响应带有当前信息的域名解析请求。主服务器和从服务器都被认为是该区域的权威。

域名服务器角色

一个区域的 master 和 slave 角色是逻辑上的,并不总是对应于单个物理硬件设备。在以下情况下,单个物理域名服务器可以扮演多个角色:

  • 它可以是一个区域的主域名服务器,也可以是多个区域的主域名服务器。在这种情况下,每个区域都有一个独特的 RR 集合,这些 RR 集合被保存在单独的主文件中。

  • 它可以是为多个区域提供从域名服务器。

  • 它也可以是某些区域的主域名服务器,同时也是其他区域的主域名服务器。

然而,请注意,单个物理名称服务器不能是同一区域的 master 和 slave 服务器。

小贴士

关键概念一个区域的 master DNS 服务器是其主服务器,它维护 DNS 信息的主副本。大多数 DNS 区域也至少有一个从服务器或辅助 DNS 服务器。这些服务器很重要,因为它们作为主服务器的备份,还可以帮助分担繁忙区域中响应请求的负载。辅助名称服务器定期从主服务器获取信息。主服务器和从服务器都被认为是它们维护的数据所在区域的权威服务器。

仅缓存名称服务器

为了提高效率,所有 DNS 服务器——无论是主服务器还是从服务器——都会执行 DNS 信息的缓存,以便在不久的将来如果需要再次使用。 (缓存将在本章后面的“名称服务器缓存”部分中描述。)缓存的重要性非常显著,以至于一些服务器仅用于从其他 DNS 服务器缓存信息。不出所料,这些被称为仅缓存名称服务器。

这些名称服务器对任何区域或域名都不是权威的,并且它们不维护任何 RR。它们只能通过联系其他权威的名称服务器来回答名称解析请求,然后转达信息。然后它们将信息存储起来以供未来的请求使用。为什么这样做?原因在于性能。通过战略性的放置,仅缓存服务器可以通过减少对权威服务器的请求来显著提高某些网络中的 DNS 解析性能。

小贴士

关键概念有一些 DNS 服务器不维护自己的 DNS RR,但仅保留来自其他区域的最近使用的信息。这些被称为仅缓存名称服务器,并且对任何区域都不是权威的。

DNS 区域管理、联系人和区域传输

特定 DNS 区域的权威性负责执行各种任务以管理它。区域管理包括与区域相关的所有工作的范围:决定区域内的名称层次结构、指定名称注册的程序、与保持 DNS 服务器运行相关的技术工作,以及各种类型的行政开销。这项工作可能非常小,也可能非常大,具体取决于组织的类型。个人拥有的小型域名不需要太多工作来管理,而大型公司的域名可能需要专门的员工来维护。

域名联系人

重要的是,任何在互联网上的人都能确定域的所有者是谁,这样那个人就可以因为任何原因被找到。在互联网上,每个 DNS 域都与一组三个联系人相关联,这些联系人负责管理域的不同方面:

管理联系人主要联系人,负责整个域名。这个个人或组织被认为是域的总体所有者。

账单联系人 负责处理域名服务和其他会计事项的付款。

技术联系人 负责处理为域名设置 DNS 并确保其正常工作的技术细节的联系人。

对于较小的域名,通常没有单独的账单联系人;它与行政联系人相同。相比之下,在大型和小型域名中,技术联系人通常与行政联系人不同。大型组织会将技术联系人指定为信息技术部门的人员。小型组织通常让他们的 ISP 提供 DNS 服务,在这种情况下,技术联系人将是该 ISP 的某位人员。

小贴士

关键概念 每个 DNS 域名都与一组三个联系人名称相关联,指示谁负责管理它。行政联系人是对域名负有总体责任的个人。账单联系人负责付款问题;这可能与行政联系人相同。技术联系人负责域的技术事宜,通常与行政联系人不同,尤其是在 DNS 服务外包的情况下。

区域传输

区域管理的最终目的是确保区域的信息在区域的主和从域名服务器上保持最新,以便可以有效地提供给名称解析器。因此,区域管理始于决策和行政行动,这些行动导致区域 RR 的变化。这些变化反映在区域主(主)DNS 服务器上的 DNS 主文件的变化中。

相比之下,每个区域的二级 DNS 服务器作为主主服务器的从服务器。它们携带有关区域的信息,但不会从本地编辑的本地主文件中加载信息。相反,它们定期从主域名服务器获取信息。负责此过程的程序称为区域传输

主域名服务器的记录可以随时更新。一旦主域名服务器的记录被更改,从域名服务器的信息就会变得部分过时。这通常不是什么大问题,因为大部分数据仍然准确,二级服务器将继续使用它所拥有的最新信息来响应解析请求。然而,定期更新从服务器显然很重要;如果不这样做,最终它们的数据将变得陈旧且不可靠。为此,有必要定期执行区域传输。

控制区域传输发生的时间

控制区域传输发生的时间需要实现在服务器之间的通信过程,该过程包括两个基本部分。首先,我们需要一个机制,允许从属服务器定期检查主服务器上的数据变化。其次,当需要时,我们必须有一个机制从主域名服务器复制区域记录(RR)到从服务器。

这两种机制都使用了标准的 DNS 查询/响应设施和区域 RR 的特殊字段。特别重要的是区域的权威开始(SOA)记录,它包含几个参数,用于控制区域状态检查和区域传输。虽然这些参数的正式描述可以在 RR 格式描述的第五十七章中找到,但我将在这里讨论它们的使用方法。

当从属域名服务器启动时,它可能对区域一无所知,或者它可能在其本地存储中存储了区域 RR 的副本,这是它上次运行时的情况。在前一种情况下,它必须立即执行完全区域传输,因为它没有任何信息。在后一种情况下,它将从本地存储中读取其最后已知的区域副本;根据配置,它可能立即在主服务器上执行一个轮询以查看数据是否已更改。轮询是通过请求区域的 SOA RR 来完成的。

SOA 记录中的序列号字段包含一个序列号(可能是任意的,也可能被编码以具有特定的含义),它充当主服务器区域数据库的版本号。每当区域的主文件被修改(无论是通过手动编辑还是通过其他方式自动修改)时,此序列号都会增加。因此,从属服务器可以通过查看最近 SOA 记录中的序列号是否大于从属服务器上次轮询主服务器时存储的序列号来检测主服务器上的更改。如果序列号已更改,从属服务器将开始区域传输。

SOA 记录中的其他三个字段控制从属域名服务器用于轮询和更新其信息的时机:

刷新 此字段指定从属服务器在尝试检查主服务器上的更新之间等待的秒数。假设从属服务器可以建立联系,这是从属服务器上的数据在主服务器发生变化时可能变得过时的最长时间段。

重试 此字段控制从属服务器在尝试再次与主服务器联系之前必须等待多长时间,如果其最后一次尝试失败。这用于防止快速连续尝试联系主服务器,这可能会阻塞网络。

过期 如果由于任何原因,从属名称服务器无法与主服务器联系给定字段值表示的几秒钟,它必须假设它拥有的信息已过时,并停止使用它。这意味着它将停止作为该区域的权威名称服务器行事,直到它收到更新。

这些参数是区域 SOA 记录的一部分,这使区域管理员完全控制主名称服务器更新的频率。在一个变化很少的小区域中,从属服务器进行检查的间隔可以增加;对于较大的区域或经常更改的区域,刷新间隔可以减少。

区域传输机制

当需要区域传输时,它通过向主服务器发送 DNS 查询来完成,使用的是用于名称解析的常规 DNS 查询/响应消息方法(下一节将讨论)。用于启动区域传输的特殊 DNS 问题类型称为 AXFR(地址传输)。服务器随后将使用一系列 DNS 响应消息传输该区域的 RR(假设请求传输的服务器有权这样做)。由于区域传输必须可靠地接收,并且要发送的数据量很大且需要管理,因此必须首先建立并使用传输控制协议(TCP)会话来执行区域传输。这与用于常规 DNS 消息的更简单的用户数据报协议(UDP)传输方式形成对比(如第五十七章开头讨论的 DNS 中使用 UDP 和 TCP 的部分所述)。

一旦区域传输完成,从属名称服务器将更新其数据库并返回常规操作。它将继续每刷新秒对主服务器进行常规轮询。如果它遇到常规轮询的问题,它将在重试秒后再次尝试。最后,如果经过的时间等于过期秒数,主名称服务器将停止从该区域提供数据,直到它与主名称服务器重新建立联系。

小贴士

关键概念 从属名称服务器不是由管理员直接管理其 DNS 信息。相反,它们通过称为区域传输的过程定期从其主名称服务器获取信息。在权威起始(SOA)DNS RR 中的几个字段控制区域传输过程,包括指定传输的频率以及从属名称服务器如何处理无法联系主服务器等问题条件。

注意,DNS 通知功能是对基本区域状态检查/区域传输模型的增强。它允许主服务器在主数据库发生变化时通知从服务器。另一个新功能允许只传输区域的一部分而不是整个区域。有关更多信息,请参阅本章后面关于 DNS 名称服务器增强的讨论。

DNS 根名称服务器

DNS 强烈围绕分层结构的概念。名称空间、注册机构和名称服务器都排列成树状结构。像这些结构一样,名称解析过程也是分层的。正如第五十三章中解释的那样,完全合格域名(FQDN)是通过从最不具体的域名元素(标签)开始,逐步向最具体的一个进行解析。

自然地,每个名称的最不具体部分是整个 DNS 结构存在的根节点。这意味着,如果没有缓存和其他性能增强,所有名称解析都从名称树的根开始。我们在这里找到一组负责 DNS 根的名称服务器功能:DNS 根名称服务器

像所有名称服务器一样,DNS 根名称服务器存储有关根区域内所有节点的信息,并提供名称解析服务。这包括某些特定的顶级域名(TLD)和子域名。然而,大多数 TLD 都有自己的区域。根名称服务器被用作获取每个这些 TLD 的权威服务器的名称和地址的“首选”地点。例如,如果我们想解析名称www.xyzindustries.co.uk,根名称服务器就是解析器找到负责.UK 的名称服务器的地方。

根名称服务器冗余

显然,这些根名称服务器对于整个 DNS 系统的运行至关重要。如果发生任何导致根名称服务器停止运行的情况,整个 DNS 系统将基本关闭。因此,显然不仅仅有一个根服务器,也不是两个或三个;目前有(目前)十三台不同的根名称服务器。

事实上,实际上物理服务器的数量远超过 13 台。这 13 个名称服务器中的大多数都是几个独立物理硬件服务器的集群实现。有些是分布在不同物理位置的分布式服务器集合。最好的例子是 F 根服务器,它已经在世界各地以超过一打的镜像形式实现,以提供更好的服务。

对于选择一个常规域的辅助域名服务器而言,冗余原则是一个好主意,显然这一点在根域名服务器上更是如此。这就是为什么组成 13 个根服务器的各种物理设备都分布在全球不同的地方。其中许多位于美国,但这些服务器遍布全国许多地方(尽管集中在加利福尼亚的几个热点地区以及华盛顿特区附近),并且配置了不同的网络来连接互联网。

根域名服务器当然非常强大。尽管有几十台硬件设备来分散负载,但它们必须每天 24 小时处理大量数据。它们由网络专业人员运行,确保它们高效运行。互联网标准 RFC 2870,“根域名服务器操作要求”,规定了这些域名服务器的基本规则和实践。它规定了确保服务器安全以及避免由于它们的关键作用而导致的性能问题的详细程序。

小贴士

关键概念 DNS 根及其顶级域(TLD)的信息由一组根域名服务器管理。这些服务器对于 DNS 的运行至关重要。它们被安排成 13 个组,并在全球范围内物理分布。

尽管已经采取了所有努力以确保根服务器广泛分布且安全,但它们仍然共同代表了全球互联网的一个弱点。数以百万计的人依赖于这些服务器。过去曾发生过互联网上的恶意元素试图通过攻击根域名服务器来破坏 DNS 的事件。一个广为人知的事件是 2002 年 10 月 21 日对根服务器的拒绝服务(DoS)攻击。攻击失败了,但它显著提高了人们对这些服务器重要性的认识以及 DNS 安全的重要性。

当前根域名服务器

最初,根域名服务器被赋予了反映运行它们的组织的域名。在这些历史名称中,我们可以看到互联网发展中的大玩家的名单:信息科学研究所(ISI)、国家航空航天局(NASA)、美国军事以及其他机构。其中一些服务器仍然由政府机构或美国军事运行,在这些机构中可以实施额外的安全措施来保护它们。然而,为了方便起见,现在所有根域名服务器都在特殊域名 root-servers.net 中赋予字母名称。

表 55-2 显示了截至本书出版日期的 DNS 根域名服务器的最新信息。为了您的兴趣和娱乐,我还将这些服务器的位置绘制在 图 55-2 中。

表 55-2. 因特网 DNS 根域名服务器

根服务器名称 IP 地址 历史名称 位置
a.root-servers.net 198.41.0.4 ns.internic.net Dulles, VA, U.S.
b.root-servers.net 128.9.0.107 ns1.isi.edu Marina Del Rey, CA, U.S.
c.root-servers.net 192.33.4.12 c.psi.net Herndon, VA and Los Angeles, CA, U.S.
d.root-servers.net 128.8.10.90 terp.umd.edu College Park, MD, U.S.
e.root-servers.net 192.203.230.10 ns.nasa.gov Mountain View, CA, U.S.
f.root-servers.net 192.5.5.241 ns.isc.org Auckland, New Zealand; Sao Paulo, Brazil; Hong Kong, China; Johannesburg, South Africa; Los Angeles, CA, U.S.; New York, NY, U.S.; Madrid, Spain; Palo Alto, CA, U.S.; Rome, Italy; Seoul, Korea; San Francisco, CA, U.S.; San Jose, CA, U.S.; Ottawa, ON, Canada
g.root-servers.net 192.112.36.4 ns.nic.ddn.mil Vienna, VA, U.S.
h.root-servers.net 128.63.2.53 aos.arl.army.mil Aberdeen, MD, U.S.
i.root-servers.net 192.36.148.17 nic.nordu.net Stockholm, Sweden; Helsinki, Finland
j.root-servers.net 192.58.128.30 Dulles, VA, U.S.; Mountain View, CA, U.S.; Sterling, VA, U.S.; Seattle, WA, U.S.; Atlanta, GA, U.S.; Los Angeles, CA, U.S.; Amsterdam, The Netherlands
k.root-servers.net 193.0.14.129 London, UK; Amsterdam, The Netherlands
l.root-servers.net 198.32.64.12 Los Angeles, CA, U.S.
m.root-servers.net 202.12.27.33 Tokyo, Japan

因特网 DNS 根域名服务器的地理位置

图 55-2. 因特网 DNS 根域名服务器的地理位置

当前根域名服务器的列表可以在文件 ftp://ftp.rs.internic.net/domain/named.root 中找到。您也可以在 www.root-servers.org 以更用户友好的格式找到这些信息。

DNS 命名服务器缓存

名称服务器所做的大部分基础工作是对名称解析请求做出响应。繁忙的服务器——如根名称服务器、携带顶级域名(TLD)区域信息的那些服务器,以及服务于非常繁忙区域的服务器——必须每秒处理数百甚至数千个名称解析请求。每个请求都需要时间和资源来解析,并且会占用网络带宽来传输数据。因此,DNS 服务器实现必须采用机制来提高其效率并减少不必要的名称解析请求。其中最重要的机制之一就是 缓存

名称服务器缓存

单词 cache 指的是存储的地方,或者存放某物的场所。在计算机世界中,这个术语通常指的是为存储最近获取的信息而保留的内存区域,以便再次使用。在 DNS 的情况下,缓存是由 DNS 名称服务器用来存储最近名称解析和其他请求的结果,这样如果请求再次发生,就可以从缓存中满足请求,而不需要再次完整地运行名称解析过程。由于大多数人使用计算机的方式,一个特定的请求通常会被对同一名称的另一个请求所跟随,因此缓存可以显著减少导致完整名称解析过程的请求数量。

举例说明是最好的方式。假设你正在使用公司局域网上的一个主机。这个主机可能被配置为使用公司的 DNS 名称服务器来处理解析请求。你将 www.xyzindustries.com 输入到你的网络浏览器中,这会导致对该地址进行解析尝试。很可能你的本地 DNS 服务器不知道这个名称,因此它将遵循完整的名称解析过程(在 第五十六章 中描述)来获取其地址。完成这些后,你的本地 DNS 服务器将 缓存 名称 www.xyzindustries.com 及其相关的地址。

如果你点击该网站页面的链接,新页面可能也位于 www.xyzindustries.com 网站上。这将导致另一个 DNS 解析请求被发送到你的本地 DNS 服务器。然而,这一次,本地服务器不需要执行解析。它记得这个名称已经在它的缓存中,并立即返回保存的地址。哇!你得到了更快的答案,并且避免了不必要的互联网流量。

小贴士

关键概念 缓存 是一个提高效率的重要特性,通过消除对最近已解析名称的不必要请求来减少 DNS 消息流量。每当解析一个名称时,产生的 DNS 信息就会被缓存,以便在之后不久发生的后续请求中使用。

当然,事情并不完全这么简单。在包括 DNS 中使用的缓存系统在内的每个缓存系统中都会出现一个非常重要的问题,那就是缓存的新鲜度问题。

缓存数据持久性和生存时间间隔

假设您的本地 DNS 服务器解析了名称www.xyzindustries.com,然后缓存了其地址。在这个例子中,如果您在 XYZ Industries 主页加载后几秒钟点击链接,您可能不太关心 DNS 数据的新鲜程度。但如果您关闭计算机去度假两周,然后回来工作并在浏览器中再次输入该名称,如果您的本地服务器仍然在缓存中保留该名称,您如何知道www.xyzindustries.com的 IP 地址在那两周期间没有发生变化?

使用两种不同的机制来解决这个问题。第一种机制是,当数据被缓存时,缓存服务器也会记录下数据来源的授权服务器。当一个解析器(客户端)请求域名解析,并且地址是从缓存中获取的,服务器会将答案标记为非授权的,以清楚地告诉客户端该名称来自缓存。服务器还会提供最初提供数据的授权服务器名称。

客户端然后有选择权:它可以使用非授权的答案,或者从授权服务器发出请求以获取新的名称解析。这是性能(使用缓存数据)和时效性(每次都请求新的解析)之间的权衡。通常,可以安全地使用缓存数据,因为 DNS 信息并不经常改变。

确保缓存数据不会过时的第二种技术是限制 DNS 缓存数据的持久性的程序。每个 RR 都与一个时间间隔相关联,称为生存时间(TTL)。每当从服务器读取 RR 时,记录的 TTL 也会被读取。任何缓存记录的服务器都应该在该时间间隔过期后丢弃该记录。

每个区域也与应用于该区域所有记录的 TTL 字段的默认值相关联。这允许管理员为区域中的所有记录选择一个 TTL 值,而无需为每个记录单独输入 TTL 数字。同时,管理员可以为需要不同默认值的任何记录分配一个覆盖 TTL 值。这个默认 TTL 最初保存在每个区域的特殊 SOA RR 中,但现在使用区域主文件中的特殊指令来处理。

注意

这个生存时间(TTL)字段与在互联网协议(IP)数据报中使用的字段无关(见第二十一章). 显然,IP 和 DNS 是完全不同的协议,而且不仅如此,IP 和 DNS 中的 TTL 字段根本不具有相同的含义

值得强调的是,DNS 将缓存控制权交给了记录的所有者,而不是运行 DNS 服务器进行缓存的人。虽然特定的缓存服务器可以覆盖 TTL 并指定数据在其缓存中保留的时间,但 DNS 不应该这样工作。按记录指定 TTL 的能力允许根据个别数据元素的需求调整缓存数据的持久性。经常变化的数据可以分配较小的 TTL 值;不常修改的记录可以分配较高的 TTL。选择 TTL 值必须谨慎。这是性能(通过较高的 TTL 值优化,减少对缓存数据的查询次数)和数据新鲜度(随着 TTL 值的降低而增加)之间的另一个权衡。

小贴士

关键概念 缓存信息可能会随着时间的推移而变得过时,并导致向查询发送错误响应。每个 RR 都可以与一个时间间隔相关联,称为生存时间(TTL),它指定记录可以在缓存中保留多长时间。此字段的值由 RR 的所有者控制,可以针对每种 RR 类型的具体需求进行调整。

负缓存

经典 DNS 缓存只存储成功的名称解析结果。DNS 服务器也可以缓存名称解析尝试失败的结果;这被称为负缓存。为了扩展本节中使用的示例,假设你错误地认为公司网站的名称是www.xyz-industries.com并将其输入到浏览器中。你的本地 DNS 服务器将无法解析该名称,并将其标记为无法解析的缓存条目——一个负缓存条目。

假设你因为有人在内部备忘录中打字错误而错误地输入了名称。如果同事后来尝试了相同的名称,DNS 服务器会说:“我已经知道这是一个无效的名称,”并且不会再次尝试解析它。由于没有无效名称的 RR,服务器本身必须决定缓存这些负面信息的时间。负缓存可以提高性能,因为解析一个不存在的名称需要资源,就像解析一个现有的名称一样。请注意,常规缓存有时被称为正缓存,以区别于负缓存。

在区域中用于负缓存的值现在由每个区域的 SOA RR 中的最小字段指定。如前所述,这以前用于指定区域的默认 TTL。

DNS 名称服务器负载均衡

地址记录(A)RR 是 DNS 中最基本的一个,因为它记录了域名与 IP 地址之间的实际映射。让我们暂时详细考虑这个句子中的一个单词。不,我的意思不是 addressRRmapping。我是指单词 an

地址记录只提及每个域名的一个地址。这意味着每个域名只映射到单个物理硬件设备。当特定服务器或其他设备需要处理的请求数量相对较少时,这并不是问题;通常可以使用单个物理硬件设备来实现该功能。如果服务器变得更繁忙,通常的解决方案是向问题投入更多硬件——获得更大的机器。

然而,在大型互联网上的一些主机,特别是互联网,拥有必须处理来自许多客户端的大量流量的服务器。例如,像 www.cnn.comwww.microsoft.com 这样的网站,根本不存在可以轻松处理这些流量而不变得难以管理的单个硬件设备。这些网站必须使用一种称为 负载均衡 的技术来分散对多个硬件服务器的请求。

使用多个地址记录来分散对域名的请求

实现负载均衡的一种简单方法是有多个机器名称。例如,CNN 可以创建几个不同的网站,称为 www1.cnn.comwww2.cnn.com 等,每个网站都指向不同的硬件设备。DNS 当然支持这种类型的解决方案。这种解决方案的问题在于它很麻烦;它要求用户记住多个服务器名称。

如果我们能自动平衡负载那就更好了。DNS 通过提供一种简单的方式来实施负载均衡来支持这一点。而不是为名称指定单个地址记录,我们可以创建多个这样的记录,从而将多个 IP 地址与特定的 DNS 名称关联起来。当我们这样做时,每次该名称存在的区域的主权名称服务器解析该名称时,它都会将列表上的所有地址发送回请求者。服务器会改变响应中提供的地址的顺序,随机或顺序、循环方式选择顺序。客户端通常会使用服务器返回的列表中的第一个地址,因此通过改变列表,服务器确保对该设备名称的请求被解析到多个硬件单元。

小贴士

关键概念 与为 DNS 域名创建单个地址(A)RR 相比,可以创建多个。这会将多个 IP 地址与一个名称关联起来,可以用来将一个域名的多个请求分散到多个物理 IP 设备上。这允许 DNS 为繁忙的互联网服务器实现负载均衡。

随着互联网流量的增加,负载均衡变得越来越流行。在 2003 年初,我看到一项调查表明,当时大约有 10%的互联网名称使用了负载均衡——这是一个相当大的数字。大多数使用了两个或三个地址,但有些使用了多达六十个地址!顺便说一下,在最后一次检查时,www.cnn.com与八个不同的 IP 地址相关联。(您可以使用描述在第八十八章中的host命令来检查与名称相关联的地址数量。)

使用多个 DNS 服务器分散 DNS 请求

术语DNS 负载均衡与我在上一节中描述的含义完全不同。在讨论 DNS 服务器角色时,我提到了每个区域除了主(主)服务器外,至少应该有一个从(辅助)DNS 服务器。通常认为这样做的主要原因是冗余,以防主服务器出现故障。然而,拥有一个从服务器还可以允许 DNS 解析请求的负载在服务器之间进行平衡。实际上,一些繁忙的域名正是因为这个原因而拥有超过两个服务器。

因此,DNS 负载均衡可以指使用 DNS 将请求(如网页请求)的负载分散到使用 DNS 命名的设备,或者是指将 DNS 请求本身的负载进行分散。

DNS 名称服务器增强

DNS 服务器操作的基本原理,如本章前面各节所述,已在主要的 DNS 标准 RFC 1034 和 1035 中指定。按照计算机行业的标准,这些文件相当古老;它们是在 1987 年发布的。DNS 的设计者值得赞扬,他们最初在 DNS 协议中放入的大部分内容至今仍然有效并在使用中。DNS 的创造者知道它必须能够扩展到非常大的规模,并且该系统已经成功处理了互联网扩展到远远超出 15 年前任何人所能想象的程度。

如最初定义的那样,DNS 要求通过编辑主服务器上的主文件来手动更新区域的信息。然后,使用本章前面描述的轮询/区域传输机制,将整个区域复制到从服务器。当互联网相对较小且区域变化不频繁时,这种方法是令人满意的。然而,在现代互联网中,大型区域可能需要几乎持续不断地更改其 RR。手动编辑和不断复制主文件可能不切实际,尤其是当它们变得很大时,而从服务器在区域传输之间过时可能会导致可靠性和性能问题。因此,多年来提出了对 DNS 服务器操作的几个改进。在这里,我们将更详细地探讨其中的三个:DNS Notify、增量区域传输和动态 DNS。

自动化区域传输:DNS Notify

许多 DNS 管理员想要解决的第一个问题是依赖轮询来更新从服务器。想象一下,你在你最喜欢的在线音乐商店订购了一张新的音乐 CD,但它缺货——已预订。哪种方式更有意义:每六小时给你打电话询问你的 CD 是否到了,还是商店在 CD 出现时直接给你打电话?

答案如此明显,以至于问题似乎很荒谬。然而,DNS 使用第一种模型:从服务器必须不断调用其区域主服务器并询问他们:“有什么变化吗?”这不仅产生了不必要的流量,而且导致从服务器在主服务器确实更改直到下一次轮询执行期间过时。调整区域的刷新时间只允许在变化发生时在更多轮询和更多陈旧性之间做出选择;两者都不是真正的好方法。

为了改善这种情况,一种新的技术被开发并在 1996 年发布的 RFC 1996 中正式化(奇怪的巧合!)。这个标准,“一种用于快速通知区域变化的机制(DNS NOTIFY)”,定义了一种新的 DNS 消息类型,称为Notify,并描述了其使用协议。Notify 消息是标准 DNS 消息类型的一种变体,其中一些字段被重新定义以支持这个新特性。

如果主服务器和从服务器都支持这个特性,当对一个 RR 进行修改时,主服务器将自动向其从服务器发送一个 Notify 消息,说:“你的 CD 已经到了!”嗯…“数据库已经更改。”然后从服务器就像其刷新计时器刚刚到期一样行动。启用此功能允许刷新间隔显著增加,因为从服务器不需要不断轮询主服务器以获取更改。

小贴士

关键概念 可选的 DNS Notify 功能允许主名称服务器在区域中更改时通知从属名称服务器。这有两个优点:它减少了从属服务器查找 DNS 信息是否已更改的不必要轮询,并且它还减少了从属名称服务器具有过时记录的时间。

提高区域传输效率:增量传输

正常 DNS 的第二个问题是,每当对区域任何部分进行更改时,都需要传输整个区域。互联网上有许多区域具有真正巨大的主文件,这些文件不断变化。例如,考虑 .COM 区域的主文件。每次更改甚至一条记录时都必须将整个数据库复制到从属名称服务器,这效率低下——简直是疯狂!

RFC 1995,“DNS 中的增量区域传输”指定了一种新的区域传输类型,称为 增量区域传输。当在区域的名称服务器上实现此功能时,主服务器会跟踪对数据库所做的最新更改。每次从属服务器确定已发生更改并且从属服务器的数据库需要更新时,它都会向主服务器发送一个包含从属服务器当前数据库副本序列号的 IXFR(增量传输)查询。然后主服务器查看自该序列号以来哪些 RR 已更改,并将仅更新的 RR 发送到从属服务器。

为了节省存储空间,主服务器显然不会永远保留对其数据库所做的所有更改。它通常会跟踪数据库的最后几次修改,并关联每个修改的序列号。如果从属服务器发送一个包含序列号的 IXFR 请求,该序列号对应的主服务器上仍有最近更改的信息,则只发送更改作为回复。如果请求的序列号如此之旧,以至于主服务器不再具有自该数据库版本以来某些更改的信息,则执行完整区域传输而不是增量传输。

小贴士

关键概念 DNS 的 增量区域传输 增强功能使用一种特殊的消息类型,允许从属名称服务器确定自上次与主服务器同步以来发生了哪些变化。通过仅传输更改,可以显著减少区域传输所需的时间和带宽。

处理动态 IP 地址:DNS 更新/动态 DNS

经典 DNS 的第三个问题是它假设对区域的更改不频繁,因此可以通过手动编辑主文件来处理。有些区域非常大,手动编辑主文件几乎会持续不断。然而,问题不仅仅是不便。常规 DNS 假设主机的 IP 地址相对静态。然而,现代网络利用诸如动态主机配置协议(DHCP)等主机技术(在第三部分-3 中描述),动态地为设备分配 IP 地址。当使用 DHCP 时,一个区域中每个主机的 IP 地址可能每周、每天甚至每小时都会改变!显然,使用人类和文本编辑器跟上这种变化速度是不可能的。

1997 年 4 月,RFC 2136,“域名系统(DNS)中的动态更新(DNS UPDATE)”被发布。该标准描述了基本 DNS 操作的一个增强,允许 DNS 信息动态更新。当此功能实现时,所得到的系统有时被称为动态 DNS(DDNS)

RFC 2136 定义了一种新的 DNS 消息类型:更新消息。像通知消息一样,更新消息是围绕常规 DNS 消息的结构设计的,但对几个字段的含义进行了更改。正如其名所示,更新消息允许在区域的权威名称服务器中选择性地更改 RR。使用特殊消息语法,可以添加、删除或修改 RR。

显然,在使用此功能时必须谨慎,因为我们不希望任何人都可以随意更改我们的主记录。标准指定了一个详细的过程来验证更新消息,以及必须实施的安全程序,以确保服务器只从某些个人或系统接受此类消息。

动态 DNS 允许管理员更容易地进行更改,但它的真正力量只有在将其用于将 DNS 与其他地址相关协议和服务集成时才会显现。动态 DNS 解决了传统 DNS 的一个主要弱点:无法轻松地将主机名与使用类似 DHCP 协议分配的地址关联起来。

当 DNS 服务器支持此功能时,DNS 和 DHCP 可以集成,允许自动地址和名称分配,并在主机的 IP 地址更改时自动更新 DNS 记录。动态 DNS 的一个常见应用是允许那些使用动态分配 IP 地址的服务提供商接入互联网的人使用 DNS 名称。动态 DNS 也被某些目录服务使用,特别是微软的 Active Directory,以将地址与设备名称关联起来。

提示

关键概念 域名系统的一个增强功能,通常称为动态 DNS(DDNS),允许服务器数据库中的 DNS 信息自动更新,而不是总是需要手动编辑主文件。这不仅可以为管理员节省时间和精力,而且还能使 DNS 更好地处理动态地址分配,例如 DHCP 等主机配置协议所执行的类型。

第五十六章。DNS 解析概念和解析器操作

无标题图片

在前三个章节中,我描述了域名系统(DNS)的命名空间、授权、注册机制和名称服务器。所有这些元素都可以被认为是 DNS 基础设施的一部分;它们是系统必须首先建立的部分,以便能够使用。一旦我们有了这些组件,我们就可以真正着手处理手头的工作:名称解析。这是通过 DNS 客户端执行的一系列特定程序来完成的,这些程序被称为解析器

在本章中,我描述了 DNS 名称解析器和名称解析的过程。我首先概述了 DNS 解析器执行的功能以及它们在一般意义上的工作方式。然后,我描述了 DNS 中使用的两种基本名称解析方法:迭代解析和递归解析。我讨论了解析器如何通过本地解析和缓存来提高效率。我描述了实际名称解析算法的步骤。然后,我涵盖了名称解析的两个特殊情况:使用特殊 IN-ADDR.ARPA 域的逆向名称解析,以及 DNS 如何使用邮件交换资源记录提供邮件支持。

小贴士

相关信息 本节的信息补充了上一章关于 DNS 名称服务器的信息。在此,我假设你对 DNS 服务器至少有基本的了解

DNS 解析器功能和一般操作

名称服务器可以说是 DNS 系统整体中最重要的部分。毕竟,它们存储了系统上的所有数据,并在名称被提供时实际上提供了我们需要的地址。没有这些服务器,DNS 将不复存在。当然,如果没有人请求服务,服务器有什么用呢?系统中的客户端,称为解析器,也很重要,因为它们启动了名称解析的过程。可以说,解析器是“接触地面”的地方。

DNS 解析器的操作在两个主要的 DNS 标准中进行了说明。RFC 1034 描述了解析器执行的功能以及它们在一般意义上的工作方式,包括讨论用于执行名称解析的算法。RFC 1035 更多地涉及解析器的实现细节以及它们如何完成工作的细微之处。几个后续标准对这些基本标准进行了修改,以不同的方式改变了解析器的工作方式。

名称解析服务

就像 DNS 服务器的主要工作是存储 DNS 名称数据并在收到请求时提供服务一样,DNS 解析器的主要工作就是解析。虽然大多数人认为名称解析仅仅是将 DNS 名称转换为 IP 地址的过程,但这只是 DNS 执行的多种解析服务类型之一。以下是一些最常见的 DNS 解析类型:

标准名称解析 以 DNS 名称作为输入,并确定其对应的 IP 地址。

反向名称解析 以 IP 地址作为输入,并确定与之关联的名称。

电子邮件解析 根据消息中使用的电子邮件地址确定发送电子邮件(email)消息的位置。

名称解析器执行的功能

还有其他类型的解析活动,尽管再次强调,大多数名称解析请求都是标准类型的,这使得它成为我们讨论的主要焦点。为了完成这项任务,名称解析器执行一系列相关功能:

提供用户界面 正常的名称解析通常不需要显式运行解析器软件。在你的网页浏览器中,你不必说,“请找到www.xyzindustries.com的 IP 地址,”然后说,“请连接到这个 IP 地址以访问 XYZ Industries。”你只需输入www.xyzindustries.com,名称解析就会发生。这里没有魔法。解析器只是被隐式地调用,而不是显式地调用。网页浏览器识别到输入的是名称而不是 IP 地址,并将其传递给解析器,说,“我需要你解析这个名称,请。”(嘿,礼貌一点总是好的。)解析器负责解析并提供 IP 地址给网页浏览器,浏览器连接到该网站。因此,解析器是用户(无论是人类用户还是软件用户,即浏览器)和 DNS 系统之间的接口。

形成和发送查询 给定一个要解析的名称,DNS 解析器必须使用 DNS 消息系统创建一个适当的查询,确定要执行哪种解析类型,并将查询发送到相应的名称服务器。

处理响应 解析器必须接收来自其发送查询的 DNS 服务器的响应,并决定如何处理回复中的信息。正如你将看到的,可能需要联系多个服务器才能完成特定的名称解析。

小贴士

关键概念 DNS 中的主要客户端是称为 DNS 名称解析器的软件模块。它们负责从客户端软件接收名称,向 DNS 服务器生成解析请求,并处理和返回响应。

这些任务看起来相当简单,在某些方面确实如此,但实施起来可能会相当复杂。解析器可能需要同时处理多个未完成的名称解析。它必须跟踪不同的请求、查询和响应,并确保一切保持清晰。

名称解析器不需要执行像名称服务器那样多的管理任务;在这一点上,客户端通常比服务器简单。然而,许多名称解析器执行的一个重要支持功能是缓存。像名称服务器一样,名称解析器可以缓存它们执行的名称解析结果,以节省时间,如果需要再次进行相同的解析。但是,并非所有解析器都执行缓存。

尽管解析器是与名称解析最相关的 DNS 组件,但名称服务器也可以在某些类型的名称解析中充当客户端。实际上,可以设置一个网络,使得每个客户端机器上的解析器除了将解析请求提交给本地 DNS 服务器外,别无他事。在这种情况下,客户端解析器几乎只是一个外壳,有时被称为stub 解析器。这有利于集中网络中的名称解析,但可能存在性能降低的潜在缺点。

DNS 名称解析技术:迭代和递归解析

传统名称解析将 DNS 名称转换为 IP 地址。在最高层次上,这个过程可以被认为有两个阶段。在第一阶段,我们找到拥有所需信息的 DNS 名称服务器:与特定名称相对应的地址。在第二阶段,我们向该服务器发送包含我们想要解析的名称的请求,然后它返回所需的地址。

有点讽刺的是,第二阶段(将名称映射到地址的实际过程)相当简单。第一阶段——找到正确的服务器——可能是困难的,并且代表了 DNS 名称解析中的大部分工作。虽然这可能令人惊讶,但这却是 DNS 结构的一个可预测的结果。DNS 中的名称信息不是集中的,而是分布在整个服务器层次结构中,每个服务器负责 DNS 名称空间中的一个区域。这意味着我们必须遵循一系列特殊的步骤来找到拥有所需信息的服务器。

域名解析的正式过程与 DNS 名称空间、权威机构和服务器类似树状层次结构。特定 DNS 名称的解析从名称的最一般部分开始,逐步到最具体部分。自然地,每个名称的最一般部分是 DNS 树的,在名称中以尾随点(.)表示,有时省略。下一个最具体的部分是顶级域名(TLD),然后是二级域名,依此类推。DNS 名称服务器之间是相互连接的,即某一层的 DNS 服务器知道下一层负责子域的服务器的名称。

假设我们以 C.B.A.作为完全限定域名(FQDN)。正式来说,每次名称解析都从树的根开始——这就是为什么根名称服务器如此重要的原因。根名称服务器可能对这个名称有权威性,但这可能不是情况;这不是根名称服务器通常被用于的目的。根名称服务器知道的是负责 TLD 的服务器名称:A.. A.的名称服务器可能拥有解析 C.B.A.所需的信息,但它仍然处于较高层次,所以 C.B.A.可能不在其区域内。在这种情况下,它将不知道我们寻求的地址,但它将知道负责 B.A.的服务器名称。反过来,那个名称服务器可能对 C.B.A.有权威性,或者它可能只知道 C.B.A.服务器的地址,该服务器将拥有我们所需的信息。正如你所看到的,在名称解析中可能需要几个不同的服务器。

小贴士

关键概念 由于 DNS 名称信息存储为分布式的数据库,分布在许多服务器上,因此通常不能使用单个请求/响应通信来执行名称解析。首先需要找到拥有解析器所需信息的服务器。这通常需要一系列的消息交换,从根名称服务器开始,逐步向下到包含客户端所需资源记录(RRs)的特定服务器。

DNS 标准实际上定义了两种不同的方法来遵循这个服务器层次结构以发现正确的一个。它们最终都会到达正确的设备,但在需要多个步骤进行解析时,它们在分配解析责任的方式上有所不同。这两种技术是迭代解析递归解析

迭代解析

当客户端向域名服务器发送迭代请求时,服务器会以以下两种方式之一响应:提供请求的答案(对于常规解析,是我们想要的 IP 地址)或者提供另一个拥有信息或更接近该信息的服务器名称。原始客户端随后必须通过向该引用服务器发送新的请求来进行迭代,该服务器再次可能回答它或提供另一个服务器名称。这个过程会一直持续,直到找到正确的服务器。迭代解析方法在图 56-1 中说明。

迭代 DNS 名称解析 在本例中,客户端正在使用严格迭代解析对 C.B.A.进行名称解析。因此,它负责形成所有 DNS 请求并处理所有回复。它首先向这个神话般的根域名服务器发送请求。该服务器没有 C.B.A.的地址,因此它返回了 A 域名服务器的地址。然后客户端向该域名服务器发送查询,该域名服务器将客户端指向 B.A.的服务器。那个域名服务器将客户端引荐给实际上拥有 C.B.A.地址的域名服务器,该服务器将其返回给客户端。与此相对比的是。

图 56-1. 迭代 DNS 名称解析在这个例子中,客户端正在使用严格迭代解析对 C.B.A.进行名称解析。因此,它负责形成所有 DNS 请求并处理所有回复。它首先向这个神话般的根域名服务器发送请求。该服务器没有 C.B.A.的地址,因此它不是仅仅将 A.名称服务器的地址返回给客户端,而是向该服务器本身发送请求。该名称服务器然后将客户端指向 B.A.的服务器。该名称服务器将客户端引荐给实际拥有 C.B.A.地址的名称服务器,该服务器将其返回给客户端。这与图 56-2

图 56-2. 递归 DNS 名称解析 这与图 56-1 中显示的理论 DNS 解析相同(图 56-1, 但这次,客户端请求名称服务器执行递归解析,并且它们同意这样做。与迭代情况一样,客户端将其初始请求发送到根名称服务器。该服务器没有 C.B.A. 的地址,但它没有仅仅返回给客户端 A 名称服务器的地址,而是向该服务器本身发送了一个请求。该名称服务器向 B.A. 的服务器发送请求,该服务器再向 C.B.A. 的服务器发送请求。C.B.A. 的地址随后沿着请求链向上传递,从 C.B.A. 的服务器到 B.A. 的服务器,然后是 A.,然后是根,最后回到客户端。

相比之下,假设你打电话给乔,乔说:“我不知道,但我认为我知道怎么找到答案。”他打电话给约翰,然后是黛比,然后给你打电话,告诉你电话号码。这就像递归解析。

所以,本质上,迭代就像是亲自做这项工作,而递归则像是推卸责任。你可能认为每个人都会总是想使用递归,因为这样可以让别人做工作。这是真的,但如果没有得到允许就推卸责任,这并不被视为好的行为。并不是所有的域名服务器都支持递归,尤其是那些处于层级顶部的服务器。显然,我们不希望某些域名服务器——如根域名服务器、处理.COM 的域名服务器和其他关键顶级域名服务器——因为递归而变得低效。正因为如此,客户端必须请求域名服务器为他们执行递归。递归经常被用在网络上的本地域名服务器中。而不是让客户端的解析器执行迭代解析,解析器通常会产生一个递归请求到本地 DNS 服务器,然后根据需要生成迭代请求到其他服务器。正如你所看到的,递归和迭代请求可以在单个解析过程中结合使用,为整个过程提供显著的灵活性。这一点在本书后面的“DNS 名称解析过程”部分的一个更现实的例子中得到了演示。

再次提醒,为了理解解析的目的,DNS 服务器可以充当客户端。一旦 DNS 服务器接受了一个它自己无法解析的名称的递归解析请求,它就成为了该过程中的客户端。此外,解析器通常知道不止一个本地 DNS 服务器的名称,所以如果到达第一个服务器有问题,他们可以尝试第二个。

小贴士

关键概念 DNS 中的名称解析有两种方法:迭代解析递归解析。在迭代解析中,如果客户端向一个没有所需信息的域名服务器发送请求,服务器会返回一个指向不同域名服务器的指针,客户端会向那个服务器发送新的请求。在递归解析中,如果客户端向一个没有所需信息的服务器发送请求,该服务器会承担向其他服务器发送请求以找到必要记录的责任,然后将它们返回给客户端。执行此操作的服务器在其对其他服务器的请求中扮演客户端的角色。

DNS 名称解析效率改进:缓存和本地解析

从算法的角度来看,基本解析技术——迭代和递归——可以被认为是完整的。通过从顶部(根)开始,逐步向下工作,我们“保证”最终会到达拥有所需信息的服务器。我把“保证”这个词加了引号,因为,就像往常一样,在网络上没有真正的保证——我们可能请求了一个不存在的名称,或者服务器可能有错误的数据,例如。但在没有这种典型问题的情况下,这个过程最终会引导我们找到信息。

问题在于最后一个词:“最终”。迭代和递归解析都会带我们到达正确的服务器,但它们需要很长时间才能完成,尤其是如果我们试图解析的名称位于 DNS 层次结构的深层(例如,F.E.D.C.B.A.)。由于解析经常进行,定义对基本解析过程的改进,尽可能提高效率是有帮助的。

缓存的动机:引用局部性

计算机科学中的一个原则叫做引用局部性,它描述了与计算机(和网络)的使用相关的两种常见现象。第一种,有时被称为空间局部性引用,观察到如果资源靠近最近被引用的另一个资源,那么它更有可能被引用。第二种,时间局部性引用,表示如果资源最近被访问过,那么它更有可能被访问。

我们可以通过浏览网页的例子来观察这两种现象。为了观察空间局部性,注意当你访问像www.tcpipguide.com这样的网站时会发生什么。最初的请求是向服务器请求《TCP/IP 指南》的主索引文档。然而,该文档包含指向几个图像和其他项目的链接,所有这些项目也都位于域名tcpipguide.com下。当你浏览网站时,你会点击链接转到其他网页。同样,其中大部分也将位于相同的域名tcpipguide.com下。

这意味着如果我们解析了一个特定的域名,我们很可能在不久的将来还需要再次解析它。每次都询问同一个域名服务器,要求它解析相同的名称,这将是愚蠢的。

第二种现象,时间局部性引用,是你自己可能已经注意到的。你访问最近使用过的资源比访问一年前没有看过的资源更有可能。这意味着维护关于最近使用过的资源的信息可以具有固有的优势。

这两种现象是计算机世界中缓存的一般理由,尤其是在 DNS 服务器中,正如你在第五十五章中看到的。相同的优势也适用于解析器,并且许多解析器也以与服务器类似的方式执行缓存。

名称解析器缓存

在特定的客户端计算机上,一旦解析了特定的名称,它就会被缓存并准备好下一次需要时使用。再次强调,这减少了 DNS 服务器上的流量和负载。(注意,然而,并非所有解析器都会执行缓存。)

你可能想知道为什么我们同时在解析器和服务器上设置缓存。这并不是多余的,看起来可能如此。或者更确切地说,它是多余的,但以好的方式。要理解为什么,我们必须认识到缓存的一个基本权衡是,缓存越靠近数据请求者,性能越好,但覆盖范围越广,距离用户越远。

如果解析器不缓存结果,但我们的本地服务器缓存了,我们可以从服务器的缓存中获取信息,但这需要等待查询和响应的交换。解析器的缓存更靠近用户,因此更高效。同时,这并不免除我们在网络本地 DNS 服务器上进行缓存的需要。服务器距离用户更远,但它的缓存被许多机器共享。它们都可以从其缓存中受益。例如,如果你查找了特定的名称,然后几分钟后另一个人也查找,她可以使用你的缓存解析,即使她第一次输入这个名称。

小贴士

关键概念 除了 DNS 名称服务器执行的缓存外,许多(但并非所有)DNS 解析器还会缓存最近解析请求的结果。在开始名称解析之前检查此缓存,以在多次请求同一名称时节省时间。

名称解析器的缓存遵循与名称服务器缓存相同的一般原则和规则,这些原则和规则在第五十五章(ch55.html "第五十五章。DNS 名称服务器概念和操作")中概述。资源记录(RR)在缓存中保留的时间由其生存时间(TTL)值指定。此外,解析器不会缓存某些查询的结果,例如反向查找,并且如果它们怀疑(无论什么原因)返回的数据不可靠或损坏,也可能不会缓存解析。

本地解析

另一个可以提高解析效率的领域是,当我们试图解析我们自身组织中的计算机名称时。假设你是 XYZ 工业公司的一名员工,想通过文件传输协议(FTP)从sales.xyzindustries.com获取一些销售信息。你的 FTP 客户端将调用你的本地解析器来解析该名称,通过将其发送到你的本地 DNS 服务器。现在,这个位于公司内部的 DNS 服务器从根域名服务器开始解析过程,这明智吗?实际上并不明智。

接受来自网络中解析器本地解析请求的本地 DNS 服务器可能是sales.xyzindustries.com的权威名称服务器。在其他情况下,它可能知道如何直接回答某些解析请求。显然,在向根服务器发起正式自顶向下的解析过程之前,服务器检查是否能够回答解析器的查询是有意义的,因为这可以为客户端提供更快的答案并节省互联网流量。这被称为本地解析

大多数 DNS 服务器都会在开始正式自顶向下的解析过程之前执行此检查,以查看它们是否拥有请求所需的信息。例外的是不维护任何区域信息的 DNS 服务器:仅缓存服务器。在某些情况下,客户端机器上的 DNS 解析器也可能有权访问某些本地区域信息,在这种情况下,它们可以使用这些信息而不是发送解析查询。

注意

大多数操作系统都支持使用旧的主机表机制(在第五十一章中描述,第五十一章),这对于网络上的本地机器很有用。如果一个主机有主机表,解析器将在开始耗时更多的 DNS 解析过程之前检查主机表,看是否可以找到名称的映射。这虽然不是 DNS 的技术组成部分,但通常与 DNS 一起使用

DNS 名称解析过程

在本章的前半部分,我描述了名称解析器的作用,解释了使用迭代和递归解析的基本自顶向下的解析过程,并讨论了如何使用本地解析和缓存来提高解析性能。现在,是时候将这些背景材料结合起来,看看整个名称解析过程是如何工作的了。

如同往常,最好的做法是通过例子来说明。在这里,我将结合两个之前用过的例子:虚构的公司 XYZ 工业公司和不存在的大学,谷歌 plex 大学。

DNS 名称解析的一个简单例子

假设 XYZ 工业公司运行自己的 DNS 服务器,用于xyzindustries.com区域。主域名服务器被称为ns1.xyzindustries.com,而从域名服务器是ns2.xyzindustries.com。这些也被用作客户端机器上解析器的本地 DNS 服务器。在这个例子中,我们将假设,正如通常情况那样,我们的 DNS 服务器将接受公司内部机器的递归请求,但我们不会假设其他机器会接受此类请求。同时,我们也假设服务器和解析器都执行缓存,并且缓存为空。

假设 Googleplex 大学运行自己的 DNS 服务器,用于 googleplex.edu 域名,正如第五十四章中的示例。有三个子域名:finearts.googleplex.edu、compsci.googleplex.edu 和 admin.googleplex.edu。在这些子域名中,compsci.googleplex.edu 位于一个独立的区域,并使用专用服务器,而其他子域名位于 googleplex.edu 区域(见图 54-2。用简化的术语来说,这个过程将涉及以下步骤(图 56-3 传递给它。

  1. 解析器检查其缓存以查看是否已经存储了该名称的地址。如果有,它会立即将其返回给网页浏览器,但在这个假设的情况下,我们假设它没有。解析器还会检查是否有本地主机表文件。如果有,它会扫描文件以查看该名称是否有静态映射。如果有,它会立即使用这些信息解析名称。再次假设它没有,因为那样会很无聊。

  2. 解析器生成一个递归查询并将其发送到ns1.xyzindustries.com(当然使用解析器知道的该服务器的 IP 地址)。

  3. 本地 DNS 服务器接收请求并检查其缓存。再次假设它没有所需的信息。如果有,它会将信息返回给解析器,并标记为非权威信息。服务器还会检查其区域资源记录中是否有可以解析www.net.compsci.googleplex.edu的记录。当然,在这种情况下,它没有,因为它们位于完全不同的域中。

  4. ns1.xyzindustries.com为该名称生成一个迭代请求并将其发送到根名称服务器。

  5. 根名称服务器不解析名称。它返回.edu 域的名称服务器名称和地址。

  6. ns1.xyzindustries.com生成一个迭代请求并将其发送到.edu 域的名称服务器。

  7. .edu 域的名称服务器返回 googleplex.edu 域的名称服务器名称和地址。

  8. ns1.xyzindustries.com生成一个迭代请求并将其发送到 googleplex.edu 域的名称服务器。

  9. googleplex.edu 域的名称服务器查阅其记录。然而,它看到这个名称位于 compsci.googleplex.edu 子域中,该子域位于一个单独的区域中。它返回那个区域的名称服务器。

  10. ns1.xyzindustries.com生成一个迭代请求并将其发送到 compsci.googleplex.edu 域的名称服务器。

  11. compsci.googleplex.edu 的名称服务器是www.net.compsci.googleplex.edu的权威名称服务器。它将那个主机的 IP 地址返回给ns1.xyzindustries.com

  12. ns1.xyzindustries.com缓存了这个解析结果。

  13. 本地名称服务器将解析结果返回到您本地机器上的解析器。

  14. 您的本地解析器也会缓存信息。

  15. 本地解析器将地址提供给您的浏览器。

  16. 您的浏览器开始向 Googleplex 机器的 IP 地址发起 HTTP 请求。

这似乎相当复杂且缓慢。当然,计算机的工作速度比你能读(或者我打字的速度)要快。即使如此,缓存的优点也是显而易见的——如果名称在解析器或本地 DNS 服务器的缓存中,那么大多数这些步骤都可以避免。

注意,这个例子非常简化,并且只展示了服务器可能设置的一种方式。例如,即使 compsci.googleplex.edu 与 googleplex.edu 在不同的区域,它们也可能使用相同的服务器。在这种情况下,处理过程中的一个迭代可能会被跳过。这个例子也没有展示如果处理过程中发生错误会发生什么。此外,如果输入的名称是一个别名,由 CNAME 记录指示,这也会改变处理过程。

DNS 名称解析过程的示例 这个相当复杂的例子说明了使用迭代和递归解析的典型 DNS 名称解析。用户在网页浏览器中输入 DNS 名称 (www.net.compsci.googleplex.edu),这会导致从她的客户端机器的解析器向本地 DNS 名称服务器发出 DNS 解析请求。该名称服务器同意代表解析器递归解析该名称,但使用迭代请求来完成。这些请求被发送到 DNS 根名称服务器,然后依次是 .edu、googleplex.edu 和 compsci.googleplex.edu 的名称服务器。然后,IP 地址被传递到本地名称服务器,然后返回到用户的解析器,最后到达她的网页浏览器软件。

图 56-3. DNS 名称解析过程的示例 这个相当复杂的例子说明了使用迭代和递归解析的典型 DNS 名称解析。用户在网页浏览器中输入 DNS 名称 (www.net.compsci.googleplex.edu),这会导致从她的客户端机器的解析器向本地 DNS 名称服务器发出 DNS 解析请求。该名称服务器同意代表解析器递归解析该名称,但使用迭代请求来完成。这些请求被发送到 DNS 根名称服务器,然后依次是 .edu、googleplex.edu 和 compsci.googleplex.edu 的名称服务器。然后,IP 地址被传递到本地名称服务器,然后返回到用户的解析器,最后到达她的网页浏览器软件。

处理别名(CNAME 记录)的解析更改

CNAME 记录用于允许设备向外界展示一个恒定的名称,同时允许与该名称对应的实际设备在组织内部变化。当使用 CNAME 时,它通过添加一个额外的步骤来改变名称解析过程:首先,我们将别名解析为规范名称,然后我们解析规范名称。

例如,Web 服务器几乎总是以 www.开头命名,所以在 XYZ Industries,我们希望人们能够通过www.xyzindustries.com找到我们的网站。然而,Web 服务器可能与bigserver.xyzindustries.com上的其他服务共享。我们可以设置一个 CNAME 记录,将www.xyzindustries.com指向bigserver.xyzindustries.com。解析 www 将导致一个指向 bigserver 的 CNAME,然后它本身被解析。如果将来我们的业务增长,我们决定将我们的 Web 服务升级到在biggerserver.xyzindustries.com上运行,我们只需更改 CNAME 记录,用户就不会受到影响。

使用 IN-ADDR.ARPA 域进行 DNS 逆向名称解析

如果大多数人被要求将 DNS 的核心功能归纳为一个功能,他们可能会说它是将对象的名称转换为与之关联的数字 IP 地址。 (好吧,如果他们对 DNS 了解很多的话。) 因此,DNS 有时被比作电话簿,或者电话 411(信息服务)。这种类比存在某些问题,但在最高层面上,它是有效的。在两种情况下,我们取一个名字,咨询一个数据库(一种或另一种类型),并从中产生一个与该名字匹配的数字。

在现实世界中,有时你可能不想找到与名字对应的电话号码,而是拥有一个电话号码,想知道它属于哪个人。例如,这可能发生在你的电话记录了来电号码,但你没有来电显示来显示与号码关联的名字时。你也可能在一张纸上找到电话号码,但记不起它是谁的。

类似地,在网络世界中,有许多情况下我们有一个 IP 地址,想知道与之对应的名称。例如,一个万维网服务器在其服务器日志中记录了连接到它的每个设备的 IP 地址,但这些数字对人类来说通常是没有意义的,他们更喜欢看到与之相关的名字。一个更严重的例子可能是一个试图破解你电脑的黑客;通过将 IP 地址转换为名称,你可能会发现他来自哪个国家,他使用的是哪个互联网服务提供商(ISP),等等。也有许多原因使得网络管理员可能想要找出与地址对应的名称,用于设置或故障排除目的。

DNS 最初包含一个名为逆向查询的功能,它将允许这种“相反”的解析。

原始方法:逆向查询

对于反向查询,解析器可以发送一个查询,其中不包含填入名称和供服务器填入 IP 地址的空间,而是包含 IP 地址和供名称填入的空间。服务器会检查其 RR(资源记录)并返回名称给解析器。

在理论上,这行得通,甚至在实践中,如果互联网非常小的话。然而,记住,由于 DNS 信息的分布式特性,解析工作的最大部分是找到正确的服务器。现在,在常规解析的情况下,我们可以通过遍历服务器的层次结构来轻松地找到正确的服务器。这是可能的,因为服务器是按照名称的层次结构连接在一起的。

然而,DNS 服务器并不是根据 IP 地址来排列的。这意味着要使用反向查询,我们需要使用正确的名称服务器来解析我们想要解析成名称的 IP 地址,而且没有简单的方法可以找到它。当然,我们可以尝试向每个区域的权威 DNS 服务器发送反向查询。如果你尝试这样做,可能比你写这本书的时间还要长,所以我们不要走那条路。所有这些最终的结果是,反向查询从未流行过,除了用于本地服务器故障排除。它们在 2002 年 11 月通过发布 RFC 3425 正式从 DNS 中移除。

那么,我们该怎么办呢?问题是服务器是按名称而不是按 IP 地址排列的。因此,解决方案就像听起来那么简单:按 IP 地址排列服务器。这并不意味着我们移除名称层次结构,或者复制所有服务器,或者任何愚蠢的事情。相反,我们创建了一个额外的、数字的层次结构,它与名称层次结构共存。然后我们使用这个层次结构从数字中找到名称,这个过程通常称为反向名称解析

反向解析的 IN-ADDR.ARPA 名称结构

互联网的名称层次结构是通过一个称为IN-ADDR.ARPA的特殊域名实现的,该域名位于保留的.ARPATLD(IN-ADDR代表INternet ADDRess)内部。回想一下第五十四章中的讨论,.ARPA 最初用于将旧互联网主机过渡到 DNS,现在被互联网的运行者用于各种目的。

在 IN-ADDR.ARPA 内部创建了一个特殊的数字层次结构,覆盖了整个 IP 地址空间(参见图 56-4 的 IP 地址是 191.27.203.8,那么其区域的 DNS 服务器将有一个地址(A)RR 来指示这一点。在主文件文本格式中,它可能会这样表示:

www.xyzindustries.com.  A  191.27.203.8

DNS IN-ADDR.ARPA 反向名称解析层次结构 特殊的 IN-ADDR.ARPA 层次结构是为了允许轻松进行 DNS 名称的反向查找。IN-ADDR.ARPA 包含编号为 0 到 255 的 256 个子域,每个子域又包含编号为 0 到 255 的 256 个子域,以此类推,直到四层。因此,每个 IP 地址都在这个层次结构中有表示。这个例子显示了 DNS 域名 www.xyzindustries.com。它将有一个指向其 IP 地址 191.27.203.8 的传统 RR,以及一个在 8.203.27.191.IN-ADDR.ARPA 的反向解析记录,指向域名 www.xyzindustries.com。

图 56-4. DNS IN-ADDR.ARPA 反向名称解析层次结构 特殊的 IN-ADDR.ARPA 层次结构是为了允许轻松进行 DNS 名称的反向查找而创建的。IN-ADDR.ARPA 包含 256 个子域,编号从 0 到 255,每个子域又有 256 个子域,编号从 0 到 255,以此类推,直到四个级别。因此,每个 IP 地址都在这个层次结构中有代表。这个例子显示了 DNS 域名 www.xyzindustries.com。它将有一个指向其 IP 地址 191.27.203.8 的常规 RR,以及一个在 8.203.27.191.IN-ADDR.ARPA 的反向解析记录,指向域名 www.xyzindustries.com

然而,在 IN-ADDR.ARPA 域中也会为其创建以下条目:

8.203.27.191.IN-ADDR.ARPA  PTR  www.xyzindustries.com

注意

请记住,DNS 名称不区分大小写,因此 IN-ADDR.ARPA 也可以写成 in-addr.arpa。

完成这一步后,可以通过对 8.203.27.191.in-addr.arpa 进行名称解析来轻松执行反向名称解析。如果我们这样做,IN-ADDR.ARPA 域的服务器将返回给我们域名 www.xyzindustries.com。这如图 图 56-4 所示。

小贴士

关键概念 大多数名称解析都需要我们将 DNS 域名转换为 IP 地址。然而,有些情况下我们希望执行 反向名称解析,即从 IP 地址开始,找出与之匹配的域名。使用传统的 DNS 分布式名称层次结构来做这件事是困难的,因为没有简单的方法可以找到包含特定 IP 地址条目的 DNS 服务器。为此,专门建立了一个名为 IN-ADDR.ARPA 的特殊层次结构,用于反向名称查找。这个层次结构包含四个级别的数字子域,结构是这样的:每个 IP 地址都有一个自己的节点。IP 地址的节点包含一个指向与该地址相关联的 DNS 域名的条目。

我相信你已经注意到了 IN-ADDR.ARPA 域中的数字是倒序的。我们之前已经看到了这个原因:名称解析是从最不具体到最具体的元素进行的,从右到左进行。相比之下,IP 地址的最不具体八位字节在左边,最具体的在右边。因此,我们将其反转以保持与 DNS 命名空间的连贯性。

这立即带来一个额外的好处。正如我们可以将常规名称空间的部分权限委派出去,例如,让 XYZ Industries 负责xyzindustries.com中的所有内容,我们也可以将 IN-ADDR.ARPA 名称空间的部分权限委派出去。例如,由于麻省理工学院(MIT)拥有所有以 18 为第一个八位的 IP 地址(至少,我认为它仍然如此),如果 MIT 想要的话,它也可以控制 18.IN-ADDR.ARPA 域名以及反向查询。没有反转八位字节,这是不可能的。

注意,为了使该系统可靠地工作,确保常规名称空间和反向名称空间中的数据保持一致是至关重要的。每当注册一个新的 DNS 名称时,必须在 IN-ADDR.ARPA 中做出适当的条目。已经实施了特殊程序,以允许自动创建这些指针条目。

提示

相关信息 在互联网协议(IPv6)的第六版中,使用不同反向域的类似方案用于 DNS。有关更多信息,请参阅第五十七章

DNS 电子邮件支持及邮件交换(MX)资源记录

大多数聪明的互联网用户都知道 DNS 的存在,并且通常将它与最常用的互联网应用联系起来。在这些应用中,“大鲸鱼”就是万维网。可能的情况是,大多数 DNS 名称解析请求都是由于每天在浏览器中输入数十亿次 Web 服务器域名,以及由用户鼠标点击和基于 Web 的应用程序生成的命名页面请求而产生的。

当然,DNS 并非特定于任何单一的应用。我们可以在任何需要 IP 地址的地方指定名称。例如,你可以使用 DNS 名称而不是地址来指定 FTP 客户端,甚至用于故障排除工具如 traceroute 或 ping(参见第八十八章)。在每个情况下,解析器都会为你处理名称的转换。

有一个应用始终使用 DNS,但当你想到 DNS 时,它通常不会立刻出现在你的脑海中:电子邮件(在第 III-7 部分[pt18.html "第 III-7 部分。TCP/IP 电子邮件系统:概念和协议"]中讨论)。实际上,电子邮件对 DNS 的依赖性比其他任何 TCP/IP 应用都要大。考虑一下,虽然你可能有时会为 traceroute 之类的命令输入 IP 地址,或者甚至将其输入浏览器,但你可能从未通过在电子邮件客户端输入 joe@14.194.29.60 来给任何人发送过邮件。你输入的是 joe@xyzindustries.com,DNS 会负责确定 XYZ Industries 的电子邮件应该发送到哪里。

电子邮件名称解析的特殊要求

电子邮件地址的名称解析与其他 DNS 应用不同,原因有三(我在第七十五章("第七十五章. TCP/IP 电子邮件地址和地址解析")的讨论中详细描述了这些原因):

  • 我们可能不希望电子邮件直接发送到地址中指定的确切机器。

  • 我们需要能够更改服务器名称,而无需更改每个人的电子邮件地址。

  • 我们需要能够支持多个服务器来处理邮件。

例如,XYZ 工业公司可能希望使用一个名为mail.xyzindustries.com的专用邮件服务器来处理收件邮件,但实际上构建所有电子邮件地址使用@xyzindustries.com。这使得地址更短,并且可以在不影响用户地址的情况下更改服务器的名称。如果公司愿意,它可能会决定使用两个服务器,mail1.xyzindustries.commail2.xyzindustries.com,以实现冗余,并且仍然只使用@xyzindustries.com 作为地址。

为了允许这些情况下所需的灵活性,定义了一种特殊的 DNS RR 类型,称为邮件交换(MX)记录

邮件交换(MX)记录及其用途

每个 MX 记录指定了一个特定的邮件服务器,用于处理特定域的收件邮件。一旦这个记录建立,电子邮件消息的解析基本上与常规解析相似。假设您想向 joe@xyzindustries.com 发送消息。基本过程如下:

  1. 您的电子邮件客户端会在本地机器上调用解析器,以对xyzindustries.com执行电子邮件解析。

  2. 您的本地解析器和本地 DNS 服务器将遵循本章前面描述的过程,以找到xyzindustries.com的授权服务器,即ns1.xyzindustries.com

  3. ns1.xyzindustries.com找到xyzindustries.com的 MX 记录,并回复指示应使用mail.xyzindustries.com进行电子邮件处理。

电子邮件客户端实际上无法向mail.xyzindustries.com发送任何内容;它需要其 IP 地址。因此,它需要解析该名称。这个解析请求很可能会回到刚刚处理 MX 请求的同一个 DNS 名称服务器。为了消除两次单独解析的低效率,DNS 名称服务器可以将信息合并。在我们的例子中,ns1.xyzindustries.com将在它发送的 DNS 消息的附加部分中包含mail.xyzindustries.com的 A(地址)RR。

注意

RFC 1035 最初还定义了与电子邮件相关的其他几种 RR 类型:邮箱(MB)、邮件组(MG)和邮件重命名(MR)。这些在标准中被称为“实验性的”。我认为无论实验是什么,它都失败了,因为这些在今天似乎没有被使用。还有两个更早的与邮件相关的 RR,邮件目的地(MD)和邮件转发器(MF),它们肯定曾经被使用过,但在 RFC 1035 本身被编写的时候就已经过时了

对于特定的域名,也可以指定多个 MX 记录,每个记录指向不同的邮件服务器的名称。这提供了冗余性,因此如果有一个邮件服务器出现问题,另一个可以填补空缺。DNS 允许为每个邮件服务器指定一个优先级值,这样您可以清楚地指出哪个是主邮件服务器,哪个是第一备份,第二备份,依此类推。DNS 服务器将首先选择优先级值最低的邮件服务器,然后是下一个最高优先级的,依此类推。

小贴士

关键概念 由于电子邮件是通过主机名而不是 IP 地址发送的,因此 DNS 包含特殊规定以支持站点之间电子邮件的传输。设置了特殊的邮件交换(MX) DNS RR,其中包含域名想要用于处理传入电子邮件的邮件服务器名称。在向站点发送电子邮件之前,设备执行名称解析以获取该站点的 MX 记录,以便知道将消息发送到哪里。

第五十七章. DNS 消息和消息、资源记录以及主文件格式

无标题图片

网络完全是关于连接设备之间信息交流的。在域名系统(DNS)的情况下,在 DNS 执行的各种操作中的每一次,都会交换关于互联网上名称和对象的信息。这涉及到在设备之间发送消息。像大多数协议一样,DNS 使用自己的一套消息,具有独特的字段格式,并遵循特定的规则来生成和通过互联网传输它们。

在本章中,我解释了 DNS 中消息的生成和发送方式,并描述了用于消息和资源记录(RR)的格式。我首先对 DNS 消息及其生成和传输进行概述性讨论。我概述了通用 DNS 消息格式及其包含的五个部分。我描述了用于名称的表示法以及有助于保持 DNS 消息大小的特殊压缩方法。然后,我展示了 DNS 消息头和问题部分中的字段。我说明了用于所有 RR 的常见字段格式以及最重要的记录类型中的特定字段。我还提供了用于 DNS 文本主文件的格式描述。

我以对 DNS 为支持互联网协议版本 6(IPv6)所做的更改的简要讨论作为结论。其中大部分更改(但并非全部)与消息格式和 RR(本章节的主题)相关。

小贴士

背景信息 本章假设你已经熟悉 DNS 概念和操作,这些内容在第五十二章到第五十六章中已有描述

DNS 消息生成和传输

在本书本部分的先前章节中,我们探讨了服务器和解析器执行的各种不同任务:常规名称解析、反向名称解析、电子邮件解析、区域传输等。这些操作中的每一个都需要在 DNS 设备对之间交换信息。像许多其他 TCP/IP 协议一样,DNS 被设计用来通过客户端/服务器模型完成这种信息传输。所有 DNS 交换都以客户端发送请求和服务器响应答案开始。

DNS 客户端/服务器消息概述

在第八章中对 TCP/IP 的客户端/服务器性质的概述中,我解释了关于这些术语的一个潜在的混淆来源:它们指的是硬件角色、软件角色和事务角色。这个问题在 DNS 的情况下肯定适用。你已经看到 DNS 实现由两组软件元素组成:作为客户端的解析器和作为服务器的域名服务器。解析器软件通常运行在客户端机器上,如 PC,而域名服务器软件通常运行在专用服务器硬件上。然而,这些命名是基于硬件和软件的整体角色的。

从消息的角度来看,客户端是通信的发起者,无论这种发起是由哪种类型的机器完成的,服务器是响应客户端的设备。解析器通常充当客户端,域名服务器充当服务器。然而,在特定的交换中,DNS 域名服务器可以充当客户端,至少有两种情况。首先,在递归名称解析中,服务器生成对其他服务器的请求,因此充当客户端。其次,在诸如区域传输之类的管理功能中,一个服务器充当客户端并向另一个服务器发送请求。(顺便说一句,据我所知,DNS 中没有解析器充当服务器的案例。)

DNS 中的大多数事务都由单个查询消息和单个响应消息的交换组成。作为事务客户端的设备创建查询并发送给服务器;然后服务器发送回响应。在某些需要发送大量数据的情况下,例如区域传输,服务器可能会发送多个消息。可能需要多个此类事务才能完成完整的名称解析,正如前一章中 DNS 解析过程的示例所示。

使用 UDP 和 TCP 进行 DNS 消息传输

TCP/IP 有两个不同的传输层协议:用户数据报协议(UDP)和传输控制协议(TCP)(见第二部分-8)。UDP 和 TCP 在 TCP/IP 模型中共享第 4 层,因为它们在功能和操作方面非常不同。一些应用层协议需要 TCP 的服务,可以使用它来利用这些服务,而其他协议则更适合使用更简单的 UDP。DNS 本身就是在协议套件中同时拥有 UDP 和 TCP 的有效理由的完美例子(见第四十二章),因为它同时使用它们。

UDP 是一种简单的无连接协议,它不提供真正的功能但非常快速。它非常适合小而快速的信息交换,并且可以比 TCP 更快,因为不需要建立连接。这使得它成为 DNS 中大多数传统查询的好选择,因为它们通常非常短,快速的数据交换很重要。因此,DNS 标准建议在常规和反向名称解析中使用 UDP 进行查询和回复。UDP DNS 消息限制为 512 字节;较长的消息将被截断,并且头部中设置了一个特殊位来指示这种情况。如果被截断的消息对其接收者造成问题,则必须使用 TCP 重新发送查询。

注意

DNS UDP 消息的 512 字节限制可以通过实现可选的 DNS 扩展机制(EDNS0)来超越。这些机制在 RFC 2671 中有描述

由于 UDP 不提供消息的可靠交付,DNS 客户端必须跟踪它们已发送的请求。如果在特定时间内没有收到响应,则必须重新发送请求。处理这些细节的需要被认为是与 UDP 的低设置成本(例如,不需要连接)的可接受的权衡。重传的发送速率通常设置为至少每两到五秒,以防止在互联网上产生过多的 DNS 流量。

对于某些特殊的 DNS 事务,UDP 显然是不合适的。这类事务中最常见的例子是区域传输。虽然区域传输的查询大小很小,但响应发送的数据量可能相当大。UDP 的 512 字节限制甚至远远不够。此外,我们确实需要确保区域传输能够可靠地完成,并具有流量控制和其它数据传输管理功能,否则我们可能会在辅助 DNS 服务器数据库中拥有损坏的区域信息。

解决方案是使用 TCP 进行这些类型的交换。TCP 允许消息具有任意长度,作为一个面向连接、确认、可靠的协议,自动提供我们确保区域传输和其他长时间操作成功完成的机制。代价是需要建立连接的小量开销,但鉴于区域传输不频繁(与常规名称解析的巨大数量相比),这并不是问题。

您可以了解到 DNS 如何很好地说明了 TCP 和 UDP 在 TCP/IP 中的作用。由于这两种传输协议都可以使用,域名服务器在同一个众所周知的端口号 53 上监听 UDP 和 TCP 请求。作为客户端的设备使用一个临时端口号进行事务处理。所有 DNS 消息都是单播从一台设备直接发送到另一台设备。

小贴士

关键概念 DNS 使用 UDP 和 TCP 发送消息。常规的消息交换很短,因此非常适合使用非常快速的 UDP;DNS 本身处理丢失请求的检测和重传。对于更大或更重要的信息交换,尤其是区域传输,使用 TCP——既因为其可靠性,也因为它能够处理任意大小的消息。

DNS 消息处理和通用消息格式

正如我们刚才讨论的,DNS 消息交换都是基于客户端/服务器计算的原则。在特定的交换中,一台设备充当客户端,通过发送查询来启动通信;另一台设备充当服务器,通过回答查询来响应。这种查询/响应行为是 DNS 的一个基本组成部分,并在 DNS 消息的格式中得到体现。

DNS 查询和响应使用一个常见的消息格式。这个消息格式包含五个部分,为客户端提出的查询、服务器提供的答案以及控制整个过程的头部信息提供了位置。表 57-1 描述了 DNS 通用消息格式,提供了每个部分的简要总结及其使用方法。您还可以在图 57-1 中看到消息格式的简化示意图。

表 57-1. DNS 通用消息格式

部分名称 描述
头部 包含描述消息类型并提供有关其重要信息的字段。还包含指示消息其他部分条目数的字段。
问题 包含一个或多个问题——即发送到 DNS 名称服务器的信息查询。
答案 包含一个或多个 RR(资源记录),用于回答问题部分中指出的一个问题或多个问题。
权限 包含一个或多个指向权威名称服务器的 RR(资源记录),这些服务器可用于继续解析过程。
附加 传达一个或多个 RR(资源记录),这些 RR 包含与查询相关的附加信息,这些信息对于严格回答消息中的查询(问题)不是必需的。

头部部分始终存在于所有消息中,并且长度固定。除了包含重要的 DNS 控制信息外,它还有一个标志(QR),指示消息是查询还是响应。它还具有四个“计数”字段,告诉接收者其他四个部分中的条目数。

当客户端发起查询时,它会创建一个消息,其中包含已填写在头部部分的字段,并在问题部分中包含一个或多个查询(信息请求)。它将 QR(查询/响应)标志设置为 0,以指示这是一个查询,并在头部部分的 QDCount 字段中放置一个数字,该数字表示问题部分中的问题数量。其他部分的条目数通常为 0,因此它们的计数字段(ANCount、NSCount 和 ARCount)在头部部分中设置为 0。(尽管可以将多个问题放入一个查询中,但通常只包含一个。)

DNS 通用消息格式

图 57-1. DNS 通用消息格式

当服务器接收到查询时,它会处理它并执行请求的信息检索操作(如果可以的话)。然后,它使用查询作为其响应消息的基础。头部和问题部分被复制到响应消息中,并将 QR 标志设置为 1,以指示该消息是回复。头部部分的一些字段也会更改,以向客户端提供信息。例如,服务器将 RCode(响应代码)字段设置为指示查询是否成功或是否发生错误,如果发生错误,则指示问题所在。本章的下一节将说明所有头部字段,并说明客户端和服务器如何使用每个字段。

服务器还负责填写消息的其他三个部分:答案、授权和附加。这些部分具有相同的基本格式,每个部分都携带一个或多个使用通用记录格式的 RR。每个部分中的记录数量由消息头中的计数字段指示。这些部分的不同之处仅在于它们携带的记录类型。答案记录与提出的问题直接相关,而授权记录携带标识其他名称服务器的 RR。因此,当服务器没有客户端请求的信息时,授权记录是名称服务器通过层次结构链接的手段。

附加部分的存在是为了特定地提高 DNS 效率。有些情况下,服务器会提供一个答案,它有理由相信这将导致一个后续问题,该服务器也可以回答。例如,假设服务器在授权部分(一个 NS RR)中提供了另一个名称服务器的名称。客户端可能没有该服务器的地址,这意味着它必须执行额外的名称解析才能联系引用的服务器。如果提供 NS 记录的服务器已经知道该名称服务器的 IP 地址,它可以将它包含在附加部分中。正如我在上一章关于 DNS 邮件支持的讨论中所解释的,提供 MX 记录的服务器也是如此。

小贴士

关键概念 DNS 为所有消息使用一个通用的消息格式。它由一个固定的 12 字节头部、包含查询的问题部分,以及随后可以携带不同类型 RR 的三个附加部分组成。答案部分通常包含直接回答消息中问题的记录;授权部分包含发送回客户端的名称服务器名称;附加部分包含可能对客户端有价值的信息,例如在授权部分中提到的名称服务器的 IP 地址。

DNS 的另一个优化是使用一种特殊的压缩技术来减少 DNS 消息的大小。这将在本章后面的“DNS 名称表示法和消息压缩”部分进行解释。

注意,特殊的“通知”和“更新”消息的格式与常规 DNS 查询/响应消息不同。这些特殊消息(其使用方法在第五十五章中关于 DNS 服务器增强的部分进行描述)基于常规格式,但某些字段的含义已改变。您可以在 RFC 1996 和 RFC 2136 中找到这些字段格式。

DNS 中的客户端/服务器信息交换是通过查询/响应消息来实现的。查询和响应具有相同的一般格式,包含最多五个独立部分,携带信息。其中,两个通常在查询和响应中都存在:头部部分和问题部分。我们将首先查看这两个部分,然后检查服务器用于其他三个消息部分的 RR 格式。

DNS 消息头格式

头部是任何消息最重要的部分,因为它是关键控制字段携带的地方。在 DNS 消息中,头部部分携带了几个关键控制标志,并且它还指示消息中使用了哪些其他部分。检查头部部分可以帮助你理解 DNS 中消息工作的一些细微之处。

所有 DNS 消息中使用的头部部分格式如图图 57-2 所示,并在表表 57-2、表 57-3 和表 57-4 中详细描述。在交换中,客户端和服务器使用不同的字段时,我在表 57-2 中提到了如何在这两个之间区分使用。

注意,当前有效的查询类型、查询操作码和响应码列表由互联网数字分配机构(IANA)作为其众多互联网参数列表之一维护。响应码 0 到 5 是常规 DNS 的一部分,并在 RFC 1035 中定义;码 6 到 10 实现了动态 DNS,并在 RFC 2136 中定义。

表 57-2. DNS 消息头部格式

字段名称 大小(字节) 描述
ID 2 标识符:由创建 DNS 查询的设备生成的 16 位标识字段。服务器将其复制到响应中,因此该设备可以使用它将查询与从 DNS 服务器收到的相应回复匹配。这类似于在许多互联网控制消息协议(ICMP)消息类型中使用的标识符字段的方式。
QR 1/8 (1 位) 查询/响应标志:区分查询和响应。当查询生成时设置为 0;当响应服务器将该查询转换为响应时,更改为 1。
OpCode 1/2 (4 位) 操作码:指定消息携带的查询类型。此字段由查询的创建者设置,并在响应中不变地复制。有关操作码值,请参阅表 57-3。
AA 1/8 (1 bit) 权威回答标志:在响应中设置为 1,表示创建响应的服务器是位于问题部分中指定的域名所在区域的权威服务器。如果为 0,则响应非权威。
TC 1/8 (1 bit) 截断标志:当设置为 1 时,表示消息由于长度超过所使用的传输机制允许的最大长度而被截断。TCP 没有消息长度限制;UDP 消息限制为 512 字节,因此发送此位通常表示消息使用 UDP 发送且过长无法适应。客户端可能需要建立 TCP 会话以获取完整消息。另一方面,如果截断的部分是额外部分的一部分,它可以选择不麻烦。
RD 1/8 (1 bit) 递归期望:当在查询中设置时,请求接收查询的服务器尝试递归地回答查询,如果服务器支持递归解析。此位的值在响应中不改变。
RA 1/8 (1 bit) 递归可用:在响应中设置为 1 或清除为 0,以指示创建响应的服务器是否支持递归查询。这可以由发送查询的设备记录下来以供将来使用。
Z 3/8 (3 bits) 零:三个保留位设置为 0。
RCode 1/2 (4 bits) 响应代码:在查询中设置为 0,然后由响应服务器在响应中更改以传达查询处理的结果。此字段用于指示查询是否成功回答或是否发生了某种错误。请参阅表 57-4 以获取 RCode 值。
QDCount 2 问题计数:指定消息中问题部分的题目数量。
ANCount 2 答案记录计数:指定消息中答案部分的 RR 数量。
ARCount 2 额外记录计数:指定消息中额外部分的 RR 数量。

表 57-3. Header OpCode Values

OpCode Value 查询名称 描述
0 Query 标准查询。
1 IQuery 反向查询;现已废弃。RFC 1035 将反向查询定义为执行反向 DNS 查找的可选方法;即,从 IP 地址找到名称。由于实施困难,该方法从未得到广泛部署,而是使用 IN-ADDR.ARPA 域名进行反向映射。OpCode 值的这种使用在 RFC 3425 中正式废弃,发布于 2002 年 11 月。
2 Status 服务器状态请求。
3 保留 保留,未使用。
4 通知 RFC 1996 添加的一种特殊消息类型。它由主(主服务器、授权服务器)服务器用于告知辅助服务器(从服务器)某个区域的数据已更改,并提示它们请求区域传输。有关 DNS 服务器增强功能的讨论,请参阅 第五十五章 以获取更多详细信息。
5 更新 RFC 2136 添加的一种特殊消息类型,用于实现动态 DNS。它允许选择性地添加、删除或更新 RR。有关 DNS 服务器增强功能的讨论,请参阅 第五十五章 以获取更多详细信息。

表 57-4. 头部 RCode 值

RCode 值 响应代码 描述
--- --- ---
0 无错误 未发生错误。
1 格式错误 服务器由于查询构建方式的问题无法响应用户查询。
2 服务器故障 服务器由于自身问题无法响应用户查询。
3 名称错误 查询中指定的名称在域名中不存在。此代码可以由区域(因为区域服务器知道域名中的所有对象和子域)的授权服务器或实现负缓存的缓存服务器使用。
4 未实现 接收到的查询类型不受服务器支持。
5 拒绝 服务器拒绝处理查询,通常是由于策略原因而不是技术原因。例如,某些类型的操作,如区域传输,受到限制。服务器只会从某些设备处尊重区域传输请求。
6 YX 域 当不应存在名称时存在名称。
7 YX RR 集合 存在不应存在的 RR 集合。
8 NX RR 集合 应存在的 RR 集合不存在。
9 非授权 接收查询的服务器不是指定区域的授权服务器。
10 非区域 消息中指定的名称不在消息中指定的区域内。

DNS 消息头部格式

图 57-2. DNS 消息头部格式

DNS 问题部分格式

DNS 查询始终包含至少一个在问题部分中的条目,该条目指定了交换中的客户端试图找出什么。这些条目在响应消息中不变地复制,以便在需要时供客户端参考。DNS 消息问题部分中每个条目所使用的格式在表 Table 57-5 和 Table 57-6 中详细描述,并在 Figure 57-3 中展示。

表 57-5. DNS 消息问题部分格式

字段名称 大小(字节) 描述
--- --- ---
QName 变量 问题名称:包含查询的对象、域名或区域名称,使用标准 DNS 名称表示法编码,将在本章后面解释。
QType 2 问题类型:指定客户端设备所询问的问题类型。此字段可能包含与请求的特定 RR 类型相对应的代码号。(表 55-1 在第五十五章中包含最常见的 RR 的编号。)如果是这样,这意味着客户端正在请求发送给 QName 中列出的域名的那种类型的记录。QType 字段还可以包含表 57-6 中列出的代码之一,对应于特殊类型的请求。
QClass 2 问题类:指定请求的 RR 的类别,通常是因特网(IN)的值 1。有关类别和 RR 类型的讨论,请参阅第五十六章中的解释。此外,QClass 值 255 被定义为具有特殊意义“任何类别”。

表 57-6. 问题部分 QType 值

QType 值 问题类型 描述
251 IXFR 按照 RFC 1995 请求增量(部分)区域传输
252 AXFR 请求区域传输
253 MAILB 请求与邮箱相关的记录(RR 类型 MB、MG 或 MR;现已废弃)
254 MAILA 请求邮件代理 RR(现已废弃;现在使用 MX 记录代替)
255 * (星号) 请求所有记录

DNS 消息问题部分格式

图 57-3. DNS 消息问题部分格式

DNS 消息资源记录字段格式

如你在本章和上一章所学,DNS 中的信息交换由一系列客户端/服务器事务组成。客户端向服务器发送请求,或称为查询,服务器则返回响应。DNS 服务器是数据库服务器,它们以 RR(资源记录)的形式存储 DNS 名称数据库信息。客户端提出的问题是从 DNS 服务器数据库请求信息,并由 DNS 服务器通过查找请求的 RR 并将它们放入 DNS 响应消息中回答。

DNS 消息格式的答案、授权和附加部分是服务器放置要发送回客户端的 DNS RR 的地方。每个部分由零个或多个记录组成,理论上,任何记录都可以放置在任何部分。这些部分的不同之处仅在于客户端从记录在某一部分而不是另一部分中得出的语义(意义)。

RRs 有两种表示形式:二进制和文本。文本格式用于由人类编辑的主文件,将在本章后面的“DNS 主文件格式”部分讨论。二进制表示由常规数字和文本字段组成,就像 DNS 消息格式中的其他字段一样。

DNS 通用 RR 格式

存在着某些类型的信息是所有 RR 共有的,而其他类型的信息是每种记录类型独有的。为了处理这种情况,所有 RR 都使用一个通用的字段格式来表示,该格式包含一个随记录类型而变化的单个 RData 字段。通用 RR 格式在表 57-7 中描述,并在图 57-4 中展示。

表 57-7. DNS 通用资源记录格式

Field Name 大小(字节) 描述
Name 可变 名称:包含 RR 的主题对象、域名或区域名称,使用标准 DNS 名称表示法编码,将在本章后面解释。RR 中的所有信息都与该对象相关联,我将其称为记录的命名对象。
Type 2 类型:指定资源记录类型的代码值。最常见 RR 的类型值在表 55-1 中显示,在第五十五章中,以及本章的以下各节中。
Class 2 类:指定请求的 RR 的类别,通常为因特网(IN)的值 1。参见第五十五章以了解解释。
TTL 4 存活时间:指定记录应在读取记录的设备的缓存中保留的秒数。参见第五十五章中关于 DNS 名称服务器缓存的讨论,以获得完整解释。值为 0 表示仅为此当前名称解析使用此信息;不要缓存它。
RDLength 2 资源数据长度:指示 RData 字段的大小,以字节为单位。
RData 可变 资源数据:RR 的数据部分。

通用 RR 的 RData 字段格式

RData 字段由一个或多个子字段组成,这些子字段携带 RR 的实际有效负载。以下各节介绍了最常见的 RR 类型。对于每种类型,我都指出了 RR 的文本代码、名称和类型值;提供了 RR 用途的简要概述;并在表中显示了 RData 字段的结构。

DNS 通用 RR 格式

图 57-4. DNS 通用 RR 格式

A (地址) RR (类型值 1)

A (地址) 是 DNS 中的主要 RR 类型。它包含与域名关联的 32 位 IP 地址,如表 57-8 所示。

表 57-8. DNS 地址 RR 数据格式

子字段名称 大小(字节) 描述
Address 4 地址:与该记录的命名对象对应的 32 位 IP 地址。

NS (名称服务器) RR (类型值 2)

The NSDName 数据字段携带名称服务器的域名,如表 57-9 所示。

表 57-9. DNS 名称服务器 RR 数据格式

子字段名称 大小(字节) 描述
NSDName 可变 名称服务器域名:一个名称服务器的可变长度名称,该名称服务器应负责该记录的命名对象。像所有名称一样,此名称使用标准的 DNS 名称表示法编码。请求此 RR 类型通常会导致在响应的附加部分返回指定的名称服务器的 A 记录,如果可用的话。

CName (规范名称) RR (类型值 5)

CName 数据字段包含使用别名引用的命名对象的实际名称,如表 57-10 所示。

表 57-10. DNS 规范名称 RR 数据格式

子字段名称 大小(字节) 描述
CName 可变 规范名称:命名对象的规范(实际)名称。然后使用标准的 DNS 解析过程解析此名称,以获取最初指定的名称的地址。

SOA (授权开始) RR (类型值 6)

SOA 记录标记 DNS 区域的开始,并包含有关如何管理和使用区域的关键信息。SOA 记录是 DNS RR 类型中最复杂的。其格式在表 57-11 中解释,并在图 57-5 RR 数据格式")中说明。有关此 RR 中字段的使用信息,请参阅第五十五章中关于区域传输的讨论。

表 57-11. DNS 授权开始 RR 数据格式

子字段名称 大小(字节) 描述
MName 可变 主名称:提供区域数据的数据源名称服务器的域名。这通常是区域的主授权服务器。它使用标准的 DNS 名称格式编码。
RName 可变 负责人名称:负责此区域的人员的电子邮件地址。DNS 中的电子邮件地址使用本章后面讨论的特殊变体编码的常规 DNS 名称表示法。
序列号 4 序列号:此区域 RR 数据库的序列号或版本号。用于确定何时对数据库进行了更改以触发区域传输。
刷新 4 刷新间隔:此区域二级域名服务器在尝试检查主域名服务器上对区域数据库所做的更改之间等待的秒数。
重试 4 重试间隔:二级域名服务器在尝试再次检查主域名服务器以查找更改之前等待的秒数,如果其之前的尝试失败。
过期 4 过期间隔:在二级域名服务器必须认为其持有的信息已过时之前,可以经过的成功联系主域名服务器的秒数。
最小值 4 负缓存 TTL:最初携带未指定显式 TTL 值的记录的默认 TTL 值。现在表示区域的负缓存 TTL。请参阅第五十五章中关于 DNS 名称服务器缓存的讨论。

PTR (指针) RR (类型值 12)

PTR 记录携带一个指向 RR 的指针。它用于反向地址查找。它包含一个数据字段,如表 57-12 所示。

表 57-12. DNS 指针 RR 数据格式

子字段名称 大小(字节) 描述
PTRDName 可变 指针域名:一个可变长度的域名。这是由 RR 指向的名称。有关此记录类型最常见使用方式的描述,请参阅第五十六章。

DNS 起始授权 (SOA) RR 数据格式

图 57-5. DNS 起始授权 (SOA) RR 数据格式

MX (邮件交换) RR (类型值 15)

特殊的 MX 记录包含有关用于向域名发送电子邮件的邮件服务器(请参阅第五十六章)的信息。每个记录包含两个字段,如表 57-13 所示。

表 57-13. DNS 邮件交换 RR 数据格式

子字段名称 大小(字节) 描述
优先级 2 优先级值:此邮件交换的优先级级别。较低的值表示较高的优先级。
交换 变量 交换域名:愿意为该命名对象提供邮件交换服务的宿主机的域名,使用标准 DNS 名称表示法编码。

TXT (文本) RR (类型值 16)

TXT 记录包含有关命名对象的附加描述信息,如表 57-14 所示。

表 57-14. DNS 文本 RR 数据格式

子字段名称 大小(字节) 描述
TXT-数据 可变 文本数据:可变长度的描述性文本。

DNS 名称表示法和消息压缩

显然,整个 DNS 协议都是围绕处理域名、子域名和对象名称来设计的。正如你在前面的主题中看到的,DNS 消息和 RR 中有许多字段携带对象、名称服务器等的名称。DNS 在 RR 和字段中使用特殊的编码名称表示法,这是电子邮件地址表示法的变体,以及一种特殊的压缩方法,该方法可以减少消息的大小以提高效率。

标准 DNS 名称表示法

在第五十三章中,你学习了 DNS 名称是如何构建的。名称层次结构中的每个节点都与一个标签相关联。特定设备的完全限定域名(FQDN)由从树根开始并向下到该设备的标签序列组成。层次结构中每个级别的标签按顺序列出,从最高级别开始,从右到左,由点分隔。这产生了我们习惯使用的域名,例如www.xyzindustries.com

将这些名称直接编码到 RR 或其他 DNS 消息字段中是可能的:将字母W放入名称的前三个字节中,然后在第四个字节中放入一个点(.),在第五个字节中放入一个x,依此类推。这种方法的缺点是,当计算机读取名称时,它无法判断每个名称何时结束。我们需要为每个名称包含一个长度字段。

相反,DNS 使用特殊的表示法来表示 DNS 名称。每个标签按顺序编码在名称字段中。在每个标签之前,使用一个字节来表示标签中的字符数。然后,将标签的字符编码,每个字节一个字符。名称的结束由一个空标签表示,代表根;这个长度为零,因此每个名称都以一个 0 字符结束,表示这个零长度的根标签。

注意,标签之间的点是不必要的,因为长度数字界定了标签。读取名称的计算机也知道自己正在读取的每个标签中有多少字节,因此它可以在读取名称时轻松地为标签分配空间。

例如,www.xyzindustries.com将被编码如下:

[3] w w w [13] x y z i n d u s t r i e s [3] c o m [0]

我已经用方括号标出了标签长度以区分它们。请记住,这些标签长度是二进制编码的数字,所以一个字节可以存储从 0 到 255 的值;[13] 是一个字节,而不是两个,正如你在 图 57-6 中看到的。标签实际上限制在最多 63 个字符,你很快就会看到这一点的重要性。

DNS 标准名称表示法 在 DNS 中,每个命名对象或其他名称都由一系列标签长度和标签组成,每个标签长度占用一个字节,每个标签占用一个字符的字节。本例显示了名称 www.xyzindustries.com 的编码。

图 57-6. DNS 标准名称表示法 在 DNS 中,每个命名对象或其他名称都由一系列标签长度和标签组成,每个标签长度占用一个字节,每个标签占用一个字符的字节。本例显示了名称 www.xyzindustries.com 的编码。

DNS 电子邮件地址表示法

电子邮件地址用于某些 DNS 资源记录中,例如 SOA RR 中的 RName 字段。电子邮件地址的形式为 <name>@<domain-name>。DNS 以与常规 DNS 域名完全相同的方式对这些进行编码,只是将 @ 视为另一个点。因此,johnny@somewhere.org 将被视为 johnny.somewhere.org,并按以下方式编码:

[6] j o h n n y [9] s o m e w h e r e [3] o r g [0]

注意,这里没有特定的指示表明这是一个电子邮件地址。根据上下文,该名称被解释为电子邮件地址而不是设备名称。

DNS 消息压缩

单个 DNS 消息可能包含许多域名。现在,考虑当某个名称服务器发送包含多个域名的响应时,它们通常都在同一个区域或与该区域相关。这些名称中的大多数将具有它们名称的共同元素。

考虑我们之前邮件示例中客户请求的 xyzindustries.com 的 MX 记录。对此客户的回复将包含以下两个记录:

MX 记录 记录中的名称字段包含 xyzindustries.com,而 RData 字段包含 mail.xyzindustries.com

A 记录 假设域名服务器知道 mail.xyzindustries.com 的 IP 地址,附加部分将包含一个 A 记录,名称字段包含 mail.xyzindustries.com,而 RData 字段包含其地址。

这只是名称重复的一个小例子。在其他类型的 DNS 消息中,它可能更加极端,某些字符串模式可能会重复多次。通常,这需要使用这里描述的编码方法将每个名称完整拼写出来。但这样做将是浪费的,因为这些名称中的大部分是通用的。为了减少这种重复,使用了一种称为消息压缩的特殊技术。

使用消息压缩避免完整名称重复

使用消息压缩,而不是使用标签和标签长度的组合来编码 DNS 名称,一个两字节的子字段代表指向消息中另一个位置的指针。这个子字段的第一个两位被设置为 1(二进制中的值 11),剩余的 14 位包含一个偏移量,它指定了在消息中可以找到名称的位置,以消息的第一个字节(ID 字段的第一个字节)为 0 开始计数。

让我们回到我们的例子。假设在 DNS 消息中,MX 记录的 RData 字段,包含mail.xyzindustries.com,从字节 47 开始。在这个第一个实例中,我们会找到名称按如下方式完整编码:

[4] m a i l [13] x y z i n d u s t r i e s [3] c o m [0]

然而,在第二个实例中,当mail.xyzindustries.com出现在 A 记录的名称字段中时,我们会用两个 1 位,然后是 47 的二进制编码。所以,这将是一个 16 位的二进制模式 11000000 00101111,或者两个数值字节 192 和 47。这个第二个实例现在只占用 2 个字节,而不是像第一个实例那样需要重复 24 个字节。

读取名称字段的设备如何区分指针和真实名称?这就是为什么字段开始处使用 11 的原因。这样做可以保证指针的第一个字节总是具有 192 或更大的值。由于标签的长度限制在 63 或更短,当主机读取名称的第一个字节时,如果它看到一个字节中的值为 63 或更少,它知道这是一个真实名称;值为 192 或更多表示它是一个指针。

使用消息压缩避免名称部分重复

之前的例子展示了如何使用指针来消除整个名称的重复:名称mail.xyzindustries.com在两个地方使用,而第二个地方使用了指针。然而,指针的功能甚至更强大。它们也可以用来指向真实名称的一部分,或者可以与额外的标签结合,以提供与 RR 中另一个名称相关的名称的压缩表示。这提供了更大的空间节省。

在前面的例子中,这意味着即使是 mail.xyzindustries.com 的第一个实例也可以被压缩。回想一下,MX 记录将在名称字段中包含 xyzindustries.com,在 RData 字段中包含 mail.xyzindustries.com。如果该记录的名称字段从字节 19 开始,那么我们可以将 RData 字段编码如下:

[4] m a i l [pointer-to-byte-19]

读取记录的设备将获取第一个标签的 "mail",然后从名称字段读取 "xyzindustries.com" 以获取完整名称,mail.xyzindustries.com

类似地,假设我们在这个消息中有一个包含对 xyzindustries.com 的父域 "com." 的引用的记录,这可以简单地编码如下:

[pointer-to-byte-33]

原因是字节 33 是我们找到名称字段中包含 [13] x y z i n d u s t r i e s [3] c o m [0][3] c o m [0] 部分。

DNS 主文件格式

DNS 服务器通过发送包含 RR 的回复消息来响应用户的查询。您在本章中已经看到了用于编码这些 RR 的二进制消息格式。这些消息格式非常适合传输消息,因为它们紧凑且高效。计算机可以快速读取字段并知道如何解释特定的字符串。

与此相反,人类并不擅长处理二进制中的晦涩代码。在服务器可以提供 RR 之前,需要人类管理员告诉服务器这些记录是什么以及它们包含的信息。为了使这项工作更容易,DNS 包含一个用于区域和 RR 的特殊文本表示。管理员编辑描述区域及其包含的记录的特殊 主文件。然后,这些文件被服务器的 DNS 软件读入内存,并转换为二进制形式以响应用户请求。这更详细地描述在 第五十六章。

每个主文件由一个简单、扁平的文本文件组成,可以使用任何类型的文本编辑器创建。每个文件包含使用一组简单的语法规则表示的若干行,这些规则描述了一个区域及其中的记录。DNS 主文件的基本语法规则在 RFC 1035 的第 5.1 节中指定。尽管某些 DNS 实现在其标准语法上有所变化,但它们都非常相似。

DNS 常见主文件记录格式

正如所有 RR 都使用一个共同的字段格式存储在内部一样,它们也使用一个共同的主文件格式。每个记录通常在文件的单独一行上出现。此格式如下,方括号中显示的是可选字段:

<*`domain-name`*>  [<*`ttl`*>]  <*`class`*>  <*`type`*>  <*`rdata`*>

字段如下:

<*`域名`*> DNS 域名,可以是完全合格域名 (FQDN) 或部分合格域名 (PQDN)。

<*ttl*> 记录的 TTL 值,以秒为单位。如果省略,则使用区域默认的 TTL 值。实际上,大多数 RR 没有指定的 TTL,而是使用 SOA 记录提供的默认值。

<*class*> RR 类。对于现代 DNS,此字段是可选的,默认为 IN,代表互联网。

<*type*> RR 类型,使用文本代码(如 A 或 NS)指定,而不是数字代码。

<*rdata*> RR 数据,它是一组由空格分隔的条目,这取决于记录类型。

<rdata> 可以是单个信息或一组条目,具体取决于记录类型。在较长的记录类型中,特别是 SOA 记录的情况下,多个 <rdata> 字段会分布在几行中,并用括号括起来;括号使得所有条目都像在单行上一样。请注意,如果存在 <ttl> 字段,则 <ttl> 字段和 <class> 字段的顺序可以互换,而不会出现任何问题,因为一个是数字,另一个是文本(IN)。

部分限定域名(PQDNs)的使用和解释

域名可以在 FQDNs 和 PQDNs(在第五十三章中描述)之间混合使用。PQDNs 用于使主文件创建更快、更易读,通过减少名称的公共部分。它们在某种程度上是 DNS 消息压缩的人类等效物。FQDN 以点(.)结尾的完整域名表示,以表示 DNS 名称树的根。PQDN 只给出一个没有根的局部名称,并由读取主文件的软件解释为 FQDN。(有关更多信息,请参阅下一节中 $ORIGIN 指令的描述。)

记住使用尾随点来标记完全限定域名(FQDNs)是很重要的。如果原始域名是 xyzindustries.com 并且在其区域文件中出现了 bigisp.net 这个名称,服务器将读取为 bigisp.net.xyzindustries.com——这很可能不是你想要的。此外,电子邮件地址,如 SOA 记录中的 <r-name> 字段,将电子邮件地址的 @ 符号转换为点,遵循标准的 DNS 习惯。

主文件指令

除了资源记录(RRs)之外,大多数主文件实现还支持使用 指令。这些是用于指定某些重要信息以指导如何解释主文件的命令。以下是最常见的三个指令:

$ORIGIN 指定附加到未限定规范中的域名。这是将 PQDN 转换为 FQDN 的基础。例如,如果起源是 xyzindustries.com,则 PQDN “sales” 将被解释为 sales.xyzindustries.com。一旦定义,起源可以通过仅使用 @ 而不是名称来引用,正如你将在本节末尾显示的示例主文件中看到的那样。

$TTL 指定用于任何未在记录本身中指定 TTL 值的 RR 的默认 TTL 值。(此值以前由 SOA 记录中的最小字段指定。)

$INCLUDE 允许一个主文件包含另一个文件的 内容。这有时用于在区域之间保存某些条目的重复。

主文件语法规则

DNS 主文件有一些其他的语法规则,其中一些是为了节省管理员的时间和精力:

多记录缩写 如果多个连续的记录属于同一域名,则第一个记录指定 <域名>,然后后续的可以留空。服务器将假设任何没有 <域名> 标示的 RR 应用于它最后看到的 <域名>

注释 分号 (😉 标记注释。从分号到行尾的任何文本都将被忽略。

转义字符 反斜杠 () 用于“转义”字符的特殊含义。例如,双引号 (quote) 标记用于分隔文本字符串;字面双引号字符由反斜杠-双引号组合 (") 表示。

空白 制表符和空格用作分隔符,空白行将被忽略。为了可读性,大多数智能管理员使用制表符缩进来明确哪些记录属于哪些名称,并使用空白行和注释来分组记录。

大小写 与 DNS 域名一样,主文件条目不区分大小写。

特定 RR 语法和示例

以下部分展示了每种常见 RR 类型的特定格式和示例。字段基本上与在 NS 二进制记录格式中解释的字段相同。示例中使用了 DNS 注释格式进行说明。假设这些示例适用于 googleplex.edu 区域。

A (地址) RR

A 记录的格式如下:

<*`domain-name`*> [<*`ttl`*>] IN A <*`ip-address`*>

以下是一个示例:

admin1.googleplex.edu IN A 204.13.100.3    ; An FQDN
admin2 IN A 204.13.100.44                  ; A PQDN equivalent to
                                           ; admin2.googleplex.edu

NS (域名服务器) RR

NS 记录的格式如下:

<*`domain-name`*>  [<*`ttl`*>]  IN  NS  <*`name-server-name`*>

以下是一个示例:

< googleplex.edu. IN NS custns.bigisp.net  ; Secondary NS

CName (规范名称) RR

CName 记录的格式如下:

<*`domain-name`*>  [<*`ttl`*>]  IN  CNAME  <*`canonical-name`*>

以下是一个示例:

www IN CNAME bigserver   ; www.googleplex.edu is really
                         ; bigserver.googleplex.edu.

SOA (授权开始) RR

SOA 记录的格式如下:

<*`domain-name`*> [<*`ttl`*>] IN SOA <*`m-name`*> <*`r-name`*> (
      <*`serial-number`*>
      <*`refresh-interval`*>
      <*`retry-interval`*>
      <*`expire-interval`*>
      <*`default-ttl`*>)

以下是一个示例:

< googleplex.edu. IN SOA ns1.googleplex.edu it.googleplex.edu (
      42     ; Version 42 of the zone.
      21600  ; Refresh every 6 hours.
      3600   ; Retry every hour.
      604800 ; Expire after one week.
      86400) ; Negative Cache TTL is one day.

PTR (指针) RR

PTR 记录的格式如下:

<*`reverse-domain-name`*> [<*`ttl`*>] IN PTR <*`domain-name`*>

以下是一个示例:

3.100.13.204.IN-ADDR.ARPA. IN PTR admin1.googleplex.edu.

注意,PTR 记录实际上位于 IN-ADDR.ARPA 域。

MX (邮件交换) RR

MX 记录的格式如下:

<*`domain-name`*> [<*`ttl`*>] IN MX <*`preference-value`*> <*`exchange-name`*>

以下是一个示例:

googleplex.edu.     IN MX 10 mainmail.googleplex.edu.
                    IN MX 20 backupmail.googleplex.edu

TXT (文本) RR

TXT 记录的格式如下:

<*`domain-name`*> [<*`ttl`*>] IN TXT <*`text-information`*>

这里有一个例子:

googleplex.edu. IN TXT "Contact Joe at X321 for more info."

样本主文件

以下是一个 DNS 主文件的真实世界示例,取自我的pcguide.com服务器(略有修改),由pair.com的优秀人士托管(并提供 DNS 信息)。注意使用@作为“此域名”的快捷方式(pcguide.com)。

$ORIGIN pcguide.com.
@ IN SOA ns23.pair.com. root.pair.com. (
      2001072300  ; Serial
      3600        ; Refresh
      300         ; Retry
      604800      ; Expire
      3600 )      ; Minimum

@ IN NS ns23.pair.com.
@ IN NS ns0.ns0.com.

localhost  IN A  127.0.0.1
@          IN A  209.68.14.80
           IN MX 50  qs939.pair.com.

www    IN CNAME   @
ftp    IN CNAME   @
mail   IN CNAME   @
relay  IN CNAME   relay.pair.com.

支持 IPv6 的 DNS 更改

互联网协议第 4 版(IPv4)是今天互联网的基础,也是 TCP/IP 协议套件建立的基础。虽然 IPv4 在过去二十多年里为我们服务得很好,但它有一些重要的缺点,如果继续使用,将限制未来的互连网络。因此,下一代 IP,即 IP 版本 6(IPv6),已经开发多年。IPv6 最终将取代 IPv4 并将 TCP/IP 带入未来。

从 IPv4 到 IPv6 的转换将对其他 TCP/IP 协议产生影响,包括 DNS。DNS 是一个高级协议,因此根据分层原理,IP 的变化不应该影响它。然而,这又是分层并不总是适用的另一个例子。DNS 直接与 IP 地址工作,IPv6 对 IP 的最重要修改之一是在地址领域,这意味着在 IPv6 上使用 DNS 需要对协议的工作方式做出一些更改。

IPv6 DNS 扩展

事实上,由于 DNS 在第三层的 IP 架构上与 IP 相距甚远,所需的变化并不广泛。1995 年 12 月发布的 RFC 1886,“IPv6 DNS 扩展”,是互联网工程任务组(IETF)首次正式尝试描述 DNS 在支持 IPv6 方面所需的变化。它定义了 DNS 在 IPv6 中的三个具体修改:

新的 RR 类型—AAAA(IPv6 地址) 常规 DNS 地址(A)RR 是为 32 位 IPv4 地址定义的,因此创建了一个新的类型,以便将域名与 128 位 IPv6 地址关联起来。四个A(AAAA)是一个助记符,表示 IPv6 地址是 IPv4 地址的四倍大小。AAAA 记录的结构与二进制和主文件格式中的 A 记录非常相似;只是更大。AAAA 的 DNS RR 类型值为 28。

新的反向解析层次结构 为 IPv6 反向查找定义了一个类似于 IN-ADDR.ARPA 的新层次结构,但 IETF 将其放在了一个不同的顶级域名(TLD)中。新域名是IP6.INT,其使用方式与 IN-ADDR.ARPA 类似。然而,由于 IPv6 地址是用十六进制表示而不是点分十进制,IP6.INT 有 16 个子域 0 到 F,每个子域也有 16 个子域 0 到 F,以此类推,共 16 层深。是的,这可能导致一个潜在的巨大反向解析数据库!

查询类型和解析程序的更改 所有与 A 记录一起工作或导致 A 记录包含在回复的附加部分中的查询类型都必须更改,以处理 AAAA 记录。此外,通常会导致在附加部分返回 A 记录的查询必须仅在答案部分返回相应的 AAAA 记录,而不是在附加部分。

小贴士

关键概念 尽管 DNS 位于 TCP/IP 协议栈架构中 IP 之上,但它与 IP 地址紧密协作。因此,需要进行一些更改以使其能够支持新的 IPv6。这些更改包括定义一个新的 IPv6 地址 RR(AAAA)、一个新的反向解析域层次结构以及某些对消息传递方式的更改。

对 IPv6 DNS 扩展的提议性更改

2000 年,IETF 发布了 RFC 2874,“支持 IPv6 地址聚合和重新编号的 DNS 扩展”。该标准提出用新的记录类型 A6 来替代 RFC 1886 中引入的 IPv6 支持,而不是使用 RFC 1886 的 AAAA。AAAA 记录与 A6 记录的主要区别在于,前者只是像 A 记录一样的完整地址,而 A6 记录可以包含完整或部分地址。

RFC 2874 背后的想法是,A6 记录可以以补充 IPv6 单播地址格式(见[第二十五章](ch25.html "第二十五章。IPv6 寻址"))的方式设置。然后,名称解析将涉及一种称为链式的技术,从一组部分指定的地址组件中确定名称的完整地址。本质上,这将使地址的行为与分层名称本身的工作方式非常相似,提供一些潜在的灵活性优势。

在几年时间里,RFC 1886 和 RFC 2874 都被提出作为标准,这导致了相当大的混淆。2002 年 8 月,发布了 RFC 3363 和 RFC 3364,这些文件澄清了这两个提案的情况。RFC 3363 代表了“最高法院的决定”,即 RFC 2874 和 A6 记录应改为实验性状态,而 RFC 1886 的 AAAA 记录应保留为 DNS IPv6 标准。

对于这一决定的完整解释可以在 RFC 3364 中找到。简而言之,它归结为 IETF 认为 RFC 2874 的成功实施存在重大潜在风险。虽然 A6 记录的功能很有趣,但并不清楚它们是否是必需的,考虑到这些风险,IETF 认为坚持使用 RFC 1886 是更好的选择。

第 III-2 部分:网络文件和资源共享协议

第五十八章")

对于普通用户来说,网络的创建主要是出于一个原因:允许信息共享。计算机上的大多数信息都以文件的形式存在,这些文件存储在硬盘等存储设备上;因此,网络的一个主要目的是让用户能够共享文件。文件传输和消息传输协议允许用户手动将文件从一个地方移动到另一个地方,但在许多情况下,更自动化的方法更受欢迎。互联网协议提供了一种以网络文件和资源共享协议的形式来实现这些功能的能力。

在这部分简短的介绍中,我将从 TCP/IP 网络的角度描述网络文件和资源共享协议。这一章提供了这类协议的概念和操作概述,讨论了不同类型协议中的一些共同元素。然后,它描述了为 TCP/IP 特定定义的最常见协议:网络文件系统(NFS)。

显然,网络文件和资源共享协议和服务与我之前提到的文件和消息传输协议密切相关。例如,NFS 可以用来完成与 TCP/IP 文件和消息传输应用程序(如文件传输协议(FTP)和超文本传输协议(HTTP))执行的任务类似的任务。我认为这些协议更像是特定的终端用户应用程序,因此将在后面的应用协议部分(第 III-6 部分 中的 FTP 和 第 III-8 部分") 中的 HTTP)中描述它们。我意识到这种手动和自动文件传输之间的区别有些武断,但在这个广阔的网络世界中,许多其他事情也都是这样。

第五十八章:网络文件和资源共享与 TCP/IP 网络文件系统(NFS)

无标题图片

文件和资源共享协议很重要,因为它们允许用户在网络中无缝共享文件。由于微软操作系统在行业中的主导地位,许多人熟悉微软网络如何以这种方式使用。然而,微软在文件共享协议方面可以说是“后来者”。在微软 Windows 存在之前很久,网络文件系统(NFS)就已经让用户使用 UNIX 操作系统在网络上共享文件。

在本章中,我简要介绍了 TCP/IP 中的网络文件和资源共享,重点关注 NFS 的操作。我首先概述了文件和资源共享协议的概念。然后,我提供了 NFS 的概述和历史,讨论了其常见版本和标准。我描述了 NFS 的架构和组成它的三个组件。接着,我描述了 NFS 文件系统模型以及如何使用外部数据表示(XDR)标准进行数据编码。我解释了 NFS 的客户端/服务器操作,使用远程过程调用(RPCs)。然后,我列出了 NFS 中使用的程序和操作,并以对用于将网络资源附加到设备的独立 NFS 挂载协议的描述结束。

文件和资源共享概念和组件

网络和互联网创建的一个主要原因是允许文件和其他资源在计算机之间共享。因此,在任何互联网协议栈中,我们需要某种机制,使用户能够以简单的方式轻松地在网络上移动文件。为了这个目的,创建了应用层文件和消息传输协议,如文件传输协议(FTP)和超文本传输协议(HTTP)。这些协议的目的是让用户能够访问网络上的资源,同时隐藏它们在下面操作层的细节。

然而,尽管这些协议隐藏了底层,但它们在本质上有些手动。它们需要用户调用应用程序协议并使用特定的命令来完成基于网络的资源访问。事实上,这类协议的问题并不在于它们需要手动干预,而在于它们使共享变得更加困难,因为它们不允许文件直接在另一个资源上使用。

考虑像 FTP 这样的协议。它确实允许你在机器之间共享文件,但它清楚地区分了属于你的文件和属于别人的文件。如果你想使用乔机器上的文件,你必须将其传输到你的机器上,使用它,然后再传输回来。此外,如果你不将文件传回,乔可能永远也看不到更新的版本。

文件和资源共享协议的力量

当我们能够隐藏文件所在位置和移动它们的命令的细节时,我们就达到了文件和资源共享的极致。这样的系统将使用一种自动共享协议,允许文件和资源在网络中无缝使用。一旦设置好,这种方案中的网络资源就可以像本地计算机上的资源一样使用。这些协议有时被称为网络文件和资源共享协议

正是这种本地文件和远程文件之间界限的模糊,使得文件和资源共享协议如此强大。一旦系统设置完成,用户就可以像访问自己的主机上的资源一样轻松地访问另一台主机上的资源。这是一种极其有用的功能,尤其是在客户端/服务器计算的现代时代。例如,它允许公司在一个共同的地方存储许多个人使用的信息,例如在服务器上的目录中,这样每个人都可以访问它。本质上,有一个跨越网络设备的虚拟文件系统,而不是仅仅在单台计算机的一个存储设备上。

文件和资源共享协议的组成部分

文件和传输协议使用户能够轻松共享文件,但这并不意味着没有工作要做。工作仍然存在,但由编写协议和负责其操作的人员承担。一般来说,这些协议至少需要以下一般组件:

文件系统模型和架构 定义要共享的资源文件,并描述虚拟文件系统如何工作的机制。

资源访问方法 描述用户如何将远程资源附加或从其本地主机分离的操作过程。

操作集 一组操作,用于完成用户需要在其他主机上的文件上执行的各种任务。

消息协议 携带要执行的操作、状态信息等消息格式,以及在这些设备之间交换这些消息的协议。

管理工具 支持协议操作并将其他元素结合在一起所需的辅助功能。

NFS 设计目标、版本和标准

如我在 第八章 中讨论的那样,TCP/IP 和互联网的历史密不可分。然而,还有一个第三合作伙伴,虽然不常被提及,但却是这些技术发展历史的重要组成部分。那就是早期互联网上运行的操作系统,今天仍然被大量互联网服务器使用:UNIX 操作系统。

Sun Microsystems 是 UNIX 和 TCP/IP 网络开发的早期先驱之一。在 TCP/IP 早期的发展中,创建了一些工具,允许用户通过网络访问另一台机器——毕竟,这可以说是网络的核心目的。远程访问协议如 Telnet 允许用户登录到另一台主机计算机并使用那里的资源。FTP 允许人们从远程机器复制文件到自己的机器并编辑它。然而,这两种解决方案都无法真正满足用户以类似本地文件使用方式访问远程机器上的文件的需求。为了满足这一需求,Sun 创建了 网络文件系统 (NFS)

NFS 设计目标

NFS 专门设计的目标是消除本地和远程文件之间的区别。对于用户来说,在完成适当的设置后,远程计算机上的文件可以像在用户的本地机器上的硬盘上一样使用。Sun 还专门设计了 NFS 以确保硬件的厂商独立性,以确保 Sun 和其他公司制造的硬件能够互操作。

NFS 最重要的设计目标之一是性能。显然,即使你将文件设置在远程机器上,就像它是本地的一样,实际的读写操作也必须跨越网络。通常,这比在计算机内部发送数据花费的时间要多,因此协议本身需要尽可能精简高效。这个决定导致了一些有趣的选择,例如在 TCP/IP 中使用不可靠的用户数据报协议(UDP)进行传输,而不是像大多数文件传输协议那样使用可靠的传输控制协议(TCP)。这反过来又对整个协议的工作方式产生了有趣的影响。

NFS 的另一个关键设计目标是简单性(这当然与性能相关)。据说 NFS 服务器是无状态的,这意味着协议被设计成服务器不需要跟踪哪些客户端打开了哪些文件。这允许请求相互独立地发出,并允许服务器优雅地处理诸如崩溃等事件,而无需复杂的恢复程序。

该协议还设计成,如果请求丢失或重复,不会发生文件损坏。

小贴士

关键概念 网络文件系统(NFS)的创建是为了允许客户端主机像访问本地文件一样访问远程服务器上的文件。它主要设计的目标是性能、简单性和跨厂商兼容性。

NFS 版本和标准

由于它最初是由 Sun 设计和推广的,NFS 最初是一个事实上的标准。NFS 的第一个广泛使用的版本是版本 2(NFSv2),这仍然是该协议最常用的版本。NFSv2 最终在 1989 年发布的 RFC 1094,“NFS:网络文件系统协议规范”中被正式确定为 TCP/IP 标准。

随后开发了 NFS 版本 3(NFSv3),并于 1995 年作为 RFC 1813,“NFS 版本 3 协议规范”发布。它与 NFSv2 相似,但进行了一些更改并添加了一些新功能。这些包括对大文件和文件传输的支持,更好的文件属性设置支持,以及几个新的文件访问和操作过程。

NFS 版本 4(NFSv4)于 2000 年作为 RFC 3010,“NFS 版本 4 协议”发布。与 NFSv3 只包含对先前版本相对较小的更改相比,NFSv4 几乎是对 NFS 的完全重写。它包括许多更改,最值得注意的是以下内容:

  • 反映现代互连网络的需求,NFSv4 更加重视安全性。

  • NFSv4 引入了 复合过程 的概念,允许将几个更简单的过程作为一个组从客户端发送到服务器。

  • NFSv4 几乎将客户端在访问 NFS 服务器上的文件时可以使用的单个过程数量翻了一番。

  • NFSv4 在消息传递方面进行了重大改变,指定 TCP 作为 NFS 的传输协议。

  • NFSv4 将挂载协议的功能集成到基本的 NFS 协议中,消除了作为单独协议的存在,就像在之前的版本中那样。

与早期标准相比,NFSv4 标准在实现和可选功能方面有更多细节——它长达 275 页。这就是简单性的代价!RFC 3010 后来在 2003 年 4 月被 RFC 3530 更新,即 "网络文件系统 (NFS) 版本 4 协议"。该标准对 NFSv4 的操作进行了进一步的修订和澄清。

网络文件系统架构和组件

NFS 遵循经典的 TCP/IP 客户端/服务器操作模型。管理员可以将特定计算机的硬盘或存储设备上的目录设置为共享资源。然后,客户端计算机可以访问此资源,通过 挂载 共享驱动器或目录,使其在客户端机器上看起来就像是一个本地目录。有些计算机可能只作为服务器或只作为客户端;而其他计算机可能两者都是,共享它们的一些资源并访问他人提供的资源。

从整个 TCP/IP 协议套件的视角来看,NFS 是一个位于 TCP/IP (DOD) 模型应用层的单一协议(在 第八章 中描述)。此 TCP/IP 层包括 OSI 参考模型(在 第六章 中描述)的会话、表示和应用层。正如我在本书中之前所说,我通常不认为在大多数情况下尝试区分第 5 层到第 7 层有很大的价值。然而,在某些情况下,这些层可以帮助理解协议的架构,而 NFS 就是这种情况。

网络文件系统主要组件

网络文件系统 (NFS) 的操作以三个主要组件的形式定义,这些组件可以视为位于三个 OSI 模型层中,对应于 TCP/IP 应用层,如图 图 58-1 所示:

远程过程调用 (RPC) RPC 是一种通用的会话层服务,用于实现客户端/服务器互连功能。它将程序在特定主机计算机上调用本地过程的概念扩展到通过网络在远程设备上调用过程。

外部数据表示 (XDR) XDR 是一种描述性语言,它允许以一致的方式定义数据类型。从概念上讲,XDR 位于表示层。它的通用表示允许使用 NFS 在可能使用非常不同的内部数据存储方法之间的计算机之间交换数据。

NFS 程序和操作 NFS 的实际功能以程序和操作的形式实现,从概念上讲,这些程序在 OSI 模型的第 7 层运行。这些程序指定在网络上的文件上执行特定任务,使用 XDR 表示数据,并通过 RPC 在互联网上传输命令。

这三个关键的“子协议”,如果你愿意这样称呼,构成了 NFS 协议的大部分。每个子协议在本章的单独部分中都有更详细的描述。

NFS 架构组件

图 58-1. NFS 架构组件

提示

关键概念 从架构上讲,NFS 位于 TCP/IP 应用层。尽管在 TCP/IP 模型中,OSI 参考模型第 5 层至第 7 层的功能通常没有明确的区分,但 NFS 的三个子协议很好地对应了这三个层次,如图所示。NFS 位于 TCP/IP 模型的应用层。其功能主要通过三个不同的功能组件来实现,这些组件实现了 OSI 参考模型第 5 层至第 7 层的功能:远程过程调用 (RPC),提供会话层服务;外部数据表示 (XDR) 标准,管理数据表示和转换;以及 NFS 程序和操作,允许使用其他两个组件在应用层执行任务。

其他重要的 NFS 功能

除了这三个主要组件之外,NFS 协议作为一个整体还涉及许多其他功能,最值得注意的是以下功能:

挂载协议 NFS 的创建者做出了一个特定的决定,即不处理文件打开和关闭的细节。相反,使用一个名为 挂载 的单独协议来处理这个问题。通过网络访问文件或其他资源首先需要使用此协议进行 挂载。挂载协议在架构上是独立的,但显然与 NFS 密切相关,甚至在 NFS 标准的附录中定义。我在本章的最后部分对其进行了描述。(注意,在 NFSv4 中,挂载协议的功能已被纳入到 NFS 本身。)

NFS 文件系统模型 NFS 使用特定的模型来实现使用它的系统的目录和文件结构。这个模型与 UNIX 文件系统模型紧密相关,但并不仅限于该操作系统。它在本章末尾关于挂载协议的解释中进行了讨论。

安全性 NFS 的版本 2 和 3 仅包含有限的安全措施。它们使用 UNIX 风格的认证来检查各种操作的权限。NFSv4 大大增加了 NFS 实现可用的安全选项。这包括多个认证和加密算法的规定,以及整个协议的许多变化,使其更加安全。

使用外部数据表示(XDR)标准的 NFS 数据定义

NFS 背后的整体思想是允许你像在本地机器上一样轻松地从另一台计算机的文件中读取或写入。当然,你本地机器上的所有文件都存储在同一个文件系统中,使用相同的文件结构和表示不同类型数据的方式。当你访问远程设备时,你无法确定这种情况是否成立,这会引发一点巴别塔问题。

一种方法是将访问限制仅限于使用相同操作系统的机器上的远程文件。然而,这将大大降低 NFS 的有效性。要求每台计算机都理解其他每台计算机的内部表示方式也非常不切实际。需要一种更通用的方法,以便即使是非常不同的机器也能共享数据。为此,NFS 的创造者定义了 NFS,使其使用通用数据描述语言来处理数据。这种语言被称为外部数据表示(XDR)标准,最初在 RFC 1014 中描述。它在 1995 年的 RFC 1832,“XDR:外部数据表示标准”中进行了更新。

一种通用数据交换方法:XDR

XDR 背后的思想很简单,可以通过类比轻松理解。如果你在大会上有 50 种不同语言的代表,他们很难进行沟通。你可以雇佣翻译人员来协助,但你永远找不到能够处理所有可能的语言组合的翻译人员。一个更实际的解决方案是宣布一种语言,例如英语,作为通用语言。然后你只需要 49 名翻译人员:一个将英语翻译成每种非英语语言,然后再翻译回来。要从瑞典语翻译成葡萄牙语,你需要先将瑞典语翻译成英语,然后再从英语翻译成葡萄牙语。通用语言可以是法语、西班牙语或其他任何语言,只要能够找到从所有其他语言到这种语言的翻译人员。

XDR 以相同的方式工作。当需要将如何访问文件的信息从设备 A 传输到设备 B 时,设备 A 首先将它从设备 A 的内部表示转换为这些数据类型的 XDR 表示。信息通过网络使用 XDR 编码进行传输。然后设备 B 将 XDR 转换回其自身的内部表示,以便将其作为本地文件系统上的内容呈现给用户。每个设备只需要知道如何将其自己的语言转换为 XDR 并再次转换回来;设备 A 不需要知道设备 B 的内部细节,反之亦然。这种转换是表示层的典型工作,而 XDR 正位于 OSI 参考模型中的表示层。XDR 本身基于一个称为“抽象语法符号”的国际标准化组织 (ISO) 标准。

注意

XDR 的理念也被用于其他协议中,以允许在底层系统的性质无关的情况下交换数据。例如,类似的想法在简单网络管理协议 (SNMP) 中用于交换管理信息,这在第六十六章 和管理信息库 (MIBs)")中有描述。同样基本的思想是 Telnet 协议中使用的重要的网络虚拟终端 (NVT) 范式的基础,这在第八十七章中有描述

提示

关键概念 外部数据表示 (XDR) 标准的目的是定义表示常见数据类型的通用方法。使用这种通用表示,数据可以在使用不同内部文件系统的设备之间进行交换。这使得 NFS 能够在可能使用非常不同的硬件和软件平台的客户端和服务器之间交换文件数据。

XDR 数据类型

为了使 XDR 具有通用性,它必须允许描述计算机中使用的所有常见数据类型。例如,它必须允许整数、浮点数、字符串和其他数据结构进行交换。XDR 标准使用与 C 编程语言类似的一种符号来描述许多数据类型的结构。正如您可能知道的,这是计算历史上最受欢迎的语言之一,它与 UNIX 密切相关(因此,也与某些 TCP/IP 技术相关)。

表 58-1 数据类型") 展示了 XDR 定义的可以用于 NFS 在客户端和服务器之间交换数据的类型。对于每一种类型,我都包括了数据类型代码、其大小(以字节为单位)和简要描述。

表 58-1. NFS 外部数据表示 (XDR) 数据类型

数据类型代码 大小(字节) 描述
int 4 有符号整数:以二进制补码表示的 32 位有符号整数,能够存储从-2,147,483,648 到+2,147,483,647 的值。
unsigned int 4 无符号整数:32 位无符号整数,范围从 0 到 4,294,967,295。
enum 4 枚举:表示有符号整数的一种替代方法,其中一些整数值用于表示特定的常量值。例如,您可以通过定义值为 1 表示紫色,2 表示蓝色,等等来表示彩虹的颜色。
bool 4 布尔值:整数的逻辑表示,类似于具有两个级别的枚举,其中 0 值定义为 FALSE,1 值定义为 TRUE。
hyper 8 有符号超整数:与常规有符号整数相同,但宽度为 8 字节,以允许更大的数字。
unsigned hyper 8 无符号超整数:与常规无符号整数相同,但宽度为 8 字节,以允许更大的数字。
float 4 浮点数:32 位有符号浮点数。1 位用于符号(正或负),8 位用于指数(幂),以 2 为基数,23 位用于尾数(数字的小数部分)。
double 8 双精度浮点数:与 float 相同,但具有更多的位以允许更高的精度。1 位用于符号,11 位用于指数,52 位用于尾数。
quadruple 16 四倍精度浮点数:与 float 和 double 相同,但具有更多的位以允许更高的精度。1 位用于符号,15 位用于指数,112 位用于尾数。
opaque Variable 不可见数据:在设备之间传递的数据,不使用 XDR 给出特定的表示。术语不可见意味着数据被处理为一个“黑盒”,其内部无法看到。显然,任何使用此数据类型的机器都必须自己知道如何处理它,因为 NFS 不知道。
字符串 变量 字符串:ASCII 字符的变长字符串。
(数组) Variable 数组:可以是上述任何单一类型的元素组,如整数、浮点数等,可以指定为数组,以允许将多个元素作为一个单元引用。它们不使用单独的数据类型代码表示。
struct Variable 结构体:包含来自此表的其他数据元素的任意结构。这允许定义复杂的数据类型。
union Variable 判别联合:一种复杂的数据类型,其中使用称为“判别符”的代码值来确定其余结构体的性质。有关详细信息,请参阅 RFC 1014 的第 3.14 节。
void 0 空类型:一个不包含任何内容的空数据类型。
const 0 常量:用于其他表示的常量值。

正如你所见,XDR 提供了相当多的数据描述能力。如果你了解 C 语言,表 58-1 中的大部分内容可能对你来说很熟悉。不幸的是,没有将这变成 C 编程指南,我无法真正描述许多更复杂的数据类型。

XDR 还提供了一种定义新数据类型和指定可选数据的方法。这为已经具体描述的大量特定类型提供了更多的灵活性。NFS 的每个版本都支持略微不同的数据类型列表。

使用远程过程调用(RPC)的 NFS 客户端/服务器操作

几乎所有应用程序都处理文件和其他资源。当特定计算机上的软件程序想要读取文件、写入文件或执行相关任务时,它需要使用为此目的的正确软件指令。要求每个软件程序都包含这些指令的副本将是不高效的,因此,它们被编码为标准化的软件模块,有时称为过程。为了执行一个动作,软件调用这个过程。过程暂时接管主程序并执行读取或写入数据等任务。然后,过程将程序的控制权返回给调用它的软件,并且可以选择性地返回数据。

由于 NFS 的关键概念是使远程文件访问看起来像本地文件访问,因此它是围绕使用基于网络的这种过程调用方法的版本来设计的。一个想要对文件进行操作的软件应用程序仍然会进行过程调用,但它调用的是另一台计算机上的过程,而不是本地计算机。使用一组特殊的例程来处理调用在网络中的传输,对执行调用的软件来说,这种方式在很大程度上是透明的。

这种功能本来可以直接在 NFS 中实现,但 Sun 创建了一个名为远程过程调用(RPC)的独立会话层协议组件,它定义了如何实现这一点。RPC 最初是作为 NFS 的一个子组件创建的,但它足够通用且有用,以至于它已被用于 TCP/IP 中的其他客户端/服务器应用程序。因此,在许多方面,它实际上被认为是一个独立的协议。

由于 RPC 是 NFS 中实际通信的过程,因此 NFS 本身与许多其他 TCP/IP 协议不同。它的操作不能像 HTTP 或动态主机配置协议(DHCP)或甚至 TCP 那样用特定的消息交换和状态图来描述,因为 RPC 做了所有这些。NFS 是用一组 RPC 服务器过程和操作来定义的,这些过程和操作允许 NFS 服务器向 NFS 客户端提供,每个过程和操作都允许对文件执行特定类型的操作,例如从它读取、写入或删除它。

RPC 操作和传输协议使用

当客户端想要在特定机器上的文件上执行某种操作时,它使用 RPC 来调用该机器上的 NFS 服务器。服务器接受请求并执行所需操作,然后根据请求返回一个结果代码和可能的数据,返回给客户端。结果代码指示操作是否成功。如果是的话,客户端可以假设它请求执行的操作已经完成。例如,在写入数据的情况下,客户端可以假设数据已经成功写入长期存储。

小贴士

关键概念 NFS 不使用像大多数其他协议那样的专用消息格式。相反,客户端和服务器使用远程过程调用(RPC)协议来交换文件操作请求和数据。

NFS 可以在任何具有有效 RPC 实现的会话层传输机制上运行。NFS 在其传输协议的使用上经历了一定程度的演变。NFSv2 标准指出它通常使用 UDP 进行操作,这仍然是 NFS 信息传输的一种常见方式。NFSv3 表示可以使用 UDP 或 TCP,但 NFSv4 指定使用 TCP 来传输数据。NFS 使用的标准注册端口号为 2049,但有时会通过使用 RPC 的端口映射器功能来使用其他端口号。

NFS 中的客户端和服务器责任

由于 UDP 不可靠,使用该协议传输重要信息可能看起来很奇怪。例如,我们显然不希望试图写入文件的数据在传输过程中丢失。然而,请记住,UDP 并不排除使用确保可靠通信的措施;它只是不提供这些功能。UDP 可以被 NFS 使用,因为该协议本身设计为能够容忍传输数据的丢失并从中恢复。

与此概念一致,NFS 的一般设计将实现协议的大部分责任放在客户端,而不是服务器上。正如 NFSv3 标准所说,“NFS 服务器是简单的,NFS 客户端是智能的。”这意味着服务器只专注于响应请求,而客户端必须处理协议的大部分繁琐细节,包括从失败的通信中恢复。当使用 UDP 时,这是一个常见的要求,因为如果客户端请求在传输过程中丢失,服务器就无法知道它曾经被发送过。

如本章前面提到的 NFS 概述中所述,NFS 服务器被设计成无状态的。简单来说,这意味着 NFS 服务器不会跟踪客户端从一个请求到另一个请求的状态。每个请求都是独立的,服务器本质上没有记忆它在收到客户端的新命令之前做了什么。这又要求客户端投入更多的智能,但具有简化服务器崩溃时恢复的重要优势。由于服务器没有为客户端跟踪任何东西,所以没有东西可以丢失。这是确保文件不会因为网络问题或拥塞而损坏的重要部分。

客户端和服务器缓存

无论是 NFS 客户端还是服务器,都可以利用缓存来提高性能。服务器可能使用缓存来存储最近请求的信息,以防再次需要。它们也可能使用预测性缓存,有时也称为预取。在这种技术中,当服务器收到读取文件数据块的请求时,它可能会将下一个数据块加载到内存中,基于它可能会被下一个请求调用的理论。

客户端缓存用于满足应用程序对 NFS 的重复请求,同时避免额外的 RPC 调用。与 NFS 的其他许多方面一样,缓存在 NFSv4 中的实现比之前的版本更为彻底。

小贴士

关键概念 NFS 被设计成一个无状态的协议,具有智能的客户端和相对简单的服务器,服务器响应请求而不维护关于正在使用的文件的状态信息。NFS 最初被设计为使用 UDP 进行传输,以提高效率。这要求 NFS 客户端负责检测丢失的请求并重新传输它们。NFSv4 使用 TCP 来利用 TCP 的可靠性和其他特性。

NFS 服务器程序和操作

实际上,NFS 客户端和服务器之间的信息交换是通过底层的 RPC 协议完成的。因此,NFS 功能不是通过具体的协议操作来描述的,而是通过界定客户端可能对服务器上的文件执行的不同操作来描述的。在 NFS 的原始版本 NFSv2 中,这些被称为 NFS 服务器程序

每个程序代表客户端可能执行的一个特定操作,例如从文件中读取、写入文件或创建或删除目录。对文件执行的操作需要使用称为文件句柄的数据结构来引用文件。正如其名所示,文件句柄,就像真实对象的句柄一样,允许客户端和服务器“抓住”文件。本章后面将描述的挂载协议用于挂载文件系统,以便文件句柄可以被访问并用于 NFS 程序。

NFSv3 使用与服务器程序相同的基本模型,但进行了一些更改。删除了两个 NFSv2 程序,并添加了几个新程序以支持新功能。分配给识别每个程序的数字也发生了变化。

NFS 版本 2 和版本 3 服务器程序

表 58-2 显示了 NFS 版本 2 和版本 3 中定义的服务器程序。该表显示了 NFSv2 和 NFSv3 的进程编号,以及每个程序的名称和它所执行的操作的描述。我已将描述保持简短,以便表格可以作为 NFS 能做什么的有用摘要。它们按照 NFSv2 中使用的进程编号顺序列出。

表 58-2. NFS 版本 2 和版本 3 服务器程序

程序编号(v2) 程序编号(v3) 程序名称 程序摘要 描述
0 0 null 无操作 为测试目的提供的虚拟程序。
1 1 getattr 获取文件属性 从远程服务器检索文件的属性。
2 2 setattr 设置文件属性 设置(更改)远程服务器上文件的属性。
3 root 获取文件系统根(已废弃) 该程序最初被定义为允许客户端找到远程文件系统的根,但现在已废弃。此功能现在作为挂载协议的一部分实现。它在 NFSv3 中被删除。
4 3 lookup 查找文件名 返回文件句柄供客户端使用。
5 5 readlink 从符号链接读取 读取使用符号链接指定的文件名。
6 6 read 从文件读取 从文件中读取数据。
7 writecache 写入缓存 建议用于 NFSv2 的未来使用,但已被放弃并在 NFSv3 中删除。
8 7 write 写入文件 将数据写入文件。
9 8 create 创建文件 在服务器上创建文件。
10 12 remove 删除文件 从服务器删除文件。
11 14 rename 重命名文件 更改文件的名称。
12 15 link 创建文件链接 创建指向文件的硬(非符号)链接。
13 10 symlink 创建符号链接 创建指向文件的符号链接。
14 9 mkdir 创建目录 在服务器上创建目录。
15 13 rmdir 删除目录 删除目录。
16 16 readdir 从目录读取 读取目录内容。
17 statfs 获取文件系统属性 向客户端提供有关远程文件系统的一般信息,包括文件系统的大小和剩余的可用空间。在 NFSv3 中,这被 fsstat 和 fsinfo 所取代。
4 access 检查访问权限 确定用户对特定文件系统对象具有的访问权限。这是 NFSv3 中的新功能。
11 mknod 创建特殊设备 创建特殊文件,如命名管道或设备文件。这是 NFSv3 中的新功能。
17 readdirplus 扩展目录读取 从目录中检索附加信息。这是 NFSv3 中的新功能。
18 fsstat 获取动态文件系统信息 返回易变(动态)文件系统状态信息,例如当前文件系统的可用空间和空闲文件槽的数量。这是 NFSv3 中的新功能。
19 fsinfo 获取静态文件系统信息 返回有关文件系统的静态信息,例如文件系统使用的一般数据和请求服务器应如何结构化的参数。这是 NFSv3 中的新功能。
20 pathconf 获取 POSIX 信息 为文件或目录检索附加信息。这是 NFSv3 中的新功能。
21 commit 在服务器上提交缓存数据到稳定存储 将服务器持有的任何写入缓存中的数据刷新到存储中。这用于确保客户端已发送给服务器但服务器尚未写入存储的数据被写入。这是 NFSv3 中的新功能。

客户端可能希望对文件执行多个操作是很常见的,例如连续的多次读取。NFSv2 和 NFSv3 中服务器过程系统的一个问题是,每个客户端操作都需要一个单独的过程调用。这在 NFS 通过高延迟链路使用时效率较低。

NFS 版本 4 服务器过程和操作

为了提高服务器过程的效率,NFSv4 对服务器过程的实现方式进行了重大改变。不是每个客户端操作都是一个单独的过程,而是定义了一个单一的过程,称为复合过程。在这个复合过程中,封装了大量的服务器操作。这些操作作为一个单元发送,服务器按顺序解释和执行每个操作中的指令。

这个改变意味着在 NFSv4 中实际上只有两个 RPC 过程,如表 58-3 所示。

表 58-3. NFS 版本 4 服务器过程

过程编号 过程名称 过程摘要 描述
0 null 不执行任何操作 为测试目的提供的虚拟过程。
1 compound 复合操作 将多个 NFS 操作组合成一个单一请求。

所有真实客户端操作都定义为复合过程内的操作,如表 58-4 所示。你会注意到,NFSv4 操作的数量比 NFSv2 和 NFSv3 中的程序数量多得多。这既是因为 NSFv4 中增加了功能,也是因为它结合了以前由单独的挂载协议执行的功能。

表 58-4. NFS 版本 4 服务器操作

操作编号 操作名称 操作摘要 描述
3 access 检查访问权限 确定用户对对象的访问权限。
4 close 关闭文件 关闭文件。
5 commit 提交缓存数据 将服务器在写缓存中持有的任何数据刷新到存储中,以确保任何挂起的数据被永久记录。
6 create 创建非常规文件对象 这类似于 NFSv3 中的 mknod 程序;它创建一个“非常规”(特殊)对象文件。(常规文件使用打开操作创建。)
7 delepurge 清除待恢复的委托 NFSv4 具有一个功能,即服务器可以委托客户端负责某些文件。此操作从客户端移除等待恢复的委托。
8 delegreturn 返回委托 返回客户端授予的服务器委托。
9 getattr 获取属性 获取文件的属性。
10 getfh 获取当前文件句柄 返回一个文件句柄,这是一个逻辑对象,用于允许访问文件。
11 link 创建文件链接 创建指向文件的硬链接(非符号链接)。
12 lock 创建锁 在文件上创建锁。锁用于管理对文件的访问——例如,防止两个客户端同时尝试写入文件,从而损坏它。
13 lockt 测试锁 测试对象上锁的存在,并返回有关它的信息。
14 locku 解锁文件 移除之前在文件上创建的锁。
15 lookup 查找文件名 查找或找到文件。
16 lookupp 查找父目录 返回对象的父目录的文件句柄。
17 nverify 验证属性差异 检查文件上的属性是否已更改。
18 open 打开常规文件 打开文件。
19 openattr 打开命名属性目录 打开与文件关联的属性目录。
20 open_confirm 确认打开 确认与打开文件相关的信息。
21 open_ downgrade 降低打开文件访问权限 调整已打开文件的访问权限。
22 putfh 设置当前文件句柄 用另一个文件句柄替换一个文件句柄。
23 putpubfh 设置公共文件句柄 将当前文件句柄设置为服务器的公共文件句柄。这可能或可能不与根文件句柄相同。
24 putrootfh 设置根文件句柄 将当前文件句柄设置为服务器文件系统的根。
25 read 从文件读取 从文件中读取数据。
26 readdir 读取目录 读取目录的内容。
27 readlink 读取符号链接 读取使用符号链接指定的文件名。
28 remove 移除文件系统对象 移除(删除)一个对象。
29 rename 重命名目录条目 更改对象名称。
30 renew 续订租约 续订服务器做出的 NFS 委托。(注意,这些租约与 DHCP 租约无关,DHCP 租约在第六十一章中讨论。)
31 restorefh 恢复保存的文件句柄 允许将先前保存的文件句柄恢复为当前文件句柄。
32 savefh 保存当前文件句柄 允许保存文件句柄,以便在需要时可以稍后恢复。
33 secinfo 获取可用安全信息 获取 NFS 安全信息。
34 setattr 设置属性 更改一个或多个文件的属性。
35 setclientid 协商客户端 ID 允许客户端向服务器传达有关客户端如何使用 NFS 的信息。
36 setclientid_confirm 确认客户端 ID 用于通过 setclientid 确认先前协商的结果。
37 verify 验证相同属性 允许客户端在执行特定操作之前验证某些属性。
38 write 写入文件 将数据写入文件。
39 release_lockowner 释放锁所有者状态 由客户端用于告诉服务器释放与文件锁相关的某些信息。
10044 illegal 非法操作 当客户端请求中使用无效操作时,用于支持错误报告的占位符(虚拟)操作。

提示

关键概念 在 NFS 中,文件操作是通过 NFS 服务器过程来执行的。在 NFS 的 2 和 3 版本中,每个过程执行一个动作,例如从文件中读取数据。在 NFSv4 中,定义了一个特殊的 复合 动作,允许将多个单个 操作 在一个请求中发送到服务器。

NFS 文件系统模型和挂载协议

由于 NFS 允许客户端模拟对远程文件系统的访问,就像它们是本地的一样,因此协议必须将远程系统的文件呈现给本地用户。就像本地存储设备上的文件使用特定的文件系统进行组织一样,NFS 使用 文件系统模型 来表示文件如何呈现给用户。

NFS 文件系统模型

NFS 使用的文件系统模型是我们大多数人所熟悉的:包含文件和子目录的目录的分层排列。分层结构的顶部是根目录,它包含任意数量的文件和一级目录。每个目录可以包含更多的文件或其他目录,允许创建任意树形结构。

一个文件可以通过其文件名和显示从根目录到该文件所需遍历的目录序列的路径名来唯一指定。由于 NFS 与 UNIX 相关联,NFS 讨论中的文件通常以 UNIX 格式表示;例如,/etc/hosts。同样的基本树形概念也可以使用 Windows 操作系统遵循的方法来表示:C:\WINDOWS\HOSTS

挂载协议

在 NFS 可以使用来允许客户端访问远程服务器上的文件之前,客户端必须有一种访问文件的方式。这意味着必须将远程文件系统的一部分提供给客户端,并打开文件以供访问。在创建 NFS 时,做出了一个特定的决定,即不在 NFS 本身中放置文件访问、打开和关闭功能。相反,创建了一个单独的协议与 NFS 一起工作,这样如果以后需要更改提供文件访问的方法,就不需要修改 NFS 本身。这个单独的机制被称为挂载协议,并在 RFC 1094(NFSv2)附录 A 中描述。请注意,尽管它在功能上独立,但挂载被视为 NFS 整体包的一部分。

当 NFS 修订到版本 3 时,挂载协议也相应地进行了修改。NFSv3 版本的挂载协议在 RFC 1813(NFSv3)附录 I 中定义。它包含了一些对协议工作方式的变化,但 NFS 挂载的两个版本的整体操作基本上是相同的。

“挂载”这个术语实际上是一个与硬件术语相对应的术语,指的是使物理存储卷可用。在过去,存储设备通常是可移动的磁盘包,要使用它,你需要将其挂载到驱动器单元上。以类似的方式,NFS 资源通过挂载协议在逻辑上挂载,从而使共享文件系统对客户端可用。然后可以打开一个文件,并将文件句柄返回给 NFS 客户端,以便它可以引用该文件进行读取和写入等操作。

小贴士

关键概念 NFS 的版本 2 和 3 不包括在远程服务器上打开或关闭资源的流程。在这些版本上完成 NFS 任务之前,必须使用特殊的挂载协议来挂载文件系统并创建一个文件句柄以访问该文件系统上的文件。当不再需要时,该协议也用于卸载文件系统。挂载协议的实现方式与 NFS 本身类似,定义了一系列使用 RPC 和 XDR 的流程。在 NFSv4 中,挂载协议不再需要,因为它执行的任务已经被实现为 NFSv4 操作。

挂载协议的实际实现与 NFS 本身非常相似。像 NFS 一样,挂载协议使用 XDR 来定义客户端和服务器之间交换的数据类型,并使用 RPC 来定义一组客户端可以用来执行不同操作的服务器流程。挂载与 NFS 之间的主要区别仅仅是挂载定义了与打开和关闭文件系统相关的流程,而不是文件访问操作。表 58-5 显示了挂载协议中使用的服务器流程。

表 58-5. NFS 挂载协议服务器流程

流程编号 流程名称 流程摘要 描述
0 null 不做任何事情 提供的用于测试的虚拟流程。
1 mnt 添加挂载条目 通过将服务器上的路径映射到客户端使用的文件句柄来执行挂载操作。
2 dump 返回挂载条目 返回远程挂载的文件系统列表。
3 umnt 删除挂载条目 通过删除挂载条目来执行卸载操作。(是的,应该是dismount;技术人员通常不是英语专业。)
4 umntall 删除所有挂载条目 删除所有挂载条目,从而消除服务器和客户端之间的所有挂载文件系统。
5 export 返回导出列表 返回导出的文件系统列表,并指示哪些客户端被允许挂载它们。这用于让客户端看到哪些被服务的文件系统可供使用。

再次强调,NFSv4 摒弃了单独的挂载协议的概念,直接将文件挂载操作纳入 NFS。

第三部分-3. 主机配置和 TCP/IP 主机配置协议

第五十九章

第六十章")

第六十一章

第六十二章

第六十三章

第六十四章

每个放置在网络上或互联网上的主机在使用之前都必须进行设置和配置。配置确保主机正常工作,并告知它与其他主机和设备成功通信所需的参数。在美好的旧日子里,管理员会手动设置每个主机,每当它被添加到网络时,他们也会根据需要手动更改配置。

然而,现代网络非常大,手动配置主机是一项耗时的工作。此外,我们经常需要只有自动化配置才能提供的功能,尤其是对于没有内部存储的特殊主机。正因为如此,才开发了 主机配置 协议。

本部分包括六章,描述了主机配置协议背后的概念,并说明了目前使用中最重要的两个协议的操作。第一章是主机配置概念和问题的概述,这将帮助您理解为什么这些协议如此重要。第二章,我描述了 TCP/IP 引导协议 (BOOTP),这是第一个真正有能力的为互联网协议 (IP) 主机提供自动化配置的工具。

本部分剩余的章节涵盖了 BOOTP 的继任者,功能丰富的动态主机配置协议 (DHCP)。第三章介绍了 DHCP,并讨论了 DHCP 分配地址的不同方式,重点关注动态寻址。第四章讨论了 DHCP 的操作,包括配置参数管理以及分配地址和管理这些分配的流程。第五章描述了 DHCP 消息,并说明了 DHCP 消息格式。最后一章详细介绍了 DHCP 客户端和服务器,探讨了 DHCP 的特殊特性和问题,并描述了 DHCP 对支持新 IP 版本 6(IPv6)所做的更改。

从技术上讲,TCP/IP 的第一个主机配置协议是反向地址解析协议(RARP)。RARP 是一个简单、原始的协议,允许执行非常基本的主机配置,但除此之外很少。RARP 与 BOOTP 和 DHCP 非常不同,不仅因为它的功能更有限,还因为它在 2 层和 3 层之间运行,就像它所基于的地址解析协议(ARP)一样。因此,它包含在第二部分-2 中,该部分还描述了 ARP。

第五十九章。主机配置概念、问题和动机

无标题图片

将主机置于互联网中需要遵循某些设置和配置程序。必须选择和设置硬件,并在硬件上选择和安装软件。一旦软件设置完成,我们还没有完成。我们还需要执行其他配置任务,告诉软件我们希望它如何运行,并给它一些参数,以便它知道自己在网络中的角色以及如何运行。

在这一简短的章节中,我讨论了主机配置的目的、与之相关的问题以及主机配置协议。

主机配置的目的

在互联网中为每个主机执行的最重要配置任务可能是为其赋予一个身份,形式为一个仅属于它的唯一地址。在 TCP/IP 网络中,每个设备都必须分配一个 IP 地址。主机通常还需要其他参数以确保它们正常运行。对于 TCP/IP 网络,我们可能希望告诉每个主机以下信息:

  • 本地网络上默认路由器的地址

  • 主机应使用的网络掩码

  • 为主机提供特定服务的服务器地址,例如邮件服务器或域名系统(DNS)名称服务器

  • 本地网络的最大传输单元(MTU)(见第二十二章

在 TCP/IP 网络上,一个设备能够有效通信之前,它需要知道自己的 IP 地址。虽然传统的网络主机可以从其内部磁盘读取此信息,但某些设备没有存储空间,因此没有这种奢侈。它们需要网络上的另一个设备提供 IP 地址以及其他它们需要成为活跃的互联网协议(IP)主机所需的信息和/或软件。将新机器启动并运行的问题通常被称为引导启动,为了向 IP 主机提供这种能力,TCP/IP 的引导协议(BOOTP)被创建。

在本章中,我详细介绍了 BOOTP。我首先概述了该协议的历史和标准,然后讨论了 BOOTP 的客户端/服务器特性以及客户端和服务器之间通信中的寻址方式。我逐步描述了 BOOTP 的操作,并说明了 BOOTP 消息的格式。最后,我描述了 BOOTP 供应商扩展,这些扩展用于允许在 BOOTP 消息中发送的信息进行定制,并讨论了 BOOTP 中继代理,这些代理允许协议在 BOOTP 服务器和客户端位于不同网络时也能运行。

小贴士

相关信息 BOOTP 是动态主机配置协议(DHCP)的前身。DHCP 被构建为与 BOOTP 高度兼容,因此这两个协议有相当程度的相似性。为了避免重复,某些信息仅包含在以下关于 DHCP 的章节中(在适当的地方引用本章节)。另一方面,一些历史背景信息,如供应商信息扩展和中继代理,这些功能最初是为 BOOTP 开发的,后来被 DHCP 采用,包含在本章中,并从 DHCP 章节中引用。如果您计划阅读关于 DHCP 和 BOOTP 的内容,我建议首先阅读本节。如果您不打算了解 DHCP,您可能希望查看第六十四章中关于 DHCP/BOOTP 互操作性的讨论

BOOTP 概述、历史和标准

TCP/IP 协议套件已经陪伴我们超过二十年了,而如何在 IP 主机上自动配置参数的问题几乎与它一样历史悠久。在 20 世纪 80 年代初,网络规模小且相对简单,因此手动配置并不困难。自动主机配置主要需要,因为这是配置无盘工作站等设备唯一的方式。

正如我在第五十九章中讨论的那样,如果没有某种形式的内部存储,设备每次开机时都必须依赖某人或某物来告诉它“它是谁”(它的地址)以及如何操作。当这种设备开机时,它处于一个困难的境地:它需要使用 IP 与另一个设备通信,该设备将告诉它如何使用 IP 进行通信!这个过程被称为引导启动,它来源于一个人“用自己的靴带把自己拉起来”的类比。你可能以前遇到过这个术语,如果不是在其他时候,那么可能是在某个技术支持人员告诉你“重新启动”你的计算机的时候。

BOOTP:纠正 RARP 的弱点

反向地址解析协议(RARP)是解决这个引导问题的第一次尝试。RARP 是在 1984 年创建的,它是将 IP 地址绑定到链路层硬件地址的低级地址解析协议(ARP)的直接改编(见第十三章)。RARP 能够通过主机和 RARP 服务器之间简单的请求和回复客户端/服务器交换,为无盘设备提供其 IP 地址。

RARP 的困难在于它有很多限制。它在一个相当低级的层面上使用硬件广播进行操作,因此需要针对不同硬件类型进行调整。每个物理网络都需要一个 RARP 服务器来响应第 2 层的广播。每个 RARP 服务器都必须由管理员手动提供地址分配。最糟糕的是,RARP 只向主机提供一个 IP 地址,而不会提供主机可能需要的其他任何信息。(我在第十四章中详细描述了这些问题。)

RARP 显然不足以满足 TCP/IP 的主机配置需求。为了支持无盘主机和其他需要自动配置好处的情况,创建了 BOOTP。BOOTP 在 1985 年 9 月发布的 RFC 951 中被标准化。这个相对简单的协议是专门设计来解决 RARP 的不足的:

  • BOOTP 仍然基于客户端/服务器交换,但作为更高层的软件协议实现,使用用户数据报协议(UDP)进行消息传输(见第四十四章)。它不依赖于网络的具体硬件,如 RARP 所做的那样。

  • 它支持向客户端发送除 IP 地址之外的其他配置信息。为了提高效率,这些额外信息通常可以包含在一个消息中。

  • 它可以处理客户端和服务器位于互联网的不同网络中。这使得提供 IP 地址的服务器管理更加集中化,从而节省了金钱以及管理时间和麻烦。

应该注意的是,尽管 BOOTP 的名字暗示它定义了无存储设备启动所需的一切,但这并不是真的。正如 BOOTP 标准本身所描述的,引导通常需要两个阶段。在第一阶段,客户端被提供地址和其他参数。在第二阶段,客户端下载软件,如操作系统和驱动程序,使其能够在网络上运行并执行其他任务。BOOTP 实际上只处理这些阶段中的第一个:地址分配和配置。第二个阶段假定使用简单的文件传输协议,如简单文件传输协议(TFTP,在第七十三章中讨论,Chapter 73"))。

小贴士

关键概念 TCP/IP 的第一个广泛使用的主机配置协议是引导协议(BOOTP)。它是专门创建的,旨在在解决 RARP 的许多弱点的同时实现主机配置。BOOTP 旨在作为无存储设备两阶段引导过程的第一阶段使用。在通过 BOOTP 获取 IP 地址和其他配置参数后,设备使用 TFTP 等协议下载在网络上运行所需的软件。

供应商特定参数

在创建 BOOTP 时做出的一个明智的决定是包含一个供应商特定区域。这是为了提供一个地方,让硬件供应商可以定义与其产品相关的参数。随着 TCP/IP 的复杂性增加,人们意识到这个字段可以用来定义一种方法,以通信 IP 主机通常需要的某些参数,实际上这些参数与供应商无关。这首先在 1988 年 2 月发布的 RFC 1048,“BOOTP 供应商信息扩展”中提出。

事实是,BOOTP 不仅可以向客户端提供 IP 地址之外的信息,这使得即使在设备已经知道其地址的情况下,它仍然很有用。BOOTP 可以用来发送管理员希望所有主机都具有的参数,以确保它们以一致的方式使用网络。此外,对于具有本地存储(因此不需要 BOOTP 获取 IP 地址)的设备,BOOTP 仍然可以用来让这些设备获取引导阶段第二阶段所需的引导文件名称,在这个阶段,客户端下载软件。

BOOTP 的变化和 DHCP 的发展

从 20 世纪 80 年代中期到 90 年代末,BOOTP 一直是 TCP/IP 主机配置协议的首选。RFC 1048 中引入的供应商扩展很受欢迎,并且多年来,定义了额外的供应商扩展。RFC 1048 随后被 RFC 1084、RFC 1395 和 RFC 1497 依次取代。

在过去几年中,关于 RFC 951 的某些部分应该如何解释以及某些 BOOTP 功能如何工作也存在一些混淆。1993 年 10 月发布的 RFC 1542,“引导协议的澄清和扩展”旨在解决这个问题,并对协议的操作进行了一些轻微的更改。(RFC 1542 实际上是与几乎相同的 RFC 1532 的更正,后者有一些小错误。)

虽然 BOOTP 显然非常成功,但它也存在某些弱点。其中最重要的一个就是缺乏对 动态 地址分配的支持。在 1990 年代后期互联网真正开始起飞时,对动态分配的需求变得更加明显。这直接导致了动态主机配置协议(DHCP)的发展。

虽然 DHCP 取代了 BOOTP 成为首选的 TCP/IP 主机配置协议,但说 BOOTP 已经消失是不准确的。它至今仍在某些网络中使用。此外,DHCP 直接基于 BOOTP,并且它们共享许多属性,包括一个通用的消息格式。BOOTP 供应商扩展被用作 DHCP 选项 的基础,这些选项以相同的方式工作,但包括额外的功能。实际上,RFC 1497 的继任者是 RFC 1533,它正式将 BOOTP 供应商扩展和 BOOTP 选项合并到同一标准中。

BOOTP 客户端/服务器消息和寻址

虽然 BOOTP 可以用于各种设备,但其创建背后的一个主要动机是为没有存储的“笨拙”设备提供一种自动配置的方法。这些设备中的大多数在功能上相对有限,因此要求它们支持复杂的引导协议是没有意义的。因此,BOOTP 是一种简单的协议,它通过不涉及太多复杂的概念或实现要求来完成主机配置。

与许多其他 TCP/IP 协议一样,BOOTP 在本质上是一种客户端/服务器架构。该协议的操作由一个 BOOTP 客户端 和一个 BOOTP 服务器 之间的单一消息交换组成。任何需要配置的设备都可以是 BOOTP 客户端。BOOTP 服务器是一种特别设置以响应 BOOTP 客户端请求的网络设备,并且已经编程了它可以在需要时提供给客户端的寻址和其他信息。

BOOTP 服务器维护一组关于其服务的客户端的特殊信息。其中关键的一部分是一个将每个客户端的硬件(第 2 层,数据链路层)地址映射到分配给该设备的 IP 地址的表。客户端在其请求中指定其硬件地址,服务器使用该地址查找客户端的 IP 地址并将其返回给客户端。(也可以使用其他技术,但映射表是最常见的。)

BOOTP 消息和传输

由于几个原因,BOOTP 消息使用 UDP 作为其第 4 层传输协议:

  • UDP 比其他层 4 传输协议(传输控制协议 TCP)简单得多,非常适合像 BOOTP 这样的简单请求/回复协议。

  • 由于客户端显然不知道 BOOTP 服务器的地址,因此请求会在其本地网络中广播。UDP 支持广播;TCP 不支持。

UDP 为 BOOTP 服务器使用一个特殊的已知(保留)端口号:UDP 端口 67。BOOTP 服务器在端口 67 上监听客户端发送的这些广播 BOOTP 请求。在处理请求后,服务器将回复发送回客户端。这如何处理取决于客户端是否知道自己的地址。

BOOTP 通常用于向不知道其地址的客户端提供 IP 地址。这有时被称为“鸡生蛋还是蛋生鸡”的问题,因为它代表了一种循环,就像古老的谜题:是鸡先还是蛋先?为了解决这个困境,BOOTP 服务器有两个选择。如果操作系统支持,服务器可以使用客户端的硬件地址为设备创建一个 ARP 条目,然后使用层 2 单播来发送回复。否则,它必须在本地网络上以广播的形式发送回复。

然而,在 BOOTP 客户端已经知道自己的地址的情况下,该地址可以被 BOOTP 服务器用来直接发送回复。

BOOTP 的广播和端口使用

由于 BOOTP 服务器可能需要向客户端广播回复,这需要从大多数 TCP/IP 协议使用客户端端口的方式中做出一些改变。回想一下,通常,在 UDP 或 TCP 的客户端/服务器事务中,客户端生成一个临时或临时的端口号,并将其用作请求中的源端口。服务器使用该临时端口号将回复发送回客户端的 IP 地址。

临时端口号必须对于特定的 IP 地址是唯一的,但可能不是网络中所有设备都唯一。例如,设备 A 可能正在使用临时端口号 1248 向 Web 服务器发送 HTTP 请求,而设备 B 可能在其 TCP/IP 堆栈上使用端口号 1248 发送域名系统(DNS)请求。由于 BOOTP 中的服务器正在广播,它不是针对特定设备进行单播传输。这意味着它不能安全地向临时端口号发送。这是因为网络上的其他设备可能已经为其他事务选择了相同的临时端口号,并可能错误地将 BOOTP 服务器的响应误认为是针对自己的。为了避免这个问题,另一个已知的端口号仅用于 BOOTP 客户端:UDP 端口 68。客户端监听此端口以接收广播或单播传输;尚未发送 BOOTP 请求的设备将忽略它。这种双广播 BOOTP 通信过程在图 60-1 中说明。

BOOTP 的通用操作

图 60-1. BOOTP 的通用操作

小贴士

关键概念 BOOTP 是一个相对简单的客户端/服务器协议,它依赖于广播来允许与没有分配 IP 地址的设备进行通信。在这个例子中,设备 A 正在尝试确定其 IP 地址和其他参数。它使用 UDP 端口 67 在本地网络上广播一个 BOOTP 请求,然后监听端口 68 上的回复。设备 D 配置为 BOOTP 服务器,并监听此端口。当它收到请求时,它会在端口 68 上发送一个广播,告诉设备 A 其 IP 地址是什么。BOOTP 客户端使用广播将其请求发送到任何监听的 BOOTP 服务器。在大多数情况下,当 BOOTP 客户端设备使用该协议时,它不知道自己的 IP 地址。因此,BOOTP 服务器通常也会使用广播发送其回复,以确保它到达客户端。

丢失消息的重传

使用 UDP 进行 BOOTP 消息传递的简单性的缺点是 UDP 不可靠,这意味着 BOOTP 请求可能在到达服务器之前丢失,或者服务器的响应可能无法返回给客户端。像许多其他使用 UDP 的协议一样,BOOTP 客户端通过使用重传计时器来处理这个问题。如果在一定时间内客户端没有收到响应,它会重新发送其请求。

然而,BOOTP 客户端必须小心实施其重传策略。考虑一个场景,一个有 200 个 BOOTP 客户端的网络断电。这些机器几乎都是相同的,所以当电力恢复时,它们都会同时启动并尝试发送 BOOTP 请求。很可能会因为所有这些请求而出现问题:一些会丢失,或者服务器可能会因为过载而丢弃一些。如果所有客户端使用相同的时间进行重传,那么在经过这段时间后,大量机器将再次发送请求并重新创建原始问题。

为了避免重传问题,BOOTP 标准建议使用指数退避方案进行重传,起始重传间隔为 4 秒,并在后续尝试中将其加倍。还添加了一个随机元素,以防止许多设备重叠其重传。这个想法与以太网使用的退避方法非常相似(实际上,标准甚至引用了以太网规范)。例如,第一次重传将在 0 到 4 秒之间的随机时间段后发生(加上或减去一个随机量);如果需要,第二次重传将在 0 到 8 秒之间的随机时间间隔后发生,加上或减去,依此类推。这有助于减少重传丢失的机会,并确保 BOOTP 流量不会使网络过载。

小贴士

关键概念 BOOTP 使用 UDP 进行传输,它不提供可靠性功能。因此,BOOTP 客户端必须检测其请求是否丢失,并在必要时重新传输它们。

BOOTP 详细操作

现在您已经了解了 BOOTP 消息在一般意义上的工作方式,让我们更详细地看看该协议的操作。这将阐明客户端和服务器如何创建和处理消息,并有助于理解 BOOTP 消息字段格式中的重要字段。了解 BOOTP 的基本操作还将有助于我们在本章后面检查 BOOTP 中继代理,甚至在讨论下一章中的 DHCP 时。

BOOTP 引导过程

以下是在常规 BOOTP 引导过程中客户端和服务器执行的基本步骤(参见图 60-2)。

客户端创建请求 客户端机器通过创建一个 BOOTP 请求消息来开始这个过程。在创建这个消息时,它填写以下信息:

  • 它将消息类型(Op)设置为值 1,表示 BOOTREQUEST 消息。

  • 如果它知道它计划继续使用的自己的 IP 地址,它将在 CIAddr(客户端 IP 地址)字段中指定它。否则,它将此字段填充为零。(CIAddr 字段将在下一节中详细讨论。)

  • 它将自己的层 2 硬件地址放入 CHAddr 字段。服务器使用这个地址来确定客户端的正确地址和其他参数。

  • 它生成一个随机的事务标识符并将其放入 XID 字段。

  • 客户端可以指定它想要发送回复的特定服务器,并将其放入 SName 字段。它还可以在 File 字段中指定它想要服务器提供的特定类型的引导文件名称。

  • 如果程序允许,客户端可以指定供应商特定的信息。

客户端发送请求 客户端通过向地址 255.255.255.255 发送 BOOTREQUEST 消息来进行广播。或者,如果它已经知道一个 BOOTP 服务器的地址,它也可以发送单播请求。

服务器接收请求并处理它 监听 UDP 端口 67 的 BOOTP 服务器接收广播请求并处理它。如果指定了特定服务器的名称,并且这个名称与该服务器的名称不同,服务器可能会丢弃请求。如果服务器知道客户端请求的服务器也在本地网络中,这种情况尤其如此。如果没有指定特定服务器,或者这个特定服务器是客户端想要的服务器,服务器将回复。

服务器创建回复 服务器通过复制请求消息并更改几个字段来创建回复消息:

  • 它将消息类型(Op)更改为 2,表示 BOOTREPLY 消息。

  • 它从 CHAddr 字段获取客户端指定的硬件地址,并使用它在表中查找以找到此主机的匹配 IP 地址。然后,它将此值放入回复的 YIAddr(您的 IP 地址)中。

  • 它处理文件字段,并提供客户端请求的文件名类型,或者如果该字段为空,则提供默认文件名。

  • 它将其自己的 IP 地址和名称放入 SIAddr 和 SName 字段。

  • 它在 Vend 字段中设置任何厂商特定的值。

服务器发送回复 服务器发送回复。它使用的方法取决于请求的内容:

  • 如果设置了 B(广播)标志,这表示客户端不能接收单播回复,因此服务器将广播它。

  • 如果 CIAddr 字段不为零,服务器将单播回复发送回该 CIAddr。

  • 如果 B 标志为零且 CIAddr 字段也为零,服务器可能使用前面描述的 ARP 条目或广播。

客户端处理回复 客户端接收服务器的回复并处理它,存储提供的信息和参数。(有关此处理的一个重要问题,请参阅下一节。)

客户端完成引导过程 一旦配置完成,客户端将使用如 TFTP 之类的协议进入引导过程的第二阶段,下载包含操作系统软件的引导文件,使用服务器提供的文件名。

客户端 IP 地址(CIAddr)字段的解释

当客户端选择在其请求的 CIAddr 字段中指定 IP 地址时,可能会出现一个复杂情况。问题是如何确切地解释此字段。这是否意味着客户端已经在使用此 IP 地址?或者这只是它上次引导时使用的 IP 地址?然后还有相关的问题,即如果服务器在 YIAddr 中提供的地址与客户端正在使用的地址不同,应该怎么办。服务器的提供地址是否应该覆盖客户端的地址?或者客户端应该忽略它?谁做出决定,是服务器还是客户端?

BOOTP 操作 BOOTP 使用一个简单的两步消息交换,包括广播请求和广播回复。在客户端从 BOOTP 服务器接收配置信息后,它使用如 TFTP 之类的协议完成引导过程。

图 60-2. BOOTP 操作 BOOTP 使用一个简单的两步消息交换,包括广播请求和广播回复。在客户端从 BOOTP 服务器接收配置信息后,它使用如 TFTP 之类的协议完成引导过程。

由于原始标准在这方面含糊不清,导致出现了很多混淆,这导致了不同实现选择处理此问题的非一致性。甚至有一些实现使用 CIAddr 表示“客户端请求此 IP 地址”,这从未是 BOOTP 功能的一部分。这是一个特别糟糕的想法,因为它可能导致 BOOTP 回复永远无法到达客户端。

RFC 1542 部分是为了尝试清理这种混乱而编写的。它建议以下是最有效的处理这些字段含义的方法:

  • 如果客户端愿意接受服务器提供的任何 IP 地址,即使它知道之前的地址,它也会将 CIAddr 设置为全零。

  • 如果客户端为该字段填写了值,它表示它将使用此地址,并且必须准备接收发送到该地址的单播消息。

  • 如果客户端在 CIAddr 中指定了一个地址,但在 YIAddr 字段中收到了不同的地址,则忽略服务器提供的地址。

注意,并非所有硬件设备都一定同意 RFC 1542 提供的这种解释,因此这里仍然存在与旧设备之间的潜在互操作性担忧。然而,RFC 1542 是在 1993 年编写的,所以这可能已经不再是多大的问题!

BOOTP 消息格式

在 BOOTP 中,信息交换的形式是由客户端发送的请求和由服务器发送的回复。BOOTP,就像许多其他请求/回复协议一样,使用通用的消息格式来处理请求和回复。客户端首先为消息预留内存空间并将其清零。然后,它填写消息的字段并发送请求,正如你在上一节中看到的。服务器不是从头开始创建回复,而是通过复制请求并更改某些字段来创建回复。

BOOTP 消息包含相当多的字段,因此消息格式相当大。它描述在表 60-1 和表 60-2 中,并在图 60-3 中展示。

表 60-1. BOOTP 消息格式

字段名称 大小(字节) 描述
Op 1 操作代码:指定消息的类型。值为 1 表示请求(BOOTREQUEST 消息)。值为 2 表示回复(BOOTREPLY 消息)。
HType 1 硬件类型:该字段指定用于本地网络的硬件类型,并且与 ARP 消息格式中的等效字段(HRD)以完全相同的方式使用(参见第十三章)。该字段的一些最常见值显示在表 60-2 中。
HLen 1 硬件地址长度:指定此消息中硬件地址的长度。对于使用 IEEE 802 MAC 地址的以太网或其他网络,该值为 6。这与 ARP 字段格式中具有类似名称的字段(HLN)的值相同。
Hops 1 跳数:客户端在发送请求之前将其设置为 0,并由 BOOTP 中继代理用于控制 BOOTP 消息的转发。
XID 4 事务标识符:客户端生成的一个 32 位标识字段,允许它与从 BOOTP 服务器接收到的回复进行匹配。
Secs 2 秒数:根据 RFC 951,客户端将“自客户端开始尝试引导以来经过的秒数”输入此字段。这应该为 BOOTP 服务器提供信息,以帮助它们决定先响应哪些请求。不幸的是,不清楚这是指自机器开机以来还是自第一个 BOOTREQUEST 消息发送以来的时间。此外,一些设备错误地实现了此字段。因此,它并不总是被使用。
Flags 2 标志:在原始 BOOTP 标准(RFC 951)中,这是一个空的 2 字节字段。RFC 1542 将其更改为标志字段,目前该字段仅包含一个标志。它有一个 B(广播)标志子字段,大小为 1 位,如果客户端在发送 BOOTP 请求时不知道自己的 IP 地址,则将其设置为 1。这作为立即指示 BOOTP 服务器或中继代理接收到的请求,它确实应该通过广播发送其回复。另一个子字段是保留字段,大小为 15 位,设置为 0,未使用。
CIAddr 4 客户端 IP 地址:如果客户端有一个当前 IP 地址,它计划继续使用,它将此地址放入此字段。通过填写此字段,客户端承诺对发送到此地址的单播 IP 数据报做出响应。否则,它将此字段设置为全 0,以告知服务器它想要分配地址。(请参阅本章前面的重要信息关于此字段。)
YIAddr 4 你的 IP 地址:服务器分配给客户端的 IP 地址。这可能与客户端当前使用的 IP 地址不同。
SIAddr 4 服务器 IP 地址:发送 BOOTREPLY 消息的 BOOTP 服务器的 IP 地址。
GIAddr 4 网关 IP 地址:当 BOOTP 中继代理在客户端和服务器在不同子网或网络之间进行 BOOTP 请求和回复通信时,用于路由 BOOTP 消息。要理解这个名称,请记住旧的 TCP/IP 术语中的路由器网关;BOOTP 中继代理通常是路由器。请注意,客户端将此字段设置为 0,并且在处理 BOOTREPLY 时应该忽略此字段。它特别不表示服务器向客户端提供用于一般 IP 路由目的的默认网关地址。
CHAddr 16 客户端硬件地址:发送 BOOTREPLY 的客户端的硬件(第 2 层)地址。它用于查找设备的分配 IP 地址,也可能用于回复消息的投递。
SName 64 服务器名称:发送 BOOTREPLY 的服务器可以选择将其名称放入此字段。这可以是一个简单的文本昵称或一个完全限定的 DNS 域名(例如 myserver.organization.org)。请注意,当客户端创建其请求时,它可以在该字段中指定一个名称。如果这样做,它表示它只想从具有此名称的 BOOTP 服务器获取回复。这可能是为了确保客户端能够访问仅存储在一个服务器上的特定启动文件。
文件 128 启动文件名:包含客户端可以下载以完成引导过程的启动文件的完整目录路径和文件名。客户端可以通过在此处输入文本描述来请求特定类型的文件,或者它也可以留空,服务器将提供默认文件的文件名。
Vend 64 供应商特定区域:最初创建是为了允许供应商根据不同类型硬件的需求定制 BOOTP,现在此字段也用于存储额外的供应商独立配置信息。下一节关于 BOOTP 供应商信息扩展,包含更多关于此字段的详细信息。它可能由客户端和/或服务器使用。

表 60-2. BOOTP 消息 HType 值

HType 值 硬件类型
1 以太网 (10 Mb)
6 IEEE 802 网络
7 ARCNet
15 帧中继
16 异步传输模式 (ATM)
17 高级数据链路控制 (HDLC)
18 光纤通道
19 ATM
20 串行线

如我在本章前面提到的,请求和回复都被封装进 UDP 消息进行传输。BOOTP 标准规定 UDP 校验和的使用是可选的。使用校验和可以提供对数据完整性错误的保护,因此是推荐的。这可能会对非常简单的客户端造成不可接受的处理需求,因此校验和可以合法地被跳过。

同样地,为了简化,BOOTP 假设其消息不会被分片。这是为了让 BOOTP 客户端避免重新组装分片消息的复杂性。由于 BOOTP 消息长度仅为 300 字节,在所有 TCP/IP 链路所需的最大传输单元(MTU)下,这通常不是问题。

BOOTP 消息格式

图 60-3. BOOTP 消息格式

BOOTP 供应商特定区域和供应商信息扩展

BOOTP 的创造者意识到某些类型的硬件可能需要从服务器传递额外的信息到客户端,以便客户端可以启动。出于这个原因,他们将 64 字节的 Vend 字段放入 BOOTP 字段格式中,也称为供应商特定区域。包含这个字段使 BOOTP 变得灵活,因为它允许供应商自己决定他们想要如何使用该协议,并根据自己的需求定制它。

客户端可以通过在其请求中请求字段中的某些类型的信息来使用 Vend 字段。然后服务器可以响应这些请求,并且它还可以包括它希望客户端拥有的参数,即使这些参数没有被请求。原始 BOOTP 协议没有定义任何结构用于供应商特定区域,将此留给每个制造商自行决定。

显然,一个制造商生产的客户端尝试向另一个制造商生产的服务器发送请求,没有任何阻止。如果每个设备都期望 Vend 字段包含不同的内容,结果将不会令人满意。因此,为了正确使用 Vend 字段,当涉及到这个字段的含义时,两个设备必须使用相同的语言。这是通过将字段的第一个四个字节设置为特殊值来实现的。每个制造商都为其自己的魔法数字选择一个值,有时也称为魔法饼干,用于这个四个字节的子字段。

注意

为什么叫魔法饼干?老实说,我不确定。我听说它的起源可能是《爱丽丝梦游仙境》中爱丽丝吃的可以让自己变大或变小的饼干

BOOTP 供应商信息扩展

在 BOOTP 中包含 Vend 字段为供应商特定信息提供了协议的可扩展性。不幸的是,原始字段格式没有包括任何从服务器发送到客户端以扩展通用、非供应商特定 TCP/IP 信息的方式。这在协议创建过程中是一个重大的疏忽,因为当 TCP/IP 主机启动时,它需要许多类型的信息,这些信息实际上与其供应商无关。例如,当主机启动时,我们可能希望它被告知默认路由器的地址、其本地子网的子网掩码、本地 DNS 服务器的地址、本地网络的 MTU 以及更多。这些都不是供应商特定的,但在 BOOTP 回复消息中没有地方可以放置它们。

由于 BOOTP 中没有非供应商特定的区域字段,因此决定定义一种使用供应商特定区域(Vend 字段)的方式来传递这种额外的通用信息。这首先在 RFC 1048 中得到了标准化,然后在后续的 RFC 中得到改进,正如我在本章前面关于 BOOTP 概述中解释的那样。这个方案基本上代表了一种使用 Vend 字段的方式,大多数 TCP/IP BOOTP 实现都选择了采用,无论它们的供应商是谁。这种增强正式称为BOOTP 供应商信息扩展

提示

关键概念 BOOTP 消息格式包括一个 Vend 字段,最初是为了供应商特定的定制字段而设计的。后来它被改为从 BOOTP 服务器发送到 BOOTP 客户端可以发送额外通用信息的地方。每个这样的参数都携带在一个 BOOTP 供应商信息字段中。

为了清楚地标记正在使用 Vend 字段的特定含义,将一个特殊的、通用的魔法 cookie 值 99.130.83.99 插入到字段的第一个四个字节中。然后剩余的 60 个字节可以包含一个或多个供应商信息字段的序列。当使用供应商信息扩展时,供应商特定区域的总体结构如图 60-4 所示。

BOOTP 供应商特定区域格式,显示供应商信息字段

图 60-4. BOOTP 供应商特定区域格式,显示供应商信息字段

注意

BOOTP 供应商特定区域以四个字节的魔法 cookie 开始,然后包含一系列可变长度的供应商信息字段,每个字段都具有上面所示和表 60-3 中的格式。尽管使用 IP 点分十进制表示值 99.130.83.99,但这不是一个 IP 地址。它只是一个标记——一个被普遍认可的魔法数字

BOOTP 供应商信息字段

每个供应商信息字段指定要传递的特定类型的信息,并使用一个特殊的子字段结构进行编码,该结构指定了字段类型、长度和值。这是一种常见的指定选项的方法,称为TLV 编码(代表类型、长度、值)。相同的基该方法用于编码互联网协议版本 4 和 6(IPv4 和 IPv6)选项。表 60-3 显示了每个供应商信息字段子字段的结构和常见名称。

表 60-3. BOOTP 供应商信息字段格式

子字段名称 大小(字节) 描述
Code 1 供应商信息字段代码:一个指定供应商信息字段类型的单字节。
Len 1 供应商信息字段长度:此特定供应商信息字段中的字节数。这不包括代码和长度字段中的两个字节。
Data 可变 供应商信息字段数据:正在发送的数据,其长度由长度子字段指示,并根据代码子字段进行解释。

有两种特殊情况违反了表 60-3 中显示的字段格式。当子字段需要对齐在字边界上时,使用代码值为 0 作为填充;它不包含任何信息。值 255 用于标记供应商信息字段的结束。这两个代码都不包含实际数据。为了节省空间,当使用任何一个时,只需包含单个代码值,并省略长度和数据字段。一个看到代码值为 0 的设备将其视为填充内容跳过;一个看到代码值为 255 的设备知道它已经到达了此 Vend 字段中的供应商信息字段末尾。

BOOTP 的供应商信息扩展变得如此流行,以至于使用此字段发送额外通用信息的做法几乎已成为标准。事实上,我不确定今天是否还有人仍然仅将 Vend 字段用于供应商特定信息。

当引入供应商信息扩展时,创建了一个指向可以找到供应商特定信息的文件的扩展。这使得设备能够兼得两者之利——它们可以使用标准的供应商独立字段,并在需要时可以包含供应商特定字段(通过引用的文件)。后来,又创建了一种新的字段类型,允许在 BOOTP 消息中直接将供应商特定字段与供应商独立字段混合。

当 DHCP 被创建时,保持了相同的供应商扩展机制并进一步增强了它,但字段不再被称为供应商信息扩展,而是更名为选项。(一个更好的名字!)BOOTP 的供应商信息字段在 DHCP 中得到了保留,并定义了新的 DHCP 特定选项。为了避免重复,我已经在第六十三章中列出了一套表格,其中包括了 BOOTP 供应商信息字段和 DHCP 选项,该章节涵盖了 DHCP 消息。这包括讨论如何混合供应商特定和供应商独立的信息。您可能还想阅读第六十三章中描述 DHCP 选项的部分,该部分讨论了它们是如何从 BOOTP 供应商信息扩展中创建出来的。

BOOTP 中继代理(转发代理)

RARP 被迅速取代的原因之一是 RARP 要求客户端配置并从服务器获取 IP 地址的客户端必须在同一物理网络上。当你运行一个拥有十台机器的小型组织时,这很正常,这些机器可能都在同一物理网络上。然而,为了效率,大型网络必须分成多个物理网络。RARP 需要为每个网络设置一个单独的 RARP 服务器,这意味着需要在多台机器上复制单个服务器的所有功能。更糟糕的是,所有配置信息也会被复制,并且每次更改都需要对所有不同的服务器进行修改。

BOOTP 被设计成允许 BOOTP 服务器及其所服务的客户端位于不同的网络中。这集中了 BOOTP 服务器,并大大减少了网络管理员所需的工作量。然而,实现这一功能意味着增加协议的复杂性。特别是,我们需要在配置过程中涉及第三方设备。

你可能会正确地想知道为什么会这样。RARP 是一个在链路层工作的低级协议,这就解释了为什么它会在将客户端和服务器放置在不同的物理网络上时遇到问题。但制作 BOOTP 为一个高级协议的整个目的不正是它能使用 IP 吗?如果 BOOTP 使用 IP,我们难道不能像任何基于 IP 的消息协议一样,任意地从网络发送到另一个网络吗?

答案是,尽管我们确实在使用 IP 和 UDP,但 BOOTP 仍然存在 RARP 的问题之一:依赖 广播。客户端通常不知道服务器的地址,因此它必须发送其请求作为广播,本质上是在说,“有人能听到这个并给我需要的信息吗?”出于效率的考虑,路由器不会路由此类广播,因为这会阻塞网络。这意味着如果服务器和客户端不在同一网络中,服务器就听不到客户端的广播。同样,如果服务器曾经收到请求并广播其回复给客户端,客户端也永远无法收到。为了使这一切都能正常工作,我们需要某种东西作为客户端和服务器之间的中介:一个 BOOTP 中继代理

BOOTP 中继代理的功能

BOOTP 中继代理的职责是坐在一个物理网络上,其中可能存在 BOOTP 客户端,并作为 BOOTP 服务器的代理。代理之所以得名,是因为它在客户端和服务器之间中继消息,从而使得它们可以位于不同的网络中。

注意

BOOTP 中继代理最初被称为转发代理。RFC 1542 将其名称更改为明确指出,BOOTP 中继与常规路由器进行的传统 IP 数据报转发不同

在实践中,BOOTP 中继代理通常不是单独的硬件设备。相反,它是一个运行在执行其他功能的现有硬件上的软件模块。在 IP 路由器上实现 BOOTP 中继代理功能是很常见的。在这种情况下,路由器既充当常规路由器,也扮演 BOOTP 代理的角色。BOOTP 中继代理所需的前进功能与路由器的正常 IP 数据报转发任务不同。

小贴士

关键概念 由于 BOOTP 使用广播,BOOTP 客户端和 BOOTP 服务器必须位于同一物理网络上,才能听到彼此的广播传输。对于位于不同网络的客户端和服务器进行通信,需要一个第三方来促成交易:一个BOOTP 中继代理。这个设备通常是路由器,它监听来自 BOOTP 客户端的传输并将它们中继到 BOOTP 服务器。服务器将回复发送回代理,然后代理将服务器的响应发送回客户端。

自然地,客户端和服务器位于不同的网络以及中继代理的存在显著改变了 BOOTP 的正常请求/回复过程。BOOTP 消息格式中的几个特定字段用于控制这个过程。RFC 951 在描述这个过程如何工作时相当模糊,因此 RFC 1542 对其进行了更详细的描述。

使用中继代理的正常 BOOTP 操作

以下以简化的形式展示了当涉及中继代理时,BOOTP 操作步骤的修订版。为了使这次讨论的规模可控,我省略了基本请求/回复过程的细节,以专注于中继功能,您也可以在图 60-5 中图形化地看到)。

客户端创建请求 客户端机器正常创建其请求。中继代理的存在对客户端来说是完全透明的。

客户端发送请求 客户端通过将其发送到地址 255.255.255.255 来广播 BOOTREQUEST 消息。(注意,在客户端已经知道自己的地址和 BOOTP 服务器地址的情况下,我们根本不需要中继代理——请求和回复都可以通过任意互联网进行单播发送。)

中继代理接收请求并处理 客户端所在的物理网络上的 BOOTP 中继代理代表服务器监听 UDP 端口 67。它按以下方式处理请求:

  • 它检查 Hops 字段的值。如果值小于或等于 16,则增加它。如果值大于 16,则丢弃请求并不再执行其他操作。

  • 它检查 GIAddr 字段的内容。如果该字段全部为零,它知道自己是处理请求的第一个中继代理,并将自己的 IP 地址放入该字段。(如果代理是路由器,它有多个 IP 地址,因此它选择接收请求的接口上的一个。)

中继代理转发请求 中继代理将 BOOTP 请求发送到 BOOTP 服务器。如果中继代理知道服务器的 IP 地址,它将直接以单播方式将其发送到服务器。否则,如果代理是路由器,它可能选择从接收请求的不同接口广播请求。在后一种情况下,可能需要多个中继代理来将请求传达给服务器。有关更多信息,请参阅下一节。

服务器接收请求并处理 BOOTP 服务器从 BOOTP 中继代理接收转发的请求。它像处理正常请求一样处理它。

服务器创建响应 服务器像往常一样创建响应消息。

服务器发送响应 由于请求中的 GIAddr 字段值不为零,服务器知道请求已被中继。它不会尝试将其响应发送回发送请求的客户端,而是将响应单播发送回 GIAddr 中指定的中继代理。

中继代理转发响应 BOOTP 中继代理将 BOOTREPLY 消息发送回客户端。它根据 CIAddr 字段的值和 B(广播)标志,以单播或广播的方式执行此操作,就像非中继情况下的服务器一样。

使用中继代理的 BOOTP 操作 在此示例中,设备 A 试图访问 BOOTP 服务器,但唯一的服务器位于不同的网络中;它们通过一个配置为充当 BOOTP 中继代理的工作组路由器连接。设备 A 广播其请求,路由器接收它。它将请求中继到 BOOTP 服务器,设备 D,并将自己的 IP 地址(IPR)放入 BOOTP GIAddr 字段。BOOTP 服务器使用 IPR 地址将响应发送回路由器。然后路由器在设备 A 的本地网络上广播它,以便设备 A 可以接收它。

图 60-5. 使用转发代理的 BOOTP 操作 在这个例子中,设备 A 正在尝试访问一个 BOOTP 服务器,但只有一个在另一个网络上;它们通过一个配置为作为 BOOTP 转发代理的工作组路由器连接。设备 A 广播其请求,路由器接收它。路由器将请求转发到 BOOTP 服务器,设备 D,并将自己的 IP 地址(IPR)放入 BOOTP GIAddr 字段。BOOTP 服务器使用地址 IPR 将回复发送回路由器。然后路由器在设备 A 的本地网络上广播它,以便设备 A 可以接收它。

使用广播转发 BOOTP 请求

转发的最简单情况是每个网络都有一个知道 BOOTP 服务器 IP 地址的转发代理。转发代理在上一节所述过程的第 3 步捕获请求,并将其直接发送到网络上的任何位置的 BOOTP 服务器。请求作为常规的单播 UDP 消息转发,并路由到 BOOTP 服务器。BOOTP 服务器的回复就像 IP 数据报中的任何 UDP 消息一样被路由回 BOOTP 转发代理,然后转发代理将回复转发出去。

还可以设置 BOOTP 转发代理来转发请求,即使它们不知道 BOOTP 服务器的地址。这些代理接收一个网络上的请求并将其转发到下一个网络,在那里它们期望另一个代理继续转发过程,直到到达 BOOTP 服务器。例如,假设我们有一组三个网络。网络 N1 通过路由器 RA 连接到网络 N2,网络 N2 通过路由器 RB 连接到网络 N3。这两个路由器都作为转发代理,但不知道 BOOTP 服务器的 IP 地址。以下是一个客户端在 N1 网络上发送请求而服务器在 N3 网络上的情况:

  1. 客户端会发送其请求。

  2. 路由器 RA 会捕获请求并将它的地址放入 GIAddr。它会将跳数字段增加到 1,然后将请求广播到网络 N2。

  3. 路由器 RB 会捕获这个请求。它会看到 GIAddr 中已经有了一个地址,所以它会保留这个地址。它会将跳数字段增加到 2,并在网络 N3 上广播请求。

  4. BOOTP 服务器会接收请求,处理它,并将回复直接发送回路由器 RA。

  5. 路由器 RA 会将回复转发回客户端。

如您所见,跳数字段的作用是确保错误的请求不会在网络中无限循环。每个转发代理都会增加它,如果值超过 16,则请求会被丢弃。您还可以看到,除了第一个以外的任何转发代理都只参与处理请求;回复会单播发送回离客户端最近的代理。

顺便提一下,如果这个多步骤中继过程听起来像 IP 路由(仅使用广播),并且跳数字段听起来像 IP 数据报中的生存时间(TTL)字段,那么你确实在注意。这本质上是一个相同的概念(如第二十一章第二十一章. 互联网协议数据报封装和格式中所述)。

第六十一章. DHCP 概述和地址分配概念

无标题图片

在某些方面,技术进步可以被认为更像是一次旅行而不是一个目的地。当某种特定技术被改进或被更优越的技术所取代时,它通常只是时间问题,它也会被更好的东西所取代。TCP/IP 引导协议(BOOTP)的情况也是如此,如前一章所述。虽然 BOOTP 比它所取代的协议——反向地址解析协议(RARP)——功能强大得多,但经过多年,BOOTP 本身也被一个新的 TCP/IP 配置协议所取代:动态主机配置协议(DHCP)

与 RARP 代表了从 RARP 到 BOOTP 的变革不同,DHCP 更多的是 BOOTP 的演变。它是基于 BOOTP 构建的,采用了相同的基本消息格式。DHCP 最显著的增加是能够动态地为客户分配地址并集中管理它们。正是这种能力使得 DHCP 如此强大。如今,DHCP 已成为标准的 TCP/IP 主机配置协议,并被用于从单客户端家庭网络到企业级互连网络的一切。

在本章关于 DHCP 的第一章中,我提供了对协议的概述,以及 DHCP 地址分配和租赁背后的概念的描述。我高屋建瓴地审视了 DHCP 地址分配的工作方式,并描述了三种 DHCP 地址分配机制。然后我深入探讨了 DHCP 租赁以及决定如何实施 DHCP 租赁的政策和技术。我概述了从开始到结束的整个租赁生命周期,并描述了帮助控制过程的两个 DHCP 租赁计时器。最后,我描述了 DHCP 租赁地址池和范围,以及地址管理背后的通用概念。

小贴士

相关信息 由于 DHCP 建立在 BOOTP 之上,它们有许多共同之处。例如,DHCP 利用了 BOOTP 中继代理功能,并且 DHCP 选项基本上与 BOOTP 供应商信息字段相同。由于 DHCP 是这两种协议中更常见的一种,我在这里尽量全面地描述了这些功能的操作,特别强调了它们在 DHCP 和 BOOTP 中工作方式的不同之处。然而,我避免重复许多这些功能的历史和存在理由。由于 BOOTP 先出现,我在上一章中放置了更多的历史信息。一般来说,如果你打算阅读关于 DHCP 和 BOOTP 的内容,我建议首先阅读关于 BOOTP 的章节。如果你不打算阅读关于 BOOTP 的内容,你可能希望查看第六十四章中的 DHCP/BOOTP 互操作性主题

DHCP 概述、历史和标准

如你在上一章所学,BOOTP 相对于 RARP 来说是一个重大的改进,因为它解决了 RARP 的许多问题。BOOTP 是一个高层协议,不像 RARP 那样依赖于硬件。它能够支持向客户端发送超出 IP 地址之外的信息,以便实现定制配置。此外,通过使用 BOOTP 中继代理,它允许大型组织只需使用一个或两个 BOOTP 服务器来处理分布在许多物理网络上的客户端。这样做,BOOTP 有效地解决了管理员在手动配置中遇到的主要问题类别之一:“我必须亲自配置每个主机”的问题。它允许“愚笨”(无存储)的主机自动配置自己,从而节省了管理员需要逐个访问每个主机以指定重要配置参数的麻烦。

BOOTP 通常使用一种静态方法来确定分配给设备的 IP 地址。当客户端发送请求时,它会包含其硬件地址,服务器会在表中查找该地址以确定该客户端的 IP 地址。(BOOTP 可以使用其他方法来确定 IP 地址和硬件地址之间的关系,但通常使用静态映射。)这意味着 BOOTP 在相对静态的环境中运行良好,在这些环境中,分配给不同设备的 IP 地址的变化不频繁。这样的网络在 20 世纪 80 年代和 90 年代初基本上是标准。

随着时间的推移,由于多种原因,许多网络迅速开始从这种模式中转变出来。随着计算机变得越来越小和轻便,它们从一个网络移动到另一个网络的频率越来越高,这就需要使用新网络的网络 ID 来分配不同的地址。笔记本电脑甚至掌上电脑每天可以多次从一个网络移动到另一个网络。另一个主要问题是 IP 地址空间的即将耗尽(参见第十七章* 是目前现代 TCP/IP 互联网上使用的主机配置协议。它基于 BOOTP,在许多方面与前辈相似,包括使用请求/回复消息交换和几乎相同的消息格式。然而,DHCP 包含了额外的功能,其中最显著的是 动态地址分配,它允许客户端从由 DHCP 服务器管理的共享池中分配 IP 地址。

原始 DHCP 规范于 1997 年 3 月随着 RFC 2131 的发布进行了修订,该 RFC 也称为“动态主机配置协议”。该标准定义了另一种新的 DHCP 消息类型(DHCPINFORM),允许活动 IP 主机请求额外的配置信息。它还对协议进行了其他一些小的修改。从那时起,已经发布了大量其他与 DHCP 相关的 RFC,其中大多数要么定义了新的 DHCP 选项类型(DHCP 服务器可以向 DHCP 客户端发送的其他类型的信息),要么稍微细化了 DHCP 在特定应用中的使用方式。

DHCP 地址分配和分配机制

DHCP 的两个主要功能是为主机分配地址并提供一种方法,使客户端可以从服务器请求地址和其他配置数据。这两个功能都基于 DHCP 的前身 BOOTP 中实现的功能,但在地址分配方面的变化比在通信方面的变化更为显著。在这里开始探讨 DHCP 是有意义的,因为这自然会引导我们深入讨论 DHCP 的定义特征:动态地址分配

DHCP 地址分配

向客户端提供 IP 地址是主机配置协议执行的最基本的配置任务。为了在不同类型的客户端上配置地址提供灵活性,DHCP 标准包括三种不同的地址分配机制:手动、自动和动态。

我并不真的喜欢“自动”和“动态”分配的名称,因为它们并不能很好地清楚地传达这些方法之间的差异。这两种方法都可以被认为是自动的,因为在每种情况下,DHCP 服务器都会分配一个地址,而不需要任何管理员的干预。它们之间的真正区别只在于 IP 地址保留的时间长短,以及主机地址是否随时间变化。我认为更好的名称应该是“静态”或“永久”自动分配和“动态”或“临时”自动分配。

无论你称它们为什么,这三种方法都是为了使用 DHCP 配置 IP 主机而存在的。管理员没有必要在这三者之间做出选择。相反,他们通常会结合使用这些方法,在每个最适合的地方使用它们。

DHCP 手动分配

在手动分配中,管理员会预先为单个设备分配一个特定的 IP 地址。DHCP 只将 IP 地址传达给设备。

手动分配是最简单的方法,它等同于上一章中描述的 BOOTP 用于地址分配的方法。每个设备都有一个管理员提前分配的地址,而 DHCP 所做的只是查找表中的地址并将其发送给预期的客户端。这种技术对于网络中的主要设备,如服务器和路由器来说最有意义。它也适用于其他必须具有稳定、永久 IP 地址的设备。

好吧,现在有一个公平的问题你可能会有。在手动分配的情况下,DHCP 基本上就像 BOOTP 一样。但是 BOOTP 是为了需要配置帮助的设备而创建的。服务器和路由器是具有自己内部存储的复杂设备,显然它们不需要像无盘工作站那样由 DHCP 服务器告诉它们 IP 地址,那么为什么还要为它们使用 DHCP 呢?

嗯,实际上,你完全可以手动直接将地址分配给设备,并告诉 DHCP 忽略这些地址。然而,使用 DHCP 进行手动分配会带来不同的好处:管理上的好处。它将所有 IP 地址信息集中存储在 DHCP 地址数据库中,而不是要求管理员从一台机器跳到另一台机器检查地址,并确保没有重复。更新也可以在单一位置进行。

DHCP 动态分配

在 DHCP 中虽然可以进行手动分配,但动态分配才是其真正的宗旨。使用动态分配,DHCP 从地址池中为客户端分配一个 IP 地址,这个地址池由服务器根据客户端选择的时间限制进行分配,或者直到客户端通知 DHCP 服务器它不再需要该地址。管理员会设置一个地址池(通常是一个范围或一系列范围),其中包含可供使用的 IP 地址。每个配置为使用 DHCP 的客户端在需要 IP 地址时都会联系服务器。服务器会跟踪哪些 IP 地址已经被分配,并从地址池中为客户端租赁一个空闲地址。服务器决定租约的持续时间。当租约到期时,客户端必须要么请求继续使用该地址的权限(续租租约),要么必须获取一个新的地址。

动态分配是现代 DHCP 启用 IP 互联网中大多数客户端机器使用的方法。它提供了许多好处,例如以下内容:

自动化 当客户端需要 IP 地址时,可以自动为其分配,无需任何管理员干预。管理员无需手动决定哪个地址分配给哪个客户端。

集中管理 所有的 IP 地址都由 DHCP 服务器管理。管理员可以轻松查看哪些设备正在使用哪些地址,并执行其他网络范围内的维护任务。

地址重用和共享 通过限制每个设备持有 IP 地址的时间,DHCP 服务器可以确保地址池仅由正在使用网络的设备使用。经过一段时间后,不再使用的地址会返回到地址池,允许其他设备使用。这允许互联网支持比可用的 IP 地址更多的设备总数,只要不是所有设备同时连接到互联网即可。

便携性和通用性 BOOTP(以及 DHCP 手动分配)都要求 DHCP 服务器知道连接到它的每个客户端的身份,以便服务器可以找到客户端分配的地址。使用动态分配时,没有预定义的分配,因此任何客户端都可以请求 IP 地址。这本质上使得动态分配成为支持在网络上移动的设备的理想选择。

冲突避免 由于 IP 地址都是从由 DHCP 服务器管理的地址池中分配的,因此避免了 IP 地址冲突。当然,这假设所有客户端都使用 DHCP。管理员必须确保地址池不会被非 DHCP 设备使用。

DHCP 自动分配

使用自动分配方法,DHCP 会自动将一个 IP 地址永久分配给一个设备,从可用的地址池中选择。这种方法适用于有足够 IP 地址分配给可能连接到网络的每个设备,但设备并不关心它们使用哪个 IP 地址的情况。一旦地址分配给客户端,该设备将一直使用它。自动分配可以被视为动态分配的特殊情况:它本质上是一种动态分配,其中客户端使用 IP 地址的时间限制(租约长度)是永久的。

实际上,自动分配的使用频率远低于动态分配,原因很简单:永久性地将 IP 地址分配给设备是一个风险行为。大多数管理员认为,对于真正需要永久 IP 地址分配的有限数量的机器,使用手动分配更好,而对于其他设备则使用动态地址分配。

小贴士

关键概念 DHCP 定义了三种基本的地址分配机制。动态分配是最常用的方法,它通过让每个客户端从 DHCP 服务器租用一个地址一段时间来实现。服务器从共享地址池中动态选择地址。自动分配类似于动态分配,但地址是永久分配而不是租用。手动分配预先将一个地址分配给特定的设备,就像 BOOTP 一样,通常仅用于服务器和其他永久性、重要的主机。

DHCP 租约

在 DHCP 支持的三个地址分配方法中,动态地址分配迄今为止是最受欢迎和最重要的。动态地址分配对 TCP/IP 中 IP 地址使用方式的影响可以从 DHCP 中处理地址的语义中看出。在传统上,主机被认为是“拥有”一个 IP 地址,而当使用动态地址分配时,主机则被认为是“租用”一个地址。

租约的概念非常准确地传达了动态分配与其他类型之间的区别。主机不再严格拥有特定的地址,服务器只是告诉它地址是什么。在 DHCP 中,服务器仍然是地址池中所有 IP 地址的真正所有者,它只是允许客户端在一定时间内使用该地址。服务器保证在此期间不会尝试将地址分配给另一个客户端。如果客户端在一段时间后未能成功重新获得使用地址的权限,它必须停止使用该地址,否则可能会在网络中造成 IP 地址冲突。

小贴士

关键概念 DHCP 最重要的新特性是动态分配,这改变了 IP 地址的管理方式。在传统的 IP 中,每个设备拥有一个特定的 IP 地址,而在 DHCP 中,服务器拥有地址池中的所有地址,每个客户端从服务器租用一个地址,通常只有有限的租期。

DHCP 租约长度策略

当使用动态地址分配时,网络管理员必须向 DHCP 服务器提供参数,以控制租约的分配和管理方式。需要做出的最重要的决定之一是互联网的租约长度策略:管理员希望客户端租约持续多长时间。这个选择将取决于网络、服务器和客户端。租期选择,就像许多其他网络参数一样,最终取决于稳定性分配效率之间的权衡。

使用长租期的主要好处是设备的地址相对稳定。设备不需要担心其 IP 地址会不断变化,用户也是如此。这在许多情况下是一个显著的优势,尤其是在客户端需要执行某些服务器功能、接受传入连接或使用 DNS 域名(暂时忽略动态 DNS 功能)时。在这些情况下,设备 IP 地址四处移动可能会导致严重的问题。

使用长租期的主要缺点是它们大大增加了 IP 地址在不再需要时被占用的时间,直到它可以被重用。在最坏的情况下,分配浪费的时间几乎可以与租期本身一样长。如果我们给设备分配一个特定的地址六个月,而在两周后设备关闭且不再使用,它所使用的 IP 地址仍然在接下来的五个月半内不可用。

因此,许多管理员更喜欢使用短租期。这迫使客户端只要需要就不断续租。当它停止请求许可时,地址会迅速返回到池中。这使得在地址数量有限且必须节约的环境中,短租期成为一个更好的选择。缺点是长租期的相反:IP 地址不断变化。

管理员不需要在短租期和长租期之间选择。他们可以通过选择最适合网络的数字来妥协。以下是一些租期示例及其背后的原因:

一小时或更少确保在非常动态的环境中实现最大的 IP 地址分配效率,在这种环境中,有许多设备连接和断开网络,且 IP 地址数量有限。

一天 适用于访客机器通常只停留一天的情况,或者在许多员工兼职工作时提高 IP 效率,或者确保每天每个客户端都必须再次请求使用地址的权限。

三天 微软默认使用的设置,这本身就使其成为了一个受欢迎的选择。

一周 在较短和较长时间之间的一种合理折衷。

一个月 在租期时间范围内更接近较长端点的另一种折衷。

三个月 提供合理的 IP 地址稳定性,以便在相对静态的环境中地址不会经常更改。如果有很多 IP 地址可用,并且机器经常连续关闭几天或几周,这也是一个好主意。例如,在大学环境中,这个持续时间可以用来确保在暑假期间返回学生的 IP 地址得到保留。

一年 无限租期的近似值。

不仅管理员不受限于有限的可能租期,而且管理员也不必为所有客户端选择一个恒定的租期策略。根据 DHCP 服务器的功能,管理员可以为某些客户端选择不同的租期。例如,管理员可能决定为永久分配给特定子网且不移动的台式机使用长租期,并为笔记本电脑和访客提供短租期地址池。在某些 DHCP 实现中,可以通过将客户端分配到特定类别来实现这一点。当然,这需要更多的工作(甚至可能需要多个服务器)。

在选择租期策略时,管理员还必须牢记,默认情况下,租期过半后,客户端将开始尝试续订租期。这可能会使使用较长的租期更加可取,以增加客户端尝试续订租期和租期到期之间的时间。例如,在只有一个 DHCP 服务器的网络中,管理员可能希望使用至少八小时的租期。这为服务器上的维护提供了四小时的窗口,而租期不会到期。

当租期非常短,例如几分钟或几小时时,通常在客户端机器关闭一段时间,例如夜间,租期就会到期。较长的租期可以在重启后持续存在。在这种情况下,客户端每次重启时仍会联系 DHCP 服务器以重新分配地址——确认它可以继续使用分配给它的地址。

小贴士

关键概念 使用 DHCP 的网络管理员必须做出的一个关键决策是确定网络的租约长度策略。较长的租约允许设备避免频繁更改地址;较短的租约在重新分配不再需要的地址方面更有效率。管理员可以从多种不同的租约时间中进行选择,并且可能为某些设备选择比其他设备更长的租约。

无限租约的问题

除了选择特定的租约长度数字外,还可以为某些客户端指定无限租约长度。这实际上将动态分配转换为特定客户端的自动分配。然而,如我之前所说,这通常不会这样做。原因是无限租约永远不会过期,正如老话所说,“永远是一段很长的时间。”

从地址池中永久分配 IP 地址是一种有一定风险的行为,因为一旦分配,如果发生任何导致该地址不再被使用的情况,它将永远无法恢复。最坏的情况是一个访问公司网站的访客将笔记本电脑插入网络以检查电子邮件或传输文件。如果这台机器使用自动分配分配了一个 IP 地址,访客离开时会带走它。显然,这不是一个好主意。

因此,大多数管理员更喜欢使用动态分配,将地址设置为非常长的时间框架,例如一年或两年。这被认为几乎等同于无限,近似于永久分配,但允许在设备停止使用 IP 地址后最终回收该地址。在这种策略中,任何真正需要永久分配的东西都会使用手动分配地址,这需要做出有意识的决策将地址分配给特定的设备。

小贴士

相关信息 有关租约长度选择的相关更多信息,请参阅第六十四章中关于 DHCP 服务器实现问题和章节

DHCP 租约生命周期和租约计时器

在 DHCP 中使用动态地址分配意味着对地址的一种全新的思考方式。客户端不再拥有地址,而是租用它。这意味着当客户端计算机设置为使用 DHCP 动态地址时,它永远不能假设它有一个永久性的地址。每次开机时,它都必须与 DHCP 服务器进行通信,以开始或确认地址的租约。它还必须在一段时间内执行其他活动来管理这个租约,并可能终止它。

将动态地址分配的租赁称为类比是很好的,因为 DHCP IP 地址租赁在许多方面类似于现实世界的租赁。例如,当你租一套公寓时,你会签署一份租赁合同。然后你会在一段时间内使用公寓。通常情况下,如果你对这个地方满意,你会在它到期之前续签租赁,以便你可以继续使用它。如果你在租赁快到期时,公寓的所有者不允许你续签,你可能需要租赁另一套公寓以确保你有住处。而且,如果你决定,比如说,搬到国外,你可能会终止租赁而不再续签。

DHCP 租赁生命周期阶段

DHCP 租赁遵循一个通常由以下六个阶段组成的租赁生命周期:

分配 客户端开始时没有活动租赁,因此没有 DHCP 分配的地址。它通过分配过程获得租赁。

重新分配 如果客户端已经从一个现有租赁中获得了地址,那么当它重新启动或从关闭状态启动后,它将联系授予它租赁的 DHCP 服务器以确认租赁并获取操作参数。这有时被称为重新分配;它类似于完整分配过程,但更短。

正常操作 一旦租赁生效,客户端将正常工作,在租赁的主要部分使用分配的 IP 地址和其他参数。客户端被认为与租赁和地址绑定

续签 在租赁时间的一定部分到期后,客户端将尝试联系最初授予租赁的服务器以续签租赁,以便它可以继续使用其 IP 地址。

续租 如果与原始租赁服务器续租失败(例如,服务器已下线),客户端将尝试与任何活动 DHCP 服务器续租,以尝试延长其当前租赁。

释放 客户端可以随时决定不再使用分配给它的 IP 地址,并可以终止租赁,释放该 IP 地址。就像搬出国外的公寓租客一样,这可能发生在设备移动到不同网络的情况下。(当然,与 DHCP 服务器不同,房东通常不会让你随意取消租赁,但嘿,没有类比是完美的。)

图 61-1 展示了使用跨越三个单独租约的示例来阐述 DHCP 生命周期。

DHCP 生命周期示例 在本例中,初始租约的有效期为 8 天,从第 0 天开始。T1 和 T2 计时器分别设置为 4 天和 7 天。当 T1 计时器到期时,客户端进入续订期,并在第 5 天成功续订了一个新的 8 天租约。当这个第二个租约的 T1 计时器到期时,客户端无法与原始服务器续订。当其 T2 计时器失效时,它进入重新绑定期,并从不同的服务器获得了一个新的 8 天租约。在这个租约的第 3 天,它被移动到不同的网络,不再需要其租用的地址,因此它自愿释放了它。

图 61-1. DHCP 生命周期示例 在本例中,初始租约的有效期为 8 天,从第 0 天开始。T1 和 T2 计时器分别设置为 4 天和 7 天。当 T1 计时器到期时,客户端进入续订期,并在第 5 天成功续订了一个新的 8 天租约。当这个第二个租约的 T1 计时器到期时,客户端无法与原始服务器续订。当其 T2 计时器失效时,它进入重新绑定期,并从不同的服务器获得了一个新的 8 天租约。在这个租约的第 3 天,它被移动到不同的网络,不再需要其租用的地址,因此它自愿释放了它。

续订和重新绑定计时器

续订和重新绑定过程的设计是为了确保客户端的租约在预定结束之前可以被延长,从而确保客户端机器的用户不会出现功能丢失或中断。每次分配或重新分配地址时,客户端都会启动两个计时器,以控制续订和重新绑定过程:

续订计时器(T1) 此计时器默认设置为租约期的 50%。当它到期时,客户端将开始续订租约的过程。在 DHCP 标准中,它简单地被称为T1

重新绑定计时器(T2) 此计时器默认设置为租约长度的 87.5%。当它到期时,客户端将尝试重新绑定,如前文所述。在 DHCP 标准中,它被赋予了简洁的名称T2

自然地,如果客户端在 T1 计时器到期时成功续订租约,这将导致一个新的租约,并且两个计时器都将重置。只有当续订不成功时,T2 才会发挥作用。可以更改这些计时器设置的时间长度,但显然 T1 必须在 T2 之前到期,而 T2 必须在租约本身结束之前到期。通常这些值不会从默认值更改,但在某些情况下可能会进行修改。

小贴士

关键概念 DHCP 租约遵循一个概念上的生命周期。租约首先通过分配过程分配给客户端;如果设备稍后重新启动,它将重新分配租约。在由续订计时器(T1)控制的时期后,设备将尝试与分配租约的服务器续订租约。如果这失败,重新绑定计时器(T2)将启动,设备将尝试与任何可用的服务器重新绑定租约。如果客户端不再需要 IP 地址,它也可以释放其 IP 地址。

租约生命周期在 DHCP 标准中以客户端在获取租约、使用它以及随后续订或结束租约时经过的状态的形式描述。下一章将描述这些状态以及客户端和服务器之间为完成不同的租约活动而进行的特定消息交换。

DHCP 租约地址池、范围和地址管理

更简单的主机配置方法,如 BOOTP(或就 DHCP 而言的手动分配),将单个 IP 地址与每个客户端机器关联。DHCP 动态地址分配取消了这种一对一的对应关系,转而根据需要灵活地将地址映射到客户端。客户端不再拥有地址,而是从真正的所有者,即服务器那里租用。因此,DHCP 服务器和该服务器的管理员的主要工作之一是维护和管理这些客户端地址。

地址池大小选择

DHCP 服务器可用于分配的所有地址集合通常被称为地址池。与地址管理相关的一个首要问题是确保地址池足够大,能够为所有将使用该服务器的客户端提供服务。所需地址的数量取决于几个因素:

客户端数量 这是一个明显的因素。

客户端的稳定性和使用频率 如果大多数客户端始终处于开启状态并连接到网络,你可能需要为每个客户端规划一个地址。相比之下,如果你在为经常旅行的兼职员工或顾问提供服务,你可以通过共享较少的地址来解决问题。

过度分配的后果 如果某些客户无法获得一个空闲地址是一个问题,你需要更仔细地管理地址池,以确保你不会耗尽 IP 地址。如果客户无法获得地址是绝对不可接受的,确保你拥有的地址数量不少于客户数量。

我相信你肯定注意到了,这些问题与我之前在本章中讨论租约长度时提出的问题相似。事实上,这两个问题密切相关。一般来说,拥有更多地址给管理员提供了使用更长租约的便利。如果你地址短缺,你可能需要使用更短的租约来减少未使用的地址继续分配给不需要它们的设备的可能性。

租约地址范围(作用域)

在其最简单的形式中,地址池是以 DHCP 服务器为动态客户端分配而保留的所有地址的列表。与每个地址一起,服务器存储某些参数,例如地址的默认租约长度以及其他配置信息,当客户端被分配该地址时发送给客户端(例如,子网掩码和默认路由器的地址)。所有这些数据都存储在服务器上的一个特殊数据库中。

当然,许多客户端会从这个池中请求地址。从 DHCP 服务器的角度来看,这些客户端大多数是平等的,并且每个客户端获得的地址并不重要。这意味着地址池中每个地址存储的信息可能都是相同的,除了地址编号本身。由于这种相似性,需要单独指定每个地址及其参数将是不高效的。相反,通常将地址的范围作为一个单一组处理,该组是为特定网络或子网定义的。在 DHCP 标准中,这些并没有被赋予任何特定的名称,但通常被称为作用域。这个术语在 Microsoft 的 DHCP 服务器实现中被普及。其他操作系统有时只是将这些地址块称为范围,但我更喜欢使用“作用域”。

小贴士

关键概念 每个 DHCP 服务器维护一组 IP 地址,它使用这些地址向客户端分配租约。这些地址通常是由管理员分配给服务器的连续地址块,称为 DHCP 地址范围或作用域

设置范围的精确方法取决于特定的操作系统和 DHCP 服务器软件。然而,每个范围定义通常从指定一个地址范围开始,使用起始和结束 IP 地址。例如,如果一家公司被分配了 IP 地址块 111.14.56.0/24,管理员可能会设置一个包括地址 111.14.56.20 至 111.14.56.254 的范围,如图 61-2 所示。然后,对于该范围,管理员可以设置各种参数,指定给从该范围分配地址的每个客户端。

DHCP 范围 单个 DHCP 服务器范围,包括地址 111.14.56.1 至 111.14.56.254.

图 61-2. DHCP 范围 单个 DHCP 服务器范围,包括地址 111.14.56.1 至 111.14.56.254。

为什么不从 111.14.56.1 开始呢?通常,我们可能想要为服务器、路由器和其他需要固定地址的设备预留某些 IP 地址进行手动配置。一个简单的方法是简单地预留一个 DHCP 未使用的地址块。或者,大多数 DHCP 服务器软件将允许你指定一个范围,但排除该范围内的地址或地址集。因此,我们可以指定 111.14.56.1 至 111.14.56.254,并单独标记为不可用的地址,我们手动分配的地址。或者,我们可以指定 111.14.56.1 至 111.14.56.19 为预留地址。

服务器不必将其所有地址(除了排除的地址)放在单个范围内,它可以使用多个范围。采用后一种方法的常见原因是在服务器上支持多个子网。当使用多个 DHCP 服务器为同一客户端提供服务时,也经常使用多个范围。有两种方法可以实现这一点:通过使用重叠非重叠的范围。

覆盖范围允许每个服务器从同一池中分配任何地址。然而,DHCP 标准并没有指定服务器在分配地址时相互通信的方式,因此如果两个服务器都被告知它们可以从同一个地址池中分配地址,这可能导致两个服务器试图将特定的地址分配给两个不同的设备。因此,如果你正在使用两个 DHCP 服务器(通常出于冗余原因推荐这样做),管理员通常会给他们不同的、不重叠的范围分配。或者,可以将相同的范围分配给每个服务器,并告知每个服务器排除其他服务器正在分配的地址的使用。

例如,假设我们有两个 DHCP 服务器:服务器 A(主服务器)和服务器 B(备份服务器)。我们希望将大多数地址分配给服务器 A,并将少量作为备份分配给服务器 B。我们可以给服务器 A 和服务器 B 分配范围 111.14.56.1 至 111.14.56.254。我们将从两者中排除 111.14.56.1 至 111.14.56.19。然后,我们会从服务器 A 中排除范围 111.14.56.200 至 111.14.56.254,并从服务器 B 中排除范围 111.14.20 至 111.14.56.199。图 61-3")展示了这将如何工作。这种方法的主要优点是,如果某个服务器出现故障,管理员可以快速移除排除,让剩余的服务器访问所有地址。此外,如果其中一个服务器地址耗尽而另一个还有大量地址,分配可以轻松调整。

DHCP 多服务器非重叠作用域 DHCP 服务器 A 和 B 已被分配了非重叠作用域以确保它们不会冲突。这是通过为两者起始于相同的范围定义来实现的。每个都排除了公共保留范围。然后服务器 A 排除了服务器 B 的地址范围(顶部栏右侧的阴影区域),服务器 B 排除了服务器 A 的范围(底部中间的阴影区域)

图 61-3. DHCP 多服务器非重叠作用域 DHCP 服务器 A 和 B 已被分配了非重叠作用域以确保它们不会冲突。这是通过为两者起始于相同的范围定义来实现的。每个都排除了公共保留范围。然后服务器 A 排除了服务器 B 的地址范围(顶部栏右侧的阴影区域),服务器 B 排除了服务器 A 的范围(底部中间的阴影区域)。

地址管理中的其他问题

与地址管理相关的问题还有很多,这些问题开始涉及到 DHCP 服务器实现的本质。例如,与 BOOTP 的情况一样,当 DHCP 服务器负责与其自身不同的子网上的地址时,我们可能需要使用中继代理。还有一些特殊的 DHCP 功能会影响地址的管理方式。例如,DHCP 冲突检测功能实际上可以允许两个服务器有重叠的作用域,尽管我在上一节中提到过。第六十四章,该章节涵盖了 DHCP 实现和功能,更详细地描述了这些问题。

小贴士

关键概念 如果一个站点有多个 DHCP 服务器,它们可以配置为具有重叠非重叠的作用域。重叠的作用域允许每个服务器从同一个池中分配地址,提供灵活性,但也增加了两个客户端被分配相同地址的可能性,除非使用了如服务器冲突检测这样的功能。非重叠的作用域更安全,因为每个服务器都有专门用于其使用的地址集,但这意味着一个服务器可能会用完地址,而另一个还有许多剩余,如果服务器宕机,其地址将暂时不可分配。

第六十二章。DHCP 配置与操作

无标题图片

DHCP 中的重大新闻是动态地址分配以及地址租赁的概念。正是这一新功能使得 DHCP 比其前身 BOOT 协议(BOOTP)复杂得多。BOOTP 是一个简单的请求/回复协议——服务器只需要查找客户端的硬件地址,并发送客户端分配的 IP 地址和其他参数。相比之下,DHCP 客户端和服务器必须执行更多的操作,以完成参数交换和许多管理 IP 地址租赁所需的任务。

在本章中,我深入探讨了 DHCP 如何运作的细节。我首先介绍两个背景主题。第一个主题概述了 DHCP 中客户端和服务器所承担的责任,并以一般性的方式展示了它们之间的关系。第二个主题讨论了 DHCP 配置参数及其存储和通信方式。

在本章的剩余部分,我详细说明了 DHCP 的操作。我解释了 DHCP 客户端的有限状态机,这将让你从高层次了解整个客户端租约生命周期,包括地址分配、重新分配、续订、重新绑定,以及可选的租约终止。这种理论描述随后被用作解释 DHCP 客户端租约活动实际过程的基础。这些展示了客户端和服务器所采取的具体行动,以及何时以及如何创建和发送 DHCP 消息。本章的最后部分描述了不使用 DHCP 进行地址分配的设备请求配置参数的特殊机制。

DHCP 客户端和服务器责任概述

DHCP 是最新的、最先进的 TCP/IP 主机配置协议。然而,正如你在上一章所看到的,它并非从头开始构建——它被设计为 BOOTP 的扩展。在许多方面,DHCP 就像 BOOTP,但功能更丰富,这可以从协议的基本设置和工作方式中看出。

BOOTP 和 DHCP 都是基于常见的 TCP/IP 客户端/服务器操作模型设计的(参见第八章)。在任何交互中,一个设备扮演客户端的角色,另一个设备扮演服务器的角色。每个设备都有特定的职责,并且必须按照 DHCP 标准中描述的协议发送和接收消息。区别在于,BOOTP 对服务器和客户端的工作量相对较小,并使用简单的单消息交换进行通信,而 DHCP 要求服务器和客户端都要做更多的工作,并使用多种类型的消息交换。

DHCP 服务器职责

DHCP 服务器是一种被编程以向客户端提供 DHCP 服务的网络设备。服务器在 DHCP 中扮演着核心角色,因为 DHCP 的主要功能是主机配置,服务器配置与它通信的主机(客户端)。较小的网络可能只有一个服务器来支持许多客户端,而较大的网络可能使用多个服务器。无论服务器的数量如何,每个服务器通常都会为许多客户端提供服务。

以下是在使 DHCP 工作过程中服务器的关键职责:

地址存储和管理 DHCP 服务器是所有 DHCP 客户端使用的地址的所有者。服务器存储地址并管理其使用,跟踪哪些地址已被分配,哪些仍然可用。

配置参数存储和管理 DHCP 服务器还存储并维护其他参数,这些参数旨在在请求时发送给客户端。其中许多是重要的配置值,详细说明了客户端应该如何操作。

租约管理 DHCP 服务器使用租约在有限的时间内动态地为客户端分配地址。DHCP 服务器维护有关它授予每个客户端的租约的信息,以及有关租约长度等策略信息。

响应客户端请求 DHCP 服务器响应来自客户端的不同类型的请求以实现 DHCP 通信协议。这包括分配地址;传达配置参数;以及授予、续订和终止租约。

管理服务 为了支持其所有其他职责,DHCP 服务器包括允许人类管理员输入、查看、更改和分析地址、租约、参数以及运行 DHCP 所需的所有其他信息的功能。

DHCP 客户端职责

DHCP 客户端是指任何向服务器发送 DHCP 请求以获取 IP 地址或其他配置信息的设备。由于 DHCP 的优势,今天 TCP/IP 互联网上的大多数主机计算机都包括 DHCP 客户端软件,如果管理员选择启用该功能,它们就成为了潜在的 DHCP 客户端。DHCP 客户端的主要职责包括:

配置初始化 客户端通过启动导致其获得 IP 地址和其他参数的通信交换来采取主动角色。相比之下,服务器是被动的,直到客户端建立联系之前,服务器实际上不会为客户端做任何事情。

配置参数管理 客户端维护与其配置相关的参数,其中一些或全部可能从 DHCP 服务器获得。

租赁管理 假设其地址是动态分配的,客户端负责跟踪其租赁的状态。它负责在适当的时间续订租赁,如果续订不可行则重新绑定,如果不再需要该地址则提前终止租赁。

消息重传 由于 DHCP 使用不可靠的用户数据报协议(UDP,见第四十四章"))进行消息传递,因此客户端负责检测消息丢失并在必要时重新传输请求。

DHCP 客户端/服务器角色

显然,DHCP 服务器和客户端扮演着互补的角色。服务器维护所有客户端的配置参数。每个客户端维护自己的参数,如下一节所述。

IP 地址分配和租赁创建、续订、重新绑定和终止是通过使用一组八种 DHCP 消息类型进行特定交换来完成的,如本章后面的“DHCP 通用操作和客户端有限状态机”和“DHCP 租赁分配、重新分配和续订”部分所述。为了完成这些消息,遵循特殊规则来生成、寻址和传输消息,如第六十三章中所述。

DHCP 中继代理

与 BOOTP 类似,DHCP 也支持第三种设备:中继代理。中继代理既不是客户端也不是服务器,而是促进服务器和客户端之间跨网络通信的中间人。它们在第六十四章中有更详细的描述(在那里您还可以找到服务器和客户端更多实现细节)。

小贴士

关键概念 DHCP 服务器是编程用于向客户端提供 DHCP 服务的设备。它们管理地址信息和其他参数,并响应用户配置请求。DHCP 客户端是设置为使用 DHCP 确定其配置的 TCP/IP 设备。它们发送请求并读取响应,并负责管理自己的租赁,包括在必要时续订或重新绑定租赁。

DHCP 配置参数、存储和通信

DHCP 的前身 BOOTP 中一个更为重要的疏忽是,它只允许服务器告诉客户端三条信息:它的 IP 地址、它可以用来下载引导文件的服务器名称以及要使用的引导文件名称。这是 BOOTP 作为主要为了允许无盘工作站引导而创建的协议的遗产。

显然,IP 地址是一个非常重要的参数,但在现代网络中,它并不是客户端正常工作所需的唯一参数。一个典型的主机需要获得其他必要信息,以便知道如何在本地网络中操作以及如何与其他设备交互。例如,它需要知道默认本地路由器的地址、它所在子网的子网掩码、创建出站 IP 数据报的参数等等。

配置参数管理

由于 BOOTP 无法指定额外的配置参数,因此通过使用 RFC 1048 中首次定义的特殊 BOOTP 供应商特定区域来为供应商独立的供应商信息字段提供了解决方案。在 DHCP 中,这一想法得到了进一步扩展,并且更为重要的是,它被正式化,作为使 DHCP 成为一个更通用配置工具的努力的一部分。配置参数的存储、维护和通信不再是可选功能;它们是主机配置过程的基本部分。

就像 DHCP 服务器是拥有和管理 IP 地址的老板一样,它们也充当着属于 DHCP 客户端的其他配置参数的存储库。这种参数存储的集中化提供了与在 DHCP 中集中 IP 地址相同的许多好处:管理员可以在一个地方检查和调整参数,而不是需要访问每一台客户端机器。

每个 DHCP 服务器在分配地址时,除了 IP 地址外,还编程了要传达给客户端的参数。或者,已经通过某种其他机制分配了地址的客户端仍然可以查询 DHCP 服务器以获取参数信息,使用 DHCPINFORM 消息类型。(这实际上是在 RFC 2131 中添加到协议中的;它不在最初的 DHCP 标准中。)

参数存储

客户端参数的存储方法在一定程度上取决于实现。通常,将有一些适用于所有客户端的参数。例如,在一个只有一台路由器的小型网络中,该路由器很可能是每个 DHCP 客户端的默认路由器,无论地址如何。

DHCP 服务器也将有一些特定于客户端的参数。IP 地址本身是一个明显的例子,但还有其他可能只适用于网络中某些客户端的参数。这些参数存储在某种数据库中,并使用特定的 客户端标识符 进行索引。默认标识符由客户端的 IP 子网号和其硬件地址组成。因此,当服务器收到特定子网的请求时,它可以使用请求中的客户端硬件地址来查找特定于客户端的参数并将它们返回。如果需要不同的标识方案,客户端标识符可以更改。

客户端还负责存储它们自己的参数。其中许多将来自 DHCP 服务器,尽管一些可能以其他方式提供。客户端的具体实现决定了它认为哪些参数是重要的以及它们是如何被发现的。

配置参数通信

DHCP 客户端和服务器之间配置参数的通信是通过使用 DHCP 选项 完成的,这些选项取代了 BOOTP 供应商信息字段。当 DHCP 首次创建时,就定义了一些选项,并且多年来还创建了额外的新的选项。

今天,有几十种 DHCP 选项。显然,能够将如此多的不同参数自动发送给客户端,为管理员提供了大量的主机配置灵活性。DHCP 选项在第六十三章中进行了进一步描述。

DHCP 通用操作和客户端有限状态机

动态地址分配可能是 DHCP 引入的最重要的新功能。在前一章中,我讨论了从 IP 地址 所有权 到 IP 地址 租赁 的变化的重要性。我还通过概述 DHCP 租赁生命周期,提供了租赁活动中所涉及活动的概览。

这种类型的概述有助于了解租赁工作的一般情况,但要真正理解 DHCP 地址分配和客户端/服务器通信的机制,你需要更多关于设备行为和它们发送的消息的细节。网络工程师经常使用一种称为 有限状态机 (FSM) 的理论模型来描述协议。使用这种技术,通过展示设备可能处于的不同 状态、从一个状态到另一个状态的可能 转换、导致转换发生的事件以及响应事件所执行的动作,可以说明协议的具体行为。TCP 操作概述包含了关于 FSM 的更多一般背景信息(见第四十七章)。

DHCP 标准使用有限状态机从 DHCP 客户端的角度描述租约的生命周期。客户端从初始的 INIT 状态开始,此时它没有任何租约,然后通过获取、续订、重新绑定和/或释放其 IP 地址的各种状态进行转换。有限状态机还指示在各个阶段服务器和客户端之间发生的消息交换。

注意

DHCP 标准并没有以有限状态机(FSM)的形式描述 DHCP 服务器的行为;只有客户端的行为是以这种方式描述的

有些人认为有限状态机(FSM)有点密集且难以理解,我也能理解这一点。当然,你可以跳过这个主题,但我认为有限状态机提供了一种有用的方式,全面地展示 DHCP 客户端的大部分行为。

表 62-1 描述了 DHCP 客户端的每个状态,并总结了客户端在每个状态中发送和接收的消息,以及显示响应中发生的状态转换。有限状态机的状态、事件和转换在图 62-1 中更容易想象,该图还采用了阴影方案,以便你可以看到哪些状态与每个主要 DHCP 过程相关联。

表 62-1. DHCP 客户端有限状态机

状态 状态描述 事件和转换
INIT 这是初始化状态,客户端开始获取租约的过程。当租约结束或租约协商失败时,它也会返回此状态。 客户端发送 DHCPDISCOVER。客户端创建一个 DHCPDISCOVER 消息,并将其广播出去,试图找到 DHCP 服务器。它转换到 SELECTING 状态。
SELECTING 客户端正在等待从一个或多个 DHCP 服务器接收 DHCPOFFER 消息,以便选择其中一个。 客户端接收报价,选择首选报价,并发送 DHCPREQUEST。客户端从收到的报价中选择一个,并向 DHCP 服务器广播一个 DHCPREQUEST 消息,告知其选择。它转换到 REQUESTING 状态。
客户端接收 DHCPACK,成功检查 IP 地址是否空闲。客户端从其选择的 DHCP 服务器接收 DHCPACK 消息,确认它可以获得提供的租约。它检查以确保地址尚未被使用,如果尚未使用,则记录服务器发送给它的参数,设置租约计时器 T1 和 T2,并转换到 BOUND 状态。
REQUESTING 客户端正在等待从其发送请求的服务器收到回复。 客户端收到 DHCPACK,但 IP 地址已被占用。客户端从其选择的服务器收到 DHCPACK 消息,确认它可以拥有提供的租约。然而,它进行检查发现地址已被占用。它向服务器发送 DHCPDECLINE 消息,并返回到 INIT 状态。
客户端收到 DHCPNAK。客户端从其选择的服务器收到 DHCPNAK 消息,这意味着服务器已撤回其提供的租约。客户端返回到 INIT 状态。
INIT-REBOOT 当一个已经拥有有效租约的客户端在断电或重启后启动时,它从这里开始,而不是从 INIT 状态开始。 客户端发送 DHCPREQUEST。客户端发送 DHCPREQUEST 消息以尝试验证其租约并重新获取其配置参数。然后它过渡到 REBOOTING 状态以等待响应。
客户端收到 DHCPACK,成功检查 IP 地址是否空闲。客户端从具有其租约信息的服务器收到 DHCPACK 消息,确认租约仍然有效。为了安全起见,客户端仍然进行检查,以确保地址尚未被其他设备使用。假设它没有被使用,客户端记录服务器发送给它的参数,并过渡到 BOUND 状态。
REBOOTING 一个已分配地址重新启动的客户端正在等待服务器的确认回复。 客户端收到 DHCPACK,但 IP 地址已被占用。客户端从其租约的服务器收到 DHCPACK 消息,确认租约仍然有效。然而,客户端进行检查发现,在客户端离线期间,某些其他设备已经抓取了它的租约 IP 地址。客户端向服务器发送 DHCPDECLINE 消息,并返回到 INIT 状态以获取新的租约。
客户端收到 DHCPNAK。客户端从一个服务器收到 DHCPNAK 消息。这告诉它其当前租约不再有效;例如,客户端可能已移动到新的网络,在那里它不能再使用其当前租约中的地址。客户端返回到 INIT 状态。
更新计时器(T1)到期。客户端过渡到 RENEWING 状态。
BOUND 客户端拥有有效租约并处于其正常操作状态。 客户端终止租约并发送 DHCPRELEASE。客户端决定终止租约(例如,由于用户命令)。它发送 DHCPRELEASE 消息并返回到 INIT 状态。
客户端收到 DHCPACK。客户端收到对 DHCPREQUEST 的 DHCPACK 回复。其租约已更新,它重新启动 T1 和 T2 计时器,并返回到 BOUND 状态。
续订 客户端正在尝试续订其租约。它定期发送指定了当前租约服务器的 DHCPREQUEST 消息,并等待回复。 客户端收到 DHCPNAK。服务器拒绝续订客户端的租约。客户端进入 INIT 状态以获取新的租约。
重新绑定定时器(T2)到期。当客户端尝试续订其租约时,T2 定时器到期,表示续订期已结束。客户端转换到重新绑定状态。
客户端收到 DHCPACK。网络上的某个服务器续订了客户端的租约。客户端绑定到授予租约的新服务器,重新启动 T1 和 T2 定时器,并返回到 BOUND 状态。
重新绑定 客户端未能与最初授予其租约的服务器续订租约,现在正寻求与任何可以听到它的服务器续订租约。它定期发送没有指定服务器的 DHCPREQUEST 消息,直到收到回复或租约结束。 客户端收到 DHCPNAK。网络上的某个服务器明确告诉客户端它需要重新启动租赁过程。这可能是在有新服务器愿意授予客户端租约,但条款与客户端当前租约不同的情况下。客户端进入 INIT 状态。
租约到期。在租约到期之前,客户端没有收到任何回复。它返回到 INIT 状态。

DHCP 客户端有限状态机 此图显示了 DHCP 客户端使用的有限状态机(FSM)。阴影背景区域显示了 DHCP 客户端在通过四个主要 DHCP 过程:分配、重新分配、续订和重新绑定时采取的转换。

图 62-1. DHCP 客户端有限状态机 此图显示了 DHCP 客户端使用的有限状态机(FSM)。阴影背景区域显示了 DHCP 客户端在通过四个主要 DHCP 过程:分配、重新分配、续订和重新绑定时采取的转换。

这只是一个 FSM 的摘要,它并没有显示每个可能的事件和转换,因为它已经足够复杂。例如,如果一个在 SELECTING 状态下收到两个提供的客户端收到其选择的服务器在 REQUESTING 状态下的 DHCPNAK,它可能会选择向其第二选择发送新的 DHCPREQUEST,而不是从头开始。此外,客户端必须具有逻辑,使其在发送的消息在各个状态下没有收到回复时超时,例如在 SELECTING 状态下没有收到任何提供。下一节将更详细地讨论这些问题。

还要注意,此 FSM 适用于动态分配的客户端——即具有传统租约的客户端。使用自动分配配置的设备将经历相同的基本分配过程,但不需要续订其租约。手动分配的过程略有不同。

DHCP 租赁分配、重新分配和续订

要实现 DHCP,管理员必须首先设置 DHCP 服务器,并为其提供配置参数和政策信息:IP 地址范围、租约长度规范以及 DHCP 主机需要交付给它们的配置数据。然后,主机设备可以启用它们的 DHCP 客户端软件,但除非客户端与服务器建立通信,否则不会发生任何事情。当 DHCP 客户端首次启动或没有当前 DHCP 租约时,它将处于初始状态,没有地址并且需要获取一个。它将通过启动 租赁分配 流程来实现这一点。

在我们检查租赁分配、重新分配和续订流程的步骤之前,我需要澄清一些与 DHCP 租赁通信相关的问题。首先,DHCP 假设客户端通常会广播消息,因为当它们发起联系时不知道服务器的地址,但服务器会向客户端发送单播回复。这甚至可以在客户端获得 IP 地址之前完成,通过在链路层发送消息。一些客户端不支持这一点,并要求向它们发送的消息进行广播。

DHCP 使用与 BOOTP 相同的许多基本字段,但协议要求的额外信息大多包含在 DHCP 选项 中。尽管名称表明这些选项不是必需的,但其中一些选项实际上是必需的,因为它们对于 DHCP 的基本功能是必要的。一个明显的例子是 DHCP 消息类型选项,它指定了消息类型本身。

消息的创建和寻址的详细信息,以及所有 DHCP 字段和选项的完整描述,在 第六十三章 中提供。

注意

我假设这里没有使用中继代理。有关 DHCP/BOOTP 中继代理的讨论,请参阅 第六十章"),以了解更多关于它们如何改变分配过程(以及其他过程)的信息

初始租赁分配过程

以下是一个 DHCP 客户端和服务器在初始 IP 地址租约分配过程中采取的基本步骤,重点关注每个设备执行的最重要任务(参见 图 62-2)。

  1. 客户端创建 DHCPDISCOVER 消息

    客户端从 INIT(初始化)状态开始。它没有 IP 地址,甚至不知道网络上是否以及在哪里可能有 DHCP 服务器。为了找到它,它创建一个包含以下信息的 DHCPDISCOVER 消息:

    • 消息 CHAddr 字段中的自己的硬件地址,以识别自己

    • 一个随机的交易标识符,放入 XID 字段(用于标识后续消息是否属于同一交易)

    可选地,客户端可以使用请求的 IP 地址 DHCP 选项请求特定的 IP 地址,使用 IP 地址租约时间选项请求特定的租约长度,以及通过在消息中包含参数请求列表选项来请求特定的配置参数

  2. 客户端发送 DHCPDISCOVER 消息

    客户端在本地网络上广播 DHCPDISCOVER 消息。客户端进入 SELECTING 状态,等待对其消息的回复。

  3. 服务器接收并处理 DHCPDISCOVER 消息

    本地网络上的每个 DHCP 服务器都会接收到客户端的 DHCPDISCOVER 消息并检查它。服务器在其数据库中查找客户端的硬件地址,并确定是否能够向客户端提供一个租约以及租约的条件。如果客户端对特定的 IP 地址、租约长度或其他参数有请求,服务器将尝试满足这些请求,但并非必须这样做。如果服务器没有编程为提供该客户端的服务,没有剩余的 IP 地址或其他原因,服务器可能决定不对特定客户端提供租约。

  4. 服务器创建 DHCPOFFER 消息

    每个选择响应客户端的服务器都会创建一个包含以下信息的 DHCPOFFER 消息:

    • 要分配给客户端的 IP 地址,在 YIAddr 字段中(如果服务器之前为此客户端有一个租约,它将尝试重用上次使用的 IP 地址;如果不行,它将尝试使用客户端请求的地址,如果有的话;否则,它将选择任何可用的地址)

    • 提供的租约长度

    • 任何由客户端请求或编程到服务器以返回给客户端的特定客户端配置参数

    • 要返回给所有客户端或此客户端类别的客户端的任何一般配置参数

    • DHCP 服务器标识选项中的服务器标识符

    • 在 DHCPDISCOVER 消息中使用相同的交易 ID(XID)

  5. 服务器探测和/或保留提供的地址(可选)

    DHCP 标准规定,在向客户端发送 DHCPOFFER 之前,服务器应检查该 IP 地址是否已被使用,通过向该地址发送 ICMP Echo 消息来实现。这被认为是 DHCP 服务器冲突检测功能的关键部分(在第六十四章

图 62-2。DHCP 租约分配过程 此图显示了 DHCP 客户端租约分配的步骤。此图与本书中大多数其他客户端/服务器交换图略有不同,因为我展示了两个服务器而不是一个。这显示了客户端如何处理来自多个 DHCP 服务器的响应,以及每个服务器如何根据其租约提议是否被客户端选择而做出不同的反应。

小贴士

关键概念 DHCP 中最重要的配置过程是租约分配过程,客户端使用该过程来获取租约。客户端广播一个请求以确定是否有任何 DHCP 服务器能够听到它。每个愿意授予客户端租约的 DHCP 服务器都会向它发送一个提议。客户端选择它偏好的租约,并向所有服务器发送一个响应,告诉它们它的选择。然后,所选的服务器将向客户端发送其租约信息。

DHCP 租约重新分配过程

当 DHCP 客户端首次启动且没有租约时,它从 INIT(初始化)状态开始,并按照上一节中描述的分配过程来获取租约。当租约到期、租约续订失败或发生某些事件导致客户端需要新的租约时,也会使用相同的过程。

然而,在某些情况下,客户端在已有租约的情况下启动。在这种情况下,客户端无需经历获取 IP 地址分配和新租约设置的全过程。相反,它只需尝试通过重新分配过程重新建立现有的租约。

当客户端在具有现有租约的情况下重新启动时,它执行的是重新分配而不是分配。客户端租约的持续时间可以从几分钟到几年不等;这完全取决于管理员为网络和客户端设置的租约长度策略。许多(如果不是大多数)客户端机器并非每天 24 小时都连接到网络。它们在白天开启,然后在夜间关闭,周末也会关闭。如果一个租约非常短,客户端关闭后再重新启动,可能会发现其租约已过期,需要获取一个新的租约。然而,如果租约超过几天,当客户端再次启动时,租约可能仍然有效。客户端有时也会重新启动,以安装新软件或纠正问题。在这种情况下,即使租约长度非常短,重新启动的客户端在启动时仍然会拥有一个有效的租约。

重新分配过程本质上是对上一节中描述的分配过程的简略版。客户端无需经历整个“喂,有服务器想给我一个租约吗?”的常规程序。相反,客户端试图找到最初授予其租约的服务器,寻求确认租约仍然有效,并且它可以继续使用之前分配的 IP 地址。它还会收到有关应使用参数的确认。

以下步骤总结了重新分配过程(参见图 62-3)。

  1. 客户端创建 DHCPREQUEST 消息

    客户端从 INIT-REBOOT 状态开始,而不是从 INIT 状态开始。它创建一个 DHCPREQUEST 消息,尝试找到有关其当前租约的服务器信息。这可能不是最初授予租约的服务器。自客户端获取租约以来,负责租约的服务器理论上可能已经改变。因此,与分配过程中的第 8 步中的 DHCPREQUEST 消息不同,客户端不包括 DHCP 服务器标识符选项。它确实包括以下信息:

    • 它在消息的 CHAddr 字段中的自己的硬件地址,以识别自己

    • 它现有租约的 IP 地址,在请求的 IP 地址 DHCP 选项中(此地址不会放入 CIAddr 字段)

    • 一个随机的事务标识符,放入 XID 字段(用于标识稍后消息是否属于同一事务)

    • 它想要的所有附加配置参数,在消息中的参数请求列表选项中

  2. 客户端发送 DHCPREQUEST 消息

    客户端广播 DHCPREQUEST 消息。然后它过渡到 REBOOTING 状态,在那里它等待来自服务器的回复。

  3. 服务器接收并处理 DHCPREQUEST 消息并生成回复

    网络上的每个服务器都会接收并处理客户端的请求。服务器在其数据库中查找客户端,试图找到有关租约的信息。然后每个服务器决定如何回复客户端:

    • 如果服务器有有效的客户端租约信息,它将发送 DHCPACK 消息以确认租约。它还将重申客户端应使用的任何参数。

    • 如果服务器确定客户端租约无效,它将发送 DHCPNAK 消息以否定租约请求。这种情况发生的原因通常是客户端在移动到不同的网络或租约已过期后尝试确认租约。

    • 如果服务器没有关于客户端租约的明确信息,它不会回复。服务器还必须确保其信息准确无误才进行回复。例如,如果服务器知道一个旧的已过期租约,它不能假设租约不再有效并发送 DHCPNAK,除非它还拥有某些知识,即没有其他服务器为该客户端拥有更新的有效租约。

  4. 服务器发送回复

    准备对客户端的 DHCPREQUEST 进行响应的服务器发送它们的 DHCPACK 或 DHCPNAK 消息。

  5. 客户端接收并处理 DHCPACK 或 DHCPNAK 消息

    客户端等待一段时间以获取对其请求的回复。同样,这里有三种可能性与步骤 3 中的三种相匹配:

    • 客户端收到 DHCPACK 消息,确认租约的有效性。客户端将准备再次使用租约,并继续进行步骤 6。

    • 客户端收到 DHCPNAK 消息,告知客户端其租约已不再有效。客户端将返回到 INIT 状态以获取新的租约——分配过程中的步骤 1。

    • 如果客户端完全没有收到回复,它可能会重新发送 DHCPREQUEST 消息。如果在一段时间后仍未收到回复,它将得出结论,没有服务器有关于其租约的信息,并将返回到 INIT 状态以尝试获取新的租约。

  6. 客户端检查地址是否未被使用

    在重新使用其租约之前,客户端设备应进行最终检查,以确保新地址尚未被使用。即使租约已经存在,这也应该不会发生,但出于安全起见,仍然会这样做。检查与分配过程中的第 13 步描述相同:在本地网络上发出 ARP 请求,以查看是否有其他设备认为它已经拥有客户端刚刚租用的 IP 地址。如果有其他设备响应,客户端会向服务器发送 DHCPDECLINE 消息,告知它租约无效,因为其他设备正在使用该地址。然后客户端返回到 INIT 状态以获取新的租约。

  7. 客户端完成租约分配

    假设地址尚未被使用,客户端将完成租约并过渡到 BOUND 状态。现在它已准备好进行正常操作。

DHCP 租约重新分配过程 该租约重新分配过程包括七个步骤,大致对应于图中的第 8 步至第 14 步,即完整的租约分配过程的步骤。在这个例子中,最初授予客户端租约的服务器是服务器 2,因此通常是唯一响应的服务器。

图 62-3. DHCP 租约重新分配过程 该租约重新分配过程包括七个步骤,大致对应于图中的第 8 步至第 14 步,即完整的租约分配过程的步骤。在这个例子中,最初授予客户端租约的服务器是服务器 2,因此通常是唯一响应的服务器。

小贴士

关键概念 如果客户端启动时已经有一个租约,它不需要经历完整的租约分配过程;相反,它可以使用更短的重新分配过程。客户端广播一个请求以找到拥有其租约当前信息的服务器。该服务器会回应以确认客户端的租约仍然有效。

DHCP 租约续订和重新绑定过程

一旦 DHCP 客户端完成分配或重新分配过程,它将进入 BOUND 状态。客户端现在处于常规操作模式,拥有从 DHCP 服务器接收的有效 IP 地址和其他配置参数,它可以像任何常规 TCP/IP 主机一样使用。

当客户端处于 BOUND 状态时,DHCP 基本上处于休眠状态。只要客户端保持开启并正常工作,在此状态下就不会发生真正的 DHCP 活动。最常见导致 DHCP 唤醒并再次变得活跃的情况是租约续订时间的到来。续订确保租约得以延续,以便可以长时间使用,并涉及自己的消息交换过程。(客户端离开 BOUND 状态的另一种方式是它提前终止租约,如下一节所述。)

如果使用 DHCP 的自动分配,或者使用无限租约期的动态分配,客户端的租约将永远不会过期,因此它永远不会需要续订。除了提前终止之外,设备将永远保持 BOUND 状态,或者至少直到它重新启动。然而,大多数租约都是有限制的。客户端必须采取行动以确保其租约得到延长,并且正常操作得以继续。

为了管理租约扩展过程,在分配租约时设置了两个计时器。续订计时器(T1)响起以告知客户端是时候尝试使用最初授予它的服务器续订租约了。如果客户端未能与该服务器续订,重新绑定计时器(T2)响起,并告知它尝试任何服务器以延长租约。如果租约被续订或重新绑定,客户端将恢复正常操作。如果不能重新绑定,它将过期,客户端将需要寻找新的租约。

以下步骤总结了续订/重新绑定过程(见图 62-4

图 62-4. DHCP 租约续租和重新绑定过程 此图展示了当前持有 Server 2 租约的客户端正在尝试联系它以续租租约的示例。然而,在这种情况下,Server 2 因维护而关闭。服务器无法响应,客户端在续租/重新绑定过程的第二步卡住。它继续向 Server 2 发送 DHCPREQUEST 消息,直到其 T2 计时器到期。然后它进入重新绑定状态并广播一个 DHCPREQUEST 消息,该消息被 Server 1 听到,Server 1 同意延长其当前的租约。

因此,在正常情况下,客户端将继续无限期地尝试延长其现有的租约。然而,在某些情况下,主机可能会决定终止其租约。这通常不会是客户端自发决定的事情。它将是对用户结束租约的具体请求的响应。用户可能出于以下原因之一终止租约:

  • 客户端正在被移动到不同的网络。

  • 网络正在重新编号其 IP 地址。

  • 用户希望主机与不同的服务器协商一个新的租约。

  • 用户希望重置租约以修复某种问题。

在任何这些情况下,用户都可以通过称为早期租约终止租约释放的过程来结束租约。这是一个非常简单、单向的通信。客户端向持有其当前租约的服务器发送一个特殊的 DHCPRELEASE 消息单播,告知它租约不再需要。然后服务器将租约记录为已结束。它不需要向客户端回复。

客户端之所以可以假设租约终止已成功,是因为这并不是 DHCP 协议的强制部分。让客户端发送 DHCPRELEASE 来结束租约被视为一种礼貌,而不是要求。当客户端通知服务器它们不再需要租约时,这更加高效,这也使得在终止的租约中的 IP 地址能够更快地被重用。然而,DHCP 服务器被设计来处理客户端看似消失而没有正式结束现有租约的情况。

非 DHCP 地址客户端的 DHCP 参数配置过程

大多数 DHCP 客户端都使用该协议来获取 IP 地址和其他配置参数。这就是为什么 DHCP 的大部分内容都围绕地址分配和租赁的原因。传统的 DHCP 客户端在获取 IP 地址的同时,使用本章前面各节中描述的消息交换和过程获取所有配置参数。

有一些情况下,使用除 DHCP 之外的方法分配 IP 地址的设备仍然希望使用 DHCP 服务器来获取其他配置参数。这样做的主要优势是管理方便;它允许具有静态 IP 地址的设备仍然能够以与常规 DHCP 客户端相同的方式自动获取其他参数。

具有讽刺意味的是,这种能力可以使用的常见情况之一是配置 DHCP 服务器本身!管理员通常不使用 DHCP 为 DHCP 服务器提供 IP 地址,但他们可能希望用它来告知服务器其他参数。在这种情况下,请求参数的服务器实际上在与其他服务器交换时充当客户端。

原始的 DHCP 标准没有提供任何机制来实现这种非 IP 配置。RFC 2131 修订了协议,增加了一种新的消息类型(DHCPINFORM),允许设备在无需经过完整的租赁过程的情况下请求配置参数。此消息用作与之前我们查看的租赁通信分开的简单双向通信的一部分。由于它不涉及 IP 地址分配,因此它不是租赁生命周期的一部分,也不是 DHCP 客户端 FSM 的一部分。

以下步骤展示了具有外部配置地址的设备如何使用 DHCP 获取其他参数(参见图 62-5

图 62-5. DHCP 参数配置过程 已拥有 IP 地址的设备可以使用此图所示的简单请求/回复交换从 DHCP 服务器获取其他配置参数。在这种情况下,客户端正在广播其请求。

如果客户端未收到对它的 DHCPINFORM 消息的回复,它将定期重新发送。在重试期过后,它将放弃并使用默认配置值。它通常还会生成一个错误报告,通知管理员或用户问题所在。

提示

关键概念 不使用 DHCP 获取 IP 地址的设备仍然可以使用其其他配置功能。客户端可以广播一个DHCPINFORM消息,请求任何可用的服务器发送有关如何使用网络的参数。DHCP 服务器通过 DHCPACK 消息的 DHCP 选项响应请求的参数和/或默认参数。

第六十三章. DHCP 消息、消息类型和格式

无标题图片

前一章关于 DHCP 配置和操作的章节通过展示各种租约和信息交换过程来演示了 DHCP 是如何工作的。所有这些过程都高度依赖于客户端和服务器之间的信息交换,这是通过 DHCP 消息来实现的。像所有协议一样,DHCP 使用一种特殊的消息格式和一套规则来规范消息的创建、寻址和传输。

在本章中,我提供了 DHCP 创建和发送消息的详细情况,并展示了 DHCP 消息和选项使用的格式。我首先描述了 DHCP 如何创建、寻址和传输消息,以及如何处理消息重传。然后,我概述了 DHCP 的一般消息格式,展示了它与基于其的 BOOTP 消息格式的相似之处以及差异之处。我描述了 DHCP 选项,它们使用的格式,以及用于提高效率的特殊选项过载功能。最后,我给出了 DHCP 选项的完整列表。

小贴士

相关信息 DHCP 在消息方面与 BOOTP 最为接近。DHCP 选项紧密基于 BOOTP 供应商扩展(见第六十章")),许多具体的 DHCP 选项类型与 BOOTP 供应商信息字段相同。为了避免重复,本章的总结表中列出了两种协议的选项/扩展,指出了哪些选项/扩展同时被 BOOTP 和 DHCP 使用,以及哪些仅由 DHCP 使用

DHCP 消息生成、寻址、传输和重传

正如你所学的,DHCP 的几乎所有操作都是围绕客户端设备与服务器交换信息这一概念展开的。你还可以在 DHCP 消息的所有主要特性中看到这一点。这包括 DHCP 消息的格式,以及 DHCP 消息是如何创建、寻址、传输,以及在必要时重新传输的具体细节。

消息生成和一般格式

DHCP 消息在许多方面与基于其的 BOOTP 协议相似。BOOTP 定义了两种消息类型:请求和回复。DHCP 要复杂得多。它使用八种不同类型的消息,但这些消息仍然根据发送者和发送原因被分类为请求或回复消息。DHCP 使用特殊的 DHCP 消息类型选项来指示确切的 DHCP 消息类型,但仍然将客户端寻求信息的消息视为请求,将服务器包含信息的回复视为回复。

客户端使用通用的 DHCP 消息格式生成消息,该格式与 BOOTP 消息格式非常相似。当服务器回复客户端消息时,它不会生成一个全新的回复,而是复制客户端请求,根据需要更改字段,并将回复发送回客户端。在请求中放置一个特殊的交易标识符(XID),并在回复中保持不变,这允许客户端知道哪个回复与特定的请求相对应。

消息传输

DHCP 使用用户数据报协议(UDP)进行传输,正如 BOOTP 所做的那样,出于相同的原因:简单性和支持广播。它也像 BOOTP 一样有许多相同的寻址问题,如第六十章")中所述。客户端通常会在本地网络上通过广播发送请求,以便它们可以联系任何可用的 DHCP 服务器。例外情况是当客户端试图与它已经知道的某个服务器续订租约时。为了与 BOOTP 兼容,DHCP 使用相同的知名(保留)UDP 端口号 67,用于客户端向服务器发送请求。

一些 DHCP 消息交换需要服务器向具有有效和活动 IP 地址的客户端进行响应。一个例子是作为对 DHCPINFORM 请求的响应发送的 DHCPACK 消息。在这种情况下,服务器可以始终向客户端发送单播回复。然而,其他消息交换却出现了我们在 BOOTP 中看到的相同的“先有鸡还是先有蛋”的困境:如果客户端正在使用 DHCP 获取 IP 地址,我们不能假设该 IP 地址可供我们使用来发送回复。

在 BOOTP 中,对此情况有两种可能的解决方案:服务器可以使用广播寻址发送回复,或者服务器可以直接在第二层向主机发送回复。由于广播相关的性能问题,DHCP 尝试将后一种方法作为服务器回复的默认方法。它假设客户端的 TCP/IP 软件将能够接受和处理在第二层交付的 IP 数据报,即使在 IP 栈初始化之前也是如此。

正如标准本身所说,“DHCP 需要创造性地使用客户端的 TCP/IP 软件,并对 RFC 1122 进行自由解释。”RFC 1122 是一个关键标准,描述了 TCP/IP 主机的详细实现要求。然而,DHCP 标准承认并非所有设备都可能支持这种行为。它允许客户端强制服务器使用广播发送回复。这是通过客户端在其请求中将特殊的广播(B)标志设置为 1 来实现的。

由于 DHCP,就像 BOOTP 一样,必须使用第 2 层交付或第 3 层广播来发送服务器响应,因此它需要一个单独的知名端口号,以便服务器发送。同样,为了与 BOOTP 兼容,使用相同的端口号 68。无论服务器响应是单播还是广播,都使用此端口号。

小贴士

关键概念 从 BOOTP 客户端发出的请求通常以广播方式发送,以到达任何可用的 DHCP 服务器。然而,有一些例外,例如在续租时,请求会直接发送到已知的服务器。DHCP 服务器可以通过广播到为 DHCP 客户端保留的特殊端口号或使用层 2 进行单播来发送其响应。DHCP 标准规定,在可能的情况下应使用层 2 交付以避免不必要的广播流量。

丢失消息的重传

使用 UDP 为 DHCP 提供了诸如简单性和效率等好处,但由于 UDP 不可靠,无法保证消息能够到达目的地。这可能导致客户端产生潜在的困惑。例如,考虑一个客户端发送 DHCPDISCOVER 消息并等待 DHCPOFFER 响应的情况。如果它没有收到任何响应,这难道意味着没有 DHCP 服务器愿意提供服务,或者只是它的 DHCPDISCOVER 在网络上某处丢失了?这种情况同样适用于大多数其他请求/响应序列,例如客户端等待 DHCPREQUEST 或 DHCPINFORM 消息的 DHCPACK 或 DHCPNAK 响应。

消息可能丢失的事实意味着 DHCP 本身必须跟踪发送的消息,并在没有响应时重新发送它们。由于 DHCP 中有许多消息交换,因此可能出现很多问题。与 BOOTP 一样,DHCP 将责任明确地放在客户端身上。这是有道理的,因为客户端是发起联系的一方,并且最容易跟踪发送的消息,并在需要时重新发送它们。服务器无法知道客户端的请求何时丢失,但客户端可以在没有收到服务器的回复时做出反应。

在任何请求/响应消息交换中,客户端使用一个重传计时器,该计时器设置为一段时间,表示它合理等待响应的时间。如果在计时器到期之前没有收到回复,客户端会假设其请求或返回的响应已丢失。然后客户端重新发送请求。如果这个请求再次没有引起回复,客户端将继续在一定时间内重传。

为了防止大量的 DHCP 客户端同时重传请求(这可能会阻塞网络),客户端必须使用随机指数退避算法来确定何时进行重传。与 BOOTP 一样,这类似于在以太网中恢复碰撞的技术。DHCP 标准指定延迟应基于客户端和服务器之间底层网络的速度。更具体地说,它表示在标准以太网网络中,第一次重传应延迟 4 秒加减 0 到 1 秒的随机值;换句话说,选择介于 3 到 5 秒之间的某个值。然后,随后的每次传输延迟加倍(7 到 9 秒,然后 15 到 17 秒,以此类推),直到最大 64 +/– 1 秒。

为了防止客户端无限重试,客户端通常具有限制重试次数的逻辑。重传的时间取决于发送请求的类型;也就是说,正在进行什么过程。如果客户端因为重试次数过多而被迫放弃,它通常会采取某种默认操作或生成错误消息。

小贴士

关键概念 与 BOOTP 一样,DHCP 使用 UDP 进行传输,这并不提供任何可靠性功能。DHCP 客户端必须检测到发送请求但没有收到响应的情况,并定期重新发送请求。使用特殊逻辑来防止客户端在网络条件困难时发送过多的请求。

DHCP 消息格式

当 DHCP 被创建时,其开发者遇到了一些关于如何确切地构建 DHCP 消息的问题。BOOTP 已经被广泛使用,保持 DHCP 与 BOOTP 的兼容性是一个重要目标。这意味着 DHCP 的设计师需要继续使用现有的 BOOTP 消息格式。然而,DHCP 比 BOOTP 具有更多的功能,这意味着它可以包含比容易适应有限的 BOOTP 消息格式更多的信息。

这种明显的矛盾以两种方式得到解决:

  • 维持现有的 BOOTP 消息格式以保持基本功能,但 DHCP 客户端和服务器被编程为以略微不同的方式使用 BOOTP 消息字段。

  • BOOTP 供应商扩展被正式化并成为 DHCP 选项。尽管名为选项,但其中一些附加字段是用于基本 DHCP 功能的,它们是相当强制性的!

采用这种双重方法,DHCP 设备可以访问它们所需的额外信息。同时,基本字段格式保持不变,允许 DHCP 服务器与较旧的 BOOTP 客户端通信,这些客户端会忽略与它们无关的额外 DHCP 信息。有关 BOOTP/DHCP 互操作性的讨论,请参阅第六十四章。

DHCP 消息格式在 图 63-1 中展示,并在表 表 63-1 和 表 63-2 中进行了详细描述。在表中,我特别指出了哪些字段在 DHCP 中的使用方式与在 BOOTP 中相似,哪些字段有显著的不同。

DHCP 消息格式

图 63-1. DHCP 消息格式

表 63-1. DHCP 消息格式

字段名称 大小(字节) 描述
Op 1 操作代码:此代码表示 DHCP 消息的一般类别。客户端向服务器发送请求时使用操作码 1;服务器回复时使用代码 2。例如,DHCPREQUEST 是一个请求,而 DHCPACK 或 DHCPNAK 是一个回复。实际具体的 DHCP 消息类型是通过 DHCP 消息类型选项进行编码的。
HType 1 硬件类型:此字段指定用于本地网络的硬件类型,并且与地址解析协议(ARP)消息格式中的等效字段(HRD)以完全相同的方式使用。此字段的一些最常见值在 表 63-2 中显示。
Hlen 1 硬件地址长度:指定此消息中硬件地址的长度。对于使用 IEEE 802 MAC 地址的以太网或其他网络,该值为 6。这也与 ARP 字段格式中的字段 HLN 相同。
Hops 1 跳数:客户端在发送请求之前将其设置为 0,并由中继代理用于控制 BOOTP 和/或 DHCP 消息的转发。
XID 4 事务标识符:客户端生成的一个 32 位标识字段,允许它与从 DHCP 服务器接收到的回复进行匹配。
Secs 2 秒数:在 BOOTP 中,此字段定义得比较模糊,并不总是使用。对于 DHCP,它定义为客户端开始尝试获取或续订租约以来经过的秒数。这可以由繁忙的 DHCP 服务器用于在多个客户端请求待处理时优先回复。
标志 2 标志:这对应于由 RFC 951 定义的 BOOTP 消息格式中的之前为空的 2 字节字段,该字段在 RFC 1542 中被重新定义为标志字段。该字段目前仅包含一个标志子字段。这是 B(广播)标志子字段,大小为 1 位,如果客户端在发送请求时不知道自己的 IP 地址,则将其设置为 1。这作为立即指示 DHCP 服务器或中继代理接收到的请求,应通过广播发送其回复的标志。另一个子字段,大小为 15 位,是保留的,设置为 0,不使用。
CIAddr 4 客户端 IP 地址:如果客户端在 BOUND、RENEWINGREBINDING 状态下具有有效的 IP 地址,则仅在此时将当前 IP 地址放入此字段;否则,将字段设置为 0。客户端只能在其实际有效且可用的地址上使用此字段,而不是在获取地址的过程中。具体来说,客户端不使用此字段请求特定的 IP 地址;它使用请求 IP 地址 DHCP 选项。
YIAddr 4 您的 IP 地址:服务器分配给客户端的 IP 地址。
SIAddr 4 服务器 IP 地址:此字段在 DHCP 中的含义略有变化。在 BOOTP 中,它是发送 BOOTREPLY 消息的 BOOTP 服务器的 IP 地址。在 DHCP 中,它是客户端在引导过程中下一步应使用的服务器的地址,这可能或可能不是发送此回复的服务器。发送服务器始终在服务器标识 DHCP 选项中包含其自己的 IP 地址。
GIAddr 4 网关 IP 地址:此字段的使用方式与 BOOTP 相同,当涉及 BOOTP 中继代理时用于路由 BOOTP 消息,以促进在不同子网或网络上的客户端和服务器之间进行 BOOTP 请求和回复的通信。有关 DHCP 中继的描述。与 BOOTP 一样,此字段不用于客户端,也不表示服务器向客户端提供默认路由器的地址(这是使用路由器 DHCP 选项完成的)。
CHAddr 16 客户端硬件地址:客户端的硬件(第 2 层)地址,用于标识和通信。
SName 64 服务器名称:发送 DHCPOFFER 或 DHCPACK 消息的服务器可以选择将其名称放入此字段。这可以是一个简单的昵称或完全限定的 DNS 域名(例如 myserver.organization.org)。此字段还可以用于携带 DHCP 选项,使用选项超载功能,由 DHCP 选项超载选项的值指示。
File 128 引导文件名:客户端可选用于在 DHCPDISCOVER 消息中请求特定类型的引导文件。服务器在 DHCPOFFER 中使用以完全指定引导文件目录路径和文件名。此字段还可以用于携带 DHCP 选项,使用选项超载功能,由 DHCP 选项超载选项的值指示。
Options 可变 选项:包含基本 DHCP 操作所需的几个参数,用于存储 DHCP 选项。请注意,在 BOOTP 中,此字段长度固定为 64 字节,但在 DHCP 中长度可变。有关更多信息,请参阅下一节。此字段可由客户端和服务器使用。

表 63-2. DHCP 消息 HType 值

HType Value 硬件类型
1 以太网(10 Mb)
6 IEEE 802 网络
7 ARCNet
11 LocalTalk
12 LocalNet(IBM PCNet 或 SYTEK LocalNET)
14 交换式多兆比特数据服务 (SMDS)
15 帧中继
16 异步传输模式 (ATM)
17 高级数据链路控制 (HDLC)
18 光纤通道
19 ATM
20 串行线

DHCP 标准没有指定 DHCP 消息如何在 UDP 中封装的细节。我假设由于与其他 BOOTP 的相似性,DHCP 维持了 BOOTP 选项使用消息校验和的做法。它还很可能假设消息不会被分片(在 IP 数据报中将 Do Not Fragment 位设置为 1)。这是为了让 BOOTP 客户端避免重新组装分片消息的复杂性。

与具有固定消息大小的 BOOTP 不同,DHCP 消息的长度是可变的。这是将 BOOTP 的 64 字节 Vend 字段更改为可变长度的 Options 字段的结果。DHCP 比 BOOTP 更依赖于选项,设备必须能够接受至少 312 字节长度的 Options 字段的消息。SName 和 File 字段也可以用来携带选项,如下一节所述。

DHCP 选项

当 BOOTP 首次开发时,其消息格式包括一个 64 字节的 Vend 字段,称为供应商特定区域。这个字段背后的想法是为协议提供灵活性。BOOTP 标准没有定义使用此字段的任何特定方式。相反,该字段被留空,供不同类型硬件的创建者使用,以将其定制为满足其客户端和/或服务器的需求。

包含这种未定义的字段是一个好主意,因为它使协议易于 扩展——允许通过定义新字段轻松增强协议,同时不影响任何现有字段。然而,BOOTP 供应商特定区域的问题在于,其可扩展性是供应商特定的。它只对特定于单个供应商的特殊字段有用。

真正需要的是一种定义新字段以进行通用、供应商无关的参数通信的方法,但在 BOOTP 消息格式中没有这样的字段可以实现这一点。解决方案以 RFC 1048 的形式出现,它定义了一种称为 BOOTP 供应商信息扩展的技术。这种方法重新定义了供应商特定区域,使其能够携带客户端和服务器之间的通用参数。这个想法非常成功,以至于在很大程度上取代了较老的供应商特定 Vend 字段的使用。

DHCP 维护、规范并进一步扩展了使用 Vend 字段来携带通用参数的想法。这些字段现在简单地被称为 DHCP 选项,而不是被称为供应商信息扩展或供应商信息字段。同样,Vend 字段已被重命名为 Options 字段,反映了它在客户端和服务器之间传达供应商无关选项的新角色。

选项和选项格式

为了保持 BOOTP 和 DHCP 之间的兼容性,DHCP 选项字段在大多数方面与 RFC 1048 引入的 BOOTP Vend 字段的无供应商解释相同。字段的前四个字节仍然携带魔数值 99.130.83.99,以标识这些信息为无供应商选项字段。选项字段的其余部分由一个或多个子字段组成,每个子字段都具有与 BOOTP 中相同的类型、长度、值(TLV 编码)子结构。

BOOTP 供应商信息字段和 DHCP 选项之间的主要区别在于字段名称以及 DHCP 选项字段长度是可变的(BOOTP Vend 字段固定为 64 字节)。整个 DHCP 选项字段的结构如图图 63-2,并且每个选项的子字段名称在表 63-3 中描述。

DHCP 选项字段格式 DHCP 选项字段的格式,不出所料,与 BOOTP 供应商特定区域非常相似,如图所示。选项字段以相同的四个字节魔数开头,然后包含多个可变长度的选项字段。每个选项的格式在。

图 63-2. DHCP 选项字段格式 DHCP 选项字段的格式,不出所料,与 BOOTP 供应商特定区域非常相似,如图图 60-4 所示,位于第六十章")。选项字段以相同的四个字节魔数开头,然后包含多个可变长度的选项字段。每个选项的格式在表 63-3 中描述。

所有的 DHCP 选项都遵循 表 63-3 中所示的格式,除了两个特殊情况,与 BOOTP 一样。代码值 0 用作填充,当子字段需要对齐在字边界上时;它不包含任何信息。值 255 用于标记供应商信息字段的结束。这两个代码都不包含实际数据,因此为了节省空间,当使用任何一个时,只需包含单个代码值,并省略 Len 和 Data 字段。看到代码值为 0 的设备将其视为填充内容跳过。看到代码值为 255 的设备知道它已到达此选项字段中的字段末尾。

表 63-3. DHCP 选项格式

子字段名称 大小(字节) 描述
代码 1 选项代码:一个单字节,用于指定选项类型。
Len 1 选项长度:此特定选项的字节数。这不包括 Code 和 Len 子字段的两个字节。
数据 可变 选项数据:正在发送的数据,其长度由 Len 子字段指示,并根据 Code 子字段进行解释。

选项类别

在 DHCP 被发明之前,一系列 BOOTP 标准被发布,定义了当前 BOOTP 供应商信息扩展的列表。当 DHCP 被开发时,创建了一个单一的标准,它合并了 BOOTP 供应商信息扩展和 DHCP 选项,因为它们基本上是相同的。其中最新的是 RFC 2132,标题为(哇!)"DHCP 选项和 BOOTP 供应商扩展"。

RFC 2132 列出了几十个字段,这些字段可以用作 DHCP 选项或 BOOTP 供应商信息字段,分为几个类别。此外,还有一个仅用于 DHCP 而不用于 BOOTP 的字段集。尽管被称为 选项,但只有一些是可选的;其他对于 DHCP 的基本操作是必要的。它们仅作为选项字段携带,只有一个原因:允许 DHCP 继续使用与 BOOTP 相同的基本消息格式以保持兼容性。表 63-4 总结了用于 DHCP 选项的类别。

表 63-4. DHCP 选项类别

选项类别 描述
RFC 1497 供应商扩展 在 RFC 1497 中定义的 BOOTP 供应商扩展,这是描述供应商扩展字段最后一个与 BOOTP 特定的 RFC(在 DHCP 创建之前)。为了便于参考,当创建 DHCP 选项时,这些都被保留在一个单独的组中,尽管它们所表示的一些功能可能更适合其他类别。(参见 表 63-5。)
每个主机的 IP 层参数 控制主机上 Internet 协议(IP)操作的参数,这些参数影响整个主机,而不是特定于接口。(参见表 63-6。)
每个接口的 IP 层参数 影响主机特定接口上 IP 操作的参数。(一些设备只有一个接口;其他设备有更多。)(参见表 63-7。)
每个接口的链路层参数 基于每个接口影响主机数据链路层操作的参数。(参见表 63-8。)
TCP 参数 影响 TCP 层操作的参数;基于每个接口指定。(参见表 63-9。)
应用和服务参数 用于配置或控制各种杂项应用或服务操作的参数。(参见表 63-10。)
DHCP 扩展 DHCP 特定的参数,用于控制 DHCP 协议本身的操作。(参见表 63-12。)

本章末尾的表格提供了 RFC 2132 中定义的所有 DHCP 选项的完整列表。

由于 DHCP 的普及,自该标准发布以来已经定义了几个其他选项。每次创建一个新选项时,都需要一个新的后续 RFC 2132 来对其进行文档化,这将很混乱且耗时。相反,这些选项和扩展的维护已从 RFC 流程转移到由互联网数字分配机构(IANA)维护的一组文件,就像许多其他参数一样。还有一个过程,开发者可以通过该过程请求将额外的标准扩展添加到 DHCP。这在本节 RFC 2132 的第十部分中描述。

小贴士

关键概念 DHCP 将 BOOTP 的供应商信息扩展正式化为一个称为 DHCP 选项 的官方功能。BOOTP 供应商特定区域字段变为 DHCP 选项字段,它可以包含从服务器发送到客户端的任意数量的参数。其中一些实际上对于 DHCP 的成功操作是必需的。有几十个 DHCP 选项,它们被分为功能类别。

选项重载

由于 DHCP 比 BOOTP 更多地依赖于选项的使用,因此选项字段的大小理论上可能会非常大。然而,由于 DHCP 使用 UDP 进行传输,消息的整体大小是有限的。这理论上可能导致消息空间不足,无法携带所有选项。同时,消息格式中还有两个更大的字段:SName 和 File,分别占用 64 字节和 128 字节。在某些情况下,这些字段可能甚至不需要,因为许多设备使用 DHCP 来获取租约和参数,而不是下载引导映像。即使需要,它们携带的信息可能远少于它们允许的大固定大小。

为了更好地利用消息格式的总空间,DHCP 包含一个称为选项过载的特殊功能,该功能允许使用 SName 和 File 字段来携带更多的选项字段,而不是它们传统的信息。使用此选项本身是通过使用一个 DHCP 选项,即选项过载来指示的,它告诉接收消息的设备如何解释这两个字段。如果使用选项过载,则在解析完选项字段中的所有选项之后,将按照与选项字段相同的方式读取和解释 SName 和/或 File 字段。如果消息实际上需要携带服务器名称或引导文件,这些将作为单独的选项(分别编号为 66 和 67)包含,这些选项的长度是可变的,因此可以精确到所需的长度。

顺便提一下,DHCP 的创造者确实认识到,尽管供应商无关的选项很重要,但供应商可能希望能够发送与原始 BOOTP 定义相同的供应商特定信息。为此,他们创建了一个名为供应商特定信息的 DHCP 选项。此选项允许供应商在正常的 DHCP 选项结构中封装一组供应商特定选项字段。本质上,你可以将其视为将传统的 BOOTP 供应商字段(可变长度)嵌套在单个 DHCP 选项中的方式。其他 DHCP 选项可以同时携带,但受整体消息长度限制。请注意,这补充了一个已经存在的 BOOTP 选项,该选项允许引用包含供应商特定信息的文件。

小贴士

关键概念 由于 DHCP 消息可以包含许多选项,因此创建了一个称为选项过载的特殊功能。当启用时,过载允许选项利用 DHCP 消息格式中的大 SName 和 File 字段。

DHCP 选项/BOOTP 供应商信息字段摘要

BOOTP 厂商信息字段用于携带额外的厂商无关的配置参数。这些被用作 DHCP 选项的基础,该选项将概念扩展到包括用于管理整个 DHCP 操作的参数,如前节所述。由于 BOOTP 厂商信息字段和 DHCP 选项本质上相同(除了 DHCP 特定的字段),它们在同一个 TCP/IP 标准中描述,因此在本书的这一部分中描述。

以下表格列出了每个 DHCP 选项/BOOTP 厂商信息字段。表格显示了每个选项的代码值、选项数据子字段的长度、选项的正式名称以及如何使用的简要描述。为了表格的简洁性,当我说选项时,请将其理解为选项/厂商信息字段,因为它们是相同的(除了 DHCP 特定的选项)。

注意

这些表格中有许多选项,其中一些定义了被某些不太为人所知的协议使用的参数,而这些协议我在本书中没有涉及。简短的描述可能不足以让您完全理解每个选项是如何使用的。特别是请注意,许多最初用于传达某些类型服务器地址的 BOOTP 厂商信息字段现在已经过时,可能不再使用

RFC 1497 厂商扩展

表 63-5 显示了最初在 RFC 1497 中定义的 DHCP/BOOTP 选项。

表 63-5. DHCP/BOOTP 选项:RFC 1497 厂商扩展

代码值 数据长度(字节) 名称和描述
0 0 填充:用作填充以将后续字段对齐到字(2 字节)边界的单个字节。它不包含任何信息。长度为单个字节的两个选项之一,没有数据子字段(另一个是结束选项)。
1 4 子网掩码:提供给客户端在当前网络中使用的 32 位子网掩码。如果两者都存在,它必须在选项列表中出现在路由器选项之前。
2 4 时间偏移:指定客户端子网相对于协调世界时(UTC,以前称为格林尼治标准时间或 GMT)的秒数偏移。正值表示位于本初子午线以东的地区(在英国);负值表示位于本初子午线以西的地区。基本上,这是用来指示子网时区的。
3 可变(4 的倍数) 路由器:指定客户端在本地网络中使用的 32 位路由器地址列表。路由器按照客户端使用的优先级顺序列出。
4 变量(4 的倍数) 时间服务器:指定客户端在本地网络中使用的时服务器地址列表(根据 RFC 868,见第八十八章[TCP/IP 管理及故障排除工具和协议])。服务器按客户端使用的优先顺序列出。
5 变量(4 的倍数) IEN-116 域名服务器:指定客户端在本地网络中使用的 IEN-116 域名服务器地址列表。服务器按客户端使用的优先顺序列出。注意,此选项不用于 DNS 域名服务器。
6 变量(4 的倍数) DNS 域名服务器:指定客户端在本地网络中使用的 DNS(见第五十二章[域名系统(DNS)概述、功能和特性])域名服务器地址列表。服务器按客户端使用的优先顺序列出。
7 变量(4 的倍数) 日志服务器:指定客户端在本地网络中使用的 MIT-LCS UDP 日志服务器地址列表。服务器按客户端使用的优先顺序列出。
8 变量(4 的倍数) Cookie 服务器:指定客户端在本地网络中使用的 RFC 865 Cookie 服务器地址列表。服务器按客户端使用的优先顺序列出。
9 变量(4 的倍数) LPR 服务器:指定客户端在本地网络中使用的 RFC 1179 行式打印机服务器地址列表。服务器按客户端使用的优先顺序列出。
10 变量(4 的倍数) Impress 服务器:指定客户端在本地网络中使用的 Imagen Impress 服务器地址列表。服务器按客户端使用的优先顺序列出。
11 变量(4 的倍数) 资源定位服务器:指定客户端在本地网络中使用的 RFC 887 资源定位服务器地址列表。服务器按客户端使用的优先顺序列出。
12 变量 主机名:指定客户端的主机名。这可能是一个 DNS 主机名,也可能不是;见选项 15。
13 2 引导文件大小:指定客户端默认引导映像文件的大小,以 512 字节为单位。
14 变量 优势转储文件:指定客户端在崩溃时应该将其核心镜像转储到哪个文件路径和文件名。
15 变量 域名:指定客户端的 DNS 域名。与选项 12 进行比较。
16 4 交换服务器:指定客户端交换服务器的地址。
17 变量 根路径:指定客户端根磁盘的路径名。这允许客户端使用网络文件系统(NFS;见第五十八章[网络文件和资源共享及 TCP/IP 网络文件系统(NFS)])等协议访问可能需要的文件。
18 可变 扩展路径:指定包含客户端可以像 DHCP/BOOTP 消息中的选项或 Vend 字段一样解释的厂商特定字段的文件名。这被定义为允许客户端和服务器在 Option/Vend 字段现在用于本章中描述的通用字段的情况下,仍然交换厂商特定信息。也请参阅选项 43。
255 0 结束:放置在其他所有选项之后,以标记选项列表的结束。这是一个长度为单字节的选项之一,没有数据子字段(另一个是填充选项)。

每个主机的 IP 层参数

表 63-6 显示了控制主机上 IP 操作的整体参数。它们不是接口特定的。

表 63-6. DHCP/BOOTP 选项:每个主机的 IP 层参数

代码值 数据长度(字节) 名称和描述
19 1 IP 转发启用/禁用:值为 1 在能够执行该功能的客户端上打开 IP 转发(即路由);值为 0 关闭它。
20 1 非本地源路由启用/禁用选项:值为 1 告诉能够路由的客户端允许转发具有非本地源路由的 IP 数据报。值为 0 告诉客户端不允许这样做。有关此选项和选项 21 的更多信息,请参阅源路由 IP 数据报选项(见第二十一章)。
21 可变(8 的倍数) 策略过滤器:一组地址/掩码对,用于过滤非本地源路由数据报。
22 2 最大数据报重组大小:告知客户端客户端应准备重新组装的最大数据报的大小。最小值为 576 字节。
23 1 默认 IP 生存时间:指定客户端在创建 IP 数据报时应用于生存时间字段的默认值。
24 4 路径 MTU 老化超时:指定客户端应使用多少秒来老化使用路径 MTU 发现确定的路径最大传输单元(MTU)值。
25 变量(2 的倍数) 路径 MTU 平台表:指定用于执行路径 MTU 发现的值表。

每个接口的 IP 层参数

表 63-7 显示了在 IP 层特定于特定主机接口的参数。

表 63-7. DHCP/BOOTP 选项:每个接口的 IP 层参数

代码值 数据长度(字节) 名称和描述
26 2 接口 MTU:指定在此接口上用于 IP 数据报的 MTU。最小值为 68。
27 1 所有子网都是本地:当设置为 1 时,告诉客户端它可能假设它所在的 IP 网络的所有子网都具有与其自己的子网相同的 MTU。当为 0 时,客户端必须假设某些子网可能具有比客户端子网更小的 MTU。
28 4 广播地址:告诉客户端在此接口上用于广播的地址。
29 1 执行掩码发现:值为 1 告诉客户端它应该使用 Internet 控制消息协议(ICMP;参见第三十一章)在本地子网上发现子网掩码。值为 0 告诉客户端不要执行此发现。
30 1 面具供应商:设置为 1 以告知客户端它应该在此接口上响应 ICMP 子网掩码请求。
31 1 执行路由器发现:值为 1 告诉客户端使用 ICMP 路由器发现过程来请求本地路由器。值为 0 告诉客户端不要这样做。注意,DHCP 本身可以使用选项 3 指定一个或多个本地路由器。
32 4 路由器请求地址:告诉客户端用于路由器请求的目的地址。
33 可变(8 的倍数) 静态路由:向客户端提供它可以放入其路由缓存中的静态路由列表。该列表由一组 IP 地址对组成;每一对定义了一个目的地和用于到达目的地的路由器。

每个接口的链路层参数

表 63-8 列出了特定于特定链路层(第二层)接口的 DHCP/BOOTP 选项。

表 63-8. DHCP/BOOTP 选项:每个接口的链路层参数

代码值 数据长度(字节) 名称和描述
34 1 尾部封装:当设置为 1 时,告诉客户端协商使用 RFC 893 中定义的尾部。值为 0 时,告诉客户端不要使用此功能。
35 4 ARP 缓存超时:指定客户端应在其 ARP 缓存中保留条目的时间长度(以秒为单位;参见第十三章")).
36 1 以太网封装:告诉客户端在第二层通过以太网传输时应使用哪种封装类型。如果选项值是 0,则指定应使用 RFC 894 中定义的以太网 II 封装;当值为 1 时,告诉客户端使用 RFC 1042 中定义的 IEEE 802.3 封装。

TCP 参数

影响 TCP 操作选项的显示在表 63-9 中。

表 63-9. DHCP/BOOTP 选项:TCP 参数

代码值 数据长度(字节) 名称和描述
37 1 默认 TTL:指定客户端在发送 TCP 数据段时应使用的默认 TTL。
38 4 TCP Keepalive 间隔:指定客户端在发送 keepalive 消息之前应在空闲 TCP 连接上等待多长时间(以秒为单位)。值为 0 指示客户端除非应用程序明确指示,否则不要发送此类消息。
39 1 TCP Keepalive 垃圾:当设置为 1 时,告诉客户端它应该发送包含一个字节“垃圾”的 TCP keepalive 消息,以与需要此功能的实现保持兼容。

应用程序和服务参数

表 63-10 显示了控制各种应用程序和服务操作的各种选项。

表 63-10. DHCP/BOOTP 选项:应用程序和服务参数

代码值 数据长度(字节) 名称和描述
40 变量 网络信息服务域:指定客户端的 Network Information Service(NIS)域。与选项 64 对比。
41 变量(4 的倍数) 网络信息服务器:指定客户端可能使用的 NIS 服务器 IP 地址列表。服务器按客户端使用的优先顺序列出。与选项 65 对比。
42 变量(4 的倍数) 网络时间协议服务器:指定客户端可能使用的网络时间协议(NTP)服务器 IP 地址列表。服务器按客户端使用的优先顺序列出。
43 变量 供应商特定信息:允许将任意一组供应商特定信息项作为单个选项包含在 DHCP 或 BOOTP 消息中。此信息使用与选项或 Vend 字段相同的格式进行结构化,但不需要以魔法 cookie 开头。有关更多详细信息,请参阅本章前面的“DHCP 选项”部分。
44 变量(4 的倍数) NetBIOS over TCP/IP 命名服务器:指定客户端可能使用的 NetBIOS 命名服务器(根据 RFC 1001/1002)的 IP 地址列表。服务器按客户端使用的优先顺序列出。
45 变量(4 的倍数) NetBIOS over TCP/IP 数据报分发服务器:指定客户端可能使用的 NetBIOS 数据报分发服务器(根据 RFC 1001/1002)的 IP 地址列表。服务器按客户端使用的优先顺序列出。
46 1 NetBIOS over TCP/IP 节点类型:告诉客户端应使用哪种 NetBIOS 节点类型。使用四个不同的位值来定义可能的节点类型组合,如 表 63-11 中列出。
47 变量 NetBIOS over TCP/IP 范围:指定客户端的 NetBIOS over TCP/IP 范围参数。
48 变量(4 的倍数) X 窗口系统字体服务器:指定客户端可能使用的 X 窗口系统字体服务器的 IP 地址列表。服务器按客户端使用的优先顺序列出。
49 变量(4 的倍数) X 窗口系统显示管理器:指定客户端可能使用的运行 X 窗口系统显示管理器的系统的 IP 地址列表。地址按客户端使用的优先顺序列出。
64 变量 网络信息服务+域:指定客户端的 NIS+域。与选项 40 相对比。
65 变量(4 的倍数) 网络信息服务+服务器:指定客户端可能使用的 NIS+服务器的 IP 地址列表。服务器按客户端使用的优先顺序列出。与选项 41 相对比。
68 变量(4 的倍数) 移动 IP 家庭代理:指定客户端在移动 IP(参见第三十章)中可以使用的家庭代理的 IP 地址列表。代理按客户端使用的优先顺序列出;通常指定单个代理。
69 变量(4 的倍数) 简单邮件传输协议(SMTP)服务器:指定客户端可能使用的 SMTP 服务器的 IP 地址列表。服务器按客户端使用的优先顺序列出。有关 SMTP 的更多信息,请参见第七十七章。
70 变量(4 的倍数) 邮局协议(POP3)服务器:指定客户端可能使用的 POP3 服务器的 IP 地址列表。服务器按客户端使用的优先顺序列出。参见第七十八章。
71 变量(4 的倍数) 网络新闻传输协议(NNTP)服务器:指定客户端可能使用的 NNTP 服务器的 IP 地址列表。服务器按客户端使用的优先顺序列出。参见第八十五章。
72 变量(4 的倍数) 默认万维网(WWW)服务器:指定客户端可能使用的万维网(HTTP)服务器的 IP 地址列表。服务器按客户端使用的优先顺序列出。参见第七十九章。
73 变量(4 的倍数) 默认 Finger 服务器:指定客户端可能使用的 Finger 服务器的 IP 地址列表。服务器按客户端使用的优先顺序列出。
74 变量(4 的倍数) 默认互联网中继聊天(IRC)服务器:指定客户端可能使用的互联网中继聊天(IRC)服务器的 IP 地址列表。服务器按客户端使用的优先顺序列出。
75 可变(4 的倍数) StreetTalk 服务器:指定客户端可能使用的 StreetTalk 服务器 IP 地址列表。服务器按客户端使用的优先顺序列出。
76 可变(4 的倍数) StreetTalk 目录辅助(STDA)服务器:指定客户端可能使用的 STDA 服务器的 IP 地址列表。服务器按客户端使用的优先顺序列出。

表 63-11. NetBIOS 通过 TCP/IP 节点类型(选项 46)值

选项 46 子字段名称 大小(位) 描述
保留 4 保留:未使用。
H-Node 1 H-Node:设置为 1 以指示客户端作为 NetBIOS H-节点操作。
M-Node 1 M-Node:设置为 1 以指示客户端作为 NetBIOS M-节点操作。
P-Node 1 P-Node:设置为 1 以指示客户端作为 NetBIOS P-节点操作。
B-Node 1 B-Node:设置为 1 以指示客户端作为 NetBIOS B-节点操作。

DHCP 扩展

最后,但同样重要的是,表 63-12 描述了仅用于控制 DHCP 协议操作的 DHCP 专用选项。

表 63-12. DHCP 选项:DHCP 扩展

代码值 数据长度(字节) 名称和描述
50 4 请求的 IP 地址:在客户端的 DHCPDISCOVER 消息中用于请求特定的 IP 地址分配。
51 4 IP 地址租约时间:在客户端请求中用于请求特定的 DHCP 租约持续时间,或在服务器回复中告知客户端提供的租约时间。它以秒为单位指定。
52 1 选项过载:用于告知 DHCP 消息的接收者,消息的 SName 和/或 File 字段正在用于携带选项,而不是它们的正常含义。此选项实现了选项过载功能。此单字节选项有三个可能的值:1 表示 File 字段携带选项数据,2 表示 SName 字段包含选项数据,3 表示两个字段都包含选项数据。
53 1 DHCP 消息类型:指示 DHCP 消息的具体类型,如表 6-13 中所示。
54 4 服务器标识符:特定 DHCP 服务器的 IP 地址。此选项包含在 DHCP 服务器发送的消息中,以标识其为消息的来源。它还由客户端在 DHCPREQUEST 消息中使用,以指定它接受的租约是哪个服务器的。
55 可变 参数请求列表:由 DHCP 客户端用于从 DHCP 服务器请求特定配置参数值的列表。
56 可变 消息:由服务器或客户端用于指示错误或其他消息。
57 2 最大 DHCP 消息大小:由 DHCP 客户端或服务器用于指定它愿意接受的最大 DHCP 消息大小。最小合法值是 576 字节。
58 4 更新(T1)时间值:告知客户端用于其更新计时器的值。
59 4 绑定(T2)时间值:告诉客户端用于其绑定定时器的值。
60 可变 供应商类标识符:在 DHCP 客户端发送的消息中包含,以指定其供应商和配置。这可能被用来提示服务器使用选项 43 发送正确的供应商特定信息。
61 可变 客户端标识符:客户端可选地用来指定一个与 DHCP 默认值不同的唯一客户端标识符。服务器期望此标识符在所有 DHCP 客户端中是唯一的,并用于索引 DHCP 服务器的配置参数数据库。
66 可变 TFTP 服务器名称:当 DHCP 消息的 SName 字段被用于选项 overload 功能时,此选项可能被包含以指定通常出现在 SName 字段中的简单文件传输协议(TFTP)服务器名称。
67 可变 引导文件名:当 DHCP 消息的文件字段被用于选项 overload 功能时,此选项可能被包含以指定通常出现在文件字段中的引导文件名。

表 63-13. DHCP 消息类型(选项 53)值

选项 53 值 DHCP 消息类型
1 DHCPDISCOVER
2 DHCPOFFER
3 DHCPREQUEST
4 DHCPDECLINE
5 DHCPACK
6 DHCPNAK
7 DHCPRELEASE
8 DHCPINFORM

第六十四章。DHCP 客户端/服务器实现、功能及 IPv6 支持

无标题图片

本部分的前几章描述了 DHCP 操作的基础:地址租赁系统、配置过程和消息。有了这个基础,我们现在可以进一步探讨 DHCP 实现的一些更有趣的细节。我们还可以深入研究一些额外的功能和特殊功能,这些功能改变了我们已研究的基本 DHCP 机制。

在本章中,我讨论了 DHCP 客户端/服务器实现问题、增强协议的特殊功能以及与使 DHCP 工作相关的一些问题和挑战。我首先讨论了 DHCP 服务器和客户端的实现与管理问题。我讨论了 DHCP 消息中继及其与用于引导协议(BOOTP)的中继功能的相关性。我描述了当客户端无法联系服务器时,DHCP 提供自动默认地址的功能以及用于多服务器的冲突检测功能。然后,我涵盖了与 DHCP 和 BOOTP 互操作性相关的一些问题,并概述了一些与 DHCP 安全相关的重要问题和挑战。最后,我概述了 IPv6(DHCPv6)的 DHCP。

DHCP 服务器和客户端实现与管理问题

DHCP 是一种客户端/服务器协议,依赖于服务器和客户端共同履行某些职责。在这两个设备角色中,DHCP 服务器可以说是更重要的,因为大多数 DHCP 功能实际上是在服务器中实现的。

DHCP 服务器实现

服务器维护配置数据库,跟踪地址范围,并管理租约。因此,DHCP 服务器通常比 DHCP 客户端复杂得多。本质上,没有 DHCP 服务器,实际上就没有 DHCP。因此,决定如何实现 DHCP 服务器是实现协议的重要组成部分。

经典的 DHCP 服务器由运行在某种服务器硬件平台上的 DHCP 服务器软件组成。通常,DHCP 服务器不会是专用计算机,除非是在非常大的网络中。更常见的是,硬件服务器在执行其他功能的同时提供 DHCP 服务,例如充当应用服务器、通用数据库服务器、提供 DNS 服务等等。因此,DHCP 服务器不需要是特殊的计算机;任何可以运行 DHCP 服务器实现的设备都可以充当服务器。

实际上,DHCP 服务器甚至可能不需要是一台主机计算机。如今,许多路由器都集成了 DHCP 功能。编程路由器以充当 DHCP 服务器允许连接到路由器的客户端自动分配 IP 地址。这在有限数量的公共 IP 地址在多个客户端之间共享的环境中,或者在使用 IP 网络地址转换(NAT;参见第二十八章协议")动态共享少量地址的环境中提供了许多潜在优势。由于 DHCP 需要数据库,充当 DHCP 服务器的路由器需要某种形式的永久存储。这通常是通过路由器上的闪存来实现;"真正的"服务器使用硬盘存储。

几乎所有现代操作系统都包括对 DHCP 的支持,包括 UNIX、Linux 的大多数变种、较新版本的 Microsoft Windows、Novell NetWare 以及其他操作系统。在某些情况下,你可能需要运行操作系统的服务器版本,以便让主机充当 DHCP 服务器。例如,虽然 Microsoft Windows XP 支持 DHCP,但我相信 Windows XP 家庭版中并没有内置 DHCP 服务器,尽管你可以自行安装一个。

DHCP 服务器软件功能

在大多数网络中,你将根据大量因素选择操作系统。然后,操作系统的选择将决定你选择 DHCP 服务器软件的选项。大多数常见的操作系统都有多种软件选项。虽然所有这些都将实现核心 DHCP 协议,但它们在通常的软件属性方面会有所不同:成本、性能、易用性等。它们也可能在功能方面有所不同,例如以下方面:

  • 他们如何定义地址范围(作用域)

  • 客户端如何分组和管理

  • 管理员对返回给客户端的参数的控制级别

  • 管理员对协议的一般操作的控制级别,例如指定 T1 和 T2 计时器和其他变量,以及如何分配租赁和如何处理续订

  • 安全功能

  • 能够与 DNS 交互以支持动态设备命名

  • 可选功能,如 BOOTP 支持、冲突检测和自动私有 IP 地址分配(本章后面将讨论)

选择服务器数量

在为网络设置 DHCP 时,需要考虑和做出许多重要因素和决策。其中最关键的是您希望拥有的服务器数量。理论上,每个网络只需要一个 DHCP 服务器;在实践中,这通常不是一个好主意。服务器有时会经历硬件或软件故障,或者必须关闭进行维护。如果只有一个服务器并且客户端无法访问它,那么没有任何 DHCP 客户端能够获取地址。因此,通常使用两个或更多服务器。

如果您使用多个服务器,您需要仔细规划如何配置每个服务器。您需要做出的第一个决定之一是哪些服务器将负责哪些地址和客户端。您需要确定您是否希望服务器具有不同的或重叠的地址池,正如在第六十一章中解释 DHCP 地址范围时所述。不同的池确保地址保持唯一,但如果服务器失败,会导致地址不可分配。重叠的地址更灵活,但如果未使用冲突检测(本章后面将讨论)等特性,则存在地址冲突的风险。

服务器位置、设置和维护

一旦您知道您想要多少个服务器,您需要确定您想在网络的哪个部分放置它们。如果您有多个物理网络,您可能还需要使用 DHCP 中继来允许所有客户端都能访问服务器。由于网络结构可能会影响您使用的服务器数量,许多这些决策是相互关联的。

您必须就前几章中讨论的所有 DHCP 操作参数做出政策决策。两个主要决策是地址池的大小和结构,以及做出租赁策略决策,例如租赁长度和 T1 和 T2 计时器的设置。您还必须决定哪些客户端将动态分配地址,以及如何处理手动配置的客户端。

最后,管理员必须记住,组织的 DHCP 服务器是一个数据库服务器,必须相应地对待。像任何数据库服务器一样,它必须得到仔细的维护和管理。必须制定管理政策以确保服务器的安全和高效运行。此外,与某些其他类型的数据库系统不同,DHCP 数据库不是自动复制的;因此,服务器数据库应定期备份,使用 RAID 存储也是一个好主意。

DHCP 客户端实现

正如 DHCP 服务器由运行在服务器平台或硬件上的服务器软件组成一样,DHCP 客户端只是运行在客户端设备上的 DHCP 客户端软件。最常见的情况是,客户端设备是连接到 TCP/IP 内部网络的宿主计算机。今天,DHCP 得到了如此广泛的接受,几乎所有的宿主都包含了 DHCP 客户端软件。DHCP 客户端通常集成到图形操作系统如 Windows 中,或者在 UNIX/Linux 上使用特定的客户端守护进程,如 dhclientdhcpd

由于 DHCP 的整个理念是将服务器置于参数存储、配置和地址管理的主导地位,因此 DHCP 客户端相对简单。客户端实现了消息协议,并根据需要将接收自 DHCP 服务器的参数传达给 TCP/IP 软件组件。它没有做很多其他的事情。

实际上,管理员在设置客户端使用 DHCP 时并没有太多事情要做。在某些操作系统中,这就像“打开一个开关”一样简单,通过在客户端内部启用 DHCP 支持。这会提示客户端停止使用任何手动配置的参数,并开始寻找 DHCP 服务器。然后,服务器负责客户端的配置和地址分配。

由于客户端在 DHCP 中除了与服务器通信之外并没有做很多工作,因此对于 DHCP 客户端来说,用户软件的需求并不多。在大多数情况下,通过 TCP/IP 配置实用程序来控制 DHCP 客户端软件,如 第八十八章 中所述。Windows 客户端使用 ipconfigwinipcfg 程序来显示当前 DHCP 租赁的状态。这些程序还允许客户端手动释放当前租赁或更新它。

释放租赁意味着使用 DHCPRELEASE 消息提前终止租赁。这通常是终止租赁的唯一方式。更新租赁是自动更新过程的手动版本。释放和更新租赁可以按顺序进行,以重置处于混乱状态或遇到其他类型 DHCP 或连接问题的客户端。

DHCP 消息中继和 BOOTP 中继代理

DHCP 是 TCP/IP 的第三代主机配置协议。我们已经广泛讨论了它是如何直接基于 BOOTP 的,而 BOOTP 本身是早期反向地址解析协议(RARP)的增强。尽管每个新协议在其前辈的基础上都做出了显著的改进,但每一代迭代都保留了一些实际上是所有主机配置协议共有的限制。

主机配置协议的一个重要限制是依赖于广播进行通信。每当我们在处理一个客户端需要通信但不知道其 IP 地址,也不知道将提供该地址的服务器地址的情况时,客户端需要使用广播地址。然而,出于性能原因,广播通常只在本地网络中传播。这意味着客户端和服务器始终需要在同一物理网络上才能进行主机配置。当然,我们不希望这种情况发生。这需要在一个大型互联网的每个网络中都有一个不同的服务器,这会大大减少集中配置信息的好处,并造成许多管理上的麻烦。

RARP 没有解决这个问题,这也是它在使用上如此有限的一个原因。BOOTP 的解决方案是允许客户端和服务器通过使用 BOOTP 中继代理在不同的网络上。

DHCP 的 BOOTP 中继代理

中继代理是一种不是 BOOTP 服务器的设备,但它运行一个特殊的软件模块,允许它代替服务器的作用。中继代理可以放置在有 BOOTP 客户端但没有 BOOTP 服务器的网络上。中继代理拦截来自客户端的请求并将它们转发到服务器。然后服务器将响应发送回代理,代理再将响应转发给客户端。BOOTP 中继代理的完整理由和操作描述可以在第六十章")中找到。

DHCP 的设计者对 BOOTP 中继代理背后的基本概念和操作感到满意,这些概念和操作已经使用了多年。因此,他们做出了继续在 DHCP 中使用 BOOTP 中继代理功能的具体决定。事实上,这也是决定保留 BOOTP 消息格式在 DHCP 中的原因之一,以及基本的请求/回复通信协议。这允许 BOOTP 中继代理将 DHCP 消息处理成 BOOTP 消息。这也是为什么在这个主题的标题中提到 BOOTP 不是打字错误——DHCP 使用 BOOTP 中继代理。甚至 DHCP 标准也说明,“BOOTP 中继代理是一个在 DHCP 客户端和 DHCP 服务器之间传递 DHCP 消息的互联网主机或路由器。”

实际上,代理有时确实被称为DHCP 中继代理。你也可能看到BOOTP/DHCP 中继代理DHCP/BOOTP 中继代理这样的术语。

DHCP 中继过程

由于 DHCP 是专门为支持 BOOTP 中继代理而设计的,因此代理在 DHCP 中的行为与在 BOOTP 中类似。尽管 DHCP 的消息交换更加复杂,但它们仍然都是围绕客户端请求和服务器响应的概念设计的。只是请求和回复更多。

BOOTP 代理寻找客户端发送的广播,然后将它们转发到服务器(如第六十章"))中所述的 BOOTP 中继代理行为讨论中所述),然后返回来自服务器的回复。DHCP 协议中的附加信息是通过在 BOOTP 消息格式中添加 DHCP 选项来实现的,中继代理不会查看这些选项。它只是像处理 BOOTP 请求和回复一样处理它们。

小贴士

关键概念 要允许 DHCP 客户端和 DHCP 服务器位于不同的物理网络上,需要一个中介设备来促进网络之间的消息交换。DHCP 为此使用与 BOOTP 相同的机制:部署BOOTP中继代理。中继代理捕获客户端请求,将它们转发到服务器,然后将服务器的响应返回给客户端。

总结来说,当使用中继代理时,DHCP 操作部分中的各种客户端请求和服务器回复如下:

客户端请求 当客户端广播请求时,中继代理在 UDP 端口 67 上拦截它。它检查跳数字段,如果值大于 16,则丢弃请求;否则,增加该字段。除非另一个中继代理已经将它的地址放入该字段,否则代理将把它的自己的地址放入 GIAddr 字段。然后代理将客户端请求转发到 DHCP 服务器,要么是单播,要么是在另一个网络上的广播。

服务器回复 服务器看到 GIAddr 字段中的非零值,并将回复发送到该字段中 IP 地址所在的中继代理。然后中继代理使用单播或广播(如第六十一章中关于 DHCP 寻址的讨论所述)将回复发送回客户端。

BOOTP 和 DHCP 之间的一个区别是,客户端到服务器的一些通信是单播的。最明显的例子是当客户端尝试使用特定的 DHCP 服务器续订其租约时。由于它以单播的形式发送此请求,它可以使用传统的 IP 路由访问不同网络上的 DHCP 服务器,中继代理不需要参与。

DHCP 自动配置/自动私有 IP 地址分配(APIPA)

TCP/IP 主机的 IP 地址在许多方面是其身份的象征。每个 TCP/IP 网络都需要所有主机都有唯一的地址,以便促进通信。当网络为每个主机手动配置一个独特的 IP 地址时,主机永久知道自己的身份。当主机成为 DHCP 客户端时,它们就不再有永久身份;它们依赖于 DHCP 服务器来告诉它们自己的身份。

只要 DHCP 正常运行并且主机能够获取到租约,这种依赖性就不会成为问题,实际上,它还带来了许多我们已经探讨过的益处。不幸的是,可能会出现一些情况,导致客户端无法获取租约。客户端可能无法获取租约,重启后也无法重新获取,或者无法续租现有的租约。这种情况可能发生的几个可能原因包括:

  • DHCP 服务器可能已经出现故障,或者可能因维护而关闭。

  • 客户端本地网络上的中继代理可能已经失败。

  • 另一次硬件故障或断电可能会导致通信无法进行。

  • 网络可能已经耗尽了可分配的地址。

没有租约,主机就没有 IP 地址,没有地址,主机实际上就处于瘫痪状态。基本的 DHCP 规范并没有为无法成功获取租约的主机指定任何补救措施。这取决于实现者来决定该做什么,以及当 DHCP 最初创建时,许多主机实现会简单地显示错误消息,并使主机直到管理员或用户采取行动才可用。

显然,这远非理想情况。如果我们可以有一个无法连接到服务器的 DHCP 客户端自动配置自己,那就更好了。实际上,互联网工程任务组(IETF)为此目的预留了一个特殊的 IP 地址块(见第十七章):它使用 ARP 在本地网络上生成一个请求,以查看是否有其他客户端使用它选择的地址响应。如果有回复,APIPA 尝试另一个随机地址并重复测试。当 APIPA 软件找到一个未被使用的地址时,它将该地址作为默认地址分配给客户端。然后客户端将使用从 DHCP 服务器通常接收的其他配置参数的默认值。这个过程在图 64-1 中进行了说明。

使用自动配置地址的客户将定期尝试联系 DHCP 服务器。默认情况下,此检查每五分钟执行一次。如果找到,它将获取一个租约,并用正确的租约地址替换自动配置的地址。

APIPA 非常适合小型网络,其中所有设备都在单个物理链路上。理论上,在一个具有单个 DHCP 服务器的网络中,如果有 20 个启用 APIPA 的 DHCP 客户端,你可以在维护期间关闭服务器,而所有客户端仍然可以正常工作,使用 169.254.x.x地址。

然而,请注意,APIPA 并不是完整 DHCP 的适当替代品。

DHCP 自动私有 IP 地址分配 (APIPA) 在本例中,客户端 1 正在尝试从其 DHCP 服务器获取 IP 地址,但服务器地址已用尽,因此它不会响应用户的请求。客户端配置为使用 APIPA,因此它从 APIPA 地址块中随机选择一个地址。它在本地网络上发送一个 ARP 请求,以查看是否有其他设备正在使用该地址。通常情况下,不会发生冲突,但在这里客户端 2 正在使用该地址,因此它做出了响应。客户端 1 选择了一个不同的地址,这次没有收到回复。它开始使用该地址,同时继续定期检查 DHCP 服务器是否上线。

图 64-1. DHCP 自动私有 IP 地址分配 (APIPA) 在本例中,客户端 1 正在尝试从其 DHCP 服务器获取 IP 地址,但服务器地址已用尽,因此它不会响应用户的请求。客户端配置为使用 APIPA,因此它从 APIPA 地址块中随机选择一个地址。它在本地网络上发送一个 ARP 请求,以查看是否有其他设备正在使用该地址。通常情况下,不会发生冲突,但在这里客户端 2 正在使用该地址,因此它做出了响应。客户端 1 选择了一个不同的地址,这次没有收到回复。它开始使用该地址,同时继续定期检查 DHCP 服务器是否上线。

APIPA 限制

169.254.0.0/16 块是一个私有 IP 范围,并带有所有私有 IP 地址的限制,包括无法在互联网上使用这些地址。此外,APIPA 无法提供客户端可能需要从 DHCP 服务器获取的其他配置参数。最后,APIPA 与代理 ARP 一起使用时可能无法正常工作,因为代理将响应用户的任何私有地址,因此它们都会看起来已被使用。

由于它使用 ARP 检查地址冲突,APIPA 不太适合大型互连网络。要在具有多个子网的网络中使用它,需要软件允许每个子网使用 169.254.0.0/16 块的不同部分,以避免冲突。

在实践中,APIPA 是小型网络的一种解决方案。大型互连网络通过确保客户端始终可以联系到 DHCP 服务器来处理无法联系 DHCP 服务器的难题。

小贴士

关键概念 一个名为 自动私有 IP 地址分配 (APIPA) 的可选 DHCP 功能被开发出来,以便在客户端无法从 DHCP 服务器获取 IP 地址的情况下,仍然能够进行通信。当启用时,客户端从专门保留的私有 IP 地址块中随机选择一个地址,并检查该地址是否已被其他设备使用。它将继续定期检查 DHCP 服务器,直到找到为止。

DHCP 服务器冲突检测

对于任何使用 DHCP 的 TCP/IP 管理员来说,必须做出的主要决定之一是部署多少个 DHCP 服务器。单个服务器具有简单性的优势,但在发生故障时没有冗余。这也意味着,每当 DHCP 服务器宕机时,客户端都无法获取地址。出于这些原因,大多数大型网络都使用两个或更多服务器。

当你有两个或更多服务器时——为了讨论方便,我们假设有两个服务器——你还需要做出另一个决定:如何将地址池在服务器之间划分?正如我在第六十一章中详细讨论 DHCP 地址池时所指出的,有两种选择:给服务器分配重叠地址或使它们不重叠。不幸的是,在经典 DHCP 中,这两种方法都不是很好的解决方案。重叠范围意味着两个服务器可能会尝试分配相同的地址,因为 DHCP 没有提供服务器之间通信的条款。非重叠范围避免了这个问题,但只让每个服务器可用一些地址。

很奇怪,尽管显然有这种需求,但 DHCP 标准没有提供更好的跨服务器协调支持。然而,某些 DHCP 实现包括一个可选功能,允许两个服务器在没有地址冲突的情况下具有重叠的作用域。这是在 Microsoft DHCP 服务器上常见的一个功能,也可能存在于其他实现中。它被称为DHCP 服务器冲突检测

冲突检测背后的想法非常简单。假设一个 DHCP 服务器从客户端收到一个 DHCPDISCOVER 消息,并决定向它提供一个租约。在发送 DHCPOFFER 消息之前,服务器通过向它计划提供的地址发送 ICMP Echo(ping)消息来进行探测(见第三十三章)。然后它等待一小段时间,看是否收到任何 ICMP Echo Reply 消息。如果收到了,它就知道该 IP 地址正在使用,并选择另一个地址。

如果所有 DHCP 服务器在提供地址之前都配置为执行此操作,那么可以给它们分配相同的、重叠的地址。它们没有协调彼此的方式,但只要它们通过执行 ICMP 检查来首先询问,就不会有任何问题。这为管理员提供了重叠地址范围的优点——简单性和所有服务器都能访问所有地址——而没有地址冲突的风险。唯一的缺点是执行检查会产生一点额外的网络流量,如果需要选择新的地址,可能还会占用服务器 CPU 时间几毫秒。

如果您在阅读第六十二章(第六十二章。DHCP 配置和操作)中关于 DHCP 分配过程的内容时留心,您可能会注意到我这里描述的内容听起来很熟悉。事实上,这个功能并不是什么新东西。在提供地址之前使用 ICMP 检查地址的做法实际上在 RFC 2131 中作为标准 DHCP 分配过程的一部分被提及,您可以在分配过程描述中找到它作为第 5 步。

那么为什么冲突检测需要成为一个额外功能呢?原因在于,使用 ICMP 不是强制性的,因为标准说服务器应该这样做,而不是必须这样做。这个选择是为了在实现 DHCP 时提供灵活性,但这种灵活性是有代价的。因此,如果您想使用这个功能,您需要在您的服务器软件中寻找对其的支持。

小贴士

关键概念 一些 DHCP 实现包括一个名为 服务器冲突检测 的功能。当此功能被激活时,它会使得每个服务器在授予地址给客户端之前,总是检查该地址是否未被使用。当网络上的所有 DHCP 服务器都使用冲突检测时,服务器可以被赋予重叠的作用域,这样每个服务器都可以分配组织中的任何 IP 地址,同时不必担心两个客户端被不同的服务器分配了相同的地址。

DHCP 和 BOOTP 互操作性

我已经广泛地讨论了 DHCP 是如何基于 BOOTP 设计的,以及它们如何使用相同的基本通信方法和消息格式。这样做是出于几个原因,其中最重要的一个原因是确保两种协议的互操作性。鉴于这一点,您可能会期望我们只需简单地说 BOOTP 和 DHCP 是兼容的,就是这样。

诚然,DHCP 的目的是与 BOOTP 兼容。RFC 2131 列出了以下内容作为 DHCP 的设计目标之一:“DHCP 必须为现有的 BOOTP 客户端提供服务。”这似乎很清楚。重新使用 BOOTP 消息格式是 DHCP 和 BOOTP 兼容的关键。DHCP 功能不是通过新字段实现的,而是通过 DHCP 特定的选项实现的,例如 DHCP 消息类型选项,它指定了至关重要的 DHCP 消息类型。DHCP 设备可以查找这些额外信息,而 BOOTP 设备可以忽略它们。

然而,尽管 DHCP 和 BOOTP 相似,但它们并不相同,因此当它们一起使用时,会出现一些互操作性问题。DHCP 消息格式在结构上与 BOOTP 格式相同,但对某些字段的解释略有不同。BOOTP 客户端不理解 DHCP,因此当 BOOTP 和 DHCP 一起使用时,DHCP 客户端或服务器有时必须稍微不同地表现以补偿。进一步复杂化问题的事实是,并非所有 DHCP 和 BOOTP 的实现都必然完全相同,以及 DHCP 标准中的一些规范不是强制的。

由于这些原因,我们不能简单地假设 DHCP 和 BOOTP 可以一起工作。为了解决这些问题中的某些,IETF 在 DHCP 最初创建的同时发布了 RFC 1534,“DHCP 和 BOOTP 之间的互操作性”。这份文件探讨了这些协议是如何协同工作的,重点关注两种不同的客户端/服务器互操作组合:一个 BOOTP 客户端连接到 DHCP 服务器,以及一个 DHCP 客户端连接到 BOOTP 服务器。让我们考虑每种情况。

连接到 DHCP 服务器的 BOOTP 客户端

如 RFC 2131 中的引言所示,DHCP 的特定目的是允许 DHCP 服务器处理来自 BOOTP 客户端的请求。该协议本身被设置成启用这一点,但它确实需要 DHCP 服务器具备一定的智能来知道如何处理 BOOTP 客户端。

其中一个最重要的问题是 BOOTP 客户端将遵循 BOOTP 配置过程,而不是 DHCP 租赁过程。当处理 BOOTP 客户端时,DHCP 服务器必须使用具有 BOOTP 含义的字段来使用 BOOTP 消息。服务器通过寻找 DHCP 消息类型选项的存在来确定客户端是否使用 BOOTP 而不是 DHCP,这个选项必须存在于所有 DHCP 消息中,但不用于 BOOTP。

如果 DHCP 服务器检测到它正在处理一个 BOOTP 客户端,它可以向客户端提供配置信息。服务器可以使用手动或自动分配给客户端。自动分配意味着服务器从其未使用的地址池中选择一个地址,但永久分配它。由于 BOOTP 本质上是静态的,BOOTP 客户端无法进行动态分配。

DHCP 服务器可以在对 BOOTP 客户端的响应中包含 BOOTP 供应商信息字段,包括自 BOOTP 创建以来定义的字段。然而,它显然不能发送任何特定的 DHCP 选项。

连接到 BOOTP 服务器的 DHCP 客户端

DHCP 客户端可以从 BOOTP 服务器获取配置信息,因为服务器将像对 BOOTP BOOTREQUEST 消息的响应一样响应客户端的初始 DHCPDISCOVER 消息。DHCP 客户端可以通过没有 DHCP 消息类型选项来识别已收到 BOOTP 回复。

应将 BOOTP 服务器的响应视为无限期租约,因为再次强调,这正是 BOOTP 所支持的。请注意,如果 DHCP 客户端同时从 BOOTP 服务器和 DHCP 服务器收到响应,它应该使用 DHCP 响应而不是 BOOTP 响应(即使这意味着它得到的租约更短)。

DHCP 安全问题

DHCP 是在 20 世纪 90 年代初设计的,当时互联网上的组织数量相对较少。此外,它基于 1980 年代创建的 BOOTP,当时我们今天所知道的互联网几乎还不存在。在那个时代,互联网安全并不是一个大问题,因为主要是少数研究机构和教育组织在互联网上使用 TCP/IP。因此,DHCP,就像那个时代的许多协议一样,并没有做很多来处理安全问题。

实际上,这有点低估了。不仅 DHCP 运行在互联网协议(IP)和用户数据报协议(UDP)上,这些协议本身就不安全,而且 DHCP 协议本身没有任何安全措施。这在现代网络中是一个相当严重的问题,因为 DHCP 的强大功能涉及到关键的配置信息。

DHCP 安全关注点

与 DHCP 相关的潜在安全问题分为两类:

未经授权的 DHCP 服务器 如果一个恶意的人放置了一个恶意 DHCP 服务器,那么这个设备可能对客户端请求做出响应,并向他们提供虚假的配置信息。这可能被用来使客户端在网络上无法使用,或者更糟,为以后的进一步滥用做准备。例如,一个黑客可以利用一个虚假的 DHCP 服务器将 DHCP 客户端引导到使用黑客控制的路由器,而不是客户端应该使用的路由器。

未经授权的 DHCP 客户端 一个客户端可能被设置成伪装成合法的 DHCP 客户端,从而获取为该客户端指定的配置信息。这些信息随后可能被用来在以后破坏网络。或者,一个恶意的人可能使用软件生成大量的虚假 DHCP 客户端请求,以耗尽 DHCP 服务器池中的所有 IP 地址。更简单地说,这可能被一个小偷用来从组织那里窃取 IP 地址以供自己使用。

这些显然是严重的问题。通常推荐的解决这些风险的方案通常涉及在较低层提供安全措施。例如,防止未经授权的服务器和客户端的一个重要技术是仔细控制对网络的物理访问:第 1 层安全。在第二层实现的安全技术也可能有用——例如,在无线局域网的情况下。由于 DHCP 运行在 UDP 和 IP 上,可以在第 3 层使用 IPSec 提供认证。

DHCP 认证

为了尝试解决 DHCP 本身的一些更具体的安全问题,2001 年 6 月,IETF 发布了 RFC 3118,“DHCP 消息的身份验证”。这个标准描述了一种增强功能,用经过身份验证的消息替换了正常的 DHCP 消息。客户端和服务器检查身份验证信息,并拒绝来自无效来源的消息。这项技术涉及使用一种新的 DHCP 选项类型,即身份验证选项,并对几个租赁过程进行操作更改以使用此选项。

不幸的是,2001 年在 DHCP 领域已经相当晚,现在有数百万的 DHCP 客户端和服务器不支持这个新标准。客户端和服务器都必须编程以使用身份验证,这样这种方法才有价值。支持身份验证的 DHCP 服务器可以为支持该功能的客户端使用它,而对于不支持该功能的客户端则跳过。然而,由于这个选项不是通用的,所以它并没有得到广泛部署,大多数网络必须依赖更传统的安全措施。

DHCP for IP Version 6 (DHCPv6)

DHCP 目前是 TCP/IP 协议套件的标准主机配置协议。TCP/IP 建立在 IP 版本 4(IPv4)之上。然而,自 20 世纪 90 年代初以来,一直在进行 IPv4 的继任者:互联网协议版本 6(IPv6;更多信息请参阅第二部分-4"))。这个新的 IP 标准将是 TCP/IP 的未来。

虽然 IPv6 带来的大多数变化影响的是 TCP/IP 架构模型中的底层技术,但这些修改的重要性意味着许多其他 TCP/IP 协议也受到影响。这尤其适用于与地址或配置信息一起工作的协议,包括 DHCP。因此,IPv6 需要一个新版本的 DHCP。在写作本文时,DHCPv6 尚未正式发布——它仍然是一个正在讨论中的互联网草案。

注意

在纯粹围绕 IPv6 的讨论中,DHCPv6 有时简称为 DHCP,而原始的 DHCP 则称为 DHCPv4

IPv6 中的两种自动配置方法

在 IPv6 中引入的许多改进之一是为更容易管理 IP 设备制定的整体策略,包括主机配置。为 IPv6 主机的自动配置定义了两种基本方法:

无状态自动配置 一种定义出来的方法,允许主机在没有其他设备帮助的情况下自行配置。

有状态自动配置 一种技术,其中配置信息由服务器提供给主机。

使用哪种方法取决于网络的特点。无状态自动配置在 RFC 2462 中描述,并在第二十四章中讨论。IPv6 的有状态自动配置由 DHCPv6 提供。与常规 DHCP 一样,DHCPv6 可以用来获取 IP 地址和其他配置参数,或者当客户端已经有一个 IP 地址时,仅获取配置参数。

DHCPv6 操作概述

DHCPv6 的操作与 DHCPv4 类似,但协议本身已经被完全重写。它不仅在概念上基于旧的 DHCP 或 BOOTP。它仍然使用 UDP,但使用新的端口号、新的消息格式和重新构建的选项。所有这些都意味着新的协议与 DHCPv4 或 BOOTP 并不完全兼容,尽管我相信正在进行一项方法的研究,以允许 DHCPv6 服务器与 IPv4 设备一起工作。

小贴士

关键概念 由于 DHCP 与 IP 地址和其他配置参数一起工作,从 IPv4 到 IPv6 的转换需要一个新的 DHCP 版本,通常称为DHCPv6。这个新的 DHCP 与原始 DHCP 有显著的不同,并且仍在开发中。DHCPv6 用于 IPv6 的有状态自动配置。另一种选择是无状态自动配置,这是 IPv6 的一个特性,允许客户端在不需要服务器的情况下确定其 IP 地址。

DHCPv6 也是围绕 IPv6 的寻址方法,特别是链路本地作用域的多播地址的使用(见[第二十五章](ch25.html "第二十五章。IPV6 寻址"))。这允许在客户端分配 IP 地址之前进行有效的通信。一旦客户端有了地址并知道了服务器的身份,它就可以使用单播寻址直接与服务器通信。

DHCPv6 消息交换

DHCPv6 中使用了两种基本的客户端/服务器消息交换:四消息交换两消息交换。前者用于客户端需要获取 IPv6 地址和其他参数时。这个过程与常规 DHCP 地址分配过程类似。高度简化地,它涉及以下步骤:

  1. 客户端发送一个多播请求消息来寻找 DHCPv6 服务器并请求租约。

  2. 任何能够满足客户端请求的服务器都会用一条广告消息来响应它。

  3. 客户端选择一个服务器并发送一个请求消息给它,请求确认提供的地址和其他参数。

  4. 服务器通过回复消息来响应,以最终完成这个过程。

上述四消息过程的简短变体也存在,其中客户端发送一个请求消息,并指示服务器应立即回复一个回复消息。

如果客户端已经有一个 IP 地址,无论是手动分配的还是以其他方式获得的,可以采取一个更简单的流程,类似于在常规 DHCP 中如何使用 DHCPINFORM 消息:

  1. 客户端广播一个 Information-Request(信息请求)消息。

  2. 拥有客户端配置信息的服务器发送回一个 Reply(回复)消息。

  3. 与常规 DHCP 一样,DHCPv6 客户端通过发送 Renew(续租)消息在一段时间后更新其租约。DHCPv6 也支持中继代理功能,与 DHCPv4 相同。

第三部分-4. TCP/IP 网络管理框架和协议

第六十五章

第六十六章

第六十七章

第六十八章

第六十九章

与多年前的前辈相比,现代网络和互联网更大、更快、功能更强大。随着我们扩展、加速和增强我们的网络,它们变得更加复杂,因此管理起来也更加困难。多年前,管理员可以用非常简单的工具来维持网络的运行,但如今,需要更复杂的网络管理技术来匹配我们网络的复杂性。

网络管理员工具箱中的一些最重要的工具现在都是以软件的形式存在的,而不是硬件。为了管理一个庞大、异构和复杂的互联网,我们可以使用软件应用程序来收集信息并使用互联网本身来控制设备。作为最受欢迎的互联网套件,TCP/IP 提供了这样的软件工具。其中最重要的一个是作为整体网络管理方法的一部分实现的两个协议,称为TCP/IP 互联网标准管理框架

本部分描述了 TCP/IP 互联网标准管理框架,探讨了其各个架构和协议组件以及它们如何交互。第一章提供了网络管理框架本身的概述,并为后续章节提供了介绍。第二章讨论了网络管理信息是如何结构化和组织到称为管理信息库(MIBs)的信息存储中的。第三章描述了 TCP/IP 网络管理中关键协议背后的概念和操作:简单网络管理协议(SNMP)。第四章提供了 SNMP 消息和消息格式的详细信息。最后,第五章简要介绍了远程网络监控(RMON),这是 SNMP 的一个增强功能——尽管它有时被称为协议,但实际上并不是——它为管理员提供了在 TCP/IP 互联网上更强大的管理和监控能力。

注意,虽然你可能想直接跳到 SNMP 章节,但如果你按照顺序阅读本部分的所有章节,那里的内容会更有意义。

第六十五章。TCP/IP 互联网标准管理框架概述

无标题图片

TCP/IP 网络管理功能最常与负责实现这些功能的关键协议相关联:简单网络管理协议(SNMP)。许多人听说过 SNMP,并且通常认为 SNMP 是 TCP/IP 中执行网络管理“的方式”。这在某种程度上是正确的,但实际上是一种过度简化。实际的 SNMP 协议只是称为互联网标准管理框架的更高层次网络管理策略的一部分。为了真正理解 SNMP 是如何工作的,你需要首先了解这种网络管理作为整体是如何构建的。

在本章中,我通过描述 TCP/IP 互联网标准管理框架的概念和组件来介绍 TCP/IP 网络管理。我首先概述了框架的历史,并讨论了它与 SNMP 的关系。我描述了 TCP/IP 网络管理模型和组成网络管理系统的主要组件。我总结了互联网标准管理框架的架构。然后,我描述了框架和 SNMP 的三个主要版本以及它们之间的比较。最后,我讨论了用于描述这项技术的许多标准。

TCP/IP 互联网标准管理框架和简单网络管理协议(SNMP)概述和历史

来自职业体育界的谚语说,当人们忘记棒球裁判的存在时,裁判就做得很好。在许多方面,这同样适用于网络管理员。当网络运行得如此顺畅和高效,以至于用户忘记了管理员的存在时,管理员就做得很好。因为,正如管理员所深知的那样,一旦出现问题,用户会很快记住他或她的存在。

网络管理员的主要工作之一是监控网络并确保其正常运行。关于网络上的硬件和软件的信息是正确执行此任务的关键。

当网络规模较小时,管理员可以通过简单的方式了解硬件和软件的状态,例如亲自走到一台计算机前使用它,或者使用低级链路层管理协议。在当今的大型、地理上分散且通常由许多不同底层技术组成的互联网中,这是不可能的。通常,网络上所有设备唯一共同之处在于它们都实现了特定的互联网协议套件,例如 TCP/IP。这使得互联网本身成为促进设备与网络管理员之间网络管理信息交流的逻辑方式。

SNMP 的早期发展

在互联网的早期,许多人认识到需要某种网络管理技术来支持 TCP/IP。不幸的是,最初并没有一个单一的标准。在 1980 年代,不同的工作组开发了多种不同的技术。有三个主要竞争者:由 RFC 1021 至 1024 定义的高层实体管理系统(HEMS)/高层实体管理协议(HEMP);由 RFC 1028 定义的 简单网关监控协议(SGMP);以及实际上是 OSI 协议套件一部分的 通用管理信息协议(CMIP)。

互联网工程任务组(IETF)认识到拥有一个统一的管理标准对于 TCP/IP 的重要性,并于 1988 年发布了 RFC 1052,“IAB 关于开发互联网网络管理标准的建议”。这份备忘录不是一个标准,而更多的是一个意向声明和对有关此主题的会议的记录。RFC 1052 的结论是使用 SGMP 作为新互联网标准的基础,该标准被称为 简单网络管理协议(SNMP)。这项发展将由 SNMP 工作组执行。

SNMP 的两种含义

简单网络管理协议(SNMP)名称中中间两个单词的合理性是显而易见的,但其他两个单词则稍微有些问题。单词 协议 假设 SNMP 只是一个 TCP/IP 通信协议,就像其他协议一样,例如动态主机配置协议(DHCP)和文件传输协议(FTP)。不幸的是,这个说法既是真的又是假的:名称是含糊的。

在较低级别,SNMP 确实指的是在设备之间传输网络管理信息的实际协议。这就是大多数人谈论 SNMP 时所想到的。然而,根据 SNMP 工作组的定义,TCP/IP 网络管理解决方案作为一个整体由多个不同的元素组成,这些元素按照一种架构排列。这个架构最初没有特定的名称,但现在被称为 互联网标准管理框架。奇怪的是,这个高级框架不是缩写为 ISMF,而是 被称为 SNMP,这意味着理解这个术语时上下文很重要。

注意

为了避免混淆,我经常会使用“SNMP 框架”和“SNMP 协议”这两个短语来区分这两个术语的用法

SNMP 的设计目标

在协议名称中的单词 简单 是另一个问题。即使在它的第一个版本中,它也只是相对简单。SNMP 的最新版本实际上相当复杂,有多个不同的标准定义了 SNMP 框架、SNMP 协议本身以及许多支持元素。

那为什么叫 简单 呢?好吧,正如他们所说,一切都是相对的。与更复杂的其他协议相比,SNMP 是简单的。这可以通过查看互联网标准管理框架和 SNMP 协议的整体基本目标来看到:

  • SNMP 定义了一种通用的方式,可以轻松地为任何对象定义管理信息,然后在该对象和用于简化网络管理的设备之间交换。

  • SNMP 将定义和通信管理信息的功能与应用程序分开,这些应用程序用于网络管理。

  • 实际的 SNMP 协议相当简单,只包含几个易于理解的协议操作。

  • 对于产品和的设计师和制造商来说,SNMP 的实现相对简单。

提示

关键概念 简单网络管理协议(SNMP) 定义了一套技术,允许网络管理员远程监控和管理 TCP/IP 网络设备。术语 SNMP 既指一个特定的通信协议(有时称为 SNMP 协议),也指一个整体的互联网管理框架(SNMP 框架)。

由于 SNMP 是一个 TCP/IP 应用层协议,理论上它可以在各种传输机制上运行。它最常在互联网协议(IP)上实现,但最新的版本也定义了可以允许 SNMP 信息通过其他互联网技术传输的 传输映射

SNMP 的进一步发展和 SNMP 变体的问题

第一个开发的互联网标准管理框架(在 1988 年)现在被称为 SNMP 版本 1(SNMPv1)。这个 SNMP 的初始版本得到了广泛的认可,并且可能仍然是 SNMP 最常用的版本。

从那时起,SNMP 的历史在很大程度上是一个相当混乱的标准噩梦。SNMPv1 在安全领域存在一些弱点。因此,在 SNMPv1 完成后不久,就开始了一个新的 SNMP 版本的工作。不幸的是,这项工作变成了一片泥潭,许多 SNMPv2 的变体被创建出来。经过多年的混乱,没有一个 SNMPv2 变体取得了显著的成功。

最近,已经发布了 SNMP 框架和协议的第三个版本,它增加了新功能,并将 SNMP 再次统一到一个单一的通用协议下。本章后面关于 SNMP 版本和 SNMP 标准的讨论进一步探讨了自 1988 年以来的 SNMP 历史。它们可以被视为这个历史概述的延续,因为它们有助于阐明过去十多年中 SNMP 版本背后的非常混乱的故事。

提示

相关信息 有关 SNMP 协议的更多背景信息可以在实际协议本身的概述中找到,在第六十七章概念和操作")中

TCP/IP SNMP 操作模型、组件和术语

因此,看起来 简单 网络管理协议实际上并不那么简单。SNMP 有许多版本、标准和用途,因此有很多东西要学习。我认为理解 SNMP 做什么的良好起点是查看其 操作模型。然后我们可以检查组成 TCP/IP 网络管理系统组件,并定义描述它们的术语。

SNMP 设备类型

SNMP 的总体思想是允许使用 TCP/IP 交换网络管理所需的信息。更具体地说,该协议允许网络管理员利用一种特殊的网络设备,该设备与其他网络设备交互以收集信息并修改其操作方式。在最简单的意义上,定义了两种不同的基本类型的硬件设备:

受管理节点 网络上的常规节点,已经安装了软件,以便可以使用 SNMP 进行管理。这些通常是传统的 TCP/IP 设备。它们有时也被称为 受管理设备

网络管理站 (NMS) 一个指定的网络设备,运行特殊软件以允许其管理上面提到的常规受管理节点。网络中必须存在一个或多个 NMS,因为这些设备是真正运行 SNMP 的设备。

SNMP 实体

参与使用 SNMP 进行网络管理的每个设备都运行一个通称为 SNMP 实体 的软件。SNMP 实体负责实现 SNMP 协议的所有各种功能。每个实体由两个主要软件组件组成。组成设备上的 SNMP 实体的组件取决于该设备是受管理节点还是 NMS。

受管理节点实体

受管理节点上的 SNMP 实体包括以下软件元素和结构:

SNMP 代理 一个实现 SNMP 协议的软件程序,允许受管理节点向 NMS 提供信息并接受其指令。

SNMP 管理信息库 (MIB) MIB 定义了关于节点可以收集和用于控制受管理节点的信息类型。使用 SNMP 交换的信息采用 MIB 中的对象形式。

网络管理站实体

NMS 上的 SNMP 实体包括以下内容:

SNMP 管理器 一个实现 SNMP 协议的软件程序,允许 NMS 从受管理节点收集信息并向它们发送指令。

SNMP 应用程序 一个或多个软件应用程序,允许网络管理员使用 SNMP 管理网络。

SNMP 操作模型摘要

因此,为了综合和重申所有这些内容,让我们总结一下。SNMP 由少数几个网络管理站(NMSs)组成,它们与被称为管理节点的常规 TCP/IP 设备交互。NMS 上的SNMP 管理器和管理节点上的SNMP 代理实现了 SNMP 协议,并允许网络管理信息交换。SNMP 应用程序运行在 NMS 上,为人类管理员提供接口,并允许从每个 SNMP 代理的管理信息库(MIBs)中收集信息。图 65-1 说明了 SNMP 操作模型。

一个 SNMP 管理的节点几乎可以是任何能够使用 TCP/IP 进行通信的网络设备,只要它被编程了适当的 SNMP 实体软件。SNMP 的设计目的是允许普通主机被管理,以及智能网络互连设备,如路由器、桥接器、集线器和交换机。其他设备——打印机、扫描仪、消费电子设备、专用医疗设备等等——也可以被管理,只要它们连接到 TCP/IP 互连网络。

在更大的网络中,一个 NMS 可能是一个独立的、高性能的 TCP/IP 计算机,专门用于网络管理。然而,真正使设备成为 NMS 的是软件,因此 NMS 可能不是一个独立的硬件设备。它可能充当 NMS 并同时在网络上执行其他功能。

SNMP 操作模型 此图显示了 SNMP 的简化实现,使用一个网络管理站(NMS)来维护三个管理节点。每个设备都有一个 SNMP 实体,它们通过 SNMP 消息进行通信。NMS 的 SNMP 实体由 SNMP 管理器和一个或多个 SNMP 应用程序组成。每个管理节点运行一个 SNMP 代理并维护一个管理信息库(MIB)

图 65-1. SNMP 操作模型 此图显示了 SNMP 的简化实现,使用一个网络管理站(NMS)来维护三个管理节点。每个设备都有一个 SNMP 实体,它们通过 SNMP 消息进行通信。NMS 的 SNMP 实体由 SNMP 管理器和一个或多个 SNMP 应用程序组成。每个管理节点运行一个 SNMP 代理并维护一个管理信息库(MIB)。

小贴士

关键概念 SNMP 允许网络管理员使用 网络管理站 (NMS) 控制一组受管节点。每个设备都包含一个实现该技术的 SNMP 实体。在 NMS 中,该实体由一个 SNMP 管理器 模块和一组 SNMP 应用程序组成。在受管节点中,该实体由一个 SNMP 代理和 管理信息库 (MIB) 组成。

TCP/IP 互联网标准管理框架架构和协议组件

互联网标准管理框架包括构成 TCP/IP 网络管理解决方案的所有技术。SNMP 框架由多个定义管理信息结构、存储和通过 SNMP 协议交换方式的架构组件组成。框架还描述了不同组件如何组合在一起,如何在网络设备中实现 SNMP,以及设备如何交互。

SNMP 框架组件

正如我们将在下一章中更详细地探讨的那样,互联网标准管理框架完全是 信息导向的。它包括四个主要组件(见 图 65-2):

管理信息结构 (SMI) 为了确保各种设备的互操作性,我们希望有一个一致的方式来描述使用 SNMP 管理的设备特性。在计算机科学中,数据描述语言 (DDL) 是完成这项工作的工具。SMI 是一个标准,它定义了 SNMP 中管理信息的结构、语法和特性。

管理信息库 (MIBs) 每个受管设备都包含一组用于管理的变量。这些变量代表发送到 NMS 的设备操作信息,以及/或发送到受管设备的参数以控制它。MIB 是描述特定类型设备管理特性的这些变量的完整集合。MIB 中的每个变量称为 MIB 对象,它使用 SMI 数据描述语言定义。设备可能有多个对象,对应于它包含的不同硬件和软件元素。

注意

最初,一个单独的文档定义了 SNMP 的 MIB,但这个模型不够灵活。为了更容易地定义新的 MIB 对象,现在将相关 MIB 对象组定义在单独的 RFC 标准中,称为 MIB 模块到目前为止,已经定义了超过 100 个这样的 MIB 模块*。

简单网络管理协议 (SNMP) 这实际上是 SNMP 协议本身。它定义了 SNMP 代理和 NMS 之间信息交换的方式。SNMP 协议操作 定义了各种 SNMP 消息以及它们的创建和使用方式。SNMP 传输映射 描述了如何在不同底层互联网(如 TCP/IP、IPX 等)上使用 SNMP。

安全和行政 在前三个主要架构组件的基础上,SNMP 框架增加了许多支持元素。这些元素增强了 SNMP 协议的操作,并解决了与 SNMP 实施相关的问题,包括版本转换和其他管理问题。

TCP/IP 互联网标准管理框架的组件

图 65-2. TCP/IP 互联网标准管理框架的组件

小贴士

关键概念 互联网标准管理框架(SNMP 框架)的三个主要组件是管理信息结构(SMI)、管理信息库(MIBs)以及 SNMP 协议本身。这些组件由 SNMP 安全性和管理元素支持。

SNMP 框架架构

SNMP 的创造者特意设计了框架以模块化,因为当 SNMP 最初被创建时,它被视为一个临时解决方案,直到可以从 OSI 协议套件过渡到另一个网络管理协议。模块化架构将定义性、数据和功能性(协议)元素分离,以便在不改变网络管理信息定义和描述方式的情况下替换 SNMP 协议本身。

这种向 OSI 协议的过渡从未发生,但该架构在定义整个 SNMP 范围以及在简化其实施方面仍然非常有价值。上一节讨论的每个主要组件——SMI、MIBs 和 SNMP 本身——都在不同的标准中进行了描述。SNMP 框架的模块化也允许相对独立地对这些组件进行更改,使得在 SNMP 版本之间的转换比如果有一个庞大的文档定义一切要容易得多。

TCP/IP 互联网标准管理框架和 SNMP 版本(SNMPv1、SNMPv2 变体和 SNMPv3)

在 第三章 中,我解释了专有标准、事实标准和开放标准之间的区别,并描述了开放标准的许多好处。历史充满了使用开放标准而成功的技术例子,当时竞争的标准是专有的。

TCP/IP 和互联网经常被作为一个合适的开放标准开发的典范。成千上万的 TCP/IP 标准是通过众所周知的请求评论(RFC)标准化过程开发和发布的。结果是计算历史上最成功的互联网互连协议集,被全球接受和使用。

然而,没有人是完美的,也没有任何过程是完美的。在引入 SNMP 版本 2 时出现了一些问题,导致通常平稳的协议标准化方法几乎崩溃,并出现了我们不习惯在 TCP/IP 中看到的许多不兼容的变体。这个故事是本章前面关于一般 SNMP 概述和历史的延续,并解释了许多 SNMP 标准名称和数字,以便你能理解它们。同时,讨论也生动地提醒了适当的标准发展的重要性,以及当没有就标准的演变达成普遍共识时可能产生的后果。

SNMPv1

SNMP 的第一个版本是在 1988 年初开发的,并于 1988 年 8 月以三个 RFC 标准的形式发布。这个第一个版本现在被称为SNMP 版本 1SNMPv1。三个 SNMPv1 标准提供了三个主要互联网标准管理框架组件的初始描述:SMI、MIB 和 SNMP 协议本身。然而,当时并没有实际使用互联网标准管理框架这个术语。

SNMPv1 被普遍接受并在许多网络中得到广泛部署。SNMPv1 完成了任务,并成为了 TCP/IP 网络管理的标准。它至今仍被广泛使用。它是 SNMP 版本中的“老忠实”。对初始标准进行了一些修订,随着时间的推移,定义了越来越多的 MIB 模块,但技术保持了多年不变。

与任何技术一样,SNMPv1 的用户发现了它的弱点以及改进的机会。SNMPv1 最被批评的领域之一是安全性。SNMPv1 仅使用了一个“简单”的(如 RFC 3410 所述)认证方案,采用了一个类似密码的结构,称为社区字符串

安全性问题最终成为导致 SNMP 发展出现严重问题的争议焦点。有些人认为社区字符串就足够安全,但许多人认为将更好的安全性引入 SNMP 很重要。提出了许多不同的方法来增加 SNMP 的安全性,但没有就如何实现达成普遍共识。关于原始 SNMPv1 中安全弱点的讨论具有一定的合理性,正如我在第六十七章概念和操作")中关于 SNMP 协议操作讨论中所述。

SNMPsec

第一次尝试增加安全性的措施是在 1992 年 7 月发布的三个标准中,这些标准定义了一种使用逻辑标识符称为参与者的新安全机制。这有时被称为SNMP 安全SNMPsec。这种方法比原始的 SNMPv1 更安全,但 SNMPsec 从未被广泛接受,现在被认为是历史性的。

SNMPv2

然而,基于党的安全的思想从未消失。它被用作定义 SNMP 的第一个完整修订版的基础,当时在 1993 年 4 月发布的 RFC 1441 至 1452 中发布了SNMP 版本 2(SNMPv2)。这个新版本包含了新的安全模型,并对实际的 SNMP 协议操作、SMI 标准(定义 SMI 的版本 2,SMIv2)进行了更改,并正式化了互联网标准管理框架的概念。

不幸的是,这个新标准也从未被普遍接受。有些人认为整个新版本是一个巨大的进步,但其他人对基于党的安全提出了异议,声称它太复杂。在接下来的几年里,进行了大量的辩论和讨论,试图让每个人都接受这个新版本。

SNMPv2 变体

SNMPv2 的接受从未发生。相反,不同的派生小组分道扬镳,开始着手于 SNMPv2 的变体。为了避免混淆,原始的 SNMPv2 被称为SNMPv2 经典(这个名字让人联想到某种特定的软饮料)或SNMPv2p,其中的p指的是基于党的安全。当以下内容被提出和/或开发时,事情变得非常有趣(并且令人困惑):

SNMPv1.5 当一个想法提出一个低于已标准化数字的版本号时,你可以立即判断这个想法可能是一个问题。SNMPv1.5 试图保留 SNMPv2p 中无争议的元素——对 SNMP 协议和 SMI 的增强——同时回到 SNMPv1 中的基于社区的安全。它本身从未成为标准,但成为下一个变体的基础。

基于社区的 SNMPv2(SNMPv2c) 这是对 SNMPv2p 的修改,使用社区字符串而不是基于党的安全;本质上与 SNMPv1.5 相同,但有一个听起来更官方的名字和一些更改。有趣的是,定义这个标准的 RFC 1901 仍然处于实验状态,尽管 SNMPv2c 实际上在商业上取得了一定的成功,而标准的 SNMPv2p 没有。SNMPv2c 由 RFC 1902 至 1908 的标准定义,这些标准包括其他更改,包括 SMI 的新版本(SMIv2)。

基于用户的 SNMPv2(SNMPv2u) 这是一种 SNMPv2c 的替代安全方法,它基于用户而不是社区字符串。它被认为比基于党的安全更简单,但比基于社区字符串的安全更安全。它由 RFC 1909 和 RFC 1910 定义。它也被正式认为是实验性的。

SNMPv2* 就像所有的其他变体都不够一样,一个知名的供应商决定定义另一个名为 SNMPv2* 的变体,它结合了 SNMPv2p 和 SNMPv2u 的元素。这从未正式标准化。(是的,名字中有星号。不,页脚下面没有脚注,所以不用找。是的,在名字中放星号是非常令人困惑的。不,我不知道营销人员是如何得到好钱的,他们能想出这样的名字。)

现在,想象一下,如果你是 1990 年代中期的网络管理员,面临着 SNMPv2p、SNMPv2c、SNMPv2u 和 SNMPv2*。你会选择哪一个?好吧,如果你像大多数人一样,你可能会选择上面的任何一个都不选,说,“我想我会坚持使用 SNMPv1,直到这些版本 2 的人把事情做好!”这正是发生的事情。这些变体的支持者中的一些推广了它们,但从未达成任何协议,结果是所有各种 SNMPv2 的成功都受到了限制。正如我所说,这是普遍标准化重要性的经典例证。

SNMPv3

我想象,在某个时候,每个人都意识到情况一团糟,并决定已经足够了。1996 年,开始了一种新的方法来解决悬而未决的问题,并将普遍性恢复到 SNMP。1998 年,开发了 SNMP 版本 3 (SNMPv3),它包括对 SNMP 的额外增强,并最终让所有参与者回到了同一个团队。

SNMPv3 是 SNMP 的最新版本,仍在积极修订中。SNMPv3 中的一个重要变化是更正式地处理对 SNMP 的不同安全方法——显然,这是从 SNMPv2 经验中吸取的教训。

SNMPv3 使用 SNMPv2 协议操作及其协议数据单元 (PDU) 消息格式,以及 SNMPv2 的 SMIv2 标准。SNMPv3 允许将多种不同的安全方法集成到其架构中,包括描述基于用户的安全性的标准,这些标准在 SNMPv2u 和 SNMPv2* 中定义,以及一个新的基于视图的访问控制模型。它还包括额外的工具来帮助管理 SNMP。

TCP/IP 互联网标准管理框架和 SNMP 标准

你现在已经看到,互联网标准管理框架有三个不同的版本。其中一些版本有不同的变体。框架的每个版本或变体都包含多个模块化组件。每个组件都有一个或多个定义它的文档。其中一些有多个修订版。再加上为 SNMP 和其他支持文档定义的数十个单独的 MIB,你会有什么?一大堆 TCP/IP 标准。可能定义 SNMP 各部分的 RFC 比任何其他单个 TCP/IP 协议或技术都要多。

正是因为与 SNMP 相关的版本、组件和文档如此之多,我认为保持所有标准清晰是很重要的。为此,表表 65-1 标准")至表 65-6 标准")展示了 SNMP 框架每个版本和变体的主要 SNMP 标准:SNMPv1、SNMPsec、SNMPv2p、SNMPv2c、SNMPv2u 和 SNMPv3。(SNMPv2*并未使用常规 RFC 流程进行标准化。)每个单独的 RFC 定义了框架一个版本的一个组件。

RFCs 通常的工作方式是,当发布新的标准版本,这些新版本是旧版本的直接替代品时,旧版本会被新版本废弃。在 SNMP 的情况下,由于存在许多版本和变体,这种情况有些不明确。例如,定义 SNMPv2p 的标准并未被 IETF 视为废弃 SNMPv1 的标准,但 IETF 表示 SNMPv2c 和 SNMPv2u 的标准废弃了 SNMPv2p 的标准。

为了保持所有这些内容的清晰区分,我决定分别展示每个版本或变体的标准。我仅在那些 RFC 针对相同 SNMP 版本或变体时,才列出已废弃 RFC 的 RFC 编号。例如,RFC 3410 废弃了 2570,因为它们都涉及 SNMPv3,而 3410 是 2570 的直接替代品。此外,还有一些情况下,标准名称在 RFC 编号之间略有变化;我已展示了当前名称。完整的、带超链接的 RFC 列表可以在www.rfc-editor.org/rfc-index.html找到。

表 65-1. SNMP 版本 1 (SNMPv1) 标准

已废弃 RFC 最近 RFC 最近 RFC 的日期 标准名称
1065 1155 1990 年 5 月 基于 TCP/IP 网络的网络管理信息结构和标识
1066 1156 1990 年 5 月 基于 TCP/IP 网络的网络管理信息库
1067, 1098 1157 1990 年 5 月 简单网络管理协议(SNMP)
1158 1213 1991 年 3 月 基于 TCP/IP 网络的网络管理信息库:MIB-II

表 65-2. SNMP 安全(SNMPsec)标准

已废弃 RFC 最近 RFC 最近 RFC 的日期 标准名称
1351 七月 1992 SNMP 管理模型
1352 1992 年 7 月 SNMP 安全协议
1353 1992 年 7 月 管理 SNMP 实体的对象定义

表 65-3. 基于实体的 SNMP 版本 2 (SNMPv2p) 标准

已废弃 RFC 最近 RFC 最近 RFC 的日期 标准名称
1441 1993 年 4 月 互联网标准网络管理框架第 2 版的介绍
1442 April 1993 SNMPv2 版本 2 的简单网络管理协议(SNMPv2)的管理信息结构
1443 April 1993 SNMPv2 版本 2 的简单网络管理协议(SNMPv2)的文本约定
1444 April 1993 SNMPv2 版本 2 的简单网络管理协议(SNMPv2)的符合性声明
1445 April 1993 SNMPv2 版本 2 的简单网络管理协议(SNMPv2)的行政模型
1446 April 1993 SNMPv2 版本 2 的简单网络管理协议(SNMPv2)的安全协议
1447 April 1993 SNMPv2 版本 2 的简单网络管理协议(SNMPv2)的党派 MIB
1448 April 1993 SNMPv2 版本 2 的简单网络管理协议(SNMPv2)的协议操作
1449 April 1993 SNMPv2 版本 2 的简单网络管理协议(SNMPv2)的传输映射
1450 April 1993 SNMPv2 版本 2 的简单网络管理协议(SNMPv2)的管理信息库
1451 April 1993 管理员到管理员的网络管理信息库
1452 April 1993 互联网标准网络管理框架第 1 版和第 2 版之间的共存

表 65-4. 基于社区的 SNMP 版本 2(SNMPv2c)标准 |

已废弃的 RFCs 最近 RFC 最近 RFC 的日期 标准名称
1901 January 1996 基于社区的 SNMPv2 简介
1902 January 1996 SNMPv2 版本 2 的简单网络管理协议(SNMPv2)的管理信息结构
1903 January 1996 SNMPv2 版本 2 的简单网络管理协议(SNMPv2)的文本约定
1904 January 1996 SNMPv2 版本 2 的简单网络管理协议(SNMPv2)的符合性声明
1905 January 1996 SNMPv2 版本 2 的简单网络管理协议(SNMPv2)的协议操作
1906 January 1996 SNMPv2 版本 2 的简单网络管理协议(SNMPv2)的传输映射
1907 January 1996 SNMPv2 版本 2 的简单网络管理协议(SNMPv2)的管理信息库
1908 January 1996 互联网标准网络管理框架第 1 版和第 2 版之间的共存

表 65-5. 基于用户的 SNMP 版本 2(SNMPv2u)标准 |

已废弃的 RFCs 最近 RFC 最近 RFC 的日期 标准名称
1909 February 1996 SNMPv2 的行政基础设施
1910 February 1996 SNMPv2 的用户安全模型

表 65-6. SNMP 版本 3(SNMPv3)标准 |

已废弃的 RFCs 最近 RFC 最近 RFC 的日期 标准名称
2576 March 2000 第 1 版、第 2 版和第 3 版互联网标准网络管理框架之间的共存
2578 April 1999 管理信息结构版本 2(SMIv2)
2579 1999 年 4 月 SMIv2 的文本约定
2580 1999 年 4 月 SMIv2 的符合性声明
2570 3410 2002 年 12 月 互联网标准管理框架的介绍和适用性声明
2261, 2271, 2571 3411 2002 年 12 月 描述简单网络管理协议(SNMP)管理框架的架构
2262, 2272, 2572 3412 2002 年 12 月 简单网络管理协议(SNMP)的消息处理和分发
2263, 2273, 2573 3413 2002 年 12 月 简单网络管理协议(SNMP)的应用程序
2264, 2274, 2574 3414 2002 年 12 月 简单网络管理协议(SNMPv3)的第 3 版用户安全模型(USM)
2265, 2275, 2575 3415 2002 年 12 月 简单网络管理协议(SNMP)的基于视图的访问控制模型(VACM)
3416 2002 年 12 月 简单网络管理协议(SNMP)协议操作的版本 2
3417 2002 年 12 月 简单网络管理协议(SNMP)的传输映射
3418 2002 年 12 月 简单网络管理协议(SNMP)的管理信息库(MIB)

除了这些表中列出的所有标准之外,还有数十个补充的 RFC,它们描述了 MIB 模块,并澄清了与 SNMP 相关的各种操作细节。您可以通过搜索“MIB”或“SNMP”来在线找到所有 MIB 的 RFC 列表。

第六十六章:TCP/IP 结构化管理信息(SMI)和管理信息库(MIBS)

无标题图片

互联网标准管理框架定义了三个主要组件,描述了如何在 TCP/IP 互联网中管理设备。其中之一,实际的简单网络管理协议(SNMP)相对较为知名,但它只是整体图景的一部分。SNMP 描述了 SNMP 实体之间信息交换的方式,但还有另外两个组件同样重要,因为它们描述了信息本身。

在本章中,我描述了 TCP/IP 互联网标准管理框架的两个重要支持元素:描述 SNMP 处理的信息类型的 MIB 标准,以及定义 MIB 信息的结构管理信息(SMI)标准。在检查实际的 SNMP 协议本身之前,理解这两个 SNMP 框架的部分是一个重要的初步步骤。

我首先概述了 SMI 数据描述语言以及 MIBs 的工作方式。我讨论了 MIB 对象名称层次结构和用于引用名称的符号。我还描述了 MIB 对象的工作方式,讨论了不同的对象类型和 MIB 对象组。我描述了所有 SNMP 版本中通用的 MIB 概念,并讨论了在那些 SNMP 版本中使用的特定 SMI 版本(SMIv1 和 SMIv2)。

小贴士

背景信息 如果您还没有阅读前面章节中描述的 SNMP 互联网标准管理框架,您应该在继续阅读此处之前先阅读它

TCP/IP SMI 和 MIBs 概述

真正理解 TCP/IP 网络管理的关键是理解整个互联网标准管理框架(SNMP 框架)的信息导向本质。为了理解我的意思,让我们暂时退后一步,从一般的角度考虑网络管理的问题,以及更具体地,管理网络中设备的问题。

SNMP 的信息导向设计

网络管理员需要执行两种基本类型的操作:收集有关设备的功能数据,以及向设备下达命令以改变其功能。用最简单的话说,第一类操作可以被视为读取操作,而第二类则相当于写入操作。

实现这种功能的一种经典方式是定义一个通信协议。大多数此类协议都是命令导向的——它们由一组特定的命令组成,用于执行读取和写入操作。例如,一个网络管理协议可能有一个读取命令,如“报告设备使用的小时数”,以及一个写入命令可能类似于“将此设备置于测试模式”。网络管理员通过下达适当的命令来控制设备。

命令导向的管理协议的优点在于其简单性,因为它很清楚命令的用途以及如何使用它们。它可能非常适合在某些环境中使用,但它不适合在大型、异构的 TCP/IP 互联网中工作。主要原因在于命令导向将协议与被管理的设备不可分割地联系在一起。考虑以下问题:

  • 每种设备可能都需要一组独特的命令。例如,给路由器下达的命令可能需要与给主机下达的命令不同。这可能导致协议中命令的激增,或者导致在允许适当管理不同设备类型时的不灵活性。

  • 每当一家公司创造了一种新型设备,或者为某种设备制作了一个独特的版本,网络管理协议就需要进行更改。

  • 每当某种设备的功能发生变化时,可能是由于另一种协议的变化,管理协议就需要进行更新。

  • 没有影响大量硬件,该协议本身很难进行更改。

解决以命令为导向的管理协议问题的方法是使用信息导向模型。不是定义特定的命令来查询或控制设备,而是通过设备与管理站之间要交换的信息单元来定义设备。

与读取命令和写入命令不同,我们拥有可以读取或写入的变量。以之前提到的两个例子来说明。不需要像“报告设备使用的小时数”这样的命令,设备会保留一个名为“使用的小时数”的变量,网络管理站可以将其作为众多变量之一读取,无需特定的协议命令。不需要名为“将此设备置于测试模式”的写入命令,设备有一个名为“当前模式”的变量。网络管理员可以通过更改变量的值来将设备的模式更改为测试模式。

这种差异可能看起来很微妙,但它构成了 SNMP 工作方式的每一个方面。我相信 SNMP 框架难以理解的部分原因是因为没有足够强调以“SNMP 方式”看待事物,这意味着考虑信息对象而不是命令。

小贴士

关键概念 与大多数以命令为导向的协议不同,SNMP 是信息导向的。SNMP 操作通过在管理设备中维护的称为变量的对象来实现。而不是发布命令,网络管理站通过读取变量来检查设备的状态,通过更改(写入)变量来控制设备操作。

MIB 和 MIB 对象

在这样的背景下,我们可以以新的视角看待 SNMP 框架。实际的 SNMP 协议本身,我们将在接下来的几章中对其进行考察,它只有少数几个通用的命令来完成读取和写入任务。它只处理网络管理信息在 SNMP 代理和网络管理站(NMS)之间的交换方法,这些方法在上一章中已经描述。网络管理信息实际上是 TCP/IP 网络管理的核心。

因此,SNMP 不是通过控制特定设备的命令来定义的,而是通过称为对象的管理信息变量来定义的。每个对象描述了设备的特定特性。一些对象相当通用,对 TCP/IP 网络上的任何设备都有意义;例如,描述与互联网协议(IP)本身相关的对象,如设备的 IP 地址。其他对象可能特定于某种类型的设备;例如,路由器将具有普通主机以太网网络接口卡所不具备的对象。

在 SNMP 中使用的对象集合被称为管理信息库(MIB),或MIB。(实际上,SNMP 对象通常被称为MIB 对象。)SNMP 的第一个版本,SNMPv1,有一个单一的标准定义了整个 SNMP 的 MIB。较新版本通过使用不同的MIB 模块提供了更多的灵活性,这些模块定义了特定于设备使用的硬件或软件的变量集。

提示

关键概念 管理设备中的管理数据变量被维护在一个逻辑集合中,称为管理信息库(MIB)。MIB 中的对象通常被称为MIB 对象,它们通常被收集到称为MIB 模块的集合中。

使用模块定义对象允许在定义允许管理不同类型设备的变量方面具有很大的灵活性。设备可以包含适用于其硬件和软件的所有适当的 MIB 模块。例如,如果你有一个使用以太网的设备,它将包含来自以太网 MIB 的变量。使用令牌环的设备将使用令牌环 MIB。这两个设备也会使用所有 TCP/IP 设备都使用的通用 SNMP MIB。根据需要,也可能包括其他模块。

注意

由于其名称,MIB 通常被称为数据库。严格来说,这是不准确的。MIB 是对象的描述。设备中的实际 MIB 可能实现为软件数据库,但这不是必需的

定义 MIB 对象:SMI

使用 MIB 对象可以解决网络管理协议与网络管理信息绑定的问题。然而,我们必须非常注意如何定义这些对象。再次强调,原因是 TCP/IP 允许连接的设备种类繁多。每种设备可能以不同的方式表示信息。为了确保它们能够相互通信,我们需要确保管理信息以一致的方式表示。

确保 MIB 对象普遍性的 SNMP 框架部分是管理信息结构(SMI)标准。SMI 定义了如何构建 MIB 对象和 MIB 模块的规则。在 SMI 中,MIB 对象使用基于 ISO 抽象语法表示 1(ASN.1)标准的精确定义集进行描述。

实质上,我们在 SNMP 中有三个抽象级别。实际的 SNMP 协议移动表示管理设备状态的值。MIB 定义了这些变量是什么。SMI 定义了 MIB 中的变量是如何定义的。

有两个主要的 SMI 标准。最初的,SMIv1,是第一个 SNMP 框架的一部分,SNMPv1,在 RFC 1155 中定义。它规定了 MIB 和 MIB 变量的基本规则。第二个,SMIv2,在 RFC 1442 中作为 SNMPv2p 的一部分定义,并在 RFC 2578 中进一步更新,这是 SNMPv3 的一部分。它与早期版本类似,但定义了更多的对象类型,以及 MIB 模块的结构。

这些 SMI 标准负责定义 SNMP 中的以下重要信息元素:

  • 与所有 MIB 对象相关的一般特征——描述所有 MIB 对象的标准方式

  • 可以创建的不同类型的 MIB 对象,例如整数、字符串和更复杂的数据类型

  • 为命名 MIB 对象创建一个层次结构,以便可以一致地引用它们,而不会发生名称重叠

  • 与每个 MIB 模块相关的信息

小贴士

关键概念 管理信息结构 (SMI) 标准负责定义 MIB 对象的结构、描述和组织规则。SMI 通过确保不同设备使用通用数据表示来交换所有管理信息,从而允许不同设备进行通信。

TCP/IP MIB 对象、对象特征和对象类型

如前几节所述,SNMP 框架旨在促进管理信息的交换。MIB 定义了设备的管理信息,并包含许多称为 MIB 对象 的变量,也称为 受管对象。这些对象是根据 SMI 标准中规定的规则定义的。

寻找 MIB 对象的最佳起点是检查定义它们的 SMI 规则。正如我在本章前面提到的,已经创建了两种不同的 SMI 版本:SMIv1 作为原始 SNMP 的一部分,以及 SMIv2 作为 SNMPv2 和 SNMPv3 的一部分。这两个版本在描述 MIB 对象方面相似,但 SMIv2 允许与每个对象关联更多信息。

MIB 对象特征

正如典型的协议使用字段格式来指定使用该协议的设备之间发送的消息的内容一样,SMI 使用一种格式来指定每个 MIB 对象的基本特征。其中最基本的是在 SMIv1 中定义的五个强制性特征。这些特征也用于 SMIv2,但一些名称有所更改,一些字段的可能值也有所修改。MIB 对象可能具有以下特征(参见图 66-1 此图显示了一个包含 N 个 MIB 对象的 SNMP MIB。每个对象有五个强制性特征和可变数量的可选特征。")):

对象名称 每个对象都有一个名称,用于唯一标识它。实际上,这并不完全正确。每个对象有两个名称:一个文本名称称为 对象描述符 和一个数字 对象标识符,它表示对象在 MIB 对象名称层次结构中的位置。我们将在稍后探讨这些名称及其使用方法。

语法 定义了对象的数据类型及其描述的结构。这个属性非常重要,因为它定义了对象包含的信息的数据类型。允许两种基本的数据类型类别:

  • 常规数据类型是我们日常经常处理的信息的单个片段,例如整数和字符串。在 SMIv2 中,这些被称为基本类型。SMIv1 区分原始类型,如 ASN.1 中定义的整数,以及定义类型,它们是原始类型的特殊形式,仍然是单个信息片段,但与它们的使用方式有关联的特殊含义。SMIv2 不使用这两个术语。

  • 表格数据类型是多个数据元素的集合。它们可能采取基本类型列表或基本类型表的形式。例如,可以构建一个整数表来表示一组值。在 SMIv1 中,这些被称为构造类型;在 SMIv2 中它们是概念表。它们可以使用为读取表格而设计的特殊 SNMP 机制进行访问。有关表格的更多信息,请参阅 SNMP 表遍历主题。

访问(SMIv2 中的 Max-Access) 此字段定义了 SNMP 应用程序通常使用对象的方式。在 SMIv1 中,有四个不同的可能值:只读读写只写不可访问。在 SMIv2 中,有五个值,这些值被描述为一种层次结构。SMIv2 将此特性称为Max-Access最大访问),以明确指出较高的访问级别包括较低的级别。例如,具有读取创建访问的对象也可以用于其下任何模式,如读写,但反之则不行。以下为 SMIv2 的五个访问值,按访问级别降序排列(请注意,SMIv2 中已删除只写):

  • 读取创建(对象可读、可写或创建)

  • 读写(对象可读可写)

  • 只读(对象只能读取)

  • 可通知访问(对象只能通过 SNMP 通知或 SNMP 陷阱使用)

  • 不可访问(用于特殊目的)

状态表示对象定义的有效性。在 SMIv1 中,有三个值:强制可选过时。在 SMIv2 中,前两个被合并为简单的当前,表示当前定义。保留值过时,并添加了已弃用,表示定义已过时但为兼容性而保留。

定义(SMIv2 中的描述) 对象的文本描述。

可选特性 SMIv2 添加了以下可能出现在对象定义中的可选特性:

  • Units是与对象相关的单位的文本描述。

  • 参考是对相关文档或其他与对象相关的信息的文本交叉引用。

  • Index是用于定义实际更复杂的其他对象行的值的值。

  • 增强是索引字段的替代品。

  • DefVal定义了对象的可接受默认值。

提示

关键概念 每个管理信息变量,称为 MIB 对象,与其相关联五个关键属性:其名称、语法、最大访问权限、状态和定义。它还可能具有许多可选特性。

SNMP 管理信息库 (MIB) 此图显示了包含 N 个 MIB 对象的 SNMP MIB。每个对象具有五个强制特性和一个可变数量的可选特性。

图 66-1. SNMP 管理信息库 (MIB) 此图显示了包含 N 个 MIB 对象的 SNMP MIB。每个对象具有五个强制特性和一个可变数量的可选特性。

SMI 数据类型

表 66-1 显示了 SMIv1 和 SMIv2 中支持的对象的常规数据类型。(包含 32 的名称是在 SMIv2 中使用的;它们被更改以使类型的位数明确。)表中的前五个条目是原始类型;其余的是定义类型,使用 SMIv1 术语。

表 66-1. SNMP SMI 常规数据类型

数据类型代码 描述 在 SMIv1 中? 在 SMIv2 中?
Integer/Integer32 以二进制补码表示的 32 位有符号整数,能够存储从 -2,147,483,648 到 +2,147,483,647 的值。也可以用来表示枚举类型;例如,其中 1 表示一个特定的常量,2 表示另一个,依此类推。
Octet String 一个可变长度的二进制或文本数据字符串。
空值 无。
Bits 命名位的枚举。用于允许一组位标志被当作一个单一的数据类型处理。
无符号 一个 32 位无符号整数,从 0 到 4,294,967,295。
网络地址/IP 地址 一个 IP 地址,编码为一个 4 字节八位组字符串。
Counter/Counter32 一个 32 位无符号整数,从 0 开始增加,直到 4,294,967,295,然后回绕到 0。
Gauge/Gauge32 一个 32 位无符号整数,其值可以从 0 到 4,294,967,295,可以增加或减少,就像一个仪表。与仪表相关联的最小值和最大值表示其正常范围。
TimeTicks 一个 32 位无符号整数,表示自某个任意起始日期以来的百分之一秒数。用于时间戳和计算经过时间。
Opaque 使用任意 ASN.1 语法的数据,在设备之间传递时不会被解释。如在网络文件系统 (NFS) 的 XDR 中(见 第五十八章")),术语 opaque 表示数据被当作一个黑盒处理,其内部细节无法看到。
Counter64 与 Counter32 类似但宽度为 64 位,允许从 0 到 18,446,744,073,709,551,615 的值。

除了表 66-1 中显示的类型之外,还创建了其他定义的类型,以表示特定数据类型的更具体语义。这些被称为文本约定,并在 RFC 2579 中描述了 SMIv2 的文本约定。例如,一个名为TimeStamp的类型与TimeTicks相同。然而,使用前者而不是后者来表示对象,可以使变量代表特定的时间戳值更加清晰。另一个名为TimeInterval的类型,其名称下也是一个整数,但传达了不同的解释意义。

如果这一切对你来说都很混乱,请注意,这个描述实际上是 SMI 对象定义的重大简化。查看示例 66-1,它展示了 RFC 3418 中使用 SMIv2 的一个对象定义。

示例 66-1. 示例 SNMP SMIv2 对象定义

sysLocation OBJECT-TYPE
     SYNTAX DisplayString (SIZE (0..255))
     MAX-ACCESS read-write
     STATUS current
     DESCRIPTION "The physical location of this node
      (e.g., 'telephone closet, 3rd floor'). If the location
      is unknown, the value is the zero-length string."
              ::= { system 6 }

注意,DisplayString是显示文本字符串的文本约定。最后一部分,{ system 6 }将在下一节中解释。

TCP/IP MIB 对象描述符、标识符和对象名称层次结构

在许多 MIB 对象特性中,只有一个足够有趣,以至于它真正值得单独阐述。或者也许我应该这么说,只有一个足够复杂,需要进一步的解释。这就是对象名称,它是用于 MIB 对象的更大命名系统的一部分。

每个 MIB 对象实际上有两个名称:一个对象描述符和一个对象标识符

对象描述符

对象描述符是一个传统的文本名称,它提供了一个用户友好的引用对象的手段。名称是根据对象所在的特定 MIB 对象组分配的。在先前的例子中,sysLocation是该 MIB 对象的对象描述符。我将在本章后面讨论 MIB 模块和对象组时,更详细地描述这些名称。

对象标识符

文本名称很方便,但它们通常是未结构化的。目前有超过 10,000 个不同的 MIB 对象,即使每个都有一个独特的文本名称,这样一大堆名称也无法帮助我们管理这些对象并了解它们之间的关系。为此,我们需要一种更结构化的方法来分类和命名对象。

这个问题与另一个你可能阅读过的类似问题相似:如何在互联网上分配名称的问题。最初,主机的名称是简单的、扁平的名称,但这很快变得难以管理。DNS 层次命名空间(见第五十三章。

这个相同的概念用于在 SNMP 中组织 MIB 对象。使用一个包含所有 MIB 对象的单一、通用的层次结构。它是按层次组织的,并且从最一般到最具体分为几个级别。每个对象在层次结构中都有一个特定的位置。

MIB 名称层次结构与 DNS 名称层次结构之间有一个重要的区别:MIB 名称层次结构比 DNS 的更通用。所有 MIB 对象的整个子树只是由国际标准化组织(ISO)和国际电信联盟(ITU)维护的完整、国际对象层次结构的一个分支。这个对象标识符层次结构如此通用,以至于它可以包含世界上任何技术使用的每个对象或变量的名称(以及可能的其他星球或太阳系)。

我为什么这么幽默的原因将在稍后变得明显。只需说,这个对象树非常庞大。这个树中的每个节点都由一个标签和一个整数来标识。标签用于描述目的。对象(或子树)标识符是通过从树的顶部开始,按顺序列出数字,直到节点,并用点分隔来形成的。然而,SNMP 并不像 DNS 那样反转标签的顺序。它们是从上到下,从左到右列出的。(文本标签也可以用作名称,但它们不是,因为由于树结构的深度,它们会变得非常长。)

小贴士

关键概念 SNMP MIB 对象有两个名称。第一个是一个文本对象描述符,它提供了一种以熟悉且易于人类的方式访问对象的方法。第二个是对象标识符,它由一系列整数组成,指定了对象在国际标准机构 ISO 和 ITU 维护的全局对象层次结构中的位置。

MIB 对象名称层次结构

让我们探讨 MIB 对象树的构成,更重要的是,SNMP MIB 对象是如何融入其中的。图 66-2 下的网纹框表示。每个子树都包含自己的子结构(其中一些在此处展示),定义了数千个不同的 MIB 对象。左侧的分支用于通用 MIB 对象,右侧的分支用于私有对象。还定义了一个单独的层次结构用于 SNMPv2。")展示了全局对象名称层次结构和 SNMP MIB 层次结构。

全局对象名称层次结构和 SNMP MIB 层次结构 此图显示了 ISO 和 CCITT(ITU)定义的对象名称层次结构,以允许所有类型的对象被普遍表示。通过跟随阴影框,可以找到通向与 SNMP 相关的树分支的路径。用于 SNMP 的两个子树以互联网(1)下的网纹框表示。每个子树都包含自己的子结构(其中一些在此处展示),定义了数千个不同的 MIB 对象。左侧的分支用于通用 MIB 对象,右侧的分支用于私有对象。还定义了一个单独的层次结构用于 SNMPv2。

图 66-2. 全局对象名称层次结构和 SNMP MIB 层次结构 此图显示了 ISO 和 CCITT(ITU)定义的对象名称层次结构,以允许所有类型的对象被普遍表示。通过跟随阴影框,可以找到通向与 SNMP 相关的树分支的路径。用于 SNMP 的两个子树以互联网(1)下的网纹框表示。每个子树都包含自己的子结构(其中一些在此处展示),定义了数千个不同的 MIB 对象。左侧的分支用于通用 MIB 对象,右侧的分支用于私有对象。还定义了一个单独的层次结构用于 SNMPv2。

树的根没有标签,有三个子节点:

  • ccitt(0)用于 ITU(以前称为 CCITT)标准(也可见为 itu(0))。

  • iso(1)用于 ISO 标准。

  • joint-iso-ccitt(2)用于联合标准(也可见为 joint-iso-itu(2))。

在 iso(1)节点之后,在接下来的几个级别上,我们看到以下内容:

  • 在 iso(1)中,ISO 为其他组织创建了一个子树,称为 org(3)。

  • 在 org(3)中,有一个子树用于美国国防部(如您可能记得,它是互联网的发起者):dod(6)。

  • 在 dod(6)中,有一个名为 internet(1)的子树。

我们在 SNMP 中使用的一切都位于这个非常具体的子树中:1.3.6.1,如果使用文本标签,将是 iso.org.dod.internet。在这个命名空间的部分中,有六个子树:

  • directory(1) 是为 ISO 保留的,供将来使用。

  • mgmt(2) 是 MIB 对象的主要子树。这是 1.3.6.1.2。它包含一个名为 mib(1) 的子树,即 1.3.6.1.2.1。当创建 MIB-II 时,使用相同的数字 1.3.6.1.2.1 创建了一个名为 mib-2(1) 的子树。

  • experimental(3) 包含用于正在开发中的标准的对象。这是 1.3.6.1.3。

  • private(4) 用于由私有公司定义的对象。此节点 1.3.6.1.4 有一个名为 enterprise(1) 的子树,即 1.3.6.1.4.1。

  • security(5) 是为安全用途保留的。

  • snmpV2(6) 定义了用于 SNMP 版本 2 的对象。

那么,这一切的底线是什么?好吧,基本上所有 MIB 模块对象都在整体对象树的两个分支之一中命名:

常规 MIB 对象 这些位于 mgmt(2) 下 mib(1) 子树中:1.3.6.1.2.1。

私有 MIB 对象 这些位于 private(4) 下 enterprise(1) 子树中,即 1.3.6.1.4.1。例如,在 enterprise(1) 中有一个 cisco(9) 的条目用于 Cisco Systems。因此,所有 Cisco 特定的 MIB 对象都以 1.3.6.1.4.1.9 开头。

清楚如泥,对吧?他们为什么不直接创建一个单独的层次结构,其中“mib”位于顶部而不是六层深?你怎么敢提出这样的建议?你不理解全球标准的重要性吗?

一切玩笑话 aside,这个名称层次结构处理起来有点繁琐(好吧,不止一点点),但它确实允许我们以合理的方式组织 MIB 对象。在 1.3.6.1.2.1 子树中,我们找到了大多数在 SNMP 中使用的常规 MIB 对象。1.3.6.1.2.1 中的每个子树都对应于一个常规 SNMP 对象组或特定的 MIB 模块。

提示

关键概念 所有 MIB 对象都具有适合于全局对象层次结构两个分支的对象标识符。常规 MIB 对象(非厂商特定)位于 mgmt(2) 子树下的 mib(1) 下:1.3.6.1.2.1。私有对象,可以由硬件厂商创建以帮助管理该厂商的产品,位于 private(4) 子树下的 enterprise(1) 下,即 1.3.6.1.4.1。

MIB 对象标识符的递归定义

通过将对象名称放在对象的开头,给对象赋予一个文本对象描述符,如示例 66-1 所示,但数字对象标识符的定义,再次,更为复杂。这是通过仅定义对象在其特定子树中的数字来完成的。这意味着对象标识符是递归定义的(一个基于另一个)并且没有为每个对象明确声明。这在语法上是精确的,但使得一眼就能看出任何特定对象的数字变得困难。

再次考虑本章前面提到的 示例 66-1。对于此对象,sysLocation 是对象描述符,{ system 6 } 是对象标识符。这意味着它是节点系统中的第 6 个对象,而节点系统被定义为 { mib-2 1 }——它是 mib-2 子树中的第一个节点。由于 mib-2 是 1.3.6.1.2.1,如前所述,这意味着 system 是 1.3.6.1.2.1.1,而 sysLocation 是 1.3.6.1.2.1.1.6。

TCP/IP MIB 模块和对象组

MIB 包含了使用 SNMP 框架描述设备特性的 MIB 对象集合。当 SNMP 首次创建时,MIB 中的对象并不多。此外,它们大多是通用的对象,可以相当普遍地应用于整个 TCP/IP 设备。实际上,MIB 中的大多数对象都与 TCP/IP 协议的操作相关,例如 IP、传输控制协议 (TCP) 和互联网控制消息协议 (ICMP)。

因此,最初,一个单独的文档定义了“MIB”的“定义”。这些文档中的第一个是 RFC 1066,它是初始 SNMPv1 规范的一部分。随后在 RFC 1156 中进行了修订。在 RFC 1158 中,定义了 MIB 的第二个版本,即 MIB II,它与第一个版本基本相同,但做了一些修改。

将 MIB 对象组织成对象组

在早期的 MIB 标准中定义的 MIB 对象数量相对较少。然而,仍然有几十个,从一开始就认识到随着时间的推移将会有更多。为了以逻辑方式组织对象,它们被安排成 对象组。这些组的作用是分离对象,并定义它们在整体对象名称层次结构中应如何分配对象标识符。

每个组都与以下三个重要信息相关联:

组名 这是一个用作本章前面所述的对象识别树中的文本标签的名称(参见 图 66-2 下的阴影框。每个都包含自己的子结构(其中一些在此处展示),定义了数千个不同的 MIB 对象。左侧的分支用于通用 MIB 对象,右侧的用于私有对象。还定义了一个单独的层次结构用于 SNMPv2。")). 这些对象都位于 iso.org.dod.internet.mgmt.mib 子树中。例如,系统组将是 iso.org.dod.internet.mgmt.mib.system。

组编号 此数字对应于用于从对象名称树中创建数字标识符的组名称。例如,系统组有数字 1,因此该组的对象标识符是 1.3.6.1.2.1.1。该组中的所有对象都将位于该树之下;例如,sysUpTime是 1.3.6.1.2.1.1.3。

组代码 这是一个文本标签,可能与组名称相同,也可能是缩写。它用于在制作对象描述符(对象的文本名称)时作为前缀。例如,对于系统组,代码是sys,因此该组中的对象是sysUpTime

表 66-2 展示了在 RFC 1158 中定义的八个通用 SNMP 组,包括它们的代码、名称和数字。

表 66-2. SNMP 通用 MIB 对象组

Group Name Group Code Group Number Full Group Identifier Description
system sys 1 1.3.6.1.2.1.1 与所有或大多数设备相关的通用对象。例如,设备的通用描述是该组中的一个对象,对象的标识符也是如此。后来的 MIB 版本大大增加了该组中的变量数量。
interfaces if 2 1.3.6.1.2.1.2 与该设备与互联网之间的 IP 接口相关的对象。(回想一下,普通主机通常有一个接口,而路由器有两个或更多。)
at (地址转换) at 3 1.3.6.1.2.1.3 用于 IP 地址转换的对象。(不再使用。)
ip ip 4 1.3.6.1.2.1.4 与设备整体 IP 层相关的对象(与if组中的接口特定信息相对)。
icmp icmp 5 1.3.6.1.2.1.5 与 ICMP 操作相关的对象。
tcp tcp 6 1.3.6.1.2.1.6 与 TCP 操作相关的对象。
udp udp 7 1.3.6.1.2.1.7 与用户数据报协议(UDP)的操作相关的对象。
egp egp 8 1.3.6.1.2.1.8 与外部网关协议(EGP)的操作相关的对象。
cmot cmot 9 1.3.6.1.2.1.9 与在 TCP 上运行 CMIP 协议相关的对象(历史性的,不再使用)。
transmission trans 10 1.3.6.1.2.1.10 与系统上每个接口使用的特定信息传输方法相关的对象。
snmp snmp 11 1.3.6.1.2.1.11 用于管理 SNMP 本身的对象。

表中的所有组都是相当通用的,除了关于 EGP 的那个组外,几乎适用于所有使用 SNMP 的 TCP/IP 系统。(提到 EGP,这是一种现在被认为是过时的路由协议,显示了该列表的年龄。)前五个组和最后一个组对所有系统都是强制性的。其他组仅由使用指示协议或功能的设备使用。

MIB 模块

在表 66-2 中列出的对象组中最引人注目的是那些未被包含的组。对于大多数其他 TCP/IP 协议,没有相应的组,也没有为特定硬件类型可能需要的变量设置任何组。例如,大多数主机都会内置一个使用层 2 协议(如以太网或令牌环)的网络卡。管理者如何检查或控制该硬件的操作?对于像开放最短路径优先(OSPF)或边界网关协议(BGP)这样的新路由协议呢?又或者是与运行域名系统(DNS)相关的对象呢?

持续更新 MIB 文档是不切实际的。相反,在 SNMPv2 中,MIB 从单一文档变为一系列文档。保留了将对象分组的基本组织结构,但不再是所有组都在同一标准中,而是被划分为多个标准。还定义了一种创建描述特定技术特定对象组的新方法的方法。这些模块的列表由互联网数字分配机构(IANA)维护,该机构维护所有这些类型的数字。当前 SNMP MIB 模块的列表可以在www.iana.org/assignments/smi-numbers找到。

使用 MIB 模块将 SNMP 支持集成到设备中,有点像去购物。将所有设备共有的基本组纳入每个设备中,然后根据需要使用其他模块/组。表 66-3 提供了一些 MIB 模块的简要选择,以给您一个关于现有内容的想法,同时也显示了模块的组号(在 1.3.6.1.2.1 名称子树中)。表中列出的模块远不止这些。

表 66-3. 一些常见的 SNMP MIB 模块

MIB 模块名称 组号 描述
ospf 14 与 OSPF 相关的对象
bgp 15 与 BGP 相关的对象
rmon 16 作为远程网络监控(RMON)一部分使用的对象
snmpDot3 RptrMgt 22 与 IEEE 802.3(以太网)中继器相关的对象
rip-2 23 作为路由信息协议(RIP)第 2 版一部分使用的对象
snmpDot3 MauMgt 26 与 IEEE 802.3(以太网)介质附件单元相关的对象
etherMIB 35 类似以太网的通用对象
mipMIB 44 移动 IP 对象
ipMIB 48 用于 SNMPv2 的 IP 对象
tcpMIB 49 用于 SNMPv2 的 TCP 对象
udpMIB 50 用于 SNMPv2 的 UDP 对象

表 66-3 中的最后三个条目可能有些令人困惑,因为如表 66-2 所示,已经存在 IP、TCP 和 UDP 的组。这些条目的原因在于,在 SNMPv2 中创建 MIB 对象的新模块化架构时,SNMPv1 中作为单一文档一部分的各个协议的对象定义被分离出来,以保持一致性并允许它们独立更新。实际上,基本的 SNMPv2 和 SNMPv3 MIB 文档现在只定义了systemsnmp组中的对象。

提示

关键概念 在 SNMP 早期历史中创建的 MIB 对象被组织成位于 mib(1)子树中的MIB 对象组,从标识符代码 1.3.6.1.2.1 开始。随着 TCP/IP 的普及,集中定义所有 MIB 对象变得不切实际,因此特定于不同硬件设备的对象集现在在MIB 模块中指定。

MIB 模块格式

MIB 模块的格式在 SMI 标准版本 2(SMIv2)中描述。本文件指定了如何定义模块,类似于对象本身的定义:通过列出每个模块描述必须包含的一组特征。模块字段如下:

模块名称 模块的名称。记住,从语法上讲,模块实际上是对象,因此像常规对象一样,它们有一个文本对象描述符(如tcpMIB)和一个对象标识符(在tcpMIB的情况下,数字 50)。

最后更新 模块最后修订的日期和时间。

组织 管理模块开发的组织的名称。

联系方式 此模块负责人的姓名、地址、电话号码和电子邮件地址。

描述 模块的描述。

修订和修订描述 每次模块的修订都会有一条修订记录,以显示其历史。每条记录都与一个描述相关联。

在模块本身的定义之后,模块中的对象将被描述。例如,请参阅 RFC 2012,它定义了 SNMPv2 TCP MIB。

第六十七章。TCP/IP 简单网络管理协议(SNMP)概念和操作

无标题图片

TCP/IP 网络的总体网络管理解决方案是互联网标准管理框架。在前两章中,我们整体地审视了该框架,并讨论了定义 TCP/IP 设备之间传输的管理信息的两个组件。SNMP 框架的第三大组成部分是实际的简单网络管理协议(SNMP),它负责在设备之间移动管理信息。

协议的核心由一组协议操作组成,这些操作允许在 SNMP 代理和管理器之间交换管理信息。在之前考察了 SNMP 的一般性和管理信息库(MIB)对象之后,我们现在可以深入探讨如何使用 SNMP 实际进行管理信息的通信。

在本章中,我详细描述了 SNMP 协议执行的操作。我首先简要概述和介绍协议的历史。然后提供 SNMP 如何操作的一般描述以及设备用于通信的两种基本方法。我还描述了 SNMP 的消息类和 SNMP 中执行的基本操作:基本请求/响应、表遍历、对象修改和通知。最后,我讨论了 SNMP 的安全问题,并总结了每个 SNMP 版本中的安全方法。

注意

SNMP 中协议操作的数量和类型在 SNMPv1 和 SNMPv2 之间发生了变化。SNMPv2 中定义的操作已延续到最新的版本 SNMPv3。大部分讨论都集中在最新的实现 SNMPv3 上,并指出它与原始的、仍然广泛使用的 SNMPv1 之间的差异

SNMP 协议概述

如前几章所述,SNMP 框架通常被描述为信息导向的。在 SNMP 框架的设计中,做出了一项特定决策,将 SNMP 代理和 SNMP 管理器之间传递的管理信息与用于携带该信息的协议解耦。这对整个技术提供了许多好处,其中最重要的是灵活性和模块化。

在这个模型中,管理协议的操作不是通过向设备发送特定命令来检查其状态或更改其操作方式来定义的。相反,协议是通过称为对象的管理信息变量来定义的,以及一个允许网络管理员检查或更改这些对象的通信协议。我在前一章中详细描述了这一概念。

MIB 和管理信息结构(SMI)规定了如何创建和描述 MIB 对象。这些 MIB 对象描述了可以从设备读取或写入设备的信息类型。最后一部分是负责这些读取和写入操作的协议本身。这就是 SNMP 本身,我给它起了一个有些冗余的名字SNMP 协议,以区分它和 SNMP 框架。

将协议与其携带的管理信息分离的结果是,协议本身的复杂性显著降低。SNMP 协议不需要定义数十个甚至数百个特定网络管理功能的操作,它只需要处理 SNMP 代理和管理员之间 MIB 对象信息的传输。SNMP 协议本身并不关注这些对象中有什么;它只是关注移动它们。在某种程度上,SNMP 协议是 SNMP 中唯一真正简单的部分!

SNMPv1 的早期开发

SNMP 协议的历史可以追溯到 SNMP 框架的前身,即简单网关监控协议(SGMP),该协议于 1987 年在 RFC 1028 中定义。SGMP 被设计为一个临时解决方案,用于在探索更大问题期间进行网络管理,正如我在第六十五章中解释的那样。然而,这个标准中可以找到许多现代 SNMP 协议背后的基本设计概念。

SGMP 标准通过仅用 SGMP 描述互联网网关(路由器)上存储的变量的检索或更改来描述 SNMP 使用的基本设计模型。该标准还概述了今天 SNMP 操作仍基于的少量协议操作。

SNMP 框架的第一个版本,SNMPv1,在 RFC 1067 中包含了 SNMP 协议的第一个正式定义(后来由 RFC 1098 和 RFC 1157 修订)。这个标准精炼了 SGMP 文档中给出的协议操作。它使 SNMP 协议的操作适合于整个 SNMP 框架,与正式定义的 MIB 对象一起工作。

SNMPv2 和将 SNMP 分为协议操作和传输映射

当创建 SNMPv2 时,描述 SNMP 协议的单个文件被拆分为两个标准,以使协议更加模块化,并更好地反映互联网中使用的层:

协议操作这对文档中的第一份文件描述了通过特定的 SNMP 消息类型在 SNMP 设备之间移动 MIB 对象的实际机制。在 SNMPv3 中,它是 RFC 3416,“简单网络管理协议(SNMP)的协议操作版本 2。”当人们谈论“SNMP 标准”时,通常指的是这份文档。

传输映射第二份文件详细说明了如何将第一标准中描述的 SNMP 协议操作传输到各种不同的协议套件中。通过使用正确的映射,SNMP 操作可以使用除了互联网协议(IP)之外的下层技术执行。这个标准在 SNMPv3 中由 RFC 3417,“简单网络管理协议(SNMP)的传输映射”表示。

小贴士

关键概念 实际上用于在网络管理站(NMS)和受管理设备之间通信管理信息的机制被称为简单网络管理协议,可能被称为SNMP 协议以区分它和 SNMP 框架。它由一系列协议操作组成,描述了设备之间实际发生的消息交换,以及一组传输映射,定义了这些消息如何在各种类型的互联网中传输。互联网协议(IP)是用于 SNMP 的最常见的传输映射。

我将在本章后面关于 SNMP 消息描述的更详细部分中讨论传输映射,但鉴于 IP/用户数据报协议(UDP)方法是最常见的传输机制,关于这一方面的 SNMP 协议并没有太多可说的。

SNMP 通信方法

为了使 SNMP 在使网络管理成为可能方面有用,它必须允许网络管理员使用网络管理站(NMS)轻松检查受管理设备中 SNMP 代理的状态。在数据通信中,有两种一般技术用于一个实体需要了解另一个实体的活动或事件的情况:

轮询驱动通信 这个术语指的是一种一般技术,即想要信息的人去请求信息——就像有人可能进行政治民意调查一样。在 SNMP 中,NMS 会轮询 SNMP 代理以获取信息。轮询的一个常见现实生活例子是常规邮件服务使用的模型;每天你都会去检查邮箱,看看是否有邮件。

中断驱动通信 这个术语指的是拥有信息而其他设备需要知道的信息设备决定主动发送信息。在 SNMP 中,这指的是 SNMP 代理在没有被要求的情况下向 NMS 发送信息。这是那个最著名的中断者——电话使用的模型。

哪种通信方式更好?通常的答案在这里适用:两者在普遍意义上都不是更好或更差,这就是为什么两种选择都存在。由于这些模型的明显优势和劣势,SNMP 协议被设计为同时使用两者。轮询用于定期收集常规信息,例如检查设备的利用率统计和一般状态。中断以陷阱的形式使用,网络管理员可以在受管理设备上设置这些陷阱。这些陷阱会在发生重要事件时使 SNMP 代理中断 NMS。

小贴士

关键概念 SNMP 使用两种基本方法来交换管理信息。常规通信使用轮询驱动技术,其中网络管理站(NMS)从受管理节点请求信息。也支持中断驱动模型。在需要立即通知 NMS 发生情况的情况下,受管理设备可以发送一个陷阱消息,而不必等待 NMS 的请求。

本章我们将重点关注 SNMP 协议操作:使用哪些消息,它们的结构如何,以及它们是如何交换的。在检查这些消息时,我们将看到 SNMP 中信息交换的两种主要方式——通过轮询和通过中断——并了解 SNMP 协议如何与 MIB 对象协同工作。

SNMP 协议操作

SNMP 协议中实际的信息通信是通过类似于大多数其他协议的方式进行的,即通过交换 SNMP 消息。这些消息有时被称为协议数据单元PDUs。你可能在其他协议中听说过这个术语,它是 OSI 参考模型中数据封装的正式定义的一部分,如第五章中所述。消息当然是由协议使用的数据单元。SNMP 消息的名称末尾都有-PDU来标识它们。

有些人认为协议数据单元类似于军事使用长形、金属头、手动操作、加速固定装置来指代锤子。不过,公平地说,严格来说,在 SNMP 中,PDU 和消息并不完全相同。PDU 是 SNMP 封装的更高层数据,如 OSI 模型所述。SNMP 消息格式是一个包装器,它封装了一个 PDU 以及头部字段,正如我在下一章“SNMP 消息”中描述的那样。然而,消息的目的就是发送 PDU,所以两者足够接近,术语有时可以互换使用。

SNMP PDU 类别

SNMPv1 最初定义了六个 PDUs。PDUs 的数量得到了扩展,在 SNMPv2 和 SNMPv3 中对它们的名称和使用进行了某些更改。当前的 SNMP 框架将 PDUs 分类到不同的类别中。这些类别描述了每种消息类型的功能以及它们执行任务时使用的通信类型(轮询与中断)。

小贴士

关键概念 SNMP 消息由一组围绕称为协议数据单元PDU的数据元素的字段组成。在某些情况下,术语消息和 PDU 可以互换使用,尽管技术上它们并不相同。SNMP PDUs 根据其功能被安排成类别

表 67-1 类别") 列出了主要的 SNMPv2/SNMPv3 PDU 类别,描述了它们,并显示了在 SNMPv2/SNMPv3 中每个类别包含哪些 PDU。这些类别在 SNMPv1 中没有使用,但为了清晰起见,我也展示了哪些 SNMPv1 消息在概念上属于这些类别。

表 67-1. SNMP PDU (消息) 类别

SNMPv3 PDU 类 描述 SNMPv1 PDUs SNMPv2/SNMPv3 PDUs
读取 使用轮询机制从受管理设备读取管理信息的消息。 GetRequest-PDU, GetNextRequest-PDU GetRequest-PDU, GetNextRequest-PDU, GetBulkRequest-PDU
写入 改变受管理设备上的管理信息以影响设备操作的消息。 SetRequest-PDU SetRequest-PDU
响应 对先前请求的响应消息。 GetResponse-PDU Response-PDU
通知 设备用于向 SNMP 管理器发送类似中断的通知的消息。 Trap-PDU Trapv2-PDU, InformRequest-PDU

GetBulkRequest-PDU 和 InformRequest-PDU 消息是 SNMPv2/v3 中的新消息。GetResponse-PDU 消息被重命名为 Response-PDU(因为它是一个响应,而不是获取任何东西的消息),新的 Trapv2-PDU 替换了 Trap-PDU。

当前 SNMP 框架定义了三个其他特殊类别,对我们来说不太重要,因为它们没有定义积极使用的消息,但我应该提到以示完整。内部类别包含一个称为 Report-PDU 的特殊消息,用于内部 SNMP 通信。SNMP 标准还提供了两个类别,称为已确认和未确认,用于根据消息是否被确认来对 表 67-1 类别") 中的消息进行分类。Report-PDU、Trapv2-PDU 和 Response-PDU 消息被认为是未确认的,其余的是已确认的。

现在我们将探讨四个主要类别中的主要消息类型是如何使用的。请注意,在一般术语中,SNMP 中的所有协议交换都是用一种 SNMP 实体向另一个实体发送消息来描述的。最常见的是,发送请求的实体是 SNMP 管理器,而响应的是 SNMP 代理,除了陷阱,陷阱是由代理发送的。为了更清晰,我尽量在可能的情况下使用更具体的术语(管理器代理),而不是仅仅 实体

使用 GetRequest 和 (Get)Response 消息进行基本请求/响应信息轮询

我们对 SNMP 协议操作进行详细研究的明显起点是信息交换的最简单类型。这将是一个简单的轮询操作,用于读取一个或多个管理信息变量,由一个 SNMP 实体(通常是 SNMP 管理器)请求或读取另一个实体(通常是在受管理设备上的 SNMP 代理)的信息。SNMP 通过一个简单、两个消息的请求/响应协议交换来实现这一点,类似于在许多 TCP/IP 协议中找到的请求/回复过程。

此信息请求过程通常从应用程序的用户想要检查设备的状态或查看有关它的信息开始。正如我们所见,所有这些信息都以 MIB 对象的形式存储在设备上。因此,通信的形式是请求特定的 MIB 对象,并从包含这些对象值的设备获得回复。以简化的形式,该过程中的步骤如下(参见图 67-1)):

  1. SNMP 管理器创建 GetRequest-PDU 根据应用程序和用户所需的信息,NMS 上的 SNMP 软件创建一个 GetRequest-PDU 消息。它包含应用程序想要检索的 MIB 对象名称。

  2. SNMP 管理器发送 GetRequest-PDU SNMP 管理器将 PDU 发送到被轮询的设备。

  3. SNMP 代理接收并处理 GetRequest-PDU SNMP 代理接收并处理请求。它查看消息中包含的 MIB 对象名称列表,并检查它们是否有效(代理实际实现的那些)。它查找每个正确指定的变量的值。

  4. SNMP 代理创建响应-PDU 代理创建一个响应-PDU 以发送回 SNMP 管理器。此消息包含请求的 MIB 对象值以及/或错误代码,以指示请求中可能出现的任何问题,例如无效的对象名称。

  5. SNMP 代理发送响应-PDU 代理将响应发送回 SNMP 管理器。

  6. SNMP 管理器处理响应-PDU 管理器处理从代理接收到的响应-PDU 中的信息。

SNMP 信息轮询过程 基本的 SNMP 信息轮询过程涉及一个简单的交换,即由 SNMP 管理器发送的 GetRequest-PDU 和由 SNMP 代理返回的 Response-PDU。

图 67-1. SNMP 信息轮询过程 基本的 SNMP 信息轮询过程涉及一个简单的交换,即由 SNMP 管理器发送的 GetRequest-PDU 和由 SNMP 代理返回的 Response-PDU。

小贴士

关键概念 SNMP 中最基本的通信类型是信息轮询,它允许 NMS 通过简单的请求/回复消息交换从受管理节点读取一个或多个 MIB 对象。

在 SNMPv1 中,响应-PDU 消息被称为 GetResponse-PDU。据推测,这个名字是基于它是 get 操作的响应而选择的,以使 GetRequest-PDU 和 GetResponse-PDU 的名称在某种程度上对称。问题是这个名字令人困惑,有两个原因。首先,它听起来好像 PDU 的目的是“获取响应”。其次,GetResponse-PDU 也被定义为除 get 操作之外的操作的响应消息,包括 SetRequest-PDU 的回复消息。将 GetResponse 消息发送作为 SetRequest 消息的回复令人不安。新的名字更通用,避免了这些问题。

使用 GetNextRequest 和 GetBulkRequest 消息进行表格遍历

GetRequest-PDU 消息由应用程序用于请求 SNMP 受管理对象的 MIB 中常规、单个变量的值。然而,正如我在第六十六章中提到的,SMI 还允许 MIB 包含表格数据

MIB 表格是设备存储和组织一组相关数据项的有用方式。试图将这些项目仅作为常规对象的集合来结构化将远非理想。例如,一个设备可能有多个 IP 地址。定义一个名为 ipAddr1 的 MIB 对象,另一个名为 ipAddr2,以此类推来存储 IP 地址信息将是不高效的。相反,在原始 SNMPv1 MIB 中定义了一个名为 ipAddrTable 的对象,它指定了一个包含一个或多个名为 ipAddrEntry 条目的表格。每个条目包含设备一个接口的 IP 地址和子网掩码。

SNMPv1 使用 GetNextRequest 进行表格遍历

需要有一个方法让 SNMP 管理器从设备中读取这些表格的内容。这可以通过使用常规的 GetRequest-PDU 消息来完成,通过依次指定表中的每个条目。然而,这种方法有些粗糙,并且留下了一个问题:SNMP 管理器可能不知道表中有多少条目,因此也不知道应该请求多少条目。

在 SNMPv1 中,通过创建一个名为 GetNextRequest-PDU 的新消息类型来解决表格遍历问题。你可以将其视为常规 GetRequest-PDU 的一个亲戚。GetNextRequest-PDU 包含一个表格变量的名称以及表中的一个特定条目。接收 GetNextRequest-PDU 的设备使用这个信息来查找表中的下一个值,并在 GetResponse-PDU 消息中返回它。

实际的协议交换与上一节中描述的类似:SNMP 管理员发送请求,SNMP 代理返回回复。区别在于,SNMP 代理不是返回指定变量的值,而是返回表中下一个变量的值。然后,这个值用作下一个请求的值,依此类推,直到达到表中的最后一个条目。一旦发生这种情况,并且发送包含此最后一个条目的 GetNextRequest-PDU,响应设备通过返回 MIB 对象来指示这一点,该对象在 MIB 的实现中概念上位于表格之后。这向 SNMP 管理员表明表格已被完全遍历。

小贴士

关键概念 SNMP GetNextRequest-PDU 消息允许 NMS 请求 MIB 中的连续变量序列。这通常用于允许更轻松地检索表格数据,而无需为表中的每个变量单独指定。

使用 GetBulkRequest 进行 SNMPv2/v3 表遍历

GetNextRequest-PDU 消息是功能性的,但尽管它比使用常规 GetRequest-PDU 消息更优雅,但它并不更高效——表中的每个条目仍然必须逐个请求。这意味着检索表中的信息需要很长时间,并且由于必须发送的大量请求和回复,还会产生大量流量。

为了使表格遍历更容易,并更保守地使用网络资源,SNMPv2 引入了一种新的消息类型,称为 GetBulkRequest-PDU。您可能可以从名称中推测出这个想法。与指定要获取或获取下一个特定 MIB 对象不同,GetBulkRequest-PDU 允许 SNMP 管理员发送一个请求,该请求在 Response-PDU 消息中返回表中的多个条目。

GetBulkRequest-PDU 被设计为允许在单个请求中检索常规变量和表格。PDU 包含一个对象列表,就像在 GetRequest-PDU 或 GetNextRequest-PDU 中一样。列表按顺序组织,常规对象首先出现,表格对象随后。请求中包含两个特殊参数:

非重复器 指定要检索的非重复常规对象的数量。这是对象列表开头的常规对象数量。

最大重复次数 指定要读取剩余表格对象的迭代次数或条目数。

例如,假设一个 SNMP 管理员想要请求四个常规变量和表中的三个条目。GetNextRequest-PDU 将包含五个 MIB 对象规范,其中表在最后。非重复器字段将被设置为 4,最大重复次数字段设置为 3。

小贴士

关键概念 为了提高表遍历的效率,SNMPv2 引入了 GetBulkRequest-PDU 消息,允许 NMS 通过向受管理节点发送单个请求来从表中请求一系列 MIB 对象。

在开发 SNMPv2 和 SNMPv3 时,保留了使用 GetRequest-PDU 和 GetNextRequest-PDU 从 SNMPv1 遍历表的原始方法。然而,引入了更高效的 GetBulkRequest-PDU 意味着 GetNextRequest-PDU 的重要性不如 SNMPv1 中那么重要。然而,请注意,使用 GetBulkRequest-PDU 确实要求请求实体知道要请求多少条记录。因此,如果不知道条目数量,可能需要进行一些尝试和错误,或者多次请求才能获取整个表。

使用 SetRequest 消息进行对象修改

GetRequest-PDU、GetNextRequest-PDU 和 GetBulkRequest-PDU 消息是 SNMP 读类 PDUs 的三个成员—they are used to let an SNMP manager read MIB objects from an SNMP agent. The opposite function is represented by the SNMP Write class, which contains a single member: the SNMP SetRequest-PDU message.

使用此 PDU 的方法相当明显;其中三个 Get PDUs 之一指定了一个要检索其值的变量,而 SetRequest-PDU 消息包含网络管理员要修改其值的变量的规范。请记住,SNMP 不包含允许网络管理员控制受管理设备的特定命令。这是控制方法,通过设置影响受管理设备操作变量的方式来实现。

集合过程是获取过程的补集,使用相同的基本思想,但在对象值如何传输以及如何处理它们方面进行了反转。该过程遵循以下步骤(参见图 67-2):

  1. SNMP 管理器创建 SetRequest-PDU 根据用户通过 SNMP 应用程序指定的信息更改,NMS 上的 SNMP 软件创建一个 SetRequest-PDU 消息。它包含一组 MIB 对象名称以及它们要设置的值。

  2. SNMP 管理器发送 SetRequest-PDU SNMP 管理器将 PDU 发送到被控制的设备。

  3. SNMP 代理接收并处理 SetRequest-PDU SNMP 代理接收并处理设置请求。它检查请求中的每个对象以及对象要设置到的值,并确定是否应该或不应执行该请求。

  4. SNMP 代理进行更改并创建响应-PDU 假设请求中的信息是正确的(并且任何安全措施都已满足),SNMP 代理会更改其内部变量。代理创建一个响应-PDU 发送回 SNMP 管理器,要么指示请求成功,要么包含错误代码以指示在处理过程中发现的任何请求问题。

  5. SNMP 代理发送响应-PDU 代理将响应发送回 SNMP 管理器。

  6. SNMP 管理器处理响应-PDU 管理器处理响应-PDU 中的信息,以查看设置的成果。

SNMP 对象修改过程 设置 MIB 对象值的通信过程与读取一个非常相似。主要区别在于对象值是从 SNMP 管理器发送到 SNMP 代理,通过 SetRequest-PDU 消息携带。

图 67-2. SNMP 对象修改过程 设置 MIB 对象值的通信过程与读取一个非常相似。主要区别在于对象值是从 SNMP 管理器发送到 SNMP 代理,通过 SetRequest-PDU 消息携带。

显然,要求设备更改变量的值比仅仅要求设备读取值是一个更重要的请求。因此,受管理的设备必须非常仔细地分析和验证请求中的信息,以确保请求有效。执行的检查包括以下内容:

  • 验证要更改的对象的名称

  • 验证对象是否允许修改(基于它们的访问或最大访问对象特性,如第六十六章所述第六十六章。管理信息(SMI)和 MIB(MIB)的 TCP/IP 结构)

  • 检查请求中包含的值,以确保其类型和大小对于要更改的对象是有效的

这也是一般协议安全问题变得更加重要的地方,我将在本章末尾讨论。

小贴士

关键概念 SNMP NMS 通过更改设备上的 MIB 对象来控制受管理设备的操作。这是通过使用 SetRequest-PDU 消息完成的,该消息指定要修改的对象及其值。

使用陷阱和 InformRequest 消息进行信息通知

在本章的早期,我介绍了在 SNMP 设备之间传递信息的基本两种方法:使用轮询或中断。本节迄今为止我们检查的所有消息类型和交换都是轮询驱动的。它们包括 SNMP 管理器发出特定请求,导致采取行动,并由 SNMP 代理生成响应。

投票对于需要定期收集的常规信息交换是理想的。例如,定期的获取请求可以用来验证设备的设置,检查一段时间内的错误计数,或检查其运行时间或使用统计信息。显然,投票是执行设置操作的唯一真正方法,其中数据被更改。

但是,对于需要快速传达的重要信息,投票并不适用。原因是,由投票驱动的通信总是由信息的接收者:SNMP 管理员来发起的。如果管理设备上发生了管理员没有预料到的重要事件,除非管理员特意请求查看已更改的变量,否则管理员不会得知这一情况。这意味着重要的变量需要由 SNMP 管理员持续检查,这非常高效。

在现实世界中,使用投票来实现需要发送关键信息的场景,就像是你所在城镇的紧急响应服务每小时给每个人打电话,以了解他们是否需要救护车或消防车。同样,在 SNMP 中,需要一个机制让 SNMP 代理启动信息的通信。这种能力最初是通过包含 Trap-PDU 消息类型成为 SNMPv1 协议的一部分。

在计算机科学中,陷阱 简单来说就是设备持续监控的一组条件。如果发生适当的条件,陷阱就会被触发,导致采取某种行动。在 SNMP 中,陷阱被编程到 SNMP 代理中,当它们被触发时,会向 SNMP 管理员发送 SNMP 陷阱-PDU 消息,通知其事件的发生。SNMPv1 规范中陷阱的例子包括在通信链路故障、设备重启或认证问题发生时触发的陷阱。

使用 SNMP 陷阱和 Trapv2 消息

在陷阱的情况下,通信非常简单。SNMP 代理发送陷阱,因此认为 SNMP 管理员已经了解发生了什么。这就是全部。这些是未确认的消息,不会向 SNMP 代理发送回复。陷阱的触发可能会使网络管理员采取对发送陷阱的设备进行后续行动。

某个 MIB 的设计者必须确定为特定对象组创建哪些陷阱。实现必须指定触发陷阱的条件,以及当这种情况发生时,将发送 Trap-PDU 消息的目的地。在 SNMPv2 中,陷阱通知消息以 Trapv2-PDU 消息的形式保留。

使用 SNMPv2 InformRequest 消息

SNMPv2 还包含第二种通知消息类型:InformRequest-PDU 消息。这种类型的消息与陷阱不同,但它与陷阱有两个相关的原因:这两种消息类型都用于在不由接收方启动过程的情况下通信信息,并且这两种消息有时会一起使用。

InformRequest-PDU 的目的实际上是为了促进 NMS 之间的信息交流。一个 NMS 上的 SNMP 管理器可以选择通过向另一个 SNMP 管理器发送 InformRequest-PDU 来通知它一些信息。接收的管理器随后会向发送 InformRequest-PDU 的管理器回复一个 Response-PDU,确认已收到通知信息。

这种消息通常被用来在发生陷阱时传播消息。假设一个设备发生电源故障,导致一个 Trapv2-PDU 被发送到 NMS 1。网络管理员可能希望设置 NMS 1,使得接收到特定的陷阱时,陷阱中的信息会被转发到另一个 NMS。InformRequest-PDU 将被用来将信息从 NMS 1 传输到,比如说,NMS 2。

小贴士

关键概念 SNMP 管理的设备可以通过发送 Trap-PDU 或 Trapv2-PDU 消息来通知 NMS 一个重要事件。网络管理员确定在什么情况下应该发送这些消息之一。SNMPv2 增加了 InformRequest-PDU 消息的这种能力,它可以用来在管理站之间传播关于事件的信息。

SNMP 协议的安全问题和解决方法

在我对第六十五章中各种 SNMP 版本的描述中,我可能对那些在 1990 年代从事 SNMP 工作的人有些苛刻。许多 SNMP 版本 2 变体的泛滥确实是不幸的,这在 TCP/IP 的世界中并不常见。然而,现在我们已经看到了 SNMP 所做的工作,对协议中安全性的需求似乎很明确。考虑到这一点,以及初始 SNMPv1 协议中非常低的安全级别,对安全问题的冲突在一定程度上是可以理解的。

在 SNMP 中需要安全性的原因很明显,因为正在通信的 MIB 对象包含有关网络设备的临界信息。我们不希望任何人都能窥探我们的网络,以找出我们的 IP 地址、我们的机器运行了多长时间、我们的链路是否已断开,或者几乎所有其他信息。当涉及到使用 SetRequest-PDU 进行的对象写操作时,担忧会更大,因为我们绝对不希望陌生人能够通过发出虚假命令来控制或干扰我们的管理设备,以更改控制设备操作的 MIB 对象!

SNMPv1 安全问题的困扰

不幸的是,SNMPv1 中集成的安全性极为有限。它实际上只是一种政策和一种简单技术的形式。

SNMP 的创建是基于这样的观念,即协议中使用的 MIB 对象将会相对 脆弱。这意味着这些对象被设计成,在使用过程中出现任何问题只会造成最小损害。SNMP 设计者的政策是,通常应该读取的 MIB 对象不应包含关键信息,而应该写入的对象不应控制关键功能。

因此,一个只读的 MIB 对象,其中包含机器的描述,是可以的,但包含管理密码的就不是。同样,一个可读写 MIB 对象,控制计算机何时重新启动是可以接受的,但告诉对象重新格式化其硬盘的肯定不行!

由一组特定的 NMS 管理的 SNMP 网络中的所有设备都被认为是处于一个 社区 中。社区成员之间发送的每个 SNMPv1 消息都通过消息头中的一个 社区字符串 来标识。这个字符串就像一个简单的密码。任何收到错误字符串的消息都将被接收者拒绝。

这些安全特性总比没有好,但也不多。使用脆弱对象相当于一种政策,即不要将未锁门的汽车停在便利店前,钥匙留在点火开关上——这基本上是在说,“不要惹麻烦。”这是明智的,但不是完整的解决方案。

社区字符串可以防止明显的篡改,如未经授权的消息。然而,这些字符串以明文形式发送,很容易被发现并被用来破坏社区。因此,这就像停车时锁上车门——它可以防止偶然的窃贼,但不能防止专业人士。

当然,对于一些人来说,停车时不开车,锁上车门就足够提供安全保障,SNMPv1 的安全对于一些 SNMP 用户来说也足够了。但在新的、更大的互联网中,尤其是在跨越较大距离或使用公共运营商的情况下,SNMPv1 无法胜任这项任务。这就是为什么 SNMPv2 出现了那么多有趣的事情。

SNMPv2/v3 安全方法

在 SNMPv2 变体的演变过程中,最终创建了 SNMPv3,在此期间,为了提高 SNMPv1 的安全性,创建了几个新的安全模型:

基于党的安全模型 基于党的安全是原始 SNMPv2 标准的模型,现在称为 SNMPv2p。定义了一个名为 party 的逻辑实体,用于指定特定的认证协议和隐私(加密)协议的通信。这些信息用于验证特定请求的真实性,并确保发送者和接收者就如何加密和解密数据达成一致。

基于用户的访问控制模型 (USM) USM 是在 SNMPv2u 变体中开发的,并在 SNMPv2* (SNMPv2 星号) 中使用。它最终被纳入 SNMPv3。这里的想法是摆脱将安全性与机器绑定在一起,而是使用更传统的基于机器用户访问权限的安全机制。可以使用各种身份验证和加密协议来确保尊重访问权限并保护消息隐私。该方法依赖于时间戳、时钟同步和其他技术来防止某些类型的攻击。

基于视图的访问控制模型 (VACM) VACM 是 SNMPv3 的一部分,它定义了一种方法,可以在设备上的对象访问上实现更精细的控制。一个 视图 指定了一组特定的 MIB 对象,这些对象可以在特定上下文中由特定组访问。通过控制这些视图,管理员可以管理谁可以访问哪些信息。

基于实体的安全机制在 SNMPv2p 中几乎已经消失。USM 和 VACM 是 SNMPv3 的一部分,为需要它们的人提供了增强的安全性。再次值得注意的是,有多少网络继续使用 SNMPv1,无论其安全问题如何。

SNMPv3 在重新定义 SNMP 架构以无缝支持多个安全模型方面又迈出了另一个重要的安全相关步骤。这使得不同的实现可以选择最适合它们的安全模型。USM 是 SNMPv3 的默认模型。

第六十八章。SNMP 协议消息和消息格式

无标题图片

正如我们在上一章中广泛看到的那样,管理信息的通信是通过交换包含 协议数据单元 (PDUs) 的简单网络管理协议 (SNMP) 消息来完成的。像大多数 TCP/IP 协议的消息一样,这些 PDU 被设计为使用特定的字段格式,并按照特定的协议规则创建、寻址和传输。SNMP 消息包括控制协议操作的字段,并以管理信息库 (MIB) 对象的形式携带管理信息负载。

在本章中,我描述了在 SNMP 协议中如何实现消息的细节。我首先从与消息生成、寻址和传输相关的一般问题开始讨论,并描述了在必要时如何处理消息的重传。我讨论了在 SNMP 消息中定义字段的方式,并描述了它们的通用格式,解释了整体消息与其包含的 PDU 之间的区别。然后,我检查了所有重要 SNMP 版本中使用的消息格式,展示了每种消息类型的结构以及使用的字段。

SNMP 协议消息生成

SNMP 中的消息生成与大多数其他协议使用的典型 TCP/IP 客户端/服务器模型略有不同。在 SNMP 中实际上并没有真正的客户端和服务器,因为管理信息可以从任何设备获取;它是分布式的。大多数的消息交换使用一对匹配的请求和回复消息。网络管理系统(NMS)通常在这些交换中充当客户端,向 SNMP 代理发送特定的获取或设置请求,而 SNMP 代理则扮演包含信息的服务器角色。然而,SNMP 代理通常不被视为传统意义上的服务器。

SNMP 陷阱与消息生成的正常请求/回复模型完全不同。当陷阱被触发时,SNMP 代理会主动向其上的 NMS 发送陷阱消息,而不是作为对请求的响应。由于陷阱消息是不确认的,因此没有回复。然而,请注意,SNMP 版本 2 和 3(SNMPv2 和 SNMPv3)的 InformRequest-PDU 消息(将在本章后面讨论)是确认的,因此会向生成它的 NMS 发送响应消息。

SNMP 传输映射

一旦生成消息,它就会使用位于应用层之下的协议层进行发送。正如你在上一章中关于 SNMP 协议概述中看到的,当前的 SNMP 标准集将协议操作和 PDUs 的描述与实际发送它们的方法分开。

从版本 2 开始,SNMP 定义了几个 传输映射,这些映射描述了 SNMP PDUs 如何通过各种互联网协议套件发送,包括 TCP/IP、OSI、IPX/SPX(Novell)和 AppleTalk。SNMP 消息的许多具体细节取决于特定实现中使用的传输映射。SNMP 主要用于 TCP/IP 互联网,因此我们在这里的兴趣点在于 TCP/IP,所以接下来的讨论将涉及在互联网协议(IP)上使用 SNMP 时的传输问题。

SNMP 的标准 IP 传输映射要求使用用户数据报协议(UDP)进行传输。这一决定可以追溯到 SNMPv1 的最初实现(在存在明确的传输映射之前)。UDP 很可能被选择,因为它对于 SNMP 使用的简单请求/回复消息方案来说更有效率。许多传输控制协议(TCP)的特性被认为是不必要的,并增加了 SNMP 设计者想要避免的开销。虽然可以将 TCP 用于携带 SNMP,定义为不同的传输映射,但我相信这实际上并没有这样做。

为 SNMP 保留了两个著名的 UDP 端口号。第一个是端口 161,这是通用 SNMP 号码。所有设置为监听 SNMP 请求的设备——包括代理和管理员——都在端口 161 上监听。每个设备接收发送的任何消息,并回复给客户端,即发出请求的 SNMP 实体,它使用一个临时端口号来识别请求进程。第二个 UDP 端口号是 162,它为 SNMP 陷阱保留。有两个号码可以保持常规消息和陷阱的分离。通常,只有 NMS 会在端口 162 上监听,因为代理不是陷阱的接收者。

使用 UDP 可以使 SNMP 信息通信更加流畅,因为不需要建立 TCP 连接,并且消息头更短,处理时间略有减少。但是,使用 UDP 引入了一些 SNMP 实现必须关注的问题,包括消息大小和丢失的消息。

UDP 消息大小问题

第一个问题就是消息长度。SNMP PDUs 可以携带许多 MIB 对象,这意味着它们可能相当大。然而,UDP 在可以携带的消息大小上有限制(而 TCP 则没有)。标准规定 SNMP 实体必须接受至少 484 字节大小的消息。它们还建议 SNMP 实现能够接受更大的消息,最多 1,472 字节,这相当于可以封装在以太网帧中的最大消息大小(1,500 字节,允许 IP 头 20 字节和 UDP 头 8 字节)。

在 SNMPv2 和 SNMPv3 中使用 GetBulkRequest-PDU 消息类型需要特别注意,因为它允许单个请求在响应中发送多个 MIB 对象。必须谨慎选择最大重复次数参数,以防止 SNMP 代理尝试发送一个过大而无法适应的消息。

丢失传输问题

UDP 的第二个问题是,我们为了其效率和简洁性所付出的代价:缺乏传输功能。UDP 不保证数据交付或处理重传,这意味着请求或回复理论上可能在传输过程中丢失。只有最初发送请求的设备才能知道传输过程中是否存在问题。它发送请求,如果没有收到回复,它知道请求或响应已经丢失。这把重传的责任放在了发送请求消息的设备上。

向 SNMP 代理发送请求的 NMS 通常使用计时器来跟踪自发送请求以来经过的时间。如果在一定时间间隔内没有收到响应,请求将再次发送。由于 SNMP 的工作方式,请求意外地被接收多次通常不会引起任何问题(这是一个称为幂等性的特性)。NMS 确实需要采用算法来确保它不会生成过多的重传并阻塞网络(尤其是由于拥塞可能首先导致其消息丢失)。

由于陷阱是不确认的,因此陷阱 PDU 的预期接收者无法知道它是否没有到达,发送者也无法知道。这只是协议的一个弱点;TCP/IP(及其底层网络)的整体可靠性确保这些消息很少丢失。

小贴士

关键概念 SNMP 设计时使用了一个单独定义的协议操作集和传输映射集,因此它可以跨越许多不同的互连网络技术。这些传输机制中最常见的是 TCP/IP,其中 SNMP 利用在 IP 上运行的 UDP,以其实效和简单的通信。UDP 缺乏可靠性特性意味着请求必须由发送它们的设备跟踪,如果没有收到回复,则必须重新发送。UDP 消息大小的限制限制了任何 SNMP PDU 中可以发送的信息量。

SNMP 通用消息格式

为了结构化其消息以便传输,SNMP 使用特殊的字段格式,就像大多数协议一样。然而,SNMP 有趣的地方在于,其标准并没有像大多数 TCP/IP 标准那样使用简单的字段列表来描述 SNMP 消息格式。相反,SNMP 消息使用与描述 MIB 对象相同的描述性数据语言(抽象语法表示 1ASN.1)来定义。

这是因为 SNMP 消息实现了各种 SNMP 协议操作,最终目标是允许 MIB 对象在 SNMP 实体之间传递。这些 MIB 对象成为要发送的消息中的字段。SNMP 消息中携带的 MIB 对象使用在结构化管理信息(SMI)标准中描述的 ASN.1 进行定义。因此,使用相同的语法来定义 SNMP 消息及其所有字段是有意义的。

由于所有 SNMP 字段都像 MIB 对象一样定义,它们具有某些特性。具体来说,每个字段都有一个名称,其内容使用标准 SMI 数据类型之一进行描述。因此,与每个字段只有名称和长度的常规消息格式不同,SNMP 消息格式字段有一个名称和一个语法,例如整数、字节字符串或 IP 地址。字段的语法定义了其长度以及其格式和用法。

正如常规消息格式使用整数来表示特定值(例如,DNS 消息头中的数值操作码字段,它指示 DNS 消息类型),在 SNMP 中也可以使用枚举整数类型来完成。一个例子是错误状态字段,其中一系列整数值代表不同的错误条件。

决定使用 ASN.1 定义 SNMP 消息,使得消息格式描述与格式中对象的描述保持一致,这是很不错的。不幸的是,这意味着字段格式很难从标准中确定,因为它们没有在同一个地方描述。相反,整体消息格式被定义为一系列组件,这些组件可能包含在其他地方定义的子组件,依此类推。实际上,完整的消息格式甚至没有在一个标准中定义;部分内容分散在几个标准中。因此,你无法在一个地方看到整个消息格式。好吧,我应该说我如果使用标准的话,你无法做到这一点,但如果你在这里查看,你就可以做到。

为了让您更容易理解,我已经将这些分散的语法描述转换成了我在本书其他部分使用的相同表格字段格式。我将从这里开始描述用于 SNMP 消息的一般格式,并在本章的剩余部分探讨每个 SNMP 版本中使用的特定格式。

SNMP 消息和 PDU 的区别

要理解 SNMP 消息,首先掌握 SNMP 消息和 SNMP PDU 之间的区别非常重要。我们在查看 SNMP 协议操作时看到,这两个术语经常被互换使用。这是因为每个消息都携带一个 PDU,而 PDU 是消息中最重要的部分。

然而,严格来说,SNMP PDU 和 SNMP 消息并不完全相同。PDU 是在 SNMP 实体之间实际传递的信息。它包含在 SNMP 消息中,并带有多个头字段,这些字段用于携带标识和安全信息。因此,从概念上讲,SNMP 消息格式可以被认为有两个主要部分:

消息头 包含用于控制消息处理方式的字段,包括用于实现 SNMP 安全性的字段。

消息体(PDU) 包含消息的主要部分。在这种情况下,消息体就是正在传输的 PDU。

整个 SNMP 消息有时被称为 PDU 的包装器,因为它封装了 PDU,并在其前面添加了额外的字段。PDU 与整个消息格式的区别最初是 SNMPv1 中的一个形式,但在后续版本中变得非常重要。原因是它允许用于基本协议操作的字段(位于 PDU 中)与用于实现安全特性的字段保持分离。在 SNMPv2 中,安全性的实现确实变得非常重要,因此这种灵活性非常重要。

通用 PDU 格式

每个 PDU 中的字段取决于 PDU 类型,但可以分为以下通用子结构:

PDU 控制字段 描述 PDU 并从 SNMP 的一个实体向另一个实体传递信息的一组字段。

PDU 变量绑定 PDU 中 MIB 对象的描述集合。每个对象都描述为名称到值的绑定

每个 PDU 都将遵循以下通用结构,如图图 68-1 所示,只是在控制字段的数量和变量绑定以及它们的使用方式上有所不同。理论上,每个 PDU 可以使用一组不同的控制字段具有不同的消息格式,但在实践中,大多数特定 SNMP 版本的 PDU 使用相同的控制字段(尽管有一些例外)。

SNMP 通用消息格式

图 68-1. SNMP 通用消息格式

每个变量绑定描述一个 MIB 对象。绑定由一对子字段组成,一个指定对象的标准 SNMP 对象标识符表示法中的名称,另一个指定其值,格式化以匹配对象的 SMI 语法。例如,如果对象是整型,则值字段将宽四字节,并包含一个数值整数。表 68-1 描述了每个 PDU 变量绑定的子字段格式。

表 68-1. SNMP 变量绑定格式

子字段名称 语法 大小(字节) 描述
对象名称 整数序列 变量 MIB 对象的数值对象标识符,指定为整数序列。例如,对象sysLocation具有对象标识符 1.3.6.1.2.1.1.6,因此它将使用 ASN.1 指定为 1 3 6 1 2 1 1 6。
对象值 变量 变量 在任何类型的 get 请求中,此子字段是一个占位符;它使用适当的语法结构化对象,但没有值(因为 get 请求是请求该值!)在 set 请求(SetRequest-PDU)或携带请求数据的回复消息(GetResponse-PDU 或 Response-PDU)中,对象的值放置在这里。

提示

关键概念 SNMP 消息的通用格式由一个 消息标题 和一个 消息体 组成。消息体也称为 协议数据单元PDU,包含一组 PDU 控制字段 和多个 变量绑定。每个变量绑定描述一个 MIB 对象,并包括对象的名称和值。

SNMP 版本 1 (SNMPv1) 消息格式

SNMP 通用消息格式最初用于定义原始 SNMP 协议(SNMPv1)中消息的格式。这个 SNMP 的第一个版本可能因其相对于后续版本的相对简单性而最为人所知。这反映在其消息格式上,该格式相当直接。

SNMPv1 通用消息格式

SNMPv1 中的通用消息格式是一个由一个小标题和一个封装的 PDU 组成的包装器。在 SNMPv1 中,不需要很多标题字段,因为 SNMPv1 中的基于社区的网络安全方法非常原始。SNMPv1 消息的整体格式在 表 68-2 通用消息格式") 中描述,并在 图 68-2 中展示。

表 68-2. SNMP 版本 1 (SNMPv1) 通用消息格式

字段名称 语法 大小(字节) 描述
版本 整数 4 版本号:描述此消息的 SNMP 版本号;用于确保版本之间的兼容性。对于 SNMPv1,此值实际上是 0,而不是 1。
Community 八位字节串 可变 社区字符串:标识发送者和接收者所在的 SNMP 社区。这用于实现前一章中描述的简单 SNMP 基于社区的安全机制。
PDU Variable 协议数据单元:作为消息体的通信 PDU。

SNMPv1 通用消息格式

图 68-2. SNMPv1 通用消息格式

SNMPv1 PDU 格式

SNMPv1 中的所有 PDU 都具有相同的格式,只有一个例外:Trap-PDU。PDU 中每个字段的精确语义取决于特定的消息。例如,ErrorStatus 字段只在回复中有意义,而不是请求中,并且对象值在请求和回复中的使用方式也不同。

表 68-3 展示了大多数 SNMPv1 PDU 的通用格式:GetRequest-PDU、GetNextRequest-PDU、SetRequest-PDU 和 GetResponse-PDU。

表 68-3. SNMPv1 常见 PDU 格式

字段名称 语法 大小(字节) 描述
PDU 类型 整数(枚举) 4 PDU 类型:表示 PDU 类型的整数值:0 = GetRequest-PDU 1 = GetNextRequest-PDU 2 = GetNextRequest-PDU 3 = SetRequest-PDU
请求 ID 整数 4 请求标识符:用于匹配请求和响应的数字。由发送请求的设备生成,并由响应的 SNMP 实体复制到 GetResponse-PDU 的此字段中。
错误状态 整数(枚举) 4 错误状态:在 GetResponse--PDU 中使用的整数值,用于告知请求的 SNMP 实体其请求的结果。零值表示没有发生错误;其他值表示发生了什么类型的错误,如 表 68-4 中列出。
错误索引 整数 4 错误索引:当错误状态非零时,此字段包含一个指针,指定哪个对象生成了错误。在请求中始终为零。
变量绑定 变量 变量 变量绑定:一组标识 PDU 中 MIB 对象的名称/值对,在 SetRequest-PDU 或 GetResponse-PDU 的情况下,包含它们的值。有关这些绑定的更多信息,请参阅本章前面关于通用 SNMP PDU 格式的讨论。

表 68-4. SNMPv1 错误状态字段值

错误状态值 错误代码 描述
0 noError 没有发生错误。此代码也用于所有请求 PDU,因为它们没有错误状态要报告。
1 tooBig GetResponse-PDU 的大小将太大而无法传输。
2 noSuchName 请求的对象名称未找到。
3 badValue 请求中的某个值与请求接收者对对象的结构不符。例如,请求中的对象指定了错误的长度或类型。
4 readOnly 尝试设置一个具有表示只读访问值的变量。
5 genErr 发生了前四种特定类型之外的错误。

SNMPv1 常见 PDU 格式

图 68-3. SNMPv1 常见 PDU 格式

表 68-5 描述了 SNMPv1 Trap-PDU 的特殊格式,并在 图 68-4 中进行了说明。

表 68-5. SNMPv1 Trap-PDU 格式

字段名称 语法 大小(字节) 描述
PDU 类型 整数(枚举) 4 PDU 类型:指示 PDU 类型的整数值,对于 Trap-PDU 消息为 4。
企业 整数序列 变量 企业:表示生成陷阱的对象类型的对象标识符。
代理地址 网络地址 4 代理地址:生成陷阱的 SNMP 代理的 IP 地址。这在较低层级的 IP 头部中也有,但将其包含在 SNMP 消息格式中可以更容易地在 SNMP 中进行陷阱记录。此外,在多宿主主机的情况下,这指定了首选地址。
通用陷阱 整数(枚举) 4 通用陷阱代码:指定预定义的几种通用陷阱类型之一的代码值。
特定陷阱 整数 4 特定陷阱代码:指示特定实现陷阱类型的代码值。
时间戳 TimeTicks 4 时间戳:自发送此消息的 SNMP 实体上次初始化或重新初始化以来经过的时间。用于为记录目的对陷阱进行时间戳。
变量绑定 变量 变量绑定:一组标识 PDU 中 MIB 对象的名称/值对。关于这些绑定的更多信息,请参阅本章前面关于通用 SNMP PDU 格式的讨论。

SNMPv1 陷阱-PDU 格式

图 68-4. SNMPv1 陷阱-PDU 格式

SNMP 版本 2(SNMPv2)消息格式

在 SNMPv1 使用了几年后,人们注意到了它的一些问题,并确定了改进的领域。这导致了原始 SNMPv2 的开发,其目的是在许多领域增强 SNMPv1,包括 MIB 对象定义、协议操作和安全。最后一个领域,安全,导致了我在第六十五章中描述的 SNMPv2 版本变种的激增。

由于存在几个不同的 SNMPv2 版本,因此也有几个 SNMPv2 的消息格式。这很令人困惑,但如果没有 SNMP 消息模块化特性的帮助,情况会更糟。SNMPv2 中的协议操作从 SNMPv1 更改,这需要修改 SNMPv2 PDU 的格式。然而,所有 SNMPv2 变体中的协议操作都是相同的。SNMPv2 变体之间的差异在于安全实现方面。因此,结果是所有 SNMPv2 类型的 PDU 格式都是相同的,而每个变体的整体消息格式都不同。(这就是为什么 PDU 和消息之间的区别不仅仅是一个学术问题!)

在 SNMPv2 的分歧期间,定义了四种变体:原始 SNMPv2(SNMPv2p)、基于社区的 SNMPv2(SNMPv2c)、基于用户的 SNMPv2(SNMPv2u)和 SNMPv2 星号(SNMPv2*)。其中,前三种在 SNMP RFC 标准集中进行了记录,如第六十五章中所述;第四种没有。每个变体的整体消息格式结构在讨论该变体的管理或安全标准中进行了讨论,该标准引用了共享的 SNMPv2 标准 PDU 格式(RFC 1905)。

SNMP 版本 2 (SNMPv2p) 消息格式

基于实体的安全模型相当复杂,但本版本的基本消息通过定义一个 管理通信 来描述,该通信描述了源和目的实体,并引用了通信的 上下文。整体消息格式在 RFC 1445 中详细描述。此信息在 表 68-6 通用消息格式") 中总结,并在 图 68-5 中以图形方式展示。

表 68-6. SNMP 版本 2 (SNMPv2p) 通用消息格式

字段名称 语法 大小(字节) 描述
版本 整数 4 版本号:描述此消息的 SNMP 版本号;用于确保版本之间的兼容性。对于 SNMPv2p,此值为 2。
目的实体 整数序列 变量 目的实体:一个对象标识符,指定消息的预期接收者实体。
源实体 整数序列 变量 源实体:一个对象标识符,指定消息的发送者实体。
上下文 整数序列 变量 上下文:定义一组 MIB 对象资源,该资源可由特定实体访问。
PDU 变量 PDU:消息的协议数据单元。

SNMPv2p 通用消息格式

图 68-5. SNMPv2p 通用消息格式

基于社区的 SNMP 版本 2 (SNMPv2c) 消息格式

SNMPv2 的基于社区的版本旨在保留 SNMPv2p 引入的新协议增强功能,但回归到简单的 SNMPv1 安全模型。因此,SNMPv2c 的定义文档 RFC 1901 指定其整体消息格式与 SNMPv1 相同,除了版本号已更改。这显示在 表 68-7 通用消息格式") 中,并在 图 68-6 中展示。

表 68-7. 基于社区的 SNMP 版本 2 (SNMPv2c) 通用消息格式

字段名称 语法 大小(字节) 描述
版本 整数 4 版本号:描述此消息的 SNMP 版本号;用于确保版本之间的兼容性。对于 SNMPv2c,此值为 1。
社区 字节串 变量 社区字符串:标识发送者和接收者所在的 SNMP 社区。
PDU 变量 协议数据单元:作为消息主体的 PDU。

SNMPv2c 通用消息格式

图 68-6. SNMPv2c 通用消息格式

基于用户的 SNMP 版本 2(SNMPv2u)消息格式

在 SNMPv2c 标准化时,基于用户的 SNMPv2 版本被定义为可选的安全模型。RFC 1910 定义了基于用户的安全模型和表 68-8 通用消息格式")中描述的消息格式,并在图 68-7 中说明。

表 68-8. 基于用户的 SNMP 版本 2(SNMPv2u)通用消息格式

字段名称 语法 大小(字节) 描述
版本 整数 4 版本号:描述此消息的 SNMP 版本号;用于确保版本之间的兼容性。对于 SNMPv2u,此值为 2。注意,这与 SNMPv2p 使用的值相同。
参数 字节串 可变 参数:用于实现基于用户的安全模型的一串参数,这些参数在表 68-9 中简要描述。
PDU 可变 协议数据单元:作为消息主体的正在通信的 PDU。这可能以加密或未加密的形式存在。

SNMPv2u 通用消息格式

图 68-7. SNMPv2u 通用消息格式

表 68-9. SNMPv2u 参数字段子字段

子字段名称 大小(字节) 描述
模型 1 模型号:设置为 1 以标识基于用户的模型。
QoS 1 服务质量:指示是否使用了认证和/或隐私(加密),以及是否允许生成报告-PDU。
代理 ID 12 代理标识符:发送消息的代理的标识符。用于防止重放攻击和其他某些类型的安全攻击。
代理启动次数 4 代理启动次数:自设置代理 ID 以来代理已启动或重启的次数;用于防止某些安全攻击。
代理时间 4 代理自上次启动以来的时间:自上次启动以来此代理的秒数。再次用于防止重放和其他安全攻击。
最大大小 2 最大消息大小:发送此消息的发送者可以接收的消息的最大大小。
用户长度 1 用户长度:下面用户名字段的长度。
用户名 可变(1 到 16) 用户名:发送消息的用户名。
认证长度 1 认证摘要长度:认证摘要字段长度。
认证摘要 可变(0 到 255) 认证摘要:用于验证此消息的身份和真实性的认证值,当使用认证时。
上下文选择器 变量(0 到 40) 上下文选择器:一个字符串,与代理 ID 结合使用,以指定包含此消息引用的管理信息的特定上下文。

SNMPv2 PDU 格式

SNMPv2 中协议数据单元的格式在 RFC 1905 中描述,它与 SNMPv1 的格式相似。SNMPv2 中所有 PDUs 的格式相同,除了 GetBulkRequest-PDU 消息。(奇怪的是,这包括 Trapv2-PDU 消息,尽管 SNMPv1 中的 Trap-PDU 消息使用了不同的格式。)

表 68-10 显示了常见的 SNMPv2 PDU 格式。表 68-11 包含错误状态字段的不同的值及其解释。图 68-8 说明了 SNMPv2 通用 PDU 格式。

表 68-10. SNMPv2 通用 PDU 格式

字段名称 语法 大小(字节) 描述
PDU 类型 整数(枚举) 4 PDU 类型:表示 PDU 类型的整数值:0 = GetRequest-PDU1 = GetNextRequest-PDU2 = Response-PDU3 = SetRequest-PDU4 = 已废弃,不再使用(这是 SNMPv1 中的旧 Trap-PDU)5 = GetBulkRequest-PDU(有自己的格式;请参阅表 68-12)6 = InformRequest-PDU7 = Trapv2-PDU8 = Report-PDU
请求 ID 整数 4 请求标识符:用于匹配请求和响应的数字。由发送请求的设备生成,并由响应的 SNMP 实体复制到响应-PDU 中的此字段。
错误状态 整数(枚举) 4 错误状态:在响应-PDU 中使用的整数值,用于告知请求的 SNMP 实体其请求的结果。零值表示没有发生错误;其他值表示发生了什么类型的错误(请参阅表 68-11)。
错误索引 整数 4 错误索引:当错误状态不为零时,此字段包含一个指针,指定哪个对象生成了错误。在请求中始终为零。
变量绑定 变量 变量 变量绑定:一组标识 PDU 中 MIB 对象的名称/值对,在请求以外的消息中包含它们的值。有关这些绑定的更多信息,请参阅本章前面关于通用 SNMP PDU 格式的讨论。

注意

前六个错误状态字段值(0 到 5)保持与 SNMPv1 中使用的值一致,以保持兼容性,但 SNMPv2 添加了许多新的错误代码,这些代码提供了对请求中错误确切性质的更具体指示。当没有特定的错误类型(无论是旧代码还是新代码)适用时,仍然使用 genErr 代码

表 68-11. SNMPv2 PDU 错误状态字段值

错误状态值 错误代码 描述
0 noError 没有发生错误。此代码也用于所有请求 PDU,因为它们没有错误状态要报告。
1 tooBig 响应-PDU 的大小将太大而无法传输。
2 noSuchName 请求的对象名称未找到。
3 badValue 请求中的值与请求接收者对对象的预期结构不匹配。例如,请求中的对象指定了不正确的长度或类型。
4 readOnly 尝试设置一个具有只读访问值的变量。
5 genErr 发生了一个错误,该错误未在本表中的更具体错误代码中指示。
6 noAccess 由于安全原因,拒绝访问对象。
7 wrongType 变量绑定中的对象类型对于对象是不正确的。
8 wrongLength 变量绑定指定了一个不适用于对象的长度。
9 wrongEncoding 变量绑定指定了一个不适用于对象的编码。
10 wrongValue 变量绑定中给出的值对于对象来说是不可能的。
11 noCreation 指定的变量不存在且无法创建。
12 inconsistentValue 变量绑定指定了一个变量可以持有的值,但在此时刻无法分配给它。
13 resourceUnavailable 设置变量需要一种不可用的资源。
14 commitFailed 尝试设置特定变量失败。
15 undoFailed 尝试将特定变量作为一组变量的一部分设置失败,然后尝试撤销其他变量的设置并未成功。
16 authorizationError 授权过程中出现问题。
17 notWritable 变量无法写入或创建。
18 inconsistentName 变量绑定中的名称指定了一个不存在的变量。

SNMPv2 常见 PDU 格式

图 68-8. SNMPv2 常见 PDU 格式

SNMPv2 GetBulkRequest-PDU 消息的特殊格式在表 68-12 中显示,并在图 68-9 中说明。

SNMPv2 GetBulkRequest-PDU 格式

图 68-9. SNMPv2 GetBulkRequest-PDU 格式

表 68-12. SNMPv2 GetBulkRequest-PDU 格式

字段名称 语法 大小(字节) 描述
PDU 类型 整数(枚举) 4 PDU 类型:一个表示 PDU 类型的整数值,对于 GetBulkRequest-PDU 消息为 5。
请求 ID 整数 4 请求标识符:用于匹配请求和响应的数字。由发送请求的设备生成,并由响应的 SNMP 实体复制到 Response-PDU 中的此字段。
非重复项 整数 4 非重复项:指定请求变量列表开头非重复、常规对象的数量。
最大重复次数 整数 4 最大重复次数:在表中读取跟随非重复对象的重复对象的迭代次数。
变量绑定 变量 变量 变量绑定:一组标识 PDU 中 MIB 对象的名称/值对。有关这些绑定的更多信息,请参阅本章前面关于通用 SNMP PDU 格式的讨论。

第六十七章概念和操作")包含了关于非重复字段和最大重复字段如何使用的详细信息。

SNMP 版本 3(SNMPv3)消息格式

在 20 世纪 90 年代末,为了解决 SNMPv2 的许多不同变体中出现的各种问题,创建了 SNMPv3。SNMPv3 框架采用了 SNMPv2 中创建的许多组件,包括 SNMPv2 协议操作、PDU 类型和 PDU 格式。SNMPv3 中做出的重大变化包括定义安全方法和参数的更灵活方式,以允许多种安全技术的共存。

SNMPv3 的通用消息格式仍然遵循整体消息包装器的基本思想,该包装器包含一个头和一个封装的 PDU,但它得到了进一步的细化。头部字段本身已经被分为处理安全和未处理安全问题的字段。与安全无关的字段对所有 SNMPv3 实现都是通用的。安全字段的使用可以由每个 SNMPv3 安全模型定制,并由处理安全的 SNMP 实体中的模块处理。这种解决方案提供了相当大的灵活性,同时避免了困扰 SNMPv2 的问题。

SNMPv3 的整体消息格式在 RFC 3412 中有描述,该规范指定了其消息处理和分发。表 68-13 通用消息格式")描述了 SNMPv3 消息格式,并在图 68-10 中进行了说明。

SNMPv3 通用消息格式

图 68-10. SNMPv3 通用消息格式

表 68-13. SNMP 版本 3 (SNMPv3)通用消息格式

字段名称 语法 大小(字节) 描述
消息版本 整数 4 消息版本号:描述此消息的 SNMP 版本号;用于确保版本之间的兼容性。对于 SNMPv3,此值为 3。
消息标识符 整数 4 消息标识符:用于识别 SNMPv3 消息并将响应消息与请求消息匹配的数字。此字段的使用方式类似于 SNMPv2 PDU 格式中的请求 ID 字段(参见 表 68-10),但它们并不相同。创建此字段是为了允许在消息处理级别进行匹配,而不管 PDU 的内容如何,以防止某些安全攻击。因此,Msg ID 和 Request ID 是独立使用的。
消息最大大小 整数 4 最大消息大小:发送此消息的发送者可以接收的消息的最大大小。此字段的最低值为 484。
消息标志 字节串 1 消息标志:控制消息处理的标志集。此字段的当前子结构在 表 68-14 中显示。
消息安全模型 整数 4 消息安全模型:表示用于此消息的安全模型的整数值。对于基于用户的模型(SNMPv3 中的默认值),此值为 3。
消息安全参数 可变 消息安全参数:包含实现此消息所使用的特定安全模型所需参数的一组字段。此字段的内容在每个描述 SNMPv3 安全模型的文档中指定。例如,基于用户的模型参数在 RFC 3414 中。
作用域 PDU 可变 作用域 PDU:包含要传输的 PDU,以及标识 SNMP 上下文的参数,该上下文描述了一组特定实体可访问的管理信息。PDU 被称为 作用域,因为它是在此上下文的作用域内应用的。(是的,安全内容很复杂,抱歉;要正确解释上下文需要很多页;请参阅 RFC 3411。)该字段可能根据 私有标志 的值进行加密或未加密。其结构在 表 68-15 中显示。

表 68-14. SNMPv3 消息标志子字段

子字段名称 大小(位) 描述
保留 5 保留:供将来使用。
可报告标志 1 可报告标志:当设置为 1 时,接收此消息的设备必须在出现应生成此类 PDU 的条件时发送回 Report-PDU。
私有标志 1 私有标志:当设置为 1 时,表示已使用加密来保护消息的隐私。除非认证标志也设置为 1,否则不得设置为 1。
认证标志 1 认证标志:当设置为 1 时,表示已使用认证来保护此消息的真实性。

表格 68-15. SNMPv3 范围 PDU 子字段

子字段名称 语法 大小 描述
上下文引擎 ID 八位字节字符串 变量 用于标识 PDU 将被发送到哪个应用程序进行处理。
上下文名称 八位字节字符串 变量 一个对象标识符,指定与该 PDU 关联的特定上下文。
PDU 变量 正在传输的协议数据单元。

幸运的是,SNMPv3 使用了 SNMPv2 的协议操作,如 RFC 3416 所述,这只是 RFC 1904 的更新。因此,SNMPv3 的 PDU 格式与 SNMPv2 相同(见表格 Table 68-10 至 Table 68-12 和图 Figure 68-8 和 Figure 68-9)。

第六十九章. TCP/IP 远程网络监控(RMON)

无标题图片

在本部分的先前章节中,我们已经看到简单网络管理协议(SNMP)定义了在 TCP/IP 互联网上交换网络信息的框架和特定协议。SNMP 使用的一般模型是网络管理站(NMS)向运行在受管理设备上的 SNMP 代理发送请求。SNMP 代理还可以通过发送trap消息来启动某些类型的通信,告知 NMS 何时发生特定事件。

这种模型运行良好,这也是为什么 SNMP 如此受欢迎的原因。然而,该协议及其使用的模型的一个基本限制是它围绕从通常是常规 TCP/IP 设备(如主机和路由器)的 SNMP 代理通信网络信息。这些设备收集的信息通常有限,因为显然主机和路由器有实际的工作要做——即执行主机和路由器的任务。它们不能全身心投入网络管理任务。

因此,在需要比传统设备收集的更多信息的情况下,管理员通常会使用称为网络分析仪监控器探针的特殊硬件单元。这些是专门用于连接到网络并严格用于收集统计数据和监视管理员感兴趣或关注的事件的设备。如果这些设备能够使用 SNMP 来允许检索它们收集的信息,并在它们注意到重要事项时生成陷阱,显然会非常有用。为了实现这一点,创建了远程网络监控(RMON)规范。

RMON 标准

RMON 通常被称为一种协议,有时你会看到 SNMP 和 RMON 被提及为 TCP/IP 网络管理协议。然而,RMON 实际上根本不是一种独立的协议——它不定义任何协议操作。RMON 实际上是 SNMP 的一部分,RMON 规范实际上是一个管理信息库(MIB)模块,它定义了一组特定的 MIB 对象,供网络监控探针使用。从架构上讲,它只是组成 SNMP 框架的许多 MIB 模块之一。

小贴士

关键概念 SNMP 远程网络监控(RMON)的创建是为了能够使用如网络分析仪、监控器或探针等专用管理设备有效地管理网络。RMON 通常被称为一种协议,但它并不定义任何新的协议操作。它实际上是一个 SNMP 的 MIB 模块,描述了允许高级网络管理功能的对象。

记录 RMON 的第一个标准是 RFC 1271,“远程网络监控管理信息库”,于 1991 年发布。RFC 1271 在 1995 年被 RFC 1757 取代,该规范进行了一些更改。2000 年 5 月发布的 RFC 2819 更新了 RMON,使其使用新的结构化管理信息版本 2(SMIv2)规范,该规范是 SNMPv2 的一部分,但在功能上与 RFC 1757 相同。

RMON MIB 层次结构和对象组

由于 RMON 是一个 MIB 模块,它几乎完全由 MIB 对象的描述组成,每个对象都具有所有此类对象的标准特征。RMON 中的所有对象都排列在 rmon 组中的 SNMP 对象名称层次结构中,该组是 SNMP mib(mib-2)对象树中的第 16 组,1.3.6.1.2.1. 因此,所有 RMON 对象的标识符都以 1.3.6.1.2.1.16 开头。这个单一的 RMON 组被分解为几个更底层的组,为规范定义的 RMON 对象提供更多结构。 图 69-1 MIB 层次结构 RMON 使用一个特殊的 MIB 模块,rmon(16),它适合于 mgmt(2) 下的 mib/mib-2(1) 总体 SNMP 对象层次树中——就像其他 MIB 对象组,如 sys(1) 和 if(2);参见图 66-2。在这个组中,该组的标识符为 1.3.6.1.2.1.16,有九个子组属于 RMON 对象。") 展示了这种结构。

表 69-1 描述了每个 RMON 组,显示了其名称、组代码(在组中用作对象描述符的前缀)以及 RMON 组编号和 SNMP 对象层次标识符。

SNMP 远程网络监控 (RMON) MIB 层次结构 RMON 使用一个特殊的 MIB 模块,rmon(16),它适合于 mgmt(2) 下的 mib/mib-2(1) 总体 SNMP 对象层次树中——就像其他 MIB 对象组,如 sys(1) 和 if(2);参见 . 在这个组中,该组的标识符为 1.3.6.1.2.1.16,有九个子组属于 RMON 对象。

图 69-1. SNMP 远程网络监控 (RMON) MIB 层次结构 RMON 使用一个特殊的 MIB 模块,rmon(16),它适合于 mgmt(2) 下的 mib/mib-2(1) 总体 SNMP 对象层次树中——就像其他 MIB 对象组,如 sys(1) 和 if(2);参见 图 66-2 定义的由对象名称层次结构,以允许所有类型的对象被普遍表示。可以通过跟随阴影框找到此较大树中与 SNMP 相关的树分支。用于 SNMP 的两个子树显示为 internet(1) 下的网状框。每个都包含自己的子结构(其中一些在此处展示)定义了数千个不同的 MIB 对象。左侧的分支用于通用 MIB 对象,右侧的用于私有对象。还定义了一个单独的层次结构用于 SNMPv2。") 在 第六十六章 和管理信息库 (MIBs)") 中。在这个组中,该组的标识符为 1.3.6.1.2.1.16,有九个子组属于 RMON 对象。

表 69-1. SNMP RMON MIB 对象组

RMON 组名称 RMON 组代码 RMON 组编号 完整组标识符 描述
statistics etherStats 1 1.3.6.1.2.1.16.1 此组包含跟踪设备测量的网络统计信息的对象。统计信息可能包括网络流量负载、平均数据包大小、观察到的广播数量、发生的错误计数、各种大小范围内的数据包数量等。
history history, etherHistory 2 1.3.6.1.2.1.16.2 历史组包含一个控制探针采样统计数据的频率的单个表对象。额外的 etherHistory 组是可选的,包含额外的以太网特定信息;它逻辑上包含在历史组中。
alarm alarm 3 1.3.6.1.2.1.16.3 此组定义了可能生成警报以通知管理员发生导入的参数。警报组包含一个表,描述将触发事件的阈值(请参阅此表中的事件组描述)。
hosts host 4 1.3.6.1.2.1.16.4 此组包含跟踪网络中每个主机信息的对象。
hostsTopN hostTopN 5 1.3.6.1.2.1.16.5 此组包含便于按特定方式报告主机的对象。管理员确定如何跟踪这些有序统计信息。例如,管理员可以生成一个报告,列出按发送数据包数量排序的主机,显示最活跃的设备。
矩阵 矩阵 6 1.3.6.1.2.1.16.6 此组跟踪特定对主机之间数据交换的统计数据。网络中任何两个设备之间发送的数据量可以在此处跟踪。由于大型网络可能有数千个此类设备对,为了在探针上节省资源,通常只保留设备对之间最近的对话记录在 MIB 中。
filter filter 7 1.3.6.1.2.1.16.7 此组允许管理员设置过滤器,以控制探针将捕获哪些类型的网络数据包。
capture buffer, capture 8 1.3.6.1.2.1.16.8 此组用于允许探针根据在过滤器组中设置的特定参数捕获数据包。
事件 事件 9 1.3.6.1.2.1.16.9 当基于警报组中对象的参数触发特定警报时,将生成一个事件。此组控制这些事件的处理方式,包括创建并发送 SNMP 陷阱消息到 NMS。

原始的 RMON 标准主要针对以太网局域网(LANs),您可以在表 69-1 中看到一些相关内容。探测器也可以通过使用为该目的创建的其他 RMON 组来收集和报告与其它网络技术相关的信息。这方面的最佳例子是 1993 年 RFC 1513 中定义的一组专门针对令牌环的组。

RMON 警报、事件和统计信息

警报和事件在 RMON 中特别有用,因为它们允许将重要信息立即传达给 NMS。管理员可以完全控制哪些条件会导致警报响起以及事件是如何产生的。这包括指定要监控哪些变量或统计信息,多久检查一次,以及哪些值会触发警报。当事件发生时,也可能记录一条日志条目。如果事件导致发送陷阱消息,管理员将因此被通知,并可以根据事件的严重性决定如何响应。

与所有 MIB 模块和组一样,特定的制造商可能决定实现哪些 RMON 组。然而,某些组——如警报和事件——是相关的,而某些组——如统计信息——通常在所有 RMON 探测器中实现。显然,当使用 RMON 时,NMS 必须了解 RMON 组,并允许运行一个网络管理应用程序来利用 RMON MIB 对象的功能。

第三部分-5. TCP/IP 应用层寻址和应用类别

第七十章

第七十一章

TCP/IP 协议套件是现代互联网的基础,因此,它被用作网络应用开发和实施的主要平台。在过去几十年里,随着全球 TCP/IP 互联网的增长,已经创建了数百个新的应用。这些程序支持各种不同的任务和功能,从执行基本业务任务到提供纯娱乐。用户可能身处同一房间或不同的大陆。

在众多 TCP/IP 应用中,少数被认为是 TCP/IP 的关键应用。大多数已经存在很长时间——在某些情况下,甚至比现代互联网协议(IP)本身还要长。许多这些协议专门处理将信息安排成离散单元(称为“文件”或“消息”)的发送。因此,最重要的 TCP/IP 应用组之一是描述在互联网设备之间移动这些文件的基本机制的应用:文件和消息传输应用

本书剩余部分将讨论最常见且确定的 TCP/IP 应用和应用层协议。然而,在描述这些应用本身之前,我需要先阐述一些与应用协议整体相关的基础知识。为此,本部分包含两章。在第一章中,我解释了为 TCP/IP 应用设置的通用系统,用于寻址互联网资源:统一资源标识符(URIs),包括统一资源定位符(URLs)和统一资源名称(URNs)。在第二章中,我概述了文件和消息传输应用,包括它们之间的区别描述。

第七十章. TCP/IP 应用层寻址:统一资源标识符、定位符和名称(URIs、URLs 和 URNs)

无标题图片

互联网由数百万个相互连接的服务器组成,每个服务器都能向请求信息的互联网用户提供有用的信息。网络拥有的信息越多,它就越丰富,但定位信息就越困难。为了使用信息,我们需要能够找到它,这至少要求我们为每个文件或对象采用某种标记方式。

为了这个目的,TCP/IP 定义了一套统一资源标识符(URIs)系统,它可以在互联网和私有 TCP/IP 网络上使用。每个 URI 唯一指定了客户端如何定位特定资源并访问它,以便可以使用。URIs 被细分为统一资源定位符(URLs)和统一资源名称(URNs),它们具有类似的作用,但工作方式不同。

在本章中,我描述了互联网上用于标识文件、对象和资源的寻址系统。我首先概述了 URI 的概念,并解释了 URI、URL 和 URN 之间的区别。然后,我详细解释了 URL 及其使用方式。这包括对 URL 的一般语法的概述,对最常见应用中使用的 URL 方案的描述,对相对 URL 及其工作方式的讨论,以及与 URL 相关的现实世界问题的全面分析,包括一些不诚实的人玩的有意混淆的游戏。最后,我讨论了 URNs,包括它们如何解决 URL 的一个主要问题以及它们使用的障碍。

URI 概述和标准

如果你在这本书中按照 OSI 参考模型层逐层阅读,你可能会期望到这一点就已经完成了寻址。毕竟,我们已经在第 2 层讨论了 MAC 地址,在第 3 层讨论了 IP 地址,以及它们之间的转换机制(参见第十三章地址解析和 TCP/IP 地址解析协议(ARP)和第十四章反向地址解析和 TCP/IP 反向地址解析协议(RARP))。我们甚至有端口和套接字,它们提供了传输层寻址能力,使得每个设备可以运行多个软件应用(参见第四十三章 TCP 和 UDP 寻址:端口和套接字)。考虑到所有这些,应用层寻址的想法可能看起来有点奇怪,我意识到用这个术语来指代本章的主题可能有点不寻常。

然而,这个概念实际上并没有看起来那么奇怪。确实,有了 IP 地址和端口号,我们理论上可以访问 TCP/IP 互联网上的任何资源;问题在于如何找到它。

应用层寻址不是计算机软件所必需的。它是使人类更容易识别和定位资源的一种方式。这与用来证明创建名称系统(如域名系统(DNS;参见第 III-1 部分名称系统和 TCP/IP 名称注册和名称解析)合理性的论据非常相似。DNS 是一种高级寻址形式,允许使用名称而不是 IP 地址。这对人们来说很有帮助,因为他们发现理解 www.intel.com 比理解 198.175.96.33 更容易。

综合应用层寻址方案的核心理念是将 DNS 已经取得的成就扩展到下一个层次。DNS 名称提供了必要的高级抽象寻址,但仅限于整个设备(无论是真实还是虚拟的)。这些名称可以用作更完整标签方案的基础,不仅指向一个站点或设备,还可以指向特定的文件、对象或其他资源。在 TCP/IP 中,这些标签被称为统一资源标识符(URIs)。

URIs 是作为万维网(WWW)开发的关键技术之一而开发的,并且它们通常与 Web 及其实现的超文本传输协议(HTTP;见第三部分-8"))联系在一起。你过去可能已经使用了成千上万的 URI;每次你将类似http://www.myfavoritewebsite.com的内容输入到网页浏览器中时,你就是在使用 URI。

URI 之所以对 Web 如此重要,是因为它们将所有必要的引用资源信息组合成一个字符串。这种表达的紧凑性对于整个超文本资源链接概念至关重要。如果我们想要使一个文档中的对象指向另一个对象,我们需要有一种简单的方式来描述该对象,而无需一整套指令。URI 允许我们做到这一点。

实际上,URI 与 Web 的联系如此紧密,以至于它们通常被描述为是特定于 Web 技术的组成部分。然而,它们并不特属于 Web,这就是为什么本章与 WWW 和 HTTP 的讨论是分开的。

URI 类别:URLs 和 URNs

URI 是引用许多种 TCP/IP 资源的一般性方法。根据它们描述资源的方式,它们目前被分为两大类:

统一资源定位符(URLs) URL 是一种 URI,通过组合协议或访问机制和特定资源位置来引用资源。URL 以要用于访问资源的协议名称开头,然后包含足够的信息来指示如何获取该资源。

统一资源名称(URNs) URN 是一种 URI,提供了一种在不指定访问协议或机制以及不指定特定位置的情况下唯一命名资源的方法。

URL 和 URN 之间的区别在于,前者更加具体,围绕如何访问资源进行定位,而后者更加抽象,设计上更多地是为了识别资源是什么,而不是描述如何获取它。

给某人一个 URL 就像给他们指路找一本书,如下所示:“乘坐火车去阿尔伯克基,然后乘坐 11 路公交车到 41 号阿尔伯特街,这是一座由乔安妮·约翰逊拥有的红砖房子。你想要的书在二楼书架最右边第三本书。”

URN 更像是用国际标准书号(ISBN)来指代一本书;它唯一地标识了这本书,无论这本书可能位于何处,都不会告诉你如何访问它。(实际上,ISBN 是用于 URN 的识别系统之一,你将在本章末尾关于 URN 的部分中看到。)

虽然 URLs 和 URNs 在理论上是对等的,但在实践中,URLs 的使用频率远高于 URNs。事实上,URLs 的地位如此之高,以至于大多数人甚至从未听说过 URIs 或 URNs。原因是,尽管寻找书籍的例子表明 URNs 比 URLs 更自然,但在实际操作中,URLs 更容易使用。URLs 提供了访问资源所需的信息,而如果不能访问资源,仅仅知道如何识别它就具有有限的价值。

URN 是一个吸引人的概念,因为它们在不需要将其与特定的访问机制或位置绑定的情况下标识资源。然而,URN 的实现需要某种方式将资源的永久标识符与其在任何给定时刻的位置联系起来,这并不是一个简单的任务。因此,URN 及其使用方法已经开发多年,而 URL 则一直处于活跃使用中。

小贴士

关键概念在任何互联网上都需要某种机制来允许资源(如文件、目录和程序)被标识和访问。在 TCP/IP 中,统一资源标识符(URIs)用于这种“应用层寻址”。URI 有两种类型:统一资源定位符(URLs),它通过结合访问方法和位置来指定如何访问一个对象,以及统一资源名称(URNs),它通过名称来标识一个对象,但并不指示如何访问它。

虽然 URL 始于 Web,并且大多数 URL 仍然与 HTTP 一起使用,但它们可以并且确实可以引用使用许多其他协议访问的资源,例如文件传输协议(FTP)和 Telnet。URI 的紧凑性使它们在这样使用时非常强大。使用 URL,我们可以使用一个字符串告诉程序使用 FTP 检索文件。这取代了启动 FTP 客户端、建立会话、登录和发出命令的完整 FTP 过程。

URI 标准

20 世纪 90 年代发布的一些互联网标准描述了 URI、URL 和 URN 的语法和基本用法。第一个是 RFC 1630,“WWW 中的通用资源标识符”,于 1994 年发布,仍然是这个主题的良好概述。1994 年 12 月,两份文件,RFC 1737 和 RFC 1738,分别提供了关于 URN 和 URL 的更具体信息。RFC 1808 描述了如何定义和使用相对 URL。RFC 2141 提供了更多关于 URN 语法的详细信息。

RFC 2396,“统一资源标识符(URI):通用语法”,于 1998 年 8 月发布,旨在修订和取代许多先前 RFC 中的一些信息。它可能是目前 URI 的权威标准,尽管仍然有 RFC 发布讨论与 URI 相关的问题。特别是 URNs,正如我之前提到的,它们仍在积极开发中。

基础文档,如 RFC 2396,描述了如何为许多常见的协议(在 URL 术语中称为 schemes,当我们更仔细地研究 URL 时将会看到)指定 URL。为了提供灵活性,还定义了一种机制,允许注册新的 URL 方案。这在本节 RFC 2717,“URL 方案名称注册程序”和 RFC 2718,“新 URL 方案指南”中有所描述。还有一些 RFC 描述了不同协议的特定 URL 方案,包括 RFC 2192(IMAP)、2224(NFS)、2368(电子邮件)和 2384(POP)。

URL 通用语法

URL 是文本字符串,允许根据资源在互联网上的位置以及访问它的主要方法或协议对其进行标记。由于它们的简单性,URL 已经成为 TCP/IP 应用层地址中使用的最常见类型的 URI。

URL 由两个组件组成,用于标识如何访问 TCP/IP 互联网上的资源:资源的位置以及访问它所使用的方法。这两个信息片段结合起来,允许具有适当软件的用户获取、读取或以其他方式处理许多不同类型的资源,如文件、对象、程序等等。

URL 的最通用语法形式只包含两个元素,这两个元素对应于前面描述的两条信息:<scheme>:<scheme-specific-part>。术语 scheme 指的是一种访问方法,它描述了资源的使用方式。它通常指的是一种应用协议,如 httpftp,或者是一种资源类型,如 file。方案名称必须只包含字母、加号(+)、点(.)和连字符(-)。在实践中,方案名称通常只包含字母。方案名称不区分大小写,但通常用小写表示。

方案之后(以及必需的冒号分隔符)的 URL 其余部分是方案特定的。这是必要的,因为各种协议和访问方法需要不同类型和数量的信息来标识特定的资源。当读取 URL 时,方案名称告诉解析该 URL 的程序如何解释 URL 其余部分的语法。

常见互联网方案语法

理论上,每个方案都可以为 URL 的<scheme-specific-part>使用完全不同的语法。然而,许多这些方案由于在引用互联网设备及其设备上的资源方面的相似性,因此在这个部分共享一个共同的语法。例如,HTTP 和 FTP 都用于通过 DNS 名称或 IP 地址指向特定的 TCP/IP 设备,然后访问存储在分层目录结构中的资源。它们的 URL 至少在某种程度上相似是有意义的。

小贴士

关键概念 URLs 是最广泛使用的 URI 类型。在其最基本的形式中,一个 URL 由两个元素组成:定义访问资源协议或其他机制的方案,以及包含标识特定资源并指示如何使用该资源的信息的方案特定部分。一些方案为它们的方案特定部分使用共同的语法;其他方案使用方案特有的语法。

这种常见互联网方案语法的最一般形式如下:

<scheme>://<user>:<password>@<host>:<port>/<url-path>;<params>?<query>#<fragment>

语法元素如下:

<scheme> URL 方案,指的是一种访问方法。

<user><password> 需要登录的方案的认证信息,形式为用户名和密码。

<host> 互联网主机,通常指定为完全限定的 DNS 域名或点分十进制表示法的 IP 地址。

<port> 在调用与方案相关的协议时使用的传输控制协议(TCP)或用户数据报协议(UDP)端口号。

<url-path> 资源位置路径。这通常是一个从根目录到资源所在位置的完整目录路径,表示要遍历的目录序列,然后是资源的名称。例如,如果在一个设备上有一个名为 project1 的目录,其中包含一个名为 memos 的子目录,子目录中有一个名为 June11th-minutes.txt 的文本文件,那么 URL 路径project1/memos/June11th-minutes.txt就指向该资源。请注意,在<url-path>之前需要斜杠,虽然从技术上讲它不被认为是路径的一部分,但它起到了在许多文件系统中表示根目录的斜杠的作用。此外,<url-path>可能以斜杠结尾,这意味着路径专门指向一个目录。然而,这通常不是必需的,因为当需要时,服务器会根据上下文将 URL 视为目录引用。路径也可以指向虚拟文件、程序或其他类型的资源。

<params> 包含在方案中以控制如何使用方案访问资源的方案特定参数。每个参数通常为<parameter>=<value>的形式,每个参数规范之间使用分号分隔。

<query> 当访问资源时传递给服务器的可选查询或其他信息。

<fragment> 用于标识用户对资源中特定位置感兴趣的地方。

图 70-1 使用 HTTP URL 的示例说明了这种常用语法及其元素。

统一资源定位符(URL)示例 此图显示了包含一般方案语法的几乎所有可能元素的示例 URL,每个元素都使用阴影框突出显示。此 URL 标识了一个必须通过特定密码在 www.mysite.org 网站使用端口 8080 访问的 Web(HTTP)资源。在这种情况下,资源是位于站点 cgi-bin 目录中的 PHP 程序,它会导致显示特定的照片页面。指定器将导致在检索到的婚礼照片页面上显示图片 Reception07。

图 70-1. 统一资源定位符(URL)示例 此图显示了包含一般方案语法的几乎所有可能元素的示例 URL,每个元素都使用阴影框突出显示。此 URL 标识了一个必须通过特定密码在 www.mysite.org 网站使用端口 8080 访问的 Web(HTTP)资源。在这种情况下,资源是位于站点 cgi-bin 目录中的 PHP 程序,它会导致显示特定的照片页面。<fragment>指定器将导致在检索到的婚礼照片页面上显示图片 Reception07。

URL 语法元素的省略

完整的 URL 语法可能看起来非常复杂,但请记住,这是一个正式的定义,它一次性显示了 URL 中所有可能元素。大多数方案并不使用这些元素中的每一个,而且其中许多元素是可选的,即使它们在特定方案中是有效的。例如,<login><password>元素在 HTTP URL 中官方支持,但它们很少使用。同样,端口号通常被省略,告诉客户端软件只需使用该方案默认的端口号。本章的“URL 方案和方案特定语法”部分描述了一些最常见的 URL 方案及其特定语法,包括这些元素如何以及何时被使用。

尽管 URL 语法的丰富性并不经常需要,但在某些特殊情况下,它可以提供各种信息。URL 在表达方式上也非常灵活。例如,虽然<host>元素通常是 DNS 名称,但它也可以是多种形式的 IP 地址,包括点分十进制、常规十进制、十六进制、八进制,甚至这些的组合。不幸的是,由于大多数人对于这些细节的不熟悉,导致 URL 被故意模糊化,以引导人们访问他们通常想要避免的“资源”。我们将在本章的“URL 模糊化、混淆和一般诡计”部分中对此进行探讨。

URL 片段

值得注意的是,从描述资源命名的标准来看,<fragment>元素在技术上不被认为是 URL 的正式部分。原因是它只标识资源的一部分,而不是标识资源本身所需的信息的一部分。它不会被发送到服务器,而是由客户端软件保留,以指导它如何显示或使用资源。然而,有些人会提出一个合理的论点,即这种区别是有些任意的。例如,方案本身也仅由客户端使用,主机本身也是如此。

URL 片段的最常见例子是在显示网页时指定一个特定的书签以滚动到。在实践中,片段标识符通常被当作 URL 的一部分来处理,因为它指定 URL 的字符串的一部分。

不安全字符和特殊编码

URLs 通常以标准的 US ASCII 字符集表示,这是大多数 TCP/IP 应用协议的默认使用。该集合中的某些字符被称为不安全字符,因为它们在不同的上下文中具有特殊含义,将它们包含在 URL 中会导致歧义或解释上的问题。空格字符是经典的不安全字符,因为空格通常用于分隔 URL,所以在 URL 中包含一个空格会将 URL 分割成几部分。其他字符不安全,因为它们在 URL 中具有特殊意义,例如冒号(:)。

URL 中的安全字符是字母数字(AZaz 和 0 到 9)以及以下特殊字符:美元符号($)、连字符(-)、下划线(_)、点(.)、加号(+)、感叹号(!)、星号(*)、撇号(')、左括号(() 和右括号())。所有其他不安全字符都可以使用一个编码方案表示,该方案由一个百分号(%)后跟字符的十六进制 ASCII 值组成。最常见的例子在表 70-1 中给出。

表 70-1. URL 特殊字符编码

字符 编码 字符 编码 字符 编码
%20 < %3C > %3E
# %23 % %25 { %7B
} %7D | %7C \ %5C
^ %5E ~ %7E [ %5B
] %5D `%60 ; %3B
/ %2F ? %3F : %3A
@ %40 = %3D % %26

当遇到这些序列时,它们被解释为它们所代表的字面字符,没有任何意义。因此,URL http://www.myfavesite.com/are%20you%20there%3F 指向名为 "are you there?" 的文件,位于 www.myfavesite.com%20 代码防止空格打断 URL,而 3F 防止文件名中的问号被解释为特殊的 URL 字符。

备注

由于百分号用于这种编码机制,它本身是特殊的。当遇到它时,下一个值被解释为字符编码。因此,要嵌入一个字面百分号,它必须编码为 %25

再次强调,这些编码有时被滥用于恶意目的,遗憾的是,例如使用它们来表示常规 ASCII 字符以隐藏 URL。

URL 方案和方案特定语法

如前几节所述,URL 使用一种通用语法,该语法描述了访问 TCP/IP 资源的位置和方法:

<scheme>://<user>:<password>@<host>:<port>/<urlpath>;<params>?<query>#<fragment>

每个访问方法,称为 方案,都有自己的特定 URL 语法,包括该方法识别资源所需的各种信息。RFC 1738 包含了几个流行 URL 方案使用的特定语法的描述。其他方案已在后续的 RFC 中定义,这些 RFC 使用了为 URL 方案注册建立的程序。

几个 URL 方案使用本章前面 图 70-1 的示例。此图显示了一个包含一般方案语法的几乎所有可能元素的示例 URL,每个元素都使用阴影框突出显示。此 URL 识别一个必须使用特定密码通过 www.mysite.org 站点访问的端口 8080 的 Web (HTTP) 资源。在这种情况下,资源是位于站点 cgi-bin 目录中的 PHP 程序,它会导致显示特定的照片页面。 指定器将导致在检索到的婚礼照片页面中显示图片 Reception07。") 中所示的共同互联网模式。其他方案使用完全不同的(通常更简单)结构,这些结构基于它们的需求。

以下各节描述了最常见的 URL 方案以及它们使用的方案特定语法。

万维网/超文本传输协议语法 (http)

Web 可能使用共同互联网方案语法的几乎所有元素,如下所示:

http://<`user`>:<password>@<host>:<port>/<url-path>?<query>#<bookmark>

如资源标识符概述中所述,Web 是目前使用 URL 的主要应用程序。理论上,URL 可以包含大多数常见的 URL 语法元素,但在实践中,大多数都被省略。大多数 URL 只包含一个主机和资源的路径。端口号通常省略,意味着应该使用默认值 80。<query> 构造通常用于从客户端传递参数或信息到 Web 服务器。

我已在第七十九章中提供了关于如何使用 Web URL 的详细说明。

文件传输协议语法(ftp)

FTP URL 的语法是:

ftp://<user>:<password>@<host>:<port>/<url-path>;type=<typecode>

FTP(见第七十二章"))是一个基于命令的交互式协议,因此使用 URL 来访问 FTP 可能看起来有些奇怪。然而,FTP 最常见的用途之一是访问和读取单个文件,这正是 FTP URL 允许客户端快速且轻松地完成的。<user><password> 元素用于登录,对于匿名 FTP 访问可以省略。端口号通常省略,默认为标准的 FTP 控制通道端口,21。

<url-path> 被解释为一个目录结构和文件名。发出适当的 CWD(更改工作目录)命令进入指定的目录,然后对命名的文件发出 RETR(检索)命令。可选的 type 参数可以用来指示文件类型:a 表示 ASCII 文件检索或 i 表示图像(二进制)文件。type 参数通常从 URL 中省略,客户端会根据文件名自动设置正确的模式。

例如,考虑以下 URL:

ftp://ftp.hardwarecompanyx.com/drivers/widgetdriver.zip

这相当于启动一个 FTP 客户端,匿名连接到 ftp.hardwarecompanyx.com,然后切换到驱动器目录并检索文件 widgetdriver.zip。客户端将以二进制模式检索文件,因为它是一个压缩的 ZIP 文件。

还可以使用 FTP URL 获取特定目录内文件的列表。这允许用户通过 URL 链接导航 FTP 服务器的目录结构,找到他们想要的文件,然后检索它。这是通过为 <url-path> 指定目录名称并使用带有 <typecode>dtype 参数来请求目录列表来完成的。同样,type 参数通常省略,当在 URL 中给出目录名称时,软件会自动确定发送 LIST 命令到服务器。

电子邮件语法(mailto)

定义了一种特殊的语法,允许 URL 表示向用户发送邮件的命令:

mailto:<email-address>

电子邮件地址(见第七十五章)采用标准互联网格式:<用户名>@<域名>。这实际上是一种非常不寻常的 URL 类型,因为它根本不表示任何对象,尽管一个人可以被看作是一种资源。请注意,可选参数,如电子邮件的主题,也可以包含在 mailto URL 中。然而,这种功能并不常用。

Gopher 协议语法(gopher)

Gopher 协议的语法类似于 HTTP 和 FTP:

gopher://<host>:<port>/<gopher-path>

有关 Gopher 协议的更多信息,请参阅第八十六章)。

网络新闻/Usenet 语法(news)

为 Usenet 新闻组访问定义了两种语法:

news://<newsgroup-name>
news://<message-id>

这两种 URL 都用于访问 Usenet 新闻组(见第八十五章"))或特定消息,通过消息 ID 进行引用。像 mailto 方案一样,这是一种特殊的 URL 类型,因为它定义了访问方法,但并不提供描述如何定位新闻组或消息的详细信息。

根据定义,这种 URL 的第一种形式被解释为本地。例如,news://alt.food.sushi 的意思是,“在本地新闻服务器上访问新闻组 alt.food.sushi,使用默认的新闻协议。”默认新闻协议通常是网络新闻传输协议(NNTP)。第二种 URL 形式是全局的,因为消息 ID 在 Usenet 上是唯一的(或者至少,它们应该是这样的!)。

网络新闻传输协议语法(nttp)

nntp 形式是新闻访问的不同 URL 类型:

nntp://<host>:<port>/<newsgroup-name>/<article-number>

news 不同,这种 URL 形式明确请求使用 NNTP(见第八十五章"))并标识一个特定的 NNTP 服务器。然后它告诉服务器要访问哪个新闻组以及该新闻组中的哪个文章编号。请注意,每个服务器使用不同的序列来编号文章,因此这仍然是一种本地新闻寻址形式。端口号默认为 119。

虽然 nntp 形式似乎提供了更完整的资源规范,但 news URL 更常被使用,因为它更简单。一旦在客户端软件中设置适当的 NNTP 服务器,就更容易一次设置好,而不是每次都指定它,因为客户端通常只使用一个 NNTP 服务器。

Telnet 语法(telnet)

这种语法用于打开到服务器的 Telnet 连接(见第八十七章):

telnet://<*`user`*>:<*`password`*>@<*`host`*>:<*`port`*>

实际上,用户名和密码通常被省略,这会导致 Telnet 服务器提示此信息。或者,可以提供<user>并省略密码(以防止其被看到),服务器将只提示密码。端口号默认为 Telnet 的标准端口 23,也经常被省略。

这种类型的 URL 很有趣,因为它标识的资源不是对象,而是一种服务。

本地文件语法(file)

对于引用特定主机计算机上的文件,使用一种特殊的 URL 类型。标准语法是:

file://<*`host`*>:<*`url-path`*>

这种类型的 URL 也有些有趣,因为它描述了对象的位置,但没有描述访问方法。它并不足够通用,无法允许在互联网上的任何地方访问文件,但通常用于引用局域网(LAN)上已分配给不同设备的计算机上的文件。

还定义了一种特殊的语法来专门引用本地计算机上的文件:

file:///<*`url-path`*>

在这里,整个//<host>:元素已被替换为一组三个斜杠,意味着在本地主机上查找。

特殊语法规则

浏览器通常使用一些额外的语法规则来支持微软操作系统的怪癖,尤其是对于文件方案。首先,微软 Windows 使用的反斜杠在 TCP/IP 要求下被表示为正斜杠。其次,由于在微软操作系统中,冒号用于驱动器字母的指定,因此这些被替换为垂直管道字符(|)。

因此,要引用文件 C:\WINDOWS\SYSTEM32\DRIVERS\ETC\HOSTS,可以使用以下 URL:

file:///C|/WINDOWS/SYSTEM32/DRIVERS/ETC/HOSTS

然而,请注意,一些浏览器实际上确实允许在驱动器指定中使用冒号。

URL 相对语法和基本 URL

到目前为止所描述的 URL 语法有时被称为指定绝对 URL。这是因为 URL 中的信息足以完全识别资源。因此,绝对 URL 具有上下文无关的特性,这意味着用户可以使用 URL 访问和检索资源,而无需任何额外信息。

整个 URL 的目的在于提供定位和访问资源所需的信息,因此我们希望它们在大多数情况下具有绝对的定义是合理的。绝对 URL 的问题在于它们可能很长且繁琐。有些情况下,需要识别许多彼此相关的不同资源;这些资源的 URL 通常有许多共同元素。在这种情况下使用绝对 URL 会导致大量多余的冗余文字。

在本章开头对 URI 的概述中,我给出了一个关于 URL 的现实世界类比,即描述一个人获取一本书的访问方法和位置:“乘坐火车去阿尔伯克基,然后乘坐 11 路公交车到 41 号阿尔伯特街,这是一座由乔安妮·约翰逊拥有的红砖房。你想要的书在二楼书架最右边第三本。”

如果我还想让同一个人在拿到第一本书后,在同一个房子的底层再拿第二本书,我应该先再说一遍,“乘坐火车去阿尔伯克基,然后乘坐 11 路公交车到 41 号阿尔伯特街,这是一座由乔安妮·约翰逊拥有的红砖房”吗?为什么麻烦,因为他们已经在那个房子里了?不,我会用相对术语给出第二个指令:“下楼,并在木桌上拿那本蓝色的书。”这个指令只有在原始上下文中才有意义。

在 URL 中也存在同样的需求。考虑一个位于 http://www.longdomainnamesareirritating.com/index.htm 的网页,其中包含 37 个嵌入的图形图像。负责维护这个网站的可怜家伙不想在每个图像的 URL 前面都加上 http://www.longdomainnamesareirritating.com/

同样,如果我们刚刚在 ftp://ftp.somesitesomewhere.org/very/deep/directory/structures/also/stink/ 上获取了一个目录列表,我们想要探索父目录,我们只想说“向上一级”,而不必说 ftp://ftp.somesitesomewhere.org/very/deep/directory/structures/also/

正是因为这些原因,URL 语法被扩展以包括相对形式。用最简单的话说,相对 URL 与绝对 URL 相同,但省略了由上下文暗示的信息部分。就像我们的“下楼”指令一样,相对 URL 本身并不包含足够的信息来指定资源。相对 URL 必须在提供缺失信息的上下文中进行解释。

相对 URL 的解释规则

从相对 URL 中查找资源所需的上下文以基本 URL 的形式提供,该基本 URL 提供了缺失的信息。基本 URL 必须是特定的绝对 URL,或者本身是另一个相对 URL,该相对 URL 指向某个其他绝对基本 URL。基本 URL 可以明确声明,也可以从使用中推断出来。处理 URL 的 RFC 定义了以下三种确定基本 URL 的方法,按列出的优先级顺序:

文档内的基本 URL 一些文档允许显式地声明基本 URL。如果存在,则此规范用于文档中的任何相对 URL。

从封装实体获取基 URL 在没有在文档中指定显式基 URL,但该文档是包含它的更高级别实体的部分的情况下,基 URL 是父文档的 URL。例如,MIME 多部分消息的正文部分中的文档(见第七十六章 展示了一些相对 URL 的示例以及它们的解释。

表 70-2. 相对 URL 规范和绝对等效

相对 URL 等效绝对 URL 说明
#bookmark2 http://site.net/dir1/subdir1/file1?query1#bookmark2 URL 与基本 URL 相同,除了书签不同。这可以在 HTML 中引用同一文档中的不同位置。技术上,这里的 URL 没有改变,因为片段(书签)不是实际 URL 的一部分。当浏览器接收到一个新的书签名称时,通常不会尝试重新访问资源。
?query2 http://site.net/dir1/subdir1/file1?query2 与基本 URL 提供的相同文件,但带有不同的查询字符串。请注意,从基本 URL 中移除了书签引用。
file2 http://site.net/dir1/subdir1/file2 这指的是使用名称 file2 的文件,它替换了基本 URL 中的 file1。在这里,查询和书签都被移除了。
/file2 http://site.net/file2 由于包含了一个单斜杠,这意味着 file2 在根目录中。这个相对 URL 替换了基本 URL 中的整个<url-path>
.. http://site.net/dir1/ 这对点表示基本 URL 中的父目录。由于基本 URL 中的目录是 dir1/subdir1,这指的是 dir1/。
../file2 http://site.net/dir1/file2 这指定了我们应该向上移动到父目录以在 dir1 中找到文件 file2。
../subdir2/file2 http://site.net/dir1/subdir2/file2 这表示通过..向上移动一个目录,然后进入子目录 subdir2 以找到 file2。
../../dir2/subdir2/file2 http://site.net/dir2/subdir2/file2 这与上一个例子相同,但向上移动两个目录层级,然后通过 dir2 和 subdir2 找到 file2。
//file2 http://file2 两个斜杠意味着 file2 替换了主机名,导致主机名右侧的所有内容都被删除。这可能不是预期的结果,这也显示了监视那些斜杠的重要性。
//www.newsite.net/otherfile.htm http://www.newsite.net/otherfile.htm 在这个例子中,除了方案之外的所有内容都被替换了。在实践中,这种相对 URL 的形式并不常见——如果指定了站点名称,通常包括方案,以保持完整性。
file2?query2#bookmark2 http://site.net/dir1/subdir1/file2?query2#bookmark2 这替换了文件名、查询名和书签名。
ftp://differentsite.net/whatever ftp://differentsite.net/whatever 使用新的方案迫使 URL 被解释为绝对 URL。

相对 URL 只对某些 URL 方案有意义。对于其他方案,它们没有意义,也无法使用。特别是,相对 URL 永远不会用于telnetmailtonews方案。它们在 HTTP 文档中非常常见,也可能用于 FTP 和文件 URL。

顺便提一下,使用相对 URL 的另一个非常重要的好处是:在文档中避免使用绝对 URL 可以使它更具可移植性,通过消除可能更改的名称的硬编码引用。回到我们之前的例子,如果维护http://www.longdomainnamesareirritating.com站点的人只使用相对链接来引用图形和其他嵌入对象,那么如果该站点迁移到www.muchshortername.com,他就不需要编辑所有指向新名称的链接。在详细讨论 HTTP URL 的第七十九章中进一步探讨了这一点在 Web URL 中的重要性。

小贴士

关键概念 除了比绝对 URL 更高效之外,相对 URL 的优势还在于它们允许资源设计者避免具体提及名称。这增加了文档在站点内或站点之间的可移植性。

URL 长度和复杂性问题

由于一些非常好的原因,URL 是某些资源寻址的最普遍形式:它们代表了一种简单、方便且易于理解的查找文档的方式。由于在 Web 上的广泛应用,URL 现在可以在从电子文档列表到电视广告的任何地方看到——这是它们普遍性和易用性的证明。

至少,这在大多数情况下是正确的。

当 URL 工作良好时,它们工作得非常好。不幸的是,关于 URL 的使用方式也存在一些担忧。URL 的误用,无论是偶然的还是故意的,都时有发生。我之所以投入大量精力来描述 URL,部分原因是因为大多数人并不真正理解它们是如何工作的,这也是问题发生的一部分原因。

许多与 URL 相关的问题直接源于长度和复杂性的相关事项。当 URL 简短且简单时,它们工作得最好,这样就可以清楚地知道它们的内容,并且易于操作。例如,http://www.ibm.com几乎每个人都能认出这是国际商业机器公司(IBM)的网站。同样,你可能不需要任何解释就能猜出这个 URL 的功能:ftp://www.somecomputercompany.com/drivers/videodrivers.zip

然而,正如你在本章前面看到的,URL 可以更加复杂。特别是,HTTP 和 FTP 等协议使用的常见互联网语法非常灵活,包含大量可选元素,当需要提供特定资源访问所需的信息时可以使用。

URL 语法中许多元素是可选的这一点很重要。大多数时候,这些可选部分都被省略了,这使得 URL 在实际使用中比在描述中简单得多。例如,尽管 HTTP URL 理论上包含用户名、密码、主机、端口、路径、查询和书签,但大多数 URL 只使用主机名和路径。这正是帮助保持 URL 简短和易于使用的原因。

尽管如此,你仍然会在互联网上找到一些相当长的 URL,原因多种多样:

长 DNS 域名和主机名 有些人没有意识到长主机名很难记住。如果你经营着超级汽车车身修理店和比萨店,拥有一个名为 www.superauto.com 的网站将比尝试注册 www.superautobodyshopandpizza.com 更容易让顾客找到你。然而,15 个、20 个甚至更多字符的 DNS 名称却很常见。

长文档或目录名称 同样,短文件名比长文件名好,而且很多人在将文件上传到互联网之前并没有考虑这一点,这给必须访问它们的人带来了更多困难。

使用不安全字符 如本章前面所述,URL 有一个处理不安全字符的机制,但这会使它们更长且更难解读。如果你有一个名为"{ABC Corp} budget; draft #3; third quarter 2004.htm"的文件,它的 URL 将不得不是%7BABC%20Corp%7D%20budget%3B%20draft%20%233%3B%20third%20quarter%202004.htm。原始的长文件名是可读的,但 URL 却是一团糟。将文件命名为"ABC budget draft 3, 3Q2004.htm"会是一个更好的选择,并且仍然包含足够的信息以便理解。甚至更好,你可以用下划线替换空格,从而完全避免需要%20编码:"ABC_budget_draft 3,_3Q2004.htm"。

参数字符串 在 HTTP URL 中,指定查询(跟随问号字符)的语法通常用于允许网络浏览器向网络服务器发送各种类型的信息,特别是交互式查询的参数。这些参数字符串可能相当长。例如,我输入了一个查询到伟大的网络搜索引擎 Google,以找到土豆沙拉的食谱。这是其中一个食谱文件的 URL 看起来像这样:

http://groups.google.com/groups?q=%22potato+salad%22&hl=en&lr=&ie=
UTF-8&safe=off&selm=B826FB57.89C0%25sbrooks%40ev1.net&rnum=2

几乎所有的内容都是由参数组成的,这些参数告诉 Google 服务器根据我的查询我想要的确切文档。这是必要的,但仍然很繁琐。

URL 换行和界定

对于人类来说,长而复杂的 URL 很难记住和使用。除了记住所有这些字符的纯粹难度外,还有 URL 换行的问题,这发生在它们以某些形式呈现时。大多数程序只能在单行中显示 78 个或 80 个字符。如果一个 URL 比这个长,URL 的字符将换行到多行;当你阅读那个 Google 参数字符串的例子时,你可能注意到了这一点。

URL 的换行可能导致在从一个表单复制到另一个表单时出错,例如如果你从这份文档中复制到你的网络浏览器中。如果一个 URL 有 81 个字符长,其中 80 个在第一行,最后一个字符在第二行,许多用户可能没有意识到 URL 已经换行了。我见过数百个字符长的 URL,需要多次手动复制粘贴才能使 URL 生效。

比起意料之外,一些软件可能也无法正确处理这种换行。虽然当在 HTML 文档等中使用超链接时这不是问题,但当链接包含在电子邮件消息或 Usenet 文章中时,可能会很麻烦。

另一个问题是在文本中出现时如何界定 URL 的开始和结束。理论上,URL 以方案名称开头,可能被用于不是 URL 的其他上下文中。如果没有明确的方法来标记一个 URL 为 URL,那么一个软件程序可能无法识别它。考虑在类似这份文档中讨论一个 URL 的情况。如果我这么说,“请访问www.thissite.com;你将在那里看到你需要的信息,”我们都知道分号是句子的一部分,而不是 URL 的一部分,但一个计算机程序可能并不这么确定。而且,当 URL 很长且复杂,并且跨越到多行文本时,这个问题会更严重。程序如何识别 URL 的结束?

明确的 URL 界定和重定向器

为了解决换行和界定问题,有时会采用特殊的 URL 超级语法,尤其是在 URL 用于其他文本时。这是通过在 URL 周围放置尖括号来完成的,可能包括在方案名称之前包含标签URL:。例如,以下所有内容都是等效的:

http://www.networkingistoodarnedcomplicated.com
<http://www.networkingistoodarnedcomplicated.com>
<URL:http://www.networkingistoodarnedcomplicated.com>

角标清楚地指出了 URL 的开始和结束位置,这使得程序和人类处理长 URL 都变得更加容易。

对于长 URL,有时会使用由许多网站提供的重定向服务作为另一种解决方案。例如,www.tinyurl.com 是一项免费服务,允许某人创建一个简短的 URL,该 URL 会自动加载一个更长的 URL 中的资源。

URL 缩写

我想要讨论的最后一个问题与长或复杂的 URL 没有直接关系,但与长度问题间接相关:URL 缩写。许多人经常使用 URL,以至于在指定 URL 时变得懒惰。他们倾向于省略完整的 URL 语法的一部分以节省时间和精力。我并不是说他们指定了相对 URL,而是他们指定了缺少部分的绝对 URL。

例如,人们可能不会输入 http://www.sitename.com,而是输入 http:www.sitename.com,省略了两个斜杠。更常见的是,人们完全省略方案名称,仅输入 www.sitename.com。从技术上讲,这并不是一个 URL——它只是一个域名。然而,大多数网络浏览器都可以处理这种情况,默认情况下假设如果没有提供方案,则方案是 http://

URL 隐藏、混淆和一般诡计

大多数时候,资源的所有者希望指向资源的 URL 简短、简单且易于理解。因此,长而复杂的 URL 通常是必需、意外或无知的结果。有些资源需要具有长名称的特定原因,例如前面提到的 Google 示例中的长查询字符串;有时,URL 之所以变长,是因为资源所有者没有意识到使用长的 DNS 主机名或文件名将导致长而难以管理的 URL。

无论这些情况的原因是什么,它们都不是故意的。然而,近年来,故意使用长、复杂、令人困惑且具有欺骗性的 URL 的使用急剧增加。这些 URL 要么结构得让人无法判断它们是什么,或者更糟糕的是,它们被设计成指向一个资源,而实际上却指向另一个资源。

为什么人们会这样做呢?因为他们不想公开诚实地关于他们的“资源”。这些人会是谁呢?哦,他们就是那些用各种可能的提议塞满我们的互联网邮箱的垃圾邮件发送者和骗子,从让你梦想成真地变得富有到将某些身体部位膨胀到不自然的大小。

他们担心,如果 URL 清楚地表明了“资源”是什么,你可能不会点击链接,或者如果你将它们识别为垃圾邮件发送者,你可能会过滤掉他们的电子邮件。他们还认为,如果他们能让 URL 看起来很有趣,你就会加载它。即使结果是你没有预料到的,也许你仍然会注意它。

你可能认为你太聪明了,不会因为一个欺骗性的 URL 而被骗购买产品。而且你无论如何也不会支持垃圾邮件发送者。多么巧合——对我来说也是一样!然而,垃圾邮件还在源源不断地来。它一定有效,否则他们不会继续这样做……是吗?

这种复杂的语法被嵌入到 URL 中,以使其具有如此灵活性,这本身就是一个残酷的讽刺。骗子知道大多数人习惯于看到简单的 URL,如http://www.myfavoritesite.com,并且没有意识到完整的 URL 语法实际上允许以文字上数百万种不同的方式指定相同的资源。因此,为了不惜一切代价增加网站的点击量,他们不断想出新的 URL 操纵技巧。这些技巧主要集中在 HTTP 方案 URL 上,尽管在理论上,这些技巧也可以应用于其他几种类型(尽管它们不会与某些方案一起工作)。

这里有一些更常见的花招,人们曾经使用过(注意,如果你在阅读时尝试这些,某些示例在某些浏览器上可能无法工作):

过长的 URL 在某些情况下,URL 会因为添加大量无意义的查询字符串而变得非常长,以至于用户仅仅看一眼就会感到眼花缭乱。然而,这种技术相对简单,因为你可以通过查看 URL 的开头很容易地判断出真正的域名。然而,大多数更好的骗子现在已经超越了这种简单的伎俩。

常规 IP 地址主机 互联网用户已经习惯了使用 DNS 名称,以至于他们没有意识到可以使用 IP 地址访问 URL。所以,大多数人没有意识到《PC 指南》可以通过<http://209.68.14.80><http://www.PCGuide.com>一样容易访问。(注意,这并不是所有互联网主机的通用情况;使用虚拟名称的主机不能仅通过 IP 地址访问。)这实际上并不是什么诡计。这是完全合法的,而且在某些方面,甚至可以说是必要的;例如,访问有 DNS 问题的网站。这里的问题是,通常你无法仅从 IP 地址判断出网站是什么,许多人会直接点击 IP 地址链接,而不费心去了解它是什么。

数字域名 可以注册只包含单个数字的 DNS 域名。例如,可以注册 114.com。然后你可以在其中创建子域名,如 42.12.205.114.com。乍一看,这似乎是一个 IP 地址规范,所以有人可能会认为它会解析到地址 42.12.205.114,但实际上是另一个地址。我相信 DNS 名称注册商已经开始打击这种诡计,所以它可能不像以前那样普遍了。

虚假认证信息 HTTP URL 理论上支持在 URL 中包含认证信息,通过在主机之前包含<user>:<password>@。然而,绝大多数网站都是开放的,既不需要也不使用这类信息。如果你指定了一个不需要的认证字符串,它将被忽略。一种滥用这种方法的方式是包含看起来无害的主机“认证信息”,以使用户认为 URL 是针对该主机的。例如,如果我想骗你访问 PC 指南,我可能会使用这个 URL 来让它看起来像点击它就会去 CNN:《http://www.cnn.com@www.PCGuide.com》。然而,这种方法仍然太明显了,所以通常还会结合以下一些技术。

欺骗性字符编码 使用百分号来编码特殊字符,如空格和标点符号,也可以被滥用以隐藏域名名称。例如,以下是以另一种方式表示 PC 指南 DNS 名称的方法:《http://%57%57%57.%50%43%47%55%49%44%45.%43%4F%4D》。试试看!

IP 地址数学技巧 好吧,这里事情变得真的很奇怪。大多数时候,我们用点分十进制数来表示 IP 地址。然而,记住,对于计算机来说,IP 地址只是一个 32 位的二进制数。大多数浏览器支持相当多的方法来表示这些数字。这是不幸的,因为这种灵活性实际上并不需要,而且几乎从未用于合法目的。它可能导致一些非常奇怪的 URL,这些 URL 无法识别,或者看起来像常规的 IP 地址但实际上不是。以下是一些例子,它们都与 PC 指南的 IP 地址形式相同(《http://209.68.14.80》):

  • 点分八进制的 IP 地址使用一个前导零来表示每个字节在八进制中的位置,例如 <http://0321.0104.016.0120>

  • 点分十六进制的 IP 地址使用一个前导零后跟一个x来表示每个字节在十六进制中的位置,例如 <http://0xD1.0x44.0x0E.0x50>

  • 我们甚至可以将整个 32 位数字作为一个单独的数字来表示,这同样也是可行的。在十进制中,这看起来就像 <http://3510898256/>;在八进制中,<http://032121007120/>;在十六进制中,<http://0xd1440e50/>

就算这些技巧单独使用已经足够糟糕了,我们还可以通过组合它们来玩得更开心!例如,从一个普通的 PC 指南 URL 开始:

<http://www.PCGuide.com>

然后将其转换为 IP 地址:

<http://209.68.14.80>

然后添加一些虚假的认证信息:

<http://www.cnn.com@209.68.14.80>

然后将真实的 URL 转换成一个单独的数字,使其看起来像 CNN 网站上的文档:

<http://www.cnn.com@3510898256>

或者,我们可以使用八进制形式,甚至为了好玩而包含很多额外的额外前导零:

<http://www.cnn.com@0000000000000321.00000000104.00000000000016.00000120>

信不信由你,这仅仅是冰山一角。在某些浏览器中,甚至可以使用百分号 ASCII 编码来表示 IP 地址数字!

虽然相当令人烦恼,但我必须至少给这些人一些创意分——其中一些技巧相当巧妙。同时,他们的创新性可能具有潜在的危险性。虽然这些虚假的 URL 通常更多的是浪费时间而不是有害,但有时人们有充分的理由不遗余力地隐藏资源的身份。欺骗性的 URL 只是网络管理员今天必须应对的又一危险。

小贴士

关键概念 互联网 URL 的语法包括许多元素,这些元素为 URL 的构建提供了极大的灵活性。不幸的是,这些表达能力现在经常被那些故意创建模糊不清的 URL 以欺骗用户访问他们的网站和其他资源的人滥用。其中一些可能具有潜在的危险性,这意味着在点击未知链接或访问奇怪的 URL 之前需要谨慎。

URNs

"HTTP 404 - NOT FOUND"

你是否曾经尝试访问一个网站或其他互联网资源,结果却看到了那些令人恐惧的字眼?你可能有过,而且在你看到它们的时候,你亲自体验到了 URL 最常见的问题之一。

URL 通过使用两关键信息来指定资源:资源的位置以及访问或检索资源的方法。这种对资源访问手段的关注使得 URL 非常实用,因为 URL 通常包含我们使用资源所需的所有数据。这就是为什么 URL 今天被广泛使用的原因。然而,这种访问导向也意味着 URL 存在许多严重的局限性。

URL 的问题

URL 的主要困难在于,由于它们基于资源的位置来描述资源,它们将资源和其位置不可分割地联系在一起。虽然这看起来可能不是什么大问题,但实际上在许多方面都是一个相当严重的问题,因为资源和其位置并不是同一件事。正是因为大多数互联网资源很少改变位置,所以我们没有在 URL 上更频繁地注意到这个问题。

假设你的名字是 Joe Xavier Zachariah,你住在澳大利亚悉尼的 44 Glendale Crescent。如果有人问你你是谁,你会说,“Joe Xavier Zachariah”,还是“住在澳大利亚悉尼 44 Glendale Crescent 的人”?几乎可以肯定,你会提供前者答案。但 URL 就像用后者描述来描述自己作为一个“资源”一样。

由于我们意识到扎卡里亚先生显然不会总是住在 44 Glendale Crescent,我们知道仅用地点来描述他是不够的。当互联网资源仅使用位置来标识时,也会发生同样的事情。

然而,互联网资源和 URL 的问题不仅仅在于移动性。考虑这样一种情况,一个特定的资源非常受欢迎,我们想在多个位置复制相同的资源。使用 URL,我们需要为资源的每个副本提供一个不同的标识符,尽管每个副本都是相同的。再次强调,问题在于我们并没有识别资源本身,而是在识别资源所在的位置。

为了解决 URL 的这个问题,开发了一种用于互联网资源的替代识别机制,称为统一资源名称(URNs)

URN 概述

描述 URN 的基本标准是 RFC 1737,“统一资源名称的功能要求”,该标准于 1994 年发布。1997 年,发布了 RFC 2141,它指定了 URN 的语法。

如您可能从该术语中看出,URN(统一资源名称)旨在根据其实际身份来标记资源,而不是根据其所在位置。因此,一个 URL 就像乔·扎卡里亚的地址一样,而一个 URN 则是他的名字。或者,正如我在本章开头关于 URI 概述中给出的例子,一个 URN 会根据 ISBN 号码来识别一本书,而不是指定它在建筑物中的哪个书架上。

要在识别特定资源时有用,URN 必须是全局唯一的,这并不像最初看起来那么简单。例如,考虑人名。尽管可能整个世界上只有一个查尔斯·马尔林·科齐罗克,但如果你的名字是约翰·保罗·史密斯或何塞·加西亚,你很可能与成千上万的人共享这个名字。这意味着使用通用名称可能不足以识别人类“资源”,可能需要设计其他方法。

URN 命名空间和语法

URNs 旨在在互联网上识别许多类型的资源,每种资源可能需要不同的命名形式。为了使 URN 能够表示多种类型的资源,定义了大量的URN 命名空间

命名空间通过一个独特的字符串来引用,这个字符串告诉解释 URN 的人或计算机该 URN 标识的是哪种类型的资源。命名空间还确保了 URN 的唯一性,当特定的标识符可能在多个上下文中存在时。例如,北美电话号码和 ISBN 号码都由十个数字组成,所以像 4167819249 这样的特定数字可能代表一个电话号码和一个书号。命名空间标识符告诉我们当在 URN 中遇到这个数字时它代表什么。

URN 的一般语法如下:

URN:<namespace-ID>:<resource-identifier>

例如,ISBN 号码为 0-679-73669-7 的书籍可以表示为URN:isbn:0-679-73669-7。这个字符串唯一地标识了这本书,无论它可能在世界上的哪个地方。还定义了许多其他命名空间来指定其他类型资源的 URN,例如互联网上的文档。

小贴士

关键概念 与 URL 通过访问方法和位置指定资源不同,统一资源名称(URNs)通过名称来标识资源。一个 URN 由一个命名空间标识符组成,它指示该名称包含的类型,以及一个资源标识符,它指定了在该命名空间上下文中的单个资源。

URN 解析和实施困难

URNs 是识别资源的一种更自然的方式,这使得它们具有直观的吸引力。尽管如此,URN 仍然没有被广泛使用,尽管它们已经开发超过十年。主要原因多少有些讽刺:这是因为 URN 与位置无关!正是提供 URN 相对于 URL 识别优势的这种特性,也使得 URN 在实际使用中更加困难,这导致了可行的 URN 系统工作上的长期延迟。

要理解这个问题,可以考虑例子 URN:isbn:0-679-73669-7。这个例子唯一地标识了一本特定的书,并且无论这本书在哪里,它都会指向这本书,这与 URL 不同。问题是,虽然 URL 等价物告诉我们如何实际找到这本书,但 URN 并不提供这样的信息。对于我们之前的例子:通过名字识别乔·泽卡利亚·泽赫里亚斯比通过他在澳大利亚悉尼格林代尔克里森特 44 号居住的人更合理,但至少后者我们知道乔在哪里!

为了使 URN 在互联网上变得有用,它们需要一个额外的机制来将简单的 URN 标识字符串转换为特定的位置和/或访问方法。换句话说,我们需要能够将 URN 转换为等效的 URL,以便找到资源。这一需求与将互联网 DNS 域名解析为 IP 地址的问题类似,并且使用相同的术语来描述它:URN 解析

理想情况下,我们希望能够使用某种技术,当我们指定名字乔·泽卡利亚·泽赫里亚斯时,我们被告知乔在哪里,这样我们就可以找到他。或者,我们提供字符串 URN:isbn:0-679-73669-7,我们得到一份可以找到这本书的图书馆或其他地点的列表。URN 的力量也可以在这种系统中得到利用,通过让解析系统指定资源副本的位置,该位置对于发起请求的实体来说是最接近的(从网络距离、成本或其他测量标准来看)。

然而,设置 URN 解析机制是一个非平凡的任务。过去十年中关于 URN 的大部分工作都集中在 URN 解析问题上。1999 年发布的 RFC 2483,“为 URN 解析必要的 URI 解析服务”讨论了 URN 解析的一些重要问题。2002 年 10 月,一系列 RFC,3401 到 3405,定义了一个新的系统,称为动态委派发现系统(DDDS),它不仅旨在解析 URN,还旨在处理整个类别的解析问题,即给定一个标识符,输出是关于如何获取该标识符更多信息的信息。同时发布的 RFC 3406 提供了更多关于 URN 命名空间的信息。

小贴士

关键概念 由于 URN 通过名称而不是位置来标识资源,因此它们比使用 URL 更自然地标识资源。不幸的是,这个优势也是劣势,因为 URN 本身并不提供用户找到资源并使用所需的信息。必须执行 URN 解析过程,将 URN 转换为允许访问资源的一组信息。

尽管 URN 的进展缓慢,但却是稳定的。虽然可能还需要几年时间才能广泛使用 URN,但我相信它们在未来很可能在互联网资源标识中扮演越来越突出的角色。

第七十一章. 文件和消息传输概述及应用类别

无标题图片

网络应用的目的允许不同类型的信息在网络设备之间发送。在计算机的世界里,信息通常被组织成称为文件的离散单元。当这些文件专门为通信目的创建时,它们通常被称为消息

在网络计算机之间传输文件和消息是最基本的网络通信类型。因此,说文件和消息传输应用可能是最重要的互联网互连应用类别并不过分。这个群体的一些成员非常普遍,以至于许多人每天都在使用它们,甚至没有意识到。

在本章简短的介绍中,我概述了文件和消息传输背后的概念,以及不同的应用如何处理它们。我首先讨论了文件背后的通用概念,然后讨论了使用它们的应用程序类别,对比了消息传输与文件传输。

文件概念

要理解文件和消息传输应用,让我们首先快速回顾一下文件的基本概念。简单来说,文件就是由计算机系统视为单一单元的信息集合。

文件存储在文件系统中的目录或文件夹中。在现代计算机中,文件通常表示为一系列字节或字符的序列,每个文件作为一个独立对象被读取、写入、复制或以其他方式操作。除了包含的数据外,每个文件还关联着描述它的文件属性

对于我们的目的来说,文件的关键特性是它是一个包含任意信息的自包含对象。由于文件是计算机系统中信息的构建块,因此网络中信息传输最初是以文件移动来定义的也就不足为奇了。描述如何传输文件的某些协议甚至早于 TCP/IP 低层所有现代协议,包括互联网协议版本 4(IPv4)、传输控制协议(TCP)和用户数据报协议(UDP)。文件传输并不是早期互联网应用的例子,而是互联网的发明在很大程度上是为了允许文件传输!

应用类别

现代计算机系统中的文件本质上被设计为通用;它们可以包含任何类型的信息。文件内容的重要性完全取决于检查它的用户或软件程序。TCP/IP 文件和消息传输协议在将文件从一个计算机移动到另一个计算机的概念上是共同的。它们的不同之处在于文件的处理和加工方式。有两种基本方法:文件传输和消息传输。

通用文件传输应用

通用传输应用通常将文件视为一个“黑盒”,将它们从一个地方移动到另一个地方,很少或根本不关注文件的内容。TCP/IP 文件传输协议(FTP)和简单文件传输协议(TFTP)属于这一类别。FTP 以一种或另一种形式存在了 30 多年,现在仍然被广泛使用。

消息传输应用

其他 TCP/IP 应用与特定类型的文件一起工作,以各种方式处理和解释它们。这些文件通常是为了特定的通信目的而设计的,因此被称为消息;这些应用允许用户构建、发送和接收符合特定消息格式的消息。本书将探讨几个突出的 TCP/IP 消息应用。

电子邮件(Email)

电子邮件是一个允许用户以类似于传统邮政系统的方式交换“信件”(实际上,任何类型的文档)的系统,但具有速度和简单性的优势。电子邮件并没有完全取代常规邮件,但现在许多人用它来处理他们的大部分通信。

网络新闻(Usenet)

Usenet 是一个类似于电子邮件的应用,它允许用户发送消息。然而,尽管电子邮件通常用于允许将消息发送给一个用户或少数几个收件人,网络新闻是一种让成千上万的用户在各个主题上共享消息的方式。

任何用户都可以贡献一个可以被他人看到的消息,任何看到的人都可以回应。与电子邮件不同,收件人不需要被明确标识,这使得网络新闻非常适合于大型群体之间的通信,这些群体可能甚至互不相识。这是第一个创建类似电子公告板的东西的 TCP/IP 应用:一个在线社区。

超文本(万维网)

你可能甚至不需要我解释什么是万维网,它在现代互联网中的重要性是如此之大。超文本将信息传递的概念从简单的文本消息或普通文件的交换扩展到包含各种类型信息的丰富消息。这包括文本、图形、多媒体和嵌入文件。

最重要的是,超文本允许一个文档链接到另一个文档,形成相关文档的网络,这就是万维网名称的由来。网络几乎可以肯定是 TCP/IP 应用中最重要的单一应用,每天有数百万人在使用。

文件和消息传输方法的融合

近年来,许多发展使得文件传输应用和消息传输应用之间的界限变得非常模糊。电子邮件不再仅限于简单的文本消息;现在可以通过特殊方法将文件编码成文本形式来传输一般文件,甚至可以传输超文本文档。万维网客户端(浏览器)继续得到增强,以便它们可以访问其他类型的服务器和文件,也可以用于一般文件传输。

这些发展意味着 TCP/IP 用户将获得更多的功能和灵活性——而对于你,TCP/IP 学习者来说,则需要更加小心。

小贴士

关键概念 最重要的 TCP/IP 应用组之一是允许在互联网上的设备之间移动文件的应用:文件和消息传输应用。这个组包含了许多 TCP/IP 用户每天用来通信的常见应用。它可以分为两大类:用于在设备之间移动任何类型文件的通用文件传输应用,以及允许使用特殊文件类型进行不同类型通信的消息传输应用,例如电子邮件消息或超文本文件。

第 III-6 部分。TCP/IP 通用文件传输协议

第七十二章")

第七十三章")

文件和消息传输协议代表了最基本的网络通信类型:简单的数据块移动。在众多文件和消息传输方法中,最基本的应用是我所说的 通用文件传输。通用文件传输协议执行一个主要功能:允许文件从一个计算机复制到另一个计算机。

由于文件传输协议在移动文件时很少考虑其内容,因此与某些消息处理应用相比,它们相对简单。然而,能够移动文件的想法如此重要,以至于通用文件传输协议是互联网互连中最早的应用之一。尽管现在许多人使用电子邮件或网络浏览器来执行以前仅通过通用文件传输执行的功能,但这些较老的协议仍然非常重要且广泛使用,并且理解它们是很有必要的。

本部分涵盖了两个 TCP/IP 通用文件传输协议:文件传输协议 (FTP) 和简单文件传输协议 (TFTP)。每个协议都在其各自的章节中进行了描述。

FTP 和 TFTP 之间的关系类似于第 4 层的两个传输协议,即传输控制协议 (TCP) 和用户数据报协议 (UDP) 之间的关系(在第 II-8 部分中讨论)。FTP 功能全面,面向会话,并且相对复杂。它是两种协议中更常使用的一种,提供完整的命令接口,并利用其运行的 TCP 的可靠性和流传输功能。TFTP,就像它在传输层使用的 UDP 一样,是 FTP 的简化版本。它比 FTP 具有更少的命令和能力,但在需要简单性和小软件程序尺寸的情况下非常理想,例如在设备嵌入式软件的情况下。

第七十二章。文件传输协议 (FTP)

无标题图片

TCP/IP 套件中的主要通用文件传输协议通过其无修饰的名称直接展示了其通用性:文件传输协议 (FTP)。FTP 是世界上使用最广泛的应用协议之一。它被设计成允许在 TCP/IP 互联网中的任何两个设备之间高效地传输文件。它自动处理文件移动的细节,提供丰富的命令语法以执行各种支持文件操作(如导航目录结构和删除文件),并使用传输控制协议 (TCP) 传输服务来保证可靠性。

在本章中,我详细描述了 FTP 的操作。我首先概述了 FTP,讨论了其悠久的历史和定义它的标准。然后解释了与 FTP 相关的关键概念及其工作方式。这包括 FTP 操作模型的描述以及 FTP 控制连接的建立方式、何时以及如何使用正常和被动数据连接、FTP 的传输模式和数据表示方法。然后我继续讨论 FTP 命令的细节及其工作方式,包括 FTP 命令组、回复代码和用户命令的讨论。最后,我提供了一个用户 FTP 会话的示例,展示了每个动作所使用的内部命令。

FTP 概述、历史和标准

我们今天所知道的 TCP/IP 协议套件是在 20 世纪 70 年代末和 80 年代初开发的,其中分水岭事件可能是 1980 年发布的 IP 和 TCP 版本 4 标准。现代 TCP/IP 是自 20 世纪 60 年代以来进行实验和开发工作的结果。这项工作包括设计并实现将实现互联网的协议,以及创建第一个允许用户执行不同任务的网络应用。

FTP 开发和标准化

早期应用程序的开发者从概念上将网络使用方法分为两类:直接间接。直接网络应用程序允许用户访问远程主机并像使用本地主机一样使用它,创造出远程网络甚至不存在(或者至少最小化距离的重要性)的错觉。间接网络使用意味着从远程主机获取资源并在本地系统上使用它们,然后再将它们传输回去。这两种使用方法成为了第一个正式化的 TCP/IP 网络应用的模型:Telnet 用于直接访问(见第八十七章*。能够在机器之间移动任何类型的文件的需求是如此基本,以至于 FTP 的历史可以追溯到 30 多年以前。FTP 通过 TCP 运行以确保文件可靠传输且无数据丢失。该协议使用一组从 FTP 客户端发送到 FTP 服务器的 FTP 命令 来执行文件传输操作;FTP 服务器向客户端发送 FTP 回复,以指示命令的成功或失败。

FTP 操作模型、协议组件和关键术语

定义 FTP 的标准使用一个简单的概念工具来描述其整体操作,这个工具被称为 FTP 模型。该模型定义了参与文件传输的设备角色以及它们之间建立的两个通信通道。它还描述了管理这些通道的 FTP 组件,并定义了用于组件的术语。这使得它成为我们了解 FTP 在广义上如何工作的理想场所。

服务器-FTP 进程和用户-FTP 进程

如前所述,FTP 是一个经典的客户端/服务器协议。然而,客户端并不被称为这个名字,而是被称为 用户。这个名字来源于发出 FTP 命令的人类用户在客户端机器上工作的事实。在设备上运行的 FTP 软件的完整集合被称为 进程。服务器上的 FTP 软件被称为 服务器-FTP 进程,而客户端上的软件被称为 用户-FTP 进程

小贴士

关键概念 FTP 客户端有时被称为 用户设备,因为人类用户直接与客户端交互。FTP 客户端软件被称为 用户-FTP 进程;FTP 服务器软件是 服务器-FTP 进程

FTP 控制连接和数据连接

理解 FTP 的一个关键概念是,尽管它像许多其他应用程序一样使用 TCP,但它不像大多数协议那样仅使用一个 TCP 连接进行所有通信。相反,FTP 模型是围绕服务器和用户 FTP 进程之间的两个逻辑通信通道设计的:

控制连接 这是当建立 FTP 会话时创建的主要逻辑 TCP 连接。它在整个 FTP 会话期间保持不变,并且仅用于传递控制信息,例如 FTP 命令和回复。它不用于发送文件。

数据连接 每次从服务器向客户端或相反方向发送数据时,它们之间都会建立一个独特的 TCP 数据连接。数据通过此连接传输。当文件传输完成后,连接被终止。

使用单独的通道提供了在协议使用方面的灵活性,但它也增加了 FTP 的复杂性。

小贴士

关键概念 与大多数协议不同,FTP 不使用单个 TCP 连接。当会话建立时,使用 TCP 建立一个永久的 控制连接,用于传递命令和回复。当需要发送文件或其他数据时,它们将通过创建并按需拆卸的单独 TCP 数据连接进行传递。

FTP 处理组件和术语

由于控制和数据功能是通过不同的通道进行通信的,FTP 模型将每个设备上的软件分为两个逻辑协议组件,每个组件负责一个通道。协议解释器(PI)是一段负责管理控制连接、发布和接收命令及回复的软件。数据传输过程(DTP)负责在客户端和服务器之间实际发送和接收数据。除了这两个元素之外,用户 FTP 进程还包括第三个组件,即 用户界面,它与人类 FTP 用户进行交互;它不在服务器端存在。

因此,FTP 中包含两个服务器过程组件和三个客户端(用户)过程组件。这些组件在 FTP 模型中用特定的名称来指代,这些名称在标准中用于描述协议的详细操作。我计划在本章中做同样的事情,因此现在我将更详细地描述该模型中每个设备上的组件,这些组件在图 72-1 中进行了说明。

FTP 操作模型 FTP 是一个客户端/服务器协议,客户端的用户-FTP 过程与服务器端的服务器-FTP 过程之间进行通信。命令、回复和状态信息通过控制连接在用户-PI 和服务器-PI 之间传递,该连接一旦建立就保持会话状态。数据通过为每次传输设置的数据连接在设备之间移动。

图 72-1. FTP 操作模型 FTP 是一个客户端/服务器协议,客户端的用户-FTP 过程与服务器端的服务器-FTP 过程之间进行通信。命令、回复和状态信息通过控制连接在用户-PI 和服务器-PI 之间传递,该连接一旦建立就保持会话状态。数据通过为每次传输设置的数据连接在设备之间移动。

服务器-FTP 过程组件

服务器-FTP 过程包含两个协议元素:

服务器协议解释器(Server-PI) 协议解释器负责管理服务器上的控制连接。它监听主保留 FTP 端口,等待来自用户的连接请求(客户端)。一旦建立连接,它接收来自用户-PI 的命令,发送回回复,并管理服务器数据传输过程。

服务器数据传输过程(Server-DTP) 服务器端的 DTP 用于向用户-DTP 发送或接收数据。服务器-DTP 可以建立数据连接或监听来自用户的连接。它与服务器的本地文件系统交互,以读取和写入文件。

用户-FTP 过程组件

用户-FTP 过程包含三个协议元素:

用户协议解释器(User-PI) 这个协议解释器负责管理客户端的控制连接。它通过向服务器-PI 发出请求来启动 FTP 会话。一旦建立连接,它处理从用户界面接收到的命令,将它们发送到服务器-PI,并接收回复。它还管理用户数据传输过程。

用户数据传输过程(User-DTP) 用户侧的 DTP 向服务器-DTP 发送或接收数据。用户-DTP 可以建立数据连接或监听来自服务器的数据连接。它与客户端设备的本地文件系统交互。

用户界面 用户界面为人类用户提供了一个更友好的 FTP 接口。它允许使用更简单的面向用户的命令来执行 FTP 功能,而不是使用一些加密的内部 FTP 命令,并允许将结果和信息传达给操作 FTP 会话的人。

提示

关键概念 服务器-FTP 进程和用户-FTP 进程都包含一个协议解释器(PI)元素和一个数据传输过程(DTP)元素。服务器-PI用户-PI通过 FTP 控制连接在逻辑上连接;服务器-DTP用户-DTP通过数据连接在逻辑上连接。用户-FTP 进程包括第三个组件,即用户界面,它为人类用户提供了一种更友好的 FTP 接口,允许使用更简单的面向用户的命令来执行 FTP 功能,而不是使用一些加密的内部 FTP 命令,并允许将结果和信息传达给操作 FTP 会话的人。

第三方文件传输(代理 FTP)

FTP 标准实际上定义了一个用于替代协议使用方式的独立模型。在这种技术中,一个主机上的用户从一个服务器向另一个服务器执行文件传输。这是通过打开两个控制连接来完成的:一个从用户的机器上的用户-PI 到两个服务器上的两个服务器-PI。然后,在每个服务器上调用一个服务器-DTP 来发送数据;用户-DTP 没有被使用。

这种方法,有时被称为第三方文件传输代理 FTP,目前在市场上并不常见。其主要原因在于它引发了安全担忧,并且在过去曾被滥用。因此,尽管它值得提及,但我不会在我的 FTP 介绍中进一步讨论它。

FTP 控制连接建立、用户认证和匿名 FTP 访问

您刚刚看到了 FTP 如何使用在 FTP 客户端(用户)和 FTP 服务器之间建立的独立逻辑数据和控制通道。在可以使用数据连接发送实际文件之前,必须建立控制连接。遵循特定的过程来设置此连接,从而在可以用于文件传输的设备之间创建永久的 FTP 会话。

与其他客户端/服务器协议一样,FTP 服务器在控制连接过程中假定一个被动角色。服务器协议解释器(服务器-PI)监听为 FTP 控制连接保留的特殊知名 TCP 端口:端口 21。用户-PI 通过从用户设备到该端口的服务器打开 TCP 连接来启动连接。它在 TCP 连接中使用一个临时端口号作为其源端口。

一旦建立了 TCP 连接,设备之间的控制连接就建立起来,允许从用户-PI 向服务器-PI 发送命令,并回送响应代码。在通道运行后的首要任务是用户认证,FTP 标准称之为登录序列。这个过程有两个目的:

访问控制 认证过程允许将服务器访问限制仅限于授权用户。它还允许服务器控制每个用户具有哪些类型的访问权限。

资源选择 通过识别建立连接的用户,FTP 服务器可以做出关于向用户提供哪些资源的决定。

FTP 登录序列和认证

FTP 的常规认证方案相当基础:它是一个简单的用户名/密码登录方案,如图 72-2 所示。我们大多数人都熟悉这种类型的认证,无论是在互联网上还是在其他地方。首先,通过使用 USER 命令从用户-PI 向服务器-PI 发送用户名来识别用户。然后,使用 PASS 命令发送用户的密码。

服务器将用户名和密码与其用户数据库进行核对,以验证连接用户是否有有效权限访问服务器。如果信息有效,服务器将向客户端发送问候以表明会话已打开。如果用户认证不正确(指定了错误的用户名或密码),服务器将要求用户再次尝试授权。在多次无效授权尝试后,服务器可能会超时并终止连接。

假设认证成功,服务器随后建立连接以允许用户有权访问的类型。某些用户可能只能访问某些文件或某些类型的文件。某些服务器可能允许特定用户在服务器上读写文件,而其他用户可能只能检索文件。管理员可以根据需要调整 FTP 访问权限。

FTP 连接建立和用户认证 FTP 会话从客户端和服务器之间建立 TCP 连接开始。客户端随后发送用户名和密码以验证服务器。假设服务器接受这些信息,它将发送一个问候回复给客户端,会话即打开。

图 72-2. FTP 连接建立和用户认证 FTP 会话从客户端和服务器之间建立 TCP 连接开始。客户端随后发送用户名和密码以验证服务器。假设服务器接受这些信息,它将发送一个问候回复给客户端,会话即打开。

一旦建立连接,服务器也可以根据用户的身份做出资源选择决策。例如,在多用户系统中,管理员可以设置 FTP,使得任何用户连接时,都会自动被带到她的个人主目录。可选的 ACCT(账户)命令还允许用户在拥有多个账户时选择特定的账户。

FTP 安全扩展

与大多数较老的协议一样,FTP 使用的简单登录方案是早期互联网相对封闭性质的遗产。它不符合当今全球互联网的安全标准,因为用户名和密码以明文形式通过控制连接发送。这使得登录信息被中间系统拦截相对容易,账户也可能被破坏。RFC 2228,“FTP 安全扩展”为那些需要在 FTP 软件中增加安全性的用户定义了更复杂的认证和加密选项。

小贴士

关键概念 FTP 会话从 FTP 客户端和服务器之间建立控制连接开始。在 TCP 连接建立后,用户必须通过客户端和服务器之间简单的用户名/密码交换来验证服务器。这仅提供了基本的安全保障,因此如果需要更高的安全性,必须通过 FTP 安全扩展或其他方式来实现。

匿名 FTP

可能令人惊讶的是,许多组织并没有看到提高安全级别的重要性。实际上,这些组织采取了相反的方向:它们使用 FTP 而不进行任何认证。但任何企业为什么要允许任何人访问其 FTP 服务器呢?答案很简单:任何想要使用服务器的人都可以用来向公众提供信息。

现在,大多数组织使用万维网向客户和其他希望获取文件的人分发文档、软件和其他文件。但在 20 世纪 80 年代,在万维网变得流行之前,FTP 常被用来分发此类信息。例如,如果今天你有一张 3Com 网络接口卡并想获取其驱动程序,你会去访问网络服务器www.3com.com,但几年前,你可能需要访问 3Com 的 FTP 服务器(ftp.3com.com)来下载驱动程序。

显然,要求每位客户在这样一个服务器上都有一个用户名和密码将是非常困难的。因此,1994 年发布的 RFC 1635 定义了该协议的一种用途,称为匿名 FTP。在这种技术中,客户端连接到服务器,并提供一个默认用户名以作为访客登录。通常支持匿名ftp这样的名称。看到这个名称后,服务器会回送一条特殊消息,例如“访客登录成功,请发送您的完整电子邮件地址作为密码。”在这种情况下,密码实际上并不是密码;它只是用来允许服务器记录谁在访问它。

然后,访客能够访问该网站,尽管服务器通常会严格限制系统上访客的访问权限。许多 FTP 服务器同时支持已识别和匿名访问,授权用户拥有更多权限(例如能够遍历完整的目录路径,以及有删除或重命名文件的权限),而匿名用户仅限于从为公共访问设置的特定目录中读取文件。

小贴士

关键概念 许多 FTP 服务器支持匿名 FTP,这允许没有服务器账户的访客有限地访问服务器资源。这通常用于希望向公众提供文件的组织,例如技术支持、客户支持或分发。

FTP 数据连接管理

使用 FTP 连接建立和认证过程在服务器-PI 和用户-PI 之间创建的控制通道在整个 FTP 会话期间保持开放。在控制通道上,协议解释器交换命令和回复,但不传输数据。

每次需要在服务器和用户 FTP 进程之间发送文件或其他数据时,必须创建一个数据连接。数据连接将用户-DTP 与服务器-DTP 连接起来。此连接对于显式文件传输操作(获取或接收文件)和隐式数据传输(例如从服务器上的目录请求文件列表)都是必需的。

FTP 标准指定了创建数据连接的两种不同方式,尽管它并没有以非常容易理解的方式解释它们。这两种方法主要区别在于哪个设备——客户端或服务器——发起连接。这最初可能看起来像是一件微不足道的事情,但正如你很快就会看到的,这实际上非常重要。

正常(主动)数据连接

第一种方法有时被称为创建一个正常数据连接(因为它默认是方法)有时也称为主动数据连接(与我们将要讨论的被动方法相对)。在这种类型的连接中,服务器-DTP 通过打开到用户-DTP 的 TCP 连接来启动数据通道。服务器使用特殊的保留端口号 20(比知名的控制 FTP 端口号 21 小 1)进行数据连接。在客户端机器上,默认使用的端口号与用于控制连接的临时端口号相同,但正如你很快就会看到的,客户端通常会为每次传输选择不同的端口号。

让我们用一个例子来看看它是如何工作的。假设用户-PI 从其临时端口号 1678 建立了一个到服务器 FTP 控制端口 21 的控制连接。然后,为了创建数据传输的数据连接,服务器-PI 会指示服务器-DTP 从服务器的端口 20 到客户端的端口 1678 发起一个 TCP 连接。客户端会确认这一点,然后就可以进行数据传输(双向——记住 TCP 是双向的)。

实际上,将客户端的控制和数据连接放在同一个端口上不是一个好主意;它会复杂化 FTP 的操作,并可能导致一些棘手的问题。因此,强烈建议在数据传输之前,客户端使用 PORT 命令指定不同的端口号。例如,假设客户端使用 PORT 指定了端口号 1742。那么,服务器-DTP 就会从其端口 20 创建一个连接到客户端的端口 1742,而不是 1678。这个过程在图 72-3 中展示。

被动数据连接

第二种方法被称为被动数据连接。客户端告诉服务器要处于被动状态——也就是说,接受由客户端发起的数据连接。服务器回复,向客户端提供它应该使用的服务器 IP 地址和端口号。服务器-DTP 随后监听这个端口,等待来自用户-DTP 的 TCP 连接。默认情况下,用户机器使用与控制连接相同的端口号,就像在主动情况下一样。然而,在这里,如果需要的话,客户端可以选择为数据连接使用不同的端口号(通常是临时端口号)。

让我们再次考虑我们的例子,客户端的控制连接从端口号 1678 到服务器的端口号 21,但这次考虑使用被动连接进行数据传输,如图图 72-4 所示。客户端会发出 PASV 命令告诉服务器它想要使用被动数据控制。服务器-PI 会回复一个客户端可以使用的端口号——比如说端口 2223。然后,服务器-PI 会指示服务器-DTP 监听这个端口 2223。用户-PI 会指示用户-DTP 从客户端端口 1742 到服务器端口 2223 创建连接。服务器会确认这一点,然后数据就可以发送和接收,再次是双向的。

FTP 主动数据连接 在传统的或主动的 FTP 数据连接中,服务器通过打开到客户端的数据连接来启动数据传输。在这种情况下,客户端首先发送一个 PORT 命令,告诉服务器使用端口 1742。然后,服务器从其默认端口 20 打开数据连接到客户端端口 1742。然后,使用这些端口在设备之间交换数据。

图 72-3. FTP 主动数据连接 在传统的或主动的 FTP 数据连接中,服务器通过打开到客户端的数据连接来启动数据传输。在这种情况下,客户端首先发送一个 PORT 命令,告诉服务器使用端口 1742。然后,服务器从其默认端口 20 打开数据连接到客户端端口 1742。然后,使用这些端口在设备之间交换数据。

连接方法相关的效率和安全性问题

到目前为止,你可能想知道主动和被动连接类型之间的实际区别是什么。我之前已经说过,在两种情况下,数据传输都可以双向进行。那么,谁启动数据连接有什么关系呢?这不是像争论谁打本地电话一样吗?

答案与令人恐惧的“S”词有关:安全。FTP 使用多个 TCP 连接的事实可能会给人们用来确保系统安全性的硬件和软件带来问题。

考虑到主动数据连接的情况,如图 72-3 中所述。从客户端的角度来看,存在一个从客户端端口 1678 到服务器端口 21 的控制连接。但是数据连接是由服务器发起的。因此,客户端看到的是对端口 1678(或另一个端口)的传入连接请求。由于在正常情况下,客户端是建立连接的——它们不会响应它们,许多客户端对收到此类传入连接持怀疑态度。由于传入 TCP 连接可能存在安全风险,许多客户端被配置为使用防火墙硬件或软件来阻止它们。

FTP 被动数据连接 在一个被动 FTP 数据连接中,客户端使用 PASV 命令来告知服务器等待客户端建立数据连接。服务器响应,告诉客户端它应该在服务器上使用哪个端口进行数据传输——在这个例子中,端口 2223。然后客户端使用服务器上的该端口号以及自己选择的客户端端口号(在这个例子中,1742)来打开数据连接。

图 72-4. FTP 被动数据连接 在一个被动 FTP 数据连接中,客户端使用 PASV 命令来告知服务器等待客户端建立数据连接。服务器响应,告诉客户端它应该在服务器上使用哪个端口进行数据传输——在这个例子中,端口 2223。然后客户端使用服务器上的该端口号以及自己选择的客户端端口号(在这个例子中,1742)来打开数据连接。

为什么不直接让客户端总是接受比用于控制连接的临时端号高一个数字的端口的连接呢?这里的问题是客户端经常使用 PORT 命令为每次传输使用不同的端口号。这样做是因为 TCP 的规则。正如我在第四十七章中描述的,在连接关闭后,必须经过一段时间才能再次使用该端口,以防止混淆连续的会话。这会导致在连续发送多个文件时出现延迟,因此为了避免这种情况,客户端通常为每次传输使用不同的端口号。这更有效率,但这也意味着保护客户端的防火墙需要接受看似将前往许多不可预测端口号的入站连接。

被动连接的使用在很大程度上消除了这个问题。大多数防火墙在处理入站连接到奇数端口方面比处理出站连接困难得多。RFC 1579,“防火墙友好的 FTP”详细讨论了这个问题。它建议客户端默认使用被动数据连接,而不是使用带有 PORT 命令的正常连接,以避免端口阻塞问题。

当然,被动的数据连接并不能真正消除问题;它们只是将问题推给了服务器。现在,这些服务器必须面对各种端口上的入站连接问题。然而,总的来说,在相对较少的服务器上处理安全问题比在大量客户端上更容易。FTP 服务器无论如何都必须能够接受来自客户端的被动模式传输,因此通常的做法是为这个目的预留一段端口,服务器的安全设置允许接受这些端口的入站连接,同时阻止其他端口的入站连接请求。

小贴士

关键概念 FTP 支持两种不同的模型来在客户端和服务器之间建立数据连接。在正常或主动数据连接中,当客户端请求传输时,服务器发起连接,客户端响应;在被动数据连接中,客户端告诉服务器它将发起连接,服务器响应。由于 TCP 是双向的,在两种情况下数据都可以双向流动;这两种模式的主要区别在于安全性。特别是,被动模式经常被使用,因为许多现代客户端设备无法接受来自服务器的入站连接。

另一个值得注意的问题是,在 FTP 命令(如 PORT 和 PASV)及其回复中传递 IP 地址和端口号违反了网络分层原则。这不仅仅是一个哲学问题。应用程序不应该处理端口号,这在使用某些底层技术时会引发问题。例如,考虑使用网络地址转换(NAT;见第二十八章协议")),它修改 IP 地址和可能端口的情况。为了防止 NAT 在 FTP 使用时“破坏”协议,必须采取特殊措施来处理该协议。

FTP 通用数据通信和传输模式

一旦在服务器-DTP 和用户-DTP 之间建立了数据连接,数据就会直接从客户端发送到服务器,或从服务器发送到客户端,具体取决于发出的特定命令。由于控制信息使用单独的控制通道发送,因此整个数据通道都可以用于数据通信。(这两个逻辑通道在底层与设备上的所有其他 TCP 和用户数据报协议(UDP)连接一起复用,因此这实际上并不代表性能上的提升。)

FTP 定义了三种不同的传输模式(也称为传输模式),这些模式精确地指定了数据如何在开放数据通道中从一个设备发送到另一个设备:流模式、块模式压缩模式

流模式

在流模式下,数据被简单地作为无结构的字节流连续发送。发送设备只需开始将数据推送到 TCP 数据连接的接收方。不使用具有不同标题字段的报文格式,这使得这种方法与其他许多协议以离散块发送信息的方式大不相同。它强烈依赖于 TCP 的数据流和可靠传输服务。由于没有标题结构,文件结束的指示仅由发送设备在完成时关闭数据连接来表示。

在这三种模式中,流模式在现实 FTP 实现中是最广泛使用的,主要原因有三:

  • 它是默认的,也是最简单的方法,因此最容易实现,并且对于兼容性是必需的。

  • 它是最通用的,因为它将所有文件视为简单的字节流,而不关注其内容。

  • 它是最有效的方法,因为不会浪费任何字节在标题等开销上。

块模式

块模式是一种更传统的数据传输模式,其中数据被分成数据块,并封装成单独的 FTP 块或记录。每个记录都有一个三字节的标题,指示其长度并包含有关正在发送的数据块的信息。使用一种特殊的算法来跟踪传输的数据,并检测和重新启动中断的传输。

压缩模式

压缩模式是一种传输模式,其中使用一种称为 运行长度编码 的相对简单的压缩技术来检测正在发送的数据中的重复模式,然后以这种方式表示数据,使得整体消息的字节数更少。压缩信息以类似于块模式的方式发送,使用标题加有效负载记录格式。

表面上看,压缩模式似乎很有用。然而,在实践中,压缩通常在网络软件堆栈的其他地方实现,使得在 FTP 中变得不必要。例如,如果你正在使用模拟调制解调器通过互联网传输文件,你的调制解调器通常在第一层执行压缩。FTP 服务器上的大文件也经常使用类似 ZIP 格式的某种东西进行压缩,这意味着进一步的压缩没有意义。

小贴士

关键概念 FTP 包含三种不同的 传输模式:流模式、块模式和压缩模式。在流模式下,这是最常用的模式,数据以连续的字节序列发送。在块模式下,数据被格式化为带有标题的块。在压缩模式下,字节使用运行长度编码进行压缩。

FTP 数据表示:数据类型、格式控制和数据结构

设计 FTP 的最通用方式可能是将其设计为将所有文件视为“黑盒”。文件将被表示为一组字节。FTP 不会关注文件包含的内容,而是一字节一字节地将文件从一个地方移动到另一个地方。在这种情况下,FTP 似乎与大多数文件系统上实现的复制命令非常相似,后者同样创建一个副本,而不会查看文件的内容。

那么,这会有什么问题呢?你可能想知道。嗯,对于某些类型的文件,这正是我们想要的,但对于其他文件,这会引入问题。某些类型的文件在不同的系统上使用不同的表示形式。如果你在同一台电脑上使用复制命令从一个地方复制文件到另一个地方,就没有问题,因为在该电脑内部,文件使用的是相同的表示形式。但是,当你将其复制到使用不同表示形式的电脑上时,你可能会遇到困难。

最常见的例子可能会让你感到惊讶:简单的文本文件。所有 ASCII 文本文件都使用 ASCII 字符集,但它们在标记文本行结束的控制字符上有所不同。在 UNIX 上,使用换行符(LF);在苹果电脑上,使用回车符(CR);而 Windows 机器则两者都使用(CR+LF)。

如果你使用常规 FTP 将文本文件从一个系统类型移动到另一个系统,数据将完全按照原样移动。将文本文件从 UNIX 系统移动到 PC 作为一组字节意味着程序将无法正确识别行结束标记。为了避免这种困境,FTP 超越了所有文件只是字节的想法,并融入了一些智能来处理不同类型的文件。FTP 标准通过允许在传输之前指定有关文件内部表示的一些细节来认可这一点。

FTP 数据类型

关于文件可以提供的第一条信息是其数据类型,它决定了文件的整体表示。FTP 标准中指定了四种不同的数据类型:

ASCII 此数据类型定义了一个 ASCII 文本文件,行由某种类型的行结束标记标记。

EBCDIC 从概念上讲,EBCDIC 与 ASCII 类型相同,但它用于使用 IBM 的 EBCDIC 字符集的文件。

图像 使用图像数据类型,文件没有正式的内部结构,并且每次发送一个字节,没有任何处理;这就是之前提到的黑盒模式。

本地 此数据类型用于处理可能存储在包含多于八个比特的逻辑字节中的数据的文件。指定此类型以及数据结构的方式允许数据以与本地表示一致的方式存储在目标系统上。

注意

术语字节传统上指代八个比特,但严格来说,描述八个比特的术语是八位组。在某些系统中,一个字节实际上可能包含多于八个比特。有关详细信息,请参阅第四章中的“二进制信息和表示:比特、字节、半字节、八位组和字符”

在实践中,最常使用的两种数据类型是 ASCII 和图像。ASCII 类型用于文本文件,并允许它们在自动转换行结束码的系统之间移动。图像类型用于通用二进制文件,例如图形图像、ZIP 文件以及其他以通用方式表示的数据。因此,它也常被称为二进制类型。

ASCII 数据类型行分隔问题

当使用 ASCII 数据类型时,系统之间内部表示的差异通过使用一种通用的外部表示来处理,这种表示充当一种通用语言。正在传输的文件行由发送 FTP 进程从发送方的内部表示转换为 Telnet 协议(NETASCII)使用的中性 ASCII 表示,每行以 CR+LF 结束。接收设备然后将此中性表示转换为接收方文件系统使用的内部格式。

例如,当使用 FTP 将文本文件从 Macintosh 传输到 UNIX 系统时,每行中的 CR 都会被转换为 CR+LF,以便通过 FTP 数据通道进行传输。接收的 UNIX 系统会将每个 CR+LF 转换为仅 LF,以便 UNIX 程序能够正确读取。

注意,由于这些变化,如果使用 ASCII 模式在不同系统之间传输,生成的文件可能比原始文件大或小。此外,由于 FTP 通过转换为通用表示来工作,因此从 UNIX 系统发送 ASCII 文件到 UNIX 系统意味着每个 LF 都会被转换为 CR+LF 进行传输,然后接收方会将其转换回 LF。这稍微有点低效,但不是什么大问题。

确保使用适当的用户命令指定正确的数据类型非常重要。在没有设置 ASCII 模式的情况下,在类似系统之间发送文本文件会导致在目标系统上无法正确读取的文件,或者包含杂乱字符的文件。相反,二进制文件必须以二进制模式发送。如果您以 ASCII 模式发送类似 ZIP 文件或 JPG 图形,FTP 软件会认为它是一个文本文件。它会将文件当作文本处理,并且每次遇到文件中看起来像 CR、LF 或 CR+LF 的字节时,都会将其转换,而这正是您不希望发生的。(设置错误的数据类型是使用 FTP 在 PC 和 UNIX 系统之间移动文件时文件损坏的主要原因之一。我有经验!)

提示

关键概念 FTP 定义了四种数据类型:ASCII、EBCDIC、图像本地ASCIIEBCDIC分别用于 ASCII 和 EBCDIC 字符集中的文本文件。图像类型用于没有特定结构的文件。本地类型用于本地表示。ASCII 类型很重要,因为它允许在可能使用不同方法指示文本行结束的文件系统之间成功传输文本文件。图像类型,也称为二进制,用于必须逐字节发送和接收且不进行转换的文件,例如可执行文件、图形和任意格式的文件。

FTP 格式控制

对于 ASCII 和 EBCDIC 类型,FTP 定义了一个可选参数,称为格式控制,允许用户指定用于描述文件的特定表示方式,以使用垂直格式。格式控制选项是为了处理从主机设备传输到打印机的文件而创建的。据我所知,今天不再使用(或者如果使用,也仅限于特殊应用)。

可以使用三种选项进行此控制:

非打印 这是默认设置,表示没有垂直格式。

Telnet 格式 文件使用 Telnet 协议中指定的垂直格式控制字符。

回车控制/FORTRAN 文件使用格式控制字符,作为每行的第一个字符,如 FORTRAN 编程语言中指定的那样。

FTP 数据结构

除了指定文件的数据类型外,还可以以三种方式指定文件的数据结构:

文件结构 文件是一个没有内部结构的连续字节流。这是默认设置,用于大多数类型的文件。

记录结构 文件由一系列顺序记录组成,每个记录都由一个记录结束标记分隔。记录结构可用于 ASCII 文本文件,但这些文件更常见的是使用 ASCII 数据类型与常规文件结构一起发送。

页面结构 文件包含一组特殊索引数据页面。这种结构不常用;它最初是为早期 ARPAnet 中使用的现已过时的计算机类型创建的。

FTP 内部命令组和协议命令

一旦 FTP 服务器与用户之间建立连接,所有用于管理协议操作的通信都将在控制通道中进行。用户-PI 向服务器-PI 发送协议命令,服务器-PI 处理这些命令并采取适当的行动。服务器-PI 以回复代码的形式响应,告知用户-PI 其发出的命令的结果,并传达其他重要信息。

有趣的是,FTP 命令在控制通道中的实际传输是使用基于 Telnet 协议的规范进行的。您可能还记得本章前面的“FTP 概述、历史和标准”部分,Telnet 和 FTP 是两个非常古老的 TCP/IP 应用程序,前者用于直接网络使用,后者用于间接资源访问。它们是在大约同一时间开发的,而设置 FTP 控制通道以作为 Telnet 连接的一种类型,是互联网标准试图不重复造轮子的一个很好的例子。

FTP 命令组和命令

每个命令都通过一个简短的三或四字母命令代码来识别,以便于使用,并且命令在 FTP 的整体功能中执行特定的任务。有几十个这样的协议命令可用,为了帮助组织它们,FTP 标准根据整体功能类型将它们分为三组:

访问控制命令 这些命令是用户登录和身份验证过程的一部分,用于资源访问,或是一般会话控制的一部分。参见表 72-1。

传输参数命令 指定数据传输参数的命令。例如,本组中的命令指定要发送的文件的数据类型,指示是否使用被动或主动数据连接,等等。参见表 72-2。

FTP 服务命令 执行实际文件操作的命令,例如发送和接收文件,以及实现支持功能,如删除或重命名文件。这是最大的组。见表 72-3。

提示

关键概念 FTP 操作通过 FTP 客户端向 FTP 服务器发出协议命令来控制。每个命令都有一个三或四字母的命令代码,表示其功能。命令被组织成三个组:访问控制命令用于登录和一般会话控制,传输参数命令用于控制传输方式,以及FTP 服务命令用于执行实际文件操作。

由于这些命令基于 Telnet 规范,它们按照 Telnet 的网络虚拟终端(NVT)约定以纯文本形式发送。表表 72-1、表 72-2 和表 72-3 列出并描述了 FTP 内部协议命令,包括访问控制、传输参数和服务命令组。它们按照在 FTP 标准(RFC 959)中出现的顺序展示。

表 72-1. FTP 访问控制命令

命令代码 命令 描述
USER 用户名 识别尝试建立 FTP 会话的用户。
PASS 密码 在登录认证期间指定由 USER 命令之前给出的用户的密码。
ACCT 账户 在 FTP 会话期间指定已验证用户的账户。仅在需要单独识别的系统上使用;大多数系统根据 USER 命令中输入的名称自动选择账户。
CWD 更改工作目录 允许用户在 FTP 会话期间指定不同的目录进行文件传输。
CDUP 切换到父目录("更改目录向上") CWD 命令的特殊情况,用于进入服务器目录结构中的一级目录。它被单独实现,以抽象出不同文件系统之间的目录结构差异;用户可以使用 CDUP 而不是知道在服务器上导航目录树的具体语法。
SMNT 结构挂载 允许用户挂载特定的文件系统以访问不同的资源。
REIN 重新初始化 重新初始化 FTP 会话,清除所有设置的参数和用户信息。这使会话回到控制连接刚刚建立时的状态。本质上,它是 USER 命令的相反操作。接下来的命令通常是 USER,用于登录不同的用户。
QUIT 登出 终止 FTP 会话并关闭控制连接。请注意,此命令的命名是不幸的。REIN 命令实际上与传统的登出命令最为相似,因为它终止已登录用户并允许其他用户登录。相比之下,QUIT 命令关闭整个会话。

表 72-2. FTP 传输参数命令

命令代码 命令 描述
PORT 数据端口 用于告诉 FTP 服务器客户端希望在特定端口号上接受一个主动数据连接。
PASV 被动 请求 FTP 服务器允许用户-DTP 发起被动数据连接。
TYPE 表示类型 指定要传输的文件的数据类型(ASCII、EBCDIC、图像或本地),以及可选的格式控制(非打印、Telnet 或换行控制)。
STRU 文件结构 指定文件的数据结构(文件、记录或页面)。
MODE 传输模式 指定要使用的传输模式(流、块或压缩)。

表 72-3. FTP 协议服务命令

命令代码 命令 描述
RETR 下载 告诉服务器向用户发送一个文件。
STOR 存储 向服务器发送一个文件。
STOU 存储唯一 与 STOR 类似,但指示服务器确保文件在当前目录中有唯一的名称。这用于防止覆盖可能已经存在的同名文件。服务器会回复用于文件的名称。
APPE 追加(与创建一起) 与 STOR 类似,但如果指定的文件名已存在,则发送的数据将附加到它而不是替换它。
ALLO 分配 一个可选命令,用于在发送文件之前在服务器上预留存储空间。
REST 重新启动 在特定的服务器标记处重新启动文件传输。仅用于块或压缩传输模式。
RNFR 重命名自 指定要重命名的文件的旧名称。参见 RNTO 命令。
RNTO 重命名到 指定要重命名的文件的新的名称。与 RNFR 命令一起使用。
ABOR 中断 告诉服务器中断最后一个 FTP 命令和/或当前的数据传输。
DELE 删除 在服务器上删除指定的文件。
RMD 删除目录 在服务器上删除一个目录。
MKD 创建目录 创建一个目录。
PWD 打印工作目录 显示 FTP 会话的当前服务器工作目录;显示用户在服务器文件系统中的位置。
LIST 列表 请求从服务器获取当前目录的内容列表,包括名称和其他信息。在概念上类似于 DOS/Windows 中的DIR命令或 UNIX 中的ls命令。
NLST 名称列表 与 LIST 类似,但仅返回目录中的名称。
SITE 站点参数 用于实现特定站点的功能。
SYST 系统 请求服务器向客户端发送有关服务器操作系统的信息。
STAT 状态 提示服务器发送关于当前正在进行的文件或传输状态的指示。
HELP 帮助 向服务器请求可能有助于用户确定如何使用服务器的任何帮助信息。
NOOP 无操作 不执行任何操作,除了提示服务器向客户端发送一个“OK”响应以验证控制通道是否活跃。

注意

FTP 命令对大小写不敏感,但在表格表 72-1、表 72-2 和表 72-3 中为了清晰起见,已显示为大写字母

FTP 命令都是在 FTP 元素之间发送的;它们通常不是由用户直接发出的。相反,使用一套特殊的用户命令来完成这个目的。FTP 用户界面实现了用户与用户-FTP 进程之间的连接,包括将用户命令转换为 FTP 命令。我们将在本章后面探讨这些命令。

FTP 响应

每当用户-PI 通过控制连接向服务器-PI 发送命令时,服务器都会发送一个回复。FTP 响应有三个主要用途:

  • 它们作为服务器已接收命令的确认。

  • 它们告诉用户设备命令是否被接受,如果发生错误,错误是什么。

  • 它们将各种类型的信息传达给会话用户,例如传输的状态。

使用文本和数字响应的优点

对于人类用户来说,一串回复文本就足以满足上述要求,FTP 响应确实包括描述性文本。但只有文本字符串会使客户端的 FTP 软件难以或无法解释来自服务器的结果。FTP 被设计成允许软件应用程序通过 FTP 命令链相互交互。因此,该协议的回复系统使用响应代码

FTP 响应代码是三位数字响应,可以很容易地被计算机程序解释。它们对熟悉 FTP 的人类用户也很有用,因为它们可以一目了然地传达各种操作的结果。虽然每个 FTP 服务器实现可能对每种类型响应发送的文本不同,但响应代码的使用方式是基于 FTP 标准的规范。因此,检查代码以确定命令的结果;文本只是描述性的。

响应代码结构和数字解释

为了使回复代码更加有用,它们不是按线性或随机顺序分配的。相反,使用了一种特殊的编码方案,其中每个代码有三个数字,每个数字都传达特定类型的信息并对回复进行分类。一个代码可以被认为是xyz的形式,其中x是第一位数字,y是第二位,z是第三位。

第一位数字表示命令在一般意义上的成功或失败,成功的命令是否完整,以及是否应该重试失败的命令。表 72-4 显示了可能的值。

表 72-4. FTP 回复代码格式:第一位数字解释

回复代码格式 含义 描述
1yz 正初步回复 表示命令已被接受且处理仍在进行中的初始响应。用户应在发送新命令之前期待另一个回复。
2yz 正完成回复 命令已成功处理并完成。
3yz 正中间回复 命令已被接受,但处理已被延迟,等待接收更多信息。这种回复用于命令序列的中间。例如,在收到 USER 命令后但在发送匹配的 PASS 命令之前,它用作身份验证序列的一部分。
4yz 临时负完成回复 命令未被接受且未采取任何行动,但错误是临时的,可以再次尝试该命令。这用于可能是暂时故障或可能改变的条件所导致的错误——例如,当请求文件时,由于其他资源正在访问它,文件正忙。
5yz 永久负完成回复 命令未被接受且未采取任何行动。再次尝试相同的命令很可能会导致另一个错误。例如,请求服务器上找不到的文件,或发送无效命令(如 BUGU)将属于此类。

回复代码的第二位数字用于将消息分类到功能组中。这些组在表 72-5 中显示。

表 72-5. FTP 回复代码格式:第二位数字解释

回复代码格式 含义 描述
x0z 语法 语法错误或杂项消息
x1z 信息 对信息请求的回复,如状态请求
x2z 连接 与控制连接或数据连接相关的回复
x3z 认证和计费 与登录程序和计费相关的回复
x4z 未指定 未定义
x5z 文件系统 与服务器文件系统相关的回复

第三个数字表示第二个数字描述的功能组中的特定消息类型。第三个数字允许每个功能组对于第一个代码数字(初步成功、暂时性失败等)给出的每种回复类型都有十个不同的回复代码。

这些x, yz数字含义的组合形成了特定的回复代码。例如,考虑回复代码 530,如图图 72-5。第一个数字告诉你这是一个永久性负面回复,第二个数字表示它与登录或计费相关。(实际上,这是在登录失败时接收到的错误消息。)第三个数字告诉你发生了特定类型的错误。

FTP 回复代码格式 此图展示了三位 FTP 回复代码格式的解释。在回复代码 530 中,数字 5 表示永久错误,数字 3 指定错误与认证或计费相关,而数字 0 是具体的错误类型。在许多其他 TCP/IP 应用协议中,包括简单邮件传输协议(SMTP)和超文本传输协议(HTTP)的回复代码中,也使用了类似的方法。

图 72-5. FTP 回复代码格式 此图展示了三位 FTP 回复代码格式的解释。在回复代码 530 中,数字 5 表示永久错误,数字 3 指定错误与认证或计费相关,而数字 0 是具体的错误类型。在许多其他 TCP/IP 应用协议中,包括简单邮件传输协议(SMTP)和超文本传输协议(HTTP)的回复代码中,也使用了类似的方法。

使用编码的回复代码允许代码本身立即传达信息,并提供了一种保持不同类型响应组织的方式。这个想法被其他几个应用协议所采用,包括用于电子邮件的简单邮件传输协议(SMTP)、用于网络新闻的网络新闻传输协议(NNTP)和用于万维网的超文本传输协议(HTTP)。

表 72-6 包含了从 RFC 959 中摘取的一些更常见的 FTP 回复代码列表。它们按数字顺序排列,并展示了在该文档中作为典型示例的回复文本以及所需的其他描述性信息。

表 72-6. FTP 回复代码

回复代码 典型回复文本 描述
110 重启标记回复。 在块模式下传输时作为标记重启功能的一部分使用。
120 服务在 nnn 分钟后就绪。 nnn 表示服务将可用的分钟数。
125 数据连接已打开;传输开始。
150 文件状态正常;即将打开数据连接。
200 命令正常。 有时文本会指示成功执行的命令名称。
202 命令未实现,或在此站点多余。
211 系统状态,或系统帮助回复。 将包含特定于系统的状态或帮助信息。
212 目录状态。
213 文件状态。
214 帮助信息。 包括对服务器的人类用户有用的帮助信息。
215 NAME 系统类型。 NAME 是操作系统类型名称。通常在响应 SYST 命令时发送。
220 服务就绪,等待新用户。 在发送 USER 命令之前建立命令通道时发送。
221 服务关闭控制连接。 在会话关闭时发送“再见”消息。
225 数据连接已打开;没有传输进行。
226 关闭数据连接。 在成功传输文件或文件中止后发送。
227 进入被动模式(h1,h2,h3,h4,p1,p2)。 作为对 PASV 命令的回复发送,指示用于数据连接的 IP 地址和端口号。
230 用户已登录,继续。 在成功进行 USER 和 PASS 认证后发送。系统通常在登录后使用此代码发送额外的问候或其他信息。
250 请求的文件操作正常,完成。 文本描述将提供有关成功完成的更多详细信息,例如确认更改目录或已删除文件。
257 PATHNAME 已创建。 PATHNAME 被替换为创建的路径。
331 用户名正确,需要密码。 在发送 USER 但在发送 PASS 之前的中继结果。
332 需要账户登录。
350 请求的文件操作待进一步信息。
421 服务不可用,关闭控制连接。 有时在 FTP 服务器正在关闭的过程中发送。
425 无法打开数据连接。
426 连接关闭;传输已取消。
450 请求的文件操作未执行。文件不可用。 文件不可用;例如,它可能被另一个用户锁定。与回复代码 550 对比。
451 请求的操作已取消:处理中的本地错误。
452 请求的操作未执行。系统存储空间不足。 文件系统已满。
500 语法错误,命令不可识别。 发送了不良或过长的命令行。
501 参数或参数中的语法错误。
502 命令未实现。
503 命令序列错误。
504 对于该参数未实现命令。
530 未登录。 如果由于用户名错误或密码不正确而导致身份验证失败,则发送。
550 请求的操作未执行。文件不可用。 文件未找到或用户无法访问。此错误代码可能在用户尚未成功登录时作为对任何文件传输命令的回复发送。与回复代码 450 相对比。
551 请求的操作被终止:页面类型未知。
552 请求的文件操作被终止。超出存储分配。
553 请求的操作未执行。文件名不允许。

提示

关键概念 每个由 FTP 客户端发送的命令都会导致 FTP 服务器发送一个回复。FTP 回复由一个三位数的数字 回复代码 和一行描述性文本组成。回复代码用于标准化 FTP 回复,以便它们可以被客户端软件解释,并且经验丰富的用户可以一眼看出命令的结果。回复代码的结构使得前两位数字表示回复的类型及其所属的类别。

FTP 多行文本回复

回复可能包含多行文本。在这种情况下,每一行都以回复代码开头,除了最后一行之外,回复代码和回复文本之间有一个连字符,以表示回复的继续。最后一行在回复代码和回复文本之间包含一个空格,就像单行回复一样。此功能通常用于用户登录后通过 230 回复代码提供额外的响应信息。示例 72-1 包含了一个示例。

示例 72-1. FTP 多行文本回复示例

230-Welcome user to FTP server jabberwockynocky.
230-
230-You are user #17 of 100 simultaneous users allowed.
230-
230-
230-Please see the file "faq.txt" for help using this server.
230-
230 Logged in.

正如我提到的,每个回复代码的实际文本字符串是特定于实现的。有时你可以找到一些与这些错误消息相关的一些相当幽默的文本字符串。例如,我尝试使用我的一个互联网账户上的 FreeBSD FTP 客户端发送了一些命令。在我登录之前,我尝试发送或接收一个文件,它没有返回像“请求的操作未执行。文件不可用。”这样的错误,而是告诉我:“先登录,然后我可能让你做那件事。”

FTP 用户界面和用户命令

FTP 命令集提供了一套丰富、完整的指令,用于实现 FTP。一个人类用户可以使用这些命令直接与 FTP 服务器执行文件传输功能。但要做到这一点,用户必须对 FTP 的工作方式有深入了解。用户必须确切知道在何时发送哪些命令,以及它们的顺序。

了解内部 FTP 命令可能是一个网络专家的合理任务,但不是典型 TCP/IP 应用程序用户的任务。因此,FTP 协议定义了一个额外的协议组件,作为用户-FTP 过程的一部分:FTP 用户界面。它为 FTP 用户提供了三个主要好处:

用户友好性 FTP 用户界面以比发出协议命令更容易、更简单的方式向人类用户展示 FTP。用户界面不需要用户了解所有那些四字母代码,可以允许使用更直观的人类语言命令来执行功能。例如,我们可以说 get 一个文件,而不是必须使用 RETR 命令。

定制 执行特定功能的命令可以根据网络行业的常用术语进行定制,而无需对 FTP 本身进行更改。例如,图像传输模式现在也通常称为二进制模式,因此创建了一个名为 binary 的用户命令来设置此模式。

细节抽象和命令序列简化 单个用户命令可以发出多个 FTP 协议命令,隐藏内部 FTP 细节,使协议更容易使用。特别是,与维护连接和其他用户不希望处理的开销问题相关的命令可以自动化。例如,FTP 客户端通常在每个数据传输之前发出 PASV 或 PORT 命令。用户界面可以在用户告诉 FTP 获取或发送文件时,自动在 RETR 或 STOR 命令之前发出此命令。

命令行和图形化 FTP 界面

传统上,FTP 客户端使用 命令行界面。在这种熟悉的安排中,FTP 客户端被调用,用户会自动被要求输入用户名和密码以建立 FTP 会话。然后用户会看到一个命令提示符,用户可以在其中输入各种 FTP 命令以执行不同的功能。服务器返回的文本响应会显示给用户,以指示各种命令的结果。通常,客户端发送的内部协议命令(如 PASV 和 STOR)会被抑制以避免屏幕杂乱,但在调试模式下可以启用显示。

命令行工具效率高,但有些人并不喜欢它们。在现代图形操作系统和应用程序的背景下,它们显得有些“老式”。因此,许多现代 FTP 客户端本质上是图形化的。它们允许用户通过点击按钮而不是输入命令来执行操作。一些 FTP 客户端允许通过从本地文件系统显示拖放到远程服务器上的显示来传输文件。这使得 FTP 更加易于使用。

小贴士

关键概念 FTP 用户界面 是 FTP 客户端中充当人类用户和 FTP 软件之间中介的组件。用户界面的存在使得 FTP 可以以友好的方式使用,而无需了解 FTP 的内部协议命令。大多数 FTP 软件使用一种理解类似英语的用户命令的 命令行界面 或一种 图形界面,其中鼠标点击和其他图形操作被转换为 FTP 命令。

常见 FTP 用户命令

要了解 FTP 客户端支持的具体命令,请参阅其文档。在命令行客户端中,您可以输入命令?以查看支持命令的列表。表 72-7 显示了在典型的 FTP 命令行客户端中遇到的常见命令,以及它们所需的典型参数。

注意这些命令中有多少实际上是同义词,例如byeexitquit。同样,您可以使用命令type ascii来设置 ASCII 数据类型或使用ascii命令。这一切都是为了用户的方便,并且是具有与 FTP 命令集不同的灵活用户界面的好处之一。

最后,使用 FTP 的另一种方法是通过指定 FTP 统一资源定位符(URL)。虽然 FTP 本质上是一个交互式系统,但 FTP URL 允许快速简单地执行简单功能,例如检索单个文件。它们还允许将 FTP 文件引用与超文本(万维网)文档集成。有关 FTP 如何使用 URL 的更多信息,请参阅“URL 方案和方案特定语法”部分,见第七十章。

表 72-7. 常见 FTP 用户命令

用户命令 描述
account <account-name> 向服务器发送 ACCT 命令以访问特定账户。
append <file-name> 使用 APPE 向文件追加数据。
ascii 设置后续传输的 ASCII 数据类型。
binary 设置后续传输的图像数据类型。与image命令相同。
bye 终止 FTP 会话并退出 FTP 客户端(与exitquit相同)。
cd <directory-path> 使用 CWD 协议命令更改远程服务器的工作目录。
cdup 返回当前工作目录的父目录。
chmod <file-name> 在 UNIX 系统上,更改文件的权限。
close 关闭特定的 FTP 会话,但用户仍停留在 FTP 命令行。
debug 设置调试模式。
delete <file-name> 在 FTP 服务器上删除一个文件。
dir [<optional-file-specification>] 列出当前工作目录的内容(或匹配指定文件名的文件)。
exit byequit的另一个同义词。
form <format> 设置传输格式。
ftp <ftp-server> 打开与 FTP 服务器的会话。
get <file-name> [<dest-file-name>] 获取一个文件。如果指定了<dest-file-name>参数,则用于获取文件的名称;否则,使用源文件名。
help [<optional-command-name>] 显示 FTP 客户端的帮助信息。与?相同。
image 设置图像数据类型,类似于binary命令。
ls [<可选文件指定>] 列出当前工作目录的内容(或符合指定的文件)。等同于 dir
mget <文件指定> 从服务器获取多个文件。
mkdir <目录名> 在远程服务器上创建目录。
mode <传输模式> 设置文件传输模式。
mput <文件指定> 向服务器发送(放置)多个文件。
msend <文件指定> mput 相同。
open <ftp 服务器> 打开到 FTP 服务器的会话(等同于 ftp)。
passive 开启或关闭被动传输模式。
put <文件名> [<目标文件名>] 将文件发送到服务器。如果指定了 <目标文件名> 参数,则用作目标主机上文件的名称;否则,使用源文件名。
pwd 打印当前工作目录。
quit 终止 FTP 会话并退出 FTP 客户端(等同于 byeexit)。
recv <文件名> [<目标文件名>] 接收文件(等同于 get)。如果指定了 <目标文件名> 参数,则用作检索到的文件的名称;否则,使用源文件名。
rename <旧文件名> <新文件名> 重命名文件。
rhelp 显示远程帮助信息,使用 FTP HELP 命令获取。
rmdir <目录名> 删除目录。
send <文件名> [<目标文件名>] 发送文件(等同于 put)。如果指定了 <目标文件名> 参数,则用作目标主机上文件的名称;否则,使用源文件名。
site 向服务器发送特定站点命令。
size <文件名> 显示远程文件的大小。
status 显示当前会话状态。
struct <结构类型> 设置文件结构。
system 显示服务器的操作系统类型。
type <数据类型> 设置传输的数据类型。
user <用户名> 以新用户身份登录到服务器。服务器将提示输入密码。
? [<可选命令名>] 显示 FTP 客户端帮助信息。等同于 help

示例 FTP 会话

现在我们已经看到了 FTP 的工作细节,让我们通过查看 FTP 客户端和服务器之间的一个示例 FTP 会话来将所有这些内容串联起来,以查看 FTP 命令和回复的实际操作。在这个例子中,我将从客户端调用 FTP 来从 FTP 服务器检索一个文本文件,然后我会从服务器及其包含的目录中删除该文件。在这个过程中,我将发出一些额外的命令来展示 FTP 的工作方式。我将在 FTP 客户端中启用调试模式,以便对于每个用户命令,您都可以看到实际生成的 FTP 命令。

表 72-8 展示了样本 FTP 会话,略有简化。第一列包含用户在 FTP 客户端输入的命令(当然,那是我输入的)。第二列显示了发送到 FTP 服务器的实际协议命令(以高亮文本显示)和服务器返回给客户端的纯文本响应。第三列包含描述性注释。

表 72-8. 样本 FTP 会话

用户命令 FTP 协议命令/FTP 服务器响应 备注

|

ftp -d
pcguide.com

|

Connected to pcguide.com.
220 ftp199.pair.com NcFTPd Server (licensed
copy) ready.
Name (pcguide.com:ixl):
这是启动 FTP 的命令。-d 选项启用调试模式。在这个初始步骤中,建立 TCP 控制连接,服务器以 220 响应码回复,表示它已准备好进行用户身份验证。FTP 客户端会自动提示输入用户名。
ixl
`USER ixl`
331 User ixl okay, need password.
我通常使用 ixl 作为用户名。在这里,FTP 客户端发送用户名,服务器响应,请求密码。
****
`PASS XXXX`
230-You are user #1 of 300 simultaneous users
allowed.
230-
230-
230-Welcome to (<system name>)
230-
230 Logged in.
`SYST`
215 UNIX Type: L8
Remote system type is UNIX.
Using binary mode to transfer files.
我输入密码,密码被发送到 FTP 服务器,服务器验证我并发回一个 230 消息。这告诉我登录成功。它还提供了额外的信息。然后 FTP 客户端自动发送一个 SYST 命令,告诉我服务器使用的是哪种类型的系统,在这个例子中是 UNIX。客户端告诉我默认选择了二进制模式;当从 UNIX 到 UNIX 进行 FTP 操作时(就像我现在这样做),这通常是默认的,因为在类似系统之间移动文本文件时不需要 ASCII 模式。
pwd
`PWD`
257 "/usr/home/ixl" is cwd.
我检查当前工作目录(cwd),服务器告诉我这是该系统上的我的主目录。
cd ftptest
`CWD ftptest`
550 No such directory.
我尝试进入一个名为 ftptest 的目录,但名字错了,所以我得到了一个 550 错误。 (我并不是真的想这么做;我忘记了目录名,但我想我还是应该向你展示一下!)
cd ftpdemo
`CWD ftpdemo`
250 "/usr/home/ixl/ftpdemo" is new cwd.
这次我输入的名字正确,服务器确认了新的工作目录。
dir
`PASV`
227 Entering Passive Mode
(ip1,ip2,ip3,ip4,193,224)
`LIST`
150 Data connection accepted from
ip5.ip6.ip7.ip8:4279; transfer starting.
-rw-r-r- 1 ixl users 16 May 22 17:47
testfile.txt
226 Listing completed.
我请求从服务器获取文件列表。FTP 客户端自动发出 PASV 命令,服务器响应并返回用于连接的端口号和 IP 地址。(出于安全原因,我没有在这里显示 IP 地址。)然后目录列表从服务器传输到客户端。
asc
`TYPE A`
200 Type okay.
我设置了 ASCII 模式,尽管我真的不需要这么做。请注意,这个客户端允许我将 ascii 命令缩写为 asc

|

get
testfile.txt

|

`PASV`
227 Entering Passive Mode
(ip1,ip2,ip3,ip4,193,226)
`RETR testfile.txt`
150 Data connection accepted from
ip5.ip6.ip7.ip8:4283; transfer starting for
testfile.txt (16 bytes).
226 Transfer completed.
17 bytes received in 0.10 seconds (0.17 KB/s)
我使用 get 命令从这个演示目录获取文件。服务器接受 PASV 命令并发送文件。传输开始时,它最初发送一个 150 响应码(初始积极响应),完成后发送 226 响应码。请注意,这里使用的端口号(服务器和客户端)与我之前进行的目录列表中的端口号不同。

|

del
testfile.txt

|

`DELE testfile.txt`
250 Deleted.
我删除了服务器上的原始文件。
cdup
`CDUP`
250 "/usr/home/ixl" is new cwd.
我返回到父目录。

|

rmdir
ftpdemo

|

`RMD ftpdemo`
250 Directory removed.
我删除了文件所在的目录。
quit
QUIT
221 Goodbye.
我结束了 FTP 会话。quit命令也会自动关闭 FTP 客户端并返回 UNIX shell。

第七十三章。简单文件传输协议 (TFTP)

无标题图片

在第七十二章")中,你看到了文件传输协议(FTP)如何实现一套完整的命令和回复功能,使用户能够执行一系列文件移动和操作任务。尽管 FTP 作为计算机之间文件传输的通用协议是理想的,但在某些类型的硬件上,它过于复杂,难以轻松实现,并且提供了实际上并不需要的更多功能。在只需要最基本文件传输功能,而简洁性和小程序大小至关重要的场合,可以使用 FTP 的伴侣协议,即简单文件传输协议 (TFTP)

本章提供了对 TFTP 操作的描述,从对协议的概述描述开始,包括其历史和动机,以及描述它的相关标准。我以一般性术语讨论其操作,涵盖 TFTP 客户端和服务器如何通信,并详细解释 TFTP 消息。然后讨论 TFTP 选项和 TFTP 选项协商机制。本章最后展示了各种 TFTP 消息格式。

小贴士

背景信息 虽然 TFTP 与 FTP 是不同的协议,但读者熟悉 FTP 时解释前者更容易。我假设读者对 FTP 有一些了解,因为它是更常用的协议。如果你在阅读第七十二章")之前来到这一章,我建议至少阅读该章节中的“FTP 概述、历史和标准”部分,然后再继续阅读

TFTP 概述、历史和标准

FTP 是 TCP/IP 互联网中大多数通用文件传输所使用的主要协议。FTP 设计者的一个目标是将协议保持相对简单,但这只可能在一定程度上实现。为了使协议能够在各种情况下以及许多类型的设备之间有用,FTP 需要一套相当大的功能和特性。因此,虽然 FTP 不像某些其他协议那样复杂,但在许多方面仍然相当复杂。

为什么需要 TFTP

FTP 的复杂性部分源于其自身协议,拥有数十条命令和回复代码,部分源于需要使用 TCP 进行连接和数据传输。对 TCP 的依赖意味着任何想要使用 FTP 的设备不仅需要 FTP 程序,还需要完整的 TCP 实现。它必须处理 FTP 对同时数据和控制通道连接的需求以及其他要求。

对于传统的计算机,如常规 PC、Macintosh 或 UNIX 工作站,这些问题实际上并不重要,尤其是在今天的大硬盘和快速、廉价的内存的情况下。但请记住,FTP 是在三十多年前开发的,当时硬件速度慢,内存昂贵。此外,即使在今天,常规计算机也不是网络中使用的唯一设备。一些网络设备没有真正的计算机功能,但它们仍然需要能够执行文件传输。对于这些设备,完整的 FTP 和 TCP 实现是一个非平凡的问题。

这种设备的显著例子之一是无盘工作站——没有永久存储的计算机,因此当它们启动时,它们不能像大多数计算机那样轻松地从硬盘读取整个 TCP/IP 实现。它们仅从少量内置软件开始,必须从服务器获取配置信息,然后从另一个网络设备下载其余的软件。对于某些没有硬盘的硬件设备,也存在同样的问题。

启动这些设备的过程通常被称为引导,并分为两个阶段。首先,工作站通过使用主机配置协议,如引导协议(BOOTP;参见第六十章"))或动态主机控制协议(DHCP;参见第第六十一章至第六十四章),获得一个 IP 地址和其他参数。其次,客户端下载软件,例如操作系统和驱动程序,使其能够在网络上像其他设备一样运行。这要求设备能够快速且轻松地传输文件。执行此引导的指令必须适合写入只读存储器(ROM)芯片,这也使得软件的大小成为一个重要问题——再次强调,尤其是在许多年前。

为了满足这一需求,创建了一个“轻量级”的 FTP 版本,该版本强调小程序大小和简单性,而不是功能性。这种新协议 TFTP 最初在 20 世纪 70 年代末开发,并于 1980 年首次标准化。现代版本TFTP 版本 2在 1981 年的 RFC 783 中进行了记录,该文件在 1992 年被修订并发布为 RFC 1350,“TFTP 协议(修订 2)”。这是当前标准的版本。

比较 FTP 和 TFTP

理解 TFTP 和 FTP 之间关系最好的方法可能是将其与传输控制协议(TCP)和用户数据报协议(UDP)在传输层的关系进行比较。UDP 是 TCP 的简化、精简的替代品,当简单性比丰富功能更重要时使用。同样,TFTP 是 FTP 的极大简化版本,只允许基本操作,并缺乏 FTP 的一些复杂功能,以保持其实施简单(甚至简单)且程序大小小。

由于其局限性,TFTP 是 FTP 的补充,而不是替代品。只有在简单性很重要而功能不足不是问题时才会使用 TFTP。它最常见的应用是引导,如上所述,尽管它可以用于其他目的。TFTP 标准为该协议描述的一个特定应用是传输电子邮件(电子邮件)。虽然该协议明确支持这一点,但今天 TFTP 并不通常用于此目的。

FTP 和 TFTP 在至少四个重要方面存在显著差异:

传输 与 TCP 和 UDP 的比较不仅基于功能/简单性权衡,而且因为 FTP 使用 TCP 进行传输,而 TFTP 使用 UDP。与 TFTP 一样,UDP 简单,这使得两者非常适合在网络设备中作为硬件程序集嵌入。

有限的命令集 FTP 包含丰富的命令集,允许文件发送、接收、重命名、删除等操作。TFTP 只允许文件发送和接收。

有限的数据表示 TFTP 不包括 FTP 的一些复杂数据表示选项;它只允许简单的 ASCII 或二进制文件传输。

缺乏认证 UDP 不使用登录机制或其他认证手段。这又是一种简化,尽管这意味着 TFTP 服务器运营商必须严格限制他们提供的可访问文件。(这也是为什么 TFTP 明确不允许客户端执行如删除等危险文件操作的原因。)

TFTP 操作概述

由于每个协议使用的传输层协议不同,TFTP 中的通信和消息与 FTP 非常不同。FTP 利用 TCP 的丰富功能,包括其流数据方向,允许它直接通过 FTP 数据连接发送数据字节。TCP 还负责为 FTP 确保数据的可靠传输,确保文件正确接收。相比之下,由于 TFTP 使用 UDP,它必须将数据打包成单独的消息,用于协议控制和数据通信。TFTP 还必须注意传输时间,以检测丢失的数据报,并在需要时重新传输。

TFTP 服务器允许 TFTP 客户端建立连接以执行文件发送和接收操作。许多运行 FTP 服务器的宿主机也会运行一个单独的 TFTP 服务器模块。TFTP 用户通过启动 TFTP 客户端程序来发起连接,该程序通常使用类似于许多 FTP 客户端的命令行界面;主要区别是 TFTP 中的命令数量要少得多。

小贴士

关键概念 对于全 FTP 既不必要也不实用的场合,开发了更简单的Trivial File Transfer Protocol (TFTP)。TFTP 与 FTP 类似,因为它用于客户端和服务器设备之间的通用文件传输,但其功能被简化了。与 FTP 不同,它包含完整的命令集并使用 TCP 进行通信,TFTP 只能用于读取或写入单个文件,并且它使用快速但不可靠的 UDP 进行传输。在需要快速且简单地传输小文件的情况下,如引导无盘工作站,它通常更受欢迎。

自从 RFC 1350 发布以来,TFTP 的基本操作没有改变,但在 1995 年该协议中增加了一个新功能。RFC 1782,“TFTP 选项扩展”定义了一种机制,通过该机制 TFTP 客户端和 TFTP 服务器可以在传输开始之前协商某些参数,这些参数将控制文件传输。这增加了 TFTP 的使用灵活性,给 TFTP 增加了一点点复杂性,但不是很多。

选项扩展与常规 TFTP 向后兼容,并且仅在服务器和客户端都支持它时才使用。两个随后的 RFC 定义了可以协商的实际选项:RFC 1783,“TFTP 块大小选项”和 RFC 1784,“TFTP 超时间隔和传输大小选项”。这组三个 RFC(1782、1783 和 1784)在 1998 年被 RFC 2347、2348 和 2349 中的更新版本所取代。

TFTP 通用操作,连接建立和客户端/服务器通信

由于在TF TP中的T代表Trivial,并且该协议被特别设计为简单,你可能认为描述它是如何工作的实际上应该是简单的,不是吗?实际上,这基本上是正确的。TFTP 通信是基于客户端/服务器的,如概述中所述。文件传输的过程包括三个主要阶段:

初始连接 TFTP 客户端通过向服务器发送初始请求来建立连接。服务器回应客户端,连接实际上就打开了。

数据传输 一旦建立连接,客户端和服务器交换 TFTP 消息。一个设备发送数据,另一个发送确认。

连接终止 当发送并确认了包含数据的最后一个 TFTP 消息后,连接就被终止了。

连接建立和识别

在 TFTP 中,连接的问题与使用 TCP 的 FTP 等协议有所不同。FTP 必须在 TCP 级别建立连接之后才能执行任何操作。然而,TFTP 使用无连接的 UDP 进行传输,因此在 TCP 中存在的那种连接不存在。在 TFTP 中,连接更多是在逻辑意义上,意味着客户端和服务器正在参与协议并交换 TFTP 消息。

TFTP 服务器持续监听在知名 UDP 端口号 69 上的请求,该端口号是为 TFTP 保留的。客户端在初始通信时选择一个临时端口号,这在 TCP/IP 中通常是这种情况。这个端口号实际上标识了数据传输,被称为传输标识符(TID)

然而,TFTP 的不同之处在于服务器还选择了一个伪随机的 TID,用于向客户端发送响应;它不是从端口号 69 发送的。这样做是因为通过使用唯一的客户端端口号和源端口号,服务器可以同时进行多个 TFTP 交换。每个传输通过源和目的端口号自动识别,因此不需要在数据消息中标识每个数据块所属的传输。这使 TFTP 头部大小降低,允许每个 UDP 消息包含更多的实际数据。

例如,假设 TFTP 客户端为其初始消息选择了一个 TID 为 3145。它会从其端口 3145 向服务器的端口 69 发送 UDP 传输。假设服务器选择了一个 TID 为 1114。它会从其端口 1114 向客户端的端口 3145 发送其回复。从那时起,客户端会向服务器端口 1114 发送消息,直到 TFTP 会话完成。

锁步客户端/服务器消息

在初始交换之后,客户端和服务器以锁步方式交换数据和确认消息。每个设备为其收到的每条消息发送一条消息:一个设备发送数据消息并等待确认;另一个设备发送确认并等待数据消息。这种严格的通信方式不如允许发送者在发送一条数据消息后继续发送另一条数据消息高效,但它很重要,因为它使 TFTP 在重要问题上的处理变得简单:重传。

与所有使用不可靠 UDP 的协议一样,TFTP 无法保证发送的消息实际上会到达目的地,因此它必须使用计时器来检测丢失的传输并重新发送。TFTP 与其他不同之处在于,客户端和服务器都会执行重传。发送数据消息的设备如果在合理的时间内没有收到确认,将会重新发送数据消息;发送确认的设备如果在没有及时收到下一个数据消息时,将会重新发送确认。这种同步通信大大简化了这一过程,因为每个设备只需同时跟踪一个未决消息。它还消除了处理诸如重新组织乱序接收到的块等复杂情况的需要(FTP 等协议依赖于 TCP 来管理这些)。

小贴士

关键概念 由于 TFTP 使用 UDP 而不是 TCP,因此不存在像 FTP 那样的显式连接概念。TFTP 会话使用逻辑连接的概念,当客户端向服务器发送请求以读取或写入文件时,该连接会被打开。客户端和服务器之间的通信以同步方式进行:一个设备发送数据消息并接收确认,以便知道数据消息已被接收;另一个设备发送确认并接收数据消息,以便知道确认已被接收。

TFTP 简化消息机制的问题

这种技术的最大缺点之一是,虽然它简化了通信,但这样做是以性能为代价的。由于一次只能有一个消息在传输中,这限制了客户端和服务器之间消息交换的吞吐量,最大为 512 字节。相比之下,当使用 FTP 时,可以大量数据流水线传输;在发送第二份数据之前,无需等待第一份数据的确认。

另一个复杂的问题是,如果数据或确认消息被重发,而原始消息并未丢失而是延迟了,将会出现两个副本。原始的 TFTP 规则指出,在接收到重复的数据报文时,接收该数据报文的设备可以重发当前的数据报文。因此,当客户端进行读取操作并接收到重复的块 2 时,客户端会发送重复的块 2 确认。这会导致服务器接收到两个确认,进而发送两份块 3。然后会有两个块 3 的确认,以此类推。

结果是,一旦初始重复发生,之后的所有消息都会被发送两次。这个问题被亲切地称为Sorcerer's Apprentice bug,这个名字来源于电影Fantasia中著名的场景,米老鼠将动画扫帚切成两半,却发现每一半都复活了。这个问题通过改变规则得到解决,即只有接收重复数据消息的设备可以发送重复的确认消息。收到重复的确认消息不会导致发送重复的数据消息。由于只有两个设备中的一个可以发送重复消息,这解决了问题。

还值得强调的是,TFTP 根本不包含任何安全性,因此没有登录或认证过程。如前所述,管理员在决定通过 TFTP 提供哪些文件以及允许对 TFTP 服务器进行写入访问时必须谨慎。

TFTP 详细操作和消息

你之前看到,TFTP 操作由三个基本步骤组成:初始连接、数据传输和连接终止。所有操作都是通过交换特定的 TFTP 消息来完成的。现在让我们更详细地看看这三个操作阶段和 TFTP 消息的具体细节。

初始消息交换

客户端发送的第一个消息用于启动 TFTP,要么是读取请求(RRQ)消息,要么是写入请求(WRQ)消息。这个消息隐式地建立了逻辑 TFTP 连接,并指示文件是从服务器发送到客户端(读取请求)还是从客户端发送到服务器(写入请求)。该消息还指定了要执行的类型文件传输。TFTP 支持两种传输模式:netascii模式(ASCII 文本文件,如 Telnet 协议所使用的)和octet模式(二进制文件)。

注意

最初,存在一个名为邮件模式的第三种文件类型选项,但 TFTP 从未真正设计用于传输邮件,这个选项现在已经过时了

假设请求过程中没有出现任何问题(例如服务器问题、无法找到文件等),服务器将返回一个积极的回复。在读取请求的情况下,服务器将立即将第一条数据消息发送回客户端。在写入请求的情况下,服务器将向客户端发送一个确认消息,告知它可以继续发送第一条数据消息。

在初始交换之后,客户端和服务器按照之前描述的方式,以同步的方式交换数据和确认消息。对于读取操作,服务器发送一条数据消息,并在发送下一条消息之前等待客户端的确认。对于写入操作,客户端发送一条数据消息,服务器对它进行确认,然后客户端发送下一条数据消息。

数据块编号

每个数据消息包含 0 到 512 字节的数据块。这些块按顺序编号,从 1 开始。每个块的编号放在携带该块的数据消息的头部,并在对该块的确认中使用,以便原始发送者知道它已被接收。发送数据的设备将始终在它有足够的数据填充消息的情况下,每次发送 512 字节的数据。当它到达文件末尾并且要发送的数据少于 512 字节时,它将只发送剩余的字节数。(有趣的是,这意味着如果文件的大小是 512 的精确倍数,则最后发送的消息将没有数据字节!)

接收到包含 0 到 511 字节数据的数据消息表示这是最后一个数据消息。一旦确认,它将自动表示数据传输结束。无需显式终止连接,就像建立连接时不需要显式一样。

TFTP 读取过程步骤

让我们看看一个示例,展示 TFTP 消息是如何工作的。假设客户端想要读取一个长度为 1200 字节的具体文件。以下是简化的步骤(也显示在图 73-1)):

  1. 客户端向服务器发送读取请求,指定文件名。

  2. 服务器发送包含块 1 的数据消息,携带 512 字节的数据。

  3. 客户端收到数据并发送对块 1 的确认。

  4. 服务器发送包含 512 字节数据的块 2。

  5. 客户端收到块 2 并发送对其的确认。

  6. 服务器发送包含 176 字节数据的块 3。它在终止逻辑连接之前等待确认。

  7. 客户端收到数据并发送对块 3 的确认。由于此数据消息少于 512 字节,它知道文件已完成。

  8. 服务器收到确认并知道文件已成功接收。

TFTP 读取过程 在此示例中,客户端通过向服务器发送请求来启动读取文件的过程。服务器通过立即发送携带块 1 的数据消息来确认此请求,其中包含文件的第一个 512 字节。客户端通过为块 1 发送 ACK 消息来确认。然后服务器发送包含字节 513 到 1024 的块 2,客户端确认。当客户端收到包含 176 字节的块 3 时,它意识到这是文件的最后一个块。

图 73-1. TFTP 读取过程 在此示例中,客户端通过向服务器发送请求来启动读取文件的过程。服务器通过立即发送携带块 1 的数据消息来确认此请求,其中包含文件的第一个 512 字节。客户端通过为块 1 发送 ACK 消息来确认。然后服务器发送包含字节 513 到 1024 的块 2,客户端确认。当客户端收到包含 176 字节的块 3 时,它意识到这是文件的最后一个块。

TFTP 写入过程步骤

这里是相同过程中的步骤,但客户端正在写入文件(参见图 73-2)):

  1. 客户端向服务器发送写入请求,指定文件名。

  2. 服务器发送回确认。由于此确认是在接收到任何数据之前发送的,因此它在确认中使用块 0。

  3. 客户端发送包含块 1 的数据消息,其中包含 512 字节数据。

  4. 服务器接收数据并发送对块 1 的确认。

  5. 客户端发送包含 512 字节数据的块 2。

  6. 服务器接收数据并发送对块 2 的确认。

  7. 客户端发送包含 176 字节数据的块 3。它在终止逻辑连接之前等待确认。

  8. 服务器接收块 3 并发送对其的确认。由于此数据消息少于 512 字节,传输完成。

  9. 客户端收到块 3 的确认,知道文件写入成功完成。

TFTP 写入过程 本例展示了客户端向服务器发送与读取的相同 1200 字节文件。客户端向服务器发送写入请求,服务器确认后;它使用块 0 来表示在收到任何数据之前对请求的确认。客户端然后一次发送一个数据块,每个数据块都由服务器确认。当服务器收到包含少于 512 字节数据的数据块 3 时,它知道已经收到了整个文件。

图 73-2. TFTP 写入过程 本例展示了客户端向服务器发送与图 73-1 中读取的相同 1200 字节的文件。客户端向服务器发送写入请求,服务器确认后;它使用块 0 来表示在收到任何数据之前对请求的确认。然后客户端一次发送一个数据块,每个数据块都由服务器确认。当服务器收到包含少于 512 字节数据的数据块 3 时,它知道已经收到了整个文件。

提示

关键概念 TFTP 的读取操作开始于客户端向 TFTP 服务器发送读取请求消息;服务器随后发送 512 字节的文件数据消息,并在每次发送后等待客户端确认接收,然后再发送下一个。TFTP 的写入操作开始于客户端向服务器发送写入请求,服务器进行确认。然后客户端以 512 字节的数据块发送文件,并在每次发送后等待服务器确认接收。在这两种情况下,都没有明确的方式来标记传输的结束;接收文件的设备只是在收到包含少于 512 字节的数据消息时知道传输已完成。

如果在连接建立或传输过程的任何阶段遇到问题,设备可能会回复一个错误消息而不是数据或确认消息,具体情况而定。错误消息通常会导致数据传输失败;这是 TFTP 简单性所付出的代价之一。

每个 TFTP 文件传输都使用所描述的过程进行,该过程仅传输单个文件。如果需要发送或接收另一个文件,将建立一个新的逻辑通信,方式类似于 FTP 创建数据连接。主要区别是 TFTP 没有 FTP 那样的持久控制连接。

TFTP 选项和选项协商

简单协议和应用的设计者似乎面临的一个困难是保持它们的简单性。许多协议最初规模较小,但随着时间的推移,一些有良好意图的用户会逐渐提出改进建议,这些改进虽然缓慢但确实被采纳。最终,曾经精简高效的程序变得,让我们说,"过于复杂"。在软件行业中,这种现象被称为 功能蔓延,并且已经发生在许多协议和应用中。

当程序或协议最初功能较少时,增加功能的诱惑尤其强烈。鉴于这一点,TFTP 的维护者多年来一直做得很好,避免了这种陷阱。然而,他们在 1995 年确实允许在协议中增加了一个新功能:"TFTP 选项扩展",它描述了 TFTP 客户端和服务器在传输文件之前如何协商 选项

添加这种功能的原因是原始的 TFTP 根本无法让客户端和服务器在发送文件之前交换重要的控制信息。这限制了协议处理特殊情况的灵活性,例如在非同寻常的网络类型上传输数据。TFTP 选项协商功能允许客户端和服务器之间交换额外的参数,以控制数据传输的方式。它这样做而没有显著复杂化协议,并且与正常 TFTP 向后兼容。它仅在客户端和服务器都支持它的情况下使用,如果一个设备尝试使用该功能而另一个不支持,则不会引起问题。

TFTP 选项协商过程

客户端通过发送修改后的 TFTP 读取请求或写入请求消息来开始协商。除了此消息中出现的正常信息(在本章后面的 "TFTP 消息格式" 部分中描述)外,还可以包括一个选项列表。每个选项都指定了一个选项代码和一个选项值。名称和值以 ASCII 字符串的形式表达,并以空字符(0 字节)结尾。请求消息中可以指定多个选项。

服务器接收包含选项的请求,如果它支持选项扩展,则处理它们。然后,它向客户端返回一个特殊选项确认(OACK)消息,其中列出客户端指定的服务器识别并接受的所有选项。客户端请求但服务器拒绝的任何选项都不包括在 OACK 中。客户端只能使用服务器接受的选项。如果客户端拒绝服务器的响应,它可以在收到不可接受的 OACK 消息时发送一个错误消息(错误代码 8)。

如果服务器识别某个选项但不满意客户端建议的值,它可以在其响应中为某些选项指定一个替代值。显然,如果服务器根本不支持选项,它将忽略客户端的选项请求,并以正常 TFTP 的方式响应,发送数据消息(用于读取)或常规确认(用于写入)。

如果服务器确实发送了 OACK,客户端将继续发送消息,使用上一节中描述的常规消息交换。在写操作的情况下,OACK 替换了消息对话中的常规确认。在读取操作的情况下,OACK 是服务器发送的第一个消息,而不是它通常发送的第一个数据块。TFTP 不允许同一设备连续发送两个数据报,因此必须在发送第一个块之前收到客户端的回复。客户端通过发送一个包含 0 号块的常规确认来实现这一点——这与服务器通常用于写操作的确认形式相同。

小贴士

关键概念 TFTP 本应是一个小而简单的协议,因此它包含很少的额外功能。它支持的一个功能是选项协商,其中 TFTP 客户端和服务器试图就他们将在文件传输中使用的附加参数达成一致。TFTP 客户端在其读取请求或写入请求消息中包含一个或多个选项;然后,TFTP 服务器发送一个选项确认(OACK)消息,列出服务器同意使用的每个选项。在读取文件时使用选项意味着客户端必须发送一个额外的确认——以确认 OACK——在服务器发送文件的第一块之前。

为了复习,让我们逐一查看四种可能的情况:读写操作,带选项和不带选项。

正常读取(无选项协商)的初始消息交换,如图图 73-1 所示,如下:

  1. 客户端发送读取请求。

  2. 服务器发送数据块 1。

  3. 客户端确认数据块 1。

    以此类推 …

在选项协商过程中,读取过程如下(参见图 73-3)):

  1. 客户端发送带有选项的读取请求。

  2. 服务器发送 OACK。

  3. 客户端发送对块 0 的常规确认;即,它确认了 OACK。

  4. 服务器发送数据块 1。

  5. 客户端确认数据块 1。

    以此类推 …

带选项协商的 TFTP 读取过程此图展示了与图 73-1 相同的示例,但增加了一个用于选项协商的消息交换。客户端的初始读取请求包括它希望用于此传输的选项。服务器不是立即发送第一个数据块,而是发送一个 OACK。客户端通过发送使用块 0 的确认来表示已收到 OACK。服务器发送数据块 1,其余的交换过程按正常进行。

图 73-3. 带有选项协商的 TFTP 读取过程 此图显示了与 图 73-1, 但增加了一个用于选项协商的消息交换。客户端的初始读取请求包括它希望用于此传输的选项。服务器不是立即发送第一个数据块,而是发送一个 OACK。客户端通过发送使用块 0 的确认来表示已收到 OACK。服务器发送数据块 1,其余的交换按正常进行。

正常写操作的初始消息交换(没有选项协商)如下:

  1. 客户端发送写请求。

  2. 服务器发送确认。

  3. 客户端发送数据块 1。

  4. 服务器确认数据块 1。

    等等 …

下面是一个带有选项协商的写操作:

  1. 客户端发送带有选项的写请求。

  2. 服务器发送选项确认(而不是常规确认)。

  3. 客户端发送数据块 1。

  4. 服务器确认数据块 1。

    等等 …

TFTP 选项

表 73-1 包含了当前定义的三个 TFTP 选项的摘要。

表 73-1. TFTP 选项

TFTP 选项名称 TFTP 选项代码(用于请求消息) 定义 RFC 描述
块大小 blksize 2348 允许客户端和服务器发送大小为 512 字节以外的数据块,以提高效率或解决特定类型网络的限制。
超时间隔 interval 2349 允许客户端和服务器就用于重传计时器的指定秒数达成一致。在具有高延迟或其他特殊要求的某些网络上,这可能很有价值。
传输大小 tsize 2349 允许发送文件的设备(在写操作中为客户端,在读取操作中为服务器)在传输开始之前告诉另一设备文件的大小。这允许接收设备提前为其分配空间。

TFTP 消息格式

与 FTP 不同,TFTP 中的所有通信都是以离散消息的形式完成的,这些消息遵循特定的消息格式。TFTP 和 FTP 在这方面差异如此之大的原因是它们使用的传输协议不同。FTP 使用 TCP,允许数据逐字节流式传输;FTP 还使用一个专用通道来发送命令。TFTP 运行在 UDP 上,它使用传统的头部/数据格式化方案。

原始 TFTP 标准定义了五种不同类型的消息:读取请求(RRQ)、写入请求(WRQ)、数据(DATA)、确认(ACK)和错误(ERROR)。TFTP 选项扩展功能定义了第六种消息:选项确认(OACK)。在这六种消息中,前两种具有相同的消息格式。每个 TFTP 消息中唯一的公共字段是操作码(Opcode),它告诉消息的接收者消息的类型。

TFTP 的消息格式与某些其他协议使用的格式不同,因为 TFTP 中的许多字段长度是可变的。通常,消息中的可变长度字段使用前导长度字段来表示可变字段的大小。相反,TFTP 使用 ASCII 字符的字符串形式通过 netascii(ASCII 的 Telnet 版本)发送这些字段。字符串的结尾由一个零字节标记。例外的是数据消息中的数据字段,其内容取决于传输模式。

本章的其余部分包含对每个 TFTP 消息的详细说明。

读取请求和写入请求消息

这些消息使用一个通用的消息格式,在表 73-2 中描述,并在图 73-4 中以图形方式展示。

表 73-2. TFTP RRQ/WRQ 消息格式

字段名称 大小(字节) 描述
操作码 2 操作码:指定 TFTP 消息类型。值为 1 表示 RRQ 消息,而值为 2 表示 WRQ 消息。
文件名 可变 要读取或写入的文件名。
模式 可变 传输模式:字符串 netascii 或字节,以零字节结尾。
选项 可变 当客户端支持 TFTP 选项时,它将在模式字段之后按顺序编码它们。每个选项由两个可变长度子字段组成。optN 子字段是选项 N 的选项代码,包含指定选项名称的字符串;目前支持 blksize、interval 和 tsize。valueN 子字段是选项 N 的选项值,包含客户端请求此选项的值。(注意,这与其他 TFTP 可变长度字段一样,是一个零终止的字符串,即使是数值。)

TFTP RRQ/WRQ 消息格式

图 73-4. TFTP RRQ/WRQ 消息格式

数据消息

数据块使用表 73-3 和图 73-5 中显示的简化格式发送。

表 73-3. TFTP 数据消息格式

字段名称 大小(字节) 描述
操作码 2 操作代码:指定 TFTP 消息类型。值为 3 表示数据消息。
块编号 2 块编号:正在发送的数据块的编号。
数据 可变 数据:0 到 512 字节的数据。

TFTP 数据消息格式

图 73-5. TFTP 数据消息格式

确认消息

确认消息具有任何 TFTP 消息中最简单的格式,如表 73-4 和图 73-6 所示。

表 73-4. TFTP 确认消息格式

字段名称 大小(字节) 描述
操作码 2 操作代码:指定 TFTP 消息类型。值为 4 表示 ACK 消息。
块编号 2 块编号:被确认的数据块的编号;值为 0 用于确认无选项的写入请求的接收或确认 OACK 的接收。

TFTP 确认消息格式

图 73-6. TFTP 确认消息格式

错误消息

在检测到通信中的问题时,客户端或服务器都可以发送错误消息。它们的格式如表 73-5 和图 73-7 所示。

TFTP 错误消息格式

图 73-7. TFTP 错误消息格式

表 73-5. TFTP 错误消息格式

字段名称 大小(字节) 描述
操作码 2 操作代码:指定 TFTP 消息类型。值为 5 表示错误消息。
错误代码 2 表示正在通信的消息类型的数字代码。值 0 到 7 由 TFTP 标准定义,而值 8 由 TFTP 选项扩展添加:0 = 未定义;请参阅错误消息字段以获取详细信息 1 = 文件未找到 2 = 访问违规 3 = 磁盘满或分配超出 4 = 非法 TFTP 操作 5 = 未知传输 ID6 = 文件已存在 7 = 没有此类用户 8 = 由于不可接受选项协商,客户端传输终止
错误消息 可变 错误消息:描述性文本错误消息字符串,如标准所述,旨在供“人类消费”。

选项确认消息

OACK 消息用于确认接收 TFTP 选项。其结构如 表 73-6 和 图 73-8 所示。

表 73-6. TFTP OACK 消息格式

字段名称 大小(字节) 描述
指令码 2 操作码:指定 TFTP 消息类型。值为 6 表示 OACK 消息。
选项 可变 服务器确认的选项列表。每个选项由两个可变长度的子字段组成。optN 子字段是选项 N 的选项码,包含指定选项名称的字符串,从 RRQ 或 WRQ 消息中复制而来。valueN 子字段是选项 N 的选项值,包含选项的确认值,这可能是客户端指定的值或替代值,具体取决于选项类型。

TFTP OACK 消息格式

图 73-8. TFTP OACK 消息格式

第三部分-7. TCP/IP 电子邮件系统:概念和协议

第七十四章

第七十五章

第七十六章

第七十七章")

第七十八章

人类创造与已知系统相似的系统是很常见的。我们都习惯于使用常规的邮件系统,从我们的位置发送信件和其他文件到邮政系统服务的任何地方的收件人。自然地,互联网的第一个应用之一就是创建一个电子版本的这种传统邮件系统,以便以类似的方式发送消息,但更快、更方便。在许多年里,TCP/IP 的 电子邮件系统 被创建和改进。现在,它是世界上使用最广泛的电子消息手段。

在本部分中,我详细描述了 TCP/IP 电子邮件(电子邮件),分为五章,讨论了电子邮件概念以及构成整体 TCP/IP 电子邮件系统的各种组件和协议。第一章提供了 TCP/IP 电子邮件的概述,并讨论了其使用方式以及构成系统的不同协议和方法。第二章讨论了电子邮件消息的寻址方式,第三章涵盖了电子邮件消息的标准和特殊格式。第四和第五章描述了实现电子邮件功能的 TCP/IP 协议。这些包括负责电子邮件投递的简单邮件传输协议 (SMTP),以及用于邮箱访问和邮件检索的几个协议和方法,包括邮局协议第 3 版 (POP3) 和互联网消息访问协议 (IMAP)。

本讨论主要关注现代互联网中用于电子邮件编写、投递和访问的机制。在 第七十四章 的电子邮件概述中,我提到了过去用于 TCP/IP 电子邮件的一些技术,但只是为了历史完整性,并且为了对比这些方法与目前使用的方法。

第七十四章。TCP/IP 电子邮件系统概述和概念

无标题图片

在 TCP/IP 协议套件中,电子邮件(email)并不是仅仅作为一个单一协议或技术来实现的。相反,它是一个完整的系统,包含了许多相互协作的相关组件。这些包括定义地址和消息格式的标准,以及一系列在实现电子邮件消息中扮演不同功能的协议。在深入考察这些各个部分之前,先对整个系统进行一个概述是有意义的。

在本章中,我提供了一个关于 TCP/IP 电子邮件的简介,以帮助您理解该系统、其工作原理以及不同组件如何融入其中。我首先概述了电子邮件及其在 TCP/IP 中的实现的历史,然后提供了电子邮件通信过程中涉及步骤的一般概述,最后更具体地讨论了 TCP/IP 中使用的通信模型以及各种 TCP/IP 设备和协议在发送和接收电子邮件中所扮演的角色。

TCP/IP 电子邮件系统概述和历史

人类对沟通的需求与人类自身一样古老。几千年前,沟通几乎完全是局部的。消息主要是口头的,即使在书写时,也很少被送到很远的距离。大多数人从未离家太远,也很少与那些远离他们的人沟通。但在古代,领导者使用信使将一些关键信息从一地传到另一地。这很慢且不可靠,但有些消息的重要性足以使得尽管困难重重,沟通的努力仍然必须付出。

交通运输的进步导致了通信能力的进步,最终导致了物理邮件系统的创建。如今,这些系统已经发展到任何发达世界的人都可以给几乎任何人发送信件或包裹的程度。尽管人们经常对邮政服务开玩笑,但可靠性已经大大提高。速度也比以前好得多,现在消息到达目的地只需要几天,而不是几周或几个月。

在我们现代世界的标准下,等待消息从一个地方传到另一个地方甚至需要几天时间,这相当慢。因此,网络最自然的应用之一就是将它们用作替代物理运输消息的手段。将邮件从物理过程转变为电子过程带来了巨大的好处,包括极大地提高了通信速度,能够瞬间将一条消息发送给多个收件人,以及能够在收到消息后几乎立即获得反馈。

电子邮件的早期阶段

电子邮件背后的想法不仅与计算机网络一样古老,实际上它还早于互联网互连。最早的电子邮件系统是在传统的主机计算机上实现的。这些是单台大型计算机,许多用户可以通过连接的终端同时访问。主机上的电子邮件系统由一套在主机上运行的软件组成,实现了整个电子邮件系统。每个用户都有一个位于这台机器上的邮箱,邮件通过将消息从一个邮箱移动到另一个邮箱来传递。用户通过用户界面程序发送和接收邮件。

这样的早期电子邮件系统对本地通信很有用,但不适用于向另一个组织的人发送消息。主机电子邮件在某种程度上类似于一个城镇的居民向另一个居民发送的本地邮件。如果没有建立用于投递的基础设施,就无法向远方城镇的人发送邮件。

互联网互连的力量真正使电子邮件成为通用的通信方式。互联网互连将系统连接在一起,就像邮政服务的飞机和车辆将邮局连接在一起一样。邮件通过互联网的基础技术从用户发送到用户。由于 TCP/IP 是最常用的互联网互连协议套件,而现代互联网使用 TCP/IP 将全球的系统连接在一起,因此它是发送电子邮件的载体。

TCP/IP 电子邮件的历史

与一些其他文件和消息传输协议一样,基于 TCP/IP 的电子邮件实际上可以追溯到 TCP/IP 和互联网正式存在之前。最早的电子邮件协议是在 ARPAnet 时代开发的。在电子邮件创建之前,一些互联网 RFC,如 RFC 95(是的,95,两位数——我们在这里回溯得很远)和 RFC 155,描述了在 20 世纪 70 年代初用于分发文件的物理邮寄名单。正是这种发送文件的需求,可能让 TCP/IP 先驱们意识到他们自己正在创造的技术——电子消息系统的有用性。

描述电子邮件的第一个互联网文件可能是 1971 年发布的 RFC 196。它描述了邮箱协议,这是一种使用 TCP/IP 前身非常基础的邮件传输方法。该协议是为了发送远程打印文档的特定目的而设计的。在当时,人们像今天一样在交互式终端上使用计算机并不常见,但通过电子方式发送文档的想法是相同的。邮箱协议在 1971 年进行了多次修订。

在 20 世纪 70 年代中期,开发者开始致力于在新兴的互联网上实施电子邮件的更全面的方法。最初,这种方法使用了许多现有的应用层传输协议来描述,包括文件传输协议(FTP)。1980 年,在 RFC 772 中发布了“邮件传输协议(MTP)”。这是今天 TCP/IP 电子邮件的第一个前身,它使用了 Telnet 协议以及 FTP 的原则。

在 20 世纪 70 年代电子邮件协议开发期间,主机系统之间正在使用各种技术交换邮件。其中最常用的方法是Unix-to-Unix Copy Protocol (UUCP),它被设计用来允许文件在 UNIX 系统之间传输,将文件从一个连接的系统移动到下一个系统。UUCP 也被用于通信 Usenet 新闻组文章和其他文件。

1981 年,随着简单邮件传输协议(SMTP)的定义,现代 TCP/IP 电子邮件时代开始形成。SMTP 详细描述了邮件如何直接或间接地从一台 TCP/IP 主机传输到另一台,而无需使用 FTP 或其他文件传输方法。(SMTP 的详细历史和讨论请见第七十七章。)大约在同一时间,还创建了其他互补规范,这些规范正式化或定义了系统的其他组件和元素。我们将在本章的其余部分探讨这些拼图碎片。

TCP/IP 电子邮件系统概述

现代电子邮件系统中的一个最重要的通用概念是,在互联网上 SMTP 主机之间传递电子邮件的协议和允许用户访问其本地主机上收到的邮件的协议之间做出区分。继续使用邮政邮件的类比,不同的协议用于在邮局之间发送邮件和进行家庭投递。正如您将看到的,这是有意为之,以便即使在发送邮件时用户未连接到互联网,也能将邮件发送给用户。这种解耦至关重要,因为它使得延迟通信成为可能,邮件可以在发送者想要传输时发送,在收件人想要阅读时接收。

小贴士

关键概念 TCP/IP 应用中最重要之一是现实世界邮政投递系统的互联网等价物,通常称为电子邮件电子邮件。电子邮件的历史可以追溯到 TCP/IP 发展的最早阶段。如今,每天都有数百万人在全球范围内使用电子邮件发送简单和复杂的信息。TCP/IP 电子邮件不是一个单一的应用程序,而是一个包含多个协议、软件元素和组件的完整系统。

多年来,1980 年代初定义的基本组件没有发生实质性变化,但它们的使用方式已经演变和改进。早期的电子邮件投递涉及一个 SMTP 主机使用路由规范来指定邮件将通过中间系统投递的方式;如今,域名系统(DNS)使许多这样的做法变得过时,大多数情况下促进了邮件的几乎即时直接投递。早期的电子邮件只支持简单的文本,但现在我们可以在电子邮件中发送图形图像、程序和其他文件附件。现代高速互联网连接和更新的访问协议使得电子邮件成为实现几乎瞬间通信终极目标的实现,即使跨越大陆。

TCP/IP 电子邮件通信概述

你刚刚看到,TCP/IP 电子邮件被实现为一个完整的系统,其中包含多个执行电子邮件通信完整工作不同部分的功能元素。这些元素包括标准消息格式、特定语法用于收件人地址,以及用于投递邮件和允许间歇性连接的 TCP/IP 客户端访问邮箱的协议。

为了帮助为检查这些组件奠定基础,在此,我提供了电子邮件通信完整端到端过程的概述,以便你可以看到一切是如何工作的。我将以简化的形式展示基本步骤,并继续与常规邮件系统进行类比以进行比较。

现代 TCP/IP 电子邮件通信过程由五个基本步骤组成:

  1. 邮件编写 用户通过创建电子邮件消息开始电子邮件之旅。消息包含两部分:正文和标题。消息的正文是实际要传达的信息。标题包含描述消息和控制其投递和处理的元数据。消息必须按照电子邮件系统的标准消息格式创建,以便可以处理(参见第七十六章)来完成的。这类似于在邮局或邮递员从邮箱中取出信封并将其带到当地邮局以加入邮件投递流程。

  2. 邮件投递 邮件消息被发送方的本地 SMTP 系统接收,并通过邮件系统发送到目标用户。如今,这通过执行目标收件人主机系统的 DNS 查找并建立到该系统的 SMTP 连接来完成。SMTP 还支持指定一系列 SMTP 服务器,消息必须通过这些服务器传递才能到达目的地。最终,邮件到达收件人的本地 SMTP 系统。这就像通过邮政系统内部的“内部互联网”中的卡车、飞机和其他设备将信封运输到目标收件人当地的邮局。

  3. 邮件接收和处理 本地 SMTP 服务器接收电子邮件消息并处理它。它将邮件放入目标收件人的邮箱中,等待用户检索。在我们的物理类比中,这是收件人当地的邮局对从邮政投递系统进入的邮件进行分类并将邮件放入单独的邮局箱子或箱子中以便投递的步骤。

  4. 邮件访问和检索 目标收件人会定期检查其本地 SMTP 服务器以确定是否有邮件到达。如果有,收件人会检索邮件,打开它并阅读其内容。这是通过特殊的邮件访问协议或方法(见第七十八章)来完成的。为了节省时间,访问协议和客户端电子邮件软件可能允许用户扫描收到的邮件的标题(如主题和发件人身份)以决定下载哪些邮件消息。这类似于在邮局或家中收到的邮件被物理取出的步骤。

提示

关键概念 TCP/IP 电子邮件通信通常涉及五个步骤,每个步骤都与通过邮政系统寄送普通信件的旅程的一部分相对应。首先,电子邮件被撰写(书写);其次,它被提交到电子邮件系统;第三,它被投递到收件人的服务器;第四,它被接收和处理;最后,它被收件人访问和检索

在某些情况下,并不是所有这些步骤都会被执行。如果一个用户是从已经是一个 SMTP 服务器的设备发送电子邮件,那么步骤 2 可以省略。如果收件人登录到一个也是 SMTP 服务器的设备,那么步骤 5 将被跳过,因为用户可以直接在服务器上阅读邮件。因此,在最简单的情况下,发生的事情只是撰写、投递和接收;这发生在一位拨号 UNIX 主机用户向另一位用户发送邮件时。然而,在当今大多数情况下,所有五个步骤都会发生。

TCP/IP 电子邮件消息通信模型

整个电子邮件系统的目的是实现 TCP/IP 互联网用户向一个或多个收件人传输消息。为了实现这一目标,需要一种特殊的通信方法,这使得电子邮件系统与大多数其他协议所使用的系统大不相同。为了理解我所说的意思,只需考虑发送信件和打电话之间的通信差异。

在这方面,大多数 TCP/IP 协议都类似于打电话:发送者和接收者必须同时都在网络上。如果你打电话给某人,而他不在那里接电话,你就无法与他交谈。(当然,我在这里忽略自动应答机和语音邮件!)大多数 TCP/IP 协议都是这样的。例如,要使用 FTP 发送文件,你必须从发送者的机器直接连接到接收者的机器。如果接收者的机器在发送者机器不在网络上的确切时间不在网络上,则无法进行通信。对于电子邮件来说,这种立即的通信是不可接受的。

就像现实世界的平信一样,乔希望能够在对他来说方便的时候将消息放入系统,而艾伦希望能够在对她来说合适的时候接收乔的邮件。为了实现这一点,电子邮件必须使用“发送后忘记”的模式,就像真正的邮件一样,乔将“信封”投入电子邮件系统,它最终会到达目的地。

这种解耦发送者和接收者的设计对电子邮件系统至关重要。这一点尤其正确,因为许多互联网电子邮件用户并不是一直都在互联网上。就像你不会希望邮件在你不在家的时候被拒绝一样,你也不希望在你不在互联网上的时候邮件无法送达。同样,你可能不希望在写消息的整个时间内都连接到互联网,尤其是如果你每天只有有限的时间可以访问互联网。

对整个电子邮件系统来说,另一个关键的想法是通信是在特定的用户之间进行的,而不是在特定的机器之间。这使得电子邮件在 TCP/IP 互联网上的许多其他通信类型中具有固有的不同。当我们查看第七十五章(第七十五章。TCP/IP 电子邮件地址和寻址)中的电子邮件地址时,你会看到为什么这一点很重要。

为了允许电子邮件所需的通信类型,整个系统被设计成便于将电子邮件消息从一位用户延迟发送到另一位用户。为了了解这是如何工作的,让我们再次看看我们之前讨论过的示例通信——但这次,考虑一下交换中不同设备的作用(如图图 74-1

图 74-1. 电子邮件通信模型 此图展示了两个用户之间典型电子邮件通信中涉及的四个设备。每个设备由多个不同元素组成,这些元素通过黑色箭头所示的方式进行通信。请注意固有的不对称性,因为用户发送电子邮件的方法与从服务器检索它的方法不同。大号阴影箭头显示了一个典型的交易:发送者编写邮件,并将其发送到她的本地电子邮件队列。它使用 SMTP 发送到发送者的本地 SMTP 服务器,然后发送到接收者的 SMTP 服务器,进入该用户的收件箱。然后通常使用 POP 或 IMAP 等协议检索。

电子邮件通信中的协议角色

你可能已经注意到,SMTP 被用于这个通信过程的大部分。实际上,如果接收者使用运行 SMTP 软件的机器,这对于使用拨号 UNIX 外壳互联网访问的人来说很常见,发送电子邮件的过程将完全使用 SMTP。然而,SMTP 服务器必须始终在互联网上可用,并准备好接收邮件。大多数人使用的是不总是在线或没有运行 SMTP 软件的设备。这就是为什么最后一步,电子邮件访问和检索,通常需要。

可能有可能定义电子邮件系统,使得这个通信的最后一步也使用 SMTP 进行,这意味着整个系统使用相同的协议。然而,SMTP 是为了特定的目的——传输和交付电子邮件而量身定制的,而不是为了远程邮箱访问。将邮箱访问的功能留给专门的、独立的协议更有意义。这不仅允许这些协议根据电子邮件接收者的需求进行定制,而且还通过为用户提供多种检索电子邮件的方式提供了灵活性。我在第七十八章中讨论了电子邮件访问协议和方法,重点介绍了两种最常用的协议:POP 和 IMAP。

在这里讨论的三个协议——SMTP、POP3 和 IMAP——在 TCP/IP 电子邮件阶段占据主导地位,但它们依赖于两个其他元素来扮演支持角色。第一个是电子邮件消息的地址分配方法,以确保它们到达目的地。第二个是用于编码消息和控制它们传递和使用的消息格式集合。这些元素通常不会得到应有的关注,但在这里,我将在接下来的两个章节中专门讨论它们。

小贴士

关键概念 邮件系统的一个关键要求是,在发送邮件时,发件人和收件人不必都在系统中。因此,TCP/IP 使用了一种具有多个设备的通信模型,允许发件人和收件人解耦。当发件人的客户端设备准备好传输时,它会将邮件排队并将邮件移动到发件人的本地 SMTP 服务器;然后使用 SMTP 将邮件传输到收件人的 SMTP 服务器。邮件可以在收件人的服务器上保留不定的时间。当收件人准备好阅读时,他可以使用一组邮件访问协议和方法之一或多个来检索邮件,其中最流行的是 POP 和 IMAP。

第七十五章。TCP/IP 电子邮件地址和地址分配

无标题图片

电子邮件(email)的整个概念基于一个类比:发送电子消息就像发送纸质消息一样。这个类比很有效,因为电子邮件确实被设计成类似于普通邮件,只是具有技术时代的优势:速度和灵活性。

邮件和普通邮件之间许多相似之处之一是需要地址。为了使信息能够送达,发件人必须指定收件人并提供足够的信息,以表明收件人如何以及在哪里可以找到。在 TCP/IP 邮件中,使用标准的电子邮件地址格式来完成这项工作,同时也支持在某些特殊情况下可能使用的替代地址方案。

在本章中,我描述了电子邮件消息的地址分配方式。我首先讨论了 TCP/IP 中的标准电子邮件地址以及如何使用这些地址来确定邮件应该发送到哪里。然后,我简要讨论了您可能会偶尔遇到的历 史性和特殊电子邮件地址。我还讨论了电子邮件地址簿(别名)的使用以及如何为多个收件人分配地址,并提供了一个关于电子邮寄列表的概述,这是电子群组通信最早实现的方式之一。

TCP/IP 电子邮件地址分配和地址解析

在互联网上的所有通信都需要一种方式来指定通信的预期接收者的身份。大多数应用协议,如文件传输协议(FTP)和超文本传输协议(HTTP),使用传统的 TCP/IP 结构——IP 地址和端口号——来指定要发送的信息的目的地。IP 地址通常标识一台特定的主机计算机,而端口号则表示在该计算机上运行的软件进程或应用程序。

然而,电子邮件使用的通信模型与大多数应用不同。正如你在前一章讨论电子邮件模型时所见,电子邮件与其他许多系统区分开来的一个要素是通信是以用户为导向的。电子邮件不是从一个机器发送到另一个机器,就像使用 FTP 传输文件一样。相反,它是从一个用户发送到另一个用户。这对于整个系统的运行至关重要。一方面,它允许某人从任何数量的不同客户端计算机检索发送的电子邮件。这使得接收者即使在旅行时也能接收电子邮件。

由于电子邮件消息是基于用户的,因此地址方案也必须是基于用户的。我们不能使用传统的 IP 地址和端口,因此我们需要一个独特的系统来指定两个主要信息:用户是谁以及用户在哪里。这些当然类似于普通邮件信封上的姓名和地址。

用户名的概念相对简单明了,但确定用户的位置则不然。在普通邮件中,地址指的是一个物理地点。本来可以以同样的方式定义电子邮件地址;也就是说,让电子邮件地址指向用户的客户端机器。然而,请记住电子邮件投递的另一个重要特征:它是间接的,基于用户的本地简单邮件传输协议(SMTP)服务器在可以检索之前保存收到的邮件的概念。用户用来访问电子邮件的机器甚至可能没有常规地连接到互联网,因此可能难以识别。我们还希望用户能够从多台机器访问电子邮件。

由于所有这些原因,我们希望地址能够识别的不是用户在任何特定时间的具体位置,而是用户永久邮箱所在的地方——在用户的 SMTP 服务器上,该服务器永久连接到互联网。

标准基于 DNS 的电子邮件地址

在 TCP/IP 中,用于识别服务器(和其他机器)的系统是 域名系统 (DNS)。DNS 是一个庞大的系统,本书的 第三部分-1 中有描述,如果您想了解更多,应该阅读这部分内容。现在,重要的是要意识到,在 DNS 中,互联网上的所有设备都被组织成一个设备命名层次结构,任何设备都可以使用由点号分隔的一系列文本标签组成的 域名 来识别。

完整的 TCP/IP 地址由两个部分组成:用户名指定和域名指定。这两个部分通过 at 符号 (@) 连接在一起,形成了我们今天熟悉的 TCP/IP 电子邮件地址语法:@

的格式遵循 DNS(域名系统)的语法规则(见 第五十三章。如果特殊字符和空格被引号包围(或通过转义字符等方式标记为名称的一部分),则 中也可以包含其他特殊字符和空格。域名不区分大小写;用户名可能区分大小写,这取决于系统。

一个有效的电子邮件地址示例是 cmk@athena.mit.edu(这是我多年前在学校时使用的地址)。在这里,cmk 是我的用户名(我的首字母缩写);athena.mit.edu 是我接收邮件的主机名称;而 athena 是麻省理工学院 (mit) 中的一个特定系统,这是一个使用 .edu 顶级域的教育机构。

还可以使用互联网标准的统一资源定位符 (URL) 来指定电子邮件地址。这允许在超文本(Web)文档中嵌入链接;当点击时,它会调用电子邮件客户端向用户发送邮件。电子邮件 URL 通过在地址前加上特殊的 URL 方案字符串 mailto: 来创建,如下所示:mailto:cmk@athena.mit.edu

电子邮件地址的特殊要求

拥有一个电子邮件地址指向用户的本地 SMTP 服务器,与地址中提到特定客户端计算机相比,提供了很大的灵活性。但这不足以处理以下情况:

  • 组织可能希望使用通用的地址,这些地址不指定处理电子邮件的 SMTP 服务器的名称,以便发送者或客户端更容易记住电子邮件地址。例如,如果某人知道我的真实姓名并且我知道我在麻省理工学院,那么他更容易记住我的电子邮件地址为 cmk@mit.edu,而不是记住 cmk@athena.mit.edu。

  • 管理员可能会在一段时间内更改处理邮件的机器。这意味着所有用户的电子邮件地址也必须更改——而且我们都知道这是多么痛苦的事情。例如,如果我从 athena 机器移动到 jabberwocky 机器,我的旧地址需要更改为 cmk@jabberwocky.mit.edu。但如果是 cmk@mit.edu 这样的地址,服务器更改就不会影响地址。

  • 在较大的组织中,可能希望有多个服务器分担处理传入电子邮件的负载。

为了满足所有这些要求,DNS 系统包括一个专门设计来支持电子邮件地址的功能。可以设置一个特殊的 邮件交换 (MX) 记录,指定特定域名到达时应使用哪个 SMTP 服务器。如果配置得当,这将为处理上述情况以及更多情况提供相当大的灵活性。有关更多详细信息,请参阅第五十六章 MX 记录和 DNS 电子邮件支持 的描述。

小贴士

关键概念 所有网络通信都需要某种形式的地址;由于电子邮件是 面向用户 的,因此电子邮件地址也是基于用户的。在现代 TCP/IP 电子邮件中,标准地址由一个 用户名 组成,它指定了收件人,以及一个 域名,它指定了用户所在的 DNS 域。为接受电子邮件的每个域名都设置了一个特殊的 DNS 邮件交换 (MX) 记录,因此发送 SMTP 服务器可以确定它应该使用哪个 SMTP 服务器来发送邮件给特定的收件人。

假设,例如,我是 pcguide.com 域名的所有者。邮件可以发送到 pcguide.com,但实际上并不存储在任何以该名称命名的服务器上。相反,它被重定向到我的收件箱实际所在的真实服务器。这使得我可以处理所有发送到 pcguide.com 的邮件,无论我的邮箱实际位于何处。

DNS 也很重要,因为它的 MX 资源记录消除了将电子邮件从一台 SMTP 服务器中继到下一台以投递的需要。在现代 TCP/IP 中,可以直接从发送者的 SMTP 服务器发送电子邮件到收件人的服务器,这使得通信更快、更高效。这一点也在第五十六章 DNS 解析概念和解析器操作 中进行了讨论。

TCP/IP 历史和特殊电子邮件地址

TCP/IP 电子邮件非常成功,可以说是全球电子消息传递最重要的标准。电子邮件的广泛应用与 TCP/IP 和互联网的整体应用紧密相连。由于大多数组织都希望成为互联网的一部分,他们连接到它并使用其技术,包括 DNS,这是 TCP/IP 电子邮件地址的基础。反过来,使用简单的 DNS 风格的电子邮件地址(用户@域名)鼓励了电子邮件的进一步使用,因为人们发现从概念上决定如何发送消息是容易的。

然而,TCP/IP 并不是唯一的电子邮件系统。多年来,已经发展了几个其他网络的电子邮件系统。由于互联网是世界上最大的互联网,TCP/IP 电子邮件经常被用作某种类型的清算所,以将这些不同的电子邮件机制连接起来。这被称为网关,它允许使用非 SMTP 电子邮件系统的人与使用 TCP/IP 的人进行交互,反之亦然。网关是复杂的,部分原因是因为电子邮件系统使用不同的方式来寻址邮件。让我们看看这些系统之一以及它们如何与 TCP/IP 交互。

FidoNet 寻址

最早的独立电子邮件系统之一是FidoNet,它已经存在很长时间,并且至今仍在使用。FidoNet 是一个使用调制解调器和专有协议连接的全球网络;从本质上讲,它是全球 TCP/IP 互联网的“竞争对手”。我把竞争对手这个词放在引号里,因为 FidoNet 和 TCP/IP 互联网在用户数量和它们支持的应用类型方面并不真正可比,但它们在总体目标上相似:全球电子通信。

FidoNet 用户使用四个数字来识别,这些数字指定了 FidoNet 的区域、网络、节点点(连接点)。这些寻址元素用于在该系统中发送邮件,这再次与 TCP/IP 完全不同。然而,为了允许 TCP/IP 和 FidoNet 之间的通信,FidoNet 管理员已经建立了一个网关系统,允许使用 TCP/IP 风格的域名发送邮件。这种映射方式也被其他具有专有邮件地址格式的系统所采用,以允许它们与互联网接口。

例如,如果一个用户在机器 4,节点 205,网络 141,区域 1(北美),FidoNet 地址将是 1:141/205:4。等效的域名将是 p4.f205.n141.z1.fidonet.org,并且可以用于 TCP/IP 风格的用户@域名寻址。

UUCP 风格的寻址

与电子邮件相关联的一种较老的地址风格是 UUCP 风格的地址。Unix-to-Unix Copy Protocol (UUCP) 在 SMTP 广泛部署之前被广泛使用来路由邮件(再次强调,它仍然在使用,但不像以前那么普遍)。在这个系统中,地址被指定为由感叹号(!)分隔的主机路径。路径决定了邮件到达特定用户的路由,通过一系列运行 UUCP 的中间机器。例如,如果发送到 joesplace 主机上的 joe 的邮件必须通过三个主机——host1、host2 和 host3,那么地址将是 host1!host2!host3!joesplace!joe。由于感叹号的俚语是 bang,因此这种表示法被称为 bang path 表示法。

当 DNS 开始使用时,UUCP 风格的表示法有时会与 TCP/IP 风格的域名地址表示法混合使用。因此,你可能会看到类似 host1!user@domain 的地址。在如何确切解释此类地址方面存在一些混淆:这是否意味着首先发送邮件到 host1,然后到 user@domain?或者这是否意味着首先发送到域名,然后到达 host1 的用户?对此没有统一的答案。这个问题主要是由 UUCP 的使用减少以及 UUCP 系统转向 TCP/IP 风格的域名地址表示法来解决的。

网关地址方式

你可能会遇到看起来像使用不寻常的标点符号嵌套了多个 TCP/IP 地址的电子邮件地址。例如,你可能会看到这样的地址:user%domain1.com@subdomain.domain2.edu。这是一种在电子邮件网关使用时有时会看到的地址方式;它会导致邮件被发送到 subdomain.domain2.edu 的 user%domain1.com。然后,该地址被解释为 user@domain1.com。然而,再次强调,并非所有系统都能保证以相同的方式解释这一点。

电子邮件网关通常不是一件简单的事情,正如你所看到的,其中一个原因是使用了不同的电子邮件地址风格,以及复杂混合地址解释的一致性问题。然而,随着互联网的扩展和 TCP/IP 的更广泛使用,这些较老的特殊地址格式变得越来越少见。它们越来越多地成为历史趣闻(除非你恰好使用其中之一)。

TCP/IP 电子邮件别名和地址簿

邮件类似于普通邮件,但由于数字和电子通信的两个主要优势,它优于普通邮件。一个优势是速度,这就是为什么现代互联网用户发明了俚语“蜗牛邮件”来指代普通邮政服务。但另一个优势,灵活性,同样至关重要。电子邮件允许你以普通邮件难以实现的方式轻松发送消息。这种灵活性在地址方面表现得尤为明显。

邮件地址的灵活性首先体现在大多数电子邮件客户端支持高级功能,允许用户以方便的方式指定收件人的身份。虽然 TCP/IP 地址比较直接,但记住你所认识的人的地址是困难的。在现实生活中,我们使用地址簿来帮助我们记住地址。通过电子邮件,我们可以通过允许电子邮件软件将一个名字与一个电子邮件地址关联来实现同样的功能。

这通常有两种方式。在老式的基于文本的电子邮件中,如许多 UNIX 系统上使用的,使用别名来执行名字和地址的关联。这些是电子邮件地址的简写形式,可以节省输入。例如,我经常给我妻子 Robyn 发邮件,但我懒得每次都输入她的完整地址。所以我在我的电子邮件程序中为她定义了一个别名,简单地叫r。我输入邮件命令并指定别名r作为预期的收件人,它会为我展开她的电子邮件地址。

在现代图形电子邮件系统中,不使用别名。相反,通常实现一个电子地址簿,这相当于纸质地址簿。区别在于没有手动复制;你只需用鼠标从列表中选择名字即可。

多个收件人地址指定

邮件地址的另一个优点是它允许轻松指定多个收件人。使用纸质邮件,给十个人发送信息意味着你需要十份信息、十个信封和十个邮票。通过电子邮件,你只需在收件人列表中以逗号分隔列出收件人地址:user1@domain1user2@domain2user3@domain3。每个收件人都会收到一个单独的副本。当然,也可以使用别名和/或地址簿来指定每个收件人,使这个过程更加简单。

由于电子邮件使得一个人向一组人发送信息变得非常容易,所以被称为一对多的消息传递,这也是电子群组通信最早实现的方式之一。在电子邮件出现之前,在小组环境中共享信息需要面对面会议或电话会议。在这两种情况下,所有参与者必须同时在场,并且涉及成本,尤其是当参与者地理位置相距遥远时。

通过电子邮件,一组人可以共享信息,而无需见面或同时在线。假设一个小组由四个人组成:Ellen、Joe、Jane 和 Tom。Ellen 有一个她想要讨论的提案。她把它发送给 Joe、Jane 和 Tom。每个收件人都会在方便的时候阅读它。然后每个人都可以向小组回复。例如,Tom 可能对提案有评论,所以他只需把它发送给 Ellen、Joe 和 Jane。大多数电子邮件客户端都包括一个群组回复功能来达到这个目的。

邮件列表

在较大的群体中,通过键入每个收件人的地址来进行沟通变得繁琐。相反,使用邮件列表。列表是由一个被称为列表所有者的个人创建的,包含该群体所有成员的电子邮件地址。创建了一个特殊的列表地址,它就像一个普通的电子邮件地址一样工作。然而,当任何人向这个特殊地址发送邮件时,它并不是简单地存入邮箱。相反,它会被特殊的软件拦截,该软件处理消息并将其自动发送给列表上的所有收件人。任何收件人都可以回复列表地址,所有成员都会收到回复。

现在有许多其他方式可以供群体用来分享信息,例如使用万维网公告板、Usenet 新闻组、互联网中继聊天(IRC)等等。其中一些拥有许多功能,使得邮件列表看起来显得不够复杂。尽管如此,电子邮件列表仍然非常受欢迎,这主要是因为电子邮件是最通用的互联网通信方式,也是使用起来最简单的方法之一。

互联网上正在使用成千上万的邮件列表,涵盖每一个可以想象的主题。每个列表在许多方面都有所不同,包括以下五个方面:

实施 通常,一些特殊的软件被用来允许列表所有者管理列表、添加和删除用户,并设置控制列表运作的参数。这些程序通常被称为机器人listservs(列表服务器)。其中较为常见的列表服务器之一名为Majordomo。一些邮件列表实际上是通过网络实现的和管理。(互联网应用之间的界限正变得越来越模糊。)

订阅规则和技术 一些邮件列表对任何希望加入的人开放;而另一些则仅限邀请加入。大多数允许新订阅者使用软件自动加入;而另一些则要求列表所有者添加新成员。

管理方法和风格 列表所有者决定在列表上讨论的内容是否可接受。有些列表是受管理的,这意味着所有提交给列表的内容都必须在发送给列表成员之前得到列表所有者的批准。有些列表允许非成员向列表发送邮件,而有些则不允许。

文化 与所有群体一样,邮件列表中的群体也有自己的文化、有趣的个性和其他独特的特质。新加入列表的成员通常会被鼓励先阅读列表内容,而不是立即发送邮件,直到他们适应了列表的运作方式。这个过程与 Usenet 新手的适应过程类似(Usenet 的内容在第八十五章 和 TCP/IP 网络新闻传输协议 (NNTP)")中有介绍)。

特殊功能 一些列表支持特殊功能,例如以摘要模式(将消息收集到大型摘要中以减少发送的单独消息数量)订阅的能力,或者通过网页访问消息。

小贴士

关键概念 电子邮件的许多好处之一是,通过指定多个收件人地址,可以轻松地向许多人同时发送消息。这使得群组通信变得简单且直接,因为每个收件人都可以发送群组回复来回应收到原始消息的每个人。电子邮件列表为群体交换思想和信息提供了一种更正式化的方式;在互联网上使用了数以千计的此类列表。

第七十六章:TCP/IP 电子邮件消息格式和消息处理:RFC 822 和 MIME

无标题图片

使用计算机进行通信的优点是显而易见的,但计算机技术的使用也带来了一些限制。当我将电子邮件与普通邮件进行比较时,我总是指出电子邮件在交付方式上要快得多,也更加灵活,这是真的。一封电子邮件可以在几秒钟内到达目的地,而一封传统信件可能需要几天。

然而,使用计算机进行通信的一个显著缺点是,它们在理解消息方面不太灵活。考虑一下,任何人都可以将任何类型的信件、备忘录或其他通信放入信封并发送给您,并且假设您知道它所写的语言,您就可以打开信封并可能理解它。您可以弄清楚如何处理信件中不寻常位置出现的日期,或者您的名字出现在顶部而不是底部,或者消息正文以不同的方式结构化。您可以阅读用钢笔、铅笔或蜡笔打字或手写的笔记——只要字母可辨认,您就可以理解正在说的话。

计算机不擅长解读这样的细微差别。正因为如此,电子邮件系统必须依赖于标准消息格式来确保所有消息都具有相同的形式和结构。这使得电子邮件系统中的所有设备都能够读取和理解彼此的消息,从而使 TCP/IP 电子邮件能够在许多不同类型的计算机上工作。

在本章中,我描述了用于 TCP/IP 电子邮件消息的两种格式:主要的 TCP/IP 电子邮件标准,该标准被称为 RFC 822 格式,这是定义该标准的标准名称,以及多用途互联网邮件扩展(MIME)标准,该标准通过定义将各种媒体和非英语文本编码到标准 RFC 822 格式的方法,极大地扩展了电子邮件支持不同类型信息通信的能力。

TCP/IP 电子邮件 RFC 822 标准消息格式概述

我阅读过的关于互联网应用的最精辟的观察之一是,它们的有用性与使用它们的人数成正比。TCP/IP 电子邮件就是一个很好的例子。它是一种强大的通信方法,在很大程度上是因为今天几乎每个拥有电脑的人都参与了该系统。使用电子邮件的人数越多,它就越强大。

TCP/IP 电子邮件的创造者意识到,使用该系统的人会使用许多不同类型的硬件和软件。为了确保每个人都能理解所有电子邮件消息,无论谁发送它们,他们都指定了一个通用的电子邮件消息格式。这个格式没有官方的华丽名称;它只是以定义它的标准名称而闻名:RFC 822 消息格式。

小贴士

相关信息 本讨论将参考对简单邮件传输协议(SMTP;见第七十七章"))的讨论,但设计得如此,以便您在学习 SMTP 之前阅读它而不会感到困惑

传递电子邮件的主要协议是简单邮件传输协议(SMTP)。因此,TCP/IP 电子邮件所使用的消息格式可以被认为是 SMTP 的协议消息格式,这与讨论其他协议(如互联网协议(IP)和传输控制协议(TCP))时提到的特殊消息格式类似。然而,TCP/IP 电子邮件消息格式不仅被 SMTP 使用,还被所有处理电子邮件的协议和应用使用。这包括邮件访问协议邮局协议(POP3)和互联网消息访问协议(IMAP),以及其他一些协议。它也被设计成可能适用于其他非 TCP/IP 邮件投递协议。也许正因为如此,TCP/IP 电子邮件格式并没有作为 SMTP 本身的一部分,即 RFC 821,来指定,而是在一个配套文件 RFC 822 中进行了指定。两者都是在 1982 年发布的。

RFC 822 消息格式标准的开发

TCP/IP 所使用的消息格式的历史可以追溯到 1982 年之前。它最初在 20 世纪 70 年代初被定义为在互联网的前身 ARPAnet 上传递文本消息的格式。该格式经过多次改进,最终在 1977 年发布了重要的电子邮件标准 RFC 733,“ARPA 网络文本消息格式标准”。RFC 822 随后简化了 RFC 733 的内容,移除了一些在早期标准中描述但未能获得认可的功能,并简化了规范。

在 2001 年,SMTP 和 RFC 822 消息格式都进行了修订;SMTP 现在由 RFC 2821 描述,消息格式由 RFC 2822 描述。这个更新的标准对 RFC 822 消息格式进行了相对较小的修改,以反映 TCP/IP 电子邮件的现代使用。尽管 RFC 2822 是当前标准,但原始名称仍然是最常用的名称。在这个讨论中,我将尊重这个惯例,基于 RFC 2822 描述消息格式,同时仍然称之为 RFC 822 消息格式。

RFC 822 格式描述了 TCP/IP 电子邮件消息的格式、结构和内容。正如我所说的,它与 TCP/IP 中其他协议使用的消息格式类似。像那些其他格式一样,RFC 822 格式可以逻辑上分为两个主要部分:消息头,其中包含重要的控制和描述信息,以及消息体有效载荷,它携带数据。

RFC 822 消息概述

RFC 822 与其他协议的字段格式在表达上有所不同。大多数 TCP/IP 协议将头信息编码成一组紧凑的字节,这些字节根据它们在消息中的位置和分配给它们的语义意义进行读取和理解。以 IP 为例。每个 IP 数据报的第九个字节是生存时间 (TTL) 字段,它编码为从 0 到 255 的值。读取 IP 数据报的设备只需知道第 9 个字节包含 TTL 值。如果它在那里看到二进制值 00010011,它就知道这个数据报的 TTL 值是十进制的 19。

与此相反,RFC 822 消息不使用二进制格式。它们完全由常规 ASCII 文本行组成(在美国使用,标准中称为 US-ASCII),即使是标题。每一行都以 ASCII 回车 (CR) 字符结束,后面跟着一个 换行 (LF) 字符;这个组合统称为 CRLF。每行文本应包含 78 个或更少的字符(不包括终止的 CRLF),并且不能超过 998 个字符(同样,不包括 CRLF)。此外,CR 和 LF 字符不得单独出现在文本中。

RFC 822 消息以一组文本行开始,这些行共同构成了消息头。每个头字段都以以下形式在文本中表示:<头名称>: <头值>。例如,如果 RFC 822 消息中有一个 TTL 字段(实际上没有,因为这个概念并不特指电子邮件),并且需要表示值为 19,则头字段将如下所示:生存时间: 19

将所有字段都表示为简单文本意味着每个头在每个消息中占用更多空间;字符串 生存时间: 19 包括终止的 CRLF 共占用 18 个字节,而 IP 头中二进制编码的 TTL 字段只占用一个字节。我们从这一点获得的是两个重要的好处:

  • 任何用户都可以轻松检查头部,并立即了解哪些头部存在以及它们的值是什么,这使得 RFC 822 消息非常易于阅读。

  • 由于每个头部都有明确的标签,RFC 822 消息在包含的头部数量以及它们出现的顺序上可以有所不同,这使得它们具有灵活性。

通用 RFC 822 消息结构

RFC 822 消息始终以一组头部字段开始(如下一节所述)。在所有头部之后,必须出现一个空行。这仅由 CRLF 字符组成,紧随最后一个头部字段行末的 CRLF 之后。看到连续的两个 CRLF 字符对,设备读取消息时会知道头部已经结束。所有剩余的行都被认为是消息的正文。像头部行一样,正文行由 ASCII 文本组成,长度不得超过 998 个字符,建议长度为 78 个字符或更少(以便在标准 80 字符终端显示器上更容易阅读)。

小贴士

关键概念 为了确保 TCP/IP 互联网上的每个设备都能读取由每个其他设备发送的电子邮件,所有消息都必须遵循特定的结构。首先指定现代 TCP/IP 电子邮件消息形式的规范是 RFC 822,因此现在被称为RFC 822 消息格式。一个 RFC 822 消息由一组消息头部和一个消息正文组成,它们由一个空行分隔。RFC 822 消息必须只包含纯 ASCII 文本字符。每行长度不得超过 1,000 个字符,最后两个字符必须是 ASCII CR 和 LF 字符,以标记行尾。

由于电子邮件消息的头部和正文都是简单的 ASCII 文本,整个消息就是一个文本文件,因此这些消息非常易于阅读,也易于创建。您可以使用简单的文本编辑器创建完整的电子邮件消息,包括头部,并且可以使用简单的文本显示工具阅读。这有助于电子邮件的普及。

缺点是,决定使消息完全为 ASCII 意味着 RFC 822 消息中没有任何原生支持用于需要更复杂结构或无法使用有限的 ASCII 字符表达的内容。因此,您不能直接使用 ASCII 表达图片、二进制文件、电子表格、声音剪辑和类似类型的文件。此外,ASCII 的使用使得 RFC 822 非常适合表达英语消息,但不适合许多 ASCII 无法表示字符的其他语言。所有这些限制最终促使了增强的 MIME 消息格式的创建,我们将在本章后面详细探讨。

TCP/IP 电子邮件 RFC 822 标准消息格式头部字段和组

RFC 822 消息格式描述了 TCP/IP 电子邮件消息的结构和内容。结构有意设计得简单,易于创建和理解。每条消息以一组描述消息及其内容的头信息开始。一个空行标志着头信息的结束,然后是消息体。

消息体包含发送者与收件人沟通的实际文本,而消息头包含各种目的的信息。头信息通过指定收件人、描述消息内容以及提供有关在消息交付过程中发生处理的信息来帮助控制消息的处理方式。

头字段结构

如前所述,

字段是头信息的名称,
是与该头信息相关联的值,这取决于头信息类型。像所有 RFC 822 行一样,头信息长度不得超过 998 个字符,建议长度不超过 78 个字符,以便更容易阅读。RFC 822 和 2822 标准支持一种特殊语法,允许在头信息非常长时将其折叠到多行。这是通过将头信息值继续到新行来完成的,该新行必须以至少一个空白字符开始,例如空格或制表符,如下所示:

: <header value part 1>
<header value part 2>
<header value part 3>

制表符通常用于此目的。例如,如果我们想指定大量收件人,可以这样做:

To:person1@domain1.org, person2@domain2.com,
person3@domain3.net, person4@domain4.edu

头字段组

RFC 822 消息格式指定了许多可以包含在电子邮件中的头信息类型。少数头信息是强制性的,意味着它们必须包含在所有消息中。一些不是强制性的,但通常存在,因为它们对于描述消息是基本的。其他可选头信息仅在需要时包含。

为了帮助组织许多头信息,RFC 2822 标准将它们分类为头字段组(RFC 822 也这样做,尽管在旧标准中组略有不同):

起源日期字段指定消息准备交付的日期和时间;有关详细信息,请参阅下一节。(这个字段单独成组的原因对我来说不太清楚;可能只是因为它非常重要。)

发件人字段包含有关消息发送者的信息。

目标地址字段指定消息的收件人,可能属于以下三个不同的收件人类别之一:主要收件人("To")、抄送收件人("Cc")和暗送收件人("Bcc")。

标识字段包含帮助识别消息的信息。

信息字段 包含可选信息,以帮助接收者了解消息的内容。

重发字段 在重发消息时保留原始发起者、目的地和其他字段。

跟踪字段 显示邮件在传输过程中所经过的路径。

此外,格式允许指定其他用户定义字段,只要它们对应于标准的 <头部名称>: <头部值> 语法。这可以用来提供各种类型的信息。例如,有时电子邮件客户端软件会包含一个头部行,指示用于编写和发送消息的软件的名称和版本。正如您将在本章后面看到的那样,MIME 使用新的头部行来编码有关 MIME 消息的信息。

小贴士

关键概念 每个 RFC 822 消息都以一组 头部 开头,这些头部包含有关消息的基本信息。这些头部用于管理消息的处理和解释方式,并且它们还描述了消息主体的内容。每个头部由一个 头部名称 和一个 头部值 组成。有十几种不同的标准 RFC 822 头部可供使用,并组织成组。还可以定义自定义用户头部。

常见头部字段分组与头部字段

表 76-1 描述了 TCP/IP 电子邮件消息中的头部字段及其使用方式。

表 76-1. RFC 822 电子邮件头部字段分组与字段

字段组 字段名称 出现形式 每条消息的出现次数 描述
发起日期 Date: 必需 1 指示邮件传输系统可供投递的日期和时间。这通常是用户告诉其电子邮件客户端发送消息的日期/时间。
发起者字段 From: 必需 1 发送消息的用户的电子邮件地址,应该是消息的来源者。
发件人: 可选 1 发送电子邮件的人的电子邮件地址,如果与消息发起者不同。例如,如果 B 人发送包含 A 人消息的电子邮件,A 人的地址将放在 From: 头部,B 人的地址将放在 Sender: 头部。如果发起者和发送者是同一人(通常是这种情况),则此字段不存在。
回复到: 可选 1 告知消息接收者,发起者希望接收者用于回复的地址。如果不存在,回复通常发送回 From: 地址。
目标地址字段 To: 通常存在 1 消息的主要接收者列表。
抄送: 可选 1 包含接收消息副本的收件人列表(抄送 代表碳副本,如旧式打字机中使用)。在将消息发送到抄送:标题中列出的某人以及标题中的某人之间没有技术上的区别。区别仅在于收件人如何解释消息。通常,抄送:列表中的人是消息的主要收件人,而抄送:列表中的人是为了信息目的而被抄送消息的人。
密送: 可选 1 包含接收“盲”副本的收件人列表,其他收件人不知道他们已经收到了副本。例如,如果 X 在 收件人 行中指定,Y 在 抄送 行中,Z 在 密送 行中,那么三个人都会收到消息的副本,但 X 和 Y 不会知道 Z 已经收到了副本。这是通过在消息交付前删除 密送 行或更改其内容来实现的。
识别字段 Message-ID: 应该存在 1 为识别消息提供唯一代码;通常在发送消息时生成。
In-Reply-To: 可选,通常用于回复 1 当回复另一条消息时,在此字段中指定原始消息的 Message-ID:字段,以告知收件人回复的消息与哪条原始消息相关。
参考文献: 可选 1 识别与该消息相关的其他文档,例如其他电子邮件消息。
信息字段 主题: 通常存在 1 描述消息的主题或内容。
评论: 可选 无限制 包含关于消息的总结性评论。
关键词: 可选 无限制 包含可能对收件人有用的逗号分隔的关键词列表。在搜索特定主题的消息时可以可选使用。
重新发送字段 重新发送-日期:重新发送-发件人:重新发送-发件人:重新发送-收件人:重新发送-抄送:重新发送-密送:重新发送-消息-ID: 每次重新发送消息时都需要一个重新发送块 对于每个重新发送块,重新发送-日期:和重新发送-发件人:是必需的;其他的是可选的 仅在原始收件人将消息转发给其他人时使用,称为转发。例如,X 可能将消息发送给 Y,Y 再将其转发给 Z。在这种情况下,原始的日期:、发件人:和其他头信息保持不变,就像 X 发送消息时一样。重新发送-日期:、重新发送-发件人:和其他重新发送头信息用于指示重新发送消息的日期、发起者、收件人和其他特征。
跟踪字段 已接收:返回路径: 由电子邮件系统插入 无限制 在处理消息并将其从发起者传输到收件人的过程中由计算机插入。可用于追踪消息在电子邮件系统中的路径。

TCP/IP 电子邮件 RFC 822 标准消息格式处理和解释

定义 SMTP 的标准将协议描述为负责传输邮件对象。邮件对象被描述为由两个组件组成:一条消息和一个信封。消息是电子邮件消息中的所有内容,包括消息头和正文;信封包含完成消息传输所需的所有信息。

这些对象之间的区别在技术上很重要。正如邮政服务在决定如何处理一封信时只看信封而不是信件内容一样,SMTP 在决定如何发送消息时也只看信封。它不依赖于实际消息中的信息来进行基本传输。

因此,信封并不等同于消息头信息。然而,正如您通过查看电子邮件头信息列表可以看出的,每条消息都包括收件人和其他用于邮件传输所需的信息。因此,通常电子邮件消息会指定足够多的头信息来完成其自身的投递。电子邮件软件可以处理和解释消息,以构建 SMTP 传输消息到目标邮箱所需的信封。关于电子邮件消息与其信封之间的区别,在描述 SMTP 邮件传输的章节中进行了更详细的讨论,请参阅第七十七章").

由于 RFC 822 消息格式简单,处理 RFC 822 消息相对直接。完整的电子邮件消息的创建始于用户创建消息时创建消息体和某些头信息。每当一条消息被软件程序“处理”时,都会检查头信息,以便程序可以确定如何处理它。根据需要,还会添加和更改额外的头信息。

以下是在消息头信息生命周期中发生的事件序列。

创作 消息的人类创作者编写消息正文,并告知电子邮件客户端程序某些重要头字段应使用的值。这些包括目标收件人、消息主题、其他信息字段以及某些可选头信息,如回复到字段。

发送客户端处理 邮件客户端处理消息,将人类提供的信息放入适当的头信息格式中,并创建初始的电子邮件消息。此时,它会在消息中插入某些头信息,例如起始日期。客户端还会解析目标收件人列表,以使用 SMTP 传输消息创建信封。

SMTP 服务器处理 在转发消息时,SMTP 服务器不会关注消息中的大多数字段。然而,它们会在传输消息时添加某些标题,特别是跟踪标题,如 Received 和 Return-Path。这些通常被添加到消息的开头,以确保现有的标题不会被重新排列或修改。请注意,然而,当在电子邮件系统之间进行网关操作(如第七十五章所述)时,某些标题实际上必须更改,以确保消息与非 TCP/IP 电子邮件软件兼容。

收件人客户端处理 当消息到达目的地时,收件人的 SMTP 服务器可能会添加标题来指示消息接收的日期和时间。

收件人访问 当消息的收件人使用客户端软件时,可以通过如 POP3 或 IMAP 等电子邮件访问协议,软件会分析邮箱中的每条消息。这使得软件能够以对人类用户有意义的方式显示消息,并可能允许选择特定的消息进行检索。例如,我们大多数人喜欢看到新收邮件的摘要列表,显示发件人、消息主题、接收消息的日期和时间,这样我们可以决定先阅读哪些邮件,哪些邮件推迟到以后阅读,以及哪些邮件不阅读直接删除(如垃圾邮件)。

MIME 概述

RFC 822 电子邮件消息格式是 TCP/IP 互联网中交换电子邮件的标准。它使用简单的 ASCII 文本,使得创建、处理和阅读电子邮件消息变得容易,这也为电子邮件作为全球通信方法的成功做出了贡献。

不幸的是,尽管 ASCII 文本非常适合撰写简单的备忘录和其他简短消息,但它没有提供灵活性来支持其他类型的通信。为了允许电子邮件携带多媒体信息、任意文件以及使用除 ASCII 字符集以外的字符集的语言消息,MIME 标准被创建。

注意

虽然 MIME 是专门为电子邮件开发的,但其编码和数据表示方法已被证明非常有用,以至于它也被其他应用协议所采用。其中最著名的是超文本传输协议(HTTP),它使用 MIME 标题来指示正在传输的数据的特征。MIME 的一些元素实际上并不是为电子邮件开发的,而是为 HTTP 或其他协议使用的,我在适当的地方指出了这一点。请注意,HTTP 只使用 MIME 的一些元素;HTTP 消息不是 MIME 兼容的

大多数协议之所以成功,特别是因为它们基于广泛接受的开放标准。RFC 822 电子邮件消息格式标准是一个很好的例子;每天都有数百万人使用它来发送和接收 TCP/IP 电子邮件。

然而,标准的成功是有代价的:对那些标准的依赖。一旦一个标准被广泛使用,就很难对其进行修改,即使时代变迁,该标准也不再满足现代计算的需求。不幸的是,RFC 822 电子邮件消息格式就是一个很好的例子。

MIME 的动机

MIME 的动机

TCP/IP 电子邮件是在 20 世纪 60 年代和 70 年代开发的。与今天计算机和网络世界相比,当时几乎一切都是“小”的。网络规模小;用户数量少;网络主机的计算能力小;网络连接的容量小;网络应用程序数量少。(当时唯一不“小”的是计算机本身的尺寸!)

由于这个原因,对电子邮件信息的要求也相对较小。当时的计算机输入和输出大多是文本基础的,因此 SMTP 和 RFC 822 标准的创造者将电子邮件视为严格意义上的文本媒介是很自然的。因此,他们指定 RFC 822 来传输文本消息。

初出茅庐的互联网也是在美利坚合众国开发的,最初,整个互联网都位于美国境内。大多数美国人讲英语,正如你可能知道的,英语使用相对较少的字符,这些字符可以用 ASCII 字符集很好地表示。当时定义电子邮件消息格式以支持美国 ASCII(US-ASCII)也是有意义的。

然而,随着计算机的发展,它们从严格的文本模型转向了图形操作系统。可以预见的是,用户对发送的内容产生了兴趣,不仅仅是文本。他们希望能够传输图表、非 ASCII 文本文档(如 Microsoft Word 文件)、二进制程序文件,以及最终的多媒体信息:数字照片、MP3 音频剪辑、幻灯片演示文稿、电影文件等等。此外,随着互联网的增长和全球化,其他国家也开始“上网”,其中一些国家使用的语言根本无法用 US-ASCII 字符集表达。

不幸的是,到了这个时候,事情已经定型。RFC 822 已经广泛使用,改变它也意味着 SMTP、POP 和 IMAP 等协议的工作方式也要改变,这些协议运行在数百万台机器上。然而,到了 20 世纪 80 年代末,很明显,纯 ASCII 电子邮件的限制是一个必须解决的问题。需要一种解决方案,而它以多用途互联网邮件扩展(MIME)的形式出现。

注意

从现在开始,MIME 通常用单数形式来指代,尽管它是一个复数术语的缩写

MIME 功能

MIME 背后的想法既巧妙又优雅:RFC 822 将电子邮件消息限制为 ASCII 文本,但这并不意味着我们不能为 ASCII 文本的创建定义一个更具体的结构。我们不仅可以让用户输入 ASCII 文本消息,还可以使用 ASCII 文本字符来编码非文本数据包(通常称为附件)。使用这种技术,MIME 允许常规的 RFC 822 电子邮件消息携带以下内容:

非文本信息 包括图形文件、多媒体剪辑以及之前列出的所有其他非文本数据示例。

任意二进制文件 包括可执行程序和存储在专有格式中的文件(例如,AutoCAD 文件、Adobe Acrobat PDF 文件等)。

使用除 ASCII 以外的字符集的文本消息 包括在 RFC 822 电子邮件消息的标题中使用非 ASCII 字符的能力。

MIME 甚至更进一步,通过实际定义一个结构,允许多个文件被编码成一个单独的电子邮件消息,包括不同类型的文件。例如,一个从事预算分析的人可以发送一个包含文本消息、PowerPoint 演示文稿和包含预算数字的电子表格的电子邮件消息。这种能力大大扩展了电子邮件在 TCP/IP 中的用途。

所有这些操作都是通过特殊的编码规则来完成的,这些规则将非 ASCII 文件和信息转换成 ASCII 形式。信息编码的方式会在消息中添加标题来指示。编码后的消息可以像其他任何消息一样通过系统发送。SMTP 和其他处理邮件的协议对消息体不感兴趣,因此它们甚至不知道 MIME 已被使用。

需要修改的电子邮件软件的唯一变化是向电子邮件客户端程序添加对 MIME 的支持。发送者和接收者都必须支持 MIME 来编码和解码消息。MIME 最初开发时,对 MIME 的支持并不广泛,但这项技术的价值非常显著,以至于今天几乎所有电子邮件客户端软件都包含它。此外,大多数客户端今天也可以使用 MIME 标题中的信息,不仅解码非文本信息,而且将其传递给适当的应用程序以供用户展示。

小贴士

关键概念 使用 RFC 822 消息格式确保所有设备都能读取彼此的电子邮件消息,但它有一个关键的限制:它只支持纯 ASCII 文本。这对于现代互连网络的需求来说是不够的,而且依赖于 RFC 822 标准会使替换它变得困难。MIME指定了几个方法,允许电子邮件消息包含多媒体内容、二进制文件和文本文件,同时仍然遵循 RFC 822 消息格式。MIME 还通过允许在单个消息中发送多个文件或内容片段来进一步扩展电子邮件的灵活性。

MIME 标准

MIME 首次在 1992 年 6 月发布的两套标准中进行了描述,分别是 RFC 1341 和 RFC 1342。这些标准在 1993 年 9 月通过 RFC 1521 和 RFC 1522 进行了更新。1994 年 3 月,又发布了一个补充标准,RFC 1590,该标准规定了定义新的 MIME 媒体类型的过程。

MIME 的工作在 1990 年代中期继续进行,并于 1996 年 11 月再次修订了标准。这次,文档被完全重构,以改善信息的可读性,并作为一套五个单独的标准发布。这些标准在 表 76-2 中展示。

自从这五个主要的 MIME 标准发布以来,已经发布了大量的附加 RFC,这些 RFC 定义了 MIME 本身的各种扩展,包括额外的 MIME 报头类型和新媒体类型。值得注意的例子是 RFC 2183 和 2557,分别定义了 MIME Content-Disposition 和 Content-Location 报头。一些其他 MIME 功能实际上被定义为使用 MIME 的其他技术的部分;例如,第一个 HTTP 标准,RFC 1945 定义了 Content-Length 报头。其他 RFC 定义了新的媒体类型和子类型(此处无法一一列出)。|

表 76-2. MIME 标准

RFC 编号 RFC 名称 描述
2045 多用途互联网邮件扩展 (MIME) 第一部分:互联网消息体的格式 描述了 MIME 背后的基本概念和 MIME 消息的结构。
2046 多用途互联网邮件扩展 (MIME) 第二部分:媒体类型 解释了 MIME 媒体类型和子类型的概念,并描述了 MIME 标准中定义编码的一些媒体类型。
2047 MIME (多用途互联网邮件扩展) 第三部分:非 ASCII 文本的消息报头扩展 描述了如何修改 RFC 822 报头以携带非 ASCII 文本。
2048 多用途互联网邮件扩展 (MIME) 第四部分:注册程序 讨论了组织如何为与 MIME 一起使用注册额外的媒体类型。
2049 多用途互联网邮件扩展 (MIME) 第五部分:一致性准则和示例 提供了额外的实现信息和 MIME 可以如何使用的示例。

MIME 基本结构和报头

MIME 标准的创建者面临着一个艰巨的挑战:如何在 RFC 822 规定消息只能包含 ASCII 文本的情况下,为电子邮件消息中的数据类型带来灵活性。为了实现这一点,MIME 创建者必须利用已经放入现有 RFC 822 中的灵活性区域。

有两种这样的机会:第一种是 RFC 822 消息体允许包含任何类型的 ASCII 文本,只要行不超过 998 个文本字符,并且每行以 CRLF 控制代码组合结束。尽管 RFC 822 的创建者自然假设这种 ASCII 文本将是可读的,但没有任何阻止它成为机器可读代码的东西。第二种机会是内置在 RFC 822(以及使用它的协议,如 SMTP)中的功能,允许向任何电子邮件消息添加自定义用户定义的头部字段。

RFC 822 消息体的非特定性质是 MIME 本身如何工作的基础。支持 MIME 标准的电子邮件客户端使用特殊的编码算法将非 ASCII 信息转换为 ASCII 形式。然后,它将这组编码的 ASCII 字符放入消息体中,就像用户使用两种特殊结构之一输入一样。

向 RFC 822 添加新头部的功能被用来从发送者向接收者传达有关 MIME 使用的信息。传输 MIME 消息的设备并不关心是否使用了 MIME,因为它们不关注消息主体的内容。然而,当消息到达目的地时,接收者的电子邮件客户端程序必须有一种方式知道使用了 MIME,并且必须被告知消息中的信息是如何编码的。否则,它可能只是将编码的非 ASCII 数据以 ASCII 文本的形式呈现给用户(这看起来像是一堆随机乱码)。

基本结构

数据在消息体中编码的方法以及 MIME 头部中包含的方法取决于 MIME 消息的整体结构。根据消息携带的媒体类型,描述了两种基本结构类型:

简单结构(离散媒体) 携带单个离散媒体类型(如文本消息或图形图像)的 MIME 消息使用简单结构。消息体中只存在一种信息编码。

复杂结构(复合媒体) 一些 MIME 消息携带复合媒体类型,这允许在单个消息中包含多种不同的媒体,例如文本消息和图形图像,或者允许电子邮件完全封装另一个电子邮件消息。许多这些消息使用更复杂的结构,其中消息体包含多个 MIME 主体部分。

MIME 实体

总体而言,整个 MIME 消息和单个体部分统称为MIME 实体。每套 MIME 头提供了关于这两种 MIME 实体类型的信息:整个 MIME 消息或复合消息中的体部分。当一个 MIME 消息被接收时,接收者首先检查整个消息的头(RFC 822 头)以确定整体消息类型。这随后指示消息是否使用简单或复杂结构。如果使用后者,则解析消息体,并对每个单独的体部分进行单独解释,包括其个性化的头。本章后面的“MIME 复合媒体类型”部分提供了关于这些体部分如何格式化的更多详细信息。

主要 MIME 头

五个主要 MIME 标准中的第一个,RFC 2045,描述了一组五个主要 MIME 头,这些头传递了关于每个 MIME 实体(消息或体部分)内容的基本信息。

MIME 版本 每个 MIME 消息都必须有一个 MIME-Version 头,它有两个作用。首先,它标识电子邮件消息是 MIME 编码的。其次,尽管到目前为止只定义了一个版本的 MIME,但拥有一个版本号头提供了未来证明,以防将来创建的新版本可能与当前版本不兼容。目前,所有 MIME 消息都使用版本 1.0。这是唯一适用于整个消息的 MIME 头;它不用于标记单个 MIME 体部分。这很容易记住,因为它是唯一一个名称不以 Content-开头的头。

Content-Type 描述了 MIME 实体中编码的数据的性质。此头指定了一个内容类型和一个内容子类型,它们由一个斜杠字符分隔。它还可以可选地包含某些参数,这些参数传达有关类型和子类型的额外信息。在消息体中,此头告诉电子邮件消息的接收者它包含什么类型的媒体以及体是否使用简单或复杂结构。在体部分中,它描述了体部分包含的媒体类型。例如,包含 HTML 文档的消息可能有一个Content-Type头为text/html,而包含 JPEG 图形文件的消息可能指定为image/jpeg。对于复合 MIME 类型,整个消息的Content-Type头将包含类似multipart/mixedmultipart/alternative的内容,并且每个体部分将包含单独的Content-Type头,如text/htmlimage/jpeg。这些内容将在下一节中详细讨论。此头是可选的。当不存在时,假定默认值为常规 US-ASCII 文本消息(常规 RFC 822 消息的媒体类型)。

内容传输编码(Content-Transfer-Encoding)对于使用简单结构的消息,指定用于在消息正文中编码数据的编码方法;对于复合消息,标识每个 MIME 正文部分的编码方法。对于已经是 ASCII 形式的数据,不需要特殊编码,但其他类型的数据必须转换为 ASCII 才能传输。此标题告诉收件人如何将数据解码回其正常表示形式。(MIME 编码方法将在本章后面描述。)此标题是可选的;如果不存在,默认值是 7 位编码,这又是常规 ASCII 的编码。

内容标识符(Content-ID)允许 MIME 内容被分配一个特定的标识代码。此标题类似于 RFC 822 消息标识符标题字段,但它是针对 MIME 内容本身的。它是可选的,通常用于多部分 MIME 消息的正文部分。

内容描述(Content-Description)此可选标题允许将任意附加文本描述与 MIME 实体关联。在多部分消息中,每个正文部分可能会被赋予一个描述标题,以便让收件人清楚地了解各部分代表的内容。

小贴士

关键概念 MIME 通过将非 ASCII 数据编码为 ASCII 形式,并添加描述这些数据及其解释方式的特殊标题,为电子邮件消息中可以携带的信息提供了灵活性。最重要的 MIME 标题是 内容类型(Content-Type),它描述了消息中包含的数据类型,以及 *内容传输编码(Content-Transfer-Encoding),它指定了数据的编码方式。MIME 支持两种基本整体格式:简单结构*,其中在消息中编码单一类型的 离散媒体,以及 复杂结构,它编码了一种 复合媒体 类型,可以携带多种类型的信息。

其他 MIME 标题

除了五个基本标题外,MIME 标准还允许定义额外的标题。唯一的限制是它们都必须以单词 Content- 开头,这清楚地表明它们是描述 MIME 实体(消息或正文部分)的内容。发送方和收件方都必须支持自定义标题,才能使其有用。

实际上已经创建了几个新的 MIME 标题,并在各种互联网 RFC 中进行了文档记录。其中一些实际上是为特定用于电子邮件消息之外设计的,而是用于利用 MIME 技术的其他协议,例如 HTTP。以下三个值得关注:

内容处置(Content-Disposition)在多部分 MIME 消息中,此标题可以用于 MIME 正文部分,以控制信息如何呈现给用户。两个最常见值是 *内联(inline),表示内容旨在与其他正文部分一起自动显示,以及 *附件(attachment),表示内容与主文档分开。此标题在 RFC 2183 中定义。

内容位置 允许使用统一资源定位符(URL)标识 MIME 主体部分的位置。这在将 HTML 和其他多媒体启用文档格式编码成 MIME 多部分消息用于电子邮件时有时会用到。它在 RFC 2557 中定义。

内容长度 指定 MIME 实体的字节数。这个报头在 MIME 的电子邮件应用中不常用,但在 HTTP 中是一个重要的报头。它在 HTTP 标准中描述,首次出现在 RFC 1945 中。

MIME 内容类型报头和离散媒体

MIME 使用特殊的技巧将各种类型的信息编码成 ASCII 文本形式,如图形图像、声音文件、视频剪辑、应用程序程序、压缩数据文件等。我们通常将这些称为不同类型的 媒体,MIME 使用相同的术语来描述它们。

由于 MIME 支持如此多种类的媒体,每个消息都包含描述其内容的必要信息,以便准确解码消息内容。这就是重要的 MIME 内容类型报头的功能。

内容类型报头语法

内容类型报头的语法如下:

Content-Type: / [; parameter1 ; parameter2 .. ; parameterN ]

这些不同元素的目的在于以从一般到具体的方式描述 MIME 实体中的媒体。第一个元素,,被称为 最高层媒体类型,描述了数据的整体形式。例如,它表示 MIME 实体是否包含文本、图像、音频等。第二个元素,,提供了关于数据形式或格式的具体信息。例如,JPEG 图像和 GIF 图像都是图像,但它们有不同的格式。在内容类型报头中, 都是必需的。

在这些元素之后可能出现一个或多个 参数,这些参数通常是可选的,但对于某些媒体类型可能是必需的。这些参数提供了关于数据性质的更多细节,当需要时提供。每个参数前面都有一个分号,并以属性/值对的形式表达,由等号(=)分隔,如下所示:; attribute=value

参数可能被用做的一个例子是在指定文本消息中的字符集。常规的 RFC 822 ASCII 文本的表示如下:

Content-type: text/plain; charset="us-ascii"

最高层媒体类型是 text,子类型是 plain,这表明这是一个纯文本消息。参数 charset 指定消息使用 US-ASCII 字符集。参数的另一个常见用途是指定附件文件的名称,如下所示:

Content-type: image/jpeg; name="ryanpicture.jpg"

离散媒体类型和子类型

如我之前所述,MIME 支持两种基本结构:简单和复杂。一个简单的消息只携带一种媒体类型,例如一段文本、一张图片或一个可执行文件。这些在 MIME 中被称为 离散媒体类型。一个复杂的消息携带一个 复合媒体类型,它可以包含多个正文部分。每个正文部分又携带与其中一个离散媒体类型相对应的数据。顶级媒体类型指示整个消息是否携带离散媒体类型或复合类型。

小贴士

关键概念 MIME 的 Content-Type 头部指定了 MIME 消息中编码的数据类型。该头部通过 顶级媒体类型 指示消息内容的通用形式,并通过指定 子类型 来指示数据的更具体性质。它还可以包含可选的 参数,提供有关内容的更多信息。

RFC 2046 标准(描述 MIME 的五个标准集中的第二个标准)定义了五个离散顶级媒体类型:textimageaudiovideoapplication。它们各自代表在 TCP/IP 上常见传输的数据的主要类别之一。每个类型都有一个或多个子类型,其中一些还包含用于提供更多信息的参数。

MIME 的创建者认识到,该标准无法描述每种媒体类型,并且未来将创建新的媒体类型。RFC 2048(MIME 集的第四部分)描述了如何通过该过程描述和将新的媒体类型、子类型和参数注册到互联网数字分配机构(IANA)。

到目前为止,只创建了一个新的顶级媒体类型;这是 model 顶级类型,用于 CAD 建模文件和类似用途,如 RFC 2077 所述。然而,多年来已经创建了数十个新的子类型,其中一些在 RFC 中指定,而另一些则直接在 IANA 进行注册。这包括许多供应商特定的子类型,通常通过子类型名称中的前缀 x-vnd 来识别。

现在存在数百种类型/子类型组合,我不会列出所有。您可以在 IANA 的网站上找到按顶级媒体类型组织的 MIME 媒体类型的完整列表:www.iana.org/assignments/media-types/index.html

在这里,我将简要描述六个 MIME 离散顶级媒体类型。对于每个类型,我都提供了一个表格,展示了一些更常见的 MIME 子类型,以给您一个大致的了解。

文本媒体类型 (text)

text 媒体类型用于发送主要以文本形式的数据。表 76-3 描述了这些子类型。

表 76-3. MIME 文本媒体类型子类型

类型/子类型 描述 定义来源
text/plain 纯文本,用于常规消息,如对应初始 RFC 822 标准的消息 RFC 2046
text/enriched 包含格式信息或其他增强信息,使其不再是纯文本的文本 RFC 1896
text/html 使用 HTML 表达的文档,通常用于万维网 RFC 2854
text/css 万维网的层叠样式表信息 RFC 2318

图像媒体类型 (image)

image 媒体类型表示图形图像文件,如图片。子类型通常表示特定的格式,以便接收者能够正确解码和展示文件。一些更常见的子类型在 表 76-4 中展示。

表 76-4. MIME 图像媒体类型子类型

类型/子类型 描述 定义来源
image/jpeg JPEG 格式的图像 RFC 2046
image/gif 图形交换格式 (GIF) 图像 IANA 表示 RFC 2046,但实际上并不在那里。
image/tiff 标记图像文件格式 (TIFF) 图像 RFC 2302

|

image/vnd.dwg,
image/vnd.dxf,
image/vnd.svf
在 AutoCAD 中使用的矢量图像 IANA 注册

音频媒体类型 (audio)

audio 媒体类型用于发送音频信息。子类型通常表示特定的格式。表 76-5 展示了一些常见的值。

表 76-5. MIME 音频媒体类型子类型

类型/子类型 描述 定义来源
audio/basic 在主要 MIME 标准中定义的基本音频类型,描述使用 8 位 ISDN mu-law 脉冲编码调制在 8,000 Hz 下编码的单通道音频 RFC 2046
audio/mpeg MPEG 标准音频(包括流行的 MP3 文件格式) RFC 3003

视频媒体类型 (video)

video 媒体类型用于发送视频信息。同样,子类型通常表示特定的格式,如 表 76-6 所示。

表 76-6. MIME 视频媒体类型子类型

类型/子类型 描述 定义来源
video/mpeg 视频编码为 MPEG 数字视频标准 RFC 2046
video/dv 与多种视频设备使用的 SD-VCR、HD-VCR 和 DVB 等多个流行标准相对应的数字视频 RFC 3189
video/quicktime 苹果的 QuickTime 电影格式 IANA 注册

模型媒体类型 (model)

model 媒体类型描述了一个模型表示,例如二维或三维物理模型。其子类型在 表 76-7 中描述。

表 76-7. MIME 模型媒体类型子类型

类型/子类型 描述 定义来源
model/mesh 用于建模的网格 RFC 2077
model/vrml 虚拟现实建模语言(VRML)模型 RFC 2077
model/iges 与初始图形交换规范(IGES)相对应的模型文件 在 IANA 进行注册

应用媒体类型(application)

application 媒体类型是任何不适合前面类别或本质上是应用程序特定的数据的通用类型。子类型通过指明使用它的应用程序类型来描述数据。这可以用来指导收件人的电子邮件程序选择一个适当的应用程序程序来显示它,就像 Windows 中的文件扩展名告诉操作系统如何打开不同类型的文件一样。

例如,如果你在电脑上安装了 Microsoft Excel,点击以 .XLS 结尾的文件名将自动启动 Excel。同样,Excel 电子表格通常使用 MIME 以 application/vnd.ms-excel 的媒体类型发送。这告诉收件人的电子邮件程序启动 Excel 来读取此文件。

由于存在许多应用程序,这个顶级类型中存在超过 100 个不同的子类型。表 76-8 包含了一些代表性的样本。

表 76-8. MIME 应用媒体类型子类型

类型/子类型 描述 定义来源
application/octet-stream 一组任意的二进制数据八位字节(有关更多详细信息,请参阅此表之后的讨论) RFC 2046
application/postscript 用于打印和生成 Adobe Acrobat (PDF) 文件的 PostScript 文件 RFC 2046
application/applefile 表示 Apple Macintosh 文件的资源文件信息 在 IANA 进行注册
application/msword Microsoft Word 文档(注意,这与大多数其他 Microsoft 文件类型不同,没有 vnd 前缀) 在 IANA 进行注册
application/pdf Adobe Acrobat 创建的便携式文档格式(PDF)文件 在 IANA 进行注册
application/vnd.framemaker Adobe FrameMaker 文件 在 IANA 进行注册
application/vnd.lotus-1-2-3 Lotus 1-2-3 文件 在 IANA 进行注册
application/vnd.lotus-notes Lotus Notes 文件 在 IANA 进行注册
application/vnd.ms-excel Microsoft Excel 工作表文件 在 IANA 进行注册
application/vnd.ms-powerpoint Microsoft PowerPoint 演示文稿文件 在 IANA 进行注册
application/vnd.ms-project Microsoft Project 文件 在 IANA 进行注册
application/zip 包含一个或多个其他文件的压缩存档文件,使用 ZIP/PKZIP 压缩格式 在 IANA 进行注册

在这些应用程序子类型中,有一种特别值得进一步提及:`application/octet-stream` 子类型。这是在应用程序类型中的万用类型,仅仅意味着文件是一系列任意二进制数据。通常在发送者不确定数据的形式或无法将其识别为属于特定应用程序时使用。当使用此类型时,接收者通常会提示将数据保存到文件。然后他必须弄清楚使用什么应用程序来读取它。

```application/octet-streamMIME 类型/子类型甚至可以用于未知格式的图像、音频或视频。如果你尝试发送发送程序不理解的多媒体文档,它通常将其编码为application/octet-stream` 以进行传输。这是你的电子邮件程序向接收者表示“我正在以这种方式发送此文件;你自己决定如何处理它。”的一种方式。``

这种 `application/octet-stream` 类型也常用于在 Windows 系统上传输可执行文件(程序)。不幸的是,虽然方便,但这可能是一个严重的安全隐患。近年来,互联网一直受到病毒和蠕虫的持续侵袭,它们通过将自身作为电子邮件附件发送给其他用户来传播。这使得打开和运行任何未知的 `application/octet-stream` 附件可能具有潜在的危险。

# MIME Composite Media Types: Multipart and Encapsulated Message Structures MIME discrete media types allow MIME to represent hundreds of different kinds of data in email messages. This alone would make MIME an incredibly useful technology, but the MIME standard goes one step further by defining *composite* media types. These allow MIME to perform even more spectacular feats, such as sending many types of data at once or encapsulating other messages or information into email. The use of a MIME composite media type is indicated via the Content-Type header of an RFC 822 message. Instead of one of the six discrete media types (`text`, `image`, `audio`, `video`, `model`, or `application`), one of these two composite media types is used: `multipart`, which allows one or more sets of data to be sent in a single MIME message, and `message`, which allows a message to encapsulate another message. ### Tip **KEY CONCEPT** Two MIME composite media types exist: `message`, which allows one message to encapsulate another, and `multipart`, which allows multiple individual media types to be encoded into a single email message. ## MIME Multipart Message Type The `multipart` media type is the more common of the two types, and for good reason: It is an *incredibly* powerful mechanism. It allows one message to contain many different kinds of information that can be used in different ways. Each piece of data is encoded separately as a MIME body part, and the parts are combined into a single email message. How these parts are used depends on the semantics of the message, indicated by the MIME subtype. RFC 2046 describes several of these, and a few new ones have also been defined by the IANA registration scheme described earlier. ### MIME Multipart Message Subtypes Table 78-9 shows the most common multipart media subtypes and how they are used. The first four are defined in RFC 2046. Table 76-9. Common MIME multipart Media Type Subtypes | Type/Subtype | Description | Defining Source | | --- | --- | --- | | `multipart/mixed` | Indicates that the body parts are not really related, but they have been bundled for transport in a single message for convenience. For example, this might be used by someone to send an office memo along with a vacation snapshot just for fun. This subtype is also sometimes used when the parts are related but the relationship is communicated to the recipient in some other way (such as via a description in a distinct body part). | RFC 2046 | | `multipart/alternative` | Specifies that the body parts are alternative representations of the same information. The recipient decodes the parts and chooses the one that is best suited to her needs. A common use of this is in sending Hypertext Markup Language (HTML)-encoded email. Some email clients can't display HTML, so it is courteous to send a *multipart/alternative* message containing the message in both HTML and plain text forms. The alternatives should be placed in the message in increasing order of preference, meaning that the preferred format goes last. In the case of a document that includes plain text and rich text alternatives—such as the preceding example with plain text and HTML versions of a document—the plainest format should go first and the fanciest last. | RFC 2046 | | `multipart/parallel` | Tells the recipient that the body parts should all be displayed at the same time (in parallel). For example, someone sends an audio clip along with explanatory text to be displayed alongside it as it plays. | RFC 2046 | | `multipart/digest` | Allows a message to carry a digest, such as a collection of other email messages. | RFC 2046 | | `multipart/related` | Indicates specifically that the body parts are related to each other. Special parameters are used to provide more information on how they are to be interpreted. | RFC 2387 | | `multipart/encrypted` | Used for encrypted data. The first body part contains information on how the data is to be decrypted, and the second contains the data itself. | RFC 1847 | ## Multipart Message Encoding You can see just from the different subtypes shown in Table 78-9 how much flexibility the multipart type provides to MIME, and there are other subtypes. In all cases, the same syntax is used to encode the constituent body parts into a single message. The basic process is as follows: 1. Each individual piece of data is processed as if it were to be transmitted as the body of a discrete media type MIME message. This includes the specification of appropriate headers, such as Content-Type, Content-ID, and Content-Transfer-Encoding, as needed. 2. A special *boundary delimiter* is chosen to separate the body parts. It must be selected so that it will not appear in any of the body parts; a random string is sometimes used. It is prepended with two dashes (—) when placed in the message to reduce the chance of it being mistaken for data. 3. The multipart message is assembled. It consists of a *preamble* text area, then a boundary line, followed by the first body part. Each subsequent body part is separated from the previous one with another boundary line. After the last body part, another boundary line appears, followed by an *epilogue* text area. 4. The special parameter *boundary* is included in the Content-Type header of the message as a whole, to tell the recipient what pattern separates the body parts. ### Tip **KEY CONCEPT** MIME multipart messages are formed by first processing each individual data component to create a MIME *body part*. Each can have a distinct encoding method and set of headers, as if it were a separate MIME message. These body parts are then combined into a single multipart message and separated with a *boundary delimiter*. The identity of the delimiter is inserted into the *boundary* parameter of the *Content-Type* header, so the recipient can easily separate the individual body parts upon receipt of the message. These rules may seem rather complicated, but once you've seen a couple of multipart messages, the structure will make sense. To help clarify multipart message encoding, Figure 76-1 shows graphically the overall structure of a multipart MIME message. Example 76-1 contains a specific example of a multipart message (with portions abbreviated to keep the length down), so you can see what one looks like in text form. (If you want to see more, you probably have several in your own email inbox right now!) Example 76-1. Example of a MIME multipart message ``` From: Joe Sender <joe@someplace.org> To: Jane Receiver <jane@somewhereelse.com> Date: Sun, 1 Jun 2003 13:28:19 —0800 Subject: Photo and discussion MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="exampledelimtext123" This is a multipart message in MIME format -exampledelimtext123 Content-Type: text/plain Jane, here is the photo you wanted from me for the new client. Here are some notes on how it was processed. (Blah blah blah...) Talk to you soon, Joe. -exampledelimtext123 Content-Type: image/jpeg; name="clientphoto.jpg" Content-Transfer-Encoding: base64 SDc9Pjv/2wBDAQoLCw4NDhwQEBw7KCIoOzs7Ozs7Ozs ... zv/wAARCADIARoDASIAAhEBAxEB/8QAHAAAAQUBA -exampledelimtext123 (Epilogue) ``` ![MIME multipart message structure A MIME multipart message consists of a set of main headers and a main body portion, like all messages. Within the main body are one or more body parts, each of which has its own body-part-specific headers followed by the body part itself; each body part is shown in a black box. The Content-Type header of the message as a whole indicates that the message type is multipart, and the boundary parameter specifies the name of the delimiter, in this case just called "Delimiter." This delimiter is used to separate the body parts from each other and from the preamble and epilogue that begin and end the message body, respectively.](https://github.com/OpenDocCN/greenhat-zh/raw/master/docs/tcpip-gd/img/httpatomoreillycomsourcenostarchimages288289.png) Figure 76-1. MIME multipart message structure A MIME multipart message consists of a set of main headers and a main body portion, like all messages. Within the main body are one or more body parts, each of which has its own body-part-specific headers followed by the body part itself; each body part is shown in a black box. The Content-Type header of the message as a whole indicates that the message type is multipart, and the boundary parameter specifies the name of the delimiter, in this case just called "Delimiter." This delimiter is used to separate the body parts from each other and from the preamble and epilogue that begin and end the message body, respectively. In this example, Joe is sending Jane a multipart message containing a JPEG photograph and some explanatory text. The main header of the message specifies the `multipart/mixed` type and a boundary string of `exampledelimtext123`. The message begins with the preamble, which is ignored by the recipient email client but can be seen by the human reader. It is common to put a string here such as the one given in this example. That way, if a person using a client that does not support MIME receives the message, the recipient will know what it is. The first delimiter string is then placed in the message, followed by the first body part, the text Joe is sending Jane. This is preceded by whatever headers are needed by the body part, in this case `Content-Type: text/plain`. (Note, however, that this is the default in MIME, so it could be omitted here.) After the text message is another delimiter, and then the encoded JPEG photo in the second body part, with its own headers. Finally, there is one more delimiter, and then a space for the epilogue. This is ignored if present and is often not used at all. It is possible to send a multipart message that has only a single body part. This is sometimes done to take advantage of the preamble area to provide information about how to decode a nontext media type. Of course, this can also be done by including such text decoding instructions as a body part. ## MIME Encapsulated Message Type The other composite media type is the `message` type, which is devoted to the special purpose of encapsulating existing email messages within the body of a new message, or encapsulating other types of messages. This may be another email message previously sent or a message of some other kind. This media type also provides flexibility for sending partial messages and other special types of communication. Table 76-10 shows the three subtypes defined in RFC 2046. Table 76-10. Common MIME message Media Type Subtypes | Type/Subtype | Description | Defining Source | | --- | --- | --- | | `message/rfc822` | Indicates that the body contains an encapsulated email, itself formatted according to the RFC 822 standard. Note that this doesn't necessarily mean it is a plain text email message; it could be a MIME message (though encapsulating MIME within MIME must be done carefully). | RFC 2046 | | `message/partial` | Allows the fragmentation of larger messages into pieces that can later be reassembled. | RFC 2046 | | `message/external-body` | Indicates that the body of the message is not actually contained in the message itself; instead, a reference is provided to where the body is located. Sufficient information to locate the real message body must be provided. | RFC 2046 | ## MIME Content-Transfer-Encoding Header and Encoding Methods One of the main reasons why MIME was created was the significant restrictions that the RFC 822 standard places on how data in email messages must be formatted. To follow the rules, messages must be encoded in US-ASCII, a 7-bit data representation. This means that even though each byte can theoretically have any of 256 values, in ASCII only 128 values are valid. Furthermore, lines can be no longer than 1,000 characters including the carriage return and line feed (CRLF) characters at the end, and those two characters cannot appear elsewhere. For some types of data, such as text files, this is no big deal; but for others it is a serious problem. This is especially the case with binary data. If you look at the data in a video clip, MP3 file, or executable program, it will appear to be random gibberish. In fact, such data is not random; it is represented using specific rules, but the data is expressed in raw binary form, where any 8-bit byte can contain any value from 0 to 255, which is why it looks like junk to humans. More important, this means that this data does not follow the rules for RFC 822 files and cannot be sent directly in this form. To send non-ASCII data in MIME, it must be encoded. The Content-Transfer-Encoding header is used to specify how a MIME message or body part has been encoded, so that it can be decoded by its recipient. Four types of encoding are defined: `7bit, 8bit`/`binary, quoted-printable`, and `base64`. The quoted-printable and base64 encodings are the most interesting ones, because they are what allow non-RFC-822 data to be sent using RFC 822. ### Tip **KEY CONCEPT** MIME supports four encoding methods: `7bit`, `8bit` (`binary`), `quoted-printable`, and `base64`. `7bit` encoding is standard ASCII and is used for text. `quoted-printable` encoding is for output that is mostly text but has some special characters that must be encoded. `base64` is used for arbitrary binary files. The 8-bit encoding method is defined in MIME but not used for RFC 822 messages. ## 7-Bit and 8-Bit Encoding `7bit` encoding indicates that the message is already in ASCII form compatible with RFC 822\. It is the default and is what is assumed if no Content-Transfer-Encoding header is present. The `8bit` and `binary` values are synonymous. They mean the message has been encoded directly in 8-bit binary form. Yes, I did just say that this would violate the rules of RFC 822\. These options appear to have been included to support future mechanisms for transporting binary data directly. RFC 1652 describes an SMTP extension that discusses this in part: "SMTP Service Extension for 8bit-MIMEtransport" (there is no space between *MIME* and *transport*). However, the standard clearly states that this still does not allow the transfer of raw binary data using SMTP and RFC 822. ## Quoted-Printable Encoding Quotable-printable encoding is a special type that is used when most of the data is ASCII text, but it contains certain violations of the rules of RFC 822\. These illegal sections are converted using special encoding rules so the data as a whole is consistent with RFC 822; only the problem bytes are encoded. The result is that RFC 822 compatibility is achieved while maintaining most of the data as regular text so it can still be easily understood by a human. An example would be letters with tildes or accents, such as those used in French or Spanish. Another would be a text message formed using an editor that inserts carriage return characters in the middle of a line. Most of the message is still text. The `quoted-printable` encoding can be used here, with the carriage return characters represented as =0D (the hexadecimal value of the character prepended by an equal sign). RFC 2046 contains more details on how this is done. ## Base64 Encoding In contrast, `base64` encoding is more often used for raw binary data that is not in human-readable form anyway, such as graphical image, audio, video, and application files. This encoding is used to allow arbitrary binary data to be represented in ASCII form. The data is then sent as ASCII and decoded back into binary form by the recipient. The idea behind this type of encoding is simple: The data that needs to be sent can have any value for each 8-bit byte, which is not allowed. So why not rearrange the bits so the data fits into the 7-bit ASCII limits of RFC 822? This is done by processing the data to be sent three bytes at a time. There are 24 bits in each three-byte block, which are carved into four sets of 6 bits each. Each 6-bit group has a value from 0 to 63 and is represented by a single ASCII character, as presented in Table 76-11. Table 76-11. MIME base64 Encoding Groups | 6-Bit Value | Encoding | 6-Bit Value | Encoding | 6-Bit Value | Encoding | 6-Bit Value | Encoding | | --- | --- | --- | --- | --- | --- | --- | --- | | 0 | A | 16 | Q | 32 | g | 48 | w | | 1 | B | 17 | R | 33 | h | 49 | x | | 2 | C | 18 | S | 34 | i | 50 | y | | 3 | D | 19 | T | 35 | j | 51 | z | | 4 | E | 20 | U | 36 | k | 52 | 0 | | 5 | F | 21 | V | 37 | l | 53 | 1 | | 6 | G | 22 | W | 38 | m | 54 | 2 | | 7 | H | 23 | X | 39 | n | 55 | 3 | | 8 | I | 24 | Y | 40 | o | 56 | 4 | | 9 | J | 25 | Z | 41 | p | 57 | 5 | | 10 | K | 26 | a | 42 | q | 58 | 6 | | 11 | L | 27 | b | 43 | r | 59 | 7 | | 12 | M | 28 | c | 44 | s | 60 | 8 | | 13 | N | 29 | d | 45 | t | 61 | 9 | | 14 | O | 30 | e | 46 | u | 62 | + | | 15 | P | 31 | f | 47 | v | 63 | / | For example, suppose the first three bytes of the data to be sent were the decimal values 212, 39, and 247\. These cannot all be expressed in 7-bit ASCII. In binary form, they are expressed like so: | 11010100 00100111 11110111 | We can divide these into four 6-bit groups: | 110101 - 00 0010 - 0111 11 - 110111 | Which yields the four values 53, 2, 31, and 55\. Thus, the values 214, 39, and 247 would be encoded as the three ASCII characters 1Cf3\. The conceptual steps of this process are shown in Figure 76-2. ### Note *The sequence of steps for the encoding are intended to help you understand the process. Computers inherently deal directly with bits and would not bother with converting to decimal before encoding the 6-bit groups into ASCII characters*. ![MIME base64 encoding In this simplified example, three binary data bytes are encoded as four ASCII characters using MIME base64 encoding. Instead of transmitting those three bytes, two of which would not be valid in RFC 822, the four ASCII characters 1Cf3 are sent.](https://github.com/OpenDocCN/greenhat-zh/raw/master/docs/tcpip-gd/img/httpatomoreillycomsourcenostarchimages288291.png.jpg) Figure 76-2. MIME base64 encoding In this simplified example, three binary data bytes are encoded as four ASCII characters using MIME base64 encoding. Instead of transmitting those three bytes, two of which would not be valid in RFC 822, the four ASCII characters 1Cf3 are sent. This 3-to-4 encoding is done for all the data. The converted ASCII characters are then placed into the body of the entity instead of the raw binary data, 76 characters to a line. I showed how this is done in the second body part in the example in Example 76-1 (except I didn't use 76 characters per line, to keep the line lengths short). One final character is involved in this scheme, the equal sign (=), which is used as a padding character when needed. Since base64 characters are regular ASCII, they appear to SMTP like a regular text message. Of course, the data looks like gibberish to us, but that's not a problem since it will be converted back to its regular form and displayed to the recipient as an image, movie, audio, or whatever. ### Tip **KEY CONCEPT** MIME uses *base64* encoding to transform arbitrary 8-bit files into a form that is acceptable for communication in email. Each set of three 8-bit bytes is divided into four 6-bit groups, and each 6-bit group is represented by an ASCII character. Since the data is ASCII, it conforms to the RFC 822 message format standard, even if it is not human-readable. The receiving device reverses the encoding, changing each four-character block back into three 8-bit bytes. The main drawback of the base64 method is that it is about 33 percent less efficient than sending binary data directly, using a protocol like the File Transfer Protocol (FTP). The reason is that three 8-bit bytes of binary data are sent as four ASCII characters, but of course, each ASCII character is represented using 8 bits itself. So there is one-third more overhead when using base64\. In most cases, this is not a big deal, but it can be significant if downloading very large email files over a slow Internet connection. Note that RFC 2046 also defines two other encodings: `ietf-token` and `x-token`. These are included to allow new encoding types to be defined in the future. # MIME Extension for non-ASCII Mail Message Headers All of the MIME mechanisms discussed up to this point deal with ways of encoding different kinds of ASCII and non-ASCII data into the *body* of an RFC 822 message. In addition to these capabilities, MIME also includes a way in which non-ASCII data can be encoded into *headers* of an RFC 822 message. At this point, you might be wondering why anyone would want to do this. Sure, it makes sense to be able to use MIME to encode binary data such as an image into an email, but why do it in a header? Well, if you can't see the need for this, chances are that you are a native English speaker. ASCII does a great job of representing English, but isn't so good with many other languages. With RFC 822, speakers of languages that use non-ASCII characters were unable to use descriptive headers fully, such as the Subject and Comments headers. Some could not even properly express their own names! The solution to this problem is the subject of RFC 2047, the third of the five main MIME standards. It describes how to encode non-ASCII text into ASCII RFC 822 message headers. The idea is straightforward: As with message bodies, the non-ASCII text is replaced with ASCII, and information is provided to describe how this was done. With this technique, the value of a regular header is replaced by a MIME *encoded-word* that has the following syntax: | =?*<charset>*?*<encoding>*?*<encoded-text>*?= | The strings `=?` and `?=` are used to *bracket* the non-ASCII header, which flags it as a MIME encoded header to the recipient's email client. The other elements, separated by `?`, indicate how the non-ASCII text is encoded, as follows: **<charset>** The character set used, such as `iso-8859-1`. **<encoding>** Two different encoding types are defined, each represented by a single letter for brevity: `B` indicates base64 encoding, and `Q` indicates quoted-printable encoding (these encoding types are discussed in the previous section. **<encoded-text>** The non-ASCII text that has been encoded as ASCII using the encoding type indicated. As you can see, this method is analogous to how a non-ASCII message body or body part would be encoded, but the information about the encoding has been condensed so everything can fit in a single header line. The *<charset>* parameter is somewhat analogous to the Content-Type header for a message body, but since headers can contain only text, it specifies what kind of text it is. The *<encoding>* parameter is clearly equivalent to the Content-Transfer-Encoding header. ### Tip **KEY CONCEPT** In addition to its many functions for encoding a variety of data in email message bodies, MIME provides a feature that allows non-ASCII information to be placed into email headers. This is done by encoding the data using either *quoted-printable or base64* encoding, and then using a special format for the header value that specifies its encoding and character set. This technique is especially useful for email sent in languages that cannot be represented easily in standard ASCII, such as many Asian languages. Here's an example of a non-ASCII header, using the GB2312 character set (for Chinese characters) and base64 encoding: ``` Subject: =?GB2312?B?u7bTrbLOvNPDwLn61bm74Q==?= ``` I hope that doesn't say anything inappropriate; I took it from a piece of spam email I received once! # Chapter 77. TCP/IP ELECTRONIC MAIL DELIVERY PROTOCOL: THE SIMPLE MAIL TRANSFER PROTOCOL (SMTP) ![image with no caption](https://github.com/OpenDocCN/greenhat-zh/raw/master/docs/tcpip-gd/img/httpatomoreillycomsourcenostarchimages287681.png.jpg) I emphasized in my overall description of TCP/IP email that communication using email requires the interaction of various protocols and elements. One mistake that some people make is to equate the method used for delivering email with the entire system. This is, however, an understandable mistake—just as the postal service is only a part of the whole system of mailing a letter, it is nonetheless a very big part. Likewise, the delivery of email from sender to recipient is arguably the most important part of email as a whole. In modern TCP/IP, this task is the responsibility of the *Simple Mail Transfer Protocol (SMTP)*. In this chapter, I describe in detail the operation of SMTP. I begin with an overview and history of the protocol and a discussion of the standards that define it. I then examine the way that SMTP client/server communication and message transport work. I explain the way that SMTP servers establish connections and transaction sessions, and then the process by which mail is transferred from one server to another. I describe some of the special features implemented in SMTP and discuss SMTP security issues. I conclude with a reference summary of SMTP commands and replies. ### Tip **BACKGROUND INFORMATION** *My discussion of SMTP assumes that you already have a basic understanding of the general concepts of TCP/IP email, as well as familiarity with TCP/IP email addressing and message formatting. These topics are discussed in Chapters Chapter 74, Chapter 75, and Chapter 76, respectively*. # SMTP Overview, History, and Standards The overview and history of the TCP/IP email system in Chapter 74 describes how TCP/IP evolved from its early beginnings to its current form. Since the mechanism used to deliver email is such a big part of the system as a whole, any overview of the system must of necessity discuss how delivery mechanisms have changed as well. In the case of TCP/IP, the delivery of mail evolved through many forms during the 1970s, as developers sought to find effective ways of communicating email messages between systems. Most of these efforts involved attempts to transmit mail using existing protocols; this makes sense, since it is easier to adapt a technology than design one from scratch. ## SMTP Standards One important achievement in the development of a mail system was the publishing of the *Mail Transfer Protocol (MTP)*, which was first defined in RFC 772 in September 1980, and then updated in RFC 780 in May 1981\. MTP describes a set of commands and procedures by which two devices can connect using TCP to exchange email messages. Its operation is described largely using elements borrowed from two early TCP/IP application protocols that were already in use at that time: Telnet and the File Transfer Protocol (FTP). The commands of MTP are actually based directly on those of FTP. Although there was nothing inherently wrong with basing email delivery on FTP, defining it this way made MTP somewhat of a hack. It was also restricted to the capabilities defined by FTP, a general file transfer protocol, so it was not possible to include features in MTP that were specific to sending and receiving mail. Due to the importance of email, a specific protocol designed for the purpose of delivering email was warranted. SMTP was first defined in RFC 788 and published in November 1981. The name suggests that SMTP is simpler than the protocol that it replaced. Whether or not this is true is somewhat a matter of opinion; I do note that RFC 788 is 61 pages long, while the earlier RFC 780 was only 43 pages. What SMTP definitely has over MTP is *elegance*; the protocol is designed specifically for the transport of email. While it retains certain similarities to FTP, it is an independent protocol running over the Transmission Control Protocol (TCP). So, from a conceptual standpoint, it can be considered simpler than MTP. In terms of mechanics, the process SMTP uses to transfer an email message is indeed rather simple, especially compared to some other protocols. RFC 788 described the operation of SMTP carrying email messages corresponding to the ARPAnet text message standard as described in RFC 733\. Development of both email messages and SMTP continued, and in August 1982, a milestone in TCP/IP email was achieved when RFCs 821 and 822 were published. RFC 821 revised SMTP and became the defining standard for the protocol for the next two decades. RFC 822, its companion standard, became the standard for TCP/IP email messages carried by SMTP. ### Tip **KEY CONCEPT** The most important component of the TCP/IP email system is the *Simple Mail Transfer Protocol (SMTP)*. SMTP was derived from the earlier Mail Transfer Protocol (MTP) and is the mechanism used for the delivery of mail between TCP/IP systems and users. The only part of the email system for which SMTP is not used is the final retrieval step by an email recipient. As the 1980s progressed, and TCP/IP and the Internet both grew in popularity, SMTP gradually overtook other methods to become the dominant method of email message delivery. For a number of years, the protocol was used mostly as is, with no new RFCs published to define new versions or formally change its behavior. This changed in February 1993, when RFC 1425, "SMTP Service Extensions," was published. As the name suggests, this standard describes a process for adding new capabilities to extend how SMTP works, while maintaining backward compatibility with existing systems. SMTP with these extensions is sometimes called *Extended SMTP* or *ESMTP* (though use of this term seems not to be entirely universal). As development of SMTP continued, RFC 1425 was revised in RFC 1651 in July 1994, and then in RFC 1869 in November 1995\. Along with these revisions, a number of other RFCs defining particular SMTP extensions, such as pipelining and message size declaration, were defined. In April 2001, another major milestone in TCP/IP email was reached when revisions of RFC 821 and RFC 822 were published, as RFCs 2821 and 2822, respectively. Both documents are consolidations of updates and changes that had been made to RFCs 821 and 822 between 1982 and 2001\. And, no, I don't think it is a coincidence that the old and new RFC numbers are exactly 2,000 apart. RFCs 2820 and 2823 were both published in May 2000, so it looks like 2821 and 2822 were reserved for the email standards. I think this naming was a great idea, as it makes it clear that the new RFCs are revisions of the old ones. RFC 2821 is the current base standard for SMTP. It incorporates the base protocol description from RFC 821 and the latest SMTP extensions as defined in RFC 1869\. It updates the description of the email communication model to reflect the realities of modern TCP/IP networks, especially the email features built into the Domain Name System (DNS). We'll examine this in more detail in the next section. ## SMTP Communication and Message Transport Methods The TCP/IP email communication model describes the way email messages are conveyed from the sender to the recipient. In most cases, this involves the sender's client machine sending the email to its local SMTP server, which sends it to the recipient's local SMTP server, which then sends it to the recipient's local host. SMTP handles the transport between SMTP servers. In fact, the overall email communication model is largely described by the RFC 821 and 2821 SMTP standards. The initial communication takes place between the sender's client machine and a local SMTP server that the sender is allowed to access. After submission of the email message, that SMTP server becomes responsible for delivering the message to the SMTP server responsible for the recipient's mailbox. ### Early Email Communication Using Relaying In the early days of email, when RFC 821 and its predecessors were first defined, the Internet was very different from what it is today. There was no DNS, and this made email delivery complex, because there was no way to map a mailbox address to the IP address of the SMTP server that managed that mailbox. Also, many proprietary networks were connected to the Internet, which meant that it was not always possible for any particular system to communicate with any other. Given this, how could email be delivered? The most common way in the early days of SMTP was through a process called *relaying*. SMTP routing information was included along with the email address, to specify a sequence of SMTP servers that the mail should be relayed through to get to its destination. For example, if a sender using SMTP Server A wanted to send email to someone whose mailbox was on SMTP Server Z, the sender might have needed to specify that the mail be sent through intermediate SMTP Servers D, P, and U to get there. An SMTP connection would be established from Server A to Server D to send the message on one leg of its journey; then it would go from Server D to P, Server P to U, and then Server U to Z. The process is analogous to how Internet Protocol (IP) routing works, but at the application layer (actually using IP routing at a lower level). You can probably see the problems with this quite easily: It's cumbersome, requires many devices to handle the mail, results in delays in communication, and requires the communication of source routes between SMTP servers. It was certainly functional, but it was far from ideal. ### Modern Email Communication Using DNS and Direct Delivery The creation of DNS radically changed how email delivery worked. DNS includes support for a special *mail exchange (MX)* record that allows easy mapping from the domain name in an email address to the IP address of the SMTP server that handles mail for that domain. I explain this in the description of the regular email address format in Chapter 76, as well as the section about DNS email support in Chapter 56. In the new system, SMTP communication is much simpler and more direct. The sending SMTP server uses DNS to find the MX record of the domain to which the email is addressed. This gives the sender the DNS name of the recipient's SMTP server. This is resolved to an IP address, and a connection can be made directly from the sender's SMTP server to the recipient's server to deliver the email. While SMTP still supports relaying, direct email delivery using MX records is faster and more efficient, and RFC 2821 makes clear that this is now the preferred method. In this new system, SMTP is generally used only for two transfers: first, from the sender's client machine to the sender's local SMTP server, and then from that server to the recipient's local SMTP server, as shown in Figure 74-1 in Chapter 74. (A distinct mail access protocol or method is used by the recipient for the last leg of the journey.) Each transfer of an email message between SMTP servers involves the establishment of a TCP connection, and then the transfer of the email headers and body using the SMTP mail transfer process. The following sections describe in detail how this occurs. ### Tip **KEY CONCEPT** In the early days of SMTP, mail was delivered using the relatively inefficient process of relaying from server to server across the internetwork. Today, when an SMTP server has mail to deliver to a user, it determines the server that handles the user's mail using the Domain Name System (DNS) and sends the mail directly to that server. ## Terminology: Client/Server and Sender/Receiver The original RFC 821 standard referred to the device that initiates an SMTP email transfer as the *sender* and the device that responds to it as the *receiver*. These terms were changed to *client* and *server* in RFC 2821 to "reflect current industry terminology." Strictly speaking, this is correct, but in some ways, the more current terminology is significantly *less* clear. As I explained in the general discussion of TCP/IP client/server operation in Chapter 8, the terms *client* and *server* are used in many different senses in networking, which often leads to confusion. In common parlance, the computers that handle email on the Internet are usually all called *SMTP servers*. This is because they run SMTP server software to provide SMTP services to client machines, such as end-user PCs. In addition, these devices are usually dedicated hardware servers running in network centers, typically managed by Internet service providers (ISPs). However, the terms *client* and *server* are now used to refer to the roles in a particular SMTP communication as well. Since all SMTP servers both send and receive email, they all act as both clients and servers at different times. An SMTP server that is relaying an email will act as both server and client for that message, receiving it as a server, and then sending it to the next server as a client. Adding to this potential confusion is the fact that the initial stage in sending an email is from the sender's client machine to the sender's local SMTP server. Thus, the client role in an SMTP transaction may not be an actual SMTP server, but the server role will always be a server. For all of these reasons, the old terms *sender* and *receiver* are still used in places in RFC 2821, where needed for clarity. I consider them much more straightforward and use them in the rest of this chapter. ### Tip **KEY CONCEPT** SMTP servers both send and receive email. The device sending mail acts as a client for that transaction, and the one receiving it acts as a server. To avoid confusion, it is easier to refer to the device sending email as the *SMTP sender* and the one receiving as the *SMTP receiver*; these terms were used when SMTP was originally created. # SMTP Connection and Session Establishment and Termination The delivery of email using SMTP involves the regular exchange of email messages among SMTP servers. SMTP servers are responsible for sending email that users of the server submit for delivery. They also receive email intended for local recipients, or for forwarding or relaying to other servers. ## Overview of Connection Establishment and Termination All SMTP communication is done using TCP. This allows SMTP servers to make use of TCP's many features that ensure efficient and reliable communication. SMTP servers generally must be kept running and connected to the Internet 24 hours a day, seven days a week, to ensure that mail can be delivered at any time. (This is a big reason why most end users employ access protocols such as the Post Office Protocol to access their received email rather than running their own SMTP servers.) The server listens continuously on the SMTP server port, well-known port number 25, for any TCP connection requests from other SMTP servers. An SMTP server that wishes to send email normally begins with a DNS lookup of the MX record corresponding to the domain name of the intended recipient's email address to get the name of the appropriate SMTP server. This name is then resolved to an IP address; for efficiency, this IP address is often included as an *additional* record in the response to the MX request to save the sending server from needing to perform two explicit DNS resolutions. The SMTP sender then establishes an SMTP session with the SMTP receiver. Once the session is established, mail transactions can be performed to allow mail to be sent between the devices. When the SMTP sender is finished sending mail, it terminates the connection. All of these processes involve specific exchanges of commands and replies, which are illustrated in Figure 77-1. Let's take a look at these processes in more detail, starting with SMTP session establishment. ## Connection Establishment and Greeting Exchange The SMTP sender begins by initiating a TCP connection to the SMTP receiver. The sending SMTP server uses an ephemeral port number, since it is playing the role of the client in the transaction. Assuming that the server is willing to accept a connection, it will indicate that it is ready to receive instructions from the client by sending reply code 220\. This is called the *greeting* or *service ready* response. It commonly includes the full domain name of the server machine, the version of the SMTP server software it is running, and possibly other information. Now, it would be rude for the server acting as a client to start sending commands to the responding server without saying hello first, wouldn't it? So that's exactly what comes next: the client says, "Hello." In the original SMTP protocol, this is done by issuing a HELO command, which includes the domain name of the sending (client) SMTP server as a courtesy. The receiving device then responds back with a return hello message using an SMTP reply code 250. For example, if the SMTP server smtp.sendersite.org was making a connection to the SMTP server [mail.receiversplace.com](http://mail.receiversplace.com), it would say: ``` HELO smtp.sendersite.org. ``` After receiving this greeting, [mail.receiversplace.com](http://mail.receiversplace.com) would respond back with a `hello` message of its own, something like this: ``` 250 mail.receiversplace.com Hello smtp.sendersite.org, nice to meet you. ``` ![SMTP transaction session establishment and termination An SMTP session begins with the SMTP sender establishing a TCP connection to the SMTP receiver. The receiver sends a ready message; the sender sends a HELO or EHLO command, to which the receiver responds. Assuming no difficulties are encountered, the session is established and mail transactions take place. When the sender is finished, it sends a QUIT command; the receiver responds with a 221 reply and closes the session.](https://github.com/OpenDocCN/greenhat-zh/raw/master/docs/tcpip-gd/img/httpatomoreillycomsourcenostarchimages288293.png.jpg) Figure 77-1. SMTP transaction session establishment and termination An SMTP session begins with the SMTP sender establishing a TCP connection to the SMTP receiver. The receiver sends a ready message; the sender sends a HELO or EHLO command, to which the receiver responds. Assuming no difficulties are encountered, the session is established and mail transactions take place. When the sender is finished, it sends a QUIT command; the receiver responds with a 221 reply and closes the session. (The chatty text is of course purely optional; most of the time, SMTP communication is between software programs, so the pleasantries are usually written by programmers who have a sense of humor.) ## Connection Establishment Using SMTP Extensions The SMTP extensions first defined in RFC 1425, and then in subsequent standards up to RFC 2821, define an alternative hello message for the client to use: EHLO (extended hello). An SMTP sender supporting SMTP extensions (and most do) uses EHLO instead of HELO in response to the 220 greeting. This serves both to say hello to the SMTP receiver and to tell it that the sender supports SMTP extensions. If the SMTP receiver supports the extensions, it replies with the usual 250 reply, as well as a series of extra 250 responses. Each of these lists an EHLO *keyword* that indicates a particular SMTP extension the receiver supports. If the receiving server doesn't support the extensions, it will reject the EHLO command with a 500 reply code ("syntax error, command not recognized"). This tells the SMTP sender that it cannot use extensions. It will then issue a conventional HELO command, or it will QUIT the connection if it requires the SMTP extension to be present. (In practice, it is rare for a server to *require* the use of SMTP extensions.) Here's the same example used earlier, but using EHLO. The sender says: ``` EHLO smtp.sendersite.org. ``` Assuming [mail.receiversplace.com](http://mail.receiversplace.com) supports the SMTP extensions, a typical reply might look like this: ``` 250-mail.receiversplace.com Hello smtp.sendersite.org, nice to meet you. 250-SIZE 250-DSN 250 PIPELINING ``` Each of these additional replies identifies a particular SMTP extension supported by [mail.receiversplace.com](http://mail.receiversplace.com); in this case, message size declaration (SIZE), delivery status notification (DSN), and command pipelining. (The dashes after the 250 indicate a multiple-line response to a command; this is discussed in the "SMTP Multiple-Line Text Replies" section later in the chapter.) Once the HELO or EHLO command has been sent and the receiving device has responded, the session is initiated. Further commands can be sent by the sending SMTP server to the responding server. These usually take the form of email message transfer transactions using the process described in the upcoming "SMTP Mail Transaction Process" section, and other command/reply exchanges as needed. ## Connection Termination When the sending device is finished sending all the email it has to transfer to the receiving device, and it has completed all its other activities, it terminates the session by issuing the QUIT command. This normally results in a 221 "goodbye" message from the SMTP receiver, which says something like "closing transmission channel." The TCP connection is then terminated. ### Tip **KEY CONCEPT** An SMTP session consists of three basic phases. The session is first *established* through the creation of a TCP connection and the exchange of identity information between the SMTP sender and receiver using the HELO command. Once established, *mail transactions* can be performed. When the SMTP sender is finished with the session, it *terminates* it using the QUIT command. If *SMTP extensions* are supported, the SMTP sender uses the *EHLO (extended hello)* command instead of *HELO*, and the SMTP receiver replies with a list of extensions it will allow the SMTP sender to use. A server may also terminate prematurely in special cases. If it is given a local command to shut down (for example, due to imminent rebooting of the hardware server on which it is running), it may respond to any routine command with a 421 response ("Service not available, closing transmission channel"). A server is not supposed to terminate a session simply due to receipt of an invalid command, however; this should happen only in special cases where session termination cannot be avoided. # SMTP Mail Transaction Process As described in the previous section, the delivery of an email message begins with the establishment of an SMTP session between the devices sending and receiving the message. The SMTP sender initiates a TCP connection to the SMTP receiver and then sends a HELO or an EHLO command, to which the receiver responds. Assuming no problems ensue, the session is then established and ready for actual email message transactions. ## Overview of SMTP Mail Transaction The SMTP mail transaction process itself consists of three steps: * **Transaction Initiation and Sender Identification** The SMTP sender tells the SMTP receiver that it wants to start sending a message and gives the receiver the email address of the message's originator. * **Recipient Identification** The sender tells the receiver the email address(es) of the intended recipients of the message. * **Mail Transfer** The sender transfers the email message to the receiver. This is a complete email message meeting the RFC 822 specification (which may be in MIME format as well). That's it! So you can see that the word *Simple* in *Simple Mail Transfer Protocol* definitely has at least *some* merit. In fact, one question that sometimes comes up when examining SMTP is "Why couldn't this process be even simpler?" The first two steps identify the sender of the email and the intended recipient(s). But all of this information is already contained in headers in the message itself. Why doesn't SMTP just read that information from the message, which would make the mail transaction a *one-step* process? The explanation isn't specifically addressed in the SMTP standards, but I believe there are several reasons for this: * Specifying the sender and recipients separately is more efficient, as it gives the SMTP receiver the information it needs up front before the message itself is transmitted. In fact, the SMTP receiver can decide whether or not to accept the message based on the source and destination email addresses. * Having this information specified separately gives greater control on how email is distributed. For example, an email message may be addressed to two recipients, but they may be on totally different systems; the SMTP sender might wish to deliver the mail using two separate SMTP sessions to two different SMTP receivers. * In a similar vein, there is the matter of delivering blind carbon copies. Someone who is BCC'ed a message must receive it without being mentioned in the message itself. * Having this information separate makes implementing security on SMTP much easier. For these reasons, SMTP draws a distinction between the message itself, which it calls the *content*, and the sender and recipient identification, which it calls the *envelope*. This is consistent with our running analogy between regular mail and email. Just as the postal service delivers a piece of mail using only the information written on the envelope, SMTP delivers email using the envelope information, not the content of the message. It's not quite the case that the SMTP server doesn't look at the message itself, just that this is not the information it uses to manage delivery. ### Note *It is possible for the sender of a message to generate envelope information based on the contents of the message, but this is somewhat external to SMTP itself. It is described in the standard, but caution is urged in exactly how this is implemented*. ## SMTP Mail Transaction Details Let's take a more detailed look at the SMTP mail transaction process, using as aids the process diagram in Figure 77-2 and the sample transaction of Example 77-1 (which has commands highlighted in bold and replies in italics). Example 77-1. Example of an SMTP mail transaction ``` `MAIL FROM:<joe@someplace.org>` *`250 <joe@someplace.org> . . . Sender ok`* `RCPT TO:<jane@somewhereelse.com>` *`250 <jane@somewhereelse.com> . . . Recipient ok`* `DATA` *`354 Enter mail, end with "." on a line by itself`* `From: Joe Sender <joe@someplace.org>` `To: Jane Receiver <jane@somewhereelse.com>` `Date: Sun, 1 Jun 2003 14:17:31 --0800` `Subject: Lunch tomorrow` `Hey Jane,` `It's my turn for lunch tomorrow. I was thinking we could` `[rest of message]` `Hope you are free. Send me a reply back when you get a chance.` `Joe.` `.` *`250 OK`* ``` ![SMTP mail transaction process Once an SMTP session is established between a sender and receiver, each mail transaction consists of a set of three command/reply sequences. The sender is first identified using the MAIL command and the recipients are specified using one or more RCPT commands. The actual mail message is then transferred using the DATA command, which involves a preliminary reply before the actual message is sent and a completion reply when it has been fully received.](https://github.com/OpenDocCN/greenhat-zh/raw/master/docs/tcpip-gd/img/httpatomoreillycomsourcenostarchimages288295.png.jpg) Figure 77-2. SMTP mail transaction process Once an SMTP session is established between a sender and receiver, each mail transaction consists of a set of three command/reply sequences. The sender is first identified using the MAIL command and the recipients are specified using one or more RCPT commands. The actual mail message is then transferred using the DATA command, which involves a preliminary reply before the actual message is sent and a completion reply when it has been fully received. The first two steps in the mail transaction are responsible for providing the receiving SMTP server with the envelope information just discussed. The transaction begins by the SMTP sender issuing a MAIL command. This serves to inform the receiver that a new transaction is commencing and also to tell it the *from* information on the envelope. Here's an example: ``` MAIL FROM:<joe@someplace.org> ``` The email address of the originator is always enclosed in angle brackets (< and >). The SMTP receiver acknowledges the command with a 250 ("OK") reply message, sometimes sending back the address as a confirmation. Here's an example: ``` 250 <joe@someplace.org> . . . Sender ok ``` Next, the SMTP sender uses RCPT commands to specify the intended recipients of the email that is being sent. Each RCPT line can contain only one recipient, so if multiple recipients are indicated, two or more RCPT commands must be issued. Each one normally specifies an email address, but if relaying is being used, the command may contain routing information as well. (As described earlier in the "SMTP Communication and Message Transport Methods" section, this is not as commonly done as it was in the past.) Here's an example: ``` RCPT TO:<jane@somewhereelse.com> ``` Assuming the server accepts the email, it will give a 250 "OK" reply again, like so: ``` 250 <jane@somewhereelse.com> . . . Recipient ok ``` The SMTP sender then issues the DATA command, which tells the SMTP receiver that the message is coming: ``` DATA ``` The SMTP receiver responds with a 354 "intermediate" reply message, such as this: ``` 354 Enter mail, end with "." on a line by itself ``` The SMTP sender then sends the email message, one line at a time, with a single dot (.) on a line to terminate it. The server confirms the receipt of the message with another 250 "OK" reply, and the transaction is finished. ### Tip **KEY CONCEPT** After an SMTP session is established, email messages are sent using the SMTP *mail transaction process*. The SMTP sender starts the transaction by identifying the sender of the email and then specifying one or more recipients. The email message itself is then transmitted to the SMTP receiver. Each email to be sent is a separate transaction. While this indeed is quite simple, notice that I have shown an email transfer from a sender to one recipient, one in which there were no problems or complications in the transaction. Due either to command syntax or server issues, it is possible for various types of errors to occur at different stages of the process, which may result in the transaction failing. As you'll see shortly, security concerns may come also into play, leading to restrictions in what transactions a server may allow. # SMTP Special Features, Capabilities, and Extensions The primary job of the SMTP is to implement the TCP/IP email delivery system. Whenever the user of an SMTP server gives it an email message addressed to a remote mailbox, the server will attempt to transfer it to the appropriate destination server, using the SMTP mail transaction process. Many billions of such transfers are performed every day on the Internet, allowing email to reach its destination quickly anywhere around the world. ## SMTP Special Features and Capabilities In addition to this basic transfer mechanism, SMTP includes a number of other features and capabilities. These allow SMTP to support special requirements and auxiliary needs of the mail system, as described in detail in RFC 2821\. It would take many pages to describe them all in detail, so I will provide a quick summary of the more important ones here so you know a bit about them. The following are some of SMTP's special features: **Mail Relaying** As discussed in the "SMTP Communication and Message Transport Methods" section earlier in this chapter, the protocol was once widely used in a relaying mode, where email was routed from one SMTP server to another to reach its destination. Today, the more efficient, normal method of email transfer on the Internet is directly from the sender's SMTP server to the recipient's server, using DNS MX records to determine the recipient SMTP server address. SMTP still includes the ability to relay mail from one server to another, provided certain conditions are met. Note that many servers won't relay mail because this feature has been abused for spamming and malicious hacking. **Mail Forwarding** Under certain conditions, an SMTP server may agree to accept email for a remote mailbox and forward it to the appropriate destination. This sounds similar to relaying but is used in a different way. A common example is when users change their email address. For example, if you have worked at XYZ Industries for years and then retire, the company may no longer wish to let you receive email at the company's SMTP server. As a courtesy, however, they may forward email sent to you there, so that you receive it at your new company. **Mail Gatewaying** Certain SMTP servers may be configured as email gateways. These devices translate TCP/IP email into a form suitable for another email system, and vice versa. Gatewaying is a complex topic because email systems can be so different. One of the more important problems is the inconsistency of addressing methods of different email systems. **Address Debugging** SMTP includes a VRFY (verify) command that can be used to check the validity of an email address without actually sending mail to it. **Mailing List Expansion** The SMTP command EXPN (expand) can be used to determine the individual email addresses associated with a mailing list. (Note, however, that this has nothing directly to do with mailing list software like *Majordomo*.) **Turning** The original SMTP included a command that allows the SMTP sender and SMTP receiver to change roles. This could be used to allow SMTP Server A to send email to Server B, and then have Server B send email it has queued for Server A in the same session. In practice, this capability was not widely used for a variety of reasons, including security considerations. It is now officially not recommended but may still be implemented in some SMTP software. These are just a few of the features that are mentioned in the SMTP standards. In addition, developers of a particular type of SMTP server software may give it other features as well. The HELP command is one way of determining what commands are supported by a particular SMTP server. SMTP servers also must perform a great deal of background processing that doesn't get a great deal of attention. This includes managing connections, checking for errors in commands and email messages, and reacting accordingly. They must also be on the lookout for problem conditions, such as looping that may result in an email message being passed back and forth between two SMTP servers, each thinking the other is the intended recipient. In the event of an initial failure to deliver mail, an SMTP server is also required to retry communication periodically with the destination device and return a failure message to the sender if it cannot deliver the message after a certain period of time. RFC 2821 contains more details. ## SMTP Extensions As discussed earlier in this chapter, during the 1990s, many extensions to the basic operation of SMTP were defined. These are enabled when two SMTP servers supporting the extension set up a session using the EHLO command and appropriate extension response codes. Table 77-1 summarizes some of the more interesting SMTP extensions that have been defined and gives the RFC number where each is described. You can find the full current set of SMTP extensions at [`www.iana.org/assignments/mail-parameters`](http://www.iana.org/assignments/mail-parameters). Table 77-1. SMTP Extensions | Extension Keyword | Extension | Defining Document | Description | | --- | --- | --- | --- | | 8BITMIME | 8-bit MIME support | RFC 1652 | Theoretically defines support for the 8-bit content transfer encoding type in MIME, but complications associated with this. See the discussion of content encoding in Chapter 76 for details. | | AUTH | Authorization | RFC 2554 | Used to implement an authorization mechanism for servers requiring enhanced security. | | DSN | Delivery status notification | RFC 1891 | Allows an SMTP sender to request that the SMTP receiver notify it if a problem occurs in delivering a message. | | ENHANCEDSTATUSCODES | Enhanced status codes | RFC 2034, RFC 1893 | Extends the traditional three-digit SMTP reply code format with extra codes that provide more information. See the "SMTP Replies and Reply Codes" section later in this chapter for more information. | | PIPELINING | Command pipelining | RFC 2920 | Allows multiple commands to be transmitted in batches from the SMTP sender to the receiver, rather than sending one command at a time and waiting for a response code. | | SIZE | Message size declaration | RFC 1870 | Allows information about the size of a message to be declared by an SMTP sender prior to transmitting it, so the SMTP receiver can decide if it wants the message or not. | ### Note *Certain commands in the basic SMTP description that are considered optional are also sometimes considered extensions, such as the EXPN and HELP commands; I have not listed these here, since they are not true SMTP extensions*. # SMTP Security Issues When it comes to security and SMTP, the theme is a common one in TCP/IP: A lack of security in how the protocol is implemented, because it was developed when the Internet was just a small group of machines controlled by individuals who mostly knew and trusted each other or who were able to use physical security. Developers never imagined TCP/IP being used by millions of anonymous average Joes around the world, which necessitates far more attention to security than a small research internetwork like the ARPAnet. With SMTP, security matters are, if anything, *worse* than they are with some of the other protocols. Not only does SMTP not have any real security mechanism, the original relaying model of SMTP communication is entirely designed around the idea of cooperation and trust among servers. Since most SMTP servers would be asked to handle a certain number of intermediate transfers, each server was required to accept mail from any originator to be delivered to any destination. The basic assumption in this model is that users of SMTP servers would all be well behaved and not abuse the system by flooding intermediate servers with a lot of mail to be delivered or sending bogus messages to cause problems. This all changed as the Internet exploded in popularity in the 1990s. Con artists, malicious hackers, and disreputable salespeople discovered that email could be used for free delivery of messages simply by submitting them to an SMTP server for delivery. The result was overloaded servers, primarily due to the sending of large quantities of unwanted email, which Internet users commonly call *spam*. ### Note *The term spam, in this context, has nothing directly to do with the Hormel processed meat product. Its use in reference to massive amounts of email comes from a Monty Python comedy sketch in which that word is repeated in phrases over and over again*. It is actually very easy to impersonate an SMTP server. You can use the Telnet Protocol to connect directly to an SMTP server on port 25\. SMTP commands are all sent as text, and so are SMTP replies, so you can have a conversation with a server, and even manually perform a mail transaction. This is useful for debugging, but it also makes abuse of a wide-open SMTP server trivially easy. Since spammers often don't want to be identified, they employ spoofing techniques to make it more difficult to identify them, so resolving these problems is even more difficult. Despite this obvious dilemma, efforts to implement a general security mechanism in SMTP have been resisted for two main reasons. First, there is no foolproof way to retrofit a new security mechanism onto something as widely used as SMTP without creating incompatibilities between newer and older systems. Second, many administrators were reluctant to do away completely with the general notion of cooperation among sites that has helped make the Internet so successful. Still, something had to be done. The compromise was for system administrators to tighten up their SMTP servers through the imposition of both technical and policy changes. Naturally, these vary from one organization to another. Some of the more common SMTP security provisions include the following: * Checking the IP address of a device attempting connection and refusing even to start an SMTP session unless it is in a list of authorized client devices. * Restricting certain commands or features, such as email relaying, to authorized users or client servers. This is sometimes done by requiring authentication via the SMTP extension AUTH before the command will be accepted. * Limiting the use of commands such as EXPN to prevent unauthorized users from determining the email addresses of users on mailing lists. * Checking the validity of envelope information before accepting a message for delivery. Some servers will first verify that the originator's email address is valid before agreeing to accept the MAIL command. Many will check the recipient's address and refuse the message if delivery is not to a local mailbox. Others use even more advanced techniques. * Limiting the size of email messages that may be sent or the number that may be sent in a given period of time. * Logging all access to the server to keep records of server use and check for abuse. Because of all the abuse in recent years, you will find that most SMTP servers implement these or other features, even though most of those features are not formally defined by the SMTP standards. Rather, they are enhancements built into individual SMTP server software packages. SMTP was designed during an era in which Internet security was not much of an issue; as a result, the base protocol includes no security mechanism at all. Since email is so often abused today, most modern SMTP servers incorporate one or more security features to avoid problems. Some of these measures can actually be quite sophisticated. For example, the SMTP server run by pair Networks, the great web-hosting company I have used for years, uses *POP-before-SMTP authentication*. This means that before the server will accept outgoing mail from the user via SMTP, the user must first log in to check incoming mail using the Post Office Protocol (POP). Since POP includes authentication, a successful POP login tells the server the user is authorized. This "flips a switch" in the server that allows the user to access the SMTP service after that login for a limited period of time. If this seems convoluted, then you're starting to get an idea of the hassle that spammers and malicious hackers have created for ISPs today. It's also worth noting that SMTP does not include any mechanism for encryption to ensure the privacy of email transmissions. Users requiring security to control who sees their messages must use a separate encryption scheme to encode the body of the message prior to submission. # SMTP Commands Early TCP/IP email mechanisms were developed by borrowing techniques and elements from existing application protocols, especially Telnet and FTP. SMTP is an independent protocol, but its heritage can still be seen clearly in a few areas. One of the more obvious of these is in the method by which commands are issued by an SMTP sender and replies returned by an SMTP receiver. Like FTP, all SMTP commands are sent as plain ASCII text over the TCP connection established between the client and server in an SMTP connection. These commands must end with the two-character CRLF sequence that normally terminates ASCII text as required for the Telnet Network Virtual Terminal (NVT; see Chapter 87). In fact, you can check the function of an SMTP server and even issue commands to it yourself simply by using Telnet to connect to it on port 25. All SMTP commands are specified using a four-letter command code. Some commands also either allow or require parameters to be specified. The basic syntax of a command is ``` <command-code> <parameters> ``` When parameters are used, they follow the command code and are separated from it by one or more space characters. For example, the HELO and EHLO commands are specified with the command code, a space character, and then the domain name of the SMTP sender, as you saw earlier in the discussion of SMTP connection establishment. Table 77-2 lists the commands currently used in modern SMTP in the order they are described in RFC 2821, with a brief description of each. Table 77-2. SMTP Commands | Command Code | Command | Parameters | Description | | --- | --- | --- | --- | | HELO | Hello | The domain name of the sender | The conventional instruction sent by an SMTP sender to an SMTP receiver to initiate the SMTP session. | | EHLO | Extended Hello | The domain name of the sender | Sent by an SMTP sender that supports SMTP extensions to greet an SMTP receiver and ask it to return a list of SMTP extensions the receiver supports. The domain name of the sender is supplied as a parameter. | | MAIL | Initiate Mail Transaction | Must include a FROM: parameter specifying the originator of the message, and may contain other parameters as well | Begins a mail transaction from the sender to the receiver. | | RCPT | Recipient | Must include a TO: parameter specifying the recipient mailbox, and may also incorporate other optional parameters | Specifies one recipient of the email message being conveyed in the current transaction. | | DATA | Mail Message Data | None | Tells the SMTP receiver that the SMTP sender is ready to transmit the email message. The receiver normally replies with an intermediate "go ahead" message, and the sender then transmits the message one line at a time, indicating the end of the message by a single period on a line by itself. | | RSET | Reset | None | Aborts a mail transaction in progress. This may be used if an error is received upon issuing a MAIL or RCPT command, if the SMTP sender cannot continue the transfer as a result. | | VRFY | Verify | Email address of mailbox to be verified | Asks the SMTP receiver to verify the validity of a mailbox. | | EXPN | Expand | Email address of mailing list | Requests that the SMTP server confirm that the address specifies a mailing list, and return a list of the addresses on the list. | | HELP | Help | Optional command name | Requests general help information if no parameter is supplied; otherwise, information specific to the command code supplied. | | NOOP | No Operation | None | Does nothing except for verifying communication with the SMTP receiver. | | QUIT | Quit | None | Terminates the SMTP session. | Like FTP commands, SMTP commands are not case-sensitive. ### Tip **KEY CONCEPT** The SMTP sender performs operations using a set of *SMTP commands*. Each command is identifies using a four-letter code. Since SMTP supports only a limited number of functions, it has a small command set. The commands in Table 77-2 are those most commonly used in SMTP today. Certain other commands were also originally defined in RFC 821 but have since become obsolete. These include the following: **SEND, SAML (Send and Mail), and SOML (Send or Mail)** RFC 821 defined a distinct mechanism for delivering mail directly to a user's terminal as opposed to a mailbox, optionally in combination with conventional email delivery. These were rarely implemented and obsoleted in RFC 2821. **TURN** Reverses the role of the SMTP sender and receiver as described earlier in the SMTP special features discussion. This had a number of implementation and security issues and was removed from the standard in RFC 2821. Finally, note that certain SMTP extensions make changes to the basic SMTP command set. For example, the *AUTH* extension specifies a new command (also called AUTH) that specifies an authentication method the SMTP client wants to use. Other extensions define new parameters for existing commands. For example, the SIZE extension defines a *SIZE* parameter that can be added to a *MAIL* command to tell the SMTP receiver the size of the message to be transferred. # SMTP Replies and Reply Codes All SMTP protocol operations consist of the plain ASCII text SMTP commands you saw in Table 77-2, issued by the sender to the receiver. The receiver analyzes each command, carries out the instruction requested by the sender if possible, and then sends a reply to the sender. The reply serves several functions: confirming command receipt, indicating whether or not the command was accepted, and communicating the result of processing the command. Just as SMTP commands are sent in a manner reminiscent of how FTP internal commands work, SMTP replies are formatted and interpreted in a way almost identical to that of FTP replies. As with FTP, the reply consists of not just a string of reply text, but a combination of reply text and a numerical *reply code*. And as with FTP, these reply codes use three digits to encode various information about the reply, with each digit having a particular significance. The reply code is really the key part of the reply, with the reply text being merely descriptive. ### Note *The discussion of FTP reply codes in Chapter 72") contains a thorough explanation of the benefits of using these structured numeric reply codes*. ## Reply Code Structure and Digit Interpretation SMTP reply codes can be considered to be of the form *xyz*, where *x* is the first digit, *y* is the second, and *z* is the third. The first reply code digit (*x*) indicates the success or failure of the command in general terms, whether a successful command is complete or incomplete, and whether an unsuccessful command should be tried again or not. This particular digit is interpreted in exactly the same way as it is in FTP, as shown in Table 77-3. Table 77-3. SMTP Reply Code Format: First Digit Interpretation | Reply Code Format | Meaning | Description | | --- | --- | --- | | 1yz | Positive Preliminary Reply | An initial response indicating that the command has been accepted and processing of it is still in progress. The SMTP sender should expect another reply before a new command may be sent. Note that while this first digit type is formally defined in the SMTP specification for completeness, it is not currently used by any of the SMTP commands; that is, no reply codes between 100 and 199 exist in SMTP. | | 2yz | Positive Completion Reply | The command has been successfully processed and completed. | | 3yz | Positive Intermediate Reply | The command was accepted but processing it has been delayed, pending receipt of additional information. For example, this type of reply is often made after receipt of a DATA command to prompt the SMTP sender to send the actual email message to be transferred. | | 4yz | Transient Negative Completion Reply | The command was not accepted and no action was taken, but the error is temporary and the command may be tried again. This is used for errors that may be a result of temporary glitches or conditions that may change, such as a resource on the SMTP server being temporarily busy. | | 5yz | Permanent Negative Completion Reply | The command was not accepted and no action was taken. Trying the same command again is likely to result in another error. An example would be sending an invalid command. | The second reply code digit (*y*) is used to categorize messages into functional groups. This digit is used in the same general way as in FTP, but some of the functional groups are different in SMTP, as you can see in Table 77-4. Table 77-4. SMTP Reply Code Format: Second Digit Interpretation | Reply Code Format | Meaning | Description | | --- | --- | --- | | x0z | Syntax | Syntax errors or miscellaneous messages. | | x1z | Information | Replies to requests for information, such as status requests. | | x2z | Connections | Replies related to the connection between the SMTP sender and SMTP receiver. | | x3z | Unspecified | Not defined. | | x4z | Unspecified | Not defined. | | x5z | Mail System | Replies related to the SMTP mail service itself. | The third reply code digit (*z*) indicates a specific type of message within each of the functional groups described by the second digit. The third digit allows each functional group to have ten different reply codes for each reply type given by the first code digit (preliminary success, transient failure, and so on). Again, as in FTP, these *x*, *y*, and *z* digit meanings are combined to make specific reply codes. For example, the reply code 250 is a positive reply indicating command completion, related to the mail system. It is usually used to indicate that a requested mail command was completed successfully. Table 77-5 contains a list of some of the more common SMTP reply codes taken from RFC 2821, in numerical order. For each, I have shown the typical reply text specified in the standard and provided additional descriptive information when needed. As mentioned earlier, the actual text string for each reply code is implementation-specific. While the standard specifies dry response text such as "Requested action completed" for a 250 message, some servers will customize this code or even give different replies to different 250 messages, depending on the context. Table 77-5. SMTP Reply Codes | Reply Code | Reply Text | Description | | --- | --- | --- | | 211 | System status or system help reply. | | | 214 | *<Help message…>* | Used for text sent in reply to the HELP command. | | 220 | *<servername>* Service ready. | Greeting message sent when TCP connection is first established to an SMTP server. | | 221 | *<servername>* closing transmission channel. | Goodbye message sent in response to a QUIT message. | | 250 | Requested mail action ok, completed | Indicates successful execution of a variety of commands. | | 251 | User not local; will forward to *<forward-path>* | Used when the SMTP receiver agrees to forward a message to a remote user. | | 252 | Cannot VRFY user, but will accept message and attempt delivery | Indicates that a server tried to verify an email address, but was not able to do so completely. Usually means the address appears to be valid but it was not possible to ascertain this to be positively true. | | 354 | Start mail input; end with <CRLF>.<CRLF> | Intermediate reply to a DATA command. | | 421 | *<servername>* Service not available, closing transmission channel | Sent in response to any command when the SMTP receiver prematurely terminates the connection. A common reason for this is receipt of a local shutdown command, due to a hardware reboot, for example. | | 450 | Requested mail action not taken: mailbox unavailable | Sent when a mailbox is busy due to another process accessing it. | | 451 | Requested action aborted: local error in processing | Local processing problem on the server. | | 452 | Requested action not taken: insufficient system storage. | Time to clean out the server's hard disk! | | 500 | Syntax error, command unrecognized | Response to a bad command or one that was too long. | | 501 | Syntax error in parameters or arguments | | | 502 | Command not implemented | Command is valid for SMTP in general but not supported by this particular server. | | 503 | Bad sequence of commands | Commands were not sent in the correct order, such as sending the DATA command before the MAIL command. | | 504 | Command parameter not implemented. | | | 550 | Requested action not taken: mailbox unavailable | Generic response given due to a problem with a specified mailbox. This includes trying to send mail to an invalid address, refusal to relay to a remote mailbox, and so forth. | | 551 | User not local; please try *<forward-path>* | Tells the SMTP sender to try a different path; may be used to support mailbox forwarding. | | 552 | Requested mail action aborted: exceeded storage allocation | User's mailbox is full. | | 553 | Requested action not taken: mailbox name not allowed | Specification of an invalid mailbox address. | | 554 | Transaction failed. | General failure of a transaction. | ## SMTP Multiple-Line Text Replies As in FTP, it is possible for an SMTP reply to contain more than one line of text. In this case, each line starts with the reply code, and all lines but the last have a hyphen between the reply code and the reply text to indicate that the reply continues. The last line has a space between the reply code and reply text, just like a single-line reply. See the "Connection Establishment Using SMTP Extensions" section earlier in this chapter for an example of a multiple-line response to an EHLO command. ## Enhanced Status Code Replies When the ENHANCEDSTATUSCODES SMTP extension is enabled, this causes supplemental reply codes to be issued by the SMTP receiver in response to each command. These codes are similar in some respects to the standard reply codes; they also use three digits, but the digits are separated by periods. These enhanced codes provide more information about the results of operations, especially errors. For example, if you try to issue a RCPT command specifying a remote mailbox on a server that does not support this feature, it will send back a 550 reply, which is a generic error meaning "requested action not taken: mailbox unavailable." When enhanced status codes are active, the response will be 550 5.7.1, which is the more specific message "delivery not authorized, request refused." A full description of these enhanced codes can be found in RFC 1893. ### Tip **KEY CONCEPT** Each time the SMTP sender issues a command, it receives a *reply* from the SMTP receiver. SMTP replies are similar to FTP replies, using both a three-digit reply code and a descriptive text line. A special *enhanced status codes* SMTP extension is also defined; when enabled, this causes the SMTP receiver to return more detailed result information after processing a command. # Chapter 78. TCP/IP ELECTRONIC MAIL ACCESS AND RETRIEVAL PROTOCOLS AND METHODS ![image with no caption](https://github.com/OpenDocCN/greenhat-zh/raw/master/docs/tcpip-gd/img/httpatomoreillycomsourcenostarchimages287681.png.jpg) The Simple Mail Transfer Protocol (SMTP) is responsible for most of the process of sending an electronic mail (email) message from the originator to the recipient. SMTP's job ends when the message has been successfully deposited into the recipient's mailbox on his local SMTP server. In some cases, this mailbox is the end of the message's travels through cyberspace. More often, however, it is only a "rest stop"—the last step of the journey is for the message to be accessed and read by the user to whom it was sent. This may require that it be retrieved from the mailbox and transferred to another client machine. For a variety of reasons, SMTP is not used for the process of accessing a mailbox; instead, a special set of protocols and methods is designed specifically for email access and retrieval. In this chapter, I describe some of the more common techniques used for TCP/IP email access and retrieval. I begin with an overview of the subject that describes in general the different paradigms used for email access and gives an overview of the protocols. I then describe the operation of the very popular Post Office Protocol (POP), focusing on version 3 (POP3). I look at the protocol in general terms, discussing its history, the various versions of the protocol, and the standards that define them. I describe POP3's general operation and the communication between a client and server, concentrating on the three main states through which the session transitions. I then describe each of these states in sequence: the *Authorization* state, *Transaction* state, and *Update* state. Following this, I discuss the other common mail access protocol: the Internet Message Access Protocol (IMAP). This includes a description of its benefits compared to the simpler POP3, a discussion of its operation, and a look at how client and server devices communicate, showing how the IMAP session moves through a series of four states. Finally, I conclude with a discussion of two alternative methods of email access and retrieval. The first I call *direct server access*, which describes several ways that mailboxes are accessed without the use of special remote-access protocols such as POP and IMAP. The second is email access using a web browser. This is the newest email access method and is growing in popularity every year. # TCP/IP Email Mailbox Access Model, Method, and Protocol Overview In an ideal world, every device on the Internet would run SMTP server software, and that one protocol would be sufficient to implement the entire TCP/IP email system. You would compose email on your machine, your SMTP software would send it to a recipient's machine, and she would read it. Here in the real world, however, this is not possible in general terms. An SMTP server must be connected to the Internet and available around the clock to receive email sent at any time by any of the millions of other computers in the world. Most of us either cannot or do not want to run machines continuously connected to the Internet, nor do we want to configure and maintain potentially complex SMTP software. For these reasons, a complete email exchange normally involves not two devices but four: A message is composed on the sender's client machine, and then transferred to the sender's SMTP server, then to the recipient's SMTP server, and finally to the recipient's machine. The communication between SMTP servers is done with SMTP; so is the initial step of sending the email from the sender's machine to the sender's SMTP server. However, SMTP is not used for the last part of the process, which is accessing the recipient's mailbox. Instead, specific mailbox access and retrieval protocols and methods were devised. Why not simply have mail wait on the recipient's SMTP server, and then have the mail sent to the recipient client device when it comes online, using SMTP? This isn't possible for two main reasons. First, SMTP was designed for the specific purpose of transporting only email. Having it responsible for client mailbox access would require adding more functionality, making it difficult to keep SMTP *simple*. In the same vein, SMTP works on a *push* model, with transactions being initiated by the sender. It would need changes to allow it to respond to requests from a client device that is only online intermittently. The second reason is probably more important, because the current protocol configuration allows *flexibility* in how email is accessed. If we used SMTP, all we would be able to do is transfer email to the recipient's client machine. This would be functional, but it would greatly limit the capabilities of how email is used, especially, for example, for users who wish to access mail directly on the server and manipulate it there. Also consider the problem of people with special requirements, such as those who travel and may need to access email from a number of different client devices. There is thus an advantage to providing more than one way to access a mailbox. ## Email Access and Retrieval Models RFC 1733, "Distributed Electronic Mail Models in IMAP4," describes three different paradigms, or models, for mail access and retrieval: **Online Access Model** We would all be using this mode of access in my ideal world scenario, where every machine was always connected to the Internet running an SMTP server. We would have constant, direct online access to our mailboxes. In the real world, this model is still used by some Internet users, especially those who have UNIX accounts or run their own SMTP servers. I call this *direct server access*. **Offline Access Model** In this paradigm, a user establishes a connection to a server where his mailbox is located. The user downloads received messages to the client device and then deletes them from the server mailbox. All reading and other activity performed on the mail can be done offline once the mail has been retrieved. **Disconnected Access Model** This is a hybrid of online and offline access. The user downloads messages from the server, so she can read or otherwise manipulate them without requiring a continuous connection to the server. However, the mail is not deleted from the server, as in the offline model. At some time in the future, the user connects back with the server and synchronizes any changes made on the local device with the mailbox on the server. What sort of changes can be made? Examples include marking whether or not a message has been read to keep track of read and unread mail, and marking messages to which the user has already replied. These are important tools to help those with busy mailboxes keep track of what they need to do. None of the three models is entirely better than the others. Each has advantages and disadvantages, which is why it is good that we have these options rather than the single SMTP protocol for mail access. Direct server access has the main benefits of instant speed and universal access from any location. As for disadvantages, you must be online to read mail, and it usually requires that you use UNIX email clients, which with most people are not familiar. However, IMAP can also be used for online access. Offline access has the main advantages of simplicity and short connection time requirements; you can easily connect to the mailbox, download messages, and then read them locally. But that makes this method somewhat inflexible and poorly suited to access from different machines. Still, it is currently the most popular access method because simplicity is important; it is best typified by POP. Disconnected access attempts to combine the advantages of offline and online access without combining their disadvantages, and it does a pretty good job. The advantages are significant: the ability to access mail quickly and use it offline, while retaining and updating the mailbox on the server to allow access from different client machines. IMAP is popularly used for disconnected access. In the IMAP overview later in this chapter, I explore its advantages over offline access as well as its main disadvantages, which are complexity and far less universal support than POP (though acceptance of IMAP is slowly increasing). Finally, in recent years, a somewhat new mailbox access method has become popular: email access using the World Wide Web. This technique allows a user to access his mailbox from any computer with an Internet connection and a web browser. It is a good example of line blurring, not only between the access models discussed here, but between TCP/IP applications—in this case, the Web and email. ### Tip **KEY CONCEPT** For flexibility, TCP/IP uses a variety of mailbox access and retrieval protocols and methods to allow users to read email. Three different models describe how these different methods work: the *online model*, in which email is accessed and read on the server; the *offline model*, in which mail is transferred to the client device and used there; and the *disconnected model*, in which mail is retrieved and read offline but remains on the server with changes synchronized for consistency. # TCP/IP Post Office Protocol (POP/POP3) The overall communication model used for TCP/IP email provides many options to an email user for accessing her electronic mailbox. The most popular access method today is the simple offline access model, in which a client device accesses a server, retrieves mail, and deletes it from the server. POP was designed for quick, simple, and efficient mail access; it is used by millions of people to access billions of email messages every day. ## POP Overview, History, Versions, and Standards Of the three mailbox access paradigms—online, offline, and disconnected—the offline model is probably the least capable in terms of features. And it is also the most popular. This may seem counterintuitive, but it is in fact a pattern that repeats itself over and over in the worlds of computing and networking. The reason is that *simplicity* and *ease of implementation* are keys to the success of any technology, and the offline mail access model beats the other two in these areas. The history of offline email access goes back farther than one might expect—to the early 1980s. Two decades ago, not everyone and his brother were accessing the Internet to check email the way we do today. In fact, only a relatively small number of machines were connected using TCP/IP, and most users of these machines could access their email on a server, using the online access model. However, even back then, developers recognized the advantages of being able to retrieve email from a server directly to a client computer, rather than accessing the mailbox on the server using Telnet or Network File System (NFS). In 1984, RFC 918 was published, defining POP. This protocol provided a simple way for a client computer to retrieve email from a mailbox on an SMTP server so it could be used locally. The emphasis was on *simple*. The RFC for this first version of POP is only five pages long, and the standard it defined is extremely rudimentary. It describes a simple sequence of operations in which a user provides a name and password for authentication and then downloads the entire contents of a mailbox. Simple is good, but simple has limits. RFC 937, "Post Office Protocol - Version 2" was published in February 1985\. POP2 expanded the capabilities of POP by defining a much richer set of commands and replies. This included the ability to read only certain messages, rather than dumping a whole mailbox. Of course, this came at the cost of a slight increase in protocol complexity, but POP2 was still quite simple as protocols go. These two early versions of POP were used in the mid-1980s, but not very widely. Again, this is simply because the need for an offline email access protocol was limited at that time; most people were not using the Internet before the 1990s. In 1988, RFC 1081 was published, describing POP3\. By this time, the personal computer (PC) was transitioning from a curiosity to a place of importance in the worlds of computing and networking. POP3 was based closely on POP2, but the new version was refined and enhanced with the idea of providing a simple and efficient way for PCs and other clients not normally connected to the Internet to access and retrieve email. Development on POP3 continued through the 1990s, with several new RFCs published every couple of years. RFC 1081 was made obsolete by, in turn, RFCs 1225, 1460, 1725, and 1939\. Despite the large number of revisions, the protocol itself has not changed a great deal since 1988; these RFCs contain only relatively minor tweaks to the original description of the protocol. RFC 1939 was published in 1996, and POP3 has not been revised since that time, though a few subsequent RFCs define optional extensions and additions to the basic protocol, such as alternative authentication mechanisms. While POP3 has been enhanced and refined, its developers have remained true to the basic idea of a very simple protocol for quick and efficient email transfer. POP3 is a straightforward state-based protocol, with a client and server proceeding through three stages during a session. A very small number of commands is defined to perform simple tasks, and even after all its changes and revisions, the protocol has a minimum of fluff. For reasons that are unclear to me, almost everyone refers to POP with its version number—that is, they say *POP3* instead of *POP*. This is true despite most people not using version numbers with many other protocols, and almost no one using any other version of POP. But it is the convention, and I will follow it in the rest of this discussion. ### Tip **KEY CONCEPT** POP is currently the most popular TCP/IP email access and retrieval protocol. It implements the offline access model, allowing users to retrieve mail from their SMTP server and use it on their local client computers. It is specifically designed to be a simple protocol and has only a small number of commands. The current revision of POP is version 3, and the protocol is usually abbreviated *POP3*. ### Note *Some implementations of POP attempt to implement the disconnected access model, with limited success. More often, however, IMAP is used for this purpose, since it is better suited to that access model. See the overview of IMAP later in this chapter for more details*. ## POP3 General Operation POP3 is a regular TCP/IP client/server protocol. In order to provide access to mailboxes, POP3 server software must be installed and continuously running on the server on which the mailboxes are located. This does not necessarily have to be the same physical hardware device that runs the SMTP server software that receives mail for those boxes—a mechanism such as NFS may be used to allow both the POP3 and SMTP servers to "see" mailboxes locally. POP3 clients are regular end-user email programs that make connections to POP3 servers to get mail; examples include Microsoft Outlook and Eudora Email. POP3 uses TCP for communication, to ensure the reliable transfer of commands, responses, and message data. POP3 servers listen on well-known port number 110 for incoming connection requests from POP3 clients. After a TCP connection is established, the POP3 session is activated. The client sends commands to the server, which replies with responses and/or email message contents. POP3 commands are three or four letters long and are case-insensitive. They are all sent in plain ASCII text and terminated with a CRLF sequence, just as with FTP and SMTP commands. POP3 replies are also textual, but the protocol does not use the complex three-digit reply code mechanism of FTP (and SMTP). In fact, it defines only two basic responses: **+OK** A positive response, sent when a command or action is successful **-ERR** A negative response, sent to indicate that an error has occurred These messages may be accompanied by explanatory text, especially in the case of an ERR response, to provide more information about the nature of the error. ## POP3 Session States POP3 is described in terms of a *finite state machine (FSM)*, with a session transitioning through three states during the course of its lifetime, as shown in Figure 78-1 to describe its operation, but it is very simple because it is linear. Once a TCP connection is established between a POP3 client and POP3 server, the session proceeds through three states in sequence, after which the connection is terminated."). (I describe the concepts behind using FSM as a descriptive tool in Chapter 47.) Fortunately, unlike the FSMs of protocols like TCP, this one really is simple, because it is *linear*. The session goes through each state once and only once, in the following sequence: 1. **Authorization State** The server provides a greeting to the client to indicate that it is ready for commands. The client then provides authentication information to allow access to the user's mailbox. 2. **Transaction State** The client is allowed to perform various operations on the mailbox. These include listing and retrieving messages and marking retrieved messages for deletion. 3. **Update State** When the client is finished with all of its tasks and issues the QUIT command, the session enters this state automatically, where the server actually deletes the messages marked for deletion in the Transaction state. The session is then concluded, and the TCP connection between the two is terminated. ![POP3 finite state machine POP uses a finite state machine (FSM) to describe its operation, but it is very simple because it is linear. Once a TCP connection is established between a POP3 client and POP3 server, the session proceeds through three states in sequence, after which the connection is terminated.](https://github.com/OpenDocCN/greenhat-zh/raw/master/docs/tcpip-gd/img/httpatomoreillycomsourcenostarchimages288297.png.jpg) Figure 78-1. POP3 finite state machine POP uses a finite state machine (FSM) to describe its operation, but it is very simple because it is linear. Once a TCP connection is established between a POP3 client and POP3 server, the session proceeds through three states in sequence, after which the connection is terminated. POP3 is designed so that only certain commands may be sent in each of these states. Here, I will describe the activities that take place in these three states, including the commands that are issued by the client in each. ### Tip **KEY CONCEPT** POP3 is a client/server protocol that is described using a simple linear sequence of states. A POP3 session begins with a POP3 client making a TCP connection to a POP3 server, at which point the session is in the *Authorization* state. After successful authentication, the session moves to the *Transaction* state, where the client can perform mail access transactions. When it is finished, the client ends the session and the *Update* state is entered automatically, where cleanup functions are performed and the POP3 session ended. ### POP3 Authorization State: User Authentication Process and Commands A session between a POP3 client and a POP3 server begins when the client sends a TCP connection request to the server. The connection is established using the standard TCP three-way handshake, and the POP3 session commences. The first of the three states of a POP3 session, the Authorization state, is responsible for authenticating the POP3 client with the server. When the session first enters this state, the server sends a greeting message to the client. This tells the client that the connection is alive and ready for the client to send the first command. An example of such a greeting follows: ``` +OK POP3 server ready ``` The client is now required to authenticate the user who is trying to access a mailbox. This proves that the user has the right to access the server and identifies the user so the server knows which mailbox is being requested. The normal method of authorization in POP3 is a standard user name/password login. This is pretty much identical to how a login is performed in FTP; even the commands are the same. First the client issues a USER command along with the user's mailbox name (his user name or email address). The server responds with an intermediate acknowledgment. The client then uses the PASS command to send the user's password. Assuming the login is valid, the server responds to the client with an acknowledgment that indicates successful authentication. The response will also typically specify the number of messages waiting for the user in the mailbox. This process is illustrated in Figure 78-2. ![POP3 user authentication process Once the TCP connection is established from the client to the server, the server responds with a greeting message, and the simple POP3 authentication process begins. The client sends a user name and password to the server using the USER and PASS commands, and the server evaluates the information to determine whether or not it will allow the client access.](https://github.com/OpenDocCN/greenhat-zh/raw/master/docs/tcpip-gd/img/httpatomoreillycomsourcenostarchimages288299.png.jpg) Figure 78-2. POP3 user authentication process Once the TCP connection is established from the client to the server, the server responds with a greeting message, and the simple POP3 authentication process begins. The client sends a user name and password to the server using the USER and PASS commands, and the server evaluates the information to determine whether or not it will allow the client access. Example 78-1 shows an example POP3 authorization, with the client's commands in boldface and the server's responses in italics. ### Note *Some servers may require only the name of the user* (jane), *while others require the full email address, as shown in Example 78-1*. Example 78-1. Example of POP3 authorization ``` *`+OK POP3 server ready`* `USER jane@somewhereelse.com` *`+OK`* `PASS *******` *`+OK jane@somewhereelse.com has 3 messages`* ``` If authorization is successful, the POP3 session transitions to the Transaction state, where mail-access commands can be performed. If the user name or password is incorrect, an error response is given, and the session cannot proceed. The authorization may also fail due to technical problems, such as an inability by the server to lock the mailbox (perhaps due to new mail arriving via SMTP). Since user name/password authorization is considered by many people to be insufficient for the security needs of modern internetworks, the POP3 standard also defines an alternative authentication method using the APOP command. This is a more sophisticated technique based on the Message Digest 5 (MD5) encryption algorithm. If the server supports this technique, in its opening greeting it provides a string indicating a *timestamp* that is unique for each POP3 session. The client then performs an MD5 calculation using this timestamp value and a shared secret known by the server and client. The result of this calculation is included in the client's APOP command. If it matches the server's calculation, authentication is successful; otherwise, the session remains in the Authorization state. POP was also designed to be extendable through the addition of other authentication mechanisms. This process is based on the use of the optional AUTH command, as described in RFC 1734. ### Tip **KEY CONCEPT** A POP3 session begins in the Authorization state, where the client device is expected to authenticate with the server. By default, POP3 uses only a simple user name/password authentication method. Optional authentication methods are also defined for applications requiring more security. ### POP3 Transaction State: Mail and Information Exchange Process and Commands Once the POP3 client has successfully authenticated the user who is performing mailbox access, the session transitions from the Authorization state to the Transaction state. There's no real mystery as to what this phase of the connection is all about: The POP3 client issues the commands that perform mailbox access and message retrieval transactions. Most of the commands defined in POP3 are valid only in the Transaction state. Table 78-1 lists each of them, in the order in which they appear in RFC 1939. Table 78-1. POP3 Transaction Commands | Command Code | Command | Parameters | Description | | --- | --- | --- | --- | | STAT | Status | None | Requests status information for the mailbox. The server will normally respond, telling the client the number of messages in the mailbox and the number of bytes of data it contains. Optionally, more information may also be returned. | | LIST | List Messages | Optional message number | Lists information for the messages in a mailbox; generally this means showing the message number and its size. If a message number is given, only that message's information is provided; otherwise, the full contents of the mailbox are described, one line at a time, with a line containing just a single period at the end. | | RETR | Retrieve | Message number | Retrieves a particular message from the mailbox. The server responds with a standard +OK message and then immediately sends the message in RFC 822 format, one line at a time. A line with a single period is sent after the last line. | | DELE | Delete | Message number | Marks a message as deleted. Once deleted, any further attempt to access a message (using LIST or RETR, for example) results in an error. | | NOOP | No Operation | None | Does nothing; the server just returns an +OK reply. | | RSET | Reset | None | Resets the session to the state it was in upon entry to the Transaction state. This includes undeleting any messages already marked for deletion. | | TOP | Retrieve Message Top | Message number and number of lines | Allows a client to retrieve only the beginning of a message. The server returns the headers of the message and only the first *N* lines, where *N* is the number of lines specified. This command is optional and may not be supported by all servers. | | UIDL | Unique ID Listing | Optional message number | If a message number was specified, returns a unique identification code for that message; otherwise, returns an identification code for each message in the mailbox. This command is optional and may not be supported by all servers. | The Transaction state is relatively unstructured in that commands do not need to be issued in any particular order to meet the requirements of the standard. However, there is a natural progression to how a mailbox is retrieved, and that means the commands are usually used in the following order: 1. The client issues a STAT command to see the number of messages in the mailbox. 2. The client issues a LIST command, and the server tells it the number of each message to be retrieved. 3. The client issues a RETR command to get the first message and, if successful, marks it for deletion with DELE. The client uses RETR/DELE for each successive message. Example 78-2 and Figure 78-3") show a sample access sequence for a mailbox containing two messages that total 574 bytes; the client's commands are in boldface and the server's responses are in italics. Example 78-2. Example of the POP3 mail exchange process ``` `STAT` *`+OK 2 574`* `LIST` *`+OK`* *`1 414`* *`2 160`* *`.`* `RETR 1` *`+OK`* *`(Message 1 is sent)`* *`.`* `DELE 1` *`+OK message 1 deleted`* `RETR 2` *`+OK`* *`(Message 2 is sent)`* *`.`* `DELE 2` *`+OK message 2 deleted`* `QUIT` ``` The exact message sent in reply to each command is server-dependent; some say +OK, while others provide more descriptive text, as I have done here for the responses to the DELE command. ### Tip **KEY CONCEPT** After successful authorization, the POP3 session transitions to the Transaction state, where the client actually accesses email messages on the server. The client normally begins by first retrieving statistics about the mailbox from the server and obtaining a list of the messages in the mailbox. The client then retrieves each message one at a time, marking each retrieved message for deletion on the server. In some cases, a POP3 client may be configured to *not* delete messages after retrieving them. This is useful, for example, when Web-based access is being combined with a conventional email client program. ### POP3 Update State: Mailbox Update and Session Termination Process and Commands Once the POP3 client has completed all the email message access and retrieval transactions that it needs to perform, it isn't quite finished yet. The POP3 standard defines a final session state, the Update state, to perform various housekeeping functions, after which both the POP3 session and the underlying TCP connection are terminated. The transition from the Transaction state to the Update state occurs when the POP3 client issues the QUIT command. This command has no parameters and serves to tell the POP3 server that the client is finished and wishes to end the session. The POP3 standard lists this command as part of its description of the Update state, though it is actually issued from the Transaction state. ![POP3 mail exchange process This diagram shows the typical exchange of commands and replies employed by a POP3 client to retrieve email from a POP3 server. The STAT command is used to get mailbox statistics, followed by the LIST command to obtain a list of message numbers. Each message in turn is then retrieved using RETR and marked for deletion by DELE. (Messages are not actually deleted until the Update state is entered.)](https://github.com/OpenDocCN/greenhat-zh/raw/master/docs/tcpip-gd/img/httpatomoreillycomsourcenostarchimages288301.png.jpg) Figure 78-3. POP3 mail exchange process This diagram shows the typical exchange of commands and replies employed by a POP3 client to retrieve email from a POP3 server. The STAT command is used to get mailbox statistics, followed by the LIST command to obtain a list of message numbers. Each message in turn is then retrieved using RETR and marked for deletion by DELE. (Messages are not actually deleted until the Update state is entered.) After the POP3 server receives the QUIT command, it deletes any messages that were previously marked for deletion by the DELE command in the Transaction state. It's interesting to note that POP chose to implement this two-stage deletion process. The standard doesn't describe specifically why this was done, but it seems likely that it is a precaution to insure against accidental deletion and loss of mail. By delaying actual deletion until the Update state, the server can verify that it has received and processed all commands prior to the move to the Update state. This also allows the deletion of messages to be undone if necessary, using the RSET command, if the user changes her mind about the deletion prior to exiting the Transaction state. Finally, if any problem occurs with communication between the client and server that causes the TCP connection to be interrupted prematurely before the QUIT command is issued, no messages will be removed from the mailbox, giving the client a second chance to retrieve them in case they were not received properly. Once the deleted messages have been removed, the server returns an acknowledgment to the client: +OK if the update was successful, or -ERR if there was a problem removing one or more of the deleted messages. Assuming no problems occurred, the +OK response will also contain a goodbye message of some sort, indicating that the session is about to be closed. The TCP connection between the client and server is then torn down and the session is done. ### Tip **KEY CONCEPT** When the POP3 client is done with its email transactions, it issues the QUIT command. This causes the Update state to be entered automatically, where the server performs necessary cleanup operations, including deleting any messages marked for deletion in the Transaction state. A POP3 mail-retrieval session normally lasts a few seconds or minutes, but it can take many minutes if the mailbox is large and the connection between the client and server is slow. There is no limit on how long the client and server can be connected, as long as commands continue to be sent by the client. A POP3 server will normally implement an inactivity timer, however, which is customizable but must have a duration of no less than ten minutes. If the connection is idle for the full duration of the inactivity timer, the server assumes that the client has experienced some sort of a problem and shuts down the connection. If this occurs, the server does not delete any messages marked for deletion—again, this is to give the client another chance to retrieve those messages if a problem occurred getting them the first time. # TCP/IP Internet Message Access Protocol (IMAP/IMAP4) The offline mailbox access model provides the basic mail access functions that most users need. Using the popular POP3, a user can access her mailbox and retrieve messages so she can read them on her local machine. This model has the advantage of simplicity, but it does not provide many features that are increasingly in demand today, such as keeping track of the status of messages and allowing access from many client devices simultaneously. To provide better control over how mail is accessed and managed, we must use either the online or disconnected access models. IMAP was created to allow these access models to be used; it provides rich functionality and flexibility for the TCP/IP email user. ### Tip **RELATED INFORMATION** *The main price that IMAP pays for having a much richer set of functionality than POP is much more complexity. In this section, I have described IMAP in approximately the same level of detail that I did earlier for POP. Please see the appropriate RFC documents for the full description of the protocol and more discussion of some of its nuances, particularly the syntax of the many commands and parameters, which would take dozens of pages to cover fully here*. ## IMAP Overview, History, Versions, and Standards POP3 has become the most popular protocol for accessing TCP/IP mailboxes, not because of its rich functionality, but in spite of its lack of functionality. POP implements the offline mail access model, where mail is retrieved and then deleted from the server where the mailbox resides, so it can be used on a local machine. Millions of people use POP3 every day to access incoming mail. Unfortunately, due to the way the offline access model works, POP3 cannot be used for much else. The online model is the one we would use in an ideal world, in which we all would be always connected to the Internet all the time. Offline access is a necessity, however, because most user client machines are connected to the Internet only periodically. The transfer of mail from the server to a client machine removes the requirement that we be online to perform mail functions, but it costs us the benefits of central mail storage on the server. This may seem counterintuitive: how can it be better to have mail stored on some remote server rather than on our local computer? The main reason for this is flexibility of access. One of the biggest problems with offline access using POP3 is that mail is transferred permanently from a central server to one client machine. This is fine as long as an individual uses only that one machine, but what if the person has separate work and home computers or travels a great deal? And what about a mailbox shared by many users? These concerns have become more and more important in recent years. Another issue is data security and safety. Mail servers run by Internet service providers (ISPs) are usually located in professionally managed data centers. They are carefully controlled and monitored, and backups occur on a routine basis. Most people do not take this sort of care with their own PCs and Macs, nor do they back up their data routinely. So, it's less likely that people will lose mail that on the server. Of course, we still have the problem of not wanting to force users to be online all the time to access their mail. The solution is the disconnected mailbox access model, which marries the benefits of online and offline access. Mail is retrieved for local use as in the offline model, so the user does not need to be connected to the server continuously. However, changes made to the mailbox are synchronized between the client and the server. The mail remains on the server, where it can be accessed from a different client in the future, and the server acts as a permanent home base for the user's mail. Recognizing these benefits, developers made some attempts to implement POP using the disconnected access model. Typically, this was done by using POP commands to retrieve mail but still leave it on the server, which is an option in many client programs. This works, but only to a limited extent; for example, keeping track of which messages are new or old becomes an issue when they are both retrieved and left on the server. POP simply lacks the features required for proper disconnected access because it was not designed for it. In the mid-1980s, development began at Stanford University on a new protocol that would provide a more capable way of accessing user mailboxes. The result was the Interactive Mail Access Protocol, later renamed the Internet Message Access Protocol (IMAP). ### IMAP Features IMAP was designed for the specific purpose of providing flexibility in how users access email messages. It, in fact, can operate in all three of the access modes: online, offline, and disconnected access. Of these, the online and disconnected access modes are of interest to most users of the protocol; offline access is similar to how POP works. IMAP allows a user to do all of the following: * Access and retrieve mail from a remote server so it can be used locally while retaining it on the server. * Set message flags so that the user can keep track of which messages he has already seen, already answered, and so on. * Manage multiple mailboxes and transfer messages from one mailbox to another. You can organize mail into categories, which is useful for those working on multiple projects or those who are on various mailing lists. * Determine information about a message prior to downloading it, to decide whether or not to retrieve it. * Download only portions of a message, such as one body part from a MIME multipart message. This can be quite helpful in cases where large multimedia files are combined with short text elements in a single message. * Manage documents other than email. For example, IMAP can be used to access Usenet messages. Of course, there are some disadvantages to IMAP, but not many. One disadvantage is that it is more complex, but it's really not that complex, and the protocol has been around for enough years that this is not a big issue. The most important sticking point with IMAP is simply that it is used less commonly than POP, so providers that support it are not as easy to find as those that support POP. This is changing, however, as more people discover IMAP's benefits. ### Tip **KEY CONCEPT** POP is popular because of its simplicity and long history, but it has few features and normally supports only the rather limited offline mail access method. To provide more flexibility for users in how they access, retrieve, and work with email messages, IMAP was developed. IMAP is used primarily in the online and disconnected access models. It allows users to access mail from many different devices, manage multiple mailboxes, select only certain messages for downloading, and much more. Due to its many capabilities, it is growing in popularity. ### IMAP History and Standards IMAP has had a rather interesting history—interesting in the sense that the normal orderly development process that is used for most TCP/IP protocols broke down. The result wasn't quite as bad as the chaos that occurred in the development of SNMP version 2 (see Chapter 65), but it was still unusual. The first version of IMAP formally documented as an Internet standard was IMAP version 2 (IMAP2) in RFC 1064, published in July 1988\. This was updated in RFC 1176, August 1990, retaining the same version number. However, it seems that some of the people involved with IMAP were not pleased with RFC 1176, so they created a new document defining version 3 of IMAP (IMAP3): RFC 1203, published in February 1991\. This is described by its authors as a "counter proposal." For whatever reason, however, IMAP3 was never accepted by the marketplace. Instead, people kept using IMAP2 for a while. An extension to the protocol was later created, called IMAP2bis, which added support for Multipurpose Internet Mail Extensions (MIME) to IMAP. This was an important development due to the usefulness of MIME, and many implementations of IMAP2bis were created. Despite this, for some reason IMAP2bis was never published as an RFC. This may have been due to the problems associated with the publishing of IMAP3. ### Note *bis is a Latin word meaning again. It is sometimes used to differentiate changed technical documents from their previous versions when no official new version number is allocated*. In December 1994, IMAP version 4 (IMAP4) was published in two RFCs: RFC 1730 describing the main protocol, and RFC 1731 describing authentication mechanisms for IMAP4\. IMAP4 is the current version of IMAP that is widely used today. It continues to be refined; the latest specific version is actually called version 4rev1 (IMAP4rev1), defined in RFC 2060, and then most recently by RFC 3501\. Most people still just call this *IMAP4*, and that's what I will do in the rest of this section. ## IMAP General Operation IMAP4 is a standard client/server protocol like POP3 and most other TCP/IP application protocols. For the protocol to function, an IMAP4 server must be operating on the server where user mailboxes are located. Again, as with POP3, this does not necessarily need to be the same physical server that provides SMTP service. The mailbox must in some way be made accessible to both SMTP for incoming mail, and to IMAP4 for message retrieval and modification. A mechanism for ensuring exclusive access to avoid interference between the various protocols is also needed. IMAP4 uses the Transmission Control Protocol (TCP) for communication. This ensures that all commands and data are sent reliably and received in the correct order. IMAP4 servers listen on well-known port number 143 for incoming connection requests from IMAP4 clients. After a TCP connection is established, the IMAP4 session begins. ## IMAP Session States The session between an IMAP4 client and server is described in the IMAP standards using an FSM. Again, this is similar to how POP3 operates, except that IMAP4 is a bit more complex. Its FSM defines four states instead of three, and where a POP3 session is linear (going through each state only once) in IMAP4 the session is not. However, the state flow is still fairly straightforward, mostly following a logical sequence from one state to the next. The IMAP FSM is illustrated in Figure 78-4 but it's still rather straightforward. Once the TCP connection is made between client and server, the Not Authenticated state is entered; after successful authorization, the session moves to the Authenticated state. The session may move between Authenticated and Selected several times, as different mailboxes are selected for use and then closed when no longer needed. From any state the session may be terminated, entering the Logout state."). ![IMAP FSM The IMAP FSM is slightly more complex than that of POP (shown in ) but it's still rather straightforward. Once the TCP connection is made between client and server, the Not Authenticated state is entered; after successful authorization, the session moves to the Authenticated state. The session may move between Authenticated and Selected several times, as different mailboxes are selected for use and then closed when no longer needed. From any state the session may be terminated, entering the Logout state.](https://github.com/OpenDocCN/greenhat-zh/raw/master/docs/tcpip-gd/img/httpatomoreillycomsourcenostarchimages288303.png.jpg) Figure 78-4. IMAP FSM The IMAP FSM is slightly more complex than that of POP (shown in Figure 78-1 to describe its operation, but it is very simple because it is linear. Once a TCP connection is established between a POP3 client and POP3 server, the session proceeds through three states in sequence, after which the connection is terminated.")) but it's still rather straightforward. Once the TCP connection is made between client and server, the Not Authenticated state is entered; after successful authorization, the session moves to the Authenticated state. The session may move between Authenticated and Selected several times, as different mailboxes are selected for use and then closed when no longer needed. From any state the session may be terminated, entering the Logout state. The following are the IMAP states, in the usual sequence in which they occur for a session: 1. **Not Authenticated State** The session normally begins in this state after a TCP connection is established, unless the special IMAP *preauthentication* feature has been used (we'll get to this feature shortly). At this point, the client cannot really do much aside from providing authentication information so it can move to the next state. 2. **Authenticated State** The client has completed authentication, either through an authentication process in the prior state or through preauthentication. The client is now allowed to perform operations on whole mailboxes. The client must select a mailbox before individual message operations are permitted. 3. **Selected State** After a mailbox has been chosen, the client is allowed to access and manipulate individual messages within the mailbox. When the client is finished with the current mailbox, it can close it and return to the Authenticated state to select a new one to work with, or it can log out to end the session. 4. **Logout State** The client may issue a Logout command from any of the other states to request that the IMAP session be ended. The session may also enter this state if the session inactivity timer expires. The server sends a response, and the connection is terminated. ### Tip **KEY CONCEPT** IMAP is a client/server application, and an IMAP session begins with the client making a TCP connection to the server. The session then normally starts in the Not Authenticated state and remains there until successful authentication. In the Authenticated state, the client may perform operations on whole mailboxes, but a mailbox must be selected to transition to the Selected state, where individual messages can be manipulated. The client can work with many mailboxes by selecting each one in turn; it then logs out from the server. Of the four IMAP states, only the first three are *interactive*, meaning states in which commands are actively issued by the client and responses provided by the server. Some IMAP commands can be used while the session is in any state; others are state-specific. ### Session Establishment and Greeting The server determines in which state the IMAP session begins and sends a *greeting* message to tell the client the session is established and indicate which state it is in. Normally, the server will begin the session in the Not Authenticated state. This is conveyed to the client with the normal OK greeting message, such as this: ``` * OK <*`server-name`*> server ready ``` ### Preauthentication In certain circumstances, a server may already know the identity of the client, perhaps as a result of some external authentication mechanism not part of the IMAP protocol. In this case, a special greeting is used: ``` * PREAUTH <*`server-name`*> server ready, logged in as <*`user-name`*> ``` This tells the client that it is already in the Authenticated state. If the server decides for whatever reason not to accept a new session from the client, it can respond with a BYE response, instead of OK or PREAUTH, and close the TCP connection. ## IMAP Commands, Results, and Responses Once an IMAP session is established, all communication between the client and server takes place in the form of *commands* sent by the client and *responses* returned by the server. Like POP3, commands and responses are sent as strings of ASCII text and terminated with a CRLF sequence, making them compatible with the way data is sent using the Telnet Protocol. However, IMAP has a few differences from POP and many other TCP/IP application protocols. The first interesting thing about IMAP commands is that most are not abbreviated into codes of three or four letters—they are spelled out in full. So where POP3 has a STAT command, the command in IMAP is called STATUS. Commands are normally shown in uppercase, as I do in this book, but they are case-insensitive. IMAP also uses an interesting system of *command tagging* to match client commands explicitly with certain server responses. Each time a client sends a command, it prefixes it with a tag that is unique for the particular session. The tags are usually short strings with a monotonically increasing number in them; the examples in the IMAP standards have the first command tagged a0001, the second a0002, and so on. That said, as long as each command is uniquely labeled, it doesn't matter what tagging scheme is used. When the server needs to send a response that is specific to a command, it tags the reply with the appropriate command tag. Not all replies are tagged, however. The standard doesn't state explicitly why this tagging scheme is needed, but I believe it is probably related to IMAP's multiple command feature. IMAP clients are allowed to send a sequence of commands to the server to be processed, rather than sending commands only one at a time. This can improve performance when certain commands would take a long time to complete. The only restriction is that the commands must be independent enough that the result of executing them all would be the same, regardless of the order in which they were processed. For example, sending a command to read a particular entity in combination with a command to store a value into the same entity is not allowed. ### Tip **KEY CONCEPT** IMAP tags its commands with a unique identifier. These tags can then be used in replies by the server to match replies with the commands to which they correspond. This enables multiple commands to be sent to an IMAP server in succession. ### Command Groups IMAP commands are organized into groups based on which session states the IMAP session may be in when they are used: **"Any State" Commands** A small number of commands that can be used at any time during an IMAP session. **Not Authenticated State Commands** Commands that can be used only in the Not Authenticated state. They are usually used for authentication, of course. **Authenticated State Commands** Commands used to perform various actions on mailboxes. (Note that despite the name, these commands can also be used in the Selected state.) **Selected State** A set of commands for accessing and manipulating individual messages that can be used only in the Selected state. The reason for having the distinct Authenticated and Selected states and command groups is that IMAP is designed specifically to enable the manipulation of multiple mailboxes. After the session starts and the client is authenticated, the client is allowed to issue commands that work with entire mailboxes. However, it may not issue commands that manipulate individual messages until it tells the server which mailbox it wants to work with, which puts it in the Selected state. The client can also issue mailbox commands from the Selected state. ### Note *In addition to these four state groups, the standard also defines an extension mechanism that allows new commands to be defined. These must begin with the letter X*. ### "Any State" Commands Table 78-2 describes the IMAP "any state" commands, which can be used whenever needed. Table 78-2. IMAP "Any State" Commands | Command | Parameters | Description | | --- | --- | --- | | CAPABILITY | None | Asks the server to tell the client what capabilities and features it supports. | | NOOP (No Operation) | None | Does nothing. May be used to reset the inactivity timer or to prompt the server periodically to send notification if new messages arrive. | | LOGOUT | None | Tells the server that the client is done and ready to end the session, which transitions to the Logout state for termination. | ### Results and Responses Each command sent by the IMAP client elicits some sort of reaction from the IMAP server. The server takes action based on what the client requested and then returns one or more text strings to indicate what occurred. The server can send two types of replies after a command is received: **Result** A reply usually indicating the status or disposition of a command. It may be tagged with the command tag of the command whose result it is communicating, or it may be a general message that is not tagged. **Response** Any type of information that is being sent by the server to the client. It is usually not tagged with a command tag and is not specifically intended to indicate server status. ### Note *The IMAP standards sometimes use the terms result, response, and reply in a manner that I find to be inconsistent. Watch out for this if you examine the IMAP RFCs*. ### Tip **KEY CONCEPT** IMAP servers issue two basic types of replies to client commands: *results* are replies that indicate the success, failure, or status of a command; *responses* are general replies containing many different types of information that the server needs to send to the client. ### Result Codes Three main result codes are sent in reply to a command, and two special ones are used in certain circumstances: **OK** A positive result to a command, usually sent with the tag of the command that was successful. May be sent untagged in the server's initial greeting when a session starts. **NO** A negative result to a command. When tagged, indicates the command failed; when untagged, serves as a general warning message about some situation on the server. **BAD** Indicates an error message. It is tagged when the error is directly related to a command that has been sent and otherwise is untagged. **PREAUTH** An untagged message sent at the start of a session to indicate that no authentication is required; the session goes directly to the Authenticated state. **BYE** Sent when the server is about to close the connection. It is always untagged and is sent in reply to a Logout command or when the connection is to be closed for any other reason. ### Response Codes In contrast to results, responses are used to communicate a wide variety of information to the client device. Responses normally include descriptive text that provides details about what is being communicated. They may be sent either directly in reply to a command or incidentally to one. An example of the latter case would be if a new message arrives in a mailbox during a session. In this case, the server will convey this information unilaterally at its first opportunity, regardless of what command was recently sent. The following are the response codes defined by the IMAP standard: **ALERT** An alert message to be sent to the human user of the IMAP client to inform him of something important. **BADCHARSET** Sent when a search fails due to use of an unsupported character set. **CAPABILITY** A list of server capabilities may be sent as part of the initial server greeting so the CAPABILITY command does not need to be used. **PARSE** Sent when an error occurs parsing the headers or MIME content of an email message. **PERMANENTFLAGS** Communicates a list of message status flags that the client is allowed to manipulate. **READ-ONLY** Tells the client that the mailbox is accessible only in a read-only mode. **READ-WRITE** Tells the client that the mailbox is accessible in read-write mode. **TRYCREATE** Sent when an APPEND or COPY command fails due to the target mailbox not existing, to suggest to the client that it try creating the mailbox first. **UIDNEXT** Sent with a decimal number that specifies the next unique identifier value to use in an operation. These identifiers allow each message to be uniquely identified. **UIDVALIDITY** Sent with a decimal number that specifies the unique identifier validity value, used to confirm unique message identification. **UNSEEN** Sent with a decimal number that tells the client the message that is flagged as not yet seen (a new message). ## IMAP Not Authenticated State: User Authentication Process and Commands An IMAP4 session begins with an IMAP4 client establishing a TCP connection with an IMAP4 server. Under normal circumstances, the IMAP4 server has no idea who the client is, and therefore starts the session in the Not Authenticated state. For security reasons, the client is not allowed to do anything until it is authenticated. Thus, the only purpose of this state is to allow the client to present valid credentials so the session can move on to the Authenticated state. ### IMAP Authentication Methods The IMAP4 standard defines three different mechanisms by which a client may authenticate itself. These are implemented using one or more of the three different commands allowed only in the Not Authenticated state, which are shown in Table 78-3. Table 78-3. IMAP Not Authenticated State Commands | Command | Parameters | Description | | --- | --- | --- | | LOGIN | User name and password | Specifies a user name and password to use for authentication. | | AUTHENTICATE | Authentication mechanism name | Tells the server that the client wants to use a particular authentication mechanism and prompts the client and server to exchange authentication information appropriate for that mechanism. | | STARTTLS | None | Tells the IMAP4 server to use the Transport Layer Security (TLS) protocol for authentication, and prompts TLS negotiation to begin. | In response to a LOGIN or AUTHENTICATE command, the server will send an OK message if the authentication was successful, and then transition to the Authenticated state. It will send a NO response if authentication failed due to incorrect information. The client can then try another method of authenticating or terminate the session with the LOGOUT command. The three authentication methods are as follows: **Plain Login** This is the typical user name/password technique, using the LOGIN command by itself. This is similar to the simple scheme used in POP3, except that in IMAP4 one command is used to send both the user name and password. Since the command and parameters are sent in plain text, this is by far the least secure method of authentication and is not recommended by the standard unless some other means is used in conjunction. **TLS Login** This is a secure login where the Transport Layer Security (TLS) protocol is first enabled with the STARTTLS command, and then the LOGIN command can be used securely. Note that STARTTLS only causes the TLS negotiation to begin and does not itself cause the IMAP client to be authenticated. Either LOGIN or AUTHENTICATE must still be used. **Negotiated Authentication Method** The AUTHENTICATE command allows the client and server to use any authentication scheme that they both support. The server may indicate which schemes it supports in response to a CAPABILITY command. After specifying the authentication mechanism to be used, the server and client exchange authentication information as required by the mechanism specified. This may require one or more additional lines of data to be sent. ### Tip **KEY CONCEPT** IMAP supports three basic types of authentication: a plain user name/password login, authentication using the Transport Layer Security (TLS) protocol, or the negotiation of some other authentication method between the client and server. In some cases, the IMAP server may choose to preauthenticate clients that it is able to identify reliably; in which case, the Not Authenticated state is skipped entirely. ## IMAP Authenticated State: Mailbox Manipulation/Selection Process and Commands In the normal progression of an IMAP session, the Authenticated state is the first state in which the IMAP client is able to perform useful work on behalf of its user. This state will normally be reached from the Not Authenticated state after successful authentication using the LOGIN or AUTHENTICATE command. Alternately, a server may preauthenticate a client and begin the session in this state directly. Once in the Authenticated state, the client is considered authorized to issue commands to the server. However, it may issue only commands that deal with *whole mailboxes*. As mentioned in the general operation overview, IMAP was created to allow access to, and manipulation of, multiple mailboxes. For this reason, the client must specify dynamically which mailbox it wants to use before commands dealing with individual messages may be given. This is done in this state using the SELECT or EXAMINE command, which both cause a transition to the Selected state. It is also possible that the Authenticated state can be reentered during the course of a session. If the CLOSE command is used from the Selected state to close a particular mailbox, the server will consider that mailbox deselected, and the session will transition back to the Authenticated state until a new selection is made. The same can occur if a new SELECT or EXAMINE command is given from the Selected state but fails. ### Authenticated State Commands Table 78-4 provides a brief description of the mailbox-manipulation commands that can be used in the Authenticated state. Table 78-4. IMAP Authenticated State Commands | Command | Parameters | Description | | --- | --- | --- | | SELECT | Mailbox name | Selects a particular mailbox so that messages within it can be accessed. If the command is successful, the session transitions to the Selected state. The server will also normally respond with information for the client about the selected mailbox, as described after this table. | | EXAMINE | Mailbox name | The same as the SELECT command, except that the mailbox is opened read-only; no changes are allowed. | | CREATE | Mailbox name | Creates a mailbox with the given name. | | DELETE | Mailbox name | Deletes the specified mailbox. | | RENAME | Current and new mailbox names | Renames a mailbox. | | SUBSCRIBE | Mailbox name | Adds the mailbox to the server's set of active mailboxes. This is sometimes used when IMAP4 is employed for Usenet message access. | | UNSUBSCRIBE | Mailbox name | Removes the mailbox from the active list. | | LIST | Mailbox name or reference string | Requests a partial list of available mailbox names, based on the parameter provided. | | LSUB | Mailbox name or reference string | The same as LIST but returns only names from the active list. | | STATUS | Mailbox name | Requests the status of the specified mailbox. The server responds providing information such as the number of messages in the box and the number of recently arrived and unseen messages. | | APPEND | Mailbox name, message, optional flags, and date/time | Adds a message to a mailbox. | ### Note *All of the commands in Table 78-4 may also be used in the Selected state; they should really be called Authenticated+Selected state commands*. When either the SELECT or EXAMINE command is successfully issued, the server will return to the client a set of useful information about the mailbox, which can be used to guide commands issued from the Selected state. This information includes the following three mandatory responses: **<*n*> EXISTS** Tells the client the number of messages in the mailbox. **<*n*> RECENT** Tells the client the number of recently arrived (new) messages. **FLAGS (<*flag-list*>)** Tells the client which flags are supported in the mailbox. These include the following: `\Seen`, `\Answered`, `\Flagged` (marked for special attention), `\Deleted`, `\Draft`, and `\Recent`. (The backslashes are part of the flag names.) The reply from the server may also contain these optional replies: **UNSEEN <*n*>** The message number of the first unseen message. **PERMANENTFLAGS (<*flag-list*>)** A list of flags (as for the FLAGS response above) that the client is allowed to change. **UIDNEXT <*n*>** The next unique identifier value. This is used to check for changes made to the mailbox since the client last accessed it. **UIDVALIDITY <*n*>** The unique identifier validity value, used to confirm valid UID values. ### Tip **KEY CONCEPT** In the Authenticated state, the IMAP client can perform operations on whole mailboxes, such as creating, renaming, or deleting mailboxes, or listing mailbox contents. The SELECT and EXAMINE commands are used to tell the IMAP server which mailbox the client wants to open for message-specific access. Successful execution of either command causes the server to provide the client with several pieces of important information about the mailbox, after which the session transitions to the Selected state. ## IMAP Selected State: Message Manipulation Process and Commands Once the IMAP client has been authorized to access the server, it enters the Authenticated state, where it is allowed to execute tasks on whole mailboxes. Since IMAP allows multiple mailboxes to be manipulated, message-specific commands cannot be used until the client tells the server which mailbox in wants to work with. Only one mailbox can be accessed at a time in a given session. After the SELECT or EXAMINE command is successfully issued, the session enters the Selected state. In this state, the full palette of message and mailbox commands is available to the client. This includes the message-specific commands in Table 78-5 as the mailbox commands defined for the Authenticated state. Most of IMAP's message-specific commands do not include a mailbox name as a parameters, since the server knows automatically that the commands apply to whatever mailbox was selected in the Authenticated state. The session remains in the Selected state for as long as the client continues to have work to do with the particular selected (or examined) mailbox. Three different actions can cause a transition out of the Selected state: * If the client has nothing more to do when it is done with the current mailbox, it can use the LOGOUT command to end the session. * The client can use the CLOSE command to tell the server it is finished with the current mailbox but keep the session active. The server will close the mailbox, and the session will go back to the Authenticated state. * The client can issue a new SELECT or EXAMINE command, which will implicitly close the current mailbox and then open the new one. The transition in this case is from the Selected state back to the Selected state, but with a new current mailbox. ### Selected State Commands Table 78-5 lists the message-specific commands that can be used only in the Selected state. Table 78-5. IMAP Selected State Commands | Command | Parameters | Description | | --- | --- | --- | | CHECK | None | Sets a checkpoint for the current mailbox. This is used to mark when a certain sequence of operations has been completed. | | CLOSE | None | Explicitly closes the current mailbox and returns the session to the Authenticated state. When this command is issued, the server will also implicitly perform an EXPUNGE operation on the mailbox. | | EXPUNGE | None | Permanently removes any messages that were flagged for deletion by the client. This is done automatically when a mailbox is closed. | | SEARCH | Search criteria and an optional character set specification | Searches the current mailbox for messages matching the specified search criteria. The server response lists the message numbers meeting the criteria. | | FETCH | Sequence of message numbers and a list of message data items (or a macro) | Retrieves information about a message or set of messages from the current mailbox. | | STORE | Sequence of message numbers, message data item name, and value | Stores a value for a particular message data item for a set of messages. | | COPY | Sequence of message numbers and a mailbox name | Copies the set of messages specified to the end of the specified mailbox. | | UID | Command name and arguments | Used to allow one of the other commands above to be performed using unique identifier numbers for specifying the messages to be operated on, rather than the usual message sequence numbers. | The list in Table 78-5 might seem surprisingly short. You might wonder, for example, where the specific commands are to read a message header or body, delete a message, mark a message as read, and so forth. The answer is that these (and much more) are all implemented as part of the powerful and flexible FETCH and STORE commands. The FETCH command can be used to read a number of specific elements from either one message or a sequence of messages. The list of message data items specifies what information is to be read. The data items that can be read include the headers of the message, the message body, flags that are set for the message, the date of the message, and much more. The FETCH command can even be used to retrieve part of a message, such as one body part of a MIME multipart message, making it very useful indeed. Special macros are also defined for convenience. For example, the client can specify the message data item FULL to get all the data associated with a message. The complement to FETCH, the STORE command, is used to make changes to a message. However, this command does not modify the basic message information such as the content of headers and the message body. Rather, it exists for changing the message's status flags. For example, after replying to a particular message, the client may set the `\Answered` flag for that message using the STORE command. Message deletion in IMAP is done in two stages for safety, as in POP and many other protocols. The client sets the `\Deleted` flag for whichever messages are to be removed, using the STORE command. The messages are deleted only when the mailbox is expunged, typically when it is closed. The search facility in IMAP4 is also surprisingly quite sophisticated, allowing the client to look for messages based on multiple criteria simultaneously. For example, with the appropriate syntax, you could search for "all posts that are flagged as having been answered that were sent by Jane Jones before April 1, 2004." Users of IMAP clients can thus easily locate specific messages even in very large mailboxes without needing to download and hunt through hundreds of messages. ### Tip **KEY CONCEPT** After the client opens a specific mailbox, the IMAP session enters the Selected state, where operations such as reading and copying individual email messages may be performed. The two most important commands used in this state are FETCH, which can be used to retrieve a whole message, part of a message, or only certain message headers or flags; and STORE, which sets a message's status information. IMAP also includes a powerful search facility, providing users with great flexibility in finding messages in a mailbox. When the client is finished working with a particular mailbox, it may choose a different one and reenter the Selected state, close the mailbox and return to the Authenticated state, or log out, automatically entering the Logout state. # TCP/IP Direct Server Email Access This final portion of the journey of a TCP/IP email message is usually the job of an email access and retrieval protocol like POP3 or IMAP4\. These are *customized* protocols, by which I mean that they were created specifically for the last step of the email communication process. However, there are also several *generic* methods by which an email client can gain access to a mailbox, without the use of a special protocol. These methods are all variations of the online email access model. They generally work by establishing *direct access* to the server where the mailbox is located. The mailbox itself is just a file on a server somewhere, so if that file can be made available, it can be viewed and manipulated like any other file using an email client program that reads and writes the mailbox file. The following are some of the ways in which this can be done: **Using the SMTP Server Directly** The simplest method for gaining access to the mailbox is to log on to the server itself. This is not an option for most people, and even in years gone by, it was not often done, for security and other reasons. However, some people do run their own SMTP servers, giving them considerable control over access to their email. **File Sharing Access** Using a protocol such as NFS, it is possible to have a mailbox mounted on a user's client machine where it can be accessed as if it were a local file. The mail is still on the server and not the client machine, but the communication between the client and the server occurs transparently to both the user and the email client software. **Dial-Up Remote Server Access** A user on a client machine dials up a server where her mailbox is located and logs in to it. The user then can issue commands to access mail on that server as if she were logged in to it directly. **Telnet Remote Server Access** Instead of dialing in to the server, a user can connect to it for remote access using the Telnet Protocol. These techniques are much more commonly associated with timesharing systems, which commonly use the UNIX family of operating systems more than others. They are also often combined; for example, remote access is often provided for UNIX users, but most companies don't want users logging in directly to the SMTP server. Instead, an ISP might run an SMTP server on one machine called *mail.companyname.com* and also operate a different server that is designed for client access called *users.companyname.com*. A user could access email by dialing into the users machine, which would employ NFS to access user mailboxes on the mail machine. Direct server access is a method that has been around for decades. At one time, this was how the majority of people accessed email, for two main reasons. First, if you go back far enough, protocols like POP or IMAP had not yet been developed; the TCP/IP email system as a whole predates them by many years, and direct access was the only option back then. Second, the general way that email and networks were used years ago was different from what it is today. Most individuals did not have PCs at home, and no Internet as we know it existed. Remotely accessing a UNIX server using a modem or Telnet for email and other services was just the way it was done. I got started using direct server access for email more than ten years ago, and I still use it today. I Telnet in to a client machine and use a UNIX email program called `elm` to access and manipulate my mailbox. To me, this provides numerous advantages: * Most important, I can access my email using Telnet from any machine on the Internet, anywhere around the world. * Since I am logged in directly, I get immediate notification when new mail arrives, without needing to check routinely for new mail. * My mailbox is always accessible, and all my mail is always on a secure server in a professionally managed data center. * I have complete control over my mailbox and can edit it, split it into folders, write custom spam filters, or do anything else I need to do. This probably sounds good, but most people today do not use direct server access because of the disadvantages of this method. One big issue is that you must be logged in to the Internet to access your email. Another one, perhaps even larger, is the need to be familiar with UNIX and a UNIX email program. UNIX is simply not as user-friendly as a graphical operating systems such as Windows or the Mac. For example, my UNIX email program doesn't support color and cannot show me attached graphic images. I must extract images and other files from MIME messages and transfer them to my own PC for viewing. Most ordinary computer users today don't know UNIX and don't want to know it. They are much happier using a fancy graphical email program based on POP3 or IMAP4\. However, a number of us old UNIX dinosaurs are still around and believe the benefits of direct access outweigh the drawbacks. (Oh, one other benefit that I forgot to mention is that it's very hard to get a computer virus in email when you use UNIX!) ### Tip **KEY CONCEPT** Instead of using a dedicated protocol like POP3 or IMAP4 to retrieve mail, on some systems it is possible for a user to have direct server access to email. This is most commonly done on UNIX systems, where protocols like Telnet or NFS can give a user shared access to mailboxes on a server. This is the oldest method of email access. It provides the user with the most control over his mailbox and is well suited to those who must access mail from many locations. The main drawback is that it means the user must be on the Internet to read email, and it also usually requires familiarity with the UNIX operating system, which few people use today. # TCP/IP World Wide Web Email Access Most email users like the advantages of online access, especially the ability to read mail from a variety of different machines. What they don't care for is direct server access using protocols like Telnet, UNIX, and nonintuitive, character-based email programs. They want online access, but they want it to be simple and easy to use. In the 1990s, the World Wide Web was developed and grew in popularity very rapidly, due in large part to its ease of use. Millions of people became accustomed to firing up a web browser to perform a variety of tasks, to the point at which using the Web has become almost second nature. It didn't take very long before someone figured out that using the Web would be a natural way of providing easy access to email on a server. This technique is straightforward. It exploits the flexibility of the Hypertext Transfer Protocol (HTTP) to tunnel email from a mailbox server to the client. A web browser (client) is opened and given a URL for a special web server document that accesses the user's mailbox. The web server reads information from the mailbox and sends it to the web browser, where it is displayed to the user. This method uses the online access model like direct server access, because requests must be sent to the web server, and this requires the user to be online. The mail also remains on the server, as when NFS or Telnet are used. The big difference between Web-based mail and the UNIX methods is that the former is much easier for nonexperts to use. Since the idea was first developed, many companies have jumped on the Web-mail bandwagon, and the number of people using this technique has exploded into the millions in just a few years. Many free services even popped up in the late 1990s as part of the dot-com bubble, allowing any Internet user to send and receive email using the Web at no charge (except perhaps for tolerating advertising). Many ISPs now offer Web access as an option in additional to conventional POP/IMAP access, which is useful for those who travel. There are drawbacks to the technique, however, which as you might imagine are directly related to its advantages. Web-based mail is easy to use, but inflexible; the user does not have direct access to her mailbox and can use only whatever features the provider's website implements. For example, suppose the user wants to search for a particular string in her mailbox; this requires that the Web interface provide this function. If it doesn't, the user is out of luck. Web-based mail also has a disadvantage that is an issue for some people: performance. Using conventional UNIX direct access, it is quick and easy to read through a mailbox; the same is true of access using POP3, once the mail is downloaded. In contrast, Web-based mail services mean each request requires another HTTP request/response cycle. The fact that many Web-based services are free often means server overload that exacerbates the speed issue. Note that when Web-based mail is combined with other methods such as POP3, care must be taken to avoid strange results. If the Web interface doesn't provide all the features of the conventional email client, certain changes made by the client may not show up when Web-based access is used. Also, mail retrieval using POP3 by default removes the mail from the server. If you use POP3 to read your mailbox and then later try to use the Web to access those messages from elsewhere, you will find that the mail is gone—it's on the client machine where you used the POP3 client. Many email client programs now allow you to specify that you want the mail left on the server after retrieving it using POP3. ### Tip **KEY CONCEPT** In the past few years, a new method has been developed to allow email access using the World Wide Web. This technique is rapidly growing in popularity, because it provides many of the benefits of direct server access, such as the ability to receive email anywhere around the world, while being much simpler and easier than the older methods of direct access such as making a Telnet connection to a server. In some cases, Web-based email can be used in combination with other methods or protocols, such as POP3, giving users great flexibility in how they read their mail.

第三部分-8. TCP/IP 万维网和超文本传输协议 (HTTP)

第七十九章

第八十章

第八十一章

第八十二章

第八十三章

第八十四章

在我对 第七十一章 中文件和消息传输协议的概述中,我说万维网“几乎肯定”是最重要的 TCP/IP 应用。如果有什么不同的话,我可能还低估了情况。万维网不仅非常明显是今天最重要的 TCP/IP 应用,它可以说是网络历史上最重要的单一应用,甚至可能是整个计算领域最重要的应用。

这可能听起来有些夸张,但考虑一下万维网在存在十年左右的时间里所做的事情。它不仅改变了互联网的使用方式,而且在许多方面也改变了社会本身。可以说,万维网将互联网推上了地图,将其从技术人员和学者的领域转移到了主流世界。

本部分包含六个章节,描述了万维网以及至关重要的 超文本传输协议 (HTTP),这是使万维网运行工作的 TCP/IP 应用层协议。第一章从一般意义上讨论了万维网以及超文本和超文本文档背后的概念。第二章概述了 HTTP 并以一般性描述其操作,重点关注连接的建立和维护。第三章概述了 HTTP 消息及其格式化方式,并描述了 HTTP 方法(命令)和状态码。第四章详细介绍了许多 HTTP 头部,这些头部至关重要,因为它们是 HTTP 服务器和客户端之间信息传递的主要方式。第五章提供了关于资源(称为 实体)在 HTTP 中编码和传输的信息。第六章和最后一章探讨了现代 HTTP 协议的特殊功能和能力。

就像许多 TCP/IP 协议一样,当 HTTP 被设计时,其创造者借鉴了其他应用协议的元素。在这种情况下,HTTP 使用了电子邮件中的某些元素,特别是多用途互联网邮件扩展(MIME)。在阅读这部分内容之前,我建议您熟悉 RFC 822 电子邮件消息格式和 MIME,特别是 MIME 头和媒体类型(这两个主题在第七十六章中都有涉及)。HTTP 与 MIME 之间的关系在第八十三章中有更全面的讨论,该章节讨论了 HTTP 实体和媒体类型。

第七十九章。万维网和超文本概述与概念

无标题图片

万维网(简称 Web)扩展了消息的概念,超越了简单文本文件传输的电子邮箱(email)、文件传输协议(FTP)和 Usenet 的界限。它的力量在于其结合了超文本,这是一个允许相关文档相互链接的系统,其丰富的文档格式不仅支持文本,还支持图形和多媒体,以及允许这些媒体高效传输的特殊协议。结果是,一个一旦推出就几乎立即被从大型公司用户到个人在内的所有人所接受的强大系统。在短短几年内,Web 就占据了互联网上所有其他应用的主导地位。

在本章中,我以高层次的视角概述了构成万维网的概念。我首先简要介绍了万维网和超文本的概述和历史,并讨论了构成万维网系统的组件。我简要描述了在万维网上使用的文档和媒体,并解释了超文本标记语言(HTML)的重要性。最后,我概述了在万维网上使用统一资源定位符(URL)对文档进行寻址的方法。

万维网和超文本概述与历史

万维网是互联网消息应用类别中的一员。但不知何故,它在我眼中并不像是一个消息传输协议。这让我想弄清楚,万维网有什么特别之处,使得它以一种先前任何消息应用都没有的方式变得流行?

对于这个问题,没有一个真正准确的单一词回答。然而,如果无论如何我都必须给出一个答案,那将是这个:超文本。当然,像电子邮件和 Usenet 这样的应用允许用户发送和接收信息,而 FTP 则允许用户访问服务器上的文件集。但这些方法缺乏任何易于表示文档之间关系的方法,或者提供一种从一份文档移动到另一份文档的方式。高度简化地说,超文本正是这样做的:它允许文档的创建者包含指向相关信息的链接,无论是该文档的其它部分还是其他文档。有了适当的软件,用户可以轻松地在不同位置之间移动。那么这为什么是个大问题呢?事实上,这比最初看起来更重要。

如果没有某种方式将文档链接在一起,它们将保持未连接的孤岛状态。在某种程度上,超文本链接的文档与未链接的文档的关系,就像联网的计算机与未联网的计算机的关系一样。

超文本的历史

超文本背后的思想实际上远早于互联网甚至电子计算机。范内瓦·布什(1890-1974)通常被归功于他在 1945 年描述一个名为Memex的理论装置时引入了这个想法,该装置旨在用于存储和检索文档。他描述了轨迹的概念,它将相关联的信息链接起来,以便更容易地组织和访问设备中的信息。

布什的思想被后续几位研究人员作为工作的基础。其中之一是特德·纳尔逊,他提出了超文本这个术语,并在 1960 年首次描述了一个名为Xanadu的系统,该系统被认为是原始的超文本软件模型之一。

互联网本身的历史可以追溯到 1989 年的欧洲核子研究中心(CERN),位于日内瓦。该缩写代表Conseil Européen pour la Recherche Nucléaire,即该组织的法语名称。CERN 进行的项目大多规模庞大且复杂,需要多年才能完成。它们还涉及许多必须共同工作和共享相关文档的科学家。

欧洲核子研究中心(CERN)的研究员蒂姆·伯纳斯-李提出了创建一个“网络”的电子链接文档的想法。快速增长的互联网显然是这个项目的明显渠道。他在 1990 年设计了 TCP/IP 的最初(非常粗糙和简单)版本的 HTTP。他还负责开发或共同开发 Web 背后的其他一些关键概念和组件,例如统一资源标识符(URIs)和 HTML。

将文档和文件链接起来的能力具有巨大的吸引力,创意人士很快就发现了这种新技术的大量用途。20 世纪 90 年代初,开发活动迅速展开。Web 服务器和客户端软件得到了开发和完善,1993 年,国家超级计算应用中心(NCSA)创建了第一个图形化 Web 浏览器Mosaic。(该程序的开发者马克·安德森最终成立了网景通信公司。)

一旦万维网开始形成,它就迅速发展。事实上,如果将万维网的增长称为其他任何非爆炸性的东西,那都不足以描述其真实情况。1993 年初,只有 50 个活跃的 HTTP Web 服务器。到 1993 年底,服务器数量超过 1000 个。到 1995 年底,每天都有成千上万的新的网站上线,HTTP 请求和响应已经超过了所有其他 TCP/IP 应用流量。到本世纪末,数百万个网站和超过十亿份文档可在互联网上获取。

今天的万维网

虽然互联网规模的快速增长令人惊叹,但更令人着迷的是其范围的扩展。既然你在阅读一本关于网络的书,你很可能是一个熟悉今天互联网上可以找到的令人难以置信的各种类型信息的 Web 用户。早期的超文本系统仅基于文本文档的使用;今天,互联网是一个包含图片、声音和电影等多种媒体的全球世界。在许多情况下,超文本这一术语已被更通用的超媒体所取代——在功能上,如果不是在官方上。

互联网已经超越了提供简单文档检索的功能,提供了各种各样的服务。一个网站可以提供不仅仅是文档的服务,使用户能够运行成千上万种程序,从购物到在线播放音乐或游戏。网站也在模糊不同类型应用之间的界限,提供基于 Web 的电子邮件、基于 Web 的 Usenet 访问、公告板以及其他用于讨论的互动论坛。

互联网对网络和社会整体的影响,即使是其最热情的早期粉丝也未曾预料到。事实上,互联网的终极“杀手级应用”就是万维网。在 20 世纪 90 年代初,大公司把互联网视为一种有趣的奇观;到本世纪末,对许多人来说,它已经成为一种商业必需品。数百万个人和家庭发现了他们指尖上的信息财富,互联网接入对许多人来说成为另一种必需的公用事业,就像电话服务一样。事实上,互联网流量的大幅增加催生了数十亿美元用于互联网基础设施的投资。

21 世纪初的互联网泡沫破灭削弱了互联网的势头。互联网的惊人增长无法以原来的速度继续,并且已经有所放缓。但总体而言,互联网仍在持续扩展和成熟,它很可能会在相当长一段时间内成为互联网上最重要的信息和资源。

提示

关键概念 万维网(Web 或 WWW)始于 1989 年,是一个旨在促进文档之间关系表示和研究人员之间信息共享的项目。使万维网如此强大的主要特征是超文本,它允许从一个文档链接到另一个文档。万维网的许多好处使得它仅在短短几年内从一个小型应用发展到世界上最大、也许是最重要的网络应用。它主要负责将互联网带入社会的主流。

万维网系统概念和组件

超文本是使万维网不仅仅是一个消息传输系统的核心概念。然而,超文本背后的想法在万维网出现之前就已经存在了几十年,以及基于该想法的某些软件产品。显然,一个想法要发展成为成功的系统,需要的不仅仅是概念。

互联网之所以成为现象,是因为它将超文本的基本思想与几个其他概念和技术相结合,创造了一个丰富、全面的交互式通信机制。这个系统今天包含了如此多的不同概念和软件元素,并且与其他技术如此集成,以至于很难找到两个对互联网究竟包含什么以及哪些部分最为关键达成共识的人。

例如,不可否认,互联网成功的关键之一是 TCP/IP 互联网互连协议套件与连接全世界计算机的互联网基础设施的结合。那么,互联网是否是互联网的必要组成部分呢?在许多方面,是的;实际上,由于互联网今天如此受欢迎,人们常常将互联网称为互联网。当然,我们知道这并不是精确的术语使用,但它显示了互联网变得多么重要,以及它与互联网的紧密联系。

万维网的主要功能组件

虽然互联网和 TCP/IP 显然是互联网成功的重要部分,但它们本质上是通用的。当具体定义万维网系统本身时,通常认为有三个特定的组件最为关键(参见图 79-1):

超文本标记语言 HTML 是一种用于定义超文本文档的文本语言。HTML 背后的想法是向常规文本文档中添加简单的结构,称为标签,以便将一个文档链接到另一个文档,并允许特殊数据格式化以及不同类型媒体的组合。HTML 已经成为实现超文本信息的标准语言,并催生了众多相关语言的创建。

超文本传输协议 HTTP 是 TCP/IP 应用层协议,通过实现客户端和服务器之间超文本文档和其他文件的传输来实施网络。HTTP 最初是一种非常原始的协议,用于在计算机之间传输 HTML 文档,并且它已经发展成为一个功能齐全且复杂的消息协议。它支持多种不同类型文档的传输,连接上的多个文件的流式传输,以及包括缓存、代理和认证在内的各种高级功能。

统一资源标识符 URIs 用于定义标识因特网上资源的标签,以便它们可以轻松找到和引用。URIs 最初是为了提供一种方式,让网络用户能够定位超文本文档,以便检索它们。尽管 URIs 并非特定于网络,但它们通常与网络和 HTTP 相关联。

万维网的主要功能组件

图 79-1. 万维网的主要功能组件

注意

统一资源定位符(URLs)实际上是统一资源标识符(URIs)的一个子集。在万维网讨论中,这两个术语经常被互换使用

这三个组件都是在同一时间创建和开发的,并且综合起来代表了定义网络的关键技术。在本章中,我将描述 HTML 以及在网络环境中 URI 的使用。HTTP 实际上是网络的中心,并在本书本部分的剩余五章中进行介绍。

网络服务器和网络浏览器

这三个主要的网络组件由许多其他元素补充,这些元素在完善整个系统方面发挥着辅助作用。其中最重要的是用于实现客户端/服务器通信的硬件和软件,这使得网络能够工作,也如图图 79-1 所示:网络服务器网络浏览器

网络服务器是运行特殊服务器软件的计算机,这使得它们能够向请求它们的客户端提供超文本文档和其他文件。现在,全世界有成千上万的此类机器作为网络所代表的巨大信息财富的虚拟分布式存储库。

网络浏览器是在 TCP/IP 客户端计算机上运行的 HTTP 客户端软件程序,用于访问网络服务器上的网络文档。这些浏览器程序检索超文本文档并显示它们,并且它们还实现了许多网络的先进功能,如缓存。今天的浏览器支持广泛的媒体,使网络能够实现许多不同的功能,除了超文本文档传输之外。例如,显示图像、播放声音和实现交互式程序。

最后,但同样重要的是,用户是万维网最重要的组成部分。用户参与在塑造网络技术发展方面发挥了比任何其他网络应用更大的作用。万维网最初是一种简单的交换文档的手段;如今,它已经发展到包括数千种不同的应用和服务,这主要归功于其用户的创造力。内容提供商通过创造新的信息和服务的想法来推动万维网所能做到的边界,以满足终端用户群体的无尽需求。

小贴士

关键概念 万维网是一个由许多相关组件组成的完整系统,其中三个是最基本的。超文本标记语言(HTML)描述了超文本文档是如何构建的。HTML 允许在文档之间表示链接。超文本传输协议(HTTP)是在网络上移动超文本和其他文档的应用层协议。统一资源标识符(URI)机制提供了一种一致的方法来标识资源,无论是在万维网上还是在更广泛的互联网上。

万维网媒体和超文本标记语言

我已经说过,网络是基于中心概念超文本的。前缀hyper通常意味着在之上或超越,因此超文本就像文本,但在功能上超越了它。用超文本编写的文档与常规文本文件类似,但包括实现超文本功能的信息。这些通常被称为超文本文档超文本文件

超文本文档中的额外信息用于告诉显示文件的计算机程序如何格式化它。这些信息以特殊指令的形式出现,穿插在文档的实际文本中,这些指令是根据定义语言的语法编写的。这种向文档内容添加额外元素的行为通常被称为标记文档

HTML 概述

HTML 是万维网的三个主要系统组件之一,由万维网的创造者蒂姆·伯纳斯-李于 1990 年发明。它不是在真空中创造的;相反,它是 ISO 标准 8879:1986 中描述的通用标记语言概念的特定应用——标准通用标记语言(SGML)

标记语言定义了特殊的项目,为显示文档的软件提供有关如何展示的信息。在超文本的目的上,文档中最基本的信息类型是特殊的指令,指定如何将一个文档链接到另一个文档——毕竟,链接过程是超文本的定义属性。

然而,HTML 的功能远不止于此;它定义了一套完整的文本代码,用于描述文档如何向用户展示的几乎所有方面。这包括格式化文本的指令(例如定义其颜色、大小和对齐方式)、交互式表单、显示表格数据的方法、如何展示图像和其他媒体与文档一起的规范,以及更多。理论上,这种语言只应该定义文档,而将如何展示留给浏览器,但在实践中,现代 HTML 文档通常也包含相当具体的指令,说明它们的信息应该如何展示。

要公正地对待 HTML,我可能需要为这个主题写上几十页。我决定不这样做,因为尽管 HTML 是网络的一个重要部分,但在理解网络如何工作方面,它实际上并不是那么重要。如果你在编写网络内容,了解 HTML 是必不可少的,如果你想要了解如何编写网络软件,它也是至关重要的。然而,具有讽刺意味的是,对于使网络工作的实际机制,如 HTTP,文档就是文档。HTTP 并不是在假设它会传输 HTML 的情况下设计的,在大多数情况下,服务器甚至不会查看 HTML 文件的内容——它们只是传输它。

话虽如此,对 HTML 的基本理解很重要,而且似乎不提供至少对该语言的概述是不合适的,所以我将在这里这样做。我鼓励你寻找许多优秀的 HTML 资源之一,如果你想要了解更多——你可以在网上找到成百上千的资源(还能在哪里?)。

HTML 元素和标签

简而言之,HTML 文档是一个普通的 ASCII 文本文件,就像一封电子邮件或其他文本文件。HTML 与普通文本的最大区别在于 HTML 文档是结构化的;也就是说,文档逻辑上组织成一系列元素,这些元素按照语言的规则排列。每个元素定义了文档整体的一部分。文档的标题、段落、表格以及指向另一个文档的超链接都是元素的例子。

每个元素都使用特殊的文本标签来描述,这些标签遵循特定的语法。每个标签以<符号开始,然后是(不区分大小写)元素名称,以及可选的描述元素的参数。标签以>符号结束。一般来说,标签看起来是这样的:

<element parameter1="value1" parameter2="value2". . .>

一些元素完全由标签的存在来描述,在这种情况下,该标签就是整个元素。更常见的是,标签成对出现,包围着元素的真正内容;开始标签以元素名称开头,结束标签以一个斜杠符号开头,后跟元素名称。例如,文档的标题是一个可以定义为以下内容的元素:

<title>This Is A Great Story</title>

每个元素的 内容可以包含其他元素,这导致标签在彼此之间嵌套。例如,如果我们想通过将单词 Great 以粗体字母的形式显示来突出显示标题中的该词,我们可以添加以下 <b> 标签:

<title>This Is A <b>Great</b> Story</title>

每个完整的 HTML 文档都定义为单个名为 html 的元素;整个文档被 <html></html> 标签包围。在这个元素内部,文档被分为两个标准子元素,每个文档都必须包含这些子元素:headbody。文档的 head 包含描述文档及其处理方式的信息;它最常见地包含文档的标题。body 包含文档的实际内容。这三个元素定义了基本的 HTML 文档结构,如下所示:

<html>
<head>
(head elements go here...)
</head>
<body>
(body elements go here...)
</body>
</html>

文档的大部分内容由放置在 <body></body> 标签之间的主体元素组成。HTML 文档可以从非常简单的只包含文本段落和几个链接的简单主体,到由计算机生成且包含数百甚至数千个嵌套标签的复杂文档。

常见 HTML 元素

表 79-1 提供了一些在 HTML 消息主体中常用元素及其定义的标签的简要描述,以帮助您了解该语言的工作方式。

表 79-1. 常见 HTML 元素

元素 示例元素和标签 描述
段落
<p>Jack and Jill went up the hill to
fetch a pail of water...</p>
标记一段文本。请注意,从开始标签到结束标签之间的所有内容都将被视为一个段落,即使它们被分成多行,就像我在这里所做的那样。在 HTML 格式化中,换行符并不重要;只有标签被识别。
换行
George W. Bush<br>
The White House<br>
1600 Pennsylvania Ave., NW<br>
Washington, DC 20500
强制换行。用于将行紧密排列,例如地址。
标题
<h1>First Topic</h1>
<h2>Subtopic</h2>
定义文档中的部分标题,以便在长文档中以分层形式显示信息。定义了六组标签,从 <h1></h1><h6></h6>。浏览器会自动以更突出的方式显示高级标题,例如使用更大的字体、下划线文本或类似处理。
列表
<p>Shopping list:
<ul>
<li>Milk
<li>Eggs
<li>Sushi
</ul>
</p>
允许以列表的形式呈现信息。标签 <ul> 表示无序列表,导致列表项通常以项目符号显示。另可使用 <ol>(有序列表)来显示前面带有 1、2、3 等的项。
水平线
...end of this part of the story.</p>
<hr size= "3">
<p>Start of next part of story...
在页面上绘制一条水平线;size 参数控制其厚度。用于在文档中分隔逻辑部分。
图片
<img src="companylogo.gif" alt="XYZ
Industries Logo" align="center">
在文本的适当部分显示内联图像。src 参数是图像的相对或绝对 URL,可以包含多个其他参数来定义图像的对齐方式、大小、如果浏览器是非图形的则显示的替代文本(如这里所示,使用 alt 参数),以及更多。
链接
<a href="http://
www.PCGuide.com">Click here to visit
The PC Guide</a>
指向另一个文档的超链接。标签中的 a 代表锚点,这是超链接的正式名称。href 参数指定链接的 URL。大多数浏览器会在开始和结束标签之间的文本下划线或以其他方式突出显示,以清楚地表明该文本代表超链接。也可以通过结合 <img><a> 标签来给图像创建超链接。
书签
<a name="Step4">Step 4: Remove paint
using scrubbing tool.</a>
创建一个书签,可以用来指向文档中的特定部分。例如,如果这个示例中的书签在一个 URL 为 www.homefixitup.com/repainting.htm 的文档中,那么 URL www.homefixitup.com/repainting.htm#Step4 就指向文档中的这个特定位置。有关更多详细信息,请参阅本章后面的 URL 讨论部分。
表格
<table>
<tr>
<td>1st row, 1st column.</td>
<td>1st row, 2nd column.</td>
</tr>
<tr>
<td>2nd row, 1st column.</td>
<td>2nd row, 2nd column.</td>
</tr>
</table>
以表格形式显示信息。每个 <tr></tr> 标签集定义表格的一行;在每一行中,每个 <td></td> 对定义一个表格数据元素。可以为这些标签中的每一个提供多个不同的参数来控制表格的大小和外观。
表格形式
<form method="POST" action="https://
www.myfavesite.com/order.php">
<input type="hidden" name="PRODUCT"
value="widget">
<input type="text" name="QUANTITY"
size="3">
<input type="submit" value="Click
Here to Proceed to the Secure
Processing Site">
</form>
定义一个 HTML 表单,允许客户端向处理表单的网站上的程序提交各种类型的信息。表单由描述提交按钮按下时要采取的操作的初始 <form> 标签组成,以及其他表单项,如预定义变量、文本输入字段和按钮。这里展示了这些项的每个示例。
脚本
<script language=javascript>
(JavaScript code)
</script>
允许在 HTML 文档中包含脚本语言的指令。它最常用于 JavaScript。

常见文本格式化标签

在文档中格式化文本外观的标签有很多,这里列出了一些更常见的标签:

<b>文本</b> 以粗体形式呈现包含的文本。

<i>文本</i> 以斜体形式呈现包含的文本。

<u>文本</u> 以下划线呈现包含的文本。

<font (参数)>文本</font> 使用指定的字体类型、大小或颜色来呈现包含的文本。

这只是冰山一角,当涉及到 HTML 时。如果你不熟悉 HTML,然而,了解这些基本标签应该有助于你解释基本的 HTML 文档并学习 HTTP 的工作原理。

提示

关键概念 互联网超文本文档使用的语言称为 HTML。HTML 文档类似于 ASCII 文本文件,但它们使用 HTML 元素的特殊结构来排列,这些元素定义了文档的不同部分以及它们应该如何显示给用户。每个元素都使用特殊的文本标签来描述,这些标签定义了它及其特征。

万维网寻址:HTTP 统一资源定位符

超文本之所以强大且有用,主要原因是它允许相关文档相互链接。在万维网的情况下,这是通过一组特殊的 HTML 标签来实现的,这些标签在一篇文档中指定了另一篇与之在某些重要方面相关的文档的名称。用户可以通过简单的鼠标点击从一个文档跳转到另一个文档。万维网在很大程度上是基于这种简单而优雅的引用方法而成功的。

超链接的概念对万维网文档和其他资源的寻址方式有重要影响。尽管万维网本质上是一种类似于 FTP 的消息传输协议,但需要能够定义超链接意味着必须放弃传统的 FTP 模型,即使用一系列命令来指定如何检索资源。相反,需要一个系统,通过一个简单紧凑的字符串可以唯一地指定资源。

这种需求的结果是定义了万维网三个主要元素之一:URI。URI 分为两类:统一资源定位符(URLs)统一资源名称(URNs)。虽然 URI、URL 和 URN 起源于万维网的发展,但现在它们已经被推广,为各种 TCP/IP 应用层协议提供寻址机制。它们在第七十章中进行了详细描述。在这里,我们将探讨它们在万维网中具体是如何使用的。

目前,万维网几乎完全使用 URLs;URNs 仍在开发中。万维网 URL 指定了使用 HTTP 进行资源检索,因此通常被称为HTTP URLs。这些 URL 允许通过指定资源所在的主机名、目录路径和文件名来唯一地寻址资源,如文档、图形图像或多媒体文件。

小贴士

关键概念 统一资源标识符(URIs)的开发是为了使万维网资源能够轻松且一致地被识别;它们现在也被用于其他协议和应用。目前万维网上使用的 URI 类型是统一资源定位符(URL),它标识了使用 HTTP 来检索资源,并提供了关于资源的位置和检索方式的信息。

HTTP URL 语法

HTTP URL 可以是绝对路径或相对路径(有关它们之间的区别,请参阅第七十章")中的“URL 相对语法和基本 URL”)。绝对路径通常用于从一个网站链接到另一个网站,或者用户在没有任何先前上下文的情况下请求新文档。绝对 HTTP URL 基于以下常见的互联网 URL 语法:

<scheme>://<user>:<password>@<host>:<port>/<urlpath>;<params>?<query>#<fragment>

对于 Web,方案是 http:,不同 URL 元素的语义被定义为与 Web 相关的含义。HTTP URL 的一般结构如下所示:

http://<user>:<password>@<host>:<port>/<url-path>?<query>#<bookmark>

这些句法元素被专门定义为 HTTP 绝对 URL 如下:

<用户> 和 <密码> 可选的认证信息,用于位于受密码保护的服务器上的资源。这种结构在实际应用中很少使用,因此大多数人没有意识到这是一个选项。因此,它成为了骗子们用来隐藏不良 URL 的目标。

<主机> 存放资源的 Web 服务器的主机名。这通常是一个完全合格的域名系统 (DNS) 域名,但它也可能是一个 IP 地址。

<端口> 用于连接到 Web 服务器的 TCP 端口号。对于 HTTP,默认端口是 80,通常省略。在罕见的情况下,您可能会看到使用其他端口号的情况,有时是为了在同一 IP 地址上允许两个用于不同用途的 Web 服务器软件副本。端口 8080 特别常见作为替代方案。

<url-path> 使用 HTTP 获取特定资源的路径。这通常是一个完整的目录路径,表示从根目录到资源所在位置的目录序列,然后是资源名称。重要的是要记住,路径是区分大小写的,尽管 DNS 域名不是。

<查询> 可选的查询或其他要传递给 Web 服务器的信息。此功能通常用于实现交互式功能,因为查询值可以由用户指定,然后从 Web 浏览器传递到 Web 服务器。另一种方法是使用 HTTP POST 方法。

<书签> 识别 HTML 文档中的特定位置。这在非常大的 HTML 文档中很常见,允许用户点击超链接并滚动到文档中的特定位置。请参阅表 79-1 末尾的示例。

虽然 Web 的 URL 语法相当丰富且可能复杂,但大多数 Web URL 实际上相当简短。这些组件中的绝大多数都被省略了,特别是用户、密码、端口和书签元素。查询仅用于特殊目的。这留下了您通常遇到的更简化的 URL 形式:

http://<*`host`*>/<*`url-path`*>

资源路径和目录列表

用来引用特定文档的<url-path>也可以省略。这为用户提供了一个方便的方法,可以在不知道要请求哪个特定文档的情况下查看网站提供的内容。例如,想要查看 CNN 当前头条新闻的用户会访问www.cnn.com。在这种情况下,请求被发送到 Web 服务器上的空文档(由/表示,如果未指定则隐含;技术上,你应该指定www.cnn.com/)。

如何处理/请求取决于服务器。技术上,这样的请求实际上是在询问服务器:“请显示服务器根目录的内容。”然而,这既不美观(文件名列表不是留下最佳第一印象的方式)也潜在存在安全风险(因为任何人都可以看到服务器上每个文件的名称)。因此,大多数 HTTP 服务器都设置为自动识别此类请求并返回默认文档,通常命名为 index.html 或 default.html。许多服务器在 URL 中指定任何其他目录时也会返回某种类型的默认文档;例如,在 Web 浏览器的 URL 地址栏中键入www.pcguide.com/ref实际上返回www.pcguide.com/ref/index.htm

注意

虽然从技术上讲,在 HTTP URL 中省略 http://是不正确的,但大多数 Web 浏览器如果省略了它,会自动添加。因此,许多 Web 用户习惯于输入仅包含主机名的 URL,例如www.tcpipguide.com

这里显示的格式适用于绝对 HTTP URL。URL 也可以是相对的,这在紧密相关的文档之间是常见的,例如与文档一起的图形,或者在一组或项目中的文档之间。在这种情况下,通常只指定 URL 路径的一部分。这将在第七十章中详细描述。

第八十章。HTTP 一般操作和连接

无标题图片

超文本传输协议(HTTP)最初是一个非常基础的协议,设计用来做一件事:允许客户端发送一个简单的请求来获取超文本文件,并从服务器接收它。现代 HTTP 在本质上仍然是一个简单的请求/回复协议,但现在包括了众多新特性和功能,以支持不断增长的万维网(Web)规模以及人们不断发现的新用途。因此,解释 HTTP 的最佳起点是查看其整体操作以及 Web 服务器和 Web 客户端之间通信的方式。

在本章中,我通过描述其一般操作来介绍 HTTP。我首先概述了 HTTP,讨论了其版本和定义它们的规范。然后,我讨论了其操作模型,这对于理解 HTTP 的工作方式非常重要。我解释了 HTTP 客户端和服务器之间支持的两个类型的连接,以及如何在当前版本的 HTTP(HTTP/1.1)中通过流水线请求。然后,我提供了更多关于如何在 HTTP/1.1 中建立、管理和终止持久连接的信息。

HTTP 版本和标准

万维网起源于瑞士研究机构欧洲核子研究组织 CERN 的一个研究项目。该项目的首要目标是允许超文本文档通过电子方式相互链接,因此在一个文档中选择一个引用到第二个文档会导致引用文档被检索。为了实现这个系统,研究人员需要某种机制来允许客户端计算机告诉服务器发送它一个文档。为了填补这个功能,早期的网络开发者创建了一个新的 TCP/IP 应用层协议:超文本传输协议(HTTP)

这个第一个版本现在被称为 HTTP/0.9。随后的版本是 HTTP/1.0 和 HTTP/1.1。

HTTP/0.9

原始的 HTTP 版本仅用于传输超文本文档,并且设计得非常简单,以便更容易实现新兴的 Web。这个早期的 HTTP 规定,HTTP 客户端使用传输控制协议(TCP)与 HTTP 服务器建立连接。然后客户端发出一个 GET 请求,指定要检索的资源。服务器通过发送文本字节流作为文件来响应,然后断开连接。定义这个版本 HTTP 的整个文档只有几页长!

这个 HTTP 的第一个版本在功能上是可行的,但在其能力上极为有限。它不支持传输除超文本之外的其他类型的数据,并且没有提供任何机制来实现客户端和服务器之间的任何智能通信。这个早期的 HTTP 原型无法为 Web 的未来数据传输提供基础。它从未成为官方的 RFC 标准,实际上甚至没有正式的版本号;它今天被称为 HTTP 版本 0.9,或 HTTP/0.9,使用 HTTP 版本格式。我相信这个数字没有特别的意义,除了比协议的第一个官方版本号小一点。

HTTP/1.0

HTTP/0.9 的功能框架为 1990 年代初 HTTP 的快速演变奠定了基础。随着网络的规模和接受度的增长,许多新想法和功能被纳入 HTTP。大量开发工作的结果是第一个 HTTP 标准的正式化:版本 1.0。这个增强后的 HTTP 标准于 1996 年 5 月作为 RFC 1945 发布,即“超文本传输协议——HTTP/1.0”。然而,在正式发布日期之前,它已经使用了几年。

HTTP/1.0 将 HTTP 从一个简单的请求/响应应用程序转变为一个真正的消息协议。它描述了 HTTP 的完整消息格式,并解释了它应该如何用于客户端请求和服务器响应。HTTP/1.0 最重要的变化之一是将协议泛化以处理多种不同类型的媒体,而不是严格限于超文本文档。为了拓宽 HTTP 的范围,其开发者从为电子邮件定义的多用途互联网邮件扩展(MIME)标准中借鉴了概念和头部结构(在第七十六章中讨论)。与此同时,它定义了更强大的网页服务器和客户端,HTTP/1.0 还保留了与仍在使用 HTTP/0.9 的服务器和客户端的向后兼容性。

HTTP/1.0 是 1990 年代中期广泛实施的 HTTP 版本,当时网络在流行度上爆炸式增长。仅仅几年后,HTTP 就占有了新兴互联网上大部分的流量。HTTP 的普及如此之大,以至于它单方面促使安装了大量新硬件来处理浏览器请求和网页服务器响应的负载。

不幸的是,大量流量中的很大一部分是由于 HTTP 本身的一些限制造成的。这些限制只有在协议使用量激增的情况下才变得明显,这结合了互联网的正常成长痛,导致许多网络用户感到沮丧。HTTP/1.0 的低效是设计限制的结果,例如以下内容:

  • 每个网站都需要托管在不同的服务器上。

  • 每个 HTTP 会话只处理一个客户端请求。

  • 对必要的性能增强功能(如缓存、代理和部分资源检索)的支持普遍不足。

HTTP/1.1

虽然不耐烦的评论家们提出了讽刺性的术语,如“全球等待”,但互联网工程任务组(IETF)继续努力改进 HTTP。1997 年 1 月,HTTP/1.1 的第一个草案版本在 RFC 2068 中出现。该文件后来经过修订并于 1999 年 6 月作为 RFC 2616 发布,即“超文本传输协议——HTTP/1.1”。HTTP/1.1 与 HTTP/1.0 和 HTTP/0.9 都保持向后兼容性。它还伴随着 RFC 2617,“HTTP 认证:基本和摘要访问认证”,该文件处理安全和认证问题。

HTTP/1.1 相比于协议的 1.0 版本引入了几个显著的改进,其中大部分专门针对我刚才描述的性能问题。HTTP1/1 中一些更重要改进包括以下内容:

多主机名支持 在 HTTP/1.0 中,没有方法可以指定客户端需要连接的服务器的名称。因此,特定 IP 地址的 Web 服务器只能支持一个域名。这不仅效率低下,而且在 1990 年代还加剧了 IP 地址的枯竭,因为每个上线的新 Web 服务器都需要一个新的 IP 地址。HTTP/1.1 允许一个 Web 服务器处理数十个甚至数百个不同虚拟主机的请求。

持久连接 HTTP/1.1 允许客户端在一个 TCP 会话中向服务器发送多个相关文档的请求。这比 HTTP/1.0 的性能有了很大提升,在 HTTP/1.0 中,每个请求都需要一个新的连接到服务器。

部分资源选择 在 HTTP/1.1 中,客户端可以请求资源的部分,而不是需要获取整个文档,这减少了服务器的负载并节省了传输带宽。

更好的缓存和代理支持 HTTP/1.1 包含了许多规定,使得缓存和代理比 HTTP/1.0 更有效率且更有效。这些技术可以通过为客户端提供更快地回复其请求来提高性能,同时减少服务器的负载,以及增强安全性和实现其他功能。

内容协商 HTTP/1.1 有一个额外的协商功能,允许客户端和服务器交换信息,以帮助在多个变体可用时选择最佳资源或资源的版本。

更好的安全性 HTTP/1.1 定义了身份验证方法,并且通常比 HTTP/1.0 更注重安全性。

除了这些显著的改进之外,HTTP/1.1 还进行了许多其他小的增强。其中一些以新头部的形式出现,可以包含在客户端请求中,以更好地控制在什么情况下从服务器检索资源,以及服务器响应中的头部提供额外的信息给客户端。

未来 HTTP 版本

尽管 HTTP/1.1 现在已经几年了,但它仍然是当前的 HTTP 版本。考虑到 HTTP 的广泛使用,这可能会让人有些惊讶。然而,这也可能是因为有数以百万计的服务器和客户端实现了 HTTP/1.1,因此没有创建新的版本。曾经有过关于 HTTP 1.2 版本将会开发的猜测,但到目前为止这还没有发生。

在 1990 年代末,开始研究通过扩展现有版本 1.1 来扩展 HTTP 的方法。HTTP 扩展框架 的开发持续了多年,到 1998 年,为一个新的互联网标准创建了一个提议的草案。然而,由于 HTTP/1.1 非常广泛部署且非常重要,因此很难就任何修改它的提议达成共识。因此,当 HTTP 扩展框架最终在 2000 年 2 月作为 RFC 2774 发布时,新的标准所需的普遍接受度并不存在。该框架被赋予实验性状态,从未成为正式标准。

小贴士

关键概念 互联网(Web)的引擎是定义服务器和客户端如何交换信息的应用协议:超文本传输协议(HTTP)。HTTP 的第一个版本是 HTTP/0.9,它是早期 Web 的一部分,是一个非常简单的请求/响应协议,只能传输文本文件。第一个广泛使用的版本是 HTTP/1.0,这是一个更完整的协议,允许传输许多类型的文件和资源。当前版本是 HTTP/1.1,它通过几个提高传输效率并解决许多现代 Web 快速增长需求的功能扩展了 HTTP/1.0 的功能。

HTTP 操作模型和客户端/服务器通信

虽然 Web 本身有许多不同的方面,但 HTTP 只关注一个基本功能:从网页服务器向网页客户端传输超文本文档和其他文件。在实际情况中,客户端主要关注向服务器发出请求,服务器对这些请求进行响应。

因此,尽管 HTTP 包含了许多功能以满足客户端和服务器需求,但当你将其简化时,你会得到一个非常简单、客户端/服务器、请求/响应协议。在这方面,HTTP 更类似于像引导协议(BOOTP)或地址解析协议(ARP)这样的基本协议,而不是像文件传输协议(FTP)和简单邮件传输协议(SMTP)这样的其他应用层协议,后者涉及多个通信步骤和命令/回复序列。

基本 HTTP 客户端/服务器通信

在其最简单的形式中,HTTP 的操作仅涉及一个 HTTP 客户端,通常是一个客户端机器上的 网页浏览器,以及一个 HTTP 服务器,更常被称为 网页服务器。在创建 TCP 连接之后,通信的步骤如下(参见 图 80-1

图 80-1. HTTP 客户端/服务器通信 在其最简单形式中,HTTP 通信包括一个客户端发送给服务器的 HTTP 请求消息,服务器以 HTTP 响应消息回复。

在 HTTP/1.0 中,每个 TCP 连接仅涉及这样一个交换,如 图 80-1 所示。在 HTTP/1.1 中,可能存在多个交换,您很快就会看到。注意,在某些情况下,服务器可能在发送完整响应之前,先发送一个或多个初步响应。这可能发生在服务器在发送实际回复之前,使用 100 Continue 状态码发送一个初步响应。有关 HTTP 状态码的更多描述,请参阅 第八十一章。

小贴士

关键概念 HTTP 是一种面向客户端/服务器的请求/回复协议。基本通信包括一个由 HTTP 客户端发送到 HTTP 服务器的 HTTP 请求 消息,服务器随后返回一个 HTTP 响应 消息给客户端。

代理和 HTTP 请求/响应链

当在客户端和服务器之间的虚拟通信路径中放置 代理 时,客户端和服务器之间的简单请求/响应对会变得更加复杂。这些设备如 代理、网关隧道 用于提高性能、提供安全性或为特定客户端或服务器执行其他必要功能。代理在互联网上尤其常用,因为它们可以大大提高相关客户端计算机组的响应时间。

当中间件参与 HTTP 通信时,它充当中间人。而不是客户端直接与服务器通信,反之亦然,每个都通过中间件进行交流。这允许中间件执行诸如缓存、翻译、聚合和封装等功能。例如,考虑通过单个中间设备进行交换。前面章节中描述的两步通信过程将变为四步:

  1. 客户端请求 HTTP 客户端向中间设备发送请求消息。

  2. 中间请求 中间件处理请求,如果需要则对其进行更改。然后它将请求转发到服务器。

  3. 服务器响应 服务器读取并解释请求,采取适当的行动,然后发送响应。由于它从中间件接收请求,所以它的回复返回到中间件。

  4. 中间件响应 中间件处理请求,再次可能进行更改,然后将它转发回客户端。

如您所见,从客户端的角度来看,中间件表现得像服务器,从服务器的角度来看,它表现得像客户端。许多中间件被设计成能够拦截各种 TCP/IP 协议,通过充当客户端对服务器和服务器对客户端。大多数协议对中间件的存在一无所知。然而,HTTP 包含对某些中间件(如代理服务器)的特殊支持,提供控制中间件如何处理 HTTP 请求和响应的头部信息。(代理服务器在第八十四章中讨论。)

在客户端和服务器之间,可能存在两个或更多中间件相互连接。例如,客户端可能向中间件 1 发送请求,然后中间件 1 转发到中间件 2,然后中间件 2 与服务器通信,如图 80-2 所示。回复的过程是相反的。HTTP 标准使用短语“请求/响应链”来指代参与 HTTP 消息交换的所有设备集合。

使用中介的 HTTP 请求/响应链

图 80-2. 使用中介的 HTTP 请求/响应链 与直接连接不同,HTTP 客户端和服务器可能通过一个或多个中介设备(如代理)连接。在这个例子中,有两个中介设备。客户端发送的 HTTP 请求消息实际上会被传输三次:从客户端到第一个中介,然后到第二个,最后到服务器。HTTP 响应消息只创建一次,但会传输三次。参与消息交换的全部设备集合称为请求/响应链。

小贴士

关键概念 当在 HTTP 客户端和服务器之间的通信路径中插入中介设备,如代理、隧道或网关时,简单的客户端/服务器操作模型变得更加复杂。HTTP/1.1 特别设计了一些功能,以支持通过一系列步骤高效地传输请求和响应,从客户端通过中介到服务器,然后再返回。参与此类通信的所有设备统称为请求/响应链

缓存对 HTTP 通信的影响

正常的 HTTP 通信模型通过应用缓存到客户端请求而改变。网络上的各种设备使用缓存来存储最近检索的资源,以便在响应请求时可以快速提供。客户端本身也会缓存最近访问的网页文档,这样如果用户再次请求它们,它们可以在不向服务器发出请求的情况下显示。如果需要请求,任何中介设备都可以在它的缓存中满足对文件的请求。

当使用缓存时,拥有请求的缓存资源的设备会直接返回它,绕过了正常的 HTTP 通信过程。在图 80-2,如果中间件 1 拥有客户端需要的文件,它将直接提供给客户端,而中间件 2 以及客户端最初试图到达的原始 Web 服务器甚至都不会意识到曾经有请求被发起。第八十四章提供了关于 HTTP 缓存的详细信息。

注意

大多数对网络资源的请求都是使用基于域名系统(DNS)主机名的 HTTP URL 进行的。满足此类请求的第一步是将 DNS 域名解析为 IP 地址,但这个过程与 HTTP 通信本身是分开的。

HTTP 的临时性连接、持久性连接和流水线

你刚刚了解到基本的 HTTP 通信过程是一个简单的两步程序:客户端向服务器发送请求,服务器回复客户端。由于 HTTP 原本就是为了做这件事而设计的,因此该协议的第一个版本被设计成在客户端和服务器之间建立 TCP 连接后,只执行一次请求/响应交换。请求得到满足后,TCP 连接就被终止了。这些临时性连接是原始 HTTP/0.9 所支持的唯一类型,在更广泛部署的 HTTP/1.0 中也保持了同样的模型。

这种连接模型的优势在于其概念上的简单性。问题是,当客户端需要向同一服务器发送多个请求时,它是不高效的。这在现代超文本文档中很常见,这些文档通常包含对图像和其他媒体的内联引用。一个典型的客户端对网站主页的请求开始于对一个超文本标记语言(HTML)文件的单一请求,但随后会引发对该文档相关其他文件的后续请求。

在临时连接中,客户端发出的每个请求都需要在客户端和服务器之间建立一个全新的、独立的 TCP 连接。每个连接都消耗服务器资源和网络带宽,因此为每个文件建立新的连接效率极低。假设你正在与某人交谈,你需要连续提出一系列问题。现在想象一下,在回答完每个问题后,对方挂断了电话,你不得不再次拨通她!你就能理解这个情况了。

有些人认为 HTTP/0.9 和 HTTP/1.0 连接的临时性是这些早期 HTTP 版本的设计缺陷,但我不认为这是公平的。在早期,这种操作模式并不是一个大问题;只有在 Web 和超文本的使用演变后,才变得有问题。在其存在的最初几年,超文本主要是这样的:文本。HTTP 会话只需持续足够长的时间来完成一次请求/响应就足够了,因为整个资源都在一个文件中。只有在 20 世纪 90 年代,超文本才变成了超媒体,强调嵌入图形和其他文件。当网页从简单的文本变为多媒体奇迹,拥有数十甚至数百个嵌入图像时,HTTP/1.0 的限制变得明显。

问题解决方案出现在 HTTP/1.1 中,它允许 HTTP 客户端和服务器建立一种持久连接

持久连接

在持久连接下,HTTP 的基本操作并未改变。主要区别在于,默认情况下,每次请求/响应集之后,TCP 连接保持开启状态,以便下一个请求和响应可以立即交换。会话仅在客户端完成请求所有需要的文档后关闭。

在请求之间保持 HTTP 客户端和服务器之间的 TCP 连接活跃,可能是 HTTP/1.1 相对于 HTTP/1.0 性能提升的最重要方式。客户端能够更快地获取文件,因为它们不需要在检索每个资源之前等待 TCP 连接。服务器负载减少,繁忙服务器中的内存使用得到节约。通过消除不必要的 TCP 握手段,减少了网络拥塞。

管道化

持久连接为 HTTP 客户端提供了另一个重要的性能提升选项:能够 管线化 请求。假设客户端需要向服务器发送对文件 A、B 和 C 的请求。由于所有这些文件的请求都将发送在同一个 TCP 会话中,客户端在发送对文件 B 的请求之前无需等待对文件 A 请求的响应。客户端可以连续快速地发送请求。这也提高了服务器的效率,服务器将能够按照接收到的顺序尽快填充请求,无需等待每个新请求的发送。

小贴士

关键概念 HTTP/0.9 和 HTTP/1.0 只支持 HTTP 客户端和服务器之间的 临时连接,在 TCP 连接上只能交换一个请求和响应。这对于现代网络来说非常低效,因为客户端经常需要向服务器发送数十个请求。默认情况下,HTTP/1.1 使用 持久连接。这意味着一旦建立了 TCP 连接,客户端就可以向服务器发送多个请求,并依次接收每个请求的回复。这允许更快地检索文件,并节省服务器资源和互联网带宽。客户端甚至可以在发送第一个请求的回复之前发送第二个请求。HTTP/1.1 仍然支持临时连接以实现向后兼容性,当需要时。

持久连接的明显优势使它们成为现代 HTTP 通信的默认选项,但它们确实有一个缺点:它们使从服务器向客户端发送数据的过程复杂化。在临时连接中,客户端知道它从服务器接收到的所有数据都是对它发送的一个请求的回复。一旦它收到了服务器发送的所有字节并且 TCP 会话结束,客户端就知道文件已经完成。

在使用持久连接,尤其是当使用管线化时,服务器通常会向客户端连续发送一个文件接着另一个文件,客户端必须区分它们。记住 TCP 将数据作为一系列无结构的字节发送;应用程序必须负责指定文件之间的分隔点。这意味着持久连接和管线化导致的数据长度问题必须在 HTTP 中特别处理。

为了与旧版本的软件保持兼容性,HTTP/1.1 服务器仍然支持临时连接,并且如果它们收到 HTTP/0.9 或 HTTP/1.0 请求,它们将自动在发送一个响应后关闭 TCP 连接。HTTP/1.1 客户端也可以在其初始请求中指定它们不想使用持久连接。

HTTP 持久连接的建立和管理

与大多数 TCP/IP 客户端/服务器协议一样,在建立持久连接时,HTTP 服务器通过监听特定端口号上的请求来扮演被动角色。HTTP 的默认端口号是众所周知的 TCP 端口号 80,并且被网页浏览器用于大多数 HTTP 请求,除非在统一资源定位符(URL)中指定了不同的端口号。客户端通过从自身到它希望联系的服务器打开一个 TCP 连接来启动 HTTP 连接。

注意

DNS 名称解析步骤可能在整个 HTTP 连接之前进行,因为大多数 URL 包含一个主机名,而 HTTP 要求客户端知道服务器的 IP 地址。这可能会导致混淆,因为 DNS 使用用户数据报协议(UDP),但 HTTP 使用 TCP。这导致一些人认为 HTTP 使用 UDP。

一旦 TCP 连接激活,客户端就会发送它的第一个请求消息。请求指定客户端正在使用哪个版本的 HTTP。如果是 HTTP/0.9 或 HTTP/1.0,服务器将自动在过渡连接模式下工作,并且它只会发送一个回复然后关闭连接。如果是 HTTP/1.1,假设希望持久连接。一个 HTTP/1.1 客户端可以通过在其初始请求中包含特殊的 Connection: Close 头来自定义这个假设,这告诉服务器它不希望在发送的请求得到满足后保持会话活跃。

假设正在使用持久连接,客户端在发送第一个请求并等待服务器对初始查询的响应时,可以开始管道后续请求。随着服务器开始响应请求,客户端处理它们并采取行动,例如向用户显示检索到的数据。从服务器接收到的数据也可能促使客户端在相同的连接上请求更多文件,例如包含图像引用的 HTML 文档。

服务器通常会在客户端缓冲一定数量的管道请求。在客户端发送请求过于频繁的情况下,服务器可能会使用 TCP 内置的流量控制机制来限制客户端。理论上,服务器也可以选择与客户端终止连接,但最好还是使用 TCP 现有的功能。关闭连接将导致客户端启动一个新的连接,这可能会加剧任何过载问题。

请求和响应的流动将持续到客户端有请求为止。客户端可以通过在其需要发送给服务器的最后一个请求中包含 Connection: Close 头来优雅地终止连接。所有请求都是按顺序填充的,因此服务器将满足所有未完成的请求,然后关闭会话。

由于 HTTP/1.1 支持请求管线化,通常客户端不需要与同一服务器建立多个并发连接。客户端偶尔也会这样做,以便更快地从服务器获取信息。许多人认为这是“反社会的”,因为它可能导致一个繁忙的服务器资源被一个客户端垄断,而其他想要访问它的客户端则无法访问。

在特殊情况下,客户端或服务器可能会意外地关闭一个活跃的持久连接。例如,如果客户端检测到自服务器上次回复以来已经过去太多时间,它可能会得出结论,服务器已崩溃并终止连接。同样,服务器可能会收到管理员发出的关闭命令或其他原因突然结束与客户端的会话。服务器通常避免在发送响应过程中关闭连接。

客户端和服务器都必须能够处理突然的会话终止。对于服务器来说,没有太多的事情要做;如果客户端终止连接,服务器只需清理与连接相关的任何资源,然后继续为下一个客户端提供服务。

当服务器提前终止会话时,客户端需要做更多的工作,尤其是在请求管线化时更是如此。客户端必须跟踪发送给服务器的所有请求,以确保每个请求都被满足。如果服务器意外关闭会话,客户端通常会尝试建立一个新的连接来重新传输未满足的请求。由于突然的会话终止通常是一个繁忙服务器的标志,HTTP 标准指定客户端使用二进制指数退避算法,在重新提交文件请求之前等待一个可变但逐渐增加的时间(与处理以太网中的冲突所使用的方法类似)。这有助于防止客户端向已经超负荷的设备堆积请求。

第八十一章:HTTP 消息、方法和状态码

无标题图片

正如你在上一章中看到的,超文本传输协议(HTTP)完全围绕发送客户端请求和服务器响应而构建。这些是以客户端和服务器之间发送的HTTP 消息的形式出现的。与所有协议一样,HTTP 使用一种特殊的格式,该格式规定了客户端请求消息和服务器响应消息的结构。理解这些消息的工作原理是理解 HTTP 整体的重要组成部分。

在本章中,我将描述 HTTP 使用的消息以及客户端和服务器发出的特定命令和响应。我首先查看通用 HTTP 消息格式和每个 HTTP 消息的主要组成部分。然后,我讨论请求和响应消息的具体格式。我解释了客户端请求中使用的不同类型的 HTTP 方法(命令)以及服务器回复中使用的 HTTP 状态码。

注意

HTTP 的大部分功能都是通过在每个 HTTP 请求和响应消息的开始处出现的标题字段实现的。标题将在下一章中详细讨论

HTTP 通用消息格式

如你在上一章所学,使用 HTTP 的设备之间的所有通信都通过 HTTP 消息进行,其中只有两种类型:请求响应消息。客户端通常发送请求并接收响应,而服务器接收请求并发送响应。中间设备,如网关或代理,可以发送和接收这两种类型的消息。

所有 HTTP 消息都是为了适应标准称为通用消息格式的消息结构而创建的。像大多数其他 TCP/IP 消息协议一样,HTTP 不使用二进制消息格式;相反,消息是基于文本的。HTTP 消息基于电子邮件(email)RFC 822 和 2822 消息标准,以及多用途互联网邮件扩展(MIME)标准(在第七十六章中描述)。我说“基于”,因为 HTTP 消息在结构上与电子邮件消息相似,但并不严格遵循所有电子邮件或 MIME 格式要求。一个区别是,并不是所有 RFC 822 和 MIME 标题都被使用;还有其他区别,我们很快就会探讨。

HTTP 通用消息格式如下:

<起始行>
<消息头>
<空行>
[<消息体>]
[<消息尾部>]

你可以看到,这基本上与用于电子邮件消息的格式相同:标题、一个空行,然后是消息体。所有文本行都以标准的回车换行(CRLF)控制字符序列结束。空行只包含这两个字符,没有其他内容。标题始终以常规文本发送。然而,正文可以是文本或 8 位二进制信息,具体取决于要发送的数据的性质。(这是 HTTP 不完全遵循 RFC 822 标准的一种方式;有关实体和媒体类型的详细讨论,请参阅第八十三章。)

通用消息格式有以下组成部分:

起始行 起始行 是一个特殊的文本行,它传达了消息的性质。在请求中,这一行以 方法 的形式表明请求的性质,并指定一个统一资源标识符 (URI),以指示请求的对象资源。响应使用起始行来指示对请求的响应状态信息。您可以在本章以下各节中找到更多关于起始行使用的详细信息,这些节详细介绍了 HTTP 请求消息和响应消息。

消息头 HTTP 中定义了许多十几个消息头。这些头根据功能分组,如本章以下各节所述。几乎所有这些头都是可选的;唯一的例外是 Host 头,在 HTTP/1.1 的每个请求中都必须存在。头可以按任何顺序发送,并且它们都遵循在电子邮件消息中使用的相同头格式:<header-name>: <header-value>

消息体 消息体是可选的,因为它只适用于某些类型的消息。消息体可以携带一组需要在客户端和服务器之间传递的信息,例如响应中的详细错误消息。更常见的是,它携带一个文件或其他资源,在 HTTP 标准中正式称为 实体。实体通常在响应消息的体中找到,因为大多数客户端请求要求服务器发送一个文件或其他资源。然而,它们也可以在某些请求消息中找到。HTTP 支持许多类型的实体,如第八十三章中详细描述。

消息尾 如前一章所述,HTTP/1.1 默认使用持久连接,因此消息从客户端到服务器再到客户端以稳定的流发送。这需要某种方法来标记一条消息的结束和下一条消息的开始,这通常通过两种方式之一实现。第一种是使用一个特殊头,它指示消息的长度,这样接收设备就知道整个消息已经接收完毕。第二种是称为 分块传输 的方法,其中消息被分成几部分进行传输,每部分的长度在消息体中指示。当进行分块传输时,可能有一组消息 随着消息体发送。尾实际上与头相同,只是它们在文件中的位置不同,但它们只能用于实体头。有关尾和分块数据的更多详细信息,请参阅第八十三章。

提示

关键概念 所有 HTTP 消息都符合称为 通用消息格式 的结构。此格式基于 RFC 822 和 MIME 电子邮件消息标准,尽管 HTTP 并不完全遵循这些格式。每个 HTTP 消息都以一个起始行开始,然后包含多个消息头部,接着是一个空行,然后可选地包含一个消息体。消息体可能包含一个资源,例如一个在客户端和服务器之间通信的文件,称为 实体

HTTP 请求消息格式

客户端通过向它希望通信的 HTTP 服务器打开一个 TCP 连接来启动一个 HTTP 会话。然后,它向服务器发送 HTTP 请求消息,每条消息都指定了 HTTP 客户端用户希望服务器执行的一种特定类型的操作。请求可以由特定的用户操作(例如在网页浏览器中点击超链接)或先前操作的结果(例如在 HTML 文档中引用内联图像导致对该图像的请求)间接生成。

HTTP 请求消息使用一种基于上一节中描述的通用消息格式的格式,但针对请求的具体需求。此格式的结构如下(参见图 81-1):

[<请求行>]
[<通用头部>]
[<请求头部>]
[<实体头部>]
[<空行>]
[<消息体>]
[<消息尾部>]

HTTP 请求消息格式 此图展示了 HTTP 请求消息的结构元素以及请求消息可能包含的头部示例。像大多数 HTTP 请求一样,此请求不携带实体,因此没有实体头部,消息体为空。有关 HTTP 响应消息格式的详细信息,请参阅。

图 81-1. HTTP 请求消息格式 此图展示了 HTTP 请求消息的结构元素以及请求消息可能包含的头部示例。像大多数 HTTP 请求一样,此请求不携带实体,因此没有实体头部,消息体为空。有关 HTTP 响应消息格式的信息,请参阅图 81-2。

请求行

所有 HTTP 消息开始处的通用 起始行 在请求消息中称为 请求行。它有三个主要目的:

  • 指示客户端希望执行的操作

  • 要指定应执行操作的资源

  • 向服务器指示客户端正在使用 HTTP 的哪个版本

请求行的正式语法如下:

<METHOD > <request-uri> <HTTP-VERSION>

以下各节将讨论请求行组件。

方法

方法 简单地是客户端希望服务器执行的动作类型;它始终以大写字母指定。HTTP/1.1 定义了八个标准方法,其中三个被广泛使用:GET, HEADPOST。它们被称为 方法 而不是 命令,因为 HTTP 标准使用了面向对象编程的术语。我将在本章后面的 "HTTP 方法" 部分解释这一点,并描述这些方法本身。

请求 URI

请求 URI 是请求所应用的资源的 URI。虽然 URI 从理论上可以指代统一资源定位符 (URL) 或统一资源名称 (URN),但目前,URI 几乎总是遵循 Web URL 的标准语法规则,即 HTTP URL,如第七十章")所述。

有趣的是,HTTP 请求行中使用的 URL 的确切形式通常与 HTML 文档中使用的或用户输入的 URL 不同。这是因为完整 URL 中的某些信息用于控制 HTTP 本身。它是用户与 HTTP 客户端之间通信的一部分,但不在客户端向服务器的请求中使用。在请求中指定资源的标准方法是在请求行中包含路径和文件名(以及任何可选的查询信息),同时在 HTTP/1.1 请求消息中必须使用的特殊 Host 头部中指定主机。

例如,假设用户输入了一个像http://www.myfavoritewebsite.com:8080/chatware/chatroom.php这样的 URL。显然,我们不需要将http:发送到服务器。客户端将取剩余的信息,将其分割,使 URI 指定为/chatware/chatroom.php,而 Host 行将包含www.myfavoritewebsite.com:8080。因此,请求的开始看起来像这样:

GET /chatware/chatroom.php HTTP/1.1
Host: www.myfavoritewebsite.com:8080

这个规则的例外情况是当请求是发送给代理服务器时。在这种情况下,请求使用其原始形式的完整 URL,这样它就可以像原始客户端处理它一样被代理处理。请求看起来像这样:

GET http://www.myfavoritewebsite.com:8080/chatware/chatroom.php HTTP/1.1

最后,有一种特殊情况,可以使用单个星号代替实际的 URL。这是用于 OPTIONS 方法的,该方法不需要指定资源。(名义上,星号表示方法指的是服务器本身。)

HTTP 版本

HTTP 版本 元素告诉服务器客户端正在使用哪个版本,这样服务器就知道如何解释请求,以及在其响应中向客户端发送什么内容,不发送什么内容。例如,接收来自使用 HTTP/0.9 或 HTTP/1.0 的客户端请求的服务器将假设正在使用临时连接而不是持久连接(如前所述),并且服务器将避免在其回复中使用 HTTP/1.1 头。版本令牌以大写字母发送,如 HTTP/0.9、HTTP/1.0 或 HTTP/1.1——正如我在讨论协议时一直所做的那样。

头部

在请求行之后,可以包含客户端想要包含在消息中的任何头。在这些头中,向服务器提供了有关请求的详细信息。所有头都使用相同的结构,但根据它们所执行的功能以及是否特定于某种消息,被组织成以下几类:

通用头 通用头主要指的是消息本身,而不是其内容,它们用于控制消息的处理或向接收者提供额外信息。它们既不是请求消息也不是响应消息特有的,因此它们可以出现在任何一种消息中。此外,它们与消息可能携带的任何实体没有特别的相关性。

请求头 这些头向服务器传达了更多关于客户端请求性质的信息,并使客户端能够更多地控制请求的处理方式。例如,客户端可以使用特殊的请求头指定一个条件请求——只有当满足某些标准时才会被填充。其他头可以告诉服务器客户端能够处理响应消息中的哪些格式或编码。

实体头 这些头描述了请求体中包含的实体(如果有的话)。

小贴士

关键概念 HTTP 请求消息是 HTTP 客户端请求服务器执行特定类型操作的手段,例如发送文件或处理用户输入。每个请求消息以一个请求行开始,该行包含三个关键信息:客户端请求的方法(动作类型)、客户端希望执行动作的资源URI以及客户端使用的 HTTP 版本。请求行之后是一系列与请求相关的消息头,然后是一个空行,然后是可选的请求消息体。

请求头显然仅在请求消息中使用,但通用头和实体头都可以出现在请求或响应消息中。由于存在如此多的头信息,并且大多数头信息并不特定于某一种消息类型,我在下一章中详细描述了它们。

HTTP 响应消息格式

每个 HTTP 客户端向服务器发送的请求消息都会促使服务器发送回一个响应消息。实际上,在某些情况下,服务器可能会发送两个响应:一个初步响应,然后是真正的响应。通常情况下,一个请求会产生一个响应,这表明服务器处理请求的结果,响应通常还携带一个实体(文件或资源)在消息体中。

与请求消息一样,响应消息使用它们自己的特定格式,该格式基于本章前面描述的 HTTP 通用消息格式。响应消息格式的头部如下(参见图 81-2

图 81-2. HTTP 响应消息格式 此图说明了 HTTP 响应消息的构建,并包括消息头部和主体的示例。状态码 200 表示这是对请求的成功响应;它包含消息主体中的简短文本 HTML 实体。参见图 81-1 了解 HTTP 请求消息格式。

状态行

状态行(注意这并不被称为响应行)是用于响应消息的起始行。它有两个功能:告诉客户端服务器正在使用哪个版本的协议,以及传达处理客户端请求的结果摘要。状态行的正式语法如下:

<HTTP-VERSION> <status-code> <reason-phrase>

下面的各节将讨论状态行各组成部分。

HTTP 版本

状态行中的 HTTP-VERSION 标签在请求消息的请求行中起到相同的作用(如前节所述)。在这里,它告诉客户端服务器正在使用哪个版本号进行响应。它使用与请求行相同的格式,版本号为大写,如 HTTP/0.9、HTTP/1.0 或 HTTP/1.1。服务器必须返回一个 HTTP 版本号,该版本号不大于客户端在其请求中发送的版本号。

状态码和原因短语

状态码原因短语以两种不同的形式提供有关处理客户端请求结果的信息。状态码是一个三位数,表示服务器向客户端传达的正式结果。它旨在让客户端 HTTP 实现处理,以便软件可以采取适当的行动。原因短语是一个额外的描述性文本字符串,可以显示给 HTTP 客户端的人类用户,以便他们可以看到服务器如何响应。我在本章后面描述状态码和原因短语,并列出所有标准代码。

头部

响应消息将始终包含一些头部,提供有关其的额外信息。响应消息头部分为三类:

通用头部 指的是消息本身且不特定于响应消息或消息主体中的实体的通用头部。这些与可以出现在请求消息中的通用头部相同(尽管某些头部在响应中出现得更频繁,而其他头部在请求中出现得更常见)。

响应头 这些头信息提供了对状态行中总结结果信息的扩展数据。服务器还可能在消息体中返回额外的结果信息,尤其是在发生错误时。

实体头 这些是描述响应体中包含的实体(如果有的话)的头信息。这些与请求消息中可能出现的实体头相同,但它们在响应消息中出现的频率更高。

大多数响应消息在消息体中包含实体。在成功请求检索资源的情况下,这本身就是资源。表示请求不成功的响应通常包含详细的错误信息,通常以 HTML 格式化的错误消息的形式出现。

注意

实体头可能出现在响应消息中,用于描述请求的主题资源,即使实体本身没有在消息中发送。这发生在使用 HEAD 方法请求仅与实体关联的头信息时

响应头仅用于响应消息,而其他头信息在消息类型方面是通用的。有关 HTTP 头信息的更多详细信息,请参阅第八十二章。

小贴士

关键概念 客户端发送的每个 HTTP 请求消息都会导致服务器返回一个或多个HTTP 响应消息。每个响应消息都以状态行开始,其中包含服务器的 HTTP 版本号、一个数字状态码和文本原因短语,这些指示了处理客户端请求的结果。然后是有关响应的头信息,接着是一个空行,然后是可选的消息体。由于大多数 HTTP 请求消息要求服务器返回文件或其他资源,因此许多 HTTP 响应消息在消息体中携带实体。

HTTP 方法

客户端向服务器发送的 HTTP 请求消息显然是要求服务器执行某些操作。所有客户端/服务器协议都提供了一种方式,允许客户端提示服务器采取行动,通常是通过客户端向服务器提供一系列命令。与 HTTP 不同,HTTP 有方法而不是命令。每个客户端请求消息都以指定请求主题的方法开始。

方法和命令之间的区别是什么?在实用意义上,没有区别;它们是相同的。那么为什么 HTTP 使用“方法”这个词而不是“命令”呢?这是一个好问题。答案可以在定义 HTTP/1.0 的标准摘要中找到,即 RFC 1945。它部分指出,HTTP 是“一种通用的、无状态的、面向对象的协议,可用于许多任务……”。用高度简化的术语来说,面向对象编程是一种技术,其中软件模块不是描述为一系列过程,而是描述为具有属性的对象。这些模块通过发送消息相互通信并执行操作,其中执行的操作取决于对象的性质。在面向对象编程中,每个对象可以执行的过程称为方法

HTTP 被认为是面向对象的,因为在许多情况下,服务器执行的操作取决于请求的主题对象。例如,如果你要求服务器检索一个文本文档,它将发送该文档;但如果你要求目录,服务器可能会返回该目录的默认文档。相比之下,指定程序名称的请求将导致程序执行并返回其输出(而不是返回程序的源代码)。

常见方法

每种方法都允许客户端指定服务器要执行的一种特定类型的操作。方法名称始终为大写字母。在 HTTP 中常用的三种方法是:GET、HEAD 和 POST。

GET

GET 方法请求服务器根据 HTTP 请求行中的 URL 检索指定的资源,并将其作为响应发送回客户端。这是最基本的请求类型,也是占 HTTP 流量大多数的类型。当你输入一个常规 URL 或点击链接到文档或其他文件时,你通常是在提示你的网页浏览器发送一个 GET 请求。

GET 请求的处理取决于许多因素。如果 URL 正确且服务器可以找到资源,它将向客户端发送适当的响应。返回的确切资源取决于请求的对象的性质。如果请求无法正确处理,可能会产生错误消息。缓存(在第八十四章中讨论)也起作用,因为代理服务器甚至客户端本身可能在请求到达服务器之前就满足请求。

需要记住,如果使用某些头部信息,例如 If-Modified-Since 或 If-Match,GET 请求的含义可能会改变。这些头部信息指示服务器仅在满足某些条件时发送资源。这种类型的请求有时被称为 条件 GET。同样,客户端可以使用 Range 头部信息请求服务器只发送资源的一部分;这通常用于大文件。当包含此头部信息时,请求可能被称为 部分 GET

HEAD 方法与 GET 方法相同,但它告诉服务器不要发送消息的实际主体。因此,响应将包含所有伴随等效 GET 消息的头部信息,包括描述服务器在方法为 GET 时将发送的实体的头部信息。客户端通常使用此方法在决定是否希望服务器发送整个文件之前,检查文件的存在、状态或大小。

HEAD 请求的处理方式与 GET 请求相同,但除了只返回头部信息外,不返回实际资源。

POST

POST 方法允许客户端向服务器发送包含任意数据的实体以进行处理。它通常用于允许客户端将信息,如交互式 HTML 表单,提交给服务器上的程序,然后该程序根据该输入采取行动并发送响应。现在这种能力被用于各种在线程序。请求中的 URL 指定了服务器上要接受数据的程序名称。这与下一节中描述的 PUT 方法形成对比。

其他方法

HTTP 标准定义的其他方法使用得不太频繁,但我将简要描述它们,因为您可能还会遇到它们。其他 HTTP 方法包括以下内容:

OPTIONS 此方法允许客户端请求服务器发送有关可用通信选项的信息。可以指定资源的 URI 以请求与访问该资源相关的信息,或者使用星号 (*) 来表示查询是关于服务器本身的。响应包括头部信息,这些头部信息向客户端提供了更多关于如何访问服务器细节。

PUT 此方法请求服务器将请求行中指定的 URL 存储在请求体中的实体。在 PUT 方法中,URI 标识请求中的实体;因此,PUT 允许将文件复制到服务器,这与 GET 请求将文件复制到客户端的方式正好相反。相比之下,使用 POST 时,URI 标识一个旨在处理请求中实体的程序,因此它用于交互式程序。现在,你希望人们能够以请求文件的方式将文件存储在你的服务器上吗?我也不希望。这是 PUT 方法不常使用的一个主要原因。它有有效的用途,例如上传网站内容,在这种情况下必须使用身份验证。然而,在网站上存储文件通常使用其他方式,如文件传输协议(FTP)。

DELETE 此方法请求删除指定的资源。这与 PUT 方法存在相同的问题,并且由于类似的原因不常使用。

TRACE 此方法允许客户端接收到它发送给服务器的请求的副本,用于诊断目的。

此外,标准为未来的使用保留了方法名称 CONNECT。HTTP/1.1 的早期版本 RFC 2068 定义了方法 PATCH、LINK 和 UNLINK。这些在最终版本中被删除了,但你可能仍然会看到对它们的引用。

提示

关键概念 每个 HTTP 客户端请求都指定服务器应执行的一种特定操作;在 HTTP 中,这些被称为方法,而不是命令。最常用的三种 HTTP 方法是GET,它提示服务器返回一个资源;HEAD,它只返回与资源关联的头部信息;以及POST,它允许客户端向服务器提交数据以进行处理。

安全和幂等方法

正如你所看到的,方法在导致服务器采取的行为类型上差异很大。HTTP 标准定义了两个可以用来根据方法对服务器的影响进行区分的特性:

安全方法 这些是管理员可以合理地允许客户端发送的方法,因为它们极不可能产生任何负面副作用。通常被归入此类的方法是 GET、HEAD、OPTIONS 和 TRACE。导致服务器接受数据进行处理或导致服务器上发生变化的方法被认为是不可安全的:POST、PUT 和 DELETE。(它们被认为是不可安全的并不意味着服务器永远不会允许它们——只是它们在处理上比其他方法需要更多的注意和细节。)

幂等方法 如果重复执行相同的方法请求多次会产生完全相同的结果,就像该方法只被发出一次一样,那么这种方法就被称作是 幂等的。例如,如果你在浏览器中加载一个网页,然后再次输入相同的 URL,你通常会得到相同的结果,至少大多数时候是这样。一般来说,HTTP 中的所有方法都具有这种属性,除了 POST 方法。

POST 方法不是幂等的,因为每个 POST 请求的实例都会导致接收服务器处理请求消息体中的数据。提交两次或更多次的 POST 请求通常会导致不希望的结果。一个经典的例子是在表单上多次点击提交按钮,这可能会导致诸如在互联网论坛上出现重复消息或在在线商店中重复订单等烦恼。

也存在一种情况,即通常幂等的方法可能不是幂等的。对简单文档的 GET 请求是幂等的,但对脚本的 GET 请求可能会更改服务器上的文件,因此不是幂等的。同样,一系列幂等方法可能也不是幂等的。例如,考虑一种情况,其中 PUT 请求后面跟着对同一资源的 GET 请求。这个序列不是幂等的,因为第二个请求依赖于第一个请求的结果。

非幂等性的重要性在于客户端必须特别处理此类请求或序列。客户端必须跟踪它们,确保它们按顺序填写且只填写一次。HTTP 标准还规定,非幂等方法不应进行管道化,以避免在 HTTP 会话意外终止时出现问题。例如,如果两个 POST 请求被管道化,并且服务器在处理它们时出现故障,客户端需要重新发出它们,但可能不知道原始请求中有多少已经成功处理。

HTTP 状态码和原因短语

每个由 HTTP 客户端发送的请求都会导致接收它的服务器返回一个或多个响应。正如你在之前关于响应消息格式的讨论中看到的,响应的第一行是一个状态行,其中包含处理请求结果的摘要。这一行的目的是快速传达请求是否成功以及原因。

HTTP 状态行包含一个数字状态码和一个文本原因短语。使用数字和文本字符串的原因是,计算机可以通过查看数字来更容易地理解请求的结果,并相应地快速响应。另一方面,人类发现文本描述更容易理解。使用这两种形式的思想直接来源于早期的应用层协议,如 FTP、简单邮件传输协议 (SMTP) 和网络新闻传输协议 (NNTP)。第七十二章") 中对 FTP 响应代码的解释更完整地讨论了为什么除了描述性文本外还使用数字响应代码。

状态码格式

HTTP 状态码长度为三位,遵循特定的格式,其中第一位数字具有特定的意义。与 FTP 和其他协议使用的响应代码不同,第二位数字不代表功能分组;第二位和第三位数字一起为第一位数字表示的每个类别提供 100 种不同的选项。因此,HTTP 状态码的一般形式为 xyy,其中第一位数字 x 如 表 81-1 所示。

表 81-1. HTTP 状态码格式:第一位数字解释

状态码格式 含义 描述
1yy 信息性消息 提供一般信息;不指示请求的成功或失败。
2yy 成功 服务器已接收、理解并接受该方法。
3yy 重定向 请求并未直接失败,但在成功完成之前需要采取额外的操作。
4yy 客户端错误 请求无效,包含语法错误,或由于其他原因无法完成,服务器认为这是客户端的过错。
5yy 服务器错误 请求是有效的,但由于服务器自身的问题无法完成。

在这五个组中的每一个组中,yy 为 00 的代码被定义为该组的通用状态码,而其他两位数组合则是更具体的响应。例如,404 是众所周知的特定错误消息,表示服务器未找到请求的资源,而 400 是不太具体的错误请求。该系统被建立起来以允许定义某些客户端可能不理解的新状态码。如果客户端收到一个奇怪的代码,它就将其视为适当类别中通用响应的等效物。因此,如果服务器响应以代码 491 开头,而客户端不知道这是什么,它就将其视为 400 错误请求响应。

原因短语

原因短语是一个文本字符串,为那些不擅长记住这些晦涩代码代表什么的人提供了更有意义的错误描述(这将是大多数我们中的人)。HTTP 标准为每个状态码提供了示例原因短语,但服务器管理员可以根据需要自定义这些短语。当服务器在其响应消息的主体中返回更详细的 HTML 错误消息时,原因短语通常用于该消息主体的标题标签。

提示

关键概念 每个 HTTP 响应消息都包含一个数字 状态码 和一个文本 原因短语,这两个都指示相应客户端请求的处理情况。数字代码允许软件程序轻松解释请求的结果,而文本短语则向人类用户提供更有用的信息。HTTP 状态码长度为三位数字,第一位数字表示响应的一般类别。

表 81-2 按数字顺序列出了 HTTP/1.1 标准定义的状态码,以及标准原因短语和每个的简要描述。

表 81-2. HTTP 状态码和原因短语

状态码 原因短语 描述
100 Continue 客户端应继续发送其请求。这是一个特殊的状态码;请参阅本章下一节以获取详细信息。
101 Switching Protocols 客户端已使用 Upgrade 头请求使用替代协议,并且服务器已同意。
200 OK 这是一个通用的成功请求消息响应,这是在请求正常完成时发送的最常见的代码。
201 Created 请求成功并导致资源被创建。这是对 PUT 方法的典型响应。
202 Accepted 服务器已接受请求,但尚未处理。这是一个故意不承诺的响应,不会告诉客户端请求是否会被执行。客户端以某种未指定的方式确定请求的最终处理。它仅在特殊情况下使用。
203 Non-Authoritative Information 请求成功,但服务器返回的一些信息来自第三方,而不是来自与资源关联的原始服务器。
204 No Content 请求成功,但服务器已确定不需要向客户端返回实体主体。
205 Reset Content 请求成功;服务器正在告诉客户端它应该重置生成请求的文档,以便不发送重复请求。此代码旨在与表单一起使用。
206 部分内容 服务器已成功满足部分 GET 请求。有关此内容的更多详细信息,请参阅本章前面的方法部分,以及下一章中关于 Range 头的描述。
300 多种选择 服务器上以多种方式表示资源。服务器正在返回描述这些表示的信息,以便客户端可以选择最合适的一个,这个过程称为代理驱动协商(在第八十三章中讨论)。
301 永久移动 请求的资源已永久移动到新的 URL。任何未来对该资源的请求都应该使用新的 URL。这是处理服务器上文件重命名或移动到新目录等情况的正确方法。大多数人懒得设置这个,这就是为什么 URL 经常损坏,导致 404 错误。
302 找到 请求的资源临时使用不同的 URL。客户端应继续使用原始 URL。参见代码 307。
303 另见 请求的响应可以在服务器指定的不同 URL 找到。客户端必须对该 URL 进行新的 GET 请求以查看先前请求的结果。
304 未修改 客户端发送了一个条件 GET 请求,但资源自指定日期/时间以来未修改,因此服务器未发送它。
305 使用代理 要访问请求的资源,客户端必须使用服务器在响应中给出的代理,其 URL 由服务器提供。
306 (未使用) 定义在 HTTP 的早期版本中,现已不再使用。
307 临时重定向 资源临时位于客户端指定的不同 URL。请注意,302 和 307 基本上是相同的状态码。代码 307 是为了澄清在 HTTP 早期版本中发生的与 302 相关的某些混淆而创建的。
400 错误请求 这是一个通用的响应,当请求因客户端端的问题无法理解或执行时。
401 未授权 客户端无权访问资源。如果尝试无适当凭据访问受密码或其他方式保护的资源,通常会返回此响应。
402 需要支付 这是为了将来使用而保留的。它在 HTTP 标准中的存在让很多人挠头思考“嗯……”。
403 禁止访问 服务器拒绝请求。这是一个通用的“无权访问”响应,与授权无关。例如,如果网站维护者阻止特定客户端访问网站,任何来自该客户端的请求都将导致 403 回复。
404 未找到 这是最常见的 HTTP 错误消息,当服务器无法找到请求的资源时返回。这通常是由于服务器已移动(或删除)资源或客户端提供了一个无效的 URL(通常是由于拼写错误)造成的。
405 方法不允许 请求的方法对于指定的资源是不允许的。响应包括一个 Allow 头,指示服务器将允许哪些方法。
406 不接受 客户端发送的请求指定了服务器无法满足的特定资源的限制条件。如果请求中放入了一个过于严格的条件列表,以至于服务器无法返回资源的任何部分,则可能会发生此错误。
407 代理认证必需 这与 401 类似,但客户端必须首先通过代理进行认证。
408 请求超时 服务器期望客户端在特定时间内发送请求,但客户端没有发送。
409 冲突 由于与资源相关的某种冲突,请求无法完成。这种情况通常在响应 PUT 方法时发生,例如,如果一个用户试图 PUT 另一个用户已打开进行编辑的资源。
410 已删除 资源在服务器上不再可用,服务器不知道其新的 URL。这是 404 代码的一个更具体版本,仅在服务器知道资源被有意删除时使用。这种情况很少见(如果有的话)。
411 长度必需 请求需要 Content-Length 头字段,但没有包含。
412 预先条件失败 这表示客户端在其请求中指定了一个预先条件,例如使用 If-Match 头,其评估结果为假值。这表明条件未满足,因此请求没有被处理。客户端在特殊情况下使用此方法以确保他们不会意外地收到错误资源。
413 请求实体过大 服务器拒绝完成请求,因为客户端请求的实体太大。
414 请求 URI 过长 服务器拒绝完成请求,因为指定的 URL 超过了服务器可以处理的最大长度。这通常不会在正确构造的 URL 中发生,但如果客户端尝试向服务器发送乱码,可能会看到这种情况。
415 不支持的媒体类型 由于请求包含服务器不支持的媒体类型的实体,无法处理请求。
416 请求范围不满足 客户端包含了一个 Range 头,指定了一个对于资源无效的值范围。一个例子可能是请求一个 2400 字节的文件的 3000 到 4000 字节。
417 期望失败 请求包含了一个服务器无法满足的 Expect 头。
500 内部服务器错误 这是一个通用错误消息,表示请求无法完成,因为服务器出现问题。
501 未实现 服务器不知道如何执行请求,因此无法满足它。
502 网关错误 服务器在充当网关或代理时,从它试图代表客户端访问的另一个服务器接收到了无效的响应。
503 服务不可用 服务器因内部原因暂时无法满足请求。这通常在服务器过载或维护时返回。
504 网关超时 服务器在充当网关或代理时,在等待从它试图代表客户端访问的另一个服务器获取响应时超时。
505 HTTP 版本不受支持 请求使用了服务器不理解的 HTTP 版本。

100(继续)初步回复

现在,让我们回到列表的顶部,查看 HTTP 状态码和原因短语,并查看特殊的状态码 100。通常,客户端会向服务器发送一个完整的请求并等待响应(同时可选地管道化其他请求,如前一章所述)。然而,在某些情况下,客户端可能希望在发送整个消息之前先检查服务器是否愿意接受该请求。这种情况并不常见,因为大多数请求都很小,所以先检查并不值得麻烦。但是,在用户想要向在线程序提交大量数据或使用 PUT 存储大文件等情况下,先与服务器检查可能是一种有用的优化。

在这种情况下,客户端发送一个包含特殊头 Expect: 100-Continue 的请求。假设服务器支持该功能,它将处理请求的头部并立即发送 100 Continue 初步回复。这告诉客户端继续发送剩余的请求。然后服务器处理它并正常响应。如果在一定时间内服务器没有发送 100 响应,客户端通常会发送剩余的请求。请注意,在某些情况下,即使服务器不应该这样做,也会发送这些初步回复,因此客户端必须准备好处理它们(它们被简单地丢弃,因为它们不包含任何信息)。

第八十二章. HTTP 消息头

图片正如你在前两章中看到的,超文本传输协议(HTTP)的通信是通过相对简单的请求和响应消息的交换来进行的。该协议支持的方法(命令)数量很少,这可能会让你觉得该协议相当有限。然而,外表可能会欺骗人。HTTP 中的许多功能实际上是以消息标题的形式实现的,这些标题在客户端和服务器之间传递重要细节。

一些标题只能出现在 HTTP 请求中,一些只能出现在 HTTP 响应中,还有一些可以出现在这两种类型的消息中。理解这些标题对于学习 HTTP 的工作方式非常重要。实际上有数十个这样的标题,其中许多适用于请求和响应消息。

在本章中,我提供了对 HTTP 请求和响应消息中使用的许多标题的描述。本章按照 HTTP 标题的四种基本类型组织:通用标题、请求标题、响应标题和实体标题。

小贴士

背景信息 在此,我假设你已经阅读了描述 HTTP 消息格式的上一章

注意

为了确定 Web 缓存如何处理 HTTP 消息,HTTP 标题被分为端到端标题和跳转标题。前者只对消息的最终接收者有意义,而后者与连接客户端和服务器的一系列设备(如代理)中的每个设备都相关。为了避免不必要的复杂性,我没有使用这些类别对标题进行分类;有关缓存的全讨论,请参阅第八十四章以获取更多信息。在个别标题的描述中,我指出了哪些是跳转标题;所有其他都是端到端标题

HTTP 通用标题

HTTP 通用标题之所以被称为通用标题,是因为与其它三个类别的标题不同,它们并不特定于任何特定类型的信息或信息组件(请求、响应或消息实体)。通用标题主要用于传达有关消息本身的信息,而不是它所携带的内容。它们提供一般信息,并控制消息的处理和操作。

尽管这些通用标题既不特定于请求也不特定于回复,但它们在一种或另一种类型的信息中要么主要使用,要么完全使用。还有一些通用标题可以出现在请求或回复消息中,但在每种情况下都有不同的含义。

在这里,我描述了 Cache-Control 和 Warning 标题,然后是其他更直接的标题。

Cache-Control 标题

Cache-Control 头部指定了管理缓存如何执行指令,这些指令适用于 HTTP 请求或响应。这些指令影响请求或响应在请求/响应链中所有设备(从 HTTP 客户端,通过任何中间代理,到 HTTP 服务器,或相反,从服务器,通过中间代理,到客户端)的处理。它们覆盖了设备执行的任何默认缓存行为。有关该主题的全面讨论,请参阅第八十四章。

在此头部中可以出现一打单独的指令,其完整细节可以在 RFC 2616 中找到。尽管这是一个通用头部,但某些指令只能出现在请求或响应中。一些还包括一个额外的参数,例如秒数,以控制它们的解释。表 82-1 提供了不同 Cache-Control 选项的简要总结以及它们的使用方法。

注意,Cache-Control 头部中只能出现一个指令,但一个消息中可以出现多个这样的头部。

表 82-1. HTTP Cache-Control 指令

Cache-Control 指令 HTTP 消息类型 描述
no-cache 请求或响应 当存在时,强制缓存设备将任何后续请求相同内容转发到服务器进行重新验证;也就是说,缓存必须与服务器联系以确保缓存的数据仍然有效。另外,请参阅 Pragma 头部描述,了解完成同一任务的另一种方法。
public 响应 表示响应可以被任何缓存存储,包括共享缓存(由多个客户端使用的缓存)。有关共享缓存的更多详细信息,请参阅第八十四章。
private 响应 指定响应仅针对特定用户,不应放入共享缓存中。
no-store 请求或响应 指定整个请求或响应不应存储在缓存中。有时用于防止将敏感文档存储在缓存中,这些缓存可能被未经授权的人访问。然而,正如 HTTP 标准所指出的,这实际上是一个非常基本的保护措施,不应过分信任(因为恶意缓存操作员可以简单地忽略该指令)。
max-age 请求或响应 在请求中,表示客户端愿意接受年龄不超过指定值的响应。在响应中,表示在被视为过时之前响应的最大年龄。这是使用 Expires 头部的替代方法,并且具有优先权。
s-maxage 响应 如果存在,指定接收响应的共享缓存的最大年龄。私有缓存(仅服务于单个客户端的缓存)使用 max-age 值(参见前面的描述)。
min-fresh 请求 指定客户端想要一个响应,不仅在该请求收到时未过时,而且将在指定的秒数内保持新鲜。
max-stale 请求 如果未发送参数,表示客户端愿意接受一个过时的回复(一个已过期的回复)。如果包含一个数值参数,表示响应可能过时的秒数。
only-if-cached 请求 仅在特殊情况下使用,强制回复只能来自缓存;内容可能不会来自实际指定的 HTTP 服务器。
must-revalidate 响应 指示缓存在条目过时后,与原始服务器重新验证给定响应的缓存条目。这用于防止将过时的缓存条目发送给客户端(可能是由于客户端使用 max-stale 指令)可能引起的问题。
proxy-revalidate 响应 与 must-revalidate 类似,但仅适用于为许多用户服务的代理。私有缓存(如个人客户端计算机上的缓存)不受影响。
no-transform 请求或响应 一些缓存默认会更改某些已缓存条目存储的格式,以节省空间或提高性能。在可能引起问题的场合,客户端或服务器可以使用此指令请求不要执行此转换。

警告

当需要提供有关消息状态的额外信息时,使用警告头。许多定义的警告头类型都与缓存相关。一个消息中可能包含多个警告头,每个通常包括一个三位数的代码以及一个纯文本消息,遵循与 HTTP 响应状态代码相同的格式(在第八十一章中描述)。表 82-2 简要列出了 RFC 2616 中定义的警告。|

表 82-2. HTTP 警告头代码

警告代码 警告文本 描述
110 响应已过时 当缓存提供的响应已过时(即,已超过为其设置的过期时间)时必须包含。
111 重验证失败 缓存尝试重验证一个已缓存条目但未成功,因此返回了其(过时)的已缓存条目。
112 断开连接操作 缓存与网络的其他部分断开连接。
113 启发式过期 如果缓存选择了一个超过 24 小时的 freshness lifetime,并且响应的年龄也大于 24 小时,则包含。
199 其他警告 其他非特定警告的通用代码。
214 应用了转换 警告接收者,中间缓存或代理对消息或消息体的内容编码或媒体类型进行了某种类型的转换。
299 其他持久性警告 与代码 199 类似,但表示一个持久性警告。

其他 HTTP 通用标题

以下是一些其他类型的 HTTP 通用标题:

连接 包含仅适用于此特定连接的指令,并且代理不得保留这些指令用于后续连接。此标题最常见的使用是与 close 参数一起使用,如下所示:Connection: close。这覆盖了 HTTP/1.1 的默认持久连接行为(在第八十章中描述),强制在服务器响应后终止连接。连接是一个跳段标题。

日期 表示消息产生的日期和时间。这与 RFC 822 电子邮件格式中的日期头相同(在第七十六章中描述)。一个典型的例子是 Date: Wed, 17 May 2006 16:43:50 GMT

Pragma 用于在请求/响应链中的所有设备上应用特定实现的指令。此标题的一个常见用途是在消息中包含 Pragma: no-cache 以抑制缓存。这与 Cache-Control: no-cache 头的含义相同,并且包含在 HTTP/1.1 中以实现与 HTTP/1.0 的向后兼容性(HTTP/1.0 支持 Pragma 但不支持 Cache-Control)。

Trailer 当使用分块传输(如第八十三章中所述)时,某些标题可以作为尾随标题放置在发送的数据之后。在这种情况下,Trailer 标题在数据之前包含,并列出该消息中实际为尾随标题的标题名称。这警告接收者数据之后查找它们。Trailer 是一个跳段标题。

传输编码 表示消息体所使用的编码,以确保它能够在设备之间正确传输。此标题通常与分块传输方法一起使用。请注意,此标题描述的是应用于整个消息的编码,因此它与特定描述消息中实体的 Content-Encoding 实体标题不同。有关完整讨论,请参阅第八十三章。此标题仅适用于单个传输,因此它是一个跳段标题。

Upgrade 允许客户端指定它支持哪些附加协议。如果服务器也支持客户端列出的协议之一,则服务器可以同意将连接升级到替代协议。它通过在客户端的 101(切换协议)响应中包含一个 Upgrade 头来指示它升级到的协议。这是一个端到端头。

Via 由中介设备包含,以向接收者指示在传达请求或响应时使用了哪些网关、代理和/或隧道。此头允许轻松追踪消息在客户端和服务器之间可能复杂的设备链中走过的路径。

小贴士

关键概念 HTTP 通用头 可以出现在 HTTP 请求或 HTTP 响应消息中。它们用于传达有关消息本身的信息,而不是其内容。通用头用于指定消息的日期和时间、控制消息的缓存方式以及指示其传输编码方法等功能。

HTTP 请求头

如您所想象的那样,HTTP 请求头 仅用于 HTTP 请求消息中,它们在消息中执行多个功能。首先,它们允许客户端向服务器提供有关自己的信息。其次,它们提供了有关客户端正在进行的请求性质的额外细节。第三,它们允许客户端对其请求的处理方式以及服务器或中介返回响应的方式(甚至是否返回)有更大的控制权。

这是 HTTP 头四个类别中最大的一个,包含十几种不同的类型,如下所示:

Accept 允许客户端告诉服务器它愿意在响应中接受哪些互联网媒体类型。该头可以列出客户端知道如何处理的多个不同的多用途互联网邮件扩展(MIME)媒体类型和子类型。每个都可以通过一个质量值(q 参数)开头,以表示客户端的偏好。如果此头未指定,则默认为服务器假设可以发送给客户端的任何媒体类型。有关此头如何使用的更多信息,请参阅关于实体媒体类型和内容协商的讨论,见第八十三章。

Accept-Charset 与 Accept 类似,但指定客户端愿意在响应中接受哪些字符集(charsets),而不是媒体类型。同样,列出的字符集可以使用 q 值,同样,如果省略了头,则默认为客户端接受任何字符集。

Accept-Encoding 与 Accept 和 Accept-Charset 类似,但指定了客户端愿意接受的内容编码。这通常用于控制服务器是否可以发送压缩形式的内容。(正如你将在第八十三章中学习到的,内容编码与传输编码不同。)

Accept-Language 与前面的 Accept-type 头部类似,但提供了一组 语言标签,表示客户端支持或期望服务器在其响应中使用哪些语言。

Authorization 由客户端用于向服务器提供身份验证信息(称为 凭证),以允许客户端进行身份验证。仅在服务器请求身份验证时才需要此信息,通常是通过向客户端的初始请求发送一个 401(未授权)响应来实现的。此响应将包含一个 WWW-Authenticate 头部,向客户端提供有关如何与服务器进行身份验证的详细信息。有关安全和隐私的讨论,请参阅第八十四章以获取更多信息。

Expect 表示客户端期望服务器执行的一些特定类型的操作。通常,服务器将接受指示的参数;如果不接受,它将发送一个 417(期望失败)响应。此字段的常见用途是控制服务器何时发送 100(继续)响应。客户端通过在其请求中包含 Expect: 100-Continue 头部来指示它希望服务器发送此初步回复。(有关状态代码的讨论,请参阅第八十一章末尾。)

From 包含发起请求的人类用户的电子邮件地址。这是可选的,并且由于它很容易被伪造,因此仅应用于信息目的,而不应用于任何类型的访问权限确定或身份验证。

Host 指定互联网主机作为域名系统(DNS)域名,并且还可以包含端口号的指定(通常,只有当需要使用除 HTTP 默认端口 80 之外的端口号时)。此头部用于允许在特定的互联网协议(IP)主机上由同一个 Web 服务器为多个域名提供服务。它具有区别于其他头部的特点——它是唯一必需的头部——必须在所有 HTTP/1.1 请求中存在。

If-Match 通过指定客户端希望访问的特定实体的 实体标签(或标签)来使方法条件化。这通常用于 GET 方法,并且只有当服务器收到的实体与该头部中指定的实体匹配时,才会响应实体。否则,服务器会发送一个 412(预条件失败)回复。

If-Modified-Since 通过告诉服务器仅在自该头中指定的时间以来实体已修改的情况下返回请求的实体,使方法条件化。否则,服务器发送 304 (未修改) 响应。这用于检查资源自上次访问以来是否已更改,以避免不必要的传输。

If-None-Match If-Match 的对立面;它创建一个条件请求,仅在指定的标签不匹配请求的实体时才填充。

If-Range 与 Range 头结合使用,有效地允许客户端在单个请求中同时检查实体是否已更改并请求发送其一部分。 (另一种选择是首先发出一个条件请求,如果它失败,再发出第二个请求。) 当存在时,If-Range 告诉服务器如果实体未更改,则向客户端发送 Range 头中指示的实体部分。如果实体已更改,服务器将发送整个实体作为响应。

If-Unmodified-Since If-Modified-Since 头的逻辑对立面;只有在自指定时间以来资源未修改的情况下才填充请求。否则,服务器发送 412 回复。

Max-Forwards 指定请求可以转发到请求链中下一个设备的次数限制。此头仅与 TRACE 或 OPTIONS 方法一起使用,以允许诊断转发失败或循环。当存在于这些方法之一中时,每次设备转发请求,此头中的数字就会递减。如果设备收到一个 Max-Forwards 值为 0 的请求,它必须不转发它,而应该向客户端响应。 (从某种意义上说,这与 IP 数据报格式中 Time to Live 字段的使用方式类似,如第二十一章所述。第二十一章。)

Proxy-Authorization 与 Authorization 头类似,但用于向代理服务器提供用于身份验证的凭据,而不是向最终服务器。它使用包含 Proxy-Authenticate 头的响应中发送的信息创建。这是一个跳到跳的头,仅发送到接收请求的第一个代理。如果需要通过多个代理进行身份验证,可以在消息中放置多个 Proxy-Authorization 头,每个代理消耗一个头。

Range 允许客户端请求服务器只发送实体的一部分,通过指定要检索的实体中的字节数范围。如果请求的范围有效,服务器将只发送指示的文件部分,使用 206 (部分内容) 状态码;如果请求的范围无法满足,则回复是 416 (请求范围无法满足)。

Referer 告诉服务器当前请求的 URL 是从哪个资源的 URL 获得的。通常,当用户点击一个网页上的链接以加载另一个网页时,原始网页的地址会在发送点击链接的请求时放入 Referer 行。这允许跟踪和记录服务器是如何被访问的。如果人工用户手动将统一资源标识符(URI)输入到网络浏览器中,则此头不会包含在请求中。由于此头提供有关网页使用方式的信息,因此它具有某些隐私影响。

注意

这个词的正确拼写是 referrer。在 HTTP 标准的早期版本中多年以前被误拼,在此拼写被发现并纠正之前,这种拼写已经融入了大量的软件中,因此互联网工程任务组(IETF)选择不在 HTTP/1.1 中纠正拼写

TE 向服务器提供有关客户端希望如何处理服务器发送的实体传输编码的信息。如果定义了标准 HTTP 传输编码的扩展,客户端可以使用此头指示其愿意接受它们。客户端还可以使用头 TE: trailers 来指示其处理在分块数据时作为拖车发送的头的功能。这是一个跳过跳(hop-by-hop)的头,仅适用于直接连接。

User-Agent 提供有关客户端软件的信息。这通常是发送请求的网页浏览器或其他程序的名称和版本号。它用于服务器访问统计日志记录,也可能被用来调整服务器如何响应不同客户端的需求。请注意,代理在转发请求时不会修改此字段;相反,它们使用 Via 头。

提示

关键概念 HTTP 请求头 仅用于 HTTP 请求消息中。它们允许客户端向服务器提供有关自己的信息,提供更多关于请求的细节,并允许控制请求的执行方式。

HTTP 响应头

请求头(request headers)的对应项,响应头(response headers),仅出现在服务器或中间件发送的 HTTP 响应中。它们提供了额外的数据,这些数据扩展了每个服务器回复开始时的状态行中存在的摘要信息。许多响应头仅在收到特定类型的请求或甚至某些请求中的特定头时发送。

HTTP/1.1 定义了九个响应头:

Accept-Ranges 告诉客户端服务器是否接受使用 Range 请求标题的局部内容请求,以及如果接受,接受哪种类型。例如,包含Accept-Range: bytes表示服务器接受字节范围,而Accept-Range: none表示不支持范围请求。请注意,此标题与其他 Accept-标题不同,这些标题用于 HTTP 请求以执行内容协商。

Age 告诉客户端资源的大致年龄,这是由发送响应的设备计算的。

ETag 指定包含在响应中的实体标签。此值可以在客户端未来的请求中使用,以唯一标识一个实体,使用 If-Match(或类似)请求标题。

位置 指示服务器指示客户端使用的新 URL,以替代客户端最初请求的 URL。此标题通常在服务器使用 301、302 或 307 响应将客户端请求重定向到新位置时使用。它还用于在 PUT 请求的 201(已创建)响应中指示创建的资源的位置。请注意,这与用于指示原始请求资源位置的 Content-Location 实体标题不同。

Proxy-Authenticate 是 WWW-Authenticate 标题的代理版本(将在下面描述)。它包含在 407(代理身份验证所需)响应中,以指示代理如何要求客户端执行身份验证。标题指定了身份验证方法以及身份验证所需的任何其他参数。客户端将使用此信息生成一个包含 Proxy-Authorization 标题的新请求。这是一个跳转-跳转标题。

Retry-After 有时包含在失败的请求中——例如,导致 503(服务不可用)响应的请求——以告诉客户端何时应再次尝试其请求。它还可以与重定向响应(如 301、302 或 307)一起使用,以指示客户端在发送重定向 URL 的请求之前应等待多长时间。Retry-After 标题可以指定一个等待的时间间隔(以秒为单位)或服务器建议客户端再次尝试的完整日期/时间。

服务器 服务器版本的 User-Agent 请求标题。它标识生成响应的服务器软件的类型和版本。请注意,当代理转发响应时,代理不会修改此字段;它们将标识信息放入 Via 标题中。

Vary 指定哪些请求头部字段完全确定缓存是否可以使用此响应来回复后续请求同一资源而不进行重新验证。缓存设备检查 Vary 头部以确定当客户端发出对此次响应中资源的下一个请求时,它需要检查哪些其他头部,以确定它是否可以使用缓存条目进行响应。(有关缓存的更多信息,请参阅第八十四章,这将有助于理解此头部的使用。)

WWW-Authenticate 包含在 401 (未授权) 响应中,以指示服务器希望客户端如何进行身份验证。该头部指定了身份验证方法以及任何其他用于身份验证的参数。客户端将使用此信息生成一个新的请求,其中包含一个授权头部。

小贴士

关键概念 HTTP 响应头部 出现在 HTTP 响应消息中,其中它们提供了有关 HTTP 服务器能力和要求的附加信息,以及处理客户端请求的结果。

HTTP 实体头部

最后,但同样重要的是,我们来到了第四组 HTTP 头部:实体头部。这些头部提供了有关 HTTP 消息主体中携带的资源的信息,在 HTTP 标准中称为 实体。它们服务于传达给消息接收者所需的信息,以便正确处理和显示实体,例如其类型和编码方法。

最常见的实体类型是客户端请求的文件或其他信息集,因此实体头部最常出现在 HTTP 响应消息中。然而,它们也可以出现在 HTTP 请求消息中,特别是使用 PUT 和 POST 方法的请求,这些方法是从客户端向服务器传输数据。

任何携带实体的 HTTP 消息至少应包含一个实体头部。然而,它们也可能出现在某些没有实际实体的响应中。最值得注意的是,对 HEAD 请求的响应将包含与请求中指定的资源相关联的所有实体头部;这些头部与在相同资源上使用 GET 方法而不是 HEAD 方法时包含在实体中的头部相同。实体头部也可能出现在某些错误响应中,以提供帮助客户端成功发出后续请求的信息。

注意

许多实体头部与某些 MIME 头部具有相同的名称,但它们通常以不同的方式使用。请参阅第八十三章中关于 HTTP 互联网媒体类型的主题,以全面了解 HTTP 与 MIME 之间的关系

HTTP/1.1 定义了十个实体头部:

允许 列出特定资源支持的所有方法。此报头可以作为服务器响应的一部分提供,以指导客户端关于将来可以在资源上使用哪些方法。当服务器返回一个包含不支持方法的请求的 405(方法不允许)响应时,必须包含此报头。

内容编码 描述可能已用于编码实体的任何可选方法。此报头最常用于传输已压缩的实体。它告诉接收者使用了哪种算法,以便可以解压缩实体。请注意,此报头仅描述在消息中对实体执行的转换;传输编码报头描述对整个消息执行的编码。有关内容编码和传输编码的更多详细信息,请参阅第八十三章中的讨论。

内容语言 指定用于使用实体的自然(人类)语言。这是一个可选的报头,并且可能不适合所有资源类型。如果需要,可以指定多种语言。此报头旨在提供指导,以便实体可以呈现给正确的受众;因此,应根据谁最能使用材料来选择语言,这不一定包括实体中使用的所有语言。例如,对意大利歌剧的德国分析可能最好只标记为语言 de

内容长度 指示实体的大小(以字节为单位)。此报头很重要,因为它被接收者用来确定消息的结束。然而,只有在可以在传输实体之前完全确定消息长度的情况下才包含此报头。在动态生成内容的情况下,这通常是不可能的,这使消息长度计算复杂化;第八十三章中关于数据长度和分块传输编码的讨论全面探讨了这个问题。

内容位置 指定实体资源的位置,形式为绝对或相对 URL。这是一个可选的报头,通常仅在实体是从与请求中指定的位置不同的位置提供时才包含。如果特定资源存储在多个位置,可能会发生这种情况。

内容-MD5 包含实体的消息摘要 5(MD5)摘要,用于检查消息完整性。

内容范围 当消息包含仅是完整资源的一部分的实体时发送——例如,在包含 Range 标题的 HTTP GET 请求中发送的文件片段。Content-Range 标题指示此消息包含整体文件的哪个部分,以及资源的总大小。此信息以字节范围的形式给出,第一个字节编号为 0。例如,如果实体包含一个 2000 字节文件的第一个 1200 字节,则此标题的值将为 0-1199/2000。

内容类型 指定实体的媒体类型和子类型,其方式与 MIME 中此标题的使用非常相似。参见第八十三章以获取全面讨论。

过期时间 指定一个日期和时间,在此之后,消息中的实体应被视为过时。这可以用来标识某些实体,这些实体在 HTTP 缓存中应比通常更长时间或更短时间保留。如果消息中存在包含 max-age 指令的 Cache-Control 标题,则忽略此标题。

最后修改时间 指示服务器认为实体最后一次被修改的日期和时间。此标题通常用于确定资源自上次检索以来是否已被修改。例如,假设客户端机器已经包含了一个两个月前获得的非常大的文件的副本,并且其用户想要检查文件是否有更新。客户端可以为该文件发送一个 HEAD 请求,并将返回的 Last-Modified 标题的值与其已有的文件副本的日期进行比较。然后,只有在文件已更改的情况下,它才需要请求整个文件。

注意在 Last-Modified 标题的前面描述中使用了“相信”这个词。这种措辞的原因是服务器不能总是确定资源被修改的时间。对于文件来说,这相对简单——通常是操作系统为文件存储的最后一次修改时间。然而,对于其他更复杂的资源,如数据库记录或虚拟对象,确定特定信息最后一次更改的时间可能更困难。在动态生成内容的情况下,Last-Modified 日期/时间可能与整个消息的日期相同,如 Date 字段中指定的。

小贴士

关键概念 HTTP 实体标题 出现在包含消息主体的请求或响应消息中。它们描述了实体的性质,包括其类型、语言和编码,以便接收设备的正确处理和展示。

第八十三章。HTTP 实体、传输、编码方法和内容管理

无标题图片

超文本传输协议(HTTP)的消息头非常重要,因为它们是 HTTP 用来允许设备指定客户端请求和服务器响应细节的机制。然而,这些头信息只是达到目的的手段,目的是将资源(如文件、表单输入和程序输出)从一个设备传输到另一个设备。当一个资源包含在 HTTP 消息体中时,它被称为 实体。HTTP 定义了特殊的规则来规定这些实体的识别、编码和传输方式。

在本章中,我解释了 HTTP 如何处理实体。我首先从一般意义上讨论实体,并查看其内容是如何被识别的。这包括对 HTTP 和多用途互联网邮件扩展(MIME)之间关系的考察。我讨论了实体在客户端和服务器之间传输的问题,以及内容编码和传输编码之间的区别。我描述了与在 HTTP 消息中识别实体长度相关的特殊问题,并详细说明了特殊的分块传输编码和消息尾迹。最后,我描述了设备如何执行内容协商的方法,以及质量值如何允许客户端智能地选择资源的不同变体。

HTTP 实体和互联网媒体类型

超文本传输协议(HTTP)名称中的“text”一词是对 HTTP 传统的提醒。正如我在第八十章中解释的那样,HTTP 最初被创建是为了允许文本文档相互链接。这在当时是有意义的,因为当时网络被创建时,大多数计算都是用文本进行的。因此,HTTP 的第一个版本(HTTP/0.9)只支持一种类型的消息体:纯 ASCII 文本文档。

在 20 世纪 90 年代初期,计算能力和网络性能的迅速增长将信息技术世界从文本转变为多媒体。这些也是网络的成型时期,不久之后,许多用户都希望利用网络的力量来分享不仅仅是文本文件,还有图片、绘图、声音剪辑、电影等等。因此,HTTP 也必须随之发展。从 HTTP/1.0 开始,该协议的开发者做出了重大改变,允许 HTTP 传输和处理比文本多得多的内容。今天,HTTP 实际上更应该被描述为处理 超媒体 而不是 超文本

在 HTTP 中支持许多类型的文件的一个缺点是增加了复杂性。以前,每个消息接收者都知道消息体包含 ASCII 文本;现在任何消息都可能包含许多种类的数据。当 HTTP 扩展到支持灵活的媒体时,它需要一个系统来解决两个具体问题:将各种类型的实体编码到 HTTP 消息体中,并清楚地识别实体特性以便消息的接收者。

当 HTTP 正在改变以支持非文本实体时,另一个重要的 TCP/IP 应用也在从其数十年的文本消息媒介角色转变为能够传输多媒体的角色:电子邮件(email)。这是通过一种称为 MIME 的技术(在第七十六章介绍)实现的,该技术定义了一种编码和标识非文本数据的方法——这正是 HTTP 需要做的。由于 TCP/IP 开发者明智地重用了有效的工作技术,HTTP 的创造者借鉴了 MIME 的许多概念,包括许多用于标识 MIME 消息内容的 MIME 电子邮件头。

媒体类型和子类型

HTTP 从 MIME 中采纳的最重要概念是使用标准化的互联网媒体类型,这些类型描述了 HTTP 实体的内容。HTTP 媒体类型的正式语法与 MIME 中使用的语法相同:

<type>/<subtype> [; parameter1 ; parameter2 … ; parameterN ]

每种媒体类型由一个顶层媒体类型定义其一般性质,以及一个更具体的子类型,该子类型指示其形式或结构。例如,文本文档使用顶层媒体类型 text,子类型包括 plain 用于常规未格式化文本和 html 用于 HTML 文档。因此,使用 HTTP 常见传输的 HTML 文档将被标识为 text/html 媒体类型。同样,image 是一个顶层媒体类型,子类型包括 jpeggiftiff。照片通常被标识为 image/jpeg,而线图通常被看作 image/gif。还可以提供额外的参数,以提供更多信息,帮助接收者解释实体。

HTTP 对媒体类型的运用

在 HTTP 中,媒体类型最常见于特殊的 Content-Type 实体头,该头出现在任何携带实体的 HTTP 消息中。此头使用与 MIME 中同名头的相同格式:

Content-Type: <type>/<subtype> [; parameter1 ; parameter2 … ; parameterN ]

Tip

相关信息 我在第七十六章提供了对内容类型头和互联网媒体类型的更完整描述,包括许多类型和子类型的描述。HTTP 也可以支持复合媒体类型,例如多部分媒体类型

HTTP 中媒体类型被使用的另一个地方是在客户端发送的 HTTP 请求中的 Accept 请求头部。如果存在,此头部的目的是告诉服务器客户端可以处理哪些媒体类型,以便服务器不会发送无法处理的响应。例如,如果客户端只能处理文本文档,它可能会在 Accept 头部中指定这一点。这是 HTTP 支持的整体内容协商过程的一部分,我将在本章后面的“HTTP 内容协商和质量值”部分中描述。

当在 Accept 头部中指定媒体类型时,子类型或类型和子类型都可以用星号 (*) 通配符替换,以表示任何可接受类型。例如,在 Accept 头部中,指定text/html指的是 HTML 文档,而text/*表示任何文本类型。字符串*/*表示任何媒体类型;这通常与一个q值一起使用,如本章后面关于 HTTP 内容协商过程的讨论中所述。

小贴士

关键概念 虽然 HTTP 通常与超文本相关联,但其消息可以传输各种不同类型的文件,包括图像、音频、视频等等。为了指示 HTTP 消息中包含的实体类型,其发送者必须识别其媒体 类型子类型。这是通过使用 HTTP Content-Type 头部来完成的,该头部是从多用途互联网邮件扩展(MIME)规范中借用的。

HTTP 和 MIME 结构之间的差异

除了媒体类型外,HTTP 还在其他几个方面借鉴了 MIME,例如 MIME 的内容编码概念以及使用头部来指示实体的长度。然而,重要的是要认识到,尽管 HTTP 处理互联网媒体的方式与 MIME 非常相似,但它们并不相同。事实上,曾有一个早期建议 HTTP 使用 MIME 的精确定义,但 HTTP 的开发者明确决定不这样做。我们将在下一节探讨 HTTP 不是严格符合 MIME 规范的可能原因。

重要的是,HTTP 的开发者选择了从 MIME 中采用有意义的概念,并省略了其他部分。因此,尽管你可能在 HTTP 消息中看到以 MIME 的 Content-前缀开始的几个头部,但 HTTP 消息并不符合 MIME 规范。例如,尽管 HTTP 有一个 Content-Encoding 头部,但其使用方式与 MIME 的完全不同。HTTP 不使用 MIME 消息中必需的 MIME-Version 头部,这证实了 HTTP 和 MIME 之间的差异。

小贴士

关键概念 尽管 HTTP 从 MIME 中借鉴了几个概念和头部类型,但该协议并不符合 MIME 规范。

HTTP 内容和传输编码

HTTP 必须解决两个具体问题,以便在其消息中携带各种媒体类型:数据编码以及识别其类型和特征。HTTP 从 MIME 借用了媒体类型和 Content-Type 报头的概念,如前所述,以处理类型识别。它还从 MIME 借用了概念和报头来处理编码问题。然而,在这里,我们遇到了 HTTP 和 MIME 之间的一些重要差异。

对 MIME 而言,编码是一个重要的问题,因为它是为了特定的目的而创建的,即使用旧的 RFC 822 电子邮件消息标准(在第七十六章中讨论,Chapter 76)发送非文本数据。RFC 822 对其携带的消息施加了几个重要的限制,其中最重要的是数据必须使用 7 位 ASCII 编码。RFC 822 消息的行长度也限制在最多 1,000 个字符,并以回车/换行(CRLF)序列结束。

这些限制意味着任意二进制文件,它们没有行的概念,由可以包含从 0 到 255 的值的字节组成,不能以它们的原生格式使用 RFC 822 发送。为了使 MIME 能够传输二进制文件,它们必须使用类似 base64(在第七十六章中描述,Chapter 76)的方法进行编码,该方法将三个 8 位字符转换为可以表示在 ASCII 中的四个 6 位字符集。当进行这种转换时,消息中会包含 MIME Content-Transfer-Encoding 报头,以便接收者可以反转编码,将数据恢复到其正常形式。尽管这种技术可行,但它不如直接以二进制形式发送数据高效,因为 base64 编码将消息的大小增加了 33%(三个字节使用四个 ASCII 字符进行编码,每个字符需要一字节来传输)。

HTTP 消息直接在客户端和服务器之间通过传输控制协议(TCP)连接传输,并且不使用 RFC 822 标准。因此,可以在 HTTP 客户端和服务器之间发送二进制数据,而无需进行 base64 编码或其他转换技术。由于发送未编码的数据更高效,这可能是 HTTP 开发者决定不使协议严格遵循 MIME 标准的一个原因。

HTTP 的双层编码方案

因此,编码似乎是一个 HTTP 比 MIME 更简单的领域。不需要对实体进行编码,因此不需要“内容传输编码”标题,所以我们少了一件要担心的事情。确实,HTTP 本可以设计成所有实体一次只发送一个字节,无需指定编码,但协议的开发者认识到这将使协议缺乏灵活性。有些情况下,可能需要转换或编码实体或消息以进行传输,然后在接收时反转操作。

这种使 HTTP 灵活的努力导致了一个表示编码的系统,实际上比 MIME 的更复杂!理解它的关键是认识到 HTTP/1.1 实际上将 MIME 的内容传输编码概念分为两个不同的编码级别:

内容编码 这种编码专门应用于 HTTP 消息中携带的实体,以便在传输之前对其进行准备或打包。内容编码被称为端到端的,因为实体的编码在客户端或服务器发送之前只进行一次,并且仅在最终接收者(服务器或客户端)接收时解码。当进行此类编码时,方法将在特殊的“内容编码”实体标题中标识。客户端还可以通过使用“接受编码”标题来指定它可以处理的内容编码,正如你将在本章后面的内容协商部分中看到的。

传输编码 这种编码专门用于确保数据可以在设备之间安全传输。它应用于整个 HTTP 消息,而不是特定于实体。这种类型的编码是逐跳的,因为对于通过多个中间代理在请求/响应链中传输的消息的每一跳,可能使用不同的传输编码。如果有传输编码方法,它将在“传输编码”通用标题中指示。

内容和传输编码的使用

由于内容编码和传输编码在不同的级别上应用,因此它们可以同时使用。内容编码可以应用于实体,然后将其放入消息中。在用于移动包含该实体的消息的一些或所有跳中,可以对整个消息(包括实体)应用传输编码。首先移除传输编码,然后移除内容编码。

那么,这些编码类型在实际应用中是用来做什么的呢?答案是并不多。HTTP 标准定义了少量内容编码和传输编码,并规定可以通过互联网数字分配机构(IANA)注册额外的编码方法。目前,只有 HTTP/1.1 标准中定义的编码正在使用。

内容编码仅用于实现压缩。这是一个虽然不是严格必要的,但由于它可以显著提高某些类型数据的性能而可能很有用的编码示例。RFC 2616 定义了三种不同的编码算法:

  • gzip,这是由 RFC 1952 描述的 UNIX gzip 程序所使用的压缩方法

  • compress,它也代表了同名 UNIX 程序所使用的压缩方法

  • deflate,这是在 RFC 1950 和 1951 中定义的方法

注意

也可以将压缩应用于整个 HTTP 消息作为传输编码。显然,如果实体已经使用内容编码进行了压缩,这将导致一些工作重复。由于 HTTP 头的大小与 HTTP 消息携带的一些实体相比并不大,通常只需使用内容编码压缩实体就足够简单了

由于传输编码旨在用于使数据安全传输,并且我们已经讨论了 HTTP 可以处理任意二进制数据的事实,这表明传输编码实际上并不是必需的。然而,有一种情况,安全传输确实成为一个问题:识别消息结束的问题。这个问题是下一节的主题。

小贴士

关键概念 HTTP 支持数据传输的两个编码级别。第一个是内容编码,在特定情况下用于转换 HTTP 消息中携带的实体。第二个是传输编码,用于对整个 HTTP 消息进行编码以确保其安全传输。当实体被压缩以提高通信效率时,通常会使用内容编码。传输编码主要用于处理识别消息结束的问题。

HTTP 数据长度问题、分块传输和消息尾迹

如你所知,HTTP 中使用了两种不同的编码级别:内容编码,它应用于 HTTP 实体,以及传输编码,它用于整个 HTTP 消息。内容编码用于方便地将实体打包以进行传输。传输编码是跳数特定的,并且旨在用于需要使数据安全传输的情况。

然而,我们已经看到 HTTP 可以传输任意二进制数据,因此与 MIME 需要使二进制数据安全(如 RFC 822 中定义的)的情况不同,这并不是 HTTP 的问题。因此,为什么传输编码是必需的呢?从理论上讲,它们不是必需的,而且 HTTP/1.0 甚至没有传输编码头(尽管它确实使用了内容编码)。传输编码的概念在 HTTP/1.1 中变得重要,这要归因于该版本 HTTP 的另一个关键特性:持久连接(在第八十章[Chapter 80. HTTP GENERAL OPERATION AND CONNECTIONS]中描述)。

动态数据长度

回想一下,HTTP 使用 TCP 进行连接。TCP 的一个关键特性是它将所有数据作为无结构的字节流传输(参见第四十六章的样本输出所示。

示例 83-1. 使用 Content-Length 头的 HTTP 响应示例

HTTP/1.1 200 OK
Date: Tue, 22 Mar 2005 11:15:03 GMT
Content-Type: text/html
Content-Length: 129
Expires: Sun, 27 Mar 2005 21:12:00 GMT

<html><body><p>The file you requested is 3,400 bytes long and was last modified:
Sun, 20 Mar 2005 21:12:00 GMT.</p></body></html>

使用分块传输而不是一次性发送整个响应,允许服务器在程序中部分响应可用时立即发送它们。使用分块传输的示例 83-1 的等效输出显示在示例 83-2 中。

示例 83-2. 使用分块传输编码的 HTTP 响应示例

HTTP/1.1 200 OK
Date: Tue, 22 Mar 2005 11:15:03 GMT
Content-Type: text/html
Transfer-Encoding: chunked
Trailer: Expires

29
<html><body><p>The file you requested is
5
3,400
23
 bytes long and was last modified:
1d
Sun, 20 Mar 2005 21:12:00 GMT
13
.</p></body></html>
0
Expires: Sun, 27 Mar 2005 21:12:00 GMT

在示例 83-2 中,请注意,Expires 头现在是一个尾部,因此可以根据程序的输出进行计算,并且这由 Trailer: Expires 头指示。记住,Content-Length 头指定长度为十进制数字,而分块传输指定分块长度为十六进制;本例中的分块长度分别为 41、5、35、29 和 19 个十进制字节。

小贴士

关键概念 由于 HTTP/1.1 使用持久连接,允许通过 TCP 连接发送多个请求和响应,因此客户端和服务器需要某种方式来识别一条消息的结束和下一条消息的开始。更简单的解决方案是使用 Content-Length 头部来指示消息的大小,但这仅在可以预先确定消息长度的情况下有效。对于动态内容或其他在发送数据之前无法轻松计算消息长度的案例,可以使用特殊的 分块 传输编码,其中消息体作为一系列块发送,每个块前面都带有块的大小。当使用分块传输编码时,消息发送者可以将某些头部从消息的开始移动到末尾,在那里它们被称为 尾部。尾部被接收者以与正常头部相同的方式解释。特殊的 Trailer 头部用于此类消息,以告知接收者在消息体之后查找尾部。

HTTP 内容协商和质量值

许多互联网资源只有一个表示形式,意味着它们只以一种方式存储或提供。在这种情况下,客户端对服务器的请求是一个全有或全无的提议。客户端可以指定条件,在满足这些条件的情况下,它希望服务器发送资源,使用上一章中描述的 If- 系列请求头部。如果条件得到满足,资源将以服务器存在的一种形式发送;如果条件未得到满足,则不会返回任何实体。

然而,其他资源可能有多个表示形式。最常见的一个例子是可用多种语言的文档,或者使用多个字符集存储的文档。同样,一个图形图像可能存在两种不同的格式:一个用于希望图像质量最大化但图像大小较大的 Tagged Image File Format (TIFF) 文件,以及一个更紧凑的 JPEG 文件,用于那些需要快速查看图像且不太关心其质量级别的人。

为了提供灵活性,允许客户端获取存在于多种形式的最佳资源版本,HTTP/1.1 定义了一系列功能,统称为 内容协商

内容协商技术

HTTP/1.1 标准定义了两种基本方法来执行这种协商。

服务器驱动协商 在这种技术中,客户端在其请求中包含头部信息,为服务器提供关于其期望的资源表示形式的指导。服务器使用一个算法处理这些信息,并提供与客户端偏好最匹配的资源版本。

代理驱动协商 这种方法将客户端置于协商过程的主导地位。它首先向服务器发送一个初步的资源请求。如果资源以多种形式可用,服务器通常会发送一个 300(多种选择)响应,其中包含资源可用的各种表示形式列表。然后客户端发送第二个请求,以获取它偏好的那个。

为了进行类比,假设一个同事提出在午餐时间出去为你们两人买午餐。他将去一家你们都没有吃过的餐厅。你可以给他一些关于你喜好的参数——“我喜欢烤牛肉三明治、炸鱼薯条和披萨,但不吃鸡肉”——然后信任他为你挑选一些你会喜欢的。或者,他可以去餐厅,用手机给你打电话,读菜单给你听,让你做出选择。这种前一种方法类似于基于服务器的协商;后一种方法类似于基于代理的协商。

这个类比不仅指出了两种方法之间的区别,而且还突出了每种方法的关键优缺点。将午餐选择托付给你的同事既简单又高效,但并非万无一失。可能的情况是,餐厅没有你指定的任何菜品,或者你的朋友可能会给你一些含有你不喜欢但忘记提及的另一种成分的东西。同样,基于服务器的协商是一个最佳猜测的过程,并不能保证客户端将以它想要的格式接收到资源。这一点由于客户端只能通过有限的几种方式使用少量请求头来指定其偏好而加剧。

相反,基于代理的协商允许客户端从可用的选项中选择它想要的,就像你可以从餐厅的菜单中选择你最喜欢的菜品一样。这里的问题是它效率不高,因为每个资源访问都需要两个请求和响应。(你真的愿意在电话里读餐厅的菜单给某人听,以便他可以选择他理想的菜品吗?)

在实践中,基于服务器的协商是目前最常用的类型。客户端使用一组四个请求头来指定它对资源表示的偏好。每个头代表资源的一个特征:Accept(媒体类型)、Accept-Charset(字符集)、Accept-Encoding(内容编码)和 Accept-Language(资源语言)。这些头中的任何一个或所有都可以包含在请求中。每个 Accept 头包含一个适当的值列表,这些值与它所指定的特征相匹配,并用逗号分隔。例如,Accept 头列出了客户端认为可接受的媒体类型,而 Accept-Language 包含语言标签。

例如,假设你有一个朋友,她懂英语、法语和西班牙语。她可以用这些语言中的任何一种阅读特定的文档,因此她可能指示她的浏览器在她的请求中包含以下头信息:

Accept-Language: en, fr, sp

小贴士

关键概念 HTTP 包含一个名为 内容协商 的功能,允许选择具有多个表示形式的资源的一个特定变体。有两种协商技术:服务器驱动,其中客户端在其请求中包含表示其需求的头信息,服务器尽力选择最合适的变体,以及代理驱动,其中服务器向客户端发送可用资源替代品的列表,客户端选择其中一个。

偏好权重质量值

为了提高服务器驱动协商的结果,HTTP 允许客户端为列表中的每个项目分配权重,以表明对替代方案的偏好。客户端通过在每个参数后添加一个十进制 质量值 来指定权重,使用语法 q=<value>,这表示该参数相对于其他参数的相对优先级。最高优先级是 1,最低优先级是 0。如果没有指定值,则默认为 1。值为 0 表示客户端不会接受具有该特性的文档。

例如,假设你的三语朋友懂英语、法语和西班牙语,但她的法语有点生疏。此外,她可能需要与只知道一点西班牙语的她的一个朋友分享她请求的文档,因此最好她能收到英文版本的文档。最后,她知道有一个她肯定不想要的资源德语版本。这可以表示如下:

Accept-Language: en, fr;q=0.3, sp;q=0.7, de;q=0

翻译成英语,这意味着:“我更希望您用英语发送文档给我。如果不是,西班牙语也可以,或者如果您只有法语,那就法语吧,但绝对不要用德语发给我。”

顺便提一下,质量值 这个名称是 HTTP 标准中使用的,但实际上这是一个不恰当的术语选择(公平地说,这一点在标准中也有提及)。这些值与质量无关;据我们所知,这份文档的德语版本可能是原始版本,而其他版本可能是糟糕的翻译。q 值仅指定发出请求的客户端的相对偏好。

最后,星号 (*) 通配符可以在 Accept 头字段的家族中使用,以表示任何值或所有其他值。这通常用来告诉服务器:“如果您找不到我具体要求的内容,那么这里是我的替代品偏好。”让我们用一个 Accept 头的例子来说明:

Accept: text/html, text/*;q=0.6, */*;q=0.1

这个标题表示客户端表示:“我的首选是 HTML 文本文档(q=1,默认值,因为没有指定q值)。如果不可用,我更喜欢其他类型的文本文档。如果这些都不行,你可以发送与我请求的资源相关的任何其他类型的文档。”

小贴士

关键概念 服务器驱动的协商是 HTTP 中最常用的类型。发送请求的客户端可以包含最多四个不同的标题,这些标题提供了有关服务器如何填充其请求的信息。这些可能包括可选的质量值,这些值指定了客户端在一系列替代资源特征(如媒体类型、语言、字符集和编码)中的相对偏好。

第八十四章:HTTP 功能、能力和问题

无标题图片

前几章涵盖了超文本传输协议(HTTP)的基本概念和基本操作。然而,现代 HTTP 不仅超越了 HTTP 请求和响应交换的简单机制,还包括了许多功能和能力,这些功能和能力扩展了基本协议,以提高性能并满足使用现代 TCP/IP 互联网的组织的需求。

在本章中,我通过讨论几个对现代万维网操作至关重要的重要问题来完成对 HTTP 的描述。我首先概述了 HTTP 缓存,这是促进 Web 事务效率的最重要功能。我讨论了 HTTP 中代理的不同用途以及与之相关的一些问题。我简要检查了与 HTTP 中的安全和隐私相关的问题,并以讨论状态管理问题以及如何在本质上是无状态的 HTTP 协议中实现它作为结论。

HTTP 缓存功能和问题

互联网的爆炸性增长对用户来说是一个奇迹,但对网络工程师来说却是一场噩梦。互联网创建的最大问题是它运行的互联网的过载。添加到 HTTP/1.1 中的许多功能都是专门设计来提高协议效率并减少 HTTP 请求和响应消耗的不必要带宽的。可以说,其中最重要的是一系列旨在支持缓存的功能。

缓存问题在计算机和网络讨论中反复出现,这是因为在这些技术中广泛观察到的现象:每当用户、硬件设备或软件进程请求特定数据时,有很大可能性在不久的将来会再次请求相同的数据。因此,通过在缓存中存储最近检索到的项目,我们可以消除重复的工作。这就是为什么缓存在诸如地址解析协议(ARP)和域名系统(DNS)等协议的效率中起着重要作用。

HTTP 缓存的益处

缓存对于 HTTP 来说非常重要,因为网络用户往往会反复请求相同的文档。例如,在撰写关于 HTTP 的这一节时,我多次引用了 RFC 2616。每次,我都会从特定的网络服务器上加载它。由于该文档从未改变,直接从本地缓存加载它将更加高效,而不是每次都需要从远程网络服务器检索它。

然而,缓存对于 HTTP 来说甚至比用于其他大多数协议或技术的缓存更为重要。原因是网络文档往往被组织成这样:对一个资源的请求会导致对许多其他资源的请求。即使你加载了多个不同的文档,它们也可能各自引用在请求之间不发生变化的共同元素。因此,即使在用户从未两次请求相同的文档,或者单个文档随时间变化而缓存文档本身价值不大的情况下,HTTP 中的缓存也能带来好处。

例如,假设你每天早上都会加载 CNN 的网站,看看世界上发生了什么。显然,每天的头条新闻都会不同,所以缓存 CNN.com 主页的价值不会很大。然而,页面上的许多图形元素(CNN 的标志、分隔栏、可能是一个“突发新闻”图形等)每天都会相同,并且这些可以缓存。另一个例子是一个网站上的讨论论坛集。当你加载不同的主题来阅读时,每个主题都是不同的,但它们有共同元素(如图标和其他图像),如果需要反复检索,将会造成浪费。

HTTP 中的缓存带来两大主要好处:

  • 通过消除不必要的请求和响应传输,减少带宽使用

  • 加载资源时用户响应时间更快

考虑到如今许多网页上,图像文件的大小往往比引用它们的 HTML 页面要大得多。缓存这些图形将允许整个页面更快地加载。图 84-1

缓存对 HTTP 请求/响应链的影响 此图说明了缓存对请求/响应链的影响(见图 84-1)。在这个例子中,中间件 2 能够从其缓存中满足客户端的请求。这缩短了通信链在两次传输后的长度,这意味着客户端可以更快地获取其资源,并且 HTTP 服务器无需处理客户端的请求。

图 84-1. 缓存对 HTTP 请求/响应链的影响 此图说明了缓存对请求/响应链的影响(见图 80-2 第八十章)。在这个例子中,中间件 2 能够从其缓存中满足客户端的请求。这缩短了通信链在两次传输后的长度,这意味着客户端可以更快地获取其资源,并且 HTTP 服务器无需处理客户端的请求。

缓存的明显优势使其从互联网的早期开始就成为了其中的一部分。然而,直到 HTTP/1.1,缓存在协议本身中的重要性才真正得到认可,并且添加了许多功能来支持它。HTTP/1.0 标准只是简单提及缓存及其相关问题,而 HTTP/1.1 则用 26 页的篇幅专门讨论缓存(占文档主体超过 20%!)。

缓存位置

HTTP 缓存可以在请求/响应链的多个位置实现。选择位置涉及到缓存中始终存在的根本权衡:邻近性与普遍性。简单来说,缓存越靠近信息请求者,从缓存中提取数据而不是从源获取时节省就越多。然而,缓存离请求者越远(因此越接近源),能够从缓存中受益的设备数量就越多。让我们看看这种影响如何在可能发现缓存的三个设备类别中体现出来:网络客户端、中间件和网络服务器。

网络客户端上的缓存

大多数互联网用户熟悉的缓存是本地客户端上的缓存。它通常内置在 Web 浏览器软件中,因此被称为Web 浏览器缓存。这个缓存存储了特定用户最近访问的文档和文件,以便在用户再次请求时可以快速提供。

由于缓存位于用户的机器上,因此请求缓存中包含的项目可以立即得到满足,从而避免了网络事务,并为用户提供即时的满足感。然而,只有该用户能够从缓存中受益,因此有时它被称为私有缓存

中间件上的缓存

位于 Web 客户端和服务器之间的设备,如代理服务器,也经常配备缓存。如果用户想要不在其本地客户端缓存中的文档,中间件可能能够提供它,如图图 84-1 所示。这不如从本地缓存检索高效,但远比回到 Web 服务器要好。

一个优点是,所有使用中间件的设备都可以从其缓存中受益,这种缓存可能被称为公共共享缓存。这可能是有用的,因为组织成员经常访问类似的文档。例如,在一个为在苹果电脑上使用的硬件产品开发组织的例子中,许多人可能正在访问苹果网站上的文档。使用共享缓存,用户 A 的请求通常会缓存可以供用户 B 使用的项目。

Web 服务器上的缓存

Web 服务器本身也可能实现缓存。虽然让服务器维护其自己的文档缓存看起来有些奇怪,但在某些情况下这可能是有益的。资源可能需要大量的服务器资源来创建。例如,考虑一个使用复杂数据库查询生成的网页。如果这个页面被许多客户端频繁检索,那么定期创建并缓存它,而不是为每个请求即时生成,可以带来很大的好处。

由于 Web 服务器缓存距离用户最远,因此缓存命中的节省最少,因为客户端请求和服务器响应仍然必须通过网络在客户端和服务器之间完整路径传输。然而,这个距离对于客户端来说也意味着服务器上的所有用户都可以从缓存中受益。

小贴士

关键概念 提高 HTTP 操作效率的最重要特性是缓存——将最近请求的资源存储在临时区域。如果稍后再次需要相同的资源,它可以从缓存中检索,而不是需要向服务器发出新的请求,从而节省时间和带宽。缓存可以由 Web 客户端、Web 服务器和中间代理执行。缓存离用户越近,效率效益就越大;离用户越远,能从缓存中受益的用户数量就越多。

缓存控制

在客户端和服务器中,缓存的控制方式与 HTTP 中大多数其他类型的控制方式相同:通过使用特殊的首部。其中最重要的是 Cache-Control 通用首部,它包含多个指令,允许管理缓存的操作。还有其他一些重要的与缓存相关的首部,包括 Expires 和 Vary。有关 HTTP 缓存的更多具体信息,请参阅 RFC 2616,第十三部分。

重要缓存问题

虽然缓存的性能优势很明显,但缓存有一个显著的缺点:它在许多方面使 HTTP 的操作复杂化。以下是一些 HTTP/1.1 客户端、服务器和中间代理需要解决的问题。这个列表并不详尽,但它让你了解 HTTP 中缓存涉及的内容。

缓存老化与过时 当用户直接从服务器上的原始源检索文档时,他们可以确保获得该资源的当前版本。当使用缓存时,情况就不再是这样了。虽然许多资源变化不频繁,但几乎所有的资源都会在某个时候发生变化。例如,在 CNN 网站上,CNN 标志不太可能经常改变,但网站可能会定期重新设计,标志可能会以某种方式修改,例如大小或颜色。因此,设备不能无限期地保留 HTTP 缓存中的项目。一个项目在缓存中保留的时间越长——这个过程称为老化——服务器上的资源发生变化并且缓存过时的可能性就越大。更复杂的是,一些资源比其他资源更快地过时。因此,HTTP 中与缓存相关的许多功能都涉及处理这个问题,即缓存老化。

缓存过期与验证 HTTP 处理缓存老化问题的一种方式是通过首部和逻辑,允许缓存、客户端和服务器指定项目在过期并需要刷新之前应该被缓存多长时间。验证过程允许缓存在不适当的时间与服务器检查,以查看它存储的项目是否已被修改。

向用户传达缓存状态 在大多数情况下,一个项目是从缓存而不是其源检索的事实对用户来说是透明的(尽管他们可能会注意到资源加载速度比预期快)。然而,在某些情况下,用户可能需要被告知资源来自缓存而不是原始源。特别是当缓存项可能已过时时,客户端应警告用户信息可能已过时。

头部缓存 HTTP 中的缓存复杂化是由于它可以在多个地方发生,并且某些 HTTP 头部与其他头部处理方式不同。HTTP 头部分为两大类:端到端头部,这些头部旨在伴随资源一直到达其最终接收者,以及跳到跳头部,这些头部仅用于两个设备(客户端、服务器或中间设备)之间的特定通信。端到端头部必须与缓存资源一起存储。跳到跳头部只对特定的传输有意义,不会被缓存。

资源更新的影响 一些 HTTP 方法(在第八十一章 Chapter 81 中讨论)将自动使缓存条目失效,因为这些方法本质上会导致底层资源发生变化。例如,如果用户对一个之前使用 GET 方法检索的资源执行 PUT 操作,那么该资源的任何缓存副本都应该自动失效,以防止从缓存中提供旧版本。

隐私问题 在共享缓存(如代理中可能存在的情况)的情况下,存在潜在的隐私问题。在大多数情况下,让用户 A 的缓存资源对用户 B 可用是有利的,但我们必须小心不要缓存任何可能特定于用户 A、而用户 B 不应该看到的项目。

HTTP 代理服务器和代理

在我对第八十章 Chapter 80 中 HTTP 操作模型的概述中,我描述了 HTTP 是如何被设计来支持不仅客户端和服务器之间的通信,还包括可能位于他们之间通信路径上的中间件的。最重要的一种中间件是称为代理服务器的设备,或者更简单地说,就是代理

代理是一个充当客户端和服务器双重角色的中间人。它像服务器一样接受来自客户端的请求,然后将这些请求(可能对其进行修改)转发到真实服务器,服务器将代理视为客户端。服务器响应代理,代理再将回复转发回客户端。代理可以是透明的,这意味着它们不会修改请求和响应,或者非透明的,如果它们修改消息以提供特定服务。

注意

“透明代理”这个术语也可以用来指代自动插入在客户端和服务器之间——例如组织范围内的防火墙——的代理,而不是用户手动配置的代理

代理的好处

由于代理能够完全处理所有客户端请求和服务器响应,它们在许多情况下都非常有用。它们可以用来实现或增强许多重要功能,例如以下内容:

安全性 代理可以被配置为检查出站请求和入站响应,以解决各种安全问题。例如,可以设置过滤来防止用户请求令人反感的内容,或筛选出有害的回复,例如包含隐藏病毒的文件。

缓存 如您之前所见,在中介上设置共享缓存是有利的,这样请求的资源就可以提供给另一个客户端。这可以在代理服务器中完成。

性能 在某些情况下,使用代理服务器可以显著提高性能,尤其是通过减少延迟。

代理服务器如何提高性能的一个很好的例子是,我的卫星互联网连接是如何使用代理的。由于地球到卫星的距离,我的 PC 和我的互联网服务提供商(ISP)之间的往返请求/响应周期需要超过 500 毫秒。如果我加载包含图像的网页,我需要等待 500+毫秒才能获取 HTML 页面,然后我的浏览器需要为每个图形元素生成新的请求,这意味着每个图形元素又会有 500+毫秒的延迟。相反,我的 ISP 有一个代理服务器,我将我的网页请求发送给它。代理服务器会查看这些页面的 HTML,并自动为我请求任何元素,例如图形。然后,它将这些元素直接发送回我的机器,从而大大减少了显示完整网页所需的时间。

小贴士

关键概念 HTTP 中最重要的一种中介设备是代理服务器,它充当客户端和服务器之间的中间人,处理请求和响应。代理服务器可能传输未更改的消息,也可能修改它们以实现某些功能和能力。代理通常用于提高 Web 访问的安全性和/或性能。

比较代理和缓存

代理和缓存是具有许多相似性的概念,尤其是在它们对基本 HTTP 操作的影响方面。像缓存一样,代理在近年来变得更加重要,并且它也在许多方面使 HTTP 变得复杂。HTTP/1.1 标准包括许多特定功能来支持代理,同时也解决了与代理相关的一些问题。

代理和缓存都代表了基本 HTTP 客户端/服务器通信发生变化的方式,加上代理执行缓存的能力,有时会导致人们认为缓存和代理是相同的,这并不正确。代理是一个位于 HTTP 请求/响应链中的独立元素。缓存可以在该链中的任何设备中实现,包括代理。

缓存和代理之间另一个关键的差异是,当启用时,缓存会自动使用,但代理不会。要使用代理,客户端软件必须被告知使用代理,并提供了其 IP 地址或域名。然后客户端将所有请求发送到代理,而不是用户指定的实际服务器。

注意

我这里的许多解释都集中在硬件代理服务器上,但代理也通常在客户端设备中作为软件实现。软件代理执行处理请求和响应的相同任务。与硬件代理相比,软件代理的实现成本要低得多,但它不能被许多设备共享

重要代理问题

与缓存一样,当在 HTTP 中使用代理时,也会出现问题。以下是一些更重要的问题。(有关代理的更多信息,请参阅 RFC 2616)。

能力不一致问题 当客户端和服务器不使用相同的 HTTP 版本或不支持相同的功能时,会出现问题。例如,一些服务器可能不支持客户端尝试使用的所有方法。当代理介入时,这个问题变得更加复杂。特别需要注意的是,客户端和服务器可能就某个代理不支持的功能达成一致。代理必须确保它传递了它可能不理解的头信息或其他元素。

认证要求 使用代理服务器通常会引入新的认证或安全要求。除了对端服务器进行认证外,代理可能还指定客户端需要向它提供单独的认证凭据。这是通过 HTTP Proxy-Authorization 和 Proxy-Authenticate 头信息实现的,如本章下一节所述。

缓存交互 不仅缓存和代理都会使 HTTP 复杂化,它们还可以相互复杂化。在处理缓存时,许多问题(如头信息缓存、过期和验证)在涉及代理时变得更加复杂。一些 Cache-Control 通用头指令是针对代理的。另一个问题是,同时使用代理和缓存可能导致对 Web 资源访问次数的明显数量扭曲。在网页由广告支持的情况下,这些广告基于页面访问次数,这种情况尤为重要。在某些情况下,在 URL 中放置称为缓存破坏者的特殊代码,以强制页面不被存储在共享缓存中。

编码 内容编码(在第八十三章讨论,Chapter 83 中的注释)请求头部是一把双刃剑。对于运营网站的人来说,它非常有用,因为它让他们可以看到指向其资源的链接来源。同时,它也可能被那些可能利用它来研究用户网络访问模式的人滥用。HTTP 标准也提出了潜在的隐私问题。例如,用户可能不希望引用公共网页的私有文档的名称通过 Referer 头部传输。

确保 HTTP 隐私的方法

如前所述,HTTP 不包含任何保护传输文档或消息隐私的机制。通常有两种不同的方法来完成这项任务:

加密 最简单的方法是在服务器上加密资源,并且只向授权用户提供有效的解密密钥。即使整个消息被截获,实体本身仍然会被保护。这里的保护水平取决于加密的质量。

安全套接字层(SSL) 另一种更常见的方法是使用专门设计来确保 HTTP 事务隐私的协议。今天经常使用的一种称为安全套接字层(SSL)。服务器使用 SSL 来保护敏感资源,例如与金融交易相关的资源。在支持该协议的网页浏览器中,它们通过使用 URL 方案https而不是http来访问。SSL 最初由 Netscape 开发,现在在互联网上被广泛使用。

使用 Cookies 进行 HTTP 状态管理

尽管现代 HTTP 有很多功能和特性,但它的核心仍然是一个简单的请求/回复协议。由此产生的一个不幸问题是 HTTP 是完全无状态的。这意味着每次服务器从客户端收到一个请求时,它都会处理该请求,发送一个响应,然后忘记该请求。来自客户端的下一个请求被视为与之前的请求无关。

注意

HTTP/1.1 的持久连接功能(在第八十章中描述,见第八十章)并没有改变协议的无状态性质。尽管可以在单个传输控制协议(TCP)连接上发送多个请求和响应,但它们仍然不被视为以任何方式相关

那么为什么 HTTP 的无状态性会成为一个问题呢?这难道不是我们对于一个旨在允许客户端快速高效地从服务器检索资源的协议的期望吗?好吧,这又是 HTTP 的行为与其最初的设计用途非常契合,但并不适应今天网络使用方式的另一个例子。当然,如果我们只是想告诉服务器,“嘿,请给我那里的文件”,那么服务器不需要关心它是否以前已经向该客户端提供了其他文件。这就是 HTTP 最初被设计成这样使用的。

今天,网络已经不仅仅是一个简单的资源检索协议。如果你去在线商店,你希望能够选择多个商品放入“购物车”,并且商店的服务器能够记住它们。你也可能想参与一个讨论论坛,这要求你提供用户名和密码才能发帖。理想情况下,服务器应该让你登录一次,然后记住你是谁,这样你就可以发很多帖子,而不需要每次都输入登录信息。(我使用过需要每次都输入登录信息的论坛——这很快就会变得很烦人,相信我。)

对于这些和其他交互式应用,HTTP 的无状态特性是一个严重的问题。解决方案是添加一种名为状态管理的新技术,它允许客户端与服务器之间的会话状态在一系列 HTTP 事务中保持。最初由网景开发,这项技术后来在 RFC 2109 中正式成为互联网标准,后来在 RFC 2965 中进行了修订,“HTTP 状态管理机制”。这个特性实际上不是 HTTP 的一部分;它是一个可选元素,但由于其有用性,大多数网络浏览器都实现了它。

状态管理的理念非常简单。当服务器实现一个需要在一系列事务中维护状态的功能时,它会向网络客户端发送一小块数据,称为饼干。饼干包含与特定网络应用相关的关键信息,例如客户姓名、购物车中的商品,或用户名和密码。客户端将信息存储在饼干中,然后在随后的请求中将其用于设置饼干的服务器。然后,服务器可以根据新请求中的信息更新饼干,并将其发送回客户端。通过这种方式,状态信息可以无限期地保持,使客户端和服务器能够保持一段时间的记忆。

注意

饼干可能听起来有些奇怪,但在某些上下文中,它被用来指代一小块重要的数据。另一个例子可以在引导协议(BOOTP)和动态主机配置协议(DHCP)的消息格式中找到。今天,如果你提到“HTTP 状态管理机制”,大多数有知识的网络用户可能会对你皱眉,但他们通常知道什么是饼干

饼干的問題

饼干听起来是个不错的想法,对吧?饼干对于许多使网络成为今天这样强大动力的应用来说绝对是必不可少的。在线购物和讨论论坛只是从饼干中受益的众多交互式应用中的两个。大多数时候,饼干被用于这些有用且良性的目的。不幸的是,有些人通过找到滥用它们的方法,将饼干转向了“黑暗面”。即使没有恶意意图,饼干也可能存在潜在问题。因此,饼干相当有争议。

这里有一些关于饼干的问题:

敏感信息的传输 假设你使用在线银行系统。你登录到服务器,服务器随后将你的用户名和密码(控制对账户的访问)存储在饼干中。如果应用程序没有谨慎实现,包含该饼干的短信可能会被截获,从而让某人能够访问你的账户。即使没有被截获,一个有知识的、能够访问你的电脑的人也可能从存储饼干信息的文件中检索到信息。

Cookies 的不当使用 理论上,Cookies 应该对用户有帮助,而不是阻碍。然而,任何服务器都可以出于任何原因设置 Cookies。在某些情况下,服务器可能会设置 Cookies 以追踪用户访问的网站,这被一些人视为侵犯隐私。由于一些网络浏览器在设置 Cookies 时不会通知用户,用户甚至可能没有意识到这种情况正在发生。

第三方或非故意设置的 Cookies 当大多数人认为 Cookies 是在请求特定资源时设置的,但实际上,任何服务器都可以在用户发送请求时设置 Cookies,无论用户是否意识到这一点。假设你向www.myfavoritesite.com/index.htm/发送了一个请求,并且该页面包含了一个位于服务器www.bigbrotherishere.com/上的小图像的引用。第二个网站可以在你的机器上设置一个 Cookies,即使你从未打算访问它。这被称为第三方 Cookies

小贴士

关键概念 HTTP 是一个本质上无状态的协议,因为服务器独立地处理来自客户端的每个请求,忘记所有之前的请求。HTTP 的这个特性对于大多数常规的 Web 使用来说不是问题,但对于需要服务器在一段时间内跟踪用户信息的交互式应用程序(如在线购物)来说是一个问题。为了支持这些应用程序,大多数 HTTP 实现包括一个可选功能,称为状态管理。当启用时,服务器向客户端发送一小块信息,称为Cookies,该信息存储在客户端机器上。Cookies 中的数据在随后的每个请求中返回给服务器,允许服务器更新它并将其再次发送回客户端。因此,Cookies 使服务器能够在请求之间记住用户数据。然而,由于与它们的使用相关的某些潜在的隐私和安全问题,它们是有争议的。

管理 Cookies 的使用

描述 Cookies 状态管理技术的 RFC 详细讨论了这些问题以及其他问题,但并没有明确的解决方案。像大多数安全和隐私问题一样,潜在 Cookies 滥用的重要决定因素是您个人的舒适度。每天有成千上万的人浏览网络,允许任何网站设置他们想要的 Cookies,并且从未遇到问题。其他人认为 Cookies 是一种侵犯性的想法,并禁用了所有 Cookies,这消除了隐私问题,但可能会影响像交互式网站这样的有用应用程序。通常,最好的方法通常是折中方案,即您选择何时以及如何允许设置 Cookies。

cookie 控制的程度在很大程度上取决于您的网络客户端软件的质量和功能集。许多浏览器在如何和何时设置 cookies 方面提供的控制能力有限;而其他浏览器在这方面则要好得多。一些浏览器允许禁用 cookies,但默认情况下它们是开启的。由于许多人甚至没有意识到与 cookies 相关的问题,他们没有意识到 cookies 正在被发送。在这方面最值得注意的是流行的 Microsoft Internet Explorer,它通常默认设置为接受所有 cookies,没有任何抱怨或评论。

Internet Explorer 允许您禁用 cookies,但您必须自己操作。它还允许您区分第一方和第三方 cookies,但同样,您必须手动开启这个功能。其他浏览器有更复杂的设置,这可以让您规定 cookies 可以设置的条件和不可以设置的条件。一些浏览器甚至允许您允许某些网站发送 cookies,同时禁止其他网站发送。更好的浏览器还会让您能够直观地检查 cookies,并选择性地清除您不希望在您的机器上的 cookies。

第三方 cookies 可以被在线广告公司和其他公司用来追踪网络用户访问的网站。因此,许多人认为它们属于一类不希望使用的软件,即所谓的间谍软件。有许多工具可以帮助您识别和从您的计算机中删除跟踪 cookies;许多工具在网络上都是免费提供的。

第三部分-9. 其他文件和消息传输应用

第八十五章

第八十六章

本书的前三部分已经探讨了几个最广泛使用的 TCP/IP 文件和消息传输协议:文件传输协议(FTP)、简单文件传输协议(TFTP)、电子邮件(email)和万维网。当然,今天互联网上使用的其他应用有成百上千,我们不可能在这里全部考察。然而,还有一些其他协议被认为是 TCP/IP 经典应用组的一部分,如 FTP、电子邮件和万维网,我认为它们值得讨论。

本部分包含两章,涵盖了这些其他文件和消息传输应用。第一章描述了 Usenet(网络新闻),这是互联网上最早的群组通信方法之一。第二章描述了 Gopher 协议,尽管今天不再广泛使用,但仍有简要讨论的价值,尤其是由于其作为万维网历史先导的角色。

第八十五章. USENET(网络新闻)和 TCP/IP 网络新闻传输协议(NNTP)

无标题图片

电子邮件(email)是现代互联网上消息传输的支柱之一,但它实际上仅设计用于相对较小的一组特定用户之间的通信。有许多情况下电子邮件并不理想,例如当需要在大批参与者之间共享信息时,其中并非所有参与者都必然相互认识。一个典型的例子是共享新闻。在这种情况下,提供新闻的人通常希望让任何感兴趣的人都能获得,而不是指定一组特定的收件人。

为了在互联网上分发新闻和其他类型的通用信息,创建了一个名为Usenet网络新闻的消息系统。像电子邮件一样,这个应用允许大量用户编写和阅读消息。然而,它使用了一个与电子邮件非常不同的模型——一个专注于公共共享和反馈的模型。在 Usenet 中,任何人都可以编写可以被任何数量收件人阅读的消息,任何人都可以对其他人编写的消息做出回应。Usenet 是第一个广泛部署的基于互联网的群组通信应用之一,它已经发展成为世界上最大的在线社区之一,被数百万人们用于分享信息、提问和讨论数千个不同的话题。

在本章中,我详细介绍了 Usenet 和网络新闻,讨论了它们的使用方式和工作原理。我提供了 Usenet 的概述和历史,对其通信模型以及消息的创建和操作进行了高级概述,解释了 Usenet 新闻组,并描述了 Usenet 消息格式和标题。然后,我详细描述了网络新闻传输协议(NNTP)的操作,这是现代 Usenet 上传输消息的手段。通常从协议概述开始,然后解释 NNTP 的两种基本使用方式:在服务器之间传播新闻文章以及客户端文章的发布和访问。从那里,我继续介绍 NNTP 命令、命令扩展、响应和响应代码的技术细节。

小贴士

背景信息 Usenet 的工作方式在许多方面与电子邮件所使用的标准和技巧密切相关。如果你还没有阅读第三部分-7,该部分涵盖了电子邮件,我建议你至少回顾一下第七十四章中的电子邮件系统概览以及第七十六章中关于电子邮件消息格式的讨论,因为 Usenet 消息是基于 RFC 822 电子邮件消息标准的。

Usenet 概述、历史和操作

在电子邮件是现代手写信件或办公室备忘录的等价物时,Usenet 则是公司通讯、食堂公告板、咖啡休息时间聊天以及饮水机旁闲聊的更新版,所有这些都被整合在一起。通过互联网在全球范围内传播,Usenet 新闻组消息为具有共同兴趣的人们提供了一个形成在线社区的手段,以讨论事件、解决问题、相互提供支持,以及进行普通的社交和娱乐活动。

我们天生就是高度社交和富有创造力的动物,因此我们总是在寻找新的沟通方式。计算机首次连接起来后不久,人们就认识到这些互连提供了将人们联系起来的手段。使用计算机创建一个 在线社区 的愿望导致了 Usenet 在二十多年前被创造出来。

Usenet 历史

与几乎所有与网络相关的事物一样,Usenet 的起点非常简陋。1979 年,Tom Truscott 是北卡罗来纳州杜克大学的学生,那个夏天他在贝尔实验室实习,UNIX 操作系统就是在这里诞生的。他非常喜欢这段经历,以至于当他秋天回到学校时,他怀念贝尔实验室密集的 UNIX 环境。他使用 Unix-to-Unix Copy Protocol (UUCP) 将信息从他的本地机器发送到其他机器,反之亦然,包括建立回贝尔实验室的电子连接。

建立在这样一个想法的基础上,Truscott 和他的杜克同学 Jim Ellis 与杜克大学和附近的北卡罗来纳大学教堂山分校(UNC)的 UNIX 热衷者合作,共同发展在线社区的想法。目标是创建一个系统,让学生可以使用 UNIX 编写和阅读消息,以便他们能够获得技术帮助并保持社交联系。他们根据一个类比于对所有连接系统用户开放的在线新闻简报来设计这个系统。为了共享信息,消息被发布到 新闻组 中,任何用户都可以访问这些消息来阅读和回复。

杜克大学和 UNC 的早期工作导致了最初的消息格式和该系统最早版本软件的开发,这些软件既被称为 网络新闻(net news),也被称为 UsenetUser's network 的缩写)。最初,该系统只有两台计算机,共享一对不同新闻组中发布的消息。然而,系统的价值立即得到了认可,很快就有许多新的站点被添加到系统中。这些站点被组织成一个结构,以便使用直接的 UUCP 连接有效地传递消息。用于传递新闻文章的软件也继续发展,变得更加功能强大,阅读和编写文章的软件也是如此。

新闻组本身也随着时间的推移而发生了变化。许多新的新闻组被创建,并定义了一个分层结构来帮助以有意义的方式组织新闻组。随着更多站点和用户加入 Usenet,识别出了更多兴趣领域。如今,Usenet 新闻组数量惊人:超过 100,000 个。虽然其中许多组未被使用,但成千上万的活跃组讨论了几乎所有可以想象的主题——从太空探索到烹饪,从生物化学到 PC 故障排除,再到养马。还有一些针对特定地区的区域新闻组;例如,有一组新闻组用于讨论加拿大的事件,另一组用于讨论纽约地区的事件,等等。

Usenet 运作和特点

Usenet 始于一个用户编写要分发的消息。在消息被“发布”到 TCP/IP 网络组之后,它被存储在该用户的本地新闻服务器上,并且特殊的软件会将它的副本发送到其他连接的新闻服务器。消息最终在世界范围内传播,任何选择阅读 TCP/IP 网络新闻组的任何人都可以看到这条消息。

Usenet 真正的力量在于,在阅读一条消息后,任何用户都可以在同一新闻组中对此做出回应。就像原始消息一样,回复会传播到每个连接的系统,包括原始消息作者的使用的系统。这使得 Usenet 在分享关于最近发生的事情的信息、进行社交讨论以及特别是在解决技术故障或寻求饮食计划帮助等问题上非常有用。

Usenet 特别有趣的地方在于,它根本不是一种形式化的系统,也不基于任何正式定义的标准。它是系统完全按即兴方式发展的一个经典例子:软件被创建,人们开始使用它,软件被改进,然后事情就从这个基础上发展起来。已经编写了一些标准来规范 Usenet 的工作方式——例如 RFC 1036,它描述了 Usenet 的消息格式——但这些更多地作为历史文件,而不是规范性标准。

同样,没有中央权威机构负责 Usenet 的运作,尽管新用户常常认为有一个。与拨号公告板系统或基于网络的论坛不同,Usenet 仅仅是通过站点之间的合作来运作的;没有负责人。因此,Usenet 有时被称为无政府状态,但这并不准确。并不是说没有规则。参与系统的管理者负责做出政策决定,例如支持哪些新闻组。系统也有一定的独裁性质,只有某些人(通常是系统管理员)可以决定是否创建某些类型的新闻组。系统还有社会主义元素,即机器所有者被期望相互分享消息。因此,简化的政治标签实际上并不适用于 Usenet。

每个社区都有一种文化,在线社区也是如此,包括 Usenet。有一个整体文化规定了在 Usenet 上可接受的行为,还有成千上万的新闻组特定文化,这些文化在多年的参与者写作中逐渐发展起来。甚至还有专门解释 Usenet 本身如何运作的新闻组,在那里你可以了解新手(新用户)、网络礼仪(发布消息的礼仪规则)和相关主题。

Usenet 传输方法

正如我之前所说的,Usenet 消息最初是通过 UUCP 传输的,UUCP 是为了让 UNIX 系统直接通信而创建的,通常使用电话线。多年来,所有 Usenet 消息都是通过计算机化的电话从一台机器发送到另一台机器(就像电子邮件曾经一样)。每个加入网络的计算机都会连接到已加入 Usenet 的计算机,并定期接收来自它的消息流。该计算机的所有者必须同意向其他计算机提供消息。

20 世纪 80 年代开发 TCP/IP 以及互联网发展到一定规模和范围后,开始使用它来传递 Usenet 消息而不是 UUCP 是有意义的。网络新闻传输协议(NNTP)专门开发出来,用于描述在传输控制协议(TCP)上传递 Usenet 消息的机制。它于 1986 年正式定义在 RFC 977 中发布,NNTP 扩展在 2000 年 10 月发布的 RFC 2980 中描述。

多年来,Usenet 使用 NNTP 和 UUCP 两种方式传递信息,但现在 NNTP 是用于绝大多数 Usenet 流量的机制,因此也是我讨论 Usenet 时的主要焦点。NNTP 不仅用于将 Usenet 文章分发到各个服务器,还用于其他客户端操作,如发布和阅读消息。因此,它在 Usenet 消息通信的大部分步骤中都被使用。

注意

许多人常常将整个 Usenet 系统等同于用于在互联网上传递 Usenet 消息的 NNTP 协议。然而,它们并不相同;Usenet 早于 NNTP,NNTP 仅仅是一个用于传递 Usenet 消息的协议。

正是因为 NNTP 和互联网在当今 Usenet 中传递信息中的关键作用,这些概念常常被混淆。然而,记住这一点是至关重要的:Usenet 并不指代任何类型的物理网络或互连技术;相反,它是一个用户的逻辑网络。这个逻辑网络已经从 UUCP 数据传输演变为 NNTP 和 TCP/IP,但 Usenet 本身并没有改变。

现在,Usenet 面临着来自许多其他群组消息应用和协议的竞争,包括基于 Web 的公告板系统和聊天室。然而,经过 25 年的时间,Usenet 已经确立了自己,并且每天都有数百万人在使用它。虽然对一些人来说,主要基于文本的媒介看起来过时,但它仍然是全球群组通信的主要支柱,并且在未来许多年里可能会继续如此。

提示

关键概念 最早的在线电子社区之一是在 1979 年由希望保持联系并分享新闻和其他信息的大学学生建立的。今天,Usenet(用户网络),也称为 网络新闻,已经发展成为一个覆盖全球的逻辑网络。通过在 Usenet 新闻组中发布消息,人们可以在各种感兴趣的主题上共享信息。Usenet 最初是以在参与主机之间建立直接连接的形式实现的。今天,互联网是消息传输的工具。

Usenet 通信模型

当杜克大学的学生决定创建他们的在线社区时,电子邮件已经被广泛使用,并且有许多邮件列表在运行。在这些互联网之前的年代,电子邮件通常使用 UUCP 传输——这是 Usenet 设计要采用的方法。那么为什么不简单地使用电子邮件在站点之间进行通信呢?

主要原因是电子邮件并未设计用于促进创建一个可以轻松在群组中共享信息的在线社区。在这方面,电子邮件的主要问题是只有被指定为消息接收者的个人才能阅读它。没有一种设施可以让某人撰写消息并将其放置在公开的地方供任何人阅读,类似于在公共场所张贴通讯稿。

在大型群组中,电子邮件的另一个问题与效率相关。考虑一下,如果你将 1,000 人列入邮件列表,发送给该列表的每条消息都必须复制并交付 1,000 次。早期的网络在带宽和资源方面有限,因此使用电子邮件进行大规模的群组通信是可能的,但远非理想。

小贴士

关键概念 虽然电子邮件可以用于群组通信,但它有两个重要的限制。首先,必须将消息专门发送给每个接收者,这使得公共消息传递变得不可能。其次,每个接收者都需要接收消息的单独副本,因此向多个接收者发送消息需要使用大量的资源。

Usenet 的公共分发导向

为了避免使用电子邮件进行群组消息传递的问题,Usenet 采用了一种与电子邮件截然不同的通信和消息处理模型。Usenet 通信模型与电子邮件模型之间的主要区别在于,Usenet 的消息处理是以 公共分发 的概念为中心,而不是向单个用户进行私人投递。这影响了 Usenet 通信的各个方面,如下所述:

地址 消息不是从发送者指向任何特定的接收者或接收者组,而是指向一个 群组,该群组与新闻组名称相对应。

存储 消息不是存储在个人邮箱中,而是在服务器上的一个中央位置,任何服务器用户都可以访问它们。

交付 消息并非从发送者的系统传递到接收者的系统,而是通过互联网传播到所有连接的系统,因此任何人都可以阅读它们。

Usenet 通信过程

为了更详细地说明 Usenet 通信的工作原理,让我们看看撰写、传输和阅读典型 Usenet 消息(也称为 文章——这两个术语可以互换使用)所涉及的步骤。假设这个过程从用户 Ellen 在 newsgroup misc.rural 上发布一个关于生病的马匹求助请求开始。由于她是发布消息的人,因此她会被认为是消息的 发布者。简化地说,这个过程(如图 85-1 通信模型 此图说明了在现代 Usenet 上使用 NNTP 创建、传播和阅读消息的方法;在某些方面与第七十四章中的电子邮件模型图(图 74-1)相似。在这个例子中,消息由发布者 Ellen 创建,并由读者 Jane 阅读。这个过程从 Ellen 在编辑器中创建消息并发布开始。她的 NNTP 客户端将其发送到她的本地 NNTP 服务器。然后,该消息从本地服务器传播到相邻的服务器,通常包括其上游服务器,用于将消息发送到整个互联网。其他 NNTP 服务器接收该消息,包括来自 Jane 本地服务器上游的服务器。它将消息传递给 Jane 的本地服务器,Jane 使用 NNTP 客户端访问并阅读该消息。Jane 可以回复该消息;在这种情况下,相同的流程会重复,但方向相反,回到 Ellen(以及成千上万的其他读者,此处未显示)") 的步骤如下:

  1. 文章撰写 Ellen 首先创建一个 Usenet 文章,该文章的结构符合 Usenet 所需的特殊消息格式。这条消息与电子邮件消息类似,因为它有一个 标题 和一个 正文。正文包含要发送的实际消息,而标题包含描述消息并控制其传递方式的标题行。例如,一条重要的标题行指定了文章针对哪个新闻组。

  2. 文章发布和本地存储 在完成她的文章后,Ellen 将文章提交到 Usenet,这个过程称为 发布。Ellen 电脑上的客户端软件程序将 Ellen 的消息传输到她的本地 Usenet 服务器。该消息存储在该服务器上适当文件存储区域。现在,所有决定阅读 misc.rural 的该服务器用户都可以立即访问它。

  3. 文章传播 到目前为止,Ellen 的本地服务器是唯一拥有她消息副本的服务器。文章必须发送到其他网站,这个过程称为 分发,或者更常见的是,传播。Ellen 的消息从她的本地 Usenet 服务器传播到她直接连接的其他服务器。然后,这些服务器将其传播到它们连接的其他服务器,依此类推,直到所有想要该消息的 Usenet 服务器都有其副本。

  4. 文章访问和检索 由于 Usenet 文章存储在中央服务器上,为了阅读它们,必须在服务器上访问。这通过使用 Usenet 新闻阅读器 程序来完成。例如,名为 Jane 的其他 misc.rural 阅读者可能会访问该组并找到 Ellen 的消息。如果 Jane 能够帮助 Ellen,她可以通过发布自己的文章来回复 Ellen。这样,文章就会传播回 Ellen 的服务器,在那里她可以阅读并回复。所有其他 misc.rural 的读者也可以随时加入对话,这也是 Usenet 对群体沟通非常有用的原因。

Usenet (网络新闻) 通信模型 此图说明了使用现代 Usenet 上的 NNTP 创建、传播和读取消息的方法;在某些方面与电子邮件模型图(见 )相似。在这个例子中,消息是由发布者 Ellen 创建并由阅读者 Jane 读取的。这个过程从 Ellen 在编辑器中创建消息并发布开始。她的 NNTP 客户端将其发送到她的本地 NNTP 服务器。然后,从该本地服务器传播到相邻的服务器,通常包括其上游服务器,用于将消息发送到整个互联网。其他 NNTP 服务器接收消息,包括 Jane 本地服务器上游的服务器。它将消息传递给 Jane 的本地服务器,Jane 使用 NNTP 客户端访问并读取消息。Jane 可以回复消息;在这种情况下,相同的流程会重复,但方向相反,回到 Ellen(以及也回到成千上万的其他读者,此处未显示)

图 85-1. Usenet(网络新闻)通信模型 此图说明了在现代 Usenet 上使用 NNTP 创建、传播和读取消息的方法;在某些方面与第七十四章中的电子邮件模型图(图 74-1 相似(第七十四章)。在这个例子中,消息是由发帖者 Ellen 创建并由读者 Jane 阅读的。这个过程从 Ellen 在编辑器中创建消息并发布开始。她的 NNTP 客户端将其发送到她的本地 NNTP 服务器。然后,该本地服务器将其传播到相邻的服务器,通常包括其上游服务器,用于将消息发送到整个互联网。其他 NNTP 服务器接收该消息,包括来自 Jane 本地服务器的上游服务器。它将消息传递给 Jane 的本地服务器,Jane 使用 NNTP 客户端访问并阅读该消息。Jane 可以回复该消息;在这种情况下,相同的流程会重复,但方向相反,回到 Ellen(以及成千上万的其他读者,此处未显示)。

小贴士

关键概念 Usenet 通信包括四个基本步骤。首先,消息被编写并发布到发件人的本地服务器。第三步是传播,其中消息从原始服务器传输到 Usenet 系统上的其他服务器。过程的最后一步是文章检索,其中新闻组的其他成员访问并阅读该文章。网络新闻传输协议(NNTP)是用于将 Usenet 文章从一个主机移动到下一个主机的技术。

消息传播与服务器组织

传播无疑是 Usenet 通信过程中最复杂的一部分。在过去,使用 UUCP 进行传播。每个 Usenet 服务器都会被编程为定期拨号连接到另一个服务器,并将自上次连接以来收到的所有新文章发送给它。文章会从一台服务器“泛滥”到另一台服务器。这既耗时又低效,而且之所以能工作,仅仅是因为文章的数量相对较少。

正如我在上一节中提到的,在现代 Usenet 中,NNTP 用于设备之间传输消息的所有阶段。文章是通过客户端机器和本地服务器之间的 NNTP 连接发布的,然后本地服务器使用相同的协议将文章传播到其他相邻的 NNTP 服务器。客户端新闻阅读软件也使用 NNTP 从服务器检索消息。

NNTP 服务器通常按照某种等级结构排列,最大的和最快的服务器为下游的较小服务器提供服务。根据连接的安排方式,一个 NNTP 服务器可能会立即与上游服务器建立连接,以便发送新发布的文章到其他 Usenet 服务器进行分发,或者服务器可能会被动等待上游服务器的连接来询问是否有新文章需要发送。在现代互联网的速度下,文章从一个服务器传播到另一个服务器通常只需要几分钟(或几秒钟),即使是在跨越大陆的情况下。

还可以限制 Usenet 消息的传播,这是一种常用于仅在特定地区或系统上相关的讨论的技术。讨论农村问题,如马匹,具有普遍兴趣,Ellen 可能在世界上任何地方都能找到帮助,因此她的消息的全球传播是有意义的。然而,如果 Ellen 住在波士顿地区,并且对了解一家好当地餐厅的位置感兴趣,那么只在本地区域发布查询到ne.food(新英格兰食品讨论)将更有意义。还有一些公司使用 Usenet 提供“内部”新闻组,这些新闻组根本不会从本地服务器传播出去。然而,由于现在许多新闻提供商都是全国性或国际性的,限制消息的传播在很大程度上已经不再流行。

Usenet 寻址:新闻组

Usenet 通信中的一个关键概念是新闻组。新闻组是 Usenet 的寻址机制,将 Usenet 文章发送到新闻组相当于将电子邮件发送到电子邮件地址。新闻组类似于其他群组通信场所,如邮件列表、聊天室、互联网中继聊天(IRC)频道或公告板系统(BBS)论坛(尽管将新闻组称为列表房间频道BBS可能会引起 Usenet 老用户的负面反应!)。

与任何寻址机制一样,新闻组必须是唯一可识别的。每个新闻组都有一个新闻组名称,它描述了新闻组的话题并将其与其他新闻组区分开来。由于有数以千计的不同新闻组,它们被组织成称为等级结构的集合。每个等级结构包含一个相关新闻组的树状结构。

Usenet 新闻组等级结构

新 sggroup 层级的总体集合在许多方面类似于域名系统(DNS)中使用的域名树结构。每个 Usenet 层级就像 DNS 顶级域名内的所有域名的集合。就像域名 www.pcguide.com 是通过将顶级域名标签 .com 添加到二级域名 pcguide 和子域名 www 来形成的,新 sggroup 名称也是以同样的方式创建的。它们是从顶级新 sggroup 层级名称创建的,然后附加一组描述性标签,这些标签描述了新 sggroup 在层级中的位置。

DNS 和 Usenet 层级之间的一个区别是,虽然 DNS 名称是从右到左创建的,但 Usenet 新 sggroup 名称是以更自然的(对于英语使用者来说)从左到右的顺序创建的。例如,主要的 Usenet 层级之一是 comp 层级,致力于计算机主题。在 comp 中有一个关于数据通信的子层级称为 dcom,在其中有一个讨论数据布线的组。这个组被称为 comp.dcom.cabling。几乎所有的新 sggroup 都是按照这种方式组织的。

“八大”新 sgroup 层级

Usenet 分散性质的一个问题是确保在某些我们希望每个人都处于同一页面的领域中的协调,其中之一就是新 sgroup 命名。如果我们让任何人都可以创建新 sgroup,我们可能会得到许多讨论相同主题的组。想象一下,如果有人对数据布线有疑问,但没有意识到 comp.dcom.cabling 存在,所以他创建了一个名为 comp.datacomm.cabling 的新组。这两个组可以共存,但这会导致对这个主题感兴趣的人群的混淆和碎片化。

为了避免新 sggroup 创建的问题,大型 Usenet 系统的管理员合作制定了一个系统,将许多常用的 Usenet 组组织成八个层级,并制定了一个在它们内部创建新新 sggroup 的特定程序。今天,这些被称为 Big Eight Usenet 层级,总结在 表 85-1 中。

表 85-1. Usenet 八大新 sgroup 层级

Hierarchy 描述
comp.* 讨论与计算机相关主题的新 sggroup,包括硬件、软件、操作系统和技术
humanities.* 讨论人文学科的新 sgroup,例如文学和艺术
misc.* 讨论不适合其他八大类别的杂项主题的新 sgroup
news.* 讨论 Usenet 本身及其管理的新 sgroup
rec.* 讨论休闲主题的新 sgroup,例如游戏、体育和活动
sci.* 科学新 sgroup,涵盖特定领域,如物理学和化学,研究主题等
soc.* 社会和社会讨论,包括特定文化的组
talk.* 主要围绕当前事件和事件讨论和辩论的新闻组

这八个层级包含了 Usenet 上今天使用最广泛的许多组。例如,职业棒球在 rec.sport.baseball 中讨论,英特尔电脑在 comp.sys.intel 中讨论,中东政治在 talk.politics.mideast 中讨论。

大八层级在结构和包含的新闻组方面控制得相当严格。创建一个新的大八新闻组的过程是民主和开放的。任何人都可以提议一个新的组,如果有足够的支持,它将由同意遵循大八系统的合作系统管理员创建。然而,这个过程相当复杂且耗时。有些人认为这是不可接受的,甚至反对整个限制性过程的观念。其他人认为这个系统有利,因为它通过减缓现有新闻组和新增组数量的变化速度,使大八层级相对有序。

Alt 和其他新闻组层级

对于那些更喜欢更自由的环境,并且不想服从大八程序的人来说,有一个替代的 Usenet 层级,它以层级名称 alt 开头。这个层级包括成千上万的组。其中一些相当受欢迎,但许多根本未被使用;这是 alt 组创建相对容易的副作用。

除了这九个层级之外,还有数十个额外的、较小的层级。其中许多是地区性的,甚至是公司特定的。例如,ne. 层级包含了一组讨论与新英格兰相关问题的新闻组;fr. 覆盖法国,而 de. 则与德国相关。微软在其 microsoft.* 层级下有自己的公共新闻组。图 85-2 展示了大八层级和一些其他存在的层级。

Usenet 新闻组层次结构 Usenet 新闻组被组织成称为层次结构的树状结构。其中八个是集中式、广泛使用的通用层次结构,今天被称为“八大”。替代(alt)层次结构是一组非常松散的结构,包含数千个覆盖所有可想象话题的组。除此之外,还有许多地区性、私人性和特殊用途的层次结构。

图 85-2. Usenet 新闻组层次结构 Usenet 新闻组被组织成称为层次结构的树状结构。其中八个是集中式、广泛使用的通用层次结构,今天被称为“八大”。替代(alt)层次结构是一组非常松散的结构,包含数千个覆盖所有可想象话题的组。除此之外,还有许多地区性、私人性和特殊用途的层次结构。

小贴士

关键概念 Usenet 消息不是针对单个用户的;相反,它们被发布到新闻组。每个新闻组代表一个主题。对组中主题感兴趣的人可以阅读其中的消息并回复它们。Usenet 新闻组被组织成类似 DNS 域结构的树状层次结构。许多最广泛使用的新闻组都位于一个名为“八大”的通用兴趣层次结构集合中。替代(alt)层次结构为“八大”提供了一个替代方案。还有许多地区性和特殊用途的层次结构。

未监管和监管新闻组

大多数新闻组对所有用户开放,被称为 未监管,因为发送给它们的消息会直接发送到整个 Usenet 服务器互联网。相比之下,只有一小部分新闻组是 监管 的,这意味着发送给组的所有消息都会被筛选,只有经过版主(或版主团队)批准的消息才会真正发布。

监管组的目的是确保特定组内的讨论保持主题相关。它们通常被创建来处理有争议的话题,以确保辩论保持建设性,避免破坏。例如,rec.guns 是监管的,以确保讨论集中在枪支的使用上,而不是无休止地围绕枪支控制等政治争论(这在 talk.politics.guns 中有位置)。监管组有时也用于仅用于公告的专业组,或内容受限的组。例如,rec.food.recipes 是监管的,这样它就只包含食谱和食谱请求,这有助于人们轻松找到食谱,而无需浏览大量讨论。最后,当一些破坏性元素选择在未监管的新闻组中发布大量内容,使得正常讨论变得困难时,有时会创建未监管组的监管版本。

在多个新闻组中交叉发布

一篇文章可以发布到多个新闻组。这个过程称为跨发帖,当一条消息涉及两个主题或允许发送者触及更广泛的受众时使用。例如,如果你住在西雅图地区,并且你的房子有问题,你可能会合法地跨发帖到seattle.generalmisc.consumers.house

跨发帖比独立向每个组发送相同消息更有效率,原因有两个:

  • 每个 Usenet 服务器上只会存储消息的一个副本,而不是两个。

  • 同时阅读这两个组的 Usenet 参与者不会看到消息两次。

然而,向大量新闻组进行跨发帖通常被认为是有破坏性的,并且违反了 Usenet 礼仪。

Usenet 消息格式和特殊标题

Usenet 被设计成允许用户以消息的形式交换信息,这些消息是从一台计算机发送到另一台计算机的。与任何基于消息的网络应用程序一样,所有 Usenet 客户端软件和服务器软件都同意使用一个共同的消息格式。这确保了所有设备和程序都能以一致的方式解释所有 Usenet 文章。

虽然 Usenet 最初被创建为电子邮件的替代品,并且显然在处理消息的方式上存在差异,但也有许多相似之处。两者都是面向文本的消息系统,具有类似的内容和控件信息沟通需求。Usenet 的创建者意识到,基于电子邮件格式而不是从头开始创建新格式,将 Usenet 消息格式建立在电子邮件格式上会有许多优势。电子邮件消息格式已经被广泛使用,为 Usenet 采用它将节省实施时间和精力。它还将增强电子邮件和 Usenet 消息之间的兼容性,使得设计用于处理或显示电子邮件的软件也能与 Usenet 文章一起工作。因此,Usenet 消息格式是基于电子邮件消息的 RFC 822 标准定义的(在第七十六章中介绍)。

RFC 822 消息以一组标题开始,包含有关消息的控制和描述性信息,然后是一个空行,接着是消息的主体,其中包含实际内容。

RFC 822 标准的一个重要属性是能够定义自定义标题,这些标题补充了标准本身定义的常规标题集。Usenet 文章需要一些电子邮件不需要的信息,这些信息可以通过特别定义的标题包含在内,同时仍然遵循基本的 RFC 822 格式。同时,对于 Usenet 不需要的特定于电子邮件的标题可以省略。因此,Usenet 文章和电子邮件消息之间没有任何结构上的差异。它们之间的区别仅在于包含的标题类型和这些标题的值。例如,Usenet 消息将始终包含一个指定文章要发布的新闻组的标题,但不会像电子邮件消息那样带有“收件人:”行。

提示

关键概念 Usenet 文章使用与电子邮件消息相同的 RFC 822 消息格式。Usenet 文章和电子邮件消息之间的唯一区别在于每个中使用的标题类型和值。

Usenet 标题分类和常见标题

所有 Usenet 标题都是根据 RFC 822 标准中指定的标准标题格式定义的:<标题名称>: <标题值>。与电子邮件消息一样,标题可以扩展到多行,按照 RFC 822 标准中描述的缩进程序进行。

当前 Usenet 消息标准,RFC 1036,描述了 Usenet 消息的标题类型。标题分为两类:强制性标题(见表 85-2 中。

表 85-4. 常见的附加 Usenet 标题

标题名称 描述
NNTP-Posting-Host: 指定最初发布消息的主机的 IP 地址或 DNS 域名。这通常是作者用于发布消息的客户端地址或发送者的本地 NNTP 服务器。
User-Agent: (或) X-Newsreader: 用于发布消息的软件的名称和版本号。
X-Trace: 提供可用于跟踪消息的附加信息。
X-Complaints-To: 用于报告滥用信息的电子邮件地址。此标题现在由许多 ISP 自动包含。

Usenet MIME 消息

由于 Usenet 遵循 RFC 822 标准,多用途互联网邮件扩展(MIME)可以用于格式化 Usenet 消息。当这样做时,您将在消息中看到通常的 MIME 标题(如 MIME-Version、Content-Type 等)。

注意,在 Usenet 消息中使用 MIME 存在一些争议。一些新闻阅读器不遵守 MIME 规范,在尝试显示这些消息时会变得混乱,许多 Usenet 老手反对在 Usenet 消息中使用除纯文本之外的内容。尽管如此,MIME 消息正在变得越来越普遍,无论是好是坏。

NNTP 概述和一般操作

正如我在本章前面解释的那样,Usenet 最初是一个非正式的 UNIX 计算机网络,使用拨号 UUCP 连接在服务器之间传输消息。这种安排是出于必要性,并且工作相当不错,尽管它存在一些问题。20 世纪 80 年代,随着互联网的广泛使用,它为更有效地分发 Usenet 文章提供了理想的机会。NNTP 被开发为一种特殊的 TCP/IP 协议,用于发送这些消息。现在,NNTP 每天从一台计算机传输数十亿份 Usenet 消息到另一台计算机。

提示

背景信息 NNTP 在许多方面与简单邮件传输协议(SMTP)相似,包括其基本操作、命令集和回复格式。如果您熟悉 SMTP,可能会发现 NNTP 的信息更容易理解,SMTP 在第七十七章")中有介绍。

Usenet 最初是一个逻辑的互连主机网络,它们直接相互联系。在早期的 Usenet 中,用户会将消息发布到她的本地服务器,消息将保留在那里,直到该服务器被另一个服务器联系或联系另一个服务器。然后,消息将被转移到新服务器,在那里它将保留,直到第二个服务器联系第三个服务器,依此类推。这种传输机制是有效的,但在许多方面存在严重缺陷。

服务器并不是持续连接在一起的;它们只能通过使用模拟调制解调器打电话来相互通信。因此,消息往往需要几个小时才能传播。那时的调制解调器按照今天的标准也非常慢——每秒 2400 比特或更少——所以从一个服务器复制消息到另一个服务器需要很长时间。最糟糕的是,除非两个站点在同一座城市,否则这些电话是长途电话,使得它们相当昂贵。

尽管存在所有这些问题,为什么还要使用这个系统?答案是简单,因为没有替代方案。在 20 世纪 70 年代末和 80 年代初,没有我们现在所知道的互联网,也没有其他物理基础设施存在来连接 Usenet 站点。要么通过电话线使用 UUCP,要么什么也不做。

随着新兴的 ARPAnet 成长为现代互联网,这一切都发生了变化。随着互联网的扩展,越来越多的站点连接到它,包括许多参与 Usenet 的站点。一旦交换中的两个站点都连接到互联网,使用互联网发送 Usenet 文章而不是依赖缓慢、昂贵的电话通话就变得很容易了。随着时间的推移,越来越多的 Usenet 站点加入了互联网,很明显,正如电子邮件从 UUCP 迁移到 TCP/IP 互联网一样,Usenet 的未来也在互联网上。

Usenet 从 UUCP 连接转移到 TCP/IP 互联网意味着需要重新思考如何将 Usenet 文章从服务器移动到服务器。在互联网上,Usenet 只是众多应用之一,消息的传输必须使用 TCP 或用户数据报协议(UDP)进行结构化。因此,就像其他应用一样,Usenet 需要一个应用层协议来描述如何在 TCP/IP 上传输 Usenet 流量。正如 Usenet 从电子邮件的 RFC 822 借用其消息格式一样,将其消息交付协议建模在电子邮件使用的协议(SMTP)上是有意义的。结果是 1986 年 2 月发布的 RFC 977 中 NNTP 的创建。

NNTP 的一般操作确实与 SMTP 非常相似。NNTP 使用 TCP,服务器在众所周知的 TCP 端口 119 上监听传入的连接,无论是来自客户端主机还是其他 NNTP 服务器。在 SMTP 中,当两个服务器使用 NNTP 进行通信时,发起连接的那个服务器在该交换中扮演客户端的角色。

连接建立后,通信以客户端发送给服务器的命令和从服务器返回给客户端设备的回复的形式进行。NNTP 命令以纯 ASCII 文本的形式发送,就像 SMTP、文件传输协议(FTP)、超文本传输协议(HTTP)和其他协议使用的文本一样。NNTP 响应以三位回复代码以及描述性文本的形式,同样就像 SMTP(它反过来又从 FTP 借用了这个概念)。

NNTP 被设计成一种用于传输 Usenet 消息的全面工具。它通常被视为一种将 Usenet 文章从一个服务器传输到另一个服务器的交付协议,但它也被用于客户端主机到 Usenet 服务器的连接,用于发布和阅读消息。因此,NNTP 命令集相当广泛,包括处理服务器之间以及客户端和服务器之间通信的命令。对于消息传播,一组命令允许服务器从一个服务器请求新文章或将新文章发送到另一个服务器。对于消息发布和访问,命令允许客户端请求新新闻组和消息的列表,并检索消息以供用户显示。

在 RFC 977 中定义的命令在十多年内是唯一的官方命令。然而,甚至在 20 世纪 80 年代末,NNTP 服务器和客户端软件的实现者就已经开始添加新的命令和功能,使 NNTP 更加高效,对用户更有用。这些NNTP 扩展最终在 2000 年发布的 RFC 2980 中被记录下来。我将在本章后面的“NNTP 命令和命令扩展”部分更详细地描述它们。

小贴士

关键概念 网络新闻传输协议(NNTP)是现代 Usenet 中实现消息通信的协议。它用于两个主要目的:在 NNTP 服务器之间传播消息,并允许 NNTP 客户端发布和阅读文章。它是一个独立的协议,但与电子邮件的简单邮件传输协议(SMTP)有许多相似之处。

NNTP 在现代 Usenet 通信过程中的所有传输步骤中都被使用。然而,NNTP 最常与 Usenet 文章的传播过程相关联。这可以说是 NNTP 最重要的功能:提供一种高效的方式,将大量 Usenet 文章从一个服务器传输到另一个服务器。因此,从协议的角度来看,这是一个合理的起点。

NNTP 服务器间通信过程:新闻文章传播

要理解 NNTP 传播是如何工作的,我们必须首先看看现代 Usenet 网络本身的组织方式。现在,所有的 Usenet 站点都在互联网上,理论上,任何 NNTP 服务器都可以联系任何其他服务器来发送和接收 Usenet 文章。然而,如果要将一篇文章提交给特定的服务器,需要通过单独的 NNTP 连接发送到每个其他 NNTP 服务器,这将是荒谬的。因此,即使在互联网时代,Usenet 的逻辑网络仍然非常重要。

Usenet 服务器结构

理论上,对 Usenet 结构的要求只是每个站点以某种形式至少连接到另一个站点。逻辑网络可以是无形的,甚至没有任何正式的结构,只要每个站点都能通过一系列中间服务器形成一条路径,相互连接。然而,现代 Usenet 非常庞大,每天都有成千上万的服务器和数以千计的文章被发布。这需要一种更组织化的结构来分发新闻。

因此,现代 Usenet 逻辑网络在结构上松散地分层。一些大型互联网服务提供商(ISP)和拥有高速互联网连接和大容量服务器的公司被认为是分层结构的顶层,有时被称为 Usenet 的骨干网。较小的组织连接到这些大型组织运行的服务器;这些组织被认为是骨干组的下游。反过来,更小的组织可能从连接到大型组织的那些组织进一步下游连接。

这种分层结构意味着大多数 Usenet 服务器只与其上游邻居以及它们提供服务的任何下游站点保持直接连接。服务器从其上游连接接收所谓的新闻源,因为那里是它将接收大部分新闻文章的地方。然后,它将其新闻源提供给其下游的所有服务器。我在图 85-1 通信模型 此图说明了在现代 Usenet 上使用 NNTP 创建、传播和读取消息的方法;在某些方面与第七十四章中的电子邮件模型图(图 74-1)相似。在这个例子中,消息由发件人 Ellen 创建并由读者 Jane 读取。过程从 Ellen 在编辑器中创建消息并发布开始。她的 NNTP 客户端将其发送到她的本地 NNTP 服务器。然后,从该本地服务器传播到相邻的服务器,通常包括其上游服务器,用于将消息发送到互联网。其他 NNTP 服务器接收该消息,包括 Jane 的本地服务器上游的服务器。它将消息传递给 Jane 的本地服务器,Jane 使用 NNTP 客户端访问并读取该消息。Jane 可以回复该消息;在这种情况下,相同的流程会重复,但方向相反,回到 Ellen(以及也回到成千上万的其他读者,此处未显示)")中展示了这种结构。

例如,假设公司 A 运行了一个名为 Largenews 的大型 Usenet 服务器,该服务器连接到主干网。从该服务器下游是 Mediumnews NNTP 服务器。该服务器为名为 Smallnews 的服务器提供服务。如果一个用户向 Mediumnews 发布文章,它将立即被放置在该服务器上。该服务器将文章向下发送到 Smallnews,以便该服务器的用户可以阅读。Mediumnews 还会在某个时候将文章发送到 Largenews。从 Largenews 出发,消息将被分发到其他主干站点,然后这些站点将消息传递到它们自己的下游站点。这样,所有站点最终都会收到消息的副本,尽管 Mediumnews 只需要直接连接到两个其他服务器。

用以描述使用 NNTP 传播新闻的术语是 洪水传播。这是因为消息从一个服务器开始,并从该服务器向外传播,最终到达主干站点,然后沿着所有下游的“河流”传播到 Usenet 上的每个站点。

尽管我把 Usenet 网络的逻辑结构描述为层次结构,但它并不是一个严格的层次结构。为了冗余,许多 NNTP 服务器维护与多个其他服务器的连接,以确保新闻能够快速传播。可以通过查看消息 ID 来控制文章的传输,以避免一个服务器从多个邻居那里同时接收到的消息重复。

基本 NNTP 传播方法

现在,让我们看看使用 NNTP 在服务器之间实际传播消息的方式。有两种技术可以实现这一点:

  • 推送模型 中,一旦服务器收到新消息,它立即通知其上游和下游邻居关于该消息的信息,并询问他们是否想要一份副本。

  • 拉模型 中,服务器不会向其邻居提供新文章。如果邻居服务器想要查看自上次连接建立以来到达了什么内容,它们必须请求新消息列表,然后请求将新消息发送给它们。

这两种技术都有优点和缺点,但推送是目前最常用的模型。

小贴士

关键概念 NNTP 扮演的一个重要角色是在 Usenet 服务器之间传播文章,这使得整个系统成为可能。用于文章传播有两种模型:推送模型,其中接收新消息的服务器立即将其提供给连接的服务器,以及拉模型,其中接收新消息的服务器在收到其他服务器的请求之前保留它们。推送模型通常更受欢迎,因为它允许系统内更快地传递消息。

使用推送模型进行文章传播

使用推送模型,当 NNTP 服务器的管理员与上游 Usenet 服务提供商建立服务关系时,他们向提供商提供一份下游服务器希望携带的新组列表。每当该列表中的某个组上游服务器收到新文章时,它会自动发送到下游站点。这使下游服务器不必不断询问是否有新内容到达。

在 RFC 977 中定义的经典 NNTP 协议中,文章的交换基于推送模型,并使用 IHAVE 命令执行。回到上一节中的例子,假设有三条新消息到达 Largenews 服务器。它将建立一个到 Mediumnews 服务器的 NNTP 连接,并使用 IHAVE 命令逐个提供三条新消息的消息 ID。(NNTP 命令将在本章后面描述。)Mediumnews 服务器将对每一条消息做出回应,表明它是否已经拥有该消息。如果没有,Largenews 将发送该消息。使用推送模型传播文章的事务示例在图 85-3 中展示。

使用推送模型传播 NNTP 文章 本例展示了 Usenet 文章是如何在服务器之间使用传统的推送模型进行移动的。在这里,作为 NNTP 客户端(实际上可能是 NNTP 服务器)的设备有两个消息可供服务器使用。它发送 IHAVE 命令指定第一条消息的消息 ID,但服务器已经有了这条消息,因此发送了一个 435(不要发送)回复。客户端随后发出一个带有第二条消息 ID 的 IHAVE 命令。服务器想要这条消息,因此发送了一个 335 回复。客户端发送 Usenet 消息,以单独一行上的单个句号结束。服务器表明它已收到消息,客户端完成其事务后,退出会话。

图 85-3. 使用推送模型进行 NNTP 文章传播 此示例展示了 Usenet 文章是如何在服务器之间使用传统的推送模型进行传播的。在这里,作为 NNTP 客户端的设备(实际上可能是 NNTP 服务器)有两个消息可供服务器使用。它发送 IHAVE 命令,指定第一条消息的消息 ID,但服务器已经有了这条消息,因此发送了一个 435(不要发送)回复。然后客户端发出一个带有第二条消息 ID 的 IHAVE 命令。服务器希望接收这条消息,因此发送了一个 335 回复。客户端发送 Usenet 消息,以单独一行上的单个句号结束。服务器表明它已收到消息,客户端完成交易后退出会话。

这种技术的优点是确保服务器不会收到它已经拥有的消息的重复副本。在现代 Usenet 中,它的缺点是速度慢,因为服务器必须在客户端发送消息或下一个命令之前响应 IHAVE 命令。

使用流模式提高传播效率

更重要的 NNTP 扩展之一是流模式,它改变了新闻推送的方式。(NNTP 命令扩展将在本章后面描述。)当此模式启用时,客户端机器使用 CHECK 命令而不是 IHAVE 来询问服务器是否希望接收特定的消息。服务器响应以表明是否希望接收消息;如果希望,客户端使用 TAKETHIS 命令发送消息。

CHECK/TAKETHIS 的好处是客户端在发送下一个命令之前不需要等待 CHECK 命令的回复。当客户端等待第一个 CHECK 命令的回复时,它可以做其他事情,比如发送下一个 CHECK 命令,允许命令以流的形式发送以提高效率。因此,客户端可以先发送一个 CHECK 命令用于第一条新消息,然后发送一个 CHECK 命令用于第二条,同时等待服务器对第一条消息的回复。可以发送多个 CHECK 命令流,然后为之前发送的每个 CHECK 命令发送 TAKETHIS 命令,以表明服务器希望接收该消息。

使用拉模型进行文章传播

拉模型是通过使用 NEWNEWS 和 ARTICLE 命令实现的。客户端连接到服务器并发送 NEWNEWS 命令,其中包含一个日期,指定客户端上次检查新消息的日期和时间。服务器响应,返回自该日期以来到达的新文章的消息 ID 集合。然后客户端使用 ARTICLE 命令请求每条新消息。

注意,推送和拉取模型可以在单个会话中结合使用。客户端可以连接到服务器,使用 NEWNEWS 检查该服务器上的新消息,然后通过 IHAVE 或 CHECK 通知服务器客户端想要发送的新消息。在实践中,一对服务器之间在特定交换中通常只使用这两种模型中的一种。

除了传播新消息外,NNTP 还用于允许服务器之间交流有关新创建的新闻组的信息。这是通过使用 NEWGROUPS 命令来完成的,该命令与 NEWNEWS 一样,指定了日期和时间。作为回应,服务器向客户端发送自指定日期和时间以来创建的新新闻组的列表。

NNTP 客户端-服务器通信过程:新闻发布和访问

NNTP 与其前身 SMTP 的一个关键区别在于,NNTP 不仅用于服务器之间的通信。它还用于 Usenet 消息的初始发布以及阅读消息。实际上,NNTP 的大多数命令都涉及用户客户端机器与 NNTP 服务器之间的交互,而不是服务器之间的通信。

NNTP 客户端是指任何了解 NNTP 协议并设计为提供用户访问 Usenet 的软件程序。NNTP 客户端通常被称为新闻阅读器,它们为用户提供两个主要功能:发布阅读Usenet 消息。Usenet 新闻阅读器几乎存在于所有硬件和软件平台上,它们在功能、用户界面和其他特性方面差异很大。如今,大多数人都在客户端计算机上使用 Usenet 新闻阅读器,这些计算机必须连接到单独的 NNTP 服务器来阅读和发布新闻。这些程序类似于电子邮件客户端,实际上,许多电子邮件客户端也充当 NNTP 客户端。

新闻发布、访问和阅读

发布 Usenet 消息是整个 Usenet 通信过程中的第一步(尽管许多 Usenet 文章实际上是其他文章的回复,所以这有点像鸡生蛋的问题)。使用 NNTP 发布文章非常直接。客户端建立与服务器的连接并发出 POST 命令。如果服务器愿意接受新文章,它会回复提示客户端发送文章。然后客户端将文章传输到服务器。一些新闻阅读器可能会批量处理新文章,以便在单个 NNTP 会话中发送,而不是逐个提交。

新闻阅读器也会建立一个 NNTP 连接到服务器来阅读 Usenet 文章。NNTP 提供大量命令来支持用户可能采取的各种不同的文章访问和检索操作。阅读的第一步有时是检查可用的新闻组列表。使用 LIST 命令,客户端从服务器请求可阅读和发布的新闻组列表。RFC 977 定义了基本的 LIST 命令,它将所有组列表返回给客户端。RFC 2980 定义了命令的多个扩展,允许客户端仅检索服务器上组的信息。由于今天 Usenet 新闻组的数量如此之大,通常情况下,除非用户明确请求,否则会跳过新闻组列表。

Usenet 消息访问的下一步通常是选择一个新闻组从可用的组列表中阅读。同样,由于今天有如此多的组,大多数新闻阅读器允许用户使用模式或部分名称字符串来搜索组名。然后,将带有所选组名的 GROUP 命令发送到服务器。服务器将组的第一和最后当前文章编号返回给客户端。

消息可以通过两种方式来识别:一种是绝对方式,另一种是站点特定方式。文章的消息 ID 是一个固定的标识符,可以在整个 Usenet 中唯一地表示它;这是在服务器间通信中用来确定每个站点是否有一个给定消息副本的方法。相比之下,文章编号是服务器特定的;它们代表那些文章到达服务器时分配的编号,并用作在新组中引用文章的简写。因此,同一消息在每个 NNTP 服务器上会有不同的文章编号。文章编号用于方便,因为它们比消息 ID 短得多。在会话期间,NNTP 服务器还维护一个当前文章指针,可以用来按顺序遍历新闻组。

新闻访问方法

新闻阅读器可以以多种不同的方式访问组中的消息,这取决于其编程方式和软件用户的需求。新闻访问方法包括以下内容:

完整新闻组检索 强制检索技术是客户端请求服务器发送该组中的所有消息。客户端发出 ARTICLE 命令以选择组中的第一条当前消息,使用 GROUP 命令返回的第一个文章编号。这会将服务器的内部会话指针设置为指向第一条文章,以便可以检索它。然后使用 NEXT 命令将指针前进到下一条消息,并使用 ARTICLE 命令检索它。这个过程一直持续到整个组都被读取。图 85-4(ch85s06.html#nntp_full_newsgroup_retrieval_process_th "图 85-4. NNTP 完整新闻组检索过程有许多方法可以让 NNTP 客户端访问和读取服务器上的 Usenet 消息。一种常见的方法是检索整个新闻组的全部内容。在这个例子中,客户端使用 GROUP 命令选择读取 comp.protocols.tcp-ip 新闻组;服务器响应 211(Group Selected)回复,其中包含有关该组的重要统计数据。客户端使用 ARTICLE 命令和组中第一条文章的编号 177,从服务器读取它。然后服务器逐行发送消息,以单行上的一个句号结束。客户端使用 NEXT 命令告诉服务器将其内部文章指针前进到下一条消息,这通常不会是刚刚读取的下一个连续编号;这里它是 179。然后客户端可以通过单独发送 ARTICLE 命令来读取那条消息。由于没有给出参数,服务器返回当前消息(179)。")说明了这个过程。检索到的消息由新闻阅读器存储,并可供用户即时访问。这种方法最适合相对较小的新闻组以及/或拥有快速互联网连接的用户。

新闻组标题检索 由于下载整个新闻组耗时较长,许多新闻阅读器通过下载所有消息的标题而不是完整消息来妥协。这个过程与完整新闻组检索相同,但使用 HEAD 命令来检索仅包含文章标题。这比使用 ARTICLE 命令检索每条消息的全部内容要快。如果服务器支持,还可以使用 XHDR 命令扩展来更有效地检索消息标题的子集,例如主题行和作者。

单篇文章检索 还可以使用 ARTICLE 命令从新闻组中检索单个消息,并指定文章的消息标识符。

提示

关键概念 虽然 NNTP 最为人所知的是其在服务器间传播中的作用,但它也被 Usenet 客户端用于撰写和阅读文章。不同的命令提供了客户端设备阅读文章的灵活性。客户端可以检索整个新闻组,仅检索一组新闻组标题,或单个文章。其他命令也支持各种管理功能。

其他客户端/服务器功能

除了阅读和发布,NNTP 还包括支持用户可能希望执行的其他各种杂项任务的命令。客户端可以通过使用 HELP 命令来请求服务器的帮助信息,或者使用 NEWGROUPS 命令来获取新新闻组的列表。

大多数现代新闻阅读器包括的功能远远超出了之前描述的基本发布和阅读功能。大多数维护自己的配置文件集,允许用户维护一组喜欢的已订阅新闻组,而不是每次访问 Usenet 时都需要从主列表中选择一个组来阅读。新闻阅读器还会跟踪用户在每个已订阅新闻组中已阅读的文章,因此用户不需要浏览整个新闻组来查看已发布的新消息。

NNTP 完整新闻组检索过程 有许多方法可以让 NNTP 客户端访问和读取服务器上的 Usenet 消息。一种常见的方法是检索整个新闻组的内容。在这个例子中,客户端使用 GROUP 命令选择用于阅读的新闻组 comp.protocols.tcp-ip;服务器响应 211(Group Selected)回复,其中包含有关该组的重要统计数据。客户端使用带有组中第一篇文章编号 177 的 ARTICLE 命令从服务器读取它。然后服务器逐行发送消息,以单行上的单个句号结束。客户端使用 NEXT 命令告诉服务器将其内部文章指针向前移动到下一篇文章,这通常不会是刚刚读取的下一个连续编号;这里它是 179。然后客户端可以通过单独发送 ARTICLE 命令来读取该消息。由于没有给出参数,服务器返回当前消息(179)。

图 85-4. NNTP 完整新闻组检索过程 有许多方式可以让 NNTP 客户端访问和读取服务器上的 Usenet 消息。一种常见的方法是检索整个新闻组的全部内容。在这个例子中,客户端使用 GROUP 命令选择用于阅读的新闻组 comp.protocols.tcp-ip;服务器响应以 211(Group Selected)回复,其中包含有关该组的重要统计数据。客户端使用带有组中第一篇文章编号的 ARTICLE 命令,即 177,从服务器读取它。然后服务器逐行发送消息,以一行上的单个句号结束。客户端使用 NEXT 命令告诉服务器将其内部文章指针向前移动到下一篇文章,这通常不会是刚刚读取的下一个连续编号;这里它是 179。然后客户端可以通过发送仅包含 ARTICLE 命令的命令来读取该消息。由于没有给出参数,服务器返回当前消息(179)。

文章线程

基本 Usenet 文章阅读的一个特别有用的增强功能是线程化。这个特性允许新闻阅读器以非严格的字母顺序或时间顺序显示文章,而是根据文章的引用头信息将文章分组到对话中。在繁忙的新闻组中,线程化特别有用,因为它允许用户一次性查看特定讨论中的所有文章,而不是同时尝试处理多个对话的消息。

线程化的问题之一是新闻阅读器需要花费很长时间来筛选所有这些引用行并构建文章线程。为了加快这一过程,许多服务器现在为新新闻组缓存额外的线程或概述信息,客户端可以在打开新闻组时检索这些信息以节省时间。这是通过使用 XTHREAD 或 XOVER NNTP 命令扩展来完成的。

NNTP 命令和命令扩展

开放、协作的过程在开发互联网标准中的巨大优势之一是,通常新的协议是通过在旧协议的基础上进行设计。这节省了开发时间和精力,并促进了技术之间的兼容性。正如我在本章前面所解释的,NNTP 在许多方面基于 SMTP 的原则;SMTP 反过来又借鉴了早期协议(如 Telnet 和 FTP)的思想。这种传统可以在 NNTP 命令与这些早期协议的相似性中看到。

命令语法

与 SMTP 类似,所有 NNTP 命令都是 ASCII 文本,通过 NNTP TCP 连接发送到 NNTP 服务器,由充当客户端的设备(可能是新闻阅读器客户端或 NNTP 服务器本身)发送。这些是遵循 Telnet 网络虚拟终端 (NVT) 格式的标准文本字符串,以两个字符的回车/换行 (CRLF) 序列结束。与 SMTP 和 FTP 一样,您可以通过使用 Telnet 在端口 119 上连接到 NNTP 服务器来与 NNTP 服务器进行交互式会话。

NNTP 命令的基本语法是 <command-code> <parameters>。与 SMTP 不同,NNTP 命令不受四个字符长度的限制。命令后面的参数由一个或多个空格字符分隔,并用于提供必要的信息,以便服务器执行命令。NNTP 命令不区分大小写。

基础命令集

主要的 NNTP 规范,RFC 977,描述了 NNTP 客户端和服务器支持的命令基础集。它们没有被分成类别,而是按字母顺序列出,正如我在 表 85-5 中所做的那样。(关于这些命令中哪些用于新闻文章传播和新闻发布/访问的详细信息,在本章前面已提供。)

表 85-5. NNTP 基础命令

命令代码 命令 参数 描述
ARTICLE 获取文章 消息 ID 或服务器文章编号 告诉服务器向客户端发送特定的 Usenet 文章。要检索的文章可以使用其绝对、通用消息 ID 或其本地分配的文章编号来指定。当命令与文章编号一起发出时,这将导致服务器的内部消息指针设置为指定的文章。如果消息指针已经设置为特定的文章,则无需文章编号即可发出 ARTICLE 命令,并将检索当前消息。
HEAD 获取文章标题 消息 ID 或服务器文章编号 与 ARTICLE 命令相同,但只检索文章的标题。
BODY 获取文章正文 消息 ID 或服务器文章编号 与 ARTICLE 命令相同,但只返回文章的正文。
STAT 获取文章统计信息 服务器文章编号 概念上与 ARTICLE 命令相同,但不返回任何消息文本,只返回文章的消息 ID。此命令通常用于设置服务器的内部消息指针,因此 STAT 通常只与文章编号(而不是消息 ID)一起调用。
GROUP 选择新闻组 新闻组名称 告知服务器客户端想要访问的新闻组名称。假设指定的组存在,服务器将返回客户端该组中第一条和最后一条文章的编号,以及该组消息数量的估计。服务器的内部文章指针也将设置为组中的第一条消息。
HELP 获取帮助信息 请求服务器向客户端发送帮助信息,这通常以服务器支持的合法命令列表的形式出现。
IHAVE 向服务器提供文章 消息 ID 客户端在 NNTP 会话中使用,告知服务器它有一个服务器可能感兴趣的新文章。服务器将检查提供的消息 ID,并响应客户端,指示是否希望客户端发送文章。
LAST 跳转到最后一条消息 告知服务器将其当前文章指针设置为新闻组中的最后一条消息。
LIST 列出新闻组 请求服务器发送它支持的新闻组列表,以及每个组中的第一条和最后一条文章编号。如 RFC 977 中描述的命令很简单,不支持参数,导致将新闻组的完整列表发送到客户端。NNTP 命令扩展显著扩展了此命令的语法,如本章下一节所述。
NEWGROUPS 列出新新闻组 日期和时间,以及可选的分布规范 请求服务器发送自指定日期和时间以来创建的新新闻组的列表。客户端还可以限制命令只返回特定区域分布内的新闻组。
NEWNEWS 列出新新闻文章 日期和时间,以及可选的分布规范 从服务器请求自特定日期和时间以来到达的所有新文章的列表。与 NEWGROUPS 命令类似,这可能受到分布的限制。服务器会响应新文章的消息 ID 列表。
NEXT 跳转到下一条消息 将服务器的当前文章指针移动到新闻组中的下一条消息。
POST 发布文章 告知服务器客户端想要发布新文章。服务器会响应一个肯定或否定的确认。假设发布是允许的,客户端随后将消息的全文发送到服务器,服务器将其存储并开始将其传播到其他服务器的过程。
QUIT 结束会话 终止 NNTP 会话。为了“礼貌”,客户端应在关闭 TCP 连接之前发出此命令。
SLAVE 设置从属状态 适用于特殊配置,其中一个 NNTP 服务器作为其他服务器的辅助。在实际应用中不常用。

提示

关键概念 主要 NNTP 标准定义了一系列基础 NNTP 命令,这些命令由发起 NNTP 连接的设备使用,以完成文章传播、发布和阅读功能。NNTP 命令由一个命令代码和可选的参数组成,这些参数指定了如何执行该命令。

NNTP 命令扩展

RFC 977 中描述的基本命令集足以支持客户端-服务器和服务器间功能,但在许多方面,它相当基础且在效率和实用性方面有限。随着 Usenet 在 1980 年代末变得更大、更受欢迎,NNTP 需要改变以提高其可用性。1991 年,开始对 NNTP 标准进行正式修订的工作,但从未完成。尽管如此,该努力中的许多概念在随后的年份中非正式地被 NNTP 实现所采用。此外,一些 Usenet 软件作者创建了他们自己的非标准功能来改进协议,其中一些功能也通过广泛采用而成为事实标准。

因此,到 1990 年代末,大多数 Usenet 软件实际上实现了 NNTP 的变体,其功能远超标准文档中记录的内容。自然地,并非所有 NNTP 软件都支持相同的额外功能,这可能导致服务器和客户端之间潜在的兼容性问题。RFC 2980,“常见 NNTP 扩展”,于 2000 年 10 月发布,旨在正式化许多这些对基于 RFC 977 的基础 NNTP 标准的扩展。

NNTP 扩展主要包含新增的 NNTP 命令,这些命令被添加到基本的 NNTP 命令集中,以及一些对其他命令和 NNTP 功能的细微调整。这些扩展通常分为三类:

  • 提高服务器间 NNTP 消息传输效率的扩展

  • 使 NNTP 更有效地用于客户端消息访问的扩展

  • 以下不属于前述任一组的杂项扩展

NNTP 传输扩展

第一组被称为 NNTP 传输扩展,它由一组相关的命令组成,旨在改善服务器之间的消息传播。其中大部分实现了 NNTP 的 流模式,这提供了一种更有效的方法,将大量文章从一个服务器移动到另一个服务器,正如本章前面关于服务器间通信的讨论中所述。表 85-6 描述了新的传输命令。

表 85-6. NNTP 传输扩展

命令代码 命令 参数 描述
模式 流模式 用于告知服务器客户端希望以流模式操作,使用 CHECK 和 TAKETHIS 命令。
检查 检查文章是否存在 消息 ID 在流模式下,由作为客户端的服务器使用,以询问另一个服务器是否拥有特定文章的副本。服务器会回复表示是否希望收到该文章的副本。此命令类似于 IHAVE,但客户端在发送下一个命令之前不需要等待回复。
TAKETHIS 将文章发送到服务器 消息 ID 当服务器对 CHECK 命令做出响应,表示希望获得特定消息的副本时,客户端使用此命令发送它。
XREPLIC 复制文章 新闻组和文章编号列表 为从一台服务器复制大量文章到另一台服务器的特殊目的而创建。它并不广泛使用。

NNTP 新闻阅读器扩展

RFC 2980 定义的第二组扩展是 新闻阅读器扩展,这些扩展主要关注新闻阅读器客户端与 NNTP 服务器交互时使用的命令。这些扩展包括几个新命令,以及一个在 RFC 977 中功能非常有限的重要命令 LIST 的重大增强。

原始的 LIST 命令没有参数,只允许客户端检索服务器携带的所有新闻组的完整列表。当只有几百个 Usenet 新闻组时,这可能已经足够了,但现在有成千上万个。RFC 2980 定义了 LIST 命令的多种新变体,以允许客户端在服务器返回的信息类型上有更大的灵活性。表 85-7 显示了新的 LIST 命令变体。

表 85-7. NNTP LIST 命令扩展

命令代码 命令 参数 描述
列出活跃组 列出活跃新闻组 新闻组名称或模式 提供服务器上活跃新闻组的列表。这在语义上与原始的 LIST 命令相同,但客户端可以提供一个新闻组名称或模式来限制返回的新闻组数量。例如,客户端可以请求只包含“football”的新闻组列表。
列出活跃新闻组创建时间 列出活跃新闻组创建时间 促使服务器向客户端发送其 active.times 文件,该文件包含有关服务器携带的新闻组创建时间的信息。
列出分发 列出分发 使服务器向客户端发送 distributions 文件的内容,该文件显示了服务器识别的区域分发字符串(用于消息的分发标题)。
列出分发模式 列出分发模式 向服务器请求其 distribution.pats 文件,该文件类似于分发文件,但使用模式来总结不同新闻组的分发信息。
LIST NEWSGROUPS 列出新闻组 新闻组名称或模式 提供新闻组名称和描述的列表。与 LIST ACTIVE 不同,它只返回新闻组名称和描述,而不返回每个新闻组的文章编号。在功能上与 XGTITLE 相同(参见表 85-8),通常由用户用来定位要添加到其订阅列表中的新闻组。
LIST OVERVIEW.FMT 显示概要格式 促使服务器显示其 概要 文件的格式信息。有关更多信息,请参见表 85-8 中的 XOVER 命令描述。
LIST SUBSCRIPTIONS 获取默认订阅列表 请求服务器向客户端发送默认的新闻组订阅列表。这用于为新用户设置一个建议的新闻组列表。例如,如果一个组织有一个内部支持新闻组,它可以将这个组放在默认订阅列表中,这样所有新用户在第一次启动新闻阅读器时就能立即了解它。

除了对 LIST 命令的这些更改外,还定义了许多与新闻阅读器相关的命令扩展,这些扩展在表 85-8 中进行了描述。

表 85-8. NNTP 新闻阅读器扩展

命令代码 命令 参数 描述
LISTGROUP 列出新闻组中的文章编号 新闻组名称 使服务器返回当前新闻组中当前消息的本地文章编号列表。服务器当前的文章指针也设置为组中的第一条消息。
MODE READER 设置新闻阅读器模式 告知服务器,作为客户端的设备是一个客户端新闻阅读器,而不是另一个 NNTP 服务器。虽然技术上不是必需的——所有命令都可以由任何充当客户端的设备发送——一些服务器可能被优化以响应新闻阅读器相关的命令,如果给出此命令。
XGTITLE 获取新闻组描述 新闻组名称或模式 用于列出与特定文本模式匹配的新闻组或一组新闻组的描述。此命令在功能上与 LIST NEWSGROUP 命令扩展相同(参见表 85-7)。因此,建议不再使用 XGTITLE。
XHDR 获取文章标题 标题名称以及可选的消息 ID 或文章编号范围 允许客户端请求从一组消息中只获取特定的标题。如果只提供了标题名称,则返回当前组中所有消息的标题。否则,为所选消息提供标题。此扩展为新闻阅读器客户端提供了一种更高效的方式,用于检索和向用户显示新闻组中的重要标题。
XINDEX 获取索引信息 新闻组名称 获取索引文件,该文件由名为TIN的新闻阅读器使用,以提高浏览新闻组的效率。TIN 现在支持更常见的概览格式,因此 XOVER 命令比这个命令更受欢迎。
XOVER 获取概览信息 新闻组中的文章编号或文章编号范围 获取文章或一系列文章的概览。支持此功能的服务器维护一个特殊数据库,其中包含关于新闻组中当前文章的信息,该信息可以由各种新闻阅读器使用。检索概览信息允许像消息线程这样的功能比客户端必须检索每条消息的标题并手动分析它们更快地执行。
XPAT 获取匹配模式的文章标题 标题名称、模式以及消息 ID 或文章编号范围 与 XHDR 类似,它允许为消息集检索特定的标题。区别在于客户端可以指定一个必须匹配的图案,以便检索标题。这允许客户端让服务器搜索并返回某些消息,例如那些主题行表明特定类型讨论的消息,而不是要求客户端下载所有标题并搜索它们。
XPATH 获取文件名信息 消息 ID 允许客户端请求在服务器上存储特定消息的实际文件名。
XROVER 获取概览引用信息 新闻组中的文章编号或文章编号范围 与 XOVER 命令类似,但专门检索指定文章的引用标题中的信息。这是包含创建线程对话所需数据的标题。
XTHREAD 获取线程信息 可选的 DBINIT 参数 与 XINDEX 类似,但检索由名为TRN的新闻阅读器使用的特殊线程信息文件。像 TIN 一样,TRN 现在支持常见的概览格式,因此 XOVER 比此命令更受欢迎。DBINIT 参数可用于检查线程数据库的存在。

其他 NNTP 扩展 |

最后一个扩展组包含与服务器间或客户端-服务器 NNTP 交互不严格相关的杂项扩展。该组中有两个命令:AUTHINFO 和 DATE。后者是一个简单的命令,会导致服务器告诉客户端其当前的日期和时间。AUTHINFO 则更有趣。它被客户端用来向服务器提供身份验证数据。

你可能已经注意到,在 RFC 977 协议中没有描述与安全相关的命令。这是因为原始 NNTP 根本没有任何安全功能。像许多在互联网时代之前编写的协议一样,在 20 世纪 80 年代初,安全性并没有被视为一个大问题。大多数新闻服务器仅由拥有该服务器的组织内部人员使用,并使用了简单的安全措施,例如通过 IP 地址或使用访问列表来限制对服务器的访问。

在 Usenet 规模扩大的早期,许多 NNTP 软件实现所做的更重要改变之一是要求进行身份验证。现代客户端通常会在建立与服务器连接时,将 AUTHINFO 作为它们的第一条命令之一发出,因为服务器在完成此操作之前将拒绝接受大多数其他命令。如果服务器因身份验证不正确而拒绝命令,还会添加一个特殊的回复代码到 NNTP 中。

AUTHINFO 命令可以通过几种不同的方式调用。命令的原始版本要求客户端发出一个带有用户名的 AUTHINFO USER 命令,然后是带有密码的 AUTHINFO PASS。这是一种简单的用户/密码登录身份验证。这种变体的 AUTHINFO SIMPLE 命令,客户端只需要发送一个密码。

客户端和服务器还可以通过使用 AUTHINFO GENERIC 命令来同意使用更复杂的身份验证方法。客户端向服务器提供它想要使用的身份验证方法的名称,以及身份验证所需的任何参数。然后,客户端和服务器根据他们使用的特定身份验证器交换消息和身份验证信息。

小贴士

关键概念 基本命令集的许多限制导致了 20 世纪 80 年代和 90 年代 NNTP 的非标准增强的激增。这些最终被记录在一系列 NNTP 命令扩展中,这些扩展正式补充了原始 RFC 977 命令。这些扩展在概念上分为三组:传输扩展,它细化了 NNTP 传播消息的方式;新闻阅读器扩展,它改善了客户端文章访问;以及杂项扩展。最重要的杂项扩展是 AUTHINFO,它为 NNTP 增加了安全性。

NNTP 状态响应和响应代码

每次作为 NNTP 连接中客户端角色的设备发送命令时,服务器都会发送一个响应。响应用于确认收到命令,通知客户端命令处理的结果,并可能提示提供更多信息。由于 NNTP 命令的结构和格式与 SMTP 命令非常相似,我相信 NNTP 响应与 SMTP(在第七十七章中描述)非常相似,这不会让人感到惊讶。反过来,SMTP 响应基于 FTP 中设计的回复系统。

NNTP 响应的第一行包含一个三位数的数值响应代码,以及一行描述性文本,总结响应内容。这些响应代码的结构使得每个数字都有特定的意义,允许客户端快速确定回复所针对的命令的状态。在初始响应行之后,根据回复的不同,可能会跟随着多个附加的响应行。例如,成功的 LIST 命令会产生一个 215 响应代码,随后是新闻组的列表。

小贴士

背景信息 第七十二章")中关于 FTP 响应代码的讨论解释了为什么除了描述性文本外还使用数值响应代码

与 SMTP 和 FTP 一样,NNTP 响应代码可以认为是xyz的形式,其中x是第一位数字,y是第二位,z是第三位。第一个响应代码数字(x)表示命令在一般意义上的成功、失败或进度;一个成功的命令是否完成或未完成;以及一个未成功的命令未能工作的主要原因。这个数字的值与 SMTP 和 FTP 中定义的略有不同。在某些情况下,术语被简化了;例如,第二类是命令已确认,而不是更晦涩的 Positive Completion Reply。表 85-9 显示了该数字可能值的特定含义。

表 85-9. NNTP 响应代码格式:第一位数字解释

响应代码格式 含义 描述
1yz 信息性消息 通用信息;用于帮助信息和调试。
2yz 命令已确认 命令已成功完成。
3yz 命令已确认,请发送剩余部分 这是一个中间回复,用于提示客户端发送更多信息。通常用于对 IHAVE 或 POST 等命令的回复,服务器确认命令后,请求客户端传输文章。
4yz 命令正确,但无法执行 命令有效但无法执行。此类错误通常由于参数错误、服务器暂时性问题、错误的命令序列或类似情况引起。
5yz 命令未实现或错误,或严重程序错误 命令无效或严重的程序错误阻止了其执行。

第二个回复代码数字(y)用于将消息分类到功能组。这个数字与 SMTP 和 FTP 中的使用方式相同,但功能组不同,如表 85-10 中所述。

表 85-10. NNTP 回复代码格式:第二个数字解释

回复代码格式 含义 描述
x0z 连接、设置和杂项 通用和杂项回复。
x1z 新闻组选择 与用于选择新闻组的命令相关的消息。
x2z 文章选择 与用于选择文章的命令相关的消息。
x3z 分布函数 与消息传输相关的消息。
x4z 发布 与发布消息相关的消息。
x5z 认证 与认证和 AUTHINFO 命令扩展相关的消息。(此类别在标准中未正式列出,但这些响应的中间数字为 5。)
x8z 非标准扩展 保留用于私有、非标准实现使用。
x9z 调试 调试输出消息。

第三个回复代码数字(z)表示第二个数字描述的功能组中的特定消息类型。第三个数字允许每个功能组对于第一个代码数字给出的每个回复类型有十个不同的回复代码。

与 FTP 和 SMTP 一样,这些xyz数字的含义组合起来形成特定的回复代码。例如,如果客户端发出 IHAVE 命令但服务器不希望提供文章,服务器会发送回复代码 435。命令是正确的,但回复是负面的,因此以 4 开头,并且消息与消息分发相关,因此中间数字为 3。

表 85-11 包含了一些更常见的 NNTP 回复代码列表,按数字顺序排列,以及来自标准的典型回复文本和额外的描述信息。

表 85-11. NNTP 回复代码

回复代码 回复文本 描述
100 接下来是帮助文本 在对 HELP 命令的响应之前发送。
111 (日期和时间) 对 DATE 命令扩展的响应。
199 (调试输出) 调试信息。
200 服务器就绪 - 允许发布 在会话初始化时由服务器发送,如果客户端被允许发布消息。
201 服务器就绪 - 不允许发布 在会话初始化时由服务器发送,如果客户端不允许发布消息。
202 已记录从属状态 对 SLAVE 命令的响应。
203 流式传输正常 对 MODE STREAM 命令的成功响应。
205 关闭连接 - 再见! 在收到 QUIT 消息后发送的再见信息。
211 n f l s 已选择组 对 GROUP 命令的成功响应,指示组中估计的消息数量 (n)、第一和最后文章编号 (fl) 以及组名 (s)。
215 随后跟有新闻组列表 (或) 随后跟有信息 对 LIST 命令的成功响应。第二种形式是针对作为 NNTP 命令扩展定义的 LIST 变体。
218 随后跟有 tin 风格索引 对 XINDEX 命令扩展的成功响应。
220 n 文章已检索 - 头部和正文随后 对 ARTICLE 命令的成功响应,指示文章编号和消息 ID。
221 n 文章已检索 - 头部信息随后 对 HEAD 命令的成功响应,指示文章编号和消息 ID。
222 n 文章已检索 - 正文信息随后 对 BODY 命令的成功响应,指示文章编号和消息 ID。
223 n 文章已检索 - 请求单独发送文本 对 STAT 命令的成功响应,指示文章编号和消息 ID。
224 随后跟有概要信息 对 XOVER 命令扩展的成功响应。
230 按消息 ID 列出新文章 对 NEWNEWS 命令的成功响应。
235 文章已成功传输 在文章发送后对 IHAVE 命令的成功响应。
239 文章已成功传输 对 TAKETHIS 命令的成功响应。
240 文章已成功发布 在文章发布后对 POST 命令的成功响应。
250 或 281 认证接受 使用 AUTHINFO 命令扩展成功认证。
282 随后跟有组和描述列表 对 XGTITLE 命令扩展的积极响应。
288 随后跟有二进制数据 对 XTHREAD 命令扩展的成功响应。
335 将文章发送以供传输 对 IHAVE 命令的初步响应。
340 将文章发送以供发布 对 POST 命令的初步响应。
381 需要更多认证信息 对 AUTHINFO 命令扩展的初步响应。
400 服务已中断 会话正在终止,可能是由于用户请求。
411 没有这样的新闻组 指定的新闻组名称无效。
412 没有选择新闻组 在使用 GROUP 命令选择新闻组之前尝试发出引用当前新闻组的命令。
420 没有当前文章被选中 在通过文章选择设置指针之前,尝试使用服务器的当前文章指针发布涉及当前文章的命令。
421 本组中没有下一篇文章 在新闻组的最后一篇文章时对 NEXT 命令的响应。
422 本组中没有上一篇文章 可能是 LAST 的响应(我不知道为什么“previous”这个词在那里)。
423 本组中没有这样的文章编号 无效文章编号的命令。
430 找不到这样的文章 文章未找到;它可能已被删除。
435 文章不受欢迎 - 不要发送 如果服务器不需要文章,则对 IHAVE 的负面响应。
436 转移失败 - 尝试稍后重试 文章传输暂时失败;重试。
437 文章被拒绝 - 不要再尝试 由于任何原因拒绝文章。
438 我已经有了,请不要发给我 与回复代码 435 相同,但针对 CHECK 命令扩展。
440 发布不允许 在不允许发布时发布 POST 命令。
441 发布失败 POST 命令失败。
450 此命令需要授权 当服务器需要认证但客户端尚未认证时发送的响应。
452 授权被拒绝 认证失败。
480 转移权限被拒绝 如果不允许转移,则对 CHECK 的响应。
500 命令未识别 坏命令。
501 命令语法错误 命令中的语法错误。
502 访问限制或权限被拒绝 权限被拒绝;如果客户端没有正确认证但服务器需要它,则发送。
503 程序故障 - 命令未执行 通用致命错误消息。

小贴士

关键概念 每个作为 NNTP 连接中客户端的设备发送的命令都会导致服务器返回一个回复。NNTP 回复由三位数的回复代码和一系列描述性文本组成。这些代码是模仿 SMTP 的,进而模仿 FTP。

第八十六章。GOPHER 协议(GOPHER)

无标题图片

假设我告诉你我将要描述一个专为分布式文档搜索和检索而设计的 TCP/IP 应用层协议。此协议使用客户端/服务器模型进行操作,其中服务器提供指向相关资源的链接,例如文件或程序,用户通过显示用户选择选项的客户端软件访问这些资源。你可能认为我在谈论万维网,而且有很好的理由。然而,在这种情况下,我实际上在谈论网络的先驱之一:Gopher 协议

在本章中,我简要描述了 Gopher 的历史、操作、与万维网的差异以及在现代互联网中的作用。

Gopher 概述和一般操作

讨论此协议的一个好地方是从其名称开始,这个名字选择得很好,有多个原因。Gopher 协议是在明尼苏达大学开发的,该校的体育队伍被称为金戈菲尔(明尼苏达州被称为戈菲州)。这是名称的直接来源,但这也很合适,因为共享这个名字的啮齿动物以挖掘而闻名,就像协议被设计成“挖掘”通过互联网一样。当然,术语 gopher 也适用于执行差事的人,例如检索文档(他们“go fer”这个,“go fer”那个)。

Gopher 协议是在 20 世纪 80 年代末期开发的,旨在为大学的学生和教师提供一个组织文档的机制,以便他们可以轻松访问。指导系统开发的核心理念是 简单性。Gopher 是基于少数核心原则设计的,并且它使用一种非常直接的机制在客户端和服务器设备之间传递信息。它被描述在 1993 年 3 月发布的 RFC 1436 中。

Gopher 服务器上的信息存储

Gopher 可访问的信息存储在 Gopher 服务器 上的文件中。它以类似于 Windows PC 或 UNIX 工作站文件系统树的方式组织。

正如文件系统由包含文件和子目录(子文件夹)的顶层目录(或文件夹)组成一样,Gopher 服务器将信息呈现为一个顶层目录,其中包含文件等资源以及/或包含更多资源的子目录。不同服务器上的资源可以通过在彼此的资源层次结构中提及它们来相互链接。还可以创建虚拟资源,它们的行为就像文件一样,例如允许 Gopher 服务器进行搜索的程序。

Gopher 客户端/服务器操作

Gopher 的典型使用是从客户端用户在客户端机器上创建一个 TCP 连接到 Gopher 服务器开始,使用众所周知的 TCP 端口号 70。连接建立后,服务器等待客户端通过发送一个称为选择字符串的文本来请求特定的资源。通常,当用户首次访问服务器时,他们不知道要请求什么资源,因此会发送一个空(空)的选择字符串。这会导致服务器向客户端发送一个列表,列出服务器文件系统树顶层(根)目录中可用的资源。

服务器发送的目录列表由一系列行组成,每行描述该目录中的一个可用资源。每行包含以下元素,每个元素由制表符分隔:

类型字符和资源名称 行的第一个字符告诉客户端软件该行代表的是哪种资源。最常见的类型字符是 0(零)表示文件,1 表示子目录,7 表示搜索服务。直到第一个制表符字符之前的其余字符包含要向用户展示的资源名称。

选择字符串 发送到服务器以检索此资源的文本字符串。

服务器名称 资源所在的服务器名称。

服务器端口号 用于访问此资源服务器的端口号;通常是 70。

每行都以符合 Telnet 网络虚拟终端(NVT)规范的回车/换行(CRLF)字符序列结束。在发送目录列表(或任何其他响应)后,客户端和服务器之间的连接将关闭。

在收到此类目录列表后,Gopher 客户端软件将向用户显示一个菜单,其中包含服务器提供的所有资源名称。然后用户从菜单中选择他想要的项,客户端通过连接到适当的服务器和端口号,并发送该资源的选择字符串来检索它。如果这本身代表一个子目录,服务器将发送该子目录的新目录列表;如果它代表其他类型的资源,它将根据资源类型的要求进行访问。

例如,假设这一行是从服务器发送到客户端的:

0Gopher Introduction<Tab>intro<Tab>gopher.someserver.org<Tab>70

这将在包含其他选项的菜单中以名为 Gopher Introduction 的文件形式展示给用户。如果用户选择它,客户端将启动与 Gopher 服务器 gopher.someserver.org 在端口 70 的连接,并向该服务器发送选择字符串 intro 以检索文档。

Gopher 和 Web 之间的重要差异

正如我在本讨论开始时暗示的那样,Gopher 和 Web 都旨在实现相同的基本目的:提供对信息库的访问,并在相关文档和资源之间建立链接。然而,它们在如何访问信息方面采取了非常不同的方法,特别是在两个关键领域:用户界面和资源链接。

Gopher 向用户展示的内容完全围绕其分层文件系统。因此,Gopher 本质上是基于菜单的,用户界面通常基于这些菜单的简单文本展示。相比之下,网络服务器上的信息可以以任何方式组织,并以服务器所有者希望的形式或风格展示给用户。网络更加自由形式,除非以某种方式有利,否则不需要使用目录结构。

在万维网中,链接是在文档之间直接进行的,通常使用超文本标记语言(HTML)标签。当某人撰写文档 A 时提到与文档 B 相关的内容,她会在文档 A 中直接放置指向文档 B 的链接。另一方面,Gopher 并没有设计成以这种方式使用链接。相反,链接的目的是使用我之前描述的目录树进行链接。

Gopher 在现代互联网中的作用

有些人认为,在许多方面,Gopher 在技术上优于万维网。他们认为,让服务器进行链接比在文档中嵌入链接更干净。也可以提出这样的论点:Gopher 的文本导向效率更高,更能确保平台之间的兼容性,并且更适合像低带宽链接和视力障碍者访问这样的特殊需求情况。因此,一些 Gopher 爱好者认为,它比万维网是一个更纯粹的超文本系统。

然而,历史告诉我们,尽管 Gopher 比万维网出现得早,但万维网在短短几年内就超过了它的人气。如今,万维网是互联网上的 900 磅巨猩,而大多数人甚至从未听说过 Gopher。发生了什么?

我认为 Gopher 输给万维网的主要原因在于万维网具有更大的灵活性。Gopher 使用文本超链接和服务器目录结构可能很高效,但它是有限的。相比之下,万维网允许以多种方式展示信息。万维网的开放和非结构化特性使其成为信息提供者和应用开发者创造力的理想载体。在 20 世纪 90 年代中期,万维网也恰好处于支持从文本到图形计算过渡的最佳位置,而 Gopher 则没有。

简而言之,你可以用万维网做更多的事情,而大多数人更关心功能性和选项的广度,而不是直接的效率。一旦万维网开始获得动力,它很快就滚雪球般地发展起来。仅仅几年时间,万维网的使用就根深蒂固,而 Gopher 无法与之竞争。

对于其本身,明尼苏达大学可能因为其有争议的决定——向希望将 Gopher 用于商业目的的公司收取许可费——加速了 Gopher 的消亡。我不认为这有什么恶意。大学预算有限,希望能够负担得起的公司支付一小笔费用来支持 Gopher 软件的开发。然而,计算历史一次又一次地表明,没有比试图对协议或标准收取许可费或版税更快的方式来杀死它,无论理由是什么。

到 20 世纪 90 年代末,Gopher 已经走向了淘汰的道路。随着该协议的使用量减少,许多组织再也无法证明继续运行 Gopher 服务器是有必要的。甚至明尼苏达大学本身也因利用率低而最终关闭了自己的 Gopher 服务器。2002 年,一个与 Gopher 相关的安全漏洞在 Internet Explorer 中被发现,微软选择简单地从产品中移除 Gopher 支持,而不是修复这个问题。如今,Gopher 仍然存在,但它只是一种由相对较少的爱好者以及一些有使用 Gopher 历史的组织所使用的利基协议。

小贴士

关键概念 Gopher 协议是一种分布式文档搜索和检索协议,它于 20 世纪 80 年代末在明尼苏达大学开发。资源存储在 Gopher 服务器上,这些服务器使用分层目录结构来组织信息。Gopher 客户端访问服务器以检索可用资源的目录列表,这些列表以菜单的形式呈现给用户,用户可以从菜单中选择一个项目进行检索。Gopher 的主要优势在于简单易用,但它缺乏在展示方面的灵活性以及有效展示图形和多媒体的能力。因此,尽管 Gopher 诞生早于万维网,但万维网几乎完全取代了它,现在 Gopher 只是一种利基协议。

第三部分-第十章. 交互式和行政工具及协议

第八十七章

第八十八章

文件和消息传输应用包括文件传输协议(FTP)、电子邮件(email)和万维网,这使得文件和消息传输成为经典 TCP/IP 应用中最重要的一类。然而,这些应用并不代表 TCP/IP 互连网使用的唯一方式。虽然不像本节中我们之前检查的一些应用协议那样引人注目,但交互式和行政协议同样重要,值得理解。

本书最后一部分涵盖了 TCP/IP 应用的几个其他类别。第一章描述了交互式和远程应用协议,这些协议传统上用于允许一台计算机的用户访问另一台计算机,或者允许信息的实时交换。第二章讨论了 TCP/IP 管理和故障排除工具,这些工具可以被管理员和最终用户用来管理 TCP/IP 网络并诊断与之相关的问题。

第八十七章. TCP/IP 交互式和远程应用协议

无标题图片

当涉及到 TCP/IP 应用时,文件和消息传输应用受到最多的关注,因为它们是现代互连网中最常使用的应用。另一个不太为人所知的 TCP/IP 应用协议类别是允许用户通过互连网直接交互式访问和使用其他计算机的组,例如公共互联网。这些应用今天并不常被最终用户使用,但它们仍然很重要——从历史角度来看,以及在某些情况下,特别是对网络管理员来说,因为它们的实用性。

在本章中,我简要介绍了 TCP/IP 中使用的经典交互式和远程应用协议。我首先描述了 Telnet 协议,这是 TCP/IP 中最早且概念上最重要的应用协议之一。这次讨论包括对 Telnet 客户端/服务器通信、Telnet 网络虚拟终端(NVT)以及 Telnet 的协议命令和选项的描述。然后,我描述了伯克利远程访问家族,通常被称为r 命令或协议,因为它们的命令名以该字母开头。最后,我简要概述了互联网中继聊天(IRC)协议,这是互联网最初的交互式聊天应用,至今仍被广泛使用。

Telnet 协议

在互联网的最初阶段,计算机科学家需要解决的最重要的问题之一是如何让操作一台计算机的用户能够访问并使用另一台计算机,就像那个远程用户是本地连接到它一样。为了满足这一需求而创建的协议被称为 Telnet,开发它的努力与整个互联网和 TCP/IP 紧密相连。尽管如今的大多数互联网用户从未直接调用 Telnet 协议,但他们一直在间接地使用其一些基本原理。每次你发送一封电子邮件,使用文件传输协议(FTP)传输文件,或加载一个网页时,你都在使用基于 Telnet 的技术。因此,Telnet 协议可以声称是 TCP/IP 历史上最重要的应用协议。

提示

背景信息 对传输控制协议(TCP)的基本理解,特别是其滑动窗口机制和流量控制功能,将有助于理解 Telnet。这些主题在第四十八章和第四十九章中有详细说明。

Telnet 概述、历史和标准

Telnet 的历史实际上可以追溯到我们今天所知道的现代 TCP/IP 协议套件之前的十多年。正如我在 FTP 概述中提到的,TCP/IP 互联网技术早期开发者确定了网络需要满足的两个总体应用需求:允许对资源的 直接访问 和允许对资源的 间接访问。FTP 是为了间接访问而创建的,允许用户从远程主机检索资源,在本地使用它,如果需要的话,将其复制回源。Telnet 是为了直接访问而设计的,允许用户访问远程机器,就像他们本地连接到它一样。

Telnet 历史

Telnet 最初是在 20 世纪 60 年代末开发的。这比我们现在许多人专用的个人电脑时代要早得多。那个时期的所有计算机都很大,通常由许多用户共享。要在计算机上工作,你必须访问连接到该机器的物理终端,这通常是根据主机的需求和要求特别定制的。由此产生了两个具体问题:

  • 如果一个组织拥有几台不同的计算机,每个用户都需要一个单独的终端来访问他们使用的每一台计算机。这既昂贵又低效。我记得曾读过一本书中的引用,将这种情况比作一个房间里有许多电视,每个电视只能显示一个频道。

  • 可能一个更显著的问题是,允许一个站点的一个用户访问并使用另一个站点的机器的困难。当时实现这一点的唯一方法是,从计算机的站点安装一条专用数据电路到用户的站点,将用户的终端连接到远程机器。同样,每个电路只能使一台机器可访问。每个用户和计算机的组合都需要安装和维护一个单独、昂贵的电路。

解决这两个问题的方案是创建一种更通用的方式,允许任何终端访问任何计算机。底层互联网提供了在计算机之间传递信息的机制。这成为了连接站点的物理网络,以及连接网络的 TCP/IP 协议套件。在此基础上运行的应用协议允许用户与任何网络计算机建立会话并使用它。这个应用协议就是 Telnet。

Telnet 是 1969 年在初生的 ARPAnet 上演示的第一个应用协议。第一个专门定义 Telnet 的 RFC 是 RFC 97,“对建议的 Telnet 协议的第一次尝试”,于 1971 年 2 月发布。Telnet 的开发在整个 1970 年代持续进行,有相当多的不同 RFC 致力于协议的修订和与其相关的问题讨论。花了多年时间来完善 Telnet 并解决与其开发相关联的所有困难。该协议的最终版本,“Telnet 协议规范”,于 1983 年 5 月作为 RFC 854 发布。多年来,还发布了其他 RFC 来阐明协议的使用并解决诸如身份验证等问题。此外,还有许多其他 RFC 定义了 Telnet 选项,如本章后面的“Telnet 选项和选项协商”部分所述。

基本 Telnet 概念

初看之下,Telnet 开发得如此之慢可能会令人惊讶,因为在理论上,它应该是一个非常简单的协议来定义。它只需要像其他任何协议一样在网络中发送按键和程序输出。如果每个终端和计算机都使用相同的通信方法,其定义将是简单的,但它们并不相同。Telnet 之所以变得复杂,是因为它需要允许一个制造商的终端能够与可能使用非常不同的数据表示的计算机进行通信。

Telnet 通过定义一种确保终端类型和计算机之间兼容性的方法来解决此问题,同时允许计算机和终端使用它们同意支持的特殊功能。该协议建立在三个主要概念的基础上。

网络虚拟终端 (NVT) Telnet 定义了一个标准化的、虚构的终端,称为 网络虚拟终端 (NVT),它被所有设备用于通用通信。Telnet 客户端从用户那里获取输入,并将其从其原生形式转换为 NVT 格式,以便发送到在远程计算机上运行的 Telnet 服务器。服务器将 NVT 转换为被访问计算机所需的任何表示形式。当数据从远程计算机发送回用户时,这个过程是相反的。这个系统允许客户端和服务器即使使用完全不同的硬件和内部数据表示也能进行通信。在数据中穿插特殊的 Telnet 命令,以便客户端和服务器设备执行管理协议操作所需的各种功能。

选项和选项协商 Telnet 客户端和服务器作为 NVT 行动,避免了设备之间的不兼容性,但这样做是通过去除所有终端特定功能来提供一个大家都能理解的通用基础表示。由于有许多情况下,更智能的终端和计算机可能希望使用更高级的通信功能和服务的场合,Telnet 定义了一个丰富的选项集和一种机制,通过这种机制,Telnet 客户端和服务器可以协商它们的使用。如果客户端和服务器就选项的使用达成一致,则可以启用该选项;如果不一致,它们始终可以回退到 NVT 以确保基本通信。

对称操作 虽然 Telnet 是一个客户端/服务器协议,但它专门设计为不对客户端和服务器软件的性质做出假设。一旦建立 Telnet 会话,计算机就可以作为平等的角色发送和接收数据。它们还可以各自启动选项协商。这使得该协议非常灵活,并导致它在各种地方得到应用,如下一节所述。

Telnet 应用

Telnet 最常与远程登录相关联,这是它的常见传统用途。用户通常使用 Telnet 客户端程序打开到远程服务器的 Telnet 连接,然后服务器将 Telnet 客户端视为本地终端,允许用户登录并访问服务器的资源,就像他正在使用直接连接的终端一样。UNIX 用户仍然广泛使用这种方式,他们经常需要从本地机器登录到远程主机(我每天使用 Telnet 以这种方式访问数百英里外的机器)。然而,对于大多数在 Windows 或 Apple 计算机上工作的互联网用户来说,这种 Telnet 的使用并不常见,他们通过网络资源不是通过直接登录,而是通过其他方式访问。

虽然远程登录是 Telnet 的一个重要部分,但该协议并非最初就是为了那个特定功能而设计的。当使用 Telnet 访问远程设备时,该协议本身仅用于在客户端和服务器机器之间建立连接,根据 Telnet NVT 规则编码要传输的数据,并促进选项的协商和使用。客户端和服务器设备决定是否使用 Telnet 进行远程访问或其他目的。

这种灵活性,加上 Telnet 在 TCP/IP 套件中的历史,导致了它在各种其他协议中的应用。由于 Telnet 对客户端和服务器是什么没有假设,任何程序或应用都可以使用它。许多文件和消息传输应用,如 FTP、简单邮件传输协议 (SMTP)、网络新闻传输协议 (NNTP) 和超文本传输协议 (HTTP),通过发送文本命令和消息进行通信,并使用 Telnet 的 NVT 规范确保设备之间通信的兼容性。它们实际上并没有建立 Telnet 会话或使用选项协商等特性;它们只是以与 Telnet 工作方式一致的方式发送数据。因此,尽管现代互联网用户可能从未有意调用 Telnet,但每次发送或接收电子邮件或浏览网页时,他们都在间接地使用它。管理员甚至可以使用 Telnet 客户端软件访问 FTP 和 HTTP 服务器等设备,并手动向这些设备发送命令。

小贴士

关键概念 Telnet 是 TCP/IP 套件中最古老的协议之一,最早在 1960 年代开发,允许一个计算机系统上的用户直接访问和使用另一个系统。它最常用于远程登录,用户的机器上的 Telnet 客户端软件与远程主机上的 Telnet 服务器建立会话,使用户能够像直接连接一样与主机工作。为了确保使用不同硬件和软件的终端和主机之间的兼容性,Telnet 客户端和服务器软件之间的通信基于一个简化的、虚构的数据表示,称为 网络虚拟终端 (NVT),可以通过协商选项来增强。

Telnet 连接和客户端/服务器操作

Telnet 的整体功能是定义一种方式,允许一台机器上的用户或进程可以访问并使用另一台机器,就像它本地连接一样。这使得 Telnet 在操作上本质上是客户端/服务器模式,就像 TCP/IP 中许多其他应用协议一样。通常,Telnet 客户端是一段软件,作为用户界面的接口,处理按键和用户命令,并展示远程机器的输出。Telnet 服务器是在远程计算机上运行的程序,已配置为允许远程会话。

TCP 会话和客户端/服务器通信

Telnet 用于在客户端和服务器之间进行长时间的数据和命令交互,因此它强烈依赖于会话的概念。因此,Telnet 通过面向连接的传输控制协议(TCP)运行。Telnet 服务器监听在著名的 TCP 端口号 23 上的连接。当客户端想要访问特定的服务器时,它会向相应的服务器发起一个 TCP 连接,服务器会响应并使用标准的 TCP 三次握手(在第四十七章中描述)来建立 TCP 连接。

TCP 连接在整个 Telnet 会话期间保持,Telnet 会话可以持续数小时、数天甚至数周。TCP 的服务质量特性保证数据可靠且有序地接收,并确保数据不会以过高的速率发送给客户端或服务器。提供 Telnet 服务的机器可以支持与不同用户的多个同时会话,通过使用客户端的 IP 地址和端口号来区分每个会话。

由于 TCP 是一种全双工协议,客户端和服务器都可以在 Telnet 会话中随意发送信息。默认情况下,两个设备开始时都使用标准的 NVT 方法来编码数据和控制命令(我们将在本章稍后全面探讨)。它们还可以协商使用 Telnet 选项来为会话提供更强大的功能。虽然选项协商可以在任何时候发生,但在 Telnet 会话首次建立时通常会有一个选项交换的爆发,之后则只有偶尔的选项命令交换。

在 TCP 连接建立且 Telnet 会话活跃时,客户端和服务器软件开始执行它们正常的任务,即使用户与远程主机进行交互。对于用户来说,Telnet 会话看起来基本上与坐在直接连接到远程主机的终端上是一样的。在大多数情况下,服务器将通过发送登录提示来开始用户的会话,要求输入用户名和密码。Telnet 客户端将从用户那里接受这些信息并将其发送到服务器。假设信息有效,用户将被登录并可以使用主机,方式取决于其账户的授权。

如 Telnet 概述中所述,尽管该协议通常用于远程登录,但它并不需要以这种方式使用。运行 Telnet 服务器的计算机管理员决定在该机器上如何使用它。举一个例子,一个 Telnet 服务器可以直接与提供服务的进程或程序接口。我记得几年前使用过一个提供公共天气信息的互联网服务器,它使用 Telnet。在通过该协议连接到该机器后,用户看到的不是登录提示,而是一个天气显示选项菜单。如今,Web 已经取代了大多数此类设施,因为它更适合此类信息检索。

小贴士

关键概念 Telnet 是一种客户端/服务器协议,它使用 TCP 在用户终端和远程主机之间建立会话。Telnet 客户端软件从用户那里获取输入并将其发送到服务器,服务器将其传递给主机机器的操作系统。Telnet 服务器从主机获取输出并将其发送到客户端以显示给用户。虽然 Telnet 最常用于实现远程登录功能,但它并非专门为登录而设计。该协议足够通用,允许它用于各种功能。

使用 Telnet 访问其他服务器

Telnet NVT 表示被 SMTP 和 HTTP 等各种其他协议使用。这意味着,允许您访问 Telnet 服务器的相同 Telnet 客户端也可以用来直接访问其他应用程序服务器。您只需指定对应于服务的端口号即可。例如,以下命令将允许您直接与一个 Web 服务器接口:

telnet *`www.someserversomewhere.org`* 80

您将不会收到登录提示,而是服务器将等待您发送 HTTP 请求消息,就像您是一个网页浏览器一样。如果您输入一个有效的请求,服务器将发送一个 HTTP 响应消息。以这种方式使用,Telnet 可以作为一个非常有价值的诊断工具。

小贴士

关键概念 Telnet 网络虚拟终端 (NVT) 数据表示已被众多其他 TCP/IP 协议采纳作为其消息系统的基础。因此,Telnet 客户端软件不仅可以用来连接到 Telnet 服务器,还可以用来连接到 SMTP 和 HTTP 等协议的服务器,这在诊断目的上非常有用。

Telnet 通信模型和网络虚拟终端 (NVT)

Telnet 的核心实际上是一个相当简单的协议。一旦建立了 TCP 连接并开始 Telnet 会话,客户端和服务器软件的唯一真正任务是捕获输入和输出,并将其通过网络重定向。因此,当用户在其本地终端上按下一个键时,Telnet 客户端软件会捕获它并将其通过网络发送到远程机器。在那里,Telnet 服务器软件将按键发送到操作系统,操作系统将其视为在本地输入。当操作系统产生输出时,过程相反:Telnet 服务器软件捕获输出并将其通过网络发送到用户的客户端程序,该程序将其显示在打印机或监视器上。

用两个众所周知的陈词滥调来说,我可以说这看起来在纸上不错,但魔鬼在于细节。这个简化的实现只有在所有计算机和终端都使用完全相同的硬件、软件和数据表示时才会工作。当然,这今天远非如此,当 Telnet 正在开发时情况更糟。在“美好的旧时光”里,计算机非常专有,并且没有设计成可以互操作。它们在许多方面都不同——从终端使用的键盘类型和它可以发送的按键到终端每行和每屏的字符数,再到用于编码数据和控制功能的字符集。简而言之,计算机 A 被设计成只能接受来自其自己的终端的特定形式的输入,而不是来自计算机 B 的终端。

这实际上是在网络世界中相当常见的问题,我可以举一个现实世界的例子来帮助解释这个问题以及它可能如何被解决。假设一个重要的国际会议有来自不同国家的 30 位大使参加,每位大使都有一位助手。每个大使和助手对只说自己的语言,因此只能相互交流——就像是为相互接口而设计的计算机和终端一样。为了让一个国家的助手能与来自其他国家的大使交流,一个解决方案就是训练助手们说所有其他参加国家的语言。回到计算世界,这就像定义 Telnet 协议,使得每个 Telnet 客户端软件都能理解如何与现有的每台计算机通信。这可以工作,但会非常不切实际且难以实现。

另一种方法是定义一种单一的共同语言,并让所有的大使和助手都学习这种语言。虽然这需要一些工作,但远不如要求人们学习几十种语言那么多。每位大使和助手都会说一种母语和这种选定的共同语言。他们可以使用这种共同语言与所有人进行交流,而无需知道会议中可能使用的所有语言。更重要的是,如果一位大使和助手在会议上说一种新的、第 31 种语言,其他所有代表就不需要学习它。

Telnet 使用了一种非常类似的方法来处理其硬件和软件兼容性问题。而不是让终端和主机使用它们各自的原生语言进行通信,所有的 Telnet 客户端和服务器都同意发送符合虚构的、虚拟终端类型(NVT)的数据和命令。

NVT

NVT 定义了信息格式化和发送的规则集,例如字符集、行终止符以及如何发送关于 Telnet 会话本身的信息。

在终端上运行的每个 Telnet 客户端都理解其原生语言和 NVT 语言。当用户在本地终端上输入信息时,它会被转换为 NVT 格式以便通过网络传输。当 Telnet 服务器接收到这些信息时,它会将其从 NVT 格式转换为远程主机期望接收的格式。从服务器到客户端的传输也执行相同的反向过程。这如图 图 87-1 Telnet 使用网络虚拟终端 (NVT) 表示法,允许使用不同内部格式的用户终端和远程主机进行通信。") 所示。

Telnet 通信和网络虚拟终端 (NVT) Telnet 使用网络虚拟终端 (NVT) 表示法,允许使用不同内部格式的用户终端和远程主机进行通信。

图 87-1. Telnet 通信和网络虚拟终端 (NVT) Telnet 使用网络虚拟终端 (NVT) 表示法,允许使用不同内部格式的用户终端和远程主机进行通信。

小贴士

关键概念 Telnet 的 网络虚拟终端 (NVT) 是一种统一的数据表示,确保了可能使用非常不同硬件、软件和数据格式的终端和主机之间通信的兼容性。Telnet 客户端将终端的原生格式输入转换为 NVT 格式以便传输到 Telnet 服务器,在那里它被转换为主机的内部格式。从主机到用户的输出过程是相反的。

NVT 被定义为包含一个逻辑键盘用于输入和一个逻辑打印机用于输出(协议的年龄在这些术语中得到了反映;几十年前没有显示器,所有输出都在纸上)。NVT 使用 7 位 美国 ASCII (US-ASCII) 字符集。每个字符使用一个 8 位字节进行编码。

然而,客户端和服务器可以使用 Telnet 选项协商其他数据表示,包括传输扩展 ASCII 或甚至完整的 8 位二进制数据。

NVT ASCII 控制码

正规 ASCII 由 95 个常规的可打印字符(代码 32 至 126)和 33 个控制码(0 至 31 和 127)组成。Telnet 标准规定输出设备必须能够处理所有可打印字符,并强制规定如何解释其他一些常见的 ASCII 控制码。在这些码中,有三个(0、10 和 13)必须被所有 Telnet 软件接受;另外五个是可选的,但如果支持,则必须以与 Telnet 规范一致的方式进行解释。表 87-1 描述了标准 Telnet NVT ASCII 控制码。

表 87-1. 标准 Telnet NVT ASCII 控制码的解释

ASCII 值(十进制) ASCII 字符代码 ASCII 字符 描述 支持可选/强制
0 NUL 空字符 无操作(对输出无影响)。 强制
7 BEL 铃声 在输出上产生可听或可视的信号,而不移动打印头。此通知可用于吸引用户的注意,例如在错误的情况下。 可选
8 BS 退格 将打印位置向左移动一个字符。 可选
9 HT 水平制表符 将打印机移动到下一个水平制表位。标准没有指定设备如何就制表位位置达成一致;这可以通过 Telnet 选项进行协商。 可选
10 LF 换行 将打印机移动到下一行,保持打印位置不变。 强制
11 VT 垂直制表符 将打印行移动到下一个垂直制表位。与 HT 字符一样,设备必须使用选项来达成关于垂直制表位位置的协议。 可选
12 FF 进纸 将打印机移动到下一页的顶部(或在显示器上,清除屏幕并将光标定位在顶部)。 可选
13 CR 回车 将打印机移动到当前打印行的左边缘。 强制

Telnet NVT 方案定义了回车(CR)和换行(LF)字符的组合来表示 ASCII 文本行的结束。这两个字符的字面意思是回到左边界(CR)和进入下一行(LF)。然而,NVT 将 CRLF 序列视为不仅仅是两个独立的字符;它们被整体地用来定义一个逻辑行结束字符。这是必要的,因为并非所有终端类型都使用 CR 和 LF 来定义行结束。在本地格式和 NVT 格式之间转换行结束字符是 Telnet 客户端和服务器软件必须执行的功能之一,以确保终端和主机之间的兼容性。

小贴士

关键概念 Telnet NVT 格式基于 7 位 US-ASCII,每个字节携带一个字符。标准规定设备必须处理所有标准可打印 ASCII 字符,以及三个强制性的控制字符。其中两个是回车(CR)和换行(LF)字符;当组合在一起时,它们定义了文本行的逻辑结束。Telnet 标准还描述了五种其他可选 ASCII 控制字符的解释。

半双工和全双工模式

Telnet 时代的另一个遗迹是,为了实现最大兼容性,NVT 规范是在假设半双工操作的情况下设计的:一次只能有一个设备传输。发送数据的设备应该用特殊的 Telnet 前进命令结束其传输,告诉另一个设备现在可以传输(下一部分将描述 Telnet 协议命令)。这类似于使用对讲机的人在每个传输结束时说“Over”,告诉他们的伙伴现在可以回应。

当然,现代网络以全双工模式运行,使用半双工通信将是无谓的低效。在大多数情况下,Telnet 客户端和服务器同意使用一个选项(抑制前进)来消除发送此命令的需要。然而,将其作为默认设置是 NVT 在 Telnet 中充当最小公倍数的一个好例子,以防任一设备需要更简单的操作模式。

Telnet 协议命令

用户在终端输入的大部分输入都是以数据和命令的形式发送给他们正在使用的应用程序。然而,计算机系统也提供了一种方法,用户可以通过它来指示终端发送某些命令,以控制终端本身的操作以及它与连接的计算机的交互。最好的例子是中断进程的命令,通常是通过在用户终端上按下特殊键或键组合来发送的。

Telnet 需要有一个方式允许用户输入这样的命令。然而,在这里我们遇到了在终端和计算机之间通信数据时出现的问题:表示的不一致性。虽然所有终端和计算机都支持中断正在运行程序的能力,例如,它们可能使用不同的按键来调用它。例如,在大多数 UNIX 系统中,ctrl-C 组合键可以中断程序,但在 Windows 系统上输入这个键组合将不会(它通常代表复制数据功能!)。

由于问题与我们在表示数据流时遇到的问题相同,因此解决方案相同并不令人惊讶:使用一组标准命令的通用表示,这些命令在终端和主机计算机之间传递。所有表示这些命令的按键都转换为标准 Telnet 代码进行传输,然后转换为主机计算机的特定需求。因此,如果用户在将 ctrl-C 定义为中断功能的 UNIX 终端上按下,而不是发送那个确切的按键,Telnet 客户端会发送特殊的 Telnet 中断进程命令,该命令由 Telnet 服务器转换为适合连接的主机的适当命令代码。

Telnet 标准包括一系列这些特殊代码,允许用户控制远程计算机的操作。它还定义了一组特定于 Telnet 协议本身的命令;这些命令允许 Telnet 客户端和 Telnet 服务器软件进行通信。这些统称为 Telnet 协议命令

所有 Telnet 命令都发送在与常规数据相同的通信流中。它们使用从 240 到 254 范围内的特殊字节值来表示。为了区分这些值的字节数据和 Telnet 命令,每个命令前面都有一个特殊的 转义字符,被称为 解释为命令 (IAC)。IAC 的值为 255;当接收方看到这个字符时,它知道下一个字节是命令,而不是数据。因此,由于 Telnet 中断进程命令的值为 244,要发送此命令,Telnet 客户端会传输字节 255 然后是 244。如果需要发送实际数据字节值 255,它将以两个 255 字节的形式传输。一些 Telnet 命令还包括额外的数据字节,这些数据字节在命令代码本身之后发送。一个很好的例子是在“Telnet 选项和选项协商”部分后面,您将看到的 Telnet 选项协商中使用参数。

提示

关键概念 Telnet 协议定义了一组协议命令,用于两个目的:首先,表示需要在终端和主机之间发送的标准控制功能,例如中断进程的命令,其次,使 Telnet 客户端和服务器软件之间的协议通信成为可能。协议命令在 Telnet 会话的 TCP 连接的正常数据通信流中发送。每个命令由 240 到 254 之间的字节值表示,并且由 Interpret As Command (IAC)命令(字节值 255) precedes,它告诉接收者流中的下一个字节是命令。

你可能会在这个时候想知道为什么 IAC 字符真的有必要。毕竟,Telnet 使用 US-ASCII,它是 0 到 127 字节范围内的 7 位数据,而 Telnet 命令的值高于 127。使用 IAC 转义字符的一般理由是明确表示正在发送命令。一个更具体的原因是适应通过 Telnet 发送可选的 8 位二进制数据,客户端和服务器可以协商此功能。如果启用此模式且命令不以 IAC 字符开头,则需要以某种方式标记所有值从 240 到 255 的数据字节,以便它们被解释为数据而不是命令。由于命令发送的频率较低,包含额外的命令字节比数据字节更有效。通过转义命令,只有数据字节值 255 需要发送两个字节。

表 87-2 按数值字节值顺序列出 Telnet 协议命令,显示每个命令的代码和名称,并描述其含义和使用方法。

表 87-2. Telnet 协议命令

命令字节值(十进制) 命令代码 命令 描述
240 SE 子协商结束 标记 Telnet 选项子协商的结束,与 SB 代码一起使用以指定更具体的选项参数。有关详细信息,请参阅本章后面的“Telnet 选项和选项协商”部分。
241 NOP 无操作 空命令;不执行任何操作。
242 DM 数据标记 用于标记接收者应扫描以查找紧急 Telnet 命令的数据序列的结束。有关详细信息,请参阅下一节中关于 Telnet 中断处理的讨论。
243 BRK 断开连接 表示在终端上按下“断开连接”或“注意”键。
244 IP 中断进程 告诉接收者中断、中止、挂起或终止当前正在使用的进程。
245 AO 终止输出 指示远程主机继续运行当前进程,但丢弃其所有剩余输出。如果程序开始向用户发送意外大量数据,则可能需要这样做。
246 AYT Are You There 可能用于检查远程主机是否仍然“活跃”。当发送此字符时,远程主机会返回某种类型的输出以指示它仍在运行。
247 EC Erase Character 指示接收方删除数据流中最后一个未删除的字符。用于撤销发送字符。
248 EL Erase Line 告诉接收方删除从最后一个换行符(CRLF)序列(但不包括)回的数据流中的所有字符。
249 GA Go Ahead 在 Telnet 半双工模式下使用,以向其他设备发出可以传输的信号。
250 SB Subnegotiation 标记 Telnet 选项子协商的开始,当选项需要客户端和服务器交换参数时使用。有关完整描述,请参阅本章后面的“Telnet 选项和选项协商”部分。
251 WILL Will Perform 在 Telnet 选项协商中,表示发送此代码的设备愿意执行或继续执行特定选项。
252 WONT Won't Perform 在 Telnet 选项协商中,表示发送此代码的设备要么不愿意执行特定选项,要么现在拒绝继续执行它。
253 DO Do Perform 在 Telnet 选项协商中,请求其他设备执行特定选项或确认对方执行该选项的期望。
254 DONT Don't Perform 在 Telnet 选项协商中,指定对方不执行选项或确认设备对对方不执行选项的期望。
255 IAC Interpret As Command 在前面描述中描述的命令值 240 到 254 前面。连续的两个 IAC 字节表示数据值 255。

也许具有讽刺意味的是,Telnet 命令不像在 Telnet 早期那样被广泛使用,因为许多我们之前讨论的兼容性问题现在不再存在。ASCII 已成为计算世界的标准字符集,因此许多如终止输出或中断进程的功能不再需要使用 Telnet 命令。然而,它们仍然被广泛用于内部 Telnet 操作,如选项协商。

Telnet 中断处理

从 Telnet 客户端发送到服务器的所有数据字节都是按照发送的顺序接收的,反之亦然。这是我们期望应用程序运行的方式。实际上,确保数据不会乱序接收是我们对可靠传输协议 TCP(Telnet 在其上运行)所承担的一项工作。然而,由于 Telnet 以相同的方式在同一个连接上发送数据和命令,这可能会给 Telnet 带来问题。

这种问题最典型的例子是当用户需要中断一个进程时出现。假设你正在使用 Telnet 运行一个需要用户输入、处理输入并产生输出的交互式程序。当你愉快地输入时,你注意到已经有一段时间没有看到程序输出。这显然是由于编程错误或其他故障而挂起了。

如果你在一个直接连接的终端上使用该程序,你只需使用适合该终端的键或按键命令来中断或终止进程,然后重新启动它。相反,你正在使用 Telnet,所以你输入适当的按键,它被转换成特殊的 Telnet 中断进程命令代码(字节值为 244,前面是 Telnet 解释为命令代码,255)。

由于 Telnet 只使用单个流来传输命令和数据,因此该代码被放入 TCP 数据流中,以便发送到 Telnet 服务器。由于你输入了一段时间的数据,Telnet 中断进程代码将位于大量常规数据字节之后。现在远程进程已经停止读取这些数据,这意味着服务器的 TCP 接收缓冲区将开始填满。因此,中断进程命令将卡在缓冲区中,等待被读取。实际上,如果命令前面的数据字节足够多,服务器上的 TCP 缓冲区可能会完全填满,导致服务器关闭客户端的 TCP 发送窗口。这意味着中断进程命令将等待在客户端的出站 TCP 队列中,并且永远不会发送到远程主机!

我们需要的是一种方法,能够标记中断进程命令,以便无论其前面的数据字节数量如何,都可以发送到远程主机。如果你已经阅读了关于 TCP 的章节,你可能认为你已经阅读了关于该协议的一个特性,这个特性似乎非常适合这个问题,而且你是对的!TCP 紧急功能(在第四十八章 Chapter 48 中描述)允许重要数据被标记,以便它比常规数据具有优先级,这个过程有时被称为带外信号(因为信号在正常数据流之外)。Telnet 使用 TCP 的这个特性来定义它所说的同步功能

当需要时,客户端通过发送特殊的 Telnet 数据标记(DM)协议命令来调用同步功能,同时指示其 TCP 层将该数据标记为紧急。携带此命令的 TCP 段中的 URG 位使其绕过 TCP 的正常流量控制机制,从而将其发送到远程主机。Telnet 服务器软件看到数据流中的同步,在其缓冲区中的所有数据中搜索,只寻找 Telnet 控制命令,如中断进程、中止输出和你在吗。然后立即执行这些命令。服务器继续搜索重要命令,直到看到数据标记命令为止。所有中间数据都被丢弃;它需要重新传输。在处理完数据标记后,服务器返回到正常操作。

服务器也可以在与其客户端设备上的用户通信时使用同步功能。例如,如果用户向服务器发送中止输出命令,她是在告诉服务器丢弃当前进程的所有剩余输出。服务器将停止发送该输出,并可以使用同步功能清除所有等待发送到客户端机器的未处理数据(因为它会导致数据被丢弃)。

小贴士

关键概念 Telnet 协议命令与用户数据在同一数据流中发送,这意味着远程主机的问题可能会停止数据流,导致用户命令积压并且主机无法接收。由于这可能包括用户尝试解决主机问题的命令,这可能会成为一个严重的问题。为了缓解这种情况,Telnet 包含了 同步功能,它使用 TCP 的紧急数据传输功能强制接收关键命令,即使常规数据没有被处理。

Telnet 选项和选项协商

基本的 Telnet NVT 规范通过定义每个 Telnet 客户端和服务器使用的通用数据表示和命令,解决了不同终端和计算机类型之间的兼容性问题。然而,这种通用表示的代价非常高:所有终端和主机的先进或特殊功能都被剥离。结果是,虽然每个人都能使用这种语言,但它并不能进行比基本对话更多的功能。

Telnet 的创造者认识到,虽然定义 NVT 作为确保跨设备兼容性的共同基础很重要,但同时也必须提供一种方式,让客户端和服务器能够同意使用更先进的通信方式。他们定义了一套 Telnet 选项 和一种机制,通过这种机制,Telnet 客户端和服务器可以 协商 他们想要使用的选项。

大多数 Telnet 选项用于提高设备之间数据传输的效率。例如,默认情况下,NVT 假设每个设备使用半双工操作,需要在每次传输后使用 Go Ahead 命令。然而,现在几乎所有硬件都支持全双工通信,因此设备通常会同意使用抑制 Go Ahead 选项来消除发送此字符的需要。同样,设备可以协商发送 8 位二进制数据而不是 Telnet NVT 的标准 7 位 ASCII 码。

Telnet 选项协商的过程在主 Telnet 标准文档 RFC 854 中以及配套文档 RFC 855,“Telnet 选项规范”中进行了描述。这些选项本身在单独的因特网标准集中进行了描述。其中一些与 RFC 854 和 RFC 855 同时发布;其他一些作为 Telnet 先前版本的组成部分在较早时定义;还有一些在多年后被添加。现在存在几十种不同的 Telnet 选项。互联网数字分配机构(IANA)维护了一个主列表,就像它维护其他 TCP/IP 参数一样。所有 Telnet 选项的最新列表可以在 IANA 网站上找到,网址为www.iana.org/assignments/telnet-options/

常见 Telnet 选项

每个 Telnet 选项都使用一个十进制字节码来标识,其可能值为 0 到 254。值 255 保留用于扩展选项列表,以防需要超过 255 个选项。每个选项还与一个文本代码字符串相关联,这通常在协议讨论和诊断输出中用作代码号的符号。表 87-3 列出了一些更有趣的 Telnet 选项,并对每个选项提供了简要描述。

表 87-3. 常见 Telnet 选项

选项编号 选项代码 选项名称 描述 定义 RFC
0 TRANSMIT-BINARY 二进制传输 允许设备以 8 位二进制形式发送数据,而不是 7 位 ASCII 码。 856
1 ECHO 回显 允许设备协商各种不同的回显模式。(当你在一个终端上按下一个键时,你也期望看到你输入的字符作为输出出现在终端屏幕上;这被称为回显输入。) 857
3 SUPPRESS-GO-AHEAD 抑制 Go Ahead 允许不使用半双工模式的设备不再需要使用 Telnet Go Ahead 命令来结束传输。 858
5 STATUS 状态 允许设备请求 Telnet 选项的状态。 859
6 TIMING-MARK 定时标记 允许设备协商在数据流中插入一个特殊的定时标记,用于同步。 860
10 NAOCRD 输出回车符处理 允许设备协商如何处理回车符。 652
11 NAOHTS 输出水平制表符位置 允许设备确定用于输出显示的水平制表符位置。 653
12 NAOHTD 输出水平制表符处理 允许设备协商如何处理水平制表符,以及通过连接的哪一端处理。 654
13 NAOFFD 输出换页符处理 允许设备协商如何处理换页符字符。 655
14 NAOVTS 输出垂直制表符位置 用于确定用于输出显示的垂直制表符位置。 656
15 NAOVTD 输出垂直制表符处理 允许设备协商垂直制表符的位置处理。 657
16 NAOLFD 输出换行符处理 允许设备决定如何处理换行符字符。 658
17 EXTEND-ASCII 扩展 ASCII 允许设备同意使用扩展 ASCII 进行传输,并协商其使用方式。 698
24 TERMINAL-TYPE 终端类型 允许客户端和服务器协商使用特定的终端类型。如果他们达成一致,这将允许服务器的输出根据用户使用的特定终端的需求进行理想化的定制。 1091
31 NAWS 协商窗口大小 允许通信终端窗口的大小。 1073
32 TERMINAL-SPEED 终端速度 允许设备报告当前的终端速度。 1079
33 TOGGLE-FLOW-CONTROL 远程流控制 允许在客户端和服务器之间启用和禁用流控制。 1372
34 LINEMODE 行模式 允许客户端一次发送一行数据而不是一个字符,通过将大量的小型 TCP 传输替换为少量的大型传输来提高性能。 1184
37 AUTHENTICATION 认证 允许客户端和服务器协商一种认证方法以安全连接。 1416

小贴士

关键概念 Telnet NVT 规范确保所有使用 Telnet 的设备都能相互通信,但这是在最低级别上完成的通信。为了允许使用更复杂的格式和服务,Telnet 定义了一系列 选项。如果客户端和服务器都实现了特定的选项,它们可以通过 协商 过程来启用其使用。

Telnet 选项协商

Telnet 选项协商的第一阶段是客户端和服务器决定是否启用特定的选项。Telnet 操作对称性的一个方面是,任何设备都可以选择启动一个选项的使用。启动设备可以指定它想要开始使用一个选项,或者它想要其他设备开始使用它。响应设备可以同意或不同意。只有当两个设备都同意使用该选项时,才能启用选项。

此协商是通过四个 Telnet 协议命令来执行的:WILL、WONT、DO 和 DONT。

要指定它想要开始使用一个选项,启动器将 WILL 命令发送到其他设备。响应设备可能有两种可能的回复:

DO 发送以表示同意启动器应使用该选项;然后它被认为是启用的。

DONT 发送以指定启动器不得使用该选项。

如果启动器希望其他设备开始使用一个选项,它将发送 DO 命令。该设备可能会以两种方式响应:

WILL 发送以指定响应设备将同意使用该选项;选项被启用。

WONT 发送以告知启动器,响应器将不会使用请求的选项。

Telnet 的对称性以及 DO 和 WILL 都可以用来启动协商或响应协商的事实,使得 Telnet 的选项协商可能变得复杂。由于任何设备都可以在任何时候启动选项的协商,如果两个设备同时尝试启用一个选项或各自持续响应对方的回复,这可能会导致确认循环。因此,Telnet 标准指定了 WHEN 使用 WILL 和 DO 命令的限制。一个是设备只能发送协商命令以请求更改选项的状态;它不能仅为了确认或加强当前选项的状态而发送 DO 或 WILL。另一个是,当设备收到请求开始使用它已经使用的选项时,它不应使用 DO 或 WILL 进行确认。

由于一个选项只能在两个设备都同意使用它的情况下被激活,因此任何设备都可以在任何时候通过发送这些命令之一来禁用选项的使用:

WONT 由设备发送,表示它将停止使用一个选项。其他设备必须以 DONT 作为确认进行响应。

DONT 由设备发送,表示它希望其他设备停止使用一个选项。其他设备必须以 WONT 响应。

小贴士

关键概念 任何设备都可以选择协商使用 Telnet 选项。发起者使用 WILL 命令来指定它想要开始使用特定选项;如果另一设备同意,它将响应 DO;否则,它发送 DONT。或者,发起者可以使用 DO 命令来指示它希望另一设备开始使用选项;如果该设备同意这样做,它将响应 WILL,如果不同意,则响应 WONT。任何设备都可以通过发送 WONT 或 DONT 命令在任何时候禁用选项的使用。

选项子协商

所述的 DO/DONT/WILL/WONT 协商仅用于启用或禁用选项。某些选项,如二进制传输选项(TRANSMIT-BINARY),要么是开启要么是关闭;在这种情况下,此选项协商就足够了。其他选项在启用后需要客户端和服务器交换参数以控制选项的工作方式。例如,TERMINAL-TYPE 选项需要客户端以某种方式向服务器发送终端名称。Telnet 允许客户端和服务器通过称为选项子协商的过程发送与选项相关的任意数量的数据。

设备通过发送一系列特殊的 Telnet 协议命令和数据开始子协商过程。首先,设备发送 SB(子协商)命令,然后是特定选项定义的选项号和参数,最后通过发送 SE(子协商结束)命令结束子协商数据。SB 和 SE 都必须在 Interpret As Command(IAC)命令字节之前。

让我们以终端类型协商为例。假设服务器支持此选项并希望客户端使用它。服务器通过发送 DO 命令开始选项协商:

IAC DO TERMINAL-TYPE

假设客户端同意,它将使用 WILL 命令响应:

IAC WILL TERMINAL-TYPE

现在终端类型选项已生效,但服务器仍然不知道客户端使用的是哪种终端。它可以通过发送此命令来提示客户端提供该信息:

IAC SB TERMINAL-TYPE SEND IAC SE

接收此选项子协商命令的客户端将使用以下方式响应:

IAC SB TERMINAL-TYPE IS <*`some_terminal_type`*> IAC SE

小贴士

关键概念 WILL 和 DO 命令仅用于开启客户端和服务器同意使用的 Telnet 选项。在某些情况下,选项需要在客户端和服务器设备之间发送额外的信息才能正常工作。这是通过一个称为选项子协商的过程来实现的。任何设备都可以通过发送包含 SB(子协商)和 SE(子协商结束)Telnet 协议命令的数据集来向另一设备发送与选项相关的数据。

伯克利远程(r)命令

TCP/IP 之所以取得成功,在很大程度上是由于其通用性——它几乎在所有主要的计算平台上都得到了实现。虽然该套件因此并非针对任何特定的操作系统,但不可否认的是,它的历史与 UNIX 紧密相连。早期互联网上的大多数计算机都使用 UNIX,TCP/IP 的发展在许多方面与 UNIX 的发展并行。

在 UNIX 开发中起着重要作用的组织之一,因此间接地影响了 TCP/IP 的发展,是加利福尼亚大学伯克利分校(UCB)。USB 开发的知名伯克利软件发行版(BSD) UNIX 已经广泛使用超过 20 年。他们还为 BSD UNIX 开发了一套命令,以方便在 TCP/IP 互联网上进行各种远程操作功能。这些程序都以字母r(代表远程)开头,因此它们被称为伯克利远程命令(或实用程序)以及简单地称为r 命令。自从它们最初创建以来,它们已经被大多数 UNIX 变体和一些其他操作系统所采用。

小贴士

背景信息 这一部分对于那些对 UNIX 操作系统有一定了解的人来说可能更容易理解,而对于那些没有了解的人来说可能就不那么容易理解了

伯克利远程登录(rlogin)

伯克利远程协议家族的头部是远程登录命令,rlogin。正如其名明显暗示的那样,该程序的目的允许 UNIX 主机上的用户通过 TCP/IP 互联网登录到另一台主机。由于 Telnet 也经常用于远程登录,因此rlogin和 Telnet 有时被认为是 TCP/IP 远程登录的替代品。虽然它们可以以类似的方式使用,但在一些方面它们是相当不同的。

从概念上讲,Telnet 被设计成一种协议,以实现终端/主机通信。正如我在本章前面的 Telnet 概述中提到的,该协议并非专门为远程登录而设计。相比之下,rlogin旨在实现这一特定目的,这在它的操作中得到了体现。

该协议要求在将要允许远程访问的主机上运行rlogin服务器软件;它通常被称为rlogind(对于rlogin 守护进程,后一词是标准 UNIX 术语,指后台服务器进程)。服务器监听 TCP 端口 513 上的传入连接请求。想要远程登录到服务器的用户在其本地主机上运行rlogin命令并指定服务器名称。客户端与服务器建立 TCP 连接,然后向服务器发送包含以下信息的字符串:

  • 客户机上的用户登录名

  • 用户希望在服务器上使用的登录名(这通常与客户端上的用户登录名相同,但并不总是如此)

  • 控制信息,例如终端的类型和速度

服务器处理这些信息并开始登录过程。它通常会提示用户输入密码以登录到远程主机。假设密码正确,用户将登录到远程主机,并可以像本地连接的用户一样使用它。

从实际角度来看,rlogin 命令比 Telnet 简单得多;它不支持 Telnet 的完整命令结构,也不支持选项协商等能力。然而,它确实包括一组小命令。客户端能够向服务器发送一条关键信息:当前使用的终端窗口的大小。服务器能够通知客户端开启或关闭流量控制,请求客户端发送当前窗口大小,或者要求客户端清除服务器已发送的挂起输出,直到数据流中的某个特定点。

一些组织每天使用许多不同的 UNIX 主机,使用 rlogin 时需要不断输入密码可能有些繁琐。在这些系统中,管理员可以设置控制文件,指定主机名、用户名和密码的组合。如果设置正确,这允许授权用户使用 rlogin 自动远程访问主机,而无需输入登录名或密码。

如最初设计的那样,rlogin 是 TCP/IP 早期协议的一个经典例子,因为它强调的是简洁性和可用性而非安全性。这一点在前面描述的自动登录过程中尤为明显。rlogin 最初用于身份验证的方案被认为不足以满足现代 TCP/IP 互连网络,尤其是连接到互联网的网络。rlogin 的后续版本增加了更安全的授权方法。还有一个名为 slogin(代表 secure login)的新程序,它使用更强的身份验证和加密,旨在在新系统上取代 rlogin

小贴士

关键概念 伯克利远程,或 r 命令,简化了 TCP/IP 互连网络中 UNIX 主机之间的远程操作。这个系列的基本命令是 远程登录 命令,rlogin,它允许一个主机上的设备访问并使用另一个主机,就像它本地连接到它一样。rlogin 常常被用作 Telnet 的替代品。在概念上和实际操作上,它都比 Telnet 简单。

伯克利远程壳(rsh)

当用户需要登录到服务器执行多项任务时,通常会使用 rlogin。然而,在某些情况下,用户只需要在远程主机上输入一条命令。使用 rlogin,用户需要登录到主机,执行命令,然后再次登出。这并不是一个巨大的不便,尤其是当正确配置了允许自动登录的配置文件时。然而,随着时间的推移,所有额外的登录和登出步骤都可能变得繁琐。为了方便起见,rlogin 的一个变体,称为 rsh(代表 远程 shell),允许用户访问远程主机并在其上执行单个命令,而无需进行登录和登出步骤。

注意

Shell 是 UNIX 中用来指代接受用户命令并在屏幕上显示输出的用户界面的标准术语。

rsh 命令基于 rlogin 并以类似的方式工作,但它围绕执行命令而不是建立持久的登录会话。远程主机上的服务器进程通常称为 rshd(代表 远程 shell 守护进程)并监听传入的 rsh 请求。当收到请求时,用户将通过与 rlogin 相同的机制登录。命令在远程主机上运行,然后用户会自动登出。

当使用自动登录时,rsh 最有用,这样程序就可以运行而无需用户输入登录名或密码。在这种情况下,程序可以使用 rsh 在远程主机上自动运行命令,而无需人工干预,这为 UNIX 用户打开了多种可能性。正常的 UNIX 用户界面概念,如 标准输入(stdin)、标准输出(stdout)和标准错误(stderr) 也适用于 rsh,因此您可以使用它来执行远程命令并将输出重定向到本地文件。例如,以下命令可以让用户获取主机服务器上其主目录的列表并将其存储在名为 remotelist 的本地文件中:

rsh <*`somehost`*> ls -l >remotelist

小贴士

关键概念 rsh(远程 shell)命令类似于伯克利 rlogin 命令,但它不是在远程主机上打开登录会话,而是执行一个用户提供的单个命令。rsh 对于需要快速在远程主机上执行操作的用户非常有用,它还可以被其他程序用来自动化网络任务。

由于 rsh 基于 rlogin,所有适用于 rlogin 的担忧也与此相关,尤其是在安全方面。(我们真的不希望未经授权的用户在我们的服务器上运行命令!)与 rlogin 一样,rsh 的新版本支持比原始软件更先进的身份验证选项。同样,正如 sloginrlogin 的一个更新、更安全的版本一样,有一个名为 ssh(代表 安全 shell)的程序在许多系统中取代了 rsh

注意

在某些系统上,如果 rsh 没有指定要执行的命令,则会建立交互式远程会话,就像输入了 rlogin 命令而不是 rsh *一样。

其他伯克利远程命令

rloginrsh 命令是伯克利 r 程序家族的通用成员,允许远程访问主机。为了补充这些,开发者还定义了一小部分特定的远程命令。这些命令本质上是一些常见 UNIX 功能的远程版本。然而,命令不是只应用于一个系统,而是在两个系统之间或整个 TCP/IP 网络上的所有系统之间使用。

所有这些命令都与 rlogin 一样基于 rsh。它们以相同的方式工作,但不是打开会话或将用户指定的命令传递给远程主机,而是执行特定功能。以下是最常见的这些远程命令:

远程复制(rcp 这是 UNIX 复制 (cp) 命令的远程版本。它允许在本地主机和远程主机之间或两个远程主机之间复制文件。通常的语法基本上与常规 cp 命令相同,但源和/或目标被指定为位于远程主机上。rcp 命令可以像 FTP 一样使用,但更简单、功能更少。或者换句话说,rcp 相对于 FTP,就像 rlogin 相对于 Telnet。这不是一个完美的类比,但非常接近。

远程运行时间(ruptime UNIX 命令 uptime 显示计算机自上次启动以来运行了多长时间,以及与其当前负载相关的信息。ruptime 是此命令的远程版本;它显示网络上每台机器的当前状态(运行或关闭),每台运行机器自上次启动以来运行了多长时间,以及其负载统计信息。

远程谁(rwho 这是 who 命令的远程版本。who 命令显示运行其上的主机上所有登录的用户,而 rwho 命令显示网络上所有机器上登录的所有用户。

ruptimerwho 命令都依赖于在联网机器上后台运行的 rwhod(远程谁守护进程)。这些进程会定期相互共享有关主机运行时间和每个系统登录用户的信息,因此当运行 ruptimerwho 时可以快速显示。

在某些操作系统上,还可能实现其他远程命令。与 rloginrsh 一样,这些命令可能存在安全问题,而其他命令(如 rwho)可能存在效率问题。因此,在许多网络上,这些命令不再使用。

互联网中继聊天协议(IRC)

电子邮件(email)相对于传统邮件的主要优势是速度。不需要等待几天或几周才能将消息送达,它通常在几分钟甚至几秒钟内到达。这使得电子邮件对于大多数类型的信息传输来说比常规邮政服务更有用。然而,在某些情况下,送达速度不足以使电子邮件成为理想的通信机制。其中一种情况是,需要双方进行对话

考虑到即使电子邮件可能非常快地送达,它也使用了解耦的通信模型。假设 Ellen 给 Jane 发送了一封电子邮件。消息可能在几秒钟内出现在 Jane 的收件箱中,但 Jane 可能不在那里阅读它。Jane 可能要过几个小时才能看到这条消息。然后 Jane 会向 Ellen 发送回复,而 Ellen 可能要过一段时间才能看到。如果他们讨论的主题需要几十次这样的迭代,那么完成交流可能需要很长时间。

在现实世界中,当然,我们大多数人永远不会用电子邮件进行这样的对话,而是更倾向于使用我们称之为电话的高科技通信设备。许多使用计算机的人意识到,如果两个人或更多人能够以类似电话对话的方式交互式地讨论问题,那将是有用的。在在线世界中,这通常被称为聊天,而第一个也是最重要的应用协议之一,旨在在 TCP/IP 中实现它,就是互联网中继聊天(IRC)协议

在互联网广泛使用之前,拥有计算机的人通常会通过拨号进入公告板系统(BBS)或其他专有服务进行通信。IRC 最初是由一位名叫 Jarkko Oikarinen 的芬兰人创建的,基于他在 BBS 上的聊天应用经验。他在 1988 年编写了第一个客户端和服务器软件。该协议后来在 1993 年 5 月正式定义在 RFC 1459,“互联网中继聊天协议”中。2000 年 4 月,IRC 标准经过修订和增强,增加了几个新的扩展功能,并作为一套四份较小的文档发布:RFC 2810 至 RFC 2813。这些文档中的每一份都专注于 IRC 功能的一个特定领域。

注意

RFC 1459 具有实验性 RFC 状态,而 RFC 2810 至 RFC 2813 组被指定为信息性。这使得 IRC 成为可选的;它不需要在 TCP/IP 设备上实现

IRC 通信模型和客户端/服务器操作

IRC 是一个有趣的协议,因为它并不严格基于 TCP/IP 协议操作的客户端/服务器模型。IRC 服务器 是运行 IRC 服务器软件的 TCP/IP 机器。它们配置了允许它们相互建立 TCP 连接的信息。IRC 使用 TCP 是因为连接会维持很长时间,并且需要可靠的数据传输。服务器连接用于交换控制信息和用户数据,形成一个在应用层的逻辑 IRC 网络,这使得任何服务器都可以向任何其他服务器发送消息,使用中间服务器作为通道。服务器由 IRC 运营商 (IRCops) 管理,他们拥有特殊权限,可以确保网络上的一切运行顺利。

IRC 网络构成了 IRC 通信服务的骨干。用户可以通过在任何 TCP/IP 兼容设备上运行 IRC 客户端 软件来访问网络。用户输入网络上的一个服务器名称,并建立与该服务器的 TCP 连接。这会导致用户直接连接到一个服务器,从而间接连接到网络上的所有其他服务器。这使得用户可以向所有其他用户发送和接收消息,无论他们是否连接到用户的服务器或其他服务器。

消息和 IRC 频道

在 IRC 中最常见的通信类型是 群组消息,这是通过 IRC 频道 实现的。频道是一种虚拟的会议场所,有时也被称为 聊天室(尽管 IRC 纯粹主义者对使用该术语嗤之以鼻)。每个 IRC 网络都有数百甚至数千个不同的频道,每个频道都致力于特定类型的讨论,从严肃到滑稽不等。例如,一群对谈论气象学感兴趣的人可以建立一个名为 #weather 的频道,他们会在那里定期讨论气候学的各个方面和有趣的天气事件。

IRC 是一种本质上基于文本的协议(尽管也可以使用 IRC 客户端在用户之间传输任意文件,包括图像和可执行程序)。要在频道中通信,用户只需在 IRC 客户端程序中适当的位置输入文本,然后程序会自动将此文本发送给频道的每一位成员。IRC 网络实时处理这些消息的转发,从发送者连接的服务器到网络中的其他服务器,然后到那些服务器上的所有用户机器。当其他用户看到第一位用户的消息时,他们可以用自己的消息回复,这些消息反过来也会在网络中传播。每个 IRC 用户都会选择一个昵称(通常缩写为 nick),这就像是在连接到网络时用于通信的 handle

IRC 还支持一对一的通信,这可以用于私人对话。要使用这种方法,用户只需要知道她想要与之交谈的另一个用户的昵称。她使用一个特殊的命令直接向该用户发送消息,该用户可以相应地回复。这不是一种安全的通信方式,因为消息没有被加密,并且它们会通过服务器传输,这些服务器可能会被监控。然而,在典型的 IRC 网络上流量如此之大,任何给定的消息不太可能被监控。

IRC 协议定义了一个丰富的命令集,允许用户执行基本功能,例如加入或离开频道、更改昵称、更改服务器、为频道设置操作模式等等。确切的命令集和可用功能既取决于用户使用的特定 IRC 客户端软件,也取决于 IRC 网络本身的功能。并非所有 IRC 网络都运行相同的协议版本。

IRC 与现代互联网

由于它允许来自互联网任何地方的用户动态地相遇和共享信息,IRC 在 20 世纪 90 年代初变得非常流行。它就像一个基于文本的电话,但全球的用户不需要长途电话的费用。

IRC 最重要的一项特性是其开放性;它给每个人提供了自由,以他们认为最好的方式进行沟通。例如,每个 IRC 频道都有一个所有者,他拥有与频道使用相关的某些权利,包括决定谁应该被允许进入频道。这可能看起来是专制的,但 IRC 允许任何人立即启动一个新的频道并成为该频道的所有者,而无需事先注册或授权。这意味着如果你不喜欢某个频道的运行方式,你可以以最小的麻烦启动自己的频道。你不必遵守任何人的规则,除了服务器设定的规则(通常只是旨在防止滥用)。

同样的原则也适用于 IRC 网络。并不是只有一个单一的 IRC 网络;有几十个不同的网络。有些是大型、成熟的网络,可能有超过 100 个服务器和数千名用户;其他则是较小,专注于特定的兴趣领域或地理区域。任何人只要有硬件和软件,都可以设置自己的 IRC 网络,并且一些组织已经为自身使用设置了私有、专用的 IRC 服务器。

对于许多用户来说,IRC 被认为是被称为 即时消息 的相关交互式应用的最重要的祖先。这些服务由多个组织提供,包括美国在线(AOL)、雅虎和微软的 MSN。它们背后的理念与 IRC 非常相似。每个都允许一个用户发送的消息立即显示给另一个用户,尽管大多数服务主要关注用户之间的消息,而不是群组消息。即时消息在整体使用上已经超过了 IRC,这或许是由于像 AOL 这样的服务拥有庞大的用户群。然而,IRC 仍然被成千上万的爱好者每天广泛用于娱乐和商业目的。

第八十八章. TCP/IP 管理和故障排除工具及协议

无标题图片

本章关于应用协议的最后一部分与前面的章节略有不同。它不描述为最终用户设计的应用。相反,它讨论了一组 TCP/IP 故障排除工具和协议,这些通常是内部网络管理员的领域。尽管数百万人在每天使用 TCP/IP 时甚至不知道这些应用的存在——更不用说它们是如何工作的——但对于维护 TCP/IP 内部网络的人来说,它们至关重要。由于你们中的许多人学习 TCP/IP 是为了实施和管理这项技术,因此了解这些应用是如何工作的值得你们花时间。

在本章中,我概述了多种常用的软件工具,这些工具通常用于帮助设置、配置和维护 TCP/IP 内部网络。这些程序允许网络管理员执行诸如检查主机身份、验证两个主机之间的连接、检查设备之间的路由器路径、检查计算机配置以及查找域名系统(DNS)域名等功能。

本章的目标是解释故障排除工具的一般用途和功能,这样你们就会知道它们如何帮助你们管理 TCP/IP 网络。作为这些描述的一部分,我演示了在 UNIX 和 Windows 中调用每个工具的典型语法。由于软件实现的不同,你们需要查阅操作系统的文档,以了解每个程序在你们网络上的具体使用细节。在 Windows 系统上,尝试 <program> /? 来查看程序的语法;在 UNIX/Linux 上,尝试 man <program>

小贴士

背景信息 许多在本节中描述的软件工具旨在管理其他 TCP/IP 协议的操作,例如互联网协议(IP)、域名系统(DNS)和动态主机配置协议(DHCP)。要充分理解这些实用程序的工作原理,你需要了解这些和其他关键 TCP/IP 协议的基础知识。特别是,这里讨论的一些实用程序使用互联网控制消息协议(ICMP)消息进行通信,因此我建议在继续之前熟悉 ICMP(在第二部分-6 中讨论)。

TCP/IP 主机名称实用程序(hostname)

在诊断网络计算机问题时,最基本的一项任务是识别它。正如我们通常在见到某人时首先交换名字一样,管理员访问设备时采取的第一个行动之一是确定其名称,如果不知道的话。这是通过使用hostname实用程序来完成的。

你可能还记得我们在第三部分-1 中关于 TCP/IP 名称系统的讨论,其中提到主机命名有两种不同的方式。第一种方式是手动使用主机表或等效方式为设备分配平坦名称;这通常用于不会在公共互联网上访问的设备。第二种是在 DNS 中为设备分配域名。hostname实用程序可以用于这两种类型的命名主机,但它在每种类型中的功能略有不同。

在大多数系统上,包括 Windows 和许多 UNIX 实现,hostname实用程序非常简单。当你单独在带有无参数的行中输入该命令时,它会显示主机的完整名称。如果使用-s(短)参数并且主机名是一个完全限定的 DNS 域名,则仅显示节点的本地标签,而不是完整的域名;如果主机有一个平坦(非 DNS)名称,则-s参数没有效果。以下是一个简单的例子:

% hostname
fearn.pair.com
% hostname -s
fearn

hostname实用程序还旨在允许管理员设置主机的名称。这种语法的设置也很简单;你只需将主机名称作为参数提供,如下所示:

hostname <*`new-hostname`*>

然而,在大多数实现中,使用hostname命令设置设备名称的功能已被禁用或受限。在 Windows 系统中,控制面板中有一个特殊的小程序用于设置设备名称;尝试使用hostname设置它将导致错误消息。在 UNIX 中,系统超级用户可以使用hostname设置设备名称,但更常见的是通过其他方式完成,例如编辑配置文件/etc/hosts。如果为该主机分配的是简单的平坦名称,则管理员对其有完全控制权。然而,如果使用 DNS,则必须遵循注册名称的正确程序。

注意

The hostname utility is not, strictly speaking, tied into the operation of DNS or other formal mechanisms for identifying a host. It simply displays what the administrator has set it to show. It makes sense for this to be set to the host's DNS name, but there may be exceptions, such as in small networks that might not use DNS.

在大多数操作系统中,-s 参数是此命令支持的唯一参数。然而,并非所有 hostname 命令的实现都支持此参数。在某些实现中,如果您使用 hostname -s,系统可能会报告其主机名为 –s。在某些 Linux 系统中,hostname 工具包含一些额外的参数,允许以不同的方式显示主机名,以及一些其他功能,例如显示程序的版本号。

小贴士

关键概念 最简单、最基本的 TCP/IP 管理工具是 hostname,它返回运行它的主机名称。

TCP/IP 通信验证工具(ping)

网络管理员被要求解决的最常见问题之一是两个主机无法通信。例如,企业网络中的用户可能无法从本地服务器检索他的文件,或者另一个用户可能难以加载她最喜欢的网站。在这些和类似情况下,诊断问题的第一步重要步骤是验证两台机器上的 TCP/IP 软件堆栈之间基本通信是否可行。这通常是通过使用 ping 工具或 IPv6 实现中的 ping6 来完成的。IPv6 版本的 ping 与 IPv4 ping 的工作方式非常相似,但 ping6 的选项和参数反映了 IPv6 中地址和路由的变化。

注意

Some people say that ping is an acronym for Packet Internet Groper, while others insist that it is actually based on the use of the term to refer to a sonar pulse sent by a submarine to check for nearby objects. I really don't know which of these is true, but I prefer the second explanation. Consider that the utility works in a way similar to a sonar ping, and that it was originally written by a gentleman named Mike Muuss, who worked at the United States Army Ballistics Research Laboratory.

ping 是最常用的诊断工具之一,几乎在每个 TCP/IP 实现中都有。它通常以命令行工具的形式实现和访问,尽管在某些操作系统中现在也有图形和基于菜单的程序版本。

ping 工具的操作

ping 实用程序是使用互联网控制消息协议(ICMP)回声(请求)和回声回复消息实现的,这些消息专门为这种诊断用途而设计。当设备 A 向设备 B 发送 ICMP 回声消息时,设备 B 通过发送 ICMP 回声回复消息回传给设备 A。在 ICMPv6 中,即 ICMP 的 IPv6 版本,也存在相同的功能;ICMPv6 回声和回声回复消息在字段结构上仅与 IPv4 的略有不同。

这似乎表明 ping 将是一个非常简单的实用程序,它会发送一个回声消息并等待查看是否收到回声回复。如果是这样,这意味着两个设备能够通信;如果没有,这表明在两个设备之间的互联网上存在某个问题。然而,几乎所有 ping 实现都比这复杂得多。它们使用多组回声和回声回复消息,以及相当多的内部逻辑,允许管理员确定以下所有内容,以及更多:

  • 两个设备是否能够通信

  • 是否存在拥塞或其他问题,有时可能允许通信成功,但有时会导致失败,这被视为数据包丢失;如果是这样,丢失有多严重

  • 在设备之间发送简单的 ICMP 消息需要多少时间,这可以指示主机之间的整体延迟,同时也表明是否存在某些类型的问题

ping 的基本用法

ping 命令最基本的使用方法是仅输入命令本身,并带有主机的 IP 地址。几乎所有的实现也允许您使用主机名,它将被自动解析为 IP 地址。当您使用没有额外选项的实用程序时,它将使用默认值来设置参数,例如发送的消息大小、要发送的消息数量、等待回复的时间等。实用程序将向主机发送一系列回声消息,并报告是否收到每个消息的回复。如果看到回复,它还会指示接收响应所需的时间。当程序完成后,它将提供一个统计摘要,显示收到的回声消息中有多少百分比收到了回复,以及它们接收的平均时间。

注意

虽然设备对 ping 命令无响应传统上被解释为通信问题,但这并不总是必然的情况。在当前提高安全意识的时代,一些网络被设置为不响应回声消息,以防止使用此类消息洪水的攻击。在这种情况下,ping 命令将失败,尽管主机可能非常可达

示例 88-1 展示了在 Windows XP 计算机上使用ping命令的例子(我的!),默认情况下,它发送四个 32 字节的回显消息,并在认为回显消息丢失之前允许四秒钟。我使用的是具有相当高延迟和偶尔丢包的卫星互联网连接。这对我不太理想,但有助于说明ping是如何工作的。

示例 88-1. 使用ping实用程序验证通信

D:\aa>ping www.pcguide.com
Pinging pcguide.com [209.68.14.80] with 32 bytes of data:

Reply from 209.68.14.80: bytes=32 time=582ms TTL=56
Reply from 209.68.14.80: bytes=32 time=601ms TTL=56
Request timed out.
Reply from 209.68.14.80: bytes=32 time=583ms TTL=56

Ping statistics for 209.68.14.80:
    Packets: Sent = 4, Received = 3, Lost = 1 (25% loss),
Approximate round trip times in milli-seconds:
    Minimum = 582ms, Maximum = 601ms, Average = 588ms

使用ping诊断连接问题的方法

大多数人发现使用默认设置的ping就足够满足他们的需求。实际上,这个实用程序可以以这种最简单的形式执行许多诊断检查。在许多情况下,你可以通过连续多次执行ping命令来诊断连接问题,通常从检查发送设备或接近发送设备的检查开始,然后向外扩展到观察到通信问题的其他设备。以下是一些如何使用ping的例子:

内部设备 TCP/IP 堆栈操作 通过对设备的自身地址执行ping操作,你可以验证其内部 TCP/IP 堆栈是否正常工作。这也可以使用标准的 IP 环回地址,127.0.0.1 来完成。

本地网络连接 如果内部测试成功,对本地网络上的另一台设备执行ping操作是个好主意,以验证本地通信是否可行。

本地路由器操作 如果本地网络没有问题,对设备使用的任何本地路由器执行ping操作是有意义的,以确保它正在运行且可访问。

域名解析功能 如果对一个 DNS 域名执行的ping操作失败,你应该尝试使用设备的 IP 地址来执行。如果那样可以工作,这表明可能存在域名配置或解析的问题。

远程主机操作 如果所有前面的检查都成功了,你可以尝试对一个远程主机执行ping操作,看看它是否响应。如果它没有响应,你可以尝试另一个远程主机。如果那个主机可以工作,那么问题可能实际上是在第一个远程设备本身,而不是你的本地设备。

小贴士

关键概念 TCP/IP ping实用程序用于验证 TCP/IP 互联网上两个设备之间的通信能力。它通过一个设备向另一个设备发送 ICMP 回显(请求)消息,另一个设备以回显响应消息进行响应。这个程序在诊断许多连接问题方面非常有用,特别是如果用它来测试与不同位置的设备通信的能力。它还允许估计与另一个设备交换消息的平均往返延迟。

ping选项和参数

除了前几节中描述的基本用法之外,所有ping实现都包含一些选项和参数,允许管理员微调其工作方式。它们允许 ping 用于更广泛的或更具体的测试类型。例如,ping可以设置为连续发送 Echo 消息的模式,以检查长时间内间歇性问题。您还可以增加发送消息的大小或它们的传输频率,以测试本地网络处理大量流量的能力。

与本章中描述的其他工具一样,ping程序的确切功能取决于实现。尽管 UNIX 和 Windows 系统通常包括许多相同的选项,但它们通常使用完全不同的选项代码。表 88-1 显示了在许多 UNIX 系统上为该工具定义的一些更重要选项,以及适当的选项参数。表 88-2 显示了典型 Windows 系统的ping选项。

表 88-1. 常见的 UNIX ping 实用工具选项和参数

选项/参数 描述
-c <count> 指定应发送的 Echo 消息的数量。
-f 洪水模式;以高速发送 Echo 数据包以对网络进行压力测试。如果不小心使用,这可能会引起严重问题!
-i <wait-interval> 告诉工具在传输之间等待多长时间。
-m <ttl-value> 覆盖输出 Echo 消息的默认生存时间(TTL)值。
-n 仅输出数字;抑制 DNS 主机名的查找以节省时间。
-p <pattern> 允许指定一个字节模式,并将其包含在传输的 Echo 消息中。这可以用于诊断某些仅在特定类型传输中出现的奇怪问题。
-q 静默输出;仅在程序执行的开始和结束时显示摘要行,而抑制每个单独消息的行。
-R 告诉工具包含记录路由 IP 选项,以便可以显示 ICMP Echo 消息的路径。此选项并非所有实现都支持。使用下一节中描述的traceroute工具通常是一个更好的选择。
-s <packet-size> 指定要使用的输出消息的大小。
-S <src-addr> 在具有多个 IP 接口(地址)的设备上,允许从其中一个接口发送的ping命令使用其他接口中的一个地址。
-t <timeout> 指定超时时间,以秒为单位,在此之后ping工具将终止,无论已发送或接收了多少请求或回复。

表 88-2. 常见的 Windows ping 工具选项和参数

选项/参数 描述
-a 如果目标设备指定为 IP 地址,则强制将地址解析为 DNS 主机名并显示。
-f 在出站数据报中设置不要分段位。
-i <ttl-value> 指定用于出站 Echo 消息的生存时间(TTL)值。
-j <host-list> 使用指定的松散源路由发送出站消息。
-k <host-list> 使用指示的严格源路由发送出站消息。
-l <buffer-size> 指定传输 Echo 消息中的数据字段的大小。
-n <count> 告诉工具发送多少个 Echo 消息。
-r <count> 指定使用记录路由 IP 选项和要记录的跳数。通常,使用traceroute工具(下一节将描述)更为可取。
-s <count> 指定使用 IP 时间戳选项来记录 Echo 和 Echo 回复消息的到达时间。
-t 连续发送 Echo 消息,直到程序被中断。
-w <timeout> 指定程序在放弃之前应等待每个 Echo 回复的时间长度,以毫秒为单位(默认为 4,000,即 4 秒)。

TCP/IP 路由跟踪工具(traceroute)

ping工具对于检查两个设备是否能够相互通信非常有帮助。然而,它提供的关于两个设备之间发生情况的信息非常有限。如果ping显示完全无法通信或间歇性连接且传输数据丢失率很高,管理员需要了解 IP 数据报在跨越互联网传输时的具体情况。当两个设备相距很远时,这一点尤为重要,尤其是当你试图连接到公共互联网上的服务器时。

在我对 IP 数据报交付的概述中,我描述了当两个设备不在同一网络中时,它们之间发送的数据必须从一个网络传递到下一个网络,直到到达目的地。这意味着,每当从网络 A 的设备 A 向网络 B 的设备 B 发送数据时,它都会遵循一条路径,这条路径可能对每次传输都不相同。当出现通信问题时,能够检查两个设备之间数据的具体路径非常有用。为此,提供了一个特殊的路由跟踪工具,称为traceroute(在 Windows 系统中简称为tracert,这是 DOS 程序名旧八字符限制的遗留问题)。

这个程序的 IPv6 等价物被称为traceroute6,其工作方式与 IPv4 前辈非常相似。它显然使用 IPv6 数据报而不是 IPv4 数据报,并且被追踪设备的响应以 ICMPv6 超时和目标不可达消息的形式出现,而不是它们的 ICMPv4 对应消息。

traceroute 工具的操作

ping工具一样,traceroute使用 ICMP 消息实现。然而,与ping不同,traceroute最初并不是设计用来使用专门为路由跟踪而设计的特殊 ICMP 消息类型。相反,它巧妙地使用了旨在防止路由问题的 IP 和 ICMP 功能。

回想一下,IP 数据报格式包括一个生存时间(TTL)字段。该字段设置为数据报在必须丢弃之前可以转发的最大次数;它存在是为了防止数据报在互联网中无限循环。如果一个数据报必须因为 TTL 字段的过期而被丢弃,那么丢弃它的设备应该向发送丢弃数据报的设备发送 ICMP 超时消息。(这在第三十二章中有详细解释。)在正常情况下,这仅在存在问题时才会发生,例如路由器循环或其他配置问题。traceroute所做的是通过故意将测试数据报中的 TTL 值设置为太低,以至于无法到达其目的地,来强制路由中的每个路由器向它报告。

假设你拥有设备 A 和设备 B,它们通过路由器 R1 和 R2(总共三个跳数,即 A 到 R1,R1 到 R2,R2 到 B)相隔。如果你从设备 A 到设备 B 执行traceroute,以下是会发生的情况(参见图 88-1 值为 1,这将导致路由器 R1 丢弃它并向设备 A 发送 ICMP 时间超限消息。第二条消息的 TTL 值为 2,因此它将被丢弃并由路由器 R2 报告。第三条消息将穿过两个路由器并到达目标主机,设备 B,但由于消息是故意选择了一个无效的端口号,这将导致返回 ICMP 目标不可达消息。这些错误消息确定了设备 A 和 B 之间路由中设备的顺序。](httpatomoreillycomsourcenostarchimages288327.png.jpg)

图 88-1. traceroute/tracert 工具的操作 traceroute 工具通过强制设备报告带有故意设置为无效值的参数的路由数据报的失败来识别路由中的设备。在这里,设备 A 发送的第一条消息的生存时间 (TTL) 值为 1,这将导致路由器 R1 丢弃它并向设备 A 发送 ICMP 时间超限消息。第二条消息的 TTL 值为 2,因此它将被丢弃并由路由器 R2 报告。第三条消息将穿过两个路由器并到达目标主机,设备 B,但由于消息是故意选择了一个无效的端口号,这将导致返回 ICMP 目标不可达消息。这些错误消息确定了设备 A 和 B 之间路由中设备的顺序。

小贴士

关键概念 traceroute 工具将 ping 的理念进一步发展,允许管理员不仅检查两个设备之间的通信,还可以看到这对设备之间所有中间设备的列表。它通过让发起主机发送一系列测试数据报,每个数据报的 TTL 值都设置为在路由上的每个设备上依次超时来实现。traceroute 程序还会显示从发送主机到目标设备之间与每个设备通信所需的时间。

traceroute 工具的基本用法

示例 88-2 展示了在两个我经常使用的 UNIX 计算机之间发送的 traceroute 示例。我添加了 -q2 参数来将每跳的默认三个虚拟消息更改为两个,以便输出更适合页面。

示例 88-2. 使用 traceroute 工具进行路由跟踪

traceroute -q2 www.pcguide.com
traceroute to www.pcguide.com (209.68.14.80), 40 hops max, 40 byte packets
 1  cisco0fe0-0-1.bf.sover.net (209.198.87.10)  1.223 ms  1.143 ms
 2  cisco1fe0.bf.sover.net (209.198.87.12)  1.265 ms  1.117 ms
 3  cisco0a5-0-102.wnskvtao.sover.net (216.114.153.170)  8.004 ms  7.270 ms
 4  207.136.212.234 (207.136.212.234)  7.163 ms  7.601 ms
 5  sl-gw18-nyc-2-0.sprintlink.net (144.232.228.145)  15.948 ms  20.931 ms
 6  sl-bb21-nyc-12-1.sprintlink.net (144.232.13.162)  21.578 ms  16.324 ms
 7  sl-bb27-pen-12-0.sprintlink.net (144.232.20.97)  18.296 ms  *
 8  sl-bb24-pen-15-0.sprintlink.net (144.232.16.81)  18.041 ms  18.338 ms
 9  sl-bb26-rly-0-0.sprintlink.net (144.232.20.111)  20.259 ms  21.648 ms
10  sl-bb20-rly-12-0.sprintlink.net (144.232.7.249)  132.302 ms  37.825 ms
11  sl-gw9-rly-8-0.sprintlink.net (144.232.14.22)  23.085 ms  20.082 ms
12  sl-exped4-1-0.sprintlink.net (144.232.248.126)  43.374 ms  42.274 ms
13  * *
14  pcguide.com (209.68.14.80)  41.310 ms  49.455 ms

在这种情况下,服务器之间相隔 14 跳。注意,随着与发送设备距离的增加,经过的时间通常会增加,但由于任何两个设备之间延迟的随机元素,它并不一致(例如,第 10 跳的不一致的大值)。还要注意第七跳中的星号(*),这意味着在 TTL 值为 7 的第二次传输的超时期间没有收到任何响应。最后,第 13 跳没有任何报告。这台机器可能被配置为不发送超时消息。

在某些情况下可能会显示一些不寻常的结果。例如,traceroute程序可能会显示一个代码,如!H!N!P,分别表示收到针对主机、网络或协议的意外目的地不可达消息。根据实现,也可能存在其他错误消息。

traceroute 选项和参数

ping类似,traceroute可以使用 IP 地址或主机名。如果没有提供参数,将使用关键参数的默认值。在我使用的系统中,默认值是每个 TTL 值 3 个探测,最多测试 64 跳,数据包大小为 40 字节。然而,我的实现也支持许多选项和参数,以便我可以更好地控制工具的功能(例如,我在示例 88-2 中使用的-q参数)。UNIX 系统中可用的典型选项在表 88-3 中描述。Windows 中存在一组更小的选项,如表 88-4 所示。

表 88-3. Common UNIX traceroute Utility Options and Parameters

选项/参数 描述
-g <host-list> 指定用于跟踪的源路由。
-M <initial-ttl-value> 覆盖第一个发出的探测消息的初始 TTL 值的默认值 1。
-m <max-ttl-value> 设置要使用的最大 TTL 值。这限制了工具尝试跟踪的路由长度。
-n 仅使用数字地址显示路由,而不是同时显示 IP 地址和主机名。这通过节省工具在路由中的所有设备上执行反向 DNS 查找的需要来加快显示速度(ICMP 消息使用 IP 地址,而不是域名)。
-p <port-number> 指定用作探测消息目的地的端口号。
-q <queries> 告诉工具为路由中的每个设备发送多少个探测(默认为 3)。
-r 告诉程序绕过正常路由表,直接发送到连接网络上的主机。
-s <源地址> 在具有多个 IP 接口(地址)的设备上,允许设备在 traceroute 使用另一个接口时使用一个接口的地址。
-S 指示程序显示未收到回复的探测数量摘要。
-v 设置详细输出模式,告知用户在跟踪过程中接收到的所有 ICMP 消息。
-w <等待时间> 指定工具等待每个探测回复的时间长度,以秒为单位(典型默认值为 3 到 5 秒)。

表 88-4. 常见 Windows tracert 工具选项和参数

选项/参数 描述
-d 仅使用数字地址显示路由,而不是同时显示 IP 地址和主机名,以便更快地显示。这在 UNIX 系统上的 -n 选项中相同。
-h <最大跳数> 指定用于跟踪的最大跳数(默认为 30)。
-j <主机列表> 使用指定的松散源路由发送出站探测。
-w <等待时间> 指定等待每个探测回复的时间长度,以毫秒为单位(默认为 4,000 毫秒,即 4 秒)。

TCP/IP 地址解析协议工具 (arp)

在互联网中,所有设备都被视为在第三层虚拟连接,因为路由过程允许任何设备与任何其他设备通信。然而,远程网络上的设备无法直接通信。第三层的互联网通信实际上包括多个步骤,称为 跳数,这些跳数将数据从源传输到目的地。路由中的每个跳数都需要在成对的硬件设备之间发送数据,并且每次传输都必须使用第二层的硬件地址。由于 TCP/IP 使用第三层地址,这意味着每个跳数都需要将跳数的目标 IP 地址转换为硬件地址。这被称为 地址解析;为什么需要它以及用于它的方法在 第十三章") 中有详细解释。

在 TCP/IP 中,地址解析功能由恰如其分的名称地址解析协议(ARP)执行。当设备需要向具有特定 IP 地址的设备传输时,它可以使用 ARP 的请求/回复消息协议来找出与该 IP 地址对应的硬件设备。然而,每次这样的消息交换都需要时间和网络带宽,因此为了效率,每个设备都维护一个 ARP 缓存,这是一个包含 IP 地址和硬件地址之间映射的表。ARP 缓存表可以包含静态缓存条目的组合,这些条目是手动插入以供频繁访问的设备使用,以及动态条目,这些条目在请求/回复解析完成后自动插入。下次需要向 ARP 缓存表中的设备发送数据时,可以避免查找过程。

为了允许管理员管理此 ARP 缓存表,TCP/IP 设备包括一个 arp 实用程序。它具有以下三个基本功能,这些功能通过使用三个不同的命令版本(这一次,UNIX 和 Windows 中的命令版本是相同的)来调用:

ARP 缓存表显示 当使用 -a 选项与该实用程序一起使用时,它会显示 ARP 缓存表当前的内容。语法是 arp -d <主机名>。表中的每个条目都显示一个设备(接口)的 IP 地址和硬件地址对。通常,它还指示每个条目是静态的还是动态的。显示的确切格式因实现而异;一些程序显示 IP 地址,其他程序显示主机名,还有一些程序可能两者都显示。某些系统默认显示主机名,但允许使用 -n 选项来强制只显示 IP 地址(而不是名称)。

ARP 缓存表条目添加 此版本允许管理员创建一个新的手动 ARP 缓存表条目,将给定的主机名映射到指定的硬件地址。语法是 arp -s <主机名> <*硬件地址*>`。

ARP 缓存表条目删除 使用 arp 命令的 -d 选项可以从表中删除指定的缓存条目。某些实现允许添加另一个参数来指定应从缓存中删除所有条目。基本语法是 arp -d <主机名>

小贴士

关键概念 TCP/IP 的 arp 实用程序由管理员用于检查或修改主机的 ARP 缓存表,该表包含 TCP/IP 主机名和 IP 地址之间的映射。

某些软件版本也可能通过附加功能来补充这些基本命令。UNIX 系统上常见的附加选项是能够指定一个文件,从中可以读取缓存表条目,使用语法 arp -f <文件名>。与手动使用 arp -s 输入每个条目相比,这可以节省大量时间和精力。

注意,操作系统可能只允许授权用户访问可以更改 ARP 缓存表的选项。这一点在删除功能上尤为明显。

TCP/IP DNS 名称解析和查找实用程序(nslookup、host 和 dig)

DNS 是 TCP/IP 互连网的一个关键重要部分,特别是现代互联网,因为它允许使用易于记忆的名称而不是令人困惑的数字地址来访问主机。DNS 操作涉及两种不同的主要设备类型:存储有关域的信息的 DNS 名称服务器和查询 DNS 服务器以将名称转换为地址以及执行其他必要功能的 DNS 解析器。

互联网用户持续使用 DNS 解析器将 DNS 名称转换为地址,但在正常情况下,它们总是间接调用的。每次用户在网页浏览器或文件传输协议(FTP)客户端等程序中输入 DNS 名称,或者在其他本章描述的实用程序(如pingtraceroute)中使用它时,解析器都会自动执行名称解析,而无需用户请求。因此,用户无需手动将 DNS 名称解析为地址。

然而,管理员经常需要手动执行 DNS 解析。例如,在解决问题时,管理员可能知道主机的名称但不知道其地址。在安全问题的案例中,地址可能出现在日志文件中,但主机名称可能未知。此外,尽管用户不需要知道定义 DNS 域的资源记录的详细信息,但管理员经常需要能够检查这些细节,以确保域设置正确。管理员还需要某种方式来诊断 DNS 服务器本身的问题。为了支持所有这些需求,现代 TCP/IP 实现配备了至少一个 DNS 名称解析和信息查找实用程序。在这里,我们将探讨三个这样的实用程序:nslookuphostdig

nslookup实用程序

最常见的 DNS 诊断实用程序之一是nslookup(用于名称服务器查找),它已经存在很多年了。程序实现的细节取决于操作系统,尽管它们中的大多数在操作和设置上提供了相当相似版本。该实用程序通常可以在两种模式下使用:交互式或非交互式。

nslookup的非交互式版本是最简单的,当管理员只想快速将名称转换为地址或相反时,通常使用此版本。要运行此版本,使用以下简单的语法发出nslookup命令:

nslookup <*`host`* > [<*`server`*>]

在这里,<host> 可以是一个 DNS 域名,用于执行正常解析,或者它可能是一个 IP 地址,用于反向解析以返回相关的 DNS 域名。<server> 参数是可选的;如果省略,程序将使用发出命令的主机的默认名称服务器。示例 88-3 显示了 nslookup 的非交互式使用的一个简单示例。

示例 88-3. 使用 nslookup 工具进行 DNS 名称解析

D:\aa>nslookup www.pcguide.com
Server:  ns1-mar.starband.com
Address:  148.78.249.200

Non-authoritative answer:
Name:    pcguide.com
Address:  209.68.14.80
Aliases:  www.pcguide.com

这个示例是在我使用 Starband 卫星互联网服务的家用电脑上完成的,该服务配置为使用 Starband 的名称服务器 (ns1-mar.starband.com)。这里提供的答案被标记为 非权威性,因为它来自 Starband 名称服务器的 DNS 缓存,而不是 www.pcguide.com 的 DNS 权威服务器之一。

注意

也可以在非交互模式下指定一个或多个选项来修改查找行为。这些选项与表 88-5 中描述的由 nslookup set 命令控制的参数相同。它们通过在前面加一个破折号来指定。例如,nslookup -timeout=10 www.pcguide.com 将执行与示例 88-3 中相同的查找,但将超时时间设置为 10 秒

通过简单地不带参数发出命令名,可以选择 nslookup 的交互模式。这将导致程序显示当前默认名称服务器的 DNS 名称和地址,然后提供一个提示,管理员可以在其中输入命令。交互模式允许用户轻松地执行多个查找,而无需每次都输入 nslookup。更重要的是,它提供了更方便的控制方式,可以请求哪些类型的信息以及如何执行查找。

你通常可以通过在 nslookup 提示符下发出 help? 命令来确定 nslookup 实现中可用的确切命令集。表 88-5 显示了大多数 nslookup 实现中通常可以找到的一些命令。

表 88-5. 典型的 nslookup 工具命令

命令和参数 描述
<host> [<server>] 查找指定的主机,可选地使用指定的 DNS 名称服务器。注意,这里实际上没有命令;你只需在命令提示符中直接输入名称即可。
server <server> 将默认服务器更改为 <server>,使用从当前默认服务器获得的信息。
lserver <server> 将默认服务器更改为 <server>,使用从初始名称服务器获得的信息;即,在启动 nslookup 命令时(在会话中当前名称服务器任何先前更改之前)系统默认的服务器。
root 将默认名称服务器更改为 DNS 根名称服务器之一。
ls [-t <type>] <name> 通过执行区域传输请求指定域名可用的信息列表。默认情况下,与域名关联的主机名和地址将被列出;可以使用 -t 选项将输出限制为特定记录类型。还可以定义其他选项。(大多数服务器将区域传输的使用限制为指定的从服务器,因此此命令可能对普通客户端不起作用。)
help 显示帮助信息(通常是有效命令和选项的列表)。
? help 相同(仅在某些系统上有效)。
set all 显示所有 nslookup 选项的当前值。
set <option>[=<value>] 设置一个选项以控制实用工具的行为。大多数实现包括相当多的选项,其中一些只需指定一个关键字即可控制,而其他选项则需要为选项指定一个值。例如,set recurse 告诉程序使用递归解析,而 set norecurse 关闭它。set retry=3 将重试次数设置为 3。
exit 退出程序。

nslookup 工具在 UNIX 和 Windows 系统上都得到了广泛部署,但该程序并非没有批评者。对其的投诉主要集中在它使用非标准的信息获取方法,而不是标准的解析例程。我也阅读过一些报告,称在某些情况下它可能会产生虚假的结果。命令的一个重大问题示例是,如果它无法执行其自身 IP 地址的反向查找,它将终止。这可能会造成混淆,因为用户会将该错误误认为是试图查找他们正在查找的名称时发生的错误。因此,出于这个和其他原因,UNIX 圈中的一些人认为 nslookup 是一种某种形式的黑客行为。在一些较新的 UNIX 系统中,nslookup 已被弃用(为了兼容性仍包含在操作系统中,但不推荐,未来可能会被移除)。取而代之的是,提供了一对较新的实用工具:hostdig

host 实用工具

host 工具最常用于简单的查询,例如通常使用 nslookup 的非交互模式执行的查询。它以与非交互式 nslookup 相同的方式调用:

host <*`host`*> [<*`server`*>]

输出与非交互式 nslookup 的输出类似,但更简洁。以下是一个示例:

%host www.pcguide.com
www.pcguide.com is an alias for pcguide.com.
pcguide.com has address 209.68.14.80

虽然 host 不支持交互式操作,但它包括一些选项,允许管理员获取使用 nslookup 交互模式所获得的信息。一些更常见的选项显示在 表 88-6 中。

表 88-6. 典型的 host 实用程序选项和参数

选项/参数 描述
-d 打开调试模式。
-l 为域名提供完整的信息列表;这与交互式 nslookup 中的 ls 命令类似。这可以与 -t 选项一起使用,以仅选择域名中特定类型的资源记录。
-r 禁用请求中的递归。当指定此选项时,只有直接查询的服务器会返回任何信息;它不会查询其他服务器。
-t <查询类型> 指定对特定资源记录类型的查询,允许检索任何类型的 DNS 信息。
-v 使用详细模式输出(提供额外细节)。
-w 等待必要的响应时间(无超时)。

dig 实用程序

nslookup 的第二种选择是 dig,代表域名信息探索者(可能是对 ping 命名来源的一种戏谑)。它与 host 命令不同,即使在最简单的方式下调用,它也提供了关于域的相当多的信息。它也相当复杂,具有大量选项和功能,例如用于获取多个域信息的批处理模式。

dig 命令的基本语法与 nslookuphost 不同。如果您指定了一个非默认的名字服务器,它将以一个符号 @ 开头,并在要查询的主机之前。您还可以指定特定的资源记录类型,如下所示:

dig [@<*`server`* >] <*`host`* >  [<*`type`* >]

示例 88-4 展示了在同一个域名 (www.pcguide.com) 上运行 dig 的输出,我将其用作 nslookup (示例 88-3) 和 host 的示例。您可以看到它提供了关于域的更多信息。

示例 88-4. 使用 nslookup 实用程序进行 DNS 名称解析

%dig www.pcguide.com
; <<>> DiG 9.2.1 <<>> www.pcguide.com
;; global options:  printcmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 15912
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 2, ADDITIONAL: 0
;; QUESTION SECTION:
;www.pcguide.com.               IN      A

;; ANSWER SECTION:
www.pcguide.com.        3600    IN      CNAME   pcguide.com.
pcguide.com.            3600    IN      A       209.68.14.80

;; AUTHORITY SECTION:
pcguide.com.            3600    IN      NS      ns0.ns0.com.
pcguide.com.            3600    IN      NS      ns23.pair.com.

;; Query time: 1840 msec
;; SERVER: 209.68.1.87#53(209.68.1.87)
;; WHEN: Tue Nov 18 16:05:08 2003
;; MSG SIZE  rcvd: 109Server:  ns1-mar.starband.com

注意

dig 实用程序非常有用,但仍然没有在一些系统上实现。幸运的是,有一个在线的 dig 实用程序,您可以通过在互联网上的浏览器访问。在 www.gont.com.ar/tools/dig 找到它。

dig命令包括数十个选项和设置。由于本章已经非常长,而dig是这三个工具中功能最强大的,我将在这里停止。请查阅您系统的文档,以获取有关dig如何工作及其参数列表的完整说明。

小贴士

关键概念 大多数 TCP/IP 实现提供了一到多个管理员可以使用的工具,这些工具可以手动将 DNS 域名解析为 IP 地址或执行相关的 DNS 信息搜索。其中最常见的是 nslookup,它允许将主机名翻译为地址或反之亦然;它具有交互和非交互两种模式。在某些操作系统上,nslookup 已被 host 实用程序替换用于简单的 DNS 查找,以及 dig 程序用于更详细地检查 DNS 资源信息。

TCP/IP DNS 注册数据库查找实用程序(whois/nicname)

类似于nslookuphost这样的实用程序允许管理员将 DNS 域名解析为地址,并查看有关域名资源记录的详细信息。然而,在某些情况下,管理员需要知道其 DNS 注册信息,而不是域名的技术信息。这包括诸如哪个组织拥有该域名、其注册何时到期以及谁是被指定的管理联系人等详细信息。

在 DNS 的早期,所有域名都由一个称为互联网网络信息中心(InterNIC 或简称 NIC)的单一机构集中注册。为了允许互联网用户查找有关域名和联系人的信息,InterNIC 建立了一个特殊的服务器。为了允许用户从该服务器检索信息,开发者创建了一个被称为nicnamewhois的协议。它最初在 1982 年的 RFC 812 中描述,后来在 1985 年的 RFC 943 中进一步描述。随着时间的推移,whois这个名字已经成为了两个中的首选,并且它是今天用于允许管理员查找 DNS 注册数据的实用程序的名称。(它也可以用来查找有关 IP 地址的信息,但用于此目的的频率要低得多。)

随着互联网的增长和扩展,它逐渐摆脱了单一集中授权的状态。现代互联网有一个负责在不同 DNS 名称空间部分注册域名的权威机构的分层结构。近年来,由于允许为通用顶级域名(如.COM、.NET 和.ORG)设立多个注册机构的不规范过程,这变得更加复杂。所有这些都意味着查找域名注册信息需要更多的工作,因为这些信息分布在不同的服务器上的许多数据库中。

为了让管理员更容易在这个大型分布式数据库中找到有关域的信息,现代 TCP/IP 实现通常附带一个智能版的whois工具。它能够接受域名作为输入,并自动定位包含该域名信息的适当注册机构。该工具通常按以下方式使用:

whois [-h <*`whois-host`* >] <*`domain`*>

在这个语法中,<domain>表示请求注册信息的域名。管理员可以使用-h参数强制程序查询特定的 whois 服务器,但通常不需要这样做。一些实现还包括其他选项,可以用来将查询定向到特定的注册机构。

示例 88-5 展示了在 FreeBSD UNIX 机器上whois命令的示例输出(我已经删除了一些初步的一般信息和法律免责声明以缩短列表)。

示例 88-5. 使用 whois 程序进行 DNS 域名注册查询

%whois pcguide.com
Registrant:
  The PC Guide
  2080 Harwood Hill Road
  Bennington, VT 05201
  US

  ixl@fearn.pair.com
   +1.8025555555

Domain Name: PCGUIDE.COM

Administrative & Technical Contact:
  Charles Kozierok
  The PC Guide
  2080 Harwood Hill Road
  Bennington, VT 05201
  US

  ixl@fearn.pair.com
   +1.8025555555

Domain Name Servers:
  NS23.PAIR.COM
  NS0.NS0.COM

 Created:     August 25, 1997
Modified:     July  7, 2003
 Expires:     August 24, 2008

** Register Now at http://www.pairNIC.com/ **

在这种情况下,域名pcguide.com的注册商是 pairNIC,这是 pair Networks 的 DNS 注册部门,我多年来(自 1997 年以来,如你所见)一直在使用的公司。这个输出是公开信息,让任何对 pcguide.com 感兴趣的人都能确定我拥有该域名,并了解如何联系我。(不,555-5555 不是我的真实电话号码。)它还告诉他们,pair Networks 运行包含我的域名信息的名称服务器。

许多操作系统,包括 Windows,都没有附带whois命令的实现,但有一些第三方程序将支持该功能。近年来,许多不同的组织也建立了实施whois功能的网站,对于那些更习惯于 Windows 等图形用户界面操作系统的用户来说,这要方便得多。许多这些网站都是由 DNS 注册商提供的免费服务,因此客户可以检查他们感兴趣的名称是否已被占用,如果是的话,由谁占用。

这些系统的一些缺点是,它们通常没有智能地检查存储域名记录的所有不同注册机构。在大多数情况下,注册商提供的whois服务只会搜索注册商运营的特定顶级域名中的名称。因此,如果注册商处理.COM、.ORG 和.NET,它可能只支持那些顶级域的whois查询。要检查更不为人知的域名(如一些不太常见的地理政治(国家代码)域名)的注册信息,可能需要进行相当多的搜索。

小贴士

关键概念 TCP/IP 的 whois 实用程序允许显示 DNS 域的注册信息,例如其所有者、联系信息和注册到期日期。该程序最常见于 UNIX 操作系统,其中它被赋予了智能,允许它自动查询正确的服务器以找到大多数域的信息。较新的基于 Web 的 whois 实用程序也存在,但它们通常仅限于显示特定顶级域子集的域信息。

TCP/IP 网络状态实用程序(netstat)

考虑到 TCP/IP 的复杂性,实际上,大多数时候,所有不同的协议、服务和程序都能高效且无声地完成它们的工作,这实际上是非常令人惊讶的。我们大多数人甚至都没有意识到后台正在进行多少工作,而这正是应该如此。另一方面,当 TCP/IP 网络出现问题时,负责修复问题的管理员需要尽可能多地了解套件背后所有这些片段和部分都在做什么。网络状态实用程序 netstat 就是为了这个目的。

netstat 程序在概念上非常简单,它被设计为只有一个目的:显示设备上 TCP/IP 运行的信息。然而,TCP/IP 的复杂性使得 netstat 本身相当复杂。该程序可以提供大量信息。通常,netstat 的选项和输出取决于特定的操作系统类型和版本。在 UNIX 和 Windows 机器上有所不同,因此我将分别描述每个平台的版本。

UNIX netstat 实用程序

在大多数 UNIX 系统上,netstat 实用程序功能非常全面,典型的实现包括数十个选项,可以用来控制显示哪些信息。这些选项可能不会同时使用;相反,它们被组织成选项组,每个选项组展示一类信息。在每个组内,一个选项是强制性的,即标识该组的选项,因此也会显示一般类型的信息。每个组内还可能有其他选项,它们是可选的,并修改命令以提供对输出的更好控制。本质上,netstat 就像许多相关实用程序合并为一个。

表 88-7 提供了典型 UNIX netstat 实现的选项组简化总结,在此例中为 FreeBSD。

表 88-7. 典型的 UNIX netstat 选项组、选项和参数

选项组、选项和参数 描述
netstat [-AaLSW] [-f <family>] [-p <protocol>] [-n] 默认的 netstat 调用,没有强制选项。它提示实用程序显示主机机器上的活动套接字列表。显示的其他选项可以用来控制精确输出内容;例如,-a 也会显示服务器进程。
netstat -i [-abdt] [-f <family>] [-n] netstat -I <interface> [-abdt] [-f <family>] [-n] 告诉 netstat 提供所有网络接口(-i)或特定网络接口(-I <interface>)的信息。-a 选项还显示多播地址,-b 显示接口上进出数据的字节数,-d 显示丢弃的报文数量,-t 显示看门狗定时器的值。
netstat -w <interval> -d [-I <interface>] <interval> 秒显示所有接口的报文流量信息,或者如果包含 -I <interface>,则仅显示指定接口的信息。如果包含 -d,则还指示丢弃的报文数量。
netstat -s [-s] [-z] [-f <family>] [-p <protocol>] 显示系统上每个协议的全局统计信息(可能修改为仅显示特定地址族或协议的信息)。如果重复使用 -s 选项,则抑制值为零的计数器。使用 -z 选项在显示统计信息后重置统计信息。
netstat -i -s [-f <family>] [-p <protocol>] netstat -I <interface> -s [-f <family>] [-p <protocol>] 显示与 netstat -s 相同的统计信息,但基于每个接口而不是整个系统的汇总。
netstat -m 输出内存管理例程统计信息。
netstat -r [-Aa] [-f <family>] [-n] [-W] 显示主机的路由表内容。-A-a 选项提供有关路由的附加信息。
netstat -rs [-s] 显示路由统计信息。-s 选项抑制值为零的计数器。
netstat -g [-W] [-f <family>] 显示多播路由信息。
netstat -gs [-s] [-f <family>] 显示多播路由统计信息。-s 选项抑制值为零的计数器。

大多数在 表 88-7 中的选项特定于这些组;例如,在发出 netstat -i 命令时不能使用 -s。然而,也有一些通用选项可以与这些组中的多个组合使用,以一致的方式修改 netstat 变体的行为。这些选项在 表 88-8 中描述。

表 88-8. 典型 UNIX netstat 通用选项和参数

选项/参数 描述
-f <地址族> 限制命令的输出只显示特定协议地址族的信息,对于运行多个协议套件的宿主。例如,常规 TCP/IP 的地址族是 inet;对于 IPv6,它是 inet6。其他也可能被支持。
-p <协议> 限制输出只显示与特定协议相关的数据,例如 IP、TCP、UDP 或 ICMP。
-n 以数字形式显示网络地址,而不是以符号名称显示。还以数字形式显示端口号,而不是将已知的 UDP 和 TCP 端口号转换为使用它们的协议名称(例如,23 而不是 telnet)。
-W 禁止自动截断地址(有时为了显示格式而这样做)。

netstat 命令可以产生大量的输出,尤其是如果你没有使用 表 88-8 中的某些选项进行限制。这对于单独使用 netstat 以及使用 -s 选项尤其如此。示例 88-6 展示了运行 "plain" netstat 的样本输出,但我已经截断了连接列表,使其不会太长(我还重新格式化了列表,以便更好地适应页面)。注意最后一列,它显示了 TCP 连接的当前状态(参见 第四十七章 中的 TCP 有限状态机描述)。

示例 88-6. 来自 UNIX netstat 工具的样本连接列表

%netstat
Active Internet connections
Prot  Rcv  Snd  Local Address     Foreign Address       (state)
tcp4  0    0    pcguide.com.http  c-24-118-141-124.3384  ESTABLISHED
tcp4  0    827  pcguide.com.http  webcacheB03a.cac.46075 ESTABLISHED
tcp4  0    0    qs36.smtp         MV1-24.171.17.64.1339  ESTABLISHED
tcp4  0    0    pcguide.com.http  1Cust234.tnt1.le.1338  ESTABLISHED
tcp4  0    0    pcguide.com.http  1Cust234.tnt1.le.1337  FIN_WAIT_1
tcp4  0    84   pcguide.com.http  dial81-131-97-70.2902  FIN_WAIT_1
tcp4  0    0    pcguide.com.http  216.76.14.221.9954     FIN_WAIT_2
tcp4  0    0    pcguide.com.http  216.76.14.221.9945     FIN_WAIT_2
tcp4  0    0    pcguide.com.http  1Cust234.tnt1.le.1326  TIME_WAIT

示例 88-7 展示了 netstat -s. 的输出示例。在这里,我通过使用 -p ip 限制了输出,告诉程序只显示与 IP 相关的统计信息。

示例 88-7. 来自 UNIX netstat 工具的样本 IP 统计信息

%netstat -s -p ip
ip:
        57156204 total packets received
        0 bad header checksums
        4 with size smaller than minimum
        0 with data size < data length
        0 with ip length > max ip packet size
        0 with header length < data size
        0 with data length < header length
        0 with bad options
        0 with incorrect version number
        138 fragments received
        6 fragments dropped (dup or out of space)
        128 fragments dropped after timeout
        2 packets reassembled ok
        57085912 packets for this host
        24736 packets for unknown/unsupported protocol
        0 packets forwarded (0 packets fast forwarded)
        44957 packets not forwardable
        4 packets received for unknown multicast group
        0 redirects sent
        66183465 packets sent from this host
        177 packets sent with fabricated ip header
        0 output packets dropped due to no bufs, etc.
        0 output packets discarded due to no route
        0 output datagrams fragmented
        0 fragments created
        0 datagrams that can't be fragmented
        0 tunneling packets that can't find gif
        22 datagrams with bad address in header

Windows netstat 工具

Windows netstat 工具比 UNIX 版本简单得多,因为它有更少的选项。这对于学习该程序的人来说是个好消息,但对于那些希望在使用它时获得最大功能和灵活性的人来说,可能就不是那么好了。

与 UNIX netstat 版本一样,Windows 工具有一组选项组,用于指定显示的一般信息类型,以及一些可以与多个组一起使用的通用选项。选项组和通用选项分别显示在 表 88-9 和 表 88-10 中。

表 88-9. 常见的 Windows netstat 选项组、选项和参数

选项组、选项和参数 描述
netstat [-n] [-o] [<间隔>] netstat -a [-n] [-o] 当不带强制选项调用时,netstat 显示有关活动 TCP 连接的信息。
[-p <协议> [<间隔>] 显示所有活动的 TCP 连接,以及主机正在监听的所有 TCP 和 UDP 端口。
netstat -e [<间隔>] 显示以太网接口的统计信息。
netstat -r [<间隔>] 显示设备的当前路由表。
netstat -s [-p <协议>] [<间隔>] 通过协议显示系统的 TCP/IP 统计信息。

表 88-10. 常见的 Windows netstat 通用选项和参数

选项/参数 描述
-n 以数字形式显示网络地址,而不是符号名称形式。还以数字形式显示端口,而不是显示与知名 UDP 或 TCP 端口号关联的标准进程名称。
-o 显示与每个连接关联的进程 ID。
-p <协议> 限制显示仅与指定协议关联的信息。
<间隔> 使 netstat 命令每隔 <间隔> 秒重复一次,而不仅仅是显示其信息一次。这可以与任何 netstat 选项组一起使用。例如,netstat -s 5 每 5 秒显示一次 TCP/IP 统计信息。

当提供相同或类似选项时,Windows netstat 程序的输出与 UNIX 工具的输出相当相似,但 UNIX 版本通常提供更多详细信息。示例 88-8 展示了一个示例,说明如何在我的家用 Windows XP 机器上使用 -p icmp 限制输出仅显示 ICMP 统计信息。

示例 88-8. Windows netstat 工具的样本 ICMP 统计信息

D:\aa>netstat -s -p icmp
ICMPv4 Statistics
                            Received    Sent
  Messages                  243         248
  Errors                    0           0
  Destination Unreachable   9           4
  Time Exceeded             7           0
  Parameter Problems        0           0
  Source Quenches           0           0
  Redirects                 0           0
  Echos                     224         20
  Echo Replies              3           224
  Timestamps                0           0
  Timestamp Replies         0           0
  Address Masks             0           0
  Address Mask Replies      0           0

示例 88-9 展示了 netstat(我稍作修改以适应页面)的路由表显示。您可以使用 UNIX 的 netstat -s -p icmpnetstat -r 命令获得类似的输出,但包含更多信息。

示例 88-9. Windows netstat 工具的样本路由表显示

D:\aa>netstat -r
Route Table
=================================================================
Interface List
0x1 ........................... MS TCP Loopback interface
0x2 ...00 04 76 4e 75 3f ...... 3Com 10/100 Mini PCI Ethernet
=================================================================
=================================================================
Active Routes:
  Network Dest     Netmask          Gateway        Interface      Met
  0.0.0.0          0.0.0.0          148.64.128.1   148.64.133.73   30
  127.0.0.0        255.0.0.0        127.0.0.1      127.0.0.1       1
  148.64.128.0     255.255.192.0    148.64.133.73  148.64.133.73   30
  148.64.133.73    255.255.255.255  127.0.0.1      127.0.0.1       30
  148.64.255.255   255.255.255.255  148.64.133.73  148.64.133.73   30
  224.0.0.0        240.0.0.0        148.64.133.73  148.64.133.73   30
  255.255.255.255  255.255.255.255  148.64.133.73  148.64.133.73   1
Default Gateway:      148.64.128.1
=================================================================
Persistent Routes:
  None

小贴士

关键概念 TCP/IP 实现包括 netstat 工具,以便显示有关网络状态的信息。在 UNIX 系统上,netstat 是一个功能齐全的程序,具有许多选项,这些选项被组织成选项组,每个选项组都显示有关 TCP/IP 协议操作特定类型的信息。在 Windows 系统上,netstat 的功能相对有限,但它仍然可以显示大量信息。

TCP/IP 配置工具(ifconfig、ipconfig 和 winipcfg)

网络管理员工作的一个重要部分是设置和维护使 TCP/IP 网络功能的各种设备,这个过程通常被称为 配置。网络主机由硬件和软件组成,它们协同工作以实现协议栈的所有层和功能。管理员使用硬件工具来配置物理设备,执行安装网络接口卡、连接电缆、操作开关和其他硬件设置等任务。同样,管理员需要工具来配置运行 TCP/IP 接口并控制网络主机上高层协议操作的软件。UNIX 管理员使用 ifconfig 工具。在 Windows NT、2000 和 XP 上,配置工具是 ipconfig。Windows 的早期版本有 winipcfg 工具。

UNIX 的 ifconfig 工具

在 UNIX 系统中,管理员使用接口配置工具 ifconfig 来查看和修改控制主机上 TCP/IP 功能的软件设置。这是一个非常强大的程序,允许管理员设置和管理非常广泛的网络设置。ifconfig 在不同类型的 UNIX 中的实现差异很大;虽然它们在一般术语上相似,但它们可能有不同的选项和语法。

您可以使用 ifconfig 程序进行各种目的:创建或删除网络接口、更改其设置,或者简单地检查现有配置。因此,像 netstat 工具一样,ifconfig 将几个相关程序合并为一个,其工作方式取决于您调用它的语法。同样,像 netstat 一样,ifconfig 有许多通用选项可以应用于其许多不同用途。

表 88-11 提供了 ifconfig 可以执行的不同功能以及用于在典型 UNIX 实现(本例中为 NetBSD)中指定每个功能的语法的简化总结。您可以使用 ifconfig 通过设置几十个配置参数之一来修改接口的配置,使用表中最后一行所示的语法。表 88-12 描述了可用于许多不同模式的常见选项和参数。我在 表 88-13 中提供了一些样本参数的简要说明(有关完整列表,请参阅您的 ifconfig 文档)。

表 88-11. 典型 UNIX ifconfig 语法、选项和参数

语法、选项和参数 描述
ifconfig [-L] [-m] <interface> 当仅使用接口指定(除 -L-m 之外)调用 ifconfig 时,它显示该网络接口的配置信息。请注意,仅输入 ifconfig 而不指定接口将仅显示参数的帮助信息。要查看所有接口,请使用 -a 参数。
ifconfig -a [-L] [-m] [-b] [-d] [-u] [-s] [<family>] 显示主机上所有接口的信息。可以使用显示的通用参数或指定地址族来限制输出(参见表 88-12).
ifconfig -l [-b] [-d] [-u] [-s] 列出系统上所有可用的接口。
ifconfig <interface> create 在主机上创建指定的逻辑网络接口,然后使用此表中最后一行所示的语法进行配置。请注意,某些 UNIX 变体允许在创建时设置某些参数。
ifconfig <interface> destroy 销毁指定的逻辑接口。
ifconfig <interface> [<family>] [<address> [<dest-address>]] [<parameters>] 配置主机上特定接口的参数。如果正在设置地址,则它是可选地址族之后的第一个参数。<dest-address> 用于指定点对点链路的目标地址。之后,可以指定几十个参数来配置接口,其中一些在表 88-13 中显示。

表 88-12. 典型的 UNIX ifconfig 通用选项和参数

选项/参数 描述
-L 显示 IPv6 地址的地址生存时间。
-m 显示接口支持的所有媒体。
-b 将接口信息显示限制为广播接口。
-d 仅显示当前处于关闭状态(禁用)的接口。
-u 仅显示当前处于开启状态(操作中)的接口。
-s 仅显示可能连接的接口。
<family> 指定特定的地址族,用于限制输出或指示正在配置的地址类型。值 inet 用于 IPv4,inet6 用于 IPv6。

表 88-13. 典型的 UNIX ifconfig 接口配置参数

参数 描述
alias / -alias 建立或删除网络地址别名。
arp / -arp 启用或禁用在此接口上使用 ARP。
delete 删除指定的网络地址。
down 将接口标记为已关闭,禁用它。
media <type> 将接口的媒体类型设置为特定值。
mtu <n> 设置接口的最大传输单元(MTU)。
netmask <掩码> 为接口地址设置网络或子网掩码。
prefixlen <*n*>` netmask相同,但允许使用 CIDR 风格的前缀长度来指定掩码。
up 设置接口为启用状态。

注意

由于创建、销毁或修改接口可能导致主机无法正常工作,因此在大多数系统中,通常需要管理员(超级用户)权限才能使用ifconfig进行除检查现有配置之外的操作

示例 88-10 显示了我在使用的一台 UNIX 机器上ifconfig -a命令的示例输出,显示了其接口的设置。

示例 88-10. UNIX ifconfig -a 命令的示例输出

%ifconfig -a
fxp0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500
  address: 00:a0:c9:8c:f4:a1
  media: Ethernet autoselect (100baseTX full-duplex)
  status: active
  inet 166.84.1.3 netmask 0xffffffe0 broadcast 166.84.1.31
  inet alias 166.84.1.13 netmask 0xffffffff broadcast 166.84.1.13
lo0: flags=8009<UP,LOOPBACK,MULTICAST> mtu 33228
  inet 127.0.0.1 netmask 0xff000000

Windows NT、2000 和 XP 的 ipconfig

Windows 在网络配置方面与 UNIX 采取的方法略有不同。如前所述,您可以使用 UNIX 的ifconfig程序查看和修改广泛的配置参数。然而,在 Windows 中,大多数设置和参数修改都是通过 Windows 控制面板完成的。Windows 确实包含一个与 UNIX 的ifconfig类似的小工具,但它的功能远不如ifconfig,主要用于检查现有配置,而不是更改配置。它还允许管理员轻松地在主机上执行一些简单功能。

在 Windows NT、2000 和 XP 上,ifconfig的等效命令行实用程序是ipconfig。与ifconfig一样,Windows 实用程序通过提供给程序选项来控制。然而,由于它比ifconfig简单得多,因此只有少数选项,如表 88-14 中总结的。

表 88-14. 典型的 Windows ipconfig 选项和参数

选项/参数 描述
(none) 当不带选项或参数调用时,ipconfig显示主机上每个接口的 IP 地址、子网掩码和默认网关。
/all 与不带选项调用ipconfig类似,但显示有关主机接口的更详细配置信息。
/release [<适配器>] 释放(终止)指定适配器(接口)或所有接口的 DHCP 租约,如果没有提供则释放所有接口。
/renew [<适配器>] 手动续订指定适配器(接口)或所有适配器的 DHCP 租约,如果没有指定则续订所有适配器。
/displaydns 显示主机的 DNS 解析器缓存内容。
/flushdns 清除主机的 DNS 解析器缓存。
/registerdns 刷新(续订)所有 DHCP 租约,并重新注册与主机关联的任何 DNS 名称。
/showclassid <适配器> 显示与此适配器关联的 DHCP 类 ID(这些用于将客户端分组,以便 DHCP 服务器对它们进行不同的处理)。即使只有一个适配器,也必须指定适配器。
/setclassid <适配器> [<classid>] 修改指定适配器的 DHCP 类 ID。

如前所述,ipconfig 最常用于仅检查现有配置。您可以从 表 88-14 中的选项列表中看到,ipconfig 的其他大多数用途都与控制 DNS 和动态主机配置协议 (DHCP) 等协议的操作有关,而不是配置主机。ipconfig 的一个常见用途是强制主机寻找新的 DHCP 租约,这可以通过先使用 ipconfig /release 然后使用 ipconfig /renew 来完成。

示例 88-11 展示了使用 ipconfig 命令不带任何选项时的输出示例。要获取接口的详细信息,可以使用 /all 选项,如 示例 88-12 中的示例所示(我已经稍作修改以便更容易阅读)。

示例 88-11. Windows ipconfig 工具的简化配置信息

D:\aa>ipconfig
Windows IP Configuration

Ethernet adapter Local Area Connection 2:

        Connection-specific DNS Suffix  . :
        IP Address. . . . . . . . . . . . : 148.64.133.73
        Subnet Mask . . . . . . . . . . . : 255.255.192.0
        Default Gateway . . . . . . . . . : 148.64.128.1

示例 88-12. Windows ipconfig 工具的详细配置信息

D:\aa>ipconfig /all
Windows IP Configuration

   Host Name . . . . . . . . . . . . : ixl
   Primary Dns Suffix  . . . . . . . :
   Node Type . . . . . . . . . . . . : Hybrid
   IP Routing Enabled. . . . . . . . : No
   WINS Proxy Enabled. . . . . . . . : No

Ethernet adapter Local Area Connection 2:

   Connection-specific DNS Suffix  . :
   Description . . . . . . . . . . . : 3Com PCI Ethernet Adapter
   Physical Address. . . . . . . . . : 00-04-76-4E-75-3F
   Dhcp Enabled. . . . . . . . . . . : Yes
   Autoconfiguration Enabled . . . . : Yes
   IP Address. . . . . . . . . . . . : 148.64.133.73
   Subnet Mask . . . . . . . . . . . : 255.255.192.0
   Default Gateway . . . . . . . . . : 148.64.128.1
   DHCP Server . . . . . . . . . . . : 148.64.128.1
   DNS Servers . . . . . . . . . . . : 148.78.249.200
                                       148.78.249.201
   Lease Obtained. . . . . . . . . . : April 19, 2003 11:51:37 AM
   Lease Expires . . . . . . . . . . : April 19, 2003 12:21:37 PM

Windows 95、98 和 Me 的 winipcfg 工具

Windows 95、98 和 Me 有一个名为 winipcfg 的图形工具,而不是 ipconfig 命令行工具。此程序允许您以与 ipconfig 相似的方式检查配置参数,并且还可以释放和更新 DHCP 租约,但它不支持 ipconfig 的其他选项(例如显示主机的 DNS 缓存)。图 88-2 展示了 winipcfg 主屏幕的一个示例。

小贴士

关键概念 在 UNIX 系统中,ifconfig 工具可以用来显示或修改大量 TCP/IP 配置设置。Windows 系统提供命令行工具 ipconfig 或图形工具 winipcfg。两者都允许管理员查看主机的 TCP/IP 基本配置信息,并允许执行诸如更新 DHCP 租约等任务,但与 UNIX 的 ifconfig 程序相比,它们在其他方面相当有限。

Windows 95/98/Me winipcfg 实用程序 winipcfg 实用程序可用于较旧的面向消费者的 Windows 版本,以检查主机的配置并释放/续订 DHCP 租约。

图 88-2. Windows 95/98/Me winipcfg 实用程序 winipcfg 实用程序可用于较旧的面向消费者的 Windows 版本,以检查主机的配置并释放/续订 DHCP 租约。

多种 TCP/IP 故障排除协议

一旦你设置了网络,它将很快出现你需要解决的问题。认识到 TCP/IP 互连网络的复杂性会使诊断某些问题变得困难,该套件的架构师定义了一系列有助于测试和故障排除网络的杂项实用程序协议。尽管这些协议已经存在超过 20 年,但它们相对不为人知,并且很少受到关注。然而,尽管它们在许多系统中不再实现,但我认为它们值得快速查看。

这些简单的协议被设计为在 TCP/IP 服务器上运行的服务。每个服务都在一个专用的已知端口号上监听请求,然后以特定类型的信息进行响应。这些协议可以与 TCP 和 UDP 一起使用,使得每种传输协议都可以进行测试。在 UDP 的情况下,服务器将其收到的每个 UDP 数据报计为一个请求,并向其发送响应。当与 TCP 一起使用时,客户端首先与服务器建立连接。在某些协议中,这个连接随后被用来在客户端和服务器之间连续发送数据;在其他协议中,建立连接被视为向服务器的一个隐含请求,服务器将立即发送响应并关闭连接。

表 88-15 提供了这些故障排除协议在 UDP 和 TCP 下的简要描述。我为每个协议展示了服务使用的端口号以及定义它的 RFC。

表 88-15. 多种 TCP/IP 故障排除协议

协议 已知端口号 定义 RFC 描述
回声协议 7 862 将接收到的数据回显给其发送者。当在 UDP 上使用时,每条消息的有效负载被简单地封装成一个返回的 UDP 数据报并发送回去。对于 TCP,服务器将回显客户端发送的每个字节,直到连接关闭。
丢弃协议 9 863 丢弃发送给它的所有数据。
字符生成器协议 19 864 生成随机数据字符并发送给设备。当与 UDP 一起使用时,每个发送到服务器的 UDP 消息都会导致它发送一个包含随机数量(0 到 512 字节)数据的 UDP 消息。当与 TCP 一起使用时,服务器在客户端建立连接后立即开始发送字符,直到客户端终止连接。
每日名言协议 17 865 向客户端设备发送一条简短的消息(由服务器管理员选择)。对于 UDP,对于每个传入的 UDP 消息都会发送消息;对于 TCP,在建立连接后,服务器发送一次消息,然后关闭连接。
活跃用户 11 866 向设备发送活跃用户列表。对于 UDP,对于每个传入的 UDP 消息都会发送列表;如果列表长度超过 512 字节,它将在多个消息中发送。对于 TCP,在连接到服务器时自动发送列表,然后终止连接。
白天协议 13 867 在接收到 UDP 消息或传入的 TCP 连接后,以人类可读的形式返回服务器上的当前时间。
时间协议 37 868 以机器可读的形式返回当前时间——具体来说,是自 1900 年 1 月 1 日凌晨以来经过的秒数。服务器接收到每个 UDP 消息或建立 TCP 连接时都会发送时间。请注意,此协议不能用于服务器的时间同步,因为它不补偿消息在互联网中传输所需时间的变化。
posted @ 2025-11-27 09:18  绝不原创的飞龙  阅读(3)  评论(0)    收藏  举报